aboutsummaryrefslogtreecommitdiff
path: root/server/game-core
diff options
context:
space:
mode:
authormetamuffin <metamuffin@disroot.org>2026-01-10 17:16:03 +0100
committertpart <tpart120@proton.me>2026-02-26 20:48:35 +0100
commitb634bad931f530ee0a207e1461ffc5e52ebb83e3 (patch)
tree90a45e8c67e6a7c66e49c7409f0c37881eade96e /server/game-core
parent0ed9e8387a66b3af78412feea62fdc8b9804f793 (diff)
downloadhurrycurry-b634bad931f530ee0a207e1461ffc5e52ebb83e3.tar
hurrycurry-b634bad931f530ee0a207e1461ffc5e52ebb83e3.tar.bz2
hurrycurry-b634bad931f530ee0a207e1461ffc5e52ebb83e3.tar.zst
compiles with tile stacks
Diffstat (limited to 'server/game-core')
-rw-r--r--server/game-core/src/gamedata_index.rs2
-rw-r--r--server/game-core/src/interaction.rs30
-rw-r--r--server/game-core/src/lib.rs85
3 files changed, 72 insertions, 45 deletions
diff --git a/server/game-core/src/gamedata_index.rs b/server/game-core/src/gamedata_index.rs
index 8aa5e4af..d4bbcce1 100644
--- a/server/game-core/src/gamedata_index.rs
+++ b/server/game-core/src/gamedata_index.rs
@@ -30,7 +30,7 @@ impl GamedataIndex {
self.tile_collide.clear();
for tile in (0..data.tile_names.len()).map(TileIndex) {
- self.tile_collide.push(!data.tile_walkable.contains(&tile));
+ self.tile_collide.push(!data.tile_collide.contains(&tile));
}
for (ri, r) in data.recipes() {
diff --git a/server/game-core/src/interaction.rs b/server/game-core/src/interaction.rs
index 275e87d1..28efc43e 100644
--- a/server/game-core/src/interaction.rs
+++ b/server/game-core/src/interaction.rs
@@ -33,9 +33,13 @@ impl Game {
ItemLocation::Player(pid, _) => Some(pid),
_ => None,
};
- let this_tile_kind = match this_loc {
- ItemLocation::Tile(t) => self.tiles.get(&t).map(|t| t.kind),
- _ => None,
+ let this_tile_parts = match this_loc {
+ ItemLocation::Tile(t) => self
+ .tiles
+ .get(&t)
+ .map(|t| t.parts.clone())
+ .unwrap_or_default(),
+ _ => Vec::new(),
};
let (this_slot, other_slot) = match (this_loc, other_loc) {
@@ -94,7 +98,7 @@ impl Game {
&& let Some(inv) = &mut item.active
{
let recipe = &self.data.recipe(inv.recipe);
- if recipe.supports_tile(this_tile_kind)
+ if this_tile_parts.iter().any(|p| recipe.supports_tile(*p))
&& let Recipe::Active { outputs, speed, .. } = recipe
{
if edge {
@@ -142,7 +146,7 @@ impl Game {
return Ok(());
}
for (ri, recipe) in self.data.recipes() {
- if !recipe.supports_tile(this_tile_kind) {
+ if !this_tile_parts.iter().any(|p| recipe.supports_tile(*p)) {
continue;
}
match recipe {
@@ -238,7 +242,7 @@ impl Game {
}
let can_place = automated
- || this_tile_kind.is_none_or(|tile| {
+ || this_tile_parts.iter().any(|tile| {
other_slot.as_ref().is_some_and(|other| {
self.data
.tile_placeable_items
@@ -276,9 +280,13 @@ impl Game {
}
pub fn tick_slot(&mut self, loc: ItemLocation, dt: f32) -> Result<(), TrError> {
- let tile = match loc {
- ItemLocation::Tile(t) => self.tiles.get(&t).map(|t| t.kind),
- _ => None,
+ let parts = match loc {
+ ItemLocation::Tile(t) => self
+ .tiles
+ .get(&t)
+ .map(|t| t.parts.clone())
+ .unwrap_or_default(),
+ _ => Vec::new(),
};
let slot = match loc {
ItemLocation::Tile(p) => {
@@ -303,7 +311,7 @@ impl Game {
let r = &self.data.recipe(a.recipe);
let prev_speed = a.speed;
- if r.supports_tile(tile) {
+ if parts.iter().any(|p| r.supports_tile(*p)) {
if a.speed <= 0.
&& let Recipe::Passive { speed, .. } = &self.data.recipe(a.recipe)
{
@@ -355,7 +363,7 @@ impl Game {
} else if let Some(recipes) = self.data_index.recipe_passive_by_input.get(&item.kind) {
for &ri in recipes {
let recipe = self.data.recipe(ri);
- if recipe.supports_tile(tile)
+ if parts.iter().any(|p| recipe.supports_tile(*p))
&& let Recipe::Passive {
input, warn, speed, ..
} = recipe
diff --git a/server/game-core/src/lib.rs b/server/game-core/src/lib.rs
index a0d4d05d..bee97652 100644
--- a/server/game-core/src/lib.rs
+++ b/server/game-core/src/lib.rs
@@ -47,7 +47,7 @@ pub struct Item {
}
pub struct Tile {
- pub kind: TileIndex,
+ pub parts: Vec<TileIndex>,
pub item: Option<Item>,
}
@@ -82,6 +82,7 @@ pub struct Game {
pub item_locations_index: HashSet<ItemLocation>,
pub events: VecDeque<PacketC>,
+ pub map_changes: HashSet<IVec2>,
}
impl Game {
@@ -165,12 +166,10 @@ impl Game {
});
}
}
- PacketC::UpdateMap {
- tile,
- kind,
- neighbors: _,
- } => {
- self.set_tile(tile, kind);
+ PacketC::UpdateMap { changes } => {
+ for (pos, tiles) in changes {
+ self.set_tile(pos, tiles);
+ }
}
PacketC::Communicate {
player,
@@ -196,32 +195,58 @@ impl Game {
}
}
- pub fn set_tile(&mut self, pos: IVec2, kind: Option<TileIndex>) {
+ pub fn set_tile(&mut self, pos: IVec2, parts: Vec<TileIndex>) {
self.tiles.remove(&pos);
self.walkable.remove(&pos);
- if let Some(prev) = self.tiles.get(&pos)
- && let Some(set) = self.tile_index.get_mut(&prev.kind)
- {
- set.remove(&pos);
- }
- if let Some(kind) = kind {
- self.tiles.insert(pos, Tile { kind, item: None });
- if !self.data_index.tile_collide[kind.0] {
- self.walkable.insert(pos);
+ if let Some(prev) = self.tiles.get(&pos) {
+ for &part in &prev.parts {
+ self.tile_index.entry(part).or_default().remove(&pos);
}
- self.tile_index.entry(kind).or_default().insert(pos);
}
- self.events.push_back(PacketC::UpdateMap {
- tile: pos,
- kind,
- neighbors: [
- self.tiles.get(&(pos + IVec2::NEG_Y)).map(|e| e.kind),
- self.tiles.get(&(pos + IVec2::NEG_X)).map(|e| e.kind),
- self.tiles.get(&(pos + IVec2::Y)).map(|e| e.kind),
- self.tiles.get(&(pos + IVec2::X)).map(|e| e.kind),
- ],
+ if self.data.walkable(&parts) {
+ self.walkable.insert(pos);
+ }
+ for &part in &parts {
+ self.tile_index.entry(part).or_default().insert(pos);
+ }
+ if !parts.is_empty() {
+ self.tiles.insert(pos, Tile { parts, item: None });
+ }
+ self.map_changes.insert(pos);
+ }
+ pub fn add_tile_part(&mut self, pos: IVec2, part: TileIndex) {
+ self.map_changes.insert(pos);
+ let tile = self.tiles.entry(pos).or_insert(Tile {
+ item: None,
+ parts: vec![],
});
+ if tile.parts.contains(&part) {
+ return;
+ }
+ tile.parts.push(part);
+ self.tile_index.entry(part).or_default().insert(pos);
+ self.walkable.remove(&pos);
+ if self.data.walkable(&tile.parts) {
+ self.walkable.insert(pos);
+ }
}
+ pub fn remove_tile_part(&mut self, pos: IVec2, part: TileIndex) {
+ let Some(tile) = self.tiles.get_mut(&pos) else {
+ return;
+ };
+ let lb = tile.parts.len();
+ tile.parts.retain(|&p| p != part);
+ if tile.parts.len() == lb {
+ return;
+ }
+ self.map_changes.insert(pos);
+ self.tile_index.entry(part).or_default().remove(&pos);
+ self.walkable.remove(&pos);
+ if self.data.walkable(&tile.parts) {
+ self.walkable.insert(pos);
+ }
+ }
+
pub fn set_item(&mut self, pos: IVec2, kind: Option<ItemIndex>) {
let Some(tile) = self.tiles.get_mut(&pos) else {
return;
@@ -292,9 +317,3 @@ impl Game {
PlayerID(self.player_id_counter)
}
}
-
-impl From<TileIndex> for Tile {
- fn from(kind: TileIndex) -> Self {
- Self { kind, item: None }
- }
-}