Spieler und Befehle
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>
This commit is contained in:
@@ -0,0 +1,96 @@
|
||||
use grovewright_core::codec::{DecodeError, Reader, Writer};
|
||||
use grovewright_core::command::Command;
|
||||
use grovewright_core::map::Pos;
|
||||
use grovewright_core::player::{PlayerId, MAX_NAME_BYTES};
|
||||
|
||||
fn round_trip(command: &Command) -> Command {
|
||||
let mut w = Writer::new();
|
||||
command.encode(&mut w);
|
||||
let bytes = w.into_bytes();
|
||||
let mut r = Reader::new(&bytes);
|
||||
let decoded = Command::decode(&mut r).expect("command decodes");
|
||||
r.finish().expect("no bytes are left over");
|
||||
decoded
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn every_command_survives_encoding() {
|
||||
let commands = [
|
||||
Command::Join {
|
||||
key: [7; 16],
|
||||
name: "Ada".to_owned(),
|
||||
},
|
||||
Command::Leave {
|
||||
player: PlayerId(3),
|
||||
},
|
||||
Command::Dig {
|
||||
player: PlayerId(1),
|
||||
pos: Pos::new(-4, 1_000),
|
||||
},
|
||||
];
|
||||
for command in &commands {
|
||||
assert_eq!(&round_trip(command), command);
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn an_overlong_name_is_shortened_when_encoded() {
|
||||
let command = Command::Join {
|
||||
key: [1; 16],
|
||||
name: "x".repeat(MAX_NAME_BYTES + 10),
|
||||
};
|
||||
assert_eq!(
|
||||
round_trip(&command),
|
||||
Command::Join {
|
||||
key: [1; 16],
|
||||
name: "x".repeat(MAX_NAME_BYTES),
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn an_unknown_command_is_rejected() {
|
||||
assert_eq!(
|
||||
Command::decode(&mut Reader::new(&[0xEE])),
|
||||
Err(DecodeError::InvalidValue("command tag"))
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn a_cut_off_command_is_rejected() {
|
||||
let mut w = Writer::new();
|
||||
Command::Dig {
|
||||
player: PlayerId(0),
|
||||
pos: Pos::new(1, 2),
|
||||
}
|
||||
.encode(&mut w);
|
||||
let bytes = w.into_bytes();
|
||||
assert_eq!(
|
||||
Command::decode(&mut Reader::new(&bytes[..bytes.len() - 1])),
|
||||
Err(DecodeError::UnexpectedEnd)
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn several_commands_can_follow_each_other_in_one_buffer() {
|
||||
let commands = vec![
|
||||
Command::Leave {
|
||||
player: PlayerId(2),
|
||||
},
|
||||
Command::Dig {
|
||||
player: PlayerId(0),
|
||||
pos: Pos::new(5, 6),
|
||||
},
|
||||
];
|
||||
let mut w = Writer::new();
|
||||
for command in &commands {
|
||||
command.encode(&mut w);
|
||||
}
|
||||
let bytes = w.into_bytes();
|
||||
let mut r = Reader::new(&bytes);
|
||||
let mut decoded = Vec::new();
|
||||
while r.remaining() > 0 {
|
||||
decoded.push(Command::decode(&mut r).unwrap());
|
||||
}
|
||||
assert_eq!(decoded, commands);
|
||||
}
|
||||
Reference in New Issue
Block a user