diff options
Diffstat (limited to 'server/src')
| -rw-r--r-- | server/src/commands.rs | 3 | ||||
| -rw-r--r-- | server/src/entity/bot.rs | 106 | ||||
| -rw-r--r-- | server/src/entity/customers.rs | 6 | ||||
| -rw-r--r-- | server/src/server.rs | 1 | ||||
| -rw-r--r-- | server/src/state.rs | 23 |
5 files changed, 73 insertions, 66 deletions
diff --git a/server/src/commands.rs b/server/src/commands.rs index 0a7b7643..f8016c9f 100644 --- a/server/src/commands.rs +++ b/server/src/commands.rs @@ -283,7 +283,6 @@ impl Server { .iter() .find(|(name, _)| *name == algo.as_str()) .ok_or(tre!("s.error.algo_not_found", s = algo))?; - let algo = cons(); self.entities.push(Box::new(BotDriver::new( format!("{}-bot", name.unwrap_or((*aname).to_owned())), Character { @@ -292,7 +291,7 @@ impl Server { headwear: 0, }, PlayerClass::Bot, - algo, + cons, ))); } Command::Scoreboard { map, text } => { diff --git a/server/src/entity/bot.rs b/server/src/entity/bot.rs index 51a09b62..36f701ec 100644 --- a/server/src/entity/bot.rs +++ b/server/src/entity/bot.rs @@ -17,77 +17,85 @@ */ use super::{Entity, EntityContext}; use anyhow::Result; -use hurrycurry_bot::{BotAlgo, DynBotAlgo}; +use hurrycurry_bot::{BotAlgo, DynBotAlgo, PacketSink}; use hurrycurry_locale::TrError; -use hurrycurry_protocol::{Character, Hand, ItemLocation, PacketS, PlayerClass, PlayerID}; +use hurrycurry_protocol::{Character, PacketS, PlayerClass, PlayerID}; use log::debug; use std::any::Any; pub type DynBotDriver = BotDriver<DynBotAlgo>; -pub struct BotDriver<T> { - algo: T, - join_data: Option<(String, Character, PlayerClass)>, - id: PlayerID, - interacting: bool, - left: bool, +pub enum BotDriver<T> { + Joining { + name: String, + character: Character, + class: PlayerClass, + constructor: Option<Box<dyn FnOnce(PlayerID) -> T + Send + Sync>>, + }, + Running { + state: T, + id: PlayerID, + }, + Left, } impl<T: BotAlgo> BotDriver<T> { - pub fn new(name: String, character: Character, class: PlayerClass, algo: T) -> Self { - Self { - algo, - id: PlayerID(0), - interacting: false, - join_data: Some((name, character, class)), - left: false, + pub fn new( + name: String, + character: Character, + class: PlayerClass, + constructor: impl FnOnce(PlayerID) -> T + 'static + Send + Sync, + ) -> Self { + Self::Joining { + character, + class, + constructor: Some(Box::new(constructor)), + name, } } } impl<T: BotAlgo + Any> Entity for BotDriver<T> { fn finished(&self) -> bool { - self.left + matches!(self, Self::Left) } fn tick(&mut self, c: EntityContext<'_>) -> Result<(), TrError> { - if let Some((name, character, class)) = self.join_data.take() { - self.id = c.game.get_unused_player_id(); // TODO clashes when multiple bots join in the same tick - debug!("join {}", self.id); - c.packet_in.push_back(PacketS::Join { + match self { + BotDriver::Joining { name, character, - id: Some(self.id), class, - position: None, - }) + constructor, + } => { + let id = c.game.get_unused_player_id(); // TODO clashes when multiple bots join in the same tick + debug!("enter {id}"); + c.packet_in.push_back(PacketS::Join { + name: name.to_string(), + character: *character, + id: Some(id), + class: *class, + position: None, + }); + *self = BotDriver::Running { + state: constructor.take().unwrap()(id), + id, + }; + Ok(()) + } + BotDriver::Running { state, id } => { + state.tick(PacketSink::new(c.packet_in), c.game, c.dt); + if state.is_finished() { + debug!("leave {id}"); + c.packet_in.push_back(PacketS::Leave { player: *id }); + *self = BotDriver::Left + } + Ok(()) + } + BotDriver::Left => Ok(()), } - - let input = self.algo.tick(self.id, c.game, c.dt); - if input.leave { - debug!("leave {}", self.id); - c.packet_in.push_back(PacketS::Leave { player: self.id }); - self.left = true; - return Ok(()); - } - if input.interact.is_some() != self.interacting { - self.interacting = input.interact.is_some(); - c.packet_in.push_back(PacketS::Interact { - player: self.id, - target: input.interact.map(ItemLocation::Tile), - hand: Hand(0), - }) - } - c.packet_in.push_back(PacketS::Movement { - player: self.id, - dir: input.direction, - boost: input.boost, - pos: None, - }); - c.packet_in.extend(input.extra); - Ok(()) } fn destructor(&mut self, c: EntityContext<'_>) { - if self.join_data.is_none() && !self.left { - c.packet_in.push_back(PacketS::Leave { player: self.id }) + if let Self::Running { id, .. } = self { + c.packet_in.push_back(PacketS::Leave { player: *id }) } } } diff --git a/server/src/entity/customers.rs b/server/src/entity/customers.rs index 36afe24a..e527580c 100644 --- a/server/src/entity/customers.rs +++ b/server/src/entity/customers.rs @@ -18,7 +18,7 @@ use super::{Entity, EntityContext, bot::BotDriver}; use crate::random_float; use anyhow::Result; -use hurrycurry_bot::algos::{Customer, CustomerConfig}; +use hurrycurry_bot::algos::Customer; use hurrycurry_locale::TrError; use hurrycurry_protocol::{Character, PlayerClass}; use std::random::random; @@ -64,9 +64,7 @@ impl Entity for Customers { headwear: 0, }, PlayerClass::Customer, - Customer::new(CustomerConfig { - unknown_order: !c.serverdata.flags.disable_unknown_orders, - }), + |id| Customer::new(id), ); self.customers.push(bot) } diff --git a/server/src/server.rs b/server/src/server.rs index 12b45aa1..ae4e82d8 100644 --- a/server/src/server.rs +++ b/server/src/server.rs @@ -615,6 +615,7 @@ impl Server { } PacketS::ReplayTick { .. } => return Err(tre!("s.error.packet_not_supported")), PacketS::Idle { .. } | PacketS::Ready => (), + PacketS::Debug(d) => self.packet_out.push_back(PacketC::Debug(d)), } Ok(()) } diff --git a/server/src/state.rs b/server/src/state.rs index 1e01036c..001e2bf0 100644 --- a/server/src/state.rs +++ b/server/src/state.rs @@ -236,16 +236,17 @@ impl Server { fn get_packet_player(packet: &PacketS) -> Option<PlayerID> { match packet { - PacketS::Join { .. } => None, - PacketS::Idle { .. } => None, - PacketS::Leave { player } => Some(*player), - PacketS::Movement { player, .. } => Some(*player), - PacketS::Interact { player, .. } => Some(*player), - PacketS::Communicate { player, .. } => Some(*player), - PacketS::ReplaceHand { player, .. } => Some(*player), - PacketS::Effect { player, .. } => Some(*player), - PacketS::Ready => None, - PacketS::ApplyScore(_) => None, - PacketS::ReplayTick { .. } => None, + PacketS::Leave { player } + | PacketS::Movement { player, .. } + | PacketS::Interact { player, .. } + | PacketS::Communicate { player, .. } + | PacketS::ReplaceHand { player, .. } + | PacketS::Effect { player, .. } => Some(*player), + PacketS::Join { .. } + | PacketS::Idle { .. } + | PacketS::Ready + | PacketS::ApplyScore(_) + | PacketS::ReplayTick { .. } + | PacketS::Debug(_) => None, } } |