More refactoring of GenericChunk and pals

- Genericized TileReference
- Unified template arguments
This commit is contained in:
OLEGSHA 2021-04-06 00:36:38 +03:00
parent 2532e80f6a
commit e0a03cad1d
Signed by: OLEGSHA
GPG Key ID: E57A4B08D64AFF7A
26 changed files with 452 additions and 220 deletions

View File

@ -27,6 +27,7 @@ import ru.windcorp.progressia.client.graphics.model.ShapeRenderHelper;
import ru.windcorp.progressia.client.world.block.BlockRender; import ru.windcorp.progressia.client.world.block.BlockRender;
import ru.windcorp.progressia.client.world.block.BlockRenderRegistry; import ru.windcorp.progressia.client.world.block.BlockRenderRegistry;
import ru.windcorp.progressia.client.world.tile.TileRender; import ru.windcorp.progressia.client.world.tile.TileRender;
import ru.windcorp.progressia.client.world.tile.TileRenderReference;
import ru.windcorp.progressia.client.world.tile.TileRenderRegistry; import ru.windcorp.progressia.client.world.tile.TileRenderRegistry;
import ru.windcorp.progressia.client.world.tile.TileRenderStack; import ru.windcorp.progressia.client.world.tile.TileRenderStack;
import ru.windcorp.progressia.common.world.ChunkData; import ru.windcorp.progressia.common.world.ChunkData;
@ -34,10 +35,11 @@ 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.BlockFace;
import ru.windcorp.progressia.common.world.rels.RelFace; import ru.windcorp.progressia.common.world.rels.RelFace;
import ru.windcorp.progressia.common.world.tile.TileDataReference;
import ru.windcorp.progressia.common.world.tile.TileDataStack; import ru.windcorp.progressia.common.world.tile.TileDataStack;
public class ChunkRender public class ChunkRender
implements GenericChunk<ChunkRender, BlockRender, TileRender, TileRenderStack> { implements GenericChunk<BlockRender, TileRender, TileRenderStack, TileRenderReference, ChunkRender> {
private final WorldRender world; private final WorldRender world;
private final ChunkData data; private final ChunkData data;
@ -108,6 +110,28 @@ public class ChunkRender
} }
private class TileRenderStackImpl extends TileRenderStack { private class TileRenderStackImpl extends TileRenderStack {
private class TileRenderReferenceImpl implements TileRenderReference {
private final TileDataReference parent;
public TileRenderReferenceImpl(TileDataReference parent) {
this.parent = parent;
}
@Override
public TileRender get() {
return TileRenderRegistry.getInstance().get(parent.get().getId());
}
@Override
public int getIndex() {
return parent.getIndex();
}
@Override
public TileRenderStack getStack() {
return TileRenderStackImpl.this;
}
}
private final TileDataStack parent; private final TileDataStack parent;
@ -130,6 +154,21 @@ public class ChunkRender
return parent.getFace(); return parent.getFace();
} }
@Override
public TileRenderReference getReference(int index) {
return new TileRenderReferenceImpl(parent.getReference(index));
}
@Override
public int getIndexByTag(int tag) {
return parent.getIndexByTag(tag);
}
@Override
public int getTagByIndex(int index) {
return parent.getTagByIndex(index);
}
@Override @Override
public TileRender get(int index) { public TileRender get(int index) {
return TileRenderRegistry.getInstance().get(parent.get(index).getId()); return TileRenderRegistry.getInstance().get(parent.get(index).getId());

View File

@ -34,6 +34,7 @@ import ru.windcorp.progressia.client.world.block.BlockRender;
import ru.windcorp.progressia.client.world.entity.EntityRenderRegistry; import ru.windcorp.progressia.client.world.entity.EntityRenderRegistry;
import ru.windcorp.progressia.client.world.entity.EntityRenderable; import ru.windcorp.progressia.client.world.entity.EntityRenderable;
import ru.windcorp.progressia.client.world.tile.TileRender; import ru.windcorp.progressia.client.world.tile.TileRender;
import ru.windcorp.progressia.client.world.tile.TileRenderReference;
import ru.windcorp.progressia.client.world.tile.TileRenderStack; import ru.windcorp.progressia.client.world.tile.TileRenderStack;
import ru.windcorp.progressia.common.util.VectorUtil; import ru.windcorp.progressia.common.util.VectorUtil;
import ru.windcorp.progressia.common.util.Vectors; import ru.windcorp.progressia.common.util.Vectors;
@ -47,7 +48,7 @@ import ru.windcorp.progressia.common.world.generic.ChunkSets;
import ru.windcorp.progressia.common.world.generic.GenericWorld; import ru.windcorp.progressia.common.world.generic.GenericWorld;
public class WorldRender public class WorldRender
implements GenericWorld<BlockRender, TileRender, TileRenderStack, ChunkRender, EntityRenderable> { implements GenericWorld<BlockRender, TileRender, TileRenderStack, TileRenderReference, ChunkRender, EntityRenderable> {
private final WorldData data; private final WorldData data;
private final Client client; private final Client client;

View File

@ -0,0 +1,27 @@
/*
* 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.client.world.tile;
import ru.windcorp.progressia.client.world.ChunkRender;
import ru.windcorp.progressia.client.world.block.BlockRender;
import ru.windcorp.progressia.common.world.generic.GenericTileReference;
public interface TileRenderReference
extends GenericTileReference<BlockRender, TileRender, TileRenderStack, TileRenderReference, ChunkRender> {
}

View File

@ -19,11 +19,12 @@
package ru.windcorp.progressia.client.world.tile; package ru.windcorp.progressia.client.world.tile;
import ru.windcorp.progressia.client.world.ChunkRender; import ru.windcorp.progressia.client.world.ChunkRender;
import ru.windcorp.progressia.client.world.block.BlockRender;
import ru.windcorp.progressia.common.world.generic.GenericTileStack; import ru.windcorp.progressia.common.world.generic.GenericTileStack;
import ru.windcorp.progressia.common.world.tile.TileDataStack; import ru.windcorp.progressia.common.world.tile.TileDataStack;
public abstract class TileRenderStack public abstract class TileRenderStack
extends GenericTileStack<TileRenderStack, TileRender, ChunkRender> { extends GenericTileStack<BlockRender, TileRender, TileRenderStack, TileRenderReference, ChunkRender> {
public abstract TileDataStack getData(); public abstract TileDataStack getData();

View File

@ -36,12 +36,12 @@ import ru.windcorp.progressia.common.world.rels.AbsFace;
import ru.windcorp.progressia.common.world.rels.BlockFace; import ru.windcorp.progressia.common.world.rels.BlockFace;
import ru.windcorp.progressia.common.world.rels.RelFace; import ru.windcorp.progressia.common.world.rels.RelFace;
import ru.windcorp.progressia.common.world.tile.TileData; import ru.windcorp.progressia.common.world.tile.TileData;
import ru.windcorp.progressia.common.world.tile.TileDataReference;
import ru.windcorp.progressia.common.world.tile.TileDataStack; import ru.windcorp.progressia.common.world.tile.TileDataStack;
import ru.windcorp.progressia.common.world.tile.TileReference;
import ru.windcorp.progressia.common.world.tile.TileStackIsFullException; import ru.windcorp.progressia.common.world.tile.TileStackIsFullException;
public class ChunkData public class ChunkData
implements GenericWritableChunk<ChunkData, BlockData, TileData, TileDataStack> { implements GenericWritableChunk<BlockData, TileData, TileDataStack, TileDataReference, ChunkData> {
public static final int BLOCKS_PER_CHUNK = Coordinates.CHUNK_SIZE; public static final int BLOCKS_PER_CHUNK = Coordinates.CHUNK_SIZE;
public static final int CHUNK_RADIUS = BLOCKS_PER_CHUNK / 2; public static final int CHUNK_RADIUS = BLOCKS_PER_CHUNK / 2;
@ -219,10 +219,10 @@ public class ChunkData
* @author javapony * @author javapony
*/ */
private class TileDataStackImpl extends TileDataStack { private class TileDataStackImpl extends TileDataStack {
private class TileReferenceImpl implements TileReference { private class TileDataReferenceImpl implements TileDataReference {
private int index; private int index;
public TileReferenceImpl(int index) { public TileDataReferenceImpl(int index) {
this.index = index; this.index = index;
} }
@ -264,7 +264,7 @@ public class ChunkData
private final TileData[] tiles = new TileData[TILES_PER_FACE]; private final TileData[] tiles = new TileData[TILES_PER_FACE];
private int size = 0; private int size = 0;
private final TileReferenceImpl[] references = new TileReferenceImpl[tiles.length]; private final TileDataReferenceImpl[] references = new TileDataReferenceImpl[tiles.length];
private final int[] indicesByTag = new int[tiles.length]; private final int[] indicesByTag = new int[tiles.length];
private final int[] tagsByIndex = new int[tiles.length]; private final int[] tagsByIndex = new int[tiles.length];
@ -437,11 +437,11 @@ public class ChunkData
} }
@Override @Override
public TileReference getReference(int index) { public TileDataReference getReference(int index) {
checkIndex(index, false); checkIndex(index, false);
if (references[index] == null) { if (references[index] == null) {
references[index] = new TileReferenceImpl(index); references[index] = new TileDataReferenceImpl(index);
} }
return references[index]; return references[index];
@ -500,7 +500,7 @@ public class ChunkData
throw new AssertionError("get(index) is null"); throw new AssertionError("get(index) is null");
if (references[index] != null) { if (references[index] != null) {
TileReference ref = getReference(index); TileDataReference ref = getReference(index);
if (ref == null) if (ref == null)
throw new AssertionError("references[index] is not null but getReference(index) is"); throw new AssertionError("references[index] is not null but getReference(index) is");
if (!ref.isValid()) if (!ref.isValid())

View File

@ -38,9 +38,10 @@ import ru.windcorp.progressia.common.world.generic.GenericWorld;
import ru.windcorp.progressia.common.world.generic.LongBasedChunkMap; import ru.windcorp.progressia.common.world.generic.LongBasedChunkMap;
import ru.windcorp.progressia.common.world.tile.TileData; import ru.windcorp.progressia.common.world.tile.TileData;
import ru.windcorp.progressia.common.world.tile.TileDataStack; import ru.windcorp.progressia.common.world.tile.TileDataStack;
import ru.windcorp.progressia.common.world.tile.TileDataReference;
public class WorldData public class WorldData
implements GenericWorld<BlockData, TileData, TileDataStack, ChunkData, EntityData> { implements GenericWorld<BlockData, TileData, TileDataStack, TileDataReference, ChunkData, EntityData> {
private final ChunkMap<ChunkData> chunksByPos = new LongBasedChunkMap<>( private final ChunkMap<ChunkData> chunksByPos = new LongBasedChunkMap<>(
TCollections.synchronizedMap(new TLongObjectHashMap<>()) TCollections.synchronizedMap(new TLongObjectHashMap<>())

View File

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

View File

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

View File

@ -75,20 +75,20 @@ public interface ChunkSet extends Iterable<Vec3i> {
return result; return result;
} }
default boolean contains(GenericChunk<?, ?, ?, ?> chunk) { default boolean contains(GenericChunk<?, ?, ?, ?, ?> chunk) {
return contains(chunk.getPosition()); return contains(chunk.getPosition());
} }
default boolean add(GenericChunk<?, ?, ?, ?> chunk) { default boolean add(GenericChunk<?, ?, ?, ?, ?> chunk) {
return add(chunk.getPosition()); return add(chunk.getPosition());
} }
default boolean remove(GenericChunk<?, ?, ?, ?> chunk) { default boolean remove(GenericChunk<?, ?, ?, ?, ?> chunk) {
return remove(chunk.getPosition()); return remove(chunk.getPosition());
} }
default <C extends GenericChunk<C, ?, ?, ?>> void forEachIn( default <C extends GenericChunk<?, ?, ?, ?, C>> void forEachIn(
GenericWorld<?, ?, ?, C, ?> world, GenericWorld<?, ?, ?, ?, C, ?> world,
Consumer<? super C> action Consumer<? super C> action
) { ) {
forEach(position -> { forEach(position -> {
@ -207,7 +207,7 @@ public interface ChunkSet extends Iterable<Vec3i> {
} }
} }
default boolean containsAllChunks(Iterable<? extends GenericChunk<?, ?, ?, ?>> chunks) { default boolean containsAllChunks(Iterable<? extends GenericChunk<?, ?, ?, ?, ?>> chunks) {
boolean[] hasMissing = new boolean[] { false }; boolean[] hasMissing = new boolean[] { false };
chunks.forEach(c -> { chunks.forEach(c -> {
@ -219,7 +219,7 @@ public interface ChunkSet extends Iterable<Vec3i> {
return hasMissing[0]; return hasMissing[0];
} }
default boolean containsAnyChunks(Iterable<? extends GenericChunk<?, ?, ?, ?>> chunks) { default boolean containsAnyChunks(Iterable<? extends GenericChunk<?, ?, ?, ?, ?>> chunks) {
boolean[] hasPresent = new boolean[] { false }; boolean[] hasPresent = new boolean[] { false };
chunks.forEach(c -> { chunks.forEach(c -> {
@ -231,11 +231,11 @@ public interface ChunkSet extends Iterable<Vec3i> {
return hasPresent[0]; return hasPresent[0];
} }
default void addAllChunks(Iterable<? extends GenericChunk<?, ?, ?, ?>> chunks) { default void addAllChunks(Iterable<? extends GenericChunk<?, ?, ?, ?, ?>> chunks) {
chunks.forEach(this::add); chunks.forEach(this::add);
} }
default void removeAllChunks(Iterable<? extends GenericChunk<?, ?, ?, ?>> chunks) { default void removeAllChunks(Iterable<? extends GenericChunk<?, ?, ?, ?, ?>> chunks) {
chunks.forEach(this::remove); chunks.forEach(this::remove);
} }

View File

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

View File

@ -56,7 +56,15 @@ import ru.windcorp.progressia.common.world.rels.BlockFace;
* @param <TS> tile stack type * @param <TS> tile stack type
* @author javapony * @author javapony
*/ */
public interface GenericChunk<Self extends GenericChunk<Self, B, T, TS>, B extends GenericBlock, T extends GenericTile, TS extends GenericTileStack<TS, T, Self>> { // @formatter:off
public interface GenericChunk<
B extends GenericBlock,
T extends GenericTile,
TS extends GenericTileStack <B, T, TS, TR, C>,
TR extends GenericTileReference <B, T, TS, TR, C>,
C extends GenericChunk <B, T, TS, TR, C>
> {
// @formatter:on
/** /**
* The count of blocks in a side of a chunk. This is guaranteed to be a * The count of blocks in a side of a chunk. This is guaranteed to be a

View File

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

View File

@ -27,9 +27,15 @@ 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.RelFace; 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>> // @formatter:off
extends AbstractList<T> public abstract class GenericTileStack<
implements RandomAccess { B extends GenericBlock,
T extends GenericTile,
TS extends GenericTileStack <B, T, TS, TR, C>,
TR extends GenericTileReference <B, T, TS, TR, C>,
C extends GenericChunk <B, T, TS, TR, C>
> extends AbstractList<T> implements RandomAccess {
// @formatter:on
public static interface TSConsumer<T> { public static interface TSConsumer<T> {
void accept(int layer, T tile); void accept(int layer, T tile);
@ -43,6 +49,12 @@ public abstract class GenericTileStack<Self extends GenericTileStack<Self, T, C>
public abstract RelFace getFace(); public abstract RelFace getFace();
public abstract TR getReference(int index);
public abstract int getIndexByTag(int tag);
public abstract int getTagByIndex(int index);
public Vec3i getBlockInWorld(Vec3i output) { public Vec3i getBlockInWorld(Vec3i output) {
// This is safe // This is safe
return Coordinates.getInWorld(getChunk().getPosition(), getBlockInChunk(output), output); return Coordinates.getInWorld(getChunk().getPosition(), getBlockInChunk(output), output);
@ -105,4 +117,8 @@ public abstract class GenericTileStack<Self extends GenericTileStack<Self, T, C>
return findClosest(id) != null; return findClosest(id) != null;
} }
public B getHost() {
return getChunk().getBlock(getBlockInChunk(null));
}
} }

View File

@ -29,7 +29,16 @@ 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.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> { // @formatter:off
public interface GenericWorld<
B extends GenericBlock,
T extends GenericTile,
TS extends GenericTileStack <B, T, TS, TR, C>,
TR extends GenericTileReference <B, T, TS, TR, C>,
C extends GenericChunk <B, T, TS, TR, C>,
E extends GenericEntity
> {
// @formatter:on
Collection<C> getChunks(); Collection<C> getChunks();

View File

@ -19,12 +19,18 @@ package ru.windcorp.progressia.common.world.generic;
import glm.vec._3.i.Vec3i; import glm.vec._3.i.Vec3i;
import ru.windcorp.progressia.common.world.block.BlockData; // @formatter:off
public interface GenericWritableChunk<
B extends GenericBlock,
T extends GenericTile,
TS extends GenericWritableTileStack <B, T, TS, TR, C>,
TR extends GenericTileReference <B, T, TS, TR, C>,
C extends GenericWritableChunk <B, T, TS, TR, C>
>
extends GenericChunk<B, T, TS, TR, C> {
// @formatter:on
public interface GenericWritableChunk<Self extends GenericWritableChunk<Self, B, T, TS>, B extends GenericBlock, T extends GenericTile, TS extends GenericTileStack<TS, T, Self>> void setBlock(Vec3i posInChunk, B block, boolean notify);
extends GenericChunk<Self, B, T, TS> {
void setBlock(Vec3i posInChunk, BlockData block, boolean notify);
void setBlockRel(Vec3i relativeBlockInChunk, B block, boolean notify); void setBlockRel(Vec3i relativeBlockInChunk, B block, boolean notify);

View File

@ -0,0 +1,160 @@
/*
* Progressia
* Copyright (C) 2020-2021 Wind Corporation and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package ru.windcorp.progressia.common.world.generic;
// @formatter:off
public abstract class GenericWritableTileStack<
B extends GenericBlock,
T extends GenericTile,
TS extends GenericWritableTileStack<B, T, TS, TR, C>,
TR extends GenericTileReference<B, T, TS, TR, C>,
C extends GenericWritableChunk<B, T, TS, TR, C>
>
extends GenericTileStack<B, T, TS, TR, C> {
// @formatter:on
/**
* Inserts the specified tile at the specified position in this stack.
* Shifts the tile currently at that position (if any) and any tiles above
* to
* the top (adds one to their indices).
*
* @param index index at which the specified tile is to be inserted
* @param tile tile to be inserted
* @throws TileStackIsFullException if this stack is {@linkplain #isFull()
* full}
*/
/*
* Impl note: AbstractList provides a useless implementation of this method,
* make sure to override it in subclass
*/
@Override
public abstract void add(int index, T tile);
/**
* Adds the specified tile at the end of this stack assigning it the
* provided tag.
* This method is useful for copying stacks when preserving tags is
* necessary.
*
* @param tile the tile to add
* @param tag the tag to assign the new tile
* @throws IllegalArgumentException if this stack already contains a tile
* with the
* provided tag
*/
public abstract void load(T tile, int tag);
/**
* Replaces the tile at the specified position in this stack with the
* specified tile.
*
* @param index index of the tile to replace
* @param tile tile to be stored at the specified position
* @return the tile previously at the specified position
*/
/*
* Impl note: AbstractList provides a useless implementation of this method,
* make sure to override it in subclass
*/
@Override
public abstract T set(int index, T tile);
/**
* Removes the tile at the specified position in this list. Shifts any
* subsequent tiles
* to the left (subtracts one from their indices). Returns the tile that was
* removed
* from the list.
*
* @param index the index of the tile to be removed
* @return the tile previously at the specified position
*/
/*
* Impl note: AbstractList provides a useless implementation of this method,
* make sure to override it in subclass
*/
@Override
public abstract T remove(int index);
/*
* Aliases and overloads
*/
public void addClosest(T tile) {
add(0, tile);
}
public void addFarthest(T tile) {
add(size(), tile);
}
/**
* Attempts to {@link #add(int, TileData) add} the provided {@code tile}
* at {@code index}. If the stack is {@linkplain #isFull() full}, does
* nothing.
*
* @param index the index to insert the tile at
* @param tile the tile to try to add
* @return {@code true} iff this stack has changed
*/
public boolean offer(int index, T tile) {
if (isFull())
return false;
add(index, tile);
return true;
}
public boolean offerClosest(T tile) {
return offer(0, tile);
}
public boolean offerFarthest(T tile) {
return offer(size(), tile);
}
public T removeClosest() {
return remove(0);
}
public T removeFarthest() {
return remove(size() - 1);
}
public T poll(int index) {
if (size() <= index)
return null;
return remove(index);
}
public T pollClosest() {
return poll(0);
}
public T pollFarthest() {
return poll(size() - 1);
}
@Override
public boolean add(T tile) {
addFarthest(tile);
return true;
}
}

View File

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

View File

@ -35,7 +35,7 @@ class Util {
return hits; return hits;
} }
public static boolean testBiC(Vec3i blockInWorld, GenericChunk<?, ?, ?, ?> chunk, Predicate<Vec3i> test) { public static boolean testBiC(Vec3i blockInWorld, GenericChunk<?, ?, ?, ?, ?> chunk, Predicate<Vec3i> test) {
Vec3i v = Vectors.grab3i(); Vec3i v = Vectors.grab3i();
v = Coordinates.getInWorld(chunk.getPosition(), Vectors.ZERO_3i, v); v = Coordinates.getInWorld(chunk.getPosition(), Vectors.ZERO_3i, v);

View File

@ -18,16 +18,10 @@
package ru.windcorp.progressia.common.world.tile; package ru.windcorp.progressia.common.world.tile;
public interface TileReference { import ru.windcorp.progressia.common.world.ChunkData;
import ru.windcorp.progressia.common.world.block.BlockData;
import ru.windcorp.progressia.common.world.generic.GenericTileReference;
TileData get(); public interface TileDataReference extends GenericTileReference<BlockData, TileData, TileDataStack, TileDataReference, ChunkData> {
int getIndex();
TileDataStack getStack();
default boolean isValid() {
return get() != null;
}
} }

View File

@ -20,147 +20,9 @@ package ru.windcorp.progressia.common.world.tile;
import ru.windcorp.progressia.common.world.ChunkData; import ru.windcorp.progressia.common.world.ChunkData;
import ru.windcorp.progressia.common.world.block.BlockData; import ru.windcorp.progressia.common.world.block.BlockData;
import ru.windcorp.progressia.common.world.generic.GenericTileStack; import ru.windcorp.progressia.common.world.generic.GenericWritableTileStack;
public abstract class TileDataStack public abstract class TileDataStack
extends GenericTileStack<TileDataStack, TileData, ChunkData> { extends GenericWritableTileStack<BlockData, TileData, TileDataStack, TileDataReference, ChunkData> {
/**
* Inserts the specified tile at the specified position in this stack.
* Shifts the tile currently at that position (if any) and any tiles above
* to
* the top (adds one to their indices).
*
* @param index index at which the specified tile is to be inserted
* @param tile tile to be inserted
* @throws TileStackIsFullException if this stack is {@linkplain #isFull()
* full}
*/
/*
* Impl note: AbstractList provides a useless implementation of this method,
* make sure to override it in subclass
*/
@Override
public abstract void add(int index, TileData tile);
/**
* Adds the specified tile at the end of this stack assigning it the
* provided tag.
* This method is useful for copying stacks when preserving tags is
* necessary.
*
* @param tile the tile to add
* @param tag the tag to assign the new tile
* @throws IllegalArgumentException if this stack already contains a tile
* with the
* provided tag
*/
public abstract void load(TileData tile, int tag);
/**
* Replaces the tile at the specified position in this stack with the
* specified tile.
*
* @param index index of the tile to replace
* @param tile tile to be stored at the specified position
* @return the tile previously at the specified position
*/
/*
* Impl note: AbstractList provides a useless implementation of this method,
* make sure to override it in subclass
*/
@Override
public abstract TileData set(int index, TileData tile);
/**
* Removes the tile at the specified position in this list. Shifts any
* subsequent tiles
* to the left (subtracts one from their indices). Returns the tile that was
* removed
* from the list.
*
* @param index the index of the tile to be removed
* @return the tile previously at the specified position
*/
/*
* Impl note: AbstractList provides a useless implementation of this method,
* make sure to override it in subclass
*/
@Override
public abstract TileData remove(int index);
public abstract TileReference getReference(int index);
public abstract int getIndexByTag(int tag);
public abstract int getTagByIndex(int index);
/*
* Aliases and overloads
*/
public void addClosest(TileData tile) {
add(0, tile);
}
public void addFarthest(TileData tile) {
add(size(), tile);
}
/**
* Attempts to {@link #add(int, TileData) add} the provided {@code tile}
* at {@code index}. If the stack is {@linkplain #isFull() full}, does
* nothing.
*
* @param index the index to insert the tile at
* @param tile the tile to try to add
* @return {@code true} iff this stack has changed
*/
public boolean offer(int index, TileData tile) {
if (isFull())
return false;
add(index, tile);
return true;
}
public boolean offerClosest(TileData tile) {
return offer(0, tile);
}
public boolean offerFarthest(TileData tile) {
return offer(size(), tile);
}
public TileData removeClosest() {
return remove(0);
}
public TileData removeFarthest() {
return remove(size() - 1);
}
public TileData poll(int index) {
if (size() <= index)
return null;
return remove(index);
}
public TileData pollClosest() {
return poll(0);
}
public TileData pollFarthest() {
return poll(size() - 1);
}
@Override
public boolean add(TileData tile) {
addFarthest(tile);
return true;
}
public BlockData getHost() {
return getChunk().getBlock(getBlockInChunk(null));
}
} }

View File

@ -33,7 +33,7 @@ import ru.windcorp.progressia.common.world.rels.AbsFace;
import ru.windcorp.progressia.common.world.rels.BlockFace; import ru.windcorp.progressia.common.world.rels.BlockFace;
import ru.windcorp.progressia.common.world.rels.RelFace; import ru.windcorp.progressia.common.world.rels.RelFace;
import ru.windcorp.progressia.common.world.tile.TileDataStack; import ru.windcorp.progressia.common.world.tile.TileDataStack;
import ru.windcorp.progressia.common.world.tile.TileReference; import ru.windcorp.progressia.common.world.tile.TileDataReference;
import ru.windcorp.progressia.server.world.block.BlockLogic; import ru.windcorp.progressia.server.world.block.BlockLogic;
import ru.windcorp.progressia.server.world.block.BlockLogicRegistry; import ru.windcorp.progressia.server.world.block.BlockLogicRegistry;
import ru.windcorp.progressia.server.world.block.TickableBlock; import ru.windcorp.progressia.server.world.block.TickableBlock;
@ -41,16 +41,17 @@ import ru.windcorp.progressia.server.world.tasks.TickChunk;
import ru.windcorp.progressia.server.world.ticking.TickingPolicy; import ru.windcorp.progressia.server.world.ticking.TickingPolicy;
import ru.windcorp.progressia.server.world.tile.TickableTile; import ru.windcorp.progressia.server.world.tile.TickableTile;
import ru.windcorp.progressia.server.world.tile.TileLogic; import ru.windcorp.progressia.server.world.tile.TileLogic;
import ru.windcorp.progressia.server.world.tile.TileLogicReference;
import ru.windcorp.progressia.server.world.tile.TileLogicRegistry; import ru.windcorp.progressia.server.world.tile.TileLogicRegistry;
import ru.windcorp.progressia.server.world.tile.TileLogicStack; import ru.windcorp.progressia.server.world.tile.TileLogicStack;
public class ChunkLogic implements GenericChunk<ChunkLogic, BlockLogic, TileLogic, TileLogicStack> { public class ChunkLogic implements GenericChunk<BlockLogic, TileLogic, TileLogicStack, TileLogicReference, ChunkLogic> {
private final WorldLogic world; private final WorldLogic world;
private final ChunkData data; private final ChunkData data;
private final Collection<Vec3i> tickingBlocks = new ArrayList<>(); private final Collection<Vec3i> tickingBlocks = new ArrayList<>();
private final Collection<TileReference> tickingTiles = new ArrayList<>(); private final Collection<TileDataReference> tickingTiles = new ArrayList<>();
private final TickChunk tickTask = new TickChunk(this); private final TickChunk tickTask = new TickChunk(this);
@ -124,7 +125,7 @@ public class ChunkLogic implements GenericChunk<ChunkLogic, BlockLogic, TileLogi
}); });
} }
public void forEachTickingTile(BiConsumer<TileReference, TileLogic> action) { public void forEachTickingTile(BiConsumer<TileDataReference, TileLogic> action) {
tickingTiles.forEach(ref -> { tickingTiles.forEach(ref -> {
action.accept( action.accept(
ref, ref,
@ -138,6 +139,28 @@ public class ChunkLogic implements GenericChunk<ChunkLogic, BlockLogic, TileLogi
} }
private class TileLogicStackImpl extends TileLogicStack { private class TileLogicStackImpl extends TileLogicStack {
private class TileLogicReferenceImpl implements TileLogicReference {
private final TileDataReference parent;
public TileLogicReferenceImpl (TileDataReference parent) {
this.parent = parent;
}
@Override
public TileLogic get() {
return TileLogicRegistry.getInstance().get(parent.get().getId());
}
@Override
public int getIndex() {
return parent.getIndex();
}
@Override
public TileLogicStack getStack() {
return TileLogicStackImpl.this;
}
}
private final TileDataStack parent; private final TileDataStack parent;
@ -160,6 +183,21 @@ public class ChunkLogic implements GenericChunk<ChunkLogic, BlockLogic, TileLogi
return parent.getFace(); return parent.getFace();
} }
@Override
public TileLogicReference getReference(int index) {
return new TileLogicReferenceImpl(parent.getReference(index));
}
@Override
public int getIndexByTag(int tag) {
return parent.getIndexByTag(tag);
}
@Override
public int getTagByIndex(int index) {
return parent.getTagByIndex(index);
}
@Override @Override
public TileLogic get(int index) { public TileLogic get(int index) {
return TileLogicRegistry.getInstance().get(parent.get(index).getId()); return TileLogicRegistry.getInstance().get(parent.get(index).getId());

View File

@ -29,7 +29,7 @@ import ru.windcorp.progressia.common.world.generic.GenericTileStack;
import ru.windcorp.progressia.common.world.rels.BlockFace; import ru.windcorp.progressia.common.world.rels.BlockFace;
import ru.windcorp.progressia.common.world.rels.RelFace; import ru.windcorp.progressia.common.world.rels.RelFace;
import ru.windcorp.progressia.common.world.tile.TileDataStack; import ru.windcorp.progressia.common.world.tile.TileDataStack;
import ru.windcorp.progressia.common.world.tile.TileReference; import ru.windcorp.progressia.common.world.tile.TileDataReference;
import ru.windcorp.progressia.server.Server; import ru.windcorp.progressia.server.Server;
import ru.windcorp.progressia.server.world.block.BlockTickContext; import ru.windcorp.progressia.server.world.block.BlockTickContext;
import ru.windcorp.progressia.server.world.tile.TSTickContext; import ru.windcorp.progressia.server.world.tile.TSTickContext;
@ -109,14 +109,14 @@ public abstract class TickContextMutable implements BlockTickContext, TSTickCont
Block withBlock(Vec3i blockInWorld); Block withBlock(Vec3i blockInWorld);
TileStack withTS(GenericTileStack<?, ?, ?> tileStack); TileStack withTS(GenericTileStack<?, ?, ?, ?, ?> tileStack);
default Builder.Chunk withChunk(ChunkData chunk) { default Builder.Chunk withChunk(ChunkData chunk) {
Objects.requireNonNull(chunk, "chunk"); Objects.requireNonNull(chunk, "chunk");
return withChunk(chunk.getPosition()); return withChunk(chunk.getPosition());
} }
default TileTickContext withTile(TileReference ref) { default TileTickContext withTile(TileDataReference ref) {
Objects.requireNonNull(ref, "ref"); Objects.requireNonNull(ref, "ref");
return withTS(ref.getStack()).withLayer(ref.getIndex()); return withTS(ref.getStack()).withLayer(ref.getIndex());
} }
@ -259,7 +259,7 @@ public abstract class TickContextMutable implements BlockTickContext, TSTickCont
} }
@Override @Override
public TileStack withTS(GenericTileStack<?, ?, ?> tileStack) { public TileStack withTS(GenericTileStack<?, ?, ?, ?, ?> tileStack) {
Objects.requireNonNull(tileStack, "tileStack"); Objects.requireNonNull(tileStack, "tileStack");
return withBlock( return withBlock(

View File

@ -37,10 +37,11 @@ import ru.windcorp.progressia.server.world.generation.WorldGenerator;
import ru.windcorp.progressia.server.world.tasks.TickEntitiesTask; import ru.windcorp.progressia.server.world.tasks.TickEntitiesTask;
import ru.windcorp.progressia.server.world.ticking.Evaluation; import ru.windcorp.progressia.server.world.ticking.Evaluation;
import ru.windcorp.progressia.server.world.tile.TileLogic; import ru.windcorp.progressia.server.world.tile.TileLogic;
import ru.windcorp.progressia.server.world.tile.TileLogicReference;
import ru.windcorp.progressia.server.world.tile.TileLogicStack; import ru.windcorp.progressia.server.world.tile.TileLogicStack;
public class WorldLogic public class WorldLogic
implements GenericWorld<BlockLogic, TileLogic, TileLogicStack, ChunkLogic, EntityData implements GenericWorld<BlockLogic, TileLogic, TileLogicStack, TileLogicReference, ChunkLogic, EntityData
// not using EntityLogic because it is stateless // not using EntityLogic because it is stateless
> { > {

View File

@ -0,0 +1,27 @@
/*
* 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.server.world.tile;
import ru.windcorp.progressia.common.world.generic.GenericTileReference;
import ru.windcorp.progressia.server.world.ChunkLogic;
import ru.windcorp.progressia.server.world.block.BlockLogic;
public interface TileLogicReference
extends GenericTileReference<BlockLogic, TileLogic, TileLogicStack, TileLogicReference, ChunkLogic> {
}

View File

@ -21,9 +21,10 @@ package ru.windcorp.progressia.server.world.tile;
import ru.windcorp.progressia.common.world.generic.GenericTileStack; import ru.windcorp.progressia.common.world.generic.GenericTileStack;
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.block.BlockLogic;
public abstract class TileLogicStack public abstract class TileLogicStack
extends GenericTileStack<TileLogicStack, TileLogic, ChunkLogic> { extends GenericTileStack<BlockLogic, TileLogic, TileLogicStack, TileLogicReference, ChunkLogic> {
public abstract TileDataStack getData(); public abstract TileDataStack getData();

View File

@ -20,7 +20,7 @@ package ru.windcorp.progressia.server.world.tile;
import ru.windcorp.progressia.common.world.tile.TileData; import ru.windcorp.progressia.common.world.tile.TileData;
import ru.windcorp.progressia.common.world.tile.TileDataStack; import ru.windcorp.progressia.common.world.tile.TileDataStack;
import ru.windcorp.progressia.common.world.tile.TileReference; import ru.windcorp.progressia.common.world.tile.TileDataReference;
public interface TileTickContext extends TSTickContext { public interface TileTickContext extends TSTickContext {
@ -53,7 +53,7 @@ public interface TileTickContext extends TSTickContext {
return stack.get(getLayer()); return stack.get(getLayer());
} }
default TileReference getReference() { default TileDataReference getReference() {
return getTDS().getReference(getLayer()); return getTDS().getReference(getLayer());
} }