pw-js-api
Version:
A PixelWalker Library, aims to be minimal with support for browsers.
116 lines (115 loc) • 6.21 kB
TypeScript
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 {};