From 8d93ddee24ac0dceb024a5c6261339fc0096cb4d Mon Sep 17 00:00:00 2001 From: Ryan Johnson Date: Thu, 23 Mar 2023 06:54:07 -0700 Subject: [PATCH] Revise examples guideline and remove some examples. (#301) # Description - Removed the advice about making examples as small as possible in CONTRIBUTING.md - Remove a couple of low-value examples. I would like to remove more, but their functionality would have to be covered by better examples first. My reasons are: - Examples are tedious to update and maintain. Boilerplate is inevitable. - The "Boilerplate to code" ratio is higher when examples are smaller. - Examples are likely the first thing that new users will try out, so we ought to make a good first impression by showing something substantial. - Complicated examples are better for showing how to use Valence in practice and serve as a useful reference. - Lots of small examples can distract from the more impressive ones. Tiny examples don't add much value. --- CONTRIBUTING.md | 6 +- crates/valence/examples/chat.rs | 106 ------------------- crates/valence/examples/gamemode_switcher.rs | 94 ---------------- 3 files changed, 1 insertion(+), 205 deletions(-) delete mode 100644 crates/valence/examples/chat.rs delete mode 100644 crates/valence/examples/gamemode_switcher.rs diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index b018025..8f704ca 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -17,11 +17,7 @@ knowledge to complete. New contributors are not required to start with these iss If you plan to work on something that's not an open issue, consider making one first so that it can be discussed. This way, your contribution will not be rejected when it is submitted for review. -## Playgrounds and Examples - -Examples (found in the `examples/` directory) are a great way to document how pieces of Valence's API fit together. It's important that they remain as simple as possible. If you're working on a feature that requires a more complex scenario, consider making a playground instead. - -Examples can be run with `cargo run -p valence --example `. +## Playgrounds Playgrounds are meant to provide a quick and minimal environment to test out new code or reproduce bugs. Playgrounds are also a great way test out quick ideas. This is the preferred method for providing code samples in issues and pull requests. diff --git a/crates/valence/examples/chat.rs b/crates/valence/examples/chat.rs deleted file mode 100644 index e050721..0000000 --- a/crates/valence/examples/chat.rs +++ /dev/null @@ -1,106 +0,0 @@ -#![allow(clippy::type_complexity)] - -use tracing::warn; -use valence::client::event::{ChatMessage, CommandExecution}; -use valence::client::{default_event_handler, despawn_disconnected_clients}; -use valence::entity::player::PlayerBundle; -use valence::prelude::*; - -const SPAWN_Y: i32 = 64; - -pub fn main() { - tracing_subscriber::fmt().init(); - - App::new() - .add_plugin(ServerPlugin::new(())) - .add_startup_system(setup) - .add_system(init_clients) - .add_systems( - ( - default_event_handler, - handle_message_events, - handle_command_events, - ) - .in_schedule(EventLoopSchedule), - ) - .add_systems(PlayerList::default_systems()) - .add_system(despawn_disconnected_clients) - .run(); -} - -fn setup(mut commands: Commands, server: Res) { - let mut instance = server.new_instance(DimensionId::default()); - - for z in -5..5 { - for x in -5..5 { - instance.insert_chunk([x, z], Chunk::default()); - } - } - - for z in -25..25 { - for x in -25..25 { - instance.set_block([x, SPAWN_Y, z], BlockState::OAK_PLANKS); - } - } - - commands.spawn(instance); -} - -fn init_clients( - mut clients: Query<(Entity, &UniqueId, &mut Client, &mut GameMode), Added>, - instances: Query>, - mut commands: Commands, -) { - for (entity, uuid, mut client, mut game_mode) in &mut clients { - *game_mode = GameMode::Adventure; - client.send_message("Welcome to Valence! Talk about something.".italic()); - - commands.entity(entity).insert(PlayerBundle { - location: Location(instances.single()), - position: Position::new([0.0, SPAWN_Y as f64 + 1.0, 0.0]), - uuid: *uuid, - ..Default::default() - }); - } -} - -fn handle_message_events( - mut clients: Query<(&mut Client, &Username)>, - mut messages: EventReader, -) { - for message in messages.iter() { - let Ok(username) = clients.get_component::(message.client) else { - warn!("Unable to find client for message: {:?}", message); - continue; - }; - - let message = message.message.to_string(); - - let formatted = format!("<{}>: ", username.0).bold().color(Color::YELLOW) - + message.not_bold().color(Color::WHITE); - - // TODO: write message to instance buffer. - for (mut client, _) in &mut clients { - client.send_message(formatted.clone()); - } - } -} - -fn handle_command_events( - mut clients: Query<&mut Client>, - mut commands: EventReader, -) { - for command in commands.iter() { - let Ok(mut client) = clients.get_component_mut::(command.client) else { - warn!("Unable to find client for message: {:?}", command); - continue; - }; - - let message = command.command.to_string(); - - let formatted = - "You sent the command ".into_text() + ("/".into_text() + (message).into_text()).bold(); - - client.send_message(formatted); - } -} diff --git a/crates/valence/examples/gamemode_switcher.rs b/crates/valence/examples/gamemode_switcher.rs deleted file mode 100644 index acda83a..0000000 --- a/crates/valence/examples/gamemode_switcher.rs +++ /dev/null @@ -1,94 +0,0 @@ -#![allow(clippy::type_complexity)] - -use valence::client::event::CommandExecution; -use valence::client::{default_event_handler, despawn_disconnected_clients}; -use valence::entity::player::PlayerBundle; -use valence::prelude::*; - -const SPAWN_Y: i32 = 64; - -pub fn main() { - tracing_subscriber::fmt().init(); - - App::new() - .add_plugin(ServerPlugin::new(())) - .add_startup_system(setup) - .add_system(init_clients) - .add_systems((default_event_handler, interpret_command).in_schedule(EventLoopSchedule)) - .add_systems(PlayerList::default_systems()) - .add_system(despawn_disconnected_clients) - .run(); -} - -fn setup(mut commands: Commands, server: Res) { - let mut instance = server.new_instance(DimensionId::default()); - - for z in -5..5 { - for x in -5..5 { - instance.insert_chunk([x, z], Chunk::default()); - } - } - - for z in -25..25 { - for x in -25..25 { - instance.set_block([x, SPAWN_Y, z], BlockState::GRASS_BLOCK); - } - } - - commands.spawn(instance); -} - -fn init_clients( - mut clients: Query< - (Entity, &UniqueId, &mut Client, &mut GameMode, &mut OpLevel), - Added, - >, - instances: Query>, - mut commands: Commands, -) { - for (entity, uuid, mut client, mut game_mode, mut op_level) in &mut clients { - *game_mode = GameMode::Creative; - op_level.set(2); // required to use F3+F4, eg /gamemode - client.send_message("Welcome to Valence! Use F3+F4 to change gamemode.".italic()); - - commands.entity(entity).insert(PlayerBundle { - location: Location(instances.single()), - position: Position::new([0.5, SPAWN_Y as f64 + 1.0, 0.5]), - uuid: *uuid, - ..Default::default() - }); - } -} - -fn interpret_command( - mut clients: Query<(&mut Client, &OpLevel, &mut GameMode)>, - mut events: EventReader, -) { - for event in events.iter() { - let Ok((mut client, op_level, mut game_mode)) = clients.get_mut(event.client) else { - continue; - }; - - let mut args = event.command.split_whitespace(); - - if args.next() == Some("gamemode") { - if op_level.get() < 2 { - // not enough permissions to use gamemode command - continue; - } - - let mode = match args.next().unwrap_or_default() { - "adventure" => GameMode::Adventure, - "creative" => GameMode::Creative, - "survival" => GameMode::Survival, - "spectator" => GameMode::Spectator, - _ => { - client.send_message("Invalid gamemode.".italic()); - continue; - } - }; - *game_mode = mode; - client.send_message(format!("Set gamemode to {mode:?}.").italic()); - } - } -}