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