Added rock DB and worldgen
- Added Rocks container - Added DiscreteNoise and a DIY Worley generator - Added RockLayer - Used to generate rock strata - Reworked SurfaceTerrainGenerator to use contexts
This commit is contained in:
parent
4f620b7261
commit
9fc1a21191
@ -0,0 +1,25 @@
|
|||||||
|
/*
|
||||||
|
* Progressia
|
||||||
|
* Copyright (C) 2020-2021 Wind Corporation and contributors
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
package ru.windcorp.progressia.common.util.noise.discrete;
|
||||||
|
|
||||||
|
public interface DiscreteNoise<T> {
|
||||||
|
|
||||||
|
T get(double x, double y);
|
||||||
|
T get(double x, double y, double z);
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,228 @@
|
|||||||
|
/*
|
||||||
|
* Progressia
|
||||||
|
* Copyright (C) 2020-2021 Wind Corporation and contributors
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
package ru.windcorp.progressia.common.util.noise.discrete;
|
||||||
|
|
||||||
|
import java.util.Collection;
|
||||||
|
import com.google.common.collect.ImmutableList;
|
||||||
|
|
||||||
|
public class WorleyProceduralNoise<T> implements DiscreteNoise<T> {
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Stolen from OpenJDK's Random implementation
|
||||||
|
* *evil cackling*
|
||||||
|
*/
|
||||||
|
private static final long MULTIPLIER = 0x5DEECE66DL;
|
||||||
|
private static final long ADDEND = 0xBL;
|
||||||
|
private static final long MASK = (1L << 48) - 1;
|
||||||
|
private static final double DOUBLE_UNIT = 0x1.0p-53; // 1.0 / (1L << 53)
|
||||||
|
|
||||||
|
private static long permute(long seed) {
|
||||||
|
return (seed * MULTIPLIER + ADDEND) & MASK;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static double getDouble(long seed) {
|
||||||
|
final int mask26bits = (1 << 26) - 1;
|
||||||
|
final int mask27bits = (1 << 27) - 1;
|
||||||
|
|
||||||
|
int randomBitsX26 = (int) (seed & 0xFFFFFFFF);
|
||||||
|
int randomBitsX27 = (int) ((seed >>> Integer.SIZE) & 0xFFFFFFFF);
|
||||||
|
|
||||||
|
randomBitsX26 = randomBitsX26 & mask26bits;
|
||||||
|
randomBitsX27 = randomBitsX27 & mask27bits;
|
||||||
|
|
||||||
|
return (((long) (randomBitsX26) << 27) + randomBitsX27) * DOUBLE_UNIT;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class Entry<T> {
|
||||||
|
private final T value;
|
||||||
|
private final double chance;
|
||||||
|
|
||||||
|
public Entry(T value, double chance) {
|
||||||
|
this.value = value;
|
||||||
|
this.chance = chance;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class Builder<T> {
|
||||||
|
|
||||||
|
com.google.common.collect.ImmutableList.Builder<Entry<T>> builder = ImmutableList.builder();
|
||||||
|
|
||||||
|
public Builder<T> add(T value, double chance) {
|
||||||
|
builder.add(new Entry<>(value, chance));
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public WorleyProceduralNoise<T> build(long seed) {
|
||||||
|
return new WorleyProceduralNoise<>(this, seed);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public static <T> Builder<T> builder() {
|
||||||
|
return new Builder<>();
|
||||||
|
}
|
||||||
|
|
||||||
|
private final Entry<?>[] entries;
|
||||||
|
private final long seed;
|
||||||
|
|
||||||
|
public WorleyProceduralNoise(Builder<T> builder, long seed) {
|
||||||
|
this(builder.builder.build(), seed);
|
||||||
|
}
|
||||||
|
|
||||||
|
public WorleyProceduralNoise(Collection<? extends Entry<? extends T>> entries, long seed) {
|
||||||
|
this.entries = new Entry<?>[entries.size()];
|
||||||
|
|
||||||
|
double chancesSum = 0;
|
||||||
|
for (Entry<? extends T> entry : entries) {
|
||||||
|
chancesSum += entry.chance;
|
||||||
|
}
|
||||||
|
|
||||||
|
int i = 0;
|
||||||
|
for (Entry<? extends T> entry : entries) {
|
||||||
|
this.entries[i] = new Entry<T>(entry.value, entry.chance / chancesSum);
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.seed = seed;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public T get(double x, double y) {
|
||||||
|
|
||||||
|
int ox = (int) x;
|
||||||
|
int oy = (int) y;
|
||||||
|
|
||||||
|
T closest = null;
|
||||||
|
double closestDistanceSq = Double.POSITIVE_INFINITY;
|
||||||
|
|
||||||
|
for (int cellX = ox - 1; cellX <= ox + 1; ++cellX) {
|
||||||
|
for (int cellY = oy - 1; cellY <= oy + 1; ++cellY) {
|
||||||
|
|
||||||
|
long cellSeed = permute(cellY ^ permute(cellX ^ seed));
|
||||||
|
|
||||||
|
int nodes = getNodeCount(cellSeed);
|
||||||
|
cellSeed = permute(cellSeed);
|
||||||
|
|
||||||
|
for (int i = 0; i < nodes; ++i) {
|
||||||
|
|
||||||
|
double nodeX = getDouble(cellSeed) + cellX;
|
||||||
|
cellSeed = permute(cellSeed);
|
||||||
|
|
||||||
|
double nodeY = getDouble(cellSeed) + cellY;
|
||||||
|
cellSeed = permute(cellSeed);
|
||||||
|
|
||||||
|
T value = getValue(getDouble(cellSeed));
|
||||||
|
cellSeed = permute(cellSeed);
|
||||||
|
|
||||||
|
double distanceSq = (x - nodeX) * (x - nodeX) + (y - nodeY) * (y - nodeY);
|
||||||
|
if (distanceSq < closestDistanceSq) {
|
||||||
|
closestDistanceSq = distanceSq;
|
||||||
|
closest = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return closest;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public T get(double x, double y, double z) {
|
||||||
|
|
||||||
|
int ox = (int) x;
|
||||||
|
int oy = (int) y;
|
||||||
|
int oz = (int) z;
|
||||||
|
|
||||||
|
T closest = null;
|
||||||
|
double closestDistanceSq = Double.POSITIVE_INFINITY;
|
||||||
|
|
||||||
|
for (int cellX = ox - 1; cellX <= ox + 1; ++cellX) {
|
||||||
|
for (int cellY = oy - 1; cellY <= oy + 1; ++cellY) {
|
||||||
|
for (int cellZ = oz - 1; cellZ <= oz + 1; ++cellZ) {
|
||||||
|
|
||||||
|
long cellSeed = permute(cellZ ^ permute(cellY ^ permute(cellX ^ seed)));
|
||||||
|
|
||||||
|
int nodes = getNodeCount(cellSeed);
|
||||||
|
cellSeed = permute(cellSeed);
|
||||||
|
|
||||||
|
for (int i = 0; i < nodes; ++i) {
|
||||||
|
|
||||||
|
double nodeX = getDouble(cellSeed) + cellX;
|
||||||
|
cellSeed = permute(cellSeed);
|
||||||
|
|
||||||
|
double nodeY = getDouble(cellSeed) + cellY;
|
||||||
|
cellSeed = permute(cellSeed);
|
||||||
|
|
||||||
|
double nodeZ = getDouble(cellSeed) + cellZ;
|
||||||
|
cellSeed = permute(cellSeed);
|
||||||
|
|
||||||
|
T value = getValue(getDouble(cellSeed));
|
||||||
|
cellSeed = permute(cellSeed);
|
||||||
|
|
||||||
|
double distanceSq = (x - nodeX) * (x - nodeX) + (y - nodeY) * (y - nodeY)
|
||||||
|
+ (z - nodeZ) * (z - nodeZ);
|
||||||
|
if (distanceSq < closestDistanceSq) {
|
||||||
|
closestDistanceSq = distanceSq;
|
||||||
|
closest = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return closest;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
private T getValue(double target) {
|
||||||
|
int i;
|
||||||
|
|
||||||
|
for (i = 0; i < entries.length && target > entries[i].chance; ++i) {
|
||||||
|
target -= entries[i].chance;
|
||||||
|
}
|
||||||
|
|
||||||
|
return (T) entries[i].value;
|
||||||
|
}
|
||||||
|
|
||||||
|
private int getNodeCount(long seed) {
|
||||||
|
int uniform = ((int) seed) % 8;
|
||||||
|
|
||||||
|
switch (uniform) {
|
||||||
|
case 0:
|
||||||
|
case 1:
|
||||||
|
case 2:
|
||||||
|
case 3:
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
case 4:
|
||||||
|
case 5:
|
||||||
|
return 2;
|
||||||
|
|
||||||
|
case 6:
|
||||||
|
return 3;
|
||||||
|
|
||||||
|
default:
|
||||||
|
return 4;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -104,7 +104,7 @@ public class PlanetGenerator extends AbstractWorldGenerator<Boolean> {
|
|||||||
DefaultChunkData chunk = getWorldData().getChunk(chunkPos);
|
DefaultChunkData chunk = getWorldData().getChunk(chunkPos);
|
||||||
|
|
||||||
if (chunk == null) {
|
if (chunk == null) {
|
||||||
chunk = terrainGenerator.generateTerrain(chunkPos);
|
chunk = terrainGenerator.generateTerrain(getServer(), chunkPos);
|
||||||
getWorldData().addChunk(chunk);
|
getWorldData().addChunk(chunk);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -17,6 +17,8 @@
|
|||||||
*/
|
*/
|
||||||
package ru.windcorp.progressia.server.world.generation.planet;
|
package ru.windcorp.progressia.server.world.generation.planet;
|
||||||
|
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
import glm.vec._3.Vec3;
|
import glm.vec._3.Vec3;
|
||||||
import glm.vec._3.i.Vec3i;
|
import glm.vec._3.i.Vec3i;
|
||||||
import ru.windcorp.progressia.common.util.FloatRangeMap;
|
import ru.windcorp.progressia.common.util.FloatRangeMap;
|
||||||
@ -26,6 +28,9 @@ import ru.windcorp.progressia.common.world.Coordinates;
|
|||||||
import ru.windcorp.progressia.common.world.block.BlockData;
|
import ru.windcorp.progressia.common.world.block.BlockData;
|
||||||
import ru.windcorp.progressia.common.world.block.BlockDataRegistry;
|
import ru.windcorp.progressia.common.world.block.BlockDataRegistry;
|
||||||
import ru.windcorp.progressia.common.world.generic.GenericChunks;
|
import ru.windcorp.progressia.common.world.generic.GenericChunks;
|
||||||
|
import ru.windcorp.progressia.common.world.rels.AbsFace;
|
||||||
|
import ru.windcorp.progressia.server.Server;
|
||||||
|
import ru.windcorp.progressia.server.world.generation.surface.Surface;
|
||||||
import ru.windcorp.progressia.server.world.generation.surface.SurfaceFloatField;
|
import ru.windcorp.progressia.server.world.generation.surface.SurfaceFloatField;
|
||||||
import ru.windcorp.progressia.server.world.generation.surface.SurfaceTerrainGenerator;
|
import ru.windcorp.progressia.server.world.generation.surface.SurfaceTerrainGenerator;
|
||||||
import ru.windcorp.progressia.server.world.generation.surface.TerrainLayer;
|
import ru.windcorp.progressia.server.world.generation.surface.TerrainLayer;
|
||||||
@ -33,25 +38,38 @@ import ru.windcorp.progressia.server.world.generation.surface.TerrainLayer;
|
|||||||
class PlanetTerrainGenerator {
|
class PlanetTerrainGenerator {
|
||||||
|
|
||||||
private final PlanetGenerator parent;
|
private final PlanetGenerator parent;
|
||||||
private final SurfaceTerrainGenerator surfaceGenerator;
|
private final Map<AbsFace, SurfaceTerrainGenerator> surfaceGenerators;
|
||||||
|
|
||||||
public PlanetTerrainGenerator(PlanetGenerator generator, SurfaceFloatField heightMap, FloatRangeMap<TerrainLayer> layers) {
|
public PlanetTerrainGenerator(
|
||||||
|
PlanetGenerator generator,
|
||||||
|
SurfaceFloatField heightMap,
|
||||||
|
FloatRangeMap<TerrainLayer> layers
|
||||||
|
) {
|
||||||
this.parent = generator;
|
this.parent = generator;
|
||||||
|
|
||||||
|
int seaLevel = (int) parent.getPlanet().getRadius();
|
||||||
SurfaceFloatField adjustedHeightMap = (f, n, w) -> heightMap.get(f, n, w) + generator.getPlanet().getRadius();
|
SurfaceFloatField adjustedHeightMap = (f, n, w) -> heightMap.get(f, n, w) + generator.getPlanet().getRadius();
|
||||||
this.surfaceGenerator = new SurfaceTerrainGenerator(adjustedHeightMap, layers);
|
|
||||||
|
this.surfaceGenerators = AbsFace.mapToFaces(
|
||||||
|
face -> new SurfaceTerrainGenerator(
|
||||||
|
new Surface(face, seaLevel),
|
||||||
|
adjustedHeightMap,
|
||||||
|
layers
|
||||||
|
)
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
public PlanetGenerator getGenerator() {
|
public PlanetGenerator getGenerator() {
|
||||||
return parent;
|
return parent;
|
||||||
}
|
}
|
||||||
|
|
||||||
public DefaultChunkData generateTerrain(Vec3i chunkPos) {
|
public DefaultChunkData generateTerrain(Server server, Vec3i chunkPos) {
|
||||||
DefaultChunkData chunk = new DefaultChunkData(chunkPos, getGenerator().getWorldData());
|
DefaultChunkData chunk = new DefaultChunkData(chunkPos, getGenerator().getWorldData());
|
||||||
|
|
||||||
if (isOrdinaryChunk(chunkPos)) {
|
if (isOrdinaryChunk(chunkPos)) {
|
||||||
generateOrdinaryTerrain(chunk);
|
generateOrdinaryTerrain(server, chunk);
|
||||||
} else {
|
} else {
|
||||||
generateBorderTerrain(chunk);
|
generateBorderTerrain(server, chunk);
|
||||||
}
|
}
|
||||||
|
|
||||||
chunk.setGenerationHint(false);
|
chunk.setGenerationHint(false);
|
||||||
@ -64,11 +82,11 @@ class PlanetTerrainGenerator {
|
|||||||
return sorted.x != sorted.y;
|
return sorted.x != sorted.y;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void generateOrdinaryTerrain(DefaultChunkData chunk) {
|
private void generateOrdinaryTerrain(Server server, DefaultChunkData chunk) {
|
||||||
surfaceGenerator.generateTerrain(chunk);
|
surfaceGenerators.get(chunk.getUp()).generateTerrain(server, chunk);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void generateBorderTerrain(DefaultChunkData chunk) {
|
private void generateBorderTerrain(Server server, DefaultChunkData chunk) {
|
||||||
BlockData stone = BlockDataRegistry.getInstance().get("Test:Stone");
|
BlockData stone = BlockDataRegistry.getInstance().get("Test:Stone");
|
||||||
BlockData air = BlockDataRegistry.getInstance().get("Test:Air");
|
BlockData air = BlockDataRegistry.getInstance().get("Test:Air");
|
||||||
|
|
||||||
|
@ -17,18 +17,28 @@
|
|||||||
*/
|
*/
|
||||||
package ru.windcorp.progressia.server.world.generation.surface;
|
package ru.windcorp.progressia.server.world.generation.surface;
|
||||||
|
|
||||||
|
import java.util.Random;
|
||||||
|
|
||||||
|
import glm.Glm;
|
||||||
|
import glm.vec._3.i.Vec3i;
|
||||||
|
import ru.windcorp.progressia.common.util.CoordinatePacker;
|
||||||
|
import ru.windcorp.progressia.common.world.generic.ChunkGenericRO;
|
||||||
import ru.windcorp.progressia.common.world.rels.AbsFace;
|
import ru.windcorp.progressia.common.world.rels.AbsFace;
|
||||||
|
import ru.windcorp.progressia.server.Server;
|
||||||
|
import ru.windcorp.progressia.server.world.context.ServerTileContext;
|
||||||
|
import ru.windcorp.progressia.server.world.generation.surface.context.SurfaceContextImpl;
|
||||||
|
import ru.windcorp.progressia.server.world.generation.surface.context.SurfaceWorldContext;
|
||||||
|
|
||||||
public class Surface {
|
public class Surface {
|
||||||
|
|
||||||
private final AbsFace up;
|
private final AbsFace up;
|
||||||
private final int seaLevel;
|
private final int seaLevel;
|
||||||
|
|
||||||
public Surface(AbsFace up, int seaLevel) {
|
public Surface(AbsFace up, int seaLevel) {
|
||||||
this.up = up;
|
this.up = up;
|
||||||
this.seaLevel = seaLevel;
|
this.seaLevel = seaLevel;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return the up
|
* @return the up
|
||||||
*/
|
*/
|
||||||
@ -43,4 +53,27 @@ public class Surface {
|
|||||||
return seaLevel;
|
return seaLevel;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public SurfaceWorldContext createContext(Server server, ChunkGenericRO<?, ?, ?, ?, ?> chunk, long seed) {
|
||||||
|
|
||||||
|
Random random = new Random(CoordinatePacker.pack3IntsIntoLong(chunk.getPosition()) ^ seed);
|
||||||
|
|
||||||
|
SurfaceContextImpl context = new SurfaceContextImpl((ServerTileContext) server.createAbsoluteContext(), this);
|
||||||
|
context.setRandom(random);
|
||||||
|
|
||||||
|
Vec3i tmpA = new Vec3i();
|
||||||
|
Vec3i tmpB = new Vec3i();
|
||||||
|
|
||||||
|
chunk.getMinBIW(tmpA);
|
||||||
|
chunk.getMaxBIW(tmpB);
|
||||||
|
|
||||||
|
context.toContext(tmpA, tmpA);
|
||||||
|
context.toContext(tmpB, tmpB);
|
||||||
|
|
||||||
|
Glm.min(tmpA, tmpB, context.getMin());
|
||||||
|
Glm.max(tmpA, tmpB, context.getMax());
|
||||||
|
|
||||||
|
return context;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -19,15 +19,9 @@ package ru.windcorp.progressia.server.world.generation.surface;
|
|||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Random;
|
|
||||||
|
|
||||||
import glm.Glm;
|
|
||||||
import glm.vec._3.i.Vec3i;
|
|
||||||
import ru.windcorp.progressia.common.util.CoordinatePacker;
|
|
||||||
import ru.windcorp.progressia.common.world.DefaultChunkData;
|
import ru.windcorp.progressia.common.world.DefaultChunkData;
|
||||||
import ru.windcorp.progressia.server.Server;
|
import ru.windcorp.progressia.server.Server;
|
||||||
import ru.windcorp.progressia.server.world.context.ServerTileContext;
|
import ru.windcorp.progressia.server.world.generation.surface.context.SurfaceWorldContext;
|
||||||
import ru.windcorp.progressia.server.world.generation.surface.context.SurfaceContextImpl;
|
|
||||||
|
|
||||||
public class SurfaceFeatureGenerator {
|
public class SurfaceFeatureGenerator {
|
||||||
|
|
||||||
@ -48,23 +42,7 @@ public class SurfaceFeatureGenerator {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void generateFeatures(Server server, DefaultChunkData chunk) {
|
public void generateFeatures(Server server, DefaultChunkData chunk) {
|
||||||
|
SurfaceWorldContext context = surface.createContext(server, chunk, 0);
|
||||||
Random random = new Random(CoordinatePacker.pack3IntsIntoLong(chunk.getPosition()) /* ^ seed*/);
|
|
||||||
|
|
||||||
SurfaceContextImpl context = new SurfaceContextImpl((ServerTileContext) server.createAbsoluteContext(), surface);
|
|
||||||
context.setRandom(random);
|
|
||||||
|
|
||||||
Vec3i tmpA = new Vec3i();
|
|
||||||
Vec3i tmpB = new Vec3i();
|
|
||||||
|
|
||||||
chunk.getMinBIW(tmpA);
|
|
||||||
chunk.getMaxBIW(tmpB);
|
|
||||||
|
|
||||||
context.toContext(tmpA, tmpA);
|
|
||||||
context.toContext(tmpB, tmpB);
|
|
||||||
|
|
||||||
Glm.min(tmpA, tmpB, context.getMin());
|
|
||||||
Glm.max(tmpA, tmpB, context.getMax());
|
|
||||||
|
|
||||||
for (SurfaceFeature feature : features) {
|
for (SurfaceFeature feature : features) {
|
||||||
feature.process(context);
|
feature.process(context);
|
||||||
|
@ -17,60 +17,73 @@
|
|||||||
*/
|
*/
|
||||||
package ru.windcorp.progressia.server.world.generation.surface;
|
package ru.windcorp.progressia.server.world.generation.surface;
|
||||||
|
|
||||||
import java.util.Random;
|
|
||||||
|
|
||||||
import glm.vec._3.Vec3;
|
import glm.vec._3.Vec3;
|
||||||
import glm.vec._3.i.Vec3i;
|
import glm.vec._3.i.Vec3i;
|
||||||
import ru.windcorp.progressia.common.util.CoordinatePacker;
|
|
||||||
import ru.windcorp.progressia.common.util.FloatRangeMap;
|
import ru.windcorp.progressia.common.util.FloatRangeMap;
|
||||||
|
import ru.windcorp.progressia.common.util.Vectors;
|
||||||
import ru.windcorp.progressia.common.world.DefaultChunkData;
|
import ru.windcorp.progressia.common.world.DefaultChunkData;
|
||||||
import ru.windcorp.progressia.common.world.block.BlockData;
|
import ru.windcorp.progressia.common.world.block.BlockData;
|
||||||
import ru.windcorp.progressia.common.world.rels.AxisRotations;
|
import ru.windcorp.progressia.common.world.rels.AxisRotations;
|
||||||
|
import ru.windcorp.progressia.server.Server;
|
||||||
|
import ru.windcorp.progressia.server.world.generation.surface.context.SurfaceBlockContext;
|
||||||
|
import ru.windcorp.progressia.server.world.generation.surface.context.SurfaceWorldContext;
|
||||||
|
|
||||||
public class SurfaceTerrainGenerator {
|
public class SurfaceTerrainGenerator {
|
||||||
|
|
||||||
|
private final Surface surface;
|
||||||
|
|
||||||
private final SurfaceFloatField heightMap;
|
private final SurfaceFloatField heightMap;
|
||||||
private final FloatRangeMap<TerrainLayer> layers;
|
private final FloatRangeMap<TerrainLayer> layers;
|
||||||
|
|
||||||
public SurfaceTerrainGenerator(SurfaceFloatField heightMap, FloatRangeMap<TerrainLayer> layers) {
|
public SurfaceTerrainGenerator(Surface surface, SurfaceFloatField heightMap, FloatRangeMap<TerrainLayer> layers) {
|
||||||
|
this.surface = surface;
|
||||||
this.heightMap = heightMap;
|
this.heightMap = heightMap;
|
||||||
this.layers = layers;
|
this.layers = layers;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void generateTerrain(DefaultChunkData chunk) {
|
public void generateTerrain(Server server, DefaultChunkData chunk) {
|
||||||
|
|
||||||
Vec3i relBIC = new Vec3i();
|
Vec3i relBIC = new Vec3i();
|
||||||
|
|
||||||
Vec3 offset = new Vec3(chunk.getMinX(), chunk.getMinY(), chunk.getMinZ());
|
Vec3 offset = new Vec3(chunk.getMinX(), chunk.getMinY(), chunk.getMinZ());
|
||||||
AxisRotations.relativize(offset, chunk.getUp(), offset);
|
AxisRotations.relativize(offset, chunk.getUp(), offset);
|
||||||
offset.z -= DefaultChunkData.CHUNK_RADIUS - 0.5f;
|
|
||||||
|
|
||||||
Random random = new Random(CoordinatePacker.pack3IntsIntoLong(chunk.getPosition()) /* ^ seed*/);
|
SurfaceWorldContext context = surface.createContext(server, chunk, 0);
|
||||||
|
|
||||||
for (relBIC.x = 0; relBIC.x < DefaultChunkData.BLOCKS_PER_CHUNK; ++relBIC.x) {
|
for (relBIC.x = 0; relBIC.x < DefaultChunkData.BLOCKS_PER_CHUNK; ++relBIC.x) {
|
||||||
for (relBIC.y = 0; relBIC.y < DefaultChunkData.BLOCKS_PER_CHUNK; ++relBIC.y) {
|
for (relBIC.y = 0; relBIC.y < DefaultChunkData.BLOCKS_PER_CHUNK; ++relBIC.y) {
|
||||||
generateColumn(chunk, relBIC, offset, random);
|
generateColumn(chunk, relBIC, offset, context);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void generateColumn(DefaultChunkData chunk, Vec3i relBIC, Vec3 offset, Random random) {
|
public void generateColumn(DefaultChunkData chunk, Vec3i relBIC, Vec3 offset, SurfaceWorldContext context) {
|
||||||
|
|
||||||
float north = relBIC.x + offset.x;
|
int north = (int) (relBIC.x + offset.x);
|
||||||
float west = relBIC.y + offset.y;
|
int west = (int) (relBIC.y + offset.y);
|
||||||
|
|
||||||
float relSurface = heightMap.get(chunk.getUp(), north, west) - offset.z;
|
float relSurface = heightMap.get(chunk.getUp(), north, west) - offset.z + DefaultChunkData.CHUNK_RADIUS - 0.5f;
|
||||||
|
Vec3i location = Vectors.grab3i();
|
||||||
|
|
||||||
for (relBIC.z = 0; relBIC.z < DefaultChunkData.BLOCKS_PER_CHUNK; ++relBIC.z) {
|
for (relBIC.z = 0; relBIC.z < DefaultChunkData.BLOCKS_PER_CHUNK; ++relBIC.z) {
|
||||||
float depth = relSurface - relBIC.z;
|
float depth = relSurface - relBIC.z;
|
||||||
BlockData block = layers.get(depth).get(chunk.getUp(), north, west, depth, random);
|
int altitude = (int) (relBIC.z + offset.z);
|
||||||
|
|
||||||
|
location.set(north, west, altitude);
|
||||||
|
SurfaceBlockContext blockContext = context.push(location);
|
||||||
|
|
||||||
|
BlockData block = layers.get(depth).get(blockContext, depth);
|
||||||
|
|
||||||
|
blockContext.pop();
|
||||||
|
|
||||||
chunk.resolve(relBIC, relBIC);
|
chunk.resolve(relBIC, relBIC);
|
||||||
chunk.setBlock(relBIC, block, false);
|
chunk.setBlock(relBIC, block, false);
|
||||||
chunk.relativize(relBIC, relBIC);
|
chunk.relativize(relBIC, relBIC);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Vectors.release(location);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -17,14 +17,12 @@
|
|||||||
*/
|
*/
|
||||||
package ru.windcorp.progressia.server.world.generation.surface;
|
package ru.windcorp.progressia.server.world.generation.surface;
|
||||||
|
|
||||||
import java.util.Random;
|
|
||||||
|
|
||||||
import ru.windcorp.progressia.common.world.block.BlockData;
|
import ru.windcorp.progressia.common.world.block.BlockData;
|
||||||
import ru.windcorp.progressia.common.world.rels.AbsFace;
|
import ru.windcorp.progressia.server.world.generation.surface.context.SurfaceBlockContext;
|
||||||
|
|
||||||
@FunctionalInterface
|
@FunctionalInterface
|
||||||
public interface TerrainLayer {
|
public interface TerrainLayer {
|
||||||
|
|
||||||
BlockData get(AbsFace face, float north, float west, float depth, Random random);
|
BlockData get(SurfaceBlockContext context, float depth);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
126
src/main/java/ru/windcorp/progressia/test/Rocks.java
Normal file
126
src/main/java/ru/windcorp/progressia/test/Rocks.java
Normal file
@ -0,0 +1,126 @@
|
|||||||
|
/*
|
||||||
|
* Progressia
|
||||||
|
* Copyright (C) 2020-2021 Wind Corporation and contributors
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
package ru.windcorp.progressia.test;
|
||||||
|
|
||||||
|
import java.util.Collection;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.EnumMap;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
import com.google.common.collect.HashMultimap;
|
||||||
|
import com.google.common.collect.Multimap;
|
||||||
|
import com.google.common.collect.Multimaps;
|
||||||
|
|
||||||
|
import ru.windcorp.progressia.client.world.block.BlockRenderOpaqueCube;
|
||||||
|
import ru.windcorp.progressia.client.world.block.BlockRenderRegistry;
|
||||||
|
import ru.windcorp.progressia.common.world.block.BlockData;
|
||||||
|
import ru.windcorp.progressia.common.world.block.BlockDataRegistry;
|
||||||
|
import ru.windcorp.progressia.server.world.block.BlockLogic;
|
||||||
|
import ru.windcorp.progressia.server.world.block.BlockLogicRegistry;
|
||||||
|
|
||||||
|
public class Rocks {
|
||||||
|
|
||||||
|
public enum RockType {
|
||||||
|
IGNEOUS, METAMORPHIC, SEDIMENTARY;
|
||||||
|
}
|
||||||
|
|
||||||
|
public enum RockVariant {
|
||||||
|
|
||||||
|
MONOLITH("Monolith"),
|
||||||
|
CRACKED("Cracked"),
|
||||||
|
GRAVEL("Gravel"),
|
||||||
|
SAND("Sand");
|
||||||
|
|
||||||
|
private final String name;
|
||||||
|
|
||||||
|
private RockVariant(String name) {
|
||||||
|
this.name = name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getName() {
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class Rock {
|
||||||
|
|
||||||
|
private final String name;
|
||||||
|
private final RockType type;
|
||||||
|
|
||||||
|
private final Map<RockVariant, BlockData> blocks = new EnumMap<>(RockVariant.class);
|
||||||
|
|
||||||
|
public Rock(String name, RockType type) {
|
||||||
|
this.name = name;
|
||||||
|
this.type = type;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getName() {
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public RockType getType() {
|
||||||
|
return type;
|
||||||
|
}
|
||||||
|
|
||||||
|
public BlockData getBlock(RockVariant variant) {
|
||||||
|
return blocks.get(variant);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void register() {
|
||||||
|
for (RockVariant variant : RockVariant.values()) {
|
||||||
|
|
||||||
|
String fullName = name + variant.getName();
|
||||||
|
String id = "Test:" + fullName;
|
||||||
|
|
||||||
|
BlockData blockData = new BlockData(id);
|
||||||
|
blocks.put(variant, blockData);
|
||||||
|
BlockDataRegistry.getInstance().register(blockData);
|
||||||
|
BlockLogicRegistry.getInstance().register(new BlockLogic(id));
|
||||||
|
BlockRenderRegistry.getInstance()
|
||||||
|
.register(new BlockRenderOpaqueCube(id, BlockRenderRegistry.getBlockTexture(fullName)));
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
private final Map<String, Rock> rocksByName = Collections.synchronizedMap(new HashMap<>());
|
||||||
|
private final Multimap<RockType, Rock> rocksByType = Multimaps.synchronizedMultimap(HashMultimap.create());
|
||||||
|
|
||||||
|
public Rock create(RockType type, String name) {
|
||||||
|
Rock rock = new Rock(name, type);
|
||||||
|
rocksByName.put(name, rock);
|
||||||
|
rocksByType.put(type, rock);
|
||||||
|
return rock;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void registerAllRocks() {
|
||||||
|
getRocks().forEach(Rock::register);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Collection<Rock> getRocks() {
|
||||||
|
return rocksByName.values();
|
||||||
|
}
|
||||||
|
|
||||||
|
public Collection<Rock> getRocks(RockType type) {
|
||||||
|
return rocksByType.get(type);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -29,8 +29,6 @@ import java.util.Set;
|
|||||||
import java.util.function.Consumer;
|
import java.util.function.Consumer;
|
||||||
import org.lwjgl.glfw.GLFW;
|
import org.lwjgl.glfw.GLFW;
|
||||||
|
|
||||||
import com.google.common.collect.ImmutableList;
|
|
||||||
|
|
||||||
import glm.vec._3.i.Vec3i;
|
import glm.vec._3.i.Vec3i;
|
||||||
import ru.windcorp.progressia.client.ClientState;
|
import ru.windcorp.progressia.client.ClientState;
|
||||||
import ru.windcorp.progressia.client.audio.Sound;
|
import ru.windcorp.progressia.client.audio.Sound;
|
||||||
@ -59,6 +57,7 @@ import ru.windcorp.progressia.server.world.block.*;
|
|||||||
import ru.windcorp.progressia.server.world.entity.*;
|
import ru.windcorp.progressia.server.world.entity.*;
|
||||||
import ru.windcorp.progressia.server.world.generation.planet.PlanetGravityModel;
|
import ru.windcorp.progressia.server.world.generation.planet.PlanetGravityModel;
|
||||||
import ru.windcorp.progressia.server.world.tile.*;
|
import ru.windcorp.progressia.server.world.tile.*;
|
||||||
|
import ru.windcorp.progressia.test.Rocks.RockType;
|
||||||
import ru.windcorp.progressia.test.gen.TestGravityModel;
|
import ru.windcorp.progressia.test.gen.TestGravityModel;
|
||||||
|
|
||||||
public class TestContent {
|
public class TestContent {
|
||||||
@ -69,6 +68,8 @@ public class TestContent {
|
|||||||
|
|
||||||
public static final List<BlockData> PLACEABLE_BLOCKS = new ArrayList<>();
|
public static final List<BlockData> PLACEABLE_BLOCKS = new ArrayList<>();
|
||||||
public static final List<TileData> PLACEABLE_TILES = new ArrayList<>();
|
public static final List<TileData> PLACEABLE_TILES = new ArrayList<>();
|
||||||
|
|
||||||
|
public static final Rocks ROCKS = new Rocks();
|
||||||
|
|
||||||
public static void registerContent() {
|
public static void registerContent() {
|
||||||
registerWorldContent();
|
registerWorldContent();
|
||||||
@ -150,33 +151,16 @@ public class TestContent {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private static void registerRocks() {
|
private static void registerRocks() {
|
||||||
List<String> rockNames = ImmutableList.of(
|
|
||||||
"BlackGranite",
|
|
||||||
"Dolomite",
|
|
||||||
"Eclogite",
|
|
||||||
"Gabbro",
|
|
||||||
"Limestone",
|
|
||||||
"Marble",
|
|
||||||
"RedGranite"
|
|
||||||
);
|
|
||||||
|
|
||||||
List<String> rockVariants = ImmutableList.of(
|
ROCKS.create(RockType.IGNEOUS, "BlackGranite");
|
||||||
"Monolith",
|
ROCKS.create(RockType.IGNEOUS, "RedGranite");
|
||||||
"Cracked",
|
ROCKS.create(RockType.IGNEOUS, "Gabbro");
|
||||||
"Gravel",
|
ROCKS.create(RockType.METAMORPHIC, "Marble");
|
||||||
"Sand"
|
ROCKS.create(RockType.METAMORPHIC, "Eclogite");
|
||||||
);
|
ROCKS.create(RockType.SEDIMENTARY, "Limestone");
|
||||||
|
ROCKS.create(RockType.SEDIMENTARY, "Dolomite");
|
||||||
|
|
||||||
for (String name : rockNames) {
|
ROCKS.registerAllRocks();
|
||||||
for (String variant : rockVariants) {
|
|
||||||
String fullName = name + variant;
|
|
||||||
String id = "Test:" + fullName;
|
|
||||||
|
|
||||||
register(new BlockData(id));
|
|
||||||
register(new BlockRenderOpaqueCube(id, getBlockTexture(fullName)));
|
|
||||||
register(new BlockLogic(id));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void registerTiles() {
|
private static void registerTiles() {
|
||||||
|
57
src/main/java/ru/windcorp/progressia/test/gen/RockLayer.java
Normal file
57
src/main/java/ru/windcorp/progressia/test/gen/RockLayer.java
Normal file
@ -0,0 +1,57 @@
|
|||||||
|
/*
|
||||||
|
* Progressia
|
||||||
|
* Copyright (C) 2020-2021 Wind Corporation and contributors
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
package ru.windcorp.progressia.test.gen;
|
||||||
|
|
||||||
|
import ru.windcorp.progressia.common.util.noise.discrete.DiscreteNoise;
|
||||||
|
import ru.windcorp.progressia.common.world.block.BlockData;
|
||||||
|
import ru.windcorp.progressia.server.world.generation.surface.SurfaceFloatField;
|
||||||
|
import ru.windcorp.progressia.server.world.generation.surface.TerrainLayer;
|
||||||
|
import ru.windcorp.progressia.server.world.generation.surface.context.SurfaceBlockContext;
|
||||||
|
|
||||||
|
public class RockLayer implements TerrainLayer {
|
||||||
|
|
||||||
|
private final DiscreteNoise<TerrainLayer> strata;
|
||||||
|
private final SurfaceFloatField depthOffsets;
|
||||||
|
|
||||||
|
private final double horizontalScale = 200;
|
||||||
|
private final double verticalScale = 10;
|
||||||
|
private final double depthInfluense = 0.1;
|
||||||
|
|
||||||
|
public RockLayer(DiscreteNoise<TerrainLayer> strata, SurfaceFloatField depthOffsets) {
|
||||||
|
this.strata = strata;
|
||||||
|
this.depthOffsets = depthOffsets;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public BlockData get(SurfaceBlockContext context, float depth) {
|
||||||
|
|
||||||
|
double z = context.getLocation().z;
|
||||||
|
z -= depth * depthInfluense;
|
||||||
|
z += depthOffsets.get(context);
|
||||||
|
z /= verticalScale;
|
||||||
|
|
||||||
|
return strata
|
||||||
|
.get(
|
||||||
|
context.getLocation().x / horizontalScale,
|
||||||
|
context.getLocation().y / horizontalScale,
|
||||||
|
z
|
||||||
|
)
|
||||||
|
.get(context, depth);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -26,6 +26,7 @@ import java.util.function.Function;
|
|||||||
import ru.windcorp.progressia.common.Units;
|
import ru.windcorp.progressia.common.Units;
|
||||||
import ru.windcorp.progressia.common.util.ArrayFloatRangeMap;
|
import ru.windcorp.progressia.common.util.ArrayFloatRangeMap;
|
||||||
import ru.windcorp.progressia.common.util.FloatRangeMap;
|
import ru.windcorp.progressia.common.util.FloatRangeMap;
|
||||||
|
import ru.windcorp.progressia.common.util.noise.discrete.WorleyProceduralNoise;
|
||||||
import ru.windcorp.progressia.common.world.Coordinates;
|
import ru.windcorp.progressia.common.world.Coordinates;
|
||||||
import ru.windcorp.progressia.common.world.block.BlockData;
|
import ru.windcorp.progressia.common.world.block.BlockData;
|
||||||
import ru.windcorp.progressia.common.world.block.BlockDataRegistry;
|
import ru.windcorp.progressia.common.world.block.BlockDataRegistry;
|
||||||
@ -36,15 +37,19 @@ import ru.windcorp.progressia.server.world.generation.planet.PlanetGenerator;
|
|||||||
import ru.windcorp.progressia.server.world.generation.surface.SurfaceFeature;
|
import ru.windcorp.progressia.server.world.generation.surface.SurfaceFeature;
|
||||||
import ru.windcorp.progressia.server.world.generation.surface.SurfaceFloatField;
|
import ru.windcorp.progressia.server.world.generation.surface.SurfaceFloatField;
|
||||||
import ru.windcorp.progressia.server.world.generation.surface.TerrainLayer;
|
import ru.windcorp.progressia.server.world.generation.surface.TerrainLayer;
|
||||||
|
import ru.windcorp.progressia.test.Rocks.RockVariant;
|
||||||
|
import ru.windcorp.progressia.test.TestContent;
|
||||||
|
|
||||||
public class TestGenerationConfig {
|
public class TestGenerationConfig {
|
||||||
|
|
||||||
|
private static final long SEED = "No bugs please".hashCode();
|
||||||
|
|
||||||
private static final float PLANET_RADIUS = Units.get("0.5 km");
|
private static final float PLANET_RADIUS = Units.get("0.5 km");
|
||||||
private static final float SURFACE_GRAVITY = Units.get("9.8 m/s^2");
|
private static final float SURFACE_GRAVITY = Units.get("9.8 m/s^2");
|
||||||
private static final float CURVATURE = Units.get("100 m");
|
private static final float CURVATURE = Units.get("100 m");
|
||||||
private static final float INNER_RADIUS = Units.get("200 m");
|
private static final float INNER_RADIUS = Units.get("200 m");
|
||||||
|
|
||||||
private static final Fields FIELDS = new Fields("No bugs please".hashCode());
|
private static final Fields FIELDS = new Fields(SEED);
|
||||||
|
|
||||||
public static Function<Server, WorldGenerator> createGenerator() {
|
public static Function<Server, WorldGenerator> createGenerator() {
|
||||||
|
|
||||||
@ -68,31 +73,36 @@ public class TestGenerationConfig {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private static void registerTerrainLayers(FloatRangeMap<TerrainLayer> layers) {
|
private static void registerTerrainLayers(FloatRangeMap<TerrainLayer> layers) {
|
||||||
BlockData granite = BlockDataRegistry.getInstance().get("Test:RedGraniteMonolith");
|
|
||||||
BlockData graniteCracked = BlockDataRegistry.getInstance().get("Test:RedGraniteCracked");
|
|
||||||
BlockData graniteGravel = BlockDataRegistry.getInstance().get("Test:RedGraniteGravel");
|
|
||||||
|
|
||||||
BlockData dirt = BlockDataRegistry.getInstance().get("Test:Dirt");
|
BlockData dirt = BlockDataRegistry.getInstance().get("Test:Dirt");
|
||||||
BlockData air = BlockDataRegistry.getInstance().get("Test:Air");
|
BlockData air = BlockDataRegistry.getInstance().get("Test:Air");
|
||||||
|
|
||||||
SurfaceFloatField cliffs = FIELDS.get("Test:CliffSelector");
|
SurfaceFloatField cliffs = FIELDS.get("Test:CliffSelector");
|
||||||
|
|
||||||
layers.put(Float.NEGATIVE_INFINITY, 0, (f, n, w, d, r) -> air);
|
WorleyProceduralNoise.Builder<TerrainLayer> builder = WorleyProceduralNoise.builder();
|
||||||
layers.put(0, 4, (f, n, w, d, r) -> {
|
TestContent.ROCKS.getRocks().forEach(rock -> {
|
||||||
if (cliffs.get(f, n, w) > 0) {
|
builder.add((c, d) -> {
|
||||||
switch (r.nextInt(4)) {
|
if (c.getRandom().nextInt(3) == 0) {
|
||||||
case 0:
|
return rock.getBlock(RockVariant.CRACKED);
|
||||||
return granite;
|
} else {
|
||||||
case 1:
|
return rock.getBlock(RockVariant.MONOLITH);
|
||||||
return graniteCracked;
|
|
||||||
default:
|
|
||||||
return graniteGravel;
|
|
||||||
}
|
}
|
||||||
|
}, 1);
|
||||||
|
});
|
||||||
|
SurfaceFloatField rockDepthOffsets = FIELDS.register(
|
||||||
|
"Test:RockDepthOffsets",
|
||||||
|
() -> tweak(FIELDS.primitive(), 40, 5)
|
||||||
|
);
|
||||||
|
RockLayer rockLayer = new RockLayer(builder.build(SEED), rockDepthOffsets);
|
||||||
|
|
||||||
|
layers.put(Float.NEGATIVE_INFINITY, 0, (c, d) -> air);
|
||||||
|
layers.put(0, 4, (c, d) -> {
|
||||||
|
if (cliffs.get(c.getSurface().getUp(), c.getLocation().x, c.getLocation().y) > 0) {
|
||||||
|
return rockLayer.get(c, d);
|
||||||
} else {
|
} else {
|
||||||
return dirt;
|
return dirt;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
layers.put(4, Float.POSITIVE_INFINITY, (f, n, w, d, r) -> granite);
|
layers.put(4, Float.POSITIVE_INFINITY, rockLayer);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void registerFeatures(List<SurfaceFeature> features) {
|
private static void registerFeatures(List<SurfaceFeature> features) {
|
||||||
@ -101,7 +111,7 @@ public class TestGenerationConfig {
|
|||||||
"Test:Forestiness",
|
"Test:Forestiness",
|
||||||
() -> squash(scale(FIELDS.primitive(), 200), 5)
|
() -> squash(scale(FIELDS.primitive(), 200), 5)
|
||||||
);
|
);
|
||||||
|
|
||||||
SurfaceFloatField floweriness = FIELDS.register(
|
SurfaceFloatField floweriness = FIELDS.register(
|
||||||
"Test:Floweriness",
|
"Test:Floweriness",
|
||||||
f -> multiply(
|
f -> multiply(
|
||||||
|
Reference in New Issue
Block a user