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:
parent
d7afe39f00
commit
9a326603cd
@ -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;
|
||||||
|
|
||||||
|
@ -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()
|
||||||
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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);
|
||||||
|
@ -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;
|
||||||
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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)];
|
||||||
|
@ -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,
|
||||||
|
@ -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;
|
||||||
|
|
||||||
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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> {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -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();
|
||||||
|
|
||||||
|
@ -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(),
|
||||||
|
@ -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(
|
||||||
|
@ -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);
|
||||||
|
@ -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);
|
||||||
}
|
}
|
@ -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;
|
|
||||||
public static final int CHUNK_RADIUS = BLOCKS_PER_CHUNK / 2;
|
|
||||||
|
|
||||||
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;
|
// @Override
|
||||||
|
// default TileDataStack getTiles(Vec3i blockInChunk, BlockFace face) {
|
||||||
private Object generationHint = null;
|
// return 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;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -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) {
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -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());
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -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
|
||||||
|
|
||||||
|
}
|
@ -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;
|
||||||
|
|
||||||
|
@ -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;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -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);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -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);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -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);
|
||||||
}
|
}
|
||||||
|
@ -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) {
|
||||||
|
@ -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 {
|
||||||
|
@ -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> {
|
||||||
|
|
||||||
|
}
|
@ -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
|
||||||
|
|
||||||
|
}
|
@ -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();
|
||||||
|
|
||||||
|
}
|
@ -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
|
||||||
|
|
||||||
|
}
|
@ -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;
|
|
||||||
}
|
/*
|
||||||
|
* Method specialization
|
||||||
/**
|
|
||||||
* @param gravityModel the gravity model to set
|
|
||||||
*/
|
*/
|
||||||
public void setGravityModel(GravityModel gravityModel) {
|
|
||||||
if (!chunks.isEmpty()) {
|
@Override
|
||||||
throw new IllegalStateException(
|
ChunkData getChunk(Vec3i pos);
|
||||||
"Attempted to change gravity model to " + gravityModel + " while " + chunks.size()
|
|
||||||
+ " chunks were loaded"
|
@Override
|
||||||
);
|
Collection<? extends ChunkData> getChunks();
|
||||||
}
|
|
||||||
|
// TODO: rename WGRO.forEachChunk -> forEachChunkRO and define WGWO.forEachChunk
|
||||||
this.gravityModel = gravityModel;
|
|
||||||
|
@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);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -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) {
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -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();
|
||||||
|
|
||||||
|
}
|
@ -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);
|
||||||
|
@ -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);
|
||||||
}
|
}
|
||||||
|
@ -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();
|
||||||
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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) {
|
||||||
|
@ -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());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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());
|
||||||
|
@ -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();
|
||||||
|
|
@ -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
|
||||||
|
|
@ -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);
|
||||||
|
|
||||||
|
}
|
@ -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) -> {
|
||||||
|
@ -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) {
|
||||||
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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);
|
||||||
}
|
}
|
||||||
|
@ -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();
|
||||||
|
|
@ -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
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -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);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@ -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());
|
||||||
}
|
}
|
||||||
|
@ -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();
|
||||||
|
|
@ -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());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -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;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
@ -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));
|
||||||
}
|
}
|
||||||
|
|
@ -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,19 +94,21 @@ 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}
|
||||||
@ -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;
|
||||||
}
|
}
|
@ -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;
|
||||||
}
|
}
|
@ -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);
|
||||||
|
|
||||||
}
|
}
|
@ -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.
|
||||||
*
|
*
|
@ -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());
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
@ -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.
|
@ -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());
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
@ -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());
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
@ -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
|
||||||
|
|
||||||
/**
|
/**
|
@ -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() {
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -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
|
@ -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);
|
||||||
|
|
||||||
}
|
}
|
@ -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;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -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;
|
||||||
|
@ -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);
|
||||||
}
|
}
|
||||||
|
@ -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());
|
||||||
|
@ -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);
|
||||||
|
@ -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> {
|
|
||||||
|
|
||||||
}
|
|
@ -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);
|
||||||
|
@ -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,
|
||||||
|
@ -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();
|
||||||
}
|
}
|
||||||
|
@ -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
|
||||||
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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();
|
||||||
}
|
}
|
||||||
|
@ -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();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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) {
|
||||||
|
@ -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,
|
||||||
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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);
|
||||||
|
@ -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();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -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;
|
||||||
|
|
||||||
|
@ -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");
|
||||||
}
|
}
|
||||||
|
@ -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;
|
||||||
|
|
||||||
|
@ -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);
|
||||||
|
@ -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> {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -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();
|
||||||
|
|
||||||
|
@ -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 {
|
||||||
|
|
||||||
|
@ -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 {
|
||||||
|
@ -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));
|
||||||
|
@ -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
Reference in New Issue
Block a user