diff options
Diffstat (limited to 'server')
-rw-r--r-- | server/bot/src/algos/customer.rs | 13 | ||||
-rw-r--r-- | server/bot/src/algos/simple.rs | 13 | ||||
-rw-r--r-- | server/bot/src/main.rs | 3 | ||||
-rw-r--r-- | server/client-lib/src/lib.rs | 21 | ||||
-rw-r--r-- | server/protocol/src/helpers.rs | 30 | ||||
-rw-r--r-- | server/protocol/src/lib.rs | 10 | ||||
-rw-r--r-- | server/src/entity/bot.rs | 3 | ||||
-rw-r--r-- | server/src/entity/tutorial.rs | 4 | ||||
-rw-r--r-- | server/src/server.rs | 127 |
9 files changed, 145 insertions, 79 deletions
diff --git a/server/bot/src/algos/customer.rs b/server/bot/src/algos/customer.rs index b243bd55..826ab534 100644 --- a/server/bot/src/algos/customer.rs +++ b/server/bot/src/algos/customer.rs @@ -22,7 +22,7 @@ use crate::{ use hurrycurry_client_lib::Game; use hurrycurry_protocol::{ glam::{IVec2, Vec2}, - DemandIndex, Message, PacketS, PlayerClass, PlayerID, Score, + DemandIndex, Hand, Message, PacketS, PlayerClass, PlayerID, Score, }; use log::info; use rand::{random, seq::IndexedRandom, thread_rng}; @@ -313,6 +313,7 @@ impl CustomerState { PacketS::Interact { pos: Some(pos), player: me, + hand: Hand::Left, }, PacketS::ApplyScore(Score { demands_completed: 1, @@ -322,6 +323,7 @@ impl CustomerState { PacketS::Interact { pos: None, player: me, + hand: Hand::Left, }, ], ..Default::default() @@ -354,6 +356,7 @@ impl CustomerState { extra: vec![PacketS::ReplaceHand { player: me, item: demand.output, + hand: Hand::Left, }], ..Default::default() }; @@ -369,7 +372,11 @@ impl CustomerState { cooldown, } => { *cooldown -= dt; - if game.players.get(&me).is_some_and(|pl| pl.item.is_none()) { + if game + .players + .get(&me) + .is_some_and(|pl| pl.items[Hand::Left.index()].is_none()) + { if let Some(path) = find_path(&game.walkable, pos.as_ivec2(), *origin) { *self = CustomerState::Exiting { path }; } @@ -383,10 +390,12 @@ impl CustomerState { PacketS::Interact { player: me, pos: Some(*table), + hand: Hand::Left, }, PacketS::Interact { player: me, pos: None, + hand: Hand::Left, }, ], direction, diff --git a/server/bot/src/algos/simple.rs b/server/bot/src/algos/simple.rs index 14eb38c4..5a7e61a0 100644 --- a/server/bot/src/algos/simple.rs +++ b/server/bot/src/algos/simple.rs @@ -21,7 +21,7 @@ use crate::{ }; use hurrycurry_client_lib::Game; use hurrycurry_protocol::{ - glam::IVec2, ItemIndex, Message, PlayerID, Recipe, RecipeIndex, TileIndex, + glam::IVec2, Hand, ItemIndex, Message, PlayerID, Recipe, RecipeIndex, TileIndex, }; use log::{debug, warn}; @@ -106,16 +106,17 @@ impl State for Simple { impl<S> Context<'_, S> { pub fn is_hand_item(&self, item: ItemIndex) -> bool { - self.game - .players - .get(&self.me) - .is_some_and(|p| p.item.as_ref().is_some_and(|i| i.kind == item)) + self.game.players.get(&self.me).is_some_and(|p| { + p.items[Hand::Left.index()] + .as_ref() + .is_some_and(|i| i.kind == item) + }) } pub fn is_hand_occupied(&self) -> bool { self.game .players .get(&self.me) - .map(|p| p.item.is_some()) + .map(|p| p.items[Hand::Left.index()].is_some()) .unwrap_or(false) } pub fn find_demand(&self) -> Option<(ItemIndex, IVec2)> { diff --git a/server/bot/src/main.rs b/server/bot/src/main.rs index 61ae1c1c..0ffbf4b6 100644 --- a/server/bot/src/main.rs +++ b/server/bot/src/main.rs @@ -19,7 +19,7 @@ use anyhow::Result; use clap::Parser; use hurrycurry_bot::{algos::ALGO_CONSTRUCTORS, BotAlgo, BotInput}; use hurrycurry_client_lib::{network::sync::Network, Game}; -use hurrycurry_protocol::{PacketC, PacketS, PlayerClass, PlayerID}; +use hurrycurry_protocol::{Hand, PacketC, PacketS, PlayerClass, PlayerID}; use log::warn; use std::{thread::sleep, time::Duration}; @@ -109,6 +109,7 @@ fn main() -> Result<()> { network.queue_out.push_back(PacketS::Interact { player: b.id, pos: interact, + hand: Hand::Left, }) } network.queue_out.push_back(PacketS::Movement { diff --git a/server/client-lib/src/lib.rs b/server/client-lib/src/lib.rs index 5d5e55d5..54c7cd6e 100644 --- a/server/client-lib/src/lib.rs +++ b/server/client-lib/src/lib.rs @@ -20,8 +20,7 @@ pub mod network; pub mod spatial_index; use hurrycurry_protocol::{ - glam::IVec2, movement::MovementBase, Gamedata, ItemIndex, ItemLocation, Message, - MessageTimeout, PacketC, PlayerClass, PlayerID, RecipeIndex, Score, TileIndex, + glam::IVec2, movement::MovementBase, Gamedata, Hand, ItemIndex, ItemLocation, Message, MessageTimeout, PacketC, PlayerClass, PlayerID, RecipeIndex, Score, TileIndex }; use spatial_index::SpatialIndex; use std::{ @@ -54,8 +53,8 @@ pub struct Player { pub name: String, pub class: PlayerClass, pub character: i32, - pub interacting: Option<IVec2>, - pub item: Option<Item>, + pub interacting: Option<(IVec2, Hand)>, + pub items: [Option<Item>; 2], pub communicate_persist: Option<(Message, MessageTimeout)>, pub movement: MovementBase, @@ -95,7 +94,7 @@ impl Game { character, class, interacting: None, - item: None, + items: [const { None }; 2], communicate_persist: None, movement: MovementBase::new(position), }, @@ -200,9 +199,11 @@ impl Game { } for player in self.players.values_mut() { - if let Some(item) = &mut player.item { - if let Some(active) = &mut item.active { - active.position += active.speed; + for item in &mut player.items { + if let Some(item) = item { + if let Some(active) = &mut item.active { + active.position += active.speed; + } } } } @@ -226,7 +227,9 @@ impl Game { pub fn get_item(&mut self, location: ItemLocation) -> &mut Option<Item> { match location { ItemLocation::Tile(pos) => &mut self.tiles.get_mut(&pos).unwrap().item, - ItemLocation::Player(pid) => &mut self.players.get_mut(&pid).unwrap().item, + ItemLocation::Player(pid, hand) => { + &mut self.players.get_mut(&pid).unwrap().items[hand.index()] + } } } } diff --git a/server/protocol/src/helpers.rs b/server/protocol/src/helpers.rs index 924d0886..21835101 100644 --- a/server/protocol/src/helpers.rs +++ b/server/protocol/src/helpers.rs @@ -1,7 +1,8 @@ use std::fmt::Display; use crate::{ - DocumentElement, Gamedata, ItemIndex, ItemLocation, PlayerID, Recipe, RecipeIndex, TileIndex, + DocumentElement, Gamedata, Hand, ItemIndex, ItemLocation, PlayerID, Recipe, RecipeIndex, + TileIndex, }; impl Gamedata { @@ -98,7 +99,32 @@ impl Display for ItemLocation { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { match self { ItemLocation::Tile(pos) => write!(f, "tile({pos})"), - ItemLocation::Player(PlayerID(id)) => write!(f, "player({id})"), + ItemLocation::Player(PlayerID(id), hand) => write!(f, "player({id}_{hand})"), + } + } +} + +impl Display for Hand { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + f.write_str(match self { + Hand::Left => "left", + Hand::Right => "right", + }) + } +} + +impl Hand { + pub fn index(&self) -> usize { + match self { + Hand::Left => 0, + Hand::Right => 1, + } + } + pub fn from_index(i: usize) -> Self { + match i { + 0 => Hand::Left, + 1 => Hand::Right, + _ => Hand::Left, } } } diff --git a/server/protocol/src/lib.rs b/server/protocol/src/lib.rs index 2ef07015..6ccd2367 100644 --- a/server/protocol/src/lib.rs +++ b/server/protocol/src/lib.rs @@ -71,6 +71,12 @@ pub struct RecipeIndex(pub usize); #[serde(transparent)] pub struct DemandIndex(pub usize); +#[derive(Debug, Clone, Copy, Serialize, Deserialize, Encode, Decode, PartialEq, Eq, Hash)] +pub enum Hand { + Left, + Right, +} + #[derive(Debug, Clone, Serialize, Deserialize, Encode, Decode)] pub struct MapMetadata { pub name: String, @@ -124,6 +130,7 @@ pub enum PacketS { }, Interact { player: PlayerID, + hand: Hand, #[bincode(with_serde)] pos: Option<IVec2>, }, @@ -144,6 +151,7 @@ pub enum PacketS { /// For internal use only (customers) ReplaceHand { player: PlayerID, + hand: Hand, item: Option<ItemIndex>, }, #[serde(skip)] @@ -344,7 +352,7 @@ pub enum Recipe { #[serde(rename_all = "snake_case")] pub enum ItemLocation { Tile(#[bincode(with_serde)] IVec2), - Player(PlayerID), + Player(PlayerID, Hand), } #[derive(Debug, Clone, Serialize, Deserialize, Encode, Decode)] diff --git a/server/src/entity/bot.rs b/server/src/entity/bot.rs index fe4d711f..368f8c9d 100644 --- a/server/src/entity/bot.rs +++ b/server/src/entity/bot.rs @@ -18,7 +18,7 @@ use super::{Entity, EntityContext}; use anyhow::Result; use hurrycurry_bot::{BotAlgo, DynBotAlgo}; -use hurrycurry_protocol::{PacketS, PlayerClass, PlayerID}; +use hurrycurry_protocol::{Hand, PacketS, PlayerClass, PlayerID}; use log::info; use rand::random; use std::any::Any; @@ -72,6 +72,7 @@ impl<T: BotAlgo + Any> Entity for BotDriver<T> { c.packet_in.push_back(PacketS::Interact { player: self.id, pos: input.interact, + hand: Hand::Left, }) } c.packet_in.push_back(PacketS::Movement { diff --git a/server/src/entity/tutorial.rs b/server/src/entity/tutorial.rs index 44244862..33c0e507 100644 --- a/server/src/entity/tutorial.rs +++ b/server/src/entity/tutorial.rs @@ -144,7 +144,7 @@ impl StepContext<'_> { .game .players .get(&self.player) - .is_some_and(|p| p.item.as_ref().is_some_and(|i| i.kind == item)) + .is_some_and(|p| p.items.iter().flatten().any(|i| i.kind == item)) } pub fn find_demand(&self, item: ItemIndex) -> Option<IVec2> { self.ent @@ -228,7 +228,7 @@ impl StepContext<'_> { .game .players .get(&self.player) - .is_some_and(|p| p.item.as_ref().is_some_and(|i| i.kind == item)) + .is_some_and(|p| p.items.iter().flatten().any(|i| i.kind == item)) { if let Some(pos) = self.find_demand(item) { Err((Some(pos), trm!("s.tutorial.serve"))) diff --git a/server/src/server.rs b/server/src/server.rs index 462e95d4..19153864 100644 --- a/server/src/server.rs +++ b/server/src/server.rs @@ -28,8 +28,8 @@ use hurrycurry_client_lib::{Game, Involvement, Item, Player, Tile}; use hurrycurry_protocol::{ glam::{IVec2, Vec2}, movement::MovementBase, - Gamedata, ItemLocation, Menu, MessageTimeout, PacketC, PacketS, PlayerClass, PlayerID, Score, - TileIndex, + Gamedata, Hand, ItemLocation, Menu, MessageTimeout, PacketC, PacketS, PlayerClass, PlayerID, + Score, TileIndex, }; use log::{info, warn}; use rand::random; @@ -163,26 +163,29 @@ impl GameServerExt for Game { character: player.character, name: player.name.clone(), }); - if let Some(item) = &player.item { - out.push(PacketC::SetItem { - location: ItemLocation::Player(id), - item: Some(item.kind), - }); - if let Some(Involvement { - player, - position, - speed, - warn, - .. - }) = item.active - { - out.push(PacketC::SetProgress { + for (i, item) in player.items.iter().enumerate() { + let hand = Hand::from_index(i); + if let Some(item) = &item { + out.push(PacketC::SetItem { + location: ItemLocation::Player(id, hand), + item: Some(item.kind), + }); + if let Some(Involvement { player, - item: ItemLocation::Player(id), position, speed, warn, - }); + .. + }) = item.active + { + out.push(PacketC::SetProgress { + player, + item: ItemLocation::Player(id, hand), + position, + speed, + warn, + }); + } } } if let Some((message, timeout)) = &player.communicate_persist { @@ -252,7 +255,7 @@ impl GameServerExt for Game { self.players.insert( id, Player { - item: None, + items: [const { None }; 2], character, class, movement: MovementBase::new(position), @@ -403,15 +406,18 @@ impl Server { self.game.players_spatial_index.remove_entry(player); - if let Some(item) = p.item { - let pos = p.movement.position.floor().as_ivec2(); - if let Some(tile) = self.game.tiles.get_mut(&pos) { - if tile.item.is_none() { - self.packet_out.push_back(PacketC::SetItem { - location: ItemLocation::Tile(pos), - item: Some(item.kind), - }); - tile.item = Some(item); + // TODO if holding two, one is destroyed + for item in p.items { + if let Some(item) = item { + let pos = p.movement.position.floor().as_ivec2(); + if let Some(tile) = self.game.tiles.get_mut(&pos) { + if tile.item.is_none() { + self.packet_out.push_back(PacketC::SetItem { + location: ItemLocation::Tile(pos), + item: Some(item.kind), + }); + tile.item = Some(item); + } } } } @@ -449,7 +455,7 @@ impl Server { } } } - PacketS::Interact { pos, player } => { + PacketS::Interact { pos, player, hand } => { for e in &mut self.entities { if e.interact( EntityContext { @@ -477,7 +483,9 @@ impl Server { .get_mut(&pid) .ok_or(tre!("s.error.no_player"))?; - let (pos, edge) = match (pos, player.interacting) { + let pos = pos.map(|p| (p, hand)); + + let ((pos, hand), edge) = match (pos, player.interacting) { (None, None) => return Ok(()), // this is silent because of auto release (None, Some(pos)) => (pos, false), (Some(pos), None) => (pos, true), @@ -497,7 +505,7 @@ impl Server { // No going back from here on - player.interacting = if edge { Some(pos) } else { None }; + player.interacting = if edge { Some((pos, hand)) } else { None }; let other_pid = if !self.game.data.is_tile_interactable(tile.kind) { self.game @@ -528,10 +536,10 @@ impl Server { edge, None, Some(pid), - &mut this.item, - ItemLocation::Player(base_pid), - &mut other.item, - ItemLocation::Player(pid), + &mut this.items[hand.index()], + ItemLocation::Player(base_pid, hand), + &mut other.items[hand.index()], + ItemLocation::Player(pid, hand), &mut self.game.score, &mut self.score_changed, false, @@ -551,8 +559,8 @@ impl Server { Some(pid), &mut tile.item, ItemLocation::Tile(pos), - &mut player.item, - ItemLocation::Player(pid), + &mut player.items[hand.index()], + ItemLocation::Player(pid, hand), &mut self.game.score, &mut self.score_changed, false, @@ -592,14 +600,14 @@ impl Server { timeout, }); } - PacketS::ReplaceHand { item, player } => { + PacketS::ReplaceHand { item, player, hand } => { let pdata = self.game.players.get_mut(&player).ok_or(tre!(""))?; - pdata.item = item.map(|i| Item { + pdata.items[hand.index()] = item.map(|i| Item { kind: i, active: None, }); self.packet_out.push_back(PacketC::SetItem { - location: ItemLocation::Player(player), + location: ItemLocation::Player(player, hand), item, }) } @@ -665,17 +673,19 @@ impl Server { rot: player.movement.rotation, }); - tick_slot( - dt, - &self.game.data, - &self.gamedata_index, - None, - &mut player.item, - ItemLocation::Player(pid), - &mut self.game.score, - &mut self.score_changed, - &mut self.packet_out, - ); + for (i, item) in player.items.iter_mut().enumerate() { + tick_slot( + dt, + &self.game.data, + &self.gamedata_index, + None, + item, + ItemLocation::Player(pid, Hand::from_index(i)), + &mut self.game.score, + &mut self.score_changed, + &mut self.packet_out, + ); + } } let mut players_auto_release = Vec::new(); @@ -686,20 +696,27 @@ impl Server { player.communicate_persist = None; } } - if let Some(pos) = player.interacting { + if let Some((pos, hand)) = player.interacting { if let Some(tile) = self.game.tiles.get(&pos) { if let Some(item) = &tile.item { if let Some(involvement) = &item.active { if involvement.position >= 1. { - players_auto_release.push(*pid); + players_auto_release.push((*pid, hand)); } } } } } } - for player in players_auto_release.drain(..) { - let _ = self.packet_in(PacketS::Interact { pos: None, player }, &mut vec![]); + for (player, hand) in players_auto_release.drain(..) { + let _ = self.packet_in( + PacketS::Interact { + pos: None, + player, + hand, + }, + &mut vec![], + ); } let mut load_map = None; |