1
0
mirror of https://github.com/SquidDev-CC/CC-Tweaked synced 2025-11-04 23:53:01 +00:00

Reschedule block entities when chunks are loaded

Minecraft sometimes keeps chunks in-memory, but not actively loaded. If
we schedule a block entity to be ticked and that chunk is is then
transitioned to this partially-loaded state, then the block entity is
never actually ticked.

This is most visible with monitors. When a monitor's contents changes,
if the monitor is not already marked as changed, we set it as changed
and schedule a tick (see ServerMonitor). However, if the tick is
dropped, we don't clear the changed flag, meaning subsequent changes
don't requeue the monitor to be ticked, and so the monitor is never
updated.

We fix this by maintaining a list of block entities whose tick was
dropped. If these block entities (or rather their owning chunk) is ever
re-loaded, then we reschedule them to be ticked.

An alternative approach here would be to add the scheduled tick directly
to the LevelChunk. However, getting hold of the LevelChunk for unloaded
blocks is quiet nasty, so I think best avoided.

Fixes #1146. Fixes #1560 - I believe the second one is a duplicate, and
I noticed too late :D.
This commit is contained in:
Jonathan Coates
2024-02-26 19:01:25 +00:00
parent 84b6edab82
commit 4daa2a2b6a
6 changed files with 171 additions and 13 deletions

View File

@@ -22,11 +22,15 @@ import dan200.computercraft.shared.turtle.blocks.TurtleBlockEntity;
import dan200.computercraft.shared.util.CapabilityProvider;
import dan200.computercraft.shared.util.SidedCapabilityProvider;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.server.level.ServerLevel;
import net.minecraft.world.level.block.entity.BlockEntity;
import net.minecraft.world.level.block.entity.CommandBlockEntity;
import net.minecraft.world.level.chunk.LevelChunk;
import net.minecraftforge.event.*;
import net.minecraftforge.event.entity.EntityJoinLevelEvent;
import net.minecraftforge.event.entity.living.LivingDropsEvent;
import net.minecraftforge.event.level.ChunkEvent;
import net.minecraftforge.event.level.ChunkTicketLevelUpdatedEvent;
import net.minecraftforge.event.level.ChunkWatchEvent;
import net.minecraftforge.event.server.ServerStartingEvent;
import net.minecraftforge.event.server.ServerStoppedEvent;
@@ -67,11 +71,23 @@ public class ForgeCommonHooks {
CommandComputerCraft.register(event.getDispatcher());
}
@SubscribeEvent
public static void onChunkUnload(ChunkEvent.Unload event) {
if (event.getLevel() instanceof ServerLevel && event.getChunk() instanceof LevelChunk chunk) {
CommonHooks.onServerChunkUnload(chunk);
}
}
@SubscribeEvent
public static void onChunkWatch(ChunkWatchEvent.Watch event) {
CommonHooks.onChunkWatch(event.getChunk(), event.getPlayer());
}
@SubscribeEvent
public static void onChunkTicketLevelChanged(ChunkTicketLevelUpdatedEvent event) {
CommonHooks.onChunkTicketLevelChanged(event.getLevel(), event.getChunkPos(), event.getOldTicketLevel(), event.getNewTicketLevel());
}
@SubscribeEvent
public static void onAddReloadListeners(AddReloadListenerEvent event) {
CommonHooks.onDatapackReload((id, listener) -> event.addListener(listener));