diff --git a/src/main/java/ru/windcorp/progressia/common/world/generic/GenericChunk.java b/src/main/java/ru/windcorp/progressia/common/world/generic/GenericChunk.java
index f9401d8..0748a34 100644
--- a/src/main/java/ru/windcorp/progressia/common/world/generic/GenericChunk.java
+++ b/src/main/java/ru/windcorp/progressia/common/world/generic/GenericChunk.java
@@ -244,13 +244,17 @@ public interface GenericChunk<
}
default void forEachBiW(Consumer super Vec3i> action) {
+ int minX = Coordinates.getInWorld(getX(), 0);
+ int minY = Coordinates.getInWorld(getY(), 0);
+ int minZ = Coordinates.getInWorld(getZ(), 0);
+
VectorUtil.iterateCuboid(
- Coordinates.getInWorld(getX(), 0),
- Coordinates.getInWorld(getY(), 0),
- Coordinates.getInWorld(getZ(), 0),
- BLOCKS_PER_CHUNK,
- BLOCKS_PER_CHUNK,
- BLOCKS_PER_CHUNK,
+ minX,
+ minY,
+ minZ,
+ minX + BLOCKS_PER_CHUNK,
+ minY + BLOCKS_PER_CHUNK,
+ minZ + BLOCKS_PER_CHUNK,
action
);
}
diff --git a/src/main/java/ru/windcorp/progressia/test/TestBushFeature.java b/src/main/java/ru/windcorp/progressia/test/TestBushFeature.java
new file mode 100644
index 0000000..9e99314
--- /dev/null
+++ b/src/main/java/ru/windcorp/progressia/test/TestBushFeature.java
@@ -0,0 +1,45 @@
+/*
+ * 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.world.ChunkData;
+import ru.windcorp.progressia.common.world.block.BlockData;
+import ru.windcorp.progressia.common.world.block.BlockDataRegistry;
+import ru.windcorp.progressia.test.gen.surface.SurfaceFeature;
+import ru.windcorp.progressia.test.gen.surface.SurfaceWorld;
+
+public class TestBushFeature extends SurfaceFeature {
+
+ public TestBushFeature(String id) {
+ super(id);
+ }
+
+ @Override
+ public void process(SurfaceWorld world, Request request) {
+ BlockData block = BlockDataRegistry.getInstance().get("Test:Log");
+
+ Vec3i location = new Vec3i(request.getRandom().nextInt(ChunkData.BLOCKS_PER_CHUNK), request.getRandom().nextInt(ChunkData.BLOCKS_PER_CHUNK), request.getRandom().nextInt(ChunkData.BLOCKS_PER_CHUNK)).add(request.getMin());
+ if (world.getBlockSfc(location) == BlockDataRegistry.getInstance().get("Test:Air")) {
+
+ world.setBlockSfc(location, block, false);
+
+ }
+ }
+
+}
diff --git a/src/main/java/ru/windcorp/progressia/test/gen/planet/PlanetFeatureGenerator.java b/src/main/java/ru/windcorp/progressia/test/gen/planet/PlanetFeatureGenerator.java
index 79f0593..1f69e00 100644
--- a/src/main/java/ru/windcorp/progressia/test/gen/planet/PlanetFeatureGenerator.java
+++ b/src/main/java/ru/windcorp/progressia/test/gen/planet/PlanetFeatureGenerator.java
@@ -19,40 +19,40 @@ package ru.windcorp.progressia.test.gen.planet;
import java.util.ArrayList;
import java.util.Collection;
-import java.util.Random;
+import java.util.Map;
import glm.vec._3.i.Vec3i;
import ru.windcorp.progressia.common.util.VectorUtil;
import ru.windcorp.progressia.common.world.ChunkData;
-import ru.windcorp.progressia.common.world.block.BlockDataRegistry;
+import ru.windcorp.progressia.common.world.rels.AbsFace;
+import ru.windcorp.progressia.test.TestBushFeature;
+import ru.windcorp.progressia.test.gen.surface.Surface;
import ru.windcorp.progressia.test.gen.surface.SurfaceFeature;
import ru.windcorp.progressia.test.gen.surface.SurfaceFeatureGenerator;
public class PlanetFeatureGenerator {
-
+
private final TestPlanetGenerator parent;
- private final SurfaceFeatureGenerator surfaceGenerator;
+
+ private final Map surfaceGenerators;
public PlanetFeatureGenerator(TestPlanetGenerator generator) {
this.parent = generator;
-
+
Collection features = new ArrayList<>();
- features.add(new SurfaceFeature("Test:GlassFeature") {
- @Override
- public void process(ChunkData chunk, Random random) {
-
- chunk.setBlockRel(new Vec3i(8, 8, 8), BlockDataRegistry.getInstance().get("Test:Glass"), true);
-
- }
- });
+ features.add(new TestBushFeature("Test:BushFeature"));
- this.surfaceGenerator = new SurfaceFeatureGenerator(features);
+ int seaLevel = (int) parent.getPlanet().getRadius();
+ this.surfaceGenerators = AbsFace.mapToFaces(face -> new SurfaceFeatureGenerator(
+ new Surface(face, seaLevel),
+ features
+ ));
}
-
+
public TestPlanetGenerator getGenerator() {
return parent;
}
-
+
public void generateFeatures(ChunkData chunk) {
if (isOrdinaryChunk(chunk.getPosition())) {
generateOrdinaryFeatures(chunk);
@@ -67,7 +67,7 @@ public class PlanetFeatureGenerator {
}
private void generateOrdinaryFeatures(ChunkData chunk) {
- surfaceGenerator.generateFeatures(chunk);
+ surfaceGenerators.get(chunk.getUp()).generateFeatures(chunk);
}
private void generateBorderFeatures(ChunkData chunk) {
diff --git a/src/main/java/ru/windcorp/progressia/test/gen/planet/PlanetTerrainGenerator.java b/src/main/java/ru/windcorp/progressia/test/gen/planet/PlanetTerrainGenerator.java
index a5b086f..649a6e9 100644
--- a/src/main/java/ru/windcorp/progressia/test/gen/planet/PlanetTerrainGenerator.java
+++ b/src/main/java/ru/windcorp/progressia/test/gen/planet/PlanetTerrainGenerator.java
@@ -26,7 +26,7 @@ import ru.windcorp.progressia.common.world.ChunkData;
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.GenericChunk;
+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;
@@ -90,7 +90,7 @@ class PlanetTerrainGenerator {
Vec3 biw = new Vec3();
- GenericChunk.forEachBiC(bic -> {
+ GenericChunks.forEachBiC(bic -> {
biw.set(
Coordinates.getInWorld(chunk.getX(), bic.x),
diff --git a/src/main/java/ru/windcorp/progressia/test/gen/surface/Surface.java b/src/main/java/ru/windcorp/progressia/test/gen/surface/Surface.java
new file mode 100644
index 0000000..0baa6f0
--- /dev/null
+++ b/src/main/java/ru/windcorp/progressia/test/gen/surface/Surface.java
@@ -0,0 +1,46 @@
+/*
+ * 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.world.rels.AbsFace;
+
+public class Surface {
+
+ private final AbsFace up;
+ private final int seaLevel;
+
+ public Surface(AbsFace up, int seaLevel) {
+ this.up = up;
+ this.seaLevel = seaLevel;
+ }
+
+ /**
+ * @return the up
+ */
+ public AbsFace getUp() {
+ return up;
+ }
+
+ /**
+ * @return the seaLevel
+ */
+ public int getSeaLevel() {
+ return seaLevel;
+ }
+
+}
diff --git a/src/main/java/ru/windcorp/progressia/test/gen/surface/SurfaceFeature.java b/src/main/java/ru/windcorp/progressia/test/gen/surface/SurfaceFeature.java
index 649b414..aa0ef6c 100644
--- a/src/main/java/ru/windcorp/progressia/test/gen/surface/SurfaceFeature.java
+++ b/src/main/java/ru/windcorp/progressia/test/gen/surface/SurfaceFeature.java
@@ -18,16 +18,137 @@
package ru.windcorp.progressia.test.gen.surface;
import java.util.Random;
+import java.util.function.Consumer;
+import glm.Glm;
+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.util.namespaces.Namespaced;
import ru.windcorp.progressia.common.world.ChunkData;
+import ru.windcorp.progressia.common.world.generic.GenericChunks;
+import ru.windcorp.progressia.common.world.rels.AxisRotations;
public abstract class SurfaceFeature extends Namespaced {
+ public static class Request {
+
+ private final ChunkData chunk;
+ private final Vec3i minSfc = new Vec3i();
+ private final Vec3i maxSfc = new Vec3i();
+
+ private final Random random;
+
+ public Request(ChunkData chunk, Random random) {
+ this.chunk = chunk;
+ this.random = random;
+
+ Vec3i absMin = chunk.getMinBIW(null);
+ Vec3i absMax = chunk.getMaxBIW(null);
+
+ AxisRotations.relativize(absMin, chunk.getUp(), absMin);
+ AxisRotations.relativize(absMax, chunk.getUp(), absMax);
+
+ Glm.min(absMin, absMax, minSfc);
+ Glm.max(absMin, absMax, maxSfc);
+ }
+
+ public ChunkData getChunk() {
+ return chunk;
+ }
+
+ public Random getRandom() {
+ return random;
+ }
+
+ public int getMinX() {
+ return minSfc.x;
+ }
+
+ public int getMaxX() {
+ return maxSfc.x;
+ }
+
+ public int getMinY() {
+ return minSfc.y;
+ }
+
+ public int getMaxY() {
+ return maxSfc.y;
+ }
+
+ public int getMinZ() {
+ return minSfc.z;
+ }
+
+ public int getMaxZ() {
+ return maxSfc.z;
+ }
+
+ public Vec3i getMin() {
+ return minSfc;
+ }
+
+ public Vec3i getMax() {
+ return maxSfc;
+ }
+
+ public boolean contains(Vec3i surfaceBlockInWorld) {
+ Vec3i bic = Vectors.grab3i();
+ bic.set(surfaceBlockInWorld.x, surfaceBlockInWorld.y, surfaceBlockInWorld.z);
+ bic.sub(minSfc);
+ boolean result = GenericChunks.containsBiC(bic);
+ Vectors.release(bic);
+ return result;
+ }
+
+ public void forEach(Consumer super Vec3i> action) {
+ VectorUtil.iterateCuboid(
+ minSfc.x,
+ minSfc.y,
+ minSfc.z,
+ maxSfc.x + 1,
+ maxSfc.y + 1,
+ maxSfc.z + 1,
+ action
+ );
+ }
+
+ /**
+ * Provided vectors have z set to {@link #getMinZ()}.
+ */
+ public void forEachOnFloor(Consumer super Vec3i> action) {
+ forEachOnLayer(action, getMinZ());
+ }
+
+ /**
+ * Provided vectors have z set to {@link #getMaxZ()}.
+ */
+ public void forEachOnCeiling(Consumer super Vec3i> action) {
+ forEachOnLayer(action, getMaxZ());
+ }
+
+ /**
+ * Provided vectors have z set to layer.
+ */
+ public void forEachOnLayer(Consumer super Vec3i> action, int layer) {
+ VectorUtil.iterateCuboid(
+ minSfc.x,
+ minSfc.y,
+ layer,
+ maxSfc.x + 1,
+ maxSfc.y + 1,
+ layer + 1,
+ action
+ );
+ }
+
+ }
+
public SurfaceFeature(String id) {
super(id);
}
-
- public abstract void process(ChunkData chunk, Random random);
+
+ public abstract void process(SurfaceWorld world, Request request);
}
diff --git a/src/main/java/ru/windcorp/progressia/test/gen/surface/SurfaceFeatureGenerator.java b/src/main/java/ru/windcorp/progressia/test/gen/surface/SurfaceFeatureGenerator.java
index 753256a..ade7869 100644
--- a/src/main/java/ru/windcorp/progressia/test/gen/surface/SurfaceFeatureGenerator.java
+++ b/src/main/java/ru/windcorp/progressia/test/gen/surface/SurfaceFeatureGenerator.java
@@ -26,17 +26,30 @@ import ru.windcorp.progressia.common.world.ChunkData;
public class SurfaceFeatureGenerator {
+ private final Surface surface;
+
private final Collection features; // TODO make ordered
- public SurfaceFeatureGenerator(Collection features) {
+ public SurfaceFeatureGenerator(Surface surface, Collection features) {
+ this.surface = surface;
this.features = new ArrayList<>(features);
}
+ /**
+ * @return the surface
+ */
+ public Surface getSurface() {
+ return surface;
+ }
+
public void generateFeatures(ChunkData chunk) {
+ SurfaceWorld world = new SurfaceWorld(surface, chunk.getWorld());
+
Random random = new Random(CoordinatePacker.pack3IntsIntoLong(chunk.getPosition()) /* ^ seed*/);
+ SurfaceFeature.Request request = new SurfaceFeature.Request(chunk, random);
for (SurfaceFeature feature : features) {
- feature.process(chunk, random);
+ feature.process(world, request);
}
chunk.setGenerationHint(true);
diff --git a/src/main/java/ru/windcorp/progressia/test/gen/surface/SurfaceWorld.java b/src/main/java/ru/windcorp/progressia/test/gen/surface/SurfaceWorld.java
new file mode 100644
index 0000000..740cc50
--- /dev/null
+++ b/src/main/java/ru/windcorp/progressia/test/gen/surface/SurfaceWorld.java
@@ -0,0 +1,168 @@
+/*
+ * 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.util.Collection;
+
+import glm.vec._3.i.Vec3i;
+import ru.windcorp.progressia.common.util.Vectors;
+import ru.windcorp.progressia.common.world.ChunkData;
+import ru.windcorp.progressia.common.world.block.BlockData;
+import ru.windcorp.progressia.common.world.entity.EntityData;
+import ru.windcorp.progressia.common.world.generic.GenericChunks;
+import ru.windcorp.progressia.common.world.generic.GenericWritableWorld;
+import ru.windcorp.progressia.common.world.rels.BlockFace;
+import ru.windcorp.progressia.common.world.tile.TileData;
+import ru.windcorp.progressia.common.world.tile.TileDataReference;
+import ru.windcorp.progressia.common.world.tile.TileDataStack;
+
+public class SurfaceWorld implements GenericWritableWorld {
+
+ private final Surface surface;
+ private final GenericWritableWorld parent;
+
+ public SurfaceWorld(
+ Surface surface,
+ GenericWritableWorld parent
+ ) {
+ this.surface = surface;
+ this.parent = parent;
+ }
+
+ /**
+ * @return the surface
+ */
+ public Surface getSurface() {
+ return surface;
+ }
+
+ /**
+ * @return the parent
+ */
+ public GenericWritableWorld getParent() {
+ return parent;
+ }
+
+ /*
+ * Delegate methods
+ */
+
+ @Override
+ public Collection getChunks() {
+ return parent.getChunks();
+ }
+
+ @Override
+ public ChunkData getChunk(Vec3i pos) {
+ return parent.getChunk(pos);
+ }
+
+ @Override
+ public Collection getEntities() {
+ return parent.getEntities();
+ }
+
+ @Override
+ public EntityData getEntity(long entityId) {
+ return parent.getEntity(entityId);
+ }
+
+ @Override
+ public void setBlock(Vec3i blockInWorld, BlockData block, boolean notify) {
+ parent.setBlock(blockInWorld, block, notify);
+ }
+
+ @Override
+ public void addEntity(EntityData entity) {
+ parent.addEntity(entity);
+ }
+
+ @Override
+ public void removeEntity(long entityId) {
+ parent.removeEntity(entityId);
+ }
+
+ public Vec3i resolve(Vec3i surfacePosition, Vec3i output) {
+ if (output == null) {
+ output = new Vec3i();
+ }
+
+ output.set(surfacePosition.x, surfacePosition.y, surfacePosition.z);
+ output.z -= getSurface().getSeaLevel();
+
+ GenericChunks.resolve(surfacePosition, output, getSurface().getUp());
+
+ return output;
+ }
+
+ public BlockData getBlockSfc(Vec3i surfaceBlockInWorld) {
+ Vec3i blockInWorld = Vectors.grab3i();
+ resolve(surfaceBlockInWorld, blockInWorld);
+ BlockData result = parent.getBlock(blockInWorld);
+ Vectors.release(blockInWorld);
+ return result;
+ }
+
+ public void setBlockSfc(Vec3i surfaceBlockInWorld, BlockData block, boolean notify) {
+ Vec3i blockInWorld = Vectors.grab3i();
+ resolve(surfaceBlockInWorld, blockInWorld);
+ parent.setBlock(blockInWorld, block, notify);
+ Vectors.release(blockInWorld);
+ }
+
+ public TileDataStack getTilesSfc(Vec3i surfaceBlockInWorld, BlockFace face) {
+ Vec3i blockInWorld = Vectors.grab3i();
+ resolve(surfaceBlockInWorld, blockInWorld);
+ TileDataStack result = parent.getTiles(blockInWorld, face);
+ Vectors.release(blockInWorld);
+ return result;
+ }
+
+ public TileDataStack getTilesOrNullSfc(Vec3i surfaceBlockInWorld, BlockFace face) {
+ Vec3i blockInWorld = Vectors.grab3i();
+ resolve(surfaceBlockInWorld, blockInWorld);
+ TileDataStack result = parent.getTilesOrNull(blockInWorld, face);
+ Vectors.release(blockInWorld);
+ return result;
+ }
+
+ public boolean hasTilesSfc(Vec3i surfaceBlockInWorld, BlockFace face) {
+ Vec3i blockInWorld = Vectors.grab3i();
+ resolve(surfaceBlockInWorld, blockInWorld);
+ boolean result = parent.hasTiles(blockInWorld, face);
+ Vectors.release(blockInWorld);
+ return result;
+ }
+
+ public TileData getTileSfc(Vec3i surfaceBlockInWorld, BlockFace face, int layer) {
+ Vec3i blockInWorld = Vectors.grab3i();
+ resolve(surfaceBlockInWorld, blockInWorld);
+ TileData result = parent.getTile(blockInWorld, face, layer);
+ Vectors.release(blockInWorld);
+ return result;
+ }
+
+ public boolean isBlockLoadedSfc(Vec3i surfaceBlockInWorld) {
+ Vec3i blockInWorld = Vectors.grab3i();
+ resolve(surfaceBlockInWorld, blockInWorld);
+ boolean result = parent.isBlockLoaded(blockInWorld);
+ Vectors.release(blockInWorld);
+ return result;
+ }
+
+}