diff options
author | metamuffin <metamuffin@disroot.org> | 2024-06-17 23:41:25 +0200 |
---|---|---|
committer | metamuffin <metamuffin@disroot.org> | 2024-06-23 19:20:50 +0200 |
commit | a99aa006599827ea999a5684e40635175c8d790a (patch) | |
tree | 1b36a73833d3a87384e7bbfb379c4adceb72cd27 | |
parent | 6f0424b9b4cddc0495eb673d314c570e27e61e83 (diff) | |
download | hurrycurry-a99aa006599827ea999a5684e40635175c8d790a.tar hurrycurry-a99aa006599827ea999a5684e40635175c8d790a.tar.bz2 hurrycurry-a99aa006599827ea999a5684e40635175c8d790a.tar.zst |
a
-rw-r--r-- | data/recipes.yaml | 8 | ||||
-rw-r--r-- | server/src/game.rs | 98 | ||||
-rw-r--r-- | server/src/interaction.rs | 64 | ||||
-rw-r--r-- | server/src/protocol.rs | 4 | ||||
-rw-r--r-- | server/src/recipes.rs | 6 | ||||
-rw-r--r-- | test-client/main.ts | 4 |
6 files changed, 134 insertions, 50 deletions
diff --git a/data/recipes.yaml b/data/recipes.yaml index de8de444..46ac8b15 100644 --- a/data/recipes.yaml +++ b/data/recipes.yaml @@ -1,10 +1,16 @@ - tile: floor action: !never # tomato pipeline + - tile: meat-spawn action: !instant - outputs: [raw-meat] + outputs: [raw-steak] + +- tile: trash + action: !instant + inputs: [raw-steak] +- { tile: table, inputs: [raw-steak, void] } - tile: table inputs: [tomato] diff --git a/server/src/game.rs b/server/src/game.rs index a7a07881..3b16cc05 100644 --- a/server/src/game.rs +++ b/server/src/game.rs @@ -1,20 +1,27 @@ use crate::{ - protocol::{ItemID, ItemIndex, PacketC, PacketS, PlayerID, TileIndex}, + interaction::{interact, Out}, + protocol::{ItemID, ItemIndex, PacketC, PacketS, PlayerID, RecipeIndex, TileIndex}, recipes::Gamedata, }; use anyhow::{anyhow, Result}; use glam::IVec2; +use log::info; use std::{ collections::{HashMap, VecDeque}, ops::Deref, sync::Arc, }; +pub struct ActiveRecipe { + pub recipe: RecipeIndex, + pub progress: f32, + pub working: usize, +} + pub struct Tile { kind: TileIndex, items: Vec<ItemID>, - active: bool, - progress: f32, + active: Option<ActiveRecipe>, } struct Player { @@ -69,17 +76,13 @@ impl Game { } g.tiles.extend( - [([-5, 1], "pan"), ([-5, 2], "pan"), ([4, 3], "meat-spawn")].map(|(k, v)| { - ( - IVec2::from_array(k), - Tile { - active: false, - items: vec![], - kind: gamedata.get_tile(v).unwrap().into(), - progress: 0., - }, - ) - }), + [ + ([-5, 1], "pan"), + ([-5, 2], "pan"), + ([4, 3], "meat-spawn"), + ([4, 1], "trash"), + ] + .map(|(k, v)| (IVec2::from_array(k), gamedata.get_tile(v).unwrap().into())), ); g @@ -150,19 +153,59 @@ impl Game { .push_back(PacketC::Position { player, pos, rot }); } PacketS::Interact { pos, edge } => { + let pid = player; + let player = self + .players + .get_mut(&player) + .ok_or(anyhow!("player does not exist"))?; + let tile = self + .tiles + .get_mut(&pos) + .ok_or(anyhow!("tile does not exist"))?; + + 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]); - // if let Some(item) = player_data.hand.take() { - // info!("put {item}"); - // tile.items.push(item); - // self.packet_out.push_back(PacketC::PutItem { item, pos }) - // } else { - // if let Some(item) = tile.items.pop() { - // info!("take {item}"); - // player_data.hand = Some(item); - // self.packet_out - // .push_back(PacketC::TakeItem { item, player }) - // } - // } + 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 }); + } + }, + ); } } Ok(()) @@ -173,9 +216,8 @@ impl From<TileIndex> for Tile { fn from(kind: TileIndex) -> Self { Self { kind, - progress: 0., - active: false, items: vec![], + active: None, } } } diff --git a/server/src/interaction.rs b/server/src/interaction.rs index 5f8b0097..7ef4a9b4 100644 --- a/server/src/interaction.rs +++ b/server/src/interaction.rs @@ -1,8 +1,11 @@ use crate::{ + game::ActiveRecipe, protocol::{ItemIndex, TileIndex}, recipes::{Action, Gamedata}, }; +use log::{debug, info}; use std::collections::BTreeSet; +use Out::*; pub enum Out { Take(usize), @@ -10,14 +13,14 @@ pub enum Out { Produce(ItemIndex), Consume(usize), } -use Out::*; pub fn interact( data: &Gamedata, edge: bool, tile: TileIndex, - items: &[ItemIndex], - hand: &Option<ItemIndex>, + active: &mut Option<ActiveRecipe>, + mut items: Vec<ItemIndex>, + mut hand: Option<ItemIndex>, mut out: impl FnMut(Out), ) { let mut allowed = BTreeSet::new(); @@ -27,28 +30,52 @@ pub fn interact( } } if !edge { + if let Some(ac) = active { + if matches!(data.recipes[ac.recipe].action, Action::Active(_)) { + ac.working -= 1; + } + } return; } - let mut put_item = None; - if let Some(hand) = hand { - if allowed.contains(hand) { + if let Some(hi) = hand { + if allowed.contains(&hi) { out(Put); - put_item = Some(*hand); + items.push(hi); + hand = None; } } - for r in &data.recipes { - let ok = r - .inputs - .iter() - .all(|e| items.contains(e) || put_item == Some(*e)) - && r.inputs.len() == items.len(); - if ok { + if hand.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(_) => todo!(), - Action::Active(_) => todo!(), + Action::Passive(_) => { + *active = Some(ActiveRecipe { + recipe: ri, + progress: 0., + working: 0, + }); + break 'rloop; + } + Action::Active(_) => {} Action::Instant => { + info!("use recipe {r:?}"); for i in 0..items.len() { out(Consume(i)) } @@ -58,9 +85,14 @@ pub fn interact( if !r.outputs.is_empty() { out(Take(r.outputs.len() - 1)); } + break 'rloop; } Action::Never => (), } } } + + if !items.is_empty() && hand.is_none() { + out(Take(items.len() - 1)); + } } diff --git a/server/src/protocol.rs b/server/src/protocol.rs index ae87ffb4..fa34954b 100644 --- a/server/src/protocol.rs +++ b/server/src/protocol.rs @@ -1,12 +1,12 @@ +use crate::recipes::Gamedata; use glam::{IVec2, Vec2}; use serde::{Deserialize, Serialize}; -use crate::recipes::Gamedata; - pub type PlayerID = usize; pub type ItemID = usize; pub type ItemIndex = usize; pub type TileIndex = usize; +pub type RecipeIndex = usize; #[derive(Debug, Clone, Serialize, Deserialize)] #[serde(rename_all = "snake_case")] diff --git a/server/src/recipes.rs b/server/src/recipes.rs index 25a4be98..11c455ba 100644 --- a/server/src/recipes.rs +++ b/server/src/recipes.rs @@ -1,13 +1,14 @@ use crate::protocol::{ItemIndex, TileIndex}; use serde::{Deserialize, Serialize}; -#[derive(Debug, Deserialize, Serialize, Clone, Copy)] +#[derive(Debug, Deserialize, Serialize, Clone, Copy, Default)] #[serde(rename_all = "snake_case")] pub enum Action { + #[default] + Never, Passive(f32), Active(f32), Instant, - Never, } #[derive(Debug, Clone, Deserialize, Serialize)] @@ -17,6 +18,7 @@ pub struct Recipe<T = TileIndex, I = ItemIndex> { pub inputs: Vec<I>, #[serde(default)] pub outputs: Vec<I>, + #[serde(default)] pub action: Action, } diff --git a/test-client/main.ts b/test-client/main.ts index 5f4475f2..6622d37f 100644 --- a/test-client/main.ts +++ b/test-client/main.ts @@ -75,7 +75,9 @@ function packet(p: PacketC) { items.set(p.produce_item.id, { kind: p.produce_item.kind, x: p.produce_item.pos[0] + 0.5, y: p.produce_item.pos[1] + 0.5, tracking_player: false, tile: { x: p.produce_item.pos[0], y: p.produce_item.pos[1] } }) tiles.get(p.produce_item.pos.toString())!.items.push(p.produce_item.id) } else if ("consume_item" in p) { - // TODO + const t = tiles.get(p.consume_item.pos.toString())! + t.items.splice(t.items.indexOf(p.consume_item.id)) + items.delete(p.consume_item.id) } else if ("set_active" in p) { // TODO } else if ("update_map" in p) { |