aboutsummaryrefslogtreecommitdiff
path: root/server/src/entity/tram.rs
diff options
context:
space:
mode:
Diffstat (limited to 'server/src/entity/tram.rs')
-rw-r--r--server/src/entity/tram.rs95
1 files changed, 95 insertions, 0 deletions
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 })
+ }
+ }
+}