From 5fa8a6d6312b94489929a0b5ce934dfb7b1eb0d2 Mon Sep 17 00:00:00 2001 From: CraftBukkit/Spigot Date: Sun, 14 Aug 2022 10:46:41 +1000 Subject: [PATCH] SPIGOT-7089: Crash when command blocks attempt to load worlds By: md_5 --- .../minecraft/server/MinecraftServer.patch | 65 +++++++++++++------ .../org/bukkit/craftbukkit/CraftServer.java | 8 +-- 2 files changed, 48 insertions(+), 25 deletions(-) diff --git a/paper-server/nms-patches/net/minecraft/server/MinecraftServer.patch b/paper-server/nms-patches/net/minecraft/server/MinecraftServer.patch index 697d5d59d4..25578bc756 100644 --- a/paper-server/nms-patches/net/minecraft/server/MinecraftServer.patch +++ b/paper-server/nms-patches/net/minecraft/server/MinecraftServer.patch @@ -32,6 +32,15 @@ public abstract class MinecraftServer extends IAsyncTaskHandlerReentrant implements ICommandListener, AutoCloseable { public static final Logger LOGGER = LogUtils.getLogger(); +@@ -195,7 +220,7 @@ + private String localIp; + private int port; + public final IRegistryCustom.Dimension registryHolder; +- public final Map, WorldServer> levels; ++ private Map, WorldServer> levels; + private PlayerList playerList; + private volatile boolean running; + private boolean stopped; @@ -239,6 +264,21 @@ protected SaveData worldData; private volatile boolean isSaving; @@ -71,15 +80,6 @@ super("Server"); this.metricsRecorder = InactiveMetricsRecorder.INSTANCE; this.profiler = this.metricsRecorder.getProfiler(); -@@ -271,7 +311,7 @@ - this.status = new ServerPing(); - this.random = RandomSource.create(); - this.port = -1; -- this.levels = Maps.newLinkedHashMap(); -+ this.levels = Maps.newLinkedHashMap(); // CraftBukkit - keep order, k+v already use identity methods - this.running = true; - this.tickTimes = new long[100]; - this.nextTickTime = SystemUtils.getMillis(); @@ -280,7 +320,7 @@ this.frameTimer = new CircularTimer(); this.registryHolder = worldstem.registryAccess(); @@ -321,7 +321,7 @@ + worlddata.setModdedInfo(this.getServerModName(), this.getModdedStatus().shouldReportAsModified()); + this.initWorld(world, worlddata, worldData, worlddata.worldGenSettings()); + -+ this.levels.put(world.dimension(), world); ++ this.addLevel(world); + this.getPlayerList().addWorldborderListener(world); + + if (worlddata.getCustomBossEvents() != null) { @@ -334,19 +334,19 @@ + worldserver.entityManager.tick(); // SPIGOT-6526: Load pending entities so they are available to the API + this.server.getPluginManager().callEvent(new org.bukkit.event.world.WorldLoadEvent(worldserver.getWorld())); + } - -- this.levels.put(World.OVERWORLD, worldserver); -- WorldPersistentData worldpersistentdata = worldserver.getDataStorage(); ++ + this.server.enablePlugins(org.bukkit.plugin.PluginLoadOrder.POSTWORLD); + this.server.getPluginManager().callEvent(new ServerLoadEvent(ServerLoadEvent.LoadType.STARTUP)); + this.connection.acceptConnections(); + } + // CraftBukkit end +- this.levels.put(World.OVERWORLD, worldserver); +- WorldPersistentData worldpersistentdata = worldserver.getDataStorage(); ++ protected void forceDifficulty() {} + - this.readScoreboard(worldpersistentdata); - this.commandStorage = new PersistentCommandStorage(worldpersistentdata); -+ protected void forceDifficulty() {} -+ + // CraftBukkit start + public void initWorld(WorldServer worldserver, IWorldDataServer iworlddataserver, SaveData saveData, GeneratorSettings generatorsettings) { + boolean flag = generatorsettings.isDebug(); @@ -649,7 +649,30 @@ this.profiler.push("tick"); -@@ -1021,7 +1315,7 @@ +@@ -995,6 +1289,22 @@ + return (WorldServer) this.levels.get(resourcekey); + } + ++ // CraftBukkit start ++ public void addLevel(WorldServer level) { ++ Map, WorldServer> oldLevels = this.levels; ++ Map, WorldServer> newLevels = Maps.newLinkedHashMap(oldLevels); ++ newLevels.put(level.dimension(), level); ++ this.levels = Collections.unmodifiableMap(newLevels); ++ } ++ ++ public void removeLevel(WorldServer level) { ++ Map, WorldServer> oldLevels = this.levels; ++ Map, WorldServer> newLevels = Maps.newLinkedHashMap(oldLevels); ++ newLevels.remove(level.dimension()); ++ this.levels = Collections.unmodifiableMap(newLevels); ++ } ++ // CraftBukkit end ++ + public Set> levelKeys() { + return this.levels.keySet(); + } +@@ -1021,7 +1331,7 @@ @DontObfuscate public String getServerModName() { @@ -658,7 +681,7 @@ } public SystemReport fillSystemReport(SystemReport systemreport) { -@@ -1372,11 +1666,11 @@ +@@ -1372,11 +1682,11 @@ public CompletableFuture reloadResources(Collection collection) { IRegistryCustom.Dimension iregistrycustom_dimension = this.registryAccess(); CompletableFuture completablefuture = CompletableFuture.supplyAsync(() -> { @@ -672,7 +695,7 @@ }, this).thenCompose((immutablelist) -> { ResourceManager resourcemanager = new ResourceManager(EnumResourcePackType.SERVER_DATA, immutablelist); -@@ -1391,6 +1685,7 @@ +@@ -1391,6 +1701,7 @@ }).thenAcceptAsync((minecraftserver_reloadableresources) -> { this.resources.close(); this.resources = minecraftserver_reloadableresources; @@ -680,7 +703,7 @@ this.packRepository.setSelected(collection); this.worldData.setDataPackConfig(getSelectedPacks(this.packRepository)); this.resources.managers.updateRegistryTags(this.registryAccess()); -@@ -1740,7 +2035,7 @@ +@@ -1740,7 +2051,7 @@ try { label51: { @@ -689,7 +712,7 @@ try { arraylist = Lists.newArrayList(NativeModuleLister.listModules()); -@@ -1790,6 +2085,22 @@ +@@ -1790,6 +2101,22 @@ } @@ -712,7 +735,7 @@ private void startMetricsRecordingTick() { if (this.willStartRecordingMetrics) { this.metricsRecorder = ActiveMetricsRecorder.createStarted(new ServerMetricsSamplersProvider(SystemUtils.timeSource, this.isDedicatedServer()), SystemUtils.timeSource, SystemUtils.ioPool(), new MetricsPersister("server"), this.onMetricsRecordingStopped, (path) -> { -@@ -1912,8 +2223,30 @@ +@@ -1912,8 +2239,30 @@ } diff --git a/paper-server/src/main/java/org/bukkit/craftbukkit/CraftServer.java b/paper-server/src/main/java/org/bukkit/craftbukkit/CraftServer.java index 998e42dade..a0f586e880 100644 --- a/paper-server/src/main/java/org/bukkit/craftbukkit/CraftServer.java +++ b/paper-server/src/main/java/org/bukkit/craftbukkit/CraftServer.java @@ -988,7 +988,7 @@ public final class CraftServer implements Server { @Override public World createWorld(WorldCreator creator) { - Preconditions.checkState(!console.levels.isEmpty(), "Cannot create additional worlds on STARTUP"); + Preconditions.checkState(console.getAllLevels().iterator().hasNext(), "Cannot create additional worlds on STARTUP"); Validate.notNull(creator, "Creator may not be null"); String name = creator.name(); @@ -1087,7 +1087,7 @@ public final class CraftServer implements Server { console.initWorld(internal, worlddata, worlddata, worlddata.worldGenSettings()); internal.setSpawnSettings(true, true); - console.levels.put(internal.dimension(), internal); + console.addLevel(internal); getServer().prepareLevels(internal.getChunkSource().chunkMap.progressListener, internal); internal.entityManager.tick(); // SPIGOT-6526: Load pending entities so they are available to the API @@ -1109,7 +1109,7 @@ public final class CraftServer implements Server { WorldServer handle = ((CraftWorld) world).getHandle(); - if (!(console.levels.containsKey(handle.dimension()))) { + if (console.getLevel(handle.dimension()) == null) { return false; } @@ -1141,7 +1141,7 @@ public final class CraftServer implements Server { } worlds.remove(world.getName().toLowerCase(java.util.Locale.ENGLISH)); - console.levels.remove(handle.dimension()); + console.removeLevel(handle); return true; }