Skip to content

EntityScaling ignores meta.rounding_unit, hardcodes rounding from modifier value #55

@rumrunner0

Description

@rumrunner0

EntityScaling ignores meta.rounding_unit config, hardcodes rounding from modifier value.

Summary

EntityScaling.apply() computes its own rounding unit from modifier.value * 0.25F instead of reading meta.rounding_unit from the config. This causes entity attribute modifiers to be rounded to arbitrary increments that don't match the user-configured rounding unit. ItemScaling correctly reads the config value via getRoundingUnit(), so loot scaling rounds properly while entity scaling does not.

Affected code

EntityScaling.java, lines 81-83:

var modifierValue = modifier.randomizedValue(level);
var roundingUnit = modifier.value * 0.25F;  // BUG: hardcoded, ignores config
modifierValue = (float) MathHelper.round(modifierValue, roundingUnit);

Reproduction

Config:

{
  "meta": {
    "rounding_unit": 0.5
  },
  "difficulty_types": [
    {
      "name": "wilds",
      "entities": [
        {
          "entity_matches": { "attitude": "ANY", "type": "" },
          "attributes": [
            {
              "attribute": "minecraft:generic.max_health",
              "operation": "MULTIPLY_BASE",
              "randomness": 0.0,
              "value": 0.15,
              "offset": 2.0
            }
          ]
        }
      ]
    }
  ]
}

Expected: Zombie (20 base HP) gets modifier value 2.0 + (0.15 * 1) = 2.15, rounded to nearest 0.5 = 2.0 or 2.5, resulting in 20 * 3.0 = 60.0 or 20 * 3.5 = 70.0 HP.

Actual: Rounding unit is computed as 0.15 * 0.25 = 0.0375. Modifier value 2.15 rounds to 57 * 0.0375 = 2.1375. Zombie gets 20 * 3.1375 = 62.75 HP.

The bug is more visible with non-zero offset, but also affects any modifier where value * 0.25 doesn't align with the configured rounding_unit. For example, with value: 0.3 and randomness: 0.05 at level 1, the rounding unit becomes 0.075 instead of the configured 0.5, producing values like 18.39 HP on mobs that should show clean half-point increments.

Additionally, when modifier.value is 0.0 (e.g., a flat offset-only modifier), the rounding unit becomes 0.0. In MathHelper.round(), this computes 1.0 / 0.0 = Infinity, then Math.round(value * Infinity) = Long.MAX_VALUE, then Long.MAX_VALUE / Infinity = 0.0. The modifier is silently zeroed out instead of being applied.

Suggested fix

Option A: Extract a shared RoundingHelper class that reads meta.rounding_unit from config. Both EntityScaling and ItemScaling use it instead of each having their own implementation.

// RoundingHelper.java (new file in net.dungeon_difficulty.logic)
package net.dungeon_difficulty.logic;

import net.dungeon_difficulty.DungeonDifficulty;
import org.jetbrains.annotations.Nullable;

public class RoundingHelper {
    @Nullable
    public static Double getRoundingUnit() {
        var config = DungeonDifficulty.config.value;
        if (config.meta != null && config.meta.rounding_unit != null) {
            return config.meta.rounding_unit;
        }
        return null;
    }
}
// EntityScaling.java, replace lines 81-83:
var modifierValue = modifier.randomizedValue(level);
var roundingUnit = RoundingHelper.getRoundingUnit();
if (roundingUnit != null) {
    modifierValue = (float) MathHelper.round(modifierValue, roundingUnit);
}
// ItemScaling.java, replace private getRoundingUnit() and its call sites:
var roundingUnit = RoundingHelper.getRoundingUnit();
if (roundingUnit != null) {
    value = MathHelper.round(value, roundingUnit);
}

Option B (more flexible, preferable): Introduce a separate config parameter for entity scaling rounding (e.g., meta.entity_rounding_unit), then wire it in EntityScaling the same way ItemScaling currently reads meta.rounding_unit. This would allow independent control over rounding precision for entity stats vs. item stats. RoundingHelper could expose two methods (getEntityRoundingUnit() and getItemRoundingUnit()) in this case.

Thank you!

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions