UNPKG

crmod-api

Version:

A dynamic mod/asset generator for Cosmic Reach

214 lines (191 loc) 6.92 kB
import BlockAction from "./blockAction.js"; import Writeable from "./writeable.js"; /** * @typedef {Function} BlockActionComparator * @param {BlockAction} action The action to compare. * @returns {boolean} Whether the action matches the comparison. */ /** * The parent for any {@link TriggerSheet} that does not have a parent explicitly declared. * * @package * @readonly * @type {Object<string, TriggerSheet>} */ const BASE_TRIGGER_SHEET = {}; /** * Defines a collection of triggers and actions that can be executed by a block. * * @class TriggerSheet * @extends {Writeable} */ class TriggerSheet extends Writeable { /** * The parent TriggerSheet for this trigger sheet. * * @type {TriggerSheet} * @memberof TriggerSheet */ parent; /** * The unique id for this trigger sheet. * * @type {string} * @memberof TriggerSheet */ id; /** * The triggers and actions for this trigger sheet. * * @type {Object<string, Array<BlockAction>>} * @memberof TriggerSheet */ triggers; /** * Initializes a new trigger sheet. * * @param {string} id The unique id for this trigger sheet. * @param {parent} [parent=null] The parent TriggerSheet for this trigger sheet. * @memberof TriggerSheet */ constructor(id, parent = null) { super(); this.parent = parent; this.id = id; this.triggers = {}; if(this.parent?.triggers != null) this.append(this.parent); } /** * Adds a new action to the trigger sheet. * * If the {@link trigger} does not exist, it will be created. * * @param {string|Array<string>} triggers A trigger or a list of triggers to add the action to. * @param {BlockAction} action The action to add. * @param {number?} index The index to insert the action at. * @memberof TriggerSheet */ addAction(triggers, action, index = this.triggers[(triggers instanceof Array) ? triggers[0] : triggers]?.length ?? 0) { if(action instanceof Array) throw new TypeError("Use addActions() for array support"); if(!(triggers instanceof Array)) triggers = [triggers]; for(const trigger of triggers) { this.triggers[trigger] ??= new Array; if(index < 0) index += this.triggers[trigger].length; this.triggers[trigger].splice(index, 0, action); } } /** * Adds multiple actions to multiple triggers within the trigger sheet. * * For each trigger on {@link triggers}, the corresponding actions in {@link actions} will be added. * * @param {string|Array<string>} triggers A trigger or a list of triggers to add the actions to. * @param {BlockAction} actions The actions to add. * @param {number?} startingIndex The index to sequentially insert the actions at. * @memberof TriggerSheet */ addActions(triggers, actions, startingIndex = this.triggers[(triggers instanceof Array) ? triggers[0] : triggers]?.length ?? 0) { if(actions instanceof BlockAction) throw new TypeError("Use addAction() to add one action"); if(!(triggers instanceof Array)) triggers = [triggers]; if(startingIndex < 0) startingIndex += this.triggers[triggers[0]]?.length ?? 0; let i = 0; for(const action of actions) this.addAction(triggers, action, startingIndex + i++); } /** * Removes a trigger from the trigger sheet. * * @param {string} trigger * @memberof TriggerSheet */ removeTrigger(trigger) { delete this.triggers[trigger]; } /** * Removes an action from all triggers within the trigger sheet. * * @param {BlockActionComparator} comparator The function to use to select actions. * @memberof TriggerSheet */ removeActionByComparison(comparator) { for(const triggerId in this.triggers) { this.removeTriggerActionByComparison(triggerId, comparator); } } /** * Removes an action from a specific trigger within the trigger sheet. * * @param {string} trigger * @param {BlockActionComparator} comparator The function to use to select actions. * @memberof TriggerSheet */ removeTriggerActionByComparison(trigger, comparator) { const actions = this.triggers[trigger]; const deletions = new Array; for(const action of actions) { if(comparator(action)) deletions.push(action); } for(const deletion of deletions) { actions.splice(actions.indexOf(deletion), 1); } this.triggers[trigger] = actions; } /** * Serializes the trigger sheet into a JSON object. * * @override * @param {string} prefix The prefix to use for the string id. * @return {Object} The serialized trigger sheet as a JSON object. * @memberof TriggerSheet */ serialize(prefix) { const output = new TriggerSheet(this.id, BASE_TRIGGER_SHEET); output.append(this); return { parent: output.parent?.id ?? BASE_TRIGGER_SHEET.id, stringId: prefix + ":" + output.id, triggers: Object.fromEntries(Object.keys(output.triggers).map(k => [k, output.triggers[k].map(t => t.serialize())])) } } /** * Clones the trigger sheet into a new instance. * * @param {string} [id=this.id] * @return {TriggerSheet} A new instance of the current trigger sheet. * @memberof TriggerSheet */ clone(id = this.id) { const sheet = new TriggerSheet(id, this.parent); for(const triggerId in this.triggers) { const triggers = this.triggers[triggerId]; for(const trigger of triggers) { sheet.addAction(triggerId, trigger.clone()); } } return sheet; } /** * Appends another trigger sheet to this trigger sheet. * * @param {TriggerSheet} other The trigger sheet to append. * @return {this} The current trigger sheet. * @memberof TriggerSheet */ append(other) { for(const triggerId in other.triggers) { for(const trigger of other.triggers[triggerId]) { this.addAction(triggerId, trigger.clone()); } } return this; } } { const sheet = new TriggerSheet("base:block_events_default", {}); sheet.addAction("onPlace", BlockAction.replaceBlock(0, 0, 0, "self")); sheet.addAction("onPlace", BlockAction.playSound2d("block-place.ogg")); sheet.addAction("onBreak", BlockAction.replaceBlock(0, 0, 0, "base:air[default]")); sheet.addAction("onBreak", BlockAction.playSound2d("block-break.ogg")); sheet.written = true; Object.assign(BASE_TRIGGER_SHEET, sheet); } export default TriggerSheet;