UNPKG

@bedrock-oss/stylish

Version:

A decorator package with for developing add-ons with Script API in Minecraft Bedrock Edition

271 lines (265 loc) 7.09 kB
// src/index.ts import { system, world as world2 } from "@minecraft/server"; // src/eventRegistry.ts import { world } from "@minecraft/server"; var debugEnabled = false; var LOG_PREFIX = "[stylish:events]"; function dbg(message, meta) { if (!debugEnabled) return; try { if (meta) console.debug(LOG_PREFIX, message, meta); else console.debug(LOG_PREFIX, message); } catch { } } var registries = /* @__PURE__ */ Object.create(null); function getRegistry(event) { return registries[event] ??= []; } var instanceEventMethods = /* @__PURE__ */ new WeakMap(); var subscribed = {}; var startupTriggered = false; function dispatch(event) { return (e) => { const reg = getRegistry(event); dbg("dispatch", { event, count: reg.length }); for (const fn of reg) fn(e); }; } function wirePlatformEvent(event) { dbg("wirePlatformEvent", { event }); if (subscribed[event]) { dbg("alreadyWired", { event }); return; } switch (event) { case "startup": case "worldLoad": break; case "beforeItemUse": dbg("subscribe", { source: "world.beforeEvents.itemUse" }); world.beforeEvents.itemUse.subscribe(dispatch("beforeItemUse")); subscribed[event] = true; break; default: break; } } function maybeWirePlatformEvents(event) { dbg("maybeWirePlatformEvents", { startupTriggered }); if (!startupTriggered) { return; } if (event) { if (getRegistry(event).length > 0) wirePlatformEvent(event); return; } for (const evt of Object.keys(registries)) { if (getRegistry(evt).length > 0) wirePlatformEvent(evt); } } function createEventDecorator(event) { const impl = function EventDecorator(target, propertyKey, descriptor) { if (typeof target === "function" && propertyKey === void 0 && descriptor === void 0) { dbg("register:function", { event }); getRegistry(event).push(target); maybeWirePlatformEvents(event); return; } if (propertyKey !== void 0 && descriptor && typeof descriptor.value === "function") { if (typeof target === "function") { dbg("register:static", { event, propertyKey: String(propertyKey) }); const bound = descriptor.value.bind(target); getRegistry(event).push(bound); maybeWirePlatformEvents(event); return descriptor; } dbg("annotate:instance", { event, propertyKey: String(propertyKey) }); const ctor = target.constructor; let map = instanceEventMethods.get(ctor); if (!map) { map = /* @__PURE__ */ new Map(); instanceEventMethods.set(ctor, map); } const list = map.get(event) ?? []; if (!list.includes(propertyKey)) list.push(propertyKey); map.set(event, list); return descriptor; } }; return impl; } var OnStartup = createEventDecorator("startup"); var OnWorldLoad = createEventDecorator("worldLoad"); var OnBeforeItemUse = createEventDecorator("beforeItemUse"); function registerInstanceEventHandlers(instance) { if (!instance) return; const ctor = instance.constructor; const map = instanceEventMethods.get(ctor); if (!map) return; for (const [event, keys] of map) { const reg = getRegistry(event); for (const key of keys) { const fn = instance[key]; if (typeof fn === "function") { reg.push(fn.bind(instance)); } } dbg("register:instance", { event, class: ctor?.name ?? "<anonymous>", count: keys.length }); maybeWirePlatformEvents(event); } } function RegisterEvents(Ctor) { return class extends Ctor { constructor(...args) { super(...args); registerInstanceEventHandlers(this); } }; } function triggerStartupEvent(e) { startupTriggered = true; maybeWirePlatformEvents(); const reg = getRegistry("startup"); dbg("triggerStartupEvent", { count: reg.length }); for (const fn of reg) { fn(e); } } function triggerWorldLoadEvent(e) { const reg = getRegistry("worldLoad"); dbg("triggerWorldLoadEvent", { count: reg.length }); for (const fn of reg) { fn(e); } } // src/itemRegistry.ts var registry = []; function ItemComponent(ctor) { if (!ctor.componentId) { throw new Error(`Component ${ctor.name} is missing static componentId`); } registry.push(ctor); } function registerAllItemComponents(itemComponentRegistry) { for (const Ctor of registry) { const instance = new Ctor(); registerInstanceEventHandlers(instance); itemComponentRegistry.registerCustomComponent( Ctor.componentId, instance ); } } // src/blockRegistry.ts var registry2 = []; function BlockComponent(ctor) { if (!ctor.componentId) { throw new Error(`Component ${ctor.name} is missing static componentId`); } registry2.push(ctor); } function registerAllBlockComponents(blockComponentRegistry) { for (const Ctor of registry2) { const instance = new Ctor(); registerInstanceEventHandlers(instance); blockComponentRegistry.registerCustomComponent( Ctor.componentId, instance ); } } // src/customCommandRegistry.ts var registry3 = []; function CustomCmd(ctor) { registry3.push(ctor); } function registerAllCustomCommands(customCommandRegistry) { for (const Ctor of registry3) { const instance = new Ctor(); registerInstanceEventHandlers(instance); let runFn; const maybeStaticRun = Ctor.run; if (typeof maybeStaticRun === "function") { runFn = maybeStaticRun.bind(Ctor); } else if (typeof instance.run === "function") { runFn = instance.run.bind(instance); } if (!runFn) { throw new Error( `Custom command ${Ctor.name} has no run method. Define a static or instance run(origin, ...args).` ); } customCommandRegistry.registerCommand(instance, runFn); } } // src/autobind.ts function BindThis(_target, propertyKey, descriptor) { const original = descriptor.value; return { configurable: true, enumerable: descriptor.enumerable, get() { const bound = original.bind(this); Object.defineProperty(this, propertyKey, { value: bound, configurable: true, writable: true, enumerable: false }); return bound; } }; } // src/index.ts function init() { system.beforeEvents.startup.subscribe((e) => { registerAllComponents(e.itemComponentRegistry, e.blockComponentRegistry); registerAllCustomCommands(e.customCommandRegistry); triggerStartupEvent(e); }); world2.afterEvents.worldLoad.subscribe((e) => { triggerWorldLoadEvent(e); }); } function initV1() { init(); } function initV2() { init(); } function registerAllComponents(itemRegistry, blockRegistry) { registerAllItemComponents(itemRegistry); registerAllBlockComponents(blockRegistry); } export { BindThis, BlockComponent, CustomCmd, ItemComponent, OnBeforeItemUse, OnStartup, OnWorldLoad, RegisterEvents, createEventDecorator, init, initV1, initV2, registerAllComponents }; //# sourceMappingURL=index.mjs.map