Added tiles. Not yet optimized.
This commit is contained in:
parent
21a30e8b97
commit
60fbfa9578
@ -30,6 +30,7 @@ import ru.windcorp.progressia.client.graphics.texture.Atlases;
|
|||||||
import ru.windcorp.progressia.client.graphics.world.LayerWorld;
|
import ru.windcorp.progressia.client.graphics.world.LayerWorld;
|
||||||
import ru.windcorp.progressia.client.graphics.world.WorldRenderProgram;
|
import ru.windcorp.progressia.client.graphics.world.WorldRenderProgram;
|
||||||
import ru.windcorp.progressia.client.world.renders.BlockRenders;
|
import ru.windcorp.progressia.client.world.renders.BlockRenders;
|
||||||
|
import ru.windcorp.progressia.client.world.renders.TileRenders;
|
||||||
import ru.windcorp.progressia.common.resource.ResourceManager;
|
import ru.windcorp.progressia.common.resource.ResourceManager;
|
||||||
|
|
||||||
public class ClientProxy implements Proxy {
|
public class ClientProxy implements Proxy {
|
||||||
@ -47,6 +48,7 @@ public class ClientProxy implements Proxy {
|
|||||||
}
|
}
|
||||||
|
|
||||||
BlockRenders.registerTest();
|
BlockRenders.registerTest();
|
||||||
|
TileRenders.registerTest();
|
||||||
Atlases.loadAllAtlases();
|
Atlases.loadAllAtlases();
|
||||||
|
|
||||||
GUI.addBottomLayer(new LayerWorld());
|
GUI.addBottomLayer(new LayerWorld());
|
||||||
|
@ -11,13 +11,13 @@ class BlockFaceVectors {
|
|||||||
|
|
||||||
private static BlockFaceVectors createInner(BlockFaceVectors outer) {
|
private static BlockFaceVectors createInner(BlockFaceVectors outer) {
|
||||||
ImmutableMap.Builder<BlockFace, Vec3> originBuilder =
|
ImmutableMap.Builder<BlockFace, Vec3> originBuilder =
|
||||||
ImmutableMap.builderWithExpectedSize(count());
|
ImmutableMap.builder();
|
||||||
|
|
||||||
ImmutableMap.Builder<BlockFace, Vec3> widthBuilder =
|
ImmutableMap.Builder<BlockFace, Vec3> widthBuilder =
|
||||||
ImmutableMap.builderWithExpectedSize(count());
|
ImmutableMap.builder();
|
||||||
|
|
||||||
ImmutableMap.Builder<BlockFace, Vec3> heightBuilder =
|
ImmutableMap.Builder<BlockFace, Vec3> heightBuilder =
|
||||||
ImmutableMap.builderWithExpectedSize(count());
|
ImmutableMap.builder();
|
||||||
|
|
||||||
for (BlockFace face : getFaces()) {
|
for (BlockFace face : getFaces()) {
|
||||||
Vec3 width = outer.getWidth(face);
|
Vec3 width = outer.getWidth(face);
|
||||||
@ -43,7 +43,7 @@ class BlockFaceVectors {
|
|||||||
|
|
||||||
static {
|
static {
|
||||||
OUTER = new BlockFaceVectors(
|
OUTER = new BlockFaceVectors(
|
||||||
ImmutableMap.<BlockFace, Vec3>builderWithExpectedSize(count())
|
ImmutableMap.<BlockFace, Vec3>builder()
|
||||||
|
|
||||||
.put(TOP, new Vec3(-0.5f, +0.5f, +0.5f))
|
.put(TOP, new Vec3(-0.5f, +0.5f, +0.5f))
|
||||||
.put(BOTTOM, new Vec3(-0.5f, -0.5f, -0.5f))
|
.put(BOTTOM, new Vec3(-0.5f, -0.5f, -0.5f))
|
||||||
@ -54,7 +54,7 @@ class BlockFaceVectors {
|
|||||||
|
|
||||||
.build(),
|
.build(),
|
||||||
|
|
||||||
ImmutableMap.<BlockFace, Vec3>builderWithExpectedSize(count())
|
ImmutableMap.<BlockFace, Vec3>builder()
|
||||||
|
|
||||||
.put(TOP, new Vec3( 0, -1, 0))
|
.put(TOP, new Vec3( 0, -1, 0))
|
||||||
.put(BOTTOM, new Vec3( 0, +1, 0))
|
.put(BOTTOM, new Vec3( 0, +1, 0))
|
||||||
@ -65,7 +65,7 @@ class BlockFaceVectors {
|
|||||||
|
|
||||||
.build(),
|
.build(),
|
||||||
|
|
||||||
ImmutableMap.<BlockFace, Vec3>builderWithExpectedSize(count())
|
ImmutableMap.<BlockFace, Vec3>builder()
|
||||||
|
|
||||||
.put(TOP, new Vec3(+1, 0, 0))
|
.put(TOP, new Vec3(+1, 0, 0))
|
||||||
.put(BOTTOM, new Vec3(+1, 0, 0))
|
.put(BOTTOM, new Vec3(+1, 0, 0))
|
||||||
|
@ -18,9 +18,11 @@
|
|||||||
package ru.windcorp.progressia.client.world;
|
package ru.windcorp.progressia.client.world;
|
||||||
|
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
|
import java.util.List;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
import glm.mat._4.Mat4;
|
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.client.graphics.model.Model;
|
import ru.windcorp.progressia.client.graphics.model.Model;
|
||||||
import ru.windcorp.progressia.client.graphics.model.Shape;
|
import ru.windcorp.progressia.client.graphics.model.Shape;
|
||||||
@ -31,9 +33,14 @@ import ru.windcorp.progressia.client.graphics.model.StaticModel.Builder;
|
|||||||
import ru.windcorp.progressia.client.world.renders.BlockRender;
|
import ru.windcorp.progressia.client.world.renders.BlockRender;
|
||||||
import ru.windcorp.progressia.client.world.renders.BlockRenderNone;
|
import ru.windcorp.progressia.client.world.renders.BlockRenderNone;
|
||||||
import ru.windcorp.progressia.client.world.renders.BlockRenders;
|
import ru.windcorp.progressia.client.world.renders.BlockRenders;
|
||||||
|
import ru.windcorp.progressia.client.world.renders.TileRender;
|
||||||
|
import ru.windcorp.progressia.client.world.renders.TileRenders;
|
||||||
import ru.windcorp.progressia.client.world.renders.cro.ChunkRenderOptimizer;
|
import ru.windcorp.progressia.client.world.renders.cro.ChunkRenderOptimizer;
|
||||||
import ru.windcorp.progressia.client.world.renders.cro.ChunkRenderOptimizerSupplier;
|
import ru.windcorp.progressia.client.world.renders.cro.ChunkRenderOptimizerSupplier;
|
||||||
import ru.windcorp.progressia.client.world.renders.cro.ChunkRenderOptimizers;
|
import ru.windcorp.progressia.client.world.renders.cro.ChunkRenderOptimizers;
|
||||||
|
import ru.windcorp.progressia.common.block.BlockFace;
|
||||||
|
import ru.windcorp.progressia.common.block.TileData;
|
||||||
|
import ru.windcorp.progressia.common.util.Vectors;
|
||||||
import ru.windcorp.progressia.common.world.ChunkData;
|
import ru.windcorp.progressia.common.world.ChunkData;
|
||||||
|
|
||||||
public class ChunkRender {
|
public class ChunkRender {
|
||||||
@ -101,23 +108,8 @@ public class ChunkRender {
|
|||||||
for (int z = 0; z < ChunkData.BLOCKS_PER_CHUNK; ++z) {
|
for (int z = 0; z < ChunkData.BLOCKS_PER_CHUNK; ++z) {
|
||||||
cursor.set(x, y, z);
|
cursor.set(x, y, z);
|
||||||
|
|
||||||
BlockRender block = getBlock(cursor);
|
buildBlock(cursor, optimizers, builder);
|
||||||
|
buildBlockTiles(cursor, optimizers, builder);
|
||||||
if (block instanceof BlockRenderNone) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
forwardToOptimizers(block, x, y, z, optimizers);
|
|
||||||
|
|
||||||
if (!block.needsOwnRenderable()) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (tryToCreateRenderable(block, x, y, z, builder)) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
addRenderAsRenderable(block, x, y, z, builder);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -133,14 +125,41 @@ public class ChunkRender {
|
|||||||
needsUpdate = false;
|
needsUpdate = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void forwardToOptimizers(
|
private void buildBlock(
|
||||||
|
Vec3i cursor,
|
||||||
|
Collection<ChunkRenderOptimizer> optimizers,
|
||||||
|
Builder builder
|
||||||
|
) {
|
||||||
|
BlockRender block = getBlock(cursor);
|
||||||
|
int x = cursor.x;
|
||||||
|
int y = cursor.y;
|
||||||
|
int z = cursor.z;
|
||||||
|
|
||||||
|
if (block instanceof BlockRenderNone) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
forwardBlockToOptimizers(block, x, y, z, optimizers);
|
||||||
|
|
||||||
|
if (!block.needsOwnRenderable()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (tryToCreateBlockRenderable(block, x, y, z, builder)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
addBlockRenderAsRenderable(block, x, y, z, builder);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void forwardBlockToOptimizers(
|
||||||
BlockRender block, int x, int y, int z,
|
BlockRender block, int x, int y, int z,
|
||||||
Collection<ChunkRenderOptimizer> optimizers
|
Collection<ChunkRenderOptimizer> optimizers
|
||||||
) {
|
) {
|
||||||
optimizers.forEach(bro -> bro.processBlock(block, x, y, z));
|
optimizers.forEach(bro -> bro.processBlock(block, x, y, z));
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean tryToCreateRenderable(
|
private boolean tryToCreateBlockRenderable(
|
||||||
BlockRender block, int x, int y, int z,
|
BlockRender block, int x, int y, int z,
|
||||||
Builder builder
|
Builder builder
|
||||||
) {
|
) {
|
||||||
@ -154,7 +173,7 @@ public class ChunkRender {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void addRenderAsRenderable(
|
private void addBlockRenderAsRenderable(
|
||||||
BlockRender block, int x, int y, int z,
|
BlockRender block, int x, int y, int z,
|
||||||
Builder builder
|
Builder builder
|
||||||
) {
|
) {
|
||||||
@ -164,4 +183,66 @@ public class ChunkRender {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void buildBlockTiles(
|
||||||
|
Vec3i cursor,
|
||||||
|
Collection<ChunkRenderOptimizer> optimizers,
|
||||||
|
Builder builder
|
||||||
|
) {
|
||||||
|
for (BlockFace face : BlockFace.getFaces()) {
|
||||||
|
buildFaceTiles(cursor, face, optimizers, builder);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void buildFaceTiles(
|
||||||
|
Vec3i cursor, BlockFace face,
|
||||||
|
Collection<ChunkRenderOptimizer> optimizers,
|
||||||
|
Builder builder
|
||||||
|
) {
|
||||||
|
List<TileData> tiles = getData().getTilesOrNull(cursor, face);
|
||||||
|
|
||||||
|
if (tiles == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int layer = 0; layer < tiles.size(); ++layer) {
|
||||||
|
|
||||||
|
if (tiles.get(layer) == null) {
|
||||||
|
System.out.println(tiles.get(layer).getId());
|
||||||
|
}
|
||||||
|
|
||||||
|
buildTile(
|
||||||
|
cursor, face,
|
||||||
|
TileRenders.get(tiles.get(layer).getId()),
|
||||||
|
layer,
|
||||||
|
optimizers, builder
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void buildTile(
|
||||||
|
Vec3i cursor, BlockFace face,
|
||||||
|
TileRender tile,
|
||||||
|
int layer,
|
||||||
|
Collection<ChunkRenderOptimizer> optimizers,
|
||||||
|
Builder builder
|
||||||
|
) {
|
||||||
|
// TODO implement
|
||||||
|
|
||||||
|
Vec3 pos = Vectors.grab3().set(cursor.x, cursor.y, cursor.z);
|
||||||
|
|
||||||
|
Vec3 offset = Vectors.grab3().set(
|
||||||
|
face.getVector().x, face.getVector().y, face.getVector().z
|
||||||
|
);
|
||||||
|
|
||||||
|
pos.add(offset.mul(1f / 64));
|
||||||
|
|
||||||
|
builder.addPart(
|
||||||
|
tile.createRenderable(face),
|
||||||
|
new Mat4().identity().translate(pos)
|
||||||
|
);
|
||||||
|
|
||||||
|
Vectors.release(pos);
|
||||||
|
Vectors.release(offset);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,33 @@
|
|||||||
|
package ru.windcorp.progressia.client.world.renders;
|
||||||
|
|
||||||
|
import ru.windcorp.progressia.client.graphics.model.ShapeRenderHelper;
|
||||||
|
import ru.windcorp.progressia.client.graphics.model.WorldRenderable;
|
||||||
|
import ru.windcorp.progressia.client.world.renders.cro.ChunkRenderOptimizer;
|
||||||
|
import ru.windcorp.progressia.common.block.BlockFace;
|
||||||
|
import ru.windcorp.progressia.common.util.Namespaced;
|
||||||
|
|
||||||
|
public class TileRender extends Namespaced {
|
||||||
|
|
||||||
|
public TileRender(String namespace, String name) {
|
||||||
|
super(namespace, name);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void render(ShapeRenderHelper renderer, BlockFace face) {
|
||||||
|
throw new UnsupportedOperationException(
|
||||||
|
"TileRender.render() not implemented in " + this
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
public WorldRenderable createRenderable(BlockFace face) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean canBeOptimized(ChunkRenderOptimizer optimizer) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean needsOwnRenderable() {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,47 @@
|
|||||||
|
package ru.windcorp.progressia.client.world.renders;
|
||||||
|
|
||||||
|
import glm.vec._3.Vec3;
|
||||||
|
import ru.windcorp.progressia.client.graphics.backend.Usage;
|
||||||
|
import ru.windcorp.progressia.client.graphics.model.Faces;
|
||||||
|
import ru.windcorp.progressia.client.graphics.model.Shape;
|
||||||
|
import ru.windcorp.progressia.client.graphics.model.ShapeRenderProgram;
|
||||||
|
import ru.windcorp.progressia.client.graphics.model.WorldRenderable;
|
||||||
|
import ru.windcorp.progressia.client.graphics.texture.Texture;
|
||||||
|
import ru.windcorp.progressia.client.graphics.world.WorldRenderProgram;
|
||||||
|
import ru.windcorp.progressia.common.block.BlockFace;
|
||||||
|
import ru.windcorp.progressia.common.util.Vectors;
|
||||||
|
|
||||||
|
public class TileRenderSimple extends TileRender {
|
||||||
|
|
||||||
|
private final Texture texture;
|
||||||
|
|
||||||
|
public TileRenderSimple(String namespace, String name, Texture texture) {
|
||||||
|
super(namespace, name);
|
||||||
|
this.texture = texture;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Texture getTexture() {
|
||||||
|
return texture;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public WorldRenderable createRenderable(BlockFace face) {
|
||||||
|
ShapeRenderProgram program = WorldRenderProgram.getDefault();
|
||||||
|
|
||||||
|
Vec3 color = Vectors.grab3().set(1, 1, 1);
|
||||||
|
Vec3 center = Vectors.grab3().set(0, 0, 0);
|
||||||
|
|
||||||
|
try {
|
||||||
|
return new Shape(
|
||||||
|
Usage.STATIC, WorldRenderProgram.getDefault(),
|
||||||
|
Faces.createBlockFace(
|
||||||
|
program, texture, color, center, face, false
|
||||||
|
)
|
||||||
|
);
|
||||||
|
} finally {
|
||||||
|
Vectors.release(color);
|
||||||
|
Vectors.release(center);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,60 @@
|
|||||||
|
/*******************************************************************************
|
||||||
|
* Progressia
|
||||||
|
* Copyright (C) 2020 Wind Corporation
|
||||||
|
*
|
||||||
|
* 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.client.world.renders;
|
||||||
|
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
import ru.windcorp.progressia.client.graphics.texture.Atlases;
|
||||||
|
import ru.windcorp.progressia.client.graphics.texture.Atlases.AtlasGroup;
|
||||||
|
import ru.windcorp.progressia.client.graphics.texture.SimpleTexture;
|
||||||
|
import ru.windcorp.progressia.client.graphics.texture.Texture;
|
||||||
|
import ru.windcorp.progressia.common.resource.ResourceManager;
|
||||||
|
|
||||||
|
public class TileRenders {
|
||||||
|
|
||||||
|
private static final Map<String, TileRender> TILE_RENDERS =
|
||||||
|
new HashMap<>();
|
||||||
|
|
||||||
|
private static final AtlasGroup TILES_ATLAS_GROUP =
|
||||||
|
new AtlasGroup("Tiles", 1 << 12);
|
||||||
|
|
||||||
|
private TileRenders() {}
|
||||||
|
|
||||||
|
public static void registerTest() {
|
||||||
|
register(new TileRenderSimple("Test", "Stones", getTexture("stones")));
|
||||||
|
}
|
||||||
|
|
||||||
|
public static TileRender get(String name) {
|
||||||
|
return TILE_RENDERS.get(name);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void register(TileRender tileRender) {
|
||||||
|
TILE_RENDERS.put(tileRender.getId(), tileRender);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Texture getTexture(String name) {
|
||||||
|
return new SimpleTexture(
|
||||||
|
Atlases.getSprite(
|
||||||
|
ResourceManager.getTextureResource("tiles/" + name),
|
||||||
|
TILES_ATLAS_GROUP
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -19,6 +19,8 @@ package ru.windcorp.progressia.common.block;
|
|||||||
|
|
||||||
import com.google.common.collect.ImmutableList;
|
import com.google.common.collect.ImmutableList;
|
||||||
|
|
||||||
|
import glm.vec._3.i.Vec3i;
|
||||||
|
|
||||||
public final class BlockFace extends BlockRelation {
|
public final class BlockFace extends BlockRelation {
|
||||||
|
|
||||||
public static final BlockFace
|
public static final BlockFace
|
||||||
@ -35,6 +37,8 @@ public final class BlockFace extends BlockRelation {
|
|||||||
private static final ImmutableList<BlockFace> PRIMARY_FACES =
|
private static final ImmutableList<BlockFace> PRIMARY_FACES =
|
||||||
ImmutableList.of(TOP, NORTH, WEST);
|
ImmutableList.of(TOP, NORTH, WEST);
|
||||||
|
|
||||||
|
public static final int BLOCK_FACE_COUNT = ALL_FACES.size();
|
||||||
|
|
||||||
public static ImmutableList<BlockFace> getFaces() {
|
public static ImmutableList<BlockFace> getFaces() {
|
||||||
return ALL_FACES;
|
return ALL_FACES;
|
||||||
}
|
}
|
||||||
@ -43,10 +47,6 @@ public final class BlockFace extends BlockRelation {
|
|||||||
return PRIMARY_FACES;
|
return PRIMARY_FACES;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static int count() {
|
|
||||||
return ALL_FACES.size();
|
|
||||||
}
|
|
||||||
|
|
||||||
static {
|
static {
|
||||||
link(TOP, BOTTOM);
|
link(TOP, BOTTOM);
|
||||||
link(NORTH, SOUTH);
|
link(NORTH, SOUTH);
|
||||||
@ -58,11 +58,15 @@ public final class BlockFace extends BlockRelation {
|
|||||||
b.counterFace = a;
|
b.counterFace = a;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static int nextId = 0;
|
||||||
|
|
||||||
|
private final int id;
|
||||||
private BlockFace counterFace;
|
private BlockFace counterFace;
|
||||||
private final boolean isPrimary;
|
private final boolean isPrimary;
|
||||||
|
|
||||||
private BlockFace(int x, int y, int z, boolean isPrimary) {
|
private BlockFace(int x, int y, int z, boolean isPrimary) {
|
||||||
super(x, y, z);
|
super(x, y, z);
|
||||||
|
this.id = nextId++;
|
||||||
this.isPrimary = isPrimary;
|
this.isPrimary = isPrimary;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -75,9 +79,42 @@ public final class BlockFace extends BlockRelation {
|
|||||||
else return counterFace;
|
else return counterFace;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public BlockFace getPrimaryAndMoveCursor(Vec3i cursor) {
|
||||||
|
if (isPrimary) return this;
|
||||||
|
|
||||||
|
cursor.add(getVector());
|
||||||
|
return counterFace;
|
||||||
|
}
|
||||||
|
|
||||||
public BlockFace getSecondary() {
|
public BlockFace getSecondary() {
|
||||||
if (isPrimary) return counterFace;
|
if (isPrimary) return counterFace;
|
||||||
else return this;
|
else return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public BlockFace getSecondaryAndMoveCursor(Vec3i cursor) {
|
||||||
|
if (!isPrimary) return this;
|
||||||
|
|
||||||
|
cursor.add(getVector());
|
||||||
|
return counterFace;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getId() {
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public float getEuclideanDistance() {
|
||||||
|
return 1.0f;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getChebyshevDistance() {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getManhattanDistance() {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,28 @@
|
|||||||
|
/*******************************************************************************
|
||||||
|
* Progressia
|
||||||
|
* Copyright (C) 2020 Wind Corporation
|
||||||
|
*
|
||||||
|
* 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.block;
|
||||||
|
|
||||||
|
import ru.windcorp.progressia.common.util.Namespaced;
|
||||||
|
|
||||||
|
public class TileData extends Namespaced {
|
||||||
|
|
||||||
|
public TileData(String namespace, String name) {
|
||||||
|
super(namespace, name);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,39 @@
|
|||||||
|
/*******************************************************************************
|
||||||
|
* Progressia
|
||||||
|
* Copyright (C) 2020 Wind Corporation
|
||||||
|
*
|
||||||
|
* 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.block;
|
||||||
|
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
public class TileDataRegistry {
|
||||||
|
|
||||||
|
private static final Map<String, TileData> REGISTRY = new HashMap<>();
|
||||||
|
|
||||||
|
static {
|
||||||
|
register(new TileData("Test", "Stones"));
|
||||||
|
}
|
||||||
|
|
||||||
|
public static TileData get(String name) {
|
||||||
|
return REGISTRY.get(name);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void register(TileData tileData) {
|
||||||
|
REGISTRY.put(tileData.getId(), tileData);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,71 @@
|
|||||||
|
package ru.windcorp.progressia.common.util;
|
||||||
|
|
||||||
|
import java.util.Collection;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Objects;
|
||||||
|
import java.util.RandomAccess;
|
||||||
|
|
||||||
|
import com.google.common.collect.ForwardingList;
|
||||||
|
|
||||||
|
public class SizeLimitedList<E> extends ForwardingList<E> {
|
||||||
|
|
||||||
|
private static final class RandomAccessSizeLimitedList<E>
|
||||||
|
extends SizeLimitedList<E>
|
||||||
|
implements RandomAccess {
|
||||||
|
protected RandomAccessSizeLimitedList(List<E> parent, int maxSize) {
|
||||||
|
super(parent, maxSize);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static <E> List<E> wrap(List<E> list, int maxSize) {
|
||||||
|
if (list instanceof RandomAccess) {
|
||||||
|
return new RandomAccessSizeLimitedList<>(list, maxSize);
|
||||||
|
} else {
|
||||||
|
return new SizeLimitedList<>(list, maxSize);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private final List<E> delegate;
|
||||||
|
|
||||||
|
private final int maxSize;
|
||||||
|
|
||||||
|
protected SizeLimitedList(List<E> parent, int maxSize) {
|
||||||
|
this.delegate = Objects.requireNonNull(parent, "parent");
|
||||||
|
this.maxSize = maxSize;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean addAll(Collection<? extends E> collection) {
|
||||||
|
return standardAddAll(collection);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean addAll(int index, Collection<? extends E> elements) {
|
||||||
|
return standardAddAll(index, elements);
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean add(E e) {
|
||||||
|
checkMaxSize();
|
||||||
|
return delegate().add(e);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void add(int index, final E e) {
|
||||||
|
checkMaxSize();
|
||||||
|
delegate().add(index, e);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void checkMaxSize() {
|
||||||
|
if (size() >= maxSize) {
|
||||||
|
throw new UnsupportedOperationException(
|
||||||
|
"Maximum size " + maxSize + " reached"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected List<E> delegate() {
|
||||||
|
return delegate;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -17,9 +17,21 @@
|
|||||||
*******************************************************************************/
|
*******************************************************************************/
|
||||||
package ru.windcorp.progressia.common.world;
|
package ru.windcorp.progressia.common.world;
|
||||||
|
|
||||||
|
import static ru.windcorp.progressia.common.block.BlockFace.*;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import com.google.common.collect.Lists;
|
||||||
|
|
||||||
import glm.vec._3.i.Vec3i;
|
import glm.vec._3.i.Vec3i;
|
||||||
import ru.windcorp.progressia.common.block.BlockData;
|
import ru.windcorp.progressia.common.block.BlockData;
|
||||||
import ru.windcorp.progressia.common.block.BlockDataRegistry;
|
import ru.windcorp.progressia.common.block.BlockDataRegistry;
|
||||||
|
import ru.windcorp.progressia.common.block.BlockFace;
|
||||||
|
import ru.windcorp.progressia.common.block.TileData;
|
||||||
|
import ru.windcorp.progressia.common.block.TileDataRegistry;
|
||||||
|
import ru.windcorp.progressia.common.util.SizeLimitedList;
|
||||||
|
import ru.windcorp.progressia.common.util.Vectors;
|
||||||
|
|
||||||
public class ChunkData {
|
public class ChunkData {
|
||||||
|
|
||||||
@ -27,23 +39,33 @@ public class ChunkData {
|
|||||||
public static final int TILES_PER_FACE = 8;
|
public static final int TILES_PER_FACE = 8;
|
||||||
|
|
||||||
private final Vec3i position = new Vec3i();
|
private final Vec3i position = new Vec3i();
|
||||||
|
private final WorldData world;
|
||||||
|
|
||||||
private final BlockData[] blocks = new BlockData[
|
private final BlockData[] blocks = new BlockData[
|
||||||
BLOCKS_PER_CHUNK * BLOCKS_PER_CHUNK * BLOCKS_PER_CHUNK
|
BLOCKS_PER_CHUNK * BLOCKS_PER_CHUNK * BLOCKS_PER_CHUNK
|
||||||
];
|
];
|
||||||
|
|
||||||
private final BlockData grass = BlockDataRegistry.get("Test:Grass");
|
@SuppressWarnings("unchecked")
|
||||||
private final BlockData dirt = BlockDataRegistry.get("Test:Dirt");
|
private final List<TileData>[] tiles = (List<TileData>[]) new List<?>[
|
||||||
private final BlockData stone = BlockDataRegistry.get("Test:Stone");
|
BLOCKS_PER_CHUNK * BLOCKS_PER_CHUNK * BLOCKS_PER_CHUNK *
|
||||||
private final BlockData air = BlockDataRegistry.get("Test:Air");
|
BLOCK_FACE_COUNT
|
||||||
|
];
|
||||||
|
|
||||||
public ChunkData(int x, int y, int z) {
|
public ChunkData(int x, int y, int z, WorldData world) {
|
||||||
this.position.set(x, y, z);
|
this.position.set(x, y, z);
|
||||||
|
this.world = world;
|
||||||
|
|
||||||
tmp_generate();
|
tmp_generate();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void tmp_generate() {
|
private void tmp_generate() {
|
||||||
|
BlockData grass = BlockDataRegistry.get("Test:Grass");
|
||||||
|
BlockData dirt = BlockDataRegistry.get("Test:Dirt");
|
||||||
|
BlockData stone = BlockDataRegistry.get("Test:Stone");
|
||||||
|
BlockData air = BlockDataRegistry.get("Test:Air");
|
||||||
|
|
||||||
|
TileData stones = TileDataRegistry.get("Test:Stones");
|
||||||
|
|
||||||
Vec3i aPoint = new Vec3i(5, 0, BLOCKS_PER_CHUNK + BLOCKS_PER_CHUNK/2);
|
Vec3i aPoint = new Vec3i(5, 0, BLOCKS_PER_CHUNK + BLOCKS_PER_CHUNK/2);
|
||||||
Vec3i pos = new Vec3i();
|
Vec3i pos = new Vec3i();
|
||||||
|
|
||||||
@ -74,46 +96,134 @@ public class ChunkData {
|
|||||||
for (pos.z = BLOCKS_PER_CHUNK - 1; pos.z >= 0 && getBlock(pos) == air; --pos.z);
|
for (pos.z = BLOCKS_PER_CHUNK - 1; pos.z >= 0 && getBlock(pos) == air; --pos.z);
|
||||||
|
|
||||||
setBlock(pos, grass);
|
setBlock(pos, grass);
|
||||||
|
|
||||||
|
int hash = x*x * 13 ^ y*y * 37 ^ pos.z*pos.z * 129;
|
||||||
|
if (hash % 5 == 0) {
|
||||||
|
getTiles(pos, BlockFace.TOP).add(stones);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public BlockData getBlock(Vec3i posInChunk) {
|
public BlockData getBlock(Vec3i posInChunk) {
|
||||||
if (!isInBounds(posInChunk)) {
|
|
||||||
throw new IllegalArgumentException(
|
|
||||||
"Coordinates " + str(posInChunk) + " "
|
|
||||||
+ "are not legal chunk coordinates"
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
return blocks[getBlockIndex(posInChunk)];
|
return blocks[getBlockIndex(posInChunk)];
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setBlock(Vec3i posInChunk, BlockData block) {
|
public void setBlock(Vec3i posInChunk, BlockData block) {
|
||||||
if (!isInBounds(posInChunk)) {
|
|
||||||
throw new IllegalArgumentException(
|
|
||||||
"Coordinates " + str(posInChunk) + " "
|
|
||||||
+ "are not legal chunk coordinates"
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
blocks[getBlockIndex(posInChunk)] = block;
|
blocks[getBlockIndex(posInChunk)] = block;
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean isInBounds(Vec3i posInChunk) {
|
public List<TileData> getTilesOrNull(Vec3i blockInChunk, BlockFace face) {
|
||||||
return
|
return tiles[getTileIndex(blockInChunk, face)];
|
||||||
posInChunk.x >= 0 && posInChunk.x < BLOCKS_PER_CHUNK &&
|
|
||||||
posInChunk.y >= 0 && posInChunk.y < BLOCKS_PER_CHUNK &&
|
|
||||||
posInChunk.z >= 0 && posInChunk.z < BLOCKS_PER_CHUNK;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private int getBlockIndex(Vec3i posInChunk) {
|
/**
|
||||||
|
* Internal use only. Modify a list returned by
|
||||||
|
* {@link #getTiles(Vec3i, BlockFace)} or
|
||||||
|
* {@link #getTilesOrNull(Vec3i, BlockFace)}
|
||||||
|
* to change tiles.
|
||||||
|
*/
|
||||||
|
protected void setTiles(
|
||||||
|
Vec3i blockInChunk, BlockFace face,
|
||||||
|
List<TileData> tiles
|
||||||
|
) {
|
||||||
|
this.tiles[getTileIndex(blockInChunk, face)] = tiles;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean hasTiles(Vec3i blockInChunk, BlockFace face) {
|
||||||
|
return getTilesOrNull(blockInChunk, face) != null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<TileData> getTiles(Vec3i blockInChunk, BlockFace face) {
|
||||||
|
int index = getTileIndex(blockInChunk, face);
|
||||||
|
|
||||||
|
if (tiles[index] == null) {
|
||||||
|
createTileContainer(blockInChunk, face);
|
||||||
|
}
|
||||||
|
|
||||||
|
return tiles[index];
|
||||||
|
}
|
||||||
|
|
||||||
|
private void createTileContainer(Vec3i blockInChunk, BlockFace face) {
|
||||||
|
if (isBorder(blockInChunk, face)) {
|
||||||
|
createBorderTileContainer(blockInChunk, face);
|
||||||
|
} else {
|
||||||
|
createNormalTileContainer(blockInChunk, face);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void createNormalTileContainer(Vec3i blockInChunk, BlockFace face) {
|
||||||
|
List<TileData> primaryList =
|
||||||
|
SizeLimitedList.wrap(
|
||||||
|
new ArrayList<>(TILES_PER_FACE), TILES_PER_FACE
|
||||||
|
);
|
||||||
|
|
||||||
|
List<TileData> secondaryList = Lists.reverse(primaryList);
|
||||||
|
|
||||||
|
|
||||||
|
Vec3i cursor = Vectors.grab3i()
|
||||||
|
.set(blockInChunk.x, blockInChunk.y, blockInChunk.z);
|
||||||
|
|
||||||
|
face = face.getPrimaryAndMoveCursor(cursor);
|
||||||
|
setTiles(cursor, face, primaryList);
|
||||||
|
|
||||||
|
face = face.getSecondaryAndMoveCursor(cursor);
|
||||||
|
setTiles(cursor, face, secondaryList);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void createBorderTileContainer(Vec3i blockInChunk, BlockFace face) {
|
||||||
|
// TODO cooperate with neighbours
|
||||||
|
setTiles(
|
||||||
|
blockInChunk, face,
|
||||||
|
SizeLimitedList.wrap(
|
||||||
|
new ArrayList<>(TILES_PER_FACE), TILES_PER_FACE
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static int getBlockIndex(Vec3i posInChunk) {
|
||||||
|
checkLocalCoordinates(posInChunk);
|
||||||
|
|
||||||
return
|
return
|
||||||
posInChunk.z * BLOCKS_PER_CHUNK * BLOCKS_PER_CHUNK +
|
posInChunk.z * BLOCKS_PER_CHUNK * BLOCKS_PER_CHUNK +
|
||||||
posInChunk.y * BLOCKS_PER_CHUNK +
|
posInChunk.y * BLOCKS_PER_CHUNK +
|
||||||
posInChunk.x;
|
posInChunk.x;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static int getTileIndex(Vec3i posInChunk, BlockFace face) {
|
||||||
|
return
|
||||||
|
getBlockIndex(posInChunk) * BLOCK_FACE_COUNT +
|
||||||
|
face.getId();
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void checkLocalCoordinates(Vec3i posInChunk) {
|
||||||
|
if (!isInBounds(posInChunk)) {
|
||||||
|
throw new IllegalArgumentException(
|
||||||
|
"Coordinates " + str(posInChunk) + " "
|
||||||
|
+ "are not legal chunk coordinates"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static boolean isInBounds(Vec3i posInChunk) {
|
||||||
|
return
|
||||||
|
posInChunk.x >= 0 && posInChunk.x < BLOCKS_PER_CHUNK &&
|
||||||
|
posInChunk.y >= 0 && posInChunk.y < BLOCKS_PER_CHUNK &&
|
||||||
|
posInChunk.z >= 0 && posInChunk.z < BLOCKS_PER_CHUNK;
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean isBorder(Vec3i blockInChunk, BlockFace face) {
|
||||||
|
final int min = 0, max = BLOCKS_PER_CHUNK - 1;
|
||||||
|
|
||||||
|
return
|
||||||
|
(blockInChunk.x == min && face == SOUTH ) ||
|
||||||
|
(blockInChunk.x == max && face == NORTH ) ||
|
||||||
|
(blockInChunk.y == min && face == WEST ) ||
|
||||||
|
(blockInChunk.y == max && face == EAST ) ||
|
||||||
|
(blockInChunk.z == min && face == BOTTOM) ||
|
||||||
|
(blockInChunk.z == max && face == TOP );
|
||||||
|
}
|
||||||
|
|
||||||
public int getX() {
|
public int getX() {
|
||||||
return position.x;
|
return position.x;
|
||||||
}
|
}
|
||||||
@ -130,6 +240,10 @@ public class ChunkData {
|
|||||||
return position;
|
return position;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public WorldData getWorld() {
|
||||||
|
return world;
|
||||||
|
}
|
||||||
|
|
||||||
private static String str(Vec3i v) {
|
private static String str(Vec3i v) {
|
||||||
return "(" + v.x + "; " + v.y + "; " + v.z + ")";
|
return "(" + v.x + "; " + v.y + "; " + v.z + ")";
|
||||||
}
|
}
|
||||||
|
@ -34,7 +34,7 @@ public class WorldData {
|
|||||||
|
|
||||||
for (int x = -(size / 2); x <= (size / 2); ++x) {
|
for (int x = -(size / 2); x <= (size / 2); ++x) {
|
||||||
for (int y = -(size / 2); y <= (size / 2); ++y) {
|
for (int y = -(size / 2); y <= (size / 2); ++y) {
|
||||||
chunks.put(CoordinatePacker.pack3IntsIntoLong(x, y, 0), new ChunkData(x, y, 0));
|
chunks.put(CoordinatePacker.pack3IntsIntoLong(x, y, 0), new ChunkData(x, y, 0, this));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
BIN
src/main/resources/assets/textures/tiles/stones.png
Normal file
BIN
src/main/resources/assets/textures/tiles/stones.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 464 B |
Reference in New Issue
Block a user