1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
|
/*
Hurry Curry! - a game about cooking
Copyright 2024 metamuffin
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as published by
the Free Software Foundation, version 3 of the License only.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
export type Vec2 = [number, number] // x, y
export type PlayerID = number // opaque number to identify players.
export type ItemIndex = number // index used primarily for item_names in Gamedata
export type TileIndex = number // index used primarily for tile_names in Gamedata
export type Hand = number
export interface MapMetadata {
name: string,
players: number,
difficulty: number,
}
export interface Gamedata {
item_names: string[], // Look-up table for ItemIndex
tile_names: string[], // Look-up table for TileIndex
tile_collide: boolean[], // Look-up table for TileIndex to check tile collision with players
tile_interact: boolean[], // Look-up table for TileIndex to check if a tile is interactable
spawn: Vec2, // Where players spawn when they join.
maps: [string, MapMetadata][], // Metadata for most available maps
hand_count: number,
}
export type PacketS =
{ type: "join", name: string, character: Character, class: PlayerClass } // Spawns a new character. The server replies with "joined". Dont send it to spectate.
| { type: "leave", player: PlayerID } // Despawns a character
| { type: "idle", paused: boolean } // Indicates that this player is actively participating in the game right now.
| { type: "movement", player: PlayerID, pos: Vec2, dir: Vec2, boost: boolean }
| { type: "interact", player: PlayerID, pos?: Vec2, hand: number } // Interact with some tile. pos is a position when pressing and null when releasing interact button
| { type: "communicate", player: PlayerID, message?: Message, timeout?: number, pin?: boolean } // Sends a message
| { type: "effect", player: PlayerID, name: string } // Sends an effect
| { type: "replay_tick", dt: number } // Steps forward in replay.
export type PacketC =
{ type: "version", minor: number, major: number, supports_bincode?: boolean } // Sent once after connecting to ensure you client is compatible
| { type: "joined", id: PlayerID } // Informs you about the id of the character you spawned
| { type: "data", data: Gamedata } // Game data was changed
| { type: "add_player", id: PlayerID, name: string, position: Vec2, character: Character, class: PlayerClass } // Somebody else joined (or was already in the game)
| { type: "remove_player", id: PlayerID } // Somebody left
| { type: "movement", player: PlayerID, pos: Vec2, rot: number, boost: boolean, dir: Vec2 } // Update the movement of a players (your own position is included here)
| { type: "movement_sync", player: PlayerID } // 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, position: number, speed: number, warn: boolean, player?: PlayerID } // 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: "flush_map" }
| { type: "communicate", player: PlayerID, message?: Message, timeout?: MessageTimeout } // A player wants to communicate something, message is null when cleared
| { type: "effect", player: PlayerID, name: string } // Player sent an effect
| { type: "server_message", message: Message, error: boolean } // Text message from the server
| { type: "server_hint", message?: Message, position?: Vec2, player: PlayerID } // Hint message from server with optional position. Message is unset to clear previous message
| { type: "score" } & Score // Supplies information for score OSD
| { type: "menu" } & Menu // Open a menu on the client-side
| { type: "environment", effects: string[] }
| { type: "tutorial_ended", item: ItemIndex, player: PlayerID, success: boolean }
| { type: "set_ingame", state: boolean, lobby: boolean } // Set to false when entering the game or switching maps
| { type: "pause", state: boolean } // Set game paused so clients dont increment timers
export interface Character {
color: number,
headwear: number,
hairstyle: number
}
export type Menu =
{ menu: "document", data: DocumentElement }
| { menu: "score", data: Score }
export interface MessageTimeout {
initial: number,
remaining: number,
pinned: boolean,
}
export interface Score {
points: number,
demands_failed: number,
demands_completed: number,
time_remaining: number,
players: number,
active_recipes: number,
passive_recipes: number,
instant_recipes: number,
stars: number,
}
export type Message =
{ item: number }
| { tile: number }
| { text: string }
| { translation: { id: string, params: Message[] } }
export type ItemLocation =
{ player: [PlayerID, Hand] }
| { tile: Vec2 }
export type PlayerClass = "chef" | "bot" | "customer" | "tram"
export type DocumentElement =
{ t: "document", es: DocumentElement[] }
| { t: "page", background?: string, es: DocumentElement[] }
| { t: "list", es: DocumentElement[] }
| { t: "table", es: DocumentElement[][] }
| { t: "par", es: DocumentElement[] }
| { t: "text", s: Message, size: number, color?: string, font?: string, bold: boolean }
| { t: "conditional", cond: string, value: boolean, e: DocumentElement }
| { t: "label", id: string, e: DocumentElement }
| { t: "ref", id: string, e: DocumentElement }
| { t: "container", es: DocumentElement[] }
| { t: "align", dir: "flow_end" | "bottom", e: DocumentElement }
|