summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authormetamuffin <metamuffin@disroot.org>2024-09-17 22:19:06 +0200
committermetamuffin <metamuffin@disroot.org>2024-09-17 22:19:06 +0200
commitcc96993499c435ea706fa21a6d8089604bc44e51 (patch)
treea55f9595ca3064a1afb9494f1b9a5632616863cf
parent4a7480a90bc54eccd2a00ded45624783fcd1179c (diff)
downloadhurrycurry-cc96993499c435ea706fa21a6d8089604bc44e51.tar
hurrycurry-cc96993499c435ea706fa21a6d8089604bc44e51.tar.bz2
hurrycurry-cc96993499c435ea706fa21a6d8089604bc44e51.tar.zst
translate tutorial and add tile message
-rw-r--r--locale/en.ini12
-rw-r--r--server/protocol/src/lib.rs1
-rw-r--r--server/src/entity/tutorial.rs44
-rw-r--r--server/src/lib.rs29
-rw-r--r--test-client/protocol.ts1
-rw-r--r--test-client/visual.ts51
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"