M1c: Gleichschritt im Netz #9
@@ -19,16 +19,20 @@ use crate::world::TICKS_PER_SECOND;
|
|||||||
/// Version of the messages. Raise it whenever a message changes.
|
/// Version of the messages. Raise it whenever a message changes.
|
||||||
pub const PROTOCOL_VERSION: u32 = 1;
|
pub const PROTOCOL_VERSION: u32 = 1;
|
||||||
/// Longest message a guest may send, in bytes. The longest one is a greeting
|
/// Longest message a guest may send, in bytes. The longest one is a greeting
|
||||||
/// with a name of full length, which needs 65 bytes.
|
/// with a name of full length, which needs 65 bytes. Greetings of every
|
||||||
|
/// future version must fit as well: a longer one is rejected unread instead
|
||||||
|
/// of being recognised as another version.
|
||||||
pub const MAX_GUEST_MESSAGE_BYTES: usize = 128;
|
pub const MAX_GUEST_MESSAGE_BYTES: usize = 128;
|
||||||
/// Ticks between two state checksums in the stream of ticks: one second.
|
/// Ticks between two state checksums in the stream of ticks: one second.
|
||||||
pub const CHECK_INTERVAL_TICKS: u64 = TICKS_PER_SECOND as u64;
|
pub const CHECK_INTERVAL_TICKS: u64 = TICKS_PER_SECOND as u64;
|
||||||
|
|
||||||
|
// Never changes, see the module documentation.
|
||||||
const TO_HOST_HELLO: u8 = 1;
|
const TO_HOST_HELLO: u8 = 1;
|
||||||
const TO_HOST_ACT: u8 = 2;
|
const TO_HOST_ACT: u8 = 2;
|
||||||
const TO_HOST_DIVERGED: u8 = 3;
|
const TO_HOST_DIVERGED: u8 = 3;
|
||||||
|
|
||||||
const TO_GUEST_WORLD: u8 = 1;
|
const TO_GUEST_WORLD: u8 = 1;
|
||||||
|
// Never changes, see the module documentation.
|
||||||
const TO_GUEST_REFUSED: u8 = 2;
|
const TO_GUEST_REFUSED: u8 = 2;
|
||||||
const TO_GUEST_TICK: u8 = 3;
|
const TO_GUEST_TICK: u8 = 3;
|
||||||
|
|
||||||
@@ -75,7 +79,8 @@ impl Action {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Why a host turned a guest away.
|
/// Why a host turned a guest away. The codes never change, because games of
|
||||||
|
/// other versions read them.
|
||||||
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
|
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
|
||||||
pub enum Refusal {
|
pub enum Refusal {
|
||||||
/// The guest's game speaks another version of these messages.
|
/// The guest's game speaks another version of these messages.
|
||||||
|
|||||||
+41
-2
@@ -12,7 +12,7 @@ use grovewright_core::command::Command;
|
|||||||
use grovewright_core::hash::fnv1a64;
|
use grovewright_core::hash::fnv1a64;
|
||||||
use grovewright_core::map::{Map, Pos, Terrain, Tile};
|
use grovewright_core::map::{Map, Pos, Terrain, Tile};
|
||||||
use grovewright_core::player::PlayerId;
|
use grovewright_core::player::PlayerId;
|
||||||
use grovewright_core::protocol::{Action, Refusal, ToGuest, ToHost};
|
use grovewright_core::protocol::{Action, Refusal, ToGuest, ToHost, PROTOCOL_VERSION};
|
||||||
use grovewright_core::replay::Recording;
|
use grovewright_core::replay::Recording;
|
||||||
use grovewright_core::rules::{
|
use grovewright_core::rules::{
|
||||||
end_hash, frozen_offline_script, frozen_script, rules_id, RULES_SEED,
|
end_hash, frozen_offline_script, frozen_script, rules_id, RULES_SEED,
|
||||||
@@ -162,6 +162,45 @@ fn the_protocol_format_is_unchanged() {
|
|||||||
fnv1a64(&bytes),
|
fnv1a64(&bytes),
|
||||||
0xc263_69c0_f892_247b,
|
0xc263_69c0_f892_247b,
|
||||||
"the messages between host and guests changed; raise \
|
"the messages between host and guests changed; raise \
|
||||||
PROTOCOL_VERSION in core/src/protocol.rs; then update this value"
|
PROTOCOL_VERSION in core/src/protocol.rs; then update this value. \
|
||||||
|
The start of a greeting and the refusal must never change, see \
|
||||||
|
the_greeting_start_and_the_refusal_never_change"
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Covers the promise that games of every version can still tell each other
|
||||||
|
/// that they do not fit: a greeting starts with its tag and the version, and
|
||||||
|
/// a refusal is its tag and the code of its reason. Unlike every other part
|
||||||
|
/// of the messages, these stay the same when PROTOCOL_VERSION is raised.
|
||||||
|
#[test]
|
||||||
|
fn the_greeting_start_and_the_refusal_never_change() {
|
||||||
|
let hello = ToHost::Hello {
|
||||||
|
rules: 1,
|
||||||
|
key: [3; 16],
|
||||||
|
name: "Ada".to_owned(),
|
||||||
|
}
|
||||||
|
.encode();
|
||||||
|
let mut start = vec![1];
|
||||||
|
start.extend(PROTOCOL_VERSION.to_le_bytes());
|
||||||
|
assert_eq!(
|
||||||
|
hello[..start.len()],
|
||||||
|
start[..],
|
||||||
|
"a greeting starts with the tag 1 and the version; this never \
|
||||||
|
changes, not even with a new PROTOCOL_VERSION"
|
||||||
|
);
|
||||||
|
let refusals = [
|
||||||
|
(Refusal::OtherProtocol, 1),
|
||||||
|
(Refusal::OtherRules, 2),
|
||||||
|
(Refusal::WorldFull, 3),
|
||||||
|
(Refusal::TooManyPlayers, 4),
|
||||||
|
(Refusal::AlreadyPlaying, 5),
|
||||||
|
];
|
||||||
|
for (refusal, code) in refusals {
|
||||||
|
assert_eq!(
|
||||||
|
ToGuest::Refused(refusal).encode(),
|
||||||
|
vec![2, code],
|
||||||
|
"a refusal is the tag 2 and the code of its reason; this never \
|
||||||
|
changes, not even with a new PROTOCOL_VERSION"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user