From 059d7b5c0397097432888d65beb53c2fece593bf Mon Sep 17 00:00:00 2001 From: ForestOfLight Date: Wed, 3 Jun 2026 23:46:32 +0200 Subject: [PATCH] feat: API is now functional ingame --- packs/BP/scripts/API/ConstructAPIModel.js | 2 +- .../API/controllers/BuildersController.js | 11 ++- .../API/controllers/InstancesController.js | 1 + packs/BP/scripts/classes/Builder/Builders.js | 1 + .../classes/Instance/InstanceOptions.js | 2 +- .../classes/Instance/StructureInstance.js | 6 +- packs/BP/scripts/lib/AddonAPIKit.js | 87 ++++++++++++------- 7 files changed, 69 insertions(+), 41 deletions(-) diff --git a/packs/BP/scripts/API/ConstructAPIModel.js b/packs/BP/scripts/API/ConstructAPIModel.js index a761777..11db487 100644 --- a/packs/BP/scripts/API/ConstructAPIModel.js +++ b/packs/BP/scripts/API/ConstructAPIModel.js @@ -1,4 +1,4 @@ -import { PROTO } from "../../lib/AddonAPIKit"; +import { PROTO } from "../lib/AddonAPIKit"; // Instances diff --git a/packs/BP/scripts/API/controllers/BuildersController.js b/packs/BP/scripts/API/controllers/BuildersController.js index 6f39523..c211e31 100644 --- a/packs/BP/scripts/API/controllers/BuildersController.js +++ b/packs/BP/scripts/API/controllers/BuildersController.js @@ -1,15 +1,14 @@ import { BuilderNotFoundError } from "../../classes/Errors/BuilderNotFoundError"; -import { APICallerError } from "../../lib/AddonAPIKit"; -import { BuilderIdParameterModel } from "../ConstructAPIModel"; +import { APICallerError, APIController } from "../../lib/AddonAPIKit"; +import { BuilderIdParameterModel, BuilderModel } from "../ConstructAPIModel"; export class BuildersController extends APIController { #context; constructor(context) { - super({ - "builders:get": { callback: this.getBuilder, parameterModel: BuilderIdParameterModel, returnModel: InstanceModel }, - "builders:edit": { callback: this.editBuilder, parameterModel: InstanceModel, returnModel: InstanceModel } - }); + super(); + this.addEndpoint("builder:get", this.getBuilder, BuilderIdParameterModel, BuilderModel); + this.addEndpoint("builder:edit", this.editBuilder, BuilderModel, BuilderModel); this.#context = context; } diff --git a/packs/BP/scripts/API/controllers/InstancesController.js b/packs/BP/scripts/API/controllers/InstancesController.js index ac82e4c..27672e6 100644 --- a/packs/BP/scripts/API/controllers/InstancesController.js +++ b/packs/BP/scripts/API/controllers/InstancesController.js @@ -48,6 +48,7 @@ export class InstancesController extends APIController { try { const instance = this.#context.get(instanceName); instance.setOptions(instanceOptions); + return instance.asPacket(); } catch(error) { if (error instanceof InstanceNotFoundError || error instanceof InstanceExistsError || error instanceof StructureNotFoundError) throw new APICallerError(error); diff --git a/packs/BP/scripts/classes/Builder/Builders.js b/packs/BP/scripts/classes/Builder/Builders.js index 359fdf0..778d57f 100644 --- a/packs/BP/scripts/classes/Builder/Builders.js +++ b/packs/BP/scripts/classes/Builder/Builders.js @@ -19,6 +19,7 @@ export class Builders { const builder = Builders.builders[id]; if (builder === void 0) throw new BuilderNotFoundError(id); + return builder; } static onJoin(playerId) { diff --git a/packs/BP/scripts/classes/Instance/InstanceOptions.js b/packs/BP/scripts/classes/Instance/InstanceOptions.js index de92691..1df2711 100644 --- a/packs/BP/scripts/classes/Instance/InstanceOptions.js +++ b/packs/BP/scripts/classes/Instance/InstanceOptions.js @@ -64,7 +64,7 @@ export class InstanceOptions extends Option { } setLayer(layer) { - this.currentLayer = layer.floor(); + this.currentLayer = Math.floor(layer); this.save(); } diff --git a/packs/BP/scripts/classes/Instance/StructureInstance.js b/packs/BP/scripts/classes/Instance/StructureInstance.js index f474002..6e5028e 100644 --- a/packs/BP/scripts/classes/Instance/StructureInstance.js +++ b/packs/BP/scripts/classes/Instance/StructureInstance.js @@ -308,8 +308,9 @@ export class StructureInstance { setOptions(newOptions) { const newVerifierOptions = newOptions.verifier; - this.options.rename(newOptions.name); - this.options.setStructure(newOptions.structureId); + if (newOptions.name !== this.getName()) + structureCollection.rename(this.getName(), newOptions.name); + this.setStructure(newOptions.structureId); this.options.setEnabled(newOptions.isEnabled); this.options.move(newOptions.dimensionId, newOptions.location); this.options.setLayer(newOptions.currentLayer); @@ -317,5 +318,6 @@ export class StructureInstance { this.options.setVerifierDistance(newVerifierOptions.trackPlayerDistance); this.options.setVerifierParticleLifetime(newVerifierOptions.particleLifetime); this.options.save(); + this.refreshBox(); } } \ No newline at end of file diff --git a/packs/BP/scripts/lib/AddonAPIKit.js b/packs/BP/scripts/lib/AddonAPIKit.js index a871864..e1c0297 100644 --- a/packs/BP/scripts/lib/AddonAPIKit.js +++ b/packs/BP/scripts/lib/AddonAPIKit.js @@ -668,7 +668,7 @@ var APIVersionMismatchError = class extends Error { }; // src/APIModels.js -var VoidModel = PROTO.Void; +var VoidModel = PROTO.Optional(PROTO.Void); var ErrorModel = PROTO.Optional(PROTO.Object({ code: PROTO.Int8, name: PROTO.Optional(PROTO.String), @@ -718,7 +718,7 @@ var EndpointsController = class extends APIController { var AddonAPIServer = class { #name; #version; - #allEndpoints; + #allEndpoints = []; constructor(name, version) { this.#name = name; this.#version = version; @@ -745,12 +745,16 @@ var AddonAPIServer = class { } } #setupEndpoint(endpoint, callback, parameterModel, returnDataModel) { + const callPacketModel = this.#resolveCallModel(parameterModel); const returnPacketModel = this.#resolveReturnModel(returnDataModel); const endpointPath = this.endpointBase + endpoint; - IPC.handle(endpointPath, parameterModel, returnPacketModel, (callPacket) => { + IPC.handle(endpointPath, callPacketModel, returnPacketModel, (callPacket) => { + console.info(`Received at ${endpointPath}: ${JSON.stringify(callPacket)}`); const apiVersion = callPacket.apiVersion; - const parameters = Object.values(callPacket.parameterMap); - return this.#handleCallback(apiVersion, callback, parameters); + const parameters = this.#resolveParameters(callPacket); + const returnPacket = this.#handleCallback(apiVersion, callback, parameters); + console.info(`Replying ${JSON.stringify(returnPacket)}`); + return returnPacket; }); this.#allEndpoints.push(endpointPath); } @@ -764,7 +768,7 @@ var AddonAPIServer = class { const errorPacket2 = this.#resolveErrorPacket(error); return this.#bundleReturnPacket(errorPacket2); } - console.error(error); + console.error(error, error.stack); const apiError = new APIServerError(error); const errorPacket = this.#resolveErrorPacket(apiError); return this.#bundleReturnPacket(errorPacket); @@ -776,11 +780,16 @@ var AddonAPIServer = class { throw new APICallerError(apiVersionMismatchError); } } + #resolveCallModel(parameterModel) { + return PROTO.Object({ ...CallModelShell, parameterMap: parameterModel }); + } #resolveReturnModel(returnDataModel) { - let returnModel = { ...ReturnModelShell }; - returnModel.data = returnDataModel; - returnModel = PROTO.Object(returnModel); - return returnModel; + return PROTO.Object({ ...ReturnModelShell, data: PROTO.Optional(returnDataModel) }); + } + #resolveParameters(callPacket) { + if (callPacket.parameterMap === void 0) + return []; + return Object.values(callPacket.parameterMap); } #bundleReturnPacket(errorPacket, returnValue = void 0) { return { @@ -810,39 +819,54 @@ var APIEndpointNotFoundError = class extends Error { }; // src/AddonAPICaller.js -var AddonAPICaller = class _AddonAPICaller { - static #validEndpointCache = []; - static async call(endpoint, parameterModel, parameterMap, returnDataModel) { - await _AddonAPICaller.#tryPopulateEndpointCache(endpoint); - if (_AddonAPICaller.#endpointExists(endpoint)) { - const response = await IPC.invoke(endpoint, parameterModel, parameterMap, returnDataModel).then((result) => result.value); - return _AddonAPICaller.#unwrapPacket(response); - } else { +var AddonAPICaller = class { + #name; + #version; + #validEndpointCache = []; + constructor(name, version) { + this.#name = name; + this.#version = version; + } + async call(endpoint, parameterMapModel, parameterMap, returnDataModel) { + await this.#tryPopulateEndpointCache(endpoint); + if (this.#endpointExists(endpoint)) + return this.#callDirect(endpoint, parameterMapModel, parameterMap, returnDataModel); + else throw new APIEndpointNotFoundError(endpoint); - } } - static async #tryPopulateEndpointCache(endpoint) { - if (_AddonAPICaller.#validEndpointCache.length === 0) { + async #tryPopulateEndpointCache(endpoint) { + if (this.#validEndpointCache.length === 0) { const endpointBase = endpoint.split(":")[0]; - await _AddonAPICaller.#populateValidEndpointCache(endpointBase); + const validEndpoints = await this.#callDirect(endpointBase + ":endpoints", VoidModel, void 0, EndpointsModel); + this.#validEndpointCache.push(...validEndpoints); } } - static #endpointExists(endpoint) { - return _AddonAPICaller.#validEndpointCache.includes(endpoint); + async #callDirect(endpoint, parameterMapModel, parameterMap, returnDataModel) { + const parameterPacket = { apiVersion: this.#version, parameterMap }; + const parameterModel = this.#resolveParameterModel(parameterMapModel); + const returnModel = this.#resolveReturnModel(returnDataModel); + console.info(`Sending to ${endpoint}: ${JSON.stringify(parameterPacket)}`); + const returnPacket = await IPC.invoke(endpoint, parameterModel, parameterPacket, returnModel); + console.info(`Received from ${endpoint}: ${JSON.stringify(returnPacket)}`); + return this.#unwrapReturnPacket(returnPacket); } - static async #populateValidEndpointCache(endpointBase) { - const endpointsEndpoint = endpointBase + ":endpoints"; - const validEndpoints = await IPC.invoke(endpointsEndpoint, VoidModel, void 0, PROTO.Boolean); - _AddonAPICaller.#validEndpointCache.push(...validEndpoints); + #endpointExists(endpoint) { + return this.#validEndpointCache.includes(endpoint); } - static #unwrapPacket(packet) { + #resolveParameterModel(parameterMapModel) { + return PROTO.Object({ ...CallModelShell, parameterMap: parameterMapModel }); + } + #resolveReturnModel(returnDataModel) { + return PROTO.Object({ ...ReturnModelShell, data: PROTO.Optional(returnDataModel) }); + } + #unwrapReturnPacket(packet) { const { data, error } = packet; if (error.code === APIErrorEnum.Success) return data; else - _AddonAPICaller.#throwAPIError(packet.error); + this.#throwAPIError(packet.error); } - static #throwAPIError(errorData) { + #throwAPIError(errorData) { switch (errorData.code) { case APIErrorEnum.Caller: throw new APICallerError(errorData); @@ -857,6 +881,7 @@ var AddonAPICaller = class _AddonAPICaller { export { APICallerError, APIController, + APIEndpointNotFoundError, APIErrorEnum, AddonAPICaller, AddonAPIServer,