Configuration Directory
EmakiAttribute configuration consists of the main config, attribute definitions, damage types, conditions, lore formats, and attribute balance data. Define a stable attribute naming convention before expanding damage types and equipment sources.
Default directory structure
plugins/EmakiAttribute/
├── config.yml
├── attribute_balance.yml
├── attributes/
├── damage_types/
├── conditions/
├── lore_formats/
├── presets/
├── gui/
├── lang/
└── data/| Path | Purpose |
|---|---|
config.yml | Main config: default resources, damage interception, regeneration, scaling curves, and vanilla damage mappings. |
attribute_balance.yml | Attribute score and balance semantics parameters. |
attributes/ | Individual attribute definitions. |
damage_types/ | Damage pipelines, such as physical, projectile, and spell. |
conditions/ | Attribute read conditions (PDC read rules). |
lore_formats/ | Attribute display format templates. |
presets/ | Attribute preset definitions. |
gui/ | Attribute points GUI configuration (attribute_points.yml). |
lang/ | Language files; bundled zh_CN.yml and en_US.yml. |
data/ | Runtime data, for example data/parent_attributes/<UUID>.yml; usually not edited manually. |
Main config fields
| Field | Description |
|---|---|
version | Config version maintained by default resource sync. |
language | Language file id. |
release_default_data | Whether bundled sample attributes, damage types, read rules, lore formats, and balance data are released. Enabled by default. |
attribute_sources.read_lore_attributes | Whether item attributes are parsed from Lore. Enabled by default. |
attribute_sources.read_pdc_attributes | Whether item attributes are read from PDC. Enabled by default. |
attribute_sources.require_lore_pdc_match | Whether Lore and PDC must match per attribute ID. Disabled by default. |
hard_lock_damage | Legacy compatibility key. It is read by the config parser but has no runtime consumer, so changing it changes nothing. Unmapped vanilla damage is governed by vanilla_event_damage. |
default_damage_type | Fallback damage type. |
projectile_damage_type | Default damage type used when cached projectile hits are resolved. Defaults to projectile, but can point to another loaded damage type such as physical. |
vanilla_event_damage | Vanilla event damage takeover settings. When enabled, vanilla side effects are preserved and the final damage is replaced; when disabled, compatibility synthetic damage mode is used. |
same_signature_ignores_invulnerability | Whether multi-hit attacks from the same attacker under the same attribute snapshot signature and damage type bypass the vanilla invulnerability window. window_ms is the batch window, default 500 ms. |
attack_speed.scope | Attack speed cooldown scope. global (default) lets EmakiAttribute manage every attack, deriving the cooldown from the current vanilla ATTACK_SPEED for items without an EmakiAttribute attack speed value. attribute_only intercepts only items that declare an EmakiAttribute attack speed value and leaves every other item to vanilla. |
regen_interval_ticks | Resource regeneration interval. |
sync_delay_ticks | Delay before syncing attributes to Bukkit. |
health_display_scaling | Client health bar display compression. It changes only client-side display, not real max health, current health, or damage calculation. |
default_profile | Default resources and attributes. |
synthetic_hit_feedback | Knockback and hurt sound feedback after vanilla damage interception. |
shield | Shield block ownership: mode (vanilla / attribute), require_facing, facing_angle_degrees. |
damage_indicator | Floating damage indicators. The render backend comes from EmakiCoreLib's display.backend. See "Damage indicators" below for the sub-keys. |
scaling_curves | Rules for diminishing returns after thresholds. Empty by default. |
allowed_damage_causes | Bukkit DamageCause to attribute damage mappings. |
Item attribute source policy
attribute_sources controls whether item attributes are read from Lore, PDC, or both, and whether both sources must validate each other:
attribute_sources:
read_lore_attributes: true
read_pdc_attributes: true
require_lore_pdc_match: falseThe default preserves the legacy behavior: all enabled Lore and PDC sources contribute to the item snapshot. When require_lore_pdc_match is enabled, values are compared per attribute ID:
- Present in both sources with equal values: count the attribute once.
- Present in both sources with different values: reject the attribute.
- Present in only one source: reject the attribute.
- Fixed and spread/range values use the same matching rule.
Match mode requires both read switches. Precheck emits a warning when either source is disabled. If both sources are disabled, default, temporary, and other entity-level sources remain available, but equipped items contribute no Lore/PDC attributes.
Default resources and attributes
default_profile defines the resources and attribute baselines a player has on initialization:
default_profile:
resources:
health:
display_name: "生命值"
default_max: 20.0
min_max: 1.0
max_max: 2048.0
sync_to_bukkit: true
full_on_init: true
mana:
display_name: "法力值"
default_max: 100.0
min_max: 0.0
max_max: 99999.0
sync_to_bukkit: false
full_on_init: true
attributes:
physical_attack: 0.0
physical_defense: 0.0
health_regen: 0.1
mana_regen: 0.1Resources cover changeable pools such as health and mana; attributes are used by equipment, gems, strengthening, skills, and damage calculation. A resource with sync_to_bukkit: true is mirrored to its Bukkit counterpart, which is typically used for health.
Damage indicators
damage_indicator controls the floating damage numbers. The render backend comes from EmakiCoreLib's display.backend: with the packet backend only the players selected by visible_to can see them; with the bukkit backend the indicator is a real entity visible to every nearby player and visible_to has no effect.
| Field | Default | Description |
|---|---|---|
enabled | true | Whether damage indicators are enabled. |
merge_window_ms | 500 | Multiple hits on the same target inside this window (milliseconds) merge into one accumulated indicator. 0 disables merging; a new hit inside the window restarts the indicator from its spawn point. |
max_per_target_per_second | 4 | Maximum indicators spawned per target per second, used to suppress AOE spam. 0 means unlimited. |
visible_to | involved | Only applies to the packet backend. involved shows the indicator to the attacker and the victim only; all shows it to every nearby player. |
ignored_causes | 7 entries | Damage causes that spawn no indicator. Defaults to FIRE_TICK, POISON, WITHER, DROWNING, FREEZE, SUFFOCATION, STARVATION. |
lifetime_ticks | 24 | Indicator lifetime in ticks, which is also the total duration of one arc. Expired indicators are reclaimed by the CoreLib display entity service. |
spawn.offset | x: 0.0 / y: 2.0 / z: 0.0 | Fixed offset in blocks relative to the target's feet. |
spawn.random_offset | x: 0.4 / y: 0.15 / z: 0.4 | Random scatter per axis in blocks, applied as ±value. 0 disables scatter on that axis. |
motion.enabled | true | Whether the arc motion is enabled. |
motion.step_ticks | 2 | Keyframe interval in ticks, which is also the client interpolation duration. 1 is smoothest; larger values send fewer packets and look more segmented. |
motion.speed | 0.30 | Initial launch speed in blocks per tick. |
motion.gravity | -0.030 | Vertical acceleration in blocks per tick², negative falls. This controls how much the arc curves. |
motion.direction.mode | random | Launch direction mode: random uses the pitch / yaw ranges; fixed uses the direction.fixed vector; away_from_attacker launches along the horizontal attacker-to-target direction plus the pitch elevation, falling back to random without an attacker. |
motion.direction.pitch | min: 55.0 / max: 85.0 | Elevation range in degrees, where 90 is straight up. |
motion.direction.yaw | min: -180.0 / max: 180.0 | Horizontal angle range in degrees. |
motion.scale.pop_from / pop_ticks | 0.6 / 3 | Entry scale; grows linearly to 1.0 over the first pop_ticks. |
motion.scale.shrink_to / shrink_ticks | 0.0 / 6 | Exit scale; shrinks linearly from 1.0 over the last shrink_ticks. 0 shrinks to invisible. |
triggers | four triggers | normal, critical, heal, dodge. Each trigger only needs the keys it overrides; the rest inherit the defaults above. dodge additionally requires dodge resolution to be enabled; vanilla combat does not perform dodge checks by default. |
Vanilla damage mapping
allowed_damage_causes decides which Bukkit DamageCause values enter attribute resolution:
allowed_damage_causes:
- cause: FALL
damage_type: physical
enabled: true
- cause: LAVA
damage_type: physical
enabled: true| Field | Description |
|---|---|
cause | Bukkit DamageCause name. |
damage_type | Damage type id from damage_types/*.yml. |
enabled | Whether this mapping is active. |
damage | Optional base damage before the attribute pipeline. When omitted, the vanilla damage value already computed by the server is used, which suits fall, explosion, burning, drowning, and other height- or state-dependent sources. |
Unmapped vanilla damage is governed by vanilla_event_damage, not by hard_lock_damage: when enabled: true it enters the attribute pipeline as vanilla_event_damage.damage_type; when enabled: false only the causes allowed in this table enter EA and everything else keeps vanilla behavior.
Suggested edit order
- Define attribute ids and display formats in
attributes/. - Add default values to
default_profile. - Configure damage pipelines in
damage_types/. - Tune score weights in
attribute_balance.yml. - Write attributes from equipment, gems, strengthening, forging, or item modules.
- Use
/ea lintto check configuration. - Use
/ea previewor/ea dumpto verify final player attributes.
Troubleshooting
- Attribute not displayed: check that the attribute file loaded, that the lore format matches, and that equipping the item triggered a refresh.
- Attribute has no effect: check that the attribute ID matches the damage type, condition, or external module.
- Unexpected environmental damage: check
vanilla_event_damageandallowed_damage_causes(hard_lock_damagehas no runtime effect and does not need investigating). - Health out of sync: check that the resource declares
sync_to_bukkit: true. Thehealthresource ceiling uses the modifiedMAX_HEALTH: the EA-computed value is written to the base, andmax_health_vanilla, health-boost potions, and third-party plugin modifiers stack on top without conflicting with each other. If the cap differs from expectations, enable theresourcedebug channel and inspect the health-cap resolution and max-health modifier lines to locate each modifier source. - External healing reverted: the
healthcurrent value follows the player entity's health, so another plugin or command setting health directly is not wiped by the next sync. If values still fall back, enable theresourcedebug channel and compare the old current value with the engine baseline value on the natural regeneration line: a persistent gap means the resource is not synced to Bukkit, or health is being rewritten by another plugin within the same tick. - Value inflation: configure
scaling_curvesfor core damage, defense, and critical attributes.