diff options
-rw-r--r-- | server/src/game.rs | 127 | ||||
-rw-r--r-- | server/src/interaction.rs | 227 | ||||
-rw-r--r-- | server/src/main.rs | 2 | ||||
-rw-r--r-- | test-client/main.ts | 10 |
4 files changed, 172 insertions, 194 deletions
diff --git a/server/src/game.rs b/server/src/game.rs index d481dc4f..46bc0569 100644 --- a/server/src/game.rs +++ b/server/src/game.rs @@ -1,6 +1,6 @@ use crate::{ data::Gamedata, - interaction::interact, + interaction::{interact, tick_tile, InteractEffect, TickEffect}, protocol::{ItemIndex, PacketC, PacketS, PlayerID, RecipeIndex, TileIndex}, }; use anyhow::{anyhow, bail, Result}; @@ -12,12 +12,14 @@ use std::{ sync::Arc, }; +#[derive(Debug, PartialEq)] pub struct Involvement { pub recipe: RecipeIndex, pub progress: f32, pub working: usize, } +#[derive(Debug, PartialEq)] pub struct Item { pub kind: ItemIndex, pub active: Option<Involvement>, @@ -80,8 +82,8 @@ impl Game { }); if let Some(item) = &tdata.item { out.push(PacketC::ProduceItem { - item: item.kind, tile, + item: item.kind, }) } } @@ -111,7 +113,7 @@ impl Game { .players .remove(&player) .ok_or(anyhow!("player does not exist"))?; - if let Some(id) = p.item { + if let Some(_id) = p.item { // TODO place on ground } self.packet_out @@ -121,6 +123,10 @@ impl Game { self.packet_out .push_back(PacketC::Position { player, pos, rot }); } + PacketS::Collide { player, force } => { + self.packet_out + .push_back(PacketC::Collide { player, force }); + } PacketS::Interact { pos, edge } => { info!("interact {pos:?} edge={edge}"); @@ -139,64 +145,83 @@ impl Game { } let tile_had_item = tile.item.is_some(); + let player_had_item = tile.item.is_some(); - 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, - // }); - // } - // }, - // ); + if let Some(effect) = interact(&self.data, edge, tile, player) { + match effect { + InteractEffect::Put => self.packet_out.push_back(PacketC::PutItem { + player: pid, + tile: pos, + }), + InteractEffect::Take => self.packet_out.push_back(PacketC::TakeItem { + player: pid, + tile: pos, + }), + InteractEffect::Produce => { + if tile_had_item { + self.packet_out + .push_back(PacketC::ConsumeItem { tile: pos }); + } + if player_had_item { + self.packet_out.push_back(PacketC::PutItem { + player: pid, + tile: pos, + }); + self.packet_out + .push_back(PacketC::ConsumeItem { tile: pos }); + } + if let Some(i) = &player.item { + self.packet_out.push_back(PacketC::ProduceItem { + tile: pos, + item: i.kind, + }); + self.packet_out.push_back(PacketC::TakeItem { + player: pid, + tile: pos, + }) + } + if let Some(i) = &tile.item { + self.packet_out.push_back(PacketC::ProduceItem { + tile: pos, + item: i.kind, + }); + } + } + } + } player.interacting = edge; } - PacketS::Collide { player, force } => {} } Ok(()) } pub fn tick(&mut self, dt: f32) { for (&pos, tile) in &mut self.tiles { + if let Some(effect) = tick_tile(dt, &self.data, tile) { + match effect { + TickEffect::Progress => self.packet_out.push_back(PacketC::SetActive { + tile: pos, + progress: tile + .item + .as_ref() + .unwrap() + .active + .as_ref() + .map(|i| i.progress), + }), + TickEffect::Produce => { + self.packet_out + .push_back(PacketC::ConsumeItem { tile: pos }); + if let Some(item) = &tile.item { + self.packet_out.push_back(PacketC::ProduceItem { + tile: pos, + item: item.kind, + }); + } + } + } + } // let items = tile.items.iter().map(|e| self.items[e]).collect::<Vec<_>>(); // tick_tile( // dt, 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 +} diff --git a/server/src/main.rs b/server/src/main.rs index 6cb65141..c4df346e 100644 --- a/server/src/main.rs +++ b/server/src/main.rs @@ -53,7 +53,7 @@ async fn main() -> Result<()> { }); } - for id in 0.. { + for id in 1.. { tokio::select! { r = raw_listener.accept() => { let (sock, addr) = r?; diff --git a/test-client/main.ts b/test-client/main.ts index 4c755e55..bfd352b3 100644 --- a/test-client/main.ts +++ b/test-client/main.ts @@ -68,7 +68,8 @@ let scale = 0 function send(p: PacketS) { ws.send(JSON.stringify(p)) } function packet(p: PacketC) { - if (!["position", "set_active"].includes(p.type)) console.log(p); + if (!["position", "set_active"].includes(p.type)) + console.log(p); switch (p.type) { case "init": my_id = p.id @@ -101,7 +102,7 @@ function packet(p: PacketC) { case "put_item": { const player = players.get(p.player)! const tile = tiles.get(p.tile.toString())! - tile.item = player.item; + tile.item = player.item player.item = undefined break; } @@ -277,10 +278,7 @@ function draw_ingame() { } for (const [_, tile] of tiles) { - ctx.save() - ctx.translate(tile.x, tile.y) if (tile.item) draw_item(tile.item) - ctx.restore() } draw_interact_target() @@ -297,7 +295,7 @@ function draw_item(item: ItemData) { } if (item.progress !== null && item.progress !== undefined) { ctx.fillStyle = "rgba(115, 230, 58, 0.66)" - ctx.fillRect(0, 0, 1, item.progress) + ctx.fillRect(-0.5, -0.5, 1, item.progress) } ctx.restore() } |