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 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 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 action) { + forEachOnLayer(action, getMinZ()); + } + + /** + * Provided vectors have z set to {@link #getMaxZ()}. + */ + public void forEachOnCeiling(Consumer action) { + forEachOnLayer(action, getMaxZ()); + } + + /** + * Provided vectors have z set to layer. + */ + public void forEachOnLayer(Consumer 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; + } + +}