Some more refactoring of generic world-related classes. May not compile.

- Added GenericWritableWorld
- Moved static methods from GenericChunk to GenericChunks
- GenericEntity now declares getEntityId()
- GenericWorld now declares getEntity(long)
- Added a lambda-based mapToFaces variations for AbsFace and RelFace
This commit is contained in:
OLEGSHA 2021-04-09 23:13:21 +03:00
parent a95bdf1efe
commit 20dccf3d12
Signed by: OLEGSHA
GPG Key ID: E57A4B08D64AFF7A
17 changed files with 196 additions and 93 deletions

View File

@ -36,7 +36,7 @@ import ru.windcorp.progressia.client.world.tile.TileRender;
import ru.windcorp.progressia.client.world.tile.TileRenderNone;
import ru.windcorp.progressia.client.world.tile.TileRenderStack;
import ru.windcorp.progressia.common.world.ChunkData;
import ru.windcorp.progressia.common.world.generic.GenericChunk;
import ru.windcorp.progressia.common.world.generic.GenericChunks;
import ru.windcorp.progressia.common.world.rels.AxisRotations;
import ru.windcorp.progressia.common.world.rels.RelFace;
@ -77,7 +77,7 @@ public class ChunkRenderModel implements Renderable {
optimizers.forEach(ChunkRenderOptimizer::startRender);
GenericChunk.forEachBiC(relBlockInChunk -> {
GenericChunks.forEachBiC(relBlockInChunk -> {
processBlockAndTiles(relBlockInChunk, sink);
});

View File

@ -111,6 +111,13 @@ public class WorldRender
public Collection<EntityRenderable> getEntities() {
return entityModels.values();
}
@Override
public EntityRenderable getEntity(long entityId) {
EntityData entityData = getData().getEntity(entityId);
if (entityData == null) return null;
return getEntityRenderable(entityData);
}
public void render(ShapeRenderHelper renderer) {
updateChunks();

View File

@ -38,7 +38,7 @@ import ru.windcorp.progressia.client.world.block.BlockRender;
import ru.windcorp.progressia.client.world.tile.TileRender;
import ru.windcorp.progressia.common.util.Vectors;
import ru.windcorp.progressia.common.world.ChunkData;
import ru.windcorp.progressia.common.world.generic.GenericChunk;
import ru.windcorp.progressia.common.world.generic.GenericChunks;
import ru.windcorp.progressia.common.world.rels.RelFace;
public class ChunkRenderOptimizerSurface extends ChunkRenderOptimizer {
@ -217,7 +217,7 @@ public class ChunkRenderOptimizerSurface extends ChunkRenderOptimizer {
Consumer<ShapePart> consumer = shapeParts::add;
GenericChunk.forEachBiC(relBlockInChunk -> {
GenericChunks.forEachBiC(relBlockInChunk -> {
processInnerFaces(relBlockInChunk, consumer);
processOuterFaces(relBlockInChunk, consumer);
});
@ -316,7 +316,7 @@ public class ChunkRenderOptimizerSurface extends ChunkRenderOptimizer {
}
private boolean shouldRenderWhenFacing(Vec3i relBlockInChunk, RelFace face) {
if (GenericChunk.containsBiC(relBlockInChunk)) {
if (GenericChunks.containsBiC(relBlockInChunk)) {
return shouldRenderWhenFacingLocal(relBlockInChunk, face);
} else {
return shouldRenderWhenFacingNeighbor(relBlockInChunk, face);

View File

@ -71,6 +71,11 @@ public abstract class EntityRenderable implements Renderable, GenericEntity {
public String getId() {
return getData().getId();
}
@Override
public long getEntityId() {
return getData().getEntityId();
}
public final Vec3 getLookingAt(Vec3 output) {
if (output == null) output = new Vec3();

View File

@ -29,7 +29,7 @@ import java.util.Objects;
import glm.vec._3.i.Vec3i;
import ru.windcorp.progressia.common.world.block.BlockData;
import ru.windcorp.progressia.common.world.generic.GenericChunk;
import ru.windcorp.progressia.common.world.generic.GenericChunks;
import ru.windcorp.progressia.common.world.generic.GenericWritableChunk;
import ru.windcorp.progressia.common.world.rels.AbsFace;
import ru.windcorp.progressia.common.world.rels.BlockFace;
@ -160,7 +160,7 @@ public class ChunkData
}
private static void checkLocalCoordinates(Vec3i posInChunk) {
if (!GenericChunk.containsBiC(posInChunk)) {
if (!GenericChunks.containsBiC(posInChunk)) {
throw new IllegalCoordinatesException(
"Coordinates (" + posInChunk.x + "; " + posInChunk.y + "; " + posInChunk.z + ") "
+ "are not legal chunk coordinates"

View File

@ -34,14 +34,14 @@ import ru.windcorp.progressia.common.world.block.BlockData;
import ru.windcorp.progressia.common.world.entity.EntityData;
import ru.windcorp.progressia.common.world.generic.ChunkMap;
import ru.windcorp.progressia.common.world.generic.ChunkSet;
import ru.windcorp.progressia.common.world.generic.GenericWorld;
import ru.windcorp.progressia.common.world.generic.GenericWritableWorld;
import ru.windcorp.progressia.common.world.generic.LongBasedChunkMap;
import ru.windcorp.progressia.common.world.tile.TileData;
import ru.windcorp.progressia.common.world.tile.TileDataStack;
import ru.windcorp.progressia.common.world.tile.TileDataReference;
public class WorldData
implements GenericWorld<BlockData, TileData, TileDataStack, TileDataReference, ChunkData, EntityData> {
implements GenericWritableWorld<BlockData, TileData, TileDataStack, TileDataReference, ChunkData, EntityData> {
private final ChunkMap<ChunkData> chunksByPos = new LongBasedChunkMap<>(
TCollections.synchronizedMap(new TLongObjectHashMap<>())
@ -128,6 +128,7 @@ public class WorldData
chunksByPos.remove(chunk);
}
@Override
public void setBlock(Vec3i blockInWorld, BlockData block, boolean notify) {
ChunkData chunk = getChunkByBlock(blockInWorld);
if (chunk == null)
@ -140,10 +141,12 @@ public class WorldData
chunk.setBlock(Coordinates.convertInWorldToInChunk(blockInWorld, null), block, notify);
}
@Override
public EntityData getEntity(long entityId) {
return entitiesById.get(entityId);
}
@Override
public void addEntity(EntityData entity) {
Objects.requireNonNull(entity, "entity");
@ -164,6 +167,7 @@ public class WorldData
getListeners().forEach(l -> l.onEntityAdded(this, entity));
}
@Override
public void removeEntity(long entityId) {
synchronized (entitiesById) {
EntityData entity = entitiesById.get(entityId);
@ -178,6 +182,7 @@ public class WorldData
}
}
@Override
public void removeEntity(EntityData entity) {
Objects.requireNonNull(entity, "entity");

View File

@ -85,6 +85,7 @@ public class EntityData extends StatefulObject implements Collideable, GenericEn
this.velocity.set(velocity);
}
@Override
public long getEntityId() {
return entityId;
}

View File

@ -106,20 +106,7 @@ public interface GenericChunk<
boolean hasTiles(Vec3i blockInChunk, BlockFace face);
default Vec3i resolve(Vec3i relativeCoords, Vec3i output) {
if (output == null) {
output = new Vec3i();
}
final int offset = BLOCKS_PER_CHUNK - 1;
output.set(relativeCoords.x, relativeCoords.y, relativeCoords.z);
output.mul(2).sub(offset);
AxisRotations.resolve(output, getUp(), output);
output.add(offset).div(2);
return output;
return GenericChunks.resolve(relativeCoords, output, getUp());
}
default B getBlockRel(Vec3i relativeBlockInChunk) {
@ -240,50 +227,20 @@ public interface GenericChunk<
return output;
}
public static boolean containsBiC(Vec3i blockInChunk) {
return blockInChunk.x >= 0 && blockInChunk.x < BLOCKS_PER_CHUNK &&
blockInChunk.y >= 0 && blockInChunk.y < BLOCKS_PER_CHUNK &&
blockInChunk.z >= 0 && blockInChunk.z < BLOCKS_PER_CHUNK;
}
public static boolean isSurfaceBiC(Vec3i blockInChunk) {
return Util.getBorderHits(blockInChunk) >= 1;
}
public static boolean isEdgeBiC(Vec3i blockInChunk) {
return Util.getBorderHits(blockInChunk) >= 2;
}
public static boolean isVertexBiC(Vec3i blockInChunk) {
return Util.getBorderHits(blockInChunk) == 3;
}
default boolean containsBiW(Vec3i blockInWorld) {
return Util.testBiC(blockInWorld, this, GenericChunk::containsBiC);
return GenericChunks.testBiC(blockInWorld, this, GenericChunks::containsBiC);
}
default boolean isSurfaceBiW(Vec3i blockInWorld) {
return Util.testBiC(blockInWorld, this, GenericChunk::isSurfaceBiC);
return GenericChunks.testBiC(blockInWorld, this, GenericChunks::isSurfaceBiC);
}
default boolean isEdgeBiW(Vec3i blockInWorld) {
return Util.testBiC(blockInWorld, this, GenericChunk::isEdgeBiC);
return GenericChunks.testBiC(blockInWorld, this, GenericChunks::isEdgeBiC);
}
default boolean isVertexBiW(Vec3i blockInWorld) {
return Util.testBiC(blockInWorld, this, GenericChunk::isVertexBiC);
}
public static void forEachBiC(Consumer<? super Vec3i> action) {
VectorUtil.iterateCuboid(
0,
0,
0,
BLOCKS_PER_CHUNK,
BLOCKS_PER_CHUNK,
BLOCKS_PER_CHUNK,
action
);
return GenericChunks.testBiC(blockInWorld, this, GenericChunks::isVertexBiC);
}
default void forEachBiW(Consumer<? super Vec3i> action) {
@ -324,7 +281,7 @@ public interface GenericChunk<
}
default void forEachTileStack(Consumer<TS> action) {
forEachBiC(blockInChunk -> {
GenericChunks.forEachBiC(blockInChunk -> {
for (AbsFace face : AbsFace.getFaces()) {
TS stack = getTilesOrNull(blockInChunk, face);
if (stack == null)

View File

@ -0,0 +1,102 @@
/*
* 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.common.world.generic;
import java.util.function.Consumer;
import java.util.function.Predicate;
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.Coordinates;
import ru.windcorp.progressia.common.world.rels.AbsFace;
import ru.windcorp.progressia.common.world.rels.AxisRotations;
public class GenericChunks {
public static Vec3i resolve(Vec3i relativeCoords, Vec3i output, AbsFace up) {
if (output == null) {
output = new Vec3i();
}
final int offset = GenericChunk.BLOCKS_PER_CHUNK - 1;
output.set(relativeCoords.x, relativeCoords.y, relativeCoords.z);
output.mul(2).sub(offset);
AxisRotations.resolve(output, up, output);
output.add(offset).div(2);
return output;
}
private static int getBorderHits(Vec3i blockInChunk) {
int hits = 0;
if (Coordinates.isOnChunkBorder(blockInChunk.x)) hits++;
if (Coordinates.isOnChunkBorder(blockInChunk.y)) hits++;
if (Coordinates.isOnChunkBorder(blockInChunk.z)) hits++;
return hits;
}
static boolean testBiC(Vec3i blockInWorld, GenericChunk<?, ?, ?, ?, ?> chunk, Predicate<Vec3i> test) {
Vec3i v = Vectors.grab3i();
v = Coordinates.getInWorld(chunk.getPosition(), Vectors.ZERO_3i, v);
v = blockInWorld.sub(v, v);
boolean result = test.test(v);
Vectors.release(v);
return result;
}
public static boolean containsBiC(Vec3i blockInChunk) {
return blockInChunk.x >= 0 && blockInChunk.x < GenericChunk.BLOCKS_PER_CHUNK &&
blockInChunk.y >= 0 && blockInChunk.y < GenericChunk.BLOCKS_PER_CHUNK &&
blockInChunk.z >= 0 && blockInChunk.z < GenericChunk.BLOCKS_PER_CHUNK;
}
public static boolean isSurfaceBiC(Vec3i blockInChunk) {
return GenericChunks.getBorderHits(blockInChunk) >= 1;
}
public static boolean isEdgeBiC(Vec3i blockInChunk) {
return GenericChunks.getBorderHits(blockInChunk) >= 2;
}
public static boolean isVertexBiC(Vec3i blockInChunk) {
return GenericChunks.getBorderHits(blockInChunk) == 3;
}
public static void forEachBiC(Consumer<? super Vec3i> action) {
VectorUtil.iterateCuboid(
0,
0,
0,
GenericChunk.BLOCKS_PER_CHUNK,
GenericChunk.BLOCKS_PER_CHUNK,
GenericChunk.BLOCKS_PER_CHUNK,
action
);
}
}

View File

@ -25,6 +25,8 @@ import ru.windcorp.progressia.common.world.Coordinates;
public interface GenericEntity {
String getId();
long getEntityId();
Vec3 getPosition();

View File

@ -46,6 +46,8 @@ public interface GenericWorld<
Collection<E> getEntities();
E getEntity(long entityId);
/*
* Chunks
*/

View File

@ -17,37 +17,29 @@
*/
package ru.windcorp.progressia.common.world.generic;
import java.util.function.Predicate;
import glm.vec._3.i.Vec3i;
import ru.windcorp.progressia.common.util.Vectors;
import ru.windcorp.progressia.common.world.Coordinates;
import ru.windcorp.progressia.common.world.block.BlockData;
class Util {
public static int getBorderHits(Vec3i blockInChunk) {
int hits = 0;
if (Coordinates.isOnChunkBorder(blockInChunk.x)) hits++;
if (Coordinates.isOnChunkBorder(blockInChunk.y)) hits++;
if (Coordinates.isOnChunkBorder(blockInChunk.z)) hits++;
return hits;
//@formatter:off
public interface GenericWritableWorld<
B extends GenericBlock,
T extends GenericTile,
TS extends GenericWritableTileStack <B, T, TS, TR, C>,
TR extends GenericTileReference <B, T, TS, TR, C>,
C extends GenericWritableChunk <B, T, TS, TR, C>,
E extends GenericEntity
>
extends GenericWorld<B, T, TS, TR, C, E> {
//@formatter:on
void setBlock(Vec3i blockInWorld, BlockData block, boolean notify);
void addEntity(E entity);
void removeEntity(long entityId);
default void removeEntity(E entity) {
removeEntity(entity.getEntityId());
}
public static boolean testBiC(Vec3i blockInWorld, GenericChunk<?, ?, ?, ?, ?> chunk, Predicate<Vec3i> test) {
Vec3i v = Vectors.grab3i();
v = Coordinates.getInWorld(chunk.getPosition(), Vectors.ZERO_3i, v);
v = blockInWorld.sub(v, v);
boolean result = test.test(v);
Vectors.release(v);
return result;
}
}

View File

@ -19,6 +19,7 @@
package ru.windcorp.progressia.common.world.rels;
import java.util.Objects;
import java.util.function.Function;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
@ -90,6 +91,17 @@ public final class AbsFace extends AbsRelation implements BlockFace {
.build();
}
public static <E> ImmutableMap<AbsFace, E> mapToFaces(Function<AbsFace, E> generator) {
return mapToFaces(
generator.apply(POS_Z),
generator.apply(NEG_Z),
generator.apply(POS_X),
generator.apply(NEG_X),
generator.apply(NEG_Y),
generator.apply(POS_Y)
);
}
/**
* Rounds the provided vector to one of {@link AbsFace}s. The returned face
* is pointing in the same general direction as the provided vector. The

View File

@ -17,6 +17,8 @@
*/
package ru.windcorp.progressia.common.world.rels;
import java.util.function.Function;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
@ -68,6 +70,17 @@ public class RelFace extends RelRelation implements BlockFace {
.put(EAST, east)
.build();
}
public static <E> ImmutableMap<RelFace, E> mapToFaces(Function<RelFace, E> generator) {
return mapToFaces(
generator.apply(UP),
generator.apply(DOWN),
generator.apply(NORTH),
generator.apply(SOUTH),
generator.apply(WEST),
generator.apply(EAST)
);
}
private static int nextId = 0;

View File

@ -22,7 +22,7 @@ import java.util.function.Consumer;
import glm.vec._3.i.Vec3i;
import ru.windcorp.progressia.common.world.ChunkData;
import ru.windcorp.progressia.common.world.generic.GenericChunk;
import ru.windcorp.progressia.common.world.generic.GenericChunks;
import ru.windcorp.progressia.common.world.rels.AbsFace;
import ru.windcorp.progressia.server.world.block.BlockTickContext;
@ -46,7 +46,7 @@ public interface ChunkTickContext extends TickContext {
default void forEachBlock(Consumer<BlockTickContext> action) {
TickContextMutable context = TickContextMutable.uninitialized();
GenericChunk.forEachBiC(blockInChunk -> {
GenericChunks.forEachBiC(blockInChunk -> {
context.rebuild().withServer(getServer()).withChunk(getChunk()).withBlockInChunk(blockInChunk).build();
action.accept(context);
});

View File

@ -90,6 +90,11 @@ public class WorldLogic
public Collection<EntityData> getEntities() {
return getData().getEntities();
}
@Override
public EntityData getEntity(long entityId) {
return getData().getEntity(entityId);
}
public Evaluation getTickEntitiesTask() {
return tickEntitiesTask;

View File

@ -38,7 +38,7 @@ import ru.windcorp.progressia.common.world.DecodingException;
import ru.windcorp.progressia.common.world.WorldData;
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.common.world.io.ChunkCodec;
import ru.windcorp.progressia.common.world.rels.RelFace;
import ru.windcorp.progressia.common.world.tile.TileData;
@ -125,7 +125,7 @@ public class TestChunkCodec extends ChunkCodec {
private void readBlocks(DataInput input, BlockData[] blockPalette, ChunkData chunk) throws IOException {
try {
GenericChunk.forEachBiC(guard(v -> {
GenericChunks.forEachBiC(guard(v -> {
chunk.setBlock(v, blockPalette[input.readInt()], false);
}));
} catch (UncheckedIOException e) {
@ -172,7 +172,7 @@ public class TestChunkCodec extends ChunkCodec {
private Palette<BlockData> createBlockPalette(ChunkData chunk) {
Palette<BlockData> blockPalette = new Palette<>();
GenericChunk.forEachBiC(v -> blockPalette.add(chunk.getBlock(v)));
GenericChunks.forEachBiC(v -> blockPalette.add(chunk.getBlock(v)));
return blockPalette;
}
@ -200,7 +200,7 @@ public class TestChunkCodec extends ChunkCodec {
private void writeBlocks(ChunkData chunk, Palette<BlockData> blockPalette, DataOutput output) throws IOException {
try {
GenericChunk.forEachBiC(guard(v -> {
GenericChunks.forEachBiC(guard(v -> {
output.writeInt(blockPalette.getNid(chunk.getBlock(v)));
}));
} catch (UncheckedIOException e) {