use crate::{ data::{Action, 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 { Passive { duration: f32, tile: Option, input: ItemIndex, output: Option, }, Active { duration: f32, tile: Option, input: ItemIndex, outputs: [Option; 2], }, Instant { tile: Option, inputs: [Option; 2], outputs: [Option; 2], }, } impl Recipe { pub fn tile(&self) -> Option { match self { Recipe::Passive { tile, .. } => *tile, Recipe::Active { tile, .. } => *tile, Recipe::Instant { tile, .. } => *tile, } } } pub fn interact(data: &Gamedata, edge: bool, tile: &mut Tile, player: &mut Player) { if !edge { return; } for recipe in &data.recipes { if let Some(tile_constraint) = recipe.tile() { if tile.kind != tile_constraint { continue; } } 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 }); } } } } } // 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; // } // 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, // items: Vec, // 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))); // } // } // }