summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--data/maps/bar.yaml2
-rw-r--r--data/maps/campaign/lobby.yaml3
-rw-r--r--data/maps/debug.yaml1
-rw-r--r--data/maps/depot.yaml1
-rw-r--r--data/maps/factory.yaml1
-rw-r--r--data/maps/junior.yaml2
-rw-r--r--data/maps/lobby.yaml2
-rw-r--r--data/maps/senior.yaml2
-rw-r--r--data/maps/sushibar.yaml2
-rw-r--r--server/src/commands.rs22
-rw-r--r--server/src/entity/book.rs21
-rw-r--r--server/src/entity/mod.rs8
-rw-r--r--server/src/state.rs2
-rw-r--r--test-client/main.ts9
14 files changed, 63 insertions, 15 deletions
diff --git a/data/maps/bar.yaml b/data/maps/bar.yaml
index 3f5674f1..7c3706ba 100644
--- a/data/maps/bar.yaml
+++ b/data/maps/bar.yaml
@@ -68,6 +68,8 @@ items:
entities:
- !customers
+tile_entities:
+ "b": !book
chef_spawn: "~"
customer_spawn: "!"
diff --git a/data/maps/campaign/lobby.yaml b/data/maps/campaign/lobby.yaml
index fbaa96ed..39dde694 100644
--- a/data/maps/campaign/lobby.yaml
+++ b/data/maps/campaign/lobby.yaml
@@ -26,7 +26,7 @@ map:
- "''''''''''''''*'"
- "'*'''''''''''*''"
- "''*'''''''''''*'"
- - "'''''''''''''*''"
+ - "''''b''''''''*''"
- "'*'''''''''''*''"
- "''*'''*'''*''*''"
- "'*''*''**'''**''"
@@ -52,6 +52,7 @@ customer_spawn: "!"
tile_entities:
"1": !map { name: "campaign/01" }
"a": !gate { condition: !all [!stars [sophomore, 2], !stars [paris, 1]] }
+ "b": !book
walkable:
- floor
diff --git a/data/maps/debug.yaml b/data/maps/debug.yaml
index f3472e22..e292a398 100644
--- a/data/maps/debug.yaml
+++ b/data/maps/debug.yaml
@@ -112,6 +112,7 @@ tile_entities:
"L": !conveyor { dir: [1, 0], filter: leek }
"ö": !conveyor { dir: [1, 0], filter: tomato-soup-pot }
"ü": !conveyor { dir: [1, 0], filter: tomato-soup-plate }
+ "b": !book
chef_spawn: "~"
customer_spawn: "!"
diff --git a/data/maps/depot.yaml b/data/maps/depot.yaml
index 8b730859..9a9f81c2 100644
--- a/data/maps/depot.yaml
+++ b/data/maps/depot.yaml
@@ -77,6 +77,7 @@ tile_entities:
"<": !conveyor { dir: [-1, 0] }
"v": !conveyor { dir: [0, 1] }
"^": !conveyor { dir: [0, -1] }
+ "b": !book
items:
"S": pot
diff --git a/data/maps/factory.yaml b/data/maps/factory.yaml
index 176ef716..c941ce00 100644
--- a/data/maps/factory.yaml
+++ b/data/maps/factory.yaml
@@ -70,6 +70,7 @@ tile_entities:
"<": !conveyor { dir: [-1, 0] }
"v": !conveyor { dir: [0, 1] }
"^": !conveyor { dir: [0, -1] }
+ "b": !book
items:
"S": pot
diff --git a/data/maps/junior.yaml b/data/maps/junior.yaml
index 9acd4dd1..f8b316ce 100644
--- a/data/maps/junior.yaml
+++ b/data/maps/junior.yaml
@@ -71,6 +71,8 @@ customer_spawn: "!"
entities:
- !customers
+tile_entities:
+ "b": !book
walkable:
- door
diff --git a/data/maps/lobby.yaml b/data/maps/lobby.yaml
index 17d8dd1d..d1d3aa8e 100644
--- a/data/maps/lobby.yaml
+++ b/data/maps/lobby.yaml
@@ -47,6 +47,8 @@ tiles:
items:
"t": tomato-soup-plate
"T": bread-slice-plate
+tile_entities:
+ "b": !book
chef_spawn: "~"
customer_spawn: "!"
diff --git a/data/maps/senior.yaml b/data/maps/senior.yaml
index b10b3ab8..67442916 100644
--- a/data/maps/senior.yaml
+++ b/data/maps/senior.yaml
@@ -68,6 +68,8 @@ items:
entities:
- !customers
+tile_entities:
+ "b": !book
chef_spawn: "~"
customer_spawn: "!"
diff --git a/data/maps/sushibar.yaml b/data/maps/sushibar.yaml
index e086fd37..f244d92c 100644
--- a/data/maps/sushibar.yaml
+++ b/data/maps/sushibar.yaml
@@ -74,6 +74,8 @@ items:
entities:
- !customers
+tile_entities:
+ "b": !book
chef_spawn: "~"
customer_spawn: "!"
diff --git a/server/src/commands.rs b/server/src/commands.rs
index c33f5832..96d9ab75 100644
--- a/server/src/commands.rs
+++ b/server/src/commands.rs
@@ -19,7 +19,7 @@ use crate::{entity::bot::BotDriver, server::Server};
use anyhow::{anyhow, bail, Result};
use clap::{Parser, ValueEnum};
use hurrycurry_bot::algos::ALGO_CONSTRUCTORS;
-use hurrycurry_protocol::{Message, PacketC, PlayerID};
+use hurrycurry_protocol::{Menu, Message, PacketC, PlayerID};
use std::{fmt::Write, time::Duration};
#[derive(Parser)]
@@ -68,6 +68,8 @@ enum Command {
/// Reload the current map
#[clap(alias = "r")]
Reload,
+ /// Shows the recipe book
+ Book,
}
#[derive(ValueEnum, Clone)]
@@ -77,7 +79,12 @@ enum DownloadType {
}
impl Server {
- pub async fn handle_command_parse(&mut self, player: PlayerID, command: &str) -> Result<()> {
+ pub async fn handle_command_parse(
+ &mut self,
+ player: PlayerID,
+ command: &str,
+ ) -> Result<Vec<PacketC>> {
+ let mut replies = Vec::new();
for line in command.split("\n") {
self.handle_command(
player,
@@ -86,12 +93,18 @@ impl Server {
.ok_or(anyhow!("quoting invalid"))?
.into_iter(),
)?,
+ &mut replies,
)
.await?;
}
- Ok(())
+ Ok(replies)
}
- async fn handle_command(&mut self, player: PlayerID, command: Command) -> Result<()> {
+ async fn handle_command(
+ &mut self,
+ player: PlayerID,
+ command: Command,
+ replies: &mut Vec<PacketC>,
+ ) -> Result<()> {
match command {
Command::Start { spec, timer } => {
let data = self.index.generate(&spec).await?;
@@ -124,6 +137,7 @@ impl Server {
Command::ReloadIndex => {
self.index.reload().await?;
}
+ Command::Book => replies.push(PacketC::Menu(Menu::Book)),
Command::Download { r#type, name } => {
let source = match r#type {
DownloadType::Map => self.index.read_map(&name).await,
diff --git a/server/src/entity/book.rs b/server/src/entity/book.rs
new file mode 100644
index 00000000..3787ffaa
--- /dev/null
+++ b/server/src/entity/book.rs
@@ -0,0 +1,21 @@
+use super::{Entity, EntityContext};
+use anyhow::Result;
+use hurrycurry_protocol::{glam::IVec2, Menu, PacketC, PlayerID};
+
+#[derive(Debug, Clone)]
+pub struct Book(pub IVec2);
+
+impl Entity for Book {
+ fn interact(
+ &mut self,
+ c: EntityContext<'_>,
+ pos: Option<IVec2>,
+ _player: PlayerID,
+ ) -> Result<bool> {
+ if pos == Some(self.0) {
+ c.packet_out.push_back(PacketC::Menu(Menu::Book));
+ return Ok(true);
+ }
+ Ok(false)
+ }
+}
diff --git a/server/src/entity/mod.rs b/server/src/entity/mod.rs
index c8424934..30a5da55 100644
--- a/server/src/entity/mod.rs
+++ b/server/src/entity/mod.rs
@@ -15,6 +15,7 @@
along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
+pub mod book;
pub mod bot;
pub mod campaign;
pub mod conveyor;
@@ -25,6 +26,7 @@ pub mod player_portal;
use crate::{data::ItemTileRegistry, scoreboard::ScoreboardStore};
use anyhow::{anyhow, Result};
+use book::Book;
use campaign::{Gate, GateCondition, Map};
use conveyor::Conveyor;
use customers::Customers;
@@ -53,7 +55,9 @@ pub struct EntityContext<'a> {
}
pub trait Entity {
- fn tick(&mut self, c: EntityContext<'_>) -> Result<()>;
+ fn tick(&mut self, _c: EntityContext<'_>) -> Result<()> {
+ Ok(())
+ }
fn destructor(&mut self, _c: EntityContext<'_>) {}
fn interact(
&mut self,
@@ -117,6 +121,7 @@ pub enum EntityDecl {
location: Option<IVec2>,
condition: GateCondition,
},
+ Book,
}
pub fn construct_entity(
@@ -125,6 +130,7 @@ pub fn construct_entity(
reg: &ItemTileRegistry,
) -> Result<DynEntity> {
Ok(match decl.to_owned() {
+ EntityDecl::Book => Box::new(Book(pos.ok_or(anyhow!("book is tile entity"))?)),
EntityDecl::ItemPortal { from, to } => Box::new(ItemPortal {
from: from
.or(pos)
diff --git a/server/src/state.rs b/server/src/state.rs
index 5e0302b2..e368317c 100644
--- a/server/src/state.rs
+++ b/server/src/state.rs
@@ -55,7 +55,7 @@ impl Server {
player,
} if let Some(command) = text.strip_prefix("/") => {
match self.handle_command_parse(*player, command).await {
- Ok(()) => return Ok(vec![]),
+ Ok(packets) => return Ok(packets),
Err(e) => {
return Ok(vec![PacketC::ServerMessage {
text: format!("{e}"),
diff --git a/test-client/main.ts b/test-client/main.ts
index c2843192..6ed3c6e1 100644
--- a/test-client/main.ts
+++ b/test-client/main.ts
@@ -248,7 +248,7 @@ function packet(p: PacketC) {
case "menu":
switch (p.menu) {
case "book": open("https://s.metamuffin.org/static/hurrycurry/book.pdf"); break
- case "score": alert("Your score: " + JSON.stringify(p.data)); break
+ case "score": global_message = { timeout: { initial: 5, remaining: 5 }, inner: { text: `Score: ${JSON.stringify(p.data, null, 4)}` }, anim_position: { x: 0, y: 0 }, anim_size: 0 }; break
default: console.warn("unknown menu");
}
break;
@@ -310,13 +310,6 @@ export function get_interact_target(): V2 | undefined {
function set_interact(edge: boolean) {
if (edge) interacting = get_interact_target()
- if (edge && interacting) {
- const kind = tiles.get([interacting.x, interacting.y].toString())?.kind;
- if (kind && data.tile_names[kind] == "book") {
- open("https://s.metamuffin.org/static/hurrycurry-1.2/book.pdf")
- return
- }
- }
if (interacting) send({ player: my_id, type: "interact", pos: edge ? [interacting.x, interacting.y] : undefined })
if (!edge) interacting = undefined
}