UNPKG

bevy-remote-protocol

Version:
439 lines (433 loc) 15.9 kB
"use strict"; var __defProp = Object.defineProperty; var __getOwnPropDesc = Object.getOwnPropertyDescriptor; var __getOwnPropNames = Object.getOwnPropertyNames; var __hasOwnProp = Object.prototype.hasOwnProperty; var __export = (target, all) => { for (var name in all) __defProp(target, name, { get: all[name], enumerable: true }); }; var __copyProps = (to, from, except, desc) => { if (from && typeof from === "object" || typeof from === "function") { for (let key of __getOwnPropNames(from)) if (!__hasOwnProp.call(to, key) && key !== except) __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable }); } return to; }; var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod); // src/index.ts var index_exports = {}; __export(index_exports, { BevyRemoteProtocol: () => BevyRemoteProtocol, BrpStructure: () => BrpStructure, ServerVersion: () => ServerVersion, short: () => short }); module.exports = __toCommonJS(index_exports); // src/protocol.ts var import_url = require("url"); // src/types.ts var BrpStructure = class _BrpStructure { constructor(tree) { this.tree = tree; } has(path = []) { return _BrpStructure.hasBrpValue(this.tree, path); } get(path = []) { return _BrpStructure.getBrpValue(this.tree, path); } set(path = [], value) { if (path.length === 0) { this.tree = value; return; } _BrpStructure.setBrpValue(this.tree, path, value); } keys(path = []) { const iterable = this.get(path); if (typeof iterable !== "object") return []; if (iterable === void 0 || iterable === null) return []; if (iterable instanceof Array) return [...iterable.keys()]; return Object.keys(iterable); } values(path = []) { const iterable = this.get(path); if (typeof iterable !== "object") return []; if (iterable === void 0 || iterable === null) return []; return Object.values(iterable); } static hasBrpValue(value, path = []) { if (value === void 0) return false; if (path.length === 0) return true; if (typeof value !== "object" || value === null) return false; const key = path[0]; if (value instanceof Array) { if (typeof key !== "number") return false; return this.hasBrpValue(value[key], path.slice(1)); } if (typeof key !== "string") return false; return this.hasBrpValue(value[key], path.slice(1)); } static getBrpValue(value, path = []) { if (value === void 0) return void 0; if (path.length === 0) return value; if (typeof value !== "object" || value === null) return void 0; const key = path[0]; if (value instanceof Array) { if (typeof key !== "number") return null; return _BrpStructure.getBrpValue(value[key], path.slice(1)); } if (typeof key !== "string") return null; return _BrpStructure.getBrpValue(value[key], path.slice(1)); } static setBrpValue(value, path = [], setter) { if (path.length === 0) return; if (typeof value !== "object" || value === null) return; const key = path[0]; if (value instanceof Array) { if (typeof key !== "number") return; if (path.length === 1) { value[key] = setter; return; } _BrpStructure.setBrpValue(value[key], path.slice(1), setter); return; } if (typeof key !== "string") return; if (path.length === 1) { value[key] = setter; return; } _BrpStructure.setBrpValue(value[key], path.slice(1), setter); } }; var ServerVersion = /* @__PURE__ */ ((ServerVersion2) => { ServerVersion2["IGNORE"] = "IGNORE"; ServerVersion2["V0_15"] = "0.15"; ServerVersion2["V0_16"] = "0.16"; return ServerVersion2; })(ServerVersion || {}); // src/protocol.ts var import_util = require("util"); function reverseMap(map) { const result = {}; for (const key in map) { const value = map[key]; result[value] = key; } return result; } function collectMaps(maps) { const collection = {}; for (const map of maps) { for (const key in map) { collection[key] = map[key]; } } return collection; } var _BevyRemoteProtocol = class _BevyRemoteProtocol { constructor(url, version) { this.id = 0; this.url = url; this.serverVersion = version; } nextId() { return this.id++; } translateToInternal(message) { const table = (() => { if (this.serverVersion === "IGNORE" /* IGNORE */) return {}; return _BevyRemoteProtocol.ANY_TO_INTERNAL; })(); for (const search in table) { message = message.replace(new RegExp(search, "g"), table[search]); } return message; } translateToSpecificVersion(message) { const table = (() => { switch (this.serverVersion) { case "0.15" /* V0_15 */: return _BevyRemoteProtocol.INTERNAL_TO_V0_15; case "0.16" /* V0_16 */: return _BevyRemoteProtocol.INTERNAL_TO_V0_16; default: return {}; } })(); for (const search in table) { message = message.replace(new RegExp(search, "g"), table[search]); } return message; } requestWrapper(rpcMethod, rpcParams, signal) { return { method: "POST", headers: { "Content-Type": "application/json", Accept: "application/json" }, body: this.translateToSpecificVersion( JSON.stringify({ jsonrpc: "2.0", id: this.nextId(), method: rpcMethod, params: rpcParams }) ), signal }; } async request(method, params) { return await JSON.parse( this.translateToInternal(await (await fetch(this.url, this.requestWrapper(method, params))).text()) ); } async requestStream(method, params, signal, observer) { const response = await fetch(this.url, this.requestWrapper(method, params, signal)); if (!response.body) return null; try { for await (const chunk of response.body) { const decoded = _BevyRemoteProtocol.decoder.decode(chunk); const translated = this.translateToInternal(decoded); const parsed = JSON.parse(translated.slice(decoded.indexOf("{"))); if (parsed.result) observer(parsed.result); } } catch (error) { } return null; } /** * Retrieve the values of one or more components from an entity. * * This function passes a flag `strict` as `false` by default. * * `params`: * - `entity`: The ID of the entity whose components will be fetched. * - `components`: An array of [fully-qualified type names] of components to fetch. * - `strict` (optional): A flag to enable strict mode which will fail if any one of the * components is not present or can not be reflected. * * `result`: * - `components`: A map associating each type name to its value on the requested entity. * - `errors`: A map associating each type name with an error if it was not on the entity * or could not be reflected. */ async get(entity, components) { return this.request("bevy/get", { entity, components, strict: false }); } /** * Retrieve the values of one or more components from an entity. * * This function passes a flag `strict` as `true` by default. * * `params`: * - `entity`: The ID of the entity whose components will be fetched. * - `components`: An array of [fully-qualified type names] of components to fetch. * - `strict` (optional): A flag to enable strict mode which will fail if any one of the * components is not present or can not be reflected. * * `result`: A map associating each type name to its value on the requested entity. */ async get_strict(entity, components) { return this.request("bevy/get", { entity, components, strict: true }); } /** * Perform a query over components in the ECS, returning all matching entities and their associated * component values. * * All of the arrays that comprise this request are optional, and when they are not provided, they * will be treated as if they were empty. * * `params`: * - `components` (optional): An array of [fully-qualified type names] of components to fetch. * - `option` (optional): An array of fully-qualified type names of components to fetch optionally. * - `has` (optional): An array of fully-qualified type names of components whose presence will be * reported as boolean values. * - `with` (optional): An array of fully-qualified type names of components that must be present * on entities in order for them to be included in results. * - `without` (optional): An array of fully-qualified type names of components that must *not* be * present on entities in order for them to be included in results. * * `result`: An array, each of which is an object containing: * - `entity`: The ID of a query-matching entity. * - `components`: A map associating each type name from `components`/`option` to its value on the matching * entity if the component is present. * - `has`: A map associating each type name from `has` to a boolean value indicating whether or not the * entity has that component. If `has` was empty or omitted, this key will be omitted in the response. */ async query({ components, option, has, filterWith, filterWithout }) { return this.request("bevy/query", { data: { components, option, has }, filter: { with: filterWith, without: filterWithout } }); } /** * Create a new entity with the provided components and return the resulting entity ID. * * `params`: * - `components`: A map associating each component's [fully-qualified type name] with its value. * * `result`: * - `entity`: The ID of the newly spawned entity. */ async spawn(components) { return this.request("bevy/spawn", { components }); } /** * Despawn the entity with the given ID. * * `params`: * - `entity`: The ID of the entity to be despawned. * * `result`: null. */ async destroy(entity) { return this.request("bevy/destroy", { entity }); } /** * Delete one or more components from an entity. * * `params`: * - `entity`: The ID of the entity whose components should be removed. * - `components`: An array of [fully-qualified type names] of components to be removed. * * `result`: null. */ async remove(entity, components) { return this.request("bevy/remove", { entity, components }); } /** * Insert one or more components into an entity. * * `params`: * - `entity`: The ID of the entity to insert components into. * - `components`: A map associating each component's fully-qualified type name with its value. * * `result`: null. */ async insert(entity, components) { return this.request("bevy/insert", { entity, components }); } /** * Assign a new parent to one or more entities. * * `params`: * - `entities`: An array of entity IDs of entities that will be made children of the `parent`. * - `parent` (optional): The entity ID of the parent to which the child entities will be assigned. * If excluded, the given entities will be removed from their parents. * * `result`: null. */ async reparent(entities, parent) { return this.request("bevy/reparent", { entities, parent }); } /** * List all registered components or all components present on an entity. * * When `params` is not provided, this lists all registered components. If `params` is provided, * this lists only those components present on the provided entity. * * `params` (optional): * - `entity`: The ID of the entity whose components will be listed. * * `result`: An array of fully-qualified type names of components. */ async list(entity) { if (entity) return this.request("bevy/list", { entity }); return this.request("bevy/list", null); } /** * Watch the values of one or more components from an entity. * * This function passes a flag `strict` as `false` by default. * * `params`: * - `entity`: The ID of the entity whose components will be fetched. * - `components`: An array of [fully-qualified type names] of components to fetch. * - `signal`: A signal object that allows you to abort it if required via an {@link AbortController} object. * - `observer`: A handler of chunks of Response. * * `result`: * - `components`: A map of components added or changed in the last tick associating each type * name to its value on the requested entity. * - `removed`: An array of fully-qualified type names of components removed from the entity * in the last tick. * - `errors`: A map associating each type name with an error if it was not on the entity * or could not be reflected. */ async get_watch(entity, components, signal, observer) { return this.requestStream("bevy/get+watch", { entity, components, strict: false }, signal, observer); } /** * Watch the values of one or more components from an entity. * * This function passes a flag `strict` as `true` by default. * Response will fail if any one of the components is not present or can not be refleceted. * * `params`: * - `entity`: The ID of the entity whose components will be fetched. * - `components`: An array of [fully-qualified type names] of components to fetch. * - `signal`: A signal object that allows you to abort it if required via an {@link AbortController} object. * - `observer`: A handler of chunks of Response. * * `result`: * - `components`: A map of components added or changed in the last tick associating each type * name to its value on the requested entity. * - `removed`: An array of fully-qualified type names of components removed from the entity * in the last tick. */ async get_watch_strict(entity, components, signal, observer) { return this.requestStream("bevy/get+watch", { entity, components, strict: true }, signal, observer); } /** * Watch all components present on an entity. * * When `entity` is not provided, this lists all registered components. If `entity` is provided, * this lists only those components present on the provided entity. * * `params`: * - `signal`: A signal object that allows you to abort it if required via an {@link AbortController} object. * - `observer`: A handler of chunks of Response. * - `entity`: (optional) The ID of the entity whose components will be listed. * * `result`: * - `added`: An array of fully-qualified type names of components added to the entity in the * last tick. * - `removed`: An array of fully-qualified type names of components removed from the entity * in the last tick. */ async list_watch(signal, observer, entity) { if (entity) return this.requestStream("bevy/list+watch", { entity }, signal, observer); return this.requestStream("bevy/list+watch", null, signal, observer); } }; _BevyRemoteProtocol.DEFAULT_URL = new import_url.URL("http://127.0.0.1:15702"); _BevyRemoteProtocol.INTERNAL_TO_V0_15 = { "bevy_ecs::hierarchy::Children": "bevy_hierarchy::components::children::Children", "bevy_ecs::name::Name": "bevy_core::name::Name" }; _BevyRemoteProtocol.INTERNAL_TO_V0_16 = {}; _BevyRemoteProtocol.ANY_TO_INTERNAL = collectMaps([reverseMap(_BevyRemoteProtocol.INTERNAL_TO_V0_15), reverseMap(_BevyRemoteProtocol.INTERNAL_TO_V0_16)]); _BevyRemoteProtocol.decoder = new import_util.TextDecoder(); var BevyRemoteProtocol = _BevyRemoteProtocol; // src/index.ts function short(typePath) { return (/[^::]*$/.exec(typePath.split("<")[0]) ?? "???")[0]; } // Annotate the CommonJS export names for ESM import in node: 0 && (module.exports = { BevyRemoteProtocol, BrpStructure, ServerVersion, short });