|
1 use crate::messages::{EngineMessage::*, SyncedEngineMessage::*, UnsyncedEngineMessage::*, *}; |
|
2 use queues::*; |
|
3 |
|
4 #[derive(PartialEq)] |
|
5 pub enum QueueChatStrategy { |
|
6 NetworkGame, |
|
7 LocalGame, |
|
8 } |
|
9 |
|
10 pub struct MessagesQueue { |
|
11 strategy: QueueChatStrategy, |
|
12 hi_ticks: u32, |
|
13 unordered: Queue<EngineMessage>, |
|
14 ordered: Queue<EngineMessage>, |
|
15 } |
|
16 |
|
17 impl MessagesQueue { |
|
18 pub fn new(strategy: QueueChatStrategy) -> Self { |
|
19 MessagesQueue { |
|
20 strategy, |
|
21 hi_ticks: 0, |
|
22 unordered: queue![], |
|
23 ordered: queue![], |
|
24 } |
|
25 } |
|
26 |
|
27 fn is_unordered(&self, message: &EngineMessage) -> bool { |
|
28 match message { |
|
29 Unordered(_) => true, |
|
30 Unsynced(HogSay(_)) | Unsynced(ChatMessage(_)) | Unsynced(TeamMessage(_)) => { |
|
31 self.strategy == QueueChatStrategy::NetworkGame |
|
32 } |
|
33 _ => false, |
|
34 } |
|
35 } |
|
36 |
|
37 pub fn push(&mut self, engine_message: EngineMessage) { |
|
38 if self.is_unordered(&engine_message) { |
|
39 self.unordered.add(engine_message).unwrap(); |
|
40 } else if let Synced(TimeWrap, timestamp) = engine_message { |
|
41 self.ordered |
|
42 .add(Synced(TimeWrap, timestamp + self.hi_ticks)) |
|
43 .unwrap(); |
|
44 self.hi_ticks += 65536; |
|
45 } else if let Synced(message, timestamp) = engine_message { |
|
46 self.ordered |
|
47 .add(Synced(message, timestamp + self.hi_ticks)) |
|
48 .unwrap(); |
|
49 } else { |
|
50 self.ordered.add(engine_message).unwrap(); |
|
51 } |
|
52 } |
|
53 |
|
54 pub fn pop(&mut self, timestamp: u32) -> Option<EngineMessage> { |
|
55 if let Ok(message) = self.unordered.remove() { |
|
56 Some(message) |
|
57 } else if let Ok(Synced(_, message_timestamp)) = self.ordered.peek() { |
|
58 if message_timestamp == timestamp { |
|
59 self.ordered.remove().ok() |
|
60 } else { |
|
61 None |
|
62 } |
|
63 } else { |
|
64 self.ordered.remove().ok() |
|
65 } |
|
66 } |
|
67 |
|
68 pub fn iter(&mut self, timestamp: u32) -> MessagesQueueIterator { |
|
69 MessagesQueueIterator { |
|
70 timestamp, |
|
71 queue: self, |
|
72 } |
|
73 } |
|
74 } |
|
75 |
|
76 pub struct MessagesQueueIterator<'a> { |
|
77 timestamp: u32, |
|
78 queue: &'a mut MessagesQueue, |
|
79 } |
|
80 |
|
81 impl<'a> Iterator for MessagesQueueIterator<'a> { |
|
82 type Item = EngineMessage; |
|
83 |
|
84 fn next(&mut self) -> Option<EngineMessage> { |
|
85 self.queue.pop(self.timestamp) |
|
86 } |
|
87 } |
|
88 |
|
89 #[test] |
|
90 fn queue_order() { |
|
91 use crate::messages::UnorderedEngineMessage::*; |
|
92 |
|
93 let mut queue = MessagesQueue::new(QueueChatStrategy::LocalGame); |
|
94 |
|
95 queue.push(Synced(Skip, 1)); |
|
96 queue.push(Unsynced(ChatMessage("hi".to_string()))); |
|
97 queue.push(Synced(TimeWrap, 65535)); |
|
98 queue.push(Unordered(Ping)); |
|
99 queue.push(Synced(Skip, 2)); |
|
100 |
|
101 let zero_tick: Vec<EngineMessage> = queue.iter(0).collect(); |
|
102 assert_eq!(zero_tick, vec![Unordered(Ping)]); |
|
103 assert_eq!(queue.pop(1), Some(Synced(Skip, 1))); |
|
104 assert_eq!(queue.pop(1), Some(Unsynced(ChatMessage("hi".to_string())))); |
|
105 assert_eq!(queue.pop(1), None); |
|
106 assert_eq!(queue.pop(2), None); |
|
107 assert_eq!(queue.pop(65535), Some(Synced(TimeWrap, 65535))); |
|
108 assert_eq!(queue.pop(65535), None); |
|
109 assert_eq!(queue.pop(65538), Some(Synced(Skip, 65538))); |
|
110 assert_eq!(queue.pop(65538), None); |
|
111 assert_eq!(queue.pop(65539), None); |
|
112 } |