aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--data/maps/debug.yaml4
-rw-r--r--data/maps/debug2.yaml112
-rw-r--r--server/src/entity/mod.rs12
-rw-r--r--server/src/entity/tram.rs95
4 files changed, 223 insertions, 0 deletions
diff --git a/data/maps/debug.yaml b/data/maps/debug.yaml
index 90cd3480..2e902315 100644
--- a/data/maps/debug.yaml
+++ b/data/maps/debug.yaml
@@ -102,6 +102,10 @@ entities:
- !environment_effect { name: rain, on: 60, off: 40 }
- !environment_effect { name: wind, on: 60, off: 40 }
- !environment [night]
+ - !tram
+ length: 3
+ character: 51
+ points: [[1, 2], [15, 2], [15, 8], [1, 8]]
tile_entities:
"}": !conveyor { dir: [1, 0], filter: dough-foodprocessor }
diff --git a/data/maps/debug2.yaml b/data/maps/debug2.yaml
new file mode 100644
index 00000000..1968c8ca
--- /dev/null
+++ b/data/maps/debug2.yaml
@@ -0,0 +1,112 @@
+# Hurry Curry! - a game about cooking
+# Copyright 2024 metamuffin
+# Copyright 2024 nokoe
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Affero General Public License as published by
+# the Free Software Foundation, version 3 of the License only.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Affero General Public License for more details.
+#
+# You should have received a copy of the GNU Affero General Public License
+# along with this program. If not, see <https://www.gnu.org/licenses/>.
+#
+score_baseline: 100000
+map:
+ - "........................"
+ - "...~...................."
+ - "........................"
+ - "........................"
+ - "........................"
+ - "........................"
+ - "........................"
+ - "........................"
+ - "........................"
+ - ".............'''''''''''"
+ - ".............''''''''.''"
+ - ".............''l''''''''"
+ - ".............'''''''''''"
+ - ".............''l''''''''"
+ - ".............'''''''''''"
+ - ".............''l''''''''"
+ - ".............'''''''''''"
+ - ".............'''''''''''"
+
+tiles:
+ "⌷": counter
+ "f": counter
+ "p": counter
+ "t": table
+ "w": counter-window
+ "s": sink
+ "o": oven
+ "z": freezer
+ "S": stove
+ "b": book
+ "C": cuttingboard
+ "0": rice-crate
+ "1": steak-crate
+ "2": tomato-crate
+ "3": leek-crate
+ "4": coconut-crate
+ "5": strawberry-crate
+ "6": flour-crate
+ "7": fish-crate
+ "8": cheese-crate
+ "9": lettuce-crate
+ "X": trash
+
+ "¹": black-hole-counter
+ "²": white-hole-counter
+ "³": black-hole
+ "⁴": white-hole
+ "l": lamp
+ "c": chair
+ "~": floor
+ ".": floor
+ "'": grass
+ "*": tree
+ "!": path
+ "_": path
+ "d": door
+ "▒": wall-window
+ "█": wall
+
+items:
+ "S": pot
+ "w": plate
+ "p": plate
+ "f": foodprocessor
+ "}": foodprocessor
+ "]": foodprocessor
+ "ö": pot
+
+entities:
+ - !environment_effect { name: rain, on: 60, off: 40 }
+ - !environment_effect { name: wind, on: 60, off: 40 }
+ - !tram
+ length: 3
+ character: 51
+ points: [[1, 2], [15, 2], [15, 8], [1, 8]]
+
+chef_spawn: "~"
+customer_spawn: "!"
+
+walkable:
+ - door
+ - floor
+ - chair
+ - grass
+ - path
+ - black-hole
+ - chandelier
+
+collider:
+ - wall
+ - wall-window
+ - tree
+ - lamp
+ - white-hole
diff --git a/server/src/entity/mod.rs b/server/src/entity/mod.rs
index 044fccab..60f02d2a 100644
--- a/server/src/entity/mod.rs
+++ b/server/src/entity/mod.rs
@@ -23,6 +23,7 @@ pub mod customers;
pub mod environment_effect;
pub mod item_portal;
pub mod player_portal;
+pub mod tram;
pub mod tutorial;
use crate::{
@@ -45,6 +46,7 @@ use item_portal::ItemPortal;
use player_portal::PlayerPortal;
use serde::{Deserialize, Serialize};
use std::{any::Any, collections::VecDeque};
+use tram::Tram;
pub type DynEntity = Box<dyn Entity + Send + Sync + 'static>;
pub type Entities = Vec<DynEntity>;
@@ -133,6 +135,11 @@ pub enum EntityDecl {
location: Option<IVec2>,
condition: GateCondition,
},
+ Tram {
+ length: usize,
+ character: Option<i32>,
+ points: Vec<Vec2>,
+ },
Book,
}
@@ -198,5 +205,10 @@ pub fn construct_entity(
}
EntityDecl::EnvironmentEffect(config) => Box::new(EnvironmentEffectController::new(config)),
EntityDecl::Environment(names) => Box::new(EnvironmentController(names)),
+ EntityDecl::Tram {
+ length,
+ character,
+ points,
+ } => Box::new(Tram::new(character.unwrap_or(51), length, points)),
})
}
diff --git a/server/src/entity/tram.rs b/server/src/entity/tram.rs
new file mode 100644
index 00000000..27c3bcbb
--- /dev/null
+++ b/server/src/entity/tram.rs
@@ -0,0 +1,95 @@
+/*
+ Hurry Curry! - a game about cooking
+ Copyright 2025 metamuffin
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Affero General Public License as published by
+ the Free Software Foundation, version 3 of the License only.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Affero General Public License for more details.
+
+ You should have received a copy of the GNU Affero General Public License
+ along with this program. If not, see <https://www.gnu.org/licenses/>.
+
+*/
+use super::{Entity, EntityContext};
+use anyhow::Result;
+use hurrycurry_protocol::{glam::Vec2, PacketS, PlayerClass, PlayerID};
+use rand::random;
+
+pub struct Tram {
+ length: usize,
+ character: i32,
+ ids: Vec<PlayerID>,
+ points: Vec<Vec2>,
+ index: usize,
+}
+
+impl Tram {
+ pub fn new(character: i32, length: usize, points: Vec<Vec2>) -> Self {
+ Self {
+ character,
+ ids: Vec::new(),
+ length,
+ points,
+ index: 0,
+ }
+ }
+}
+impl Entity for Tram {
+ fn finished(&self) -> bool {
+ false
+ }
+ fn tick(&mut self, c: EntityContext<'_>) -> Result<()> {
+ if self.ids.is_empty() {
+ for i in 0..self.length {
+ let id = PlayerID(random());
+ c.packet_in.push_back(PacketS::Join {
+ name: format!("Tram {i}"),
+ character: self.character,
+ class: PlayerClass::Bot,
+ id: Some(id),
+ });
+ self.ids.push(id);
+ }
+ }
+
+ let mut ppos = None;
+ for id in &self.ids {
+ if let Some(p) = c.game.players.get(id) {
+ let target = if let Some(pos) = ppos {
+ pos
+ } else {
+ let tar = self.points[self.index];
+ if p.movement.position.distance(tar) < 2. {
+ self.index += 1;
+ self.index %= self.points.len();
+ }
+ tar
+ };
+ ppos = Some(p.movement.position);
+ let dir = if p.movement.position.distance(target) > 2. {
+ target - p.movement.position
+ } else {
+ Vec2::ZERO
+ };
+ c.packet_in.push_back(PacketS::Movement {
+ player: *id,
+ dir,
+ boost: false,
+ pos: None,
+ });
+ }
+ }
+
+ Ok(())
+ }
+ fn destructor(&mut self, c: EntityContext<'_>) {
+ for id in self.ids.drain(..) {
+ c.packet_in.push_back(PacketS::Leave { player: id })
+ }
+ }
+}