UNPKG

pw-js-api

Version:

A PixelWalker Library, aims to be minimal with support for browsers.

116 lines (115 loc) 6.21 kB
import type PWApiClient from "../api/PWApiClient.js"; import { type PlayerChatPacket, type WorldBlockFilledPacket, type WorldBlockPlacedPacket } from "../gen/world_pb.js"; import type { GameClientSettings, WorldJoinData, Hook } from "../types/game.js"; import type { CustomBotEvents, MergedEvents, WorldEvents } from "../types/events.js"; import Queue from "../util/Queue.js"; import type { OmitRecursively, Optional, Promisable } from "../types/misc.js"; type SafeCheck<K extends keyof MergedEvents, State extends Partial<{ [K in keyof MergedEvents]: any; }>> = State extends CustomBotEvents ? never : State[K]; export default class PWGameClient<StateT extends Partial<{ [K in keyof WorldEvents]: never; }> = {}> { settings: GameClientSettings; api?: PWApiClient; socket?: WebSocket; private prevWorldId?; protected totalBucket: Queue; protected chatBucket: Queue; protected connectAttempts: { time: number; count: number; }; /** * NOTE: After constructing, you must then run .init() to connect the API IF you're using email/password. */ constructor(api: PWApiClient, settings?: Partial<GameClientSettings>); constructor(settings?: Partial<GameClientSettings>); get connected(): boolean; /** * This will connect to the world. * * (This returns itself for chaining) */ joinWorld(roomId: string, joinData?: WorldJoinData): Promise<this>; /** * INTERNAL */ private createSocket; /** * This is a more direct route if you already have a join key acquired via Pixelwalker's API. * * Useful for those wary of security. */ static joinWorld(joinKey: string, obj?: { joinData?: WorldJoinData; gameSettings?: Partial<GameClientSettings>; }, EndpointURL?: string): Promise<PWGameClient>; /** * For faster performance (even if it seems insignificant), * direct functions are used instead of events which are also inconsistent with browsers/nodejs etc. * * NOTE: the "this" won't be the client itself. You will need to bind yourself if you want to keep this. */ protected callbacks: Partial<{ [K in keyof MergedEvents]: Array<(data: MergedEvents[K], states?: SafeCheck<K, StateT>) => Promisable<void | "STOP">>; }>; /** * Poorly documented because I cba */ private hooks; /** * This is different to addCallback as all hooks (regardless of the type) will execute first before the callbacks, each hook may modify something or do something in the background * and may pass it to callbacks (via the second parameter in callbacks). If an error occurs while executing one of the hooks, * the execution of hooks will halt for that packet and callbacks will run without the states. * * NOTE: This is permanent, if a hook is added, it can't be removed. */ addHook<HookState extends Pick<Partial<{ [K in keyof WorldEvents]: any; }>, keyof WorldEvents>>(hook: Hook<HookState>): PWGameClient<StateT & HookState>; /** * Adds listeners to the end of the chain for that event type, it can even be a promise too. * * If the callback returns a specific string "STOP", it will prevent further listeners from being invoked. */ addCallback<Event extends keyof CustomBotEvents>(type: Event, ...cbs: Array<(data: MergedEvents[Event]) => Promisable<void | "STOP">>): this; addCallback<Event extends keyof WorldEvents>(type: Event, ...cbs: Array<(data: MergedEvents[Event], states?: SafeCheck<Event, StateT>) => Promisable<void | "STOP">>): this; /** * Inserts listeners at the start of the chain for that event type, it can even be a promise too. * * If the callback returns a specific string "STOP", it will prevent further listeners from being invoked. */ prependCallback<Event extends keyof CustomBotEvents>(type: Event, ...cbs: Array<(data: MergedEvents[Event]) => Promisable<void | "STOP">>): this; prependCallback<Event extends keyof WorldEvents>(type: Event, ...cbs: Array<(data: MergedEvents[Event], states?: SafeCheck<Event, StateT>) => Promisable<void | "STOP">>): this; /** * @param type The type of the event * @param cb It can be the function itself (to remove that specific function). If undefined, it will remove ALL functions from that list, it will return undefined. */ removeCallback<Event extends keyof MergedEvents>(type: Event, cb?: (data: MergedEvents[Event], states: SafeCheck<Event, StateT>) => Promisable<void | "STOP">): undefined | ((data: MergedEvents[Event], states: SafeCheck<Event, StateT>) => Promisable<void | "STOP">); /** * INTERNAL. Invokes all functions of a callback type, unless one of them prohibits in transit. */ protected invoke<Event extends keyof CustomBotEvents>(type: Event, data: MergedEvents[Event]): Promise<{ count: number; stopped: boolean; }>; protected invoke<Event extends keyof WorldEvents>(type: Event, data: MergedEvents[Event], states: SafeCheck<Event, StateT>): Promise<{ count: number; stopped: boolean; }>; /** * This assumes that the connection * * @param type Type of the packet. * @param value Value of the packet to send along with, note that some properties are optional. * @param direct If it should skip queue. */ send<Event extends keyof WorldEvents>(type: Event, value?: OmitRecursively<Sendable<Event, WorldEvents>, "$typeName" | "$unknown">, direct?: boolean): void; /** * By default this will set the game client settings reconnectable to false. * * If reconnect is true, an additionl parameter can be passed which is the amount of time to wait before it attempts to reconnect (DEFAULT: none) */ disconnect(reconnect?: number | boolean): boolean; } type Sendable<E extends keyof WorldEvents, WE extends WorldEvents> = E extends "worldBlockPlacedPacket" ? Optional<WorldBlockPlacedPacket, "extraFields"> : E extends "WorldBlockFilledPacket" ? Optional<WorldBlockFilledPacket, "extraFields"> : E extends "playerChatPacket" ? Omit<PlayerChatPacket, "playerId"> : WE[E]; export {};