English
EmakiItem
EmakiItem provides lightweight custom items, stable item IDs (the unique ID you assign each item in config), sets, trigger actions, auto update, and PlaceholderAPI support, and the sections below show which page covers each feature, what config.yml exposes, and how it works with other modules. Treat it as the starting point for equipment progression: create one item with a stable ID first, then hand it to Forge, Strengthen, Gem, Attribute, and Skills to keep building on it
Module facts
| Item | Value |
|---|---|
| Module version | 2.8.16 |
| Main command | /emakiitem |
| Alias | /ei |
| Hard dependency | EmakiCoreLib |
| Soft dependencies | EmakiAttribute, EmakiSkills, MythicMobs, PlaceholderAPI |
| Permissions | emakiitem.use, emakiitem.give, emakiitem.browse, emakiitem.inspect, emakiitem.update, emakiitem.reload, emakiitem.debug, emakiitem.admin |
Pages
| Page | Contents |
|---|---|
| Commands | Listing and giving items, inspecting the held item and its components, refreshing items and sets, reload and debug |
| Definitions and Sets | The fields of items/*.yml and sets/*.yml, and how an item ID produces an ItemStack |
| Browser GUI | The two-level browser opened by /ei browse, pack.yml pack metadata, and slot types |
| Triggers | Running actions on interact, attack, projectile, block, and drop events |
| Update Strategy | Bringing items players already hold up to a changed definition |
| Repair System | The disabled state at zero durability and the material/currency repair flow |
| Cross-Module Integration | Item source syntax when Attribute, Forge, Strengthen, Gem, Skills, or Cooking reference an item |
| MythicMobs Integration | Dropping EmakiItem items from MythicMobs Drops |
| Placeholders | PlaceholderAPI output |
| CoreLib Actions | Main-hand update, redraw, repair, durability, and vanilla data component actions |
| API | Creating, identifying, and querying items through EmakiItemApi, and extending custom effect types |
| Event API | Bukkit events and interception points across the item flow |
Core capabilities
| Capability | Description |
|---|---|
| Stable item ID | Uses config IDs instead of display names |
| Item components | Configures material, name, lore, model, enchants, flags, durability, and more |
| Attribute output | Can provide attribute payloads to Attribute |
| Skill binding | Can expose skills or skill unlock data |
| Set system | Grants attributes, skills, or lore based on equipped piece count |
| Triggers | Runs actions on interaction, combat, projectile, block, drop, and other events |
| Auto update | Refreshes item state on login, hand switch, inventory click, pickup, and similar cases |
| Repair system | Items enter a disabled state at zero durability and can be repaired with materials or currency |
| Browser GUI | A two-level GUI browses every item by pack and takes pieces directly |
| ID aliases and migration | Maps renamed item IDs and can migrate configs and player inventories in bulk |
Default runtime folder
text
plugins/EmakiItem/
├── config.yml
├── id_aliases.yml
├── items/
├── sets/
├── gui/
└── lang/You write items into items/ and sets into sets/; gui/ holds the repair and two browser templates (repair_gui.yml, pack_browser_gui.yml, item_browser_gui.yml), and id_aliases.yml stores renamed item ID mappings
Every subdirectory of items/ is an item pack; drop a pack.yml in it to define how that pack looks in the browser, see Browser GUI
Main configuration
Before reading the tables, keep two points in mind. config.yml holds only global settings; each item's own behavior lives in its definition file. "Required" asks whether the plugin falls back on its own when a key is missing: every key below has a fallback, so all read "No". "Range" states the constraint the plugin actually enforces; "—" means the plugin performs no validation
Top-level settings
| Field | Type | Required | Default | Range | Description |
|---|---|---|---|---|---|
version | string | No | "2.8.16" | — | Config structure marker maintained by the project's resource sync flow, not a feature switch. Falls back to 2.6.7 when absent |
language | string | No | zh_CN | — | Language file name, matching lang/<language>.yml. Falls back to zh_CN when absent |
release_default_data | boolean | No | true | true / false | Whether bundled default data such as items/ and sets/ is released at startup; when disabled only existing data is loaded and no missing sample is generated. This does not control config.yml or language files |
yaml
# Shipped defaults
version: "2.8.16"
language: "zh_CN"
release_default_data: trueUsage example: switch to English and stop releasing sample data
yaml
language: "en_US"
release_default_data: falsedata_directories
| Field | Type | Required | Default | Range | Description |
|---|---|---|---|---|---|
data_directories | object | No | — | — | Directory scan settings, applied to items/ and sets/ |
data_directories.max_depth | int | No | 2 | >= 1 (the source applies max(1, value)) | Maximum recursive subdirectory depth, counting the data directory itself: 1 reads only .yml files at the directory root, 2 allows one level of subdirectories, 3 allows two. Directories beyond the limit are skipped with a warning |
yaml
# Shipped defaults
data_directories:
max_depth: 2Usage example: allow two levels of subdirectories (for example items/<pack>/<subdir>/*.yml)
yaml
data_directories:
max_depth: 3set_bonus
| Field | Type | Required | Default | Range | Description |
|---|---|---|---|---|---|
set_bonus | object | No | — | — | Set bonus settings. Set definitions live in sets/*.yml; items declare their set and piece through their own config |
set_bonus.enabled | boolean | No | true | true / false | Whether the set bonus system is enabled. When off, no set bonus is computed or applied |
set_bonus.refresh_triggers | object | No | — | — | Set refresh triggers. Equipment changes, inventory changes, and command refreshes recompute the currently worn/held piece count and bonuses; omitted entries are treated as true |
set_bonus.refresh_triggers.join | boolean | No | true | true / false | Refresh set state when a player joins |
set_bonus.refresh_triggers.held_change | boolean | No | true | true / false | Refresh when the held item changes |
set_bonus.refresh_triggers.inventory_click | boolean | No | true | true / false | Refresh on inventory click |
set_bonus.refresh_triggers.inventory_drag | boolean | No | true | true / false | Refresh on item drag |
set_bonus.refresh_triggers.pickup | boolean | No | true | true / false | Refresh on item pickup |
set_bonus.refresh_triggers.interact | boolean | No | true | true / false | Refresh on interaction |
set_bonus.refresh_triggers.command | boolean | No | true | true / false | Allow a set refresh when related EmakiItem commands run |
yaml
# Shipped defaults
set_bonus:
enabled: true
refresh_triggers:
join: true
held_change: true
inventory_click: true
inventory_drag: true
pickup: true
interact: true
command: trueUsage example: turn off the high-frequency inventory click and drag refreshes and keep only the low-frequency ones
yaml
set_bonus:
refresh_triggers:
inventory_click: false
inventory_drag: falseitem_state
| Field | Type | Required | Default | Range | Description |
|---|---|---|---|---|---|
item_state | object | No | — | — | Custom item-state settings written to the emaki:item_state PDC and read/written by the item_state_* action stages and the API. The whole section is additive: leaving it untouched keeps the previous behavior |
item_state.clamp | boolean | No | true | true / false | Whether written values are clamped to the min/max declared in fields. When disabled only overflow protection remains, with no configurable clamping |
item_state.fill_defaults | boolean | No | true | true / false | Whether add uses the fields default as the starting value when the field is absent. When disabled a missing field is rejected outright (reason=missing_state) |
item_state.fields | map | No | {} | — | Field declarations keyed by state key name (lowercased on write). Undeclared fields are unaffected by clamping, defaults, and thresholds |
item_state.migrations | map | No | {} | — | Migration steps per schema version; an empty map means no migration |
item_state.preservation | object | No | — | — | State preservation policy |
item_state.derivation | object | No | — | — | State-change-driven derived refreshes |
item_state.fields
| Field | Type | Required | Default | Range | Description |
|---|---|---|---|---|---|
item_state.fields.<key> | object | No | — | — | One field declaration; <key> is the state key name |
item_state.fields.<key>.type | string | No | double | INTEGER / LONG / DOUBLE / BOOLEAN / STRING (case-insensitive) | Field type. A blank or unrecognized type skips the whole field; min/max/thresholds only apply to numeric types (INTEGER, LONG, DOUBLE) |
item_state.fields.<key>.default | scalar | No | none | Must coerce to type | Used as the starting value for add when the field is absent and fill_defaults is on. A value that cannot coerce means no default |
item_state.fields.<key>.min | number | No | none | numeric | Lower clamp bound; only when clamp is on and the field is numeric |
item_state.fields.<key>.max | number | No | none | numeric | Upper clamp bound |
item_state.fields.<key>.thresholds | map | No | {} | — | Threshold set keyed by threshold id. At most the 64 smallest thresholds by ascending value are kept per field, regardless of write order; changing the set re-arms that field's once latch |
item_state.fields.<key>.thresholds.<id>.value | number | Yes | none | numeric | The threshold value. An entry without this key is dropped |
item_state.fields.<key>.thresholds.<id>.once | boolean | No | false | true / false | Whether the reward fires only once until it is re-armed |
item_state.fields.<key>.thresholds.<id>.reward_on_fall | boolean | No | false | true / false | Whether a downward crossing also triggers the reward |
item_state.fields.<key>.thresholds.<id>.actions | list | No | empty | — | Actions run when the threshold is crossed |
item_state.fields.<key>.thresholds.<id>.message_key | string | No | "" | — | Language key used for the threshold message |
item_state.fields.<key>.thresholds.<id>.sound | string | No | "" | — | Sound played when the threshold is crossed |
item_state.fields.<key>.thresholds.<id>.sound_volume | double | No | 1.0 | — | Sound volume |
item_state.fields.<key>.thresholds.<id>.sound_pitch | double | No | 1.0 | — | Sound pitch |
item_state.fields.<key>.thresholds.<id>.refresh_derived | boolean | No | true | true / false | Whether this threshold runs a derived refresh after firing |
item_state.migrations
| Field | Type | Required | Default | Range | Description |
|---|---|---|---|---|---|
item_state.migrations.<key> | object | No | — | — | One migration step; <key> is only an identifier |
item_state.migrations.<key>.from | int | Yes | none | — | Source schema version. The step is skipped when it is absent or when to <= from |
item_state.migrations.<key>.to | int | Yes | none | > from | Target schema version |
item_state.migrations.<key>.rename | map | No | empty | — | Field renames written as old_field: new_field; entries whose source equals their target are ignored |
item_state.migrations.<key>.retype | map | No | empty | target type as in type | Field type changes written as field: type |
item_state.migrations.<key>.drop | list | No | empty | — | Field names to drop |
item_state.preservation
| Field | Type | Required | Default | Range | Description |
|---|---|---|---|---|---|
item_state.preservation.verify_rebuild | boolean | No | true | true / false | Verify state survives an item rebuild and backfill from the pre-rebuild snapshot when it is missing; it only writes when state was genuinely lost, so the normal path is a no-op |
item_state.preservation.repair_on_pickup | boolean | No | false | true / false | Repair damaged state metadata on pickup |
item_state.preservation.repair_on_drop | boolean | No | false | true / false | Repair damaged state metadata on drop |
item_state.preservation.repair_on_trade | boolean | No | false | true / false | Repair damaged state metadata on trade |
item_state.preservation.repair_on_container_transfer | boolean | No | false | true / false | Repair damaged state metadata on container transfer |
item_state.preservation.repair_on_join | boolean | No | false | true / false | Repair damaged state metadata when a player joins |
item_state.derivation
| Field | Type | Required | Default | Range | Description |
|---|---|---|---|---|---|
item_state.derivation.enabled | boolean | No | false | true / false | Master switch for derived refreshes. Off by default to avoid adding refresh overhead to existing servers |
item_state.derivation.refresh_lore | boolean | No | true | true / false | Refresh set lore during a derived refresh |
item_state.derivation.refresh_attributes | boolean | No | true | true / false | Sync attributes during a derived refresh |
item_state.derivation.scan_holder | boolean | No | true | true / false | Allow scanning online players to locate the item when holder information is missing |
item_state.derivation.max_depth | int | No | 2 | 1–8 (the source applies clamp(value, 1, 8)) | Maximum recursion depth for derived refreshes and threshold rewards, blocking self-triggering loops |
yaml
# Shipped defaults
item_state:
clamp: true
fill_defaults: true
preservation:
verify_rebuild: true
repair_on_pickup: false
repair_on_drop: false
repair_on_trade: false
repair_on_container_transfer: false
repair_on_join: false
derivation:
enabled: false
refresh_lore: true
refresh_attributes: true
scan_holder: true
max_depth: 2Usage example: declare a kill counter with thresholds and migrate a legacy field by schema version
yaml
item_state:
fields:
kills:
type: INTEGER
default: 0
min: 0
max: 9999
thresholds:
novice:
value: 10
once: true
message_key: "state.kills.novice"
sound: "minecraft:entity.player.levelup"
sound_volume: 1.0
sound_pitch: 1.2
veteran:
value: 100
actions:
- 'send_message text="<gold>Kill streak reached.</gold>"'
migrations:
"1":
from: 0
to: 1
rename:
kill_count: kills
retype:
kills: LONG
drop:
- legacy_tagproficiency_guard
| Field | Type | Required | Default | Range | Description |
|---|---|---|---|---|---|
proficiency_guard | object | No | — | — | Proficiency dispatch guard applied to damage_dealt / kill_entity / kill_player slot dispatch. Everything except dedupe_per_event defaults to disabled or unlimited, so existing gain rates are unchanged |
proficiency_guard.dedupe_per_event | boolean | No | true | true / false | Dispatch one item definition at most once per event, fixing "the same definition sitting in several slots fires once per slot" |
proficiency_guard.max_dispatches_per_event | int | No | 0 | >= 0 (the source applies max(0, value)); 0 means unlimited | Maximum dispatches per event |
proficiency_guard.same_target_cooldown_seconds | number | No | 0 | >= 0 (converted to milliseconds internally); 0 means no cooldown | Cooldown in seconds against the same target |
proficiency_guard.daily_soft_cap | int | No | 0 | >= 0 (the source applies max(0, value)); 0 means no cap | Daily soft cap. Counts live in memory, reset on the server's local date change, and do not survive a restart |
proficiency_guard.decay_factor | double | No | 1.0 | (0, 1]; out-of-range or non-finite values fall back to 1.0 | Decay factor once the soft cap is exceeded. 1.0 means no decay (reject outright past the cap) |
proficiency_guard.decay_minimum_ratio | double | No | 0.0 | [0, 1] (clamped by the source) | Lower bound for the decayed pass probability |
proficiency_guard.guarded_triggers | list | No | damage_dealt, kill_entity, kill_player | — | Triggers governed by this section; an empty list falls back to the three defaults |
yaml
# Shipped defaults
proficiency_guard:
dedupe_per_event: true
max_dispatches_per_event: 0
same_target_cooldown_seconds: 0
daily_soft_cap: 0
decay_factor: 1.0
decay_minimum_ratio: 0.0
guarded_triggers:
- "damage_dealt"
- "kill_entity"
- "kill_player"Usage example: cap dispatches per event and add a 1-second cooldown against the same target
yaml
proficiency_guard:
max_dispatches_per_event: 3
same_target_cooldown_seconds: 1mythicmobs
| Field | Type | Required | Default | Range | Description |
|---|---|---|---|---|---|
mythicmobs | object | No | — | — | MythicMobs integration settings. Skipped automatically when MythicMobs is not installed, without affecting other features |
mythicmobs.enabled | boolean | No | true | true / false | Master switch for the MythicMobs integration. When off no drop is registered |
mythicmobs.drops | object | No | — | — | Custom drop settings |
mythicmobs.drops.enabled | boolean | No | true | true / false | Whether the MythicMobs custom drop is registered |
mythicmobs.drops.names | list | No | emakiitem, ei_item | — | Recognized drop names; falls back to the defaults when empty |
yaml
# Shipped defaults
mythicmobs:
enabled: true
drops:
enabled: true
names:
- "emakiitem"
- "ei_item"Usage example: expose only a custom drop name
yaml
mythicmobs:
drops:
names:
- "emakiitem"Interactions
Keep the split in mind: set_bonus.refresh_triggers controls set state refreshing, while item auto-update is controlled separately by update.triggers in an item definition; neither overrides the other
item_state.* applies to the emaki:item_state PDC partition (plugin-defined data, the hidden fields a plugin writes onto an item) and is read and written by the item_state_* action stages and the API. The whole section is additive: leave every key untouched and the behavior matches the previous version. proficiency_guard.* applies to slot dispatch for damage_dealt, kill_entity, and kill_player; everything except dedupe_per_event defaults to disabled or unlimited
Typical item lifecycle
- You define item IDs, material, name, lore, and components in
items/ - Add Attribute stats, Skills, or set info when you need them
- Give the item out with a command
- A player equips or uses the item
- Item refreshes the item automatically at each trigger
- Forge / Strengthen / Gem then keep writing their own layers on top
- CoreLib rebuilds the final display
Relations with other modules
| Module | Integration |
|---|---|
| EmakiAttribute | Item writes base or set attributes |
| EmakiSkills | Item writes equipment skill IDs and forced equipment triggers. The PDC keys are owned by a standalone protocol module and do not depend on EmakiSkills being enabled |
| EmakiForge | Forge can modify items created by EmakiItem |
| EmakiStrengthen | Strengthen can strengthen EmakiItem equipment |
| EmakiGem | Gem can add sockets and inlay gems onto EmakiItem equipment |
| MythicMobs | MythicMobs mobs can drop EmakiItem items through Drops |