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

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

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

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

View File

@ -24,7 +24,7 @@ import ru.windcorp.progressia.client.graphics.world.Camera;
import ru.windcorp.progressia.client.graphics.world.EntityAnchor;
import ru.windcorp.progressia.client.graphics.world.LocalPlayer;
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;
public class Client {
@ -36,7 +36,7 @@ public class Client {
private final ServerCommsChannel comms;
public Client(WorldData world, ServerCommsChannel comms) {
public Client(DefaultWorldData world, ServerCommsChannel comms) {
this.world = new WorldRender(world, this);
this.comms = comms;

View File

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

View File

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

View File

@ -35,7 +35,7 @@ import ru.windcorp.progressia.client.world.cro.ChunkRenderOptimizerRegistry;
import ru.windcorp.progressia.client.world.tile.TileRender;
import ru.windcorp.progressia.client.world.tile.TileRenderNone;
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.rels.AxisRotations;
import ru.windcorp.progressia.common.world.rels.RelFace;
@ -55,12 +55,12 @@ public class ChunkRenderModel implements Renderable {
public void render(ShapeRenderHelper renderer) {
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(
chunk.getX() * ChunkData.BLOCKS_PER_CHUNK,
chunk.getY() * ChunkData.BLOCKS_PER_CHUNK,
chunk.getZ() * ChunkData.BLOCKS_PER_CHUNK
chunk.getX() * DefaultChunkData.BLOCKS_PER_CHUNK,
chunk.getY() * DefaultChunkData.BLOCKS_PER_CHUNK,
chunk.getZ() * DefaultChunkData.BLOCKS_PER_CHUNK
).translate(offset, offset, offset)
.mul(AxisRotations.getResolutionMatrix4(chunk.getUp()))
.translate(-offset, -offset, -offset);

View File

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

View File

@ -38,54 +38,54 @@ import ru.windcorp.progressia.client.world.tile.TileRenderReference;
import ru.windcorp.progressia.client.world.tile.TileRenderStack;
import ru.windcorp.progressia.common.util.VectorUtil;
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.WorldData;
import ru.windcorp.progressia.common.world.DefaultWorldData;
import ru.windcorp.progressia.common.world.WorldDataListener;
import ru.windcorp.progressia.common.world.entity.EntityData;
import ru.windcorp.progressia.common.world.generic.ChunkSet;
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
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 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 ChunkSet chunksToUpdate = ChunkSets.newSyncHashSet();
public WorldRender(WorldData data, Client client) {
public WorldRender(DefaultWorldData data, Client client) {
this.data = data;
this.client = client;
data.addListener(ChunkDataListeners.createAdder(new ChunkUpdateListener(this)));
data.addListener(new WorldDataListener() {
@Override
public void onChunkLoaded(WorldData world, ChunkData chunk) {
public void onChunkLoaded(DefaultWorldData world, DefaultChunkData chunk) {
addChunk(chunk);
}
@Override
public void beforeChunkUnloaded(WorldData world, ChunkData chunk) {
public void beforeChunkUnloaded(DefaultWorldData world, DefaultChunkData chunk) {
removeChunk(chunk);
}
});
}
protected void addChunk(ChunkData chunk) {
protected void addChunk(DefaultChunkData chunk) {
chunks.put(chunk, new ChunkRender(WorldRender.this, chunk));
markChunkForUpdate(chunk.getPosition());
}
protected void removeChunk(ChunkData chunk) {
protected void removeChunk(DefaultChunkData chunk) {
chunks.remove(chunk);
}
public WorldData getData() {
public DefaultWorldData getData() {
return data;
}
@ -93,7 +93,7 @@ public class WorldRender
return client;
}
public ChunkRender getChunk(ChunkData chunkData) {
public ChunkRender getChunk(DefaultChunkData chunkData) {
return chunks.get(chunkData);
}

View File

@ -19,18 +19,18 @@
package ru.windcorp.progressia.client.world.block;
import ru.windcorp.progressia.common.util.namespaces.Namespaced;
import ru.windcorp.progressia.common.world.ChunkData;
import ru.windcorp.progressia.common.world.generic.GenericBlock;
import ru.windcorp.progressia.common.world.DefaultChunkData;
import ru.windcorp.progressia.common.world.generic.BlockGeneric;
import glm.vec._3.i.Vec3i;
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) {
super(id);
}
public Renderable createRenderable(ChunkData chunk, Vec3i relBlockInChunk) {
public Renderable createRenderable(DefaultChunkData chunk, Vec3i relBlockInChunk) {
return null;
}

View File

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

View File

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

View File

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

View File

@ -23,9 +23,9 @@ import ru.windcorp.progressia.client.graphics.backend.GraphicsInterface;
import ru.windcorp.progressia.client.graphics.model.Renderable;
import ru.windcorp.progressia.client.graphics.model.ShapeRenderHelper;
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;

View File

@ -22,17 +22,17 @@ import glm.vec._3.i.Vec3i;
import ru.windcorp.progressia.client.graphics.model.Renderable;
import ru.windcorp.progressia.client.world.cro.ChunkRenderOptimizer;
import ru.windcorp.progressia.common.util.namespaces.Namespaced;
import ru.windcorp.progressia.common.world.ChunkData;
import ru.windcorp.progressia.common.world.generic.GenericTile;
import ru.windcorp.progressia.common.world.DefaultChunkData;
import ru.windcorp.progressia.common.world.generic.TileGeneric;
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) {
super(id);
}
public Renderable createRenderable(ChunkData chunk, Vec3i blockInChunk, RelFace face) {
public Renderable createRenderable(DefaultChunkData chunk, Vec3i blockInChunk, RelFace face) {
return null;
}

View File

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

View File

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

View File

@ -18,13 +18,15 @@
package ru.windcorp.progressia.client.world.tile;
import java.util.AbstractList;
import ru.windcorp.progressia.client.world.ChunkRender;
import ru.windcorp.progressia.client.world.block.BlockRender;
import ru.windcorp.progressia.common.world.generic.GenericTileStack;
import ru.windcorp.progressia.common.world.tile.TileDataStack;
import ru.windcorp.progressia.common.world.TileDataStack;
import ru.windcorp.progressia.common.world.generic.TileGenericStackRO;
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();

View File

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

View File

@ -24,7 +24,7 @@ import java.util.Collection;
import glm.vec._3.Vec3;
import glm.vec._3.i.Vec3i;
import ru.windcorp.progressia.common.util.LowOverheadCache;
import ru.windcorp.progressia.common.world.WorldData;
import ru.windcorp.progressia.common.world.DefaultWorldData;
public class WorldCollisionHelper {
@ -79,7 +79,7 @@ public class WorldCollisionHelper {
* checked against
* @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.clear();
CollisionPathComputer.forEveryBlockInCollisionPath(

View File

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

View File

@ -16,12 +16,9 @@
* 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.GenericTileReference;
public interface TileDataReference extends GenericTileReference<BlockData, TileData, TileDataStack, TileDataReference, ChunkData> {
package ru.windcorp.progressia.common.state;
@FunctionalInterface
public interface StateChange<T> {
void change(T object);
}

View File

@ -1,527 +1,14 @@
/*
* Progressia
* Copyright (C) 2020-2021 Wind Corporation and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package ru.windcorp.progressia.common.world;
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.generic.GenericChunks;
import ru.windcorp.progressia.common.world.generic.GenericWritableChunk;
import ru.windcorp.progressia.common.world.rels.AbsFace;
import ru.windcorp.progressia.common.world.rels.BlockFace;
import ru.windcorp.progressia.common.world.rels.RelFace;
import ru.windcorp.progressia.common.world.generic.ChunkGenericWO;
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
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
];
public interface ChunkData extends ChunkDataRO, ChunkGenericWO<BlockData, TileData, TileDataStack, TileDataReference, ChunkData> {
private final AbsFace up;
private Object generationHint = null;
private final Collection<ChunkDataListener> listeners = Collections.synchronizedCollection(new ArrayList<>());
public ChunkData(Vec3i position, WorldData world) {
this.position.set(position.x, position.y, position.z);
this.world = world;
this.up = world.getGravityModel().getDiscreteUp(position);
}
@Override
public Vec3i getPosition() {
return position;
}
@Override
public AbsFace getUp() {
return up;
}
@Override
public BlockData getBlock(Vec3i posInChunk) {
return blocks[getBlockIndex(posInChunk)];
}
@Override
public void setBlock(Vec3i posInChunk, BlockData block, boolean notify) {
BlockData previous = blocks[getBlockIndex(posInChunk)];
blocks[getBlockIndex(posInChunk)] = block;
if (notify) {
getListeners().forEach(l -> {
l.onChunkBlockChanged(this, posInChunk, previous, block);
l.onChunkChanged(this);
});
}
}
@Override
public TileDataStack getTilesOrNull(Vec3i blockInChunk, BlockFace face) {
return tiles[getTileIndex(blockInChunk, face)];
}
/**
* Internal use only. Modify a list returned by
* {@link #getTiles(Vec3i, BlockFace)} or
* {@link #getTilesOrNull(Vec3i, BlockFace)}
* to change tiles.
*/
protected void setTiles(
Vec3i blockInChunk,
BlockFace face,
TileDataStack tiles
) {
this.tiles[getTileIndex(blockInChunk, face)] = tiles;
}
@Override
public boolean hasTiles(Vec3i blockInChunk, BlockFace face) {
return getTilesOrNull(blockInChunk, face) != null;
}
@Override
public TileDataStack getTiles(Vec3i blockInChunk, BlockFace face) {
int index = getTileIndex(blockInChunk, face);
if (tiles[index] == null) {
createTileStack(blockInChunk, face);
}
return tiles[index];
}
private void createTileStack(Vec3i blockInChunk, BlockFace face) {
Vec3i independentBlockInChunk = conjureIndependentBlockInChunkVec3i(blockInChunk);
TileDataStackImpl stack = new TileDataStackImpl(independentBlockInChunk, face);
setTiles(blockInChunk, face, stack);
}
private Vec3i conjureIndependentBlockInChunkVec3i(Vec3i blockInChunk) {
for (int i = 0; i < AbsFace.BLOCK_FACE_COUNT; ++i) {
TileDataStack stack = getTilesOrNull(blockInChunk, AbsFace.getFaces().get(i));
if (stack instanceof TileDataStackImpl) {
return ((TileDataStackImpl) stack).blockInChunk;
}
}
return new Vec3i(blockInChunk);
}
private static int getBlockIndex(Vec3i posInChunk) {
checkLocalCoordinates(posInChunk);
return posInChunk.z * BLOCKS_PER_CHUNK * BLOCKS_PER_CHUNK +
posInChunk.y * BLOCKS_PER_CHUNK +
posInChunk.x;
}
private int getTileIndex(Vec3i posInChunk, BlockFace face) {
return getBlockIndex(posInChunk) * BLOCK_FACE_COUNT +
face.resolve(getUp()).getId();
}
private static void checkLocalCoordinates(Vec3i posInChunk) {
if (!GenericChunks.containsBiC(posInChunk)) {
throw new IllegalCoordinatesException(
"Coordinates (" + posInChunk.x + "; " + posInChunk.y + "; " + posInChunk.z + ") "
+ "are not legal chunk coordinates"
);
}
}
public WorldData getWorld() {
return world;
}
public Collection<ChunkDataListener> getListeners() {
return listeners;
}
public void addListener(ChunkDataListener listener) {
this.listeners.add(listener);
}
public void removeListener(ChunkDataListener listener) {
this.listeners.remove(listener);
}
protected void onLoaded() {
getListeners().forEach(l -> l.onChunkLoaded(this));
}
protected void beforeUnloaded() {
getListeners().forEach(l -> l.beforeChunkUnloaded(this));
}
public Object getGenerationHint() {
return generationHint;
}
public void setGenerationHint(Object generationHint) {
this.generationHint = generationHint;
}
/**
* Implementation of {@link TileDataStack} used internally by
* {@link ChunkData} to
* actually store the tiles. This is basically an array wrapper with
* reporting
* capabilities.
*
* @author javapony
*/
private class TileDataStackImpl extends TileDataStack {
private class TileDataReferenceImpl implements TileDataReference {
private int index;
public TileDataReferenceImpl(int index) {
this.index = index;
}
public void incrementIndex() {
this.index++;
}
public void decrementIndex() {
this.index--;
}
public void invalidate() {
this.index = 0;
}
@Override
public TileData get() {
if (!isValid())
return null;
return TileDataStackImpl.this.get(this.index);
}
@Override
public int getIndex() {
return index;
}
@Override
public TileDataStack getStack() {
return TileDataStackImpl.this;
}
@Override
public boolean isValid() {
return this.index >= 0;
}
}
private final TileData[] tiles = new TileData[TILES_PER_FACE];
private int size = 0;
private final TileDataReferenceImpl[] references = new TileDataReferenceImpl[tiles.length];
private final int[] indicesByTag = new int[tiles.length];
private final int[] tagsByIndex = new int[tiles.length];
{
Arrays.fill(indicesByTag, -1);
Arrays.fill(tagsByIndex, -1);
}
/*
* Potentially shared
*/
private final Vec3i blockInChunk;
private final RelFace face;
public TileDataStackImpl(Vec3i blockInChunk, BlockFace face) {
this.blockInChunk = blockInChunk;
this.face = face.relativize(getUp());
}
@Override
public Vec3i getBlockInChunk(Vec3i output) {
if (output == null)
output = new Vec3i();
output.set(blockInChunk.x, blockInChunk.y, blockInChunk.z);
return output;
}
@Override
public RelFace getFace() {
return face;
}
@Override
public ChunkData getChunk() {
return ChunkData.this;
}
@Override
public int size() {
return size;
}
@Override
public TileData get(int index) {
checkIndex(index, false);
return tiles[index];
}
@Override
public TileData set(int index, TileData tile) {
Objects.requireNonNull(tile, "tile");
TileData previous = get(index); // checks index
tiles[index] = tile;
if (references[index] != null) {
references[index].invalidate();
references[index] = null;
}
assert checkConsistency();
report(previous, tile);
return previous;
}
@Override
public void add(int index, TileData tile) {
Objects.requireNonNull(tile, "tile");
checkIndex(index, true);
if (index != size()) {
System.arraycopy(tiles, index + 1, tiles, index + 2, size - index);
for (int i = index; i < size; ++i) {
if (references[i] != null) {
references[i].incrementIndex();
}
indicesByTag[tagsByIndex[i]]++;
}
System.arraycopy(references, index + 1, references, index + 2, size - index);
System.arraycopy(tagsByIndex, index + 1, tagsByIndex, index + 2, size - index);
}
size++;
tiles[index] = tile;
references[index] = null;
for (int tag = 0; tag < indicesByTag.length; ++tag) {
if (indicesByTag[tag] == -1) {
indicesByTag[tag] = index;
tagsByIndex[index] = tag;
break;
}
}
modCount++;
assert checkConsistency();
report(null, tile);
}
@Override
public void load(TileData tile, int tag) {
addFarthest(tile);
int assignedIndex = size() - 1;
// Skip if we already have the correct tag
int assignedTag = getTagByIndex(assignedIndex);
if (assignedTag == tag) {
return;
}
assert assignedTag != -1 : "Adding farthest tile resulted in -1 tag";
// Make sure we aren't trying to assign a tag already in use
int tileWithRequestedTag = getIndexByTag(tag);
if (tileWithRequestedTag != -1) {
throw new IllegalArgumentException(
"Tag " + tag + " already used by tile at index " + tileWithRequestedTag
);
}
assert tileWithRequestedTag != assignedIndex : "tag == assignedTag yet tileWithRequestedTag != assignedIndex";
// Do the tag editing
indicesByTag[assignedTag] = -1; // Release assigned tag
tagsByIndex[assignedIndex] = tag; // Reroute assigned index to requested tag
indicesByTag[tag] = assignedIndex; // Claim requested tag
assert checkConsistency();
}
@Override
public TileData remove(int index) {
TileData previous = get(index); // checks index
if (references[index] != null) {
references[index].invalidate();
}
indicesByTag[tagsByIndex[index]] = -1;
if (index != size() - 1) {
System.arraycopy(tiles, index + 1, tiles, index, size - index - 1);
for (int i = index + 1; i < size; ++i) {
if (references[i] != null) {
references[i].decrementIndex();
}
indicesByTag[tagsByIndex[i]]--;
}
System.arraycopy(references, index + 1, references, index, size - index - 1);
System.arraycopy(tagsByIndex, index + 1, tagsByIndex, index, size - index - 1);
}
size--;
tiles[size] = null;
references[size] = null;
tagsByIndex[size] = -1;
modCount++;
assert checkConsistency();
report(previous, null);
return previous;
}
@Override
public TileDataReference getReference(int index) {
checkIndex(index, false);
if (references[index] == null) {
references[index] = new TileDataReferenceImpl(index);
}
return references[index];
}
@Override
public int getIndexByTag(int tag) {
return indicesByTag[tag];
}
@Override
public int getTagByIndex(int index) {
checkIndex(index, false);
return tagsByIndex[index];
}
@Override
public void clear() {
while (!isEmpty()) {
removeFarthest();
}
}
private void checkIndex(int index, boolean isSizeAllowed) {
if (isSizeAllowed ? (index > size()) : (index >= size()))
throw new IndexOutOfBoundsException("Index " + index + " is out of bounds: size is " + size);
if (index < 0)
throw new IndexOutOfBoundsException("Index " + index + " is out of bounds: index cannot be negative");
if (index >= TILES_PER_FACE)
throw new TileStackIsFullException(
"Index " + index + " is out of bounds: maximum tile stack size is " + TILES_PER_FACE
);
}
private void report(TileData previous, TileData current) {
ChunkData.this.getListeners().forEach(l -> {
if (previous != null) {
l.onChunkTilesChanged(ChunkData.this, blockInChunk, face, previous, false);
}
if (current != null) {
l.onChunkTilesChanged(ChunkData.this, blockInChunk, face, current, true);
}
l.onChunkChanged(ChunkData.this);
});
}
private boolean checkConsistency() {
int index;
for (index = 0; index < size(); ++index) {
if (get(index) == null)
throw new AssertionError("get(index) is null");
if (references[index] != null) {
TileDataReference ref = getReference(index);
if (ref == null)
throw new AssertionError("references[index] is not null but getReference(index) is");
if (!ref.isValid())
throw new AssertionError("Reference is not valid");
if (ref.get() != get(index))
throw new AssertionError("Reference points to " + (ref.get() == null ? "null" : "wrong tile"));
if (ref.getIndex() != index)
throw new AssertionError("Reference has invalid index");
if (ref.getStack() != this)
throw new AssertionError("Reference has invalid TDS");
}
if (index != indicesByTag[tagsByIndex[index]])
throw new AssertionError("Tag mapping is inconsistent");
if (index != getIndexByTag(getTagByIndex(index)))
throw new AssertionError("Tag methods are inconsistent with tag mapping");
}
for (; index < tiles.length; ++index) {
if (tiles[index] != null)
throw new AssertionError("Leftover tile detected");
if (references[index] != null)
throw new AssertionError("Leftover reference detected");
if (tagsByIndex[index] != -1)
throw new AssertionError("Leftover tags detected");
}
return true;
}
}
// @Override
// default TileDataStack getTiles(Vec3i blockInChunk, BlockFace face) {
// return null;
// }
}

View File

@ -36,7 +36,7 @@ public interface ChunkDataListener {
* @param previous the previous 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
*/
default void onChunkTilesChanged(
ChunkData chunk,
DefaultChunkData chunk,
Vec3i blockInChunk,
RelFace face,
TileData tile,
@ -70,7 +70,7 @@ public interface ChunkDataListener {
*
* @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
*/
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
*/
default void beforeChunkUnloaded(ChunkData chunk) {
default void beforeChunkUnloaded(DefaultChunkData chunk) {
}
}

View File

@ -28,7 +28,7 @@ public class ChunkDataListeners {
public static WorldDataListener createAdder(Supplier<ChunkDataListener> listenerSupplier) {
return new WorldDataListener() {
@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());
}
};

View File

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

View File

@ -18,7 +18,7 @@
package ru.windcorp.progressia.common.world;
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;

View File

@ -0,0 +1,525 @@
/*
* Progressia
* Copyright (C) 2020-2021 Wind Corporation and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package ru.windcorp.progressia.common.world;
import static ru.windcorp.progressia.common.world.rels.BlockFace.BLOCK_FACE_COUNT;
import java.util.AbstractList;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.Objects;
import glm.vec._3.i.Vec3i;
import ru.windcorp.progressia.common.world.block.BlockData;
import ru.windcorp.progressia.common.world.generic.GenericChunks;
import ru.windcorp.progressia.common.world.rels.AbsFace;
import ru.windcorp.progressia.common.world.rels.BlockFace;
import ru.windcorp.progressia.common.world.rels.RelFace;
import ru.windcorp.progressia.common.world.tile.TileData;
import ru.windcorp.progressia.common.world.tile.TileStackIsFullException;
public class DefaultChunkData implements ChunkData {
public static final int BLOCKS_PER_CHUNK = Coordinates.CHUNK_SIZE;
public static final int CHUNK_RADIUS = BLOCKS_PER_CHUNK / 2;
private final Vec3i position = new Vec3i();
private final DefaultWorldData world;
private final BlockData[] blocks = new BlockData[BLOCKS_PER_CHUNK * BLOCKS_PER_CHUNK * BLOCKS_PER_CHUNK];
private final TileDataStack[] tiles = new TileDataStack[BLOCKS_PER_CHUNK * BLOCKS_PER_CHUNK * BLOCKS_PER_CHUNK
* BLOCK_FACE_COUNT];
private final AbsFace up;
private Object generationHint = null;
private final Collection<ChunkDataListener> listeners = Collections.synchronizedCollection(new ArrayList<>());
public DefaultChunkData(Vec3i position, DefaultWorldData world) {
this.position.set(position.x, position.y, position.z);
this.world = world;
this.up = world.getGravityModel().getDiscreteUp(position);
}
@Override
public Vec3i getPosition() {
return position;
}
@Override
public AbsFace getUp() {
return up;
}
@Override
public BlockData getBlock(Vec3i posInChunk) {
return blocks[getBlockIndex(posInChunk)];
}
@Override
public void setBlock(Vec3i posInChunk, BlockData block, boolean notify) {
BlockData previous = blocks[getBlockIndex(posInChunk)];
blocks[getBlockIndex(posInChunk)] = block;
if (notify) {
getListeners().forEach(l -> {
l.onChunkBlockChanged(this, posInChunk, previous, block);
l.onChunkChanged(this);
});
}
}
@Override
public TileDataStack getTilesOrNull(Vec3i blockInChunk, BlockFace face) {
return tiles[getTileIndex(blockInChunk, face)];
}
/**
* Internal use only. Modify a list returned by
* {@link #getTiles(Vec3i, BlockFace)} or
* {@link #getTilesOrNull(Vec3i, BlockFace)}
* to change tiles.
*/
protected void setTiles(
Vec3i blockInChunk,
BlockFace face,
TileDataStack tiles
) {
this.tiles[getTileIndex(blockInChunk, face)] = tiles;
}
@Override
public boolean hasTiles(Vec3i blockInChunk, BlockFace face) {
return getTilesOrNull(blockInChunk, face) != null;
}
@Override
public TileDataStack getTiles(Vec3i blockInChunk, BlockFace face) {
int index = getTileIndex(blockInChunk, face);
if (tiles[index] == null) {
createTileStack(blockInChunk, face);
}
return tiles[index];
}
private void createTileStack(Vec3i blockInChunk, BlockFace face) {
Vec3i independentBlockInChunk = conjureIndependentBlockInChunkVec3i(blockInChunk);
TileDataStackImpl stack = new TileDataStackImpl(independentBlockInChunk, face);
setTiles(blockInChunk, face, stack);
}
private Vec3i conjureIndependentBlockInChunkVec3i(Vec3i blockInChunk) {
for (int i = 0; i < AbsFace.BLOCK_FACE_COUNT; ++i) {
TileDataStack stack = getTilesOrNull(blockInChunk, AbsFace.getFaces().get(i));
if (stack instanceof TileDataStackImpl) {
return ((TileDataStackImpl) stack).blockInChunk;
}
}
return new Vec3i(blockInChunk);
}
private static int getBlockIndex(Vec3i posInChunk) {
checkLocalCoordinates(posInChunk);
return posInChunk.z * BLOCKS_PER_CHUNK * BLOCKS_PER_CHUNK +
posInChunk.y * BLOCKS_PER_CHUNK +
posInChunk.x;
}
private int getTileIndex(Vec3i posInChunk, BlockFace face) {
return getBlockIndex(posInChunk) * BLOCK_FACE_COUNT +
face.resolve(getUp()).getId();
}
private static void checkLocalCoordinates(Vec3i posInChunk) {
if (!GenericChunks.containsBiC(posInChunk)) {
throw new IllegalCoordinatesException(
"Coordinates (" + posInChunk.x + "; " + posInChunk.y + "; " + posInChunk.z + ") "
+ "are not legal chunk coordinates"
);
}
}
public DefaultWorldData getWorld() {
return world;
}
public Collection<ChunkDataListener> getListeners() {
return listeners;
}
public void addListener(ChunkDataListener listener) {
this.listeners.add(listener);
}
public void removeListener(ChunkDataListener listener) {
this.listeners.remove(listener);
}
protected void onLoaded() {
getListeners().forEach(l -> l.onChunkLoaded(this));
}
protected void beforeUnloaded() {
getListeners().forEach(l -> l.beforeChunkUnloaded(this));
}
public Object getGenerationHint() {
return generationHint;
}
public void setGenerationHint(Object generationHint) {
this.generationHint = generationHint;
}
/**
* Implementation of {@link TileDataStack} used internally by
* {@link DefaultChunkData} to
* actually store the tiles. This is basically an array wrapper with
* reporting
* capabilities.
*
* @author javapony
*/
private class TileDataStackImpl extends AbstractList<TileData> implements TileDataStack {
private class TileDataReferenceImpl implements TileDataReference {
private int index;
public TileDataReferenceImpl(int index) {
this.index = index;
}
public void incrementIndex() {
this.index++;
}
public void decrementIndex() {
this.index--;
}
public void invalidate() {
this.index = 0;
}
@Override
public TileData get() {
if (!isValid())
return null;
return TileDataStackImpl.this.get(this.index);
}
@Override
public int getIndex() {
return index;
}
@Override
public TileDataStack getStack() {
return TileDataStackImpl.this;
}
@Override
public boolean isValid() {
return this.index >= 0;
}
}
private final TileData[] tiles = new TileData[TILES_PER_FACE];
private int size = 0;
private final TileDataReferenceImpl[] references = new TileDataReferenceImpl[tiles.length];
private final int[] indicesByTag = new int[tiles.length];
private final int[] tagsByIndex = new int[tiles.length];
{
Arrays.fill(indicesByTag, -1);
Arrays.fill(tagsByIndex, -1);
}
/*
* Potentially shared
*/
private final Vec3i blockInChunk;
private final RelFace face;
public TileDataStackImpl(Vec3i blockInChunk, BlockFace face) {
this.blockInChunk = blockInChunk;
this.face = face.relativize(getUp());
}
@Override
public Vec3i getBlockInChunk(Vec3i output) {
if (output == null)
output = new Vec3i();
output.set(blockInChunk.x, blockInChunk.y, blockInChunk.z);
return output;
}
@Override
public RelFace getFace() {
return face;
}
@Override
public DefaultChunkData getChunk() {
return DefaultChunkData.this;
}
@Override
public int size() {
return size;
}
@Override
public TileData get(int index) {
checkIndex(index, false);
return tiles[index];
}
@Override
public TileData set(int index, TileData tile) {
Objects.requireNonNull(tile, "tile");
TileData previous = get(index); // checks index
tiles[index] = tile;
if (references[index] != null) {
references[index].invalidate();
references[index] = null;
}
assert checkConsistency();
report(previous, tile);
return previous;
}
@Override
public void add(int index, TileData tile) {
Objects.requireNonNull(tile, "tile");
checkIndex(index, true);
if (index != size()) {
System.arraycopy(tiles, index + 1, tiles, index + 2, size - index);
for (int i = index; i < size; ++i) {
if (references[i] != null) {
references[i].incrementIndex();
}
indicesByTag[tagsByIndex[i]]++;
}
System.arraycopy(references, index + 1, references, index + 2, size - index);
System.arraycopy(tagsByIndex, index + 1, tagsByIndex, index + 2, size - index);
}
size++;
tiles[index] = tile;
references[index] = null;
for (int tag = 0; tag < indicesByTag.length; ++tag) {
if (indicesByTag[tag] == -1) {
indicesByTag[tag] = index;
tagsByIndex[index] = tag;
break;
}
}
modCount++;
assert checkConsistency();
report(null, tile);
}
@Override
public void load(TileData tile, int tag) {
addFarthest(tile);
int assignedIndex = size() - 1;
// Skip if we already have the correct tag
int assignedTag = getTagByIndex(assignedIndex);
if (assignedTag == tag) {
return;
}
assert assignedTag != -1 : "Adding farthest tile resulted in -1 tag";
// Make sure we aren't trying to assign a tag already in use
int tileWithRequestedTag = getIndexByTag(tag);
if (tileWithRequestedTag != -1) {
throw new IllegalArgumentException(
"Tag " + tag + " already used by tile at index " + tileWithRequestedTag
);
}
assert tileWithRequestedTag != assignedIndex
: "tag == assignedTag yet tileWithRequestedTag != assignedIndex";
// Do the tag editing
indicesByTag[assignedTag] = -1; // Release assigned tag
tagsByIndex[assignedIndex] = tag; // Reroute assigned index to
// requested tag
indicesByTag[tag] = assignedIndex; // Claim requested tag
assert checkConsistency();
}
@Override
public TileData remove(int index) {
TileData previous = get(index); // checks index
if (references[index] != null) {
references[index].invalidate();
}
indicesByTag[tagsByIndex[index]] = -1;
if (index != size() - 1) {
System.arraycopy(tiles, index + 1, tiles, index, size - index - 1);
for (int i = index + 1; i < size; ++i) {
if (references[i] != null) {
references[i].decrementIndex();
}
indicesByTag[tagsByIndex[i]]--;
}
System.arraycopy(references, index + 1, references, index, size - index - 1);
System.arraycopy(tagsByIndex, index + 1, tagsByIndex, index, size - index - 1);
}
size--;
tiles[size] = null;
references[size] = null;
tagsByIndex[size] = -1;
modCount++;
assert checkConsistency();
report(previous, null);
return previous;
}
@Override
public TileDataReference getReference(int index) {
checkIndex(index, false);
if (references[index] == null) {
references[index] = new TileDataReferenceImpl(index);
}
return references[index];
}
@Override
public int getIndexByTag(int tag) {
return indicesByTag[tag];
}
@Override
public int getTagByIndex(int index) {
checkIndex(index, false);
return tagsByIndex[index];
}
@Override
public void clear() {
while (!isEmpty()) {
removeFarthest();
}
}
private void checkIndex(int index, boolean isSizeAllowed) {
if (isSizeAllowed ? (index > size()) : (index >= size()))
throw new IndexOutOfBoundsException("Index " + index + " is out of bounds: size is " + size);
if (index < 0)
throw new IndexOutOfBoundsException("Index " + index + " is out of bounds: index cannot be negative");
if (index >= TILES_PER_FACE)
throw new TileStackIsFullException(
"Index " + index + " is out of bounds: maximum tile stack size is " + TILES_PER_FACE
);
}
private void report(TileData previous, TileData current) {
DefaultChunkData.this.getListeners().forEach(l -> {
if (previous != null) {
l.onChunkTilesChanged(DefaultChunkData.this, blockInChunk, face, previous, false);
}
if (current != null) {
l.onChunkTilesChanged(DefaultChunkData.this, blockInChunk, face, current, true);
}
l.onChunkChanged(DefaultChunkData.this);
});
}
private boolean checkConsistency() {
int index;
for (index = 0; index < size(); ++index) {
if (get(index) == null)
throw new AssertionError("get(index) is null");
if (references[index] != null) {
TileDataReference ref = getReference(index);
if (ref == null)
throw new AssertionError("references[index] is not null but getReference(index) is");
if (!ref.isValid())
throw new AssertionError("Reference is not valid");
if (ref.get() != get(index))
throw new AssertionError("Reference points to " + (ref.get() == null ? "null" : "wrong tile"));
if (ref.getIndex() != index)
throw new AssertionError("Reference has invalid index");
if (ref.getStack() != this)
throw new AssertionError("Reference has invalid TDS");
}
if (index != indicesByTag[tagsByIndex[index]])
throw new AssertionError("Tag mapping is inconsistent");
if (index != getIndexByTag(getTagByIndex(index)))
throw new AssertionError("Tag methods are inconsistent with tag mapping");
}
for (; index < tiles.length; ++index) {
if (tiles[index] != null)
throw new AssertionError("Leftover tile detected");
if (references[index] != null)
throw new AssertionError("Leftover reference detected");
if (tagsByIndex[index] != -1)
throw new AssertionError("Leftover tags detected");
}
return true;
}
}
}

View File

@ -0,0 +1,262 @@
/*
* Progressia
* Copyright (C) 2020-2021 Wind Corporation and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package ru.windcorp.progressia.common.world;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Objects;
import java.util.function.Consumer;
import glm.vec._3.i.Vec3i;
import gnu.trove.TCollections;
import gnu.trove.map.TLongObjectMap;
import gnu.trove.map.hash.TLongObjectHashMap;
import gnu.trove.set.TLongSet;
import ru.windcorp.progressia.common.collision.CollisionModel;
import ru.windcorp.progressia.common.state.StateChange;
import ru.windcorp.progressia.common.state.StatefulObject;
import ru.windcorp.progressia.common.world.block.BlockData;
import ru.windcorp.progressia.common.world.entity.EntityData;
import ru.windcorp.progressia.common.world.generic.ChunkMap;
import ru.windcorp.progressia.common.world.generic.ChunkSet;
import ru.windcorp.progressia.common.world.generic.EntityGeneric;
import ru.windcorp.progressia.common.world.rels.BlockFace;
import ru.windcorp.progressia.common.world.generic.LongBasedChunkMap;
public class DefaultWorldData implements WorldData {
private final ChunkMap<DefaultChunkData> chunksByPos = new LongBasedChunkMap<>(
TCollections.synchronizedMap(new TLongObjectHashMap<>())
);
private final Collection<DefaultChunkData> chunks = Collections.unmodifiableCollection(chunksByPos.values());
private final TLongObjectMap<EntityData> entitiesById = TCollections.synchronizedMap(new TLongObjectHashMap<>());
private final Collection<EntityData> entities = Collections.unmodifiableCollection(entitiesById.valueCollection());
private GravityModel gravityModel = null;
private float time = 0;
private final Collection<WorldDataListener> listeners = Collections.synchronizedCollection(new ArrayList<>());
public DefaultWorldData() {
}
@Override
public DefaultChunkData getChunk(Vec3i pos) {
return chunksByPos.get(pos);
}
@Override
public DefaultChunkData getChunkByBlock(Vec3i blockInWorld) {
return (DefaultChunkData) WorldData.super.getChunkByBlock(blockInWorld);
}
@Override
public Collection<DefaultChunkData> getChunks() {
return chunks;
}
public ChunkSet getLoadedChunks() {
return chunksByPos.keys();
}
@Override
public Collection<EntityData> getEntities() {
return entities;
}
@Override
public void forEachEntity(Consumer<? super EntityData> action) {
synchronized (entitiesById) { // TODO HORRIBLY MUTILATE THE CORPSE OF
// TROVE4J so that
// gnu.trove.impl.sync.SynchronizedCollection.forEach
// is synchronized
getEntities().forEach(action);
}
}
public TLongSet getLoadedEntities() {
return entitiesById.keySet();
}
private void addChunkListeners(DefaultChunkData chunk) {
getListeners().forEach(l -> l.getChunkListeners(this, chunk.getPosition(), chunk::addListener));
}
public synchronized void addChunk(DefaultChunkData chunk) {
addChunkListeners(chunk);
DefaultChunkData previous = chunksByPos.get(chunk);
if (previous != null) {
throw new IllegalArgumentException(
String.format(
"Chunk at (%d; %d; %d) already exists",
chunk.getPosition().x,
chunk.getPosition().y,
chunk.getPosition().z
)
);
}
chunksByPos.put(chunk, chunk);
chunk.onLoaded();
getListeners().forEach(l -> l.onChunkLoaded(this, chunk));
}
public synchronized void removeChunk(DefaultChunkData chunk) {
getListeners().forEach(l -> l.beforeChunkUnloaded(this, chunk));
chunk.beforeUnloaded();
chunksByPos.remove(chunk);
}
@Override
public void setBlock(Vec3i blockInWorld, BlockData block, boolean notify) {
DefaultChunkData chunk = getChunkByBlock(blockInWorld);
if (chunk == null)
throw new IllegalCoordinatesException(
"Coordinates "
+ "(" + blockInWorld.x + "; " + blockInWorld.y + "; " + blockInWorld.z + ") "
+ "do not belong to a loaded chunk"
);
chunk.setBlock(Coordinates.convertInWorldToInChunk(blockInWorld, null), block, notify);
}
@Override
public TileDataStack getTiles(Vec3i blockInWorld, BlockFace face) {
return WorldData.super.getTiles(blockInWorld, face);
}
@Override
public EntityData getEntity(long entityId) {
return entitiesById.get(entityId);
}
@Override
public void addEntity(EntityData entity) {
Objects.requireNonNull(entity, "entity");
EntityData previous = entitiesById.putIfAbsent(entity.getEntityId(), entity);
if (previous != null) {
String message = "Cannot add entity " + entity + ": ";
if (previous == entity) {
message += "already present";
} else {
message += "entity with the same EntityID already present (" + previous + ")";
}
throw new IllegalStateException(message);
}
getListeners().forEach(l -> l.onEntityAdded(this, entity));
}
@Override
public void removeEntity(long entityId) {
synchronized (entitiesById) {
EntityData entity = entitiesById.get(entityId);
if (entity == null) {
throw new IllegalArgumentException(
"Entity with EntityID " + EntityData.formatEntityId(entityId) + " not present"
);
} else {
removeEntity(entity);
}
}
}
@Override
public void removeEntity(EntityData entity) {
Objects.requireNonNull(entity, "entity");
getListeners().forEach(l -> l.beforeEntityRemoved(this, entity));
entitiesById.remove(entity.getEntityId());
}
@Override
public <SE extends StatefulObject & EntityGeneric> void changeEntity(SE entity, StateChange<SE> change) {
change.change(entity);
}
@Override
public float getTime() {
return time;
}
@Override
public void advanceTime(float change) {
this.time += change;
}
public CollisionModel getCollisionModelOfBlock(Vec3i blockInWorld) {
DefaultChunkData chunk = getChunkByBlock(blockInWorld);
if (chunk == null)
return null;
BlockData block = chunk.getBlock(Coordinates.convertInWorldToInChunk(blockInWorld, null));
if (block == null)
return null;
return block.getCollisionModel();
}
/**
* @return the gravity model
*/
@Override
public GravityModel getGravityModel() {
return gravityModel;
}
/**
* @param gravityModel the gravity model to set
*/
public void setGravityModel(GravityModel gravityModel) {
if (!chunks.isEmpty()) {
throw new IllegalStateException(
"Attempted to change gravity model to " + gravityModel + " while " + chunks.size()
+ " chunks were loaded"
);
}
this.gravityModel = gravityModel;
}
public Collection<WorldDataListener> getListeners() {
return listeners;
}
public void addListener(WorldDataListener e) {
listeners.add(e);
}
public void removeListener(WorldDataListener o) {
listeners.remove(o);
}
}

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -1,245 +1,52 @@
/*
* Progressia
* Copyright (C) 2020-2021 Wind Corporation and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package ru.windcorp.progressia.common.world;
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.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.GenericWritableWorld;
import ru.windcorp.progressia.common.world.generic.LongBasedChunkMap;
import ru.windcorp.progressia.common.world.generic.WorldGenericWO;
import ru.windcorp.progressia.common.world.rels.BlockFace;
import ru.windcorp.progressia.common.world.tile.TileData;
import ru.windcorp.progressia.common.world.tile.TileDataStack;
import ru.windcorp.progressia.common.world.tile.TileDataReference;
public class WorldData
implements GenericWritableWorld<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() {
}
public interface WorldData
extends WorldDataRO, WorldGenericWO<BlockData, TileData, TileDataStack, TileDataReference, ChunkData, EntityData> {
@Override
public ChunkData getChunk(Vec3i pos) {
return chunksByPos.get(pos);
}
@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();
default TileDataStack getTiles(Vec3i blockInWorld, BlockFace face) {
return (TileDataStack) WorldDataRO.super.getTiles(blockInWorld, face);
}
/**
* @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() {
return gravityModel;
}
/**
* @param gravityModel the gravity model to set
void advanceTime(float change);
/*
* Method specialization
*/
public void setGravityModel(GravityModel gravityModel) {
if (!chunks.isEmpty()) {
throw new IllegalStateException(
"Attempted to change gravity model to " + gravityModel + " while " + chunks.size()
+ " chunks were loaded"
);
}
this.gravityModel = gravityModel;
@Override
ChunkData getChunk(Vec3i pos);
@Override
Collection<? extends ChunkData> getChunks();
// TODO: rename WGRO.forEachChunk -> forEachChunkRO and define WGWO.forEachChunk
@Override
default ChunkData getChunkByBlock(Vec3i blockInWorld) {
return (ChunkData) WorldDataRO.super.getChunkByBlock(blockInWorld);
}
public Collection<WorldDataListener> getListeners() {
return listeners;
}
public void addListener(WorldDataListener e) {
listeners.add(e);
}
public void removeListener(WorldDataListener o) {
listeners.remove(o);
@Override
default TileDataStack getTilesOrNull(Vec3i blockInWorld, BlockFace face) {
return (TileDataStack) WorldDataRO.super.getTilesOrNull(blockInWorld, face);
}
}

View File

@ -26,11 +26,11 @@ import ru.windcorp.progressia.common.world.entity.EntityData;
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
* {@link ChunkDataListener}s to a new chunk. When listeners are added with
* this method,
* their {@link ChunkDataListener#onChunkLoaded(ChunkData) onChunkLoaded}
* their {@link ChunkDataListener#onChunkLoaded(DefaultChunkData) onChunkLoaded}
* methods will be invoked.
*
* @param world the world instance
@ -41,7 +41,7 @@ public interface WorldDataListener {
* {@link Consumer#accept(Object) accept} method
* 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 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 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 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 entity the entity that is going to be removed
*/
default void beforeEntityRemoved(WorldData world, EntityData entity) {
default void beforeEntityRemoved(DefaultWorldData world, EntityData entity) {
}
}

View File

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

View File

@ -21,9 +21,9 @@ package ru.windcorp.progressia.common.world.block;
import ru.windcorp.progressia.common.collision.AABB;
import ru.windcorp.progressia.common.collision.CollisionModel;
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) {
super(id);

View File

@ -24,7 +24,7 @@ import java.io.IOException;
import glm.vec._3.i.Vec3i;
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 {
@ -60,7 +60,7 @@ public class PacketSetBlock extends PacketAffectBlock {
}
@Override
public void apply(WorldData world) {
public void apply(DefaultWorldData world) {
BlockData block = BlockDataRegistry.getInstance().get(getBlockId());
world.setBlock(getBlockInWorld(), block, true);
}

View File

@ -32,10 +32,10 @@ import ru.windcorp.progressia.common.collision.CollisionModel;
import ru.windcorp.progressia.common.state.IOContext;
import ru.windcorp.progressia.common.state.StatefulObject;
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;
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 velocity = new Vec3();

View File

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

View File

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

View File

@ -23,7 +23,7 @@ import java.io.DataOutput;
import java.io.IOException;
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 {
@ -51,7 +51,7 @@ public class PacketRevokeEntity extends PacketAffectEntity {
}
@Override
public void apply(WorldData world) {
public void apply(DefaultWorldData world) {
world.removeEntity(getEntityId());
}

View File

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

View File

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

View File

@ -32,37 +32,37 @@ import ru.windcorp.progressia.common.world.rels.BlockFace;
/**
* An unmodifiable chunk representation. Per default, it is usually one of
* {@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.server.world.ChunkLogic ChunkLogic}, but this
* interface may be implemented differently for various reasons.
* <p>
* A generic chunk contains {@linkplain GenericBlock blocks} and
* {@linkplain GenericTileStack tile stacks} and is characterized by its
* A generic chunk contains {@linkplain BlockGeneric blocks} and
* {@linkplain TileGenericStackRO tile stacks} and is characterized by its
* 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.
* <p>
* This interface defines the most common methods for examining a chunk and
* implements many of them as default methods. It also contains several static
* 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.
*
* @param <Self> a reference to itself (required to properly reference a
* {@link GenericTileStack})
* {@link TileGenericStackRO})
* @param <B> block type
* @param <T> tile type
* @param <TS> tile stack type
* @author javapony
*/
// @formatter:off
public interface GenericChunk<
B extends GenericBlock,
T extends GenericTile,
TS extends GenericTileStack <B, T, TS, TR, C>,
TR extends GenericTileReference <B, T, TS, TR, C>,
C extends GenericChunk <B, T, TS, TR, C>
public interface ChunkGenericRO<
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

View File

@ -0,0 +1,37 @@
/*
* Progressia
* Copyright (C) 2020-2021 Wind Corporation and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package ru.windcorp.progressia.common.world.generic;
import glm.vec._3.i.Vec3i;
import ru.windcorp.progressia.common.world.rels.BlockFace;
// @formatter:off
public interface ChunkGenericWO<
B extends BlockGeneric,
T extends TileGeneric,
TS extends TileGenericStackWO <B, T, TS, TR, C>,
TR extends TileGenericReferenceWO <B, T, TS, TR, C>,
C extends ChunkGenericWO <B, T, TS, TR, C>
> {
// @formatter:on
void setBlock(Vec3i posInChunk, B block, boolean notify);
TS getTiles(Vec3i blockInChunk, BlockFace face);
}

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -34,7 +34,7 @@ public class GenericChunks {
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.mul(2).sub(offset);
@ -51,7 +51,7 @@ public class GenericChunks {
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.mul(2).sub(offset);
@ -73,7 +73,7 @@ public class GenericChunks {
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();
v = Coordinates.getInWorld(chunk.getPosition(), Vectors.ZERO_3i, v);
@ -87,9 +87,9 @@ public class GenericChunks {
}
public static boolean containsBiC(Vec3i blockInChunk) {
return blockInChunk.x >= 0 && blockInChunk.x < GenericChunk.BLOCKS_PER_CHUNK &&
blockInChunk.y >= 0 && blockInChunk.y < GenericChunk.BLOCKS_PER_CHUNK &&
blockInChunk.z >= 0 && blockInChunk.z < GenericChunk.BLOCKS_PER_CHUNK;
return blockInChunk.x >= 0 && blockInChunk.x < ChunkGenericRO.BLOCKS_PER_CHUNK &&
blockInChunk.y >= 0 && blockInChunk.y < ChunkGenericRO.BLOCKS_PER_CHUNK &&
blockInChunk.z >= 0 && blockInChunk.z < ChunkGenericRO.BLOCKS_PER_CHUNK;
}
public static boolean isSurfaceBiC(Vec3i blockInChunk) {
@ -109,9 +109,9 @@ public class GenericChunks {
0,
0,
0,
GenericChunk.BLOCKS_PER_CHUNK,
GenericChunk.BLOCKS_PER_CHUNK,
GenericChunk.BLOCKS_PER_CHUNK,
ChunkGenericRO.BLOCKS_PER_CHUNK,
ChunkGenericRO.BLOCKS_PER_CHUNK,
ChunkGenericRO.BLOCKS_PER_CHUNK,
action
);
}

View File

@ -1,43 +0,0 @@
/*
* Progressia
* Copyright (C) 2020-2021 Wind Corporation and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package ru.windcorp.progressia.common.world.generic;
import glm.vec._3.i.Vec3i;
import ru.windcorp.progressia.common.util.Vectors;
// @formatter:off
public interface GenericWritableChunk<
B extends GenericBlock,
T extends GenericTile,
TS extends GenericWritableTileStack <B, T, TS, TR, C>,
TR extends GenericTileReference <B, T, TS, TR, C>,
C extends GenericWritableChunk <B, T, TS, TR, C>
>
extends GenericChunk<B, T, TS, TR, C> {
// @formatter:on
void setBlock(Vec3i posInChunk, B block, boolean notify);
default void setBlockRel(Vec3i relativeBlockInChunk, B block, boolean notify) {
Vec3i absoluteBlockInChunk = Vectors.grab3i();
resolve(relativeBlockInChunk, absoluteBlockInChunk);
setBlock(absoluteBlockInChunk, block, notify);
Vectors.release(absoluteBlockInChunk);
}
}

View File

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

View File

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

View File

@ -0,0 +1,50 @@
/*
* Progressia
* Copyright (C) 2020-2021 Wind Corporation and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package ru.windcorp.progressia.common.world.generic;
// @formatter:off
public interface TileGenericReferenceRO<
B extends BlockGeneric,
T extends TileGeneric,
TS extends TileGenericStackRO <B, T, TS, TR, C>,
TR extends TileGenericReferenceRO <B, T, TS, TR, C>,
C extends ChunkGenericRO <B, T, TS, TR, C>
> {
// @formatter:on
T get();
int getIndex();
TS getStack();
default boolean isValid() {
return get() != null;
}
default int getTag() {
TS tileStack = getStack();
if (tileStack == null) {
return -1;
} else {
return tileStack.getTagByIndex(getIndex());
}
}
}

View File

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

View File

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

View File

@ -18,15 +18,18 @@
package ru.windcorp.progressia.common.world.generic;
import java.util.List;
import java.util.RandomAccess;
// @formatter:off
public abstract class GenericWritableTileStack<
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>
public interface TileGenericStackWO<
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>
>
extends GenericTileStack<B, T, TS, TR, C> {
extends List<T>, RandomAccess {
// @formatter:on
/**
@ -45,7 +48,7 @@ public abstract class GenericWritableTileStack<
* make sure to override it in subclass
*/
@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
@ -59,7 +62,7 @@ public abstract class GenericWritableTileStack<
* with the
* 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
@ -74,7 +77,7 @@ public abstract class GenericWritableTileStack<
* make sure to override it in subclass
*/
@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
@ -91,19 +94,21 @@ public abstract class GenericWritableTileStack<
* make sure to override it in subclass
*/
@Override
public abstract T remove(int index);
T remove(int index);
/*
* Aliases and overloads
*/
public void addClosest(T tile) {
default void addClosest(T tile) {
add(0, tile);
}
public void addFarthest(T tile) {
default void addFarthest(T tile) {
add(size(), tile);
}
boolean isFull();
/**
* 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
* @return {@code true} iff this stack has changed
*/
public boolean offer(int index, T tile) {
default boolean offer(int index, T tile) {
if (isFull())
return false;
add(index, tile);
return true;
}
public boolean offerClosest(T tile) {
default boolean offerClosest(T tile) {
return offer(0, tile);
}
public boolean offerFarthest(T tile) {
default boolean offerFarthest(T tile) {
return offer(size(), tile);
}
public T removeClosest() {
default T removeClosest() {
return remove(0);
}
public T removeFarthest() {
default T removeFarthest() {
return remove(size() - 1);
}
public T poll(int index) {
default T poll(int index) {
if (size() <= index)
return null;
return remove(index);
}
public T pollClosest() {
default T pollClosest() {
return poll(0);
}
public T pollFarthest() {
default T pollFarthest() {
return poll(size() - 1);
}
@Override
public boolean add(T tile) {
default boolean add(T tile) {
addFarthest(tile);
return true;
}

View File

@ -30,17 +30,17 @@ import ru.windcorp.progressia.common.world.rels.AbsFace;
import ru.windcorp.progressia.common.world.rels.BlockFace;
// @formatter:off
public interface GenericWorld<
B extends GenericBlock,
T extends GenericTile,
TS extends GenericTileStack <B, T, TS, TR, C>,
TR extends GenericTileReference <B, T, TS, TR, C>,
C extends GenericChunk <B, T, TS, TR, C>,
E extends GenericEntity
public interface WorldGenericRO<
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>,
E extends EntityGeneric
> {
// @formatter:on
Collection<C> getChunks();
Collection<? extends C> getChunks();
C getChunk(Vec3i pos);
@ -131,6 +131,15 @@ public interface GenericWorld<
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) {
return getChunk(chunkPos) != null;
}

View File

@ -18,21 +18,24 @@
package ru.windcorp.progressia.common.world.generic;
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
public interface GenericWritableWorld<
B extends GenericBlock,
T extends GenericTile,
TS extends GenericWritableTileStack <B, T, TS, TR, C>,
TR extends GenericTileReference <B, T, TS, TR, C>,
C extends GenericWritableChunk <B, T, TS, TR, C>,
E extends GenericEntity
>
extends GenericWorld<B, T, TS, TR, C, E> {
public interface WorldGenericWO<
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>,
E extends EntityGeneric
> {
//@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);
@ -42,4 +45,13 @@ public interface GenericWritableWorld<
removeEntity(entity.getEntityId());
}
/**
* Requests that the specified change is applied to the given entity. The
* {@code change} object provided may be stored until the change is applied.
*
* @param entity the entity to change
* @param change the change to apply
*/
<SE extends StatefulObject & EntityGeneric> void changeEntity(SE entity, StateChange<SE> change);
}

View File

@ -18,13 +18,7 @@
package ru.windcorp.progressia.common.world.generic.context;
import ru.windcorp.progressia.common.world.context.Context;
import ru.windcorp.progressia.common.world.generic.GenericBlock;
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;
import ru.windcorp.progressia.common.world.generic.*;
/**
* 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.
*/
//@formatter:off
public interface GenericROBlockFaceContext<
B extends GenericBlock,
T extends GenericTile,
TS extends GenericROTileStack <B, T, TS, TR, C>,
TR extends GenericROTileReference <B, T, TS, TR, C>,
C extends GenericROChunk <B, T, TS, TR, C>,
E extends GenericEntity
> extends GenericROBlockContext<B, T, TS, TR, C, E> {
public interface BlockFaceGenericContextRO<
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>,
E extends EntityGeneric
> extends WorldContexts.BlockFace, BlockGenericContextRO<B, T, TS, TR, C, E> {
//@formatter:on
/**
* Returns the face relevant to this context.
*
* @return the block face
*/
RelFace getFace();
/**
* Gets the tile stack at the relevant position.
*

View File

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

View File

@ -17,14 +17,8 @@
*/
package ru.windcorp.progressia.common.world.generic.context;
import glm.vec._3.i.Vec3i;
import ru.windcorp.progressia.common.world.context.Context;
import ru.windcorp.progressia.common.world.generic.GenericBlock;
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.*;
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.
*/
//@formatter:off
public interface GenericROBlockContext<
B extends GenericBlock,
T extends GenericTile,
TS extends GenericROTileStack <B, T, TS, TR, C>,
TR extends GenericROTileReference <B, T, TS, TR, C>,
C extends GenericROChunk <B, T, TS, TR, C>,
E extends GenericEntity
> extends GenericROWorldContext<B, T, TS, TR, C, E> {
public interface BlockGenericContextRO<
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>,
E extends EntityGeneric
> extends WorldContexts.Block, WorldGenericContextRO<B, T, TS, TR, C, E> {
//@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
* loaded.

View File

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

View File

@ -18,12 +18,7 @@
package ru.windcorp.progressia.common.world.generic.context;
import ru.windcorp.progressia.common.world.context.Context;
import ru.windcorp.progressia.common.world.generic.GenericBlock;
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.*;
/**
* 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.
*/
//@formatter:off
public interface GenericROTileContext<
B extends GenericBlock,
T extends GenericTile,
TS extends GenericROTileStack <B, T, TS, TR, C>,
TR extends GenericROTileReference <B, T, TS, TR, C>,
C extends GenericROChunk <B, T, TS, TR, C>,
E extends GenericEntity
> extends GenericROBlockFaceContext<B, T, TS, TR, C, E> {
public interface TileGenericContextRO<
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>,
E extends EntityGeneric
> extends WorldContexts.Tile, BlockFaceGenericContextRO<B, T, TS, TR, C, E> {
//@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.
*
@ -67,12 +55,7 @@ public interface GenericROTileContext<
return getTile(getLocation(), getFace(), 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
*/
@Override
default int getTag() {
TS tileStack = getTilesOrNull();
if (tileStack == null) {
@ -82,4 +65,23 @@ public interface GenericROTileContext<
return tileStack.getTagByIndex(getLayer());
}
/**
* Gets the {@link TileGenericReferenceRO TileReference} to the relevant
* tile.
*
* @return the reference to the tile relevant to this context or
* {@code null} if the location is not loaded or the tile does not
* exist
*
* @see TileGenericStackRO#getReference(int)
*/
default TR getTileReference() {
TS tileStack = getTilesOrNull();
if (tileStack == null) {
return null;
}
return tileStack.getReference(getLayer());
}
}

View File

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

View File

@ -0,0 +1,127 @@
/*
* Progressia
* Copyright (C) 2020-2021 Wind Corporation and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package ru.windcorp.progressia.common.world.generic.context;
import glm.vec._3.i.Vec3i;
import ru.windcorp.progressia.common.world.context.Context;
import ru.windcorp.progressia.common.world.rels.RelFace;
/**
* This class defines several {@link Context} subinterfaces that are further
* extended by Generic contexts. These interfaces declare methods for
* determining which location is "relevant" to the context. Since they are not
* Java generics they can safely be extended more than once.
* <p>
* Do not reuse these interfaces outside the Generic contexts' package; consider
* them to be an implementation detail.
*
* @author javapony
*
*/
class WorldContexts {
/**
* A {@link Context} with a world instance. This interface should not be
* implemented directly; see {@link WorldGenericContextRO} or
* {@link WorldGenericContextWO}.
*
* @author javapony
*
*/
public static interface World extends Context {
// currently empty
}
/**
* A {@link Context} with a world instance and a block location. This interface
* should not be implemented directly; see {@link BlockGenericContextRO} or
* {@link BlockGenericContextWO}.
*
* @author javapony
*
*/
public static interface Block extends World {
/**
* Returns the location of the block.
* <p>
* The coordinate system in use is not specified, but it is consistent across
* all methods of this context.
* <p>
* The object returned by this method must not be modified. It is only valid
* while the context is {@linkplain valid}.
*
* @return a vector describing the block's position
*/
Vec3i getLocation();
}
/**
* A {@link Context} with a world instance, a block location and a block face
* (block side). This interface should not be implemented directly; see
* {@link BlockFaceGenericContextRO} or {@link BlockFaceGenericContextWO}.
*
* @author javapony
*
*/
public static interface BlockFace extends Block {
/**
* Returns the face relevant to this context.
*
* @return the block face
*/
RelFace getFace();
}
/**
* A {@link Context} with a world instance, a block location, a block face
* (block side) and a tile layer. This interface should not be implemented
* directly; see {@link TileGenericContextRO} or {@link TileGenericContextWO}.
*
* @author javapony
*
*/
public static interface Tile extends BlockFace {
/**
* Returns the tile layer relevant to this context.
*
* @return the tile layer
*/
int getLayer();
/**
* Gets the tag of the tile at the relevant position.
*
* @return the tag of the tile or {@code -1} if the location is not loaded
* or the tile does not exist
*/
int getTag();
}
WorldContexts() {
}
}

View File

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

View File

@ -30,14 +30,14 @@ import ru.windcorp.progressia.common.world.rels.BlockFace;
* may not be immediate, see {@link #isImmediate()}.
*/
// @formatter:off
public interface GenericRWWorldContext<
B extends GenericBlock,
T extends GenericTile,
TS extends GenericRWTileStack <B, T, TS, TR, C>,
TR extends GenericROTileReference <B, T, TS, TR, C>,
C extends GenericRWChunk <B, T, TS, TR, C>,
E extends GenericEntity
> extends GenericROWorldContext<B, T, TS, TR, C, E>, GenericRWWorld<B, T, TS, TR, C, E> {
public interface WorldGenericContextWO<
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>,
E extends EntityGeneric
> extends WorldContexts.World, WorldGenericWO<B, T, TS, TR, C, E> {
// @formatter:on
/**
@ -92,17 +92,20 @@ public interface GenericRWWorldContext<
void removeTile(Vec3i location, BlockFace face, int 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.
* Requests that the referenced tile is removed from its tile stack. If the
* tile could not be found at the time of application this method fails
* 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
*/
default void removeTile(Vec3i location, BlockFace face, TR tileReference) {
removeTile(location, face, tileReference.getTag());
default void removeTile(TileGenericReferenceRO<?, ?, ?, ?, ?> tileReference) {
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
* @see #isImmediate()
* @see #removeEntity(GenericEntity)
* @see #removeEntity(EntityGeneric)
*/
@Override
void removeEntity(long entityId);
@ -140,12 +143,13 @@ public interface GenericRWWorldContext<
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 change the change to apply
*/
@Override
<SE extends StatefulObject & GenericEntity> void changeEntity(SE entity, StateChange<SE> change);
<SE extends StatefulObject & EntityGeneric> void changeEntity(SE entity, StateChange<SE> change);
}

View File

@ -25,9 +25,9 @@ import java.io.IOException;
import glm.vec._3.i.Vec3i;
import ru.windcorp.progressia.common.state.IOContext;
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.WorldData;
import ru.windcorp.progressia.common.world.DefaultWorldData;
public abstract class ChunkCodec extends Namespaced {
@ -46,12 +46,12 @@ public abstract class ChunkCodec extends Namespaced {
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,
IOException;
public abstract boolean shouldEncode(ChunkData chunk, IOContext context);
public abstract boolean shouldEncode(DefaultChunkData chunk, IOContext context);
public abstract void encode(ChunkData chunk, DataOutputStream output, IOContext context) throws IOException;
public abstract void encode(DefaultChunkData chunk, DataOutputStream output, IOContext context) throws IOException;
}

View File

@ -31,16 +31,16 @@ import gnu.trove.map.TByteObjectMap;
import gnu.trove.map.hash.TByteObjectHashMap;
import ru.windcorp.progressia.common.state.IOContext;
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.WorldData;
import ru.windcorp.progressia.common.world.DefaultWorldData;
public class ChunkIO {
private static final TByteObjectMap<ChunkCodec> CODECS_BY_ID = new TByteObjectHashMap<>();
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,
IOException {
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 {
ChunkCodec codec = getCodec(chunk, context);
@ -100,7 +100,7 @@ public class ChunkIO {
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) {
if (codec.shouldEncode(chunk, context)) {
return codec;

View File

@ -24,7 +24,7 @@ import java.io.IOException;
import glm.vec._3.i.Vec3i;
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;
public class PacketAddTile extends PacketAffectTile {
@ -61,7 +61,7 @@ public class PacketAddTile extends PacketAffectTile {
}
@Override
public void apply(WorldData world) {
public void apply(DefaultWorldData world) {
TileData tile = TileDataRegistry.getInstance().get(getTileId());
world.getTiles(getBlockInWorld(), getFace()).add(tile);
}

View File

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

View File

@ -19,9 +19,9 @@
package ru.windcorp.progressia.common.world.tile;
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) {
super(id);

View File

@ -1,28 +0,0 @@
/*
* Progressia
* Copyright (C) 2020-2021 Wind Corporation and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package ru.windcorp.progressia.common.world.tile;
import ru.windcorp.progressia.common.world.ChunkData;
import ru.windcorp.progressia.common.world.block.BlockData;
import ru.windcorp.progressia.common.world.generic.GenericWritableTileStack;
public abstract class TileDataStack
extends GenericWritableTileStack<BlockData, TileData, TileDataStack, TileDataReference, ChunkData> {
}

View File

@ -22,7 +22,7 @@ import java.util.function.Consumer;
import glm.vec._3.i.Vec3i;
import 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.PlayerData;
import ru.windcorp.progressia.common.world.entity.EntityData;
@ -55,7 +55,7 @@ public class Player extends PlayerData implements ChunkLoader {
Coordinates.convertInWorldToChunk(start, start);
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;
int iRadius = (int) Math.ceil(radius);

View File

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

View File

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

View File

@ -18,10 +18,10 @@
package ru.windcorp.progressia.server.management.load;
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.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.Server;
import ru.windcorp.progressia.test.TestWorldDiskIO;
@ -113,9 +113,9 @@ public class ChunkManager {
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) {
world.addChunk(chunk);
return LoadResult.LOADED_FROM_DISK;
@ -133,8 +133,8 @@ public class ChunkManager {
* this method
*/
public boolean unloadChunk(Vec3i chunkPos) {
WorldData world = getServer().getWorld().getData();
ChunkData chunk = world.getChunk(chunkPos);
DefaultWorldData world = getServer().getWorld().getData();
DefaultChunkData chunk = world.getChunk(chunkPos);
if (chunk == null) {
return false;
@ -147,7 +147,7 @@ public class ChunkManager {
}
public void sendChunk(Player player, Vec3i chunkPos) {
ChunkData chunk = getServer().getWorld().getData().getChunk(chunkPos);
DefaultChunkData chunk = getServer().getWorld().getData().getChunk(chunkPos);
if (chunk == null) {
throw new IllegalStateException(
@ -180,7 +180,7 @@ public class ChunkManager {
/**
* 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
* @return {@code true} iff the chunk is loaded

View File

@ -26,14 +26,14 @@ import java.util.WeakHashMap;
import java.util.function.BiConsumer;
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.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.BlockFace;
import ru.windcorp.progressia.common.world.rels.RelFace;
import ru.windcorp.progressia.common.world.tile.TileDataStack;
import ru.windcorp.progressia.common.world.tile.TileDataReference;
import ru.windcorp.progressia.common.world.TileDataStack;
import ru.windcorp.progressia.common.world.TileDataReference;
import ru.windcorp.progressia.server.world.block.BlockLogic;
import ru.windcorp.progressia.server.world.block.BlockLogicRegistry;
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.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 ChunkData data;
private final DefaultChunkData data;
private final Collection<Vec3i> tickingBlocks = 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
.synchronizedMap(new WeakHashMap<>());
public ChunkLogic(WorldLogic world, ChunkData data) {
public ChunkLogic(WorldLogic world, DefaultChunkData data) {
this.world = world;
this.data = data;
@ -103,7 +103,7 @@ public class ChunkLogic implements GenericChunk<BlockLogic, TileLogic, TileLogic
return world;
}
public ChunkData getData() {
public DefaultChunkData getData() {
return data;
}

View File

@ -21,7 +21,7 @@ package ru.windcorp.progressia.server.world;
import java.util.function.Consumer;
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.rels.AbsFace;
import ru.windcorp.progressia.server.world.block.BlockTickContext;
@ -34,7 +34,7 @@ public interface ChunkTickContext extends TickContext {
return getWorld().getChunk(getChunk());
}
default ChunkData getChunkData() {
default DefaultChunkData getChunkData() {
ChunkLogic chunkLogic = getChunkLogic();
return chunkLogic == null ? null : chunkLogic.getData();
}

View File

@ -20,7 +20,7 @@ package ru.windcorp.progressia.server.world;
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.world.tasks.WorldAccessor;
@ -42,7 +42,7 @@ public interface TickContext {
return getServer().getAdHocRandom();
}
default WorldData getWorldData() {
default DefaultWorldData getWorldData() {
return getWorld().getData();
}

View File

@ -23,13 +23,13 @@ import java.util.function.Consumer;
import java.util.function.Function;
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.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.RelFace;
import ru.windcorp.progressia.common.world.tile.TileDataStack;
import ru.windcorp.progressia.common.world.tile.TileDataReference;
import ru.windcorp.progressia.common.world.TileDataStack;
import ru.windcorp.progressia.common.world.TileDataReference;
import ru.windcorp.progressia.server.Server;
import ru.windcorp.progressia.server.world.block.BlockTickContext;
import ru.windcorp.progressia.server.world.tile.TSTickContext;
@ -109,9 +109,9 @@ public abstract class TickContextMutable implements BlockTickContext, TSTickCont
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");
return withChunk(chunk.getPosition());
}
@ -259,7 +259,7 @@ public abstract class TickContextMutable implements BlockTickContext, TSTickCont
}
@Override
public TileStack withTS(GenericTileStack<?, ?, ?, ?, ?> tileStack) {
public TileStack withTS(TileGenericStackRO<?, ?, ?, ?, ?> tileStack) {
Objects.requireNonNull(tileStack, "tileStack");
return withBlock(
@ -324,7 +324,7 @@ public abstract class TickContextMutable implements BlockTickContext, TSTickCont
final int minX = Coordinates.getInWorld(chunk.x, 0);
final int minY = Coordinates.getInWorld(chunk.y, 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.y = minY; v.y < minY + size; ++v.y) {

View File

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

View File

@ -25,12 +25,12 @@ import java.util.Map;
import glm.Glm;
import glm.vec._3.i.Vec3i;
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.WorldData;
import ru.windcorp.progressia.common.world.DefaultWorldData;
import ru.windcorp.progressia.common.world.WorldDataListener;
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.world.block.BlockLogic;
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;
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
> {
private final WorldData data;
private final DefaultWorldData data;
private final Server server;
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();
public WorldLogic(WorldData data, Server server, WorldGenerator generator) {
public WorldLogic(DefaultWorldData data, Server server, WorldGenerator generator) {
this.data = data;
this.server = server;
@ -63,12 +63,12 @@ public class WorldLogic
data.addListener(new WorldDataListener() {
@Override
public void onChunkLoaded(WorldData world, ChunkData chunk) {
public void onChunkLoaded(DefaultWorldData world, DefaultChunkData chunk) {
chunks.put(chunk, new ChunkLogic(WorldLogic.this, chunk));
}
@Override
public void beforeChunkUnloaded(WorldData world, ChunkData chunk) {
public void beforeChunkUnloaded(DefaultWorldData world, DefaultChunkData chunk) {
chunks.remove(chunk);
}
});
@ -104,7 +104,7 @@ public class WorldLogic
return server;
}
public WorldData getData() {
public DefaultWorldData getData() {
return data;
}
@ -112,8 +112,8 @@ public class WorldLogic
return generator;
}
public ChunkData generate(Vec3i chunkPos) {
ChunkData chunk = getGenerator().generate(chunkPos);
public DefaultChunkData generate(Vec3i chunkPos) {
DefaultChunkData chunk = getGenerator().generate(chunkPos);
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)",
@ -147,7 +147,7 @@ public class WorldLogic
return chunk;
}
public ChunkLogic getChunk(ChunkData chunkData) {
public ChunkLogic getChunk(DefaultChunkData chunkData) {
return chunks.get(chunkData);
}

View File

@ -19,10 +19,10 @@
package ru.windcorp.progressia.server.world.block;
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;
public class BlockLogic extends Namespaced implements GenericBlock {
public class BlockLogic extends Namespaced implements BlockGeneric {
public BlockLogic(String id) {
super(id);

View File

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

View File

@ -25,10 +25,10 @@ import java.io.IOException;
import glm.vec._3.Vec3;
import glm.vec._3.i.Vec3i;
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.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.world.WorldLogic;
@ -39,7 +39,7 @@ public abstract class WorldGenerator extends Namespaced {
// 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;
@ -53,6 +53,6 @@ public abstract class WorldGenerator extends Namespaced {
public abstract Server getServer();
public abstract WorldLogic getWorldLogic();
public abstract WorldData getWorldData();
public abstract DefaultWorldData getWorldData();
}

View File

@ -27,9 +27,9 @@ import com.google.common.collect.ImmutableList;
import glm.vec._3.i.Vec3i;
import 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.tile.TileDataStack;
import ru.windcorp.progressia.common.world.TileDataStack;
import ru.windcorp.progressia.server.Server;
import ru.windcorp.progressia.server.world.ChunkLogic;
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.TickableTile;
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 {
private static final int CHUNK_VOLUME = ChunkData.BLOCKS_PER_CHUNK *
ChunkData.BLOCKS_PER_CHUNK *
ChunkData.BLOCKS_PER_CHUNK;
private static final int CHUNK_VOLUME = DefaultChunkData.BLOCKS_PER_CHUNK *
DefaultChunkData.BLOCKS_PER_CHUNK *
DefaultChunkData.BLOCKS_PER_CHUNK;
private final List<Consumer<Server>> randomTickMethods;

View File

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

View File

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

View File

@ -19,10 +19,10 @@
package ru.windcorp.progressia.server.world.tile;
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;
public class TileLogic extends Namespaced implements GenericTile {
public class TileLogic extends Namespaced implements TileGeneric {
public TileLogic(String id) {
super(id);

View File

@ -17,11 +17,11 @@
*/
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.block.BlockLogic;
public interface TileLogicReference
extends GenericTileReference<BlockLogic, TileLogic, TileLogicStack, TileLogicReference, ChunkLogic> {
extends TileGenericReferenceRO<BlockLogic, TileLogic, TileLogicStack, TileLogicReference, ChunkLogic> {
}

View File

@ -18,13 +18,16 @@
package ru.windcorp.progressia.server.world.tile;
import ru.windcorp.progressia.common.world.generic.GenericTileStack;
import ru.windcorp.progressia.common.world.tile.TileDataStack;
import java.util.AbstractList;
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.block.BlockLogic;
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();

View File

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

View File

@ -33,9 +33,9 @@ import gnu.trove.map.TObjectIntMap;
import gnu.trove.map.hash.TObjectIntHashMap;
import ru.windcorp.jputil.functions.ThrowingConsumer;
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.WorldData;
import ru.windcorp.progressia.common.world.DefaultWorldData;
import ru.windcorp.progressia.common.world.block.BlockData;
import ru.windcorp.progressia.common.world.block.BlockDataRegistry;
import ru.windcorp.progressia.common.world.generic.GenericChunks;
@ -76,7 +76,7 @@ public class TestChunkCodec extends ChunkCodec {
}
@Override
public boolean shouldEncode(ChunkData chunk, IOContext context) {
public boolean shouldEncode(DefaultChunkData chunk, IOContext context) {
return true;
}
@ -85,13 +85,13 @@ public class TestChunkCodec extends ChunkCodec {
*/
@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,
IOException {
BlockData[] blockPalette = readBlockPalette(input);
TileData[] tilePalette = readTilePalette(input);
ChunkData chunk = new ChunkData(position, world);
DefaultChunkData chunk = new DefaultChunkData(position, world);
readBlocks(input, blockPalette, chunk);
readTiles(input, tilePalette, chunk);
@ -121,7 +121,7 @@ public class TestChunkCodec extends ChunkCodec {
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 {
GenericChunks.forEachBiC(guard(v -> {
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();
while (true) {
@ -157,7 +157,7 @@ public class TestChunkCodec extends ChunkCodec {
*/
@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<TileData> tilePalette = createTilePalette(chunk);
@ -168,13 +168,13 @@ public class TestChunkCodec extends ChunkCodec {
writeTiles(chunk, tilePalette, output);
}
private Palette<BlockData> createBlockPalette(ChunkData chunk) {
private Palette<BlockData> createBlockPalette(DefaultChunkData chunk) {
Palette<BlockData> blockPalette = new Palette<>();
GenericChunks.forEachBiC(v -> blockPalette.add(chunk.getBlock(v)));
return blockPalette;
}
private Palette<TileData> createTilePalette(ChunkData chunk) {
private Palette<TileData> createTilePalette(DefaultChunkData chunk) {
Palette<TileData> tilePalette = new Palette<>();
chunk.forEachTile((ts, t) -> tilePalette.add(t));
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 {
GenericChunks.forEachBiC(guard(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();
try {

View File

@ -34,9 +34,9 @@ import org.apache.logging.log4j.Logger;
import glm.vec._3.i.Vec3i;
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.WorldData;
import ru.windcorp.progressia.common.world.DefaultWorldData;
import ru.windcorp.progressia.common.world.io.ChunkIO;
import ru.windcorp.progressia.server.Server;
@ -47,7 +47,7 @@ public class TestWorldDiskIO {
private static final boolean ENABLE = false;
public static void saveChunk(ChunkData chunk, Server server) {
public static void saveChunk(DefaultChunkData chunk, Server server) {
if (!ENABLE)
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 {
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)
return null;
@ -113,7 +113,7 @@ public class TestWorldDiskIO {
}
try {
ChunkData result = load(path, chunkPos, world, server);
DefaultChunkData result = load(path, chunkPos, world, server);
LOG.debug(
"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,
DecodingException {
try (
@ -143,13 +143,13 @@ public class TestWorldDiskIO {
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);
return chunk;
}
}
private static void readGenerationHint(ChunkData chunk, DataInputStream input, Server server)
private static void readGenerationHint(DefaultChunkData chunk, DataInputStream input, Server server)
throws IOException,
DecodingException {
chunk.setGenerationHint(server.getWorld().getGenerator().readGenerationHint(input));

View File

@ -19,12 +19,12 @@ package ru.windcorp.progressia.test.gen;
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;
@FunctionalInterface
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