Added generic implementations of of Chunk and World classes

Also fixed a whole bunch of missing Override annotations
This commit is contained in:
OLEGSHA 2020-12-22 19:33:27 +03:00
parent a582727cc0
commit f921acf317
35 changed files with 612 additions and 202 deletions

View File

@ -192,6 +192,7 @@ public class VertexBufferObject implements OpenGLDeletable {
return usage;
}
@Override
public int getHandle() {
return handle;
}

View File

@ -91,6 +91,7 @@ public class Shader implements OpenGLDeletable {
);
}
@Override
public int getHandle() {
return handle;
}

View File

@ -24,6 +24,7 @@ import ru.windcorp.progressia.client.graphics.input.bus.Input;
public abstract class GUILayer extends AssembledFlatLayer {
private final Component root = new Component("Root") {
@Override
protected void handleReassemblyRequest() {
GUILayer.this.invalidate();
}

View File

@ -264,6 +264,7 @@ public class ShapeRenderProgram extends Program {
private final List<Vertex> vertices = new ArrayList<>();
@Override
public VertexBuilder addVertex(
float x, float y, float z,
float r, float g, float b,
@ -278,6 +279,7 @@ public class ShapeRenderProgram extends Program {
return this;
}
@Override
public VertexBuilder addVertex(
Vec3 position,
Vec3 colorMultiplier,
@ -292,6 +294,7 @@ public class ShapeRenderProgram extends Program {
return this;
}
@Override
public ByteBuffer assemble() {
ByteBuffer result = BufferUtils.createByteBuffer(
DEFAULT_BYTES_PER_VERTEX * vertices.size()

View File

@ -55,6 +55,7 @@ public abstract class MutableString {
return data;
}
@Override
public String toString() {
return get();
}

View File

@ -18,8 +18,11 @@
package ru.windcorp.progressia.client.world;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.WeakHashMap;
import java.util.stream.Collectors;
import glm.mat._4.Mat4;
@ -38,11 +41,20 @@ import ru.windcorp.progressia.client.world.cro.ChunkRenderOptimizerSupplier;
import ru.windcorp.progressia.client.world.cro.ChunkRenderOptimizers;
import ru.windcorp.progressia.client.world.tile.TileRender;
import ru.windcorp.progressia.client.world.tile.TileRenderRegistry;
import ru.windcorp.progressia.client.world.tile.TileRenderStack;
import ru.windcorp.progressia.common.world.ChunkData;
import ru.windcorp.progressia.common.world.block.BlockFace;
import ru.windcorp.progressia.common.world.generic.GenericChunk;
import ru.windcorp.progressia.common.world.tile.TileData;
import ru.windcorp.progressia.common.world.tile.TileDataStack;
public class ChunkRender {
public class ChunkRender
implements GenericChunk<
ChunkRender,
BlockRender,
TileRender,
TileRenderStack
> {
private final WorldRender world;
private final ChunkData data;
@ -50,11 +62,43 @@ public class ChunkRender {
private boolean needsUpdate;
private Model model = null;
private final Map<TileDataStack, TileRenderStackImpl> tileRenderLists =
Collections.synchronizedMap(new WeakHashMap<>());
public ChunkRender(WorldRender world, ChunkData data) {
this.world = world;
this.data = data;
}
@Override
public Vec3i getPosition() {
return getData().getPosition();
}
@Override
public BlockRender getBlock(Vec3i posInChunk) {
return BlockRenderRegistry.getInstance().get(
getData().getBlock(posInChunk).getId()
);
}
@Override
public TileRenderStack getTiles(Vec3i blockInChunk, BlockFace face) {
return getTileStackWrapper(getData().getTiles(blockInChunk, face));
}
@Override
public boolean hasTiles(Vec3i blockInChunk, BlockFace face) {
return getData().hasTiles(blockInChunk, face);
}
private TileRenderStack getTileStackWrapper(TileDataStack tileDataList) {
return tileRenderLists.computeIfAbsent(
tileDataList,
TileRenderStackImpl::new
);
}
public WorldRender getWorld() {
return world;
}
@ -71,12 +115,6 @@ public class ChunkRender {
return needsUpdate;
}
public BlockRender getBlock(Vec3i posInChunk) {
return BlockRenderRegistry.getInstance().get(
getData().getBlock(posInChunk).getId()
);
}
public void render(ShapeRenderHelper renderer) {
if (model == null || needsUpdate()) {
buildModel();
@ -233,4 +271,44 @@ public class ChunkRender {
);
}
private class TileRenderStackImpl extends TileRenderStack {
private final TileDataStack parent;
public TileRenderStackImpl(TileDataStack parent) {
this.parent = parent;
}
@Override
public Vec3i getBlockInChunk(Vec3i output) {
return parent.getBlockInChunk(output);
}
@Override
public ChunkRender getChunk() {
return ChunkRender.this;
}
@Override
public BlockFace getFace() {
return parent.getFace();
}
@Override
public TileRender get(int index) {
return TileRenderRegistry.getInstance().get(parent.get(index).getId());
}
@Override
public int size() {
return parent.size();
}
@Override
public TileDataStack getData() {
return parent;
}
}
}

View File

@ -26,15 +26,26 @@ import java.util.WeakHashMap;
import glm.vec._3.i.Vec3i;
import ru.windcorp.progressia.client.graphics.backend.FaceCulling;
import ru.windcorp.progressia.client.graphics.model.ShapeRenderHelper;
import ru.windcorp.progressia.client.world.block.BlockRender;
import ru.windcorp.progressia.client.world.entity.EntityRenderRegistry;
import ru.windcorp.progressia.client.world.entity.EntityRenderable;
import ru.windcorp.progressia.client.world.tile.TileRender;
import ru.windcorp.progressia.client.world.tile.TileRenderStack;
import ru.windcorp.progressia.common.world.ChunkData;
import ru.windcorp.progressia.common.world.ChunkDataListeners;
import ru.windcorp.progressia.common.world.WorldData;
import ru.windcorp.progressia.common.world.WorldDataListener;
import ru.windcorp.progressia.common.world.entity.EntityData;
import ru.windcorp.progressia.common.world.generic.GenericWorld;
public class WorldRender {
public class WorldRender
implements GenericWorld<
BlockRender,
TileRender,
TileRenderStack,
ChunkRender,
EntityRenderable
> {
private final WorldData data;
@ -67,14 +78,21 @@ public class WorldRender {
return chunks.get(chunkData);
}
@Override
public ChunkRender getChunk(Vec3i pos) {
return chunks.get(getData().getChunk(pos));
}
@Override
public Collection<ChunkRender> getChunks() {
return chunks.values();
}
@Override
public Collection<EntityRenderable> getEntities() {
return entityModels.values();
}
public void render(ShapeRenderHelper renderer) {
for (ChunkRender chunk : getChunks()) {
chunk.render(renderer);

View File

@ -19,9 +19,10 @@ package ru.windcorp.progressia.client.world.block;
import ru.windcorp.progressia.client.graphics.model.ShapeRenderHelper;
import ru.windcorp.progressia.common.util.namespaces.Namespaced;
import ru.windcorp.progressia.common.world.generic.GenericBlock;
import ru.windcorp.progressia.client.graphics.model.Renderable;
public abstract class BlockRender extends Namespaced {
public abstract class BlockRender extends Namespaced implements GenericBlock {
public BlockRender(String id) {
super(id);

View File

@ -18,8 +18,8 @@
package ru.windcorp.progressia.client.world.cro;
import static ru.windcorp.progressia.common.world.ChunkData.BLOCKS_PER_CHUNK;
import static ru.windcorp.progressia.common.world.tile.GenericTileStack.TILES_PER_FACE;
import static ru.windcorp.progressia.common.world.block.BlockFace.BLOCK_FACE_COUNT;
import static ru.windcorp.progressia.common.world.generic.GenericTileStack.TILES_PER_FACE;
import java.util.ArrayList;
import java.util.Collection;

View File

@ -3,8 +3,9 @@ package ru.windcorp.progressia.client.world.entity;
import glm.vec._3.Vec3;
import ru.windcorp.progressia.client.graphics.model.Renderable;
import ru.windcorp.progressia.common.world.entity.EntityData;
import ru.windcorp.progressia.common.world.generic.GenericEntity;
public abstract class EntityRenderable implements Renderable {
public abstract class EntityRenderable implements Renderable, GenericEntity {
private final EntityData data;
@ -16,6 +17,16 @@ public abstract class EntityRenderable implements Renderable {
return data;
}
@Override
public Vec3 getPosition() {
return getData().getPosition();
}
@Override
public String getId() {
return getData().getId();
}
public void getViewPoint(Vec3 output) {
output.set(0, 0, 0);
}

View File

@ -5,8 +5,9 @@ import ru.windcorp.progressia.client.graphics.model.Renderable;
import ru.windcorp.progressia.client.world.cro.ChunkRenderOptimizer;
import ru.windcorp.progressia.common.util.namespaces.Namespaced;
import ru.windcorp.progressia.common.world.block.BlockFace;
import ru.windcorp.progressia.common.world.generic.GenericTile;
public class TileRender extends Namespaced {
public class TileRender extends Namespaced implements GenericTile {
public TileRender(String id) {
super(id);

View File

@ -0,0 +1,16 @@
package ru.windcorp.progressia.client.world.tile;
import ru.windcorp.progressia.client.world.ChunkRender;
import ru.windcorp.progressia.common.world.generic.GenericTileStack;
import ru.windcorp.progressia.common.world.tile.TileDataStack;
public abstract class TileRenderStack
extends GenericTileStack<
TileRenderStack,
TileRender,
ChunkRender
> {
public abstract TileDataStack getData();
}

View File

@ -8,10 +8,12 @@ public class OptimizedStateStorage extends StateStorage {
this.ints = new int[sizes.getInts()];
}
@Override
public int getInt(int index) {
return ints[index];
}
@Override
public void setInt(int index, int value) {
ints[index] = value;
}

View File

@ -32,6 +32,7 @@ public class ByteBufferInputStream extends InputStream {
this.buffer = buffer;
}
@Override
public int read() {
if (!buffer.hasRemaining()) {
return -1;
@ -39,6 +40,7 @@ public class ByteBufferInputStream extends InputStream {
return buffer.get() & 0xFF;
}
@Override
public int read(byte[] bytes, int off, int len) {
if (!buffer.hasRemaining()) {
return -1;

View File

@ -30,6 +30,7 @@ public class ByteBufferOutputStream extends OutputStream {
this.buffer = buffer;
}
@Override
public void write(int b) throws IOException {
try {
buffer.put((byte) b);
@ -38,6 +39,7 @@ public class ByteBufferOutputStream extends OutputStream {
}
}
@Override
public void write(byte[] bytes, int off, int len) throws IOException {
try {
buffer.put(bytes, off, len);

View File

@ -44,6 +44,7 @@ public class SizeLimitedList<E> extends ForwardingList<E> {
return standardAddAll(index, elements);
}
@Override
public boolean add(E e) {
checkMaxSize();
return delegate().add(e);

View File

@ -22,7 +22,7 @@ public class VectorUtil {
public static void forEachVectorInCuboid(
int x0, int y0, int z0,
int x1, int y1, int z1,
Consumer<Vec3i> action
Consumer<? super Vec3i> action
) {
Vec3i cursor = Vectors.grab3i();

View File

@ -33,12 +33,19 @@ import ru.windcorp.progressia.common.util.VectorUtil;
import ru.windcorp.progressia.common.world.block.BlockData;
import ru.windcorp.progressia.common.world.block.BlockFace;
import ru.windcorp.progressia.common.world.entity.EntityData;
import ru.windcorp.progressia.common.world.generic.GenericChunk;
import ru.windcorp.progressia.common.world.tile.TileData;
import ru.windcorp.progressia.common.world.tile.TileDataStack;
import ru.windcorp.progressia.common.world.tile.TileReference;
import ru.windcorp.progressia.common.world.tile.TileStackIsFullException;
public class ChunkData {
public class ChunkData
implements GenericChunk<
ChunkData,
BlockData,
TileData,
TileDataStack
> {
public static final int BLOCKS_PER_CHUNK = Coordinates.CHUNK_SIZE;
@ -65,6 +72,12 @@ public class ChunkData {
this.world = world;
}
@Override
public Vec3i getPosition() {
return position;
}
@Override
public BlockData getBlock(Vec3i posInChunk) {
return blocks[getBlockIndex(posInChunk)];
}
@ -81,6 +94,7 @@ public class ChunkData {
}
}
@Override
public TileDataStack getTilesOrNull(Vec3i blockInChunk, BlockFace face) {
return tiles[getTileIndex(blockInChunk, face)];
}
@ -98,10 +112,12 @@ public class ChunkData {
this.tiles[getTileIndex(blockInChunk, face)] = tiles;
}
@Override
public boolean hasTiles(Vec3i blockInChunk, BlockFace face) {
return getTilesOrNull(blockInChunk, face) != null;
}
@Override
public TileDataStack getTiles(Vec3i blockInChunk, BlockFace face) {
int index = getTileIndex(blockInChunk, face);
@ -207,22 +223,6 @@ public class ChunkData {
getEntities().forEach(action);
}
public int getX() {
return position.x;
}
public int getY() {
return position.y;
}
public int getZ() {
return position.z;
}
public Vec3i getPosition() {
return position;
}
public WorldData getWorld() {
return world;
}

View File

@ -30,9 +30,19 @@ import ru.windcorp.progressia.common.collision.CollisionModel;
import ru.windcorp.progressia.common.util.CoordinatePacker;
import ru.windcorp.progressia.common.world.block.BlockData;
import ru.windcorp.progressia.common.world.entity.EntityData;
import ru.windcorp.progressia.common.world.generic.GenericWorld;
import ru.windcorp.progressia.common.world.tile.TileData;
import ru.windcorp.progressia.common.world.tile.TileDataStack;
import ru.windcorp.progressia.test.TestContent;
public class WorldData {
public class WorldData
implements GenericWorld<
BlockData,
TileData,
TileDataStack,
ChunkData,
EntityData
>{
private final TLongObjectMap<ChunkData> chunksByPos =
new TSynchronizedLongObjectMap<>(new TLongObjectHashMap<>(), this);
@ -55,6 +65,21 @@ public class WorldData {
}
@Override
public ChunkData getChunk(Vec3i pos) {
return chunksByPos.get(CoordinatePacker.pack3IntsIntoLong(pos));
}
@Override
public Collection<ChunkData> getChunks() {
return chunks;
}
@Override
public Collection<EntityData> getEntities() {
return entities;
}
public void tmp_generate() {
final int size = 10;
Vec3i cursor = new Vec3i(0, 0, 0);
@ -112,21 +137,6 @@ public class WorldData {
return CoordinatePacker.pack3IntsIntoLong(chunk.getPosition());
}
public ChunkData getChunk(Vec3i pos) {
return chunksByPos.get(CoordinatePacker.pack3IntsIntoLong(pos));
}
public ChunkData getChunkByBlock(Vec3i blockInWorld) {
return getChunk(Coordinates.convertInWorldToChunk(blockInWorld, null));
}
public BlockData getBlock(Vec3i blockInWorld) {
ChunkData chunk = getChunkByBlock(blockInWorld);
if (chunk == null) return null;
return chunk.getBlock(Coordinates.convertInWorldToInChunk(blockInWorld, null));
}
public void setBlock(Vec3i blockInWorld, BlockData block, boolean notify) {
ChunkData chunk = getChunkByBlock(blockInWorld);
if (chunk == null)
@ -139,10 +149,6 @@ public class WorldData {
chunk.setBlock(Coordinates.convertInWorldToInChunk(blockInWorld, null), block, notify);
}
public Collection<ChunkData> getChunks() {
return chunks;
}
public TLongSet getChunkKeys() {
return chunksByPos.keySet();
}
@ -151,10 +157,6 @@ public class WorldData {
return entitiesById.get(entityId);
}
public Collection<EntityData> getEntities() {
return entities;
}
public float getTime() {
return time;
}

View File

@ -20,8 +20,9 @@ package ru.windcorp.progressia.common.world.block;
import ru.windcorp.progressia.common.collision.AABB;
import ru.windcorp.progressia.common.collision.CollisionModel;
import ru.windcorp.progressia.common.util.namespaces.Namespaced;
import ru.windcorp.progressia.common.world.generic.GenericBlock;
public class BlockData extends Namespaced {
public class BlockData extends Namespaced implements GenericBlock {
public BlockData(String id) {
super(id);

View File

@ -2,13 +2,12 @@ package ru.windcorp.progressia.common.world.entity;
import glm.vec._2.Vec2;
import glm.vec._3.Vec3;
import glm.vec._3.i.Vec3i;
import ru.windcorp.progressia.common.collision.Collideable;
import ru.windcorp.progressia.common.collision.CollisionModel;
import ru.windcorp.progressia.common.state.StatefulObject;
import ru.windcorp.progressia.common.world.Coordinates;
import ru.windcorp.progressia.common.world.generic.GenericEntity;
public class EntityData extends StatefulObject implements Collideable {
public class EntityData extends StatefulObject implements Collideable, GenericEntity {
private final Vec3 position = new Vec3();
private final Vec3 velocity = new Vec3();
@ -25,20 +24,11 @@ public class EntityData extends StatefulObject implements Collideable {
super(EntityDataRegistry.getInstance(), id);
}
@Override
public Vec3 getPosition() {
return position;
}
public Vec3i getBlockInWorld(Vec3i output) {
if (output == null) output = new Vec3i();
return position.round(output);
}
public Vec3i getChunkCoords(Vec3i output) {
output = getBlockInWorld(output);
return Coordinates.convertInWorldToChunk(output, output);
}
public void setPosition(Vec3 position) {
move(position.sub_(getPosition()));
}

View File

@ -0,0 +1,7 @@
package ru.windcorp.progressia.common.world.generic;
public interface GenericBlock {
String getId();
}

View File

@ -0,0 +1,85 @@
package ru.windcorp.progressia.common.world.generic;
import java.util.function.Consumer;
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.block.BlockFace;
public interface GenericChunk<
Self extends GenericChunk<Self, B, T, TS>,
B extends GenericBlock,
T extends GenericTile,
TS extends GenericTileStack<TS, T, Self>
> {
public static final int BLOCKS_PER_CHUNK = Coordinates.CHUNK_SIZE;
Vec3i getPosition();
B getBlock(Vec3i blockInChunk);
TS getTiles(Vec3i blockInChunk, BlockFace face);
boolean hasTiles(Vec3i blockInChunk, BlockFace face);
default int getX() {
return getPosition().x;
}
default int getY() {
return getPosition().y;
}
default int getZ() {
return getPosition().z;
}
default 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;
}
default boolean containsBiW(Vec3i blockInWorld) {
Vec3i v = Vectors.grab3i();
v = Coordinates.getInWorld(getPosition(), Vectors.ZERO_3i, v);
v = blockInWorld.sub(v, v);
boolean result = containsBiC(v);
Vectors.release(v);
return result;
}
default void forEachBiC(Consumer<? super Vec3i> action) {
VectorUtil.forEachVectorInCuboid(
0, 0, 0,
BLOCKS_PER_CHUNK, BLOCKS_PER_CHUNK, BLOCKS_PER_CHUNK,
action
);
}
default void forEachBiW(Consumer<? super Vec3i> action) {
VectorUtil.forEachVectorInCuboid(
Coordinates.getInWorld(getX(), 0),
Coordinates.getInWorld(getY(), 0),
Coordinates.getInWorld(getZ(), 0),
BLOCKS_PER_CHUNK,
BLOCKS_PER_CHUNK,
BLOCKS_PER_CHUNK,
action
);
}
default TS getTilesOrNull(Vec3i blockInChunk, BlockFace face) {
if (hasTiles(blockInChunk, face)) {
return getTiles(blockInChunk, face);
}
return null;
}
}

View File

@ -0,0 +1,22 @@
package ru.windcorp.progressia.common.world.generic;
import glm.vec._3.Vec3;
import glm.vec._3.i.Vec3i;
import ru.windcorp.progressia.common.world.Coordinates;
public interface GenericEntity {
String getId();
Vec3 getPosition();
default Vec3i getBlockInWorld(Vec3i output) {
if (output == null) output = new Vec3i();
return getPosition().round(output);
}
default Vec3i getChunkCoords(Vec3i output) {
output = getBlockInWorld(output);
return Coordinates.convertInWorldToChunk(output, output);
}
}

View File

@ -0,0 +1,7 @@
package ru.windcorp.progressia.common.world.generic;
public interface GenericTile {
String getId();
}

View File

@ -1,4 +1,4 @@
package ru.windcorp.progressia.common.world.tile;
package ru.windcorp.progressia.common.world.generic;
import java.util.AbstractList;
import java.util.Objects;
@ -6,11 +6,14 @@ import java.util.RandomAccess;
import java.util.function.Consumer;
import glm.vec._3.i.Vec3i;
import ru.windcorp.progressia.common.util.namespaces.Namespaced;
import ru.windcorp.progressia.common.world.Coordinates;
import ru.windcorp.progressia.common.world.block.BlockFace;
public abstract class GenericTileStack<T extends Namespaced, C>
public abstract class GenericTileStack<
Self extends GenericTileStack<Self, T, C>,
T extends GenericTile,
C extends GenericChunk<C, ?, T, Self>
>
extends AbstractList<T>
implements RandomAccess {
@ -21,13 +24,12 @@ implements RandomAccess {
public static final int TILES_PER_FACE = 8;
public abstract Vec3i getBlockInChunk(Vec3i output);
protected abstract Vec3i getChunkPos();
public abstract C getChunk();
public abstract BlockFace getFace();
public Vec3i getBlockInWorld(Vec3i output) {
// This is safe
return Coordinates.getInWorld(getChunkPos(), getBlockInChunk(output), output);
return Coordinates.getInWorld(getChunk().getPosition(), getBlockInChunk(output), output);
}
public boolean isFull() {

View File

@ -0,0 +1,176 @@
package ru.windcorp.progressia.common.world.generic;
import java.util.Collection;
import java.util.function.Consumer;
import glm.Glm;
import glm.vec._3.Vec3;
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.BlockFace;
public interface GenericWorld<
B extends GenericBlock,
T extends GenericTile,
TS extends GenericTileStack<TS, T, C>,
C extends GenericChunk<C, B, T, TS>,
E extends GenericEntity
> {
Collection<C> getChunks();
C getChunk(Vec3i pos);
Collection<E> getEntities();
/*
* Chunks
*/
default C getChunkByBlock(Vec3i blockInWorld) {
Vec3i chunkCoords = Vectors.grab3i();
chunkCoords = Coordinates.convertInWorldToChunk(blockInWorld, chunkCoords);
C result = getChunk(chunkCoords);
Vectors.release(chunkCoords);
return result;
}
default B getBlock(Vec3i blockInWorld) {
Vec3i v = Vectors.grab3i();
B result;
C chunk = getChunk(Coordinates.convertInWorldToChunk(blockInWorld, v));
if (chunk == null) {
result = null;
} else {
result = chunk.getBlock(Coordinates.convertInWorldToInChunk(blockInWorld, v));
}
Vectors.release(v);
return result;
}
default TS getTiles(Vec3i blockInWorld, BlockFace face) {
Vec3i v = Vectors.grab3i();
TS result;
C chunk = getChunk(Coordinates.convertInWorldToChunk(blockInWorld, v));
if (chunk == null) {
result = null;
} else {
result = chunk.getTiles(Coordinates.convertInWorldToInChunk(blockInWorld, v), face);
}
Vectors.release(v);
return result;
}
default TS getTilesOrNull(Vec3i blockInWorld, BlockFace face) {
Vec3i v = Vectors.grab3i();
TS result;
C chunk = getChunk(Coordinates.convertInWorldToChunk(blockInWorld, v));
if (chunk == null) {
result = null;
} else {
result = chunk.getTilesOrNull(Coordinates.convertInWorldToInChunk(blockInWorld, v), face);
}
Vectors.release(v);
return result;
}
default boolean hasTiles(Vec3i blockInWorld, BlockFace face) {
Vec3i v = Vectors.grab3i();
boolean result;
C chunk = getChunk(Coordinates.convertInWorldToChunk(blockInWorld, v));
if (chunk == null) {
result = false;
} else {
result = chunk.hasTiles(Coordinates.convertInWorldToInChunk(blockInWorld, v), face);
}
Vectors.release(v);
return result;
}
default T getTile(Vec3i blockInWorld, BlockFace face, int layer) {
TS stack = getTilesOrNull(blockInWorld, face);
if (stack == null || stack.size() <= layer) return null;
return stack.get(layer);
}
default boolean isChunkLoaded(Vec3i pos) {
return getChunk(pos) != null;
}
default boolean isBlockLoaded(Vec3i blockInWorld) {
return getChunkByBlock(blockInWorld) != null;
}
default void forEachChunk(Consumer<? super C> action) {
getChunks().forEach(action);
}
/*
* Entities
*/
default void forEachEntity(Consumer<? super E> action) {
getEntities().forEach(action);
}
default void forEachEntityIn(Vec3i min, Vec3i max, Consumer<? super E> action) {
forEachEntity(e -> {
Vec3 pos = e.getPosition();
if (pos.x < min.x || pos.y < min.y || pos.z < min.z || pos.x > max.x || pos.y > max.y || pos.z > max.z) {
action.accept(e);
}
});
}
default void forEachEntityIn(Vec3 min, Vec3 max, Consumer<? super E> action) {
forEachEntity(e -> {
Vec3 pos = e.getPosition();
if (pos.x < min.x || pos.y < min.y || pos.z < min.z || pos.x > max.x || pos.y > max.y || pos.z > max.z) {
action.accept(e);
}
});
}
default void forEachEntityInChunk(Vec3i pos, Consumer<? super E> action) {
Vec3i v = Vectors.grab3i();
forEachEntity(e -> {
e.getChunkCoords(v);
if (Glm.equals(v, pos)) {
action.accept(e);
}
});
Vectors.release(v);
}
default void forEachEntityInChunk(C chunk, Consumer<? super E> action) {
Vec3i v = Vectors.grab3i();
forEachEntity(e -> {
e.getChunkCoords(v);
if (Glm.equals(v, chunk.getPosition())) {
action.accept(e);
}
});
Vectors.release(v);
}
default void forEachEntityWithId(String id, Consumer<? super E> action) {
forEachEntity(e -> {
if (id.equals(e.getId())) {
action.accept(e);
}
});
}
}

View File

@ -18,8 +18,9 @@
package ru.windcorp.progressia.common.world.tile;
import ru.windcorp.progressia.common.util.namespaces.Namespaced;
import ru.windcorp.progressia.common.world.generic.GenericTile;
public class TileData extends Namespaced {
public class TileData extends Namespaced implements GenericTile {
public TileData(String id) {
super(id);

View File

@ -1,10 +1,15 @@
package ru.windcorp.progressia.common.world.tile;
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.generic.GenericTileStack;
public abstract class TileDataStack extends GenericTileStack<TileData, ChunkData> {
public abstract class TileDataStack
extends GenericTileStack<
TileDataStack,
TileData,
ChunkData
> {
/**
* Inserts the specified tile at the specified position in this stack.
@ -54,15 +59,6 @@ public abstract class TileDataStack extends GenericTileStack<TileData, ChunkData
public abstract int getTagByIndex(int index);
/*
* Implementation
*/
@Override
public Vec3i getChunkPos() {
return getChunk().getPosition();
}
/*
* Aliases and overloads
*/

View File

@ -12,6 +12,7 @@ import ru.windcorp.progressia.common.world.ChunkData;
import ru.windcorp.progressia.common.world.Coordinates;
import ru.windcorp.progressia.common.world.block.BlockFace;
import ru.windcorp.progressia.common.world.entity.EntityData;
import ru.windcorp.progressia.common.world.generic.GenericChunk;
import ru.windcorp.progressia.common.world.tile.TileDataStack;
import ru.windcorp.progressia.common.world.tile.TileReference;
import ru.windcorp.progressia.server.world.block.BlockLogic;
@ -26,7 +27,12 @@ import ru.windcorp.progressia.server.world.tile.TileLogic;
import ru.windcorp.progressia.server.world.tile.TileLogicRegistry;
import ru.windcorp.progressia.server.world.tile.TileLogicStack;
public class ChunkLogic {
public class ChunkLogic implements GenericChunk<
ChunkLogic,
BlockLogic,
TileLogic,
TileLogicStack
> {
private final WorldLogic world;
private final ChunkData data;
@ -43,31 +49,36 @@ public class ChunkLogic {
this.world = world;
this.data = data;
generateTickLists();
tmp_generateTickLists();
}
private void generateTickLists() {
ChunkTickContext context = TickContextMutable.start().withChunk(this).build();
context.forEachBlock(bctxt -> {
BlockLogic block = bctxt.getBlock();
if (!(block instanceof TickableBlock)) return;
if (((TickableBlock) block).getTickingPolicy(bctxt) == TickingPolicy.REGULAR) {
tickingBlocks.add(Coordinates.convertInWorldToInChunk(bctxt.getBlockInWorld(), null));
@Override
public Vec3i getPosition() {
return getData().getPosition();
}
bctxt.forEachFace(fctxt -> fctxt.forEachTile(tctxt -> {
TileLogic tile = tctxt.getTile();
if (!(tile instanceof TickableTile)) return;
if (((TickableTile) tile).getTickingPolicy(tctxt) == TickingPolicy.REGULAR) {
tickingTiles.add(tctxt.getReference());
@Override
public BlockLogic getBlock(Vec3i blockInChunk) {
return BlockLogicRegistry.getInstance().get(
getData().getBlock(blockInChunk).getId()
);
}
}));
});
@Override
public TileLogicStack getTiles(Vec3i blockInChunk, BlockFace face) {
return getTileStackWrapper(getData().getTiles(blockInChunk, face));
}
@Override
public boolean hasTiles(Vec3i blockInChunk, BlockFace face) {
return getData().hasTiles(blockInChunk, face);
}
private TileLogicStack getTileStackWrapper(TileDataStack tileDataList) {
return tileLogicLists.computeIfAbsent(
tileDataList,
TileLogicStackImpl::new
);
}
public WorldLogic getWorld() {
@ -78,10 +89,6 @@ public class ChunkLogic {
return data;
}
public Vec3i getPosition() {
return getData().getPosition();
}
public boolean hasTickingBlocks() {
return !tickingBlocks.isEmpty();
}
@ -114,29 +121,6 @@ public class ChunkLogic {
});
}
public BlockLogic getBlock(Vec3i blockInChunk) {
return BlockLogicRegistry.getInstance().get(
getData().getBlock(blockInChunk).getId()
);
}
public TileLogicStack getTiles(Vec3i blockInChunk, BlockFace face) {
return getTileStackWrapper(getData().getTiles(blockInChunk, face));
}
public TileLogicStack getTilesOrNull(Vec3i blockInChunk, BlockFace face) {
TileDataStack tiles = getData().getTilesOrNull(blockInChunk, face);
if (tiles == null) return null;
return getTileStackWrapper(tiles);
}
private TileLogicStack getTileStackWrapper(TileDataStack tileDataList) {
return tileLogicLists.computeIfAbsent(
tileDataList,
TileLogicStackImpl::new
);
}
public TickChunk getTickTask() {
return tickTask;
}
@ -154,11 +138,6 @@ public class ChunkLogic {
return parent.getBlockInChunk(output);
}
@Override
public Vec3i getChunkPos() {
return ChunkLogic.this.getPosition();
}
@Override
public ChunkLogic getChunk() {
return ChunkLogic.this;
@ -186,4 +165,28 @@ public class ChunkLogic {
}
private void tmp_generateTickLists() {
ChunkTickContext context = TickContextMutable.start().withChunk(this).build();
context.forEachBlock(bctxt -> {
BlockLogic block = bctxt.getBlock();
if (!(block instanceof TickableBlock)) return;
if (((TickableBlock) block).getTickingPolicy(bctxt) == TickingPolicy.REGULAR) {
tickingBlocks.add(Coordinates.convertInWorldToInChunk(bctxt.getBlockInWorld(), null));
}
bctxt.forEachFace(fctxt -> fctxt.forEachTile(tctxt -> {
TileLogic tile = tctxt.getTile();
if (!(tile instanceof TickableTile)) return;
if (((TickableTile) tile).getTickingPolicy(tctxt) == TickingPolicy.REGULAR) {
tickingTiles.add(tctxt.getReference());
}
}));
});
}
}

View File

@ -8,7 +8,7 @@ import glm.vec._3.i.Vec3i;
import ru.windcorp.progressia.common.world.ChunkData;
import ru.windcorp.progressia.common.world.Coordinates;
import ru.windcorp.progressia.common.world.block.BlockFace;
import ru.windcorp.progressia.common.world.tile.GenericTileStack;
import ru.windcorp.progressia.common.world.generic.GenericTileStack;
import ru.windcorp.progressia.common.world.tile.TileDataStack;
import ru.windcorp.progressia.common.world.tile.TileReference;
import ru.windcorp.progressia.server.Server;
@ -87,7 +87,7 @@ public abstract class TickContextMutable implements BlockTickContext, TSTickCont
public static interface World extends Builder {
Chunk withChunk(Vec3i chunk);
Block withBlock(Vec3i blockInWorld);
TileStack withTS(GenericTileStack<?, ?> tileStack);
TileStack withTS(GenericTileStack<?, ?, ?> tileStack);
default Builder.Chunk withChunk(ChunkData chunk) {
Objects.requireNonNull(chunk, "chunk");
@ -237,7 +237,7 @@ public abstract class TickContextMutable implements BlockTickContext, TSTickCont
}
@Override
public TileStack withTS(GenericTileStack<?, ?> tileStack) {
public TileStack withTS(GenericTileStack<?, ?, ?> tileStack) {
Objects.requireNonNull(tileStack, "tileStack");
return withBlock(tileStack.getBlockInWorld(this.blockInWorld)).withFace(tileStack.getFace());

View File

@ -2,22 +2,29 @@ package ru.windcorp.progressia.server.world;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import glm.vec._3.i.Vec3i;
import ru.windcorp.progressia.common.world.ChunkData;
import ru.windcorp.progressia.common.world.ChunkDataListeners;
import ru.windcorp.progressia.common.world.Coordinates;
import ru.windcorp.progressia.common.world.WorldData;
import ru.windcorp.progressia.common.world.WorldDataListener;
import ru.windcorp.progressia.common.world.block.BlockFace;
import ru.windcorp.progressia.common.world.entity.EntityData;
import ru.windcorp.progressia.common.world.generic.GenericWorld;
import ru.windcorp.progressia.server.Server;
import ru.windcorp.progressia.server.world.block.BlockLogic;
import ru.windcorp.progressia.server.world.tile.TileLogic;
import ru.windcorp.progressia.server.world.tile.TileLogicStack;
import ru.windcorp.progressia.test.TestChunkSender;
public class WorldLogic {
public class WorldLogic
implements GenericWorld<
BlockLogic,
TileLogic,
TileLogicStack,
ChunkLogic,
EntityData // not using EntityLogic because it is stateless
> {
private final WorldData data;
private final Server server;
@ -44,6 +51,21 @@ public class WorldLogic {
data.addListener(new TestChunkSender(server));
}
@Override
public ChunkLogic getChunk(Vec3i pos) {
return chunks.get(getData().getChunk(pos));
}
@Override
public Collection<ChunkLogic> getChunks() {
return chunks.values();
}
@Override
public Collection<EntityData> getEntities() {
return getData().getEntities();
}
public Server getServer() {
return server;
}
@ -56,52 +78,4 @@ public class WorldLogic {
return chunks.get(chunkData);
}
public ChunkLogic getChunk(Vec3i pos) {
return chunks.get(getData().getChunk(pos));
}
public ChunkLogic getChunkByBlock(Vec3i blockInWorld) {
return getChunk(Coordinates.convertInWorldToChunk(blockInWorld, null));
}
public BlockLogic getBlock(Vec3i blockInWorld) {
ChunkLogic chunk = getChunkByBlock(blockInWorld);
if (chunk == null) return null;
return chunk.getBlock(Coordinates.convertInWorldToInChunk(blockInWorld, null));
}
public List<TileLogic> getTiles(Vec3i blockInWorld, BlockFace face) {
return getTilesImpl(blockInWorld, face, true);
}
public List<TileLogic> getTilesOrNull(Vec3i blockInWorld, BlockFace face) {
return getTilesImpl(blockInWorld, face, false);
}
private List<TileLogic> getTilesImpl(Vec3i blockInWorld, BlockFace face, boolean createIfMissing) {
ChunkLogic chunk = getChunkByBlock(blockInWorld);
if (chunk == null) return null;
Vec3i blockInChunk = Coordinates.convertInWorldToInChunk(blockInWorld, null);
List<TileLogic> result =
createIfMissing
? chunk.getTiles(blockInChunk, face)
: chunk.getTilesOrNull(blockInChunk, face);
return result;
}
public TileLogic getTile(Vec3i blockInWorld, BlockFace face, int layer) {
List<TileLogic> tiles = getTilesOrNull(blockInWorld, face);
if (tiles == null || tiles.size() <= layer) return null;
return tiles.get(layer);
}
public Collection<ChunkLogic> getChunks() {
return chunks.values();
}
}

View File

@ -2,8 +2,9 @@ package ru.windcorp.progressia.server.world.block;
import ru.windcorp.progressia.common.util.namespaces.Namespaced;
import ru.windcorp.progressia.common.world.block.BlockFace;
import ru.windcorp.progressia.common.world.generic.GenericBlock;
public class BlockLogic extends Namespaced {
public class BlockLogic extends Namespaced implements GenericBlock {
public BlockLogic(String id) {
super(id);

View File

@ -2,8 +2,9 @@ package ru.windcorp.progressia.server.world.tile;
import ru.windcorp.progressia.common.util.namespaces.Namespaced;
import ru.windcorp.progressia.common.world.block.BlockFace;
import ru.windcorp.progressia.common.world.generic.GenericTile;
public class TileLogic extends Namespaced {
public class TileLogic extends Namespaced implements GenericTile {
public TileLogic(String id) {
super(id);

View File

@ -1,12 +1,15 @@
package ru.windcorp.progressia.server.world.tile;
import ru.windcorp.progressia.common.world.tile.GenericTileStack;
import ru.windcorp.progressia.common.world.generic.GenericTileStack;
import ru.windcorp.progressia.common.world.tile.TileDataStack;
import ru.windcorp.progressia.server.world.ChunkLogic;
public abstract class TileLogicStack extends GenericTileStack<TileLogic, ChunkLogic> {
// TODO add @Deprecated or smth similar to all modification methods
public abstract class TileLogicStack
extends GenericTileStack<
TileLogicStack,
TileLogic,
ChunkLogic
> {
public abstract TileDataStack getData();