diff --git a/src/main/java/ru/windcorp/progressia/server/Server.java b/src/main/java/ru/windcorp/progressia/server/Server.java index 2ad6171..e975b90 100644 --- a/src/main/java/ru/windcorp/progressia/server/Server.java +++ b/src/main/java/ru/windcorp/progressia/server/Server.java @@ -19,6 +19,7 @@ package ru.windcorp.progressia.server; import java.util.function.Consumer; +import java.util.function.Function; import org.apache.logging.log4j.LogManager; @@ -44,12 +45,11 @@ import ru.windcorp.progressia.server.world.context.ServerWorldContext; import ru.windcorp.progressia.server.world.context.impl.DefaultServerContext; import ru.windcorp.progressia.server.world.context.impl.ReportingServerContext; import ru.windcorp.progressia.server.world.context.impl.RotatingServerContext; +import ru.windcorp.progressia.server.world.generation.WorldGenerator; import ru.windcorp.progressia.server.world.tasks.WorldAccessor; import ru.windcorp.progressia.server.world.ticking.Change; import ru.windcorp.progressia.server.world.ticking.Evaluation; import ru.windcorp.progressia.server.world.ticking.TickerCoordinator; -import ru.windcorp.progressia.test.gen.planet.Planet; -import ru.windcorp.progressia.test.gen.planet.TestPlanetGenerator; public class Server { @@ -78,11 +78,11 @@ public class Server { private final TickingSettings tickingSettings = new TickingSettings(); - public Server(DefaultWorldData world) { + public Server(DefaultWorldData world, Function generatorCreator) { this.world = new DefaultWorldLogic( world, this, - new TestPlanetGenerator("Test:PlanetGenerator", this, new Planet(4, 9.8f, 16f, 16f)), + generatorCreator.apply(this), worldAccessor ); this.serverThread = new ServerThread(this); diff --git a/src/main/java/ru/windcorp/progressia/server/ServerState.java b/src/main/java/ru/windcorp/progressia/server/ServerState.java index de505f5..00aa901 100644 --- a/src/main/java/ru/windcorp/progressia/server/ServerState.java +++ b/src/main/java/ru/windcorp/progressia/server/ServerState.java @@ -19,6 +19,7 @@ package ru.windcorp.progressia.server; import ru.windcorp.progressia.common.world.DefaultWorldData; +import ru.windcorp.progressia.test.gen.TestGenerationConfig; public class ServerState { @@ -33,7 +34,7 @@ public class ServerState { } public static void startServer() { - Server server = new Server(new DefaultWorldData()); + Server server = new Server(new DefaultWorldData(), TestGenerationConfig.createGenerator()); setInstance(server); server.start(); } diff --git a/src/main/java/ru/windcorp/progressia/server/world/context/impl/RotatingServerContext.java b/src/main/java/ru/windcorp/progressia/server/world/context/impl/RotatingServerContext.java index c6459c4..a73d2b0 100644 --- a/src/main/java/ru/windcorp/progressia/server/world/context/impl/RotatingServerContext.java +++ b/src/main/java/ru/windcorp/progressia/server/world/context/impl/RotatingServerContext.java @@ -18,8 +18,8 @@ package ru.windcorp.progressia.server.world.context.impl; import glm.vec._3.i.Vec3i; +import ru.windcorp.progressia.common.world.generic.GenericChunks; import ru.windcorp.progressia.common.world.rels.AbsFace; -import ru.windcorp.progressia.common.world.rels.AxisRotations; import ru.windcorp.progressia.common.world.rels.RelFace; import ru.windcorp.progressia.server.world.context.ServerTileContext; @@ -38,12 +38,12 @@ public class RotatingServerContext extends TransformingServerContext { @Override protected void transform(Vec3i userLocation, Vec3i output) { - AxisRotations.resolve(userLocation, up, output); + GenericChunks.resolve(userLocation, up, output); } @Override protected void untransform(Vec3i parentLocation, Vec3i output) { - AxisRotations.relativize(parentLocation, up, output); + GenericChunks.relativize(parentLocation, up, output); } @Override diff --git a/src/main/java/ru/windcorp/progressia/test/gen/planet/Planet.java b/src/main/java/ru/windcorp/progressia/server/world/generation/planet/Planet.java similarity index 88% rename from src/main/java/ru/windcorp/progressia/test/gen/planet/Planet.java rename to src/main/java/ru/windcorp/progressia/server/world/generation/planet/Planet.java index 3637078..161e2c0 100644 --- a/src/main/java/ru/windcorp/progressia/test/gen/planet/Planet.java +++ b/src/main/java/ru/windcorp/progressia/server/world/generation/planet/Planet.java @@ -15,7 +15,7 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ -package ru.windcorp.progressia.test.gen.planet; +package ru.windcorp.progressia.server.world.generation.planet; import ru.windcorp.progressia.common.world.DefaultChunkData; @@ -23,7 +23,7 @@ public class Planet { private final int radiusInChunks; - private final TestPlanetGravityModel.Settings gravityModelSettings; + private final PlanetGravityModel.Settings gravityModelSettings; public Planet( int radiusInChunks, @@ -32,7 +32,7 @@ public class Planet { float innerGravityRadius ) { this.radiusInChunks = radiusInChunks; - this.gravityModelSettings = new TestPlanetGravityModel.Settings( + this.gravityModelSettings = new PlanetGravityModel.Settings( surfaceGravitationalAcceleration, curvature, innerGravityRadius @@ -82,7 +82,7 @@ public class Planet { /** * @return the gravityModelSettings */ - public TestPlanetGravityModel.Settings getGravityModelSettings() { + public PlanetGravityModel.Settings getGravityModelSettings() { return gravityModelSettings; } diff --git a/src/main/java/ru/windcorp/progressia/test/gen/planet/PlanetFeatureGenerator.java b/src/main/java/ru/windcorp/progressia/server/world/generation/planet/PlanetFeatureGenerator.java similarity index 70% rename from src/main/java/ru/windcorp/progressia/test/gen/planet/PlanetFeatureGenerator.java rename to src/main/java/ru/windcorp/progressia/server/world/generation/planet/PlanetFeatureGenerator.java index 38ed248..97e2424 100644 --- a/src/main/java/ru/windcorp/progressia/test/gen/planet/PlanetFeatureGenerator.java +++ b/src/main/java/ru/windcorp/progressia/server/world/generation/planet/PlanetFeatureGenerator.java @@ -15,10 +15,9 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ -package ru.windcorp.progressia.test.gen.planet; +package ru.windcorp.progressia.server.world.generation.planet; -import java.util.ArrayList; -import java.util.Collection; +import java.util.List; import java.util.Map; import glm.vec._3.i.Vec3i; @@ -26,26 +25,18 @@ import ru.windcorp.progressia.common.util.VectorUtil; import ru.windcorp.progressia.common.world.DefaultChunkData; import ru.windcorp.progressia.common.world.rels.AbsFace; import ru.windcorp.progressia.server.Server; -import ru.windcorp.progressia.test.TestBushFeature; -import ru.windcorp.progressia.test.TestGrassFeature; -import ru.windcorp.progressia.test.TestTreeFeature; -import ru.windcorp.progressia.test.gen.surface.Surface; -import ru.windcorp.progressia.test.gen.surface.SurfaceFeature; -import ru.windcorp.progressia.test.gen.surface.SurfaceFeatureGenerator; +import ru.windcorp.progressia.server.world.generation.surface.Surface; +import ru.windcorp.progressia.server.world.generation.surface.SurfaceFeature; +import ru.windcorp.progressia.server.world.generation.surface.SurfaceFeatureGenerator; public class PlanetFeatureGenerator { - private final TestPlanetGenerator parent; + private final PlanetGenerator parent; private final Map surfaceGenerators; - public PlanetFeatureGenerator(TestPlanetGenerator generator) { + public PlanetFeatureGenerator(PlanetGenerator generator, List features) { this.parent = generator; - - Collection features = new ArrayList<>(); - features.add(new TestBushFeature("Test:BushFeature")); - features.add(new TestTreeFeature("Test:TreeFeature")); - features.add(new TestGrassFeature("Test:GrassFeature")); int seaLevel = (int) parent.getPlanet().getRadius(); this.surfaceGenerators = AbsFace.mapToFaces(face -> new SurfaceFeatureGenerator( @@ -54,7 +45,7 @@ public class PlanetFeatureGenerator { )); } - public TestPlanetGenerator getGenerator() { + public PlanetGenerator getGenerator() { return parent; } diff --git a/src/main/java/ru/windcorp/progressia/test/gen/planet/TestPlanetGenerator.java b/src/main/java/ru/windcorp/progressia/server/world/generation/planet/PlanetGenerator.java similarity index 74% rename from src/main/java/ru/windcorp/progressia/test/gen/planet/TestPlanetGenerator.java rename to src/main/java/ru/windcorp/progressia/server/world/generation/planet/PlanetGenerator.java index 0846be7..1d31417 100644 --- a/src/main/java/ru/windcorp/progressia/test/gen/planet/TestPlanetGenerator.java +++ b/src/main/java/ru/windcorp/progressia/server/world/generation/planet/PlanetGenerator.java @@ -15,49 +15,61 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ -package ru.windcorp.progressia.test.gen.planet; +package ru.windcorp.progressia.server.world.generation.planet; import java.io.DataInputStream; import java.io.DataOutputStream; import java.io.IOException; +import java.util.List; import glm.vec._3.Vec3; import glm.vec._3.i.Vec3i; +import ru.windcorp.progressia.common.util.FloatRangeMap; import ru.windcorp.progressia.common.util.VectorUtil; import ru.windcorp.progressia.common.world.DefaultChunkData; import ru.windcorp.progressia.common.world.DecodingException; import ru.windcorp.progressia.server.Server; import ru.windcorp.progressia.server.world.generation.AbstractWorldGenerator; +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.TerrainLayer; + +public class PlanetGenerator extends AbstractWorldGenerator { -public class TestPlanetGenerator extends AbstractWorldGenerator { - private final Planet planet; - + private final PlanetTerrainGenerator terrainGenerator; private final PlanetFeatureGenerator featureGenerator; - public TestPlanetGenerator(String id, Server server, Planet planet) { + public PlanetGenerator( + String id, + Server server, + Planet planet, + SurfaceFloatField heightMap, + FloatRangeMap layers, + List features + ) { super(id, server, Boolean.class, "Test:PlanetGravityModel"); - + this.planet = planet; - - TestPlanetGravityModel model = (TestPlanetGravityModel) this.getGravityModel(); + + PlanetGravityModel model = (PlanetGravityModel) this.getGravityModel(); model.configure(planet.getGravityModelSettings()); - - this.terrainGenerator = new PlanetTerrainGenerator(this); - this.featureGenerator = new PlanetFeatureGenerator(this); + + this.terrainGenerator = new PlanetTerrainGenerator(this, heightMap, layers); + this.featureGenerator = new PlanetFeatureGenerator(this, features); } - + /** * @return the planet */ public Planet getPlanet() { return planet; } - + @Override public Vec3 suggestSpawnLocation() { - return new Vec3(7f, 7f, getPlanet().getRadius() + 10); + return new Vec3(407f, 1f, getPlanet().getRadius() + 10); } @Override @@ -79,14 +91,14 @@ public class TestPlanetGenerator extends AbstractWorldGenerator { public DefaultChunkData generate(Vec3i chunkPos) { VectorUtil.iterateCuboidAround(chunkPos, 3, r -> conjureTerrain(r)); DefaultChunkData chunk = getWorldData().getChunk(chunkPos); - + if (!isChunkReady(chunk.getGenerationHint())) { featureGenerator.generateFeatures(getServer(), chunk); } - + return chunk; } - + private void conjureTerrain(Vec3i chunkPos) { getServer().getLoadManager().getChunkManager().loadChunk(chunkPos); DefaultChunkData chunk = getWorldData().getChunk(chunkPos); diff --git a/src/main/java/ru/windcorp/progressia/test/gen/planet/TestPlanetGravityModel.java b/src/main/java/ru/windcorp/progressia/server/world/generation/planet/PlanetGravityModel.java similarity index 94% rename from src/main/java/ru/windcorp/progressia/test/gen/planet/TestPlanetGravityModel.java rename to src/main/java/ru/windcorp/progressia/server/world/generation/planet/PlanetGravityModel.java index a7fb334..e2545b5 100644 --- a/src/main/java/ru/windcorp/progressia/test/gen/planet/TestPlanetGravityModel.java +++ b/src/main/java/ru/windcorp/progressia/server/world/generation/planet/PlanetGravityModel.java @@ -15,7 +15,7 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ -package ru.windcorp.progressia.test.gen.planet; +package ru.windcorp.progressia.server.world.generation.planet; import glm.vec._3.Vec3; import glm.vec._3.i.Vec3i; @@ -30,7 +30,7 @@ import java.io.DataInput; import java.io.DataOutput; import java.io.IOException; -public class TestPlanetGravityModel extends GravityModel { +public class PlanetGravityModel extends GravityModel { public static class Settings { public float surfaceGravitationalAcceleration; @@ -66,7 +66,7 @@ public class TestPlanetGravityModel extends GravityModel { private Settings settings = new Settings(); - public TestPlanetGravityModel(String id) { + public PlanetGravityModel(String id) { super(id); } @@ -90,7 +90,6 @@ public class TestPlanetGravityModel extends GravityModel { protected void doGetGravity(Vec3 pos, Vec3 output) { float r = getInnerRadius(); float c = getCurvature(); - float g = getSurfaceGravitationalAcceleration(); // Change to a CS where (0;0;0) is the center of the center chunk float px = pos.x - DefaultChunkData.CHUNK_RADIUS + 0.5f; @@ -142,14 +141,14 @@ public class TestPlanetGravityModel extends GravityModel { assert output.dot(output) == 1 : "maxAbs - midAbs = " + maxAbs + " - " + midAbs + " > " + c + " yet l*l != 1"; } - output.mul(-g); + output.mul(-getSurfaceGravitationalAcceleration()); } private void computeEdgeGravity(float lx, float ly, float lz, float rx, float ry, float rz, Vec3 output) { // da math is gud, no worry // - Javapony - float r = getInnerRadius(); + float c = getCurvature(); if (lx == 0) rx = 0; if (ly == 0) ry = 0; @@ -159,10 +158,10 @@ public class TestPlanetGravityModel extends GravityModel { float rSquared = rx*rx + ry*ry + rz*rz; float distanceAlongEdge = scalarProduct - (float) sqrt( - scalarProduct*scalarProduct - rSquared + r*r + scalarProduct*scalarProduct - rSquared + c*c ); - output.set(lx, ly, lz).mul(-distanceAlongEdge).add(rx, ry, rz).div(r); + output.set(lx, ly, lz).mul(-distanceAlongEdge).add(rx, ry, rz).div(c); final float f = (float) sqrt(3.0/2); diff --git a/src/main/java/ru/windcorp/progressia/test/gen/planet/PlanetTerrainGenerator.java b/src/main/java/ru/windcorp/progressia/server/world/generation/planet/PlanetTerrainGenerator.java similarity index 67% rename from src/main/java/ru/windcorp/progressia/test/gen/planet/PlanetTerrainGenerator.java rename to src/main/java/ru/windcorp/progressia/server/world/generation/planet/PlanetTerrainGenerator.java index 227187d..ab081db 100644 --- a/src/main/java/ru/windcorp/progressia/test/gen/planet/PlanetTerrainGenerator.java +++ b/src/main/java/ru/windcorp/progressia/server/world/generation/planet/PlanetTerrainGenerator.java @@ -15,11 +15,10 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ -package ru.windcorp.progressia.test.gen.planet; +package ru.windcorp.progressia.server.world.generation.planet; import glm.vec._3.Vec3; import glm.vec._3.i.Vec3i; -import ru.windcorp.progressia.common.util.ArrayFloatRangeMap; import ru.windcorp.progressia.common.util.FloatRangeMap; import ru.windcorp.progressia.common.util.VectorUtil; import ru.windcorp.progressia.common.world.DefaultChunkData; @@ -27,37 +26,22 @@ import ru.windcorp.progressia.common.world.Coordinates; import ru.windcorp.progressia.common.world.block.BlockData; import ru.windcorp.progressia.common.world.block.BlockDataRegistry; import ru.windcorp.progressia.common.world.generic.GenericChunks; -import ru.windcorp.progressia.test.gen.TerrainLayer; -import ru.windcorp.progressia.test.gen.surface.SurfaceFloatField; -import ru.windcorp.progressia.test.gen.surface.SurfaceTerrainGenerator; +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.TerrainLayer; class PlanetTerrainGenerator { - private final TestPlanetGenerator parent; + private final PlanetGenerator parent; private final SurfaceTerrainGenerator surfaceGenerator; - public PlanetTerrainGenerator(TestPlanetGenerator generator) { + public PlanetTerrainGenerator(PlanetGenerator generator, SurfaceFloatField heightMap, FloatRangeMap layers) { this.parent = generator; - - SurfaceFloatField heightMap = new TestHeightMap( - generator.getPlanet().getRadius() - DefaultChunkData.BLOCKS_PER_CHUNK, - generator.getPlanet().getRadius() / 4, - 5, - 6 - ); - - FloatRangeMap layers = new ArrayFloatRangeMap<>(); - BlockData granite = BlockDataRegistry.getInstance().get("Test:GraniteMonolith"); - BlockData dirt = BlockDataRegistry.getInstance().get("Test:Dirt"); - BlockData air = BlockDataRegistry.getInstance().get("Test:Air"); - layers.put(Float.NEGATIVE_INFINITY, 0, (n, w, d, r, c) -> air); - layers.put(0, 4, (n, w, d, r, c) -> dirt); - layers.put(4, Float.POSITIVE_INFINITY, (n, w, d, r, c) -> granite); - - this.surfaceGenerator = new SurfaceTerrainGenerator((f, n, w) -> heightMap.get(f, n, w) + generator.getPlanet().getRadius(), layers); + SurfaceFloatField adjustedHeightMap = (f, n, w) -> heightMap.get(f, n, w) + generator.getPlanet().getRadius(); + this.surfaceGenerator = new SurfaceTerrainGenerator(adjustedHeightMap, layers); } - public TestPlanetGenerator getGenerator() { + public PlanetGenerator getGenerator() { return parent; } @@ -69,7 +53,7 @@ class PlanetTerrainGenerator { } else { generateBorderTerrain(chunk); } - + chunk.setGenerationHint(false); return chunk; @@ -87,24 +71,24 @@ class PlanetTerrainGenerator { private void generateBorderTerrain(DefaultChunkData chunk) { BlockData stone = BlockDataRegistry.getInstance().get("Test:Stone"); BlockData air = BlockDataRegistry.getInstance().get("Test:Air"); - + float radius = parent.getPlanet().getRadius(); Vec3 biw = new Vec3(); - + GenericChunks.forEachBiC(bic -> { - + biw.set( Coordinates.getInWorld(chunk.getX(), bic.x), Coordinates.getInWorld(chunk.getY(), bic.y), Coordinates.getInWorld(chunk.getZ(), bic.z) ); - + biw.sub(DefaultChunkData.CHUNK_RADIUS - 0.5f); VectorUtil.sortAfterAbs(biw, biw); - + chunk.setBlock(bic, biw.x <= radius ? stone : air, false); - + }); } diff --git a/src/main/java/ru/windcorp/progressia/test/gen/surface/Surface.java b/src/main/java/ru/windcorp/progressia/server/world/generation/surface/Surface.java similarity index 94% rename from src/main/java/ru/windcorp/progressia/test/gen/surface/Surface.java rename to src/main/java/ru/windcorp/progressia/server/world/generation/surface/Surface.java index 0baa6f0..296e3eb 100644 --- a/src/main/java/ru/windcorp/progressia/test/gen/surface/Surface.java +++ b/src/main/java/ru/windcorp/progressia/server/world/generation/surface/Surface.java @@ -15,7 +15,7 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ -package ru.windcorp.progressia.test.gen.surface; +package ru.windcorp.progressia.server.world.generation.surface; import ru.windcorp.progressia.common.world.rels.AbsFace; diff --git a/src/main/java/ru/windcorp/progressia/test/gen/surface/SurfaceFeature.java b/src/main/java/ru/windcorp/progressia/server/world/generation/surface/SurfaceFeature.java similarity index 60% rename from src/main/java/ru/windcorp/progressia/test/gen/surface/SurfaceFeature.java rename to src/main/java/ru/windcorp/progressia/server/world/generation/surface/SurfaceFeature.java index e4bb250..8430168 100644 --- a/src/main/java/ru/windcorp/progressia/test/gen/surface/SurfaceFeature.java +++ b/src/main/java/ru/windcorp/progressia/server/world/generation/surface/SurfaceFeature.java @@ -15,10 +15,13 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ -package ru.windcorp.progressia.test.gen.surface; +package ru.windcorp.progressia.server.world.generation.surface; + +import java.util.List; import ru.windcorp.progressia.common.util.namespaces.Namespaced; -import ru.windcorp.progressia.test.gen.surface.context.SurfaceWorldContext; +import ru.windcorp.progressia.server.world.context.ServerContext; +import ru.windcorp.progressia.server.world.generation.surface.context.SurfaceWorldContext; public abstract class SurfaceFeature extends Namespaced { @@ -27,5 +30,17 @@ public abstract class SurfaceFeature extends Namespaced { } public abstract void process(SurfaceWorldContext context); + + protected static double randomDouble(ServerContext context, double from, double to) { + return from + (to - from) * context.getRandom().nextDouble(); + } + + protected static double stretch(double t, double from, double to) { + return from + (to - from) * t; + } + + protected static T pickRandom(ServerContext context, List from) { + return from.get(context.getRandom().nextInt(from.size())); + } } diff --git a/src/main/java/ru/windcorp/progressia/test/gen/surface/SurfaceFeatureGenerator.java b/src/main/java/ru/windcorp/progressia/server/world/generation/surface/SurfaceFeatureGenerator.java similarity index 86% rename from src/main/java/ru/windcorp/progressia/test/gen/surface/SurfaceFeatureGenerator.java rename to src/main/java/ru/windcorp/progressia/server/world/generation/surface/SurfaceFeatureGenerator.java index aafd0ea..abfbcb3 100644 --- a/src/main/java/ru/windcorp/progressia/test/gen/surface/SurfaceFeatureGenerator.java +++ b/src/main/java/ru/windcorp/progressia/server/world/generation/surface/SurfaceFeatureGenerator.java @@ -15,10 +15,10 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ -package ru.windcorp.progressia.test.gen.surface; +package ru.windcorp.progressia.server.world.generation.surface; import java.util.ArrayList; -import java.util.Collection; +import java.util.List; import java.util.Random; import glm.Glm; @@ -27,15 +27,15 @@ import ru.windcorp.progressia.common.util.CoordinatePacker; import ru.windcorp.progressia.common.world.DefaultChunkData; import ru.windcorp.progressia.server.Server; import ru.windcorp.progressia.server.world.context.ServerTileContext; -import ru.windcorp.progressia.test.gen.surface.context.SurfaceContextImpl; +import ru.windcorp.progressia.server.world.generation.surface.context.SurfaceContextImpl; public class SurfaceFeatureGenerator { private final Surface surface; - private final Collection features; // TODO make ordered + private final List features; - public SurfaceFeatureGenerator(Surface surface, Collection features) { + public SurfaceFeatureGenerator(Surface surface, List features) { this.surface = surface; this.features = new ArrayList<>(features); } diff --git a/src/main/java/ru/windcorp/progressia/test/gen/surface/SurfaceFloatField.java b/src/main/java/ru/windcorp/progressia/server/world/generation/surface/SurfaceFloatField.java similarity index 68% rename from src/main/java/ru/windcorp/progressia/test/gen/surface/SurfaceFloatField.java rename to src/main/java/ru/windcorp/progressia/server/world/generation/surface/SurfaceFloatField.java index 4b368d4..81506f1 100644 --- a/src/main/java/ru/windcorp/progressia/test/gen/surface/SurfaceFloatField.java +++ b/src/main/java/ru/windcorp/progressia/server/world/generation/surface/SurfaceFloatField.java @@ -15,13 +15,20 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ -package ru.windcorp.progressia.test.gen.surface; +package ru.windcorp.progressia.server.world.generation.surface; +import glm.vec._3.i.Vec3i; import ru.windcorp.progressia.common.world.rels.AbsFace; +import ru.windcorp.progressia.server.world.generation.surface.context.SurfaceBlockContext; @FunctionalInterface public interface SurfaceFloatField { - float get(AbsFace face, float north, float west); + float get(AbsFace face, float x, float y); + + default float get(SurfaceBlockContext context) { + Vec3i location = context.getLocation(); + return get(context.getSurface().getUp(), location.x, location.y); + } } diff --git a/src/main/java/ru/windcorp/progressia/test/gen/surface/SurfaceTerrainGenerator.java b/src/main/java/ru/windcorp/progressia/server/world/generation/surface/SurfaceTerrainGenerator.java similarity index 91% rename from src/main/java/ru/windcorp/progressia/test/gen/surface/SurfaceTerrainGenerator.java rename to src/main/java/ru/windcorp/progressia/server/world/generation/surface/SurfaceTerrainGenerator.java index ec93d58..a3511bd 100644 --- a/src/main/java/ru/windcorp/progressia/test/gen/surface/SurfaceTerrainGenerator.java +++ b/src/main/java/ru/windcorp/progressia/server/world/generation/surface/SurfaceTerrainGenerator.java @@ -15,7 +15,7 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ -package ru.windcorp.progressia.test.gen.surface; +package ru.windcorp.progressia.server.world.generation.surface; import java.util.Random; @@ -26,7 +26,6 @@ import ru.windcorp.progressia.common.util.FloatRangeMap; import ru.windcorp.progressia.common.world.DefaultChunkData; import ru.windcorp.progressia.common.world.block.BlockData; import ru.windcorp.progressia.common.world.rels.AxisRotations; -import ru.windcorp.progressia.test.gen.TerrainLayer; public class SurfaceTerrainGenerator { @@ -44,7 +43,7 @@ public class SurfaceTerrainGenerator { Vec3 offset = new Vec3(chunk.getMinX(), chunk.getMinY(), chunk.getMinZ()); AxisRotations.relativize(offset, chunk.getUp(), offset); - offset.sub(DefaultChunkData.CHUNK_RADIUS - 0.5f); + offset.z -= DefaultChunkData.CHUNK_RADIUS - 0.5f; Random random = new Random(CoordinatePacker.pack3IntsIntoLong(chunk.getPosition()) /* ^ seed*/); @@ -65,7 +64,7 @@ public class SurfaceTerrainGenerator { for (relBIC.z = 0; relBIC.z < DefaultChunkData.BLOCKS_PER_CHUNK; ++relBIC.z) { float depth = relSurface - relBIC.z; - BlockData block = layers.get(depth).get(north, west, depth, random, chunk); + BlockData block = layers.get(depth).get(chunk.getUp(), north, west, depth, random); chunk.resolve(relBIC, relBIC); chunk.setBlock(relBIC, block, false); diff --git a/src/main/java/ru/windcorp/progressia/test/gen/surface/SurfaceTopLayerFeature.java b/src/main/java/ru/windcorp/progressia/server/world/generation/surface/SurfaceTopLayerFeature.java similarity index 86% rename from src/main/java/ru/windcorp/progressia/test/gen/surface/SurfaceTopLayerFeature.java rename to src/main/java/ru/windcorp/progressia/server/world/generation/surface/SurfaceTopLayerFeature.java index 4981dff..d96d68b 100644 --- a/src/main/java/ru/windcorp/progressia/test/gen/surface/SurfaceTopLayerFeature.java +++ b/src/main/java/ru/windcorp/progressia/server/world/generation/surface/SurfaceTopLayerFeature.java @@ -15,11 +15,11 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ -package ru.windcorp.progressia.test.gen.surface; +package ru.windcorp.progressia.server.world.generation.surface; import glm.vec._3.i.Vec3i; -import ru.windcorp.progressia.test.gen.surface.context.SurfaceBlockContext; -import ru.windcorp.progressia.test.gen.surface.context.SurfaceWorldContext; +import ru.windcorp.progressia.server.world.generation.surface.context.SurfaceBlockContext; +import ru.windcorp.progressia.server.world.generation.surface.context.SurfaceWorldContext; public abstract class SurfaceTopLayerFeature extends SurfaceFeature { diff --git a/src/main/java/ru/windcorp/progressia/test/gen/TerrainLayer.java b/src/main/java/ru/windcorp/progressia/server/world/generation/surface/TerrainLayer.java similarity index 81% rename from src/main/java/ru/windcorp/progressia/test/gen/TerrainLayer.java rename to src/main/java/ru/windcorp/progressia/server/world/generation/surface/TerrainLayer.java index 21c1809..7af46fa 100644 --- a/src/main/java/ru/windcorp/progressia/test/gen/TerrainLayer.java +++ b/src/main/java/ru/windcorp/progressia/server/world/generation/surface/TerrainLayer.java @@ -15,16 +15,16 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ -package ru.windcorp.progressia.test.gen; +package ru.windcorp.progressia.server.world.generation.surface; import java.util.Random; -import ru.windcorp.progressia.common.world.DefaultChunkData; import ru.windcorp.progressia.common.world.block.BlockData; +import ru.windcorp.progressia.common.world.rels.AbsFace; @FunctionalInterface public interface TerrainLayer { - BlockData get(float north, float west, float depth, Random random, DefaultChunkData chunk); + BlockData get(AbsFace face, float north, float west, float depth, Random random); } diff --git a/src/main/java/ru/windcorp/progressia/test/gen/surface/context/SurfaceBlockContext.java b/src/main/java/ru/windcorp/progressia/server/world/generation/surface/context/SurfaceBlockContext.java similarity index 97% rename from src/main/java/ru/windcorp/progressia/test/gen/surface/context/SurfaceBlockContext.java rename to src/main/java/ru/windcorp/progressia/server/world/generation/surface/context/SurfaceBlockContext.java index be3c285..64531fb 100644 --- a/src/main/java/ru/windcorp/progressia/test/gen/surface/context/SurfaceBlockContext.java +++ b/src/main/java/ru/windcorp/progressia/server/world/generation/surface/context/SurfaceBlockContext.java @@ -15,7 +15,7 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ -package ru.windcorp.progressia.test.gen.surface.context; +package ru.windcorp.progressia.server.world.generation.surface.context; import glm.vec._3.i.Vec3i; import ru.windcorp.progressia.common.world.rels.RelFace; diff --git a/src/main/java/ru/windcorp/progressia/test/gen/surface/context/SurfaceContext.java b/src/main/java/ru/windcorp/progressia/server/world/generation/surface/context/SurfaceContext.java similarity index 95% rename from src/main/java/ru/windcorp/progressia/test/gen/surface/context/SurfaceContext.java rename to src/main/java/ru/windcorp/progressia/server/world/generation/surface/context/SurfaceContext.java index b0b1aca..a69d60b 100644 --- a/src/main/java/ru/windcorp/progressia/test/gen/surface/context/SurfaceContext.java +++ b/src/main/java/ru/windcorp/progressia/server/world/generation/surface/context/SurfaceContext.java @@ -15,13 +15,13 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ -package ru.windcorp.progressia.test.gen.surface.context; +package ru.windcorp.progressia.server.world.generation.surface.context; import java.util.function.Consumer; import glm.vec._3.i.Vec3i; import ru.windcorp.progressia.common.util.VectorUtil; -import ru.windcorp.progressia.test.gen.surface.Surface; +import ru.windcorp.progressia.server.world.generation.surface.Surface; public interface SurfaceContext { diff --git a/src/main/java/ru/windcorp/progressia/test/gen/surface/context/SurfaceContextImpl.java b/src/main/java/ru/windcorp/progressia/server/world/generation/surface/context/SurfaceContextImpl.java similarity index 94% rename from src/main/java/ru/windcorp/progressia/test/gen/surface/context/SurfaceContextImpl.java rename to src/main/java/ru/windcorp/progressia/server/world/generation/surface/context/SurfaceContextImpl.java index 307330e..6050c49 100644 --- a/src/main/java/ru/windcorp/progressia/test/gen/surface/context/SurfaceContextImpl.java +++ b/src/main/java/ru/windcorp/progressia/server/world/generation/surface/context/SurfaceContextImpl.java @@ -15,7 +15,7 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ -package ru.windcorp.progressia.test.gen.surface.context; +package ru.windcorp.progressia.server.world.generation.surface.context; import java.util.Random; @@ -23,7 +23,7 @@ import glm.vec._3.i.Vec3i; import ru.windcorp.progressia.common.world.rels.RelFace; import ru.windcorp.progressia.server.world.context.ServerTileContext; import ru.windcorp.progressia.server.world.context.impl.RotatingServerContext; -import ru.windcorp.progressia.test.gen.surface.Surface; +import ru.windcorp.progressia.server.world.generation.surface.Surface; public class SurfaceContextImpl extends RotatingServerContext implements SurfaceTileContext { diff --git a/src/main/java/ru/windcorp/progressia/test/gen/surface/context/SurfaceContextImplLogic.java b/src/main/java/ru/windcorp/progressia/server/world/generation/surface/context/SurfaceContextImplLogic.java similarity index 92% rename from src/main/java/ru/windcorp/progressia/test/gen/surface/context/SurfaceContextImplLogic.java rename to src/main/java/ru/windcorp/progressia/server/world/generation/surface/context/SurfaceContextImplLogic.java index b8f45df..cbf9b88 100644 --- a/src/main/java/ru/windcorp/progressia/test/gen/surface/context/SurfaceContextImplLogic.java +++ b/src/main/java/ru/windcorp/progressia/server/world/generation/surface/context/SurfaceContextImplLogic.java @@ -15,12 +15,12 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ -package ru.windcorp.progressia.test.gen.surface.context; +package ru.windcorp.progressia.server.world.generation.surface.context; import glm.vec._3.i.Vec3i; import ru.windcorp.progressia.common.world.rels.RelFace; import ru.windcorp.progressia.server.world.context.impl.DefaultServerContextLogic; -import ru.windcorp.progressia.test.gen.surface.Surface; +import ru.windcorp.progressia.server.world.generation.surface.Surface; public class SurfaceContextImplLogic extends DefaultServerContextLogic implements SurfaceTileContext.Logic { diff --git a/src/main/java/ru/windcorp/progressia/test/gen/surface/context/SurfaceTileContext.java b/src/main/java/ru/windcorp/progressia/server/world/generation/surface/context/SurfaceTileContext.java similarity index 95% rename from src/main/java/ru/windcorp/progressia/test/gen/surface/context/SurfaceTileContext.java rename to src/main/java/ru/windcorp/progressia/server/world/generation/surface/context/SurfaceTileContext.java index 13f2211..ce28c6e 100644 --- a/src/main/java/ru/windcorp/progressia/test/gen/surface/context/SurfaceTileContext.java +++ b/src/main/java/ru/windcorp/progressia/server/world/generation/surface/context/SurfaceTileContext.java @@ -15,7 +15,7 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ -package ru.windcorp.progressia.test.gen.surface.context; +package ru.windcorp.progressia.server.world.generation.surface.context; import ru.windcorp.progressia.server.world.context.ServerTileContext; diff --git a/src/main/java/ru/windcorp/progressia/test/gen/surface/context/SurfaceTileStackContext.java b/src/main/java/ru/windcorp/progressia/server/world/generation/surface/context/SurfaceTileStackContext.java similarity index 96% rename from src/main/java/ru/windcorp/progressia/test/gen/surface/context/SurfaceTileStackContext.java rename to src/main/java/ru/windcorp/progressia/server/world/generation/surface/context/SurfaceTileStackContext.java index 54f65bc..d090e94 100644 --- a/src/main/java/ru/windcorp/progressia/test/gen/surface/context/SurfaceTileStackContext.java +++ b/src/main/java/ru/windcorp/progressia/server/world/generation/surface/context/SurfaceTileStackContext.java @@ -15,7 +15,7 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ -package ru.windcorp.progressia.test.gen.surface.context; +package ru.windcorp.progressia.server.world.generation.surface.context; import ru.windcorp.progressia.server.world.context.ServerTileStackContext; diff --git a/src/main/java/ru/windcorp/progressia/test/gen/surface/context/SurfaceWorldContext.java b/src/main/java/ru/windcorp/progressia/server/world/generation/surface/context/SurfaceWorldContext.java similarity index 95% rename from src/main/java/ru/windcorp/progressia/test/gen/surface/context/SurfaceWorldContext.java rename to src/main/java/ru/windcorp/progressia/server/world/generation/surface/context/SurfaceWorldContext.java index 76510cf..96a0922 100644 --- a/src/main/java/ru/windcorp/progressia/test/gen/surface/context/SurfaceWorldContext.java +++ b/src/main/java/ru/windcorp/progressia/server/world/generation/surface/context/SurfaceWorldContext.java @@ -15,7 +15,7 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ -package ru.windcorp.progressia.test.gen.surface.context; +package ru.windcorp.progressia.server.world.generation.surface.context; import glm.vec._3.i.Vec3i; import ru.windcorp.progressia.common.world.rels.RelFace; diff --git a/src/main/java/ru/windcorp/progressia/test/TestBushFeature.java b/src/main/java/ru/windcorp/progressia/test/TestBushFeature.java deleted file mode 100644 index a7174f9..0000000 --- a/src/main/java/ru/windcorp/progressia/test/TestBushFeature.java +++ /dev/null @@ -1,66 +0,0 @@ -/* - * 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 . - */ -package ru.windcorp.progressia.test; - -import glm.vec._3.i.Vec3i; -import ru.windcorp.progressia.common.util.VectorUtil; -import ru.windcorp.progressia.common.world.block.BlockData; -import ru.windcorp.progressia.common.world.block.BlockDataRegistry; -import ru.windcorp.progressia.common.world.rels.RelFace; -import ru.windcorp.progressia.test.gen.surface.SurfaceTopLayerFeature; -import ru.windcorp.progressia.test.gen.surface.context.SurfaceBlockContext; -import ru.windcorp.progressia.test.gen.surface.context.SurfaceWorldContext; - -public class TestBushFeature extends SurfaceTopLayerFeature { - - public TestBushFeature(String id) { - super(id); - } - - private void tryToSetLeaves(SurfaceWorldContext context, Vec3i location, BlockData leaves) { - if (context.getBlock(location).getId().equals("Test:Air")) { - context.setBlock(location, leaves); - } - } - - @Override - protected void processTopBlock(SurfaceBlockContext context) { - if (context.getRandom().nextInt(10*10) > 0) return; - - Vec3i center = context.getLocation().add_(0, 0, 1); - - BlockData log = BlockDataRegistry.getInstance().get("Test:Log"); - BlockData leaves = BlockDataRegistry.getInstance().get("Test:TemporaryLeaves"); - - context.setBlock(center, log); - - VectorUtil.iterateCuboidAround(center.x, center.y, center.z, 3, 3, 3, p -> { - tryToSetLeaves(context, p, leaves); - }); - - VectorUtil.iterateCuboidAround(center.x, center.y, center.z, 5, 5, 1, p -> { - tryToSetLeaves(context, p, leaves); - }); - } - - @Override - protected boolean isSolid(SurfaceBlockContext context) { - return context.logic().getBlock().isSolid(RelFace.UP); - } - -} diff --git a/src/main/java/ru/windcorp/progressia/test/TestContent.java b/src/main/java/ru/windcorp/progressia/test/TestContent.java index fe972a4..b8a5b33 100644 --- a/src/main/java/ru/windcorp/progressia/test/TestContent.java +++ b/src/main/java/ru/windcorp/progressia/test/TestContent.java @@ -27,7 +27,6 @@ import java.util.HashSet; import java.util.List; import java.util.Set; import java.util.function.Consumer; - import org.lwjgl.glfw.GLFW; import glm.vec._3.i.Vec3i; @@ -56,9 +55,9 @@ import ru.windcorp.progressia.server.Server; import ru.windcorp.progressia.server.comms.controls.*; import ru.windcorp.progressia.server.world.block.*; import ru.windcorp.progressia.server.world.entity.*; +import ru.windcorp.progressia.server.world.generation.planet.PlanetGravityModel; import ru.windcorp.progressia.server.world.tile.*; import ru.windcorp.progressia.test.gen.TestGravityModel; -import ru.windcorp.progressia.test.gen.planet.TestPlanetGravityModel; public class TestContent { @@ -435,7 +434,7 @@ public class TestContent { ChunkIO.registerCodec(new TestChunkCodec()); ChunkRenderOptimizerRegistry.getInstance().register("Core:SurfaceOptimizer", ChunkRenderOptimizerSurface::new); GravityModelRegistry.getInstance().register("Test:TheGravityModel", TestGravityModel::new); - GravityModelRegistry.getInstance().register("Test:PlanetGravityModel", TestPlanetGravityModel::new); + GravityModelRegistry.getInstance().register("Test:PlanetGravityModel", PlanetGravityModel::new); } } diff --git a/src/main/java/ru/windcorp/progressia/test/TestGrassFeature.java b/src/main/java/ru/windcorp/progressia/test/TestGrassFeature.java deleted file mode 100644 index cd18ebe..0000000 --- a/src/main/java/ru/windcorp/progressia/test/TestGrassFeature.java +++ /dev/null @@ -1,70 +0,0 @@ -/* - * 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 . - */ -package ru.windcorp.progressia.test; - -import java.util.Set; - -import com.google.common.collect.ImmutableSet; - -import ru.windcorp.progressia.common.world.rels.RelFace; -import ru.windcorp.progressia.common.world.tile.TileData; -import ru.windcorp.progressia.common.world.tile.TileDataRegistry; -import ru.windcorp.progressia.test.gen.surface.SurfaceTopLayerFeature; -import ru.windcorp.progressia.test.gen.surface.context.SurfaceBlockContext; - -public class TestGrassFeature extends SurfaceTopLayerFeature { - - private static final Set WHITELIST = ImmutableSet.of( - "Test:Dirt", - "Test:Stone", - "Test:GraniteMonolith", - "Test:GraniteCracked", - "Test:GraniteGravel" - ); - - public TestGrassFeature(String id) { - super(id); - } - - @Override - protected void processTopBlock(SurfaceBlockContext context) { - if (!WHITELIST.contains(context.getBlock().getId())) { - return; - } - - TileData grass = TileDataRegistry.getInstance().get("Test:Grass"); - - for (RelFace face : RelFace.getFaces()) { - if (face == RelFace.DOWN) continue; - - if (context.pushRelative(face).logic().getBlock().isTransparent()) { - context.pop(); - context.addTile(face, grass); - } else { - context.pop(); - } - - } - } - - @Override - protected boolean isSolid(SurfaceBlockContext context) { - return context.logic().getBlock().isSolid(RelFace.UP); - } - -} diff --git a/src/main/java/ru/windcorp/progressia/test/TestTreeFeature.java b/src/main/java/ru/windcorp/progressia/test/TestTreeFeature.java deleted file mode 100644 index 2e91dc9..0000000 --- a/src/main/java/ru/windcorp/progressia/test/TestTreeFeature.java +++ /dev/null @@ -1,106 +0,0 @@ -/* - * 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 . - */ -package ru.windcorp.progressia.test; - -import java.util.function.Consumer; - -import glm.vec._3.i.Vec3i; -import ru.windcorp.progressia.common.util.VectorUtil; -import ru.windcorp.progressia.common.world.block.BlockData; -import ru.windcorp.progressia.common.world.block.BlockDataRegistry; -import ru.windcorp.progressia.common.world.rels.RelFace; -import ru.windcorp.progressia.test.gen.surface.SurfaceTopLayerFeature; -import ru.windcorp.progressia.test.gen.surface.context.SurfaceBlockContext; -import ru.windcorp.progressia.test.gen.surface.context.SurfaceWorldContext; - -public class TestTreeFeature extends SurfaceTopLayerFeature { - - public TestTreeFeature(String id) { - super(id); - } - - private void tryToSetLeaves(SurfaceWorldContext context, Vec3i location, BlockData leaves) { - if (context.getBlock(location).getId().equals("Test:Air")) { - context.setBlock(location, leaves); - } - } - - private void iterateSpheroid(Vec3i center, double horDiameter, double vertDiameter, Consumer action) { - VectorUtil.iterateCuboidAround( - center.x, - center.y, - center.z, - (int) Math.ceil(horDiameter) / 2 * 2 + 5, - (int) Math.ceil(horDiameter) / 2 * 2 + 5, - (int) Math.ceil(vertDiameter) / 2 * 2 + 5, - pos -> { - double sx = (pos.x - center.x) / horDiameter; - double sy = (pos.y - center.y) / horDiameter; - double sz = (pos.z - center.z) / vertDiameter; - - if (sx * sx + sy * sy + sz * sz <= 1) { - action.accept(pos); - } - } - ); - } - - @Override - protected void processTopBlock(SurfaceBlockContext context) { - if (context.getRandom().nextInt(20 * 20) > 0) - return; - - Vec3i start = context.getLocation().add_(0, 0, 1); - - BlockData log = BlockDataRegistry.getInstance().get("Test:Log"); - BlockData leaves = BlockDataRegistry.getInstance().get("Test:TemporaryLeaves"); - - Vec3i center = start.add_(0); - - int height = context.getRandom().nextInt(3) + 5; - for (; center.z < start.z + height; ++center.z) { - context.setBlock(center, log); - } - - double branchHorDistance = 0; - - do { - double branchSize = 0.5 + 1 * context.getRandom().nextDouble(); - double branchHorAngle = 2 * Math.PI * context.getRandom().nextDouble(); - int branchVertOffset = -2 + context.getRandom().nextInt(3); - - Vec3i branchCenter = center.add_( - (int) (Math.sin(branchHorAngle) * branchHorDistance), - (int) (Math.cos(branchHorAngle) * branchHorDistance), - branchVertOffset - ); - - iterateSpheroid(branchCenter, 1.75 * branchSize, 2.5 * branchSize, p -> { - tryToSetLeaves(context, p, leaves); - }); - - branchHorDistance = 1 + 2 * context.getRandom().nextDouble(); - } while (context.getRandom().nextInt(8) > 1); - } - - @Override - protected boolean isSolid(SurfaceBlockContext context) { - return context.logic().getBlock().isSolid(RelFace.UP); - } - -} diff --git a/src/main/java/ru/windcorp/progressia/test/gen/Fields.java b/src/main/java/ru/windcorp/progressia/test/gen/Fields.java new file mode 100644 index 0000000..86741df --- /dev/null +++ b/src/main/java/ru/windcorp/progressia/test/gen/Fields.java @@ -0,0 +1,321 @@ +/* + * 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 . + */ +package ru.windcorp.progressia.test.gen; + +import java.util.Collections; +import java.util.HashMap; +import java.util.Map; +import java.util.Objects; +import java.util.Random; +import java.util.function.Function; +import java.util.function.Supplier; + +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; + +import kdotjpg.opensimplex2.areagen.OpenSimplex2S; +import ru.windcorp.progressia.common.util.namespaces.Namespaced; +import ru.windcorp.progressia.common.world.Coordinates; +import ru.windcorp.progressia.common.world.DefaultChunkData; +import ru.windcorp.progressia.common.world.rels.AbsFace; +import ru.windcorp.progressia.server.world.generation.planet.Planet; +import ru.windcorp.progressia.server.world.generation.surface.SurfaceFloatField; + +public class Fields { + + @FunctionalInterface + public interface Field { + double compute(double x, double y); + } + + public static class FieldSet extends Namespaced implements SurfaceFloatField { + + private final Field[] fields = new Field[AbsFace.getFaces().size()]; + + public FieldSet(String id) { + super(id); + } + + public void put(AbsFace face, Field field) { + fields[face.getId()] = field; + } + + public Field get(AbsFace face) { + return fields[face.getId()]; + } + + @Override + public float get(AbsFace face, float x, float y) { + float offset = DefaultChunkData.CHUNK_RADIUS - 0.5f; + return (float) fields[face.getId()].compute(x - offset, y - offset); + } + + } + + private final Random primitiveRandomizer; + + private final OpenSimplex2S noise; + + private final Map registeredFields = Collections.synchronizedMap(new HashMap<>()); + + private final Logger logger = LogManager.getLogger(getClass()); + + public Fields(long seed) { + this.primitiveRandomizer = new Random(seed); + this.noise = new OpenSimplex2S(seed); + } + + public Field register(String id, AbsFace face, Field f) { + Objects.requireNonNull(f, "f"); + Objects.requireNonNull(face, "face"); + + synchronized (registeredFields) { + FieldSet fieldSet = registeredFields.computeIfAbsent(id, FieldSet::new); + + Field previous = fieldSet.get(face); + if (previous != null) { + throw new IllegalArgumentException( + "Duplicate field definition " + id + ":" + face + " for fields " + f + " and " + previous + ); + } + fieldSet.put(face, f); + + logger.debug("Registering {}:{} in {}", id, face, getClass().getSimpleName()); + } + + return f; + } + + public SurfaceFloatField register(String id, Function fieldGenerator) { + for (AbsFace face : AbsFace.getFaces()) { + register(id, face, fieldGenerator.apply(face)); + } + return get(id); + } + + public SurfaceFloatField register(String id, Supplier fieldGenerator) { + for (AbsFace face : AbsFace.getFaces()) { + register(id, face, fieldGenerator.get()); + } + return get(id); + } + + public SurfaceFloatField get(String id) { + return registeredFields.get(id); + } + + public Field get(String id, AbsFace face) { + return registeredFields.get(id).get(face); + } + + public static Field cutoff(Field f, double outerRadius, double thickness) { + return (x, y) -> { + + double cutoffCoefficient = 1; + cutoffCoefficient *= cutoffFunction(outerRadius - x, thickness); + cutoffCoefficient *= cutoffFunction(outerRadius + x, thickness); + cutoffCoefficient *= cutoffFunction(outerRadius - y, thickness); + cutoffCoefficient *= cutoffFunction(outerRadius + y, thickness); + + if (cutoffCoefficient == 0) { + return 0; + } + + return cutoffCoefficient * f.compute(x, y); + + }; + } + + public static Field cutoff(Field f, Planet planet, double thickness) { + return cutoff(f, planet.getRadius() - Coordinates.CHUNK_SIZE, thickness); + } + + private static double cutoffFunction(double distanceToCutoffPoint, double thickness) { + if (distanceToCutoffPoint < 0) { + return 0; + } else if (distanceToCutoffPoint < thickness) { + double t = distanceToCutoffPoint / thickness; + return (1 - Math.cos(Math.PI * t)) / 2; + } else { + return 1; + } + } + + public Field primitive() { + double xOffset = primitiveRandomizer.nextDouble() * 200 - 100; + double yOffset = primitiveRandomizer.nextDouble() * 200 - 100; + double rotation = primitiveRandomizer.nextDouble() * 2 * Math.PI; + + double sin = Math.sin(rotation); + double cos = Math.cos(rotation); + + return (x, y) -> noise.noise2(x * cos - y * sin + xOffset, x * sin + y * cos + yOffset); + } + + public static Field add(Field a, Field b) { + return (x, y) -> a.compute(x, y) + b.compute(x, y); + } + + public static Field multiply(Field a, Field b) { + return (x, y) -> a.compute(x, y) * b.compute(x, y); + } + + public static Field add(Field... functions) { + return (x, y) -> { + double sum = 0; + for (Field function : functions) { + sum += function.compute(x, y); + } + return sum; + }; + } + + public static Field multiply(Field... functions) { + return (x, y) -> { + double product = 1; + for (Field function : functions) { + product *= function.compute(x, y); + } + return product; + }; + } + + public static Field tweak(Field f, double scale, double amplitude, double bias) { + return (x, y) -> f.compute(x / scale, y / scale) * amplitude + bias; + } + + public static Field tweak(Field f, double scale, double amplitude) { + return tweak(f, scale, amplitude, 0); + } + + public static Field scale(Field f, double scale) { + return tweak(f, scale, 1, 0); + } + + public static Field amplify(Field f, double amplitude) { + return tweak(f, 1, amplitude, 0); + } + + public static Field bias(Field f, double bias) { + return tweak(f, 1, 1, bias); + } + + public static Field octaves(Field f, double scaleFactor, double amplitudeFactor, int octaves) { + return (x, y) -> { + double result = 0; + + double scale = 1; + double amplitude = 1; + + for (int i = 0; i < octaves; ++i) { + result += f.compute(x * scale, y * scale) * amplitude; + scale *= scaleFactor; + amplitude /= amplitudeFactor; + } + + return result; + }; + } + + public static Field octaves(Field f, double factor, int octaves) { + return octaves(f, factor, factor, octaves); + } + + public static Field squash(Field f, double slope) { + return (x, y) -> 1 / (1 + Math.exp(-slope * f.compute(x, y))); + } + + public static Field ridge(Field f) { + return (x, y) -> 1 - Math.abs(f.compute(x, y)); + } + + public static Field clamp(Field f, double min, double max) { + return (x, y) -> Math.min(Math.max(f.compute(x, y), min), max); + } + + public static Field withMin(Field f, double min) { + return (x, y) -> Math.max(f.compute(x, y), min); + } + + public static Field withMax(Field f, double max) { + return (x, y) -> Math.min(f.compute(x, y), max); + } + + public static Field select(Field f, double target, double width) { + return (x, y) -> { + double value = f.compute(x, y); + if (value < target - width) { + return 0; + } else if (value < target) { + return (width - (target - value)) / width; + } else if (value < target + width) { + return (width - (value - target)) / width; + } else { + return 0; + } + }; + } + + public static Field selectPositive(Field f, double target, double width) { + return (x, y) -> { + double value = f.compute(x, y); + if (value < target - width) { + return 0; + } else if (value < target + width) { + return (width - (target - value)) / (2*width); + } else { + return 1; + } + }; + } + + public static Field selectNegative(Field f, double target, double width) { + return (x, y) -> { + double value = target - f.compute(x, y); + if (value < target - width) { + return 0; + } else if (value < target + width) { + return (width - (target - value)) / (2*width); + } else { + return 1; + } + }; + } + + public static Field cliff(Field f, double target, double featureWidth, double slopeWidth) { + return (x, y) -> { + double value = f.compute(x, y); + + if (value < target - featureWidth) { + return 0; + } else if (value < target - slopeWidth) { + double t = (value - (target - featureWidth)) / (featureWidth - slopeWidth); + return -0.5 + Math.cos(t * Math.PI) / 2; + } else if (value < target + slopeWidth) { + double t = (value - (target - slopeWidth)) / (2 * slopeWidth); + return -Math.cos(t * Math.PI); + } else if (value < target + featureWidth) { + double t = (value - (target + slopeWidth)) / (featureWidth - slopeWidth); + return +0.5 + Math.cos(t * Math.PI) / 2; + } else { + return 0; + } + }; + } + +} diff --git a/src/main/java/ru/windcorp/progressia/test/gen/MultiblockVegetationFeature.java b/src/main/java/ru/windcorp/progressia/test/gen/MultiblockVegetationFeature.java new file mode 100644 index 0000000..5cfcc43 --- /dev/null +++ b/src/main/java/ru/windcorp/progressia/test/gen/MultiblockVegetationFeature.java @@ -0,0 +1,148 @@ +/* + * 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 . + */ +package ru.windcorp.progressia.test.gen; + +import java.util.Set; +import java.util.function.Consumer; + +import com.google.common.collect.ImmutableSet; + +import glm.vec._3.i.Vec3i; +import kdotjpg.opensimplex2.areagen.OpenSimplex2S; +import ru.windcorp.progressia.common.util.VectorUtil; +import ru.windcorp.progressia.common.world.block.BlockData; +import ru.windcorp.progressia.common.world.rels.RelFace; +import ru.windcorp.progressia.server.world.generation.surface.SurfaceFloatField; +import ru.windcorp.progressia.server.world.generation.surface.SurfaceTopLayerFeature; +import ru.windcorp.progressia.server.world.generation.surface.context.SurfaceBlockContext; +import ru.windcorp.progressia.server.world.generation.surface.context.SurfaceWorldContext; + +public abstract class MultiblockVegetationFeature extends SurfaceTopLayerFeature { + + private final SurfaceFloatField selector; + private final OpenSimplex2S wavinessGenerator = new OpenSimplex2S(0); + + private final double maximumDensity; + + private final Set soilWhitelist; + + public MultiblockVegetationFeature(String id, SurfaceFloatField selector, double minimumPeriod) { + super(id); + this.selector = selector; + this.maximumDensity = 1 / minimumPeriod; + + ImmutableSet.Builder soilWhitelistBuilder = ImmutableSet.builder(); + createSoilWhitelist(soilWhitelistBuilder::add); + this.soilWhitelist = soilWhitelistBuilder.build(); + } + + protected void createSoilWhitelist(Consumer output) { + output.accept("Test:Dirt"); + } + + @Override + protected void processTopBlock(SurfaceBlockContext context) { + Vec3i location = context.getLocation(); + + if (location.z < 0) { + return; + } + + if (!soilWhitelist.isEmpty() && !soilWhitelist.contains(context.getBlock().getId())) { + return; + } + + double selectorValue = selector.get(context); + double chance = selectorValue * maximumDensity; + if (context.getRandom().nextDouble() >= chance) { + return; + } + + grow(context, selectorValue); + } + + protected abstract void grow(SurfaceBlockContext context, double selectorValue); + + @Override + protected boolean isSolid(SurfaceBlockContext context) { + return context.logic().getBlock().isSolid(RelFace.UP); + } + + /* + * Utilities + */ + + protected void setLeaves(SurfaceWorldContext context, Vec3i location, BlockData leaves) { + if (context.getBlock(location).getId().equals("Test:Air")) { + context.setBlock(location, leaves); + } + } + + protected void iterateBlob( + Vec3i center, + double horDiameter, + double vertDiameter, + double wavinessAmplitude, + double wavinessScale, + Consumer action + ) { + VectorUtil.iterateCuboidAround( + center.x, + center.y, + center.z, + (int) Math.ceil(horDiameter) / 2 * 2 + 5, + (int) Math.ceil(horDiameter) / 2 * 2 + 5, + (int) Math.ceil(vertDiameter) / 2 * 2 + 5, + pos -> { + + double sx = (pos.x - center.x) / horDiameter; + double sy = (pos.y - center.y) / horDiameter; + double sz = (pos.z - center.z) / vertDiameter; + + double radius = 1; + + if (wavinessAmplitude > 0) { + radius += wavinessAmplitude * wavinessGenerator.noise3_Classic( + sx / wavinessScale, + sy / wavinessScale, + sz / wavinessScale + ); + } + + if (sx * sx + sy * sy + sz * sz <= radius * radius) { + action.accept(pos); + } + + } + ); + } + + protected void iterateSpheroid( + Vec3i center, + double horDiameter, + double vertDiameter, + Consumer action + ) { + iterateBlob(center, horDiameter, vertDiameter, 0, 0, action); + } + + protected void iterateSphere(Vec3i center, double diameter, Consumer action) { + iterateBlob(center, diameter, diameter, 0, 0, action); + } + +} diff --git a/src/main/java/ru/windcorp/progressia/test/gen/TestBushFeature.java b/src/main/java/ru/windcorp/progressia/test/gen/TestBushFeature.java new file mode 100644 index 0000000..ca2765c --- /dev/null +++ b/src/main/java/ru/windcorp/progressia/test/gen/TestBushFeature.java @@ -0,0 +1,49 @@ +/* + * 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 . + */ +package ru.windcorp.progressia.test.gen; + +import glm.vec._3.i.Vec3i; +import ru.windcorp.progressia.common.world.block.BlockData; +import ru.windcorp.progressia.common.world.block.BlockDataRegistry; +import ru.windcorp.progressia.server.world.generation.surface.SurfaceFloatField; +import ru.windcorp.progressia.server.world.generation.surface.context.SurfaceBlockContext; + +public class TestBushFeature extends MultiblockVegetationFeature { + + private final BlockData trunk = BlockDataRegistry.getInstance().get("Test:Log"); + private final BlockData leaves = BlockDataRegistry.getInstance().get("Test:TemporaryLeaves"); + + public TestBushFeature(String id, SurfaceFloatField selector) { + super(id, selector, 7 * 7); + } + + @Override + protected void grow(SurfaceBlockContext context, double selectorValue) { + double size = selectorValue * randomDouble(context, 0.8, 1.2); + + Vec3i center = context.getLocation().add_(0, 0, 1); + + context.setBlock(center, trunk); + context.setBlock(center.add_(0, 0, 1), leaves); + + iterateBlob(center, stretch(size, 1.3, 2.5), stretch(size, 0.6, 1.5), 0.7, 2, p -> { + setLeaves(context, p, leaves); + }); + } + +} diff --git a/src/main/java/ru/windcorp/progressia/test/gen/TestGenerationConfig.java b/src/main/java/ru/windcorp/progressia/test/gen/TestGenerationConfig.java new file mode 100644 index 0000000..b4ed652 --- /dev/null +++ b/src/main/java/ru/windcorp/progressia/test/gen/TestGenerationConfig.java @@ -0,0 +1,118 @@ +/* + * 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 . + */ +package ru.windcorp.progressia.test.gen; + +import static ru.windcorp.progressia.test.gen.Fields.*; + +import java.util.ArrayList; +import java.util.List; +import java.util.function.Function; + +import ru.windcorp.progressia.common.Units; +import ru.windcorp.progressia.common.util.ArrayFloatRangeMap; +import ru.windcorp.progressia.common.util.FloatRangeMap; +import ru.windcorp.progressia.common.world.Coordinates; +import ru.windcorp.progressia.common.world.block.BlockData; +import ru.windcorp.progressia.common.world.block.BlockDataRegistry; +import ru.windcorp.progressia.server.Server; +import ru.windcorp.progressia.server.world.generation.WorldGenerator; +import ru.windcorp.progressia.server.world.generation.planet.Planet; +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.SurfaceFloatField; +import ru.windcorp.progressia.server.world.generation.surface.TerrainLayer; + +public class TestGenerationConfig { + + 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 CURVATURE = Units.get("100 m"); + private static final float INNER_RADIUS = Units.get("200 m"); + + private static final Fields FIELDS = new Fields("No bugs please".hashCode()); + + public static Function createGenerator() { + + Planet planet = new Planet( + ((int) PLANET_RADIUS) / Coordinates.CHUNK_SIZE, + SURFACE_GRAVITY, + CURVATURE, + INNER_RADIUS + ); + + TestHeightMap heightMap = new TestHeightMap(planet, planet.getRadius() / 4, FIELDS); + + FloatRangeMap layers = new ArrayFloatRangeMap<>(); + registerTerrainLayers(layers); + + List features = new ArrayList<>(); + registerFeatures(features); + + return server -> new PlanetGenerator("Test:PlanetGenerator", server, planet, heightMap, layers, features); + + } + + private static void registerTerrainLayers(FloatRangeMap layers) { + BlockData granite = BlockDataRegistry.getInstance().get("Test:GraniteMonolith"); + BlockData graniteCracked = BlockDataRegistry.getInstance().get("Test:GraniteCracked"); + BlockData graniteGravel = BlockDataRegistry.getInstance().get("Test:GraniteGravel"); + + BlockData dirt = BlockDataRegistry.getInstance().get("Test:Dirt"); + BlockData air = BlockDataRegistry.getInstance().get("Test:Air"); + + SurfaceFloatField cliffs = FIELDS.get("Test:CliffSelector"); + + layers.put(Float.NEGATIVE_INFINITY, 0, (f, n, w, d, r) -> air); + layers.put(0, 4, (f, n, w, d, r) -> { + if (cliffs.get(f, n, w) > 0) { + switch (r.nextInt(4)) { + case 0: + return granite; + case 1: + return graniteCracked; + default: + return graniteGravel; + } + } else { + return dirt; + } + }); + layers.put(4, Float.POSITIVE_INFINITY, (f, n, w, d, r) -> granite); + } + + private static void registerFeatures(List features) { + + SurfaceFloatField forestiness = FIELDS.register( + "Test:Forestiness", + () -> squash(scale(FIELDS.primitive(), 200), 5) + ); + + SurfaceFloatField floweriness = FIELDS.register( + "Test:Floweriness", + f -> multiply( + scale(octaves(FIELDS.primitive(), 2, 2), 40), + tweak(FIELDS.get("Test:Forestiness", f), 1, -1, 1.1) + ) + ); + + features.add(new TestBushFeature("Test:BushFeature", forestiness)); + features.add(new TestTreeFeature("Test:TreeFeature", forestiness)); + features.add(new TestGrassFeature("Test:GrassFeature", FIELDS.get("Test:CliffSelector"), floweriness)); + } + +} diff --git a/src/main/java/ru/windcorp/progressia/test/gen/TestGrassFeature.java b/src/main/java/ru/windcorp/progressia/test/gen/TestGrassFeature.java new file mode 100644 index 0000000..d1d73e5 --- /dev/null +++ b/src/main/java/ru/windcorp/progressia/test/gen/TestGrassFeature.java @@ -0,0 +1,122 @@ +/* + * 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 . + */ +package ru.windcorp.progressia.test.gen; + +import java.util.List; +import java.util.Set; + +import com.google.common.collect.ImmutableList; +import com.google.common.collect.ImmutableSet; + +import ru.windcorp.progressia.common.world.rels.RelFace; +import ru.windcorp.progressia.common.world.tile.TileData; +import ru.windcorp.progressia.common.world.tile.TileDataRegistry; +import ru.windcorp.progressia.server.world.generation.surface.SurfaceFloatField; +import ru.windcorp.progressia.server.world.generation.surface.SurfaceTopLayerFeature; +import ru.windcorp.progressia.server.world.generation.surface.context.SurfaceBlockContext; + +public class TestGrassFeature extends SurfaceTopLayerFeature { + + private static final Set WHITELIST = ImmutableSet.of( + "Test:Dirt", + "Test:Stone", + "Test:GraniteMonolith", + "Test:GraniteCracked", + "Test:GraniteGravel" + ); + + private final SurfaceFloatField grassiness; + private final SurfaceFloatField floweriness; + private final double scatterDensity = 1.0 / (3*3); + + private final TileData grass = TileDataRegistry.getInstance().get("Test:Grass"); + private final List flowers = ImmutableList.of( + TileDataRegistry.getInstance().get("Test:YellowFlowers") + ); + private final List scatter = ImmutableList.of( + TileDataRegistry.getInstance().get("Test:Stones"), + TileDataRegistry.getInstance().get("Test:Sand") + ); + + public TestGrassFeature(String id, SurfaceFloatField grassiness, SurfaceFloatField floweriness) { + super(id); + this.grassiness = grassiness; + this.floweriness = floweriness; + } + + @Override + protected void processTopBlock(SurfaceBlockContext context) { + if (context.getLocation().z < 0) { + return; + } + if (!WHITELIST.contains(context.getBlock().getId())) { + return; + } + + if (!context.pushRelative(RelFace.UP).logic().getBlock().isTransparent()) { + context.pop(); + return; + } + context.pop(); + + double grassiness = this.grassiness.get(context); + if (grassiness < 0.2) { + growGrass(context); + } + + placeScatter(context); + + if (grassiness < 0.2) { + growFlowers(context); + } + } + + private void placeScatter(SurfaceBlockContext context) { + if (context.getRandom().nextDouble() < scatterDensity) { + TileData tile = pickRandom(context, scatter); + context.addTile(RelFace.UP, tile); + } + } + + private void growGrass(SurfaceBlockContext context) { + for (RelFace face : RelFace.getFaces()) { + if (face == RelFace.DOWN) continue; + + if (context.pushRelative(face).logic().getBlock().isTransparent()) { + context.pop(); + context.addTile(face, grass); + } else { + context.pop(); + } + + } + } + + private void growFlowers(SurfaceBlockContext context) { + if (context.getRandom().nextDouble() < floweriness.get(context)) { + TileData tile = pickRandom(context, flowers); + context.addTile(RelFace.UP, tile); + } + } + + @Override + protected boolean isSolid(SurfaceBlockContext context) { + return context.logic().getBlock().isSolid(RelFace.UP); + } + +} diff --git a/src/main/java/ru/windcorp/progressia/test/gen/TestHeightMap.java b/src/main/java/ru/windcorp/progressia/test/gen/TestHeightMap.java new file mode 100644 index 0000000..c09aec1 --- /dev/null +++ b/src/main/java/ru/windcorp/progressia/test/gen/TestHeightMap.java @@ -0,0 +1,79 @@ +/* + * 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 . + */ +package ru.windcorp.progressia.test.gen; + +import static ru.windcorp.progressia.test.gen.Fields.*; + +import ru.windcorp.progressia.common.world.rels.AbsFace; +import ru.windcorp.progressia.server.world.generation.planet.Planet; +import ru.windcorp.progressia.server.world.generation.surface.SurfaceFloatField; + +public class TestHeightMap implements SurfaceFloatField { + + private final SurfaceFloatField shape; + + public TestHeightMap( + Planet planet, + float cutoffThickness, + Fields fields + ) { + + for (AbsFace face : AbsFace.getFaces()) { + + Field landmassDistribution = scale(octaves(fields.primitive(), 2, 5), 400); + Field landmasses = tweak(squash(landmassDistribution, 4), 1, 20, -20); + + Field plainsSelector = squash(withMin(landmassDistribution, 0), 10); + Field plains = tweak(octaves(fields.primitive(), 2, 3), 100, 3); + + Field randomCliffSelector = scale(fields.primitive(), 200); + randomCliffSelector = add( + select(randomCliffSelector, +0.7, 0.3), + amplify(select(randomCliffSelector, -0.7, 0.3), -1) + ); + Field randomCliffs = octaves(scale(fields.primitive(), 300), 3, 5); + + Field shoreCliffSelector = withMin(scale(fields.primitive(), 200), 0); + Field shoreCliffs = add( + landmassDistribution, + tweak(octaves(fields.primitive(), 2, 3), 50, 0.2) + ); + + fields.register("Test:CliffSelector", face, multiply( + shoreCliffSelector, + bias(select(shoreCliffs, 0, 0.07), 0) + )); + + fields.register("Test:Height", face, cutoff(add( + landmasses, + multiply(plains, plainsSelector), + multiply(amplify(cliff(randomCliffs, 0, 0.5, 0.03), 10), randomCliffSelector), + multiply(tweak(cliff(shoreCliffs, 0, 0.5, 0.03), 1, 15, 15), shoreCliffSelector) + ), planet, cutoffThickness)); + + } + + this.shape = fields.get("Test:Height"); + } + + @Override + public float get(AbsFace face, float x, float y) { + return (float) shape.get(face, x, y); + } + +} diff --git a/src/main/java/ru/windcorp/progressia/test/gen/TestTerrainGenerator.java b/src/main/java/ru/windcorp/progressia/test/gen/TestTerrainGenerator.java deleted file mode 100644 index 8112105..0000000 --- a/src/main/java/ru/windcorp/progressia/test/gen/TestTerrainGenerator.java +++ /dev/null @@ -1,152 +0,0 @@ -/* - * 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 . - */ - -package ru.windcorp.progressia.test.gen; - -import kdotjpg.opensimplex2.areagen.OpenSimplex2S; -import ru.windcorp.progressia.server.world.DefaultWorldLogic; - -class TestTerrainGenerator { - - @FunctionalInterface - private interface Func2D { - double compute(double x, double y); - } - - private final OpenSimplex2S noise; - private final Func2D shape; - - public TestTerrainGenerator(TestWorldGenerator testWorldGenerator, DefaultWorldLogic world) { - this.noise = new OpenSimplex2S("We're getting somewhere".hashCode()); - - Func2D plainsHeight = tweak( - octaves( - tweak(primitive(), 0.01, 0.5), - 2, - 3 - ), - 1, - 0.2, - 0.2 - ); - - Func2D mountainsHeight = tweak( - octaves( - ridge(tweak(primitive(), 0.01, 1)), - 2, - 1.5, - 12 - ), - 1, - 3 - ); - - Func2D mountainousity = tweak( - octaves( - tweak(primitive(), 0.007, 1), - 2, - 3 - ), - 1, - 1, - -0.25 - ); - - shape = tweak( - add(multiply(squash(mountainousity, 10), mountainsHeight), plainsHeight), - 0.001, - 1000, - 0 - ); - } - - public void compute(int startX, int startY, double[][] heightMap, double[][] slopeMap) { - for (int x = 0; x < heightMap.length; ++x) { - for (int y = 0; y < heightMap.length; ++y) { - heightMap[x][y] = shape.compute(x + startX, y + startY); - slopeMap[x][y] = computeSlope(shape, x + startX, y + startY, heightMap[x][y]); - } - } - } - - private double computeSlope(Func2D f, double x0, double y0, double f0) { - double di = 0.5; - - double dfdx = (f.compute(x0 + di, y0) - f0) / di; - double dfdy = (f.compute(x0, y0 + di) - f0) / di; - - return Math.hypot(dfdx, dfdy); - } - - /* - * Utility functions - */ - - private Func2D primitive() { - return noise::noise2; - } - - private Func2D add(Func2D a, Func2D b) { - return (x, y) -> a.compute(x, y) + b.compute(x, y); - } - - private Func2D multiply(Func2D a, Func2D b) { - return (x, y) -> a.compute(x, y) * b.compute(x, y); - } - - private Func2D tweak(Func2D f, double scale, double amplitude, double bias) { - return (x, y) -> f.compute(x * scale, y * scale) * amplitude + bias; - } - - private Func2D tweak(Func2D f, double scale, double amplitude) { - return tweak(f, scale, amplitude, 0); - } - - private Func2D octaves(Func2D f, double scaleFactor, double amplitudeFactor, int octaves) { - return (x, y) -> { - double result = 0; - - double scale = 1; - double amplitude = 1; - - for (int i = 0; i < octaves; ++i) { - result += f.compute(x * scale, y * scale) * amplitude; - scale *= scaleFactor; - amplitude /= amplitudeFactor; - } - - return result; - }; - } - - private Func2D octaves(Func2D f, double factor, int octaves) { - return octaves(f, factor, factor, octaves); - } - - private Func2D squash(Func2D f, double slope) { - return (x, y) -> 1 / (1 + Math.exp(-slope * f.compute(x, y))); - } - - private Func2D ridge(Func2D f) { - return (x, y) -> { - double result = 1 - Math.abs(f.compute(x, y)); - return result * result; - }; - } - -} diff --git a/src/main/java/ru/windcorp/progressia/test/gen/TestTreeFeature.java b/src/main/java/ru/windcorp/progressia/test/gen/TestTreeFeature.java new file mode 100644 index 0000000..d08862e --- /dev/null +++ b/src/main/java/ru/windcorp/progressia/test/gen/TestTreeFeature.java @@ -0,0 +1,69 @@ +/* + * 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 . + */ +package ru.windcorp.progressia.test.gen; + +import glm.vec._3.i.Vec3i; +import ru.windcorp.progressia.common.world.block.BlockData; +import ru.windcorp.progressia.common.world.block.BlockDataRegistry; +import ru.windcorp.progressia.server.world.generation.surface.SurfaceFloatField; +import ru.windcorp.progressia.server.world.generation.surface.context.SurfaceBlockContext; + +public class TestTreeFeature extends MultiblockVegetationFeature { + + private final BlockData trunk = BlockDataRegistry.getInstance().get("Test:Log"); + private final BlockData leaves = BlockDataRegistry.getInstance().get("Test:TemporaryLeaves"); + + public TestTreeFeature(String id, SurfaceFloatField selector) { + super(id, selector, 10 * 10); + } + + @Override + protected void grow(SurfaceBlockContext context, double selectorValue) { + + Vec3i start = context.getLocation().add_(0, 0, 1); + Vec3i center = start.add_(0); + + double size = selectorValue * randomDouble(context, 0.8, 1.2); + + int height = (int) stretch(size, 3, 7); + for (; center.z < start.z + height; ++center.z) { + context.setBlock(center, trunk); + } + + double branchHorDistance = 0; + + do { + double branchSize = 0.5 + randomDouble(context, 1, 2) * size; + double branchHorAngle = randomDouble(context, 0, 2 * Math.PI); + int branchVertOffset = (int) randomDouble(context, -2, 0); + + Vec3i branchCenter = center.add_( + (int) (Math.sin(branchHorAngle) * branchHorDistance), + (int) (Math.cos(branchHorAngle) * branchHorDistance), + branchVertOffset + ); + + iterateBlob(branchCenter, 1 * branchSize, 2.3 * branchSize, 0.5, 3, p -> { + setLeaves(context, p, leaves); + }); + + branchHorDistance = randomDouble(context, 0.7, 1.5); + } while (context.getRandom().nextInt(8) > 1); + } + +} diff --git a/src/main/java/ru/windcorp/progressia/test/gen/TestWorldGenerator.java b/src/main/java/ru/windcorp/progressia/test/gen/TestWorldGenerator.java deleted file mode 100644 index 75d4eb0..0000000 --- a/src/main/java/ru/windcorp/progressia/test/gen/TestWorldGenerator.java +++ /dev/null @@ -1,400 +0,0 @@ -/* - * 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 . - */ - -package ru.windcorp.progressia.test.gen; - -import java.io.DataInputStream; -import java.io.DataOutputStream; -import java.io.IOException; -import java.util.Random; - -import glm.vec._3.Vec3; -import glm.vec._3.i.Vec3i; -import ru.windcorp.progressia.common.util.VectorUtil; -import ru.windcorp.progressia.common.util.Vectors; -import ru.windcorp.progressia.common.world.DefaultChunkData; -import ru.windcorp.progressia.common.world.Coordinates; -import ru.windcorp.progressia.common.world.DecodingException; -import ru.windcorp.progressia.common.world.DefaultWorldData; -import ru.windcorp.progressia.common.world.WorldDataListener; -import ru.windcorp.progressia.common.world.block.BlockData; -import ru.windcorp.progressia.common.world.block.BlockDataRegistry; -import ru.windcorp.progressia.common.world.rels.AbsFace; -import ru.windcorp.progressia.common.world.tile.TileData; -import ru.windcorp.progressia.common.world.tile.TileDataRegistry; -import ru.windcorp.progressia.server.Server; -import ru.windcorp.progressia.server.world.generation.AbstractWorldGenerator; - -public class TestWorldGenerator extends AbstractWorldGenerator { - - private final TestTerrainGenerator terrainGen; - - public TestWorldGenerator(Server server) { - super("Test:WorldGenerator", server, Boolean.class, "Test:TheGravityModel"); - this.terrainGen = new TestTerrainGenerator(this, server.getWorld()); - - getWorldData().addListener(new WorldDataListener() { - @Override - public void onChunkLoaded(DefaultWorldData world, DefaultChunkData chunk) { - findAndPopulate(chunk.getPosition(), world); - } - }); - } - - @Override - public Vec3 suggestSpawnLocation() { - return new Vec3(8, 8, 880); - } - - @Override - protected Boolean doReadGenerationHint(DataInputStream input) throws IOException, DecodingException { - return input.readBoolean(); - } - - @Override - protected void doWriteGenerationHint(DataOutputStream output, Boolean hint) throws IOException { - output.writeBoolean(hint); - } - - @Override - protected boolean checkIsChunkReady(Boolean hint) { - return hint; - } - - @Override - public DefaultChunkData generate(Vec3i chunkPos) { - DefaultChunkData chunk = generateUnpopulated(chunkPos, getWorldData()); - getWorldData().addChunk(chunk); - return chunk; - } - - private DefaultChunkData generateUnpopulated(Vec3i chunkPos, DefaultWorldData world) { - DefaultChunkData chunk = new DefaultChunkData(chunkPos, world); - chunk.setGenerationHint(false); - - final int bpc = DefaultChunkData.BLOCKS_PER_CHUNK; - Random random = new Random(chunkPos.x + chunkPos.y + chunkPos.z); - - BlockData dirt = BlockDataRegistry.getInstance().get("Test:Dirt"); - BlockData stone = BlockDataRegistry.getInstance().get("Test:Stone"); - BlockData air = BlockDataRegistry.getInstance().get("Test:Air"); - - BlockData[] granites = new BlockData[] { - BlockDataRegistry.getInstance().get("Test:GraniteGravel"), - BlockDataRegistry.getInstance().get("Test:GraniteGravel"), - BlockDataRegistry.getInstance().get("Test:GraniteCracked"), - BlockDataRegistry.getInstance().get("Test:GraniteMonolith") - }; - - double[][] heightMap = new double[bpc][bpc]; - double[][] gradMap = new double[bpc][bpc]; - - int startX = Coordinates.getInWorld(chunk.getX(), 0); - int startY = Coordinates.getInWorld(chunk.getY(), 0); - int startZ = Coordinates.getInWorld(chunk.getZ(), 0); - - terrainGen.compute(startX, startY, heightMap, gradMap); - - VectorUtil.iterateCuboid(0, 0, 0, bpc, bpc, bpc, pos -> { - double layer = pos.z - heightMap[pos.x][pos.y] + startZ; - - if (layer < -4) { - chunk.setBlock(pos, stone, false); - } else if (layer < 0) { - if (gradMap[pos.x][pos.y] > 0.5) { - BlockData granite = granites[random.nextInt(4)]; - chunk.setBlock(pos, granite, false); - } else { - chunk.setBlock(pos, dirt, false); - } - } else { - chunk.setBlock(pos, air, false); - } - }); - - return chunk; - } - - private void findAndPopulate(Vec3i changePos, DefaultWorldData world) { - VectorUtil.iterateCuboidAround(changePos, 3, candidatePos -> { - if (canBePopulated(candidatePos, world)) { - populate(candidatePos, world); - } - }); - } - - private boolean canBePopulated(Vec3i candidatePos, DefaultWorldData world) { - Vec3i cursor = Vectors.grab3i(); - - DefaultChunkData candidate = world.getChunk(candidatePos); - if (candidate == null || isChunkReady(candidate.getGenerationHint())) - return false; - - for (int dx = -1; dx <= 1; ++dx) { - cursor.x = candidatePos.x + dx; - for (int dy = -1; dy <= 1; ++dy) { - cursor.y = candidatePos.y + dy; - for (int dz = -1; dz <= 1; ++dz) { - - if ((dx | dy | dz) == 0) - continue; - - cursor.z = candidatePos.z + dz; - - DefaultChunkData chunk = world.getChunk(cursor); - if (chunk == null) { - return false; - } - - } - } - } - - Vectors.release(cursor); - return true; - } - - private void populate(Vec3i chunkPos, DefaultWorldData world) { - Random random = new Random(chunkPos.x + chunkPos.y + chunkPos.z); - - DefaultChunkData chunk = world.getChunk(chunkPos); - assert chunk != null : "Something went wrong when populating chunk at (" + chunkPos.x + "; " + chunkPos.y + "; " - + chunkPos.z + ")"; - - BlockData air = BlockDataRegistry.getInstance().get("Test:Air"); - BlockData dirt = BlockDataRegistry.getInstance().get("Test:Dirt"); - - Vec3i biw = new Vec3i(); - - int minX = chunk.getMinX(); - int maxX = chunk.getMaxX() + 1; - int minY = chunk.getMinY(); - int maxY = chunk.getMaxY() + 1; - int minZ = chunk.getMinZ(); - int maxZ = chunk.getMaxZ() + 1; - - final int bpc = DefaultChunkData.BLOCKS_PER_CHUNK; - double[][] heightMap = new double[bpc][bpc]; - double[][] gradMap = new double[bpc][bpc]; - - terrainGen.compute(minX, minY, heightMap, gradMap); - - for (biw.x = minX; biw.x < maxX; ++biw.x) { - for (biw.y = minY; biw.y < maxY; ++biw.y) { - - for (biw.z = minZ; biw.z < maxZ + 1 && world.getBlock(biw) != air; ++biw.z) - ; - biw.z -= 1; - - if (biw.z == maxZ) - continue; - if (biw.z < minZ) - continue; - - int xic = Coordinates.convertInWorldToInChunk(biw.x); - int yic = Coordinates.convertInWorldToInChunk(biw.y); - - addTiles( - chunk, - biw, - world, - random, - world.getBlock(biw) == dirt, - heightMap[xic][yic], - gradMap[xic][yic] - ); - - } - } - - chunk.setGenerationHint(true); - } - - private void addTiles( - DefaultChunkData chunk, - Vec3i biw, - DefaultWorldData world, - Random random, - boolean isDirt, - double height, - double grad - ) { - if (isDirt) - addGrass(chunk, biw, world, random); - addDecor(chunk, biw, world, random, isDirt); - addSnow(chunk, biw, world, random, isDirt, height, grad); - } - - private void addGrass(DefaultChunkData chunk, Vec3i biw, DefaultWorldData world, Random random) { - BlockData air = BlockDataRegistry.getInstance().get("Test:Air"); - TileData grass = TileDataRegistry.getInstance().get("Test:Grass"); - - world.getTiles(biw, AbsFace.POS_Z).add(grass); - - for (AbsFace face : AbsFace.getFaces()) { - if (face.getVector().z != 0) - continue; - biw.add(face.getVector()); - - if (world.getBlock(biw) == air) { - biw.sub(face.getVector()); - world.getTiles(biw, face).add(grass); - } else { - biw.sub(face.getVector()); - } - } - } - - private void addDecor(DefaultChunkData chunk, Vec3i biw, DefaultWorldData world, Random random, boolean isDirt) { - if (isDirt) { - if (random.nextInt(8) == 0) { - world.getTiles(biw, AbsFace.POS_Z).addFarthest( - TileDataRegistry.getInstance().get("Test:Sand") - ); - } - - if (random.nextInt(8) == 0) { - world.getTiles(biw, AbsFace.POS_Z).addFarthest( - TileDataRegistry.getInstance().get("Test:Stones") - ); - } - - if (random.nextInt(8) == 0) { - world.getTiles(biw, AbsFace.POS_Z).addFarthest( - TileDataRegistry.getInstance().get("Test:YellowFlowers") - ); - } - } else { - if (random.nextInt(2) == 0) { - world.getTiles(biw, AbsFace.POS_Z).addFarthest( - TileDataRegistry.getInstance().get("Test:Stones") - ); - } - } - } - - private void addSnow( - DefaultChunkData chunk, - Vec3i biw, - DefaultWorldData world, - Random random, - boolean isDirt, - double height, - double grad - ) { - if (height < 1500) - return; - - BlockData air = BlockDataRegistry.getInstance().get("Test:Air"); - - double quarterChance = computeSnowQuarterChance(height, grad); - double halfChance = computeSnowHalfChance(height, grad); - double opaqueChance = computeSnowOpaqueChance(height, grad); - - for (AbsFace face : AbsFace.getFaces()) { - if (face == AbsFace.NEG_Z) - continue; - - if (face.getVector().z == 0) { - biw.add(face.getVector()); - BlockData neighbour = world.getBlock(biw); - biw.sub(face.getVector()); - - if (neighbour != air) - continue; - } - - TileData tile; - - double maxValue = height > 3000 ? 3 : (1 + 2 * ((height - 1500) / 1500)); - double value = random.nextDouble() * maxValue; - if (value < quarterChance) { - tile = TileDataRegistry.getInstance().get("Test:SnowQuarter"); - } else if ((value -= quarterChance) < halfChance) { - tile = TileDataRegistry.getInstance().get("Test:SnowHalf"); - } else if ((value -= halfChance) < opaqueChance) { - tile = TileDataRegistry.getInstance().get("Test:SnowOpaque"); - } else { - tile = null; - } - - if (tile != null) { - world.getTiles(biw, face).addFarthest(tile); - } - } - } - - private double computeSnowQuarterChance(double height, double grad) { - double heightCoeff; - - if (height < 1500) - heightCoeff = 0; - else if (height < 2000) - heightCoeff = (height - 1500) / 500; - else - heightCoeff = 1; - - if (heightCoeff < 1e-4) - return 0; - - double gradCoeff = computeSnowGradCoeff(height, grad); - return heightCoeff * gradCoeff; - } - - private double computeSnowHalfChance(double height, double grad) { - double heightCoeff; - - if (height < 2000) - heightCoeff = 0; - else if (height < 2500) - heightCoeff = (height - 2000) / 500; - else - heightCoeff = 1; - - if (heightCoeff < 1e-4) - return 0; - - double gradCoeff = computeSnowGradCoeff(height, grad); - return heightCoeff * gradCoeff; - } - - private double computeSnowOpaqueChance(double height, double grad) { - double heightCoeff; - - if (height < 2500) - heightCoeff = 0; - else if (height < 3000) - heightCoeff = (height - 2500) / 500; - else - heightCoeff = 1; - - if (heightCoeff < 1e-4) - return 0; - - double gradCoeff = computeSnowGradCoeff(height, grad); - return heightCoeff * gradCoeff; - } - - private double computeSnowGradCoeff(double height, double grad) { - final double a = -0.00466666666666667; - final double b = 12.66666666666667; - double characteristicGrad = 1 / (a * height + b); - return Math.exp(-grad / characteristicGrad); - } - -} diff --git a/src/main/java/ru/windcorp/progressia/test/gen/planet/TestHeightMap.java b/src/main/java/ru/windcorp/progressia/test/gen/planet/TestHeightMap.java deleted file mode 100644 index 2141c63..0000000 --- a/src/main/java/ru/windcorp/progressia/test/gen/planet/TestHeightMap.java +++ /dev/null @@ -1,70 +0,0 @@ -/* - * 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 . - */ -package ru.windcorp.progressia.test.gen.planet; - -import ru.windcorp.progressia.common.world.rels.AbsFace; -import ru.windcorp.progressia.test.gen.surface.SurfaceFloatField; - -public class TestHeightMap implements SurfaceFloatField { - - private final float cutoffPoint; - private final float cutoffDistance; - private final float amplitude; - private final float characteristicSize; - - public TestHeightMap( - float cutoffPoint, - float cutoffDistance, - float amplitude, - float characteristicSize - ) { - this.cutoffPoint = cutoffPoint; - this.cutoffDistance = cutoffDistance; - this.amplitude = amplitude; - this.characteristicSize = characteristicSize; - } - - @Override - public float get(AbsFace face, float north, float west) { - double cutoffCoefficient = 1; - cutoffCoefficient *= cutoffFunction(cutoffPoint - north); - cutoffCoefficient *= cutoffFunction(cutoffPoint + north); - cutoffCoefficient *= cutoffFunction(cutoffPoint - west); - cutoffCoefficient *= cutoffFunction(cutoffPoint + west); - - if (cutoffCoefficient == 0) { - return 0; - } - - double base = Math.sin(north / characteristicSize) * Math.sin(west / characteristicSize); - base *= amplitude; - - return (float) (base * cutoffCoefficient); - } - - private double cutoffFunction(float distanceToCutoffPoint) { - if (distanceToCutoffPoint < 0) { - return 0; - } else if (distanceToCutoffPoint < cutoffDistance) { - return (1 - Math.cos(Math.PI * distanceToCutoffPoint / cutoffDistance)) / 2; - } else { - return 1; - } - } - -} diff --git a/src/main/java/ru/windcorp/progressia/test/gen/surface/SurfaceCachingFloatField.java b/src/main/java/ru/windcorp/progressia/test/gen/surface/SurfaceCachingFloatField.java deleted file mode 100644 index 01a98f0..0000000 --- a/src/main/java/ru/windcorp/progressia/test/gen/surface/SurfaceCachingFloatField.java +++ /dev/null @@ -1,77 +0,0 @@ -/* - * 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 . - */ -package ru.windcorp.progressia.test.gen.surface; - -import ru.windcorp.progressia.common.util.namespaces.Namespaced; -import ru.windcorp.progressia.common.world.rels.AbsFace; - -/** - * A scalar field defined on a plane. For each pair of {@code float}s (north; west) a single {@code float} is defined by this object. - */ -public abstract class SurfaceCachingFloatField extends Namespaced implements SurfaceFloatField { - - private final int levels; - - private SurfaceFieldRegistry registry = null; - private int index; - - public SurfaceCachingFloatField(String id, int levels) { - super(id); - this.levels = levels; - } - - int getIndex() { - if (getRegistry() == null) { - throw new IllegalStateException("No registry assigned to field " + this); - } - return index; - } - - void setIndex(int index) { - if (getRegistry() == null) { - throw new IllegalStateException("No registry assigned to field " + this); - } - this.index = index; - } - - SurfaceFieldRegistry getRegistry() { - return registry; - } - - void setRegistry(SurfaceFieldRegistry registry) { - this.registry = registry; - } - - public int getLevels() { - return levels; - } - - protected abstract float computeDetailAt(AbsFace surface, int level, float north, float west); - - @Override - public float get(AbsFace surface, float north, float west) { - float result = 0; - - for (int level = 0; level < getLevels(); ++level) { - result += computeDetailAt(surface, level, north, west); - } - - return result; - } - -} diff --git a/src/main/java/ru/windcorp/progressia/test/gen/surface/SurfaceFieldRegistry.java b/src/main/java/ru/windcorp/progressia/test/gen/surface/SurfaceFieldRegistry.java deleted file mode 100644 index f1decd4..0000000 --- a/src/main/java/ru/windcorp/progressia/test/gen/surface/SurfaceFieldRegistry.java +++ /dev/null @@ -1,29 +0,0 @@ -/* - * 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 . - */ -package ru.windcorp.progressia.test.gen.surface; - -public class SurfaceFieldRegistry { - - private int nextIndex = 0; - - public void register(SurfaceCachingFloatField field) { - field.setIndex(nextIndex); - nextIndex++; - } - -} diff --git a/src/main/java/ru/windcorp/progressia/test/gen/surface/SurfaceNodeStorage.java b/src/main/java/ru/windcorp/progressia/test/gen/surface/SurfaceNodeStorage.java deleted file mode 100644 index ad1ec39..0000000 --- a/src/main/java/ru/windcorp/progressia/test/gen/surface/SurfaceNodeStorage.java +++ /dev/null @@ -1,57 +0,0 @@ -/* - * 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 . - */ -package ru.windcorp.progressia.test.gen.surface; - -import java.io.DataInput; -import java.io.DataOutput; -import java.io.IOException; - -import gnu.trove.map.TLongObjectMap; -import gnu.trove.map.hash.TLongObjectHashMap; -import ru.windcorp.progressia.common.util.CoordinatePacker; -import ru.windcorp.progressia.common.world.DecodingException; - -public class SurfaceNodeStorage { - - public static class Node { -// private float[] floats; - } - - private final TLongObjectMap map = new TLongObjectHashMap<>(); - - public Node getNode(int north, int west) { - return map.get(CoordinatePacker.pack2IntsIntoLong(north, west)); - } - - public boolean hasNode(int north, int west) { - return map.containsKey(CoordinatePacker.pack2IntsIntoLong(north, west)); - } - - public void put(int north, int west, Node node) { - map.put(CoordinatePacker.pack2IntsIntoLong(north, west), node); - } - - public void read(DataInput input) throws IOException, DecodingException { - System.err.println("PlaneNodeMap.read did nothing because nobody implemented it yet"); - } - - public void write(DataOutput output) throws IOException { - System.err.println("PlaneNodeMap.write did nothing because nobody implemented it yet"); - } - -}