166 lines
6.3 KiB
JavaScript
166 lines
6.3 KiB
JavaScript
/**
|
|
* @license
|
|
* MIT License
|
|
*
|
|
* Copyright (c) 2024 ForestOfLight
|
|
*
|
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
* of this software and associated documentation files (the "Software"), to deal
|
|
* in the Software without restriction, including without limitation the rights
|
|
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
* copies of the Software, and to permit persons to whom the Software is
|
|
* furnished to do so, subject to the following conditions:
|
|
*
|
|
* The above copyright notice and this permission notice shall be included in all
|
|
* copies or substantial portions of the Software.
|
|
*
|
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
* SOFTWARE.
|
|
*/
|
|
import { world } from '@minecraft/server';
|
|
import IPC from '../ipc/ipc';
|
|
import Command from './Command';
|
|
import Rule from './Rule';
|
|
import { CommandCallbackRequest, CommandPrefixRequest, Ready, RegisterCommand, RegisterExtension, RegisterRule, RuleValueRequest, RuleValueSet, CommandPrefixResponse, RuleValueResponse } from './extension.ipc';
|
|
|
|
class CanopyExtension {
|
|
name;
|
|
version;
|
|
author;
|
|
description;
|
|
#commands = {};
|
|
#rules = {};
|
|
#isRegistrationReady = false;
|
|
|
|
constructor({ name = 'Unnamed', version = '1.0.0', author = 'Unknown', description = { text: '' } }) {
|
|
this.id = this.#makeID(name);
|
|
this.name = name;
|
|
this.version = version;
|
|
this.author = author;
|
|
this.description = description;
|
|
|
|
this.#registerExtension();
|
|
this.#setupCommandPrefix();
|
|
this.#handleCommandCallbacks();
|
|
this.#handleRuleValueRequests();
|
|
this.#handleRuleValueSetters();
|
|
}
|
|
|
|
addCommand(command) {
|
|
if (!(command instanceof Command))
|
|
throw new Error('Command must be an instance of Command.');
|
|
this.#commands[command.getName()] = command;
|
|
if (this.#isRegistrationReady)
|
|
this.#registerCommand(command);
|
|
}
|
|
|
|
addRule(rule) {
|
|
if (!(rule instanceof Rule))
|
|
throw new Error('Rule must be an instance of Rule.');
|
|
this.#rules[rule.getID()] = rule;
|
|
if (this.#isRegistrationReady)
|
|
this.#registerRule(rule);
|
|
}
|
|
|
|
getRuleValue(ruleID) {
|
|
return this.#rules[ruleID].getValue();
|
|
}
|
|
|
|
#makeID(name) {
|
|
if (typeof name !== 'string')
|
|
throw new Error(`[${name}] Could not register extension. Extension name must be a string.`);
|
|
const id = name.toLowerCase().replace(/[^a-z0-9 ]/g, '').replace(/ /g, '_');
|
|
if (id.length === 0)
|
|
throw new Error(`[${name}] Could not register extension. Extension name must contain at least one alphanumeric character.`);
|
|
return id;
|
|
}
|
|
|
|
#registerExtension() {
|
|
IPC.once('canopyExtension:ready', Ready, () => {
|
|
IPC.send('canopyExtension:registerExtension', RegisterExtension, {
|
|
name: this.name,
|
|
version: this.version,
|
|
author: this.author,
|
|
description: this.description
|
|
});
|
|
});
|
|
IPC.once(`canopyExtension:${this.id}:ready`, Ready, () => {
|
|
this.#isRegistrationReady = true;
|
|
for (const rule of Object.values(this.#rules))
|
|
this.#registerRule(rule);
|
|
for (const command of Object.values(this.#commands))
|
|
this.#registerCommand(command);
|
|
});
|
|
}
|
|
|
|
#registerCommand(command) {
|
|
IPC.send(`canopyExtension:${this.id}:registerCommand`, RegisterCommand, {
|
|
name: command.getName(),
|
|
description: command.getDescription(),
|
|
usage: command.getUsage(),
|
|
callback: false,
|
|
args: command.getArgs(),
|
|
contingentRules: command.getContingentRules(),
|
|
adminOnly: command.isAdminOnly(),
|
|
helpEntries: command.getHelpEntries(),
|
|
helpHidden: command.isHelpHidden(),
|
|
extensionName: this.name
|
|
});
|
|
}
|
|
|
|
#handleCommandCallbacks() {
|
|
IPC.on(`canopyExtension:${this.id}:commandCallbackRequest`, CommandCallbackRequest, (cmdData) => {
|
|
if (cmdData.senderName === undefined)
|
|
return;
|
|
const sender = world.getPlayers({ name: cmdData.senderName })[0];
|
|
if (!sender)
|
|
throw new Error(`Sender ${cmdData.senderName} of ${cmdData.commandName} not found.`);
|
|
const parsedArgs = JSON.parse(cmdData.args);
|
|
this.#commands[cmdData.commandName].runCallback(sender, parsedArgs);
|
|
});
|
|
}
|
|
|
|
#registerRule(rule) {
|
|
IPC.send(`canopyExtension:${this.id}:registerRule`, RegisterRule, {
|
|
identifier: rule.getID(),
|
|
description: rule.getDescription(),
|
|
contingentRules: rule.getContigentRules(),
|
|
independentRules: rule.getIndependentRules(),
|
|
extensionName: this.name
|
|
});
|
|
if (rule.getValue() === true)
|
|
rule.onEnable();
|
|
}
|
|
|
|
#handleRuleValueRequests() {
|
|
IPC.handle(`canopyExtension:${this.id}:ruleValueRequest`, RuleValueRequest, RuleValueResponse, (data) => {
|
|
const rule = this.#rules[data.ruleID];
|
|
if (!rule)
|
|
throw new Error(`Rule ${data.ruleID} not found.`);
|
|
const value = rule.getValue();
|
|
return { value };
|
|
});
|
|
}
|
|
|
|
#handleRuleValueSetters() {
|
|
IPC.on(`canopyExtension:${this.id}:ruleValueSet`, RuleValueSet, (data) => {
|
|
const rule = this.#rules[data.ruleID];
|
|
if (!rule)
|
|
throw new Error(`Rule ${data.ruleID} not found.`);
|
|
rule.setValue(data.value);
|
|
});
|
|
}
|
|
|
|
#setupCommandPrefix() {
|
|
const prefix = IPC.invoke(`canopyExtension:commandPrefixRequest`, CommandPrefixRequest, void 0, CommandPrefixResponse).then(result => {
|
|
Command.setPrefix(result.prefix);
|
|
});
|
|
}
|
|
}
|
|
|
|
export { CanopyExtension, Command, Rule }; |