7f904b5e1d
Ein Spieler hat eine dauerhafte Kennung, einen Namen, eine Werkzeugstufe und ein Inventar. Befehle (Beitreten, Verlassen, Graben) sind der einzige Weg, die Welt zu ändern, und lassen sich kodieren. Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
70 lines
2.1 KiB
Rust
70 lines
2.1 KiB
Rust
//! Everything a player can ask the world to do.
|
|
|
|
use crate::codec::{DecodeError, Reader, Writer};
|
|
use crate::map::Pos;
|
|
use crate::player::{clamp_name, PlayerId, PlayerKey, MAX_NAME_BYTES};
|
|
|
|
/// A request that changes the world. Commands are the only way to change it.
|
|
#[derive(Clone, Debug, PartialEq, Eq)]
|
|
pub enum Command {
|
|
/// A player enters the world, new or returning.
|
|
Join { key: PlayerKey, name: String },
|
|
/// A player leaves the world. Their inventory stays.
|
|
Leave { player: PlayerId },
|
|
/// A player hits the tile at `pos` with their pickaxe.
|
|
Dig { player: PlayerId, pos: Pos },
|
|
}
|
|
|
|
const TAG_JOIN: u8 = 1;
|
|
const TAG_LEAVE: u8 = 2;
|
|
const TAG_DIG: u8 = 3;
|
|
|
|
impl Command {
|
|
pub fn encode(&self, w: &mut Writer) {
|
|
match self {
|
|
Command::Join { key, name } => {
|
|
w.u8(TAG_JOIN);
|
|
w.raw(key);
|
|
w.str(&clamp_name(name));
|
|
}
|
|
Command::Leave { player } => {
|
|
w.u8(TAG_LEAVE);
|
|
w.u8(player.0);
|
|
}
|
|
Command::Dig { player, pos } => {
|
|
w.u8(TAG_DIG);
|
|
w.u8(player.0);
|
|
w.i32(pos.x);
|
|
w.i32(pos.y);
|
|
}
|
|
}
|
|
}
|
|
|
|
pub fn decode(r: &mut Reader<'_>) -> Result<Self, DecodeError> {
|
|
match r.u8()? {
|
|
TAG_JOIN => {
|
|
let mut key = [0u8; 16];
|
|
key.copy_from_slice(r.raw(16)?);
|
|
let name = r.string()?;
|
|
if name.len() > MAX_NAME_BYTES {
|
|
return Err(DecodeError::InvalidValue("player name"));
|
|
}
|
|
Ok(Command::Join { key, name })
|
|
}
|
|
TAG_LEAVE => Ok(Command::Leave {
|
|
player: PlayerId(r.u8()?),
|
|
}),
|
|
TAG_DIG => {
|
|
let player = PlayerId(r.u8()?);
|
|
let x = r.i32()?;
|
|
let y = r.i32()?;
|
|
Ok(Command::Dig {
|
|
player,
|
|
pos: Pos::new(x, y),
|
|
})
|
|
}
|
|
_ => Err(DecodeError::InvalidValue("command tag")),
|
|
}
|
|
}
|
|
}
|