feat: worldgen improvements

This commit is contained in:
Ninjdai 2024-10-03 22:00:56 +02:00
parent 1b736b5e31
commit b1b243fd1c
10 changed files with 277 additions and 30 deletions

View File

@ -1,5 +1,5 @@
minestom_version = d0754f2a15
minestom_version = e8f34c317a
minestompvp_version = 547b6e95af
vri_version = a79a2d9422
jnoise_version = 5.0.0-SNAPSHOT

View File

@ -30,7 +30,11 @@ public class EventHandler {
public static void onPlayerConfiguration(AsyncPlayerConfigurationEvent event) {
final Player player = event.getPlayer();
event.setSpawningInstance(Main.overworld);
player.setRespawnPoint(new Pos(0, 42, 0));
int y = 200;
while (Main.overworld.getBlock(0, y, 0) == Block.AIR) {
y--;
}
player.setRespawnPoint(new Pos(0, y, 0));
};
public static void onPlayerDeath(EntityPreDeathEvent event) {

View File

@ -6,6 +6,8 @@ import dev.ninjdai.werewolf.commands.PlayerKillCommand;
import dev.ninjdai.werewolf.gui.Gui;
import dev.ninjdai.werewolf.uhc.UHCPlayer;
import dev.ninjdai.werewolf.worldgen.LGGenerator;
import dev.ninjdai.werewolf.worldgen.LGTerrainBuilder;
import dev.ninjdai.werewolf.worldgen.TerrainBuilder;
import io.github.togar2.pvp.MinestomPvP;
import io.github.togar2.pvp.feature.CombatFeatureSet;
import io.github.togar2.pvp.feature.CombatFeatures;
@ -33,8 +35,8 @@ public class Main {
//VanillaReimplementation vri = VanillaReimplementation.hook(MinecraftServer.process());
overworld.setGenerator(LGGenerator::generate);
overworld.setChunkSupplier(LightingChunk::new);
overworld.setGenerator(new LGGenerator(new LGTerrainBuilder(3301)));
GlobalEventHandler globalEventHandler = MinecraftServer.getGlobalEventHandler();
EventHandler.register(globalEventHandler);
@ -50,6 +52,8 @@ public class Main {
MinecraftServer.getConnectionManager().setPlayerProvider(UHCPlayer::new);
overworld.loadChunk(0, 0);
OpenToLAN.open();
MinecraftServer.setBrandName("Playground");
//VelocityProxy.enable("cMkrrJ8tdUS6");

View File

@ -0,0 +1,68 @@
package dev.ninjdai.werewolf.worldgen;
import de.articdive.jnoise.generators.noisegen.opensimplex.FastSimplexNoiseGenerator;
import de.articdive.jnoise.modules.octavation.fractal_functions.FractalFunction;
import de.articdive.jnoise.pipeline.JNoise;
import dev.ninjdai.werewolf.worldgen.utils.AbsClampNoiseModifier;
import net.minestom.vanilla.datapack.worldgen.math.SplineInterpolator;
public enum InterpolatedNoises {
CONTINENTALNESS(
JNoise.newBuilder()
.fastSimplex(FastSimplexNoiseGenerator.newBuilder()
.setSeed(0)
.build())
.octavate(5, 0.5, 2.2, FractalFunction.FBM, false)
.scale(0.002)
.addModifier(new AbsClampNoiseModifier())
.build(),
new SplineInterpolatorBuilder()
.add(0.0, 0.0)
.add(0.25, 0.1)
.add(0.285, 0.38)
.add(0.3, 0.444)
.add(0.39, 0.666)
.add(0.433, 0.777)
.add(0.5, 0.888)
.add(0.7, 0.97)
.add(1, 1)
.build()
),
EROSION(
JNoise.newBuilder()
.fastSimplex(FastSimplexNoiseGenerator.newBuilder()
.setSeed(0)
.build())
.octavate(5, 0.3, 3, FractalFunction.FBM, false)
.scale(0.0015)
.invert()
.addModifier(new AbsClampNoiseModifier())
.build(),
new SplineInterpolatorBuilder()
.add(0, 0)
.add(0.1, 0.3)
.add(0.5, 0.9)
.add(0.6, 0.91)
.add(0.62, 0.7)
.add(0.7, 0.71)
.add(0.72, 0.91)
.add(1, 1)
.build()
);
final private JNoise noise;
final private SplineInterpolator interpolator;
InterpolatedNoises(JNoise noise, SplineInterpolator interpolator) {
this.noise = noise;
this.interpolator = interpolator;
}
public double evaluateNoise(int x, int z) {
return interpolator.interpolate(noise.evaluateNoise(x, z));
}
double evaluateNoise(int x, int y, int z) {
return interpolator.interpolate(noise.evaluateNoise(x, y, z));
}
}

View File

@ -1,39 +1,89 @@
package dev.ninjdai.werewolf.worldgen;
import de.articdive.jnoise.core.api.functions.Interpolation;
import de.articdive.jnoise.core.api.modifiers.NoiseModifier;
import de.articdive.jnoise.generators.noise_parameters.fade_functions.FadeFunction;
import de.articdive.jnoise.modifiers.clamp.ClampModifier;
import de.articdive.jnoise.modules.octavation.fractal_functions.FractalFunction;
import de.articdive.jnoise.pipeline.JNoise;
import net.minestom.server.coordinate.Point;
import net.minestom.server.coordinate.Pos;
import net.minestom.server.coordinate.Vec;
import net.minestom.server.instance.block.Block;
import net.minestom.server.instance.generator.GenerationUnit;
import net.minestom.server.instance.generator.Generator;
import net.minestom.server.world.biome.Biome;
import net.minestom.vanilla.generation.VanillaWorldGenerationFeature;
import net.minestom.vanilla.tag.Tags;
import org.jetbrains.annotations.NotNull;
public class LGGenerator {
static final JNoise noise1 = JNoise.newBuilder()
.perlin(3301, Interpolation.LINEAR, FadeFunction.QUINTIC_POLY)
.scale(1/48.0)
.addModifier(v -> (v + 1) / 2.0)
.clamp(0.0, 1.0)
.octavate(3, 0.5, .75, FractalFunction.TURBULENCE, true)
.build();
import java.util.Random;
public static void generate(@NotNull GenerationUnit unit) {
Point start = unit.absoluteStart();
for (int x = 0; x < unit.size().x(); x++) {
for (int z = 0; z < unit.size().z(); z++) {
Point bottom = start.add(x, 0, z);
public class LGGenerator implements Generator {
TerrainBuilder terrainBuilder;
Random random;
double densityThreshold = 1;//0.6;
int upperRelativeDensityLimit = 50;
int lowerRelativeDensityLimit = 50;
synchronized (noise1) {
double height = noise1.evaluateNoise(bottom.x(), bottom.z()) * 16 + 20;
// * 16 means the height will be between -16 and +16
unit.modifier().fill(bottom, bottom.add(1, 0, 1).withY(height), Block.STONE);
unit.modifier().fill(bottom.withY(height), bottom.add(1, 0, 1).withY(height+3), Block.DIRT);
unit.modifier().fill(bottom.withY(height+3), bottom.add(1, 0, 1).withY(height+4), Block.GRASS_BLOCK);
public LGGenerator(TerrainBuilder tb) {
this.terrainBuilder = tb;
this.random = new Random(tb.seed);
}
@Override
public void generate(@NotNull GenerationUnit unit) {
final Point min = unit.absoluteStart();
final Point max = unit.absoluteEnd();
for (int x = min.blockX(); x < max.blockX(); x++) {
for (int z = min.blockZ(); z < max.blockZ(); z++) {
generate3D(min, max, x, z, unit);
}
}
}
private void generate3D(Point min, Point max, int x, int z, GenerationUnit unit) {
int height = terrainBuilder.getSurfaceHeight(x, z);
int upperDensityLimit = height + upperRelativeDensityLimit;
int lowerDensityLimit = height - lowerRelativeDensityLimit;
int terrainHeight = lowerDensityLimit;
for (int y = upperDensityLimit; y >= lowerDensityLimit; y--) {
if (y == lowerDensityLimit) {
unit.modifier().fill(min.withX(x).withZ(z), new Vec(x + 1, lowerDensityLimit + 1, z + 1), Block.STONE);
break;
}
Vec pos = new Vec(x, y, z);
if (terrainBuilder.getDensity(x, y, z) > densityThreshold) {
unit.modifier().setBlock(pos, Block.STONE);
terrainHeight = Math.max(terrainHeight, y);
}
}
decorate(x, terrainHeight, z, unit);
}
private void decorate(int x, int y, int z, GenerationUnit unit) {
unit.modifier().setBlock(x, y + 4, z, Block.GRASS_BLOCK);
for (int i = 0; i < 4; i++) {
Block b = switch ((int) (2*Noises.FEATURES.evaluateNoise(x, y+i, z))) {
case 0 -> Block.COARSE_DIRT;
case 1 -> Block.ROOTED_DIRT;
default -> Block.DIRT;
};
unit.modifier().setBlock(x, y + i, z, b);
}
int ry = y+5;
double ft = Noises.FEATURES.evaluateNoise(x, z);
if (ft > 0.995) {
int height = (int) (3 + 3*Noises.FEATURES.evaluateNoise(x, y, z));
GenerationUnit fork = unit.fork(new Vec(x-2, ry, z-2), new Vec(x+3, ry+height+4, z+3));
fork.modifier().fill(new Vec(x, ry, z), new Vec(x+1, ry+height, z+1), Block.OAK_LOG);
fork.modifier().fill(new Vec(x-2, ry+height, z-2), new Vec(x+3, ry+height+2, z+3), Block.OAK_LEAVES);
fork.modifier().fill(new Vec(x-1, ry+height+2, z-1), new Vec(x+2, ry+height+3, z+2), Block.OAK_LEAVES);
} else if (ft > 0.95) {
unit.modifier().setBlock(x, ry, z, Block.TALL_GRASS);
unit.modifier().setBlock(x, ry+1, z, Block.TALL_GRASS.withProperty("half", "upper"));
} else if (ft > 0.8) {
unit.modifier().setBlock(x, ry, z, Block.SHORT_GRASS);
} else if (ft < -0.99) {
unit.modifier().setBlock(x, ry, z, Block.POPPY);
}
}
}

View File

@ -0,0 +1,29 @@
package dev.ninjdai.werewolf.worldgen;
public class LGTerrainBuilder extends TerrainBuilder {
// 0: no squashing the terrain, 1: basically the surface height
private final double squashingFactor = 1.5;
public LGTerrainBuilder(long seed) {
super(seed);
}
@Override
public int getSurfaceHeight(int x, int z) {
double continentalness = InterpolatedNoises.CONTINENTALNESS.evaluateNoise(x, z);
double erosion = InterpolatedNoises.EROSION.evaluateNoise(x, z);
return (int) ((continentalness + erosion) * 50);
}
@Override
public double getDensity(int x, int y, int z) {
double density = Noises.DENSITY.evaluateNoise(x, y, z);
int surfaceHeight = getSurfaceHeight(x, z);
density *= (double) surfaceHeight / y;
return density;
}
}

View File

@ -0,0 +1,45 @@
package dev.ninjdai.werewolf.worldgen;
import de.articdive.jnoise.generators.noisegen.opensimplex.FastSimplexNoiseGenerator;
import de.articdive.jnoise.generators.noisegen.random.white.WhiteNoiseGenerator;
import de.articdive.jnoise.modules.octavation.fractal_functions.FractalFunction;
import de.articdive.jnoise.pipeline.JNoise;
import dev.ninjdai.werewolf.worldgen.utils.AbsClampNoiseModifier;
public enum Noises {
WEIRDNESS(JNoise.newBuilder()
.fastSimplex(FastSimplexNoiseGenerator.newBuilder()
.setSeed(0)
.build())
.octavate(5, 0.5, 1.2, FractalFunction.FBM, false)
.scale(0.005)
.addModifier(new AbsClampNoiseModifier())
.build()),
DENSITY(JNoise.newBuilder()
.fastSimplex(FastSimplexNoiseGenerator.newBuilder()
.setSeed(0)
.build())
.octavate(5, 0.7, 1.6, FractalFunction.FBM, true)
.scale(0.006)
.addModifier(new AbsClampNoiseModifier())
.build()),
FEATURES(JNoise.newBuilder()
.white(WhiteNoiseGenerator.newBuilder().setSeed(0).build())
.addModifier(new AbsClampNoiseModifier())
.build());
final private JNoise noise;
Noises(JNoise noise) {
this.noise = noise;
}
public double evaluateNoise(int x, int z) {
return noise.evaluateNoise(x, z);
}
public double evaluateNoise(int x, int y, int z) {
return noise.evaluateNoise(x, y, z);
}
}

View File

@ -0,0 +1,25 @@
package dev.ninjdai.werewolf.worldgen;
import it.unimi.dsi.fastutil.doubles.DoubleArrayList;
import it.unimi.dsi.fastutil.doubles.DoubleList;
import net.minestom.vanilla.datapack.worldgen.math.SplineInterpolator;
public class SplineInterpolatorBuilder {
private DoubleList xList;
private DoubleList yList;
SplineInterpolatorBuilder() {
this.xList = new DoubleArrayList();
this.yList = new DoubleArrayList();
}
public SplineInterpolatorBuilder add(double x, double y) {
this.xList.add(x);
this.yList.add(y);
return this;
}
public SplineInterpolator build() {
return SplineInterpolator.createMonotoneCubicSpline(xList, yList);
}
}

View File

@ -0,0 +1,12 @@
package dev.ninjdai.werewolf.worldgen;
public abstract class TerrainBuilder {
long seed;
TerrainBuilder(long seed) {
this.seed = seed;
}
abstract int getSurfaceHeight(int x, int z);
abstract double getDensity(int x, int y, int z);
}

View File

@ -0,0 +1,10 @@
package dev.ninjdai.werewolf.worldgen.utils;
import de.articdive.jnoise.core.api.modifiers.NoiseModifier;
public class AbsClampNoiseModifier implements NoiseModifier {
@Override
public double apply(double result) {
return (result + 1) * 0.5;
}
}