Store ticking blocks in chunk sections as positions only
Since we no longer use the state stored directly in the IBlockDataList, it makes no sense to use IBlockDataList at all.
This commit is contained in:
@@ -13,15 +13,15 @@ import java.util.NoSuchElementException;
|
||||
*/
|
||||
public final class EntityList implements Iterable<Entity> {
|
||||
|
||||
protected final Int2IntOpenHashMap entityToIndex = new Int2IntOpenHashMap(2, 0.8f);
|
||||
private final Int2IntOpenHashMap entityToIndex = new Int2IntOpenHashMap(2, 0.8f);
|
||||
{
|
||||
this.entityToIndex.defaultReturnValue(Integer.MIN_VALUE);
|
||||
}
|
||||
|
||||
protected static final Entity[] EMPTY_LIST = new Entity[0];
|
||||
private static final Entity[] EMPTY_LIST = new Entity[0];
|
||||
|
||||
protected Entity[] entities = EMPTY_LIST;
|
||||
protected int count;
|
||||
private Entity[] entities = EMPTY_LIST;
|
||||
private int count;
|
||||
|
||||
public int size() {
|
||||
return this.count;
|
||||
@@ -94,10 +94,9 @@ public final class EntityList implements Iterable<Entity> {
|
||||
|
||||
@Override
|
||||
public Iterator<Entity> iterator() {
|
||||
return new Iterator<Entity>() {
|
||||
|
||||
Entity lastRet;
|
||||
int current;
|
||||
return new Iterator<>() {
|
||||
private Entity lastRet;
|
||||
private int current;
|
||||
|
||||
@Override
|
||||
public boolean hasNext() {
|
||||
|
||||
@@ -1,125 +0,0 @@
|
||||
package ca.spottedleaf.moonrise.common.list;
|
||||
|
||||
import it.unimi.dsi.fastutil.longs.LongIterator;
|
||||
import it.unimi.dsi.fastutil.shorts.Short2LongOpenHashMap;
|
||||
import java.util.Arrays;
|
||||
import net.minecraft.world.level.block.Block;
|
||||
import net.minecraft.world.level.block.state.BlockState;
|
||||
import net.minecraft.world.level.chunk.GlobalPalette;
|
||||
|
||||
public final class IBlockDataList {
|
||||
|
||||
private static final GlobalPalette<BlockState> GLOBAL_PALETTE = new GlobalPalette<>(Block.BLOCK_STATE_REGISTRY);
|
||||
|
||||
// map of location -> (index | (location << 16) | (palette id << 32))
|
||||
private final Short2LongOpenHashMap map = new Short2LongOpenHashMap(2, 0.8f);
|
||||
{
|
||||
this.map.defaultReturnValue(Long.MAX_VALUE);
|
||||
}
|
||||
|
||||
private static final long[] EMPTY_LIST = new long[0];
|
||||
|
||||
private long[] byIndex = EMPTY_LIST;
|
||||
private int size;
|
||||
|
||||
public static int getLocationKey(final int x, final int y, final int z) {
|
||||
return (x & 15) | (((z & 15) << 4)) | ((y & 255) << (4 + 4));
|
||||
}
|
||||
|
||||
public static BlockState getBlockDataFromRaw(final long raw) {
|
||||
return GLOBAL_PALETTE.valueFor((int)(raw >>> 32));
|
||||
}
|
||||
|
||||
public static int getIndexFromRaw(final long raw) {
|
||||
return (int)(raw & 0xFFFF);
|
||||
}
|
||||
|
||||
public static int getLocationFromRaw(final long raw) {
|
||||
return (int)((raw >>> 16) & 0xFFFF);
|
||||
}
|
||||
|
||||
public static long getRawFromValues(final int index, final int location, final BlockState data) {
|
||||
return (long)index | ((long)location << 16) | (((long)GLOBAL_PALETTE.idFor(data)) << 32);
|
||||
}
|
||||
|
||||
public static long setIndexRawValues(final long value, final int index) {
|
||||
return value & ~(0xFFFF) | (index);
|
||||
}
|
||||
|
||||
public long add(final int x, final int y, final int z, final BlockState data) {
|
||||
return this.add(getLocationKey(x, y, z), data);
|
||||
}
|
||||
|
||||
public long add(final int location, final BlockState data) {
|
||||
final long curr = this.map.get((short)location);
|
||||
|
||||
if (curr == Long.MAX_VALUE) {
|
||||
final int index = this.size++;
|
||||
final long raw = getRawFromValues(index, location, data);
|
||||
this.map.put((short)location, raw);
|
||||
|
||||
if (index >= this.byIndex.length) {
|
||||
this.byIndex = Arrays.copyOf(this.byIndex, (int)Math.max(4L, this.byIndex.length * 2L));
|
||||
}
|
||||
|
||||
this.byIndex[index] = raw;
|
||||
return raw;
|
||||
} else {
|
||||
final int index = getIndexFromRaw(curr);
|
||||
final long raw = this.byIndex[index] = getRawFromValues(index, location, data);
|
||||
|
||||
this.map.put((short)location, raw);
|
||||
|
||||
return raw;
|
||||
}
|
||||
}
|
||||
|
||||
public long remove(final int x, final int y, final int z) {
|
||||
return this.remove(getLocationKey(x, y, z));
|
||||
}
|
||||
|
||||
public long remove(final int location) {
|
||||
final long ret = this.map.remove((short)location);
|
||||
final int index = getIndexFromRaw(ret);
|
||||
if (ret == Long.MAX_VALUE) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
// move the entry at the end to this index
|
||||
final int endIndex = --this.size;
|
||||
final long end = this.byIndex[endIndex];
|
||||
if (index != endIndex) {
|
||||
// not empty after this call
|
||||
this.map.put((short)getLocationFromRaw(end), setIndexRawValues(end, index));
|
||||
}
|
||||
this.byIndex[index] = end;
|
||||
this.byIndex[endIndex] = 0L;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
public int size() {
|
||||
return this.size;
|
||||
}
|
||||
|
||||
public long getRaw(final int index) {
|
||||
return this.byIndex[index];
|
||||
}
|
||||
|
||||
public int getLocation(final int index) {
|
||||
return getLocationFromRaw(this.getRaw(index));
|
||||
}
|
||||
|
||||
public BlockState getData(final int index) {
|
||||
return getBlockDataFromRaw(this.getRaw(index));
|
||||
}
|
||||
|
||||
public void clear() {
|
||||
this.size = 0;
|
||||
this.map.clear();
|
||||
}
|
||||
|
||||
public LongIterator getRawIterator() {
|
||||
return this.map.values().iterator();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,70 @@
|
||||
package ca.spottedleaf.moonrise.common.list;
|
||||
|
||||
import it.unimi.dsi.fastutil.ints.Int2IntOpenHashMap;
|
||||
import java.util.Arrays;
|
||||
|
||||
public final class IntList {
|
||||
|
||||
private final Int2IntOpenHashMap map = new Int2IntOpenHashMap();
|
||||
{
|
||||
this.map.defaultReturnValue(Integer.MIN_VALUE);
|
||||
}
|
||||
|
||||
private static final int[] EMPTY_LIST = new int[0];
|
||||
|
||||
private int[] byIndex = EMPTY_LIST;
|
||||
private int count;
|
||||
|
||||
public int size() {
|
||||
return this.count;
|
||||
}
|
||||
|
||||
public int getRaw(final int index) {
|
||||
return this.byIndex[index];
|
||||
}
|
||||
|
||||
public boolean add(final int value) {
|
||||
final int count = this.count;
|
||||
final int currIndex = this.map.putIfAbsent(value, count);
|
||||
|
||||
if (currIndex != Integer.MIN_VALUE) {
|
||||
return false; // already in this list
|
||||
}
|
||||
|
||||
int[] list = this.byIndex;
|
||||
|
||||
if (list.length == count) {
|
||||
// resize required
|
||||
list = this.byIndex = Arrays.copyOf(list, (int)Math.max(4L, count * 2L)); // overflow results in negative
|
||||
}
|
||||
|
||||
list[count] = value;
|
||||
this.count = count + 1;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public boolean remove(final int value) {
|
||||
final int index = this.map.remove(value);
|
||||
if (index == Integer.MIN_VALUE) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// move the entry at the end to this index
|
||||
final int endIndex = --this.count;
|
||||
final int end = this.byIndex[endIndex];
|
||||
if (index != endIndex) {
|
||||
// not empty after this call
|
||||
this.map.put(end, index);
|
||||
}
|
||||
this.byIndex[index] = end;
|
||||
this.byIndex[endIndex] = 0;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public void clear() {
|
||||
this.count = 0;
|
||||
this.map.clear();
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
package ca.spottedleaf.moonrise.mixin.block_counting;
|
||||
|
||||
import ca.spottedleaf.moonrise.common.list.IBlockDataList;
|
||||
import ca.spottedleaf.moonrise.common.list.IntList;
|
||||
import ca.spottedleaf.moonrise.patches.block_counting.BlockCountingBitStorage;
|
||||
import ca.spottedleaf.moonrise.patches.collisions.CollisionUtil;
|
||||
import ca.spottedleaf.moonrise.patches.block_counting.BlockCountingChunkSection;
|
||||
@@ -58,7 +58,7 @@ abstract class LevelChunkSectionMixin implements BlockCountingChunkSection {
|
||||
private int specialCollidingBlocks;
|
||||
|
||||
@Unique
|
||||
private final IBlockDataList tickingBlocks = new IBlockDataList();
|
||||
private final IntList tickingBlocks = new IntList();
|
||||
|
||||
@Override
|
||||
public final int moonrise$getSpecialCollidingBlocks() {
|
||||
@@ -66,7 +66,7 @@ abstract class LevelChunkSectionMixin implements BlockCountingChunkSection {
|
||||
}
|
||||
|
||||
@Override
|
||||
public final IBlockDataList moonrise$getTickingBlockList() {
|
||||
public final IntList moonrise$getTickingBlockList() {
|
||||
return this.tickingBlocks;
|
||||
}
|
||||
|
||||
@@ -92,11 +92,13 @@ abstract class LevelChunkSectionMixin implements BlockCountingChunkSection {
|
||||
++this.specialCollidingBlocks;
|
||||
}
|
||||
|
||||
final int position = x | (z << 4) | (y << (4+4));
|
||||
|
||||
if (oldState.isRandomlyTicking()) {
|
||||
this.tickingBlocks.remove(x, y, z);
|
||||
this.tickingBlocks.remove(position);
|
||||
}
|
||||
if (newState.isRandomlyTicking()) {
|
||||
this.tickingBlocks.add(x, y, z, newState);
|
||||
this.tickingBlocks.add(position);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -149,14 +151,14 @@ abstract class LevelChunkSectionMixin implements BlockCountingChunkSection {
|
||||
|
||||
Objects.checkFromToIndex(0, paletteCount, raw.length);
|
||||
for (int i = 0; i < paletteCount; ++i) {
|
||||
this.tickingBlocks.add(raw[i], state);
|
||||
this.tickingBlocks.add(raw[i]);
|
||||
}
|
||||
}
|
||||
|
||||
final FluidState fluid = state.getFluidState();
|
||||
|
||||
if (!fluid.isEmpty()) {
|
||||
//this.nonEmptyBlockCount += count; // fix vanilla bug: make non empty block count correct
|
||||
//this.nonEmptyBlockCount += count; // fix vanilla bug: make non-empty block count correct
|
||||
if (fluid.isRandomlyTicking()) {
|
||||
this.tickingFluidCount += paletteCount;
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
package ca.spottedleaf.moonrise.mixin.random_ticking;
|
||||
|
||||
import ca.spottedleaf.moonrise.common.list.IBlockDataList;
|
||||
import ca.spottedleaf.moonrise.common.list.IntList;
|
||||
import ca.spottedleaf.moonrise.common.util.MoonriseCommon;
|
||||
import ca.spottedleaf.moonrise.common.util.WorldUtil;
|
||||
import ca.spottedleaf.moonrise.patches.block_counting.BlockCountingChunkSection;
|
||||
@@ -70,10 +70,7 @@ abstract class ServerLevelMixin extends Level implements WorldGenLevel {
|
||||
continue;
|
||||
}
|
||||
|
||||
final IBlockDataList tickList = ((BlockCountingChunkSection)section).moonrise$getTickingBlockList();
|
||||
if (tickList.size() == 0) {
|
||||
continue;
|
||||
}
|
||||
final IntList tickList = ((BlockCountingChunkSection)section).moonrise$getTickingBlockList();
|
||||
|
||||
for (int i = 0; i < tickSpeed; ++i) {
|
||||
final int tickingBlocks = tickList.size();
|
||||
@@ -84,15 +81,11 @@ abstract class ServerLevelMixin extends Level implements WorldGenLevel {
|
||||
continue;
|
||||
}
|
||||
|
||||
final long raw = tickList.getRaw(index);
|
||||
final int location = IBlockDataList.getLocationFromRaw(raw);
|
||||
final int randomX = (location & 15);
|
||||
final int randomY = ((location >>> (4 + 4)) & 255);
|
||||
final int randomZ = ((location >>> 4) & 15);
|
||||
final BlockState state = states.get(randomX | (randomZ << 4) | (randomY << 8));
|
||||
final int location = tickList.getRaw(index);
|
||||
final BlockState state = states.get(location);
|
||||
|
||||
// do not use a mutable pos, as some random tick implementations store the input without calling immutable()!
|
||||
final BlockPos pos = new BlockPos(randomX | offsetX, randomY | offsetY, randomZ | offsetZ);
|
||||
final BlockPos pos = new BlockPos((location & 15) | offsetX, ((location >>> (4 + 4)) & 15) | offsetY, ((location >>> 4) & 15) | offsetZ);
|
||||
|
||||
state.randomTick((ServerLevel)(Object)this, pos, random);
|
||||
if (tickFluids) {
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
package ca.spottedleaf.moonrise.patches.block_counting;
|
||||
|
||||
import ca.spottedleaf.moonrise.common.list.IBlockDataList;
|
||||
import ca.spottedleaf.moonrise.common.list.IntList;
|
||||
|
||||
public interface BlockCountingChunkSection {
|
||||
|
||||
public int moonrise$getSpecialCollidingBlocks();
|
||||
|
||||
public IBlockDataList moonrise$getTickingBlockList();
|
||||
public IntList moonrise$getTickingBlockList();
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user