Reintroduce earth layers to zone generator

This commit is contained in:
kuroppoi 2022-07-26 01:33:09 +02:00
parent bb990a2293
commit 9e907ce56d
8 changed files with 84 additions and 33 deletions

View file

@ -73,6 +73,9 @@ public class Item {
@JsonProperty("power")
private float power;
@JsonProperty("earthy")
private boolean earthy;
@JsonProperty("diggable")
private boolean diggable;
@ -233,6 +236,10 @@ public class Item {
return power;
}
public boolean isEarthy() {
return earthy;
}
public boolean isDiggable() {
return diggable;
}

View file

@ -60,6 +60,7 @@ public class Zone {
private final int numChunksHeight;
private int[] surface;
private int[] sunlight;
private int[] depths;
private boolean[] chunksExplored;
private float time = (float)Math.random(); // TODO temporary
private float temperature = 0;
@ -79,8 +80,10 @@ public class Zone {
this(documentId, config.getName(), config.getBiome(), config.getWidth(), config.getHeight());
surface = data.getSurface();
sunlight = data.getSunlight();
setDepths(data.getDepths());
// Ha ha silly me!
// TODO make nifty setters for these too, perhaps?
if(data.getPendingSunlight() != null) {
pendingSunlight.addAll(data.getPendingSunlight());
}
@ -98,6 +101,7 @@ public class Zone {
this.height = height;
numChunksWidth = width / chunkWidth;
numChunksHeight = height / chunkHeight;
depths = new int[] {(int)(height * 0.6), (int)(height * 0.75), (int)(height * 0.9)};
surface = new int[width];
sunlight = new int[width];
chunksExplored = new boolean[numChunksWidth * numChunksHeight];
@ -1015,6 +1019,22 @@ public class Zone {
return sunlight;
}
public void setDepths(int deep, int deeper, int deepest) {
depths[0] = deep;
depths[1] = deeper;
depths[2] = deepest;
}
public void setDepths(int[] depths) {
if(depths != null && depths.length == 3) {
setDepths(depths[0], depths[1], depths[2]);
}
}
public int[] getDepths() {
return depths;
}
public boolean exploreArea(int x, int y) {
if(!areCoordinatesInBounds(x, y)) {
return false;
@ -1122,20 +1142,15 @@ public class Zone {
List<Object> earth = new ArrayList<>();
if(player.isV3()) {
// For some reason this layer is completely broken for desert biomes on Unity clients.
// TODO should depth be unique per biome? Per zone even, perhaps?
if(biome != Biome.DESERT) {
earth.add(Arrays.asList(height * 0.9, "ground/earth-deepest"));
}
earth.add(Arrays.asList(height * 0.75, "ground/earth-deeper"));
earth.add(Arrays.asList(height * 0.6, "ground/earth-deep"));
earth.add(Arrays.asList(depths[2], "ground/earth-deepest"));
earth.add(Arrays.asList(depths[1], "ground/earth-deeper"));
earth.add(Arrays.asList(depths[0], "ground/earth-deep"));
depth.put("ground/earth", earth);
} else {
String key = biome == Biome.PLAIN ? "temperate" : biome.getId();
earth.add(Arrays.asList(height * 0.45, String.format("%s/earth-front-deep", key)));
earth.add(Arrays.asList(height * 0.7, String.format("%s/earth-front-deeper", key)));
earth.add(Arrays.asList(height * 0.9, String.format("%s/earth-front-deepest", key)));
earth.add(Arrays.asList(depths[0], String.format("%s/earth-front-deep", key)));
earth.add(Arrays.asList(depths[1], String.format("%s/earth-front-deeper", key)));
earth.add(Arrays.asList(depths[2], String.format("%s/earth-front-deepest", key)));
depth.put(String.format("%s/earth-front", key), earth);
}

View file

@ -10,17 +10,19 @@ public class ZoneData {
private final int[] surface;
private final int[] sunlight;
private final int[] depths;
private final Collection<Integer> pendingSunlight;
private final boolean[] chunksExplored;
public ZoneData(Zone zone) {
this(zone.getSurface(), zone.getSunlight(), zone.getPendingSunlight(), zone.getChunksExplored());
this(zone.getSurface(), zone.getSunlight(), zone.getDepths(), zone.getPendingSunlight(), zone.getChunksExplored());
}
@ConstructorProperties({"surface", "sunlight", "pending_sunlight", "chunks_explored"})
public ZoneData(int[] surface, int[] sunlight, Collection<Integer> pendingSunlight, boolean[] chunksExplored) {
@ConstructorProperties({"surface", "sunlight", "depths", "pending_sunlight", "chunks_explored"})
public ZoneData(int[] surface, int[] sunlight, int[] depths, Collection<Integer> pendingSunlight, boolean[] chunksExplored) {
this.surface = surface;
this.sunlight = sunlight;
this.depths = depths;
this.pendingSunlight = pendingSunlight;
this.chunksExplored = chunksExplored;
}
@ -33,6 +35,10 @@ public class ZoneData {
return sunlight;
}
public int[] getDepths() {
return depths;
}
public Collection<Integer> getPendingSunlight() {
return pendingSunlight;
}

View file

@ -118,7 +118,7 @@ public class ZoneManager {
chunksExplored[i] = unpacker.unpackBoolean();
}
ZoneData data = new ZoneData(surface, sunlight, pendingSunlight, chunksExplored);
ZoneData data = new ZoneData(surface, sunlight, null, pendingSunlight, chunksExplored);
mapper.writeValue(outputFile, data);
return data;
}

View file

@ -102,7 +102,12 @@ public class CaveGenerator implements GeneratorTask {
if(distance <= maxDistance) {
ctx.updateBlock(i, j, Layer.BASE, variant.getBaseItem());
ctx.updateBlock(i, j, Layer.FRONT, variant.getFrontItem());
if(variant == StoneVariant.DEFAULT) {
ctx.updateBlock(i, j, Layer.FRONT, ctx.getEarthLayer(j));
} else {
ctx.updateBlock(i, j, Layer.FRONT, variant.getFrontItem());
}
}
}
}

View file

@ -43,7 +43,7 @@ public class DecorGenerator implements GeneratorTask {
int y = ctx.getZone().getSurface()[x];
// ha ez
if(ctx.isEarth(x, y) && ctx.isEarth(x + 1, y) && ctx.nextDouble() <= surfaceFillerRate) {
if(ctx.isEarthy(x, y) && ctx.isEarthy(x + 1, y) && ctx.nextDouble() <= surfaceFillerRate) {
ctx.updateBlock(x, y - 1, Layer.FRONT, surfaceFillers[ctx.nextInt(surfaceFillers.length)]);
}
}
@ -125,7 +125,7 @@ public class DecorGenerator implements GeneratorTask {
for(int i = x; i < x + width; i++) {
for(int j = y; j < y + height; j++) {
if(!ctx.isEarth(i, j)) {
if(!ctx.isEarthy(i, j)) {
return;
}
}
@ -151,7 +151,7 @@ public class DecorGenerator implements GeneratorTask {
int y = ctx.nextInt(maxY - minY + 1) + minY;
BlockPosition current = new BlockPosition(x, y);
if(ctx.isEarth(x, y)) {
if(ctx.isEarthy(x, y)) {
ctx.updateBlock(x, y, Layer.FRONT, item, 0);
}
@ -162,7 +162,7 @@ public class DecorGenerator implements GeneratorTask {
int nY = current.getY() + ctx.nextInt(3) - 1;
current = new BlockPosition(nX, nY);
if(ctx.isEarth(nX, nY)) {
if(ctx.isEarthy(nX, nY)) {
ctx.updateBlock(nX, nY, Layer.FRONT, item, 1);
}
}

View file

@ -10,6 +10,7 @@ import java.util.Random;
import brainwine.gameserver.item.Item;
import brainwine.gameserver.item.Layer;
import brainwine.gameserver.prefab.Prefab;
import brainwine.gameserver.zone.Biome;
import brainwine.gameserver.zone.Chunk;
import brainwine.gameserver.zone.Zone;
import brainwine.gameserver.zone.gen.caves.Cave;
@ -96,13 +97,19 @@ public class GeneratorContext {
return zone.areCoordinatesInBounds(x, y) && y >= zone.getSurface()[x];
}
public boolean isEarth(int x, int y) {
public boolean isEarthy(int x, int y) {
if(!zone.areCoordinatesInBounds(x, y)) {
return false;
}
int item = zone.getBlock(x, y).getFrontItem().getId();
return item == 512;
return zone.getBlock(x, y).getFrontItem().isEarthy();
}
public int getEarthLayer(int y) {
int[] depths = zone.getDepths();
return zone.getBiome() == Biome.DEEP
? y >= depths[2] ? 598 : y >= depths[1] ? 597 : y >= depths[0] ? 596 : 595
: y >= depths[2] ? 518 : y >= depths[1] ? 517 : y >= depths[0] ? 516 : 512;
}
public int getWidth() {

View file

@ -15,19 +15,16 @@ public class TerrainGenerator implements GeneratorTask {
int width = ctx.getWidth();
int height = ctx.getHeight();
int surfaceLevel = height < 600 ? height / 3 : 200;
int lowestSurfaceLevel = 0;
boolean asteroids = type == TerrainType.ASTEROIDS;
// Determine surface first, then start placing blocks.
if(type == TerrainType.FILLED) {
for(int x = 0; x < width; x++) {
ctx.getZone().setSurface(x, 0);
for(int y = 0; y < height; y++) {
ctx.updateBlock(x, y, Layer.FRONT, 512);
ctx.updateBlock(x, y, Layer.BASE, 2);
}
}
} else {
PerlinNoise noise = new PerlinNoise(ctx.getSeed());
boolean asteroids = type == TerrainType.ASTEROIDS;
double minAmplitude = asteroids ? 10 : 40;
double maxAmplitude = asteroids ? 20 : 80;
double amplitude = ctx.nextDouble() * minAmplitude + (maxAmplitude - minAmplitude);
@ -36,12 +33,26 @@ public class TerrainGenerator implements GeneratorTask {
int surface = (int)(noise.perlinNoise(x * 0.01, 0.5, 7) * amplitude) + surfaceLevel;
ctx.getZone().setSurface(x, surface);
// Only generate a thin layer for asteroids, cave gen will take care of the rest.
for(int y = surface; y < (asteroids ? surface + 6 : height); y++) {
ctx.updateBlock(x, y, Layer.FRONT, 512);
ctx.updateBlock(x, y, Layer.BASE, 2);
if(surface > lowestSurfaceLevel) {
lowestSurfaceLevel = surface;
}
}
}
int heightBelowSurface = height - lowestSurfaceLevel;
ctx.getZone().setDepths(
(int)(heightBelowSurface * 0.25 + lowestSurfaceLevel),
(int)(heightBelowSurface * 0.5 + lowestSurfaceLevel),
(int)(heightBelowSurface * 0.75 + lowestSurfaceLevel));
for(int x = 0; x < width; x++) {
int surface = ctx.getZone().getSurface()[x];
// Only generate a thin layer for asteroids, cave gen will take care of the rest.
for(int y = surface; y < (asteroids ? surface + 6 : height); y++) {
ctx.updateBlock(x, y, Layer.FRONT, ctx.getEarthLayer(y));
ctx.updateBlock(x, y, Layer.BASE, 2);
}
}
}
}