From 227c73bc38ca82876e9ea198cc75b0f0c0391957 Mon Sep 17 00:00:00 2001 From: "KHODA\\khoda" Date: Sun, 11 Jan 2026 12:01:28 +0300 Subject: [PATCH 1/3] Refactor world initialization in MinecraftServerMixin to use Redirect for createLevels method, improving scoreboard manager setup and world border listener registration. --- .../core/server/MinecraftServerMixin.java | 42 +++++++++++-------- 1 file changed, 24 insertions(+), 18 deletions(-) diff --git a/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/server/MinecraftServerMixin.java b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/server/MinecraftServerMixin.java index 92948e4dc..2dbcd643f 100644 --- a/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/server/MinecraftServerMixin.java +++ b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/server/MinecraftServerMixin.java @@ -79,6 +79,7 @@ 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.Redirect; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; import org.spongepowered.asm.mixin.injection.callback.LocalCapture; @@ -279,25 +280,30 @@ private void executeModerately() { return new ArclightDelegatedBorderListener(arg, (BorderChangeListener.DelegateBorderChangeListener) DecorationOps.callsite().invoke(arg)); } - @Decorate(method = "createLevels", at = @At(value = "INVOKE", remap = false, target = "Ljava/util/Map;put(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;")) - private Object arclight$worldInit(Map instance, Object k, Object v, ChunkProgressListener chunkProgressListener) throws Throwable { - if (v instanceof ServerLevel level) { - if (((CraftServer) Bukkit.getServer()).scoreboardManager == null) { - ((CraftServer) Bukkit.getServer()).scoreboardManager = new CraftScoreboardManager((MinecraftServer) (Object) this, level.getScoreboard()); - } - if (((WorldBridge) level).bridge$getGenerator() != null) { - level.bridge$getWorld().getPopulators().addAll( - ((WorldBridge) level).bridge$getGenerator().getDefaultPopulators( - level.bridge$getWorld())); - } - Bukkit.getPluginManager().callEvent(new WorldInitEvent(level.bridge$getWorld())); - - // Arclight: move world border listener initialization to world registration - // Arclight: ArclightBorderChangeListener is singleton so won't be added more than once - // Arclight: since it seems that we can't apply multiple Decorators to a target on Forge... - level.getWorldBorder().addListener(ArclightBorderChangeListener.typed()); + @SuppressWarnings("rawtypes") + @Redirect(method = "createLevels", at = @At(value = "INVOKE", remap = false, target = "Ljava/util/Map;put(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;")) + private Object arclight$worldInit(Map instance, Object key, Object value) { + ResourceKey k = (ResourceKey) key; + ServerLevel level = (ServerLevel) value; + + Object result = instance.put(k, level); + + if (((CraftServer) Bukkit.getServer()).scoreboardManager == null) { + ((CraftServer) Bukkit.getServer()).scoreboardManager = new CraftScoreboardManager((MinecraftServer) (Object) this, level.getScoreboard()); } - return DecorationOps.callsite().invoke(instance, k, v); + if (((WorldBridge) level).bridge$getGenerator() != null) { + level.bridge$getWorld().getPopulators().addAll( + ((WorldBridge) level).bridge$getGenerator().getDefaultPopulators( + level.bridge$getWorld())); + } + Bukkit.getPluginManager().callEvent(new WorldInitEvent(level.bridge$getWorld())); + + // Arclight: move world border listener initialization to world registration + // Arclight: ArclightBorderChangeListener is singleton so won't be added more than once + // Arclight: since it seems that we can't apply multiple Decorators to a target on Forge... + level.getWorldBorder().addListener(ArclightBorderChangeListener.typed()); + + return result; } /** From 40ee36486a278d24b3d0efa2a5edc285b37fc053 Mon Sep 17 00:00:00 2001 From: "KHODA\\khoda" Date: Sun, 11 Jan 2026 12:01:34 +0300 Subject: [PATCH 2/3] Refactor ServerLevelMixin to replace arclight$isActual() checks with DistValidate.isValid() for improved validation during world initialization and chunk generation. --- .../mixin/core/server/level/ServerLevelMixin.java | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/server/level/ServerLevelMixin.java b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/server/level/ServerLevelMixin.java index a5451ce75..cbc44c6ae 100644 --- a/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/server/level/ServerLevelMixin.java +++ b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/server/level/ServerLevelMixin.java @@ -166,14 +166,14 @@ public ResourceKey getTypeKey() { @Decorate(method = "", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/level/dimension/LevelStem;generator()Lnet/minecraft/world/level/chunk/ChunkGenerator;")) private ChunkGenerator arclight$initChunkGenerator(LevelStem instance, @Local(ordinal = -1) MinecraftServer server, @Local(ordinal = -1) ServerLevelData worldInfo) throws Throwable { // Pulling up world info init since level info is used when selecting ChunkGenerator. - if (arclight$isActual() && worldInfo instanceof PrimaryLevelData primary) { + if (DistValidate.isValid(this) && worldInfo instanceof PrimaryLevelData primary) { this.K = primary; } else { // damn spigot again this.K = DelegateWorldInfo.wrap(worldInfo); } - if (arclight$isActual()) { + if (DistValidate.isValid(this)) { var craftBridge = (CraftServerBridge) (Object) ((MinecraftServerBridge) server).bridge$getServer(); this.biomeProvider = craftBridge.bridge$consumeBiomeProviderCache(worldInfo.getLevelName()); @@ -200,7 +200,7 @@ public ResourceKey getTypeKey() { } ChunkGenerator raw = (ChunkGenerator) DecorationOps.callsite().invoke(instance); - if (arclight$isActual()) { + if (DistValidate.isValid(this)) { // Data needed by getWorld() are all initialized for possible creating CraftWorld. // CraftBukkit start: select custom chunk generator if (biomeProvider != null) { @@ -230,7 +230,7 @@ public ResourceKey getTypeKey() { private void arclight$init(MinecraftServer minecraftServer, Executor backgroundExecutor, LevelStorageSource.LevelStorageAccess levelSave, ServerLevelData worldInfo, ResourceKey dimension, LevelStem levelStem, ChunkProgressListener statusListener, boolean isDebug, long seed, List specialSpawners, boolean shouldBeTicking, RandomSequences seq, CallbackInfo ci) { this.pvpMode = minecraftServer.isPvpAllowed(); this.convertable = levelSave; - if (arclight$isActual() && this.dragonFight == null && this.environment == World.Environment.THE_END) { + if (DistValidate.isValid(this) && this.dragonFight == null && this.environment == World.Environment.THE_END) { this.dragonFight = new EndDragonFight((ServerLevel)(Object) this, K.worldGenOptions().seed(), K.endDragonFightData()); } var typeKey = ((LevelStorageSourceBridge.LevelStorageAccessBridge) levelSave).bridge$getTypeKey(); @@ -256,7 +256,7 @@ public ResourceKey getTypeKey() { this.uuid = WorldUUID.getUUID(levelSave.getDimensionPath(this.dimension()).toFile()); ((ServerChunkProviderBridge) this.chunkSource).bridge$setViewDistance(spigotConfig.viewDistance); ((ServerChunkProviderBridge) this.chunkSource).bridge$setSimulationDistance(spigotConfig.simulationDistance); - if (arclight$isActual()) { + if (DistValidate.isValid(this)) { ((WorldInfoBridge) this.K).bridge$setWorld((ServerLevel) (Object) this); var data = this.getDataStorage().computeIfAbsent(LevelPersistentData.factory(), "bukkit_pdc"); this.getWorld().readBukkitValues(data.getTag()); @@ -447,7 +447,7 @@ public int sendParticles(T type, double posX, double return; } CreatureSpawnEvent.SpawnReason spawnReason = reason == null ? CreatureSpawnEvent.SpawnReason.DEFAULT : reason; - if (!arclight$isActual()) { + if (!DistValidate.isValid(this)) { return; } ((EntityBridge) entityIn).arclight$onAddedToLevel(); From 3c183c63d7a960007fd0daf402b96df248f869b7 Mon Sep 17 00:00:00 2001 From: "KHODA\\khoda" Date: Sun, 11 Jan 2026 12:01:40 +0300 Subject: [PATCH 3/3] Update LevelMixin to utilize DistValidate.isValid() for arclight$isActual() checks, enhancing world initialization validation. --- .../arclight/common/mixin/core/world/level/LevelMixin.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/level/LevelMixin.java b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/level/LevelMixin.java index beb92b59d..44704958e 100644 --- a/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/level/LevelMixin.java +++ b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/level/LevelMixin.java @@ -8,6 +8,7 @@ import io.izzel.arclight.common.mod.mixins.annotation.TransformAccess; import io.izzel.arclight.common.mod.server.world.ArclightWorldConfig; import io.izzel.arclight.common.mod.util.ArclightCaptures; +import io.izzel.arclight.common.mod.util.DistValidate; import it.unimi.dsi.fastutil.objects.Object2LongOpenHashMap; import net.minecraft.core.BlockPos; import net.minecraft.core.Holder; @@ -114,7 +115,7 @@ public abstract class LevelMixin implements WorldBridge, LevelAccessor, LevelWri // InitAuther97: unsafe = true can't be removed because unsafe is default to false on Forge @Inject(method = "", at = @At(value = "CTOR_HEAD", unsafe = true)) private void arclight$preInit(WritableLevelData writableLevelData, ResourceKey resourceKey, RegistryAccess registryAccess, Holder holder, Supplier supplier, boolean bl, boolean bl2, long l, int i, CallbackInfo ci) { - this.arclight$isActual = WorldBridge.super.arclight$isActual(); + this.arclight$isActual = DistValidate.isValid((LevelAccessor) this); } // InitAuther97: inject later than ironsspellbooks, see their LevelMixin