aboutsummaryrefslogtreecommitdiff
path: root/server/src
diff options
context:
space:
mode:
authormetamuffin <metamuffin@disroot.org>2024-06-18 19:36:36 +0200
committermetamuffin <metamuffin@disroot.org>2024-06-23 19:21:22 +0200
commit48934ff63ee14d4759eda36512af87361dd915dd (patch)
treef7a80115eacfee7b6871040a87f5fb0087098ea8 /server/src
parent6ec47d729509db83eaeb6a9d855ce2483d70f227 (diff)
downloadhurrycurry-48934ff63ee14d4759eda36512af87361dd915dd.tar
hurrycurry-48934ff63ee14d4759eda36512af87361dd915dd.tar.bz2
hurrycurry-48934ff63ee14d4759eda36512af87361dd915dd.tar.zst
remodel game.
Diffstat (limited to 'server/src')
-rw-r--r--server/src/data.rs127
-rw-r--r--server/src/game.rs224
-rw-r--r--server/src/interaction.rs302
-rw-r--r--server/src/lib.rs2
-rw-r--r--server/src/main.rs2
-rw-r--r--server/src/protocol.rs24
-rw-r--r--server/src/recipes.rs104
7 files changed, 427 insertions, 358 deletions
diff --git a/server/src/data.rs b/server/src/data.rs
new file mode 100644
index 00000000..6affccb5
--- /dev/null
+++ b/server/src/data.rs
@@ -0,0 +1,127 @@
+use crate::{interaction::Recipe, protocol::TileIndex};
+use glam::{IVec2, Vec2};
+use serde::{Deserialize, Serialize};
+use std::{collections::HashMap, sync::RwLock};
+
+#[derive(Debug, Deserialize, Serialize, Clone, Copy, Default)]
+#[serde(rename_all = "snake_case")]
+pub enum Action {
+ #[default]
+ Never,
+ Passive(f32),
+ Active(f32),
+ Instant,
+}
+
+#[derive(Debug, Clone, Deserialize, Serialize)]
+pub struct RecipeDecl {
+ #[serde(default)]
+ pub tile: Option<String>,
+ #[serde(default)]
+ pub inputs: Vec<String>,
+ #[serde(default)]
+ pub outputs: Vec<String>,
+ #[serde(default)]
+ pub action: Action,
+}
+
+#[derive(Debug, Clone, Deserialize)]
+pub struct InitialMap {
+ map: Vec<String>,
+ tiles: HashMap<String, String>,
+}
+
+#[derive(Debug, Clone, Serialize, Deserialize)]
+pub struct Gamedata {
+ pub recipes: Vec<Recipe>,
+ pub item_names: Vec<String>,
+ pub tile_names: Vec<String>,
+ #[serde(skip)]
+ pub initial_map: HashMap<IVec2, TileIndex>,
+ pub spawn: Vec2,
+}
+
+pub fn build_gamedata(recipes_in: Vec<RecipeDecl>, map_in: InitialMap) -> Gamedata {
+ let item_names = RwLock::new(Vec::new());
+ let tile_names = RwLock::new(Vec::new());
+ let mut recipes = Vec::new();
+
+ for r in recipes_in {
+ let r2 = r.clone();
+ let mut inputs = r.inputs.into_iter().map(|i| register(&item_names, i));
+ let mut outputs = r.outputs.into_iter().map(|o| register(&item_names, o));
+ let tile = r.tile.map(|t| register(&tile_names, t));
+ match r.action {
+ Action::Never => {}
+ Action::Passive(duration) => recipes.push(Recipe::Passive {
+ duration,
+ tile,
+ input: inputs.next().expect("passive recipe without input"),
+ output: outputs.next(),
+ }),
+ Action::Active(duration) => recipes.push(Recipe::Active {
+ duration,
+ tile,
+ input: inputs.next().expect("active recipe without input"),
+ outputs: [outputs.next(), outputs.next()],
+ }),
+ Action::Instant => {
+ recipes.push(Recipe::Instant {
+ tile,
+ inputs: [inputs.next(), inputs.next()],
+ outputs: [outputs.next(), outputs.next()],
+ });
+ }
+ }
+ assert_eq!(inputs.next(), None, "{r2:?}");
+ assert_eq!(outputs.next(), None, "{r2:?}");
+ }
+
+ let mut spawn = Vec2::new(0., 0.);
+ let mut initial_map = HashMap::new();
+ for (y, line) in map_in.map.iter().enumerate() {
+ for (x, tile) in line.trim().char_indices() {
+ let pos = IVec2::new(x as i32, y as i32);
+ let mut tilename = map_in.tiles[&tile.to_string()].clone();
+ if tilename == "spawn" {
+ spawn = pos.as_vec2();
+ tilename = "floor".to_owned();
+ }
+ let tile = register(&tile_names, tilename);
+ initial_map.insert(pos, tile);
+ }
+ }
+
+ Gamedata {
+ recipes,
+ initial_map,
+ item_names: item_names.into_inner().unwrap(),
+ tile_names: tile_names.into_inner().unwrap(),
+ spawn,
+ }
+}
+
+fn register(db: &RwLock<Vec<String>>, name: String) -> usize {
+ let mut db = db.write().unwrap();
+ if let Some(index) = db.iter().position(|e| e == &name) {
+ index
+ } else {
+ let index = db.len();
+ db.push(name);
+ index
+ }
+}
+
+impl Gamedata {
+ pub fn get_tile(&self, name: &str) -> Option<TileIndex> {
+ self.tile_names.iter().position(|t| t == name)
+ }
+}
+impl Action {
+ pub fn duration(&self) -> f32 {
+ match self {
+ Action::Instant | Action::Never => 0.,
+ Action::Passive(x) | Action::Active(x) => *x,
+ }
+ }
+}
diff --git a/server/src/game.rs b/server/src/game.rs
index 5cb155f1..d481dc4f 100644
--- a/server/src/game.rs
+++ b/server/src/game.rs
@@ -1,10 +1,10 @@
use crate::{
- interaction::{interact, tick_tile, Out},
- protocol::{ItemID, ItemIndex, PacketC, PacketS, PlayerID, RecipeIndex, TileIndex},
- recipes::Gamedata,
+ data::Gamedata,
+ interaction::interact,
+ protocol::{ItemIndex, PacketC, PacketS, PlayerID, RecipeIndex, TileIndex},
};
use anyhow::{anyhow, bail, Result};
-use glam::IVec2;
+use glam::{IVec2, Vec2};
use log::info;
use std::{
collections::{HashMap, VecDeque},
@@ -12,29 +12,32 @@ use std::{
sync::Arc,
};
-pub struct ActiveRecipe {
+pub struct Involvement {
pub recipe: RecipeIndex,
pub progress: f32,
pub working: usize,
}
+pub struct Item {
+ pub kind: ItemIndex,
+ pub active: Option<Involvement>,
+}
+
pub struct Tile {
- kind: TileIndex,
- items: Vec<ItemID>,
- active: Option<ActiveRecipe>,
+ pub kind: TileIndex,
+ pub item: Option<Item>,
}
-struct Player {
- name: String,
- interacting: bool,
- hand: Option<ItemID>,
+pub struct Player {
+ pub name: String,
+ pub position: Vec2,
+ pub interacting: bool,
+ pub item: Option<Item>,
}
pub struct Game {
data: Arc<Gamedata>,
- item_id_counter: ItemID,
tiles: HashMap<IVec2, Tile>,
- items: HashMap<ItemID, ItemIndex>,
players: HashMap<PlayerID, Player>,
packet_out: VecDeque<PacketC>,
}
@@ -43,8 +46,6 @@ impl Game {
pub fn new(gamedata: Arc<Gamedata>) -> Self {
let mut g = Self {
data: gamedata.clone(),
- item_id_counter: 0,
- items: Default::default(),
packet_out: Default::default(),
players: Default::default(),
tiles: Default::default(),
@@ -69,19 +70,18 @@ impl Game {
out.push(PacketC::AddPlayer {
id,
name: player.name.clone(),
- hand: player.hand.map(|i| (i, self.items[&i].clone())),
+ hand: player.item.as_ref().map(|i| i.kind),
})
}
- for (&pos, tdata) in &self.tiles {
+ for (&tile, tdata) in &self.tiles {
out.push(PacketC::UpdateMap {
- pos,
+ pos: tile,
tile: tdata.kind.clone(),
});
- for &id in &tdata.items {
+ if let Some(item) = &tdata.item {
out.push(PacketC::ProduceItem {
- id,
- pos,
- kind: self.items[&id].clone(),
+ item: item.kind,
+ tile,
})
}
}
@@ -94,7 +94,8 @@ impl Game {
self.players.insert(
player,
Player {
- hand: None,
+ item: None,
+ position: self.data.spawn,
interacting: false,
name: name.clone(),
},
@@ -110,8 +111,8 @@ impl Game {
.players
.remove(&player)
.ok_or(anyhow!("player does not exist"))?;
- if let Some(id) = p.hand {
- self.items.remove(&id).expect("hand item lost");
+ if let Some(id) = p.item {
+ // TODO place on ground
}
self.packet_out
.push_back(PacketC::RemovePlayer { id: player })
@@ -137,108 +138,105 @@ impl Game {
bail!("already (not) interacting")
}
- let items = tile.items.iter().map(|e| self.items[e]).collect::<Vec<_>>();
- let tilekind = tile.kind;
- let hand = player.hand.map(|e| self.items[&e]);
+ let tile_had_item = tile.item.is_some();
- interact(
- &self.data,
- edge,
- tilekind,
- &mut tile.active,
- items,
- hand,
- |out| match out {
- Out::Take(index) => {
- info!("take");
- let item = tile.items.remove(index);
- player.hand = Some(item);
- self.packet_out
- .push_back(PacketC::TakeItem { item, player: pid })
- }
- Out::Put => {
- info!("put");
- let hand = player.hand.take().unwrap();
- tile.items.push(hand);
- self.packet_out
- .push_back(PacketC::PutItem { item: hand, pos })
- }
- Out::Produce(kind) => {
- info!("produce");
- let id = self.item_id_counter;
- self.item_id_counter += 1;
- self.items.insert(id, kind);
- tile.items.push(id);
- self.packet_out
- .push_back(PacketC::ProduceItem { id, pos, kind });
- }
- Out::Consume(index) => {
- info!("consume");
- let id = tile.items.remove(index);
- info!("left {:?}", tile.items);
- self.packet_out.push_back(PacketC::ConsumeItem { id, pos });
- }
- Out::SetActive(progress) => {
- self.packet_out.push_back(PacketC::SetActive {
- tile: pos,
- progress,
- });
- }
- },
- );
+ interact(&self.data, edge, tile, player);
+
+ // interact(
+ // &self.data,
+ // edge,
+ // tilekind,
+ // &mut tile.active,
+ // item,
+ // hand,
+ // |out| match out {
+ // Out::Take(index) => {
+ // info!("take");
+ // let item = tile.items.remove(index);
+ // player.hand = Some(item);
+ // self.packet_out
+ // .push_back(PacketC::TakeItem { item, player: pid })
+ // }
+ // Out::Put => {
+ // info!("put");
+ // let hand = player.hand.take().unwrap();
+ // tile.items.push(hand);
+ // self.packet_out
+ // .push_back(PacketC::PutItem { item: hand, pos })
+ // }
+ // Out::Produce(kind) => {
+ // info!("produce");
+ // let id = self.item_id_counter;
+ // self.item_id_counter += 1;
+ // self.items.insert(id, kind);
+ // tile.items.push(id);
+ // self.packet_out
+ // .push_back(PacketC::ProduceItem { id, pos, kind });
+ // }
+ // Out::Consume(index) => {
+ // info!("consume");
+ // let id = tile.items.remove(index);
+ // info!("left {:?}", tile.items);
+ // self.packet_out.push_back(PacketC::ConsumeItem { id, pos });
+ // }
+ // Out::SetActive(progress) => {
+ // self.packet_out.push_back(PacketC::SetActive {
+ // tile: pos,
+ // progress,
+ // });
+ // }
+ // },
+ // );
player.interacting = edge;
}
+ PacketS::Collide { player, force } => {}
}
Ok(())
}
pub fn tick(&mut self, dt: f32) {
for (&pos, tile) in &mut self.tiles {
- let items = tile.items.iter().map(|e| self.items[e]).collect::<Vec<_>>();
- tick_tile(
- dt,
- &self.data,
- tile.kind,
- &mut tile.active,
- items,
- |out| match out {
- Out::Take(_) | Out::Put => {
- unreachable!()
- }
- Out::Produce(kind) => {
- info!("produce");
- let id = self.item_id_counter;
- self.item_id_counter += 1;
- self.items.insert(id, kind);
- tile.items.push(id);
- self.packet_out
- .push_back(PacketC::ProduceItem { id, pos, kind });
- }
- Out::Consume(index) => {
- info!("consume");
- let id = tile.items.remove(index);
- info!("left {:?}", tile.items);
- self.packet_out.push_back(PacketC::ConsumeItem { id, pos });
- }
- Out::SetActive(progress) => {
- self.packet_out.push_back(PacketC::SetActive {
- tile: pos,
- progress,
- });
- }
- },
- );
+ // let items = tile.items.iter().map(|e| self.items[e]).collect::<Vec<_>>();
+ // tick_tile(
+ // dt,
+ // &self.data,
+ // tile.kind,
+ // &mut tile.active,
+ // items,
+ // |out| match out {
+ // Out::Take(_) | Out::Put => {
+ // unreachable!()
+ // }
+ // Out::Produce(kind) => {
+ // info!("produce");
+ // let id = self.item_id_counter;
+ // self.item_id_counter += 1;
+ // self.items.insert(id, kind);
+ // tile.items.push(id);
+ // self.packet_out
+ // .push_back(PacketC::ProduceItem { id, pos, kind });
+ // }
+ // Out::Consume(index) => {
+ // info!("consume");
+ // let id = tile.items.remove(index);
+ // info!("left {:?}", tile.items);
+ // self.packet_out.push_back(PacketC::ConsumeItem { id, pos });
+ // }
+ // Out::SetActive(progress) => {
+ // self.packet_out.push_back(PacketC::SetActive {
+ // tile: pos,
+ // progress,
+ // });
+ // }
+ // },
+ // );
}
}
}
impl From<TileIndex> for Tile {
fn from(kind: TileIndex) -> Self {
- Self {
- kind,
- items: vec![],
- active: None,
- }
+ Self { kind, item: None }
}
}
diff --git a/server/src/interaction.rs b/server/src/interaction.rs
index 11409b10..aa216410 100644
--- a/server/src/interaction.rs
+++ b/server/src/interaction.rs
@@ -1,150 +1,196 @@
use crate::{
- game::ActiveRecipe,
+ data::{Action, Gamedata},
+ game::{Involvement, Item, Player, Tile},
protocol::{ItemIndex, TileIndex},
- recipes::{Action, Gamedata},
};
use log::{debug, info};
+use serde::{Deserialize, Serialize};
use std::collections::BTreeSet;
-use Out::*;
-pub enum Out {
- Take(usize),
- Put,
- Produce(ItemIndex),
- Consume(usize),
- SetActive(Option<f32>),
+#[derive(Debug, Clone, Serialize, Deserialize)]
+pub enum Recipe {
+ Passive {
+ duration: f32,
+ tile: Option<TileIndex>,
+ input: ItemIndex,
+ output: Option<ItemIndex>,
+ },
+ Active {
+ duration: f32,
+ tile: Option<TileIndex>,
+ input: ItemIndex,
+ outputs: [Option<ItemIndex>; 2],
+ },
+ Instant {
+ tile: Option<TileIndex>,
+ inputs: [Option<ItemIndex>; 2],
+ outputs: [Option<ItemIndex>; 2],
+ },
}
-pub fn interact(
- data: &Gamedata,
- edge: bool,
- tile: TileIndex,
- active: &mut Option<ActiveRecipe>,
- mut items: Vec<ItemIndex>,
- mut hand: Option<ItemIndex>,
- mut out: impl FnMut(Out),
-) {
- let mut allowed = BTreeSet::new();
- for r in &data.recipes {
- if r.tile == tile {
- allowed.extend(r.inputs.clone())
- }
- }
- if !edge {
- debug!("falling edge");
- if let Some(ac) = active {
- if matches!(data.recipes[ac.recipe].action, Action::Active(_)) {
- debug!("workers--");
- ac.working -= 1;
- }
- }
- return;
- }
-
- if hand.is_none() {
- debug!("rising edge");
- if let Some(active) = active {
- if matches!(data.recipes[active.recipe].action, Action::Active(_)) {
- debug!("workers++");
- active.working += 1;
- }
+impl Recipe {
+ pub fn tile(&self) -> Option<TileIndex> {
+ match self {
+ Recipe::Passive { tile, .. } => *tile,
+ Recipe::Active { tile, .. } => *tile,
+ Recipe::Instant { tile, .. } => *tile,
}
}
+}
- if active.is_none() && !items.is_empty() && hand.is_none() {
- out(Take(items.len() - 1));
+pub fn interact(data: &Gamedata, edge: bool, tile: &mut Tile, player: &mut Player) {
+ if !edge {
return;
}
- if active.is_none() {
- if let Some(hi) = hand {
- if allowed.contains(&hi) {
- out(Put);
- items.push(hi);
- hand = None;
- }
- }
- }
-
- if hand.is_none() && active.is_none() {
- 'rloop: for (ri, r) in data.recipes.iter().enumerate() {
- if tile != r.tile {
- continue;
- }
- let mut inputs = r.inputs.clone();
- for i in &items {
- debug!("take {i:?} {inputs:?}");
- let Some(pos) = inputs.iter().position(|e| e == i) else {
- continue 'rloop;
- };
- inputs.remove(pos);
- }
- debug!("end {inputs:?}");
- if !inputs.is_empty() {
+ for recipe in &data.recipes {
+ if let Some(tile_constraint) = recipe.tile() {
+ if tile.kind != tile_constraint {
continue;
}
-
- match r.action {
- Action::Passive(_) => {
- info!("use passive recipe {ri}");
- *active = Some(ActiveRecipe {
- recipe: ri,
- progress: 0.,
- working: 1,
- });
- break 'rloop;
- }
- Action::Active(_) => {
- info!("use active recipe {ri}");
- *active = Some(ActiveRecipe {
- recipe: ri,
- progress: 0.,
- working: 1,
- });
- break 'rloop;
- }
- Action::Instant => {
- info!("use instant recipe {ri}");
- for _ in 0..items.len() {
- out(Consume(0))
- }
- for i in &r.outputs {
- out(Produce(*i));
- }
- if !r.outputs.is_empty() {
- out(Take(r.outputs.len() - 1));
- }
- items.clear();
- break 'rloop;
+ }
+ match recipe {
+ Recipe::Passive {
+ duration,
+ input,
+ output,
+ ..
+ } => todo!(),
+ Recipe::Active {
+ duration,
+ input: inputs,
+ outputs,
+ ..
+ } => todo!(),
+ Recipe::Instant {
+ inputs, outputs, ..
+ } => {
+ let on_tile = tile.item.as_ref().map(|i| i.kind);
+ let in_hand = player.item.as_ref().map(|i| i.kind);
+ let ok = (inputs[0] == on_tile && inputs[1] == in_hand)
+ || (inputs[1] == on_tile && inputs[0] == in_hand);
+ if ok {
+ player.item = outputs[0].map(|kind| Item { kind, active: None });
+ tile.item = outputs[1].map(|kind| Item { kind, active: None });
}
- Action::Never => (),
}
}
}
}
+// if !edge {
+// debug!("falling edge");
+// if let Some(ac) = active {
+// if matches!(data.recipes[ac.recipe].action, Action::Active(_)) {
+// debug!("workers--");
+// ac.working -= 1;
+// }
+// }
+// return;
+// }
-pub fn tick_tile(
- dt: f32,
- data: &Gamedata,
- _tile: TileIndex,
- active: &mut Option<ActiveRecipe>,
- items: Vec<ItemIndex>,
- mut out: impl FnMut(Out),
-) {
- if let Some(a) = active {
- let r = &data.recipes[a.recipe];
- a.progress += a.working as f32 * dt / r.action.duration();
- if a.progress >= 1. {
- for _ in 0..items.len() {
- out(Consume(0))
- }
- for i in &r.outputs {
- out(Produce(*i));
- }
- out(SetActive(None));
- active.take();
- } else {
- out(SetActive(Some(a.progress)));
- }
- }
-}
+// if hand.is_none() {
+// debug!("rising edge");
+// if let Some(active) = active {
+// if matches!(data.recipes[active.recipe].action, Action::Active(_)) {
+// debug!("workers++");
+// active.working += 1;
+// }
+// }
+// }
+
+// if active.is_none() && !items.is_empty() && hand.is_none() {
+// out(Take(items.len() - 1));
+// return;
+// }
+
+// if active.is_none() {
+// if let Some(hi) = hand {
+// if allowed.contains(&hi) {
+// out(Put);
+// items.push(hi);
+// hand = None;
+// }
+// }
+// }
+
+// if hand.is_none() && active.is_none() {
+// 'rloop: for (ri, r) in data.recipes.iter().enumerate() {
+// if tile != r.tile {
+// continue;
+// }
+// let mut inputs = r.inputs.clone();
+// for i in &items {
+// debug!("take {i:?} {inputs:?}");
+// let Some(pos) = inputs.iter().position(|e| e == i) else {
+// continue 'rloop;
+// };
+// inputs.remove(pos);
+// }
+// debug!("end {inputs:?}");
+// if !inputs.is_empty() {
+// continue;
+// }
+
+// match r.action {
+// Action::Passive(_) => {
+// info!("use passive recipe {ri}");
+// *active = Some(Involvement {
+// recipe: ri,
+// progress: 0.,
+// working: 1,
+// });
+// break 'rloop;
+// }
+// Action::Active(_) => {
+// info!("use active recipe {ri}");
+// *active = Some(Involvement {
+// recipe: ri,
+// progress: 0.,
+// working: 1,
+// });
+// break 'rloop;
+// }
+// Action::Instant => {
+// info!("use instant recipe {ri}");
+// for _ in 0..items.len() {
+// out(Consume(0))
+// }
+// for i in &r.outputs {
+// out(Produce(*i));
+// }
+// if !r.outputs.is_empty() {
+// out(Take(r.outputs.len() - 1));
+// }
+// items.clear();
+// break 'rloop;
+// }
+// Action::Never => (),
+// }
+// }
+// }
+
+// pub fn tick_tile(
+// dt: f32,
+// data: &Gamedata,
+// _tile: TileIndex,
+// active: &mut Option<Involvement>,
+// items: Vec<ItemIndex>,
+// mut out: impl FnMut(Out),
+// ) {
+// if let Some(a) = active {
+// let r = &data.recipes[a.recipe];
+// a.progress += a.working as f32 * dt / r.action.duration();
+// if a.progress >= 1. {
+// for _ in 0..items.len() {
+// out(Consume(0))
+// }
+// for i in &r.outputs {
+// out(Produce(*i));
+// }
+// out(SetActive(None));
+// active.take();
+// } else {
+// out(SetActive(Some(a.progress)));
+// }
+// }
+// }
diff --git a/server/src/lib.rs b/server/src/lib.rs
index 5bb09e41..b40bcdd8 100644
--- a/server/src/lib.rs
+++ b/server/src/lib.rs
@@ -1,4 +1,4 @@
pub mod game;
pub mod protocol;
-pub mod recipes;
+pub mod data;
pub mod interaction;
diff --git a/server/src/main.rs b/server/src/main.rs
index 5414e9fd..6cb65141 100644
--- a/server/src/main.rs
+++ b/server/src/main.rs
@@ -13,7 +13,7 @@ use tokio_tungstenite::tungstenite::Message;
use undercooked::{
game::Game,
protocol::{PacketC, PacketS},
- recipes::build_gamedata,
+ data::build_gamedata,
};
#[tokio::main]
diff --git a/server/src/protocol.rs b/server/src/protocol.rs
index 9e6717a3..4f04793f 100644
--- a/server/src/protocol.rs
+++ b/server/src/protocol.rs
@@ -1,9 +1,8 @@
-use crate::recipes::Gamedata;
+use crate::data::Gamedata;
use glam::{IVec2, Vec2};
use serde::{Deserialize, Serialize};
pub type PlayerID = usize;
-pub type ItemID = usize;
pub type ItemIndex = usize;
pub type TileIndex = usize;
pub type RecipeIndex = usize;
@@ -15,6 +14,7 @@ pub enum PacketS {
Leave,
Position { pos: Vec2, rot: f32 },
Interact { pos: IVec2, edge: bool },
+ Collide { player: PlayerID, force: Vec2 },
}
#[derive(Debug, Clone, Serialize, Deserialize)]
@@ -27,7 +27,7 @@ pub enum PacketC {
AddPlayer {
id: PlayerID,
name: String,
- hand: Option<(ItemID, ItemIndex)>,
+ hand: Option<ItemIndex>,
},
RemovePlayer {
id: PlayerID,
@@ -38,21 +38,19 @@ pub enum PacketC {
rot: f32,
},
TakeItem {
- item: ItemID,
+ tile: IVec2,
player: PlayerID,
},
PutItem {
- item: ItemID,
- pos: IVec2,
+ player: PlayerID,
+ tile: IVec2,
},
ProduceItem {
- id: ItemID,
- pos: IVec2,
- kind: ItemIndex,
+ tile: IVec2,
+ item: ItemIndex,
},
ConsumeItem {
- id: ItemID,
- pos: IVec2,
+ tile: IVec2,
},
SetActive {
tile: IVec2,
@@ -62,4 +60,8 @@ pub enum PacketC {
pos: IVec2,
tile: TileIndex,
},
+ Collide {
+ player: PlayerID,
+ force: Vec2,
+ },
}
diff --git a/server/src/recipes.rs b/server/src/recipes.rs
deleted file mode 100644
index 2dcb215c..00000000
--- a/server/src/recipes.rs
+++ /dev/null
@@ -1,104 +0,0 @@
-use crate::protocol::{ItemIndex, TileIndex};
-use glam::IVec2;
-use log::debug;
-use serde::{Deserialize, Serialize};
-use std::collections::HashMap;
-
-#[derive(Debug, Deserialize, Serialize, Clone, Copy, Default)]
-#[serde(rename_all = "snake_case")]
-pub enum Action {
- #[default]
- Never,
- Passive(f32),
- Active(f32),
- Instant,
-}
-
-#[derive(Debug, Clone, Deserialize, Serialize)]
-pub struct Recipe<T = TileIndex, I = ItemIndex> {
- pub tile: T,
- #[serde(default)]
- pub inputs: Vec<I>,
- #[serde(default)]
- pub outputs: Vec<I>,
- #[serde(default)]
- pub action: Action,
-}
-
-#[derive(Debug, Clone, Deserialize)]
-pub struct InitialMap {
- map: Vec<String>,
- tiles: HashMap<String, String>,
-}
-
-#[derive(Debug, Clone, Serialize, Deserialize)]
-pub struct Gamedata {
- pub recipes: Vec<Recipe>,
- pub item_names: Vec<String>,
- pub tile_names: Vec<String>,
- #[serde(skip)]
- pub initial_map: HashMap<IVec2, TileIndex>,
-}
-pub fn build_gamedata(recipes_in: Vec<Recipe<String, String>>, map_in: InitialMap) -> Gamedata {
- let mut item_names = Vec::new();
- let mut tile_names = Vec::new();
- let mut recipes = Vec::new();
-
- for r in recipes_in {
- recipes.push(Recipe {
- action: r.action,
- tile: register(&mut tile_names, r.tile.clone()),
- inputs: r
- .inputs
- .clone()
- .into_iter()
- .map(|e| register(&mut item_names, e))
- .collect(),
- outputs: r
- .outputs
- .clone()
- .into_iter()
- .map(|e| register(&mut item_names, e))
- .collect(),
- })
- }
-
- let mut initial_map = HashMap::new();
- for (y, line) in map_in.map.iter().enumerate() {
- for (x, tile) in line.trim().char_indices() {
- debug!("{tile:?}");
- let tile = register(&mut tile_names, map_in.tiles[&tile.to_string()].clone());
- initial_map.insert(IVec2::new(x as i32, y as i32), tile);
- }
- }
-
- Gamedata {
- recipes,
- initial_map,
- item_names,
- tile_names,
- }
-}
-fn register(db: &mut Vec<String>, name: String) -> usize {
- if let Some(index) = db.iter().position(|e| e == &name) {
- index
- } else {
- let index = db.len();
- db.push(name);
- index
- }
-}
-
-impl Gamedata {
- pub fn get_tile(&self, name: &str) -> Option<TileIndex> {
- self.tile_names.iter().position(|t| t == name)
- }
-}
-impl Action {
- pub fn duration(&self) -> f32 {
- match self {
- Action::Instant | Action::Never => 0.,
- Action::Passive(x) | Action::Active(x) => *x,
- }
- }
-}