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.
This commit is contained in:
Ryan Johnson 2023-03-23 06:54:07 -07:00 committed by GitHub
parent 1aae22ca3e
commit 8d93ddee24
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 1 additions and 205 deletions

View file

@ -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 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. way, your contribution will not be rejected when it is submitted for review.
## Playgrounds and Examples ## Playgrounds
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 <example_name>`.
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. 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.

View file

@ -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<Server>) {
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<Client>>,
instances: Query<Entity, With<Instance>>,
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<ChatMessage>,
) {
for message in messages.iter() {
let Ok(username) = clients.get_component::<Username>(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<CommandExecution>,
) {
for command in commands.iter() {
let Ok(mut client) = clients.get_component_mut::<Client>(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);
}
}

View file

@ -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<Server>) {
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<Client>,
>,
instances: Query<Entity, With<Instance>>,
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<CommandExecution>,
) {
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());
}
}
}