Still working on Contexts. Introduced a billion interfaces. WIP.

*takes a deep breath
- Renamed Generic world structure interfaces to the following scheme:

      {Block,Tile,Chunk,World}Generic{,Stack,Reference}{RO,WO}
      (e.g. GenericWritableChunk -> ChunkGenericWO)

    - RO is Read Only, WO is Write Only
- Generic writable interfaces no longer extend their read-only
counterparts (thus Write Only)
- TileGenericStack{RO,WO} are now interfaces; AbstractList is only
introduced by final implementations
- TileGenericReferenceRO now has a WO counterpart
- Fixed compilation issues with the previous commit
- Declared some additional functionality for Generic interfaces
- Old ChunkData and WorldData renamed to DefaultChunkData and
DefaultWorldData
  - Now considered to be an implementation detail; references will be
minimized
- Introduced TileDataStack{,RO}, TileDataReference{,RO}, ChunkData{,RO},
WorldData{,RO} interfaces
  - Suffix -RO indicates Read Only, no suffix means read-write
  - To be used in place of DefaultChunk and DefaultWorld
  - Designed to support wrappers and "fake" implementations
  - May need some refinement (fix return/parameter types, ...)
- Surface world generator is now implemented poorly (WIP)
- Should compile. May work fine. Unless Java inheritance rules have
screwed me over.
This commit is contained in:
OLEGSHA 2021-07-23 22:46:49 +03:00
parent d7afe39f00
commit 9a326603cd
110 changed files with 1733 additions and 1419 deletions

View File

@ -24,7 +24,7 @@ import ru.windcorp.progressia.client.graphics.world.Camera;
import ru.windcorp.progressia.client.graphics.world.EntityAnchor; import ru.windcorp.progressia.client.graphics.world.EntityAnchor;
import ru.windcorp.progressia.client.graphics.world.LocalPlayer; import ru.windcorp.progressia.client.graphics.world.LocalPlayer;
import ru.windcorp.progressia.client.world.WorldRender; import ru.windcorp.progressia.client.world.WorldRender;
import ru.windcorp.progressia.common.world.WorldData; import ru.windcorp.progressia.common.world.DefaultWorldData;
import ru.windcorp.progressia.common.world.entity.EntityData; import ru.windcorp.progressia.common.world.entity.EntityData;
public class Client { public class Client {
@ -36,7 +36,7 @@ public class Client {
private final ServerCommsChannel comms; private final ServerCommsChannel comms;
public Client(WorldData world, ServerCommsChannel comms) { public Client(DefaultWorldData world, ServerCommsChannel comms) {
this.world = new WorldRender(world, this); this.world = new WorldRender(world, this);
this.comms = comms; this.comms = comms;

View File

@ -21,7 +21,7 @@ package ru.windcorp.progressia.client;
import ru.windcorp.progressia.client.comms.localhost.LocalServerCommsChannel; import ru.windcorp.progressia.client.comms.localhost.LocalServerCommsChannel;
import ru.windcorp.progressia.client.graphics.GUI; import ru.windcorp.progressia.client.graphics.GUI;
import ru.windcorp.progressia.client.graphics.world.LayerWorld; import ru.windcorp.progressia.client.graphics.world.LayerWorld;
import ru.windcorp.progressia.common.world.WorldData; import ru.windcorp.progressia.common.world.DefaultWorldData;
import ru.windcorp.progressia.server.ServerState; import ru.windcorp.progressia.server.ServerState;
import ru.windcorp.progressia.test.LayerAbout; import ru.windcorp.progressia.test.LayerAbout;
import ru.windcorp.progressia.test.LayerTestUI; import ru.windcorp.progressia.test.LayerTestUI;
@ -41,7 +41,7 @@ public class ClientState {
public static void connectToLocalServer() { public static void connectToLocalServer() {
WorldData world = new WorldData(); DefaultWorldData world = new DefaultWorldData();
LocalServerCommsChannel channel = new LocalServerCommsChannel( LocalServerCommsChannel channel = new LocalServerCommsChannel(
ServerState.getInstance() ServerState.getInstance()

View File

@ -30,26 +30,26 @@ import ru.windcorp.progressia.client.world.tile.TileRender;
import ru.windcorp.progressia.client.world.tile.TileRenderReference; import ru.windcorp.progressia.client.world.tile.TileRenderReference;
import ru.windcorp.progressia.client.world.tile.TileRenderRegistry; import ru.windcorp.progressia.client.world.tile.TileRenderRegistry;
import ru.windcorp.progressia.client.world.tile.TileRenderStack; import ru.windcorp.progressia.client.world.tile.TileRenderStack;
import ru.windcorp.progressia.common.world.ChunkData; import ru.windcorp.progressia.common.world.DefaultChunkData;
import ru.windcorp.progressia.common.world.generic.GenericChunk; import ru.windcorp.progressia.common.world.TileDataReference;
import ru.windcorp.progressia.common.world.TileDataStack;
import ru.windcorp.progressia.common.world.generic.ChunkGenericRO;
import ru.windcorp.progressia.common.world.rels.AbsFace; import ru.windcorp.progressia.common.world.rels.AbsFace;
import ru.windcorp.progressia.common.world.rels.BlockFace; import ru.windcorp.progressia.common.world.rels.BlockFace;
import ru.windcorp.progressia.common.world.rels.RelFace; import ru.windcorp.progressia.common.world.rels.RelFace;
import ru.windcorp.progressia.common.world.tile.TileDataReference;
import ru.windcorp.progressia.common.world.tile.TileDataStack;
public class ChunkRender public class ChunkRender
implements GenericChunk<BlockRender, TileRender, TileRenderStack, TileRenderReference, ChunkRender> { implements ChunkGenericRO<BlockRender, TileRender, TileRenderStack, TileRenderReference, ChunkRender> {
private final WorldRender world; private final WorldRender world;
private final ChunkData data; private final DefaultChunkData data;
private final ChunkRenderModel model; private final ChunkRenderModel model;
private final Map<TileDataStack, TileRenderStackImpl> tileRenderLists = Collections private final Map<TileDataStack, TileRenderStackImpl> tileRenderLists = Collections
.synchronizedMap(new WeakHashMap<>()); .synchronizedMap(new WeakHashMap<>());
public ChunkRender(WorldRender world, ChunkData data) { public ChunkRender(WorldRender world, DefaultChunkData data) {
this.world = world; this.world = world;
this.data = data; this.data = data;
this.model = new ChunkRenderModel(this); this.model = new ChunkRenderModel(this);
@ -93,7 +93,7 @@ public class ChunkRender
return world; return world;
} }
public ChunkData getData() { public DefaultChunkData getData() {
return data; return data;
} }

View File

@ -35,7 +35,7 @@ import ru.windcorp.progressia.client.world.cro.ChunkRenderOptimizerRegistry;
import ru.windcorp.progressia.client.world.tile.TileRender; import ru.windcorp.progressia.client.world.tile.TileRender;
import ru.windcorp.progressia.client.world.tile.TileRenderNone; import ru.windcorp.progressia.client.world.tile.TileRenderNone;
import ru.windcorp.progressia.client.world.tile.TileRenderStack; import ru.windcorp.progressia.client.world.tile.TileRenderStack;
import ru.windcorp.progressia.common.world.ChunkData; import ru.windcorp.progressia.common.world.DefaultChunkData;
import ru.windcorp.progressia.common.world.generic.GenericChunks; import ru.windcorp.progressia.common.world.generic.GenericChunks;
import ru.windcorp.progressia.common.world.rels.AxisRotations; import ru.windcorp.progressia.common.world.rels.AxisRotations;
import ru.windcorp.progressia.common.world.rels.RelFace; import ru.windcorp.progressia.common.world.rels.RelFace;
@ -55,12 +55,12 @@ public class ChunkRenderModel implements Renderable {
public void render(ShapeRenderHelper renderer) { public void render(ShapeRenderHelper renderer) {
if (model == null) return; if (model == null) return;
float offset = ChunkData.BLOCKS_PER_CHUNK / 2 - 0.5f; float offset = DefaultChunkData.BLOCKS_PER_CHUNK / 2 - 0.5f;
renderer.pushTransform().translate( renderer.pushTransform().translate(
chunk.getX() * ChunkData.BLOCKS_PER_CHUNK, chunk.getX() * DefaultChunkData.BLOCKS_PER_CHUNK,
chunk.getY() * ChunkData.BLOCKS_PER_CHUNK, chunk.getY() * DefaultChunkData.BLOCKS_PER_CHUNK,
chunk.getZ() * ChunkData.BLOCKS_PER_CHUNK chunk.getZ() * DefaultChunkData.BLOCKS_PER_CHUNK
).translate(offset, offset, offset) ).translate(offset, offset, offset)
.mul(AxisRotations.getResolutionMatrix4(chunk.getUp())) .mul(AxisRotations.getResolutionMatrix4(chunk.getUp()))
.translate(-offset, -offset, -offset); .translate(-offset, -offset, -offset);

View File

@ -21,7 +21,7 @@ package ru.windcorp.progressia.client.world;
import glm.vec._3.i.Vec3i; import glm.vec._3.i.Vec3i;
import ru.windcorp.progressia.common.util.VectorUtil; import ru.windcorp.progressia.common.util.VectorUtil;
import ru.windcorp.progressia.common.util.Vectors; import ru.windcorp.progressia.common.util.Vectors;
import ru.windcorp.progressia.common.world.ChunkData; import ru.windcorp.progressia.common.world.DefaultChunkData;
import ru.windcorp.progressia.common.world.ChunkDataListener; import ru.windcorp.progressia.common.world.ChunkDataListener;
import ru.windcorp.progressia.common.world.block.BlockData; import ru.windcorp.progressia.common.world.block.BlockData;
import ru.windcorp.progressia.common.world.rels.AbsFace; import ru.windcorp.progressia.common.world.rels.AbsFace;
@ -37,12 +37,12 @@ class ChunkUpdateListener implements ChunkDataListener {
} }
@Override @Override
public void onChunkChanged(ChunkData chunk) { public void onChunkChanged(DefaultChunkData chunk) {
world.getChunk(chunk).markForUpdate(); world.getChunk(chunk).markForUpdate();
} }
@Override @Override
public void onChunkLoaded(ChunkData chunk) { public void onChunkLoaded(DefaultChunkData chunk) {
Vec3i cursor = new Vec3i(); Vec3i cursor = new Vec3i();
for (AbsFace face : AbsFace.getFaces()) { for (AbsFace face : AbsFace.getFaces()) {
cursor.set(chunk.getX(), chunk.getY(), chunk.getZ()); cursor.set(chunk.getX(), chunk.getY(), chunk.getZ());
@ -52,13 +52,13 @@ class ChunkUpdateListener implements ChunkDataListener {
} }
@Override @Override
public void onChunkBlockChanged(ChunkData chunk, Vec3i blockInChunk, BlockData previous, BlockData current) { public void onChunkBlockChanged(DefaultChunkData chunk, Vec3i blockInChunk, BlockData previous, BlockData current) {
onLocationChanged(chunk, blockInChunk); onLocationChanged(chunk, blockInChunk);
} }
@Override @Override
public void onChunkTilesChanged( public void onChunkTilesChanged(
ChunkData chunk, DefaultChunkData chunk,
Vec3i blockInChunk, Vec3i blockInChunk,
RelFace face, RelFace face,
TileData tile, TileData tile,
@ -67,7 +67,7 @@ class ChunkUpdateListener implements ChunkDataListener {
onLocationChanged(chunk, blockInChunk); onLocationChanged(chunk, blockInChunk);
} }
private void onLocationChanged(ChunkData chunk, Vec3i blockInChunk) { private void onLocationChanged(DefaultChunkData chunk, Vec3i blockInChunk) {
Vec3i chunkPos = Vectors.grab3i().set(chunk.getX(), chunk.getY(), chunk.getZ()); Vec3i chunkPos = Vectors.grab3i().set(chunk.getX(), chunk.getY(), chunk.getZ());
checkCoordinate(blockInChunk, chunkPos, VectorUtil.Axis.X); checkCoordinate(blockInChunk, chunkPos, VectorUtil.Axis.X);
@ -83,7 +83,7 @@ class ChunkUpdateListener implements ChunkDataListener {
if (block == 0) { if (block == 0) {
diff = -1; diff = -1;
} else if (block == ChunkData.BLOCKS_PER_CHUNK - 1) { } else if (block == DefaultChunkData.BLOCKS_PER_CHUNK - 1) {
diff = +1; diff = +1;
} else { } else {
return; return;

View File

@ -38,54 +38,54 @@ import ru.windcorp.progressia.client.world.tile.TileRenderReference;
import ru.windcorp.progressia.client.world.tile.TileRenderStack; import ru.windcorp.progressia.client.world.tile.TileRenderStack;
import ru.windcorp.progressia.common.util.VectorUtil; import ru.windcorp.progressia.common.util.VectorUtil;
import ru.windcorp.progressia.common.util.Vectors; import ru.windcorp.progressia.common.util.Vectors;
import ru.windcorp.progressia.common.world.ChunkData; import ru.windcorp.progressia.common.world.DefaultChunkData;
import ru.windcorp.progressia.common.world.ChunkDataListeners; import ru.windcorp.progressia.common.world.ChunkDataListeners;
import ru.windcorp.progressia.common.world.WorldData; import ru.windcorp.progressia.common.world.DefaultWorldData;
import ru.windcorp.progressia.common.world.WorldDataListener; import ru.windcorp.progressia.common.world.WorldDataListener;
import ru.windcorp.progressia.common.world.entity.EntityData; import ru.windcorp.progressia.common.world.entity.EntityData;
import ru.windcorp.progressia.common.world.generic.ChunkSet; import ru.windcorp.progressia.common.world.generic.ChunkSet;
import ru.windcorp.progressia.common.world.generic.ChunkSets; import ru.windcorp.progressia.common.world.generic.ChunkSets;
import ru.windcorp.progressia.common.world.generic.GenericWorld; import ru.windcorp.progressia.common.world.generic.WorldGenericRO;
public class WorldRender public class WorldRender
implements GenericWorld<BlockRender, TileRender, TileRenderStack, TileRenderReference, ChunkRender, EntityRenderable> { implements WorldGenericRO<BlockRender, TileRender, TileRenderStack, TileRenderReference, ChunkRender, EntityRenderable> {
private final WorldData data; private final DefaultWorldData data;
private final Client client; private final Client client;
private final Map<ChunkData, ChunkRender> chunks = Collections.synchronizedMap(new HashMap<>()); private final Map<DefaultChunkData, ChunkRender> chunks = Collections.synchronizedMap(new HashMap<>());
private final Map<EntityData, EntityRenderable> entityModels = Collections.synchronizedMap(new WeakHashMap<>()); private final Map<EntityData, EntityRenderable> entityModels = Collections.synchronizedMap(new WeakHashMap<>());
private final ChunkSet chunksToUpdate = ChunkSets.newSyncHashSet(); private final ChunkSet chunksToUpdate = ChunkSets.newSyncHashSet();
public WorldRender(WorldData data, Client client) { public WorldRender(DefaultWorldData data, Client client) {
this.data = data; this.data = data;
this.client = client; this.client = client;
data.addListener(ChunkDataListeners.createAdder(new ChunkUpdateListener(this))); data.addListener(ChunkDataListeners.createAdder(new ChunkUpdateListener(this)));
data.addListener(new WorldDataListener() { data.addListener(new WorldDataListener() {
@Override @Override
public void onChunkLoaded(WorldData world, ChunkData chunk) { public void onChunkLoaded(DefaultWorldData world, DefaultChunkData chunk) {
addChunk(chunk); addChunk(chunk);
} }
@Override @Override
public void beforeChunkUnloaded(WorldData world, ChunkData chunk) { public void beforeChunkUnloaded(DefaultWorldData world, DefaultChunkData chunk) {
removeChunk(chunk); removeChunk(chunk);
} }
}); });
} }
protected void addChunk(ChunkData chunk) { protected void addChunk(DefaultChunkData chunk) {
chunks.put(chunk, new ChunkRender(WorldRender.this, chunk)); chunks.put(chunk, new ChunkRender(WorldRender.this, chunk));
markChunkForUpdate(chunk.getPosition()); markChunkForUpdate(chunk.getPosition());
} }
protected void removeChunk(ChunkData chunk) { protected void removeChunk(DefaultChunkData chunk) {
chunks.remove(chunk); chunks.remove(chunk);
} }
public WorldData getData() { public DefaultWorldData getData() {
return data; return data;
} }
@ -93,7 +93,7 @@ public class WorldRender
return client; return client;
} }
public ChunkRender getChunk(ChunkData chunkData) { public ChunkRender getChunk(DefaultChunkData chunkData) {
return chunks.get(chunkData); return chunks.get(chunkData);
} }

View File

@ -19,18 +19,18 @@
package ru.windcorp.progressia.client.world.block; package ru.windcorp.progressia.client.world.block;
import ru.windcorp.progressia.common.util.namespaces.Namespaced; import ru.windcorp.progressia.common.util.namespaces.Namespaced;
import ru.windcorp.progressia.common.world.ChunkData; import ru.windcorp.progressia.common.world.DefaultChunkData;
import ru.windcorp.progressia.common.world.generic.GenericBlock; import ru.windcorp.progressia.common.world.generic.BlockGeneric;
import glm.vec._3.i.Vec3i; import glm.vec._3.i.Vec3i;
import ru.windcorp.progressia.client.graphics.model.Renderable; import ru.windcorp.progressia.client.graphics.model.Renderable;
public abstract class BlockRender extends Namespaced implements GenericBlock { public abstract class BlockRender extends Namespaced implements BlockGeneric {
public BlockRender(String id) { public BlockRender(String id) {
super(id); super(id);
} }
public Renderable createRenderable(ChunkData chunk, Vec3i relBlockInChunk) { public Renderable createRenderable(DefaultChunkData chunk, Vec3i relBlockInChunk) {
return null; return null;
} }

View File

@ -21,7 +21,7 @@ package ru.windcorp.progressia.client.world.block;
import glm.vec._3.i.Vec3i; import glm.vec._3.i.Vec3i;
import ru.windcorp.progressia.client.graphics.model.EmptyModel; import ru.windcorp.progressia.client.graphics.model.EmptyModel;
import ru.windcorp.progressia.client.graphics.model.Renderable; import ru.windcorp.progressia.client.graphics.model.Renderable;
import ru.windcorp.progressia.common.world.ChunkData; import ru.windcorp.progressia.common.world.DefaultChunkData;
public class BlockRenderNone extends BlockRender { public class BlockRenderNone extends BlockRender {
@ -30,7 +30,7 @@ public class BlockRenderNone extends BlockRender {
} }
@Override @Override
public Renderable createRenderable(ChunkData chunk, Vec3i blockInChunk) { public Renderable createRenderable(DefaultChunkData chunk, Vec3i blockInChunk) {
return EmptyModel.getInstance(); return EmptyModel.getInstance();
} }

View File

@ -36,7 +36,7 @@ import ru.windcorp.progressia.client.graphics.texture.Texture;
import ru.windcorp.progressia.client.graphics.world.WorldRenderProgram; import ru.windcorp.progressia.client.graphics.world.WorldRenderProgram;
import ru.windcorp.progressia.client.world.cro.ChunkRenderOptimizerSurface.BlockOptimizedSurface; import ru.windcorp.progressia.client.world.cro.ChunkRenderOptimizerSurface.BlockOptimizedSurface;
import ru.windcorp.progressia.common.util.Vectors; import ru.windcorp.progressia.common.util.Vectors;
import ru.windcorp.progressia.common.world.ChunkData; import ru.windcorp.progressia.common.world.DefaultChunkData;
import ru.windcorp.progressia.common.world.rels.AbsFace; import ru.windcorp.progressia.common.world.rels.AbsFace;
import ru.windcorp.progressia.common.world.rels.RelFace; import ru.windcorp.progressia.common.world.rels.RelFace;
@ -69,7 +69,7 @@ public abstract class BlockRenderTexturedCube
@Override @Override
public final void getShapeParts( public final void getShapeParts(
ChunkData chunk, Vec3i blockInChunk, RelFace blockFace, DefaultChunkData chunk, Vec3i blockInChunk, RelFace blockFace,
boolean inner, boolean inner,
Consumer<ShapePart> output, Consumer<ShapePart> output,
Vec3 offset Vec3 offset
@ -78,7 +78,7 @@ public abstract class BlockRenderTexturedCube
} }
private ShapePart createFace( private ShapePart createFace(
ChunkData chunk, Vec3i blockInChunk, RelFace blockFace, DefaultChunkData chunk, Vec3i blockInChunk, RelFace blockFace,
boolean inner, boolean inner,
Vec3 offset Vec3 offset
) { ) {
@ -93,7 +93,7 @@ public abstract class BlockRenderTexturedCube
} }
@Override @Override
public Renderable createRenderable(ChunkData chunk, Vec3i blockInChunk) { public Renderable createRenderable(DefaultChunkData chunk, Vec3i blockInChunk) {
boolean opaque = isBlockOpaque(); boolean opaque = isBlockOpaque();
ShapePart[] faces = new ShapePart[BLOCK_FACE_COUNT + (opaque ? BLOCK_FACE_COUNT : 0)]; ShapePart[] faces = new ShapePart[BLOCK_FACE_COUNT + (opaque ? BLOCK_FACE_COUNT : 0)];

View File

@ -18,8 +18,8 @@
package ru.windcorp.progressia.client.world.cro; 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.DefaultChunkData.BLOCKS_PER_CHUNK;
import static ru.windcorp.progressia.common.world.generic.GenericTileStack.TILES_PER_FACE; import static ru.windcorp.progressia.common.world.generic.TileGenericStackRO.TILES_PER_FACE;
import static ru.windcorp.progressia.common.world.rels.AbsFace.BLOCK_FACE_COUNT; import static ru.windcorp.progressia.common.world.rels.AbsFace.BLOCK_FACE_COUNT;
import java.util.ArrayList; import java.util.ArrayList;
@ -37,7 +37,7 @@ import ru.windcorp.progressia.client.world.ChunkRender;
import ru.windcorp.progressia.client.world.block.BlockRender; import ru.windcorp.progressia.client.world.block.BlockRender;
import ru.windcorp.progressia.client.world.tile.TileRender; import ru.windcorp.progressia.client.world.tile.TileRender;
import ru.windcorp.progressia.common.util.Vectors; import ru.windcorp.progressia.common.util.Vectors;
import ru.windcorp.progressia.common.world.ChunkData; import ru.windcorp.progressia.common.world.DefaultChunkData;
import ru.windcorp.progressia.common.world.generic.GenericChunks; import ru.windcorp.progressia.common.world.generic.GenericChunks;
import ru.windcorp.progressia.common.world.rels.RelFace; import ru.windcorp.progressia.common.world.rels.RelFace;
@ -71,7 +71,7 @@ public class ChunkRenderOptimizerSurface extends ChunkRenderOptimizer {
* vertices * vertices
*/ */
void getShapeParts( void getShapeParts(
ChunkData chunk, DefaultChunkData chunk,
Vec3i relBlockInChunk, Vec3i relBlockInChunk,
RelFace blockFace, RelFace blockFace,
boolean inner, boolean inner,

View File

@ -23,9 +23,9 @@ import ru.windcorp.progressia.client.graphics.backend.GraphicsInterface;
import ru.windcorp.progressia.client.graphics.model.Renderable; import ru.windcorp.progressia.client.graphics.model.Renderable;
import ru.windcorp.progressia.client.graphics.model.ShapeRenderHelper; import ru.windcorp.progressia.client.graphics.model.ShapeRenderHelper;
import ru.windcorp.progressia.common.world.entity.EntityData; import ru.windcorp.progressia.common.world.entity.EntityData;
import ru.windcorp.progressia.common.world.generic.GenericEntity; import ru.windcorp.progressia.common.world.generic.EntityGeneric;
public abstract class EntityRenderable implements Renderable, GenericEntity { public abstract class EntityRenderable implements Renderable, EntityGeneric {
private final EntityData data; private final EntityData data;

View File

@ -22,17 +22,17 @@ import glm.vec._3.i.Vec3i;
import ru.windcorp.progressia.client.graphics.model.Renderable; import ru.windcorp.progressia.client.graphics.model.Renderable;
import ru.windcorp.progressia.client.world.cro.ChunkRenderOptimizer; import ru.windcorp.progressia.client.world.cro.ChunkRenderOptimizer;
import ru.windcorp.progressia.common.util.namespaces.Namespaced; import ru.windcorp.progressia.common.util.namespaces.Namespaced;
import ru.windcorp.progressia.common.world.ChunkData; import ru.windcorp.progressia.common.world.DefaultChunkData;
import ru.windcorp.progressia.common.world.generic.GenericTile; import ru.windcorp.progressia.common.world.generic.TileGeneric;
import ru.windcorp.progressia.common.world.rels.RelFace; import ru.windcorp.progressia.common.world.rels.RelFace;
public class TileRender extends Namespaced implements GenericTile { public class TileRender extends Namespaced implements TileGeneric {
public TileRender(String id) { public TileRender(String id) {
super(id); super(id);
} }
public Renderable createRenderable(ChunkData chunk, Vec3i blockInChunk, RelFace face) { public Renderable createRenderable(DefaultChunkData chunk, Vec3i blockInChunk, RelFace face) {
return null; return null;
} }

View File

@ -20,7 +20,7 @@ package ru.windcorp.progressia.client.world.tile;
import glm.vec._3.i.Vec3i; import glm.vec._3.i.Vec3i;
import ru.windcorp.progressia.client.graphics.model.EmptyModel; import ru.windcorp.progressia.client.graphics.model.EmptyModel;
import ru.windcorp.progressia.client.graphics.model.Renderable; import ru.windcorp.progressia.client.graphics.model.Renderable;
import ru.windcorp.progressia.common.world.ChunkData; import ru.windcorp.progressia.common.world.DefaultChunkData;
import ru.windcorp.progressia.common.world.rels.RelFace; import ru.windcorp.progressia.common.world.rels.RelFace;
public class TileRenderNone extends TileRender { public class TileRenderNone extends TileRender {
@ -30,7 +30,7 @@ public class TileRenderNone extends TileRender {
} }
@Override @Override
public Renderable createRenderable(ChunkData chunk, Vec3i blockInChunk, RelFace face) { public Renderable createRenderable(DefaultChunkData chunk, Vec3i blockInChunk, RelFace face) {
return EmptyModel.getInstance(); return EmptyModel.getInstance();
} }

View File

@ -19,9 +19,9 @@ package ru.windcorp.progressia.client.world.tile;
import ru.windcorp.progressia.client.world.ChunkRender; import ru.windcorp.progressia.client.world.ChunkRender;
import ru.windcorp.progressia.client.world.block.BlockRender; import ru.windcorp.progressia.client.world.block.BlockRender;
import ru.windcorp.progressia.common.world.generic.GenericTileReference; import ru.windcorp.progressia.common.world.generic.TileGenericReferenceRO;
public interface TileRenderReference public interface TileRenderReference
extends GenericTileReference<BlockRender, TileRender, TileRenderStack, TileRenderReference, ChunkRender> { extends TileGenericReferenceRO<BlockRender, TileRender, TileRenderStack, TileRenderReference, ChunkRender> {
} }

View File

@ -18,13 +18,15 @@
package ru.windcorp.progressia.client.world.tile; package ru.windcorp.progressia.client.world.tile;
import java.util.AbstractList;
import ru.windcorp.progressia.client.world.ChunkRender; import ru.windcorp.progressia.client.world.ChunkRender;
import ru.windcorp.progressia.client.world.block.BlockRender; import ru.windcorp.progressia.client.world.block.BlockRender;
import ru.windcorp.progressia.common.world.generic.GenericTileStack; import ru.windcorp.progressia.common.world.TileDataStack;
import ru.windcorp.progressia.common.world.tile.TileDataStack; import ru.windcorp.progressia.common.world.generic.TileGenericStackRO;
public abstract class TileRenderStack public abstract class TileRenderStack
extends GenericTileStack<BlockRender, TileRender, TileRenderStack, TileRenderReference, ChunkRender> { extends AbstractList<TileRender>
implements TileGenericStackRO<BlockRender, TileRender, TileRenderStack, TileRenderReference, ChunkRender> {
public abstract TileDataStack getData(); public abstract TileDataStack getData();

View File

@ -33,7 +33,7 @@ import ru.windcorp.progressia.client.graphics.texture.Texture;
import ru.windcorp.progressia.client.graphics.world.WorldRenderProgram; import ru.windcorp.progressia.client.graphics.world.WorldRenderProgram;
import ru.windcorp.progressia.client.world.cro.ChunkRenderOptimizerSurface.TileOptimizedSurface; import ru.windcorp.progressia.client.world.cro.ChunkRenderOptimizerSurface.TileOptimizedSurface;
import ru.windcorp.progressia.common.util.Vectors; import ru.windcorp.progressia.common.util.Vectors;
import ru.windcorp.progressia.common.world.ChunkData; import ru.windcorp.progressia.common.world.DefaultChunkData;
import ru.windcorp.progressia.common.world.rels.AbsFace; import ru.windcorp.progressia.common.world.rels.AbsFace;
import ru.windcorp.progressia.common.world.rels.RelFace; import ru.windcorp.progressia.common.world.rels.RelFace;
@ -60,7 +60,7 @@ public abstract class TileRenderSurface extends TileRender implements TileOptimi
@Override @Override
public final void getShapeParts( public final void getShapeParts(
ChunkData chunk, Vec3i relBlockInChunk, RelFace blockFace, DefaultChunkData chunk, Vec3i relBlockInChunk, RelFace blockFace,
boolean inner, boolean inner,
Consumer<ShapePart> output, Consumer<ShapePart> output,
Vec3 offset Vec3 offset
@ -69,7 +69,7 @@ public abstract class TileRenderSurface extends TileRender implements TileOptimi
} }
private ShapePart createFace( private ShapePart createFace(
ChunkData chunk, Vec3i blockInChunk, RelFace blockFace, DefaultChunkData chunk, Vec3i blockInChunk, RelFace blockFace,
boolean inner, boolean inner,
Vec3 offset Vec3 offset
) { ) {
@ -84,7 +84,7 @@ public abstract class TileRenderSurface extends TileRender implements TileOptimi
} }
@Override @Override
public Renderable createRenderable(ChunkData chunk, Vec3i blockInChunk, RelFace blockFace) { public Renderable createRenderable(DefaultChunkData chunk, Vec3i blockInChunk, RelFace blockFace) {
return new Shape( return new Shape(
Usage.STATIC, Usage.STATIC,
WorldRenderProgram.getDefault(), WorldRenderProgram.getDefault(),

View File

@ -24,7 +24,7 @@ import java.util.Collection;
import glm.vec._3.Vec3; import glm.vec._3.Vec3;
import glm.vec._3.i.Vec3i; import glm.vec._3.i.Vec3i;
import ru.windcorp.progressia.common.util.LowOverheadCache; import ru.windcorp.progressia.common.util.LowOverheadCache;
import ru.windcorp.progressia.common.world.WorldData; import ru.windcorp.progressia.common.world.DefaultWorldData;
public class WorldCollisionHelper { public class WorldCollisionHelper {
@ -79,7 +79,7 @@ public class WorldCollisionHelper {
* checked against * checked against
* @param maxTime maximum collision time * @param maxTime maximum collision time
*/ */
public void tuneToCollideable(WorldData world, Collideable collideable, float maxTime) { public void tuneToCollideable(DefaultWorldData world, Collideable collideable, float maxTime) {
activeBlockModels.forEach(blockModelCache::release); activeBlockModels.forEach(blockModelCache::release);
activeBlockModels.clear(); activeBlockModels.clear();
CollisionPathComputer.forEveryBlockInCollisionPath( CollisionPathComputer.forEveryBlockInCollisionPath(

View File

@ -27,7 +27,7 @@ import glm.vec._3.Vec3;
import ru.windcorp.progressia.common.collision.*; import ru.windcorp.progressia.common.collision.*;
import ru.windcorp.progressia.common.util.LowOverheadCache; import ru.windcorp.progressia.common.util.LowOverheadCache;
import ru.windcorp.progressia.common.util.Vectors; import ru.windcorp.progressia.common.util.Vectors;
import ru.windcorp.progressia.common.world.WorldData; import ru.windcorp.progressia.common.world.DefaultWorldData;
public class Collider { public class Collider {
@ -36,7 +36,7 @@ public class Collider {
/** /**
* Dear Princess Celestia, * Dear Princess Celestia,
* <p> * <p>
* When {@linkplain #advanceTime(Collection, Collision, WorldData, float) * When {@linkplain #advanceTime(Collection, Collision, DefaultWorldData, float)
* advancing time}, * advancing time},
* time step for all entities <em>except</em> currently colliding bodies is * time step for all entities <em>except</em> currently colliding bodies is
* the current * the current
@ -61,7 +61,7 @@ public class Collider {
public static void performCollisions( public static void performCollisions(
List<? extends Collideable> colls, List<? extends Collideable> colls,
WorldData world, DefaultWorldData world,
float tickLength, float tickLength,
ColliderWorkspace workspace ColliderWorkspace workspace
) { ) {
@ -96,7 +96,7 @@ public class Collider {
private static Collision getFirstCollision( private static Collision getFirstCollision(
List<? extends Collideable> colls, List<? extends Collideable> colls,
float tickLength, float tickLength,
WorldData world, DefaultWorldData world,
ColliderWorkspace workspace ColliderWorkspace workspace
) { ) {
Collision result = null; Collision result = null;
@ -126,7 +126,7 @@ public class Collider {
private static void tuneWorldCollisionHelper( private static void tuneWorldCollisionHelper(
Collideable coll, Collideable coll,
float tickLength, float tickLength,
WorldData world, DefaultWorldData world,
ColliderWorkspace workspace ColliderWorkspace workspace
) { ) {
WorldCollisionHelper wch = workspace.worldCollisionHelper; WorldCollisionHelper wch = workspace.worldCollisionHelper;
@ -194,7 +194,7 @@ public class Collider {
Collision collision, Collision collision,
Collection<? extends Collideable> colls, Collection<? extends Collideable> colls,
WorldData world, DefaultWorldData world,
float tickLength, float tickLength,
ColliderWorkspace workspace ColliderWorkspace workspace
) { ) {
@ -361,7 +361,7 @@ public class Collider {
private static void advanceTime( private static void advanceTime(
Collection<? extends Collideable> colls, Collection<? extends Collideable> colls,
Collision exceptions, Collision exceptions,
WorldData world, DefaultWorldData world,
float step float step
) { ) {
world.advanceTime(step); world.advanceTime(step);

View File

@ -16,12 +16,9 @@
* along with this program. If not, see <https://www.gnu.org/licenses/>. * along with this program. If not, see <https://www.gnu.org/licenses/>.
*/ */
package ru.windcorp.progressia.common.world.tile; package ru.windcorp.progressia.common.state;
import ru.windcorp.progressia.common.world.ChunkData;
import ru.windcorp.progressia.common.world.block.BlockData;
import ru.windcorp.progressia.common.world.generic.GenericTileReference;
public interface TileDataReference extends GenericTileReference<BlockData, TileData, TileDataStack, TileDataReference, ChunkData> {
@FunctionalInterface
public interface StateChange<T> {
void change(T object);
} }

View File

@ -1,527 +1,14 @@
/*
* 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; package ru.windcorp.progressia.common.world;
import static ru.windcorp.progressia.common.world.rels.BlockFace.BLOCK_FACE_COUNT;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.Objects;
import glm.vec._3.i.Vec3i;
import ru.windcorp.progressia.common.world.block.BlockData; import ru.windcorp.progressia.common.world.block.BlockData;
import ru.windcorp.progressia.common.world.generic.GenericChunks; import ru.windcorp.progressia.common.world.generic.ChunkGenericWO;
import ru.windcorp.progressia.common.world.generic.GenericWritableChunk;
import ru.windcorp.progressia.common.world.rels.AbsFace;
import ru.windcorp.progressia.common.world.rels.BlockFace;
import ru.windcorp.progressia.common.world.rels.RelFace;
import ru.windcorp.progressia.common.world.tile.TileData; import ru.windcorp.progressia.common.world.tile.TileData;
import ru.windcorp.progressia.common.world.tile.TileDataReference;
import ru.windcorp.progressia.common.world.tile.TileDataStack;
import ru.windcorp.progressia.common.world.tile.TileStackIsFullException;
public class ChunkData public interface ChunkData extends ChunkDataRO, ChunkGenericWO<BlockData, TileData, TileDataStack, TileDataReference, ChunkData> {
implements GenericWritableChunk<BlockData, TileData, TileDataStack, TileDataReference, ChunkData> {
public static final int BLOCKS_PER_CHUNK = Coordinates.CHUNK_SIZE; // @Override
public static final int CHUNK_RADIUS = BLOCKS_PER_CHUNK / 2; // default TileDataStack getTiles(Vec3i blockInChunk, BlockFace face) {
// return null;
private final Vec3i position = new Vec3i(); // }
private final WorldData world;
private final BlockData[] blocks = new BlockData[BLOCKS_PER_CHUNK * BLOCKS_PER_CHUNK * BLOCKS_PER_CHUNK];
private final TileDataStack[] tiles = new TileDataStack[
BLOCKS_PER_CHUNK * BLOCKS_PER_CHUNK * BLOCKS_PER_CHUNK * BLOCK_FACE_COUNT
];
private final AbsFace up;
private Object generationHint = null;
private final Collection<ChunkDataListener> listeners = Collections.synchronizedCollection(new ArrayList<>());
public ChunkData(Vec3i position, WorldData world) {
this.position.set(position.x, position.y, position.z);
this.world = world;
this.up = world.getGravityModel().getDiscreteUp(position);
}
@Override
public Vec3i getPosition() {
return position;
}
@Override
public AbsFace getUp() {
return up;
}
@Override
public BlockData getBlock(Vec3i posInChunk) {
return blocks[getBlockIndex(posInChunk)];
}
@Override
public void setBlock(Vec3i posInChunk, BlockData block, boolean notify) {
BlockData previous = blocks[getBlockIndex(posInChunk)];
blocks[getBlockIndex(posInChunk)] = block;
if (notify) {
getListeners().forEach(l -> {
l.onChunkBlockChanged(this, posInChunk, previous, block);
l.onChunkChanged(this);
});
}
}
@Override
public TileDataStack getTilesOrNull(Vec3i blockInChunk, BlockFace face) {
return tiles[getTileIndex(blockInChunk, face)];
}
/**
* Internal use only. Modify a list returned by
* {@link #getTiles(Vec3i, BlockFace)} or
* {@link #getTilesOrNull(Vec3i, BlockFace)}
* to change tiles.
*/
protected void setTiles(
Vec3i blockInChunk,
BlockFace face,
TileDataStack tiles
) {
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);
if (tiles[index] == null) {
createTileStack(blockInChunk, face);
}
return tiles[index];
}
private void createTileStack(Vec3i blockInChunk, BlockFace face) {
Vec3i independentBlockInChunk = conjureIndependentBlockInChunkVec3i(blockInChunk);
TileDataStackImpl stack = new TileDataStackImpl(independentBlockInChunk, face);
setTiles(blockInChunk, face, stack);
}
private Vec3i conjureIndependentBlockInChunkVec3i(Vec3i blockInChunk) {
for (int i = 0; i < AbsFace.BLOCK_FACE_COUNT; ++i) {
TileDataStack stack = getTilesOrNull(blockInChunk, AbsFace.getFaces().get(i));
if (stack instanceof TileDataStackImpl) {
return ((TileDataStackImpl) stack).blockInChunk;
}
}
return new Vec3i(blockInChunk);
}
private static int getBlockIndex(Vec3i posInChunk) {
checkLocalCoordinates(posInChunk);
return posInChunk.z * BLOCKS_PER_CHUNK * BLOCKS_PER_CHUNK +
posInChunk.y * BLOCKS_PER_CHUNK +
posInChunk.x;
}
private int getTileIndex(Vec3i posInChunk, BlockFace face) {
return getBlockIndex(posInChunk) * BLOCK_FACE_COUNT +
face.resolve(getUp()).getId();
}
private static void checkLocalCoordinates(Vec3i posInChunk) {
if (!GenericChunks.containsBiC(posInChunk)) {
throw new IllegalCoordinatesException(
"Coordinates (" + posInChunk.x + "; " + posInChunk.y + "; " + posInChunk.z + ") "
+ "are not legal chunk coordinates"
);
}
}
public WorldData getWorld() {
return world;
}
public Collection<ChunkDataListener> getListeners() {
return listeners;
}
public void addListener(ChunkDataListener listener) {
this.listeners.add(listener);
}
public void removeListener(ChunkDataListener listener) {
this.listeners.remove(listener);
}
protected void onLoaded() {
getListeners().forEach(l -> l.onChunkLoaded(this));
}
protected void beforeUnloaded() {
getListeners().forEach(l -> l.beforeChunkUnloaded(this));
}
public Object getGenerationHint() {
return generationHint;
}
public void setGenerationHint(Object generationHint) {
this.generationHint = generationHint;
}
/**
* Implementation of {@link TileDataStack} used internally by
* {@link ChunkData} to
* actually store the tiles. This is basically an array wrapper with
* reporting
* capabilities.
*
* @author javapony
*/
private class TileDataStackImpl extends TileDataStack {
private class TileDataReferenceImpl implements TileDataReference {
private int index;
public TileDataReferenceImpl(int index) {
this.index = index;
}
public void incrementIndex() {
this.index++;
}
public void decrementIndex() {
this.index--;
}
public void invalidate() {
this.index = 0;
}
@Override
public TileData get() {
if (!isValid())
return null;
return TileDataStackImpl.this.get(this.index);
}
@Override
public int getIndex() {
return index;
}
@Override
public TileDataStack getStack() {
return TileDataStackImpl.this;
}
@Override
public boolean isValid() {
return this.index >= 0;
}
}
private final TileData[] tiles = new TileData[TILES_PER_FACE];
private int size = 0;
private final TileDataReferenceImpl[] references = new TileDataReferenceImpl[tiles.length];
private final int[] indicesByTag = new int[tiles.length];
private final int[] tagsByIndex = new int[tiles.length];
{
Arrays.fill(indicesByTag, -1);
Arrays.fill(tagsByIndex, -1);
}
/*
* Potentially shared
*/
private final Vec3i blockInChunk;
private final RelFace face;
public TileDataStackImpl(Vec3i blockInChunk, BlockFace face) {
this.blockInChunk = blockInChunk;
this.face = face.relativize(getUp());
}
@Override
public Vec3i getBlockInChunk(Vec3i output) {
if (output == null)
output = new Vec3i();
output.set(blockInChunk.x, blockInChunk.y, blockInChunk.z);
return output;
}
@Override
public RelFace getFace() {
return face;
}
@Override
public ChunkData getChunk() {
return ChunkData.this;
}
@Override
public int size() {
return size;
}
@Override
public TileData get(int index) {
checkIndex(index, false);
return tiles[index];
}
@Override
public TileData set(int index, TileData tile) {
Objects.requireNonNull(tile, "tile");
TileData previous = get(index); // checks index
tiles[index] = tile;
if (references[index] != null) {
references[index].invalidate();
references[index] = null;
}
assert checkConsistency();
report(previous, tile);
return previous;
}
@Override
public void add(int index, TileData tile) {
Objects.requireNonNull(tile, "tile");
checkIndex(index, true);
if (index != size()) {
System.arraycopy(tiles, index + 1, tiles, index + 2, size - index);
for (int i = index; i < size; ++i) {
if (references[i] != null) {
references[i].incrementIndex();
}
indicesByTag[tagsByIndex[i]]++;
}
System.arraycopy(references, index + 1, references, index + 2, size - index);
System.arraycopy(tagsByIndex, index + 1, tagsByIndex, index + 2, size - index);
}
size++;
tiles[index] = tile;
references[index] = null;
for (int tag = 0; tag < indicesByTag.length; ++tag) {
if (indicesByTag[tag] == -1) {
indicesByTag[tag] = index;
tagsByIndex[index] = tag;
break;
}
}
modCount++;
assert checkConsistency();
report(null, tile);
}
@Override
public void load(TileData tile, int tag) {
addFarthest(tile);
int assignedIndex = size() - 1;
// Skip if we already have the correct tag
int assignedTag = getTagByIndex(assignedIndex);
if (assignedTag == tag) {
return;
}
assert assignedTag != -1 : "Adding farthest tile resulted in -1 tag";
// Make sure we aren't trying to assign a tag already in use
int tileWithRequestedTag = getIndexByTag(tag);
if (tileWithRequestedTag != -1) {
throw new IllegalArgumentException(
"Tag " + tag + " already used by tile at index " + tileWithRequestedTag
);
}
assert tileWithRequestedTag != assignedIndex : "tag == assignedTag yet tileWithRequestedTag != assignedIndex";
// Do the tag editing
indicesByTag[assignedTag] = -1; // Release assigned tag
tagsByIndex[assignedIndex] = tag; // Reroute assigned index to requested tag
indicesByTag[tag] = assignedIndex; // Claim requested tag
assert checkConsistency();
}
@Override
public TileData remove(int index) {
TileData previous = get(index); // checks index
if (references[index] != null) {
references[index].invalidate();
}
indicesByTag[tagsByIndex[index]] = -1;
if (index != size() - 1) {
System.arraycopy(tiles, index + 1, tiles, index, size - index - 1);
for (int i = index + 1; i < size; ++i) {
if (references[i] != null) {
references[i].decrementIndex();
}
indicesByTag[tagsByIndex[i]]--;
}
System.arraycopy(references, index + 1, references, index, size - index - 1);
System.arraycopy(tagsByIndex, index + 1, tagsByIndex, index, size - index - 1);
}
size--;
tiles[size] = null;
references[size] = null;
tagsByIndex[size] = -1;
modCount++;
assert checkConsistency();
report(previous, null);
return previous;
}
@Override
public TileDataReference getReference(int index) {
checkIndex(index, false);
if (references[index] == null) {
references[index] = new TileDataReferenceImpl(index);
}
return references[index];
}
@Override
public int getIndexByTag(int tag) {
return indicesByTag[tag];
}
@Override
public int getTagByIndex(int index) {
checkIndex(index, false);
return tagsByIndex[index];
}
@Override
public void clear() {
while (!isEmpty()) {
removeFarthest();
}
}
private void checkIndex(int index, boolean isSizeAllowed) {
if (isSizeAllowed ? (index > size()) : (index >= size()))
throw new IndexOutOfBoundsException("Index " + index + " is out of bounds: size is " + size);
if (index < 0)
throw new IndexOutOfBoundsException("Index " + index + " is out of bounds: index cannot be negative");
if (index >= TILES_PER_FACE)
throw new TileStackIsFullException(
"Index " + index + " is out of bounds: maximum tile stack size is " + TILES_PER_FACE
);
}
private void report(TileData previous, TileData current) {
ChunkData.this.getListeners().forEach(l -> {
if (previous != null) {
l.onChunkTilesChanged(ChunkData.this, blockInChunk, face, previous, false);
}
if (current != null) {
l.onChunkTilesChanged(ChunkData.this, blockInChunk, face, current, true);
}
l.onChunkChanged(ChunkData.this);
});
}
private boolean checkConsistency() {
int index;
for (index = 0; index < size(); ++index) {
if (get(index) == null)
throw new AssertionError("get(index) is null");
if (references[index] != null) {
TileDataReference ref = getReference(index);
if (ref == null)
throw new AssertionError("references[index] is not null but getReference(index) is");
if (!ref.isValid())
throw new AssertionError("Reference is not valid");
if (ref.get() != get(index))
throw new AssertionError("Reference points to " + (ref.get() == null ? "null" : "wrong tile"));
if (ref.getIndex() != index)
throw new AssertionError("Reference has invalid index");
if (ref.getStack() != this)
throw new AssertionError("Reference has invalid TDS");
}
if (index != indicesByTag[tagsByIndex[index]])
throw new AssertionError("Tag mapping is inconsistent");
if (index != getIndexByTag(getTagByIndex(index)))
throw new AssertionError("Tag methods are inconsistent with tag mapping");
}
for (; index < tiles.length; ++index) {
if (tiles[index] != null)
throw new AssertionError("Leftover tile detected");
if (references[index] != null)
throw new AssertionError("Leftover reference detected");
if (tagsByIndex[index] != -1)
throw new AssertionError("Leftover tags detected");
}
return true;
}
}
} }

View File

@ -36,7 +36,7 @@ public interface ChunkDataListener {
* @param previous the previous occupant of {@code blockInChunk} * @param previous the previous occupant of {@code blockInChunk}
* @param current the current (new) occupant of {@code blockInChunk} * @param current the current (new) occupant of {@code blockInChunk}
*/ */
default void onChunkBlockChanged(ChunkData chunk, Vec3i blockInChunk, BlockData previous, BlockData current) { default void onChunkBlockChanged(DefaultChunkData chunk, Vec3i blockInChunk, BlockData previous, BlockData current) {
} }
/** /**
@ -53,7 +53,7 @@ public interface ChunkDataListener {
* {@code false} iff the tile has been removed * {@code false} iff the tile has been removed
*/ */
default void onChunkTilesChanged( default void onChunkTilesChanged(
ChunkData chunk, DefaultChunkData chunk,
Vec3i blockInChunk, Vec3i blockInChunk,
RelFace face, RelFace face,
TileData tile, TileData tile,
@ -70,7 +70,7 @@ public interface ChunkDataListener {
* *
* @param chunk the chunk that has changed * @param chunk the chunk that has changed
*/ */
default void onChunkChanged(ChunkData chunk) { default void onChunkChanged(DefaultChunkData chunk) {
} }
/** /**
@ -78,7 +78,7 @@ public interface ChunkDataListener {
* *
* @param chunk the chunk that has loaded * @param chunk the chunk that has loaded
*/ */
default void onChunkLoaded(ChunkData chunk) { default void onChunkLoaded(DefaultChunkData chunk) {
} }
/** /**
@ -86,7 +86,7 @@ public interface ChunkDataListener {
* *
* @param chunk the chunk that is going to be loaded * @param chunk the chunk that is going to be loaded
*/ */
default void beforeChunkUnloaded(ChunkData chunk) { default void beforeChunkUnloaded(DefaultChunkData chunk) {
} }
} }

View File

@ -28,7 +28,7 @@ public class ChunkDataListeners {
public static WorldDataListener createAdder(Supplier<ChunkDataListener> listenerSupplier) { public static WorldDataListener createAdder(Supplier<ChunkDataListener> listenerSupplier) {
return new WorldDataListener() { return new WorldDataListener() {
@Override @Override
public void getChunkListeners(WorldData world, Vec3i chunk, Consumer<ChunkDataListener> chunkListenerSink) { public void getChunkListeners(DefaultWorldData world, Vec3i chunk, Consumer<ChunkDataListener> chunkListenerSink) {
chunkListenerSink.accept(listenerSupplier.get()); chunkListenerSink.accept(listenerSupplier.get());
} }
}; };

View File

@ -0,0 +1,12 @@
package ru.windcorp.progressia.common.world;
import ru.windcorp.progressia.common.world.block.BlockData;
import ru.windcorp.progressia.common.world.generic.ChunkGenericRO;
import ru.windcorp.progressia.common.world.tile.TileData;
public interface ChunkDataRO
extends ChunkGenericRO<BlockData, TileData, TileDataStackRO, TileDataReferenceRO, ChunkDataRO> {
// currently empty
}

View File

@ -18,7 +18,7 @@
package ru.windcorp.progressia.common.world; package ru.windcorp.progressia.common.world;
import static ru.windcorp.progressia.common.world.ChunkData.BLOCKS_PER_CHUNK; import static ru.windcorp.progressia.common.world.DefaultChunkData.BLOCKS_PER_CHUNK;
import glm.vec._3.i.Vec3i; import glm.vec._3.i.Vec3i;

View File

@ -0,0 +1,525 @@
/*
* 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;
import static ru.windcorp.progressia.common.world.rels.BlockFace.BLOCK_FACE_COUNT;
import java.util.AbstractList;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
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.GenericChunks;
import ru.windcorp.progressia.common.world.rels.AbsFace;
import ru.windcorp.progressia.common.world.rels.BlockFace;
import ru.windcorp.progressia.common.world.rels.RelFace;
import ru.windcorp.progressia.common.world.tile.TileData;
import ru.windcorp.progressia.common.world.tile.TileStackIsFullException;
public class DefaultChunkData implements ChunkData {
public static final int BLOCKS_PER_CHUNK = Coordinates.CHUNK_SIZE;
public static final int CHUNK_RADIUS = BLOCKS_PER_CHUNK / 2;
private final Vec3i position = new Vec3i();
private final DefaultWorldData world;
private final BlockData[] blocks = new BlockData[BLOCKS_PER_CHUNK * BLOCKS_PER_CHUNK * BLOCKS_PER_CHUNK];
private final TileDataStack[] tiles = new TileDataStack[BLOCKS_PER_CHUNK * BLOCKS_PER_CHUNK * BLOCKS_PER_CHUNK
* BLOCK_FACE_COUNT];
private final AbsFace up;
private Object generationHint = null;
private final Collection<ChunkDataListener> listeners = Collections.synchronizedCollection(new ArrayList<>());
public DefaultChunkData(Vec3i position, DefaultWorldData world) {
this.position.set(position.x, position.y, position.z);
this.world = world;
this.up = world.getGravityModel().getDiscreteUp(position);
}
@Override
public Vec3i getPosition() {
return position;
}
@Override
public AbsFace getUp() {
return up;
}
@Override
public BlockData getBlock(Vec3i posInChunk) {
return blocks[getBlockIndex(posInChunk)];
}
@Override
public void setBlock(Vec3i posInChunk, BlockData block, boolean notify) {
BlockData previous = blocks[getBlockIndex(posInChunk)];
blocks[getBlockIndex(posInChunk)] = block;
if (notify) {
getListeners().forEach(l -> {
l.onChunkBlockChanged(this, posInChunk, previous, block);
l.onChunkChanged(this);
});
}
}
@Override
public TileDataStack getTilesOrNull(Vec3i blockInChunk, BlockFace face) {
return tiles[getTileIndex(blockInChunk, face)];
}
/**
* Internal use only. Modify a list returned by
* {@link #getTiles(Vec3i, BlockFace)} or
* {@link #getTilesOrNull(Vec3i, BlockFace)}
* to change tiles.
*/
protected void setTiles(
Vec3i blockInChunk,
BlockFace face,
TileDataStack tiles
) {
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);
if (tiles[index] == null) {
createTileStack(blockInChunk, face);
}
return tiles[index];
}
private void createTileStack(Vec3i blockInChunk, BlockFace face) {
Vec3i independentBlockInChunk = conjureIndependentBlockInChunkVec3i(blockInChunk);
TileDataStackImpl stack = new TileDataStackImpl(independentBlockInChunk, face);
setTiles(blockInChunk, face, stack);
}
private Vec3i conjureIndependentBlockInChunkVec3i(Vec3i blockInChunk) {
for (int i = 0; i < AbsFace.BLOCK_FACE_COUNT; ++i) {
TileDataStack stack = getTilesOrNull(blockInChunk, AbsFace.getFaces().get(i));
if (stack instanceof TileDataStackImpl) {
return ((TileDataStackImpl) stack).blockInChunk;
}
}
return new Vec3i(blockInChunk);
}
private static int getBlockIndex(Vec3i posInChunk) {
checkLocalCoordinates(posInChunk);
return posInChunk.z * BLOCKS_PER_CHUNK * BLOCKS_PER_CHUNK +
posInChunk.y * BLOCKS_PER_CHUNK +
posInChunk.x;
}
private int getTileIndex(Vec3i posInChunk, BlockFace face) {
return getBlockIndex(posInChunk) * BLOCK_FACE_COUNT +
face.resolve(getUp()).getId();
}
private static void checkLocalCoordinates(Vec3i posInChunk) {
if (!GenericChunks.containsBiC(posInChunk)) {
throw new IllegalCoordinatesException(
"Coordinates (" + posInChunk.x + "; " + posInChunk.y + "; " + posInChunk.z + ") "
+ "are not legal chunk coordinates"
);
}
}
public DefaultWorldData getWorld() {
return world;
}
public Collection<ChunkDataListener> getListeners() {
return listeners;
}
public void addListener(ChunkDataListener listener) {
this.listeners.add(listener);
}
public void removeListener(ChunkDataListener listener) {
this.listeners.remove(listener);
}
protected void onLoaded() {
getListeners().forEach(l -> l.onChunkLoaded(this));
}
protected void beforeUnloaded() {
getListeners().forEach(l -> l.beforeChunkUnloaded(this));
}
public Object getGenerationHint() {
return generationHint;
}
public void setGenerationHint(Object generationHint) {
this.generationHint = generationHint;
}
/**
* Implementation of {@link TileDataStack} used internally by
* {@link DefaultChunkData} to
* actually store the tiles. This is basically an array wrapper with
* reporting
* capabilities.
*
* @author javapony
*/
private class TileDataStackImpl extends AbstractList<TileData> implements TileDataStack {
private class TileDataReferenceImpl implements TileDataReference {
private int index;
public TileDataReferenceImpl(int index) {
this.index = index;
}
public void incrementIndex() {
this.index++;
}
public void decrementIndex() {
this.index--;
}
public void invalidate() {
this.index = 0;
}
@Override
public TileData get() {
if (!isValid())
return null;
return TileDataStackImpl.this.get(this.index);
}
@Override
public int getIndex() {
return index;
}
@Override
public TileDataStack getStack() {
return TileDataStackImpl.this;
}
@Override
public boolean isValid() {
return this.index >= 0;
}
}
private final TileData[] tiles = new TileData[TILES_PER_FACE];
private int size = 0;
private final TileDataReferenceImpl[] references = new TileDataReferenceImpl[tiles.length];
private final int[] indicesByTag = new int[tiles.length];
private final int[] tagsByIndex = new int[tiles.length];
{
Arrays.fill(indicesByTag, -1);
Arrays.fill(tagsByIndex, -1);
}
/*
* Potentially shared
*/
private final Vec3i blockInChunk;
private final RelFace face;
public TileDataStackImpl(Vec3i blockInChunk, BlockFace face) {
this.blockInChunk = blockInChunk;
this.face = face.relativize(getUp());
}
@Override
public Vec3i getBlockInChunk(Vec3i output) {
if (output == null)
output = new Vec3i();
output.set(blockInChunk.x, blockInChunk.y, blockInChunk.z);
return output;
}
@Override
public RelFace getFace() {
return face;
}
@Override
public DefaultChunkData getChunk() {
return DefaultChunkData.this;
}
@Override
public int size() {
return size;
}
@Override
public TileData get(int index) {
checkIndex(index, false);
return tiles[index];
}
@Override
public TileData set(int index, TileData tile) {
Objects.requireNonNull(tile, "tile");
TileData previous = get(index); // checks index
tiles[index] = tile;
if (references[index] != null) {
references[index].invalidate();
references[index] = null;
}
assert checkConsistency();
report(previous, tile);
return previous;
}
@Override
public void add(int index, TileData tile) {
Objects.requireNonNull(tile, "tile");
checkIndex(index, true);
if (index != size()) {
System.arraycopy(tiles, index + 1, tiles, index + 2, size - index);
for (int i = index; i < size; ++i) {
if (references[i] != null) {
references[i].incrementIndex();
}
indicesByTag[tagsByIndex[i]]++;
}
System.arraycopy(references, index + 1, references, index + 2, size - index);
System.arraycopy(tagsByIndex, index + 1, tagsByIndex, index + 2, size - index);
}
size++;
tiles[index] = tile;
references[index] = null;
for (int tag = 0; tag < indicesByTag.length; ++tag) {
if (indicesByTag[tag] == -1) {
indicesByTag[tag] = index;
tagsByIndex[index] = tag;
break;
}
}
modCount++;
assert checkConsistency();
report(null, tile);
}
@Override
public void load(TileData tile, int tag) {
addFarthest(tile);
int assignedIndex = size() - 1;
// Skip if we already have the correct tag
int assignedTag = getTagByIndex(assignedIndex);
if (assignedTag == tag) {
return;
}
assert assignedTag != -1 : "Adding farthest tile resulted in -1 tag";
// Make sure we aren't trying to assign a tag already in use
int tileWithRequestedTag = getIndexByTag(tag);
if (tileWithRequestedTag != -1) {
throw new IllegalArgumentException(
"Tag " + tag + " already used by tile at index " + tileWithRequestedTag
);
}
assert tileWithRequestedTag != assignedIndex
: "tag == assignedTag yet tileWithRequestedTag != assignedIndex";
// Do the tag editing
indicesByTag[assignedTag] = -1; // Release assigned tag
tagsByIndex[assignedIndex] = tag; // Reroute assigned index to
// requested tag
indicesByTag[tag] = assignedIndex; // Claim requested tag
assert checkConsistency();
}
@Override
public TileData remove(int index) {
TileData previous = get(index); // checks index
if (references[index] != null) {
references[index].invalidate();
}
indicesByTag[tagsByIndex[index]] = -1;
if (index != size() - 1) {
System.arraycopy(tiles, index + 1, tiles, index, size - index - 1);
for (int i = index + 1; i < size; ++i) {
if (references[i] != null) {
references[i].decrementIndex();
}
indicesByTag[tagsByIndex[i]]--;
}
System.arraycopy(references, index + 1, references, index, size - index - 1);
System.arraycopy(tagsByIndex, index + 1, tagsByIndex, index, size - index - 1);
}
size--;
tiles[size] = null;
references[size] = null;
tagsByIndex[size] = -1;
modCount++;
assert checkConsistency();
report(previous, null);
return previous;
}
@Override
public TileDataReference getReference(int index) {
checkIndex(index, false);
if (references[index] == null) {
references[index] = new TileDataReferenceImpl(index);
}
return references[index];
}
@Override
public int getIndexByTag(int tag) {
return indicesByTag[tag];
}
@Override
public int getTagByIndex(int index) {
checkIndex(index, false);
return tagsByIndex[index];
}
@Override
public void clear() {
while (!isEmpty()) {
removeFarthest();
}
}
private void checkIndex(int index, boolean isSizeAllowed) {
if (isSizeAllowed ? (index > size()) : (index >= size()))
throw new IndexOutOfBoundsException("Index " + index + " is out of bounds: size is " + size);
if (index < 0)
throw new IndexOutOfBoundsException("Index " + index + " is out of bounds: index cannot be negative");
if (index >= TILES_PER_FACE)
throw new TileStackIsFullException(
"Index " + index + " is out of bounds: maximum tile stack size is " + TILES_PER_FACE
);
}
private void report(TileData previous, TileData current) {
DefaultChunkData.this.getListeners().forEach(l -> {
if (previous != null) {
l.onChunkTilesChanged(DefaultChunkData.this, blockInChunk, face, previous, false);
}
if (current != null) {
l.onChunkTilesChanged(DefaultChunkData.this, blockInChunk, face, current, true);
}
l.onChunkChanged(DefaultChunkData.this);
});
}
private boolean checkConsistency() {
int index;
for (index = 0; index < size(); ++index) {
if (get(index) == null)
throw new AssertionError("get(index) is null");
if (references[index] != null) {
TileDataReference ref = getReference(index);
if (ref == null)
throw new AssertionError("references[index] is not null but getReference(index) is");
if (!ref.isValid())
throw new AssertionError("Reference is not valid");
if (ref.get() != get(index))
throw new AssertionError("Reference points to " + (ref.get() == null ? "null" : "wrong tile"));
if (ref.getIndex() != index)
throw new AssertionError("Reference has invalid index");
if (ref.getStack() != this)
throw new AssertionError("Reference has invalid TDS");
}
if (index != indicesByTag[tagsByIndex[index]])
throw new AssertionError("Tag mapping is inconsistent");
if (index != getIndexByTag(getTagByIndex(index)))
throw new AssertionError("Tag methods are inconsistent with tag mapping");
}
for (; index < tiles.length; ++index) {
if (tiles[index] != null)
throw new AssertionError("Leftover tile detected");
if (references[index] != null)
throw new AssertionError("Leftover reference detected");
if (tagsByIndex[index] != -1)
throw new AssertionError("Leftover tags detected");
}
return true;
}
}
}

View File

@ -0,0 +1,262 @@
/*
* 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;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Objects;
import java.util.function.Consumer;
import glm.vec._3.i.Vec3i;
import gnu.trove.TCollections;
import gnu.trove.map.TLongObjectMap;
import gnu.trove.map.hash.TLongObjectHashMap;
import gnu.trove.set.TLongSet;
import ru.windcorp.progressia.common.collision.CollisionModel;
import ru.windcorp.progressia.common.state.StateChange;
import ru.windcorp.progressia.common.state.StatefulObject;
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.EntityGeneric;
import ru.windcorp.progressia.common.world.rels.BlockFace;
import ru.windcorp.progressia.common.world.generic.LongBasedChunkMap;
public class DefaultWorldData implements WorldData {
private final ChunkMap<DefaultChunkData> chunksByPos = new LongBasedChunkMap<>(
TCollections.synchronizedMap(new TLongObjectHashMap<>())
);
private final Collection<DefaultChunkData> chunks = Collections.unmodifiableCollection(chunksByPos.values());
private final TLongObjectMap<EntityData> entitiesById = TCollections.synchronizedMap(new TLongObjectHashMap<>());
private final Collection<EntityData> entities = Collections.unmodifiableCollection(entitiesById.valueCollection());
private GravityModel gravityModel = null;
private float time = 0;
private final Collection<WorldDataListener> listeners = Collections.synchronizedCollection(new ArrayList<>());
public DefaultWorldData() {
}
@Override
public DefaultChunkData getChunk(Vec3i pos) {
return chunksByPos.get(pos);
}
@Override
public DefaultChunkData getChunkByBlock(Vec3i blockInWorld) {
return (DefaultChunkData) WorldData.super.getChunkByBlock(blockInWorld);
}
@Override
public Collection<DefaultChunkData> getChunks() {
return chunks;
}
public ChunkSet getLoadedChunks() {
return chunksByPos.keys();
}
@Override
public Collection<EntityData> getEntities() {
return entities;
}
@Override
public void forEachEntity(Consumer<? super EntityData> action) {
synchronized (entitiesById) { // TODO HORRIBLY MUTILATE THE CORPSE OF
// TROVE4J so that
// gnu.trove.impl.sync.SynchronizedCollection.forEach
// is synchronized
getEntities().forEach(action);
}
}
public TLongSet getLoadedEntities() {
return entitiesById.keySet();
}
private void addChunkListeners(DefaultChunkData chunk) {
getListeners().forEach(l -> l.getChunkListeners(this, chunk.getPosition(), chunk::addListener));
}
public synchronized void addChunk(DefaultChunkData chunk) {
addChunkListeners(chunk);
DefaultChunkData previous = chunksByPos.get(chunk);
if (previous != null) {
throw new IllegalArgumentException(
String.format(
"Chunk at (%d; %d; %d) already exists",
chunk.getPosition().x,
chunk.getPosition().y,
chunk.getPosition().z
)
);
}
chunksByPos.put(chunk, chunk);
chunk.onLoaded();
getListeners().forEach(l -> l.onChunkLoaded(this, chunk));
}
public synchronized void removeChunk(DefaultChunkData chunk) {
getListeners().forEach(l -> l.beforeChunkUnloaded(this, chunk));
chunk.beforeUnloaded();
chunksByPos.remove(chunk);
}
@Override
public void setBlock(Vec3i blockInWorld, BlockData block, boolean notify) {
DefaultChunkData chunk = getChunkByBlock(blockInWorld);
if (chunk == null)
throw new IllegalCoordinatesException(
"Coordinates "
+ "(" + blockInWorld.x + "; " + blockInWorld.y + "; " + blockInWorld.z + ") "
+ "do not belong to a loaded chunk"
);
chunk.setBlock(Coordinates.convertInWorldToInChunk(blockInWorld, null), block, notify);
}
@Override
public TileDataStack getTiles(Vec3i blockInWorld, BlockFace face) {
return WorldData.super.getTiles(blockInWorld, face);
}
@Override
public EntityData getEntity(long entityId) {
return entitiesById.get(entityId);
}
@Override
public void addEntity(EntityData entity) {
Objects.requireNonNull(entity, "entity");
EntityData previous = entitiesById.putIfAbsent(entity.getEntityId(), entity);
if (previous != null) {
String message = "Cannot add entity " + entity + ": ";
if (previous == entity) {
message += "already present";
} else {
message += "entity with the same EntityID already present (" + previous + ")";
}
throw new IllegalStateException(message);
}
getListeners().forEach(l -> l.onEntityAdded(this, entity));
}
@Override
public void removeEntity(long entityId) {
synchronized (entitiesById) {
EntityData entity = entitiesById.get(entityId);
if (entity == null) {
throw new IllegalArgumentException(
"Entity with EntityID " + EntityData.formatEntityId(entityId) + " not present"
);
} else {
removeEntity(entity);
}
}
}
@Override
public void removeEntity(EntityData entity) {
Objects.requireNonNull(entity, "entity");
getListeners().forEach(l -> l.beforeEntityRemoved(this, entity));
entitiesById.remove(entity.getEntityId());
}
@Override
public <SE extends StatefulObject & EntityGeneric> void changeEntity(SE entity, StateChange<SE> change) {
change.change(entity);
}
@Override
public float getTime() {
return time;
}
@Override
public void advanceTime(float change) {
this.time += change;
}
public CollisionModel getCollisionModelOfBlock(Vec3i blockInWorld) {
DefaultChunkData chunk = getChunkByBlock(blockInWorld);
if (chunk == null)
return null;
BlockData block = chunk.getBlock(Coordinates.convertInWorldToInChunk(blockInWorld, null));
if (block == null)
return null;
return block.getCollisionModel();
}
/**
* @return the gravity model
*/
@Override
public GravityModel getGravityModel() {
return gravityModel;
}
/**
* @param gravityModel the gravity model to set
*/
public void setGravityModel(GravityModel gravityModel) {
if (!chunks.isEmpty()) {
throw new IllegalStateException(
"Attempted to change gravity model to " + gravityModel + " while " + chunks.size()
+ " chunks were loaded"
);
}
this.gravityModel = gravityModel;
}
public Collection<WorldDataListener> getListeners() {
return listeners;
}
public void addListener(WorldDataListener e) {
listeners.add(e);
}
public void removeListener(WorldDataListener o) {
listeners.remove(o);
}
}

View File

@ -26,6 +26,6 @@ public abstract class PacketAffectWorld extends Packet {
super(id); super(id);
} }
public abstract void apply(WorldData world); public abstract void apply(DefaultWorldData world);
} }

View File

@ -53,9 +53,9 @@ public class PacketRevokeChunk extends PacketAffectChunk {
} }
@Override @Override
public void apply(WorldData world) { public void apply(DefaultWorldData world) {
synchronized (world) { synchronized (world) {
ChunkData chunk = world.getChunk(position); DefaultChunkData chunk = world.getChunk(position);
if (chunk != null) { if (chunk != null) {
world.removeChunk(chunk); world.removeChunk(chunk);
} }

View File

@ -41,7 +41,7 @@ public class PacketSendChunk extends PacketAffectChunk {
super(id); super(id);
} }
public void set(ChunkData chunk) { public void set(DefaultChunkData chunk) {
this.position.set(chunk.getX(), chunk.getY(), chunk.getZ()); this.position.set(chunk.getX(), chunk.getY(), chunk.getZ());
try { try {
@ -67,7 +67,7 @@ public class PacketSendChunk extends PacketAffectChunk {
} }
@Override @Override
public void apply(WorldData world) { public void apply(DefaultWorldData world) {
try { try {
world.addChunk(ChunkIO.load(world, position, data.getReader(), IOContext.COMMS)); world.addChunk(ChunkIO.load(world, position, data.getReader(), IOContext.COMMS));
} catch (DecodingException | IOException e) { } catch (DecodingException | IOException e) {

View File

@ -61,7 +61,7 @@ public class PacketSetGravityModel extends PacketAffectWorld {
} }
@Override @Override
public void apply(WorldData world) { public void apply(DefaultWorldData world) {
GravityModel model = GravityModelRegistry.getInstance().create(gravityModelId); GravityModel model = GravityModelRegistry.getInstance().create(gravityModelId);
world.setGravityModel(model); world.setGravityModel(model);
try { try {

View File

@ -0,0 +1,10 @@
package ru.windcorp.progressia.common.world;
import ru.windcorp.progressia.common.world.block.BlockData;
import ru.windcorp.progressia.common.world.generic.TileGenericReferenceWO;
import ru.windcorp.progressia.common.world.tile.TileData;
public interface TileDataReference extends TileDataReferenceRO,
TileGenericReferenceWO<BlockData, TileData, TileDataStack, TileDataReference, ChunkData> {
}

View File

@ -0,0 +1,12 @@
package ru.windcorp.progressia.common.world;
import ru.windcorp.progressia.common.world.block.BlockData;
import ru.windcorp.progressia.common.world.generic.TileGenericReferenceRO;
import ru.windcorp.progressia.common.world.tile.TileData;
public interface TileDataReferenceRO
extends TileGenericReferenceRO<BlockData, TileData, TileDataStackRO, TileDataReferenceRO, ChunkDataRO> {
// currently empty
}

View File

@ -0,0 +1,25 @@
package ru.windcorp.progressia.common.world;
import ru.windcorp.progressia.common.world.block.BlockData;
import ru.windcorp.progressia.common.world.generic.TileGenericStackWO;
import ru.windcorp.progressia.common.world.tile.TileData;
public interface TileDataStack
extends TileDataStackRO, TileGenericStackWO<BlockData, TileData, TileDataStack, TileDataReference, ChunkData> {
@Override
default boolean isFull() {
return TileDataStackRO.super.isFull();
}
/*
* Method specialization
*/
@Override
TileDataReference getReference(int index);
@Override
ChunkData getChunk();
}

View File

@ -0,0 +1,12 @@
package ru.windcorp.progressia.common.world;
import ru.windcorp.progressia.common.world.block.BlockData;
import ru.windcorp.progressia.common.world.generic.TileGenericStackRO;
import ru.windcorp.progressia.common.world.tile.TileData;
public interface TileDataStackRO
extends TileGenericStackRO<BlockData, TileData, TileDataStackRO, TileDataReferenceRO, ChunkDataRO> {
// currently empty
}

View File

@ -1,245 +1,52 @@
/*
* 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; package ru.windcorp.progressia.common.world;
import java.util.ArrayList;
import java.util.Collection; import java.util.Collection;
import java.util.Collections;
import java.util.Objects;
import java.util.function.Consumer;
import glm.vec._3.i.Vec3i; import glm.vec._3.i.Vec3i;
import gnu.trove.TCollections;
import gnu.trove.map.TLongObjectMap;
import gnu.trove.map.hash.TLongObjectHashMap;
import gnu.trove.set.TLongSet;
import ru.windcorp.progressia.common.collision.CollisionModel;
import ru.windcorp.progressia.common.world.block.BlockData; import ru.windcorp.progressia.common.world.block.BlockData;
import ru.windcorp.progressia.common.world.entity.EntityData; import ru.windcorp.progressia.common.world.entity.EntityData;
import ru.windcorp.progressia.common.world.generic.ChunkMap; import ru.windcorp.progressia.common.world.generic.WorldGenericWO;
import ru.windcorp.progressia.common.world.generic.ChunkSet; import ru.windcorp.progressia.common.world.rels.BlockFace;
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.TileData;
import ru.windcorp.progressia.common.world.tile.TileDataStack;
import ru.windcorp.progressia.common.world.tile.TileDataReference;
public class WorldData public interface WorldData
implements GenericWritableWorld<BlockData, TileData, TileDataStack, TileDataReference, ChunkData, EntityData> { extends WorldDataRO, WorldGenericWO<BlockData, TileData, TileDataStack, TileDataReference, ChunkData, EntityData> {
private final ChunkMap<ChunkData> chunksByPos = new LongBasedChunkMap<>(
TCollections.synchronizedMap(new TLongObjectHashMap<>())
);
private final Collection<ChunkData> chunks = Collections.unmodifiableCollection(chunksByPos.values());
private final TLongObjectMap<EntityData> entitiesById = TCollections.synchronizedMap(new TLongObjectHashMap<>());
private final Collection<EntityData> entities = Collections.unmodifiableCollection(entitiesById.valueCollection());
private GravityModel gravityModel = null;
private float time = 0;
private final Collection<WorldDataListener> listeners = Collections.synchronizedCollection(new ArrayList<>());
public WorldData() {
}
@Override @Override
public ChunkData getChunk(Vec3i pos) { default TileDataStack getTiles(Vec3i blockInWorld, BlockFace face) {
return chunksByPos.get(pos); return (TileDataStack) WorldDataRO.super.getTiles(blockInWorld, face);
}
@Override
public Collection<ChunkData> getChunks() {
return chunks;
}
public ChunkSet getLoadedChunks() {
return chunksByPos.keys();
}
@Override
public Collection<EntityData> getEntities() {
return entities;
}
@Override
public void forEachEntity(Consumer<? super EntityData> action) {
synchronized (entitiesById) { // TODO HORRIBLY MUTILATE THE CORPSE OF
// TROVE4J so that
// gnu.trove.impl.sync.SynchronizedCollection.forEach
// is synchronized
getEntities().forEach(action);
}
}
public TLongSet getLoadedEntities() {
return entitiesById.keySet();
}
private void addChunkListeners(ChunkData chunk) {
getListeners().forEach(l -> l.getChunkListeners(this, chunk.getPosition(), chunk::addListener));
}
public synchronized void addChunk(ChunkData chunk) {
addChunkListeners(chunk);
ChunkData previous = chunksByPos.get(chunk);
if (previous != null) {
throw new IllegalArgumentException(
String.format(
"Chunk at (%d; %d; %d) already exists",
chunk.getPosition().x,
chunk.getPosition().y,
chunk.getPosition().z
)
);
}
chunksByPos.put(chunk, chunk);
chunk.onLoaded();
getListeners().forEach(l -> l.onChunkLoaded(this, chunk));
}
public synchronized void removeChunk(ChunkData chunk) {
getListeners().forEach(l -> l.beforeChunkUnloaded(this, chunk));
chunk.beforeUnloaded();
chunksByPos.remove(chunk);
}
@Override
public void setBlock(Vec3i blockInWorld, BlockData block, boolean notify) {
ChunkData chunk = getChunkByBlock(blockInWorld);
if (chunk == null)
throw new IllegalCoordinatesException(
"Coordinates "
+ "(" + blockInWorld.x + "; " + blockInWorld.y + "; " + blockInWorld.z + ") "
+ "do not belong to a loaded chunk"
);
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");
EntityData previous = entitiesById.putIfAbsent(entity.getEntityId(), entity);
if (previous != null) {
String message = "Cannot add entity " + entity + ": ";
if (previous == entity) {
message += "already present";
} else {
message += "entity with the same EntityID already present (" + previous + ")";
}
throw new IllegalStateException(message);
}
getListeners().forEach(l -> l.onEntityAdded(this, entity));
}
@Override
public void removeEntity(long entityId) {
synchronized (entitiesById) {
EntityData entity = entitiesById.get(entityId);
if (entity == null) {
throw new IllegalArgumentException(
"Entity with EntityID " + EntityData.formatEntityId(entityId) + " not present"
);
} else {
removeEntity(entity);
}
}
}
@Override
public void removeEntity(EntityData entity) {
Objects.requireNonNull(entity, "entity");
getListeners().forEach(l -> l.beforeEntityRemoved(this, entity));
entitiesById.remove(entity.getEntityId());
}
public float getTime() {
return time;
}
public void advanceTime(float change) {
this.time += change;
}
public CollisionModel getCollisionModelOfBlock(Vec3i blockInWorld) {
ChunkData chunk = getChunkByBlock(blockInWorld);
if (chunk == null)
return null;
BlockData block = chunk.getBlock(Coordinates.convertInWorldToInChunk(blockInWorld, null));
if (block == null)
return null;
return block.getCollisionModel();
} }
/** /**
* @return the gravity model * Increases in-game time of this world by {@code change}. Total time is
* decreased when {@code change} is negative.
*
* @param change the amount of time to add to current world time. May be
* negative.
* @see #getTime()
*/ */
public GravityModel getGravityModel() { void advanceTime(float change);
return gravityModel;
}
/** /*
* @param gravityModel the gravity model to set * Method specialization
*/ */
public void setGravityModel(GravityModel gravityModel) {
if (!chunks.isEmpty()) {
throw new IllegalStateException(
"Attempted to change gravity model to " + gravityModel + " while " + chunks.size()
+ " chunks were loaded"
);
}
this.gravityModel = gravityModel; @Override
ChunkData getChunk(Vec3i pos);
@Override
Collection<? extends ChunkData> getChunks();
// TODO: rename WGRO.forEachChunk -> forEachChunkRO and define WGWO.forEachChunk
@Override
default ChunkData getChunkByBlock(Vec3i blockInWorld) {
return (ChunkData) WorldDataRO.super.getChunkByBlock(blockInWorld);
} }
public Collection<WorldDataListener> getListeners() { @Override
return listeners; default TileDataStack getTilesOrNull(Vec3i blockInWorld, BlockFace face) {
} return (TileDataStack) WorldDataRO.super.getTilesOrNull(blockInWorld, face);
public void addListener(WorldDataListener e) {
listeners.add(e);
}
public void removeListener(WorldDataListener o) {
listeners.remove(o);
} }
} }

View File

@ -26,11 +26,11 @@ import ru.windcorp.progressia.common.world.entity.EntityData;
public interface WorldDataListener { public interface WorldDataListener {
/** /**
* Invoked when a new {@link ChunkData} instance is created. This method * Invoked when a new {@link DefaultChunkData} instance is created. This method
* should be used to add * should be used to add
* {@link ChunkDataListener}s to a new chunk. When listeners are added with * {@link ChunkDataListener}s to a new chunk. When listeners are added with
* this method, * this method,
* their {@link ChunkDataListener#onChunkLoaded(ChunkData) onChunkLoaded} * their {@link ChunkDataListener#onChunkLoaded(DefaultChunkData) onChunkLoaded}
* methods will be invoked. * methods will be invoked.
* *
* @param world the world instance * @param world the world instance
@ -41,7 +41,7 @@ public interface WorldDataListener {
* {@link Consumer#accept(Object) accept} method * {@link Consumer#accept(Object) accept} method
* will be added to the chunk. * will be added to the chunk.
*/ */
default void getChunkListeners(WorldData world, Vec3i chunk, Consumer<ChunkDataListener> chunkListenerSink) { default void getChunkListeners(DefaultWorldData world, Vec3i chunk, Consumer<ChunkDataListener> chunkListenerSink) {
} }
/** /**
@ -50,7 +50,7 @@ public interface WorldDataListener {
* @param world the world instance * @param world the world instance
* @param chunk the chunk that has loaded * @param chunk the chunk that has loaded
*/ */
default void onChunkLoaded(WorldData world, ChunkData chunk) { default void onChunkLoaded(DefaultWorldData world, DefaultChunkData chunk) {
} }
/** /**
@ -59,7 +59,7 @@ public interface WorldDataListener {
* @param world the world instance * @param world the world instance
* @param chunk the chunk that is going to be unloaded * @param chunk the chunk that is going to be unloaded
*/ */
default void beforeChunkUnloaded(WorldData world, ChunkData chunk) { default void beforeChunkUnloaded(DefaultWorldData world, DefaultChunkData chunk) {
} }
/** /**
@ -68,7 +68,7 @@ public interface WorldDataListener {
* @param world the world instance * @param world the world instance
* @param entity the entity that has been added * @param entity the entity that has been added
*/ */
default void onEntityAdded(WorldData world, EntityData entity) { default void onEntityAdded(DefaultWorldData world, EntityData entity) {
} }
/** /**
@ -77,7 +77,7 @@ public interface WorldDataListener {
* @param world the world instance * @param world the world instance
* @param entity the entity that is going to be removed * @param entity the entity that is going to be removed
*/ */
default void beforeEntityRemoved(WorldData world, EntityData entity) { default void beforeEntityRemoved(DefaultWorldData world, EntityData entity) {
} }
} }

View File

@ -0,0 +1,29 @@
package ru.windcorp.progressia.common.world;
import ru.windcorp.progressia.common.world.block.BlockData;
import ru.windcorp.progressia.common.world.entity.EntityData;
import ru.windcorp.progressia.common.world.generic.WorldGenericRO;
import ru.windcorp.progressia.common.world.tile.TileData;
public interface WorldDataRO
extends WorldGenericRO<BlockData, TileData, TileDataStackRO, TileDataReferenceRO, ChunkDataRO, EntityData> {
/**
* Returns in-world time since creation. World time is zero before and
* during first tick.
* <p>
* Game logic should assume that this value mostly increases uniformly.
* However, it is not guaranteed that in-world time always increments.
*
* @return time, in in-game seconds, since the world was created
*/
float getTime();
/**
* Gets the {@link GravityModel} used by this world.
*
* @return the gravity model
*/
GravityModel getGravityModel();
}

View File

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

View File

@ -24,7 +24,7 @@ import java.io.IOException;
import glm.vec._3.i.Vec3i; import glm.vec._3.i.Vec3i;
import ru.windcorp.progressia.common.world.DecodingException; import ru.windcorp.progressia.common.world.DecodingException;
import ru.windcorp.progressia.common.world.WorldData; import ru.windcorp.progressia.common.world.DefaultWorldData;
public class PacketSetBlock extends PacketAffectBlock { public class PacketSetBlock extends PacketAffectBlock {
@ -60,7 +60,7 @@ public class PacketSetBlock extends PacketAffectBlock {
} }
@Override @Override
public void apply(WorldData world) { public void apply(DefaultWorldData world) {
BlockData block = BlockDataRegistry.getInstance().get(getBlockId()); BlockData block = BlockDataRegistry.getInstance().get(getBlockId());
world.setBlock(getBlockInWorld(), block, true); world.setBlock(getBlockInWorld(), block, true);
} }

View File

@ -32,10 +32,10 @@ import ru.windcorp.progressia.common.collision.CollisionModel;
import ru.windcorp.progressia.common.state.IOContext; import ru.windcorp.progressia.common.state.IOContext;
import ru.windcorp.progressia.common.state.StatefulObject; import ru.windcorp.progressia.common.state.StatefulObject;
import ru.windcorp.progressia.common.util.Matrices; import ru.windcorp.progressia.common.util.Matrices;
import ru.windcorp.progressia.common.world.generic.GenericEntity; import ru.windcorp.progressia.common.world.generic.EntityGeneric;
import ru.windcorp.progressia.common.world.rels.AbsFace; import ru.windcorp.progressia.common.world.rels.AbsFace;
public class EntityData extends StatefulObject implements Collideable, GenericEntity { public class EntityData extends StatefulObject implements Collideable, EntityGeneric {
private final Vec3 position = new Vec3(); private final Vec3 position = new Vec3();
private final Vec3 velocity = new Vec3(); private final Vec3 velocity = new Vec3();

View File

@ -24,7 +24,7 @@ import java.io.IOException;
import ru.windcorp.progressia.common.world.DecodingException; import ru.windcorp.progressia.common.world.DecodingException;
import ru.windcorp.progressia.common.world.PacketAffectWorld; import ru.windcorp.progressia.common.world.PacketAffectWorld;
import ru.windcorp.progressia.common.world.WorldData; import ru.windcorp.progressia.common.world.DefaultWorldData;
public class PacketAffectEntity extends PacketAffectWorld { public class PacketAffectEntity extends PacketAffectWorld {
@ -53,7 +53,7 @@ public class PacketAffectEntity extends PacketAffectWorld {
} }
@Override @Override
public void apply(WorldData world) { public void apply(DefaultWorldData world) {
world.removeEntity(this.entityId); world.removeEntity(this.entityId);
} }

View File

@ -26,7 +26,7 @@ import ru.windcorp.progressia.common.state.IOContext;
import ru.windcorp.progressia.common.util.DataBuffer; import ru.windcorp.progressia.common.util.DataBuffer;
import ru.windcorp.progressia.common.util.crash.CrashReports; import ru.windcorp.progressia.common.util.crash.CrashReports;
import ru.windcorp.progressia.common.world.DecodingException; import ru.windcorp.progressia.common.world.DecodingException;
import ru.windcorp.progressia.common.world.WorldData; import ru.windcorp.progressia.common.world.DefaultWorldData;
public class PacketChangeEntity extends PacketAffectEntity { public class PacketChangeEntity extends PacketAffectEntity {
@ -68,7 +68,7 @@ public class PacketChangeEntity extends PacketAffectEntity {
} }
@Override @Override
public void apply(WorldData world) { public void apply(DefaultWorldData world) {
EntityData entity = world.getEntity(getEntityId()); EntityData entity = world.getEntity(getEntityId());
if (entity == null) { if (entity == null) {

View File

@ -23,7 +23,7 @@ import java.io.DataOutput;
import java.io.IOException; import java.io.IOException;
import ru.windcorp.progressia.common.world.DecodingException; import ru.windcorp.progressia.common.world.DecodingException;
import ru.windcorp.progressia.common.world.WorldData; import ru.windcorp.progressia.common.world.DefaultWorldData;
public class PacketRevokeEntity extends PacketAffectEntity { public class PacketRevokeEntity extends PacketAffectEntity {
@ -51,7 +51,7 @@ public class PacketRevokeEntity extends PacketAffectEntity {
} }
@Override @Override
public void apply(WorldData world) { public void apply(DefaultWorldData world) {
world.removeEntity(getEntityId()); world.removeEntity(getEntityId());
} }

View File

@ -26,7 +26,7 @@ import ru.windcorp.progressia.common.state.IOContext;
import ru.windcorp.progressia.common.util.DataBuffer; import ru.windcorp.progressia.common.util.DataBuffer;
import ru.windcorp.progressia.common.util.crash.CrashReports; import ru.windcorp.progressia.common.util.crash.CrashReports;
import ru.windcorp.progressia.common.world.DecodingException; import ru.windcorp.progressia.common.world.DecodingException;
import ru.windcorp.progressia.common.world.WorldData; import ru.windcorp.progressia.common.world.DefaultWorldData;
public class PacketSendEntity extends PacketAffectEntity { public class PacketSendEntity extends PacketAffectEntity {
@ -85,7 +85,7 @@ public class PacketSendEntity extends PacketAffectEntity {
} }
@Override @Override
public void apply(WorldData world) { public void apply(DefaultWorldData world) {
EntityData entity = EntityDataRegistry.getInstance().create(getEntityTypeId()); EntityData entity = EntityDataRegistry.getInstance().create(getEntityTypeId());
entity.setEntityId(getEntityId()); entity.setEntityId(getEntityId());

View File

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

View File

@ -32,37 +32,37 @@ import ru.windcorp.progressia.common.world.rels.BlockFace;
/** /**
* An unmodifiable chunk representation. Per default, it is usually one of * An unmodifiable chunk representation. Per default, it is usually one of
* {@link ru.windcorp.progressia.common.world.ChunkData ChunkData}, * {@link ru.windcorp.progressia.common.world.DefaultChunkData ChunkData},
* {@link ru.windcorp.progressia.client.world.ChunkRender ChunkRender} or * {@link ru.windcorp.progressia.client.world.ChunkRender ChunkRender} or
* {@link ru.windcorp.progressia.server.world.ChunkLogic ChunkLogic}, but this * {@link ru.windcorp.progressia.server.world.ChunkLogic ChunkLogic}, but this
* interface may be implemented differently for various reasons. * interface may be implemented differently for various reasons.
* <p> * <p>
* A generic chunk contains {@linkplain GenericBlock blocks} and * A generic chunk contains {@linkplain BlockGeneric blocks} and
* {@linkplain GenericTileStack tile stacks} and is characterized by its * {@linkplain TileGenericStackRO tile stacks} and is characterized by its
* location. It also bears a discrete up direction. Note that no * location. It also bears a discrete up direction. Note that no
* {@linkplain GenericWorld world} object is directly accessible through this * {@linkplain WorldGenericRO world} object is directly accessible through this
* interface. * interface.
* <p> * <p>
* This interface defines the most common methods for examining a chunk and * This interface defines the most common methods for examining a chunk and
* implements many of them as default methods. It also contains several static * implements many of them as default methods. It also contains several static
* methods useful when dealing with chunks. {@code GenericChunk} does not * methods useful when dealing with chunks. {@code GenericChunk} does not
* provide a way to modify a chunk; use {@link GenericWritableChunk} methods * provide a way to modify a chunk; use {@link ChunkGenericWO} methods
* when applicable. * when applicable.
* *
* @param <Self> a reference to itself (required to properly reference a * @param <Self> a reference to itself (required to properly reference a
* {@link GenericTileStack}) * {@link TileGenericStackRO})
* @param <B> block type * @param <B> block type
* @param <T> tile type * @param <T> tile type
* @param <TS> tile stack type * @param <TS> tile stack type
* @author javapony * @author javapony
*/ */
// @formatter:off // @formatter:off
public interface GenericChunk< public interface ChunkGenericRO<
B extends GenericBlock, B extends BlockGeneric,
T extends GenericTile, T extends TileGeneric,
TS extends GenericTileStack <B, T, TS, TR, C>, TS extends TileGenericStackRO <B, T, TS, TR, C>,
TR extends GenericTileReference <B, T, TS, TR, C>, TR extends TileGenericReferenceRO <B, T, TS, TR, C>,
C extends GenericChunk <B, T, TS, TR, C> C extends ChunkGenericRO <B, T, TS, TR, C>
> { > {
// @formatter:on // @formatter:on

View File

@ -0,0 +1,37 @@
/*
* 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 glm.vec._3.i.Vec3i;
import ru.windcorp.progressia.common.world.rels.BlockFace;
// @formatter:off
public interface ChunkGenericWO<
B extends BlockGeneric,
T extends TileGeneric,
TS extends TileGenericStackWO <B, T, TS, TR, C>,
TR extends TileGenericReferenceWO <B, T, TS, TR, C>,
C extends ChunkGenericWO <B, T, TS, TR, C>
> {
// @formatter:on
void setBlock(Vec3i posInChunk, B block, boolean notify);
TS getTiles(Vec3i blockInChunk, BlockFace face);
}

View File

@ -77,27 +77,27 @@ public interface ChunkMap<V> {
// TODO implement (int, int, int) and GenericChunk versions of all of the // TODO implement (int, int, int) and GenericChunk versions of all of the
// above // above
default boolean containsChunk(GenericChunk<?, ?, ?, ?, ?> chunk) { default boolean containsChunk(ChunkGenericRO<?, ?, ?, ?, ?> chunk) {
return containsKey(chunk.getPosition()); return containsKey(chunk.getPosition());
} }
default V get(GenericChunk<?, ?, ?, ?, ?> chunk) { default V get(ChunkGenericRO<?, ?, ?, ?, ?> chunk) {
return get(chunk.getPosition()); return get(chunk.getPosition());
} }
default V put(GenericChunk<?, ?, ?, ?, ?> chunk, V obj) { default V put(ChunkGenericRO<?, ?, ?, ?, ?> chunk, V obj) {
return put(chunk.getPosition(), obj); return put(chunk.getPosition(), obj);
} }
default V remove(GenericChunk<?, ?, ?, ?, ?> chunk) { default V remove(ChunkGenericRO<?, ?, ?, ?, ?> chunk) {
return remove(chunk.getPosition()); return remove(chunk.getPosition());
} }
default V getOrDefault(GenericChunk<?, ?, ?, ?, ?> chunk, V def) { default V getOrDefault(ChunkGenericRO<?, ?, ?, ?, ?> chunk, V def) {
return containsChunk(chunk) ? def : get(chunk); return containsChunk(chunk) ? def : get(chunk);
} }
default <C extends GenericChunk<?, ?, ?, ?, C>> V compute( default <C extends ChunkGenericRO<?, ?, ?, ?, C>> V compute(
C chunk, C chunk,
BiFunction<? super C, ? super V, ? extends V> remappingFunction BiFunction<? super C, ? super V, ? extends V> remappingFunction
) { ) {
@ -128,8 +128,8 @@ public interface ChunkMap<V> {
void forEach(BiConsumer<? super Vec3i, ? super V> action); void forEach(BiConsumer<? super Vec3i, ? super V> action);
default <C extends GenericChunk<?, ?, ?, ?, C>> void forEachIn( default <C extends ChunkGenericRO<?, ?, ?, ?, C>> void forEachIn(
GenericWorld<?, ?, ?, ?, C, ?> world, WorldGenericRO<?, ?, ?, ?, C, ?> world,
BiConsumer<? super C, ? super V> action BiConsumer<? super C, ? super V> action
) { ) {
forEach((pos, value) -> { forEach((pos, value) -> {

View File

@ -174,42 +174,42 @@ public class ChunkMaps {
} }
@Override @Override
public boolean containsChunk(GenericChunk<?, ?, ?, ?, ?> chunk) { public boolean containsChunk(ChunkGenericRO<?, ?, ?, ?, ?> chunk) {
synchronized (mutex) { synchronized (mutex) {
return parent.containsChunk(chunk); return parent.containsChunk(chunk);
} }
} }
@Override @Override
public V get(GenericChunk<?, ?, ?, ?, ?> chunk) { public V get(ChunkGenericRO<?, ?, ?, ?, ?> chunk) {
synchronized (mutex) { synchronized (mutex) {
return parent.get(chunk); return parent.get(chunk);
} }
} }
@Override @Override
public V put(GenericChunk<?, ?, ?, ?, ?> chunk, V obj) { public V put(ChunkGenericRO<?, ?, ?, ?, ?> chunk, V obj) {
synchronized (mutex) { synchronized (mutex) {
return parent.put(chunk, obj); return parent.put(chunk, obj);
} }
} }
@Override @Override
public V remove(GenericChunk<?, ?, ?, ?, ?> chunk) { public V remove(ChunkGenericRO<?, ?, ?, ?, ?> chunk) {
synchronized (mutex) { synchronized (mutex) {
return parent.remove(chunk); return parent.remove(chunk);
} }
} }
@Override @Override
public V getOrDefault(GenericChunk<?, ?, ?, ?, ?> chunk, V def) { public V getOrDefault(ChunkGenericRO<?, ?, ?, ?, ?> chunk, V def) {
synchronized (mutex) { synchronized (mutex) {
return parent.getOrDefault(chunk, def); return parent.getOrDefault(chunk, def);
} }
} }
@Override @Override
public <C extends GenericChunk<?, ?, ?, ?, C>> V compute( public <C extends ChunkGenericRO<?, ?, ?, ?, C>> V compute(
C chunk, C chunk,
BiFunction<? super C, ? super V, ? extends V> remappingFunction BiFunction<? super C, ? super V, ? extends V> remappingFunction
) { ) {
@ -247,8 +247,8 @@ public class ChunkMaps {
} }
@Override @Override
public <C extends GenericChunk<?, ?, ?, ?, C>> void forEachIn( public <C extends ChunkGenericRO<?, ?, ?, ?, C>> void forEachIn(
GenericWorld<?, ?, ?, ?, C, ?> world, WorldGenericRO<?, ?, ?, ?, C, ?> world,
BiConsumer<? super C, ? super V> action BiConsumer<? super C, ? super V> action
) { ) {
synchronized (mutex) { synchronized (mutex) {

View File

@ -78,20 +78,20 @@ public interface ChunkSet extends Iterable<Vec3i> {
return result; return result;
} }
default boolean contains(GenericChunk<?, ?, ?, ?, ?> chunk) { default boolean contains(ChunkGenericRO<?, ?, ?, ?, ?> chunk) {
return contains(chunk.getPosition()); return contains(chunk.getPosition());
} }
default boolean add(GenericChunk<?, ?, ?, ?, ?> chunk) { default boolean add(ChunkGenericRO<?, ?, ?, ?, ?> chunk) {
return add(chunk.getPosition()); return add(chunk.getPosition());
} }
default boolean remove(GenericChunk<?, ?, ?, ?, ?> chunk) { default boolean remove(ChunkGenericRO<?, ?, ?, ?, ?> chunk) {
return remove(chunk.getPosition()); return remove(chunk.getPosition());
} }
default <C extends GenericChunk<?, ?, ?, ?, C>> void forEachIn( default <C extends ChunkGenericRO<?, ?, ?, ?, C>> void forEachIn(
GenericWorld<?, ?, ?, ?, C, ?> world, WorldGenericRO<?, ?, ?, ?, C, ?> world,
Consumer<? super C> action Consumer<? super C> action
) { ) {
forEach(position -> { forEach(position -> {
@ -210,7 +210,7 @@ public interface ChunkSet extends Iterable<Vec3i> {
} }
} }
default boolean containsAllChunks(Iterable<? extends GenericChunk<?, ?, ?, ?, ?>> chunks) { default boolean containsAllChunks(Iterable<? extends ChunkGenericRO<?, ?, ?, ?, ?>> chunks) {
boolean[] hasMissing = new boolean[] { false }; boolean[] hasMissing = new boolean[] { false };
chunks.forEach(c -> { chunks.forEach(c -> {
@ -222,7 +222,7 @@ public interface ChunkSet extends Iterable<Vec3i> {
return hasMissing[0]; return hasMissing[0];
} }
default boolean containsAnyChunks(Iterable<? extends GenericChunk<?, ?, ?, ?, ?>> chunks) { default boolean containsAnyChunks(Iterable<? extends ChunkGenericRO<?, ?, ?, ?, ?>> chunks) {
boolean[] hasPresent = new boolean[] { false }; boolean[] hasPresent = new boolean[] { false };
chunks.forEach(c -> { chunks.forEach(c -> {
@ -234,11 +234,11 @@ public interface ChunkSet extends Iterable<Vec3i> {
return hasPresent[0]; return hasPresent[0];
} }
default void addAllChunks(Iterable<? extends GenericChunk<?, ?, ?, ?, ?>> chunks) { default void addAllChunks(Iterable<? extends ChunkGenericRO<?, ?, ?, ?, ?>> chunks) {
chunks.forEach(this::add); chunks.forEach(this::add);
} }
default void removeAllChunks(Iterable<? extends GenericChunk<?, ?, ?, ?, ?>> chunks) { default void removeAllChunks(Iterable<? extends ChunkGenericRO<?, ?, ?, ?, ?>> chunks) {
chunks.forEach(this::remove); chunks.forEach(this::remove);
} }

View File

@ -198,29 +198,29 @@ public class ChunkSets {
} }
@Override @Override
public boolean contains(GenericChunk<?, ?, ?, ?, ?> chunk) { public boolean contains(ChunkGenericRO<?, ?, ?, ?, ?> chunk) {
synchronized (mutex) { synchronized (mutex) {
return parent.contains(chunk); return parent.contains(chunk);
} }
} }
@Override @Override
public boolean add(GenericChunk<?, ?, ?, ?, ?> chunk) { public boolean add(ChunkGenericRO<?, ?, ?, ?, ?> chunk) {
synchronized (mutex) { synchronized (mutex) {
return parent.add(chunk); return parent.add(chunk);
} }
} }
@Override @Override
public boolean remove(GenericChunk<?, ?, ?, ?, ?> chunk) { public boolean remove(ChunkGenericRO<?, ?, ?, ?, ?> chunk) {
synchronized (mutex) { synchronized (mutex) {
return parent.remove(chunk); return parent.remove(chunk);
} }
} }
@Override @Override
public <C extends GenericChunk<?, ?, ?, ?, C>> void forEachIn( public <C extends ChunkGenericRO<?, ?, ?, ?, C>> void forEachIn(
GenericWorld<?, ?, ?, ?, C, ?> world, WorldGenericRO<?, ?, ?, ?, C, ?> world,
Consumer<? super C> action Consumer<? super C> action
) { ) {
synchronized (mutex) { synchronized (mutex) {
@ -320,28 +320,28 @@ public class ChunkSets {
} }
@Override @Override
public boolean containsAllChunks(Iterable<? extends GenericChunk<?, ?, ?, ?, ?>> chunks) { public boolean containsAllChunks(Iterable<? extends ChunkGenericRO<?, ?, ?, ?, ?>> chunks) {
synchronized (mutex) { synchronized (mutex) {
return parent.containsAllChunks(chunks); return parent.containsAllChunks(chunks);
} }
} }
@Override @Override
public boolean containsAnyChunks(Iterable<? extends GenericChunk<?, ?, ?, ?, ?>> chunks) { public boolean containsAnyChunks(Iterable<? extends ChunkGenericRO<?, ?, ?, ?, ?>> chunks) {
synchronized (mutex) { synchronized (mutex) {
return parent.containsAnyChunks(chunks); return parent.containsAnyChunks(chunks);
} }
} }
@Override @Override
public void addAllChunks(Iterable<? extends GenericChunk<?, ?, ?, ?, ?>> chunks) { public void addAllChunks(Iterable<? extends ChunkGenericRO<?, ?, ?, ?, ?>> chunks) {
synchronized (mutex) { synchronized (mutex) {
parent.addAllChunks(chunks); parent.addAllChunks(chunks);
} }
} }
@Override @Override
public void removeAllChunks(Iterable<? extends GenericChunk<?, ?, ?, ?, ?>> chunks) { public void removeAllChunks(Iterable<? extends ChunkGenericRO<?, ?, ?, ?, ?>> chunks) {
synchronized (mutex) { synchronized (mutex) {
parent.removeAllChunks(chunks); parent.removeAllChunks(chunks);
} }

View File

@ -22,7 +22,7 @@ import glm.vec._3.Vec3;
import glm.vec._3.i.Vec3i; import glm.vec._3.i.Vec3i;
import ru.windcorp.progressia.common.world.Coordinates; import ru.windcorp.progressia.common.world.Coordinates;
public interface GenericEntity { public interface EntityGeneric {
String getId(); String getId();

View File

@ -34,7 +34,7 @@ public class GenericChunks {
output = new Vec3i(); output = new Vec3i();
} }
final int offset = GenericChunk.BLOCKS_PER_CHUNK - 1; final int offset = ChunkGenericRO.BLOCKS_PER_CHUNK - 1;
output.set(relativeCoords.x, relativeCoords.y, relativeCoords.z); output.set(relativeCoords.x, relativeCoords.y, relativeCoords.z);
output.mul(2).sub(offset); output.mul(2).sub(offset);
@ -51,7 +51,7 @@ public class GenericChunks {
output = new Vec3i(); output = new Vec3i();
} }
final int offset = GenericChunk.BLOCKS_PER_CHUNK - 1; final int offset = ChunkGenericRO.BLOCKS_PER_CHUNK - 1;
output.set(absoluteCoords.x, absoluteCoords.y, absoluteCoords.z); output.set(absoluteCoords.x, absoluteCoords.y, absoluteCoords.z);
output.mul(2).sub(offset); output.mul(2).sub(offset);
@ -73,7 +73,7 @@ public class GenericChunks {
return hits; return hits;
} }
static boolean testBiC(Vec3i blockInWorld, GenericChunk<?, ?, ?, ?, ?> chunk, Predicate<Vec3i> test) { static boolean testBiC(Vec3i blockInWorld, ChunkGenericRO<?, ?, ?, ?, ?> chunk, Predicate<Vec3i> test) {
Vec3i v = Vectors.grab3i(); Vec3i v = Vectors.grab3i();
v = Coordinates.getInWorld(chunk.getPosition(), Vectors.ZERO_3i, v); v = Coordinates.getInWorld(chunk.getPosition(), Vectors.ZERO_3i, v);
@ -87,9 +87,9 @@ public class GenericChunks {
} }
public static boolean containsBiC(Vec3i blockInChunk) { public static boolean containsBiC(Vec3i blockInChunk) {
return blockInChunk.x >= 0 && blockInChunk.x < GenericChunk.BLOCKS_PER_CHUNK && return blockInChunk.x >= 0 && blockInChunk.x < ChunkGenericRO.BLOCKS_PER_CHUNK &&
blockInChunk.y >= 0 && blockInChunk.y < GenericChunk.BLOCKS_PER_CHUNK && blockInChunk.y >= 0 && blockInChunk.y < ChunkGenericRO.BLOCKS_PER_CHUNK &&
blockInChunk.z >= 0 && blockInChunk.z < GenericChunk.BLOCKS_PER_CHUNK; blockInChunk.z >= 0 && blockInChunk.z < ChunkGenericRO.BLOCKS_PER_CHUNK;
} }
public static boolean isSurfaceBiC(Vec3i blockInChunk) { public static boolean isSurfaceBiC(Vec3i blockInChunk) {
@ -109,9 +109,9 @@ public class GenericChunks {
0, 0,
0, 0,
0, 0,
GenericChunk.BLOCKS_PER_CHUNK, ChunkGenericRO.BLOCKS_PER_CHUNK,
GenericChunk.BLOCKS_PER_CHUNK, ChunkGenericRO.BLOCKS_PER_CHUNK,
GenericChunk.BLOCKS_PER_CHUNK, ChunkGenericRO.BLOCKS_PER_CHUNK,
action action
); );
} }

View File

@ -1,43 +0,0 @@
/*
* 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 glm.vec._3.i.Vec3i;
import ru.windcorp.progressia.common.util.Vectors;
// @formatter:off
public interface GenericWritableChunk<
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>
>
extends GenericChunk<B, T, TS, TR, C> {
// @formatter:on
void setBlock(Vec3i posInChunk, B block, boolean notify);
default void setBlockRel(Vec3i relativeBlockInChunk, B block, boolean notify) {
Vec3i absoluteBlockInChunk = Vectors.grab3i();
resolve(relativeBlockInChunk, absoluteBlockInChunk);
setBlock(absoluteBlockInChunk, block, notify);
Vectors.release(absoluteBlockInChunk);
}
}

View File

@ -45,7 +45,7 @@ public class LongBasedChunkSet implements ChunkSet {
addAll(copyFrom); addAll(copyFrom);
} }
public LongBasedChunkSet(TLongSet impl, GenericWorld<?, ?, ?, ?, ?, ?> copyFrom) { public LongBasedChunkSet(TLongSet impl, WorldGenericRO<?, ?, ?, ?, ?, ?> copyFrom) {
this(impl); this(impl);
addAllChunks(copyFrom.getChunks()); addAllChunks(copyFrom.getChunks());
} }

View File

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

View File

@ -0,0 +1,50 @@
/*
* 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;
// @formatter:off
public interface TileGenericReferenceRO<
B extends BlockGeneric,
T extends TileGeneric,
TS extends TileGenericStackRO <B, T, TS, TR, C>,
TR extends TileGenericReferenceRO <B, T, TS, TR, C>,
C extends ChunkGenericRO <B, T, TS, TR, C>
> {
// @formatter:on
T get();
int getIndex();
TS getStack();
default boolean isValid() {
return get() != null;
}
default int getTag() {
TS tileStack = getStack();
if (tileStack == null) {
return -1;
} else {
return tileStack.getTagByIndex(getIndex());
}
}
}

View File

@ -19,23 +19,15 @@
package ru.windcorp.progressia.common.world.generic; package ru.windcorp.progressia.common.world.generic;
// @formatter:off // @formatter:off
public interface GenericTileReference< public interface TileGenericReferenceWO<
B extends GenericBlock, B extends BlockGeneric,
T extends GenericTile, T extends TileGeneric,
TS extends GenericTileStack <B, T, TS, TR, C>, TS extends TileGenericStackWO <B, T, TS, TR, C>,
TR extends GenericTileReference <B, T, TS, TR, C>, TR extends TileGenericReferenceWO <B, T, TS, TR, C>,
C extends GenericChunk <B, T, TS, TR, C> C extends ChunkGenericWO <B, T, TS, TR, C>
> { > {
// @formatter:on // @formatter:on
T get(); // currently empty
int getIndex();
TS getStack();
default boolean isValid() {
return get() != null;
}
} }

View File

@ -18,7 +18,7 @@
package ru.windcorp.progressia.common.world.generic; package ru.windcorp.progressia.common.world.generic;
import java.util.AbstractList; import java.util.List;
import java.util.Objects; import java.util.Objects;
import java.util.RandomAccess; import java.util.RandomAccess;
import java.util.function.Consumer; import java.util.function.Consumer;
@ -28,13 +28,13 @@ import ru.windcorp.progressia.common.world.Coordinates;
import ru.windcorp.progressia.common.world.rels.RelFace; import ru.windcorp.progressia.common.world.rels.RelFace;
// @formatter:off // @formatter:off
public abstract class GenericTileStack< public interface TileGenericStackRO<
B extends GenericBlock, B extends BlockGeneric,
T extends GenericTile, T extends TileGeneric,
TS extends GenericTileStack <B, T, TS, TR, C>, TS extends TileGenericStackRO <B, T, TS, TR, C>,
TR extends GenericTileReference <B, T, TS, TR, C>, TR extends TileGenericReferenceRO <B, T, TS, TR, C>,
C extends GenericChunk <B, T, TS, TR, C> C extends ChunkGenericRO <B, T, TS, TR, C>
> extends AbstractList<T> implements RandomAccess { > extends List<T>, RandomAccess {
// @formatter:on // @formatter:on
public static interface TSConsumer<T> { public static interface TSConsumer<T> {
@ -43,36 +43,36 @@ public abstract class GenericTileStack<
public static final int TILES_PER_FACE = 8; public static final int TILES_PER_FACE = 8;
public abstract Vec3i getBlockInChunk(Vec3i output); Vec3i getBlockInChunk(Vec3i output);
public abstract C getChunk(); C getChunk();
public abstract RelFace getFace(); RelFace getFace();
public abstract TR getReference(int index); TR getReference(int index);
public abstract int getIndexByTag(int tag); int getIndexByTag(int tag);
public abstract int getTagByIndex(int index); int getTagByIndex(int index);
public Vec3i getBlockInWorld(Vec3i output) { default Vec3i getBlockInWorld(Vec3i output) {
// This is safe // This is safe
return Coordinates.getInWorld(getChunk().getPosition(), getBlockInChunk(output), output); return Coordinates.getInWorld(getChunk().getPosition(), getBlockInChunk(output), output);
} }
public boolean isFull() { default boolean isFull() {
return size() >= TILES_PER_FACE; return size() >= TILES_PER_FACE;
} }
public T getClosest() { default T getClosest() {
return get(0); return get(0);
} }
public T getFarthest() { default T getFarthest() {
return get(size() - 1); return get(size() - 1);
} }
public void forEach(TSConsumer<T> action) { default void forEach(TSConsumer<T> action) {
Objects.requireNonNull(action, "action"); Objects.requireNonNull(action, "action");
for (int i = 0; i < size(); ++i) { for (int i = 0; i < size(); ++i) {
action.accept(i, get(i)); action.accept(i, get(i));
@ -80,14 +80,14 @@ public abstract class GenericTileStack<
} }
@Override @Override
public void forEach(Consumer<? super T> action) { default void forEach(Consumer<? super T> action) {
Objects.requireNonNull(action, "action"); Objects.requireNonNull(action, "action");
for (int i = 0; i < size(); ++i) { for (int i = 0; i < size(); ++i) {
action.accept(get(i)); action.accept(get(i));
} }
} }
public T findClosest(String id) { default T findClosest(String id) {
Objects.requireNonNull(id, "id"); Objects.requireNonNull(id, "id");
for (int i = 0; i < size(); ++i) { for (int i = 0; i < size(); ++i) {
@ -100,7 +100,7 @@ public abstract class GenericTileStack<
return null; return null;
} }
public T findFarthest(String id) { default T findFarthest(String id) {
Objects.requireNonNull(id, "id"); Objects.requireNonNull(id, "id");
for (int i = 0; i < size(); ++i) { for (int i = 0; i < size(); ++i) {
@ -113,11 +113,11 @@ public abstract class GenericTileStack<
return null; return null;
} }
public boolean contains(String id) { default boolean contains(String id) {
return findClosest(id) != null; return findClosest(id) != null;
} }
public B getHost() { default B getHost() {
return getChunk().getBlock(getBlockInChunk(null)); return getChunk().getBlock(getBlockInChunk(null));
} }

View File

@ -18,15 +18,18 @@
package ru.windcorp.progressia.common.world.generic; package ru.windcorp.progressia.common.world.generic;
import java.util.List;
import java.util.RandomAccess;
// @formatter:off // @formatter:off
public abstract class GenericWritableTileStack< public interface TileGenericStackWO<
B extends GenericBlock, B extends BlockGeneric,
T extends GenericTile, T extends TileGeneric,
TS extends GenericWritableTileStack<B, T, TS, TR, C>, TS extends TileGenericStackWO <B, T, TS, TR, C>,
TR extends GenericTileReference<B, T, TS, TR, C>, TR extends TileGenericReferenceWO <B, T, TS, TR, C>,
C extends GenericWritableChunk<B, T, TS, TR, C> C extends ChunkGenericWO <B, T, TS, TR, C>
> >
extends GenericTileStack<B, T, TS, TR, C> { extends List<T>, RandomAccess {
// @formatter:on // @formatter:on
/** /**
@ -45,7 +48,7 @@ public abstract class GenericWritableTileStack<
* make sure to override it in subclass * make sure to override it in subclass
*/ */
@Override @Override
public abstract void add(int index, T tile); void add(int index, T tile);
/** /**
* Adds the specified tile at the end of this stack assigning it the * Adds the specified tile at the end of this stack assigning it the
@ -59,7 +62,7 @@ public abstract class GenericWritableTileStack<
* with the * with the
* provided tag * provided tag
*/ */
public abstract void load(T tile, int tag); void load(T tile, int tag);
/** /**
* Replaces the tile at the specified position in this stack with the * Replaces the tile at the specified position in this stack with the
@ -74,7 +77,7 @@ public abstract class GenericWritableTileStack<
* make sure to override it in subclass * make sure to override it in subclass
*/ */
@Override @Override
public abstract T set(int index, T tile); T set(int index, T tile);
/** /**
* Removes the tile at the specified position in this list. Shifts any * Removes the tile at the specified position in this list. Shifts any
@ -91,20 +94,22 @@ public abstract class GenericWritableTileStack<
* make sure to override it in subclass * make sure to override it in subclass
*/ */
@Override @Override
public abstract T remove(int index); T remove(int index);
/* /*
* Aliases and overloads * Aliases and overloads
*/ */
public void addClosest(T tile) { default void addClosest(T tile) {
add(0, tile); add(0, tile);
} }
public void addFarthest(T tile) { default void addFarthest(T tile) {
add(size(), tile); add(size(), tile);
} }
boolean isFull();
/** /**
* Attempts to {@link #add(int, TileData) add} the provided {@code tile} * Attempts to {@link #add(int, TileData) add} the provided {@code tile}
* at {@code index}. If the stack is {@linkplain #isFull() full}, does * at {@code index}. If the stack is {@linkplain #isFull() full}, does
@ -114,45 +119,45 @@ public abstract class GenericWritableTileStack<
* @param tile the tile to try to add * @param tile the tile to try to add
* @return {@code true} iff this stack has changed * @return {@code true} iff this stack has changed
*/ */
public boolean offer(int index, T tile) { default boolean offer(int index, T tile) {
if (isFull()) if (isFull())
return false; return false;
add(index, tile); add(index, tile);
return true; return true;
} }
public boolean offerClosest(T tile) { default boolean offerClosest(T tile) {
return offer(0, tile); return offer(0, tile);
} }
public boolean offerFarthest(T tile) { default boolean offerFarthest(T tile) {
return offer(size(), tile); return offer(size(), tile);
} }
public T removeClosest() { default T removeClosest() {
return remove(0); return remove(0);
} }
public T removeFarthest() { default T removeFarthest() {
return remove(size() - 1); return remove(size() - 1);
} }
public T poll(int index) { default T poll(int index) {
if (size() <= index) if (size() <= index)
return null; return null;
return remove(index); return remove(index);
} }
public T pollClosest() { default T pollClosest() {
return poll(0); return poll(0);
} }
public T pollFarthest() { default T pollFarthest() {
return poll(size() - 1); return poll(size() - 1);
} }
@Override @Override
public boolean add(T tile) { default boolean add(T tile) {
addFarthest(tile); addFarthest(tile);
return true; return true;
} }

View File

@ -30,17 +30,17 @@ import ru.windcorp.progressia.common.world.rels.AbsFace;
import ru.windcorp.progressia.common.world.rels.BlockFace; import ru.windcorp.progressia.common.world.rels.BlockFace;
// @formatter:off // @formatter:off
public interface GenericWorld< public interface WorldGenericRO<
B extends GenericBlock, B extends BlockGeneric,
T extends GenericTile, T extends TileGeneric,
TS extends GenericTileStack <B, T, TS, TR, C>, TS extends TileGenericStackRO <B, T, TS, TR, C>,
TR extends GenericTileReference <B, T, TS, TR, C>, TR extends TileGenericReferenceRO <B, T, TS, TR, C>,
C extends GenericChunk <B, T, TS, TR, C>, C extends ChunkGenericRO <B, T, TS, TR, C>,
E extends GenericEntity E extends EntityGeneric
> { > {
// @formatter:on // @formatter:on
Collection<C> getChunks(); Collection<? extends C> getChunks();
C getChunk(Vec3i pos); C getChunk(Vec3i pos);
@ -131,6 +131,15 @@ public interface GenericWorld<
return stack.get(layer); return stack.get(layer);
} }
/**
* Determines whether the specified position has a tile.
*
* @return {@code true} iff the tile exists
*/
default boolean hasTile(Vec3i location, BlockFace face, int layer) {
return hasTile(location, face, layer);
}
default boolean isChunkLoaded(Vec3i chunkPos) { default boolean isChunkLoaded(Vec3i chunkPos) {
return getChunk(chunkPos) != null; return getChunk(chunkPos) != null;
} }

View File

@ -18,21 +18,24 @@
package ru.windcorp.progressia.common.world.generic; package ru.windcorp.progressia.common.world.generic;
import glm.vec._3.i.Vec3i; import glm.vec._3.i.Vec3i;
import ru.windcorp.progressia.common.world.block.BlockData; import ru.windcorp.progressia.common.state.StateChange;
import ru.windcorp.progressia.common.state.StatefulObject;
import ru.windcorp.progressia.common.world.rels.BlockFace;
//@formatter:off //@formatter:off
public interface GenericWritableWorld< public interface WorldGenericWO<
B extends GenericBlock, B extends BlockGeneric,
T extends GenericTile, T extends TileGeneric,
TS extends GenericWritableTileStack <B, T, TS, TR, C>, TS extends TileGenericStackWO <B, T, TS, TR, C>,
TR extends GenericTileReference <B, T, TS, TR, C>, TR extends TileGenericReferenceWO <B, T, TS, TR, C>,
C extends GenericWritableChunk <B, T, TS, TR, C>, C extends ChunkGenericWO <B, T, TS, TR, C>,
E extends GenericEntity E extends EntityGeneric
> > {
extends GenericWorld<B, T, TS, TR, C, E> {
//@formatter:on //@formatter:on
void setBlock(Vec3i blockInWorld, BlockData block, boolean notify); void setBlock(Vec3i blockInWorld, B block, boolean notify);
TS getTiles(Vec3i blockInWorld, BlockFace face);
void addEntity(E entity); void addEntity(E entity);
@ -42,4 +45,13 @@ public interface GenericWritableWorld<
removeEntity(entity.getEntityId()); removeEntity(entity.getEntityId());
} }
/**
* Requests that the specified change is applied to the given entity. The
* {@code change} object provided may be stored until the change is applied.
*
* @param entity the entity to change
* @param change the change to apply
*/
<SE extends StatefulObject & EntityGeneric> void changeEntity(SE entity, StateChange<SE> change);
} }

View File

@ -18,13 +18,7 @@
package ru.windcorp.progressia.common.world.generic.context; package ru.windcorp.progressia.common.world.generic.context;
import ru.windcorp.progressia.common.world.context.Context; import ru.windcorp.progressia.common.world.context.Context;
import ru.windcorp.progressia.common.world.generic.GenericBlock; import ru.windcorp.progressia.common.world.generic.*;
import ru.windcorp.progressia.common.world.generic.GenericROChunk;
import ru.windcorp.progressia.common.world.generic.GenericEntity;
import ru.windcorp.progressia.common.world.generic.GenericTile;
import ru.windcorp.progressia.common.world.generic.GenericROTileReference;
import ru.windcorp.progressia.common.world.generic.GenericROTileStack;
import ru.windcorp.progressia.common.world.rels.RelFace;
/** /**
* A {@link Context} referencing a world with a block location and a block face * A {@link Context} referencing a world with a block location and a block face
@ -32,23 +26,16 @@ import ru.windcorp.progressia.common.world.rels.RelFace;
* not actually exist. * not actually exist.
*/ */
//@formatter:off //@formatter:off
public interface GenericROBlockFaceContext< public interface BlockFaceGenericContextRO<
B extends GenericBlock, B extends BlockGeneric,
T extends GenericTile, T extends TileGeneric,
TS extends GenericROTileStack <B, T, TS, TR, C>, TS extends TileGenericStackRO <B, T, TS, TR, C>,
TR extends GenericROTileReference <B, T, TS, TR, C>, TR extends TileGenericReferenceRO <B, T, TS, TR, C>,
C extends GenericROChunk <B, T, TS, TR, C>, C extends ChunkGenericRO <B, T, TS, TR, C>,
E extends GenericEntity E extends EntityGeneric
> extends GenericROBlockContext<B, T, TS, TR, C, E> { > extends WorldContexts.BlockFace, BlockGenericContextRO<B, T, TS, TR, C, E> {
//@formatter:on //@formatter:on
/**
* Returns the face relevant to this context.
*
* @return the block face
*/
RelFace getFace();
/** /**
* Gets the tile stack at the relevant position. * Gets the tile stack at the relevant position.
* *

View File

@ -28,14 +28,14 @@ import ru.windcorp.progressia.common.world.generic.*;
* stack may or may not actually exist. * stack may or may not actually exist.
*/ */
//@formatter:off //@formatter:off
public interface GenericRWBlockFaceContext< public interface BlockFaceGenericContextWO<
B extends GenericBlock, B extends BlockGeneric,
T extends GenericTile, T extends TileGeneric,
TS extends GenericRWTileStack <B, T, TS, TR, C>, TS extends TileGenericStackWO <B, T, TS, TR, C>,
TR extends GenericROTileReference <B, T, TS, TR, C>, TR extends TileGenericReferenceWO <B, T, TS, TR, C>,
C extends GenericRWChunk <B, T, TS, TR, C>, C extends ChunkGenericWO <B, T, TS, TR, C>,
E extends GenericEntity E extends EntityGeneric
> extends GenericRWBlockContext<B, T, TS, TR, C, E>, GenericROBlockFaceContext<B, T, TS, TR, C, E> { > extends WorldContexts.BlockFace, BlockGenericContextWO<B, T, TS, TR, C, E> {
//@formatter:on //@formatter:on
/** /**
@ -63,16 +63,4 @@ public interface GenericRWBlockFaceContext<
removeTile(getLocation(), getFace(), tag); removeTile(getLocation(), getFace(), tag);
} }
/**
* Requests that the referenced tile is removed from the specified tile
* stack. If the tile could not be found at the time of application this
* method fails silently. The location and the face of the block are implied
* by the context.
*
* @param tileReference a reference to the tile
*/
default void removeTile(TR tileReference) {
removeTile(getLocation(), getFace(), tileReference.getTag());
}
} }

View File

@ -17,14 +17,8 @@
*/ */
package ru.windcorp.progressia.common.world.generic.context; package ru.windcorp.progressia.common.world.generic.context;
import glm.vec._3.i.Vec3i;
import ru.windcorp.progressia.common.world.context.Context; import ru.windcorp.progressia.common.world.context.Context;
import ru.windcorp.progressia.common.world.generic.GenericBlock; import ru.windcorp.progressia.common.world.generic.*;
import ru.windcorp.progressia.common.world.generic.GenericROChunk;
import ru.windcorp.progressia.common.world.generic.GenericEntity;
import ru.windcorp.progressia.common.world.generic.GenericTile;
import ru.windcorp.progressia.common.world.generic.GenericROTileReference;
import ru.windcorp.progressia.common.world.generic.GenericROTileStack;
import ru.windcorp.progressia.common.world.rels.BlockFace; import ru.windcorp.progressia.common.world.rels.BlockFace;
/** /**
@ -32,29 +26,16 @@ import ru.windcorp.progressia.common.world.rels.BlockFace;
* location may or may not be loaded. * location may or may not be loaded.
*/ */
//@formatter:off //@formatter:off
public interface GenericROBlockContext< public interface BlockGenericContextRO<
B extends GenericBlock, B extends BlockGeneric,
T extends GenericTile, T extends TileGeneric,
TS extends GenericROTileStack <B, T, TS, TR, C>, TS extends TileGenericStackRO <B, T, TS, TR, C>,
TR extends GenericROTileReference <B, T, TS, TR, C>, TR extends TileGenericReferenceRO <B, T, TS, TR, C>,
C extends GenericROChunk <B, T, TS, TR, C>, C extends ChunkGenericRO <B, T, TS, TR, C>,
E extends GenericEntity E extends EntityGeneric
> extends GenericROWorldContext<B, T, TS, TR, C, E> { > extends WorldContexts.Block, WorldGenericContextRO<B, T, TS, TR, C, E> {
//@formatter:on //@formatter:on
/**
* Returns the location of the block.
* <p>
* The coordinate system in use is not specified, but it is consistent
* across all methods of this context.
* <p>
* The object returned by this method must not be modified. It is only valid
* while the context is {@linkplain valid}.
*
* @return a vector describing the block's position
*/
Vec3i getLocation();
/** /**
* Determines whether the location relevant to this context is currently * Determines whether the location relevant to this context is currently
* loaded. * loaded.

View File

@ -28,14 +28,14 @@ import ru.windcorp.progressia.common.world.rels.BlockFace;
* {@link #isImmediate()}. The location may or may not be loaded. * {@link #isImmediate()}. The location may or may not be loaded.
*/ */
//@formatter:off //@formatter:off
public interface GenericRWBlockContext< public interface BlockGenericContextWO<
B extends GenericBlock, B extends BlockGeneric,
T extends GenericTile, T extends TileGeneric,
TS extends GenericRWTileStack <B, T, TS, TR, C>, TS extends TileGenericStackWO <B, T, TS, TR, C>,
TR extends GenericROTileReference <B, T, TS, TR, C>, TR extends TileGenericReferenceWO <B, T, TS, TR, C>,
C extends GenericRWChunk <B, T, TS, TR, C>, C extends ChunkGenericWO <B, T, TS, TR, C>,
E extends GenericEntity E extends EntityGeneric
> extends GenericRWWorldContext<B, T, TS, TR, C, E>, GenericROBlockContext<B, T, TS, TR, C, E> { > extends WorldContexts.Block, WorldGenericContextWO<B, T, TS, TR, C, E> {
//@formatter:on //@formatter:on
/** /**
@ -76,17 +76,4 @@ public interface GenericRWBlockContext<
removeTile(getLocation(), face, tag); removeTile(getLocation(), face, tag);
} }
/**
* Requests that the referenced tile is removed from the specified tile
* stack. If the tile could not be found at the time of application this
* method fails silently. The location of the block is implied by the
* context.
*
* @param face the of the block to remove the tile from
* @param tileReference a reference to the tile
*/
default void removeTile(BlockFace face, TR tileReference) {
removeTile(getLocation(), face, tileReference.getTag());
}
} }

View File

@ -18,12 +18,7 @@
package ru.windcorp.progressia.common.world.generic.context; package ru.windcorp.progressia.common.world.generic.context;
import ru.windcorp.progressia.common.world.context.Context; import ru.windcorp.progressia.common.world.context.Context;
import ru.windcorp.progressia.common.world.generic.GenericBlock; import ru.windcorp.progressia.common.world.generic.*;
import ru.windcorp.progressia.common.world.generic.GenericROChunk;
import ru.windcorp.progressia.common.world.generic.GenericEntity;
import ru.windcorp.progressia.common.world.generic.GenericTile;
import ru.windcorp.progressia.common.world.generic.GenericROTileReference;
import ru.windcorp.progressia.common.world.generic.GenericROTileStack;
/** /**
* A {@link Context} referencing a world with a block location, a block face and * A {@link Context} referencing a world with a block location, a block face and
@ -31,23 +26,16 @@ import ru.windcorp.progressia.common.world.generic.GenericROTileStack;
* or may not actually exist. * or may not actually exist.
*/ */
//@formatter:off //@formatter:off
public interface GenericROTileContext< public interface TileGenericContextRO<
B extends GenericBlock, B extends BlockGeneric,
T extends GenericTile, T extends TileGeneric,
TS extends GenericROTileStack <B, T, TS, TR, C>, TS extends TileGenericStackRO <B, T, TS, TR, C>,
TR extends GenericROTileReference <B, T, TS, TR, C>, TR extends TileGenericReferenceRO <B, T, TS, TR, C>,
C extends GenericROChunk <B, T, TS, TR, C>, C extends ChunkGenericRO <B, T, TS, TR, C>,
E extends GenericEntity E extends EntityGeneric
> extends GenericROBlockFaceContext<B, T, TS, TR, C, E> { > extends WorldContexts.Tile, BlockFaceGenericContextRO<B, T, TS, TR, C, E> {
//@formatter:on //@formatter:on
/**
* Returns the tile layer relevant to this context.
*
* @return the tile layer
*/
int getLayer();
/** /**
* Determines whether the location relevant to this context has a tile. * Determines whether the location relevant to this context has a tile.
* *
@ -67,12 +55,7 @@ public interface GenericROTileContext<
return getTile(getLocation(), getFace(), getLayer()); return getTile(getLocation(), getFace(), getLayer());
} }
/** @Override
* Gets the tag of the tile at the relevant position.
*
* @return the tag of the tile or {@code -1} if the location is not loaded
* or the tile does not exist
*/
default int getTag() { default int getTag() {
TS tileStack = getTilesOrNull(); TS tileStack = getTilesOrNull();
if (tileStack == null) { if (tileStack == null) {
@ -82,4 +65,23 @@ public interface GenericROTileContext<
return tileStack.getTagByIndex(getLayer()); return tileStack.getTagByIndex(getLayer());
} }
/**
* Gets the {@link TileGenericReferenceRO TileReference} to the relevant
* tile.
*
* @return the reference to the tile relevant to this context or
* {@code null} if the location is not loaded or the tile does not
* exist
*
* @see TileGenericStackRO#getReference(int)
*/
default TR getTileReference() {
TS tileStack = getTilesOrNull();
if (tileStack == null) {
return null;
}
return tileStack.getReference(getLayer());
}
} }

View File

@ -28,14 +28,14 @@ import ru.windcorp.progressia.common.world.generic.*;
* The tile may or may not actually exist. * The tile may or may not actually exist.
*/ */
//@formatter:off //@formatter:off
public interface GenericRWTileContext< public interface TileGenericContextWO<
B extends GenericBlock, B extends BlockGeneric,
T extends GenericTile, T extends TileGeneric,
TS extends GenericRWTileStack <B, T, TS, TR, C>, TS extends TileGenericStackWO <B, T, TS, TR, C>,
TR extends GenericROTileReference <B, T, TS, TR, C>, TR extends TileGenericReferenceWO <B, T, TS, TR, C>,
C extends GenericRWChunk <B, T, TS, TR, C>, C extends ChunkGenericWO <B, T, TS, TR, C>,
E extends GenericEntity E extends EntityGeneric
> extends GenericRWBlockFaceContext<B, T, TS, TR, C, E>, GenericROTileContext<B, T, TS, TR, C, E> { > extends WorldContexts.Tile, BlockFaceGenericContextWO<B, T, TS, TR, C, E> {
//@formatter:on //@formatter:on
/** /**

View File

@ -0,0 +1,127 @@
/*
* 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.context;
import glm.vec._3.i.Vec3i;
import ru.windcorp.progressia.common.world.context.Context;
import ru.windcorp.progressia.common.world.rels.RelFace;
/**
* This class defines several {@link Context} subinterfaces that are further
* extended by Generic contexts. These interfaces declare methods for
* determining which location is "relevant" to the context. Since they are not
* Java generics they can safely be extended more than once.
* <p>
* Do not reuse these interfaces outside the Generic contexts' package; consider
* them to be an implementation detail.
*
* @author javapony
*
*/
class WorldContexts {
/**
* A {@link Context} with a world instance. This interface should not be
* implemented directly; see {@link WorldGenericContextRO} or
* {@link WorldGenericContextWO}.
*
* @author javapony
*
*/
public static interface World extends Context {
// currently empty
}
/**
* A {@link Context} with a world instance and a block location. This interface
* should not be implemented directly; see {@link BlockGenericContextRO} or
* {@link BlockGenericContextWO}.
*
* @author javapony
*
*/
public static interface Block extends World {
/**
* Returns the location of the block.
* <p>
* The coordinate system in use is not specified, but it is consistent across
* all methods of this context.
* <p>
* The object returned by this method must not be modified. It is only valid
* while the context is {@linkplain valid}.
*
* @return a vector describing the block's position
*/
Vec3i getLocation();
}
/**
* A {@link Context} with a world instance, a block location and a block face
* (block side). This interface should not be implemented directly; see
* {@link BlockFaceGenericContextRO} or {@link BlockFaceGenericContextWO}.
*
* @author javapony
*
*/
public static interface BlockFace extends Block {
/**
* Returns the face relevant to this context.
*
* @return the block face
*/
RelFace getFace();
}
/**
* A {@link Context} with a world instance, a block location, a block face
* (block side) and a tile layer. This interface should not be implemented
* directly; see {@link TileGenericContextRO} or {@link TileGenericContextWO}.
*
* @author javapony
*
*/
public static interface Tile extends BlockFace {
/**
* Returns the tile layer relevant to this context.
*
* @return the tile layer
*/
int getLayer();
/**
* Gets the tag of the tile at the relevant position.
*
* @return the tag of the tile or {@code -1} if the location is not loaded
* or the tile does not exist
*/
int getTag();
}
WorldContexts() {
}
}

View File

@ -18,26 +18,20 @@
package ru.windcorp.progressia.common.world.generic.context; package ru.windcorp.progressia.common.world.generic.context;
import ru.windcorp.progressia.common.world.context.Context; import ru.windcorp.progressia.common.world.context.Context;
import ru.windcorp.progressia.common.world.generic.GenericBlock; import ru.windcorp.progressia.common.world.generic.*;
import ru.windcorp.progressia.common.world.generic.GenericROChunk;
import ru.windcorp.progressia.common.world.generic.GenericEntity;
import ru.windcorp.progressia.common.world.generic.GenericTile;
import ru.windcorp.progressia.common.world.generic.GenericROTileReference;
import ru.windcorp.progressia.common.world.generic.GenericROTileStack;
import ru.windcorp.progressia.common.world.generic.GenericROWorld;
/** /**
* A {@link Context} with a world instance. * A {@link Context} with a world instance.
*/ */
// @formatter:off // @formatter:off
public interface GenericROWorldContext< public interface WorldGenericContextRO<
B extends GenericBlock, B extends BlockGeneric,
T extends GenericTile, T extends TileGeneric,
TS extends GenericROTileStack <B, T, TS, TR, C>, TS extends TileGenericStackRO <B, T, TS, TR, C>,
TR extends GenericROTileReference <B, T, TS, TR, C>, TR extends TileGenericReferenceRO <B, T, TS, TR, C>,
C extends GenericROChunk <B, T, TS, TR, C>, C extends ChunkGenericRO <B, T, TS, TR, C>,
E extends GenericEntity E extends EntityGeneric
> extends Context, GenericROWorld<B, T, TS, TR, C, E> { > extends WorldContexts.World, WorldGenericRO<B, T, TS, TR, C, E> {
// @formatter:on // @formatter:on
// currently empty // currently empty

View File

@ -30,14 +30,14 @@ import ru.windcorp.progressia.common.world.rels.BlockFace;
* may not be immediate, see {@link #isImmediate()}. * may not be immediate, see {@link #isImmediate()}.
*/ */
// @formatter:off // @formatter:off
public interface GenericRWWorldContext< public interface WorldGenericContextWO<
B extends GenericBlock, B extends BlockGeneric,
T extends GenericTile, T extends TileGeneric,
TS extends GenericRWTileStack <B, T, TS, TR, C>, TS extends TileGenericStackWO <B, T, TS, TR, C>,
TR extends GenericROTileReference <B, T, TS, TR, C>, TR extends TileGenericReferenceWO <B, T, TS, TR, C>,
C extends GenericRWChunk <B, T, TS, TR, C>, C extends ChunkGenericWO <B, T, TS, TR, C>,
E extends GenericEntity E extends EntityGeneric
> extends GenericROWorldContext<B, T, TS, TR, C, E>, GenericRWWorld<B, T, TS, TR, C, E> { > extends WorldContexts.World, WorldGenericWO<B, T, TS, TR, C, E> {
// @formatter:on // @formatter:on
/** /**
@ -92,17 +92,20 @@ public interface GenericRWWorldContext<
void removeTile(Vec3i location, BlockFace face, int tag); void removeTile(Vec3i location, BlockFace face, int tag);
/** /**
* Requests that the referenced tile is removed from the specified tile * Requests that the referenced tile is removed from its tile stack. If the
* stack. If the tile could not be found at the time of application this * tile could not be found at the time of application this method fails
* method fails silently. * silently.
* *
* @param location the location of the block from which the tile is to
* be removed
* @param face the of the block to remove the tile from
* @param tileReference a reference to the tile * @param tileReference a reference to the tile
*/ */
default void removeTile(Vec3i location, BlockFace face, TR tileReference) { default void removeTile(TileGenericReferenceRO<?, ?, ?, ?, ?> tileReference) {
removeTile(location, face, tileReference.getTag()); TileGenericStackRO<?, ?, ?, ?, ?> tileStack = tileReference.getStack();
if (tileStack == null) {
return;
}
removeTile(tileStack.getBlockInWorld(null), tileStack.getFace(), tileReference.getTag());
} }
/** /**
@ -123,7 +126,7 @@ public interface GenericRWWorldContext<
* *
* @param entityId the ID of the entity to remove * @param entityId the ID of the entity to remove
* @see #isImmediate() * @see #isImmediate()
* @see #removeEntity(GenericEntity) * @see #removeEntity(EntityGeneric)
*/ */
@Override @Override
void removeEntity(long entityId); void removeEntity(long entityId);
@ -140,12 +143,13 @@ public interface GenericRWWorldContext<
void removeEntity(E entity); void removeEntity(E entity);
/** /**
* Requests that the specified change is applied to the given entity. The {@code change} object provided may be stored until the change is applied. * Requests that the specified change is applied to the given entity. The
* {@code change} object provided may be stored until the change is applied.
* *
* @param entity the entity to change * @param entity the entity to change
* @param change the change to apply * @param change the change to apply
*/ */
@Override @Override
<SE extends StatefulObject & GenericEntity> void changeEntity(SE entity, StateChange<SE> change); <SE extends StatefulObject & EntityGeneric> void changeEntity(SE entity, StateChange<SE> change);
} }

View File

@ -25,9 +25,9 @@ import java.io.IOException;
import glm.vec._3.i.Vec3i; import glm.vec._3.i.Vec3i;
import ru.windcorp.progressia.common.state.IOContext; import ru.windcorp.progressia.common.state.IOContext;
import ru.windcorp.progressia.common.util.namespaces.Namespaced; import ru.windcorp.progressia.common.util.namespaces.Namespaced;
import ru.windcorp.progressia.common.world.ChunkData; import ru.windcorp.progressia.common.world.DefaultChunkData;
import ru.windcorp.progressia.common.world.DecodingException; import ru.windcorp.progressia.common.world.DecodingException;
import ru.windcorp.progressia.common.world.WorldData; import ru.windcorp.progressia.common.world.DefaultWorldData;
public abstract class ChunkCodec extends Namespaced { public abstract class ChunkCodec extends Namespaced {
@ -46,12 +46,12 @@ public abstract class ChunkCodec extends Namespaced {
return signature; return signature;
} }
public abstract ChunkData decode(WorldData world, Vec3i position, DataInputStream input, IOContext context) public abstract DefaultChunkData decode(DefaultWorldData world, Vec3i position, DataInputStream input, IOContext context)
throws DecodingException, throws DecodingException,
IOException; IOException;
public abstract boolean shouldEncode(ChunkData chunk, IOContext context); public abstract boolean shouldEncode(DefaultChunkData chunk, IOContext context);
public abstract void encode(ChunkData chunk, DataOutputStream output, IOContext context) throws IOException; public abstract void encode(DefaultChunkData chunk, DataOutputStream output, IOContext context) throws IOException;
} }

View File

@ -31,16 +31,16 @@ import gnu.trove.map.TByteObjectMap;
import gnu.trove.map.hash.TByteObjectHashMap; import gnu.trove.map.hash.TByteObjectHashMap;
import ru.windcorp.progressia.common.state.IOContext; import ru.windcorp.progressia.common.state.IOContext;
import ru.windcorp.progressia.common.util.crash.CrashReports; import ru.windcorp.progressia.common.util.crash.CrashReports;
import ru.windcorp.progressia.common.world.ChunkData; import ru.windcorp.progressia.common.world.DefaultChunkData;
import ru.windcorp.progressia.common.world.DecodingException; import ru.windcorp.progressia.common.world.DecodingException;
import ru.windcorp.progressia.common.world.WorldData; import ru.windcorp.progressia.common.world.DefaultWorldData;
public class ChunkIO { public class ChunkIO {
private static final TByteObjectMap<ChunkCodec> CODECS_BY_ID = new TByteObjectHashMap<>(); private static final TByteObjectMap<ChunkCodec> CODECS_BY_ID = new TByteObjectHashMap<>();
private static final List<ChunkCodec> CODECS_BY_PRIORITY = new ArrayList<>(); private static final List<ChunkCodec> CODECS_BY_PRIORITY = new ArrayList<>();
public static ChunkData load(WorldData world, Vec3i position, DataInputStream data, IOContext context) public static DefaultChunkData load(DefaultWorldData world, Vec3i position, DataInputStream data, IOContext context)
throws DecodingException, throws DecodingException,
IOException { IOException {
if (CODECS_BY_ID.isEmpty()) if (CODECS_BY_ID.isEmpty())
@ -73,7 +73,7 @@ public class ChunkIO {
} }
} }
public static void save(ChunkData chunk, DataOutputStream output, IOContext context) public static void save(DefaultChunkData chunk, DataOutputStream output, IOContext context)
throws IOException { throws IOException {
ChunkCodec codec = getCodec(chunk, context); ChunkCodec codec = getCodec(chunk, context);
@ -100,7 +100,7 @@ public class ChunkIO {
return CODECS_BY_ID.get(signature); return CODECS_BY_ID.get(signature);
} }
public static ChunkCodec getCodec(ChunkData chunk, IOContext context) { public static ChunkCodec getCodec(DefaultChunkData chunk, IOContext context) {
for (ChunkCodec codec : CODECS_BY_PRIORITY) { for (ChunkCodec codec : CODECS_BY_PRIORITY) {
if (codec.shouldEncode(chunk, context)) { if (codec.shouldEncode(chunk, context)) {
return codec; return codec;

View File

@ -24,7 +24,7 @@ import java.io.IOException;
import glm.vec._3.i.Vec3i; import glm.vec._3.i.Vec3i;
import ru.windcorp.progressia.common.world.DecodingException; import ru.windcorp.progressia.common.world.DecodingException;
import ru.windcorp.progressia.common.world.WorldData; import ru.windcorp.progressia.common.world.DefaultWorldData;
import ru.windcorp.progressia.common.world.rels.AbsFace; import ru.windcorp.progressia.common.world.rels.AbsFace;
public class PacketAddTile extends PacketAffectTile { public class PacketAddTile extends PacketAffectTile {
@ -61,7 +61,7 @@ public class PacketAddTile extends PacketAffectTile {
} }
@Override @Override
public void apply(WorldData world) { public void apply(DefaultWorldData world) {
TileData tile = TileDataRegistry.getInstance().get(getTileId()); TileData tile = TileDataRegistry.getInstance().get(getTileId());
world.getTiles(getBlockInWorld(), getFace()).add(tile); world.getTiles(getBlockInWorld(), getFace()).add(tile);
} }

View File

@ -25,7 +25,8 @@ import java.io.IOException;
import glm.vec._3.i.Vec3i; import glm.vec._3.i.Vec3i;
import ru.windcorp.progressia.common.util.crash.CrashReports; import ru.windcorp.progressia.common.util.crash.CrashReports;
import ru.windcorp.progressia.common.world.DecodingException; import ru.windcorp.progressia.common.world.DecodingException;
import ru.windcorp.progressia.common.world.WorldData; import ru.windcorp.progressia.common.world.DefaultWorldData;
import ru.windcorp.progressia.common.world.TileDataStack;
import ru.windcorp.progressia.common.world.rels.AbsFace; import ru.windcorp.progressia.common.world.rels.AbsFace;
public class PacketRemoveTile extends PacketAffectTile { public class PacketRemoveTile extends PacketAffectTile {
@ -54,7 +55,7 @@ public class PacketRemoveTile extends PacketAffectTile {
} }
@Override @Override
public void apply(WorldData world) { public void apply(DefaultWorldData world) {
TileDataStack stack = world.getTiles(getBlockInWorld(), getFace()); TileDataStack stack = world.getTiles(getBlockInWorld(), getFace());
int index = stack.getIndexByTag(getTag()); int index = stack.getIndexByTag(getTag());

View File

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

View File

@ -1,28 +0,0 @@
/*
* 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.tile;
import ru.windcorp.progressia.common.world.ChunkData;
import ru.windcorp.progressia.common.world.block.BlockData;
import ru.windcorp.progressia.common.world.generic.GenericWritableTileStack;
public abstract class TileDataStack
extends GenericWritableTileStack<BlockData, TileData, TileDataStack, TileDataReference, ChunkData> {
}

View File

@ -22,7 +22,7 @@ import java.util.function.Consumer;
import glm.vec._3.i.Vec3i; import glm.vec._3.i.Vec3i;
import ru.windcorp.progressia.common.Units; import ru.windcorp.progressia.common.Units;
import ru.windcorp.progressia.common.world.ChunkData; import ru.windcorp.progressia.common.world.DefaultChunkData;
import ru.windcorp.progressia.common.world.Coordinates; import ru.windcorp.progressia.common.world.Coordinates;
import ru.windcorp.progressia.common.world.PlayerData; import ru.windcorp.progressia.common.world.PlayerData;
import ru.windcorp.progressia.common.world.entity.EntityData; import ru.windcorp.progressia.common.world.entity.EntityData;
@ -55,7 +55,7 @@ public class Player extends PlayerData implements ChunkLoader {
Coordinates.convertInWorldToChunk(start, start); Coordinates.convertInWorldToChunk(start, start);
Vec3i cursor = new Vec3i(); Vec3i cursor = new Vec3i();
float radius = getServer().getLoadDistance(this) / Units.get(ChunkData.BLOCKS_PER_CHUNK, "m"); float radius = getServer().getLoadDistance(this) / Units.get(DefaultChunkData.BLOCKS_PER_CHUNK, "m");
float radiusSq = radius * radius; float radiusSq = radius * radius;
int iRadius = (int) Math.ceil(radius); int iRadius = (int) Math.ceil(radius);

View File

@ -28,7 +28,7 @@ import ru.windcorp.jputil.functions.ThrowingRunnable;
import ru.windcorp.progressia.common.Units; import ru.windcorp.progressia.common.Units;
import ru.windcorp.progressia.common.util.TaskQueue; import ru.windcorp.progressia.common.util.TaskQueue;
import ru.windcorp.progressia.common.util.crash.ReportingEventBus; import ru.windcorp.progressia.common.util.crash.ReportingEventBus;
import ru.windcorp.progressia.common.world.WorldData; import ru.windcorp.progressia.common.world.DefaultWorldData;
import ru.windcorp.progressia.server.comms.ClientManager; import ru.windcorp.progressia.server.comms.ClientManager;
import ru.windcorp.progressia.server.events.ServerEvent; import ru.windcorp.progressia.server.events.ServerEvent;
import ru.windcorp.progressia.server.management.load.ChunkRequestDaemon; import ru.windcorp.progressia.server.management.load.ChunkRequestDaemon;
@ -68,7 +68,7 @@ public class Server {
private final TickingSettings tickingSettings = new TickingSettings(); private final TickingSettings tickingSettings = new TickingSettings();
public Server(WorldData world) { public Server(DefaultWorldData world) {
this.world = new WorldLogic( this.world = new WorldLogic(
world, world,
this, this,

View File

@ -18,7 +18,7 @@
package ru.windcorp.progressia.server; package ru.windcorp.progressia.server;
import ru.windcorp.progressia.common.world.WorldData; import ru.windcorp.progressia.common.world.DefaultWorldData;
public class ServerState { public class ServerState {
@ -33,7 +33,7 @@ public class ServerState {
} }
public static void startServer() { public static void startServer() {
Server server = new Server(new WorldData()); Server server = new Server(new DefaultWorldData());
setInstance(server); setInstance(server);
server.start(); server.start();
} }

View File

@ -18,10 +18,10 @@
package ru.windcorp.progressia.server.management.load; package ru.windcorp.progressia.server.management.load;
import glm.vec._3.i.Vec3i; import glm.vec._3.i.Vec3i;
import ru.windcorp.progressia.common.world.ChunkData; import ru.windcorp.progressia.common.world.DefaultChunkData;
import ru.windcorp.progressia.common.world.PacketRevokeChunk; import ru.windcorp.progressia.common.world.PacketRevokeChunk;
import ru.windcorp.progressia.common.world.PacketSendChunk; import ru.windcorp.progressia.common.world.PacketSendChunk;
import ru.windcorp.progressia.common.world.WorldData; import ru.windcorp.progressia.common.world.DefaultWorldData;
import ru.windcorp.progressia.server.Player; import ru.windcorp.progressia.server.Player;
import ru.windcorp.progressia.server.Server; import ru.windcorp.progressia.server.Server;
import ru.windcorp.progressia.test.TestWorldDiskIO; import ru.windcorp.progressia.test.TestWorldDiskIO;
@ -113,9 +113,9 @@ public class ChunkManager {
return LoadResult.ALREADY_LOADED; return LoadResult.ALREADY_LOADED;
} }
WorldData world = getServer().getWorld().getData(); DefaultWorldData world = getServer().getWorld().getData();
ChunkData chunk = TestWorldDiskIO.tryToLoad(chunkPos, world, getServer()); DefaultChunkData chunk = TestWorldDiskIO.tryToLoad(chunkPos, world, getServer());
if (chunk != null) { if (chunk != null) {
world.addChunk(chunk); world.addChunk(chunk);
return LoadResult.LOADED_FROM_DISK; return LoadResult.LOADED_FROM_DISK;
@ -133,8 +133,8 @@ public class ChunkManager {
* this method * this method
*/ */
public boolean unloadChunk(Vec3i chunkPos) { public boolean unloadChunk(Vec3i chunkPos) {
WorldData world = getServer().getWorld().getData(); DefaultWorldData world = getServer().getWorld().getData();
ChunkData chunk = world.getChunk(chunkPos); DefaultChunkData chunk = world.getChunk(chunkPos);
if (chunk == null) { if (chunk == null) {
return false; return false;
@ -147,7 +147,7 @@ public class ChunkManager {
} }
public void sendChunk(Player player, Vec3i chunkPos) { public void sendChunk(Player player, Vec3i chunkPos) {
ChunkData chunk = getServer().getWorld().getData().getChunk(chunkPos); DefaultChunkData chunk = getServer().getWorld().getData().getChunk(chunkPos);
if (chunk == null) { if (chunk == null) {
throw new IllegalStateException( throw new IllegalStateException(
@ -180,7 +180,7 @@ public class ChunkManager {
/** /**
* Checks whether or not the chunk at the specified location is loaded. A * Checks whether or not the chunk at the specified location is loaded. A
* loaded chunk is accessible through the server's {@link WorldData} object. * loaded chunk is accessible through the server's {@link DefaultWorldData} object.
* *
* @param chunkPos the position of the chunk * @param chunkPos the position of the chunk
* @return {@code true} iff the chunk is loaded * @return {@code true} iff the chunk is loaded

View File

@ -26,14 +26,14 @@ import java.util.WeakHashMap;
import java.util.function.BiConsumer; import java.util.function.BiConsumer;
import glm.vec._3.i.Vec3i; import glm.vec._3.i.Vec3i;
import ru.windcorp.progressia.common.world.ChunkData; import ru.windcorp.progressia.common.world.DefaultChunkData;
import ru.windcorp.progressia.common.world.Coordinates; import ru.windcorp.progressia.common.world.Coordinates;
import ru.windcorp.progressia.common.world.generic.GenericChunk; import ru.windcorp.progressia.common.world.generic.ChunkGenericRO;
import ru.windcorp.progressia.common.world.rels.AbsFace; import ru.windcorp.progressia.common.world.rels.AbsFace;
import ru.windcorp.progressia.common.world.rels.BlockFace; import ru.windcorp.progressia.common.world.rels.BlockFace;
import ru.windcorp.progressia.common.world.rels.RelFace; import ru.windcorp.progressia.common.world.rels.RelFace;
import ru.windcorp.progressia.common.world.tile.TileDataStack; import ru.windcorp.progressia.common.world.TileDataStack;
import ru.windcorp.progressia.common.world.tile.TileDataReference; import ru.windcorp.progressia.common.world.TileDataReference;
import ru.windcorp.progressia.server.world.block.BlockLogic; import ru.windcorp.progressia.server.world.block.BlockLogic;
import ru.windcorp.progressia.server.world.block.BlockLogicRegistry; import ru.windcorp.progressia.server.world.block.BlockLogicRegistry;
import ru.windcorp.progressia.server.world.block.TickableBlock; import ru.windcorp.progressia.server.world.block.TickableBlock;
@ -45,10 +45,10 @@ import ru.windcorp.progressia.server.world.tile.TileLogicReference;
import ru.windcorp.progressia.server.world.tile.TileLogicRegistry; import ru.windcorp.progressia.server.world.tile.TileLogicRegistry;
import ru.windcorp.progressia.server.world.tile.TileLogicStack; import ru.windcorp.progressia.server.world.tile.TileLogicStack;
public class ChunkLogic implements GenericChunk<BlockLogic, TileLogic, TileLogicStack, TileLogicReference, ChunkLogic> { public class ChunkLogic implements ChunkGenericRO<BlockLogic, TileLogic, TileLogicStack, TileLogicReference, ChunkLogic> {
private final WorldLogic world; private final WorldLogic world;
private final ChunkData data; private final DefaultChunkData data;
private final Collection<Vec3i> tickingBlocks = new ArrayList<>(); private final Collection<Vec3i> tickingBlocks = new ArrayList<>();
private final Collection<TileDataReference> tickingTiles = new ArrayList<>(); private final Collection<TileDataReference> tickingTiles = new ArrayList<>();
@ -58,7 +58,7 @@ public class ChunkLogic implements GenericChunk<BlockLogic, TileLogic, TileLogic
private final Map<TileDataStack, TileLogicStackImpl> tileLogicLists = Collections private final Map<TileDataStack, TileLogicStackImpl> tileLogicLists = Collections
.synchronizedMap(new WeakHashMap<>()); .synchronizedMap(new WeakHashMap<>());
public ChunkLogic(WorldLogic world, ChunkData data) { public ChunkLogic(WorldLogic world, DefaultChunkData data) {
this.world = world; this.world = world;
this.data = data; this.data = data;
@ -103,7 +103,7 @@ public class ChunkLogic implements GenericChunk<BlockLogic, TileLogic, TileLogic
return world; return world;
} }
public ChunkData getData() { public DefaultChunkData getData() {
return data; return data;
} }

View File

@ -21,7 +21,7 @@ package ru.windcorp.progressia.server.world;
import java.util.function.Consumer; import java.util.function.Consumer;
import glm.vec._3.i.Vec3i; import glm.vec._3.i.Vec3i;
import ru.windcorp.progressia.common.world.ChunkData; import ru.windcorp.progressia.common.world.DefaultChunkData;
import ru.windcorp.progressia.common.world.generic.GenericChunks; import ru.windcorp.progressia.common.world.generic.GenericChunks;
import ru.windcorp.progressia.common.world.rels.AbsFace; import ru.windcorp.progressia.common.world.rels.AbsFace;
import ru.windcorp.progressia.server.world.block.BlockTickContext; import ru.windcorp.progressia.server.world.block.BlockTickContext;
@ -34,7 +34,7 @@ public interface ChunkTickContext extends TickContext {
return getWorld().getChunk(getChunk()); return getWorld().getChunk(getChunk());
} }
default ChunkData getChunkData() { default DefaultChunkData getChunkData() {
ChunkLogic chunkLogic = getChunkLogic(); ChunkLogic chunkLogic = getChunkLogic();
return chunkLogic == null ? null : chunkLogic.getData(); return chunkLogic == null ? null : chunkLogic.getData();
} }

View File

@ -20,7 +20,7 @@ package ru.windcorp.progressia.server.world;
import java.util.Random; import java.util.Random;
import ru.windcorp.progressia.common.world.WorldData; import ru.windcorp.progressia.common.world.DefaultWorldData;
import ru.windcorp.progressia.server.Server; import ru.windcorp.progressia.server.Server;
import ru.windcorp.progressia.server.world.tasks.WorldAccessor; import ru.windcorp.progressia.server.world.tasks.WorldAccessor;
@ -42,7 +42,7 @@ public interface TickContext {
return getServer().getAdHocRandom(); return getServer().getAdHocRandom();
} }
default WorldData getWorldData() { default DefaultWorldData getWorldData() {
return getWorld().getData(); return getWorld().getData();
} }

View File

@ -23,13 +23,13 @@ import java.util.function.Consumer;
import java.util.function.Function; import java.util.function.Function;
import glm.vec._3.i.Vec3i; import glm.vec._3.i.Vec3i;
import ru.windcorp.progressia.common.world.ChunkData; import ru.windcorp.progressia.common.world.DefaultChunkData;
import ru.windcorp.progressia.common.world.Coordinates; import ru.windcorp.progressia.common.world.Coordinates;
import ru.windcorp.progressia.common.world.generic.GenericTileStack; import ru.windcorp.progressia.common.world.generic.TileGenericStackRO;
import ru.windcorp.progressia.common.world.rels.BlockFace; import ru.windcorp.progressia.common.world.rels.BlockFace;
import ru.windcorp.progressia.common.world.rels.RelFace; import ru.windcorp.progressia.common.world.rels.RelFace;
import ru.windcorp.progressia.common.world.tile.TileDataStack; import ru.windcorp.progressia.common.world.TileDataStack;
import ru.windcorp.progressia.common.world.tile.TileDataReference; import ru.windcorp.progressia.common.world.TileDataReference;
import ru.windcorp.progressia.server.Server; import ru.windcorp.progressia.server.Server;
import ru.windcorp.progressia.server.world.block.BlockTickContext; import ru.windcorp.progressia.server.world.block.BlockTickContext;
import ru.windcorp.progressia.server.world.tile.TSTickContext; import ru.windcorp.progressia.server.world.tile.TSTickContext;
@ -109,9 +109,9 @@ public abstract class TickContextMutable implements BlockTickContext, TSTickCont
Block withBlock(Vec3i blockInWorld); Block withBlock(Vec3i blockInWorld);
TileStack withTS(GenericTileStack<?, ?, ?, ?, ?> tileStack); TileStack withTS(TileGenericStackRO<?, ?, ?, ?, ?> tileStack);
default Builder.Chunk withChunk(ChunkData chunk) { default Builder.Chunk withChunk(DefaultChunkData chunk) {
Objects.requireNonNull(chunk, "chunk"); Objects.requireNonNull(chunk, "chunk");
return withChunk(chunk.getPosition()); return withChunk(chunk.getPosition());
} }
@ -259,7 +259,7 @@ public abstract class TickContextMutable implements BlockTickContext, TSTickCont
} }
@Override @Override
public TileStack withTS(GenericTileStack<?, ?, ?, ?, ?> tileStack) { public TileStack withTS(TileGenericStackRO<?, ?, ?, ?, ?> tileStack) {
Objects.requireNonNull(tileStack, "tileStack"); Objects.requireNonNull(tileStack, "tileStack");
return withBlock( return withBlock(
@ -324,7 +324,7 @@ public abstract class TickContextMutable implements BlockTickContext, TSTickCont
final int minX = Coordinates.getInWorld(chunk.x, 0); final int minX = Coordinates.getInWorld(chunk.x, 0);
final int minY = Coordinates.getInWorld(chunk.y, 0); final int minY = Coordinates.getInWorld(chunk.y, 0);
final int minZ = Coordinates.getInWorld(chunk.z, 0); final int minZ = Coordinates.getInWorld(chunk.z, 0);
final int size = ChunkData.BLOCKS_PER_CHUNK; final int size = DefaultChunkData.BLOCKS_PER_CHUNK;
for (v.x = minX; v.x < minX + size; ++v.x) { for (v.x = minX; v.x < minX + size; ++v.x) {
for (v.y = minY; v.y < minY + size; ++v.y) { for (v.y = minY; v.y < minY + size; ++v.y) {

View File

@ -19,7 +19,7 @@
package ru.windcorp.progressia.server.world; package ru.windcorp.progressia.server.world;
import glm.vec._3.i.Vec3i; import glm.vec._3.i.Vec3i;
import ru.windcorp.progressia.common.world.ChunkData; import ru.windcorp.progressia.common.world.DefaultChunkData;
import ru.windcorp.progressia.common.world.ChunkDataListener; import ru.windcorp.progressia.common.world.ChunkDataListener;
import ru.windcorp.progressia.common.world.Coordinates; import ru.windcorp.progressia.common.world.Coordinates;
import ru.windcorp.progressia.common.world.block.BlockData; import ru.windcorp.progressia.common.world.block.BlockData;
@ -37,7 +37,7 @@ public class UpdateTriggerer implements ChunkDataListener {
@Override @Override
public void onChunkBlockChanged( public void onChunkBlockChanged(
ChunkData chunk, DefaultChunkData chunk,
Vec3i blockInChunk, Vec3i blockInChunk,
BlockData previous, BlockData previous,
BlockData current BlockData current
@ -47,7 +47,7 @@ public class UpdateTriggerer implements ChunkDataListener {
@Override @Override
public void onChunkTilesChanged( public void onChunkTilesChanged(
ChunkData chunk, DefaultChunkData chunk,
Vec3i blockInChunk, Vec3i blockInChunk,
RelFace face, RelFace face,
TileData tile, TileData tile,

View File

@ -25,12 +25,12 @@ import java.util.Map;
import glm.Glm; import glm.Glm;
import glm.vec._3.i.Vec3i; import glm.vec._3.i.Vec3i;
import ru.windcorp.progressia.common.util.crash.CrashReports; import ru.windcorp.progressia.common.util.crash.CrashReports;
import ru.windcorp.progressia.common.world.ChunkData; import ru.windcorp.progressia.common.world.DefaultChunkData;
import ru.windcorp.progressia.common.world.ChunkDataListeners; import ru.windcorp.progressia.common.world.ChunkDataListeners;
import ru.windcorp.progressia.common.world.WorldData; import ru.windcorp.progressia.common.world.DefaultWorldData;
import ru.windcorp.progressia.common.world.WorldDataListener; import ru.windcorp.progressia.common.world.WorldDataListener;
import ru.windcorp.progressia.common.world.entity.EntityData; import ru.windcorp.progressia.common.world.entity.EntityData;
import ru.windcorp.progressia.common.world.generic.GenericWorld; import ru.windcorp.progressia.common.world.generic.WorldGenericRO;
import ru.windcorp.progressia.server.Server; import ru.windcorp.progressia.server.Server;
import ru.windcorp.progressia.server.world.block.BlockLogic; import ru.windcorp.progressia.server.world.block.BlockLogic;
import ru.windcorp.progressia.server.world.generation.WorldGenerator; import ru.windcorp.progressia.server.world.generation.WorldGenerator;
@ -41,20 +41,20 @@ import ru.windcorp.progressia.server.world.tile.TileLogicReference;
import ru.windcorp.progressia.server.world.tile.TileLogicStack; import ru.windcorp.progressia.server.world.tile.TileLogicStack;
public class WorldLogic public class WorldLogic
implements GenericWorld<BlockLogic, TileLogic, TileLogicStack, TileLogicReference, ChunkLogic, EntityData implements WorldGenericRO<BlockLogic, TileLogic, TileLogicStack, TileLogicReference, ChunkLogic, EntityData
// not using EntityLogic because it is stateless // not using EntityLogic because it is stateless
> { > {
private final WorldData data; private final DefaultWorldData data;
private final Server server; private final Server server;
private final WorldGenerator generator; private final WorldGenerator generator;
private final Map<ChunkData, ChunkLogic> chunks = new HashMap<>(); private final Map<DefaultChunkData, ChunkLogic> chunks = new HashMap<>();
private final Evaluation tickEntitiesTask = new TickEntitiesTask(); private final Evaluation tickEntitiesTask = new TickEntitiesTask();
public WorldLogic(WorldData data, Server server, WorldGenerator generator) { public WorldLogic(DefaultWorldData data, Server server, WorldGenerator generator) {
this.data = data; this.data = data;
this.server = server; this.server = server;
@ -63,12 +63,12 @@ public class WorldLogic
data.addListener(new WorldDataListener() { data.addListener(new WorldDataListener() {
@Override @Override
public void onChunkLoaded(WorldData world, ChunkData chunk) { public void onChunkLoaded(DefaultWorldData world, DefaultChunkData chunk) {
chunks.put(chunk, new ChunkLogic(WorldLogic.this, chunk)); chunks.put(chunk, new ChunkLogic(WorldLogic.this, chunk));
} }
@Override @Override
public void beforeChunkUnloaded(WorldData world, ChunkData chunk) { public void beforeChunkUnloaded(DefaultWorldData world, DefaultChunkData chunk) {
chunks.remove(chunk); chunks.remove(chunk);
} }
}); });
@ -104,7 +104,7 @@ public class WorldLogic
return server; return server;
} }
public WorldData getData() { public DefaultWorldData getData() {
return data; return data;
} }
@ -112,8 +112,8 @@ public class WorldLogic
return generator; return generator;
} }
public ChunkData generate(Vec3i chunkPos) { public DefaultChunkData generate(Vec3i chunkPos) {
ChunkData chunk = getGenerator().generate(chunkPos); DefaultChunkData chunk = getGenerator().generate(chunkPos);
if (!Glm.equals(chunkPos, chunk.getPosition())) { if (!Glm.equals(chunkPos, chunk.getPosition())) {
throw CrashReports.report(null, "Generator %s has generated a chunk at (%d; %d; %d) when requested to generate a chunk at (%d; %d; %d)", throw CrashReports.report(null, "Generator %s has generated a chunk at (%d; %d; %d) when requested to generate a chunk at (%d; %d; %d)",
@ -147,7 +147,7 @@ public class WorldLogic
return chunk; return chunk;
} }
public ChunkLogic getChunk(ChunkData chunkData) { public ChunkLogic getChunk(DefaultChunkData chunkData) {
return chunks.get(chunkData); return chunks.get(chunkData);
} }

View File

@ -19,10 +19,10 @@
package ru.windcorp.progressia.server.world.block; package ru.windcorp.progressia.server.world.block;
import ru.windcorp.progressia.common.util.namespaces.Namespaced; import ru.windcorp.progressia.common.util.namespaces.Namespaced;
import ru.windcorp.progressia.common.world.generic.GenericBlock; import ru.windcorp.progressia.common.world.generic.BlockGeneric;
import ru.windcorp.progressia.common.world.rels.RelFace; import ru.windcorp.progressia.common.world.rels.RelFace;
public class BlockLogic extends Namespaced implements GenericBlock { public class BlockLogic extends Namespaced implements BlockGeneric {
public BlockLogic(String id) { public BlockLogic(String id) {
super(id); super(id);

View File

@ -23,11 +23,11 @@ import java.io.DataOutputStream;
import java.io.IOException; import java.io.IOException;
import java.util.Objects; import java.util.Objects;
import ru.windcorp.progressia.common.world.ChunkData; import ru.windcorp.progressia.common.world.DefaultChunkData;
import ru.windcorp.progressia.common.world.DecodingException; import ru.windcorp.progressia.common.world.DecodingException;
import ru.windcorp.progressia.common.world.GravityModel; import ru.windcorp.progressia.common.world.GravityModel;
import ru.windcorp.progressia.common.world.GravityModelRegistry; import ru.windcorp.progressia.common.world.GravityModelRegistry;
import ru.windcorp.progressia.common.world.WorldData; import ru.windcorp.progressia.common.world.DefaultWorldData;
import ru.windcorp.progressia.server.Server; import ru.windcorp.progressia.server.Server;
import ru.windcorp.progressia.server.world.WorldLogic; import ru.windcorp.progressia.server.world.WorldLogic;
@ -71,11 +71,11 @@ public abstract class AbstractWorldGenerator<H> extends WorldGenerator {
protected abstract boolean checkIsChunkReady(H hint); protected abstract boolean checkIsChunkReady(H hint);
protected H getHint(ChunkData chunk) { protected H getHint(DefaultChunkData chunk) {
return hintClass.cast(chunk.getGenerationHint()); return hintClass.cast(chunk.getGenerationHint());
} }
protected void setHint(ChunkData chunk, H hint) { protected void setHint(DefaultChunkData chunk, H hint) {
chunk.setGenerationHint(hint); chunk.setGenerationHint(hint);
} }
@ -95,7 +95,7 @@ public abstract class AbstractWorldGenerator<H> extends WorldGenerator {
} }
@Override @Override
public WorldData getWorldData() { public DefaultWorldData getWorldData() {
return server.getWorld().getData(); return server.getWorld().getData();
} }

View File

@ -25,10 +25,10 @@ import java.io.IOException;
import glm.vec._3.Vec3; import glm.vec._3.Vec3;
import glm.vec._3.i.Vec3i; import glm.vec._3.i.Vec3i;
import ru.windcorp.progressia.common.util.namespaces.Namespaced; import ru.windcorp.progressia.common.util.namespaces.Namespaced;
import ru.windcorp.progressia.common.world.ChunkData; import ru.windcorp.progressia.common.world.DefaultChunkData;
import ru.windcorp.progressia.common.world.DecodingException; import ru.windcorp.progressia.common.world.DecodingException;
import ru.windcorp.progressia.common.world.GravityModel; import ru.windcorp.progressia.common.world.GravityModel;
import ru.windcorp.progressia.common.world.WorldData; import ru.windcorp.progressia.common.world.DefaultWorldData;
import ru.windcorp.progressia.server.Server; import ru.windcorp.progressia.server.Server;
import ru.windcorp.progressia.server.world.WorldLogic; import ru.windcorp.progressia.server.world.WorldLogic;
@ -39,7 +39,7 @@ public abstract class WorldGenerator extends Namespaced {
// package-private constructor; extend AbstractWorldGeneration // package-private constructor; extend AbstractWorldGeneration
} }
public abstract ChunkData generate(Vec3i chunkPos); public abstract DefaultChunkData generate(Vec3i chunkPos);
public abstract Object readGenerationHint(DataInputStream input) throws IOException, DecodingException; public abstract Object readGenerationHint(DataInputStream input) throws IOException, DecodingException;
@ -53,6 +53,6 @@ public abstract class WorldGenerator extends Namespaced {
public abstract Server getServer(); public abstract Server getServer();
public abstract WorldLogic getWorldLogic(); public abstract WorldLogic getWorldLogic();
public abstract WorldData getWorldData(); public abstract DefaultWorldData getWorldData();
} }

View File

@ -27,9 +27,9 @@ import com.google.common.collect.ImmutableList;
import glm.vec._3.i.Vec3i; import glm.vec._3.i.Vec3i;
import ru.windcorp.progressia.common.util.FloatMathUtil; import ru.windcorp.progressia.common.util.FloatMathUtil;
import ru.windcorp.progressia.common.world.ChunkData; import ru.windcorp.progressia.common.world.DefaultChunkData;
import ru.windcorp.progressia.common.world.rels.AbsFace; import ru.windcorp.progressia.common.world.rels.AbsFace;
import ru.windcorp.progressia.common.world.tile.TileDataStack; import ru.windcorp.progressia.common.world.TileDataStack;
import ru.windcorp.progressia.server.Server; import ru.windcorp.progressia.server.Server;
import ru.windcorp.progressia.server.world.ChunkLogic; import ru.windcorp.progressia.server.world.ChunkLogic;
import ru.windcorp.progressia.server.world.TickContextMutable; import ru.windcorp.progressia.server.world.TickContextMutable;
@ -40,13 +40,13 @@ import ru.windcorp.progressia.server.world.ticking.TickingPolicy;
import ru.windcorp.progressia.server.world.tile.TSTickContext; import ru.windcorp.progressia.server.world.tile.TSTickContext;
import ru.windcorp.progressia.server.world.tile.TickableTile; import ru.windcorp.progressia.server.world.tile.TickableTile;
import ru.windcorp.progressia.server.world.tile.TileLogic; import ru.windcorp.progressia.server.world.tile.TileLogic;
import static ru.windcorp.progressia.common.world.ChunkData.BLOCKS_PER_CHUNK; import static ru.windcorp.progressia.common.world.DefaultChunkData.BLOCKS_PER_CHUNK;
public class TickChunk extends Evaluation { public class TickChunk extends Evaluation {
private static final int CHUNK_VOLUME = ChunkData.BLOCKS_PER_CHUNK * private static final int CHUNK_VOLUME = DefaultChunkData.BLOCKS_PER_CHUNK *
ChunkData.BLOCKS_PER_CHUNK * DefaultChunkData.BLOCKS_PER_CHUNK *
ChunkData.BLOCKS_PER_CHUNK; DefaultChunkData.BLOCKS_PER_CHUNK;
private final List<Consumer<Server>> randomTickMethods; private final List<Consumer<Server>> randomTickMethods;

View File

@ -34,7 +34,7 @@ import com.google.common.collect.ImmutableList;
import ru.windcorp.progressia.common.Units; import ru.windcorp.progressia.common.Units;
import ru.windcorp.progressia.common.util.crash.CrashReports; import ru.windcorp.progressia.common.util.crash.CrashReports;
import ru.windcorp.progressia.common.world.ChunkData; import ru.windcorp.progressia.common.world.DefaultChunkData;
import ru.windcorp.progressia.common.world.ChunkDataListener; import ru.windcorp.progressia.common.world.ChunkDataListener;
import ru.windcorp.progressia.common.world.ChunkDataListeners; import ru.windcorp.progressia.common.world.ChunkDataListeners;
import ru.windcorp.progressia.server.Server; import ru.windcorp.progressia.server.Server;
@ -105,7 +105,7 @@ public class TickerCoordinator {
server.getWorld().getData().addListener(ChunkDataListeners.createAdder(new ChunkDataListener() { server.getWorld().getData().addListener(ChunkDataListeners.createAdder(new ChunkDataListener() {
@Override @Override
public void onChunkChanged(ChunkData chunk) { public void onChunkChanged(DefaultChunkData chunk) {
if (!canChange.get()) { if (!canChange.get()) {
throw CrashReports.report(null, "A change has been detected during evaluation phase"); throw CrashReports.report(null, "A change has been detected during evaluation phase");
} }

View File

@ -22,9 +22,9 @@ import java.util.Objects;
import java.util.function.Consumer; import java.util.function.Consumer;
import java.util.function.Function; import java.util.function.Function;
import ru.windcorp.progressia.common.world.ChunkData; import ru.windcorp.progressia.common.world.DefaultChunkData;
import ru.windcorp.progressia.common.world.rels.RelFace; import ru.windcorp.progressia.common.world.rels.RelFace;
import ru.windcorp.progressia.common.world.tile.TileDataStack; import ru.windcorp.progressia.common.world.TileDataStack;
import ru.windcorp.progressia.server.world.ChunkLogic; import ru.windcorp.progressia.server.world.ChunkLogic;
import ru.windcorp.progressia.server.world.TickContextMutable; import ru.windcorp.progressia.server.world.TickContextMutable;
import ru.windcorp.progressia.server.world.block.BlockTickContext; import ru.windcorp.progressia.server.world.block.BlockTickContext;
@ -54,7 +54,7 @@ public interface TSTickContext extends BlockTickContext {
} }
default TileDataStack getTDSOrNull() { default TileDataStack getTDSOrNull() {
ChunkData chunkData = getChunkData(); DefaultChunkData chunkData = getChunkData();
if (chunkData == null) if (chunkData == null)
return null; return null;

View File

@ -19,10 +19,10 @@
package ru.windcorp.progressia.server.world.tile; package ru.windcorp.progressia.server.world.tile;
import ru.windcorp.progressia.common.util.namespaces.Namespaced; import ru.windcorp.progressia.common.util.namespaces.Namespaced;
import ru.windcorp.progressia.common.world.generic.GenericTile; import ru.windcorp.progressia.common.world.generic.TileGeneric;
import ru.windcorp.progressia.common.world.rels.RelFace; import ru.windcorp.progressia.common.world.rels.RelFace;
public class TileLogic extends Namespaced implements GenericTile { public class TileLogic extends Namespaced implements TileGeneric {
public TileLogic(String id) { public TileLogic(String id) {
super(id); super(id);

View File

@ -17,11 +17,11 @@
*/ */
package ru.windcorp.progressia.server.world.tile; package ru.windcorp.progressia.server.world.tile;
import ru.windcorp.progressia.common.world.generic.GenericTileReference; import ru.windcorp.progressia.common.world.generic.TileGenericReferenceRO;
import ru.windcorp.progressia.server.world.ChunkLogic; import ru.windcorp.progressia.server.world.ChunkLogic;
import ru.windcorp.progressia.server.world.block.BlockLogic; import ru.windcorp.progressia.server.world.block.BlockLogic;
public interface TileLogicReference public interface TileLogicReference
extends GenericTileReference<BlockLogic, TileLogic, TileLogicStack, TileLogicReference, ChunkLogic> { extends TileGenericReferenceRO<BlockLogic, TileLogic, TileLogicStack, TileLogicReference, ChunkLogic> {
} }

View File

@ -18,13 +18,16 @@
package ru.windcorp.progressia.server.world.tile; package ru.windcorp.progressia.server.world.tile;
import ru.windcorp.progressia.common.world.generic.GenericTileStack; import java.util.AbstractList;
import ru.windcorp.progressia.common.world.tile.TileDataStack;
import ru.windcorp.progressia.common.world.TileDataStack;
import ru.windcorp.progressia.common.world.generic.TileGenericStackRO;
import ru.windcorp.progressia.server.world.ChunkLogic; import ru.windcorp.progressia.server.world.ChunkLogic;
import ru.windcorp.progressia.server.world.block.BlockLogic; import ru.windcorp.progressia.server.world.block.BlockLogic;
public abstract class TileLogicStack public abstract class TileLogicStack
extends GenericTileStack<BlockLogic, TileLogic, TileLogicStack, TileLogicReference, ChunkLogic> { extends AbstractList<TileLogic>
implements TileGenericStackRO<BlockLogic, TileLogic, TileLogicStack, TileLogicReference, ChunkLogic> {
public abstract TileDataStack getData(); public abstract TileDataStack getData();

View File

@ -19,8 +19,8 @@
package ru.windcorp.progressia.server.world.tile; package ru.windcorp.progressia.server.world.tile;
import ru.windcorp.progressia.common.world.tile.TileData; import ru.windcorp.progressia.common.world.tile.TileData;
import ru.windcorp.progressia.common.world.tile.TileDataStack; import ru.windcorp.progressia.common.world.TileDataStack;
import ru.windcorp.progressia.common.world.tile.TileDataReference; import ru.windcorp.progressia.common.world.TileDataReference;
public interface TileTickContext extends TSTickContext { public interface TileTickContext extends TSTickContext {

View File

@ -33,9 +33,9 @@ import gnu.trove.map.TObjectIntMap;
import gnu.trove.map.hash.TObjectIntHashMap; import gnu.trove.map.hash.TObjectIntHashMap;
import ru.windcorp.jputil.functions.ThrowingConsumer; import ru.windcorp.jputil.functions.ThrowingConsumer;
import ru.windcorp.progressia.common.state.IOContext; import ru.windcorp.progressia.common.state.IOContext;
import ru.windcorp.progressia.common.world.ChunkData; import ru.windcorp.progressia.common.world.DefaultChunkData;
import ru.windcorp.progressia.common.world.DecodingException; import ru.windcorp.progressia.common.world.DecodingException;
import ru.windcorp.progressia.common.world.WorldData; import ru.windcorp.progressia.common.world.DefaultWorldData;
import ru.windcorp.progressia.common.world.block.BlockData; import ru.windcorp.progressia.common.world.block.BlockData;
import ru.windcorp.progressia.common.world.block.BlockDataRegistry; import ru.windcorp.progressia.common.world.block.BlockDataRegistry;
import ru.windcorp.progressia.common.world.generic.GenericChunks; import ru.windcorp.progressia.common.world.generic.GenericChunks;
@ -76,7 +76,7 @@ public class TestChunkCodec extends ChunkCodec {
} }
@Override @Override
public boolean shouldEncode(ChunkData chunk, IOContext context) { public boolean shouldEncode(DefaultChunkData chunk, IOContext context) {
return true; return true;
} }
@ -85,13 +85,13 @@ public class TestChunkCodec extends ChunkCodec {
*/ */
@Override @Override
public ChunkData decode(WorldData world, Vec3i position, DataInputStream input, IOContext context) public DefaultChunkData decode(DefaultWorldData world, Vec3i position, DataInputStream input, IOContext context)
throws DecodingException, throws DecodingException,
IOException { IOException {
BlockData[] blockPalette = readBlockPalette(input); BlockData[] blockPalette = readBlockPalette(input);
TileData[] tilePalette = readTilePalette(input); TileData[] tilePalette = readTilePalette(input);
ChunkData chunk = new ChunkData(position, world); DefaultChunkData chunk = new DefaultChunkData(position, world);
readBlocks(input, blockPalette, chunk); readBlocks(input, blockPalette, chunk);
readTiles(input, tilePalette, chunk); readTiles(input, tilePalette, chunk);
@ -121,7 +121,7 @@ public class TestChunkCodec extends ChunkCodec {
return palette; return palette;
} }
private void readBlocks(DataInput input, BlockData[] blockPalette, ChunkData chunk) throws IOException { private void readBlocks(DataInput input, BlockData[] blockPalette, DefaultChunkData chunk) throws IOException {
try { try {
GenericChunks.forEachBiC(guard(v -> { GenericChunks.forEachBiC(guard(v -> {
chunk.setBlock(v, blockPalette[input.readInt()], false); chunk.setBlock(v, blockPalette[input.readInt()], false);
@ -131,7 +131,7 @@ public class TestChunkCodec extends ChunkCodec {
} }
} }
private void readTiles(DataInput input, TileData[] tilePalette, ChunkData chunk) throws IOException { private void readTiles(DataInput input, TileData[] tilePalette, DefaultChunkData chunk) throws IOException {
Vec3i bic = new Vec3i(); Vec3i bic = new Vec3i();
while (true) { while (true) {
@ -157,7 +157,7 @@ public class TestChunkCodec extends ChunkCodec {
*/ */
@Override @Override
public void encode(ChunkData chunk, DataOutputStream output, IOContext context) throws IOException { public void encode(DefaultChunkData chunk, DataOutputStream output, IOContext context) throws IOException {
Palette<BlockData> blockPalette = createBlockPalette(chunk); Palette<BlockData> blockPalette = createBlockPalette(chunk);
Palette<TileData> tilePalette = createTilePalette(chunk); Palette<TileData> tilePalette = createTilePalette(chunk);
@ -168,13 +168,13 @@ public class TestChunkCodec extends ChunkCodec {
writeTiles(chunk, tilePalette, output); writeTiles(chunk, tilePalette, output);
} }
private Palette<BlockData> createBlockPalette(ChunkData chunk) { private Palette<BlockData> createBlockPalette(DefaultChunkData chunk) {
Palette<BlockData> blockPalette = new Palette<>(); Palette<BlockData> blockPalette = new Palette<>();
GenericChunks.forEachBiC(v -> blockPalette.add(chunk.getBlock(v))); GenericChunks.forEachBiC(v -> blockPalette.add(chunk.getBlock(v)));
return blockPalette; return blockPalette;
} }
private Palette<TileData> createTilePalette(ChunkData chunk) { private Palette<TileData> createTilePalette(DefaultChunkData chunk) {
Palette<TileData> tilePalette = new Palette<>(); Palette<TileData> tilePalette = new Palette<>();
chunk.forEachTile((ts, t) -> tilePalette.add(t)); chunk.forEachTile((ts, t) -> tilePalette.add(t));
return tilePalette; return tilePalette;
@ -196,7 +196,7 @@ public class TestChunkCodec extends ChunkCodec {
} }
} }
private void writeBlocks(ChunkData chunk, Palette<BlockData> blockPalette, DataOutput output) throws IOException { private void writeBlocks(DefaultChunkData chunk, Palette<BlockData> blockPalette, DataOutput output) throws IOException {
try { try {
GenericChunks.forEachBiC(guard(v -> { GenericChunks.forEachBiC(guard(v -> {
output.writeInt(blockPalette.getNid(chunk.getBlock(v))); output.writeInt(blockPalette.getNid(chunk.getBlock(v)));
@ -206,7 +206,7 @@ public class TestChunkCodec extends ChunkCodec {
} }
} }
private void writeTiles(ChunkData chunk, Palette<TileData> tilePalette, DataOutput output) throws IOException { private void writeTiles(DefaultChunkData chunk, Palette<TileData> tilePalette, DataOutput output) throws IOException {
Vec3i bic = new Vec3i(); Vec3i bic = new Vec3i();
try { try {

View File

@ -34,9 +34,9 @@ import org.apache.logging.log4j.Logger;
import glm.vec._3.i.Vec3i; import glm.vec._3.i.Vec3i;
import ru.windcorp.progressia.common.state.IOContext; import ru.windcorp.progressia.common.state.IOContext;
import ru.windcorp.progressia.common.world.ChunkData; import ru.windcorp.progressia.common.world.DefaultChunkData;
import ru.windcorp.progressia.common.world.DecodingException; import ru.windcorp.progressia.common.world.DecodingException;
import ru.windcorp.progressia.common.world.WorldData; import ru.windcorp.progressia.common.world.DefaultWorldData;
import ru.windcorp.progressia.common.world.io.ChunkIO; import ru.windcorp.progressia.common.world.io.ChunkIO;
import ru.windcorp.progressia.server.Server; import ru.windcorp.progressia.server.Server;
@ -47,7 +47,7 @@ public class TestWorldDiskIO {
private static final boolean ENABLE = false; private static final boolean ENABLE = false;
public static void saveChunk(ChunkData chunk, Server server) { public static void saveChunk(DefaultChunkData chunk, Server server) {
if (!ENABLE) if (!ENABLE)
return; return;
@ -83,12 +83,12 @@ public class TestWorldDiskIO {
} }
} }
private static void writeGenerationHint(ChunkData chunk, DataOutputStream output, Server server) private static void writeGenerationHint(DefaultChunkData chunk, DataOutputStream output, Server server)
throws IOException { throws IOException {
server.getWorld().getGenerator().writeGenerationHint(output, chunk.getGenerationHint()); server.getWorld().getGenerator().writeGenerationHint(output, chunk.getGenerationHint());
} }
public static ChunkData tryToLoad(Vec3i chunkPos, WorldData world, Server server) { public static DefaultChunkData tryToLoad(Vec3i chunkPos, DefaultWorldData world, Server server) {
if (!ENABLE) if (!ENABLE)
return null; return null;
@ -113,7 +113,7 @@ public class TestWorldDiskIO {
} }
try { try {
ChunkData result = load(path, chunkPos, world, server); DefaultChunkData result = load(path, chunkPos, world, server);
LOG.debug( LOG.debug(
"Loaded {} {} {}", "Loaded {} {} {}",
@ -135,7 +135,7 @@ public class TestWorldDiskIO {
} }
} }
private static ChunkData load(Path path, Vec3i chunkPos, WorldData world, Server server) private static DefaultChunkData load(Path path, Vec3i chunkPos, DefaultWorldData world, Server server)
throws IOException, throws IOException,
DecodingException { DecodingException {
try ( try (
@ -143,13 +143,13 @@ public class TestWorldDiskIO {
new InflaterInputStream(new BufferedInputStream(Files.newInputStream(path))) new InflaterInputStream(new BufferedInputStream(Files.newInputStream(path)))
) )
) { ) {
ChunkData chunk = ChunkIO.load(world, chunkPos, input, IOContext.SAVE); DefaultChunkData chunk = ChunkIO.load(world, chunkPos, input, IOContext.SAVE);
readGenerationHint(chunk, input, server); readGenerationHint(chunk, input, server);
return chunk; return chunk;
} }
} }
private static void readGenerationHint(ChunkData chunk, DataInputStream input, Server server) private static void readGenerationHint(DefaultChunkData chunk, DataInputStream input, Server server)
throws IOException, throws IOException,
DecodingException { DecodingException {
chunk.setGenerationHint(server.getWorld().getGenerator().readGenerationHint(input)); chunk.setGenerationHint(server.getWorld().getGenerator().readGenerationHint(input));

View File

@ -19,12 +19,12 @@ package ru.windcorp.progressia.test.gen;
import java.util.Random; import java.util.Random;
import ru.windcorp.progressia.common.world.ChunkData; import ru.windcorp.progressia.common.world.DefaultChunkData;
import ru.windcorp.progressia.common.world.block.BlockData; import ru.windcorp.progressia.common.world.block.BlockData;
@FunctionalInterface @FunctionalInterface
public interface TerrainLayer { public interface TerrainLayer {
BlockData get(float north, float west, float depth, Random random, ChunkData chunk); BlockData get(float north, float west, float depth, Random random, DefaultChunkData chunk);
} }

Some files were not shown because too many files have changed in this diff Show More