diff --git a/gameserver/src/main/java/brainwine/gameserver/item/Item.java b/gameserver/src/main/java/brainwine/gameserver/item/Item.java index dceb67b..39170ea 100644 --- a/gameserver/src/main/java/brainwine/gameserver/item/Item.java +++ b/gameserver/src/main/java/brainwine/gameserver/item/Item.java @@ -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; } diff --git a/gameserver/src/main/java/brainwine/gameserver/zone/Zone.java b/gameserver/src/main/java/brainwine/gameserver/zone/Zone.java index 487a172..1402a1c 100644 --- a/gameserver/src/main/java/brainwine/gameserver/zone/Zone.java +++ b/gameserver/src/main/java/brainwine/gameserver/zone/Zone.java @@ -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 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); } diff --git a/gameserver/src/main/java/brainwine/gameserver/zone/ZoneData.java b/gameserver/src/main/java/brainwine/gameserver/zone/ZoneData.java index 4800423..8243559 100644 --- a/gameserver/src/main/java/brainwine/gameserver/zone/ZoneData.java +++ b/gameserver/src/main/java/brainwine/gameserver/zone/ZoneData.java @@ -10,17 +10,19 @@ public class ZoneData { private final int[] surface; private final int[] sunlight; + private final int[] depths; private final Collection 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 pendingSunlight, boolean[] chunksExplored) { + @ConstructorProperties({"surface", "sunlight", "depths", "pending_sunlight", "chunks_explored"}) + public ZoneData(int[] surface, int[] sunlight, int[] depths, Collection 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 getPendingSunlight() { return pendingSunlight; } diff --git a/gameserver/src/main/java/brainwine/gameserver/zone/ZoneManager.java b/gameserver/src/main/java/brainwine/gameserver/zone/ZoneManager.java index 48239fd..1f59408 100644 --- a/gameserver/src/main/java/brainwine/gameserver/zone/ZoneManager.java +++ b/gameserver/src/main/java/brainwine/gameserver/zone/ZoneManager.java @@ -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; } diff --git a/gameserver/src/main/java/brainwine/gameserver/zone/gen/CaveGenerator.java b/gameserver/src/main/java/brainwine/gameserver/zone/gen/CaveGenerator.java index 17dfa74..2dc4e45 100644 --- a/gameserver/src/main/java/brainwine/gameserver/zone/gen/CaveGenerator.java +++ b/gameserver/src/main/java/brainwine/gameserver/zone/gen/CaveGenerator.java @@ -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()); + } } } } diff --git a/gameserver/src/main/java/brainwine/gameserver/zone/gen/DecorGenerator.java b/gameserver/src/main/java/brainwine/gameserver/zone/gen/DecorGenerator.java index de01488..b70e8cc 100644 --- a/gameserver/src/main/java/brainwine/gameserver/zone/gen/DecorGenerator.java +++ b/gameserver/src/main/java/brainwine/gameserver/zone/gen/DecorGenerator.java @@ -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); } } diff --git a/gameserver/src/main/java/brainwine/gameserver/zone/gen/GeneratorContext.java b/gameserver/src/main/java/brainwine/gameserver/zone/gen/GeneratorContext.java index 156176e..bb333a3 100644 --- a/gameserver/src/main/java/brainwine/gameserver/zone/gen/GeneratorContext.java +++ b/gameserver/src/main/java/brainwine/gameserver/zone/gen/GeneratorContext.java @@ -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() { diff --git a/gameserver/src/main/java/brainwine/gameserver/zone/gen/TerrainGenerator.java b/gameserver/src/main/java/brainwine/gameserver/zone/gen/TerrainGenerator.java index 2c2c2f0..b379466 100644 --- a/gameserver/src/main/java/brainwine/gameserver/zone/gen/TerrainGenerator.java +++ b/gameserver/src/main/java/brainwine/gameserver/zone/gen/TerrainGenerator.java @@ -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); + } + } } }