summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--pixel-client/src/game.rs30
-rw-r--r--server/client-lib/src/lib.rs38
-rw-r--r--server/protocol/src/lib.rs8
-rw-r--r--server/src/entity/conveyor.rs10
-rw-r--r--server/src/entity/item_portal.rs10
-rw-r--r--server/src/interaction.rs203
-rw-r--r--server/src/server.rs139
-rw-r--r--test-client/main.ts23
-rw-r--r--test-client/protocol.ts3
-rw-r--r--test-client/visual.ts6
10 files changed, 284 insertions, 186 deletions
diff --git a/pixel-client/src/game.rs b/pixel-client/src/game.rs
index 1f74d491..5239a002 100644
--- a/pixel-client/src/game.rs
+++ b/pixel-client/src/game.rs
@@ -26,12 +26,12 @@ use crate::{
tilemap::Tilemap,
State,
};
-use hurrycurry_client_lib::{network::sync::Network, spatial_index::SpatialIndex};
+use hurrycurry_client_lib::{network::sync::Network, spatial_index::SpatialIndex, Involvement};
use hurrycurry_protocol::{
glam::{IVec2, Vec2},
movement::MovementBase,
- Gamedata, ItemIndex, ItemLocation, Message, MessageTimeout, PacketC, PacketS, PlayerID, Score,
- TileIndex,
+ Gamedata, ItemIndex, ItemLocation, Message, MessageTimeout, PacketC, PacketS, PlayerID,
+ RecipeIndex, Score, TileIndex,
};
use log::{info, warn};
use sdl2::{
@@ -80,7 +80,7 @@ pub struct Item {
parent_position: Vec2,
kind: ItemIndex,
alive: f32,
- progress: Option<(f32, bool)>,
+ active: Option<Involvement>,
}
impl Game {
@@ -340,15 +340,22 @@ impl Game {
parent_position: position,
alive: 0.,
position,
- progress: None,
+ active: None,
})
}
+ PacketC::ClearProgress { item } => self.get_item(item).as_mut().unwrap().active = None,
PacketC::SetProgress {
item,
- progress,
+ position,
+ speed,
warn,
} => {
- self.get_item(item).as_mut().unwrap().progress = progress.map(|s| (s, warn));
+ self.get_item(item).as_mut().unwrap().active = Some(Involvement {
+ position,
+ speed,
+ warn,
+ recipe: RecipeIndex(0),
+ });
}
PacketC::ServerMessage { text: _ } => {
// TODO
@@ -428,7 +435,10 @@ impl Game {
impl Item {
pub fn tick(&mut self, alive: f32, dt: f32) {
self.position.exp_to(self.parent_position, dt * 20.);
- self.alive.exp_to(alive, dt * 20.)
+ self.alive.exp_to(alive, dt * 20.);
+ if let Some(active) = &mut self.active {
+ active.position += active.speed * dt;
+ }
}
pub fn draw(&self, ctx: &mut Renderer, item_sprites: &[Sprite]) {
ctx.draw_world(
@@ -436,7 +446,7 @@ impl Item {
.at(self.position)
.alpha(self.alive),
);
- if let Some((progress, warn)) = self.progress {
+ if let Some(Involvement { position, warn, .. }) = self.active {
let (bg, fg) = if warn {
([100, 0, 0, 200], [255, 0, 0, 200])
} else {
@@ -451,7 +461,7 @@ impl Item {
ctx.draw_world(SpriteDraw::overlay(
ctx.misc_textures.solid,
self.position + Vec2::new(-0.5, -1.3),
- Vec2::new(progress, 0.2),
+ Vec2::new(position, 0.2),
Some(fg),
))
}
diff --git a/server/client-lib/src/lib.rs b/server/client-lib/src/lib.rs
index 38f1070e..38b328b9 100644
--- a/server/client-lib/src/lib.rs
+++ b/server/client-lib/src/lib.rs
@@ -32,9 +32,9 @@ use std::{
#[derive(Debug, PartialEq)]
pub struct Involvement {
- pub progress: f32,
+ pub position: f32,
+ pub speed: f32,
pub recipe: RecipeIndex,
- pub working: usize,
pub warn: bool,
}
@@ -135,18 +135,21 @@ impl Game {
PacketC::SetItem { location, item } => {
*self.get_item(location) = item.map(|kind| Item { kind, active: None });
}
+ PacketC::ClearProgress { item } => {
+ self.get_item(item).as_mut().unwrap().active = None;
+ }
PacketC::SetProgress {
item,
- progress,
+ position,
+ speed,
warn,
} => {
- self.get_item(item).as_mut().unwrap().active =
- progress.map(|progress| Involvement {
- working: 1,
- warn,
- progress,
- recipe: RecipeIndex(0),
- });
+ self.get_item(item).as_mut().unwrap().active = Some(Involvement {
+ speed,
+ warn,
+ position,
+ recipe: RecipeIndex(0),
+ });
}
PacketC::UpdateMap {
tile,
@@ -205,6 +208,21 @@ impl Game {
.update_entry(pid, player.movement.position);
}
+ for (_, player) in &mut self.players {
+ if let Some(item) = &mut player.item {
+ if let Some(active) = &mut item.active {
+ active.position += active.speed;
+ }
+ }
+ }
+ for (_, tile) in &mut self.tiles {
+ if let Some(item) = &mut tile.item {
+ if let Some(active) = &mut item.active {
+ active.position += active.speed;
+ }
+ }
+ }
+
self.players_spatial_index.all(|p1, pos1| {
self.players_spatial_index.query(pos1, 2., |p2, _pos2| {
if let Some([a, b]) = self.players.get_many_mut([&p1, &p2]) {
diff --git a/server/protocol/src/lib.rs b/server/protocol/src/lib.rs
index a55eabe2..68af0e63 100644
--- a/server/protocol/src/lib.rs
+++ b/server/protocol/src/lib.rs
@@ -27,7 +27,7 @@ pub use glam;
pub mod movement;
-pub const VERSION: (u32, u32) = (5, 0);
+pub const VERSION: (u32, u32) = (6, 0);
pub const BINCODE_CONFIG: Configuration<LittleEndian, Varint, Limit<4096>> =
standard().with_limit();
@@ -185,9 +185,13 @@ pub enum PacketC {
location: ItemLocation,
item: Option<ItemIndex>,
},
+ ClearProgress {
+ item: ItemLocation,
+ },
SetProgress {
item: ItemLocation,
- progress: Option<f32>,
+ position: f32,
+ speed: f32,
warn: bool,
},
UpdateMap {
diff --git a/server/src/entity/conveyor.rs b/server/src/entity/conveyor.rs
index 5602e082..4efbd385 100644
--- a/server/src/entity/conveyor.rs
+++ b/server/src/entity/conveyor.rs
@@ -15,8 +15,8 @@
along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
-use super::{EntityContext, Entity};
-use crate::server::interact_effect;
+use super::{Entity, EntityContext};
+use crate::interaction::interact;
use anyhow::{anyhow, Result};
use hurrycurry_protocol::{glam::IVec2, ItemIndex, ItemLocation};
@@ -68,18 +68,18 @@ impl Entity for Conveyor {
.get_many_mut([&self.from, &self.to])
.ok_or(anyhow!("conveyor does ends in itself"))?;
- interact_effect(
+ interact(
&c.game.data,
true,
+ Some(to.kind),
&mut to.item,
ItemLocation::Tile(self.to),
&mut from.item,
ItemLocation::Tile(self.from),
- Some(to.kind),
- c.packet_out,
&mut c.game.score,
c.score_changed,
true,
+ c.packet_out,
);
}
diff --git a/server/src/entity/item_portal.rs b/server/src/entity/item_portal.rs
index faaa210b..99b9d57a 100644
--- a/server/src/entity/item_portal.rs
+++ b/server/src/entity/item_portal.rs
@@ -15,8 +15,8 @@
along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
-use super::{EntityContext, Entity};
-use crate::server::interact_effect;
+use super::{Entity, EntityContext};
+use crate::interaction::interact;
use anyhow::{anyhow, Result};
use hurrycurry_protocol::{glam::IVec2, ItemLocation};
@@ -35,18 +35,18 @@ impl Entity for ItemPortal {
.ok_or(anyhow!("conveyor does ends in itself"))?;
if from.item.is_some() {
- interact_effect(
+ interact(
&c.game.data,
true,
+ Some(to.kind),
&mut to.item,
ItemLocation::Tile(self.to),
&mut from.item,
ItemLocation::Tile(self.from),
- Some(to.kind),
- c.packet_out,
&mut c.game.score,
c.score_changed,
true,
+ c.packet_out,
);
}
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<TileIndex>,
this: &mut Option<Item>,
+ this_loc: ItemLocation,
other: &mut Option<Item>,
+ other_loc: ItemLocation,
score: &mut Score,
+ score_changed: &mut bool,
automated: bool,
-) -> Option<InteractEffect> {
+ packet_out: &mut VecDeque<PacketC>,
+) {
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<Item>,
+ this_loc: ItemLocation,
+ other: &Option<Item>,
+ other_loc: ItemLocation,
+ score_changed: &mut bool,
+ packet_out: &mut VecDeque<PacketC>,
+) {
+ 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),
+ });
+ }
+}
diff --git a/server/src/server.rs b/server/src/server.rs
index 63664354..109d5561 100644
--- a/server/src/server.rs
+++ b/server/src/server.rs
@@ -18,7 +18,7 @@
use crate::{
data::{DataIndex, Serverdata},
entity::{Entities, EntityContext},
- interaction::{interact, tick_slot, InteractEffect, TickEffect},
+ interaction::{interact, tick_slot, TickEffect},
scoreboard::ScoreboardStore,
ConnectionID,
};
@@ -444,18 +444,18 @@ impl Server {
bail!("You shall not interact with customers.")
}
- interact_effect(
+ interact(
&self.game.data,
edge,
+ None,
&mut this.item,
ItemLocation::Player(base_pid),
&mut other.item,
ItemLocation::Player(pid),
- None,
- &mut self.packet_out,
&mut self.game.score,
&mut self.score_changed,
false,
+ &mut self.packet_out,
)
} else {
let player = self
@@ -464,18 +464,18 @@ impl Server {
.get_mut(&pid)
.ok_or(anyhow!("The player does not exist"))?;
- interact_effect(
+ interact(
&self.game.data,
edge,
+ Some(tile.kind),
&mut tile.item,
ItemLocation::Tile(pos),
&mut player.item,
ItemLocation::Player(pid),
- Some(tile.kind),
- &mut self.packet_out,
&mut self.game.score,
&mut self.score_changed,
false,
+ &mut self.packet_out,
)
}
}
@@ -550,22 +550,27 @@ impl Server {
&mut self.game.score,
) {
match effect {
- TickEffect::Progress(warn) => self.packet_out.push_back(PacketC::SetProgress {
+ TickEffect::Progress {
+ speed,
+ position,
+ warn,
+ } => self.packet_out.push_back(PacketC::SetProgress {
+ position,
+ speed,
warn,
item: ItemLocation::Tile(pos),
- progress: tile
- .item
- .as_ref()
- .unwrap()
- .active
- .as_ref()
- .map(|i| i.progress),
}),
+ TickEffect::ClearProgress => {
+ self.packet_out.push_back(PacketC::ClearProgress {
+ item: ItemLocation::Tile(pos),
+ })
+ }
TickEffect::Produce => {
self.packet_out.push_back(PacketC::SetProgress {
warn: false,
item: ItemLocation::Tile(pos),
- progress: None,
+ position: 1.,
+ speed: 0.,
});
self.packet_out.push_back(PacketC::SetItem {
location: ItemLocation::Tile(pos),
@@ -611,22 +616,27 @@ impl Server {
&mut self.game.score,
) {
match effect {
- TickEffect::Progress(warn) => self.packet_out.push_back(PacketC::SetProgress {
+ TickEffect::Progress {
+ position,
+ speed,
warn,
+ } => self.packet_out.push_back(PacketC::SetProgress {
+ warn,
+ position,
+ speed,
item: ItemLocation::Player(pid),
- progress: player
- .item
- .as_ref()
- .unwrap()
- .active
- .as_ref()
- .map(|i| i.progress),
}),
+ TickEffect::ClearProgress => {
+ self.packet_out.push_back(PacketC::ClearProgress {
+ item: ItemLocation::Player(pid),
+ })
+ }
TickEffect::Produce => {
self.packet_out.push_back(PacketC::SetProgress {
warn: false,
item: ItemLocation::Player(pid),
- progress: None,
+ position: 1.,
+ speed: 0.,
});
self.packet_out.push_back(PacketC::SetItem {
location: ItemLocation::Player(pid),
@@ -649,7 +659,7 @@ impl Server {
if let Some(tile) = self.game.tiles.get(&pos) {
if let Some(item) = &tile.item {
if let Some(involvement) = &item.active {
- if involvement.progress >= 1. {
+ if involvement.position >= 1. {
players_auto_release.push(*pid);
}
}
@@ -727,80 +737,3 @@ impl Server {
.sum()
}
}
-
-pub fn interact_effect(
- data: &Gamedata,
- edge: bool,
- this: &mut Option<Item>,
- this_loc: ItemLocation,
- other: &mut Option<Item>,
- other_loc: ItemLocation,
- this_tile_kind: Option<TileIndex>,
- packet_out: &mut VecDeque<PacketC>,
- score: &mut Score,
- score_changed: &mut bool,
- automated: bool,
-) {
- let this_had_item = this.is_some();
- let other_had_item = other.is_some();
-
- if let Some(effect) = interact(data, edge, this_tile_kind, this, other, score, automated) {
- match effect {
- InteractEffect::Put => {
- info!("put {this_loc} <- {other_loc}");
- packet_out.push_back(PacketC::MoveItem {
- from: other_loc,
- to: this_loc,
- })
- }
- InteractEffect::Take => {
- info!("take {this_loc} -> {other_loc}");
- packet_out.push_back(PacketC::MoveItem {
- from: this_loc,
- to: other_loc,
- })
- }
- InteractEffect::Produce => {
- info!("produce {this_loc} <~ {other_loc}");
- *score_changed = true;
- if this_had_item {
- packet_out.push_back(PacketC::SetProgress {
- item: this_loc,
- progress: None,
- 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),
- });
- }
- }
- }
- }
-}
diff --git a/test-client/main.ts b/test-client/main.ts
index 2990c685..c2843192 100644
--- a/test-client/main.ts
+++ b/test-client/main.ts
@@ -68,10 +68,14 @@ export interface ItemData {
x: number,
y: number,
tracking?: V2,
- progress?: number
- progress_warn?: boolean
+ active?: Involvement
remove_anim?: number
}
+export interface Involvement {
+ position: number,
+ speed: number,
+ warn: boolean
+}
export interface PlayerData extends MovementBase {
id: number,
name: string,
@@ -125,7 +129,7 @@ function get_item_location(loc: ItemLocation): PlayerData | TileData {
function send(p: PacketS) { ws.send(JSON.stringify(p)) }
function packet(p: PacketC) {
- if (!["movement", "set_progress", "update_map"].includes(p.type))
+ if (!["movement", "update_map"].includes(p.type))
console.log(p);
switch (p.type) {
case "version":
@@ -186,11 +190,18 @@ function packet(p: PacketC) {
if (p.item !== undefined && p.item !== null) slot.item = { kind: p.item, x: slot.position.x, y: slot.position.y, tracking: slot.position }
break;
}
+ case "clear_progress": {
+ delete get_item_location(p.item).item!.active
+ break;
+ }
case "set_progress": {
const slot = get_item_location(p.item)
if (!slot.item) return
- slot.item.progress = p.progress
- slot.item.progress_warn = p.warn
+ slot.item.active = {
+ position: p.position,
+ speed: p.speed,
+ warn: p.warn
+ }
break;
}
case "update_map":
@@ -336,6 +347,8 @@ function frame_update(dt: number) {
const update_item = (item: ItemData) => {
if (item.tracking) lerp_exp_v2_mut(item, item.tracking, dt * 10.)
+ if (item.active) item.active.position += item.active.speed * dt
+
}
for (const [pid, player] of players) {
if (pid == my_id) player.anim_position.x = player.position.x, player.anim_position.y = player.position.y
diff --git a/test-client/protocol.ts b/test-client/protocol.ts
index 40532c08..16cfec2c 100644
--- a/test-client/protocol.ts
+++ b/test-client/protocol.ts
@@ -53,7 +53,8 @@ export type PacketC =
| { type: "movement_sync" } // Your movement is difference on the server, you should update your position from a `position` packet
| { type: "move_item", from: ItemLocation, to: ItemLocation } // Item moved
| { type: "set_item", location: ItemLocation, item?: ItemIndex } // the item contained in a tile or player changed
- | { type: "set_progress", item: ItemLocation, progress?: number, warn: boolean } // A tile is doing something. progress goes from 0 to 1, then null when finished
+ | { type: "set_progress", item: ItemLocation, position: number, speed: number, warn: boolean } // A tile is doing something. position goes from 0 to 1, speed unit is in 1 per second
+ | { type: "clear_progress", item: ItemLocation }
| { type: "update_map", tile: Vec2, kind: TileIndex | null, neighbors: [TileIndex | null] } // A map tile was changed
| { type: "communicate", player: PlayerID, message?: Message, timeout?: MessageTimeout } // A player wants to communicate something, message is null when cleared
| { type: "server_message", text: string } // Text message from the server
diff --git a/test-client/visual.ts b/test-client/visual.ts
index a54ca143..4c0a8ecc 100644
--- a/test-client/visual.ts
+++ b/test-client/visual.ts
@@ -120,9 +120,9 @@ function draw_item(item: ItemData) {
ctx.translate(item.x, item.y)
if (item.remove_anim) ctx.scale(1 - item.remove_anim, 1 - item.remove_anim)
draw_item_sprite(ctx, data.item_names[item.kind] as ItemName)
- if (item.progress !== null && item.progress !== undefined) {
- ctx.fillStyle = item.progress_warn ? "rgba(230, 58, 58, 0.66)" : "rgba(115, 230, 58, 0.66)"
- ctx.fillRect(-0.5, -0.5, 1, item.progress)
+ if (item.active) {
+ ctx.fillStyle = item.active.warn ? "rgba(230, 58, 58, 0.66)" : "rgba(115, 230, 58, 0.66)"
+ ctx.fillRect(-0.5, -0.5, 1, item.active.position)
}
ctx.restore()
}