diff --git a/patches/minecraft/net/minecraft/server/level/ChunkMap.java.patch b/patches/minecraft/net/minecraft/server/level/ChunkMap.java.patch index 95b6c6afdd..8d1739b67d 100644 --- a/patches/minecraft/net/minecraft/server/level/ChunkMap.java.patch +++ b/patches/minecraft/net/minecraft/server/level/ChunkMap.java.patch @@ -1,5 +1,13 @@ --- a/net/minecraft/server/level/ChunkMap.java +++ b/net/minecraft/server/level/ChunkMap.java +@@ -385,6 +_,7 @@ + this.f_140140_ = true; + } + ++ net.minecraftforge.event.ForgeEventFactory.fireChunkTicketLevelUpdated(this.f_140133_, p_140177_, p_140180_, p_140178_, p_140179_); + return p_140179_; + } + } @@ -490,6 +_,7 @@ if (this.f_140131_.remove(p_140182_, p_140183_) && p_203002_ != null) { if (p_203002_ instanceof LevelChunk) { diff --git a/src/main/java/net/minecraftforge/event/ForgeEventFactory.java b/src/main/java/net/minecraftforge/event/ForgeEventFactory.java index 4c5af112b0..60909c1d6b 100644 --- a/src/main/java/net/minecraftforge/event/ForgeEventFactory.java +++ b/src/main/java/net/minecraftforge/event/ForgeEventFactory.java @@ -16,6 +16,7 @@ import com.mojang.brigadier.CommandDispatcher; import net.minecraft.commands.CommandBuildContext; import net.minecraft.server.MinecraftServer; import net.minecraft.server.ReloadableServerResources; +import net.minecraft.server.level.ChunkHolder; import net.minecraft.server.players.PlayerList; import net.minecraft.util.RandomSource; import net.minecraft.util.random.WeightedRandomList; @@ -118,6 +119,7 @@ import net.minecraftforge.event.level.BlockEvent.CreateFluidSourceEvent; import net.minecraftforge.event.level.BlockEvent.EntityMultiPlaceEvent; import net.minecraftforge.event.level.BlockEvent.EntityPlaceEvent; import net.minecraftforge.event.level.BlockEvent.NeighborNotifyEvent; +import net.minecraftforge.event.level.ChunkTicketLevelUpdatedEvent; import net.minecraftforge.event.level.ChunkWatchEvent; import net.minecraftforge.event.level.ExplosionEvent; import net.minecraftforge.event.level.PistonEvent; @@ -610,6 +612,12 @@ public class ForgeEventFactory return event.getResult() != Result.DENY; } + public static void fireChunkTicketLevelUpdated(ServerLevel level, long chunkPos, int oldTicketLevel, int newTicketLevel, @Nullable ChunkHolder chunkHolder) + { + if (oldTicketLevel != newTicketLevel) + MinecraftForge.EVENT_BUS.post(new ChunkTicketLevelUpdatedEvent(level, chunkPos, oldTicketLevel, newTicketLevel, chunkHolder)); + } + public static void fireChunkWatch(ServerPlayer entity, LevelChunk chunk, ServerLevel level) { MinecraftForge.EVENT_BUS.post(new ChunkWatchEvent.Watch(entity, chunk, level)); diff --git a/src/main/java/net/minecraftforge/event/level/ChunkTicketLevelUpdatedEvent.java b/src/main/java/net/minecraftforge/event/level/ChunkTicketLevelUpdatedEvent.java new file mode 100644 index 0000000000..04da357eaa --- /dev/null +++ b/src/main/java/net/minecraftforge/event/level/ChunkTicketLevelUpdatedEvent.java @@ -0,0 +1,90 @@ +/* + * Copyright (c) Forge Development LLC and contributors + * SPDX-License-Identifier: LGPL-2.1-only + */ + +package net.minecraftforge.event.level; + +import net.minecraft.server.level.ChunkHolder; +import net.minecraft.server.level.ServerLevel; +import net.minecraftforge.common.MinecraftForge; +import net.minecraftforge.eventbus.api.Cancelable; +import net.minecraftforge.eventbus.api.Event; +import net.minecraftforge.fml.LogicalSide; +import org.jetbrains.annotations.Nullable; + +/** + * This event is fired whenever a chunk has its ticket level changed via the server's ChunkMap. + *

+ * This event does not fire if the new ticket level is the same as the old level, or if both the + * new AND old ticket levels represent values past the max chunk distance. + *

+ * Due to how vanilla processes ticket level changes this event may be fired "twice" in one tick for the same chunk. + * The scenario where this happens is when increasing the level from say 31 (ticking) to 32, the way vanilla does it + * is by first changing it from 31 to 46, and then queuing the update from 46 to 32. However, when going from 32 to 31, + * vanilla is able to go directly. + *

+ * This event is not {@linkplain Cancelable cancellable} and does not {@linkplain HasResult have a result}. + *

+ * This event is fired on the {@linkplain MinecraftForge#EVENT_BUS main Forge event bus} + * only on the {@linkplain LogicalSide#SERVER logical server}. + **/ +public class ChunkTicketLevelUpdatedEvent extends Event +{ + private final ServerLevel level; + private final long chunkPos; + private final int oldTicketLevel; + private final int newTicketLevel; + @Nullable + private final ChunkHolder chunkHolder; + + public ChunkTicketLevelUpdatedEvent(ServerLevel level, long chunkPos, int oldTicketLevel, int newTicketLevel, @Nullable ChunkHolder chunkHolder) + { + this.level = level; + this.chunkPos = chunkPos; + this.oldTicketLevel = oldTicketLevel; + this.newTicketLevel = newTicketLevel; + this.chunkHolder = chunkHolder; + } + + /** + * {@return the server level containing the chunk} + */ + public ServerLevel getLevel() + { + return this.level; + } + + /** + * {@return the long representation of the chunk position the ticket level changed for} + */ + public long getChunkPos() + { + return this.chunkPos; + } + + /** + * {@return the previous ticket level the chunk had} + */ + public int getOldTicketLevel() + { + return this.oldTicketLevel; + } + + /** + * {@return the new ticket level for the chunk} + */ + public int getNewTicketLevel() + { + return this.newTicketLevel; + } + + /** + * {@return chunk that had its ticket level updated} + */ + @Nullable + public ChunkHolder getChunkHolder() + { + return this.chunkHolder; + } +}