1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
|
use std::time::Duration;
use crate::{
data::DataIndex,
game::Game,
protocol::{Message, PacketC, PacketS, PlayerID},
};
use anyhow::{anyhow, bail, Result};
use clap::Parser;
use log::debug;
use tokio::sync::broadcast::Sender;
pub struct State {
index: DataIndex,
tx: Sender<PacketC>,
pub game: Game,
}
#[derive(Parser)]
#[clap(multicall = true)]
enum Command {
Start {
#[arg(default_value = "small-default-default")]
spec: String,
#[arg(default_value = "420")]
timer: u64,
},
List,
Effect {
name: String,
},
Reload,
End,
}
impl State {
pub fn new(tx: Sender<PacketC>) -> Result<Self> {
let mut index = DataIndex::default();
index.reload()?;
let mut game = Game::new();
game.load(index.generate("lobby-none-none".to_string())?, None);
Ok(Self { game, index, tx })
}
pub async fn tick(&mut self, dt: f32) -> anyhow::Result<()> {
if self.game.tick(dt) {
self.tx
.send(PacketC::ServerMessage {
text: format!("Game finished. You reached {} points.", self.game.points),
})
.ok();
self.game
.load(self.index.generate("lobby-none-none".to_string())?, None);
}
while let Some(p) = self.game.packet_out() {
debug!("-> {p:?}");
let _ = self.tx.send(p);
}
Ok(())
}
pub async fn packet_in(&mut self, player: PlayerID, packet: PacketS) -> Result<Vec<PacketC>> {
match &packet {
PacketS::Communicate {
message: Some(Message::Text(text)),
persist: false,
} if let Some(command) = text.strip_prefix("/") => {
match self.handle_command_parse(player, command).await {
Ok(()) => return Ok(vec![]),
Err(e) => {
return Ok(vec![PacketC::ServerMessage {
text: format!("{e}"),
}]);
}
}
}
_ => (),
}
self.game.packet_in(player, packet)?;
Ok(vec![])
}
async fn handle_command_parse(&mut self, player: PlayerID, command: &str) -> Result<()> {
self.handle_command(
player,
Command::try_parse_from(
shlex::split(command)
.ok_or(anyhow!("quoting invalid"))?
.into_iter(),
)?,
)
.await?;
Ok(())
}
async fn handle_command(&mut self, player: PlayerID, command: Command) -> Result<()> {
match command {
Command::Start { spec, timer } => {
let data = self.index.generate(spec)?;
self.game.load(data, Some(Duration::from_secs(timer)));
}
Command::End => {
self.tx
.send(PacketC::ServerMessage {
text: format!(
"Game was aborted by {}.",
self.game
.players
.get(&player)
.ok_or(anyhow!("player missing"))?
.name
),
})
.ok();
self.game
.load(self.index.generate("lobby-none-none".to_string())?, None);
}
Command::Reload => {
self.index.reload()?;
}
Command::List => {
bail!(
"Maps: {:?}\nDemands: {:?}\nRecipes: {:?}",
self.index.maps,
self.index.demands,
self.index.recipes
)
}
Command::Effect { name } => {
self.tx
.send(PacketC::Communicate {
player,
message: Some(Message::Effect(name)),
persist: false,
})
.ok();
}
}
Ok(())
}
}
|