--- a/rust/hedgewars-engine-messages/src/messages.rs Thu Nov 15 15:39:59 2018 -0500
+++ b/rust/hedgewars-engine-messages/src/messages.rs Fri Nov 16 16:32:51 2018 +0100
@@ -25,26 +25,34 @@
TeamControlGained(String),
TeamControlLost(String),
TimeWrap,
+ Taunt(u8),
+ HogSay(String),
+ Heartbeat,
}
#[derive(Debug, PartialEq)]
pub enum UnsyncedEngineMessage {
+ TeamControlGained(String),
+ TeamControlLost(String),
+}
+
+#[derive(Debug, PartialEq)]
+pub enum UnorderedEngineMessage {
Ping,
Pong,
- Say(String),
- Taunt(u8),
- GameType(u8),
+ ChatMessage(String),
+ TeamMessage(String),
+ Error(String),
Warning(String),
StopSyncing,
GameOver,
GameInterrupted,
GameSetupChecksum(String),
- TeamControlGained(String),
- TeamControlLost(String),
+ PauseToggled,
}
-
#[derive(Debug, PartialEq)]
pub enum ConfigEngineMessage {
+ GameType(u8),
ConfigRequest,
SetAmmo(String),
SetScript(String),
@@ -117,19 +125,140 @@
#[derive(Debug, PartialEq)]
pub enum EngineMessage {
- Synced(SyncedEngineMessage, u32),
- Unsynced(UnsyncedEngineMessage),
- Config(ConfigEngineMessage),
Unknown,
Empty,
+ Synced(SyncedEngineMessage, u32),
+ Unsynced(UnsyncedEngineMessage),
+ Unordered(UnorderedEngineMessage),
+ Config(ConfigEngineMessage),
+}
+
+macro_rules! em {
+ [$msg: expr] => {
+ vec![($msg) as u8]
+ };
+}
+
+macro_rules! ems {
+ [$msg: expr, $param: expr] => {
+ {
+ let mut v = vec![($msg) as u8];
+ v.extend(String::into_bytes($param.to_string()).iter());
+ v
+ }
+ };
}
-impl EngineMessage {
- fn from_bytes(buf: &[u8]) -> Self {
- unimplemented!()
+impl SyncedEngineMessage {
+ fn to_bytes(&self) -> Vec<u8> {
+ use self::KeystrokeAction::*;
+ use self::SyncedEngineMessage::*;
+ match self {
+ Left(Press) => em!['L'],
+ Left(Release) => em!['l'],
+ Right(Press) => em!['R'],
+ Right(Release) => em!['r'],
+ Up(Press) => em!['U'],
+ Up(Release) => em!['u'],
+ Down(Press) => em!['D'],
+ Down(Release) => em!['d'],
+ Precise(Press) => em!['Z'],
+ Precise(Release) => em!['z'],
+ Attack(Press) => em!['A'],
+ Attack(Release) => em!['a'],
+ NextTurn => em!['N'],
+ Switch => em!['S'],
+ Timer(t) => vec!['0' as u8 + t],
+ Slot(s) => vec!['~' as u8, *s],
+ SetWeapon(s) => vec!['~' as u8, *s],
+ Put(x, y) => unimplemented!(),
+ CursorMove(x, y) => unimplemented!(),
+ HighJump => em!['J'],
+ LongJump => em!['j'],
+ Skip => em![','],
+ TeamControlGained(str) => ems!['g', str],
+ TeamControlLost(str) => ems!['f', str],
+ Taunt(s) => vec!['t' as u8, *s],
+ HogSay(str) => ems!['h', str],
+ Heartbeat => em!['+'],
+ TimeWrap => unreachable!(),
+ }
}
+}
+impl UnsyncedEngineMessage {
+ fn to_bytes(&self) -> Vec<u8> {
+ use self::UnsyncedEngineMessage::*;
+ match self {
+ TeamControlGained(str) => ems!['G', str],
+ TeamControlLost(str) => ems!['F', str],
+ }
+ }
+}
+
+impl UnorderedEngineMessage {
fn to_bytes(&self) -> Vec<u8> {
unimplemented!()
}
}
+
+impl ConfigEngineMessage {
+ fn to_bytes(&self) -> Vec<u8> {
+ unimplemented!()
+ }
+}
+
+impl EngineMessage {
+ pub const MAX_LEN: u16 = 49215;
+
+ fn to_unwrapped(&self) -> Vec<u8> {
+ use self::EngineMessage::*;
+ match self {
+ Unknown => unreachable!("you're not supposed to construct such messages"),
+ Empty => unreachable!("you're not supposed to construct such messages"),
+ Synced(SyncedEngineMessage::TimeWrap, _) => vec!['#' as u8, 0xff, 0xff],
+ Synced(msg, timestamp) => {
+ let mut v = msg.to_bytes();
+ v.push((*timestamp / 256) as u8);
+ v.push(*timestamp as u8);
+
+ v
+ }
+ Unsynced(msg) => msg.to_bytes(),
+ Unordered(msg) => msg.to_bytes(),
+ Config(msg) => msg.to_bytes(),
+ }
+ }
+
+ pub fn to_bytes(&self) -> Vec<u8> {
+ let mut unwrapped = self.to_unwrapped();
+ let mut size = unwrapped.len();
+
+ if size > EngineMessage::MAX_LEN as usize - 2 {
+ size = EngineMessage::MAX_LEN as usize - 2;
+ unwrapped.truncate(size);
+ }
+
+ if size < 64 {
+ unwrapped.insert(0, size as u8);
+ } else {
+ size -= 64;
+ unwrapped.insert(0, (size / 256 + 64) as u8);
+ unwrapped.insert(1, size as u8);
+ }
+
+ unwrapped
+ }
+}
+
+#[test]
+fn message_contruction() {
+ assert_eq!(
+ EngineMessage::Synced(SyncedEngineMessage::TimeWrap, 0).to_bytes(),
+ vec![3, '#' as u8, 255, 255]
+ );
+ assert_eq!(
+ EngineMessage::Synced(SyncedEngineMessage::NextTurn, 258).to_bytes(),
+ vec![3, 'N' as u8, 1, 2]
+ );
+}