diff --git a/paper-server/patches/sources/net/minecraft/server/MinecraftServer.java.patch b/paper-server/patches/sources/net/minecraft/server/MinecraftServer.java.patch index 40752ad5f1..f46e7cc94f 100644 --- a/paper-server/patches/sources/net/minecraft/server/MinecraftServer.java.patch +++ b/paper-server/patches/sources/net/minecraft/server/MinecraftServer.java.patch @@ -150,7 +150,7 @@ @Nullable private KeyPair keyPair; @Nullable -@@ -277,6 +308,26 @@ +@@ -277,6 +308,27 @@ private final SuppressedExceptionCollector suppressedExceptions; private final DiscontinuousFrame tickFrame; @@ -173,11 +173,12 @@ + public final double[] recentTps = new double[ 3 ]; + // Spigot end + public final io.papermc.paper.configuration.PaperConfigurations paperConfigurations; // Paper - add paper configuration files ++ public boolean isIteratingOverLevels = false; // Paper - Throw exception on world create while being ticked + public static S spin(Function serverFactory) { AtomicReference atomicreference = new AtomicReference(); Thread thread = new Thread(() -> { -@@ -286,19 +337,21 @@ +@@ -286,19 +338,21 @@ thread.setUncaughtExceptionHandler((thread1, throwable) -> { MinecraftServer.LOGGER.error("Uncaught exception in server thread", throwable); }); @@ -201,7 +202,7 @@ this.metricsRecorder = InactiveMetricsRecorder.INSTANCE; this.onMetricsRecordingStopped = (methodprofilerresults) -> { this.stopRecordingMetrics(); -@@ -319,36 +372,68 @@ +@@ -319,36 +373,68 @@ this.scoreboard = new ServerScoreboard(this); this.customBossEvents = new CustomBossEvents(); this.suppressedExceptions = new SuppressedExceptionCollector(); @@ -285,7 +286,7 @@ } private void readScoreboard(DimensionDataStorage persistentStateManager) { -@@ -357,7 +442,7 @@ +@@ -357,7 +443,7 @@ protected abstract boolean initServer() throws IOException; @@ -294,7 +295,7 @@ if (!JvmProfiler.INSTANCE.isRunning()) { ; } -@@ -365,12 +450,8 @@ +@@ -365,12 +451,8 @@ boolean flag = false; ProfiledDuration profiledduration = JvmProfiler.INSTANCE.onWorldLoadedStarted(); @@ -308,7 +309,7 @@ if (profiledduration != null) { profiledduration.finish(true); } -@@ -387,23 +468,241 @@ +@@ -387,23 +469,241 @@ protected void forceDifficulty() {} @@ -564,7 +565,7 @@ if (!iworlddataserver.isInitialized()) { try { -@@ -427,30 +726,8 @@ +@@ -427,30 +727,8 @@ iworlddataserver.setInitialized(true); } @@ -596,7 +597,7 @@ private static void setInitialSpawn(ServerLevel world, ServerLevelData worldProperties, boolean bonusChest, boolean debugWorld) { if (debugWorld) { -@@ -458,6 +735,21 @@ +@@ -458,6 +736,21 @@ } else { ServerChunkCache chunkproviderserver = world.getChunkSource(); ChunkPos chunkcoordintpair = new ChunkPos(chunkproviderserver.randomState().sampler().findSpawnPosition()); @@ -618,7 +619,7 @@ int i = chunkproviderserver.getGenerator().getSpawnHeight(world); if (i < world.getMinY()) { -@@ -516,31 +808,36 @@ +@@ -516,31 +809,36 @@ iworlddataserver.setGameType(GameType.SPECTATOR); } @@ -666,7 +667,7 @@ ForcedChunksSavedData forcedchunk = (ForcedChunksSavedData) worldserver1.getDataStorage().get(ForcedChunksSavedData.factory(), "chunks"); if (forcedchunk != null) { -@@ -555,10 +852,17 @@ +@@ -555,10 +853,17 @@ } } @@ -688,7 +689,7 @@ } public GameType getDefaultGameType() { -@@ -588,12 +892,16 @@ +@@ -588,12 +893,16 @@ worldserver.save((ProgressListener) null, flush, worldserver.noSave && !force); } @@ -707,7 +708,7 @@ if (flush) { Iterator iterator1 = this.getAllLevels().iterator(); -@@ -628,18 +936,45 @@ +@@ -628,18 +937,45 @@ this.stopServer(); } @@ -754,7 +755,7 @@ } MinecraftServer.LOGGER.info("Saving worlds"); -@@ -693,6 +1028,15 @@ +@@ -693,6 +1029,15 @@ } catch (IOException ioexception1) { MinecraftServer.LOGGER.error("Failed to unlock level {}", this.storageSource.getLevelId(), ioexception1); } @@ -770,7 +771,7 @@ } -@@ -709,6 +1053,14 @@ +@@ -709,6 +1054,14 @@ } public void halt(boolean waitForShutdown) { @@ -785,7 +786,7 @@ this.running = false; if (waitForShutdown) { try { -@@ -720,6 +1072,64 @@ +@@ -720,6 +1073,64 @@ } @@ -850,7 +851,7 @@ protected void runServer() { try { if (!this.initServer()) { -@@ -727,9 +1137,16 @@ +@@ -727,9 +1138,16 @@ } this.nextTickTimeNanos = Util.getNanos(); @@ -868,7 +869,7 @@ while (this.running) { long i; -@@ -744,11 +1161,30 @@ +@@ -744,12 +1162,31 @@ if (j > MinecraftServer.OVERLOADED_THRESHOLD_NANOS + 20L * i && this.nextTickTimeNanos - this.lastOverloadWarningNanos >= MinecraftServer.OVERLOADED_WARNING_INTERVAL_NANOS + 100L * i) { long k = j / i; @@ -887,7 +888,7 @@ + tps1.add(currentTps, diff); + tps5.add(currentTps, diff); + tps15.add(currentTps, diff); -+ + + // Backwards compat with bad plugins + this.recentTps[0] = tps1.getAverage(); + this.recentTps[1] = tps5.getAverage(); @@ -896,10 +897,11 @@ + } + // Paper end - further improve server tick loop + // Spigot end - ++ boolean flag = i == 0L; -@@ -757,6 +1193,8 @@ + if (this.debugCommandProfilerDelayStart) { +@@ -757,6 +1194,8 @@ this.debugCommandProfiler = new MinecraftServer.TimeProfiler(Util.getNanos(), this.tickCount); } @@ -908,7 +910,7 @@ this.nextTickTimeNanos += i; try { -@@ -830,6 +1268,13 @@ +@@ -830,6 +1269,13 @@ this.services.profileCache().clearExecutor(); } @@ -922,7 +924,7 @@ this.onServerExit(); } -@@ -889,9 +1334,16 @@ +@@ -889,9 +1335,16 @@ } private boolean haveTime() { @@ -940,7 +942,7 @@ public static boolean throwIfFatalException() { RuntimeException runtimeexception = (RuntimeException) MinecraftServer.fatalException.get(); -@@ -903,7 +1355,7 @@ +@@ -903,7 +1356,7 @@ } public static void setFatalException(RuntimeException exception) { @@ -949,7 +951,7 @@ } @Override -@@ -961,6 +1413,7 @@ +@@ -961,6 +1414,7 @@ if (super.pollTask()) { return true; } else { @@ -957,7 +959,7 @@ if (this.tickRateManager.isSprinting() || this.haveTime()) { Iterator iterator = this.getAllLevels().iterator(); -@@ -968,16 +1421,16 @@ +@@ -968,16 +1422,16 @@ ServerLevel worldserver = (ServerLevel) iterator.next(); if (worldserver.getChunkSource().pollTask()) { @@ -977,7 +979,7 @@ Profiler.get().incrementCounter("runTask"); super.doRunTask(ticktask); } -@@ -1025,6 +1478,7 @@ +@@ -1025,6 +1479,7 @@ } public void tickServer(BooleanSupplier shouldKeepTicking) { @@ -985,7 +987,7 @@ long i = Util.getNanos(); int j = this.pauseWhileEmptySeconds() * 20; -@@ -1041,11 +1495,13 @@ +@@ -1041,11 +1496,13 @@ this.autoSave(); } @@ -999,7 +1001,7 @@ ++this.tickCount; this.tickRateManager.tick(); this.tickChildren(shouldKeepTicking); -@@ -1055,12 +1511,18 @@ +@@ -1055,12 +1512,18 @@ } --this.ticksUntilAutosave; @@ -1019,7 +1021,7 @@ gameprofilerfiller.push("tallying"); long k = Util.getNanos() - i; int l = this.tickCount % 100; -@@ -1069,12 +1531,17 @@ +@@ -1069,12 +1532,17 @@ this.aggregatedTickTimesNanos += k; this.tickTimesNanos[l] = k; this.smoothedTickTimeMillis = this.smoothedTickTimeMillis * 0.8F + (float) k / (float) TimeUtil.NANOSECONDS_PER_MILLISECOND * 0.19999999F; @@ -1038,7 +1040,7 @@ MinecraftServer.LOGGER.debug("Autosave started"); ProfilerFiller gameprofilerfiller = Profiler.get(); -@@ -1123,7 +1590,7 @@ +@@ -1123,7 +1591,7 @@ private ServerStatus buildServerStatus() { ServerStatus.Players serverping_serverpingplayersample = this.buildPlayerStatus(); @@ -1047,7 +1049,7 @@ } private ServerStatus.Players buildPlayerStatus() { -@@ -1133,7 +1600,7 @@ +@@ -1133,7 +1601,7 @@ if (this.hidesOnlinePlayers()) { return new ServerStatus.Players(i, list.size(), List.of()); } else { @@ -1056,7 +1058,7 @@ ObjectArrayList objectarraylist = new ObjectArrayList(j); int k = Mth.nextInt(this.random, 0, list.size() - j); -@@ -1154,24 +1621,56 @@ +@@ -1154,24 +1622,58 @@ this.getPlayerList().getPlayers().forEach((entityplayer) -> { entityplayer.connection.suspendFlushing(); }); @@ -1065,7 +1067,8 @@ gameprofilerfiller.push("commandFunctions"); this.getFunctions().tick(); gameprofilerfiller.popPush("levels"); - Iterator iterator = this.getAllLevels().iterator(); +- Iterator iterator = this.getAllLevels().iterator(); ++ //Iterator iterator = this.getAllLevels().iterator(); // Paper - Throw exception on world create while being ticked; moved down + // CraftBukkit start + // Run tasks that are waiting on processing @@ -1093,6 +1096,8 @@ + } + } + ++ this.isIteratingOverLevels = true; // Paper - Throw exception on world create while being ticked ++ Iterator iterator = this.getAllLevels().iterator(); // Paper - Throw exception on world create while being ticked; move down while (iterator.hasNext()) { ServerLevel worldserver = (ServerLevel) iterator.next(); + worldserver.hasPhysicsEvent = org.bukkit.event.block.BlockPhysicsEvent.getHandlerList().getRegisteredListeners().length > 0; // Paper - BlockPhysicsEvent @@ -1113,15 +1118,17 @@ gameprofilerfiller.push("tick"); -@@ -1186,6 +1685,7 @@ +@@ -1186,7 +1688,9 @@ gameprofilerfiller.pop(); gameprofilerfiller.pop(); + worldserver.explosionDensityCache.clear(); // Paper - Optimize explosions } ++ this.isIteratingOverLevels = false; // Paper - Throw exception on world create while being ticked gameprofilerfiller.popPush("connection"); -@@ -1267,6 +1767,22 @@ + this.tickConnection(); +@@ -1267,6 +1771,22 @@ return (ServerLevel) this.levels.get(key); } @@ -1144,7 +1151,7 @@ public Set> levelKeys() { return this.levels.keySet(); } -@@ -1296,7 +1812,7 @@ +@@ -1296,7 +1816,7 @@ @DontObfuscate public String getServerModName() { @@ -1153,7 +1160,7 @@ } public SystemReport fillSystemReport(SystemReport details) { -@@ -1347,7 +1863,7 @@ +@@ -1347,7 +1867,7 @@ @Override public void sendSystemMessage(Component message) { @@ -1162,7 +1169,7 @@ } public KeyPair getKeyPair() { -@@ -1385,11 +1901,14 @@ +@@ -1385,11 +1905,14 @@ } } @@ -1182,7 +1189,7 @@ } } -@@ -1403,7 +1922,7 @@ +@@ -1403,7 +1926,7 @@ while (iterator.hasNext()) { ServerLevel worldserver = (ServerLevel) iterator.next(); @@ -1191,7 +1198,7 @@ } } -@@ -1481,10 +2000,20 @@ +@@ -1481,10 +2004,20 @@ @Override public String getMotd() { @@ -1213,7 +1220,7 @@ this.motd = motd; } -@@ -1507,7 +2036,7 @@ +@@ -1507,7 +2040,7 @@ } public ServerConnectionListener getConnection() { @@ -1222,7 +1229,7 @@ } public boolean isReady() { -@@ -1632,13 +2161,19 @@ +@@ -1632,13 +2165,19 @@ return this.functionManager; } @@ -1244,7 +1251,7 @@ }, this).thenCompose((immutablelist) -> { MultiPackResourceManager resourcemanager = new MultiPackResourceManager(PackType.SERVER_DATA, immutablelist); List> list = TagLoader.loadTagsForExistingRegistries(resourcemanager, this.registries.compositeAccess()); -@@ -1654,17 +2189,21 @@ +@@ -1654,17 +2193,21 @@ }).thenAcceptAsync((minecraftserver_reloadableresources) -> { this.resources.close(); this.resources = minecraftserver_reloadableresources; @@ -1266,7 +1273,7 @@ }, this); if (this.isSameThread()) { -@@ -1789,14 +2328,15 @@ +@@ -1789,14 +2332,15 @@ if (this.isEnforceWhitelist()) { PlayerList playerlist = source.getServer().getPlayerList(); UserWhiteList whitelist = playerlist.getWhiteList(); @@ -1284,7 +1291,7 @@ } } -@@ -1952,7 +2492,7 @@ +@@ -1952,7 +2496,7 @@ final List list = Lists.newArrayList(); final GameRules gamerules = this.getGameRules(); @@ -1293,7 +1300,7 @@ @Override public > void visit(GameRules.Key key, GameRules.Type type) { list.add(String.format(Locale.ROOT, "%s=%s\n", key.getId(), gamerules.getRule(key))); -@@ -2058,7 +2598,7 @@ +@@ -2058,7 +2602,7 @@ try { label51: { @@ -1302,19 +1309,22 @@ try { arraylist = Lists.newArrayList(NativeModuleLister.listModules()); -@@ -2108,6 +2648,21 @@ - - } - +@@ -2105,9 +2649,24 @@ + if (bufferedwriter != null) { + bufferedwriter.close(); + } ++ ++ } ++ + // CraftBukkit start + public boolean isDebugging() { + return false; + } -+ + + public static MinecraftServer getServer() { + return SERVER; // Paper -+ } -+ + } + + @Deprecated + public static RegistryAccess getDefaultRegistryAccess() { + return CraftRegistry.getMinecraftRegistry(); @@ -1324,7 +1334,7 @@ private ProfilerFiller createProfiler() { if (this.willStartRecordingMetrics) { this.metricsRecorder = ActiveMetricsRecorder.createStarted(new ServerMetricsSamplersProvider(Util.timeSource, this.isDedicatedServer()), Util.timeSource, Util.ioPool(), new MetricsPersister("server"), this.onMetricsRecordingStopped, (path) -> { -@@ -2225,18 +2780,24 @@ +@@ -2225,18 +2784,24 @@ } public void logChatMessage(Component message, ChatType.Bound params, @Nullable String prefix) { @@ -1353,13 +1363,11 @@ } public boolean logIPs() { -@@ -2377,6 +2938,32 @@ - } - +@@ -2379,4 +2944,30 @@ public static record ServerResourcePackInfo(UUID id, String url, String hash, boolean isRequired, @Nullable Component prompt) { -+ -+ } + } ++ + // Paper start - Add tick times API and /mspt command + public static class TickTimes { + private final long[] times; @@ -1383,6 +1391,6 @@ + } + return ((double) total / (double) times.length) * 1.0E-6D; + } - } ++ } + // Paper end - Add tick times API and /mspt command } 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 4b89422338..557eb1a75a 100644 --- a/paper-server/src/main/java/org/bukkit/craftbukkit/CraftServer.java +++ b/paper-server/src/main/java/org/bukkit/craftbukkit/CraftServer.java @@ -919,6 +919,11 @@ public final class CraftServer implements Server { return new ArrayList(this.worlds.values()); } + @Override + public boolean isTickingWorlds() { + return console.isIteratingOverLevels; + } + public DedicatedPlayerList getHandle() { return this.playerList; } @@ -1182,6 +1187,7 @@ public final class CraftServer implements Server { @Override public World createWorld(WorldCreator creator) { Preconditions.checkState(this.console.getAllLevels().iterator().hasNext(), "Cannot create additional worlds on STARTUP"); + //Preconditions.checkState(!this.console.isIteratingOverLevels, "Cannot create a world while worlds are being ticked"); // Paper - Cat - Temp disable. We'll see how this goes. Preconditions.checkArgument(creator != null, "WorldCreator cannot be null"); String name = creator.name(); @@ -1358,6 +1364,7 @@ public final class CraftServer implements Server { @Override public boolean unloadWorld(World world, boolean save) { + //Preconditions.checkState(!this.console.isIteratingOverLevels, "Cannot unload a world while worlds are being ticked"); // Paper - Cat - Temp disable. We'll see how this goes. if (world == null) { return false; }