Added SurfaceWorld to facilitate surface feature generation
This commit is contained in:
parent
20dccf3d12
commit
6fb7e7fc04
@ -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
|
||||
);
|
||||
}
|
||||
|
@ -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 <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
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);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -19,34 +19,34 @@ 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<AbsFace, SurfaceFeatureGenerator> surfaceGenerators;
|
||||
|
||||
public PlanetFeatureGenerator(TestPlanetGenerator generator) {
|
||||
this.parent = generator;
|
||||
|
||||
Collection<SurfaceFeature> features = new ArrayList<>();
|
||||
features.add(new SurfaceFeature("Test:GlassFeature") {
|
||||
@Override
|
||||
public void process(ChunkData chunk, Random random) {
|
||||
features.add(new TestBushFeature("Test:BushFeature"));
|
||||
|
||||
chunk.setBlockRel(new Vec3i(8, 8, 8), BlockDataRegistry.getInstance().get("Test:Glass"), true);
|
||||
|
||||
}
|
||||
});
|
||||
|
||||
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() {
|
||||
@ -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) {
|
||||
|
@ -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),
|
||||
|
@ -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 <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
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;
|
||||
}
|
||||
|
||||
}
|
@ -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);
|
||||
|
||||
}
|
||||
|
@ -26,17 +26,30 @@ import ru.windcorp.progressia.common.world.ChunkData;
|
||||
|
||||
public class SurfaceFeatureGenerator {
|
||||
|
||||
private final Surface surface;
|
||||
|
||||
private final Collection<SurfaceFeature> features; // TODO make ordered
|
||||
|
||||
public SurfaceFeatureGenerator(Collection<SurfaceFeature> features) {
|
||||
public SurfaceFeatureGenerator(Surface surface, Collection<SurfaceFeature> 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);
|
||||
|
@ -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 <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
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<BlockData, TileData, TileDataStack, TileDataReference, ChunkData, EntityData> {
|
||||
|
||||
private final Surface surface;
|
||||
private final GenericWritableWorld<BlockData, TileData, TileDataStack, TileDataReference, ChunkData, EntityData> parent;
|
||||
|
||||
public SurfaceWorld(
|
||||
Surface surface,
|
||||
GenericWritableWorld<BlockData, TileData, TileDataStack, TileDataReference, ChunkData, EntityData> parent
|
||||
) {
|
||||
this.surface = surface;
|
||||
this.parent = parent;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the surface
|
||||
*/
|
||||
public Surface getSurface() {
|
||||
return surface;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the parent
|
||||
*/
|
||||
public GenericWritableWorld<BlockData, TileData, TileDataStack, TileDataReference, ChunkData, EntityData> getParent() {
|
||||
return parent;
|
||||
}
|
||||
|
||||
/*
|
||||
* Delegate methods
|
||||
*/
|
||||
|
||||
@Override
|
||||
public Collection<ChunkData> getChunks() {
|
||||
return parent.getChunks();
|
||||
}
|
||||
|
||||
@Override
|
||||
public ChunkData getChunk(Vec3i pos) {
|
||||
return parent.getChunk(pos);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Collection<EntityData> 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;
|
||||
}
|
||||
|
||||
}
|
Reference in New Issue
Block a user