From 68cf6e83a0c008ae6ca5d91edd4e20da11a61a95 Mon Sep 17 00:00:00 2001 From: AviiNL Date: Sun, 12 Mar 2023 12:51:49 +0100 Subject: [PATCH] Abstract scoreboard display position (#286) ## Description The scoreboard display packet has a position field that can contain one of the following: - 0: List - 1: Sidebar - 2: BelowName - 3..=18: Team specific sidebar indexed as 3 + team color (according to wiki.vg) I'm not really sure how team specific sidebars are supposed to work, so left that as a byte, maybe that can have some more abstraction? ## Test Plan
Playground ```rust use valence::client::despawn_disconnected_clients; use valence::client::event::default_event_handler; use valence::prelude::*; use valence::protocol::packet::s2c::play::scoreboard_display::ScoreboardPosition; use valence::protocol::packet::s2c::play::scoreboard_objective_update::{Mode, RenderType}; use valence::protocol::packet::s2c::play::scoreboard_player_update::Action; use valence::protocol::packet::s2c::play::{ ScoreboardDisplayS2c, ScoreboardObjectiveUpdateS2c, ScoreboardPlayerUpdateS2c, }; use valence::protocol::var_int::VarInt; const SPAWN_Y: i32 = 64; pub fn build_app(app: &mut App) { app.add_plugin(ServerPlugin::new(())) .add_system(default_event_handler.in_schedule(EventLoopSchedule)) .add_startup_system(setup) .add_system(init_clients) .add_system(scoreboard) .add_system(despawn_disconnected_clients) .add_systems(PlayerList::default_systems()); } 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<&mut Client, Added>, instances: Query>, ) { for mut client in &mut clients { client.set_position([0.0, SPAWN_Y as f64 + 1.0, 0.0]); client.set_instance(instances.single()); client.set_game_mode(GameMode::Creative); } } // Add new systems here! fn scoreboard(mut clients: Query<&mut Client, Added>) { for mut client in &mut clients { client.write_packet(&ScoreboardObjectiveUpdateS2c { objective_name: "sidebar", mode: Mode::Create { objective_display_name: "Sidebar".into_text(), render_type: RenderType::Integer, }, }); client.write_packet(&ScoreboardPlayerUpdateS2c { action: Action::Update { objective_score: VarInt(42), objective_name: "sidebar", }, entity_name: "name", }); client.write_packet(&ScoreboardDisplayS2c { position: ScoreboardPosition::Sidebar, // Position is now an Enum score_name: "sidebar", }); } } ```
--------- Co-authored-by: Ryan Johnson --- .../src/packet/s2c/play/scoreboard_display.rs | 69 ++++++++++++++++++- 1 file changed, 68 insertions(+), 1 deletion(-) diff --git a/crates/valence_protocol/src/packet/s2c/play/scoreboard_display.rs b/crates/valence_protocol/src/packet/s2c/play/scoreboard_display.rs index b683eee..1a204be 100644 --- a/crates/valence_protocol/src/packet/s2c/play/scoreboard_display.rs +++ b/crates/valence_protocol/src/packet/s2c/play/scoreboard_display.rs @@ -1,7 +1,74 @@ use crate::{Decode, Encode}; +use super::team::TeamColor; + #[derive(Copy, Clone, Debug, Encode, Decode)] pub struct ScoreboardDisplayS2c<'a> { - pub position: u8, + pub position: ScoreboardPosition, pub score_name: &'a str, } + +#[derive(Copy, Clone, PartialEq, Debug)] +pub enum ScoreboardPosition { + List, + Sidebar, + BelowName, + SidebarTeam(TeamColor), +} + +impl Encode for ScoreboardPosition { + fn encode(&self, w: impl std::io::Write) -> anyhow::Result<()> { + match self { + ScoreboardPosition::List => 0u8.encode(w), + ScoreboardPosition::Sidebar => 1u8.encode(w), + ScoreboardPosition::BelowName => 2u8.encode(w), + ScoreboardPosition::SidebarTeam(TeamColor::Black) => 3u8.encode(w), + ScoreboardPosition::SidebarTeam(TeamColor::DarkBlue) => 4u8.encode(w), + ScoreboardPosition::SidebarTeam(TeamColor::DarkGreen) => 5u8.encode(w), + ScoreboardPosition::SidebarTeam(TeamColor::DarkCyan) => 6u8.encode(w), + ScoreboardPosition::SidebarTeam(TeamColor::DarkRed) => 7u8.encode(w), + ScoreboardPosition::SidebarTeam(TeamColor::Purple) => 8u8.encode(w), + ScoreboardPosition::SidebarTeam(TeamColor::Gold) => 9u8.encode(w), + ScoreboardPosition::SidebarTeam(TeamColor::Gray) => 10u8.encode(w), + ScoreboardPosition::SidebarTeam(TeamColor::DarkGray) => 11u8.encode(w), + ScoreboardPosition::SidebarTeam(TeamColor::Blue) => 12u8.encode(w), + ScoreboardPosition::SidebarTeam(TeamColor::BrightGreen) => 13u8.encode(w), + ScoreboardPosition::SidebarTeam(TeamColor::Cyan) => 14u8.encode(w), + ScoreboardPosition::SidebarTeam(TeamColor::Red) => 15u8.encode(w), + ScoreboardPosition::SidebarTeam(TeamColor::Pink) => 16u8.encode(w), + ScoreboardPosition::SidebarTeam(TeamColor::Yellow) => 17u8.encode(w), + ScoreboardPosition::SidebarTeam(TeamColor::White) => 18u8.encode(w), + ScoreboardPosition::SidebarTeam(_) => { + Err(anyhow::anyhow!("Invalid scoreboard display position")) + } + } + } +} + +impl<'a> Decode<'a> for ScoreboardPosition { + fn decode(r: &mut &'a [u8]) -> anyhow::Result { + let value = u8::decode(r)?; + match value { + 0 => Ok(ScoreboardPosition::List), + 1 => Ok(ScoreboardPosition::Sidebar), + 2 => Ok(ScoreboardPosition::BelowName), + 3 => Ok(ScoreboardPosition::SidebarTeam(TeamColor::Black)), + 4 => Ok(ScoreboardPosition::SidebarTeam(TeamColor::DarkBlue)), + 5 => Ok(ScoreboardPosition::SidebarTeam(TeamColor::DarkGreen)), + 6 => Ok(ScoreboardPosition::SidebarTeam(TeamColor::DarkCyan)), + 7 => Ok(ScoreboardPosition::SidebarTeam(TeamColor::DarkRed)), + 8 => Ok(ScoreboardPosition::SidebarTeam(TeamColor::Purple)), + 9 => Ok(ScoreboardPosition::SidebarTeam(TeamColor::Gold)), + 10 => Ok(ScoreboardPosition::SidebarTeam(TeamColor::Gray)), + 11 => Ok(ScoreboardPosition::SidebarTeam(TeamColor::DarkGray)), + 12 => Ok(ScoreboardPosition::SidebarTeam(TeamColor::Blue)), + 13 => Ok(ScoreboardPosition::SidebarTeam(TeamColor::BrightGreen)), + 14 => Ok(ScoreboardPosition::SidebarTeam(TeamColor::Cyan)), + 15 => Ok(ScoreboardPosition::SidebarTeam(TeamColor::Red)), + 16 => Ok(ScoreboardPosition::SidebarTeam(TeamColor::Pink)), + 17 => Ok(ScoreboardPosition::SidebarTeam(TeamColor::Yellow)), + 18 => Ok(ScoreboardPosition::SidebarTeam(TeamColor::White)), + _ => Err(anyhow::anyhow!("Invalid scoreboard display position")), + } + } +}