aboutsummaryrefslogtreecommitdiff
path: root/test-client/protocol.ts
blob: 878f344c21a1e98a67846ee2fa50475f25de2ae5 (plain)
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 (C) 2025 Hurry Curry! Contributors

    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 }