feat: API is now functional ingame

This commit is contained in:
ForestOfLight
2026-06-03 23:46:32 +02:00
Unverified
parent 630d5e0950
commit 059d7b5c03
7 changed files with 69 additions and 41 deletions
+1 -1
View File
@@ -1,4 +1,4 @@
import { PROTO } from "../../lib/AddonAPIKit"; import { PROTO } from "../lib/AddonAPIKit";
// Instances // Instances
@@ -1,15 +1,14 @@
import { BuilderNotFoundError } from "../../classes/Errors/BuilderNotFoundError"; import { BuilderNotFoundError } from "../../classes/Errors/BuilderNotFoundError";
import { APICallerError } from "../../lib/AddonAPIKit"; import { APICallerError, APIController } from "../../lib/AddonAPIKit";
import { BuilderIdParameterModel } from "../ConstructAPIModel"; import { BuilderIdParameterModel, BuilderModel } from "../ConstructAPIModel";
export class BuildersController extends APIController { export class BuildersController extends APIController {
#context; #context;
constructor(context) { constructor(context) {
super({ super();
"builders:get": { callback: this.getBuilder, parameterModel: BuilderIdParameterModel, returnModel: InstanceModel }, this.addEndpoint("builder:get", this.getBuilder, BuilderIdParameterModel, BuilderModel);
"builders:edit": { callback: this.editBuilder, parameterModel: InstanceModel, returnModel: InstanceModel } this.addEndpoint("builder:edit", this.editBuilder, BuilderModel, BuilderModel);
});
this.#context = context; this.#context = context;
} }
@@ -48,6 +48,7 @@ export class InstancesController extends APIController {
try { try {
const instance = this.#context.get(instanceName); const instance = this.#context.get(instanceName);
instance.setOptions(instanceOptions); instance.setOptions(instanceOptions);
return instance.asPacket();
} catch(error) { } catch(error) {
if (error instanceof InstanceNotFoundError || error instanceof InstanceExistsError || error instanceof StructureNotFoundError) if (error instanceof InstanceNotFoundError || error instanceof InstanceExistsError || error instanceof StructureNotFoundError)
throw new APICallerError(error); throw new APICallerError(error);
@@ -19,6 +19,7 @@ export class Builders {
const builder = Builders.builders[id]; const builder = Builders.builders[id];
if (builder === void 0) if (builder === void 0)
throw new BuilderNotFoundError(id); throw new BuilderNotFoundError(id);
return builder;
} }
static onJoin(playerId) { static onJoin(playerId) {
@@ -64,7 +64,7 @@ export class InstanceOptions extends Option {
} }
setLayer(layer) { setLayer(layer) {
this.currentLayer = layer.floor(); this.currentLayer = Math.floor(layer);
this.save(); this.save();
} }
@@ -308,8 +308,9 @@ export class StructureInstance {
setOptions(newOptions) { setOptions(newOptions) {
const newVerifierOptions = newOptions.verifier; const newVerifierOptions = newOptions.verifier;
this.options.rename(newOptions.name); if (newOptions.name !== this.getName())
this.options.setStructure(newOptions.structureId); structureCollection.rename(this.getName(), newOptions.name);
this.setStructure(newOptions.structureId);
this.options.setEnabled(newOptions.isEnabled); this.options.setEnabled(newOptions.isEnabled);
this.options.move(newOptions.dimensionId, newOptions.location); this.options.move(newOptions.dimensionId, newOptions.location);
this.options.setLayer(newOptions.currentLayer); this.options.setLayer(newOptions.currentLayer);
@@ -317,5 +318,6 @@ export class StructureInstance {
this.options.setVerifierDistance(newVerifierOptions.trackPlayerDistance); this.options.setVerifierDistance(newVerifierOptions.trackPlayerDistance);
this.options.setVerifierParticleLifetime(newVerifierOptions.particleLifetime); this.options.setVerifierParticleLifetime(newVerifierOptions.particleLifetime);
this.options.save(); this.options.save();
this.refreshBox();
} }
} }
+56 -31
View File
@@ -668,7 +668,7 @@ var APIVersionMismatchError = class extends Error {
}; };
// src/APIModels.js // src/APIModels.js
var VoidModel = PROTO.Void; var VoidModel = PROTO.Optional(PROTO.Void);
var ErrorModel = PROTO.Optional(PROTO.Object({ var ErrorModel = PROTO.Optional(PROTO.Object({
code: PROTO.Int8, code: PROTO.Int8,
name: PROTO.Optional(PROTO.String), name: PROTO.Optional(PROTO.String),
@@ -718,7 +718,7 @@ var EndpointsController = class extends APIController {
var AddonAPIServer = class { var AddonAPIServer = class {
#name; #name;
#version; #version;
#allEndpoints; #allEndpoints = [];
constructor(name, version) { constructor(name, version) {
this.#name = name; this.#name = name;
this.#version = version; this.#version = version;
@@ -745,12 +745,16 @@ var AddonAPIServer = class {
} }
} }
#setupEndpoint(endpoint, callback, parameterModel, returnDataModel) { #setupEndpoint(endpoint, callback, parameterModel, returnDataModel) {
const callPacketModel = this.#resolveCallModel(parameterModel);
const returnPacketModel = this.#resolveReturnModel(returnDataModel); const returnPacketModel = this.#resolveReturnModel(returnDataModel);
const endpointPath = this.endpointBase + endpoint; 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 apiVersion = callPacket.apiVersion;
const parameters = Object.values(callPacket.parameterMap); const parameters = this.#resolveParameters(callPacket);
return this.#handleCallback(apiVersion, callback, parameters); const returnPacket = this.#handleCallback(apiVersion, callback, parameters);
console.info(`Replying ${JSON.stringify(returnPacket)}`);
return returnPacket;
}); });
this.#allEndpoints.push(endpointPath); this.#allEndpoints.push(endpointPath);
} }
@@ -764,7 +768,7 @@ var AddonAPIServer = class {
const errorPacket2 = this.#resolveErrorPacket(error); const errorPacket2 = this.#resolveErrorPacket(error);
return this.#bundleReturnPacket(errorPacket2); return this.#bundleReturnPacket(errorPacket2);
} }
console.error(error); console.error(error, error.stack);
const apiError = new APIServerError(error); const apiError = new APIServerError(error);
const errorPacket = this.#resolveErrorPacket(apiError); const errorPacket = this.#resolveErrorPacket(apiError);
return this.#bundleReturnPacket(errorPacket); return this.#bundleReturnPacket(errorPacket);
@@ -776,11 +780,16 @@ var AddonAPIServer = class {
throw new APICallerError(apiVersionMismatchError); throw new APICallerError(apiVersionMismatchError);
} }
} }
#resolveCallModel(parameterModel) {
return PROTO.Object({ ...CallModelShell, parameterMap: parameterModel });
}
#resolveReturnModel(returnDataModel) { #resolveReturnModel(returnDataModel) {
let returnModel = { ...ReturnModelShell }; return PROTO.Object({ ...ReturnModelShell, data: PROTO.Optional(returnDataModel) });
returnModel.data = returnDataModel; }
returnModel = PROTO.Object(returnModel); #resolveParameters(callPacket) {
return returnModel; if (callPacket.parameterMap === void 0)
return [];
return Object.values(callPacket.parameterMap);
} }
#bundleReturnPacket(errorPacket, returnValue = void 0) { #bundleReturnPacket(errorPacket, returnValue = void 0) {
return { return {
@@ -810,39 +819,54 @@ var APIEndpointNotFoundError = class extends Error {
}; };
// src/AddonAPICaller.js // src/AddonAPICaller.js
var AddonAPICaller = class _AddonAPICaller { var AddonAPICaller = class {
static #validEndpointCache = []; #name;
static async call(endpoint, parameterModel, parameterMap, returnDataModel) { #version;
await _AddonAPICaller.#tryPopulateEndpointCache(endpoint); #validEndpointCache = [];
if (_AddonAPICaller.#endpointExists(endpoint)) { constructor(name, version) {
const response = await IPC.invoke(endpoint, parameterModel, parameterMap, returnDataModel).then((result) => result.value); this.#name = name;
return _AddonAPICaller.#unwrapPacket(response); this.#version = version;
} else { }
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); throw new APIEndpointNotFoundError(endpoint);
} }
} async #tryPopulateEndpointCache(endpoint) {
static async #tryPopulateEndpointCache(endpoint) { if (this.#validEndpointCache.length === 0) {
if (_AddonAPICaller.#validEndpointCache.length === 0) {
const endpointBase = endpoint.split(":")[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) { async #callDirect(endpoint, parameterMapModel, parameterMap, returnDataModel) {
return _AddonAPICaller.#validEndpointCache.includes(endpoint); 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) { #endpointExists(endpoint) {
const endpointsEndpoint = endpointBase + ":endpoints"; return this.#validEndpointCache.includes(endpoint);
const validEndpoints = await IPC.invoke(endpointsEndpoint, VoidModel, void 0, PROTO.Boolean);
_AddonAPICaller.#validEndpointCache.push(...validEndpoints);
} }
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; const { data, error } = packet;
if (error.code === APIErrorEnum.Success) if (error.code === APIErrorEnum.Success)
return data; return data;
else else
_AddonAPICaller.#throwAPIError(packet.error); this.#throwAPIError(packet.error);
} }
static #throwAPIError(errorData) { #throwAPIError(errorData) {
switch (errorData.code) { switch (errorData.code) {
case APIErrorEnum.Caller: case APIErrorEnum.Caller:
throw new APICallerError(errorData); throw new APICallerError(errorData);
@@ -857,6 +881,7 @@ var AddonAPICaller = class _AddonAPICaller {
export { export {
APICallerError, APICallerError,
APIController, APIController,
APIEndpointNotFoundError,
APIErrorEnum, APIErrorEnum,
AddonAPICaller, AddonAPICaller,
AddonAPIServer, AddonAPIServer,