diff --git a/patches/net/minecraft/server/level/ServerLevel.java.patch b/patches/net/minecraft/server/level/ServerLevel.java.patch index 64b583a4d3..11eecc1149 100644 --- a/patches/net/minecraft/server/level/ServerLevel.java.patch +++ b/patches/net/minecraft/server/level/ServerLevel.java.patch @@ -9,12 +9,23 @@ private final StructureManager structureManager; private final StructureCheck structureCheck; private final boolean tickTime; -@@ -298,6 +_,8 @@ +@@ -232,7 +_,6 @@ + ); + this.tickTime = p_215009_; + this.server = p_214999_; +- this.customSpawners = p_215008_; + this.serverLevelData = p_215002_; + ChunkGenerator chunkgenerator = p_215004_.generator(); + boolean flag = p_214999_.forceSynchronousWrites(); +@@ -298,6 +_,11 @@ this.randomSequences = Objects.requireNonNullElseGet( p_288977_, () -> this.getDataStorage().computeIfAbsent(RandomSequences.factory(i), "random_sequences") ); + + net.neoforged.neoforge.attachment.LevelAttachmentsSavedData.init(this); ++ // Neo: Move the initialization of customSpawners to the end of costructor ++ // Providing a fully initialized ServerLevel instance for the ServerLevelEvent.CustomSpawners ++ this.customSpawners = net.neoforged.neoforge.event.EventHooks.getCustomSpawners(this, p_215008_); } @Deprecated diff --git a/src/main/java/net/neoforged/neoforge/event/EventHooks.java b/src/main/java/net/neoforged/neoforge/event/EventHooks.java index b1b80c5fd5..b25e1ad2b3 100644 --- a/src/main/java/net/neoforged/neoforge/event/EventHooks.java +++ b/src/main/java/net/neoforged/neoforge/event/EventHooks.java @@ -10,6 +10,7 @@ import com.mojang.datafixers.util.Either; import com.mojang.serialization.DynamicOps; import java.io.File; +import java.util.ArrayList; import java.util.EnumSet; import java.util.List; import java.util.Optional; @@ -81,6 +82,7 @@ import net.minecraft.world.level.BaseSpawner; import net.minecraft.world.level.BlockGetter; import net.minecraft.world.level.ChunkPos; +import net.minecraft.world.level.CustomSpawner; import net.minecraft.world.level.Explosion; import net.minecraft.world.level.GameRules; import net.minecraft.world.level.Level; @@ -169,6 +171,7 @@ import net.neoforged.neoforge.event.level.ExplosionEvent; import net.neoforged.neoforge.event.level.ExplosionKnockbackEvent; import net.neoforged.neoforge.event.level.LevelEvent; +import net.neoforged.neoforge.event.level.ModifyCustomSpawnersEvent; import net.neoforged.neoforge.event.level.PistonEvent; import net.neoforged.neoforge.event.level.SleepFinishedTimeEvent; import net.neoforged.neoforge.event.level.block.CreateFluidSourceEvent; @@ -1120,4 +1123,17 @@ public static MobSplitEvent onMobSplit(Mob parent, List children) { NeoForge.EVENT_BUS.post(event); return event; } + + /** + * Fires the {@link ModifyCustomSpawnersEvent}. Returns the custom spawners list. + * + * @param serverLevel The server level. + * @param customSpawners The original custom spawners. + * @return The new custom spawners list. + */ + public static List getCustomSpawners(ServerLevel serverLevel, List customSpawners) { + ModifyCustomSpawnersEvent event = new ModifyCustomSpawnersEvent(serverLevel, new ArrayList<>(customSpawners)); + NeoForge.EVENT_BUS.post(event); + return event.getCustomSpawners(); + } } diff --git a/src/main/java/net/neoforged/neoforge/event/level/ModifyCustomSpawnersEvent.java b/src/main/java/net/neoforged/neoforge/event/level/ModifyCustomSpawnersEvent.java new file mode 100644 index 0000000000..b556da6245 --- /dev/null +++ b/src/main/java/net/neoforged/neoforge/event/level/ModifyCustomSpawnersEvent.java @@ -0,0 +1,51 @@ +/* + * Copyright (c) NeoForged and contributors + * SPDX-License-Identifier: LGPL-2.1-only + */ + +package net.neoforged.neoforge.event.level; + +import java.util.List; +import net.minecraft.server.level.ServerLevel; +import net.minecraft.world.level.CustomSpawner; +import net.neoforged.bus.api.Event; +import org.jetbrains.annotations.ApiStatus; + +/** + * This event is fired on the {@linkplain net.neoforged.fml.LogicalSide#SERVER logical server} when a {@link ServerLevel} is building its {@linkplain CustomSpawner custom spawners}. + *

+ * Subscribe to this event to add/remove {@linkplain CustomSpawner custom spawners} for the level. + *

+ * This event is not {@link net.neoforged.bus.api.ICancellableEvent cancellable} and does not have a result. + */ +public class ModifyCustomSpawnersEvent extends Event { + private final ServerLevel serverLevel; + private final List customSpawners; + + @ApiStatus.Internal + public ModifyCustomSpawnersEvent(ServerLevel serverLevel, List customSpawners) { + this.serverLevel = serverLevel; + this.customSpawners = customSpawners; + } + + /** + * {@return the server level this event is affecting} + */ + public ServerLevel getLevel() { + return this.serverLevel; + } + + /** + * @return the modifiable custom spawner list. + */ + public List getCustomSpawners() { + return this.customSpawners; + } + + /** + * Adds a custom spawner to the list. + */ + public void addCustomSpawner(CustomSpawner customSpawner) { + this.customSpawners.add(customSpawner); + } +}