Skip to content

Configuration ​

Every EmakiLevel configuration file is covered below: the main config.yml, the level-up requirements requirements.yml, the level types types/*.yml, and what each field in the player data file does

EmakiLevel configuration is split into the main config, requirement curves, level types, experience sources, GUI templates, and language files. The files you edit most are:

  • 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.6.9"
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

pdc:
  enabled: true
  namespace: "emakilevel"

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"
FieldTypeRequiredDefaultRangeDescription
versionstringno1.6.9—Default resource version marker, maintained by resource sync; not a feature switch
languagestringnozh_CN—Language file under lang/<language>.yml
release_default_databooleannotruetrue / falseWhether missing bundled data files should be released
primary_typestringnomainA loaded level type idDefault level type for /elv levelup without type and some actions without type
level.default_start_levelintno1—Fallback start level when a type omits start_level
level.default_max_levelintno100—Fallback max level when a type omits max_level
level.max_auto_upgrade_stepsintno10Values below 1 are treated as 1Maximum auto-level-up steps from one exp operation
level.keep_total_exp_at_max_levelbooleannotruetrue / falseKeep increasing total_exp after a player reaches max level. Current-level exp stops increasing
multipliers.enabledbooleannotruetrue / falseEnable the experience multiplier stage
multipliers.globaldoubleno1.0Result clamped to be non-negativeGlobal experience multiplier
multipliers.types.<type>doubleno1.0Result clamped to be non-negativePer level type multiplier. Keys are normalized to lower case; unlisted types use 1.0
multipliers.reasons.<reason>doubleno1.0Result clamped to be non-negativePer experience reason multiplier. Keys are normalized to lower case; unlisted reasons use 1.0
daily_caps.enabledbooleannotruetrue / falseEnable the daily experience cap stage
daily_caps.default_limitdoubleno-1-1 or a positive numberDaily cap used when a type has no explicit entry. -1 means unlimited
daily_caps.types.<type>doubleno-1-1 or a positive numberPer level type daily cap. -1 means unlimited
pdc.enabledbooleannotruetrue / falseWrite level data to online player PDC
pdc.namespacestringnoemakilevel—PDC namespace; a blank value falls back to emakilevel
attribute.enabledbooleannotruetrue / falseTry to connect to EmakiAttribute contributions
attribute.provider_idstringnoemakilevel—Contribution provider ID registered into EmakiAttribute
mythicmobs.enabledbooleannotruetrue / falseGlobal MythicMobs switch
mythicmobs.kill_sourcesbooleannotruetrue / falseEnable mythic_mob_kill sources
mythicmobs.drops.enabledbooleannotruetrue / falseRegister MythicMobs intangible exp drops
mythicmobs.drops.nameslist<string>noemakilevel_exp, elv_exp—Recognized drop names. Empty list falls back to defaults
anti_abuse.placed_block_trackingbooleannotruetrue / falseTrack player-placed blocks
anti_abuse.placed_block_expbooleannofalsetrue / falseWhether player-placed blocks can grant break exp
anti_abuse.placed_block_record_ttl_ticksintno864000<=0 disables pruningLifetime of placed-block records in ticks. Expired records are pruned on the next read/write
anti_abuse.last_damager_tracking.enabledbooleannotruetrue / falseWhether indirect kills (attributed through the recent damager) are accepted. When false, only direct Bukkit-killer kills are processed
anti_abuse.last_damager_tracking.expire_ticksintno200—Key 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.enabledbooleannotruetrue / falseEnables the level GUI template entry
gui.default_templatestringnolevel_gui—Default GUI template ID

Multipliers and daily caps ​

multipliers and daily_caps run before experience is written to the player, in this order: multiplier → 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

FieldTypeRequiredDefaultRangeDescription
globalmappingno——Global requirement group; the lowest fallback for every type
global.formulastringnofloor(100 + 25 * %target_level% + 8 * pow(%target_level%, 2))expressionGlobal requirement formula, used when neither the type nor the group provides one
global.values.<level>mapping<int, double>no{}key is a positive integer level, value is required expGlobal exact target-level values; values greater than 0 take priority over the formula
groupsmappingno——Requirement groups keyed by the id referenced from requirement.group
groups.<group>mappingno——One requirement group
groups.<group>.formulastringnosee bundled file (each built-in group ships its own curve)expressionGroup requirement formula
groups.<group>.values.<level>mapping<int, double>nosee bundled file (main, combat, ... ship sample values)key is a positive integer level, value is required expGroup exact target-level values

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 ​

Requirements are computed by the CoreLib expression engine using %key% variables. Note: requirements are cached per type and the formula only depends on the target level; no live player level or exp is injected:

VariableDescription
%current_level%Always the type's start_level (the current implementation injects no live player level)
%target_level%Target level
%max_level%Type max level
%exp%Always 0 (the current implementation injects no live player exp)
%total_exp%Always 0 (the current implementation injects no live player 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"
FieldTypeRequiredDefaultRangeDescription
idstringnofile name without .yml—Unique level type ID referenced by commands, placeholders, sources, and actions
enabledbooleannotruetrue / falseDisabled types cannot gain exp or level up
display_namestringnoid—MiniMessage display name; blank falls back to id
descriptionlist<string>no[]—Description lines for configuration maintenance and GUI display
primarybooleannofalsetrue / falseMarks a type as primary metadata. The active default is still config.yml > primary_type
start_levelintnoconfig.yml > level.default_start_level (ships as 1)—Initial and reset level
max_levelintnoconfig.yml > level.default_max_level (ships as 100)—Maximum level. Direct level edits are clamped to this range
requirement.groupstringnoglobala defined group idRequirement group in requirements.yml
requirement.formulastringno""expressionType-specific formula overriding group/global formulas
requirement.values.<level>mapping<int, double>no{}key is a positive integer levelType-specific exact target-level values. Highest priority
upgrade.enabledbooleannotruetrue / falseWhether this type can level up at all
upgrade.auto_upgradebooleannotruetrue / falseWhether exp gain triggers automatic level-up
upgrade.manual_upgradebooleannotruetrue / falseWhether players can use /elv levelup
upgrade.cost.enabledbooleannofalsetrue / falseWhether level-up costs are charged at all
upgrade.cost.economy.enabledbooleannofalsetrue / falseWhether economy costs are enabled; only read when cost.enabled: true
upgrade.cost.economy.currencies[]list<mapping>no[]see "Economy cost"Economy cost entries, only read when economy.enabled: true and applied when cost.enabled: true
upgrade.cost.materials[]list<mapping>no[]see "Material cost"Material cost entries, only applied when cost.enabled: true
upgrade.rewards.items[]list<mapping>no[]see "Rewards"Item rewards on successful level-up
upgrade.actions.gainlist<string>no[]CoreLib action lineCoreLib actions after exp gain
upgrade.actions.successlist<string>no[]CoreLib action lineCoreLib actions after successful level-up
upgrade.actions.failurelist<string>no[]CoreLib action lineCoreLib actions after failed level-up
pdc.enabledbooleannotruetrue / falseWhether this type syncs PDC. Requires global pdc.enabled: true
attributes.enabledbooleannofalsetrue / falseWhether this type contributes EmakiAttribute attributes; false when the key is absent
attributes.values.<attr>mapping<string, string>no{}attribute ID to formulaMap 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>"
FieldTypeRequiredDefaultRangeDescription
providerstringnoautoCoreLib economy provider id, usually auto, vault, or excellenteconomyEconomy provider
currency_idstringno""—Currency ID. Usually empty for Vault
base_costdoubleno0—Base amount exposed as %base_cost%
cost_formulastringno%base_cost% * %target_level%expression; a result ≤0 charges nothingFinal cost formula
display_namestringno""—Display 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)"
FieldTypeRequiredDefaultRangeDescription
item_sourceslist<string>no[]valid CoreLib ItemSourceCoreLib ItemSource values to consume, processed in order; unparseable entries are ignored
base_amountlongno1 (amount is also accepted as input)—Base amount exposed as %base_amount%. New configs should use base_amount
amount_formulastringno%base_amount%expression, rounded to a long; a result ≤0 consumes nothingFinal amount formula, rounded to an integer

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

Rewards ​

yaml
upgrade:
  rewards:
    items:
      - levels: "*"
        item_source: "minecraft-experience_bottle"
        amount: 1
      - levels: "10,20,30"
        item_source: "minecraft-diamond"
        amount: 2
      - levels: "50-60"
        item_source: "minecraft-nether_star"
        amount: 1
FieldTypeRequiredDefaultRangeDescription
levelsstringno**, single level, comma list (10,20,30), or min-max range (50-60)Level pattern
item_sourcestringyes (one of item_source / item_sources)—valid CoreLib ItemSourceReward item source (canonical form, single)
item_sourceslist<string>yes (one of item_source / item_sources)—exactly one valid ItemSourceLegacy form. Must contain exactly one entry
amountintno1minimum 1Reward amount

item_source and item_sources cannot both be declared, and item_sources may contain exactly one entry; violating either throws at load time. matcher is not allowed on reward entries. 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 send_action_bar text="<gray>%type_display_name% exp +%amount%</gray>"'
    success:
      - 'send_message text="<green>%type_display_name% reached <yellow>%new_level%</yellow>!</green>"'
    failure:
      - 'send_message 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, and the fields mean the following:

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