/// import { Command, CommandSender, ConsumedArgs, } from "pumpkin:plugin/command@0.1.0"; import { Context } from "pumpkin:plugin/context@0.1.0"; import { Event, EventType, EventPriority } from "pumpkin:plugin/event@0.1.0"; import { IpcMessage, PluginId } from "pumpkin:plugin/ipc@0.1.0"; import { PluginMetadata } from "pumpkin:plugin/metadata@0.1.0"; import * as scheduler from "pumpkin:plugin/scheduler@0.1.0"; import { Server } from "pumpkin:plugin/server@0.1.0"; import { Entity } from "pumpkin:plugin/world@0.1.0"; export type EventHandler = (srv: Server, evt: T) => T | void; export type CommandHandler = ( sender: CommandSender, srv: Server, args: ConsumedArgs, ) => number; export type TaskHandler = (srv: Server) => void; export interface AiGoal { canStart: (server: Server, entity: Entity) => boolean; shouldContinue: (server: Server, entity: Entity) => boolean; start: (server: Server, entity: Entity) => void; tick: (server: Server, entity: Entity) => void; stop: (server: Server, entity: Entity) => void; } let pluginInstance: Plugin | null = null; const eventHandlers = new Map(); const commandHandlers = new Map(); const taskHandlers = new Map(); const aiGoals = new Map(); let nextHandlerId = 0; let nextAiGoalId = 0; function getNextHandlerId(): number { return nextHandlerId++; } function getAiGoalId(): number { return nextAiGoalId++; } export abstract class Plugin { private pendingEvents: Array<{ eventType: EventType; handler: EventHandler; priority: EventPriority; blocking: boolean; }> = []; abstract metadata(): PluginMetadata; onLoad(ctx: Context): void { for (const { eventType, handler, priority, blocking } of this .pendingEvents) { this.registerEvent(ctx, eventType, handler, priority, blocking); } } onUnload(_ctx: Context): void {} handleIpcMessage(sender: PluginId, message: IpcMessage): IpcMessage { throw "This plugin cannot recieve messages"; } registerEvent( ctx: Context, eventType: EventType, handler: EventHandler, priority: EventPriority = "normal", blocking: boolean = true, ): void { const handlerId = getNextHandlerId(); eventHandlers.set(handlerId, handler); ctx.registerEvent(handlerId, eventType, priority, blocking); } registerCommand( ctx: Context, cmd: Command, handler: CommandHandler, permission: string = "", ): void { const handlerId = getNextHandlerId(); commandHandlers.set(handlerId, handler); cmd.executeWithHandlerId(handlerId); ctx.registerCommand(cmd, permission); } scheduleDelayedTask( delayTicks: number | bigint, handler: TaskHandler, ): number { const handlerId = getNextHandlerId(); taskHandlers.set(handlerId, handler); return scheduler.scheduleDelayedTask(handlerId, BigInt(delayTicks)); } scheduleRepeatingTask( delayTicks: number | bigint, periodTicks: number | bigint, handler: TaskHandler, ): number { const handlerId = getNextHandlerId(); taskHandlers.set(handlerId, handler); return scheduler.scheduleRepeatingTask( handlerId, BigInt(delayTicks), BigInt(periodTicks), ); } registerAiGoal(goal: AiGoal): number { const aiGoalId = getAiGoalId(); aiGoals.set(aiGoalId, goal); return aiGoalId; } } export function registerPlugin(plugin: Plugin) { pluginInstance = plugin; } // Exports for the WIT world export function initPlugin(): void {} export function onLoad(ctx: Context): void { if (pluginInstance) { pluginInstance.onLoad(ctx); } } export function onUnload(ctx: Context): void { if (pluginInstance) { pluginInstance.onUnload(ctx); } } export function handleEvent(eventId: number, srv: Server, evt: Event): Event { const handler = eventHandlers.get(eventId); if (handler) { const result = handler(srv, evt.val); if (result !== undefined) { evt.val = result; } } return evt; } export function handleCommand( commandId: number, sender: CommandSender, srv: Server, args: ConsumedArgs, ): number { const handler = commandHandlers.get(commandId); if (handler) { return handler(sender, srv, args); } throw new Error(`No handler for command ID ${commandId}`); } export function handleTask(handlerId: number, srv: Server): void { const handler = taskHandlers.get(handlerId); if (handler) { handler(srv); } } export function handleIpcMessage( sender: PluginId, message: IpcMessage, ): IpcMessage { if (pluginInstance) { return pluginInstance.handleIpcMessage(sender, message); } throw new Error("No plugin instance available?"); } export function handleAiGoalCanStart( goalId: number, server: Server, entity: Entity, ): boolean { const aiGoal = aiGoals.get(goalId); if (aiGoal) { return aiGoal.canStart(server, entity); } throw new Error(`No AI goal registered for ID ${goalId}`); } export function handleAiGoalShouldContinue( goalId: number, server: Server, entity: Entity, ): boolean { const aiGoal = aiGoals.get(goalId); if (aiGoal) { return aiGoal.shouldContinue(server, entity); } throw new Error(`No AI goal registered for ID ${goalId}`); } export function handleAiGoalStart( goalId: number, server: Server, entity: Entity, ): void { const aiGoal = aiGoals.get(goalId); if (aiGoal) { aiGoal.start(server, entity); return; } throw new Error(`No AI goal registered for ID ${goalId}`); } export function handleAiGoalTick( goalId: number, server: Server, entity: Entity, ): void { const aiGoal = aiGoals.get(goalId); if (aiGoal) { aiGoal.tick(server, entity); return; } throw new Error(`No AI goal registered for ID ${goalId}`); } export function handleAiGoalStop( goalId: number, server: Server, entity: Entity, ): void { const aiGoal = aiGoals.get(goalId); if (aiGoal) { aiGoal.stop(server, entity); return; } throw new Error(`No AI goal registered for ID ${goalId}`); } export const metadata = { getMetadata(): PluginMetadata { if (pluginInstance) { return pluginInstance.metadata(); } return { name: "unknown", version: "0.0.0", authors: [], description: "No metadata", dependencies: [], permissions: [], }; }, }; export const common = {};