Skip to content

Configuration

EmakiLevel configuration is split into the main config, requirement curves, level types, experience sources, GUI templates, and language files.

Server owners usually edit:

  • config.yml: global switches.
  • requirements.yml: required exp curves.
  • types/*.yml: level types, upgrade behavior, rewards, costs, and attributes.
  • sources/*.yml: which events grant exp to which level types.

Run /elv reload after editing most EmakiLevel files to reload configuration and synchronize online players.

config.yml

Default main config:

yaml
version: "1.4.0"
language: "zh_CN"
release_default_data: true
primary_type: "main"

level:
  default_start_level: 1
  default_max_level: 100
  max_auto_upgrade_steps: 10
  keep_total_exp_at_max_level: true

multipliers:
  enabled: true
  global: 1.0
  types:
    main: 1.0
    combat: 1.0
    cooking: 1.0
    forging: 1.0
  reasons:
    action: 1.0
    mythic_drop: 1.0
    event_bonus: 1.0

daily_caps:
  enabled: true
  default_limit: -1
  types:
    main: -1
    combat: -1
    cooking: -1
    forging: -1

storage:
  type: "yaml"
  save_on_quit: true
  save_on_shutdown: true

pdc:
  enabled: true
  namespace: "emakilevel"
  sync_on_join: true
  sync_on_exp_change: true
  sync_on_level_change: true
  sync_on_reload: true

attribute:
  enabled: true
  provider_id: "emakilevel"

mythicmobs:
  enabled: true
  kill_sources: true
  drops:
    enabled: true
    names:
      - "emakilevel_exp"
      - "elv_exp"

anti_abuse:
  placed_block_tracking: true
  placed_block_exp: false
  placed_block_record_ttl_ticks: 864000
  last_damager_tracking:
    enabled: true
    expire_ticks: 200

gui:
  enabled: true
  default_template: "level_gui"
FieldTypeDefaultDescription
versionstring1.4.0Default resource version marker.
languagestringzh_CNLanguage file under lang/<language>.yml.
release_default_databooleantrueWhether missing bundled data files should be released.
primary_typestringmainDefault level type for /elv levelup without type and some actions without type.
level.default_start_levelint1Fallback start level when a type omits start_level.
level.default_max_levelint100Fallback max level when a type omits max_level.
level.max_auto_upgrade_stepsint10Maximum auto-level-up steps from one exp operation.
level.keep_total_exp_at_max_levelbooleantrueKeep increasing total_exp after a player reaches max level. Current-level exp stops increasing.
multipliers.enabledbooleantrueEnable the experience multiplier stage.
multipliers.globaldouble1.0Global experience multiplier.
multipliers.types.<type>double1.0Per level type multiplier. Keys are normalized to lower case.
multipliers.reasons.<reason>double1.0Per experience reason multiplier. Keys are normalized to lower case.
daily_caps.enabledbooleantrueEnable the daily experience cap stage.
daily_caps.default_limitdouble-1Daily cap used when a type has no explicit entry. -1 means unlimited.
daily_caps.types.<type>double-1Per level type daily cap. -1 means unlimited.
storage.typestringyamlKey kept in the default config. The current implementation always uses YAML files and does not read this key.
storage.save_on_quitbooleantrueKey kept in the default config. Not read by the current implementation: quitting or being kicked always saves and unloads the cache asynchronously.
storage.save_on_shutdownbooleantrueKey kept in the default config. Not read by the current implementation: disabling always flushes and seals the data store.
pdc.enabledbooleantrueWrite level data to online player PDC.
pdc.namespacestringemakilevelPDC namespace.
pdc.sync_on_join / sync_on_exp_change / sync_on_level_change / sync_on_reloadbooleantrueKeys kept in the default config. Not read by the current implementation: while pdc.enabled is true, join, exp change, level change, and reload all synchronize.
attribute.enabledbooleantrueTry to connect to EmakiAttribute contributions.
attribute.provider_idstringemakilevelContribution provider ID registered into EmakiAttribute.
mythicmobs.enabledbooleantrueGlobal MythicMobs switch.
mythicmobs.kill_sourcesbooleantrueEnable mythic_mob_kill sources.
mythicmobs.drops.enabledbooleantrueRegister MythicMobs intangible exp drops.
mythicmobs.drops.nameslistemakilevel_exp, elv_expRecognized drop names. Empty list falls back to defaults.
anti_abuse.placed_block_trackingbooleantrueTrack player-placed blocks.
anti_abuse.placed_block_expbooleanfalseWhether player-placed blocks can grant break exp.
anti_abuse.placed_block_record_ttl_ticksint864000Lifetime of placed-block records in ticks. Expired records are pruned on the next read/write.
anti_abuse.last_damager_tracking.enabledbooleantrueWhether indirect kills (attributed through the recent damager) are accepted. When false, only direct Bukkit-killer kills are processed.
anti_abuse.last_damager_tracking.expire_ticksint200Key kept in the default config. Not read by the current implementation: the recent damager window is controlled by CoreLib config.yml > gameplay_events.last_damager_expire_ticks (also 200 by default).
gui.enabledbooleantrueEnables the level GUI template entry.
gui.default_templatestringlevel_guiDefault GUI template ID.

Multipliers and daily caps

multipliers and daily_caps run before experience is written to the player, in this order: multiplier → JavaScript exp rules → daily cap.

Multiplier calculation:

text
multiplier = multipliers.global × multipliers.types.<type> × multipliers.reasons.<reason>
  • Keys not listed under types or reasons are skipped instead of being treated as 0.
  • With multipliers.enabled: false the multiplier is fixed at 1.0.
  • The result is clamped to be non-negative.
  • <reason> is the reason passed by the exp source, for example the source rule trigger ID, an action reason argument, or a MythicMobs drop reason.

Daily caps:

  • With daily_caps.enabled: false there is no cap.
  • A type uses daily_caps.types.<type> when present, otherwise daily_caps.default_limit.
  • -1 means unlimited.
  • When the remaining daily budget is smaller than the incoming amount, the gain is clamped to the remaining budget. When the budget is exhausted the operation fails with reason daily_cap_reached.
  • Counters are bucketed by date in the system default time zone, kept in memory only, and reset when the server restarts.

requirements.yml

requirements.yml controls required exp:

yaml
global:
  formula: "floor(100 + 25 * %target_level% + 8 * pow(%target_level%, 2))"
  values: {}

groups:
  main:
    formula: "floor(150 + 40 * %target_level% + 14 * pow(%target_level%, 2))"
    values:
      2: 150
      3: 350
      4: 750
      5: 1200
  combat:
    formula: "floor(60 + 18 * %target_level% + 5 * pow(%target_level%, 2))"
    values:
      2: 80
      3: 160
      4: 300
  # mining / logging / farming / fishing / gathering / taming use the same default curve as combat
  crafting:
    formula: "floor(80 + 22 * %target_level% + 6 * pow(%target_level%, 2))"
    values: {}
  # brewing / cooking / forging / smelting use the same default curve as crafting

The bundled requirements.yml defines one group per built-in level type: main, combat, mining, logging, farming, fishing, gathering, taming, crafting, brewing, cooking, forging, smelting. Each types/<type>.yml > requirement.group points at the group with the same name by default.

Resolution order

Required exp for a target level resolves in this order:

  1. types/<type>.yml > requirement.values.<target_level>
  2. types/<type>.yml > requirement.formula
  3. requirements.yml > groups.<group>.values.<target_level>
  4. requirements.yml > groups.<group>.formula
  5. requirements.yml > global.values.<target_level>
  6. requirements.yml > global.formula

Exact values greater than zero take priority over formulas.

Formula variables

VariableDescription
%current_level%Player's current level, or type start level when no player entry exists.
%target_level%Target level.
%max_level%Type max level.
%exp%Current-level exp.
%total_exp%Total exp.

Use /elv debug requirement <type> <level> to inspect the final value and source.

types/*.yml

Each types/*.yml file defines one level type. File name is only a fallback; the internal id field is authoritative.

yaml
id: "combat"
enabled: true
display_name: "<red>Combat Level</red>"
description:
  - "<gray>Gain exp from vanilla or MythicMobs kills.</gray>"
primary: false
start_level: 1
max_level: 80
requirement:
  group: "combat"
  formula: ""
  values: {}
upgrade:
  enabled: true
  auto_upgrade: true
  manual_upgrade: true
  cost:
    enabled: false
    economy:
      enabled: false
      currencies: []
    materials: []
  rewards:
    items: []
  actions:
    gain: []
    success: []
    failure: []
pdc:
  enabled: true
attributes:
  enabled: true
  values:
    physical_attack: "%level% * 0.25"
FieldDescription
idUnique level type ID referenced by commands, placeholders, sources, and actions.
enabledDisabled types cannot gain exp or level up.
display_nameMiniMessage display name.
descriptionDescription lines for configuration maintenance and GUI display.
primaryMarks a type as primary metadata. The active default is still config.yml > primary_type.
start_levelInitial and reset level.
max_levelMaximum level. Direct level edits are clamped to this range.
requirement.groupRequirement group in requirements.yml.
requirement.formulaType-specific formula overriding group/global formulas.
requirement.valuesType-specific exact target-level values. Highest priority.
upgrade.enabledWhether this type can level up at all.
upgrade.auto_upgradeWhether exp gain triggers automatic level-up.
upgrade.manual_upgradeWhether players can use /elv levelup.
upgrade.costMoney/material level-up costs.
upgrade.rewards.itemsItem rewards on successful level-up.
upgrade.actions.gainCoreLib actions after exp gain.
upgrade.actions.successCoreLib actions after successful level-up.
upgrade.actions.failureCoreLib actions after failed level-up.
pdc.enabledWhether this type syncs PDC. Requires global pdc.enabled: true.
attributes.enabledWhether this type contributes EmakiAttribute attributes.
attributes.valuesMap of attribute ID to formula.

Level-up costs

Costs only apply when upgrade.cost.enabled: true.

Economy cost

yaml
upgrade:
  cost:
    enabled: true
    economy:
      enabled: true
      currencies:
        - provider: "auto"
          currency_id: ""
          base_cost: 100
          cost_formula: "%base_cost% * %target_level%"
          display_name: "<gold>Coins</gold>"
FieldDescription
providerCoreLib economy provider, usually auto, vault, or excellenteconomy.
currency_idCurrency ID. Usually empty for Vault.
base_costBase amount exposed as %base_cost%.
cost_formulaFinal cost formula.
display_nameDisplay label for readability and future UI.

Economy variables: %target_level%, %type%, %base_cost%.

Material cost

yaml
upgrade:
  cost:
    enabled: true
    materials:
      - item_sources:
          - "minecraft-diamond"
        base_amount: 1
        amount_formula: "%base_amount% + floor(%target_level% / 10)"
FieldDescription
item_sourcesCoreLib ItemSource values to consume, processed in order.
base_amountBase amount exposed as %base_amount%. New configs should use this field.
amount_formulaFinal amount formula, rounded to an integer.

Material variables: %target_level%, %type%, %base_amount%.

Rewards

yaml
upgrade:
  rewards:
    items:
      - levels: "*"
        item_sources:
          - "minecraft-experience_bottle"
        amount: 1
      - levels: "10,20,30"
        item_sources:
          - "minecraft-diamond"
        amount: 2
      - levels: "50-60"
        item_sources:
          - "minecraft-nether_star"
        amount: 1
FieldDescription
levelsLevel pattern: *, single level, comma list, or min-max range.
item_sourcesReward item sources. The first creatable source is used.
amountReward amount, minimum 1.

Rewards are created through CoreLib ItemSource and delivered with give-or-drop behavior.

Upgrade action variables

upgrade.actions.gain, success, and failure are CoreLib action line lists. They receive these variables:

VariableDescription
%type%Level type ID.
%type_display_name%Type display name.
%level%Current level.
%old_level%Level before operation.
%new_level%Level after operation.
%exp%Current-level exp, formatted.
%old_exp%Exp before operation, formatted.
%new_exp%Exp after operation, formatted.
%total_exp%Total exp, formatted.
%required_exp%Required exp for next level, formatted.
%progress%Progress from 0 to 1.
%progress_percent%Progress from 0 to 100, formatted.
%amount%Operation amount, formatted.
%reason%Operation reason.
%failure_reason%Failure reason, especially useful in failure actions.

Example:

yaml
upgrade:
  actions:
    gain:
      - '@chance=10 sendactionbar text="<gray>%type_display_name% exp +%amount%</gray>"'
    success:
      - 'sendmessage text="<green>%type_display_name% reached <yellow>%new_level%</yellow>!</green>"'
    failure:
      - 'sendmessage text="<red>Level-up failed: %failure_reason%</red>"'

Attribute contributions

When EmakiAttribute is installed and enabled, EmakiLevel registers level-based contributions. The default provider ID is config.yml > attribute.provider_id, usually emakilevel.

yaml
attributes:
  enabled: true
  values:
    physical_attack: "%level% * 0.25"
    physical_crit_rate: "%level% * 0.02"

Attribute formula variables: %level%, %exp%, %total_exp%.

If EmakiAttribute is not installed, this bridge is skipped automatically.

PDC sync

When global pdc.enabled: true and type-level pdc.enabled: true, online players receive these logical PDC fields under the configured namespace, default emakilevel:

FieldTypeDescription
player/<type>_levelintCurrent level.
player/<type>_expdoubleCurrent-level exp.
player/<type>_total_expdoubleTotal exp.
player/<type>_required_expdoubleRequired exp for next level.
player/<type>_progressdoubleProgress from 0 to 1.

PDC sync happens on join, exp changes, level changes, reload, and explicit debug sync.

Player data files

Player data is stored in data/<uuid>.yml:

yaml
schema_version: 1
uuid: "00000000-0000-0000-0000-000000000000"
name: "PlayerName"
levels:
  main:
    level: 1
    exp: 0.0
    total_exp: 0.0
    updated_at: 1730000000000

Prefer commands such as /elv setexp, /elv setlevel, and /elv reset over editing data files while the server is running.