Skip to content

Level Based Values

JohnSmith474 edited this page Sep 22, 2026 · 2 revisions

Registers custom mathematical formula codecs into the vanilla LevelBasedValue ecosystem. Allows enchantments to scale variables non-linearly or retrieve externally defined configuration values.

Core Operations

Method Description
initialize() Injects all custom mathematical codecs into the built-in LevelBasedValue registry (BuiltInRegistries.ENCHANTMENT_LEVEL_BASED_VALUE_TYPE).
register(String, MapCodec) Maps a specific map codec implementation to the LevelBasedValue registry under the mod's namespace.

Common Objects

ConfigReference

Defines a configuration target and an optional fallback. Resolves the active target based on mod load status and handles orphaned configurations. This object utilizes an Either codec, allowing it to be defined either directly as a single ConfigDescription object, or as a dual-target object with primary and fallback configurations.

Type 1: Direct Definition Define the reference directly using the properties of a ConfigDescription.

Template (Direct)
{
  "mod_id": "example_mod",
  "category": "combat",
  "group": "weapons",
  "property": "damage_multiplier"
}

Type 2: Fallback Definition Defines a primary target, falling back to a secondary target if the primary mod is not loaded.

Property Type Required Default Description
try_config ConfigDescription Yes - The primary configuration target to attempt loading.
else_config ConfigDescription Yes - The fallback configuration target if the primary mod is missing.
Codec
private static final Codec<ConfigReference> TRY_ELSE_CODEC = RecordCodecBuilder.create(instance -> instance.group(
        ConfigDescription.CODEC.fieldOf("try_config").forGetter(ConfigReference::target),
        ConfigDescription.CODEC.fieldOf("else_config").forGetter(ref -> ref.fallback.orElse(null))
).apply(instance, (tryConfig, elseConfig) -> new ConfigReference(tryConfig, Optional.ofNullable(elseConfig))));

public static final Codec<ConfigReference> CODEC = Codec.either(ConfigDescription.CODEC, TRY_ELSE_CODEC)
        .xmap(
                either -> either.map(
                        single -> new ConfigReference(single, Optional.empty()),
                        tryElse -> tryElse
                ),
                ref -> ref.fallback.isPresent() ? Either.right(ref) : Either.left(ref.target)
        );
Template (Fallback)
{
  "try_config": {
    "mod_id": "addon_mod",
    "category": "combat",
    "group": "weapons",
    "property": "damage_multiplier"
  },
  "else_config": {
    "mod_id": "base_mod",
    "category": "combat",
    "group": "weapons",
    "property": "damage_multiplier"
  }
}

Standard Value Codecs

diminishing_returns

Calculates a total value based on an arithmetic progression where the increment decreases (diminishes) for each subsequent level until a defined minimum value is reached.

Property Type Required Default Description
base Float Yes - The initial value added at the first level.
decrement Float Yes - The amount by which the value added is reduced for each subsequent level.
minimum Float Yes - The floor value. The added value per level will never drop below this amount.
Codec
public static final MapCodec<DiminishingReturnsValue> CODEC = RecordCodecBuilder.mapCodec(instance -> instance.group(
        Codec.FLOAT.fieldOf("base").forGetter(DiminishingReturnsValue::base),
        Codec.FLOAT.fieldOf("decrement").forGetter(DiminishingReturnsValue::decrement),
        Codec.FLOAT.fieldOf("minimum").forGetter(DiminishingReturnsValue::minimum)
).apply(instance, DiminishingReturnsValue::new));
Template
{
  "type": "enchantment_core:diminishing_returns",
  "base": 5.0,
  "decrement": 0.5,
  "minimum": 1.0
}

polynomial

Calculates a final value using a generalized polynomial function: value = offset + (scale * (level + levelOffset)^power). Allows for custom linear, quadratic, or exponential growth curves.

Property Type Required Default Description
scale Float No 1.0 The coefficient that multiplies the result of the power calculation.
power Float No 1.0 The exponent applied to the level calculation.
offset Float No 0.0 A constant value added to the final result.
level_offset Float No 0.0 A constant value added to the enchantment level before the power calculation.
Codec
public static final MapCodec<PolynomialValue> CODEC = RecordCodecBuilder.mapCodec(instance -> instance.group(
        Codec.FLOAT.optionalFieldOf("scale", 1.0f).forGetter(PolynomialValue::scale),
        Codec.FLOAT.optionalFieldOf("power", 1.0f).forGetter(PolynomialValue::power),
        Codec.FLOAT.optionalFieldOf("offset", 0.0f).forGetter(PolynomialValue::offset),
        Codec.FLOAT.optionalFieldOf("level_offset", 0.0f).forGetter(PolynomialValue::levelOffset)
).apply(instance, PolynomialValue::new));
Template
{
  "type": "enchantment_core:polynomial",
  "scale": 1.5,
  "power": 2.0,
  "offset": 0.0,
  "level_offset": -1.0
}

probabilistic

Calculates the success or failure of a probabilistic event based on an inner chance provider, returning 0.0 for success and 1.0 for failure. Intended for boolean outcome mechanics (like ammo usage).

Property Type Required Default Description
chance LevelBasedValue Yes - An inner value determining the probability (0.0 to 1.0) of a successful outcome.
Codec
public static final MapCodec<ProbabilisticValue> CODEC = RecordCodecBuilder.mapCodec(instance -> instance.group(
        LevelBasedValue.CODEC.fieldOf("chance").forGetter(ProbabilisticValue::chance)
).apply(instance, ProbabilisticValue::new));
Template
{
  "type": "enchantment_core:probabilistic",
  "chance": 0.5
}

negative

Calculates the negative additive inverse of the value returned by an inner value provider.

Property Type Required Default Description
value LevelBasedValue Yes - The inner value whose calculated result will be negated.
Codec
public static final MapCodec<NegateValue> CODEC = RecordCodecBuilder.mapCodec(instance -> instance.group(
        LevelBasedValue.CODEC.fieldOf("value").forGetter(NegateValue::input)
).apply(instance, NegateValue::new));
Template
{
  "type": "enchantment_core:negative",
  "value": 5.0
}

Configurable Value Codecs

These codecs dynamically bridge data-driven enchantments with runtime configuration files, updating immediately when a user alters their server/client configs.

config_aware

A dynamic delegation codec that executes entirely different LevelBasedValue logic branches depending on the stringified output of a configuration property.

Property Type Required Default Description
config ConfigDescription Yes - The target configuration property to read at runtime.
cases Map<String, LevelBasedValue> Yes - A map of stringified config states mapped to their respective value logic.
fallback LevelBasedValue Yes - The logic executed if the config property is invalid, missing, or unmatched.
Codec
public static final MapCodec<ConfigAwareValue> CODEC = RecordCodecBuilder.mapCodec(instance -> instance.group(
        ConfigDescription.CODEC.fieldOf("config").forGetter(val -> val.target),
        Codec.unboundedMap(Codec.STRING, LevelBasedValue.CODEC).fieldOf("cases").forGetter(val -> val.cases),
        LevelBasedValue.CODEC.fieldOf("fallback").forGetter(val -> val.fallback)
).apply(instance, ConfigAwareValue::new));
Template
{
  "type": "enchantment_core:config_aware",
  "config": {
    "mod_id": "my_mod",
    "category": "balance",
    "group": "scaling",
    "property": "mode"
  },
  "cases": {
    "linear": { "type": "minecraft:linear", "base": 1.0, "per_level_above_first": 1.0 },
    "flat": 5.0
  },
  "fallback": 1.0
}

configurable_constant

Fetches a flat float value from the configuration registry.

Property Type Required Default Description
config ConfigReference Yes - The reference path to the configuration property.
default_value Float Yes - The fallback value if the config is not found or fails to load.
min Float No -MAX_VALUE The absolute lowest permitted value bounds.
max Float No MAX_VALUE The absolute highest permitted value bounds.
Codec
public static final MapCodec<ConfigurableConstantValue> CODEC = RecordCodecBuilder.mapCodec(instance -> instance.group(
        ConfigReference.CODEC.fieldOf("config").forGetter(ConfigurableConstantValue::reference),
        Codec.FLOAT.fieldOf("default_value").forGetter(ConfigurableConstantValue::defaultValue),
        Codec.FLOAT.optionalFieldOf("min", -Float.MAX_VALUE).forGetter(ConfigurableConstantValue::min),
        Codec.FLOAT.optionalFieldOf("max", Float.MAX_VALUE).forGetter(ConfigurableConstantValue::max)
).apply(instance, ConfigurableConstantValue::new));
Template
{
  "type": "enchantment_core:configurable_constant",
  "config": {
    "mod_id": "my_mod",
    "category": "combat",
    "group": "weapons",
    "property": "bonus"
  },
  "default_value": 2.0,
  "min": 0.0,
  "max": 10.0
}

configurable_clamped

Wraps a standard LevelBasedValue but bounds the final calculated output between dynamic configurable minimum and maximum thresholds.

Property Type Required Default Description
value LevelBasedValue Yes - The inner logic generating the raw calculation.
min_config ConfigReference Yes - The config property dictating the clamp floor.
min_default Float Yes - Fallback default for the minimum bound.
max_config ConfigReference Yes - The config property dictating the clamp ceiling.
max_default Float Yes - Fallback default for the maximum bound.
Codec
public static final MapCodec<ConfigurableClampedValue> CODEC = RecordCodecBuilder.mapCodec(instance -> instance.group(
        LevelBasedValue.CODEC.fieldOf("value").forGetter(ConfigurableClampedValue::value),
        ConfigReference.CODEC.fieldOf("min_config").forGetter(ConfigurableClampedValue::minReference),
        Codec.FLOAT.fieldOf("min_default").forGetter(ConfigurableClampedValue::minDefault),
        ConfigReference.CODEC.fieldOf("max_config").forGetter(ConfigurableClampedValue::maxReference),
        Codec.FLOAT.fieldOf("max_default").forGetter(ConfigurableClampedValue::maxDefault)
).apply(instance, ConfigurableClampedValue::new));
Template
{
  "type": "enchantment_core:configurable_clamped",
  "value": { "type": "minecraft:linear", "base": 1.0, "per_level_above_first": 2.0 },
  "min_config": {
    "mod_id": "my_mod",
    "category": "limits",
    "group": "bounds",
    "property": "min_val"
  },
  "min_default": 1.0,
  "max_config": {
    "mod_id": "my_mod",
    "category": "limits",
    "group": "bounds",
    "property": "max_val"
  },
  "max_default": 10.0
}

configurable_diminishing_returns

A configurable implementation of the diminishing_returns logic, pulling its structural parameters from external config definitions.

Property Type Required Default Description
base_config ConfigReference Yes - Config reference dictating the starting base value.
base_default Float Yes - Fallback base value.
decrement_config ConfigReference Yes - Config reference dictating the per-level decrement amount.
decrement_default Float Yes - Fallback decrement amount.
minimum_config ConfigReference Yes - Config reference dictating the lowest allowed addition per level.
minimum_default Float Yes - Fallback minimum amount.
Codec
public static final MapCodec<ConfigurableDiminishingReturnsValue> CODEC = RecordCodecBuilder.mapCodec(instance -> instance.group(
        ConfigReference.CODEC.fieldOf("base_config").forGetter(ConfigurableDiminishingReturnsValue::baseReference),
        Codec.FLOAT.fieldOf("base_default").forGetter(ConfigurableDiminishingReturnsValue::baseDefault),
        ConfigReference.CODEC.fieldOf("decrement_config").forGetter(ConfigurableDiminishingReturnsValue::decrementReference),
        Codec.FLOAT.fieldOf("decrement_default").forGetter(ConfigurableDiminishingReturnsValue::decrementDefault),
        ConfigReference.CODEC.fieldOf("minimum_config").forGetter(ConfigurableDiminishingReturnsValue::minimumReference),
        Codec.FLOAT.fieldOf("minimum_default").forGetter(ConfigurableDiminishingReturnsValue::minimumDefault)
).apply(instance, ConfigurableDiminishingReturnsValue::new));
Template
{
  "type": "enchantment_core:configurable_diminishing_returns",
  "base_config": {
    "mod_id": "my_mod",
    "category": "scaling",
    "group": "base",
    "property": "val"
  },
  "base_default": 5.0,
  "decrement_config": {
    "mod_id": "my_mod",
    "category": "scaling",
    "group": "decrement",
    "property": "val"
  },
  "decrement_default": 0.5,
  "minimum_config": {
    "mod_id": "my_mod",
    "category": "scaling",
    "group": "minimum",
    "property": "val"
  },
  "minimum_default": 1.0
}

configurable_levels_squared

Returns (level^2) + added_constant, where the added constant is bound to a configuration property.

Property Type Required Default Description
config ConfigReference Yes - The configuration reference dictating the constant added to the squared level.
default_added Float Yes - Fallback constant added if the config fails to resolve.
min Float No -MAX_VALUE Absolute lower bound for the added constant.
max Float No MAX_VALUE Absolute upper bound for the added constant.
Codec
public static final MapCodec<ConfigurableLevelsSquaredValue> CODEC = RecordCodecBuilder.mapCodec(instance -> instance.group(
        ConfigReference.CODEC.fieldOf("config").forGetter(ConfigurableLevelsSquaredValue::reference),
        Codec.FLOAT.fieldOf("default_added").forGetter(ConfigurableLevelsSquaredValue::defaultValue),
        Codec.FLOAT.optionalFieldOf("min", -Float.MAX_VALUE).forGetter(ConfigurableLevelsSquaredValue::min),
        Codec.FLOAT.optionalFieldOf("max", Float.MAX_VALUE).forGetter(ConfigurableLevelsSquaredValue::max)
).apply(instance, ConfigurableLevelsSquaredValue::new));
Template
{
  "type": "enchantment_core:configurable_levels_squared",
  "config": {
    "mod_id": "my_mod",
    "category": "combat",
    "group": "weapons",
    "property": "squared_offset"
  },
  "default_added": 0.0,
  "min": 0.0,
  "max": 10.0
}

configurable_linear

A linear multiplier (base + per_level * (level - 1)) fully bound to configuration variables with hard limits.

Property Type Required Default Description
base_config ConfigReference Yes - Config reference defining the Level 1 value.
base_default Float Yes - Fallback default for the base.
base_min Float No -MAX_VALUE Absolute lower limit for the base property.
base_max Float No MAX_VALUE Absolute upper limit for the base property.
per_level_config ConfigReference Yes - Config reference defining the scalar added per subsequent level.
per_level_default Float Yes - Fallback default for the per-level multiplier.
per_level_min Float No -MAX_VALUE Absolute lower limit for the per-level multiplier.
per_level_max Float No MAX_VALUE Absolute upper limit for the per-level multiplier.
Codec
public static final MapCodec<ConfigurableLinearValue> CODEC = RecordCodecBuilder.mapCodec(instance -> instance.group(
        ConfigReference.CODEC.fieldOf("base_config").forGetter(ConfigurableLinearValue::baseReference),
        Codec.FLOAT.fieldOf("base_default").forGetter(ConfigurableLinearValue::baseDefault),
        Codec.FLOAT.optionalFieldOf("base_min", -Float.MAX_VALUE).forGetter(ConfigurableLinearValue::baseMin),
        Codec.FLOAT.optionalFieldOf("base_max", Float.MAX_VALUE).forGetter(ConfigurableLinearValue::baseMax),
        ConfigReference.CODEC.fieldOf("per_level_config").forGetter(ConfigurableLinearValue::perLevelReference),
        Codec.FLOAT.fieldOf("per_level_default").forGetter(ConfigurableLinearValue::perLevelDefault),
        Codec.FLOAT.optionalFieldOf("per_level_min", -Float.MAX_VALUE).forGetter(ConfigurableLinearValue::perLevelMin),
        Codec.FLOAT.optionalFieldOf("per_level_max", Float.MAX_VALUE).forGetter(ConfigurableLinearValue::perLevelMax)
).apply(instance, ConfigurableLinearValue::new));
Template
{
  "type": "enchantment_core:configurable_linear",
  "base_config": {
    "mod_id": "my_mod",
    "category": "scaling",
    "group": "base",
    "property": "val"
  },
  "base_default": 1.0,
  "base_min": 0.0,
  "base_max": 10.0,
  "per_level_config": {
    "mod_id": "my_mod",
    "category": "scaling",
    "group": "per_level",
    "property": "val"
  },
  "per_level_default": 1.0,
  "per_level_min": 0.0,
  "per_level_max": 5.0
}

configurable_polynomial

A configurable implementation of the polynomial value logic.

Property Type Required Default Description
scale_config ConfigReference Yes - Config dictating the final multiplier scale.
scale_default Float Yes - Fallback default for the scale.
power_config ConfigReference Yes - Config dictating the level exponent.
power_default Float Yes - Fallback default for the exponent power.
offset_config ConfigReference Yes - Config dictating the flat offset added to the result.
offset_default Float Yes - Fallback default for the offset.
level_offset_config ConfigReference Yes - Config dictating the offset added to the raw enchantment level.
level_offset_default Float Yes - Fallback default for the level offset.
Codec
public static final MapCodec<ConfigurablePolynomialValue> CODEC = RecordCodecBuilder.mapCodec(instance -> instance.group(
        ConfigReference.CODEC.fieldOf("scale_config").forGetter(ConfigurablePolynomialValue::scaleReference),
        Codec.FLOAT.fieldOf("scale_default").forGetter(ConfigurablePolynomialValue::scaleDefault),
        ConfigReference.CODEC.fieldOf("power_config").forGetter(ConfigurablePolynomialValue::powerReference),
        Codec.FLOAT.fieldOf("power_default").forGetter(ConfigurablePolynomialValue::powerDefault),
        ConfigReference.CODEC.fieldOf("offset_config").forGetter(ConfigurablePolynomialValue::offsetReference),
        Codec.FLOAT.fieldOf("offset_default").forGetter(ConfigurablePolynomialValue::offsetDefault),
        ConfigReference.CODEC.fieldOf("level_offset_config").forGetter(ConfigurablePolynomialValue::levelOffsetReference),
        Codec.FLOAT.fieldOf("level_offset_default").forGetter(ConfigurablePolynomialValue::levelOffsetDefault)
).apply(instance, ConfigurablePolynomialValue::new));
Template
{
  "type": "enchantment_core:configurable_polynomial",
  "scale_config": {
    "mod_id": "my_mod",
    "category": "poly",
    "group": "scale",
    "property": "val"
  },
  "scale_default": 1.0,
  "power_config": {
    "mod_id": "my_mod",
    "category": "poly",
    "group": "power",
    "property": "val"
  },
  "power_default": 2.0,
  "offset_config": {
    "mod_id": "my_mod",
    "category": "poly",
    "group": "offset",
    "property": "val"
  },
  "offset_default": 0.0,
  "level_offset_config": {
    "mod_id": "my_mod",
    "category": "poly",
    "group": "level_offset",
    "property": "val"
  },
  "level_offset_default": -1.0
}

Clone this wiki locally