diff --git a/src/main/java/ca/spottedleaf/moonrise/common/list/EntityList.java b/src/main/java/ca/spottedleaf/moonrise/common/list/EntityList.java index ba68998..7fed43a 100644 --- a/src/main/java/ca/spottedleaf/moonrise/common/list/EntityList.java +++ b/src/main/java/ca/spottedleaf/moonrise/common/list/EntityList.java @@ -13,15 +13,15 @@ import java.util.NoSuchElementException; */ public final class EntityList implements Iterable { - 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 { @Override public Iterator iterator() { - return new Iterator() { - - Entity lastRet; - int current; + return new Iterator<>() { + private Entity lastRet; + private int current; @Override public boolean hasNext() { diff --git a/src/main/java/ca/spottedleaf/moonrise/common/list/IBlockDataList.java b/src/main/java/ca/spottedleaf/moonrise/common/list/IBlockDataList.java deleted file mode 100644 index fcfbca3..0000000 --- a/src/main/java/ca/spottedleaf/moonrise/common/list/IBlockDataList.java +++ /dev/null @@ -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 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(); - } -} \ No newline at end of file diff --git a/src/main/java/ca/spottedleaf/moonrise/common/list/IntList.java b/src/main/java/ca/spottedleaf/moonrise/common/list/IntList.java new file mode 100644 index 0000000..b08a2bd --- /dev/null +++ b/src/main/java/ca/spottedleaf/moonrise/common/list/IntList.java @@ -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(); + } +} diff --git a/src/main/java/ca/spottedleaf/moonrise/mixin/block_counting/LevelChunkSectionMixin.java b/src/main/java/ca/spottedleaf/moonrise/mixin/block_counting/LevelChunkSectionMixin.java index 48fbffe..7503572 100644 --- a/src/main/java/ca/spottedleaf/moonrise/mixin/block_counting/LevelChunkSectionMixin.java +++ b/src/main/java/ca/spottedleaf/moonrise/mixin/block_counting/LevelChunkSectionMixin.java @@ -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; } diff --git a/src/main/java/ca/spottedleaf/moonrise/mixin/random_ticking/ServerLevelMixin.java b/src/main/java/ca/spottedleaf/moonrise/mixin/random_ticking/ServerLevelMixin.java index cee750a..2c3bd83 100644 --- a/src/main/java/ca/spottedleaf/moonrise/mixin/random_ticking/ServerLevelMixin.java +++ b/src/main/java/ca/spottedleaf/moonrise/mixin/random_ticking/ServerLevelMixin.java @@ -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) { diff --git a/src/main/java/ca/spottedleaf/moonrise/patches/block_counting/BlockCountingChunkSection.java b/src/main/java/ca/spottedleaf/moonrise/patches/block_counting/BlockCountingChunkSection.java index a08ddb0..b992eb8 100644 --- a/src/main/java/ca/spottedleaf/moonrise/patches/block_counting/BlockCountingChunkSection.java +++ b/src/main/java/ca/spottedleaf/moonrise/patches/block_counting/BlockCountingChunkSection.java @@ -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(); }