Replaced AbsFace with RelFace or BlockFace where appropriate
- Added BlockFace - a *Face superclass - Refactored and optimized Rel{Relation, Face} - Replaced most AbsFace references with BlockFace or RelFace - Chunks now have an up direction - Determined by GravityModel's discrete up - Static; cannot change unless chunk is reloaded - Chunk models are now rendered rotated accordingly - Fixed some minor bugs that were somehow revealed by these changes - Moved TileLogicGrass to .test, where it belongs - Disabled grass despawn until a new worldgen is implemented
This commit is contained in:
@ -32,6 +32,8 @@ 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.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;
|
||||
|
||||
public class ChunkRender
|
||||
@ -55,6 +57,11 @@ public class ChunkRender
|
||||
public Vec3i getPosition() {
|
||||
return getData().getPosition();
|
||||
}
|
||||
|
||||
@Override
|
||||
public AbsFace getUp() {
|
||||
return getData().getUp();
|
||||
}
|
||||
|
||||
@Override
|
||||
public BlockRender getBlock(Vec3i posInChunk) {
|
||||
@ -64,12 +71,12 @@ public class ChunkRender
|
||||
}
|
||||
|
||||
@Override
|
||||
public TileRenderStack getTiles(Vec3i blockInChunk, AbsFace face) {
|
||||
public TileRenderStack getTiles(Vec3i blockInChunk, BlockFace face) {
|
||||
return getTileStackWrapper(getData().getTiles(blockInChunk, face));
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasTiles(Vec3i blockInChunk, AbsFace face) {
|
||||
public boolean hasTiles(Vec3i blockInChunk, BlockFace face) {
|
||||
return getData().hasTiles(blockInChunk, face);
|
||||
}
|
||||
|
||||
@ -119,7 +126,7 @@ public class ChunkRender
|
||||
}
|
||||
|
||||
@Override
|
||||
public AbsFace getFace() {
|
||||
public RelFace getFace() {
|
||||
return parent.getFace();
|
||||
}
|
||||
|
||||
|
@ -36,7 +36,8 @@ 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.rels.AbsFace;
|
||||
import ru.windcorp.progressia.common.world.rels.RelFace;
|
||||
import ru.windcorp.progressia.common.world.rels.RelRelation;
|
||||
|
||||
public class ChunkRenderModel implements Renderable {
|
||||
|
||||
@ -53,11 +54,15 @@ public class ChunkRenderModel implements Renderable {
|
||||
public void render(ShapeRenderHelper renderer) {
|
||||
if (model == null) return;
|
||||
|
||||
float offset = ChunkData.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
|
||||
);
|
||||
).translate(offset, offset, offset)
|
||||
.mul(RelRelation.getResolutionMatrix4(chunk.getUp()))
|
||||
.translate(-offset, -offset, -offset);
|
||||
|
||||
model.render(renderer);
|
||||
|
||||
@ -71,8 +76,8 @@ public class ChunkRenderModel implements Renderable {
|
||||
|
||||
optimizers.forEach(ChunkRenderOptimizer::startRender);
|
||||
|
||||
chunk.forEachBiC(blockInChunk -> {
|
||||
processBlockAndTiles(blockInChunk, sink);
|
||||
chunk.forEachBiC(relBlockInChunk -> {
|
||||
processBlockAndTiles(relBlockInChunk, sink);
|
||||
});
|
||||
|
||||
for (ChunkRenderOptimizer optimizer : optimizers) {
|
||||
@ -96,16 +101,16 @@ public class ChunkRenderModel implements Renderable {
|
||||
}
|
||||
}
|
||||
|
||||
private void processBlockAndTiles(Vec3i blockInChunk, Builder sink) {
|
||||
processBlock(blockInChunk, sink);
|
||||
private void processBlockAndTiles(Vec3i relBlockInChunk, Builder sink) {
|
||||
processBlock(relBlockInChunk, sink);
|
||||
|
||||
for (AbsFace face : AbsFace.getFaces()) {
|
||||
processTileStack(blockInChunk, face, sink);
|
||||
for (RelFace face : RelFace.getFaces()) {
|
||||
processTileStack(relBlockInChunk, face, sink);
|
||||
}
|
||||
}
|
||||
|
||||
private void processBlock(Vec3i blockInChunk, Builder sink) {
|
||||
BlockRender block = chunk.getBlock(blockInChunk);
|
||||
private void processBlock(Vec3i relBlockInChunk, Builder sink) {
|
||||
BlockRender block = chunk.getBlockRel(relBlockInChunk);
|
||||
|
||||
if (block instanceof BlockRenderNone) {
|
||||
return;
|
||||
@ -113,48 +118,48 @@ public class ChunkRenderModel implements Renderable {
|
||||
|
||||
if (block.needsOwnRenderable()) {
|
||||
sink.addPart(
|
||||
block.createRenderable(chunk.getData(), blockInChunk),
|
||||
new Mat4().identity().translate(blockInChunk.x, blockInChunk.y, blockInChunk.z)
|
||||
block.createRenderable(chunk.getData(), relBlockInChunk),
|
||||
new Mat4().identity().translate(relBlockInChunk.x, relBlockInChunk.y, relBlockInChunk.z)
|
||||
);
|
||||
}
|
||||
|
||||
processBlockWithCROs(block, blockInChunk);
|
||||
processBlockWithCROs(block, relBlockInChunk);
|
||||
}
|
||||
|
||||
private void processBlockWithCROs(BlockRender block, Vec3i blockInChunk) {
|
||||
private void processBlockWithCROs(BlockRender block, Vec3i relBlockInChunk) {
|
||||
for (ChunkRenderOptimizer optimizer : optimizers) {
|
||||
optimizer.addBlock(block, blockInChunk);
|
||||
optimizer.addBlock(block, relBlockInChunk);
|
||||
}
|
||||
}
|
||||
|
||||
private void processTileStack(Vec3i blockInChunk, AbsFace face, Builder sink) {
|
||||
TileRenderStack trs = chunk.getTilesOrNull(blockInChunk, face);
|
||||
private void processTileStack(Vec3i relBlockInChunk, RelFace face, Builder sink) {
|
||||
TileRenderStack trs = chunk.getTilesOrNullRel(relBlockInChunk, face);
|
||||
|
||||
if (trs == null || trs.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
trs.forEach(tile -> processTile(tile, blockInChunk, face, sink));
|
||||
trs.forEach(tile -> processTile(tile, relBlockInChunk, face, sink));
|
||||
}
|
||||
|
||||
private void processTile(TileRender tile, Vec3i blockInChunk, AbsFace face, Builder sink) {
|
||||
private void processTile(TileRender tile, Vec3i relBlockInChunk, RelFace face, Builder sink) {
|
||||
if (tile instanceof TileRenderNone) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (tile.needsOwnRenderable()) {
|
||||
sink.addPart(
|
||||
tile.createRenderable(chunk.getData(), blockInChunk, face),
|
||||
new Mat4().identity().translate(blockInChunk.x, blockInChunk.y, blockInChunk.z)
|
||||
tile.createRenderable(chunk.getData(), relBlockInChunk, face),
|
||||
new Mat4().identity().translate(relBlockInChunk.x, relBlockInChunk.y, relBlockInChunk.z)
|
||||
);
|
||||
}
|
||||
|
||||
processTileWithCROs(tile, blockInChunk, face);
|
||||
processTileWithCROs(tile, relBlockInChunk, face);
|
||||
}
|
||||
|
||||
private void processTileWithCROs(TileRender tile, Vec3i blockInChunk, AbsFace face) {
|
||||
private void processTileWithCROs(TileRender tile, Vec3i relBlockInChunk, RelFace face) {
|
||||
for (ChunkRenderOptimizer optimizer : optimizers) {
|
||||
optimizer.addTile(tile, blockInChunk, face);
|
||||
optimizer.addTile(tile, relBlockInChunk, face);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -23,6 +23,7 @@ import ru.windcorp.progressia.common.world.ChunkData;
|
||||
import ru.windcorp.progressia.common.world.ChunkDataListener;
|
||||
import ru.windcorp.progressia.common.world.block.BlockData;
|
||||
import ru.windcorp.progressia.common.world.rels.AbsFace;
|
||||
import ru.windcorp.progressia.common.world.rels.RelFace;
|
||||
import ru.windcorp.progressia.common.world.tile.TileData;
|
||||
|
||||
class ChunkUpdateListener implements ChunkDataListener {
|
||||
@ -57,7 +58,7 @@ class ChunkUpdateListener implements ChunkDataListener {
|
||||
public void onChunkTilesChanged(
|
||||
ChunkData chunk,
|
||||
Vec3i blockInChunk,
|
||||
AbsFace face,
|
||||
RelFace face,
|
||||
TileData tile,
|
||||
boolean wasAdded
|
||||
) {
|
||||
|
@ -18,7 +18,6 @@
|
||||
|
||||
package ru.windcorp.progressia.client.world.block;
|
||||
|
||||
import ru.windcorp.progressia.client.graphics.model.ShapeRenderHelper;
|
||||
import ru.windcorp.progressia.common.util.namespaces.Namespaced;
|
||||
import ru.windcorp.progressia.common.world.ChunkData;
|
||||
import ru.windcorp.progressia.common.world.generic.GenericBlock;
|
||||
@ -31,13 +30,7 @@ public abstract class BlockRender extends Namespaced implements GenericBlock {
|
||||
super(id);
|
||||
}
|
||||
|
||||
public void render(ShapeRenderHelper renderer) {
|
||||
throw new UnsupportedOperationException(
|
||||
"BlockRender.render() not implemented in " + this
|
||||
);
|
||||
}
|
||||
|
||||
public Renderable createRenderable(ChunkData chunk, Vec3i blockInChunk) {
|
||||
public Renderable createRenderable(ChunkData chunk, Vec3i relBlockInChunk) {
|
||||
return null;
|
||||
}
|
||||
|
||||
|
@ -19,27 +19,27 @@
|
||||
package ru.windcorp.progressia.client.world.block;
|
||||
|
||||
import ru.windcorp.progressia.client.graphics.texture.Texture;
|
||||
import ru.windcorp.progressia.common.world.rels.AbsFace;
|
||||
import ru.windcorp.progressia.common.world.rels.RelFace;
|
||||
|
||||
public class BlockRenderOpaqueCube extends BlockRenderTexturedCube {
|
||||
|
||||
public BlockRenderOpaqueCube(
|
||||
String id,
|
||||
Texture posZTexture,
|
||||
Texture negZTexture,
|
||||
Texture posXTexture,
|
||||
Texture negXTexture,
|
||||
Texture negYTexture,
|
||||
Texture posYTexture
|
||||
Texture topTexture,
|
||||
Texture bottomTexture,
|
||||
Texture northTexture,
|
||||
Texture southTexture,
|
||||
Texture westTexture,
|
||||
Texture eastTexture
|
||||
) {
|
||||
super(
|
||||
id,
|
||||
posZTexture,
|
||||
negZTexture,
|
||||
posXTexture,
|
||||
negXTexture,
|
||||
negYTexture,
|
||||
posYTexture
|
||||
topTexture,
|
||||
bottomTexture,
|
||||
northTexture,
|
||||
southTexture,
|
||||
westTexture,
|
||||
eastTexture
|
||||
);
|
||||
}
|
||||
|
||||
@ -54,9 +54,21 @@ public class BlockRenderOpaqueCube extends BlockRenderTexturedCube {
|
||||
texture
|
||||
);
|
||||
}
|
||||
|
||||
public BlockRenderOpaqueCube(String id, Texture topTexture, Texture bottomTexture, Texture sideTexture) {
|
||||
this(
|
||||
id,
|
||||
topTexture,
|
||||
bottomTexture,
|
||||
sideTexture,
|
||||
sideTexture,
|
||||
sideTexture,
|
||||
sideTexture
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isOpaque(AbsFace face) {
|
||||
public boolean isOpaque(RelFace face) {
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -20,7 +20,6 @@ package ru.windcorp.progressia.client.world.block;
|
||||
|
||||
import static ru.windcorp.progressia.common.world.rels.AbsFace.*;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
@ -39,43 +38,38 @@ import ru.windcorp.progressia.client.world.cro.ChunkRenderOptimizerSurface.Block
|
||||
import ru.windcorp.progressia.common.util.Vectors;
|
||||
import ru.windcorp.progressia.common.world.ChunkData;
|
||||
import ru.windcorp.progressia.common.world.rels.AbsFace;
|
||||
import ru.windcorp.progressia.common.world.rels.RelFace;
|
||||
|
||||
public abstract class BlockRenderTexturedCube
|
||||
extends BlockRender
|
||||
implements BlockOptimizedSurface {
|
||||
|
||||
private final Map<AbsFace, Texture> textures = new HashMap<>();
|
||||
private final Map<RelFace, Texture> textures;
|
||||
|
||||
public BlockRenderTexturedCube(
|
||||
String id,
|
||||
Texture posZTexture,
|
||||
Texture negZTexture,
|
||||
Texture posXTexture,
|
||||
Texture negXTexture,
|
||||
Texture negYTexture,
|
||||
Texture posYTexture
|
||||
Texture topTexture,
|
||||
Texture bottomTexture,
|
||||
Texture northTexture,
|
||||
Texture southTexture,
|
||||
Texture westTexture,
|
||||
Texture eastTexture
|
||||
) {
|
||||
super(id);
|
||||
|
||||
textures.put(POS_Z, posZTexture);
|
||||
textures.put(NEG_Z, negZTexture);
|
||||
textures.put(POS_X, posXTexture);
|
||||
textures.put(NEG_X, negXTexture);
|
||||
textures.put(NEG_Y, negYTexture);
|
||||
textures.put(POS_Y, posYTexture);
|
||||
this.textures = RelFace.mapToFaces(topTexture, bottomTexture, northTexture, southTexture, westTexture, eastTexture);
|
||||
}
|
||||
|
||||
public Texture getTexture(AbsFace blockFace) {
|
||||
public Texture getTexture(RelFace blockFace) {
|
||||
return textures.get(blockFace);
|
||||
}
|
||||
|
||||
public Vec4 getColorMultiplier(AbsFace blockFace) {
|
||||
public Vec4 getColorMultiplier(RelFace blockFace) {
|
||||
return Colors.WHITE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void getShapeParts(
|
||||
ChunkData chunk, Vec3i blockInChunk, AbsFace blockFace,
|
||||
ChunkData chunk, Vec3i blockInChunk, RelFace blockFace,
|
||||
boolean inner,
|
||||
Consumer<ShapePart> output,
|
||||
Vec3 offset
|
||||
@ -84,7 +78,7 @@ public abstract class BlockRenderTexturedCube
|
||||
}
|
||||
|
||||
private ShapePart createFace(
|
||||
ChunkData chunk, Vec3i blockInChunk, AbsFace blockFace,
|
||||
ChunkData chunk, Vec3i blockInChunk, RelFace blockFace,
|
||||
boolean inner,
|
||||
Vec3 offset
|
||||
) {
|
||||
@ -93,7 +87,7 @@ public abstract class BlockRenderTexturedCube
|
||||
getTexture(blockFace),
|
||||
getColorMultiplier(blockFace),
|
||||
offset,
|
||||
blockFace,
|
||||
blockFace.resolve(AbsFace.POS_Z),
|
||||
inner
|
||||
);
|
||||
}
|
||||
@ -105,12 +99,12 @@ public abstract class BlockRenderTexturedCube
|
||||
ShapePart[] faces = new ShapePart[BLOCK_FACE_COUNT + (opaque ? BLOCK_FACE_COUNT : 0)];
|
||||
|
||||
for (int i = 0; i < BLOCK_FACE_COUNT; ++i) {
|
||||
faces[i] = createFace(chunk, blockInChunk, AbsFace.getFaces().get(i), false, Vectors.ZERO_3);
|
||||
faces[i] = createFace(chunk, blockInChunk, RelFace.getFaces().get(i), false, Vectors.ZERO_3);
|
||||
}
|
||||
|
||||
if (!opaque) {
|
||||
for (int i = 0; i < BLOCK_FACE_COUNT; ++i) {
|
||||
faces[i + BLOCK_FACE_COUNT] = createFace(chunk, blockInChunk, AbsFace.getFaces().get(i), true, Vectors.ZERO_3);
|
||||
faces[i + BLOCK_FACE_COUNT] = createFace(chunk, blockInChunk, RelFace.getFaces().get(i), true, Vectors.ZERO_3);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -19,27 +19,27 @@
|
||||
package ru.windcorp.progressia.client.world.block;
|
||||
|
||||
import ru.windcorp.progressia.client.graphics.texture.Texture;
|
||||
import ru.windcorp.progressia.common.world.rels.AbsFace;
|
||||
import ru.windcorp.progressia.common.world.rels.RelFace;
|
||||
|
||||
public class BlockRenderTransparentCube extends BlockRenderTexturedCube {
|
||||
|
||||
public BlockRenderTransparentCube(
|
||||
String id,
|
||||
Texture posZTexture,
|
||||
Texture negZTexture,
|
||||
Texture posXTexture,
|
||||
Texture negXTexture,
|
||||
Texture negYTexture,
|
||||
Texture posYTexture
|
||||
Texture topTexture,
|
||||
Texture bottomTexture,
|
||||
Texture northTexture,
|
||||
Texture southTexture,
|
||||
Texture westTexture,
|
||||
Texture eastTexture
|
||||
) {
|
||||
super(
|
||||
id,
|
||||
posZTexture,
|
||||
negZTexture,
|
||||
posXTexture,
|
||||
negXTexture,
|
||||
negYTexture,
|
||||
posYTexture
|
||||
topTexture,
|
||||
bottomTexture,
|
||||
northTexture,
|
||||
southTexture,
|
||||
westTexture,
|
||||
eastTexture
|
||||
);
|
||||
}
|
||||
|
||||
@ -54,9 +54,21 @@ public class BlockRenderTransparentCube extends BlockRenderTexturedCube {
|
||||
texture
|
||||
);
|
||||
}
|
||||
|
||||
public BlockRenderTransparentCube(String id, Texture topTexture, Texture bottomTexture, Texture sideTexture) {
|
||||
this(
|
||||
id,
|
||||
topTexture,
|
||||
bottomTexture,
|
||||
sideTexture,
|
||||
sideTexture,
|
||||
sideTexture,
|
||||
sideTexture
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isOpaque(AbsFace face) {
|
||||
public boolean isOpaque(RelFace face) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -24,7 +24,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.namespaces.Namespaced;
|
||||
import ru.windcorp.progressia.common.world.rels.AbsFace;
|
||||
import ru.windcorp.progressia.common.world.rels.RelFace;
|
||||
|
||||
/**
|
||||
* Chunk render optimizer (CRO) is an object that produces optimized models for
|
||||
@ -35,6 +35,12 @@ import ru.windcorp.progressia.common.world.rels.AbsFace;
|
||||
* tiles. An example of a CRO is {@link ChunkRenderOptimizerSurface}: it removes
|
||||
* block surfaces and tiles that it knows cannot be seen, thus significantly
|
||||
* reducing total polygon count.
|
||||
* <p>
|
||||
* As with everything related to rendering chunks, CROs are interacted with
|
||||
* using the relative local chunk coordinate system. In this coordinate system,
|
||||
* the coordinates are the chunk coordinates relativized using the chunks's up
|
||||
* direction. In simpler terms, coordinates are {@code [0; BLOCKS_PER_CHUNK)}
|
||||
* and Z is always up.
|
||||
* <h3>CRO lifecycle</h3>
|
||||
* A CRO instance is created by {@link ChunkRenderOptimizerRegistry}. It may
|
||||
* then be used to work on multiple chunks sequentially. Each chunk is processed
|
||||
@ -44,7 +50,7 @@ import ru.windcorp.progressia.common.world.rels.AbsFace;
|
||||
* instance.</li>
|
||||
* <li>{@link #startRender()} is invoked. The CRO must reset its state.</li>
|
||||
* <li>{@link #addBlock(BlockRender, Vec3i)} and
|
||||
* {@link #addTile(TileRender, Vec3i, AbsFace)} are invoked for each block and
|
||||
* {@link #addTile(TileRender, Vec3i, RelFace)} are invoked for each block and
|
||||
* tile that this CRO should optimize. {@code addTile} specifies tiles in order
|
||||
* of ascension within a tile stack.</li>
|
||||
* <li>{@link #endRender()} is invoked. The CRO may perform any pending
|
||||
@ -98,12 +104,13 @@ public abstract class ChunkRenderOptimizer extends Namespaced {
|
||||
* method is only invoked once per block. This method is not necessarily
|
||||
* invoked for each block.
|
||||
*
|
||||
* @param block a {@link BlockRender} instance describing the block.
|
||||
* It corresponds to
|
||||
* {@code getChunk().getBlock(blockInChunk)}.
|
||||
* @param blockInChunk the position of the block
|
||||
* @param block a {@link BlockRender} instance describing the
|
||||
* block.
|
||||
* It corresponds to
|
||||
* {@code getChunk().getBlock(blockInChunk)}.
|
||||
* @param relBlockInChunk the relative position of the block
|
||||
*/
|
||||
public abstract void addBlock(BlockRender block, Vec3i blockInChunk);
|
||||
public abstract void addBlock(BlockRender block, Vec3i relBlockInChunk);
|
||||
|
||||
/**
|
||||
* Requests that this CRO processes the provided tile. This method may only
|
||||
@ -112,11 +119,12 @@ public abstract class ChunkRenderOptimizer extends Namespaced {
|
||||
* invoked for each tile. When multiple tiles in a tile stack are requested,
|
||||
* this method is invoked for lower tiles first.
|
||||
*
|
||||
* @param tile a {@link BlockRender} instance describing the tile
|
||||
* @param blockInChunk the position of the block that the tile belongs to
|
||||
* @param blockFace the face that the tile belongs to
|
||||
* @param tile a {@link BlockRender} instance describing the tile
|
||||
* @param relBlockInChunk the relative position of the block that the tile
|
||||
* belongs to
|
||||
* @param blockFace the face that the tile belongs to
|
||||
*/
|
||||
public abstract void addTile(TileRender tile, Vec3i blockInChunk, AbsFace blockFace);
|
||||
public abstract void addTile(TileRender tile, Vec3i relBlockInChunk, RelFace blockFace);
|
||||
|
||||
/**
|
||||
* Requests that the CRO assembles and outputs its model. This method may
|
||||
|
@ -38,7 +38,7 @@ import ru.windcorp.progressia.client.world.block.BlockRender;
|
||||
import ru.windcorp.progressia.client.world.tile.TileRender;
|
||||
import ru.windcorp.progressia.common.util.Vectors;
|
||||
import ru.windcorp.progressia.common.world.ChunkData;
|
||||
import ru.windcorp.progressia.common.world.rels.AbsFace;
|
||||
import ru.windcorp.progressia.common.world.rels.RelFace;
|
||||
|
||||
public class ChunkRenderOptimizerSurface extends ChunkRenderOptimizer {
|
||||
|
||||
@ -56,20 +56,23 @@ public class ChunkRenderOptimizerSurface extends ChunkRenderOptimizer {
|
||||
* surface. The coordinates of the face vertices must be in chunk
|
||||
* coordinate system.
|
||||
*
|
||||
* @param chunk the chunk that contains the requested face
|
||||
* @param blockInChunk the block in chunk
|
||||
* @param blockFace the requested face
|
||||
* @param inner whether this face should be visible from inside
|
||||
* ({@code true}) or outside ({@code false})
|
||||
* @param output a consumer that the created shape parts must be
|
||||
* given to
|
||||
* @param offset an additional offset that must be applied to all
|
||||
* vertices
|
||||
* @param chunk the chunk that contains the requested face
|
||||
* @param relBlockInChunk the relative block in chunk
|
||||
* @param blockFace the requested face
|
||||
* @param inner whether this face should be visible from
|
||||
* inside
|
||||
* ({@code true}) or outside ({@code false})
|
||||
* @param output a consumer that the created shape parts must
|
||||
* be
|
||||
* given to
|
||||
* @param offset an additional offset that must be applied to
|
||||
* all
|
||||
* vertices
|
||||
*/
|
||||
void getShapeParts(
|
||||
ChunkData chunk,
|
||||
Vec3i blockInChunk,
|
||||
AbsFace blockFace,
|
||||
Vec3i relBlockInChunk,
|
||||
RelFace blockFace,
|
||||
boolean inner,
|
||||
Consumer<ShapePart> output,
|
||||
Vec3 offset /* kostyl 156% */
|
||||
@ -77,14 +80,14 @@ public class ChunkRenderOptimizerSurface extends ChunkRenderOptimizer {
|
||||
|
||||
/**
|
||||
* Returns the opacity of the surface identified by the provided
|
||||
* {@link AbsFace}.
|
||||
* {@link RelFace}.
|
||||
* Opaque surfaces prevent surfaces behind them from being included in
|
||||
* chunk models.
|
||||
*
|
||||
* @param blockFace the face to query
|
||||
* @return {@code true} iff the surface is opaque.
|
||||
*/
|
||||
boolean isOpaque(AbsFace blockFace);
|
||||
boolean isOpaque(RelFace blockFace);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -159,29 +162,29 @@ public class ChunkRenderOptimizerSurface extends ChunkRenderOptimizer {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addBlock(BlockRender block, Vec3i pos) {
|
||||
public void addBlock(BlockRender block, Vec3i relBlockInChunk) {
|
||||
if (!(block instanceof BlockOptimizedSurface))
|
||||
return;
|
||||
|
||||
BlockOptimizedSurface bos = (BlockOptimizedSurface) block;
|
||||
addBlock(pos, bos);
|
||||
addBlock(relBlockInChunk, bos);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addTile(TileRender tile, Vec3i pos, AbsFace face) {
|
||||
public void addTile(TileRender tile, Vec3i relBlockInChunk, RelFace face) {
|
||||
if (!(tile instanceof TileOptimizedSurface))
|
||||
return;
|
||||
|
||||
TileOptimizedSurface tos = (TileOptimizedSurface) tile;
|
||||
addTile(pos, face, tos);
|
||||
addTile(relBlockInChunk, face, tos);
|
||||
}
|
||||
|
||||
protected void addBlock(Vec3i pos, BlockOptimizedSurface block) {
|
||||
getBlock(pos).block = block;
|
||||
private void addBlock(Vec3i relBlockInChunk, BlockOptimizedSurface block) {
|
||||
getBlock(relBlockInChunk).block = block;
|
||||
}
|
||||
|
||||
private void addTile(Vec3i pos, AbsFace face, TileOptimizedSurface tile) {
|
||||
FaceInfo faceInfo = getFace(pos, face);
|
||||
private void addTile(Vec3i relBlockInChunk, RelFace face, TileOptimizedSurface tile) {
|
||||
FaceInfo faceInfo = getFace(relBlockInChunk, face);
|
||||
|
||||
int index = faceInfo.tileCount;
|
||||
faceInfo.tileCount++;
|
||||
@ -197,12 +200,12 @@ public class ChunkRenderOptimizerSurface extends ChunkRenderOptimizer {
|
||||
}
|
||||
}
|
||||
|
||||
protected BlockInfo getBlock(Vec3i cursor) {
|
||||
return data[cursor.x][cursor.y][cursor.z];
|
||||
protected BlockInfo getBlock(Vec3i relBlockInChunk) {
|
||||
return data[relBlockInChunk.x][relBlockInChunk.y][relBlockInChunk.z];
|
||||
}
|
||||
|
||||
protected FaceInfo getFace(Vec3i cursor, AbsFace face) {
|
||||
return getBlock(cursor).faces[face.getId()];
|
||||
protected FaceInfo getFace(Vec3i relBlockInChunk, RelFace face) {
|
||||
return getBlock(relBlockInChunk).faces[face.getId()];
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -211,17 +214,12 @@ public class ChunkRenderOptimizerSurface extends ChunkRenderOptimizer {
|
||||
BLOCKS_PER_CHUNK * BLOCKS_PER_CHUNK * BLOCKS_PER_CHUNK * 3
|
||||
);
|
||||
|
||||
Vec3i cursor = new Vec3i();
|
||||
Consumer<ShapePart> consumer = shapeParts::add;
|
||||
|
||||
for (cursor.x = 0; cursor.x < BLOCKS_PER_CHUNK; ++cursor.x) {
|
||||
for (cursor.y = 0; cursor.y < BLOCKS_PER_CHUNK; ++cursor.y) {
|
||||
for (cursor.z = 0; cursor.z < BLOCKS_PER_CHUNK; ++cursor.z) {
|
||||
processInnerFaces(cursor, consumer);
|
||||
processOuterFaces(cursor, consumer);
|
||||
}
|
||||
}
|
||||
}
|
||||
chunk.forEachBiC(relBlockInChunk -> {
|
||||
processInnerFaces(relBlockInChunk, consumer);
|
||||
processOuterFaces(relBlockInChunk, consumer);
|
||||
});
|
||||
|
||||
if (shapeParts.isEmpty()) {
|
||||
return null;
|
||||
@ -235,25 +233,25 @@ public class ChunkRenderOptimizerSurface extends ChunkRenderOptimizer {
|
||||
}
|
||||
|
||||
private void processOuterFaces(
|
||||
Vec3i blockInChunk,
|
||||
Vec3i relBlockInChunk,
|
||||
Consumer<ShapePart> output
|
||||
) {
|
||||
for (AbsFace blockFace : AbsFace.getFaces()) {
|
||||
processOuterFace(blockInChunk, blockFace, output);
|
||||
for (RelFace blockFace : RelFace.getFaces()) {
|
||||
processOuterFace(relBlockInChunk, blockFace, output);
|
||||
}
|
||||
}
|
||||
|
||||
private void processOuterFace(Vec3i blockInChunk, AbsFace blockFace, Consumer<ShapePart> output) {
|
||||
if (!shouldRenderOuterFace(blockInChunk, blockFace))
|
||||
private void processOuterFace(Vec3i relBlockInChunk, RelFace blockFace, Consumer<ShapePart> output) {
|
||||
if (!shouldRenderOuterFace(relBlockInChunk, blockFace))
|
||||
return;
|
||||
|
||||
FaceInfo info = getFace(blockInChunk, blockFace);
|
||||
FaceInfo info = getFace(relBlockInChunk, blockFace);
|
||||
|
||||
if (info.tileCount == 0 && info.block.block == null)
|
||||
return;
|
||||
|
||||
Vec3 faceOrigin = new Vec3(blockInChunk.x, blockInChunk.y, blockInChunk.z);
|
||||
Vec3 offset = new Vec3(blockFace.getFloatVector()).mul(OVERLAY_OFFSET);
|
||||
Vec3 faceOrigin = new Vec3(relBlockInChunk.x, relBlockInChunk.y, relBlockInChunk.z);
|
||||
Vec3 offset = new Vec3(blockFace.getRelFloatVector()).mul(OVERLAY_OFFSET);
|
||||
|
||||
for (
|
||||
int layer = info.topOpaqueSurface;
|
||||
@ -264,32 +262,29 @@ public class ChunkRenderOptimizerSurface extends ChunkRenderOptimizer {
|
||||
if (surface == null)
|
||||
continue; // layer may be BLOCK_LAYER, then block may be null
|
||||
|
||||
surface.getShapeParts(chunk.getData(), blockInChunk, blockFace, false, output, faceOrigin);
|
||||
surface.getShapeParts(chunk.getData(), relBlockInChunk, blockFace, false, output, faceOrigin);
|
||||
|
||||
faceOrigin.add(offset);
|
||||
}
|
||||
}
|
||||
|
||||
private void processInnerFaces(
|
||||
Vec3i blockInChunk,
|
||||
Consumer<ShapePart> output
|
||||
) {
|
||||
for (AbsFace blockFace : AbsFace.getFaces()) {
|
||||
processInnerFace(blockInChunk, blockFace, output);
|
||||
private void processInnerFaces(Vec3i relBlockInChunk, Consumer<ShapePart> output) {
|
||||
for (RelFace blockFace : RelFace.getFaces()) {
|
||||
processInnerFace(relBlockInChunk, blockFace, output);
|
||||
}
|
||||
}
|
||||
|
||||
private void processInnerFace(Vec3i blockInChunk, AbsFace blockFace, Consumer<ShapePart> output) {
|
||||
if (!shouldRenderInnerFace(blockInChunk, blockFace))
|
||||
private void processInnerFace(Vec3i relBlockInChunk, RelFace blockFace, Consumer<ShapePart> output) {
|
||||
if (!shouldRenderInnerFace(relBlockInChunk, blockFace))
|
||||
return;
|
||||
|
||||
FaceInfo info = getFace(blockInChunk, blockFace);
|
||||
FaceInfo info = getFace(relBlockInChunk, blockFace);
|
||||
|
||||
if (info.tileCount == 0 && info.block.block == null)
|
||||
return;
|
||||
|
||||
Vec3 faceOrigin = new Vec3(blockInChunk.x, blockInChunk.y, blockInChunk.z);
|
||||
Vec3 offset = new Vec3(blockFace.getFloatVector()).mul(OVERLAY_OFFSET);
|
||||
Vec3 faceOrigin = new Vec3(relBlockInChunk.x, relBlockInChunk.y, relBlockInChunk.z);
|
||||
Vec3 offset = new Vec3(blockFace.getRelFloatVector()).mul(OVERLAY_OFFSET);
|
||||
|
||||
for (
|
||||
int layer = FaceInfo.BLOCK_LAYER;
|
||||
@ -300,35 +295,35 @@ public class ChunkRenderOptimizerSurface extends ChunkRenderOptimizer {
|
||||
if (surface == null)
|
||||
continue; // layer may be BLOCK_LAYER, then block may be null
|
||||
|
||||
surface.getShapeParts(chunk.getData(), blockInChunk, blockFace, true, output, faceOrigin);
|
||||
surface.getShapeParts(chunk.getData(), relBlockInChunk, blockFace, true, output, faceOrigin);
|
||||
|
||||
faceOrigin.add(offset);
|
||||
}
|
||||
}
|
||||
|
||||
private boolean shouldRenderOuterFace(Vec3i blockInChunk, AbsFace face) {
|
||||
blockInChunk.add(face.getVector());
|
||||
private boolean shouldRenderOuterFace(Vec3i relBlockInChunk, RelFace face) {
|
||||
relBlockInChunk.add(face.getRelVector());
|
||||
try {
|
||||
return shouldRenderWhenFacing(blockInChunk, face);
|
||||
return shouldRenderWhenFacing(relBlockInChunk, face);
|
||||
} finally {
|
||||
blockInChunk.sub(face.getVector());
|
||||
relBlockInChunk.sub(face.getRelVector());
|
||||
}
|
||||
}
|
||||
|
||||
private boolean shouldRenderInnerFace(Vec3i blockInChunk, AbsFace face) {
|
||||
return shouldRenderWhenFacing(blockInChunk, face);
|
||||
private boolean shouldRenderInnerFace(Vec3i relBlockInChunk, RelFace face) {
|
||||
return shouldRenderWhenFacing(relBlockInChunk, face);
|
||||
}
|
||||
|
||||
private boolean shouldRenderWhenFacing(Vec3i blockInChunk, AbsFace face) {
|
||||
if (chunk.containsBiC(blockInChunk)) {
|
||||
return shouldRenderWhenFacingLocal(blockInChunk, face);
|
||||
private boolean shouldRenderWhenFacing(Vec3i relBlockInChunk, RelFace face) {
|
||||
if (chunk.containsBiC(relBlockInChunk)) {
|
||||
return shouldRenderWhenFacingLocal(relBlockInChunk, face);
|
||||
} else {
|
||||
return shouldRenderWhenFacingNeighbor(blockInChunk, face);
|
||||
return shouldRenderWhenFacingNeighbor(relBlockInChunk, face);
|
||||
}
|
||||
}
|
||||
|
||||
private boolean shouldRenderWhenFacingLocal(Vec3i blockInChunk, AbsFace face) {
|
||||
BlockOptimizedSurface block = getBlock(blockInChunk).block;
|
||||
private boolean shouldRenderWhenFacingLocal(Vec3i relBlockInChunk, RelFace face) {
|
||||
BlockOptimizedSurface block = getBlock(relBlockInChunk).block;
|
||||
|
||||
if (block == null) {
|
||||
return true;
|
||||
@ -340,36 +335,37 @@ public class ChunkRenderOptimizerSurface extends ChunkRenderOptimizer {
|
||||
return true;
|
||||
}
|
||||
|
||||
private boolean shouldRenderWhenFacingNeighbor(Vec3i blockInLocalChunk, AbsFace face) {
|
||||
Vec3i blockInChunk = Vectors.grab3i().set(blockInLocalChunk.x, blockInLocalChunk.y, blockInLocalChunk.z);
|
||||
private boolean shouldRenderWhenFacingNeighbor(Vec3i relBlockInLocalChunk, RelFace face) {
|
||||
Vec3i blockInChunk = Vectors.grab3i();
|
||||
chunk.resolve(relBlockInLocalChunk, blockInChunk);
|
||||
Vec3i chunkPos = Vectors.grab3i().set(chunk.getX(), chunk.getY(), chunk.getZ());
|
||||
|
||||
try {
|
||||
// Determine blockInChunk and chunkPos
|
||||
if (blockInLocalChunk.x == -1) {
|
||||
if (blockInChunk.x == -1) {
|
||||
blockInChunk.x = BLOCKS_PER_CHUNK - 1;
|
||||
chunkPos.x -= 1;
|
||||
} else if (blockInLocalChunk.x == BLOCKS_PER_CHUNK) {
|
||||
} else if (blockInChunk.x == BLOCKS_PER_CHUNK) {
|
||||
blockInChunk.x = 0;
|
||||
chunkPos.x += 1;
|
||||
} else if (blockInLocalChunk.y == -1) {
|
||||
} else if (blockInChunk.y == -1) {
|
||||
blockInChunk.y = BLOCKS_PER_CHUNK - 1;
|
||||
chunkPos.y -= 1;
|
||||
} else if (blockInLocalChunk.y == BLOCKS_PER_CHUNK) {
|
||||
} else if (blockInChunk.y == BLOCKS_PER_CHUNK) {
|
||||
blockInChunk.y = 0;
|
||||
chunkPos.y += 1;
|
||||
} else if (blockInLocalChunk.z == -1) {
|
||||
} else if (blockInChunk.z == -1) {
|
||||
blockInChunk.z = BLOCKS_PER_CHUNK - 1;
|
||||
chunkPos.z -= 1;
|
||||
} else if (blockInLocalChunk.z == BLOCKS_PER_CHUNK) {
|
||||
} else if (blockInChunk.z == BLOCKS_PER_CHUNK) {
|
||||
blockInChunk.z = 0;
|
||||
chunkPos.z += 1;
|
||||
} else {
|
||||
throw new AssertionError(
|
||||
"Requested incorrent neighbor ("
|
||||
+ blockInLocalChunk.x + "; "
|
||||
+ blockInLocalChunk.y + "; "
|
||||
+ blockInLocalChunk.z + ")"
|
||||
+ relBlockInLocalChunk.x + "; "
|
||||
+ relBlockInLocalChunk.y + "; "
|
||||
+ relBlockInLocalChunk.z + ")"
|
||||
);
|
||||
}
|
||||
|
||||
@ -382,8 +378,11 @@ public class ChunkRenderOptimizerSurface extends ChunkRenderOptimizer {
|
||||
return true;
|
||||
|
||||
BlockOptimizedSurface bos = (BlockOptimizedSurface) block;
|
||||
if (!bos.isOpaque(face))
|
||||
RelFace rotatedFace = face.rotate(this.chunk.getUp(), chunk.getUp());
|
||||
|
||||
if (!bos.isOpaque(rotatedFace)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
|
||||
|
@ -18,14 +18,13 @@
|
||||
|
||||
package ru.windcorp.progressia.client.world.tile;
|
||||
|
||||
import ru.windcorp.progressia.client.graphics.model.ShapeRenderHelper;
|
||||
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.rels.AbsFace;
|
||||
import ru.windcorp.progressia.common.world.rels.RelFace;
|
||||
|
||||
public class TileRender extends Namespaced implements GenericTile {
|
||||
|
||||
@ -33,13 +32,7 @@ public class TileRender extends Namespaced implements GenericTile {
|
||||
super(id);
|
||||
}
|
||||
|
||||
public void render(ShapeRenderHelper renderer, AbsFace face) {
|
||||
throw new UnsupportedOperationException(
|
||||
"TileRender.render() not implemented in " + this
|
||||
);
|
||||
}
|
||||
|
||||
public Renderable createRenderable(ChunkData chunk, Vec3i blockInChunk, AbsFace face) {
|
||||
public Renderable createRenderable(ChunkData chunk, Vec3i blockInChunk, RelFace face) {
|
||||
return null;
|
||||
}
|
||||
|
||||
|
@ -21,7 +21,7 @@ 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.rels.AbsFace;
|
||||
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, AbsFace face) {
|
||||
public Renderable createRenderable(ChunkData chunk, Vec3i blockInChunk, RelFace face) {
|
||||
return EmptyModel.getInstance();
|
||||
}
|
||||
|
||||
|
@ -19,7 +19,7 @@
|
||||
package ru.windcorp.progressia.client.world.tile;
|
||||
|
||||
import ru.windcorp.progressia.client.graphics.texture.Texture;
|
||||
import ru.windcorp.progressia.common.world.rels.AbsFace;
|
||||
import ru.windcorp.progressia.common.world.rels.RelFace;
|
||||
|
||||
public class TileRenderOpaqueSurface extends TileRenderSurface {
|
||||
|
||||
@ -28,7 +28,7 @@ public class TileRenderOpaqueSurface extends TileRenderSurface {
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isOpaque(AbsFace face) {
|
||||
public boolean isOpaque(RelFace face) {
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -35,6 +35,7 @@ import ru.windcorp.progressia.client.world.cro.ChunkRenderOptimizerSurface.TileO
|
||||
import ru.windcorp.progressia.common.util.Vectors;
|
||||
import ru.windcorp.progressia.common.world.ChunkData;
|
||||
import ru.windcorp.progressia.common.world.rels.AbsFace;
|
||||
import ru.windcorp.progressia.common.world.rels.RelFace;
|
||||
|
||||
public abstract class TileRenderSurface extends TileRender implements TileOptimizedSurface {
|
||||
|
||||
@ -49,26 +50,26 @@ public abstract class TileRenderSurface extends TileRender implements TileOptimi
|
||||
this(id, null);
|
||||
}
|
||||
|
||||
public Texture getTexture(AbsFace blockFace) {
|
||||
public Texture getTexture(RelFace blockFace) {
|
||||
return texture;
|
||||
}
|
||||
|
||||
public Vec4 getColorMultiplier(AbsFace blockFace) {
|
||||
public Vec4 getColorMultiplier(RelFace blockFace) {
|
||||
return Colors.WHITE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void getShapeParts(
|
||||
ChunkData chunk, Vec3i blockInChunk, AbsFace blockFace,
|
||||
ChunkData chunk, Vec3i relBlockInChunk, RelFace blockFace,
|
||||
boolean inner,
|
||||
Consumer<ShapePart> output,
|
||||
Vec3 offset
|
||||
) {
|
||||
output.accept(createFace(chunk, blockInChunk, blockFace, inner, offset));
|
||||
output.accept(createFace(chunk, relBlockInChunk, blockFace, inner, offset));
|
||||
}
|
||||
|
||||
private ShapePart createFace(
|
||||
ChunkData chunk, Vec3i blockInChunk, AbsFace blockFace,
|
||||
ChunkData chunk, Vec3i blockInChunk, RelFace blockFace,
|
||||
boolean inner,
|
||||
Vec3 offset
|
||||
) {
|
||||
@ -77,13 +78,13 @@ public abstract class TileRenderSurface extends TileRender implements TileOptimi
|
||||
getTexture(blockFace),
|
||||
getColorMultiplier(blockFace),
|
||||
offset,
|
||||
blockFace,
|
||||
blockFace.resolve(AbsFace.POS_Z),
|
||||
inner
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Renderable createRenderable(ChunkData chunk, Vec3i blockInChunk, AbsFace blockFace) {
|
||||
public Renderable createRenderable(ChunkData chunk, Vec3i blockInChunk, RelFace blockFace) {
|
||||
return new Shape(
|
||||
Usage.STATIC,
|
||||
WorldRenderProgram.getDefault(),
|
||||
|
@ -19,7 +19,7 @@
|
||||
package ru.windcorp.progressia.client.world.tile;
|
||||
|
||||
import ru.windcorp.progressia.client.graphics.texture.Texture;
|
||||
import ru.windcorp.progressia.common.world.rels.AbsFace;
|
||||
import ru.windcorp.progressia.common.world.rels.RelFace;
|
||||
|
||||
public class TileRenderTransparentSurface extends TileRenderSurface {
|
||||
|
||||
@ -28,7 +28,7 @@ public class TileRenderTransparentSurface extends TileRenderSurface {
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isOpaque(AbsFace face) {
|
||||
public boolean isOpaque(RelFace face) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -18,7 +18,7 @@
|
||||
|
||||
package ru.windcorp.progressia.common.world;
|
||||
|
||||
import static ru.windcorp.progressia.common.world.rels.AbsFace.*;
|
||||
import static ru.windcorp.progressia.common.world.rels.BlockFace.BLOCK_FACE_COUNT;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
@ -33,6 +33,8 @@ import ru.windcorp.progressia.common.util.VectorUtil;
|
||||
import ru.windcorp.progressia.common.world.block.BlockData;
|
||||
import ru.windcorp.progressia.common.world.generic.GenericChunk;
|
||||
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.TileDataStack;
|
||||
import ru.windcorp.progressia.common.world.tile.TileReference;
|
||||
@ -50,6 +52,8 @@ public class ChunkData
|
||||
|
||||
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;
|
||||
|
||||
@ -58,12 +62,18 @@ public class ChunkData
|
||||
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) {
|
||||
@ -83,31 +93,31 @@ public class ChunkData
|
||||
}
|
||||
|
||||
@Override
|
||||
public TileDataStack getTilesOrNull(Vec3i blockInChunk, AbsFace face) {
|
||||
public TileDataStack getTilesOrNull(Vec3i blockInChunk, BlockFace face) {
|
||||
return tiles[getTileIndex(blockInChunk, face)];
|
||||
}
|
||||
|
||||
/**
|
||||
* Internal use only. Modify a list returned by
|
||||
* {@link #getTiles(Vec3i, AbsFace)} or
|
||||
* {@link #getTilesOrNull(Vec3i, AbsFace)}
|
||||
* {@link #getTiles(Vec3i, BlockFace)} or
|
||||
* {@link #getTilesOrNull(Vec3i, BlockFace)}
|
||||
* to change tiles.
|
||||
*/
|
||||
protected void setTiles(
|
||||
Vec3i blockInChunk,
|
||||
AbsFace face,
|
||||
BlockFace face,
|
||||
TileDataStack tiles
|
||||
) {
|
||||
this.tiles[getTileIndex(blockInChunk, face)] = tiles;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasTiles(Vec3i blockInChunk, AbsFace face) {
|
||||
public boolean hasTiles(Vec3i blockInChunk, BlockFace face) {
|
||||
return getTilesOrNull(blockInChunk, face) != null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public TileDataStack getTiles(Vec3i blockInChunk, AbsFace face) {
|
||||
public TileDataStack getTiles(Vec3i blockInChunk, BlockFace face) {
|
||||
int index = getTileIndex(blockInChunk, face);
|
||||
|
||||
if (tiles[index] == null) {
|
||||
@ -117,7 +127,7 @@ public class ChunkData
|
||||
return tiles[index];
|
||||
}
|
||||
|
||||
private void createTileStack(Vec3i blockInChunk, AbsFace face) {
|
||||
private void createTileStack(Vec3i blockInChunk, BlockFace face) {
|
||||
Vec3i independentBlockInChunk = conjureIndependentBlockInChunkVec3i(blockInChunk);
|
||||
TileDataStackImpl stack = new TileDataStackImpl(independentBlockInChunk, face);
|
||||
setTiles(blockInChunk, face, stack);
|
||||
@ -142,15 +152,15 @@ public class ChunkData
|
||||
posInChunk.x;
|
||||
}
|
||||
|
||||
private static int getTileIndex(Vec3i posInChunk, AbsFace face) {
|
||||
private int getTileIndex(Vec3i posInChunk, BlockFace face) {
|
||||
return getBlockIndex(posInChunk) * BLOCK_FACE_COUNT +
|
||||
face.getId();
|
||||
face.resolve(getUp()).getId();
|
||||
}
|
||||
|
||||
private static void checkLocalCoordinates(Vec3i posInChunk) {
|
||||
if (!isInBounds(posInChunk)) {
|
||||
throw new IllegalCoordinatesException(
|
||||
"Coordinates " + str(posInChunk) + " "
|
||||
"Coordinates (" + posInChunk.x + "; " + posInChunk.y + "; " + posInChunk.z + ") "
|
||||
+ "are not legal chunk coordinates"
|
||||
);
|
||||
}
|
||||
@ -162,14 +172,15 @@ public class ChunkData
|
||||
posInChunk.z >= 0 && posInChunk.z < BLOCKS_PER_CHUNK;
|
||||
}
|
||||
|
||||
public boolean isBorder(Vec3i blockInChunk, AbsFace face) {
|
||||
public boolean isBorder(Vec3i blockInChunk, BlockFace face) {
|
||||
final int min = 0, max = BLOCKS_PER_CHUNK - 1;
|
||||
return (blockInChunk.x == min && face == NEG_X) ||
|
||||
(blockInChunk.x == max && face == POS_X) ||
|
||||
(blockInChunk.y == min && face == NEG_Y) ||
|
||||
(blockInChunk.y == max && face == POS_Y) ||
|
||||
(blockInChunk.z == min && face == NEG_Z) ||
|
||||
(blockInChunk.z == max && face == POS_Z);
|
||||
AbsFace absFace = face.resolve(getUp());
|
||||
return (blockInChunk.x == min && absFace == AbsFace.NEG_X) ||
|
||||
(blockInChunk.x == max && absFace == AbsFace.POS_X) ||
|
||||
(blockInChunk.y == min && absFace == AbsFace.NEG_Y) ||
|
||||
(blockInChunk.y == max && absFace == AbsFace.POS_Y) ||
|
||||
(blockInChunk.z == min && absFace == AbsFace.NEG_Z) ||
|
||||
(blockInChunk.z == max && absFace == AbsFace.POS_Z);
|
||||
}
|
||||
|
||||
public void forEachBlock(Consumer<Vec3i> action) {
|
||||
@ -221,10 +232,6 @@ public class ChunkData
|
||||
this.listeners.remove(listener);
|
||||
}
|
||||
|
||||
private static String str(Vec3i v) {
|
||||
return "(" + v.x + "; " + v.y + "; " + v.z + ")";
|
||||
}
|
||||
|
||||
protected void onLoaded() {
|
||||
getListeners().forEach(l -> l.onChunkLoaded(this));
|
||||
}
|
||||
@ -309,11 +316,11 @@ public class ChunkData
|
||||
* Potentially shared
|
||||
*/
|
||||
private final Vec3i blockInChunk;
|
||||
private final AbsFace face;
|
||||
private final RelFace face;
|
||||
|
||||
public TileDataStackImpl(Vec3i blockInChunk, AbsFace face) {
|
||||
public TileDataStackImpl(Vec3i blockInChunk, BlockFace face) {
|
||||
this.blockInChunk = blockInChunk;
|
||||
this.face = face;
|
||||
this.face = face.relativize(getUp());
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -325,7 +332,7 @@ public class ChunkData
|
||||
}
|
||||
|
||||
@Override
|
||||
public AbsFace getFace() {
|
||||
public RelFace getFace() {
|
||||
return face;
|
||||
}
|
||||
|
||||
@ -389,7 +396,7 @@ public class ChunkData
|
||||
references[index] = null;
|
||||
|
||||
for (int tag = 0; tag < indicesByTag.length; ++tag) {
|
||||
if (tagsByIndex[tag] == -1) {
|
||||
if (indicesByTag[tag] == -1) {
|
||||
indicesByTag[tag] = index;
|
||||
tagsByIndex[index] = tag;
|
||||
break;
|
||||
@ -405,21 +412,29 @@ public class ChunkData
|
||||
@Override
|
||||
public void load(TileData tile, int tag) {
|
||||
addFarthest(tile);
|
||||
|
||||
int assignedTag = getIndexByTag(tag);
|
||||
|
||||
if (assignedTag == tag)
|
||||
|
||||
int assignedIndex = size() - 1;
|
||||
|
||||
// Skip if we already have the correct tag
|
||||
int assignedTag = getTagByIndex(assignedIndex);
|
||||
if (assignedTag == tag) {
|
||||
return;
|
||||
if (assignedTag == -1) {
|
||||
}
|
||||
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 " + getIndexByTag(tag)
|
||||
"Tag " + tag + " already used by tile at index " + tileWithRequestedTag
|
||||
);
|
||||
}
|
||||
assert tileWithRequestedTag != assignedIndex : "tag == assignedTag yet tileWithRequestedTag != assignedIndex";
|
||||
|
||||
indicesByTag[tagsByIndex[size() - 1]] = -1;
|
||||
tagsByIndex[size() - 1] = tag;
|
||||
indicesByTag[tag] = size() - 1;
|
||||
|
||||
// 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();
|
||||
}
|
||||
|
||||
|
@ -20,7 +20,7 @@ package ru.windcorp.progressia.common.world;
|
||||
|
||||
import glm.vec._3.i.Vec3i;
|
||||
import ru.windcorp.progressia.common.world.block.BlockData;
|
||||
import ru.windcorp.progressia.common.world.rels.AbsFace;
|
||||
import ru.windcorp.progressia.common.world.rels.RelFace;
|
||||
import ru.windcorp.progressia.common.world.tile.TileData;
|
||||
|
||||
public interface ChunkDataListener {
|
||||
@ -55,7 +55,7 @@ public interface ChunkDataListener {
|
||||
default void onChunkTilesChanged(
|
||||
ChunkData chunk,
|
||||
Vec3i blockInChunk,
|
||||
AbsFace face,
|
||||
RelFace face,
|
||||
TileData tile,
|
||||
boolean wasAdded
|
||||
) {
|
||||
|
@ -25,19 +25,64 @@ import ru.windcorp.progressia.common.util.VectorUtil;
|
||||
import ru.windcorp.progressia.common.util.Vectors;
|
||||
import ru.windcorp.progressia.common.world.Coordinates;
|
||||
import ru.windcorp.progressia.common.world.rels.AbsFace;
|
||||
import ru.windcorp.progressia.common.world.rels.BlockFace;
|
||||
import ru.windcorp.progressia.common.world.rels.RelRelation;
|
||||
|
||||
public interface GenericChunk<Self extends GenericChunk<Self, B, T, TS>, B extends GenericBlock, T extends GenericTile, TS extends GenericTileStack<TS, T, Self>> {
|
||||
|
||||
public static final int BLOCKS_PER_CHUNK = Coordinates.CHUNK_SIZE;
|
||||
|
||||
Vec3i getPosition();
|
||||
|
||||
AbsFace getUp();
|
||||
|
||||
B getBlock(Vec3i blockInChunk);
|
||||
|
||||
TS getTiles(Vec3i blockInChunk, AbsFace face);
|
||||
|
||||
boolean hasTiles(Vec3i blockInChunk, AbsFace face);
|
||||
TS getTiles(Vec3i blockInChunk, BlockFace face);
|
||||
|
||||
boolean hasTiles(Vec3i blockInChunk, BlockFace face);
|
||||
|
||||
default Vec3i resolve(Vec3i relativeBlockInChunk, Vec3i output) {
|
||||
if (output == null) {
|
||||
output = new Vec3i();
|
||||
}
|
||||
|
||||
final int offset = BLOCKS_PER_CHUNK - 1;
|
||||
|
||||
output.set(relativeBlockInChunk.x, relativeBlockInChunk.y, relativeBlockInChunk.z);
|
||||
output.mul(2).sub(offset);
|
||||
|
||||
RelRelation.resolve(output, getUp(), output);
|
||||
|
||||
output.add(offset).div(2);
|
||||
|
||||
return output;
|
||||
}
|
||||
|
||||
default B getBlockRel(Vec3i relativeBlockInChunk) {
|
||||
Vec3i absoluteBlockInChunk = Vectors.grab3i();
|
||||
resolve(relativeBlockInChunk, absoluteBlockInChunk);
|
||||
B result = getBlock(absoluteBlockInChunk);
|
||||
Vectors.release(absoluteBlockInChunk);
|
||||
return result;
|
||||
}
|
||||
|
||||
default TS getTilesRel(Vec3i relativeBlockInChunk, BlockFace face) {
|
||||
Vec3i absoluteBlockInChunk = Vectors.grab3i();
|
||||
resolve(relativeBlockInChunk, absoluteBlockInChunk);
|
||||
TS result = getTiles(absoluteBlockInChunk, face);
|
||||
Vectors.release(absoluteBlockInChunk);
|
||||
return result;
|
||||
}
|
||||
|
||||
default boolean hasTilesRel(Vec3i relativeBlockInChunk, BlockFace face) {
|
||||
Vec3i absoluteBlockInChunk = Vectors.grab3i();
|
||||
resolve(relativeBlockInChunk, absoluteBlockInChunk);
|
||||
boolean result = hasTiles(absoluteBlockInChunk, face);
|
||||
Vectors.release(absoluteBlockInChunk);
|
||||
return result;
|
||||
}
|
||||
|
||||
default int getX() {
|
||||
return getPosition().x;
|
||||
}
|
||||
@ -182,12 +227,29 @@ public interface GenericChunk<Self extends GenericChunk<Self, B, T, TS>, B exten
|
||||
);
|
||||
}
|
||||
|
||||
default TS getTilesOrNull(Vec3i blockInChunk, AbsFace face) {
|
||||
default TS getTilesOrNull(Vec3i blockInChunk, BlockFace face) {
|
||||
if (hasTiles(blockInChunk, face)) {
|
||||
return getTiles(blockInChunk, face);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
default TS getTilesOrNullRel(Vec3i relativeBlockInChunk, BlockFace face) {
|
||||
Vec3i absoluteBlockInChunk = Vectors.grab3i();
|
||||
resolve(relativeBlockInChunk, absoluteBlockInChunk);
|
||||
|
||||
TS result;
|
||||
|
||||
if (hasTiles(absoluteBlockInChunk, face)) {
|
||||
result = getTiles(absoluteBlockInChunk, face);
|
||||
} else {
|
||||
result = null;
|
||||
}
|
||||
|
||||
Vectors.release(absoluteBlockInChunk);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -25,7 +25,7 @@ import java.util.function.Consumer;
|
||||
|
||||
import glm.vec._3.i.Vec3i;
|
||||
import ru.windcorp.progressia.common.world.Coordinates;
|
||||
import ru.windcorp.progressia.common.world.rels.AbsFace;
|
||||
import ru.windcorp.progressia.common.world.rels.RelFace;
|
||||
|
||||
public abstract class GenericTileStack<Self extends GenericTileStack<Self, T, C>, T extends GenericTile, C extends GenericChunk<C, ?, T, Self>>
|
||||
extends AbstractList<T>
|
||||
@ -41,7 +41,7 @@ public abstract class GenericTileStack<Self extends GenericTileStack<Self, T, C>
|
||||
|
||||
public abstract C getChunk();
|
||||
|
||||
public abstract AbsFace getFace();
|
||||
public abstract RelFace getFace();
|
||||
|
||||
public Vec3i getBlockInWorld(Vec3i output) {
|
||||
// This is safe
|
||||
|
@ -27,6 +27,7 @@ import glm.vec._3.i.Vec3i;
|
||||
import ru.windcorp.progressia.common.util.Vectors;
|
||||
import ru.windcorp.progressia.common.world.Coordinates;
|
||||
import ru.windcorp.progressia.common.world.rels.AbsFace;
|
||||
import ru.windcorp.progressia.common.world.rels.BlockFace;
|
||||
|
||||
public interface GenericWorld<B extends GenericBlock, T extends GenericTile, TS extends GenericTileStack<TS, T, C>, C extends GenericChunk<C, B, T, TS>, E extends GenericEntity> {
|
||||
|
||||
@ -47,6 +48,10 @@ public interface GenericWorld<B extends GenericBlock, T extends GenericTile, TS
|
||||
Vectors.release(chunkCoords);
|
||||
return result;
|
||||
}
|
||||
|
||||
default AbsFace getUp(Vec3i blockInWorld) {
|
||||
return getChunkByBlock(blockInWorld).getUp();
|
||||
}
|
||||
|
||||
default B getBlock(Vec3i blockInWorld) {
|
||||
Vec3i v = Vectors.grab3i();
|
||||
@ -63,7 +68,7 @@ public interface GenericWorld<B extends GenericBlock, T extends GenericTile, TS
|
||||
return result;
|
||||
}
|
||||
|
||||
default TS getTiles(Vec3i blockInWorld, AbsFace face) {
|
||||
default TS getTiles(Vec3i blockInWorld, BlockFace face) {
|
||||
Vec3i v = Vectors.grab3i();
|
||||
TS result;
|
||||
|
||||
@ -78,7 +83,7 @@ public interface GenericWorld<B extends GenericBlock, T extends GenericTile, TS
|
||||
return result;
|
||||
}
|
||||
|
||||
default TS getTilesOrNull(Vec3i blockInWorld, AbsFace face) {
|
||||
default TS getTilesOrNull(Vec3i blockInWorld, BlockFace face) {
|
||||
Vec3i v = Vectors.grab3i();
|
||||
TS result;
|
||||
|
||||
@ -93,7 +98,7 @@ public interface GenericWorld<B extends GenericBlock, T extends GenericTile, TS
|
||||
return result;
|
||||
}
|
||||
|
||||
default boolean hasTiles(Vec3i blockInWorld, AbsFace face) {
|
||||
default boolean hasTiles(Vec3i blockInWorld, BlockFace face) {
|
||||
Vec3i v = Vectors.grab3i();
|
||||
boolean result;
|
||||
|
||||
@ -108,7 +113,7 @@ public interface GenericWorld<B extends GenericBlock, T extends GenericTile, TS
|
||||
return result;
|
||||
}
|
||||
|
||||
default T getTile(Vec3i blockInWorld, AbsFace face, int layer) {
|
||||
default T getTile(Vec3i blockInWorld, BlockFace face, int layer) {
|
||||
TS stack = getTilesOrNull(blockInWorld, face);
|
||||
if (stack == null || stack.size() <= layer)
|
||||
return null;
|
||||
|
@ -26,7 +26,7 @@ import com.google.common.collect.ImmutableMap;
|
||||
import glm.vec._3.Vec3;
|
||||
import glm.vec._3.i.Vec3i;
|
||||
|
||||
public final class AbsFace extends AbsRelation {
|
||||
public final class AbsFace extends AbsRelation implements BlockFace {
|
||||
|
||||
// @formatter:off
|
||||
public static final AbsFace
|
||||
@ -52,7 +52,6 @@ public final class AbsFace extends AbsRelation {
|
||||
private static final ImmutableList<AbsFace> SECONDARY_FACES = ALL_FACES.stream().filter(AbsFace::isSecondary)
|
||||
.collect(ImmutableList.toImmutableList());
|
||||
|
||||
public static final int BLOCK_FACE_COUNT = ALL_FACES.size();
|
||||
public static final int PRIMARY_BLOCK_FACE_COUNT = PRIMARY_FACES.size();
|
||||
public static final int SECONDARY_BLOCK_FACE_COUNT = SECONDARY_FACES.size();
|
||||
|
||||
@ -226,6 +225,16 @@ public final class AbsFace extends AbsRelation {
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
@Override
|
||||
public AbsFace resolve(AbsFace up) {
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public RelFace relativize(AbsFace up) {
|
||||
return BlockFaceResolver.relativize(this, up);
|
||||
}
|
||||
|
||||
public boolean isPrimary() {
|
||||
return isPrimary;
|
||||
|
@ -41,6 +41,18 @@ public class AbsRelation extends BlockRelation {
|
||||
this(vector.x, vector.y, vector.z);
|
||||
}
|
||||
|
||||
public static AbsRelation of(Vec3i vector) {
|
||||
return of(vector.x, vector.y, vector.z);
|
||||
}
|
||||
|
||||
public static AbsRelation of(int x, int y, int z) {
|
||||
if (Math.abs(x) + Math.abs(y) + Math.abs(z) == 1) {
|
||||
return AbsFace.roundToFace(x, y, z);
|
||||
}
|
||||
|
||||
return new AbsRelation(x, y, z);
|
||||
}
|
||||
|
||||
@Override
|
||||
public AbsRelation resolve(AbsFace up) {
|
||||
return this;
|
||||
|
@ -0,0 +1,42 @@
|
||||
/*
|
||||
* 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.rels;
|
||||
|
||||
import glm.vec._3.Vec3;
|
||||
import glm.vec._3.i.Vec3i;
|
||||
|
||||
public interface BlockFace {
|
||||
|
||||
public static final int BLOCK_FACE_COUNT = 6;
|
||||
|
||||
AbsFace resolve(AbsFace up);
|
||||
RelFace relativize(AbsFace up);
|
||||
|
||||
public default Vec3i getVector(AbsFace up) {
|
||||
return resolve(up).getVector();
|
||||
}
|
||||
|
||||
public default Vec3 getFloatVector(AbsFace up) {
|
||||
return resolve(up).getFloatVector();
|
||||
}
|
||||
|
||||
public default Vec3 getNormalized(AbsFace up) {
|
||||
return resolve(up).getNormalized();
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,78 @@
|
||||
/*
|
||||
* 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.rels;
|
||||
|
||||
import java.util.Objects;
|
||||
|
||||
import static ru.windcorp.progressia.common.world.rels.AbsFace.BLOCK_FACE_COUNT;
|
||||
|
||||
public class BlockFaceResolver {
|
||||
|
||||
/**
|
||||
* A mapping from (up; relative) to absolute. Face IDs are used as keys.
|
||||
*/
|
||||
private static final AbsFace[][] RESOLUTION_TABLE = new AbsFace[BLOCK_FACE_COUNT][BLOCK_FACE_COUNT];
|
||||
|
||||
/**
|
||||
* A mapping from (up; absolute) to relative. Face IDs are used as keys.
|
||||
*/
|
||||
private static final RelFace[][] RELATIVIZATION_TABLE = new RelFace[BLOCK_FACE_COUNT][BLOCK_FACE_COUNT];
|
||||
|
||||
static {
|
||||
for (AbsFace up : AbsFace.getFaces()) {
|
||||
for (RelFace relative : RelFace.getFaces()) {
|
||||
|
||||
AbsFace absolute = (AbsFace) AbsRelation.of(RelRelation.resolve(relative.getRelVector(), up, null));
|
||||
|
||||
RESOLUTION_TABLE[up.getId()][relative.getId()] = absolute;
|
||||
RELATIVIZATION_TABLE[up.getId()][absolute.getId()] = relative;
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static AbsFace resolve(RelFace relative, AbsFace up) {
|
||||
Objects.requireNonNull(relative, "relative");
|
||||
Objects.requireNonNull(up, "up");
|
||||
|
||||
if (relative == RelFace.UP) {
|
||||
return up;
|
||||
} else if (relative == RelFace.DOWN) {
|
||||
return up.getCounter();
|
||||
}
|
||||
|
||||
return RESOLUTION_TABLE[up.getId()][relative.getId()];
|
||||
}
|
||||
|
||||
public static RelFace relativize(AbsFace absolute, AbsFace up) {
|
||||
Objects.requireNonNull(absolute, "absolute");
|
||||
Objects.requireNonNull(up, "up");
|
||||
|
||||
if (absolute == up) {
|
||||
return RelFace.UP;
|
||||
} else if (absolute.getCounter() == up) {
|
||||
return RelFace.DOWN;
|
||||
}
|
||||
|
||||
return RELATIVIZATION_TABLE[up.getId()][absolute.getId()];
|
||||
}
|
||||
|
||||
private BlockFaceResolver() {
|
||||
}
|
||||
|
||||
}
|
@ -22,7 +22,7 @@ import com.google.common.collect.ImmutableMap;
|
||||
|
||||
import glm.vec._3.i.Vec3i;
|
||||
|
||||
public class RelFace extends RelRelation {
|
||||
public class RelFace extends RelRelation implements BlockFace {
|
||||
|
||||
// @formatter:off
|
||||
public static final RelFace
|
||||
@ -76,7 +76,7 @@ public class RelFace extends RelRelation {
|
||||
private RelFace counterFace;
|
||||
|
||||
private RelFace(int x, int y, int z, String name) {
|
||||
super(x, y, z, true);
|
||||
super(x, y, z, false);
|
||||
this.id = nextId++;
|
||||
this.name = name;
|
||||
}
|
||||
@ -84,6 +84,24 @@ public class RelFace extends RelRelation {
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
@Override
|
||||
public AbsFace resolve(AbsFace up) {
|
||||
return BlockFaceResolver.resolve(this, up);
|
||||
}
|
||||
|
||||
@Override
|
||||
public RelFace relativize(AbsFace up) {
|
||||
return this;
|
||||
}
|
||||
|
||||
public RelFace rotate(AbsFace fromUp, AbsFace toUp) {
|
||||
if (fromUp == toUp) {
|
||||
return this;
|
||||
}
|
||||
|
||||
return resolve(fromUp).relativize(toUp);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the id
|
||||
@ -97,7 +115,7 @@ public class RelFace extends RelRelation {
|
||||
}
|
||||
|
||||
public RelFace getCounterAndMoveCursor(Vec3i cursor) {
|
||||
cursor.add(getVector());
|
||||
cursor.add(getRelVector());
|
||||
return counterFace;
|
||||
}
|
||||
|
||||
|
@ -19,8 +19,12 @@ package ru.windcorp.progressia.common.world.rels;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
import glm.mat._3.Mat3;
|
||||
import glm.mat._4.Mat4;
|
||||
import glm.vec._3.Vec3;
|
||||
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.util.VectorUtil.SignedAxis;
|
||||
|
||||
import static ru.windcorp.progressia.common.util.VectorUtil.SignedAxis.*;
|
||||
@ -35,20 +39,64 @@ public class RelRelation extends BlockRelation {
|
||||
private final SignedAxis westDestination;
|
||||
private final SignedAxis upDestination;
|
||||
|
||||
public Rotation(SignedAxis northDestination, SignedAxis westDestination, SignedAxis upDestination) {
|
||||
private final Mat3 resolutionMatrix3 = new Mat3();
|
||||
private final Mat4 resolutionMatrix4 = new Mat4();
|
||||
|
||||
private final Mat3 relativizationMatrix3 = new Mat3();
|
||||
private final Mat4 relativizationMatrix4 = new Mat4();
|
||||
|
||||
private Rotation(SignedAxis northDestination, SignedAxis westDestination, SignedAxis upDestination) {
|
||||
this.northDestination = northDestination;
|
||||
this.westDestination = westDestination;
|
||||
this.upDestination = upDestination;
|
||||
|
||||
resolutionMatrix3.c0(apply(null, new Vec3(1, 0, 0)));
|
||||
resolutionMatrix3.c1(apply(null, new Vec3(0, 1, 0)));
|
||||
resolutionMatrix3.c2(apply(null, new Vec3(0, 0, 1)));
|
||||
resolutionMatrix3.toMat4(resolutionMatrix4);
|
||||
|
||||
relativizationMatrix3.set(resolutionMatrix3).transpose();
|
||||
relativizationMatrix4.set(resolutionMatrix4).transpose();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the resolutionMatrix3
|
||||
*/
|
||||
public Mat3 getResolutionMatrix3() {
|
||||
return resolutionMatrix3;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the resolutionMatrix4
|
||||
*/
|
||||
public Mat4 getResolutionMatrix4() {
|
||||
return resolutionMatrix4;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the relativizationMatrix3
|
||||
*/
|
||||
public Mat3 getRelativizationMatrix3() {
|
||||
return relativizationMatrix3;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the relativizationMatrix4
|
||||
*/
|
||||
public Mat4 getRelativizationMatrix4() {
|
||||
return relativizationMatrix4;
|
||||
}
|
||||
|
||||
public Vec3i apply(Vec3i output, Vec3i input) {
|
||||
if (output == null) {
|
||||
return output;
|
||||
output = new Vec3i();
|
||||
}
|
||||
|
||||
set(output, input.x, northDestination);
|
||||
set(output, input.y, westDestination);
|
||||
set(output, input.z, upDestination);
|
||||
int inX = input.x, inY = input.y, inZ = input.z;
|
||||
|
||||
set(output, inX, northDestination);
|
||||
set(output, inY, westDestination);
|
||||
set(output, inZ, upDestination);
|
||||
|
||||
return output;
|
||||
}
|
||||
@ -56,6 +104,24 @@ public class RelRelation extends BlockRelation {
|
||||
private static void set(Vec3i output, int value, SignedAxis axis) {
|
||||
VectorUtil.set(output, axis.getAxis(), axis.isPositive() ? +value : -value);
|
||||
}
|
||||
|
||||
public Vec3 apply(Vec3 output, Vec3 input) {
|
||||
if (output == null) {
|
||||
output = new Vec3();
|
||||
}
|
||||
|
||||
float inX = input.x, inY = input.y, inZ = input.z;
|
||||
|
||||
set(output, inX, northDestination);
|
||||
set(output, inY, westDestination);
|
||||
set(output, inZ, upDestination);
|
||||
|
||||
return output;
|
||||
}
|
||||
|
||||
private static void set(Vec3 output, float value, SignedAxis axis) {
|
||||
VectorUtil.set(output, axis.getAxis(), axis.isPositive() ? +value : -value);
|
||||
}
|
||||
}
|
||||
|
||||
private final static Map<AbsFace, Rotation> TRANSFORMATIONS = AbsFace.mapToFaces(
|
||||
@ -68,14 +134,27 @@ public class RelRelation extends BlockRelation {
|
||||
);
|
||||
|
||||
private final Vec3i vector = new Vec3i();
|
||||
private final Vec3 floatVector = new Vec3();
|
||||
private final Vec3 normalized = new Vec3();
|
||||
|
||||
private AbsRelation[] resolved = null;
|
||||
|
||||
public RelRelation(int north, int west, int up) {
|
||||
this(north, west, up, false);
|
||||
}
|
||||
|
||||
public RelRelation(Vec3i vector) {
|
||||
this(vector.x, vector.y, vector.z, false);
|
||||
}
|
||||
|
||||
protected RelRelation(int north, int west, int up, boolean precomputeAllResolutions) {
|
||||
vector.set(north, west, up);
|
||||
floatVector.set(north, west, up);
|
||||
normalized.set(north, west, up);
|
||||
|
||||
if (normalized.any()) {
|
||||
normalized.normalize();
|
||||
}
|
||||
|
||||
if (precomputeAllResolutions) {
|
||||
for (AbsFace face : AbsFace.getFaces()) {
|
||||
@ -84,13 +163,46 @@ public class RelRelation extends BlockRelation {
|
||||
}
|
||||
}
|
||||
|
||||
public static RelRelation of(Vec3i vector) {
|
||||
return of(vector.x, vector.y, vector.z);
|
||||
}
|
||||
|
||||
public static RelRelation of(int north, int west, int up) {
|
||||
if (Math.abs(north) + Math.abs(west) + Math.abs(up) == 1) {
|
||||
if (up == 1) {
|
||||
return RelFace.UP;
|
||||
} else if (up == -1) {
|
||||
return RelFace.DOWN;
|
||||
} else if (north == 1) {
|
||||
return RelFace.NORTH;
|
||||
} else if (north == -1) {
|
||||
return RelFace.SOUTH;
|
||||
} else if (west == 1) {
|
||||
return RelFace.WEST;
|
||||
} else {
|
||||
assert west == -1;
|
||||
return RelFace.EAST;
|
||||
}
|
||||
}
|
||||
|
||||
return new RelRelation(north, west, up);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the relative vector (northward, westward, upward)
|
||||
*/
|
||||
public Vec3i getVector() {
|
||||
public Vec3i getRelVector() {
|
||||
return vector;
|
||||
}
|
||||
|
||||
public Vec3 getRelFloatVector() {
|
||||
return floatVector;
|
||||
}
|
||||
|
||||
public Vec3 getRelNormalized() {
|
||||
return normalized;
|
||||
}
|
||||
|
||||
public int getNorthward() {
|
||||
return vector.x;
|
||||
}
|
||||
@ -129,12 +241,43 @@ public class RelRelation extends BlockRelation {
|
||||
}
|
||||
|
||||
private AbsRelation computeResolution(AbsFace up) {
|
||||
return new AbsRelation(TRANSFORMATIONS.get(up).apply(new Vec3i(), vector));
|
||||
Vec3i resolution = Vectors.grab3i();
|
||||
resolve(vector, up, resolution);
|
||||
AbsRelation result = AbsRelation.of(resolution);
|
||||
Vectors.release(resolution);
|
||||
return result;
|
||||
}
|
||||
|
||||
public static Vec3i resolve(Vec3i relative, AbsFace up, Vec3i output) {
|
||||
if (output == null) {
|
||||
output = new Vec3i();
|
||||
}
|
||||
|
||||
TRANSFORMATIONS.get(up).apply(output, relative);
|
||||
|
||||
return output;
|
||||
}
|
||||
|
||||
public static Mat3 getResolutionMatrix3(AbsFace up) {
|
||||
return TRANSFORMATIONS.get(up).getResolutionMatrix3();
|
||||
}
|
||||
|
||||
public static Mat4 getResolutionMatrix4(AbsFace up) {
|
||||
return TRANSFORMATIONS.get(up).getResolutionMatrix4();
|
||||
}
|
||||
|
||||
|
||||
public static Mat3 getRelativizationMatrix3(AbsFace up) {
|
||||
return TRANSFORMATIONS.get(up).getRelativizationMatrix3();
|
||||
}
|
||||
|
||||
public static Mat4 getRelativizationMatrix4(AbsFace up) {
|
||||
return TRANSFORMATIONS.get(up).getRelativizationMatrix4();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Vec3i getSample() {
|
||||
return getVector();
|
||||
return getRelVector();
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -68,9 +68,9 @@ public class Server {
|
||||
this.chunkManager = new ChunkManager(this);
|
||||
this.entityManager = new EntityManager(this);
|
||||
|
||||
schedule(this::scheduleWorldTicks);
|
||||
schedule(chunkManager::tick);
|
||||
schedule(entityManager::tick);
|
||||
schedule(this::scheduleWorldTicks); // Must run after chunkManager so it only schedules chunks that hadn't unloaded
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -30,6 +30,8 @@ import ru.windcorp.progressia.common.world.ChunkData;
|
||||
import ru.windcorp.progressia.common.world.Coordinates;
|
||||
import ru.windcorp.progressia.common.world.generic.GenericChunk;
|
||||
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.TileReference;
|
||||
import ru.windcorp.progressia.server.world.block.BlockLogic;
|
||||
@ -66,6 +68,11 @@ public class ChunkLogic implements GenericChunk<ChunkLogic, BlockLogic, TileLogi
|
||||
public Vec3i getPosition() {
|
||||
return getData().getPosition();
|
||||
}
|
||||
|
||||
@Override
|
||||
public AbsFace getUp() {
|
||||
return getData().getUp();
|
||||
}
|
||||
|
||||
@Override
|
||||
public BlockLogic getBlock(Vec3i blockInChunk) {
|
||||
@ -75,12 +82,12 @@ public class ChunkLogic implements GenericChunk<ChunkLogic, BlockLogic, TileLogi
|
||||
}
|
||||
|
||||
@Override
|
||||
public TileLogicStack getTiles(Vec3i blockInChunk, AbsFace face) {
|
||||
public TileLogicStack getTiles(Vec3i blockInChunk, BlockFace face) {
|
||||
return getTileStackWrapper(getData().getTiles(blockInChunk, face));
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasTiles(Vec3i blockInChunk, AbsFace face) {
|
||||
public boolean hasTiles(Vec3i blockInChunk, BlockFace face) {
|
||||
return getData().hasTiles(blockInChunk, face);
|
||||
}
|
||||
|
||||
@ -149,7 +156,7 @@ public class ChunkLogic implements GenericChunk<ChunkLogic, BlockLogic, TileLogi
|
||||
}
|
||||
|
||||
@Override
|
||||
public AbsFace getFace() {
|
||||
public RelFace getFace() {
|
||||
return parent.getFace();
|
||||
}
|
||||
|
||||
|
@ -22,6 +22,7 @@ import java.util.function.Consumer;
|
||||
|
||||
import glm.vec._3.i.Vec3i;
|
||||
import ru.windcorp.progressia.common.world.ChunkData;
|
||||
import ru.windcorp.progressia.common.world.rels.AbsFace;
|
||||
import ru.windcorp.progressia.server.world.block.BlockTickContext;
|
||||
|
||||
public interface ChunkTickContext extends TickContext {
|
||||
@ -36,6 +37,10 @@ public interface ChunkTickContext extends TickContext {
|
||||
ChunkLogic chunkLogic = getChunkLogic();
|
||||
return chunkLogic == null ? null : chunkLogic.getData();
|
||||
}
|
||||
|
||||
default AbsFace getUp() {
|
||||
return getChunkData().getUp();
|
||||
}
|
||||
|
||||
default void forEachBlock(Consumer<BlockTickContext> action) {
|
||||
TickContextMutable context = TickContextMutable.uninitialized();
|
||||
|
@ -21,7 +21,7 @@ package ru.windcorp.progressia.server.world;
|
||||
import glm.vec._3.i.Vec3i;
|
||||
import ru.windcorp.progressia.common.util.crash.CrashReports;
|
||||
import ru.windcorp.progressia.common.world.entity.EntityData;
|
||||
import ru.windcorp.progressia.common.world.rels.AbsFace;
|
||||
import ru.windcorp.progressia.common.world.rels.BlockFace;
|
||||
import ru.windcorp.progressia.server.Server;
|
||||
import ru.windcorp.progressia.server.world.block.BlockLogic;
|
||||
import ru.windcorp.progressia.server.world.block.BlockTickContext;
|
||||
@ -61,17 +61,22 @@ public class TickAndUpdateUtil {
|
||||
}
|
||||
}
|
||||
|
||||
public static void tickTile(WorldLogic world, Vec3i blockInWorld, AbsFace face, int layer) {
|
||||
public static void tickTile(WorldLogic world, Vec3i blockInWorld, BlockFace face, int layer) {
|
||||
TileLogic tile = world.getTile(blockInWorld, face, layer);
|
||||
if (!(tile instanceof TickableTile))
|
||||
if (!(tile instanceof TickableTile)) {
|
||||
return;
|
||||
}
|
||||
|
||||
TileTickContext tickContext = TickContextMutable.start().withWorld(world).withBlock(blockInWorld).withFace(face)
|
||||
.withLayer(layer);
|
||||
tickTile((TickableTile) tile, tickContext);
|
||||
}
|
||||
|
||||
public static void tickTiles(WorldLogic world, Vec3i blockInWorld, AbsFace face) {
|
||||
public static void tickTiles(WorldLogic world, Vec3i blockInWorld, BlockFace face) {
|
||||
if (!world.isBlockLoaded(blockInWorld)) {
|
||||
return;
|
||||
}
|
||||
|
||||
TickContextMutable.start().withWorld(world).withBlock(blockInWorld).withFace(face).build()
|
||||
.forEachTile(context -> {
|
||||
TileLogic tile = context.getTile();
|
||||
@ -106,17 +111,22 @@ public class TickAndUpdateUtil {
|
||||
}
|
||||
}
|
||||
|
||||
public static void updateTile(WorldLogic world, Vec3i blockInWorld, AbsFace face, int layer) {
|
||||
public static void updateTile(WorldLogic world, Vec3i blockInWorld, BlockFace face, int layer) {
|
||||
TileLogic tile = world.getTile(blockInWorld, face, layer);
|
||||
if (!(tile instanceof UpdateableTile))
|
||||
if (!(tile instanceof UpdateableTile)) {
|
||||
return;
|
||||
}
|
||||
|
||||
TileTickContext tickContext = TickContextMutable.start().withWorld(world).withBlock(blockInWorld).withFace(face)
|
||||
.withLayer(layer);
|
||||
updateTile((UpdateableTile) tile, tickContext);
|
||||
}
|
||||
|
||||
public static void updateTiles(WorldLogic world, Vec3i blockInWorld, AbsFace face) {
|
||||
public static void updateTiles(WorldLogic world, Vec3i blockInWorld, BlockFace face) {
|
||||
if (!world.isBlockLoaded(blockInWorld)) {
|
||||
return;
|
||||
}
|
||||
|
||||
TickContextMutable.start().withWorld(world).withBlock(blockInWorld).withFace(face).build()
|
||||
.forEachTile(context -> {
|
||||
TileLogic tile = context.getTile();
|
||||
|
@ -15,7 +15,7 @@
|
||||
* 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.server.world;
|
||||
|
||||
import java.util.Objects;
|
||||
@ -26,7 +26,8 @@ import glm.vec._3.i.Vec3i;
|
||||
import ru.windcorp.progressia.common.world.ChunkData;
|
||||
import ru.windcorp.progressia.common.world.Coordinates;
|
||||
import ru.windcorp.progressia.common.world.generic.GenericTileStack;
|
||||
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.TileReference;
|
||||
import ru.windcorp.progressia.server.Server;
|
||||
@ -126,7 +127,7 @@ public abstract class TickContextMutable implements BlockTickContext, TSTickCont
|
||||
}
|
||||
|
||||
public static interface Block extends Builder {
|
||||
Builder.TileStack withFace(AbsFace face);
|
||||
Builder.TileStack withFace(BlockFace face);
|
||||
}
|
||||
|
||||
public static interface TileStack extends Builder {
|
||||
@ -148,7 +149,7 @@ public abstract class TickContextMutable implements BlockTickContext, TSTickCont
|
||||
protected Server server;
|
||||
protected final Vec3i chunk = new Vec3i();
|
||||
protected final Vec3i blockInWorld = new Vec3i();
|
||||
protected AbsFace face;
|
||||
protected RelFace face;
|
||||
protected int layer;
|
||||
|
||||
protected Role role = Role.NONE;
|
||||
@ -188,7 +189,7 @@ public abstract class TickContextMutable implements BlockTickContext, TSTickCont
|
||||
}
|
||||
|
||||
@Override
|
||||
public AbsFace getFace() {
|
||||
public RelFace getFace() {
|
||||
checkContextState(Role.TILE_STACK);
|
||||
return this.face;
|
||||
}
|
||||
@ -261,8 +262,9 @@ public abstract class TickContextMutable implements BlockTickContext, TSTickCont
|
||||
public TileStack withTS(GenericTileStack<?, ?, ?> tileStack) {
|
||||
Objects.requireNonNull(tileStack, "tileStack");
|
||||
|
||||
return withBlock(tileStack.getBlockInWorld(this.blockInWorld)).withFace(tileStack.getFace());
|
||||
// ^^^^^^^^^^^^^^^^^ This is safe
|
||||
return withBlock(
|
||||
tileStack.getBlockInWorld(this.blockInWorld) // This is safe
|
||||
).withFace(tileStack.getFace());
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -277,11 +279,11 @@ public abstract class TickContextMutable implements BlockTickContext, TSTickCont
|
||||
}
|
||||
|
||||
@Override
|
||||
public TileStack withFace(AbsFace face) {
|
||||
public TileStack withFace(BlockFace face) {
|
||||
Objects.requireNonNull(face, "face");
|
||||
checkBuilderState(Role.BLOCK);
|
||||
|
||||
this.face = face;
|
||||
this.face = face.relativize(server.getWorld().getChunk(chunk).getUp());
|
||||
|
||||
this.role = Role.TILE_STACK;
|
||||
return this;
|
||||
@ -339,12 +341,12 @@ public abstract class TickContextMutable implements BlockTickContext, TSTickCont
|
||||
@Override
|
||||
public void forEachFace(Consumer<TSTickContext> action) {
|
||||
checkContextState(Role.BLOCK);
|
||||
AbsFace previousFace = this.face;
|
||||
RelFace previousFace = this.face;
|
||||
Role previousRole = this.role;
|
||||
|
||||
this.role = Role.TILE_STACK;
|
||||
for (int i = 0; i < AbsFace.BLOCK_FACE_COUNT; ++i) {
|
||||
this.face = AbsFace.getFaces().get(i);
|
||||
for (int i = 0; i < BlockFace.BLOCK_FACE_COUNT; ++i) {
|
||||
this.face = RelFace.getFaces().get(i);
|
||||
action.accept(this);
|
||||
}
|
||||
|
||||
@ -393,11 +395,13 @@ public abstract class TickContextMutable implements BlockTickContext, TSTickCont
|
||||
Objects.requireNonNull(action, "action");
|
||||
checkContextState(Role.TILE_STACK);
|
||||
|
||||
this.blockInWorld.add(this.face.getVector());
|
||||
Vec3i vector = this.face.getVector(getUp());
|
||||
|
||||
this.blockInWorld.add(vector);
|
||||
this.face = this.face.getCounter();
|
||||
R result = action.apply(this);
|
||||
this.face = this.face.getCounter();
|
||||
this.blockInWorld.sub(this.face.getVector());
|
||||
this.blockInWorld.sub(vector);
|
||||
|
||||
return result;
|
||||
}
|
||||
@ -407,11 +411,13 @@ public abstract class TickContextMutable implements BlockTickContext, TSTickCont
|
||||
Objects.requireNonNull(action, "action");
|
||||
checkContextState(Role.TILE_STACK);
|
||||
|
||||
this.blockInWorld.add(this.face.getVector());
|
||||
Vec3i vector = this.face.getVector(getUp());
|
||||
|
||||
this.blockInWorld.add(vector);
|
||||
this.face = this.face.getCounter();
|
||||
action.accept(this);
|
||||
this.face = this.face.getCounter();
|
||||
this.blockInWorld.sub(this.face.getVector());
|
||||
this.blockInWorld.sub(vector);
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -23,7 +23,7 @@ import ru.windcorp.progressia.common.world.ChunkData;
|
||||
import ru.windcorp.progressia.common.world.ChunkDataListener;
|
||||
import ru.windcorp.progressia.common.world.Coordinates;
|
||||
import ru.windcorp.progressia.common.world.block.BlockData;
|
||||
import ru.windcorp.progressia.common.world.rels.AbsFace;
|
||||
import ru.windcorp.progressia.common.world.rels.RelFace;
|
||||
import ru.windcorp.progressia.common.world.tile.TileData;
|
||||
import ru.windcorp.progressia.server.Server;
|
||||
|
||||
@ -49,7 +49,7 @@ public class UpdateTriggerer implements ChunkDataListener {
|
||||
public void onChunkTilesChanged(
|
||||
ChunkData chunk,
|
||||
Vec3i blockInChunk,
|
||||
AbsFace face,
|
||||
RelFace face,
|
||||
TileData tile,
|
||||
boolean wasAdded
|
||||
) {
|
||||
|
@ -39,13 +39,8 @@ import ru.windcorp.progressia.server.world.tile.TileLogic;
|
||||
import ru.windcorp.progressia.server.world.tile.TileLogicStack;
|
||||
|
||||
public class WorldLogic
|
||||
implements GenericWorld<BlockLogic, TileLogic, TileLogicStack, ChunkLogic, EntityData // not
|
||||
// using
|
||||
// EntityLogic
|
||||
// because
|
||||
// it
|
||||
// is
|
||||
// stateless
|
||||
implements GenericWorld<BlockLogic, TileLogic, TileLogicStack, ChunkLogic, EntityData
|
||||
// not using EntityLogic because it is stateless
|
||||
> {
|
||||
|
||||
private final WorldData data;
|
||||
|
@ -20,7 +20,7 @@ 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.rels.AbsFace;
|
||||
import ru.windcorp.progressia.common.world.rels.RelFace;
|
||||
|
||||
public class BlockLogic extends Namespaced implements GenericBlock {
|
||||
|
||||
@ -28,11 +28,11 @@ public class BlockLogic extends Namespaced implements GenericBlock {
|
||||
super(id);
|
||||
}
|
||||
|
||||
public boolean isSolid(BlockTickContext context, AbsFace face) {
|
||||
public boolean isSolid(BlockTickContext context, RelFace face) {
|
||||
return isSolid(face);
|
||||
}
|
||||
|
||||
public boolean isSolid(AbsFace face) {
|
||||
public boolean isSolid(RelFace face) {
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -26,7 +26,7 @@ import glm.vec._3.i.Vec3i;
|
||||
import ru.windcorp.progressia.common.world.Coordinates;
|
||||
import ru.windcorp.progressia.common.world.block.BlockData;
|
||||
import ru.windcorp.progressia.common.world.rels.AbsFace;
|
||||
import ru.windcorp.progressia.common.world.rels.AbsRelation;
|
||||
import ru.windcorp.progressia.common.world.rels.BlockRelation;
|
||||
import ru.windcorp.progressia.server.world.ChunkTickContext;
|
||||
import ru.windcorp.progressia.server.world.TickContextMutable;
|
||||
import ru.windcorp.progressia.server.world.tile.TSTickContext;
|
||||
@ -67,9 +67,9 @@ public interface BlockTickContext extends ChunkTickContext {
|
||||
return TickContextMutable.copyWorld(this).withBlock(getBlockInWorld().add_(direction)).build();
|
||||
}
|
||||
|
||||
default BlockTickContext getNeighbor(AbsRelation relation) {
|
||||
default BlockTickContext getNeighbor(BlockRelation relation) {
|
||||
Objects.requireNonNull(relation, "relation");
|
||||
return getNeighbor(relation.getVector());
|
||||
return getNeighbor(relation.getVector(getChunkData().getUp()));
|
||||
}
|
||||
|
||||
default <R> R evalNeighbor(Vec3i direction, Function<BlockTickContext, R> action) {
|
||||
@ -78,10 +78,10 @@ public interface BlockTickContext extends ChunkTickContext {
|
||||
return action.apply(getNeighbor(direction));
|
||||
}
|
||||
|
||||
default <R> R evalNeighbor(AbsRelation relation, Function<BlockTickContext, R> action) {
|
||||
default <R> R evalNeighbor(BlockRelation relation, Function<BlockTickContext, R> action) {
|
||||
Objects.requireNonNull(action, "action");
|
||||
Objects.requireNonNull(relation, "relation");
|
||||
return evalNeighbor(relation.getVector(), action);
|
||||
return evalNeighbor(relation.getVector(getChunkData().getUp()), action);
|
||||
}
|
||||
|
||||
default void forNeighbor(Vec3i direction, Consumer<BlockTickContext> action) {
|
||||
@ -93,10 +93,10 @@ public interface BlockTickContext extends ChunkTickContext {
|
||||
});
|
||||
}
|
||||
|
||||
default void forNeighbor(AbsRelation relation, Consumer<BlockTickContext> action) {
|
||||
default void forNeighbor(BlockRelation relation, Consumer<BlockTickContext> action) {
|
||||
Objects.requireNonNull(action, "action");
|
||||
Objects.requireNonNull(relation, "relation");
|
||||
forNeighbor(relation.getVector(), action);
|
||||
forNeighbor(relation.getVector(getChunkData().getUp()), action);
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -25,7 +25,7 @@ import ru.windcorp.progressia.common.util.MultiLOC;
|
||||
import ru.windcorp.progressia.common.world.block.BlockData;
|
||||
import ru.windcorp.progressia.common.world.block.BlockDataRegistry;
|
||||
import ru.windcorp.progressia.common.world.entity.EntityData;
|
||||
import ru.windcorp.progressia.common.world.rels.AbsFace;
|
||||
import ru.windcorp.progressia.common.world.rels.BlockFace;
|
||||
import ru.windcorp.progressia.common.world.tile.TileData;
|
||||
import ru.windcorp.progressia.common.world.tile.TileDataRegistry;
|
||||
import ru.windcorp.progressia.server.Server;
|
||||
@ -64,19 +64,19 @@ public class WorldAccessor {
|
||||
setBlock(blockInWorld, BlockDataRegistry.getInstance().get(id));
|
||||
}
|
||||
|
||||
public void addTile(Vec3i blockInWorld, AbsFace face, TileData tile) {
|
||||
public void addTile(Vec3i blockInWorld, BlockFace face, TileData tile) {
|
||||
AddTile change = cache.grab(AddTile.class);
|
||||
change.getPacket().set(tile, blockInWorld, face);
|
||||
change.getPacket().set(tile, blockInWorld, face.resolve(server.getWorld().getUp(blockInWorld)));
|
||||
server.requestChange(change);
|
||||
}
|
||||
|
||||
public void addTile(Vec3i blockInWorld, AbsFace face, String id) {
|
||||
public void addTile(Vec3i blockInWorld, BlockFace face, String id) {
|
||||
addTile(blockInWorld, face, TileDataRegistry.getInstance().get(id));
|
||||
}
|
||||
|
||||
public void removeTile(Vec3i blockInWorld, AbsFace face, int tag) {
|
||||
public void removeTile(Vec3i blockInWorld, BlockFace face, int tag) {
|
||||
RemoveTile change = cache.grab(RemoveTile.class);
|
||||
change.getPacket().set(blockInWorld, face, tag);
|
||||
change.getPacket().set(blockInWorld, face.resolve(server.getWorld().getUp(blockInWorld)), tag);
|
||||
server.requestChange(change);
|
||||
}
|
||||
|
||||
@ -91,6 +91,7 @@ public class WorldAccessor {
|
||||
|
||||
public void tickBlock(Vec3i blockInWorld) {
|
||||
// TODO
|
||||
System.err.println("WorldAccessor.tickBlock(Vec3i) NYI!");
|
||||
}
|
||||
|
||||
/**
|
||||
@ -112,9 +113,9 @@ public class WorldAccessor {
|
||||
* @param face
|
||||
*/
|
||||
// TODO rename to something meaningful
|
||||
public void triggerUpdates(Vec3i blockInWorld, AbsFace face) {
|
||||
public void triggerUpdates(Vec3i blockInWorld, BlockFace face) {
|
||||
TileTriggeredUpdate evaluation = cache.grab(TileTriggeredUpdate.class);
|
||||
evaluation.init(blockInWorld, face);
|
||||
evaluation.init(blockInWorld, face.resolve(server.getWorld().getUp(blockInWorld)));
|
||||
server.requestEvaluation(evaluation);
|
||||
}
|
||||
|
||||
|
@ -23,7 +23,7 @@ import java.util.function.Consumer;
|
||||
import java.util.function.Function;
|
||||
|
||||
import ru.windcorp.progressia.common.world.ChunkData;
|
||||
import ru.windcorp.progressia.common.world.rels.AbsFace;
|
||||
import ru.windcorp.progressia.common.world.rels.RelFace;
|
||||
import ru.windcorp.progressia.common.world.tile.TileDataStack;
|
||||
import ru.windcorp.progressia.server.world.ChunkLogic;
|
||||
import ru.windcorp.progressia.server.world.TickContextMutable;
|
||||
@ -35,7 +35,7 @@ public interface TSTickContext extends BlockTickContext {
|
||||
* Specifications
|
||||
*/
|
||||
|
||||
AbsFace getFace();
|
||||
RelFace getFace();
|
||||
|
||||
/*
|
||||
* Getters
|
||||
@ -91,7 +91,7 @@ public interface TSTickContext extends BlockTickContext {
|
||||
|
||||
default TSTickContext getComplementary() {
|
||||
return TickContextMutable.copyWorld(this)
|
||||
.withBlock(getBlockInWorld().add_(getFace().getVector()))
|
||||
.withBlock(getBlockInWorld().add_(getFace().getVector(getUp())))
|
||||
.withFace(getFace().getCounter())
|
||||
.build();
|
||||
}
|
||||
|
@ -20,7 +20,7 @@ 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.rels.AbsFace;
|
||||
import ru.windcorp.progressia.common.world.rels.RelFace;
|
||||
|
||||
public class TileLogic extends Namespaced implements GenericTile {
|
||||
|
||||
@ -32,7 +32,7 @@ public class TileLogic extends Namespaced implements GenericTile {
|
||||
return canOccupyFace(context.getFace());
|
||||
}
|
||||
|
||||
public boolean canOccupyFace(AbsFace face) {
|
||||
public boolean canOccupyFace(RelFace face) {
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -18,7 +18,7 @@
|
||||
|
||||
package ru.windcorp.progressia.test;
|
||||
|
||||
import ru.windcorp.progressia.common.world.rels.AbsFace;
|
||||
import ru.windcorp.progressia.common.world.rels.RelFace;
|
||||
import ru.windcorp.progressia.server.world.block.BlockLogic;
|
||||
|
||||
public class TestBlockLogicAir extends BlockLogic {
|
||||
@ -28,7 +28,7 @@ public class TestBlockLogicAir extends BlockLogic {
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isSolid(AbsFace face) {
|
||||
public boolean isSolid(RelFace face) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -18,7 +18,7 @@
|
||||
|
||||
package ru.windcorp.progressia.test;
|
||||
|
||||
import ru.windcorp.progressia.common.world.rels.AbsFace;
|
||||
import ru.windcorp.progressia.common.world.rels.RelFace;
|
||||
import ru.windcorp.progressia.server.world.block.BlockLogic;
|
||||
|
||||
public class TestBlockLogicGlass extends BlockLogic {
|
||||
@ -28,7 +28,7 @@ public class TestBlockLogicGlass extends BlockLogic {
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isSolid(AbsFace face) {
|
||||
public boolean isSolid(RelFace face) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -39,7 +39,7 @@ import ru.windcorp.progressia.common.world.WorldData;
|
||||
import ru.windcorp.progressia.common.world.block.BlockData;
|
||||
import ru.windcorp.progressia.common.world.block.BlockDataRegistry;
|
||||
import ru.windcorp.progressia.common.world.io.ChunkCodec;
|
||||
import ru.windcorp.progressia.common.world.rels.AbsFace;
|
||||
import ru.windcorp.progressia.common.world.rels.RelFace;
|
||||
import ru.windcorp.progressia.common.world.tile.TileData;
|
||||
import ru.windcorp.progressia.common.world.tile.TileDataRegistry;
|
||||
|
||||
@ -91,6 +91,9 @@ public class TestChunkCodec extends ChunkCodec {
|
||||
TileData[] tilePalette = readTilePalette(input);
|
||||
|
||||
ChunkData chunk = new ChunkData(position, world);
|
||||
|
||||
assert chunk.getUp() == ru.windcorp.progressia.server.ServerState.getInstance().getWorld().getData().getChunk(position).getUp();
|
||||
|
||||
readBlocks(input, blockPalette, chunk);
|
||||
readTiles(input, tilePalette, chunk);
|
||||
|
||||
@ -138,7 +141,7 @@ public class TestChunkCodec extends ChunkCodec {
|
||||
break;
|
||||
|
||||
bic.set(xOrEndMarker, input.readByte() & 0xFF, input.readByte() & 0xFF);
|
||||
AbsFace face = AbsFace.getFaces().get(input.readByte() & 0xFF);
|
||||
RelFace face = RelFace.getFaces().get(input.readByte() & 0xFF);
|
||||
|
||||
int tiles = input.readByte() & 0xFF;
|
||||
|
||||
|
@ -137,9 +137,6 @@ public class TestContent {
|
||||
"Test:Log",
|
||||
getBlockTexture("LogTop"),
|
||||
getBlockTexture("LogTop"),
|
||||
getBlockTexture("LogSide"),
|
||||
getBlockTexture("LogSide"),
|
||||
getBlockTexture("LogSide"),
|
||||
getBlockTexture("LogSide")
|
||||
)
|
||||
);
|
||||
@ -159,7 +156,7 @@ public class TestContent {
|
||||
Set<String> placeableBlacklist = new HashSet<>();
|
||||
|
||||
register(new TileData("Test:Grass"));
|
||||
register(new TileRenderGrass("Test:Grass", getTileTexture("GrassTop"), getTileTexture("GrassSide")));
|
||||
register(new TestTileRenderGrass("Test:Grass", getTileTexture("GrassTop"), getTileTexture("GrassSide")));
|
||||
register(new TestTileLogicGrass("Test:Grass"));
|
||||
|
||||
register(new TileData("Test:Stones"));
|
||||
|
@ -78,14 +78,7 @@ public class TestEntityRenderJavapony extends EntityRender {
|
||||
b.addStaticPart(
|
||||
new PppBuilder(
|
||||
WorldRenderProgram.getDefault(),
|
||||
AbsFace.mapToFaces(
|
||||
tailStartTexture,
|
||||
tailStartTexture,
|
||||
tailStartTexture,
|
||||
tailStartTexture,
|
||||
tailStartTexture,
|
||||
tailStartTexture
|
||||
)
|
||||
tailStartTexture
|
||||
)
|
||||
.setOrigin(-60, -4, 14)
|
||||
.setDepth(32, 0, -16).setWidth(8).setHeight(8)
|
||||
@ -97,14 +90,7 @@ public class TestEntityRenderJavapony extends EntityRender {
|
||||
b.addStaticPart(
|
||||
new PppBuilder(
|
||||
WorldRenderProgram.getDefault(),
|
||||
AbsFace.mapToFaces(
|
||||
neckTexture,
|
||||
neckTexture,
|
||||
neckTexture,
|
||||
neckTexture,
|
||||
neckTexture,
|
||||
neckTexture
|
||||
)
|
||||
neckTexture
|
||||
)
|
||||
.setOrigin(0, -8, 8)
|
||||
.setWidth(16).setDepth(16).setHeight(2, 0, 16)
|
||||
|
@ -18,7 +18,7 @@
|
||||
|
||||
package ru.windcorp.progressia.test;
|
||||
|
||||
import ru.windcorp.progressia.common.world.rels.AbsFace;
|
||||
import ru.windcorp.progressia.common.world.rels.RelFace;
|
||||
import ru.windcorp.progressia.server.world.block.BlockLogic;
|
||||
import ru.windcorp.progressia.server.world.block.BlockTickContext;
|
||||
import ru.windcorp.progressia.server.world.ticking.TickingPolicy;
|
||||
@ -34,12 +34,12 @@ public class TestTileLogicGrass extends HangingTileLogic implements TickableTile
|
||||
|
||||
@Override
|
||||
public boolean canOccupyFace(TileTickContext context) {
|
||||
return context.getFace() != AbsFace.NEG_Z && super.canOccupyFace(context);
|
||||
return context.getFace() != RelFace.DOWN && super.canOccupyFace(context);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canOccupyFace(AbsFace face) {
|
||||
return face != AbsFace.NEG_Z;
|
||||
public boolean canOccupyFace(RelFace face) {
|
||||
return face != RelFace.DOWN;
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -50,7 +50,7 @@ public class TestTileLogicGrass extends HangingTileLogic implements TickableTile
|
||||
@Override
|
||||
public void tick(TileTickContext context) {
|
||||
if (!isLocationSuitable(context)) {
|
||||
context.removeThisTile();
|
||||
// context.removeThisTile();
|
||||
}
|
||||
}
|
||||
|
||||
@ -64,7 +64,7 @@ public class TestTileLogicGrass extends HangingTileLogic implements TickableTile
|
||||
}
|
||||
|
||||
private boolean isBlockAboveTransparent(BlockTickContext context) {
|
||||
return context.evalNeighbor(AbsFace.POS_Z, bctxt -> {
|
||||
return context.evalNeighbor(RelFace.UP, bctxt -> {
|
||||
BlockLogic block = bctxt.getBlock();
|
||||
if (block == null)
|
||||
return true;
|
||||
|
@ -16,17 +16,18 @@
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package ru.windcorp.progressia.client.world.tile;
|
||||
package ru.windcorp.progressia.test;
|
||||
|
||||
import ru.windcorp.progressia.client.graphics.texture.Texture;
|
||||
import ru.windcorp.progressia.common.world.rels.AbsFace;
|
||||
import ru.windcorp.progressia.client.world.tile.TileRenderSurface;
|
||||
import ru.windcorp.progressia.common.world.rels.RelFace;
|
||||
|
||||
public class TileRenderGrass extends TileRenderSurface {
|
||||
public class TestTileRenderGrass extends TileRenderSurface {
|
||||
|
||||
private final Texture topTexture;
|
||||
private final Texture sideTexture;
|
||||
|
||||
public TileRenderGrass(
|
||||
public TestTileRenderGrass(
|
||||
String id,
|
||||
Texture top,
|
||||
Texture side
|
||||
@ -37,13 +38,13 @@ public class TileRenderGrass extends TileRenderSurface {
|
||||
}
|
||||
|
||||
@Override
|
||||
public Texture getTexture(AbsFace face) {
|
||||
return (face == AbsFace.POS_Z) ? topTexture : sideTexture;
|
||||
public Texture getTexture(RelFace face) {
|
||||
return (face == RelFace.UP) ? topTexture : sideTexture;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isOpaque(AbsFace face) {
|
||||
return face == AbsFace.POS_Z;
|
||||
public boolean isOpaque(RelFace face) {
|
||||
return face == RelFace.UP;
|
||||
}
|
||||
|
||||
}
|
@ -30,14 +30,7 @@ public class TestGravityModel extends GravityModel {
|
||||
|
||||
@Override
|
||||
protected void doGetGravity(Vec3 pos, Vec3 output) {
|
||||
output.set(pos);
|
||||
|
||||
if (output.length() < 10) {
|
||||
output.set(0);
|
||||
return;
|
||||
}
|
||||
|
||||
output.normalize().mul(-9.8f);
|
||||
output.set(0, 0, -9.8f);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
Reference in New Issue
Block a user