Enchanting Power

Custom Table Power

enchanting.table-power (in config.yml) replaces vanilla's enchanting table math end to end: how "power" is measured around the table, and how that power turns into the three slot levels shown in the enchanting UI. It only affects MythicEnchants' custom enchanting table — vanilla enchanting tables are untouched.

Everything in this section is optional. Omit the whole block, or any piece of it, to fall back to vanilla behavior for that piece.

enchanting:
  table-power:
    materials:
      BOOKSHELF: 1
    require-line-of-sight: true
    equations:
      slot1: "floor(min(max((randomInt(1,8)+floor(count/2)+randomInt(0,count))/6, 1), 10))"
      slot2: "floor(min((((randomInt(1,8)+floor(count/2)+randomInt(0,count))*2)/4)+1, 15))"
      slot3: "floor(max(((randomInt(1,8)+floor(count/2)+randomInt(0,count))/2)+2, min(30, count*2)))"
    slot-caps:
      slot1: 10
      slot2: 15
      slot3: 30
    max-base-level: 30

How it fits together

  1. Scan the positions around the table (vanilla's 30 bookshelf spots, or a custom radius cuboid) and sum a power weight (count) for every block that matches an entry in materials.
  2. Feed count into the three equations (one per enchanting-table slot) to get each slot's base level.
  3. Clamp each slot's result to its slot-caps entry.
  4. Clamp the result one more time to the global max-base-level.

Any step can be skipped by omitting its config — a skipped step just uses vanilla's own logic (vanilla scan positions, vanilla's power→level formula, vanilla's 10/15/30/30 caps).


materials — what counts as power

A map of block → power weight. Only blocks listed here contribute; everything else scanned is ignored, exactly like vanilla ignores every block except bookshelves.

materials:
  BOOKSHELF: 1
  EMERALD_BLOCK: 3

With the weights above, 5 bookshelves + 2 emerald blocks → count = 5*1 + 2*3 = 11.

Flat vs. state-weighted entries

A material's value can be a flat number (as above) or a map that weights the block by its block state:

materials:
  CHISELED_BOOKSHELF:
    default: 0            # weight when no rule below matches
    states:
      - match: "books>=3" # first match wins, evaluated top → bottom
        weight: 2
      - match: "books>=1"
        weight: 1
  • match is an exp4j expression (the same engine equations uses — see below), evaluated against that block's state variables. Rules are tried in file order; the first one whose match evaluates non-zero wins. If none match (or evaluation fails, e.g. an unbound variable), the block falls back to default.
  • State variables come from the block's vanilla blockstate properties: booleans become 1/0 (e.g. waterlogged). Numeric properties are exposed as-is.
  • Non-numeric enum properties (e.g. facing=north) are not exposed — they can't be compared numerically, so there's nothing useful to bind them to.
  • A few blocks additionally expose derived variables. Currently: books for CHISELED_BOOKSHELF — the number of occupied slots, 06.

Custom blocks (Nexo / MythicCrucible / ItemsAdder)

A materials key can reference an addon's custom block instead of a vanilla Material, using the same nexo:<id> / crucible:<id> / itemsadder:<id> syntax the blockdrops and customblock config sections use:

materials:
  nexo:ruby_ore: 2
  crucible:sapphire_block: 3
  itemsadder:amethyst_lamp: 1

Rules for these entries:

  • Flat weights only. There's no states: support for addon blocks — their underlying carrier block has no state worth exposing.
  • Fallback only. A scanned position is checked against addon keys only if its plain Material isn't in materials at all. Addon entries never shadow a vanilla materials entry.
  • Requires the addon plugin. If the corresponding plugin (Nexo, MythicCrucible, or ItemsAdder) isn't installed, matching blocks simply contribute 0 power — this never errors.

require-line-of-sight

When true, mirrors vanilla's air-gap rule: the cell directly between the table and a power block must be air (or otherwise replaceable) for that block to count. This stops players from cheesing the bonus with a solid wall between the table and a stack of bookshelves.

For the default vanilla-shaped scan, this is a straightforward "is the cell between the two blocks clear" check. For a wide radius scan (see below), there's no single cell that sits "between" the table and a shelf once the radius exceeds vanilla's, so the check approximates: it requires the doorway cell at (table.x + sign(dx), table.y, table.z + sign(dz)) — i.e. the cell adjacent to the table in the shelf's general direction — to be clear. A solid wall built directly around the table still blocks the bonus in every direction; the approximation only matters once shelves are further away than the doorway itself.


radius — custom scan shape

Optional. When omitted, the scan uses vanilla's hand-picked 30 positions — the exact set vanilla checks for bookshelves (8 directions × 2 Y-levels, with knight-move-style outer cells).

When present, it replaces that with a chebyshev-distance cuboid scan centered on the table:

radius:
  inner: 2
  outer: 7
  y-min: 0
  y-max: 1
Key Meaning
inner Exclusive lower bound on max(|dx|, |dz|). 2 reproduces vanilla's rule that shelves can't be directly adjacent to the table. 0 lets blocks touching the table count.
outer Inclusive upper bound on max(|dx|, |dz|).
y-min / y-max Inclusive Y offsets relative to the table block. Vanilla's equivalent range is 0..1 (two layers).

Every block position inside that cuboid whose chebyshev distance falls in (inner, outer] and whose Y offset falls in [y-min, y-max] is scanned — a much larger and denser area than vanilla's 30 fixed spots, useful for big libraries or shrine-style setups.


equations — power → slot level

Three exp4j expressions, one per enchanting-table slot (slot1/slot2/slot3, top → bottom in the UI). Each has access to a single variable, count — the summed power from the scan step.

equations:
  slot1: "floor(min(max((randomInt(1,8)+floor(count/2)+randomInt(0,count))/6, 1), 10))"
  slot2: "floor(min((((randomInt(1,8)+floor(count/2)+randomInt(0,count))*2)/4)+1, 15))"
  slot3: "floor(max(((randomInt(1,8)+floor(count/2)+randomInt(0,count))/2)+2, min(30, count*2)))"

Omit a slot's key (or the whole equations: block) to fall back to vanilla's own power→level formula for that slot. If an equation throws at evaluation time (e.g. a bad expression), that slot silently falls back to the vanilla formula rather than erroring for the player.

Available functions

  • floor, ceil, min, max, clamp(v, min, max)
  • randomInt(a, b) — random integer, inclusive on both ends
  • random(a, b) — random decimal in [a, b)
  • Standard math: sin, cos, tan, asin, acos, atan, atan2(y, x), sinh, cosh, tanh, sqrt, cbrt, abs, exp, log, log2, log10, logb(x, base)
  • Extras: todegree, toradian, step(edge, x), lerp(a, b, t), round, signum, sec, sech, csch
  • Standard operators including ^ for exponentiation (count^2, not pow(count, 2))

This is the same expression engine used elsewhere in MythicEnchants' skill-line <math:...> blocks.


slot-caps — per-slot ceiling

After a slot's equation evaluates, its result is clamped to a maximum. This exists mainly so you don't have to wrap every equation in min(...) yourself.

slot-caps:
  slot1: 10
  slot2: 15
  slot3: 30
  • These defaults (10/15/30) mirror vanilla's own per-slot progression.
  • Omitting the whole slot-caps block, or omitting a single slot's key, keeps that slot's default cap.
  • Set a slot to 0 to opt it out of a per-slot cap entirely — only the global max-base-level (below) applies to it in that case.

max-base-level — global ceiling

A hard upper bound applied last, after everything above. Defaults to 30, matching vanilla's enchanting-table UI.

Raising it above 30 works — the algorithm will genuinely reach for higher-tier enchants when building the candidate pool, since the final enchant level is derived from this base level. The tradeoff: the vanilla client renders the XP-cost number in red once it exceeds what a player can normally reach, and confirming the enchant demands that many player levels. This is normal Minecraft client behavior for an unexpectedly high level requirement, not something MythicEnchants renders itself — set this carefully if you intend deeper progression than vanilla allows.


See also

  • Reagents can layer additional overrides on top of this base table-power calculation (override or additive modes) — see the reagent documentation for TablePowerOverride.
Updated Aug 19, 2026