diff options
Diffstat (limited to 'server/src/interaction.rs')
-rw-r--r-- | server/src/interaction.rs | 227 |
1 files changed, 91 insertions, 136 deletions
diff --git a/server/src/interaction.rs b/server/src/interaction.rs index aa216410..75cd0c84 100644 --- a/server/src/interaction.rs +++ b/server/src/interaction.rs @@ -1,11 +1,9 @@ use crate::{ - data::{Action, Gamedata}, + data::Gamedata, game::{Involvement, Item, Player, Tile}, protocol::{ItemIndex, TileIndex}, }; -use log::{debug, info}; use serde::{Deserialize, Serialize}; -use std::collections::BTreeSet; #[derive(Debug, Clone, Serialize, Deserialize)] pub enum Recipe { @@ -36,32 +34,47 @@ impl Recipe { Recipe::Instant { tile, .. } => *tile, } } + pub fn duration(&self) -> Option<f32> { + match self { + Recipe::Passive { duration, .. } => Some(*duration), + Recipe::Active { duration, .. } => Some(*duration), + _ => None, + } + } + pub fn supports_tile(&self, tile: TileIndex) -> bool { + if let Some(tile_constraint) = self.tile() { + if tile != tile_constraint { + false + } else { + true + } + } else { + true + } + } +} + +pub enum InteractEffect { + Put, + Take, + Produce, } -pub fn interact(data: &Gamedata, edge: bool, tile: &mut Tile, player: &mut Player) { +pub fn interact( + data: &Gamedata, + edge: bool, + tile: &mut Tile, + player: &mut Player, +) -> Option<InteractEffect> { if !edge { - return; + return None; } for recipe in &data.recipes { - if let Some(tile_constraint) = recipe.tile() { - if tile.kind != tile_constraint { - continue; - } + if !recipe.supports_tile(tile.kind) { + continue; } match recipe { - Recipe::Passive { - duration, - input, - output, - .. - } => todo!(), - Recipe::Active { - duration, - input: inputs, - outputs, - .. - } => todo!(), Recipe::Instant { inputs, outputs, .. } => { @@ -72,125 +85,67 @@ pub fn interact(data: &Gamedata, edge: bool, tile: &mut Tile, player: &mut Playe if ok { player.item = outputs[0].map(|kind| Item { kind, active: None }); tile.item = outputs[1].map(|kind| Item { kind, active: None }); + return Some(InteractEffect::Produce); } } + _ => (), } } -} -// 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; -// } -// } -// } -// 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; -// } + if tile.item.is_none() { + if let Some(item) = player.item.take() { + tile.item = Some(item); + return Some(InteractEffect::Put); + } + } + if player.item.is_none() { + if let Some(item) = tile.item.take() { + player.item = Some(item); + return Some(InteractEffect::Take); + } + } -// 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 => (), -// } -// } -// } + None +} -// 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))); -// } -// } -// } +pub enum TickEffect { + Progress, + Produce, +} +pub fn tick_tile(dt: f32, data: &Gamedata, tile: &mut Tile) -> Option<TickEffect> { + if let Some(item) = &mut tile.item { + if let Some(a) = &mut item.active { + let r = &data.recipes[a.recipe]; + if r.supports_tile(tile.kind) { + a.progress += a.working as f32 * dt / r.duration().unwrap(); + if a.progress >= 1. { + let Recipe::Passive { output, .. } = &data.recipes[a.recipe] else { + unreachable!() + }; + tile.item = output.map(|kind| Item { kind, active: None }); + return Some(TickEffect::Produce); + } + return Some(TickEffect::Progress); + } + } else { + for (ri, recipe) in data.recipes.iter().enumerate() { + if let Some(tile_constraint) = recipe.tile() { + if tile.kind != tile_constraint { + continue; + } + } + if let Recipe::Passive { input, .. } = recipe { + if *input == item.kind { + item.active = Some(Involvement { + recipe: ri, + progress: 0., + working: 1, + }) + } + } + } + return Some(TickEffect::Progress); + } + } + None +} |