mirror of
https://github.com/SquidDev-CC/CC-Tweaked
synced 2025-12-04 05:18:05 +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:
@@ -6,20 +6,37 @@ package dan200.computercraft.mixin;
|
||||
|
||||
import dan200.computercraft.shared.CommonHooks;
|
||||
import net.minecraft.network.protocol.game.ClientboundLevelChunkWithLightPacket;
|
||||
import net.minecraft.server.level.ChunkHolder;
|
||||
import net.minecraft.server.level.ChunkMap;
|
||||
import net.minecraft.server.level.ServerLevel;
|
||||
import net.minecraft.server.level.ServerPlayer;
|
||||
import net.minecraft.world.level.chunk.LevelChunk;
|
||||
import org.apache.commons.lang3.mutable.MutableObject;
|
||||
import org.spongepowered.asm.mixin.Final;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.Shadow;
|
||||
import org.spongepowered.asm.mixin.injection.At;
|
||||
import org.spongepowered.asm.mixin.injection.Inject;
|
||||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
|
||||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
@Mixin(ChunkMap.class)
|
||||
class ChunkMapMixin {
|
||||
@Final
|
||||
@Shadow
|
||||
ServerLevel level;
|
||||
|
||||
@Inject(method = "playerLoadedChunk", at = @At("TAIL"))
|
||||
@SuppressWarnings("UnusedMethod")
|
||||
private void onPlayerLoadedChunk(ServerPlayer player, MutableObject<ClientboundLevelChunkWithLightPacket> packetCache, LevelChunk chunk, CallbackInfo callback) {
|
||||
CommonHooks.onChunkWatch(chunk, player);
|
||||
}
|
||||
|
||||
@Inject(method = "updateChunkScheduling", at = @At("HEAD"))
|
||||
@SuppressWarnings("UnusedMethod")
|
||||
private void onUpdateChunkScheduling(long chunkPos, int newLevel, @Nullable ChunkHolder holder, int oldLevel, CallbackInfoReturnable<ChunkHolder> callback) {
|
||||
CommonHooks.onChunkTicketLevelChanged(level, chunkPos, oldLevel, newLevel);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -24,6 +24,7 @@ import dan200.computercraft.shared.peripheral.modem.wireless.WirelessModemBlockE
|
||||
import dan200.computercraft.shared.platform.FabricConfigFile;
|
||||
import dan200.computercraft.shared.platform.FabricMessageType;
|
||||
import net.fabricmc.fabric.api.command.v2.CommandRegistrationCallback;
|
||||
import net.fabricmc.fabric.api.event.lifecycle.v1.ServerChunkEvents;
|
||||
import net.fabricmc.fabric.api.event.lifecycle.v1.ServerLifecycleEvents;
|
||||
import net.fabricmc.fabric.api.event.lifecycle.v1.ServerTickEvents;
|
||||
import net.fabricmc.fabric.api.event.player.PlayerBlockBreakEvents;
|
||||
@@ -96,6 +97,7 @@ public class ComputerCraft {
|
||||
|
||||
ServerTickEvents.START_SERVER_TICK.register(CommonHooks::onServerTickStart);
|
||||
ServerTickEvents.START_SERVER_TICK.register(s -> CommonHooks.onServerTickEnd());
|
||||
ServerChunkEvents.CHUNK_UNLOAD.register((l, c) -> CommonHooks.onServerChunkUnload(c));
|
||||
|
||||
PlayerBlockBreakEvents.BEFORE.register(FabricCommonHooks::onBlockDestroy);
|
||||
UseBlockCallback.EVENT.register(FabricCommonHooks::useOnBlock);
|
||||
|
||||
Reference in New Issue
Block a user