diff --git a/src/worldgen/DensityFunction.ts b/src/worldgen/DensityFunction.ts index 2e4feacf..9384e310 100644 --- a/src/worldgen/DensityFunction.ts +++ b/src/worldgen/DensityFunction.ts @@ -88,8 +88,8 @@ export namespace DensityFunction { case 'find_top_surface': return new FindTopSurface( inputParser(root.density), inputParser(root.upper_bound), - Json.readNumber(root.lower_bound) ?? 0, - Json.readNumber(root.cell_height) ?? 1, + Json.readInt(root.lower_bound) ?? 0, + Json.readInt(root.cell_height) ?? 1, ) case 'weird_scaled_sampler': return new WeirdScaledSampler( inputParser(root.input), diff --git a/src/worldgen/NoiseChunk.ts b/src/worldgen/NoiseChunk.ts index a7419f5c..560302da 100644 --- a/src/worldgen/NoiseChunk.ts +++ b/src/worldgen/NoiseChunk.ts @@ -15,10 +15,10 @@ export class NoiseChunk { public readonly firstNoiseX: number public readonly firstNoiseZ: number public readonly noiseSizeXZ: number - private readonly preliminarySurfaceLevel: Map = new Map() + private readonly preliminarySurfaceLevelCache: Map = new Map() private readonly aquifer: Aquifer private readonly materialRule: MaterialRule - private readonly initialDensity: DensityFunction + private readonly preliminarySurfaceLevel: DensityFunction constructor( public readonly cellCountXZ: number, @@ -51,7 +51,7 @@ export class NoiseChunk { this.materialRule = MaterialRule.fromList([ (context) => this.aquifer.compute(context, finalDensity.compute(context)), ]) - this.initialDensity = randomState.router.initialDensityWithoutJaggedness + this.preliminarySurfaceLevel = randomState.router.preliminarySurfaceLevel } public getFinalState(x: number, y: number, z: number): BlockState | undefined { @@ -59,16 +59,11 @@ export class NoiseChunk { } public getPreliminarySurfaceLevel(quartX: number, quartZ: number) { - return computeIfAbsent(this.preliminarySurfaceLevel, ChunkPos.asLong(quartX, quartZ), () => { + return computeIfAbsent(this.preliminarySurfaceLevelCache, ChunkPos.asLong(quartX, quartZ), () => { const x = quartX << 2 const z = quartZ << 2 - for (let y = this.settings.minY + this.settings.height; y >= this.settings.minY; y -= this.cellHeight) { - const density = this.initialDensity.compute(DensityFunction.context(x, y, z)) - if (density > 0.390625) { - return y - } - } - return Number.MAX_SAFE_INTEGER + + return Math.floor(this.preliminarySurfaceLevel.compute(DensityFunction.context(x, 0, z))) }) } } diff --git a/src/worldgen/NoiseRouter.ts b/src/worldgen/NoiseRouter.ts index 2c91b946..242ddb9a 100644 --- a/src/worldgen/NoiseRouter.ts +++ b/src/worldgen/NoiseRouter.ts @@ -16,7 +16,7 @@ export interface NoiseRouter { erosion: DensityFunction, depth: DensityFunction, ridges: DensityFunction, - initialDensityWithoutJaggedness: DensityFunction, + preliminarySurfaceLevel: DensityFunction, finalDensity: DensityFunction, veinToggle: DensityFunction, veinRidged: DensityFunction, @@ -39,7 +39,7 @@ export namespace NoiseRouter { erosion: fieldParser(root.erosion), depth: fieldParser(root.depth), ridges: fieldParser(root.ridges), - initialDensityWithoutJaggedness: fieldParser(root.initial_density_without_jaggedness), + preliminarySurfaceLevel: fieldParser(root.preliminary_surface_level), finalDensity: fieldParser(root.final_density), veinToggle: fieldParser(root.vein_toggle), veinRidged: fieldParser(root.vein_ridged), @@ -59,7 +59,7 @@ export namespace NoiseRouter { erosion: DensityFunction.Constant.ZERO, depth: DensityFunction.Constant.ZERO, ridges: DensityFunction.Constant.ZERO, - initialDensityWithoutJaggedness: DensityFunction.Constant.ZERO, + preliminarySurfaceLevel: DensityFunction.Constant.ZERO, finalDensity: DensityFunction.Constant.ZERO, veinToggle: DensityFunction.Constant.ZERO, veinRidged: DensityFunction.Constant.ZERO, @@ -80,7 +80,7 @@ export namespace NoiseRouter { erosion: router.erosion.mapAll(visitor), depth: router.depth.mapAll(visitor), ridges: router.ridges.mapAll(visitor), - initialDensityWithoutJaggedness: router.initialDensityWithoutJaggedness.mapAll(visitor), + preliminarySurfaceLevel: router.preliminarySurfaceLevel.mapAll(visitor), finalDensity: router.finalDensity.mapAll(visitor), veinToggle: router.veinToggle.mapAll(visitor), veinRidged: router.veinRidged.mapAll(visitor), diff --git a/test/worldgen/DensityFunction.test.ts b/test/worldgen/DensityFunction.test.ts index d1fcfc4e..ebeb1934 100644 --- a/test/worldgen/DensityFunction.test.ts +++ b/test/worldgen/DensityFunction.test.ts @@ -2,8 +2,8 @@ import { afterEach, beforeEach, describe, expect, it } from 'vitest' import { Holder } from '../../src/core/Holder.js' import { Identifier } from '../../src/core/Identifier.js' import { CubicSpline, NoiseParameters } from '../../src/math/index.js' -import { DensityFunction as DF, NoiseGeneratorSettings, NoiseRouter, WorldgenRegistries } from '../../src/worldgen/index.js' import { RandomState } from '../../src/worldgen/RandomState.js' +import { DensityFunction as DF, NoiseGeneratorSettings, NoiseRouter, WorldgenRegistries } from '../../src/worldgen/index.js' describe('DensityFunction', () => { const DELTA = 1e-7 @@ -107,6 +107,13 @@ describe('DensityFunction', () => { expect(fn3.compute(ContextA)).toEqual(-0.33570833333333333) }) + it('Invert', () => { + const fn1 = wrap(new DF.Mapped('invert', new DF.Constant(2))) + expect(fn1.compute(ContextA)).toEqual(0.5) + const fn2 = wrap(new DF.Mapped('invert', new DF.Constant(0))) + expect(fn2.compute(ContextA)).toEqual(Number.POSITIVE_INFINITY) + }) + it('Add', () => { const fn1 = wrap(new DF.Ap2('add', new DF.Constant(2), new DF.Constant(3))) expect(fn1.compute(ContextA)).toEqual(5) @@ -177,4 +184,13 @@ describe('DensityFunction', () => { expect(fn2.compute(DF.context(0, 128, 0))).toEqual(0) expect(fn2.compute(DF.context(0, 129, 0))).toEqual(0) }) + + it('FindTopSurface', () => { + const fn1 = wrap(new DF.FindTopSurface(new DF.YClampedGradient(128, -128, -1, 1), new DF.Constant(128), -128, 1)) + expect(fn1.compute(ContextA)).toEqual(-1) + const fn2 = wrap(new DF.FindTopSurface(new DF.YClampedGradient(128, -128, -1, 1), new DF.Constant(-20), -128, 1)) + expect(fn2.compute(ContextA)).toEqual(-20) + const fn3 = wrap(new DF.FindTopSurface(new DF.YClampedGradient(128, -128, -1, 1), new DF.Constant(50), 128, 1)) + expect(fn3.compute(ContextA)).toEqual(128) + }) })