Skip to content

Reference.MaintainPrecision.en

inf32768 edited this page Oct 24, 2026 · 9 revisions

English | 简体中文

maintainPrecision Method

Note: All identifiers used in this document follow the Fabric Yarn mapping.

The maintainPrecision method is a utility function in the Minecraft Java Edition server that prevents overflow caused by excessively large coordinate values during noise sampling.

Implementation

The maintainPrecision method is implemented in the net.minecraft.util.math.noise.OctavePerlinNoiseSampler class, with the following source code:

public static double maintainPrecision(double value) {
    return value - MathHelper.lfloor(value / 33554432D + 0.5D) * 33554432D;
}

Among them, MathHelper.lfloor is a method used for rounding down. Its parameter is of type double, and it returns a value of type long, following the saturated overflow rule (if the input value is greater than Long.MAX_VALUE, it returns Long.MAX_VALUE, and similarly for the minimum value).

Analysis

Principle

From the implementation, it can be seen that this method essentially performs an operation similar to modulo on the input value. Mathematically, it is equivalent to mod(value-2^24, 2^25)-2^24. Under normal conditions, the output value will fall within the range [-2^24, 2^24), ensuring it does not exceed the integer range of 2^24.

The graph of the maintainPrecision method, with the horizontal axis representing input values and the vertical axis representing output values

Overflow

Under normal circumstances (assuming no precision loss), this method always behaves as described by the mathematical formula above. However, because the lfloor method returns a long value, if the input value exceeds 2^63-1, it will always return 2^63-1. At this point, the method experiences an "overflow," losing its modulo effect, and the return value will increase indefinitely as the input grows, leading to various issues.

The function graph when this method overflows. Note that the 'horizontal line' near the origin is actually made up of countless graphs shown in the lower right corner.

Role

In the Perlin noise sampling algorithm used in Minecraft Java Edition, if any axis coordinate exceeds the range of the int type, it causes an overflow in the noise generator (not to be confused with the overflow of this method), generating the so-called "far lands". Therefore, before performing noise sampling, the game passes the final sampling coordinates (after scaling by the noise coordinate scale and applying offsets) into the maintainPrecision method to prevent excessive sampling coordinates from causing overflow. This is essentially the solution implemented in versions 1.14+ to fix the far lands. Since the sampling algorithm itself has periodicity, repeating every 256 units in each axis, this fix does not affect normal terrain generation.

However, as is well known, the far lands in versions 1.14+ were not completely fixed; instead, they were pushed back by a factor of 2^25. This is precisely due to the overflow issue mentioned above. A simple calculation shows that when the absolute value of the input exceeds 2^88 (≈ 3.09485e+26), the method overflows, which is the source of the upper limit for noise sampling coordinates in versions 1.14+. And 2^88 / 171.103 ≈ 1.8088e+24, which corresponds to the coordinate value where the far lands begin to generate in versions 1.14+.

Modifications

As a critical checkpoint before noise sampling, the maintainPrecision method holds significant potential for modification. Below is the modified source code of maintainPrecision from this mod:

public static double maintainPrecision(double value) {
    // config = ConfigManager.getConfig()
    double result = switch (config.worldGen.farLandsControl.farLandsPos) {
        case BETA -> value;
        case RELEASE -> {
            long l = (long) value;
            yield value - l + l % 16777216L;
        }
        case REMOVED -> (value + 1.6777216E7D) % 3.3554432E7D - 1.6777216E7D;
        case DEFAULT ->
                value - (double) MathHelper.lfloor(value / config.worldGen.farLandsControl.customDivisor + (double) 0.5F) * config.worldGen.farLandsControl.customDivisor;
    };
    if (config.worldGen.farLandsControl.limitReturnValue) {
        result = Math.log10(Math.abs(result)) > config.worldGen.farLandsControl.maxLogarithmValue ? Math.pow(10, Math.log10(Math.abs(result)) - Math.floor(Math.log10(Math.abs(result)) - config.worldGen.farLandsControl.maxLogarithmValue)) * Math.signum(result) : result;
    }
    return result;
}

With this, we have implemented two features: shifting the far lands and limiting the return value range.

Shifting the Far Lands

Based on the value of the config.worldGen.farLandsControl.farLandsPos configuration option, we can choose to shift the location of the far lands (effectively altering the range of parameters that cause the method to overflow, referred to as the "parameter upper limit" below) without affecting normal terrain generation.

  • BETA: Similar to Java Edition Infdev 20100327 to Beta 1.7.3 and Bedrock Edition, the parameter upper limit is Integer.MAX_VALUE.

    Principle: Directly returns the input value. Once the input exceeds Integer.MAX_VALUE, overflow occurs.

  • RELEASE: Similar to Java Edition Beta 1.8 to release 1.13.2, the parameter upper limit is Long.MAX_VALUE.

    Principle: The input is converted to a long, and the result is reconstructed from the fractional part and the low 24 bits (l % 16777216). This reproduces the Beta 1.8–1.13.2 behavior. Once the input exceeds the long range, the conversion saturates, the modulo effect is lost, and the return value grows indefinitely with the input, eventually leading to overflow.

  • DEFAULT: Maintains the original 1.14+ implementation. The divisor is read from config.worldGen.farLandsControl.customDivisor (hereafter referred to as divisor) instead of being hardcoded. The default value 33554432 reproduces the original behavior. The old CUSTOM option has been removed: selecting DEFAULT and changing divisor is the equivalent. Note that this is an advanced parameter that changes terrain generation behavior; it is not a precise "Far Lands position" control.

    After modification, the method retains its original functionality, mathematically equivalent to mod(value-divisor/2, divisor)-divisor/2, but the parameter upper limit becomes 2^63 * divisor + 2^31. Additionally, if divisor is too large, too small, or not an integer multiple of 2, it can affect normal terrain generation. See below:

    • divisor is not an integer multiple of 2: When the input value is large but does not trigger overflow, precision loss may cause the return value to exceed 2^31, leading to far lands generation. However, not every large value will trigger overflow, resulting in alternating far lands and normal terrain.
    • divisor > 2^32: Input values exceeding 2^31 may still remain unaffected (remainder < divisor/2), causing the noise generator to overflow at the usual location (corresponding to BETA), but the overflow will not persist indefinitely (as input values reaching divisor/2 will be affected).
    • 512 <= divisor <= 2^32: Typically no issues; far lands can be shifted normally.
    • 4 <= divisor < 512: The method's period becomes smaller than the Perlin noise period, affecting normal terrain generation.
    • 1 <= divisor < 4: The method's period becomes very small, causing noticeable changes in normal terrain. As the value decreases, normal terrain becomes increasingly irregular and fragmented.
    • 0.01 <= divisor < 1: Unlike the fragmentation of the previous stage, this stage results in terrain that becomes smoother and repeats in patterns. The smaller the value, the more pronounced the repetition and the smoother the terrain, giving it a stretched appearance. At 0.01, the terrain becomes almost completely flat.
    • 1.0e-15 <= divisor < 0.01: Terrain becomes almost entirely flat until the far lands.
    • divisor <= 1.0e-15: Terrain undulations slowly begin to recover. The smaller the value, the closer the terrain gets to normal, and the far lands' position approaches the "normal" location of the BETA option.
    • divisor = 0: The generated terrain (including far lands) is identical to the BETA option. This occurs because the return value of lfloor multiplied by divisor (which is 0) always results in 0, so the input minus 0 remains the input, effectively making it no different from the BETA option.
  • REMOVED: Completely fixes the overflow issue in this method, thereby preventing the noise generator from overflowing.

    Principle: Replaces the pseudo-modulo operation (which could overflow) with a true modulo operation.

Limiting the Return Value Range

When config.worldGen.farLandsControl.limitReturnValue is set to true, we can restrict the return value range of this method based on the value of config.worldGen.farLandsControl.maxLogarithmValue (hereafter referred to as maxLog). This feature is designed to prevent the generation of fringe lands.

Principle: After processing the input value through the "shifting the far lands" step, the result is expressed in scientific notation, and its exponent is extracted. If the exponent exceeds maxLog, it is capped at maxLog, and the return value is computed by multiplying the coefficient with 10 raised to the capped exponent. The advantage of this approach is that the growth trend of the return value remains consistent with the input value (ignoring abrupt changes). Who on earth wrote this method? A simple clamp would suffice, and the issues caused by abrupt changes in the return value far outweigh any benefits of maintaining consistent growth trends. This needs to be replaced as soon as possible!

Testing has revealed that setting maxLog less than or equal to 26 prevents the generation of fringe lands, while values less than or equal to 9 prevent noise overflow (i.e., the far lands no longer generate). Excessively small values can also cause issues with normal terrain, similar to the problems caused by an overly small divisor as described earlier.


Appendix

A1. Mappings Comparison

Type Mojmap Yarn
Class net.minecraft.world.level.levelgen.synth.PerlinNoise net.minecraft.util.math.noise.OctavePerlinNoiseSampler
Method PerlinNoise.wrap(double) OctavePerlinNoiseSampler.maintainPrecision(double)
Class net.minecraft.util.Mth net.minecraft.util.math.MathHelper
Method Mth.lfloor(double) MathHelper.lfloor(double)

Wiki 导航 | Navigation

🏠 首页 | Home

🧭 用户指南 | User Guide

📈 项目治理 | Project Management

📚 参考资料 | References

Clone this wiki locally