From f93e0b2271f003762e4c86bd441b3af2040c4103 Mon Sep 17 00:00:00 2001 From: Ruthenic Date: Mon, 24 Apr 2023 20:56:07 -0400 Subject: [PATCH] stuffsies :3 also my n plushie really needs to ship already >:( --- Cargo.lock | 129 ++++++++++++++++++++++++++++++++++++++++++ Cargo.toml | 5 +- src/chests.rs | 39 ++++++++++++- src/commands/debug.rs | 32 +++++++++++ src/commands/mod.rs | 6 ++ src/game_state.rs | 26 +++++++++ src/loot_tables.rs | 39 +++++++++++++ src/main.rs | 39 +++++++++---- src/tracing.rs | 43 ++++++++++++++ src/world.rs | 4 +- 10 files changed, 346 insertions(+), 16 deletions(-) create mode 100644 src/commands/debug.rs create mode 100644 src/game_state.rs create mode 100644 src/tracing.rs diff --git a/Cargo.lock b/Cargo.lock index 41b4356..065588a 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -126,6 +126,7 @@ checksum = "01db46963eb9486f7884121527ec69751d0e448f9e1d5329e80ea3424118a31a" dependencies = [ "bevy_derive", "bevy_ecs", + "bevy_reflect", "bevy_utils", "downcast-rs", "wasm-bindgen", @@ -152,6 +153,7 @@ dependencies = [ "async-channel", "bevy_ecs_macros", "bevy_ptr", + "bevy_reflect", "bevy_tasks", "bevy_utils", "downcast-rs", @@ -185,12 +187,56 @@ dependencies = [ "toml_edit", ] +[[package]] +name = "bevy_math" +version = "0.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "da6a1109d06fe947990db032e719e162414cf9bf7a478dcc52742f1c7136c42a" +dependencies = [ + "glam", + "serde", +] + [[package]] name = "bevy_ptr" version = "0.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0c4b88451d4c5a353bff67dbaa937b6886efd26ae114769c17f2b35099c7a4de" +[[package]] +name = "bevy_reflect" +version = "0.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9fc3979471890e336f3ba87961ef3ecd45c331cf2cb2f582c885e541af228b48" +dependencies = [ + "bevy_math", + "bevy_ptr", + "bevy_reflect_derive", + "bevy_utils", + "downcast-rs", + "erased-serde", + "glam", + "once_cell", + "parking_lot", + "serde", + "smallvec", + "thiserror", +] + +[[package]] +name = "bevy_reflect_derive" +version = "0.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2bc7ea7c9bc2c531eb29ba5619976613d6680453ff5dd4a7fcd08848e8bec5ad" +dependencies = [ + "bevy_macro_utils", + "bit-set", + "proc-macro2", + "quote", + "syn 1.0.109", + "uuid", +] + [[package]] name = "bevy_tasks" version = "0.10.1" @@ -206,6 +252,20 @@ dependencies = [ "wasm-bindgen-futures", ] +[[package]] +name = "bevy_time" +version = "0.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d3edbd605df1bced312eb9888d6be3d5a5fcac3d4140038bbe3233d218399eef" +dependencies = [ + "bevy_app", + "bevy_ecs", + "bevy_reflect", + "bevy_utils", + "crossbeam-channel", + "thiserror", +] + [[package]] name = "bevy_utils" version = "0.10.1" @@ -234,6 +294,21 @@ dependencies = [ "syn 1.0.109", ] +[[package]] +name = "bit-set" +version = "0.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0700ddab506f33b20a03b13996eccd309a48e5ff77d0d95926aa0210fb4e95f1" +dependencies = [ + "bit-vec", +] + +[[package]] +name = "bit-vec" +version = "0.6.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "349f9b6a179ed607305526ca489b34ad0a41aed5f7980fa90eb03160b69598fb" + [[package]] name = "bitfield-struct" version = "0.3.2" @@ -266,6 +341,12 @@ version = "3.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0d261e256854913907f67ed06efbc3338dfe6179796deefc1ff763fc1aee5535" +[[package]] +name = "bytemuck" +version = "1.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "17febce684fd15d89027105661fec94afb475cb995fbc59d2865198446ba2eea" + [[package]] name = "byteorder" version = "1.4.3" @@ -347,6 +428,16 @@ dependencies = [ "cfg-if", ] +[[package]] +name = "crossbeam-channel" +version = "0.5.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a33c2bf77f2df06183c3aa30d1e96c0695a313d4f9c453cc3762a6db39f99200" +dependencies = [ + "cfg-if", + "crossbeam-utils", +] + [[package]] name = "crossbeam-utils" version = "0.8.15" @@ -404,6 +495,15 @@ dependencies = [ "cfg-if", ] +[[package]] +name = "erased-serde" +version = "0.3.25" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4f2b0c2380453a92ea8b6c8e5f64ecaafccddde8ceab55ff7a8ac1029f894569" +dependencies = [ + "serde", +] + [[package]] name = "event-listener" version = "2.5.3" @@ -551,6 +651,10 @@ name = "glam" version = "0.23.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8e4afd9ad95555081e109fe1d21f2a30c691b5f0919c67dfa690a2e1eb6bd51c" +dependencies = [ + "bytemuck", + "serde", +] [[package]] name = "h2" @@ -908,6 +1012,12 @@ version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b15813163c1d831bf4a13c3610c05c0d03b39feb07f7e09fa234dac9b15aaf39" +[[package]] +name = "owo-colors" +version = "3.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c1b04fb49957986fdce4d6ee7a65027d55d4b6d2265e5848bbb507b58ccfdb6f" + [[package]] name = "parking" version = "2.0.0" @@ -1348,6 +1458,9 @@ name = "smallvec" version = "1.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a507befe795404456341dfab10cef66ead4c041f62b8b11bbb92bffe5d0953e0" +dependencies = [ + "serde", +] [[package]] name = "socket2" @@ -1606,6 +1719,16 @@ dependencies = [ "tracing-core", ] +[[package]] +name = "tracing-serde" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bc6b213177105856957181934e4920de57730fc69bf42c37ee5bb664d406d9e1" +dependencies = [ + "serde", + "tracing-core", +] + [[package]] name = "tracing-subscriber" version = "0.3.16" @@ -1613,11 +1736,14 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a6176eae26dd70d0c919749377897b54a9276bd7061339665dd68777926b5a70" dependencies = [ "nu-ansi-term", + "serde", + "serde_json", "sharded-slab", "smallvec", "thread_local", "tracing-core", "tracing-log", + "tracing-serde", ] [[package]] @@ -1710,13 +1836,16 @@ name = "valence-battle" version = "0.0.1" dependencies = [ "anyhow", + "bevy_time", "flume", "once_cell", + "owo-colors", "proc-macro2", "rand", "ron", "serde", "tracing", + "tracing-core", "tracing-subscriber", "valence", ] diff --git a/Cargo.toml b/Cargo.toml index 066a287..73a48f1 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -8,7 +8,7 @@ edition = "2021" [dependencies] proc-macro2 = "1.0.56" tracing = "0.1.37" -tracing-subscriber = "0.3.16" +tracing-subscriber = { version = "0.3.16", features = ["json"] } valence = { git = "https://github.com/valence-rs/valence", rev = "1da1a58" } flume = "0.10.14" anyhow = "1.0.70" @@ -16,3 +16,6 @@ once_cell = "1.17.1" rand = "0.8.5" ron = "0.8.0" serde = { version = "1.0.160", features = ["derive"] } +bevy_time = "0.10.1" +tracing-core = "0.1.30" +owo-colors = "3.5.0" diff --git a/src/chests.rs b/src/chests.rs index d29c9c1..46bac47 100644 --- a/src/chests.rs +++ b/src/chests.rs @@ -1,4 +1,4 @@ -use crate::loot_tables::EARLY_GAME; +use crate::{game_state::GameState, loot_tables::*, CurrentGameState, MessageQueue}; use valence::{block::BlockEntityKind, client::misc::InteractBlock, ecs as bevy_ecs, prelude::*}; #[derive(Component, Debug)] @@ -10,10 +10,40 @@ pub struct Chest { #[derive(Component)] pub struct Pos(BlockPos); +pub fn refill_chests_system( + mut chests: Query<(Entity, &mut Inventory, &Pos), (With, With)>, + game_state: Res, + mut message_queue: ResMut, +) { + if game_state.is_changed() { + for mut chest in &mut chests { + tracing::info!( + "Generating new chest at ({}, {}, {})", + chest.2 .0.x, + chest.2 .0.y, + chest.2 .0.z + ); + + let inventory = match game_state.0 { + GameState::EarlyGame => EARLY_GAME.clone(), + GameState::MidGame => MID_GAME.clone(), + GameState::LateGame => LATE_GAME.clone(), + } + .get_random_inventory(5, 7); + + *chest.1 = inventory + } + message_queue + .0 + .push("Chests have been refilled!".bold().color(Color::GREEN)) + } +} + pub fn open_chests( mut commands: Commands, chests: Query<(Entity, &Inventory, &Pos), (With, With)>, instances: Query<&Instance>, + game_state: Res, mut events: EventReader, ) { let instance = instances.single(); @@ -40,7 +70,12 @@ pub fn open_chests( event.position.y, event.position.z ); - let inventory = EARLY_GAME.get_random_inventory(5, 7); + let inventory = match game_state.0 { + GameState::EarlyGame => EARLY_GAME.clone(), + GameState::MidGame => MID_GAME.clone(), + GameState::LateGame => LATE_GAME.clone(), + } + .get_random_inventory(5, 7); let chest_commands = commands.spawn((inventory, Pos(event.position))); diff --git a/src/commands/debug.rs b/src/commands/debug.rs new file mode 100644 index 0000000..fa146ac --- /dev/null +++ b/src/commands/debug.rs @@ -0,0 +1,32 @@ +use valence::{ + prelude::{Client, GameMode}, + text::{Color, TextFormat}, +}; + +use crate::{game_state::GameState, CurrentGameState}; + +use super::Command; + +pub fn advance_game_state(game_state: &mut CurrentGameState) { + match game_state.0 { + GameState::EarlyGame => { + game_state.0 = GameState::MidGame; + game_state.1 += 1; + } + GameState::MidGame => { + game_state.0 = GameState::LateGame; + game_state.1 += 1; + } + GameState::LateGame => { + game_state.1 += 1; + } + } +} + +pub fn game_state(client: &mut Client, game_state: &CurrentGameState) { + client.send_message(match game_state.0 { + GameState::EarlyGame => "Early game".italic().color(Color::GRAY), + GameState::MidGame => "Mid game".italic().color(Color::GRAY), + GameState::LateGame => "Late game".italic().color(Color::GRAY), + }) +} diff --git a/src/commands/mod.rs b/src/commands/mod.rs index a1371b0..7b2be0a 100644 --- a/src/commands/mod.rs +++ b/src/commands/mod.rs @@ -1,9 +1,12 @@ +mod debug; mod gamemode; use valence::{ client::event_loop::PacketEvent, packet::c2s::play::CommandExecutionC2s, prelude::*, }; +use crate::CurrentGameState; + #[derive(Clone, Debug)] pub struct CommandExecution { pub client: Entity, @@ -51,6 +54,7 @@ impl Command { pub fn command_executor( mut clients: Query<(&mut Client, &mut GameMode)>, + mut game_state: ResMut, mut events: EventReader, ) { for event in events.iter() { @@ -59,6 +63,8 @@ pub fn command_executor( match cmd.name.as_str() { "gamemode" => gamemode::run(cmd, &mut client, &mut gamemode), + "advance_game_state" => debug::advance_game_state(&mut game_state), + "game_state" => debug::game_state(&mut client, &game_state), _ => client.send_message(format!("Command {} not found!", cmd.name)), } } diff --git a/src/game_state.rs b/src/game_state.rs new file mode 100644 index 0000000..d7384fd --- /dev/null +++ b/src/game_state.rs @@ -0,0 +1,26 @@ +use valence::prelude::*; + +use crate::CurrentGameState; + +#[derive(Clone, Debug)] +pub enum GameState { + EarlyGame, + MidGame, + LateGame, +} + +pub fn game_state_update(mut game_state: ResMut) { + match game_state.0 { + GameState::EarlyGame => { + game_state.0 = GameState::MidGame; + game_state.1 += 1; + } + GameState::MidGame => { + game_state.0 = GameState::LateGame; + game_state.1 += 1; + } + GameState::LateGame => { + game_state.1 += 1; + } + } +} diff --git a/src/loot_tables.rs b/src/loot_tables.rs index 8474d9b..af82731 100644 --- a/src/loot_tables.rs +++ b/src/loot_tables.rs @@ -2,6 +2,7 @@ use once_cell::sync::Lazy; use rand::{distributions::WeightedIndex, prelude::Distribution, Rng}; use valence::prelude::*; +#[derive(Clone)] pub struct LootTable { items: Vec, index: WeightedIndex, @@ -61,3 +62,41 @@ pub static EARLY_GAME: Lazy = Lazy::new(|| { LootTable::new(table) }); + +pub static MID_GAME: Lazy = Lazy::new(|| { + let table = vec![ + // Armor + (ItemKind::LeatherHelmet, 20.0), + (ItemKind::LeatherChestplate, 16.5), + (ItemKind::LeatherLeggings, 16.0), + (ItemKind::LeatherBoots, 25.0), + // Attacking items (swords/axes) + (ItemKind::WoodenSword, 20.0), + (ItemKind::WoodenAxe, 10.0), + (ItemKind::StoneSword, 15.0), + (ItemKind::StoneAxe, 7.5), + (ItemKind::IronSword, 5.0), + (ItemKind::IronAxe, 2.5), + ]; + + LootTable::new(table) +}); + +pub static LATE_GAME: Lazy = Lazy::new(|| { + let table = vec![ + // Armor + (ItemKind::LeatherHelmet, 20.0), + (ItemKind::LeatherChestplate, 16.5), + (ItemKind::LeatherLeggings, 16.0), + (ItemKind::LeatherBoots, 25.0), + // Attacking items (swords/axes) + (ItemKind::WoodenSword, 20.0), + (ItemKind::WoodenAxe, 10.0), + (ItemKind::StoneSword, 15.0), + (ItemKind::StoneAxe, 7.5), + (ItemKind::IronSword, 5.0), + (ItemKind::IronAxe, 2.5), + ]; + + LootTable::new(table) +}); diff --git a/src/main.rs b/src/main.rs index 32055e0..00367b7 100644 --- a/src/main.rs +++ b/src/main.rs @@ -2,9 +2,11 @@ mod chat; mod chests; mod combat; mod commands; +mod game_state; mod loot_tables; mod player; mod special; +mod tracing; mod utils; mod world; @@ -12,7 +14,9 @@ use std::net::SocketAddr; use std::sync::atomic::{AtomicI32, Ordering}; +use bevy_time::fixed_timestep::FixedTime; use commands::{handle_command_execution, CommandExecution}; +use game_state::GameState; use valence::{ ecs as bevy_ecs, network::{async_trait, ServerListPing}, @@ -44,8 +48,13 @@ impl NetworkCallbacks for MyCallbacks { #[derive(Resource, Debug)] pub struct MessageQueue(pub Vec); +#[derive(Resource, Debug)] +pub struct CurrentGameState(pub GameState, pub i64); + fn main() { - tracing_subscriber::fmt::init(); + tracing_subscriber::fmt() + .event_format(tracing::Formatter) + .init(); App::new() .insert_resource(NetworkSettings { @@ -54,21 +63,29 @@ fn main() { ..Default::default() }) .insert_resource(MessageQueue(vec![])) + .insert_resource(CurrentGameState(GameState::EarlyGame, 0)) .add_plugins(DefaultPlugins) + .add_plugin(bevy_time::TimePlugin) .add_startup_system(world::setup) .add_event::() + .add_system(game_state::game_state_update.in_schedule(CoreSchedule::FixedUpdate)) + .insert_resource(FixedTime::new_from_secs(120.0)) .add_system(player::update_username_cache) .add_system(handle_command_execution) - .add_systems(( - chat::player_message_handler, - chests::open_chests, - commands::command_executor, - player::fall_damage, - combat::handle_combat_events, - player::death, - player::respawn, - chat::flush_message_queue, - )) + .add_systems( + ( + chests::refill_chests_system, + chat::player_message_handler, + chests::open_chests, + commands::command_executor, + player::fall_damage, + combat::handle_combat_events, + player::death, + player::respawn, + chat::flush_message_queue, + ) + .in_schedule(EventLoopSchedule), + ) .add_system(player::init_clients) .add_system(player::despawn_disconnected_clients) .run(); diff --git a/src/tracing.rs b/src/tracing.rs new file mode 100644 index 0000000..0ca627c --- /dev/null +++ b/src/tracing.rs @@ -0,0 +1,43 @@ +use owo_colors::OwoColorize; +use std::fmt; +use tracing::Level; +use tracing_core::{Event, Subscriber}; +use tracing_subscriber::fmt::{ + format::{self, FormatEvent, FormatFields}, + FmtContext, +}; +use tracing_subscriber::registry::LookupSpan; + +pub struct Formatter; + +impl FormatEvent for Formatter +where + S: Subscriber + for<'a> LookupSpan<'a>, + N: for<'a> FormatFields<'a> + 'static, +{ + fn format_event( + &self, + ctx: &FmtContext<'_, S, N>, + mut writer: format::Writer<'_>, + event: &Event<'_>, + ) -> fmt::Result { + // Format values from the event's's metadata: + let metadata = event.metadata(); + write!( + &mut writer, + "{} {}: ", + match *metadata.level() { + Level::ERROR => "ERROR".red().to_string(), + Level::WARN => "WARN".yellow().to_string(), + Level::INFO => "INFO".green().to_string(), + _ => "UNKN".white().to_string(), + }, + metadata.target() + )?; + + // Write fields on the event + ctx.field_format().format_fields(writer.by_ref(), event)?; + + writeln!(writer) + } +} diff --git a/src/world.rs b/src/world.rs index 2438dff..c53e148 100644 --- a/src/world.rs +++ b/src/world.rs @@ -17,14 +17,14 @@ pub fn setup( for z in -25..25 { for x in -25..25 { let Ok(Some(AnvilChunk {data, ..})) = anvil.read_chunk(x, z) else { - tracing::warn!("Failed to load chunk ({x}, {z}); could not read Anvil chunk"); + tracing::debug!("Failed to load chunk ({x}, {z}); could not read Anvil chunk"); continue }; let mut chunk = Chunk::new(24); let Ok(_) = valence::anvil::to_valence(&data, &mut chunk, 4, |_| BiomeId::default()) else { - tracing::warn!("Failed to load chunk ({x}, {z}); could not convert Anvil chunk to Valence chunk"); + tracing::debug!("Failed to load chunk ({x}, {z}); could not convert Anvil chunk to Valence chunk"); continue };