summaryrefslogtreecommitdiff
path: root/server/src
diff options
context:
space:
mode:
authormetamuffin <metamuffin@noreply.codeberg.org>2024-12-25 19:05:05 +0000
committermetamuffin <metamuffin@noreply.codeberg.org>2024-12-25 19:05:05 +0000
commitcc6b50debb9d5b740adbe6f803755413c972659a (patch)
treeb34a0a5669707992f1334f88a1959d5b1e120415 /server/src
parent2ceeea0e5fc245602618ec47f6ff1f91a094e130 (diff)
parent53cf167c08986caf346957d1f357cefaee1bd6b5 (diff)
downloadhurrycurry-cc6b50debb9d5b740adbe6f803755413c972659a.tar
hurrycurry-cc6b50debb9d5b740adbe6f803755413c972659a.tar.bz2
hurrycurry-cc6b50debb9d5b740adbe6f803755413c972659a.tar.zst
Merge pull request 'Two-handed players' (#236) from two-handed into master
Reviewed-on: https://codeberg.org/hurrycurry/hurrycurry/pulls/236
Diffstat (limited to 'server/src')
-rw-r--r--server/src/data/mod.rs2
-rw-r--r--server/src/entity/bot.rs3
-rw-r--r--server/src/entity/tutorial.rs4
-rw-r--r--server/src/server.rs142
4 files changed, 90 insertions, 61 deletions
diff --git a/server/src/data/mod.rs b/server/src/data/mod.rs
index 57051fe9..64f40217 100644
--- a/server/src/data/mod.rs
+++ b/server/src/data/mod.rs
@@ -73,6 +73,7 @@ pub struct MapDecl {
walkable: Vec<String>,
chef_spawn: char,
customer_spawn: char,
+ #[serde(default)] hand_count: Option<usize>,
#[serde(default)] entities: Vec<EntityDecl>,
#[serde(default)] tile_entities: HashMap<char, EntityDecl>,
#[serde(default)] score_baseline: i64,
@@ -314,6 +315,7 @@ pub fn build_data(
item_names,
demands,
tile_names,
+ hand_count: map_in.hand_count.unwrap_or(1),
},
Serverdata {
initial_map,
diff --git a/server/src/entity/bot.rs b/server/src/entity/bot.rs
index fe4d711f..6e6c9162 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(0),
})
}
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..0889cd71 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,28 @@ 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() {
+ if let Some(item) = &item {
+ out.push(PacketC::SetItem {
+ location: ItemLocation::Player(id, Hand(i)),
+ 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(i)),
+ position,
+ speed,
+ warn,
+ });
+ }
}
}
if let Some((message, timeout)) = &player.communicate_persist {
@@ -252,7 +254,7 @@ impl GameServerExt for Game {
self.players.insert(
id,
Player {
- item: None,
+ items: (0..self.data.hand_count).map(|_| None).collect(),
character,
class,
movement: MovementBase::new(position),
@@ -403,15 +405,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 +454,7 @@ impl Server {
}
}
}
- PacketS::Interact { pos, player } => {
+ PacketS::Interact { pos, player, hand } => {
for e in &mut self.entities {
if e.interact(
EntityContext {
@@ -477,7 +482,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 +504,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
@@ -523,15 +530,18 @@ impl Server {
return Err(tre!("s.error.customer_interact"));
}
+ let this_hslot = this.items.get_mut(hand.0).ok_or(tre!("s.error.no_hand"))?;
+ let other_hslot = other.items.get_mut(hand.0).ok_or(tre!("s.error.no_hand"))?;
+
interact(
&self.game.data,
edge,
None,
Some(pid),
- &mut this.item,
- ItemLocation::Player(base_pid),
- &mut other.item,
- ItemLocation::Player(pid),
+ this_hslot,
+ ItemLocation::Player(base_pid, hand),
+ other_hslot,
+ ItemLocation::Player(pid, hand),
&mut self.game.score,
&mut self.score_changed,
false,
@@ -544,6 +554,11 @@ impl Server {
.get_mut(&pid)
.ok_or(tre!("s.error.no_player"))?;
+ let hslot = player
+ .items
+ .get_mut(hand.0)
+ .ok_or(tre!("s.error.no_hand"))?;
+
interact(
&self.game.data,
edge,
@@ -551,8 +566,8 @@ impl Server {
Some(pid),
&mut tile.item,
ItemLocation::Tile(pos),
- &mut player.item,
- ItemLocation::Player(pid),
+ hslot,
+ ItemLocation::Player(pid, hand),
&mut self.game.score,
&mut self.score_changed,
false,
@@ -592,14 +607,16 @@ 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 {
- kind: i,
- active: None,
- });
+ if let Some(slot) = pdata.items.get_mut(hand.0) {
+ *slot = 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 +682,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(i)),
+ &mut self.game.score,
+ &mut self.score_changed,
+ &mut self.packet_out,
+ );
+ }
}
let mut players_auto_release = Vec::new();
@@ -686,20 +705,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;