From 60c91447ac3bcc38dcb08ec4635627a7c745f9cd Mon Sep 17 00:00:00 2001 From: Demetrius Kanios Date: Mon, 10 Aug 2026 12:36:49 -0700 Subject: [PATCH] AI goals and IPC --- dist/index.ts | 98 +++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 98 insertions(+) diff --git a/dist/index.ts b/dist/index.ts index 7b7e2e5..13d70cf 100644 --- a/dist/index.ts +++ b/dist/index.ts @@ -7,9 +7,11 @@ import { } 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 = ( @@ -18,17 +20,30 @@ export type CommandHandler = ( 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; @@ -48,6 +63,10 @@ export abstract class Plugin { onUnload(_ctx: Context): void {} + handleIpcMessage(sender: PluginId, message: IpcMessage): IpcMessage { + throw "This plugin cannot recieve messages"; + } + registerEvent( ctx: Context, eventType: EventType, @@ -94,6 +113,12 @@ export abstract class Plugin { BigInt(periodTicks), ); } + + registerAiGoal(goal: AiGoal): number { + const aiGoalId = getAiGoalId(); + aiGoals.set(aiGoalId, goal); + return aiGoalId; + } } export function registerPlugin(plugin: Plugin) { @@ -146,6 +171,79 @@ export function handleTask(handlerId: number, srv: Server): void { } } +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) {