Skip to content

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

text
plugins/EmakiAttribute/
├── config.yml
├── attribute_balance.yml
├── attributes/
├── damage_types/
├── conditions/
├── lore_formats/
├── presets/
├── gui/
├── lang/
└── data/
PathPurpose
config.ymlMain config: default resources, damage interception, regeneration, scaling curves, and vanilla damage mappings.
attribute_balance.ymlAttribute 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

FieldDescription
versionConfig version maintained by default resource sync.
languageLanguage file id.
release_default_dataWhether bundled sample attributes, damage types, read rules, lore formats, and balance data are released. Enabled by default.
attribute_sources.read_lore_attributesWhether item attributes are parsed from Lore. Enabled by default.
attribute_sources.read_pdc_attributesWhether item attributes are read from PDC. Enabled by default.
attribute_sources.require_lore_pdc_matchWhether Lore and PDC must match per attribute ID. Disabled by default.
hard_lock_damageLegacy 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_typeFallback damage type.
projectile_damage_typeDefault 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_damageVanilla 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_invulnerabilityWhether 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.scopeAttack 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_ticksResource regeneration interval.
sync_delay_ticksDelay before syncing attributes to Bukkit.
health_display_scalingClient health bar display compression. It changes only client-side display, not real max health, current health, or damage calculation.
default_profileDefault resources and attributes.
synthetic_hit_feedbackKnockback and hurt sound feedback after vanilla damage interception.
shieldShield block ownership: mode (vanilla / attribute), require_facing, facing_angle_degrees.
damage_indicatorFloating damage indicators. The render backend comes from EmakiCoreLib's display.backend. See "Damage indicators" below for the sub-keys.
scaling_curvesRules for diminishing returns after thresholds. Empty by default.
allowed_damage_causesBukkit 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:

yaml
attribute_sources:
  read_lore_attributes: true
  read_pdc_attributes: true
  require_lore_pdc_match: false

The 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:

yaml
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.1

Resources 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.

FieldDefaultDescription
enabledtrueWhether damage indicators are enabled.
merge_window_ms500Multiple 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_second4Maximum indicators spawned per target per second, used to suppress AOE spam. 0 means unlimited.
visible_toinvolvedOnly applies to the packet backend. involved shows the indicator to the attacker and the victim only; all shows it to every nearby player.
ignored_causes7 entriesDamage causes that spawn no indicator. Defaults to FIRE_TICK, POISON, WITHER, DROWNING, FREEZE, SUFFOCATION, STARVATION.
lifetime_ticks24Indicator lifetime in ticks, which is also the total duration of one arc. Expired indicators are reclaimed by the CoreLib display entity service.
spawn.offsetx: 0.0 / y: 2.0 / z: 0.0Fixed offset in blocks relative to the target's feet.
spawn.random_offsetx: 0.4 / y: 0.15 / z: 0.4Random scatter per axis in blocks, applied as ±value. 0 disables scatter on that axis.
motion.enabledtrueWhether the arc motion is enabled.
motion.step_ticks2Keyframe interval in ticks, which is also the client interpolation duration. 1 is smoothest; larger values send fewer packets and look more segmented.
motion.speed0.30Initial launch speed in blocks per tick.
motion.gravity-0.030Vertical acceleration in blocks per tick², negative falls. This controls how much the arc curves.
motion.direction.moderandomLaunch 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.pitchmin: 55.0 / max: 85.0Elevation range in degrees, where 90 is straight up.
motion.direction.yawmin: -180.0 / max: 180.0Horizontal angle range in degrees.
motion.scale.pop_from / pop_ticks0.6 / 3Entry scale; grows linearly to 1.0 over the first pop_ticks.
motion.scale.shrink_to / shrink_ticks0.0 / 6Exit scale; shrinks linearly from 1.0 over the last shrink_ticks. 0 shrinks to invisible.
triggersfour triggersnormal, 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:

yaml
allowed_damage_causes:
  - cause: FALL
    damage_type: physical
    enabled: true
  - cause: LAVA
    damage_type: physical
    enabled: true
FieldDescription
causeBukkit DamageCause name.
damage_typeDamage type id from damage_types/*.yml.
enabledWhether this mapping is active.
damageOptional 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

  1. Define attribute ids and display formats in attributes/.
  2. Add default values to default_profile.
  3. Configure damage pipelines in damage_types/.
  4. Tune score weights in attribute_balance.yml.
  5. Write attributes from equipment, gems, strengthening, forging, or item modules.
  6. Use /ea lint to check configuration.
  7. Use /ea preview or /ea dump to 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_damage and allowed_damage_causes (hard_lock_damage has no runtime effect and does not need investigating).
  • Health out of sync: check that the resource declares sync_to_bukkit: true. The health resource ceiling uses the modified MAX_HEALTH: the EA-computed value is written to the base, and max_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 the resource debug channel and inspect the health-cap resolution and max-health modifier lines to locate each modifier source.
  • External healing reverted: the health current 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 the resource debug 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_curves for core damage, defense, and critical attributes.