diff options
| author | metamuffin <metamuffin@disroot.org> | 2024-12-23 15:37:11 +0100 | 
|---|---|---|
| committer | metamuffin <metamuffin@disroot.org> | 2024-12-23 15:37:11 +0100 | 
| commit | 1a9f7e9a20bff0fbc854454f131d4bc546e73e72 (patch) | |
| tree | 7be16db47cd819177ae73d42af7b59c37593060a /server | |
| parent | bd71cd120fa4d8caf4987fd9c76838ccbeec19f7 (diff) | |
| download | hurrycurry-1a9f7e9a20bff0fbc854454f131d4bc546e73e72.tar hurrycurry-1a9f7e9a20bff0fbc854454f131d4bc546e73e72.tar.bz2 hurrycurry-1a9f7e9a20bff0fbc854454f131d4bc546e73e72.tar.zst | |
two-handed server
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 9928ac90..9b90d6b3 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), @@ -399,15 +402,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); +                            }                          }                      }                  } @@ -445,7 +451,7 @@ impl Server {                      }                  }              } -            PacketS::Interact { pos, player } => { +            PacketS::Interact { pos, player, hand } => {                  for e in &mut self.entities {                      if e.interact(                          EntityContext { @@ -473,7 +479,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), @@ -493,7 +501,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 @@ -524,10 +532,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, @@ -547,8 +555,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, @@ -588,14 +596,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,                  })              } @@ -661,17 +669,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(); @@ -682,20 +692,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; | 
