From 7e19bfa19bc4d4129bf22a79ac360da35c72cdd7 Mon Sep 17 00:00:00 2001 From: Robbe Pincket <7889478+Kroppeb@users.noreply.github.com> Date: Mon, 3 Apr 2023 23:03:47 +0200 Subject: [PATCH] Make the gc free serializer compatible with lithium (maybe) I can't test this for some reason? --- .../common/ChunkDataSerializer.java | 112 +++++++----------- .../common/utils/LithiumUtil.java | 42 +++++++ 2 files changed, 88 insertions(+), 66 deletions(-) create mode 100644 c2me-opts-chunk-serializer/src/main/java/com/ishland/c2me/opts/chunk_serializer/common/utils/LithiumUtil.java diff --git a/c2me-opts-chunk-serializer/src/main/java/com/ishland/c2me/opts/chunk_serializer/common/ChunkDataSerializer.java b/c2me-opts-chunk-serializer/src/main/java/com/ishland/c2me/opts/chunk_serializer/common/ChunkDataSerializer.java index b85ce60f..95e5a797 100644 --- a/c2me-opts-chunk-serializer/src/main/java/com/ishland/c2me/opts/chunk_serializer/common/ChunkDataSerializer.java +++ b/c2me-opts-chunk-serializer/src/main/java/com/ishland/c2me/opts/chunk_serializer/common/ChunkDataSerializer.java @@ -1,5 +1,6 @@ package com.ishland.c2me.opts.chunk_serializer.common; +import com.ishland.c2me.opts.chunk_serializer.common.utils.LithiumUtil; import com.ishland.c2me.opts.chunk_serializer.common.utils.StarLightUtil; import com.ishland.c2me.opts.chunk_serializer.mixin.BelowZeroRetrogenAccessor; import com.ishland.c2me.opts.chunk_serializer.mixin.BlendingDataAccessor; @@ -18,12 +19,12 @@ import net.minecraft.block.Block; import net.minecraft.block.BlockState; import net.minecraft.block.Blocks; -import net.minecraft.fluid.Fluid; import net.minecraft.nbt.NbtCompound; import net.minecraft.nbt.NbtElement; import net.minecraft.nbt.NbtList; import net.minecraft.nbt.NbtOps; import net.minecraft.nbt.NbtShort; +import net.minecraft.registry.DefaultedRegistry; import net.minecraft.registry.Registries; import net.minecraft.registry.Registry; import net.minecraft.registry.RegistryKeys; @@ -71,10 +72,10 @@ import org.jetbrains.annotations.Nullable; import java.util.BitSet; +import java.util.Collection; import java.util.List; import java.util.Map; import java.util.Optional; -import java.util.Queue; import java.util.function.Function; import java.util.stream.LongStream; @@ -627,10 +628,10 @@ public static NbtList toNbt(ShortList[] lists) { * mirror of {@link ChunkSerializer#serializeTicks(ServerWorld, NbtCompound, Chunk.TickSchedulers)} */ private static void serializeTicks(NbtWriter writer, ServerWorld world, Chunk.TickSchedulers tickSchedulers) { - long l = world.getLevelProperties().getTime(); + long time = world.getLevelProperties().getTime(); - writeBlockTicks(writer, l, tickSchedulers.blocks()); - writeFluidTicks(writer, l, tickSchedulers.fluids()); + writeTicks(writer, time, tickSchedulers.blocks(), Registries.BLOCK, STRING_BLOCK_TICKS); + writeTicks(writer, time, tickSchedulers.fluids(), Registries.FLUID, STRING_FLUID_TICKS); } @@ -639,91 +640,70 @@ private static void serializeTicks(NbtWriter writer, ServerWorld world, Chunk.Ti * {@link ChunkTickScheduler#toNbt(long, Function)} and * {@link Tick#toNbt(Function)} */ - private static void writeBlockTicks(NbtWriter writer, long l, SerializableTickScheduler blocks) { - if (blocks instanceof SimpleTickSchedulerAccessor simpleTickSchedulerAccessor) { - final List> scheduledTicks = simpleTickSchedulerAccessor.getScheduledTicks(); - writer.startFixedList(STRING_BLOCK_TICKS, scheduledTicks.size(), NbtElement.COMPOUND_TYPE); - for (Tick scheduledTick : scheduledTicks) { - writeBlockTick(writer, scheduledTick); + private static void writeTicks( + NbtWriter writer, + long time, + SerializableTickScheduler scheduler, + DefaultedRegistry reg, + byte[] key + ) { + if (scheduler instanceof SimpleTickSchedulerAccessor simpleTickSchedulerAccessor) { + final List> scheduledTicks = simpleTickSchedulerAccessor.getScheduledTicks(); + writer.startFixedList(key, scheduledTicks.size(), NbtElement.COMPOUND_TYPE); + for (Tick scheduledTick : scheduledTicks) { + writeTick(writer, scheduledTick, reg); } - } else if (blocks instanceof ChunkTickSchedulerAccessor chunkTickSchedulerAccessor) { + } else if (scheduler instanceof ChunkTickSchedulerAccessor chunkTickSchedulerAccessor) { - final @Nullable List> scheduledTicks = chunkTickSchedulerAccessor.getTicks(); - final Queue> tickQueue = chunkTickSchedulerAccessor.getTickQueue(); + int size = 0; + long list = writer.startList(key, NbtElement.COMPOUND_TYPE); - int size = (scheduledTicks == null ? tickQueue.size() : scheduledTicks.size() + tickQueue.size()); + final @Nullable List> scheduledTicks = chunkTickSchedulerAccessor.getTicks(); - writer.startFixedList(STRING_BLOCK_TICKS, size, NbtElement.COMPOUND_TYPE); if (scheduledTicks != null) { - for (Tick scheduledTick : scheduledTicks) { - writeBlockTick(writer, scheduledTick); + size += scheduledTicks.size(); + + for (Tick scheduledTick : scheduledTicks) { + writeTick(writer, scheduledTick, reg); } } - for (OrderedTick orderedTick : tickQueue) { - writeOrderedBlockTick(writer, orderedTick, l); - } - } else { - // FALLBACK? - //noinspection deprecation - writer.putElement(STRING_BLOCK_TICKS, blocks.toNbt(l, block -> Registries.BLOCK.getId(block).toString())); - } - } - - private static void writeFluidTicks(NbtWriter writer, long l, SerializableTickScheduler fluids) { - if (fluids instanceof SimpleTickSchedulerAccessor simpleTickSchedulerAccessor) { - final List> scheduledTicks = simpleTickSchedulerAccessor.getScheduledTicks(); - writer.startFixedList(STRING_FLUID_TICKS, scheduledTicks.size(), NbtElement.COMPOUND_TYPE); - for (Tick scheduledTick : scheduledTicks) { - writeFluidTick(writer, scheduledTick); - } - } else if (fluids instanceof ChunkTickSchedulerAccessor chunkTickSchedulerAccessor) { - final @Nullable List> scheduledTicks = chunkTickSchedulerAccessor.getTicks(); - final Queue> tickQueue = chunkTickSchedulerAccessor.getTickQueue(); + if (LithiumUtil.IS_LITHIUM_TICK_QUEUE_ACTIVE) { + final Collection>> tickQueues = LithiumUtil.getTickQueueCollection(chunkTickSchedulerAccessor); - int size = (scheduledTicks == null ? tickQueue.size() : scheduledTicks.size() + tickQueue.size()); + for (Collection> tickQueue : tickQueues) { + size += tickQueue.size(); + for (OrderedTick orderedTick : tickQueue) { + writeOrderedTick(writer, orderedTick, time, reg); + } + } + } else { + final Collection> tickQueue = chunkTickSchedulerAccessor.getTickQueue(); + size += tickQueue.size(); - writer.startFixedList(STRING_FLUID_TICKS, size, NbtElement.COMPOUND_TYPE); - if (scheduledTicks != null) { - for (Tick scheduledTick : scheduledTicks) { - writeFluidTick(writer, scheduledTick); + for (OrderedTick orderedTick : tickQueue) { + writeOrderedTick(writer, orderedTick, time, reg); } } - for (OrderedTick orderedTick : tickQueue) { - writeOrderedFluidTick(writer, orderedTick, l); - } + writer.finishList(list, size); } else { // FALLBACK? //noinspection deprecation - writer.putElement(STRING_FLUID_TICKS, fluids.toNbt(l, block -> Registries.FLUID.getId(block).toString())); + writer.putElement(key, scheduler.toNbt(time, block -> reg.getId(block).toString())); } } - private static void writeOrderedBlockTick(NbtWriter writer, OrderedTick orderedTick, long l) { - writer.compoundEntryStart(); - writer.putRegistry(STRING_CHAR_SMALL_I, Registries.BLOCK, orderedTick.type()); - writeGenericTickData(writer, orderedTick.pos(), (int) (orderedTick.triggerTick() - l), orderedTick.priority()); - writer.finishCompound(); - } - - private static void writeOrderedFluidTick(NbtWriter writer, OrderedTick orderedTick, long l) { - writer.compoundEntryStart(); - writer.putRegistry(STRING_CHAR_SMALL_I, Registries.FLUID, orderedTick.type()); - writeGenericTickData(writer, orderedTick.pos(), (int) (orderedTick.triggerTick() - l), orderedTick.priority()); - writer.finishCompound(); - } - - private static void writeFluidTick(NbtWriter writer, Tick scheduledTick) { + private static void writeOrderedTick(NbtWriter writer, OrderedTick orderedTick, long time, Registry reg) { writer.compoundEntryStart(); - writer.putRegistry(STRING_CHAR_SMALL_I, Registries.FLUID, scheduledTick.type()); - writeGenericTickData(writer, scheduledTick); + writer.putRegistry(STRING_CHAR_SMALL_I, reg, orderedTick.type()); + writeGenericTickData(writer, orderedTick.pos(), (int) (orderedTick.triggerTick() - time), orderedTick.priority()); writer.finishCompound(); } - private static void writeBlockTick(NbtWriter writer, Tick scheduledTick) { + private static void writeTick(NbtWriter writer, Tick scheduledTick, Registry reg) { writer.compoundEntryStart(); - writer.putRegistry(STRING_CHAR_SMALL_I, Registries.BLOCK, scheduledTick.type()); + writer.putRegistry(STRING_CHAR_SMALL_I, reg, scheduledTick.type()); writeGenericTickData(writer, scheduledTick); writer.finishCompound(); } diff --git a/c2me-opts-chunk-serializer/src/main/java/com/ishland/c2me/opts/chunk_serializer/common/utils/LithiumUtil.java b/c2me-opts-chunk-serializer/src/main/java/com/ishland/c2me/opts/chunk_serializer/common/utils/LithiumUtil.java new file mode 100644 index 00000000..9727db7c --- /dev/null +++ b/c2me-opts-chunk-serializer/src/main/java/com/ishland/c2me/opts/chunk_serializer/common/utils/LithiumUtil.java @@ -0,0 +1,42 @@ +package com.ishland.c2me.opts.chunk_serializer.common.utils; + +import com.ishland.c2me.opts.chunk_serializer.mixin.ChunkTickSchedulerAccessor; +import it.unimi.dsi.fastutil.longs.Long2ReferenceAVLTreeMap; +import net.minecraft.world.tick.ChunkTickScheduler; +import net.minecraft.world.tick.OrderedTick; + +import java.lang.reflect.Field; +import java.util.Collection; + +public class LithiumUtil { + static final Field chunkTickScheduler$TickQueuesByTimeAndPriority; + + + static { + Class chunkTickSchedulerClass = ChunkTickScheduler.class; + + Field tickQueuesByTimeAndPriority = null; + try { + tickQueuesByTimeAndPriority = chunkTickSchedulerClass.getDeclaredField("tickQueuesByTimeAndPriority"); + tickQueuesByTimeAndPriority.setAccessible(true); + } catch (NoSuchFieldException e) { + // pass + } + + chunkTickScheduler$TickQueuesByTimeAndPriority = tickQueuesByTimeAndPriority; + } + + public static final boolean IS_LITHIUM_TICK_QUEUE_ACTIVE = chunkTickScheduler$TickQueuesByTimeAndPriority != null; + + public static Collection>> getTickQueueCollection(ChunkTickSchedulerAccessor accessor) { + try { + //noinspection unchecked + Long2ReferenceAVLTreeMap>> tickQueuesByTimeAndPriority = + (Long2ReferenceAVLTreeMap>>) + chunkTickScheduler$TickQueuesByTimeAndPriority.get(accessor); + return tickQueuesByTimeAndPriority.values(); + } catch (IllegalAccessException e) { + throw new RuntimeException(e); + } + } +}