feat: worldgen improvements
This commit is contained in:
parent
1b736b5e31
commit
b1b243fd1c
@ -1,5 +1,5 @@
|
|||||||
|
|
||||||
minestom_version = d0754f2a15
|
minestom_version = e8f34c317a
|
||||||
minestompvp_version = 547b6e95af
|
minestompvp_version = 547b6e95af
|
||||||
vri_version = a79a2d9422
|
vri_version = a79a2d9422
|
||||||
jnoise_version = 5.0.0-SNAPSHOT
|
jnoise_version = 5.0.0-SNAPSHOT
|
||||||
|
@ -30,7 +30,11 @@ public class EventHandler {
|
|||||||
public static void onPlayerConfiguration(AsyncPlayerConfigurationEvent event) {
|
public static void onPlayerConfiguration(AsyncPlayerConfigurationEvent event) {
|
||||||
final Player player = event.getPlayer();
|
final Player player = event.getPlayer();
|
||||||
event.setSpawningInstance(Main.overworld);
|
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) {
|
public static void onPlayerDeath(EntityPreDeathEvent event) {
|
||||||
|
@ -6,6 +6,8 @@ import dev.ninjdai.werewolf.commands.PlayerKillCommand;
|
|||||||
import dev.ninjdai.werewolf.gui.Gui;
|
import dev.ninjdai.werewolf.gui.Gui;
|
||||||
import dev.ninjdai.werewolf.uhc.UHCPlayer;
|
import dev.ninjdai.werewolf.uhc.UHCPlayer;
|
||||||
import dev.ninjdai.werewolf.worldgen.LGGenerator;
|
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.MinestomPvP;
|
||||||
import io.github.togar2.pvp.feature.CombatFeatureSet;
|
import io.github.togar2.pvp.feature.CombatFeatureSet;
|
||||||
import io.github.togar2.pvp.feature.CombatFeatures;
|
import io.github.togar2.pvp.feature.CombatFeatures;
|
||||||
@ -33,8 +35,8 @@ public class Main {
|
|||||||
|
|
||||||
//VanillaReimplementation vri = VanillaReimplementation.hook(MinecraftServer.process());
|
//VanillaReimplementation vri = VanillaReimplementation.hook(MinecraftServer.process());
|
||||||
|
|
||||||
overworld.setGenerator(LGGenerator::generate);
|
|
||||||
overworld.setChunkSupplier(LightingChunk::new);
|
overworld.setChunkSupplier(LightingChunk::new);
|
||||||
|
overworld.setGenerator(new LGGenerator(new LGTerrainBuilder(3301)));
|
||||||
|
|
||||||
GlobalEventHandler globalEventHandler = MinecraftServer.getGlobalEventHandler();
|
GlobalEventHandler globalEventHandler = MinecraftServer.getGlobalEventHandler();
|
||||||
EventHandler.register(globalEventHandler);
|
EventHandler.register(globalEventHandler);
|
||||||
@ -50,6 +52,8 @@ public class Main {
|
|||||||
|
|
||||||
MinecraftServer.getConnectionManager().setPlayerProvider(UHCPlayer::new);
|
MinecraftServer.getConnectionManager().setPlayerProvider(UHCPlayer::new);
|
||||||
|
|
||||||
|
overworld.loadChunk(0, 0);
|
||||||
|
|
||||||
OpenToLAN.open();
|
OpenToLAN.open();
|
||||||
MinecraftServer.setBrandName("Playground");
|
MinecraftServer.setBrandName("Playground");
|
||||||
//VelocityProxy.enable("cMkrrJ8tdUS6");
|
//VelocityProxy.enable("cMkrrJ8tdUS6");
|
||||||
|
@ -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));
|
||||||
|
}
|
||||||
|
}
|
@ -1,39 +1,89 @@
|
|||||||
package dev.ninjdai.werewolf.worldgen;
|
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.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.block.Block;
|
||||||
import net.minestom.server.instance.generator.GenerationUnit;
|
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;
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
|
||||||
public class LGGenerator {
|
import java.util.Random;
|
||||||
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();
|
|
||||||
|
|
||||||
public static void generate(@NotNull GenerationUnit unit) {
|
public class LGGenerator implements Generator {
|
||||||
Point start = unit.absoluteStart();
|
TerrainBuilder terrainBuilder;
|
||||||
for (int x = 0; x < unit.size().x(); x++) {
|
Random random;
|
||||||
for (int z = 0; z < unit.size().z(); z++) {
|
double densityThreshold = 1;//0.6;
|
||||||
Point bottom = start.add(x, 0, z);
|
int upperRelativeDensityLimit = 50;
|
||||||
|
int lowerRelativeDensityLimit = 50;
|
||||||
|
|
||||||
synchronized (noise1) {
|
public LGGenerator(TerrainBuilder tb) {
|
||||||
double height = noise1.evaluateNoise(bottom.x(), bottom.z()) * 16 + 20;
|
this.terrainBuilder = tb;
|
||||||
// * 16 means the height will be between -16 and +16
|
this.random = new Random(tb.seed);
|
||||||
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);
|
@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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -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;
|
||||||
|
}
|
||||||
|
}
|
45
src/main/java/dev/ninjdai/werewolf/worldgen/Noises.java
Normal file
45
src/main/java/dev/ninjdai/werewolf/worldgen/Noises.java
Normal 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);
|
||||||
|
}
|
||||||
|
}
|
@ -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);
|
||||||
|
}
|
||||||
|
}
|
@ -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);
|
||||||
|
}
|
@ -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;
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user