diff --git a/java/noppes/npcs/api/handler/IHookDefinition.java b/java/noppes/npcs/api/handler/IHookDefinition.java new file mode 100644 index 0000000..6068203 --- /dev/null +++ b/java/noppes/npcs/api/handler/IHookDefinition.java @@ -0,0 +1,106 @@ +package noppes.npcs.api.handler; + +/** + * Defines metadata for a script hook, enabling rich hook registration with proper + * type information for stub generation, imports, and documentation. + * + *
{@code
+ * // Addon registration with full metadata
+ * IScriptHookHandler hooks = NpcAPI.Instance().getScriptHooks();
+ * hooks.registerHookDefinition("player", HookDefinition.builder("onDBCTransform")
+ * .eventClass("com.dbc.api.event.IDBCEvent$TransformEvent")
+ * .paramNames("event")
+ * .requiredImports("com.dbc.api.event.IDBCEvent")
+ * .cancelable(true)
+ * .build());
+ * }
+ */
+public interface IHookDefinition {
+
+ /**
+ * The hook name (function name in scripts).
+ *
+ * @return Hook name, e.g., "questStart", "onDBCTransform"
+ */
+ String hookName();
+
+ /**
+ * Full qualified class name of the event type.
+ * Uses '$' for nested classes (e.g., "noppes.npcs.api.event.IQuestEvent$QuestStartEvent").
+ *
+ * @return Fully qualified event class name, or null if unknown
+ */
+ String eventClassName();
+
+ /**
+ * Parameter names for stub generation.
+ *
+ * @return Array of parameter names, defaults to ["event"]
+ */
+ String[] paramNames();
+
+ /**
+ * Imports required for this hook's event type.
+ * These will be added to the script's default imports.
+ *
+ * @return Array of fully qualified class/package names to import
+ */
+ String[] requiredImports();
+
+ /**
+ * Whether the event is cancelable (has @Cancelable annotation).
+ *
+ * @return true if event can be canceled
+ */
+ boolean isCancelable();
+
+ /**
+ * Lazily resolve the event class. Returns null if class is not available
+ * (e.g., addon not loaded).
+ *
+ * @return The event class, or null if unavailable
+ */
+ default Class> getEventClass() {
+ String className = eventClassName();
+ if (className == null || className.isEmpty()) {
+ return null;
+ }
+ try {
+ return Class.forName(className);
+ } catch (ClassNotFoundException e) {
+ return null;
+ }
+ }
+
+ /**
+ * Generate a usable type name for stub generation.
+ * Handles nested classes by converting '$' to '.'.
+ *
+ * Examples:
+ *{@code
+ * hooks.registerHookDefinition("player", HookDefinition.builder("onDBCTransform")
+ * .eventClass(IDBCEvent.TransformEvent.class)
+ * .requiredImports("com.dbc.api.event.IDBCEvent")
+ * .cancelable(true)
+ * .build());
+ * }
*/
public interface IScriptHookHandler {
+ // ==================== RICH HOOK REGISTRATION (NEW) ====================
+
/**
- * Register a hook for a single context.
+ * Register a hook with full metadata including event type, imports, and cancelability.
+ * This is the recommended way to register addon hooks.
+ *
+ * @param context The context identifier (e.g., "npc", "player", "block")
+ * @param definition The hook definition containing all metadata
+ */
+ void registerHookDefinition(String context, IHookDefinition definition);
+
+ /**
+ * Get the hook definition for a specific hook.
+ *
+ * @param context The context identifier
+ * @param hookName The hook function name
+ * @return The hook definition, or null if not found or no metadata available
+ */
+ IHookDefinition getHookDefinition(String context, String hookName);
+
+ /**
+ * Get all hook definitions for a context.
+ *
+ * @param context The context identifier
+ * @return List of all hook definitions (may be empty, never null)
+ */
+ List