// messages sent between the client and the server, as json over a websocket import type { Faces } from "./constants.ts"; import type { ItemData } from "./inventory.ts"; import type { ModListing } from "./mod_loader.ts"; export const AIR_ID = "bworld:air"; export interface PlayerInfo { id: string; name: string; x: number; y: number; z: number; yaw: number; pitch: number; } // x, y, z, block id export type BlockChange = [number, number, number, string]; // the containers a client can see and click. "screen" is whatever the open server screen shows export type ContainerKey = "inventory" | "crafting" | "screen"; export const CRAFTING_RESULT_SLOT = 9; // a screen the server opens, drawn below the player's inventory and hotbar export interface ScreenLayout { // height of the screen's own area, in slots rows: number; // x and y in slots, can be fractional // output slots can only be taken from, like the furnace result slots: { index: number; x: number; y: number; output?: boolean }[]; // progress bars filled from properties[value] / properties[max] bars: { x: number; y: number; value: string; max: string; direction: "up" | "right"; empty_texture: string; full_texture: string; }[]; } // clients send what the player is trying to do, the server decides what happens export type ClientMessage = | { type: "hello"; name: string } | { type: "move"; x: number; y: number; z: number; yaw: number; pitch: number } | { type: "break_block"; x: number; y: number; z: number } // right click on a block: interact with it, or place the held block against `face` | { type: "use_block"; x: number; y: number; z: number; face: Faces } | { type: "select_slot"; slot: number } | { type: "click"; container: ContainerKey; index: number; button: number } // closes the open screen, including the player's own inventory screen | { type: "close_screen" } | { type: "chat"; text: string }; export type ServerMessage = | { type: "welcome"; id: string; // the server may change the name asked for, like alice to alice2 name: string; seed: string; // in load order, the client loads them before joining the world mods: ModListing[]; players: PlayerInfo[]; changes: BlockChange[]; spawn: { x: number; y: number; z: number; yaw: number; pitch: number }; selected_slot: number; } | { type: "player_join"; player: PlayerInfo } | { type: "player_leave"; id: string } | { type: "player_move"; id: string; x: number; y: number; z: number; yaw: number; pitch: number } // also sent to the player who caused it, which corrects anything their client predicted wrong | { type: "set_block"; x: number; y: number; z: number; id: string } | { type: "chat"; from?: string; text: string } | { type: "teleport"; x: number; y: number; z: number } | { type: "container"; container: ContainerKey; items: (ItemData | null)[] } | { type: "cursor"; item: ItemData | null } | { type: "open_screen"; layout: ScreenLayout; properties: Record } | { type: "screen_properties"; properties: Record } | { type: "close_screen" }; export const MAX_NAME_LENGTH = 16; export const MAX_CHAT_LENGTH = 256;