diff options
-rw-r--r-- | locale/en.ini | 12 | ||||
-rw-r--r-- | server/protocol/src/lib.rs | 1 | ||||
-rw-r--r-- | server/src/entity/tutorial.rs | 44 | ||||
-rw-r--r-- | server/src/lib.rs | 29 | ||||
-rw-r--r-- | test-client/protocol.ts | 1 | ||||
-rw-r--r-- | test-client/visual.ts | 51 |
6 files changed, 71 insertions, 67 deletions
diff --git a/locale/en.ini b/locale/en.ini index 155f8f6c..73510a7c 100644 --- a/locale/en.ini +++ b/locale/en.ini @@ -167,6 +167,18 @@ c.setup.par13=F.Miller c.setup.sign=Click to sign s.bot.chef=Simple chef s.bot.waiter=Waiter +s.tutorial.active=Interact here for %ss +s.tutorial.clear_tile=Clear this tile +s.tutorial.error=Tutorial code handle this recipe yet. +s.tutorial.finished=Tutorial finished! +s.tutorial.hold_interact=Hold interact +s.tutorial.interact_empty=Interact with an empty tile +s.tutorial.interact=Interact here +s.tutorial.pickup=Take this item. +s.tutorial.put_away=Put away this item for later +s.tutorial.put_on=Place on %s +s.tutorial.take=Take %s from here +s.tutorial.wait_finish=... unknown298=Signature of the Employer:%nMusterfoods Ltd.%nFrank Miller, Head of HR unknown312=Signature of the Employee:%n%n%n unknown33=Automatic diff --git a/server/protocol/src/lib.rs b/server/protocol/src/lib.rs index 1bfb280e..323cf2c2 100644 --- a/server/protocol/src/lib.rs +++ b/server/protocol/src/lib.rs @@ -142,6 +142,7 @@ pub enum Message { Translation { id: String, params: Vec<Message> }, Text(String), Item(ItemIndex), + Tile(TileIndex), Effect(String), } diff --git a/server/src/entity/tutorial.rs b/server/src/entity/tutorial.rs index 24c83550..fba43fd0 100644 --- a/server/src/entity/tutorial.rs +++ b/server/src/entity/tutorial.rs @@ -1,3 +1,5 @@ +use crate::trm; + use super::{Entity, EntityContext}; use anyhow::Result; use hurrycurry_protocol::{ @@ -41,7 +43,7 @@ impl Entity for Tutorial { if self.delete_timer <= 0. { hint = None } else { - hint = Some((None, Message::Text("Tutorial finished.".to_string()))); + hint = Some((None, trm!("s.tutorial.finished"))); } } @@ -122,23 +124,20 @@ impl<'a> StepContext<'a> { return Ok(pos); } self.aquire_item(item)?; - Err((None, Message::Text("put down this item".to_string()))) + Err((None, trm!("s.tutorial.put_away"))) } fn aquire_item(&mut self, item: ItemIndex) -> Result<(), (Option<IVec2>, Message)> { debug!("aquire item {:?}", self.ent.game.data.item_names[item.0]); self.recursion_abort += 1; if self.recursion_abort > 32 { warn!("too much recursion"); - return Err(( - None, - Message::Text("server cant handle the recipe, too much recursion".to_string()), - )); + return Err((None, trm!("s.tutorial.error"))); } if self.is_hand_item(item) { return Ok(()); } if let Some(pos) = self.find_item_on_map(item) { - return Err((Some(pos), Message::Text("pickup".to_string()))); + return Err((Some(pos), trm!("s.tutorial.pickup"))); } if let Some(recipe) = self.find_recipe_with_output(item) { let r = &self.ent.game.data.recipes[recipe.0]; @@ -149,7 +148,7 @@ impl<'a> StepContext<'a> { .. } => { if let Some(pos) = self.find_tile(*tile) { - return Err((Some(pos), Message::Text("take from crate".to_string()))); + return Err((Some(pos), trm!("s.tutorial.take", i = item))); } } Recipe::Instant { @@ -159,7 +158,7 @@ impl<'a> StepContext<'a> { } => { let apos = self.aquire_placed_item(*a)?; self.aquire_item(*b)?; - return Err((Some(apos), Message::Text("interact here".to_string()))); + return Err((Some(apos), trm!("s.tutorial.interact"))); } Recipe::Instant { tile: None, @@ -167,7 +166,7 @@ impl<'a> StepContext<'a> { .. } => { self.aquire_item(*input)?; - return Err((None, Message::Text("interact with empty tile".to_string()))); + return Err((None, trm!("s.tutorial.interact_empty"))); } Recipe::Active { tile: Some(tile), @@ -178,18 +177,13 @@ impl<'a> StepContext<'a> { if let Some(pos) = self.find_tile(*tile) { if let Some(item) = &self.ent.game.tiles.get(&pos).unwrap().item { if item.kind == *input { - return Err(( - Some(pos), - Message::Text(format!("hold interact here")), - )); - } else { - return Err((Some(pos), Message::Text(format!("clear tile")))); + return Err((Some(pos), trm!("s.tutorial.hold_interact"))); } } self.aquire_item(*input)?; return Err(( Some(pos), - Message::Text(format!("active here for {:.01}s", 1. / speed)), + trm!("s.tutorial.active", s = format!("{:.01}", 1. / speed)), )); } } @@ -201,26 +195,18 @@ impl<'a> StepContext<'a> { if let Some(pos) = self.find_tile(*tile) { if let Some(item) = &self.ent.game.tiles.get(&pos).unwrap().item { if item.kind == *input { - return Err((Some(pos), Message::Text(format!("wait for finish")))); - } else { - return Err((Some(pos), Message::Text(format!("clear tile")))); + return Err((Some(pos), trm!("s.tutorial.wait_finish"))); } } self.aquire_item(*input)?; - return Err(( - Some(pos), - Message::Text(format!( - "put on {}", - self.ent.game.data.tile_name(*tile) - )), - )); + return Err((Some(pos), trm!("s.tutorial.put_on", t = *tile))); } } Recipe::Passive { tile: None, input, .. } => { self.aquire_item(*input)?; - return Err((None, Message::Text(format!("wait for finish")))); + return Err((None, trm!("s.tutorial.wait_finish"))); } _ => warn!("recipe too hard {r:?}"), } @@ -229,6 +215,6 @@ impl<'a> StepContext<'a> { "stuck at making item {:?}", self.ent.game.data.item_names[item.0] ); - Err((None, Message::Text(format!("stuck")))) + Err((None, trm!("s.tutorial.error"))) } } diff --git a/server/src/lib.rs b/server/src/lib.rs index 89822133..3969c67c 100644 --- a/server/src/lib.rs +++ b/server/src/lib.rs @@ -16,13 +16,13 @@ */ #![feature(if_let_guard, map_many_mut, let_chains, iterator_try_collect, isqrt)] +pub mod commands; pub mod data; pub mod entity; -pub mod server; pub mod interaction; -pub mod state; pub mod scoreboard; -pub mod commands; +pub mod server; +pub mod state; use hurrycurry_protocol::glam::Vec2; @@ -43,3 +43,26 @@ impl InterpolateExt for f32 { *self = target + (*self - target) * (-dt).exp(); } } + +#[macro_export] +macro_rules! trm { + ($id:literal $(, $typ:ident = $param:expr)*) => { + hurrycurry_protocol::Message::Translation { + id: $id.to_owned(), + params: vec![$(crate::trm_param!($typ, $param)),*] + } + }; +} + +#[macro_export] +macro_rules! trm_param { + (s, $x:expr) => { + hurrycurry_protocol::Message::Text($x) + }; + (i, $x:expr) => { + hurrycurry_protocol::Message::Item($x) + }; + (t, $x:expr) => { + hurrycurry_protocol::Message::Tile($x) + }; +} diff --git a/test-client/protocol.ts b/test-client/protocol.ts index 4d243702..6d7bf464 100644 --- a/test-client/protocol.ts +++ b/test-client/protocol.ts @@ -88,6 +88,7 @@ export interface Score { export type Message = { item: number } + | { tile: number } | { text: string } | { effect: string } | { translation: { id: string, params: Message[] } } diff --git a/test-client/visual.ts b/test-client/visual.ts index f25be1ef..e1bb7681 100644 --- a/test-client/visual.ts +++ b/test-client/visual.ts @@ -20,6 +20,7 @@ import { ItemData, MessageData, PlayerData, TileData, camera, camera_scale, canv import { PLAYER_SIZE } from "./movement.ts"; import { draw_item_sprite, draw_tile_sprite, ItemName, TileName } from "./tiles.ts"; import { V2, ceil_v2, floor_v2 } from "./util.ts"; +import { Message } from "./protocol.ts"; export function draw_wait(text: string) { ctx.fillStyle = "#444" @@ -49,38 +50,30 @@ export function draw_ingame() { draw_grid() - // Draw tiles - for (const [_, tile] of tiles) { + for (const [_, tile] of tiles) draw_tile(tile) - } - // Draw players for (const [_, player] of players) draw_player(player) - // Draw removed items for (const item of items_removed) draw_item(item) - // Draw items on tiles for (const [_, tile] of tiles) if (tile.item) draw_item(tile.item) - // Draw player messages - for (const [_, player] of players) { + for (const [_, player] of players) if (player.message) draw_message(player.message) + + for (const [_, player] of players) if (player.message_persist) draw_message(player.message_persist) - } - // Draw nametags for (const [_, player] of players) draw_player_nametag(player) - // Draw server hints for (const [_, message] of server_hints) draw_message(message) - // Draw interact target draw_interact_target() ctx.restore() @@ -90,9 +83,8 @@ export function draw_ingame() { if (!is_lobby) draw_score() - if (keys_down.has("KeyP")) { + if (keys_down.has("KeyP")) draw_debug() - } } function draw_score() { @@ -219,6 +211,14 @@ function draw_character(character: number) { ctx.fill() } +function message_str(m: Message): string { + if ("text" in m) return m.text + if ("translation" in m) return tr(m.translation.id, ...m.translation.params.map(message_str)) + if ("tile" in m) return data.tile_names[m.tile] + if ("item" in m) return data.item_names[m.item] + return "[unknown message type]" +} + function draw_message(m: MessageData) { ctx.save() ctx.translate(m.anim_position.x, m.anim_position.y) @@ -245,33 +245,14 @@ function draw_message(m: MessageData) { draw_item_sprite(ctx, data.item_names[m.inner.item] as ItemName) ctx.translate(0, 1) } - if ("text" in m.inner) { - ctx.translate(0, -1) - - ctx.textAlign = "center" - ctx.font = "15px sans-serif" - ctx.scale(2 / camera_scale, 2 / camera_scale) - const w = ctx.measureText(m.inner.text).width + 30 - - ctx.fillStyle = "#fffa" - ctx.beginPath() - ctx.roundRect(-w / 2, -15, w, 30, 5) - ctx.fill() - - ctx.fillStyle = "black" - ctx.textBaseline = "middle" - ctx.fillText(m.inner.text, 0, 0) - - ctx.translate(0, 1) - } - if ("translation" in m.inner) { + if ("text" in m.inner || "translation" in m.inner) { ctx.translate(0, -1) ctx.textAlign = "center" ctx.font = "15px sans-serif" ctx.scale(2 / camera_scale, 2 / camera_scale) - const text = tr(m.inner.translation.id, ...m.inner.translation.params.map(p => "text" in p ? p.text : "[not text]")); + const text = message_str(m.inner); const w = ctx.measureText(text).width + 30 ctx.fillStyle = "#fffa" |