From 740dc4b45cb59ff184e5cebc5b19f402bb9d54d2 Mon Sep 17 00:00:00 2001 From: metamuffin Date: Wed, 4 Sep 2024 20:00:30 +0200 Subject: refactor interact function and new progress proto --- server/src/interaction.rs | 203 ++++++++++++++++++++++++++++++++++++---------- 1 file changed, 161 insertions(+), 42 deletions(-) (limited to 'server/src/interaction.rs') diff --git a/server/src/interaction.rs b/server/src/interaction.rs index c0fa5731..e2e4d08b 100644 --- a/server/src/interaction.rs +++ b/server/src/interaction.rs @@ -16,24 +16,23 @@ */ use hurrycurry_client_lib::{Involvement, Item}; -use hurrycurry_protocol::{Gamedata, Recipe, Score, TileIndex}; +use hurrycurry_protocol::{Gamedata, ItemLocation, PacketC, Recipe, Score, TileIndex}; use log::info; - -pub enum InteractEffect { - Put, - Take, - Produce, -} +use std::collections::VecDeque; pub fn interact( data: &Gamedata, edge: bool, tile: Option, this: &mut Option, + this_loc: ItemLocation, other: &mut Option, + other_loc: ItemLocation, score: &mut Score, + score_changed: &mut bool, automated: bool, -) -> Option { + packet_out: &mut VecDeque, +) { let interactable = automated || tile .map(|tile| data.is_tile_interactable(tile)) @@ -43,16 +42,31 @@ pub fn interact( if let Some(active) = &mut item.active { let recipe = &data.recipe(active.recipe); if recipe.supports_tile(tile) { - if let Recipe::Active { outputs, .. } = recipe { + if let Recipe::Active { + outputs, duration, .. + } = recipe + { if edge { - active.working += 1; + active.speed += 1. / duration; } else { - active.working -= 1; - if active.progress >= 1. { - *other = outputs[0].map(|kind| Item { kind, active: None }); - *this = outputs[1].map(|kind| Item { kind, active: None }); - return Some(InteractEffect::Produce); - } + active.speed -= 1. / duration; + } + if active.position >= 1. { + let this_had_item = this.is_some(); + let other_had_item = other.is_some(); + *other = outputs[0].map(|kind| Item { kind, active: None }); + *this = outputs[1].map(|kind| Item { kind, active: None }); + produce( + this_had_item, + other_had_item, + this, + this_loc, + other, + other_loc, + score_changed, + packet_out, + ); + return; } } } @@ -60,7 +74,7 @@ pub fn interact( } } if !edge { - return None; + return; } if interactable { for (ri, recipe) in data.recipes() { @@ -68,15 +82,17 @@ pub fn interact( continue; } match recipe { - Recipe::Active { input, .. } => { + Recipe::Active { + input, duration, .. + } => { if other.is_none() { if let Some(item) = this { if item.kind == *input && item.active.is_none() { info!("start active recipe {ri:?}"); item.active = Some(Involvement { recipe: ri, - working: 1, - progress: 0., + speed: 1. / duration, + position: 0., warn: false, }); } @@ -87,19 +103,23 @@ pub fn interact( if item.kind == *input { let mut item = other.take().unwrap(); if let Some(active) = &mut item.active { - active.working += 1; + active.speed += 1. / duration; } else { info!("start active recipe {ri:?}"); item.active = Some(Involvement { recipe: ri, - working: 1, - progress: 0., + speed: 1. / duration, + position: 0., warn: false, }); } *this = Some(item); score.active_recipes += 1; - return Some(InteractEffect::Put); + packet_out.push_back(PacketC::MoveItem { + from: other_loc, + to: this_loc, + }); + return; } } } @@ -117,11 +137,24 @@ pub fn interact( if ok || ok_rev { info!("instant recipe {ri:?} reversed={ok_rev}"); let ok_rev = ok_rev as usize; + let this_had_item = this.is_some(); + let other_had_item = other.is_some(); *other = outputs[1 - ok_rev].map(|kind| Item { kind, active: None }); *this = outputs[ok_rev].map(|kind| Item { kind, active: None }); score.points += pd; score.instant_recipes += 1; - return Some(InteractEffect::Produce); + *score_changed = true; + produce( + this_had_item, + other_had_item, + this, + this_loc, + other, + other_loc, + score_changed, + packet_out, + ); + return; } } _ => (), @@ -132,21 +165,32 @@ pub fn interact( if interactable && this.is_none() { if let Some(item) = other.take() { *this = Some(item); - return Some(InteractEffect::Put); + packet_out.push_back(PacketC::MoveItem { + from: other_loc, + to: this_loc, + }); + return; } } if other.is_none() { if let Some(item) = this.take() { *other = Some(item); - return Some(InteractEffect::Take); + packet_out.push_back(PacketC::MoveItem { + from: this_loc, + to: other_loc, + }); + return; } } - - None } pub enum TickEffect { - Progress(bool), + Progress { + speed: f32, + position: f32, + warn: bool, + }, + ClearProgress, Produce, } pub fn tick_slot( @@ -159,35 +203,58 @@ pub fn tick_slot( if let Some(item) = slot { if let Some(a) = &mut item.active { let r = &data.recipe(a.recipe); - if r.supports_tile(tile) { - a.progress += a.working as f32 * dt / r.duration().unwrap(); - } else if let Some(revert_duration) = r.revert_duration() { - a.progress -= dt / revert_duration; + let prev_speed = a.speed; + + if !r.supports_tile(tile) { + if let Some(revert_duration) = r.revert_duration() { + a.speed = -1. / revert_duration + } } - if a.progress >= 1. { + + if a.position >= 1. { if let Recipe::Passive { output, .. } = &data.recipe(a.recipe) { *slot = output.map(|kind| Item { kind, active: None }); score.passive_recipes += 1; return Some(TickEffect::Produce); }; - a.progress = 1.; } - if a.progress < 0. { + if a.position < 0. { item.active = None; + return Some(TickEffect::ClearProgress); + } + + a.position += dt * a.speed; + a.position = a.position.clamp(0., 1.); + + if a.speed != prev_speed { + return Some(TickEffect::Progress { + warn: r.warn(), + position: a.position, + speed: a.speed, + }); } - return Some(TickEffect::Progress(r.warn())); } else { for (ri, recipe) in data.recipes() { if recipe.supports_tile(tile) { - if let Recipe::Passive { input, warn, .. } = recipe { + if let Recipe::Passive { + input, + warn, + duration, + .. + } = recipe + { if *input == item.kind { item.active = Some(Involvement { recipe: ri, - progress: 0., + position: 0., + warn: *warn, + speed: 1. / *duration, + }); + return Some(TickEffect::Progress { + position: 0., + speed: 1. / *duration, warn: *warn, - working: 1, }); - return Some(TickEffect::Progress(recipe.warn())); } } } @@ -196,3 +263,55 @@ pub fn tick_slot( } None } + +fn produce( + this_had_item: bool, + other_had_item: bool, + this: &Option, + this_loc: ItemLocation, + other: &Option, + other_loc: ItemLocation, + score_changed: &mut bool, + packet_out: &mut VecDeque, +) { + info!("produce {this_loc} <~ {other_loc}"); + *score_changed = true; + if this_had_item { + packet_out.push_back(PacketC::SetProgress { + item: this_loc, + position: 1., + speed: 0., + warn: false, + }); + packet_out.push_back(PacketC::SetItem { + location: this_loc, + item: None, + }); + } + if other_had_item { + packet_out.push_back(PacketC::MoveItem { + from: other_loc, + to: this_loc, + }); + packet_out.push_back(PacketC::SetItem { + location: this_loc, + item: None, + }); + } + if let Some(i) = &other { + packet_out.push_back(PacketC::SetItem { + location: this_loc, + item: Some(i.kind), + }); + packet_out.push_back(PacketC::MoveItem { + from: this_loc, + to: other_loc, + }) + } + if let Some(i) = &this { + packet_out.push_back(PacketC::SetItem { + location: this_loc, + item: Some(i.kind), + }); + } +} -- cgit v1.2.3-70-g09d2