@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
JavaScript
// 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