itemscore-helper 1.2.3 → 1.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/manifest.js +38 -4
- package/package.json +1 -1
- package/skill/ITEM_FORMAT.md +27 -4
- package/skill/SKILL.md +2 -1
package/lib/manifest.js
CHANGED
|
@@ -289,6 +289,33 @@ function validateItem(idx, item) {
|
|
|
289
289
|
}
|
|
290
290
|
}
|
|
291
291
|
|
|
292
|
+
if (item.events !== undefined && item.customEvents === undefined) {
|
|
293
|
+
warnings.push('the custom-event field is named "customEvents", not "events"; rename it so the plugin reads it')
|
|
294
|
+
}
|
|
295
|
+
|
|
296
|
+
if (item.customEvents !== undefined) {
|
|
297
|
+
if (!Array.isArray(item.customEvents)) errors.push("customEvents must be an array")
|
|
298
|
+
else {
|
|
299
|
+
item.customEvents.forEach((ce, ci) => {
|
|
300
|
+
const cp = "customEvents[" + ci + "]"
|
|
301
|
+
if (typeof ce !== "object" || ce === null) {
|
|
302
|
+
errors.push(cp + " must be an object")
|
|
303
|
+
return
|
|
304
|
+
}
|
|
305
|
+
if (typeof ce.event !== "string" || ce.event.length === 0) {
|
|
306
|
+
errors.push(cp + '.event is required and must be a full Bukkit event class name, e.g. "org.bukkit.event.block.BlockBreakEvent"')
|
|
307
|
+
} else if (!ce.event.includes(".")) {
|
|
308
|
+
warnings.push(cp + '.event "' + ce.event + '" should be a fully-qualified class name like org.bukkit.event.block.BlockBreakEvent')
|
|
309
|
+
}
|
|
310
|
+
if (ce.cooldown !== undefined && typeof ce.cooldown !== "string" && typeof ce.cooldown !== "number") {
|
|
311
|
+
warnings.push(cp + '.cooldown should be a duration like "5s", "1m", "1h" or a number of seconds')
|
|
312
|
+
}
|
|
313
|
+
if (!Array.isArray(ce.steps)) errors.push(cp + ".steps must be an array")
|
|
314
|
+
else ce.steps.forEach((s, si) => validateStep(idx, s, cp + ".steps[" + si + "]", errors, warnings))
|
|
315
|
+
})
|
|
316
|
+
}
|
|
317
|
+
}
|
|
318
|
+
|
|
292
319
|
if (item.stats !== undefined && !Array.isArray(item.stats)) errors.push("stats must be an array when present")
|
|
293
320
|
if (item.lore !== undefined && !Array.isArray(item.lore)) errors.push("lore must be an array of strings when present")
|
|
294
321
|
if (item.enchantments !== undefined && !Array.isArray(item.enchantments)) errors.push("enchantments must be an array when present")
|
|
@@ -314,8 +341,15 @@ function itemSchema(idx) {
|
|
|
314
341
|
customModelData: "number",
|
|
315
342
|
skullOwner: "string - player name for PLAYER_HEAD skins",
|
|
316
343
|
stats: "object[] - stat modifiers (see editor)",
|
|
317
|
-
actions: "Action[] - the behavior graph",
|
|
318
|
-
|
|
344
|
+
actions: "Action[] - the built-in trigger behavior graph",
|
|
345
|
+
customEvents: "object[] - react to ANY Bukkit event by its full class name (see customEvent)",
|
|
346
|
+
},
|
|
347
|
+
customEvent: {
|
|
348
|
+
event:
|
|
349
|
+
'string (required) - the FULL Bukkit event class name, e.g. "org.bukkit.event.block.BlockBreakEvent", "org.bukkit.event.entity.EntityDeathEvent". The plugin checks it exists on import.',
|
|
350
|
+
cooldown: "optional - per-player reuse delay, same format as an action cooldown",
|
|
351
|
+
steps:
|
|
352
|
+
"Step[] - same step format as an action. Variables available: player (the player from the event), item, event (the fired Bukkit event), plus core/particles/values/api.",
|
|
319
353
|
},
|
|
320
354
|
action: {
|
|
321
355
|
trigger: "string (required) - one of: " + idx.TRIGGER_NAMES.join(", "),
|
|
@@ -354,7 +388,7 @@ function generateItemTemplate(kind) {
|
|
|
354
388
|
actions: [
|
|
355
389
|
{ trigger: "rightAction", needBlock: "BOTH", steps: [{ call: "core.broadcastMessage", args: ["A wand was cast!"], operatorToNext: "END" }] },
|
|
356
390
|
],
|
|
357
|
-
|
|
391
|
+
customEvents: [],
|
|
358
392
|
}
|
|
359
393
|
}
|
|
360
394
|
return {
|
|
@@ -369,7 +403,7 @@ function generateItemTemplate(kind) {
|
|
|
369
403
|
actions: [
|
|
370
404
|
{ trigger: "leftAction", needBlock: "BOTH", steps: [{ call: "core.broadcastMessage", args: ["Hello from my custom sword!"], operatorToNext: "END" }] },
|
|
371
405
|
],
|
|
372
|
-
|
|
406
|
+
customEvents: [],
|
|
373
407
|
}
|
|
374
408
|
}
|
|
375
409
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "itemscore-helper",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.3.0",
|
|
4
4
|
"description": "One command sets up any AI (Claude, Codex, Cursor, Gemini, and others) to build and edit custom Minecraft items for the ItemsCore plugin. Auto-detects your AI tools and connects a local MCP server that runs entirely on your machine.",
|
|
5
5
|
"bin": {
|
|
6
6
|
"itemscore-helper": "bin/cli.js",
|
package/skill/ITEM_FORMAT.md
CHANGED
|
@@ -18,8 +18,8 @@ This is the offline reference for the item format ItemsCore imports. When the li
|
|
|
18
18
|
| `customModelData` | number | Resource-pack model id |
|
|
19
19
|
| `skullOwner` | string | Player name, for `PLAYER_HEAD` skins |
|
|
20
20
|
| `stats` | object[] | Stat modifiers (authored in the editor; preserved on re-import) |
|
|
21
|
-
| `actions` | Action[] | The behavior graph (see below) |
|
|
22
|
-
| `
|
|
21
|
+
| `actions` | Action[] | The built-in trigger behavior graph (see below) |
|
|
22
|
+
| `customEvents` | object[] | React to ANY Bukkit event by its full class name (see Custom events) |
|
|
23
23
|
|
|
24
24
|
## Action
|
|
25
25
|
|
|
@@ -112,6 +112,29 @@ For most items, every step uses `END`. Operators other than `END` build a single
|
|
|
112
112
|
| `landLocation` | arrowLandAction |
|
|
113
113
|
| `lastLocation` | projectile hit events |
|
|
114
114
|
|
|
115
|
+
## Custom events
|
|
116
|
+
|
|
117
|
+
`actions` only cover the built-in triggers above. To react to ANY other Bukkit event, add a `customEvents` entry with the event's full class name. The plugin checks the class exists on import and blocks the import if it does not.
|
|
118
|
+
|
|
119
|
+
```json
|
|
120
|
+
"customEvents": [
|
|
121
|
+
{
|
|
122
|
+
"event": "org.bukkit.event.block.BlockBreakEvent",
|
|
123
|
+
"steps": [
|
|
124
|
+
{ "call": "core.sendColorMessage", "args": [ { "var": "player" }, "&aYou broke a block while holding this!" ], "operatorToNext": "END" }
|
|
125
|
+
]
|
|
126
|
+
}
|
|
127
|
+
]
|
|
128
|
+
```
|
|
129
|
+
|
|
130
|
+
| Field | Type | Notes |
|
|
131
|
+
|---|---|---|
|
|
132
|
+
| `event` | string, required | The FULL Bukkit event class, e.g. `org.bukkit.event.block.BlockBreakEvent`, `org.bukkit.event.entity.EntityDeathEvent`, `org.bukkit.event.player.PlayerInteractEvent` |
|
|
133
|
+
| `cooldown` | duration string | Optional, same format as an action cooldown |
|
|
134
|
+
| `steps` | Step[] | Same step format as an action (below) |
|
|
135
|
+
|
|
136
|
+
Variables in a custom event step: `player` (the player the plugin finds on the event), `item`, `event` (the fired event itself - read its data with calls like `{ "call": "event.getBlock", "args": [] }`), plus `core` / `particles` / `values` / `api`. A custom event only fires while the player has the item (held, worn, or anywhere in the inventory for talismans). Use the exact class name; do not guess the package.
|
|
137
|
+
|
|
115
138
|
## Bukkit objects expose their full Spigot API
|
|
116
139
|
|
|
117
140
|
`player`, `shooter`, `victim`, `arrow`, `event`, and any entity, block, world, location, or `ItemStack` returned by a method are real Bukkit/Spigot objects. You can call any standard Spigot method on them in a step, not only the ItemsCore methods:
|
|
@@ -160,7 +183,7 @@ Always confirm a method's exact name and parameters with `get_method` / `search_
|
|
|
160
183
|
]
|
|
161
184
|
}
|
|
162
185
|
],
|
|
163
|
-
"
|
|
186
|
+
"customEvents": []
|
|
164
187
|
}
|
|
165
188
|
```
|
|
166
189
|
|
|
@@ -184,7 +207,7 @@ Always confirm a method's exact name and parameters with `get_method` / `search_
|
|
|
184
207
|
]
|
|
185
208
|
}
|
|
186
209
|
],
|
|
187
|
-
"
|
|
210
|
+
"customEvents": []
|
|
188
211
|
}
|
|
189
212
|
```
|
|
190
213
|
|
package/skill/SKILL.md
CHANGED
|
@@ -53,7 +53,7 @@ Minimal shape:
|
|
|
53
53
|
]
|
|
54
54
|
}
|
|
55
55
|
],
|
|
56
|
-
"
|
|
56
|
+
"customEvents": []
|
|
57
57
|
}
|
|
58
58
|
```
|
|
59
59
|
|
|
@@ -64,6 +64,7 @@ Rules:
|
|
|
64
64
|
- Each step has a `call`, an `args` array, and `operatorToNext`. `call` is `core.method`, `particles.method`, a Bukkit call like `player.getLocation`, or a bare variable name to read it.
|
|
65
65
|
- An arg is a JSON literal, `{ "var": "player" }` to pass a variable, or a nested `{ "call": ..., "args": ... }` to pass one method's result into another.
|
|
66
66
|
- `operatorToNext` joins a step to the next one. Use `END` to end a statement. Other values (`ADD`, `EQUALS`, `AND`, ...) build expressions and conditions. See `ITEM_FORMAT.md`.
|
|
67
|
+
- `actions` only cover the built-in triggers. To react to any OTHER Bukkit event, add a `customEvents` entry with the event's full class name (e.g. `org.bukkit.event.block.BlockBreakEvent`) and the same `steps` format - variables are `player`, `item`, `event`. The import is blocked if the class name is not found on the server, so use the exact fully-qualified name.
|
|
67
68
|
|
|
68
69
|
Find the exact method you need with `search_methods` / `get_method` before using it. Do not invent method names.
|
|
69
70
|
|