From 64500a201f8aeaca21e668b0e16fda0b70087fae Mon Sep 17 00:00:00 2001 From: Jake Potrebic Date: Fri, 13 Dec 2024 19:12:33 -0800 Subject: [PATCH] net.minecraft.server --- .../net/minecraft/server/Bootstrap.java.patch | 44 +- .../net/minecraft/server/Main.java.patch | 254 ++++ .../server/MinecraftServer.java.patch | 1222 +++++++++-------- .../server/PlayerAdvancements.java.patch | 54 +- .../ReloadableServerRegistries.java.patch | 38 + .../ReloadableServerResources.java.patch | 12 +- .../ServerAdvancementManager.java.patch | 36 +- .../server/ServerFunctionLibrary.java.patch | 11 + .../server/ServerFunctionManager.java.patch | 2 +- .../server/ServerScoreboard.java.patch | 140 +- .../server/ServerTickRateManager.java.patch | 23 +- .../net/minecraft/server/Services.java.patch | 18 +- .../minecraft/server/WorldLoader.java.patch | 6 +- .../net/minecraft/server/Main.java.patch | 290 ---- .../ReloadableServerRegistries.java.patch | 32 - .../server/ServerFunctionLibrary.java.patch | 11 - 16 files changed, 1083 insertions(+), 1110 deletions(-) rename paper-server/patches/{unapplied => sources}/net/minecraft/server/Bootstrap.java.patch (80%) create mode 100644 paper-server/patches/sources/net/minecraft/server/Main.java.patch rename paper-server/patches/{unapplied => sources}/net/minecraft/server/MinecraftServer.java.patch (54%) rename paper-server/patches/{unapplied => sources}/net/minecraft/server/PlayerAdvancements.java.patch (62%) create mode 100644 paper-server/patches/sources/net/minecraft/server/ReloadableServerRegistries.java.patch rename paper-server/patches/{unapplied => sources}/net/minecraft/server/ReloadableServerResources.java.patch (79%) rename paper-server/patches/{unapplied => sources}/net/minecraft/server/ServerAdvancementManager.java.patch (50%) create mode 100644 paper-server/patches/sources/net/minecraft/server/ServerFunctionLibrary.java.patch rename paper-server/patches/{unapplied => sources}/net/minecraft/server/ServerFunctionManager.java.patch (95%) rename paper-server/patches/{unapplied => sources}/net/minecraft/server/ServerScoreboard.java.patch (55%) rename paper-server/patches/{unapplied => sources}/net/minecraft/server/ServerTickRateManager.java.patch (74%) rename paper-server/patches/{unapplied => sources}/net/minecraft/server/Services.java.patch (84%) rename paper-server/patches/{unapplied => sources}/net/minecraft/server/WorldLoader.java.patch (73%) delete mode 100644 paper-server/patches/unapplied/net/minecraft/server/Main.java.patch delete mode 100644 paper-server/patches/unapplied/net/minecraft/server/ReloadableServerRegistries.java.patch delete mode 100644 paper-server/patches/unapplied/net/minecraft/server/ServerFunctionLibrary.java.patch diff --git a/paper-server/patches/unapplied/net/minecraft/server/Bootstrap.java.patch b/paper-server/patches/sources/net/minecraft/server/Bootstrap.java.patch similarity index 80% rename from paper-server/patches/unapplied/net/minecraft/server/Bootstrap.java.patch rename to paper-server/patches/sources/net/minecraft/server/Bootstrap.java.patch index efce551cae..b1ee24c3e7 100644 --- a/paper-server/patches/unapplied/net/minecraft/server/Bootstrap.java.patch +++ b/paper-server/patches/sources/net/minecraft/server/Bootstrap.java.patch @@ -1,6 +1,6 @@ --- a/net/minecraft/server/Bootstrap.java +++ b/net/minecraft/server/Bootstrap.java -@@ -17,6 +17,9 @@ +@@ -17,6 +_,9 @@ import net.minecraft.core.dispenser.DispenseItemBehavior; import net.minecraft.core.registries.BuiltInRegistries; import net.minecraft.locale.Language; @@ -10,45 +10,15 @@ import net.minecraft.world.effect.MobEffect; import net.minecraft.world.entity.EntityType; import net.minecraft.world.entity.ai.attributes.Attribute; -@@ -30,7 +33,8 @@ - import net.minecraft.world.level.block.state.BlockBehaviour; - import org.slf4j.Logger; - --@SuppressForbidden(a = "System.out setup") -+@SuppressForbidden(reason = "System.out setup") -+// CraftBukkit end - public class Bootstrap { - - public static final PrintStream STDOUT = System.out; -@@ -42,9 +46,27 @@ - - public static void bootStrap() { - if (!Bootstrap.isBootstrapped) { -+ // CraftBukkit start -+ /*String name = Bootstrap.class.getSimpleName(); // Paper -+ switch (name) { -+ case "DispenserRegistry": -+ break; -+ case "Bootstrap": -+ System.err.println("***************************************************************************"); -+ System.err.println("*** WARNING: This server jar may only be used for development purposes. ***"); -+ System.err.println("***************************************************************************"); -+ break; -+ default: -+ System.err.println("**********************************************************************"); -+ System.err.println("*** WARNING: This server jar is unsupported, use at your own risk. ***"); -+ System.err.println("**********************************************************************"); -+ break; -+ }*/ // Paper -+ // CraftBukkit end - Bootstrap.isBootstrapped = true; +@@ -43,6 +_,7 @@ + if (!isBootstrapped) { + isBootstrapped = true; Instant instant = Instant.now(); - + io.papermc.paper.plugin.entrypoint.LaunchEntryPointHandler.enterBootstrappers(); // Paper - Entrypoint for bootstrapping if (BuiltInRegistries.REGISTRY.keySet().isEmpty()) { throw new IllegalStateException("Unable to load registries"); } else { -@@ -56,11 +78,77 @@ +@@ -54,11 +_,77 @@ EntitySelectorOptions.bootStrap(); DispenseItemBehavior.bootStrap(); CauldronInteraction.bootStrap(); @@ -58,8 +28,8 @@ + }); + // Paper end CreativeModeTabs.validate(); - Bootstrap.wrapStreams(); - Bootstrap.bootstrapDuration.set(Duration.between(instant, Instant.now()).toMillis()); + wrapStreams(); + bootstrapDuration.set(Duration.between(instant, Instant.now()).toMillis()); } + // CraftBukkit start - easier than fixing the decompile + BlockStateData.register(1008, "{Name:'minecraft:oak_sign',Properties:{rotation:'0'}}", "{Name:'minecraft:standing_sign',Properties:{rotation:'0'}}"); diff --git a/paper-server/patches/sources/net/minecraft/server/Main.java.patch b/paper-server/patches/sources/net/minecraft/server/Main.java.patch new file mode 100644 index 0000000000..001042f60c --- /dev/null +++ b/paper-server/patches/sources/net/minecraft/server/Main.java.patch @@ -0,0 +1,254 @@ +--- a/net/minecraft/server/Main.java ++++ b/net/minecraft/server/Main.java +@@ -37,6 +_,7 @@ + import net.minecraft.server.dedicated.DedicatedServerProperties; + import net.minecraft.server.dedicated.DedicatedServerSettings; + import net.minecraft.server.level.progress.LoggerChunkProgressListener; ++import net.minecraft.server.packs.PackType; + import net.minecraft.server.packs.repository.PackRepository; + import net.minecraft.server.packs.repository.ServerPacksSource; + import net.minecraft.util.Mth; +@@ -67,8 +_,9 @@ + reason = "System.out needed before bootstrap" + ) + @DontObfuscate +- public static void main(String[] args) { ++ public static void main(final OptionSet optionSet) { // CraftBukkit - replaces main(String[] args) + SharedConstants.tryDetectVersion(); ++ /* CraftBukkit start - Replace everything + OptionParser optionParser = new OptionParser(); + OptionSpec optionSpec = optionParser.accepts("nogui"); + OptionSpec optionSpec1 = optionParser.accepts("initSettings", "Initializes 'server.properties' and 'eula.txt', then quits"); +@@ -93,41 +_,94 @@ + optionParser.printHelpOn(System.err); + return; + } ++ */ // CraftBukkit end ++ try { + +- Path path = optionSet.valueOf(optionSpec14); ++ Path path = (Path) optionSet.valueOf("pidFile"); // CraftBukkit + if (path != null) { + writePidFile(path); + } + + CrashReport.preload(); +- if (optionSet.has(optionSpec13)) { ++ if (optionSet.has("jfrProfile")) { // CraftBukkit + JvmProfiler.INSTANCE.start(Environment.SERVER); + } + ++ io.papermc.paper.plugin.PluginInitializerManager.load(optionSet); // Paper + Bootstrap.bootStrap(); + Bootstrap.validate(); + Util.startTimerHackThread(); + Path path1 = Paths.get("server.properties"); +- DedicatedServerSettings dedicatedServerSettings = new DedicatedServerSettings(path1); ++ DedicatedServerSettings dedicatedServerSettings = new DedicatedServerSettings(optionSet); // CraftBukkit - CLI argument support + dedicatedServerSettings.forceSave(); + RegionFileVersion.configure(dedicatedServerSettings.getProperties().regionFileComression); + Path path2 = Paths.get("eula.txt"); + Eula eula = new Eula(path2); +- if (optionSet.has(optionSpec1)) { ++ // Paper start - load config files early for access below if needed ++ org.bukkit.configuration.file.YamlConfiguration bukkitConfiguration = io.papermc.paper.configuration.PaperConfigurations.loadLegacyConfigFile((File) optionSet.valueOf("bukkit-settings")); ++ org.bukkit.configuration.file.YamlConfiguration spigotConfiguration = io.papermc.paper.configuration.PaperConfigurations.loadLegacyConfigFile((File) optionSet.valueOf("spigot-settings")); ++ // Paper end - load config files early for access below if needed ++ if (optionSet.has("initSettings")) { // CraftBukkit ++ // CraftBukkit start - SPIGOT-5761: Create bukkit.yml and commands.yml if not present ++ File configFile = (File) optionSet.valueOf("bukkit-settings"); ++ org.bukkit.configuration.file.YamlConfiguration configuration = org.bukkit.configuration.file.YamlConfiguration.loadConfiguration(configFile); ++ configuration.options().copyDefaults(true); ++ configuration.setDefaults(org.bukkit.configuration.file.YamlConfiguration.loadConfiguration(new java.io.InputStreamReader(Main.class.getClassLoader().getResourceAsStream("configurations/bukkit.yml"), com.google.common.base.Charsets.UTF_8))); ++ configuration.save(configFile); ++ ++ File commandFile = (File) optionSet.valueOf("commands-settings"); ++ org.bukkit.configuration.file.YamlConfiguration commandsConfiguration = org.bukkit.configuration.file.YamlConfiguration.loadConfiguration(commandFile); ++ commandsConfiguration.options().copyDefaults(true); ++ commandsConfiguration.setDefaults(org.bukkit.configuration.file.YamlConfiguration.loadConfiguration(new java.io.InputStreamReader(Main.class.getClassLoader().getResourceAsStream("configurations/commands.yml"), com.google.common.base.Charsets.UTF_8))); ++ commandsConfiguration.save(commandFile); ++ // CraftBukkit end + LOGGER.info("Initialized '{}' and '{}'", path1.toAbsolutePath(), path2.toAbsolutePath()); + return; + } + +- if (!eula.hasAgreedToEULA()) { ++ // Spigot Start ++ boolean eulaAgreed = Boolean.getBoolean("com.mojang.eula.agree"); ++ if (eulaAgreed) { ++ System.err.println("You have used the Spigot command line EULA agreement flag."); ++ System.err.println("By using this setting you are indicating your agreement to Mojang's EULA (https://account.mojang.com/documents/minecraft_eula)."); ++ System.err.println("If you do not agree to the above EULA please stop your server and remove this flag immediately."); ++ } ++ // Spigot End ++ if (!eula.hasAgreedToEULA() && !eulaAgreed) { // Spigot + LOGGER.info("You need to agree to the EULA in order to run the server. Go to eula.txt for more info."); + return; + } + +- File file = new File(optionSet.valueOf(optionSpec9)); +- Services services = Services.create(new YggdrasilAuthenticationService(Proxy.NO_PROXY), file); +- String string = Optional.ofNullable(optionSet.valueOf(optionSpec10)).orElse(dedicatedServerSettings.getProperties().levelName); ++ // Paper start - Detect headless JRE ++ String awtException = io.papermc.paper.util.ServerEnvironment.awtDependencyCheck(); ++ if (awtException != null) { ++ Main.LOGGER.error("You are using a headless JRE distribution."); ++ Main.LOGGER.error("This distribution is missing certain graphic libraries that the Minecraft server needs to function."); ++ Main.LOGGER.error("For instructions on how to install the non-headless JRE, see https://docs.papermc.io/misc/java-install"); ++ Main.LOGGER.error(""); ++ Main.LOGGER.error(awtException); ++ return; ++ } ++ // Paper end - Detect headless JRE ++ ++ org.spigotmc.SpigotConfig.disabledAdvancements = spigotConfiguration.getStringList("advancements.disabled"); // Paper - fix SPIGOT-5885, must be set early in init ++ ++ // Paper start - fix SPIGOT-5824 ++ File file; ++ File userCacheFile = new File(Services.USERID_CACHE_FILE); ++ if (optionSet.has("universe")) { ++ file = (File) optionSet.valueOf("universe"); // CraftBukkit ++ userCacheFile = new File(file, Services.USERID_CACHE_FILE); ++ } else { ++ file = new File(bukkitConfiguration.getString("settings.world-container", ".")); ++ } ++ // Paper end - fix SPIGOT-5824 ++ Services services = Services.create(new com.destroystokyo.paper.profile.PaperAuthenticationService(Proxy.NO_PROXY), file, userCacheFile, optionSet); // Paper - pass OptionSet to load paper config files; override authentication service; fix world-container ++ // CraftBukkit start ++ String string = Optional.ofNullable((String) optionSet.valueOf("world")).orElse(dedicatedServerSettings.getProperties().levelName); + LevelStorageSource levelStorageSource = LevelStorageSource.createDefault(file.toPath()); +- LevelStorageSource.LevelStorageAccess levelStorageAccess = levelStorageSource.validateAndCreateAccess(string); ++ LevelStorageSource.LevelStorageAccess levelStorageAccess = levelStorageSource.validateAndCreateAccess(string, LevelStem.OVERWORLD); ++ // CraftBukkit end + Dynamic dataTag; + if (levelStorageAccess.hasWorldData()) { + LevelSummary summary; +@@ -169,12 +_,30 @@ + } + + Dynamic dynamic = dataTag; +- boolean hasOptionSpec = optionSet.has(optionSpec7); ++ boolean hasOptionSpec = optionSet.has("safeMode"); // CraftBukkit + if (hasOptionSpec) { + LOGGER.warn("Safe mode active, only vanilla datapack will be loaded"); + } + + PackRepository packRepository = ServerPacksSource.createPackRepository(levelStorageAccess); ++ // CraftBukkit start ++ File bukkitDataPackFolder = new File(levelStorageAccess.getLevelPath(net.minecraft.world.level.storage.LevelResource.DATAPACK_DIR).toFile(), "bukkit"); ++ if (!bukkitDataPackFolder.exists()) { ++ bukkitDataPackFolder.mkdirs(); ++ } ++ File mcMeta = new File(bukkitDataPackFolder, "pack.mcmeta"); ++ try { ++ com.google.common.io.Files.write("{\n" ++ + " \"pack\": {\n" ++ + " \"description\": \"Data pack for resources provided by Bukkit plugins\",\n" ++ + " \"pack_format\": " + SharedConstants.getCurrentVersion().getPackVersion(PackType.SERVER_DATA) + "\n" ++ + " }\n" ++ + "}\n", mcMeta, com.google.common.base.Charsets.UTF_8); ++ } catch (java.io.IOException ex) { ++ throw new RuntimeException("Could not initialize Bukkit datapack", ex); ++ } ++ java.util.concurrent.atomic.AtomicReference worldLoader = new java.util.concurrent.atomic.AtomicReference<>(); ++ // CraftBukkit end + + WorldStem worldStem; + try { +@@ -183,6 +_,7 @@ + executor -> WorldLoader.load( + initConfig, + context -> { ++ worldLoader.set(context); // CraftBukkit + Registry registry = context.datapackDimensions().lookupOrThrow(Registries.LEVEL_STEM); + if (dynamic != null) { + LevelDataAndDimensions levelDataAndDimensions = LevelStorageSource.getLevelDataAndDimensions( +@@ -196,7 +_,7 @@ + LevelSettings levelSettings; + WorldOptions worldOptions; + WorldDimensions worldDimensions; +- if (optionSet.has(optionSpec2)) { ++ if (optionSet.has("demo")) { // CraftBukkit + levelSettings = MinecraftServer.DEMO_SETTINGS; + worldOptions = WorldOptions.DEMO_OPTIONS; + worldDimensions = WorldPresets.createNormalWorldDimensions(context.datapackWorldgen()); +@@ -211,7 +_,7 @@ + new GameRules(context.dataConfiguration().enabledFeatures()), + context.dataConfiguration() + ); +- worldOptions = optionSet.has(optionSpec3) ? properties.worldOptions.withBonusChest(true) : properties.worldOptions; ++ worldOptions = optionSet.has("bonusChest") ? properties.worldOptions.withBonusChest(true) : properties.worldOptions; // CraftBukkit + worldDimensions = properties.createDimensions(context.datapackWorldgen()); + } + +@@ -237,6 +_,7 @@ + return; + } + ++ /* + RegistryAccess.Frozen frozen = worldStem.registries().compositeAccess(); + boolean hasOptionSpec1 = optionSet.has(optionSpec6); + if (optionSet.has(optionSpec4) || hasOptionSpec1) { +@@ -245,9 +_,13 @@ + + WorldData worldData = worldStem.worldData(); + levelStorageAccess.saveDataTag(frozen, worldData); ++ */ + final DedicatedServer dedicatedServer = MinecraftServer.spin( + thread1 -> { + DedicatedServer dedicatedServer1 = new DedicatedServer( ++ // CraftBukkit start ++ optionSet, ++ worldLoader.get(), + thread1, + levelStorageAccess, + packRepository, +@@ -257,17 +_,29 @@ + services, + LoggerChunkProgressListener::createFromGameruleRadius + ); ++ /* + dedicatedServer1.setPort(optionSet.valueOf(optionSpec11)); +- dedicatedServer1.setDemo(optionSet.has(optionSpec2)); ++ */ ++ dedicatedServer1.setDemo(optionSet.has("demo")); // Paper ++ /* + dedicatedServer1.setId(optionSet.valueOf(optionSpec12)); +- boolean flag = !optionSet.has(optionSpec) && !optionSet.valuesOf(optionSpec15).contains("nogui"); ++ */ ++ boolean flag = !optionSet.has("nogui") && !optionSet.nonOptionArguments().contains("nogui"); + if (flag && !GraphicsEnvironment.isHeadless()) { + dedicatedServer1.showGui(); + } + ++ if (optionSet.has("port")) { ++ int port = (Integer) optionSet.valueOf("port"); ++ if (port > 0) { ++ dedicatedServer1.setPort(port); ++ } ++ } ++ + return dedicatedServer1; + } + ); ++ /* CraftBukkit start + Thread thread = new Thread("Server Shutdown Thread") { + @Override + public void run() { +@@ -276,6 +_,7 @@ + }; + thread.setUncaughtExceptionHandler(new DefaultUncaughtExceptionHandler(LOGGER)); + Runtime.getRuntime().addShutdownHook(thread); ++ */ // CraftBukkit end + } catch (Exception var42) { + LOGGER.error(LogUtils.FATAL_MARKER, "Failed to start the minecraft server", (Throwable)var42); + } +@@ -316,7 +_,7 @@ + RegistryAccess registryAccess, + boolean recreateRegionFiles + ) { +- LOGGER.info("Forcing world upgrade!"); ++ LOGGER.info("Forcing world upgrade! {}", levelStorage.getLevelId()); // CraftBukkit + + try (WorldUpgrader worldUpgrader = new WorldUpgrader(levelStorage, dataFixer, registryAccess, eraseCache, recreateRegionFiles)) { + Component component = null; diff --git a/paper-server/patches/unapplied/net/minecraft/server/MinecraftServer.java.patch b/paper-server/patches/sources/net/minecraft/server/MinecraftServer.java.patch similarity index 54% rename from paper-server/patches/unapplied/net/minecraft/server/MinecraftServer.java.patch rename to paper-server/patches/sources/net/minecraft/server/MinecraftServer.java.patch index b2aec783a8..21203c0786 100644 --- a/paper-server/patches/unapplied/net/minecraft/server/MinecraftServer.java.patch +++ b/paper-server/patches/sources/net/minecraft/server/MinecraftServer.java.patch @@ -1,6 +1,6 @@ --- a/net/minecraft/server/MinecraftServer.java +++ b/net/minecraft/server/MinecraftServer.java -@@ -3,6 +3,9 @@ +@@ -3,6 +_,9 @@ import com.google.common.base.Preconditions; import com.google.common.base.Splitter; import com.google.common.collect.ImmutableList; @@ -10,15 +10,7 @@ import com.google.common.collect.Lists; import com.google.common.collect.Maps; import com.google.common.collect.Sets; -@@ -45,7 +48,6 @@ - import java.util.UUID; - import java.util.concurrent.CompletableFuture; - import java.util.concurrent.Executor; --import java.util.concurrent.RejectedExecutionException; - import java.util.concurrent.atomic.AtomicReference; - import java.util.concurrent.locks.LockSupport; - import java.util.function.BooleanSupplier; -@@ -84,17 +86,6 @@ +@@ -80,17 +_,6 @@ import net.minecraft.obfuscate.DontObfuscate; import net.minecraft.resources.ResourceKey; import net.minecraft.resources.ResourceLocation; @@ -36,7 +28,7 @@ import net.minecraft.server.packs.PackType; import net.minecraft.server.packs.repository.Pack; import net.minecraft.server.packs.repository.PackRepository; -@@ -116,6 +107,7 @@ +@@ -111,6 +_,7 @@ import net.minecraft.util.RandomSource; import net.minecraft.util.SignatureValidator; import net.minecraft.util.TimeUtil; @@ -44,75 +36,10 @@ import net.minecraft.util.debugchart.RemoteDebugSampleType; import net.minecraft.util.debugchart.SampleLogger; import net.minecraft.util.debugchart.TpsDebugDimensions; -@@ -156,37 +148,71 @@ - import net.minecraft.world.level.biome.BiomeManager; - import net.minecraft.world.level.block.Block; - import net.minecraft.world.level.block.entity.FuelValues; --import net.minecraft.world.level.border.BorderChangeListener; - import net.minecraft.world.level.border.WorldBorder; - import net.minecraft.world.level.chunk.storage.ChunkIOErrorReporter; - import net.minecraft.world.level.chunk.storage.RegionStorageInfo; - import net.minecraft.world.level.dimension.LevelStem; --import net.minecraft.world.level.levelgen.Heightmap; --import net.minecraft.world.level.levelgen.PatrolSpawner; --import net.minecraft.world.level.levelgen.PhantomSpawner; - import net.minecraft.world.level.levelgen.WorldOptions; - import net.minecraft.world.level.levelgen.feature.ConfiguredFeature; - import net.minecraft.world.level.levelgen.structure.templatesystem.StructureTemplateManager; -+import net.minecraft.world.level.storage.WorldData; -+import org.slf4j.Logger; -+ -+// CraftBukkit start -+import com.mojang.serialization.Dynamic; -+import com.mojang.serialization.Lifecycle; -+import java.io.File; -+import java.util.Random; -+// import jline.console.ConsoleReader; // Paper -+import joptsimple.OptionSet; -+import net.minecraft.nbt.NbtException; -+import net.minecraft.nbt.ReportedNbtException; -+import net.minecraft.server.bossevents.CustomBossEvents; -+import net.minecraft.server.dedicated.DedicatedServer; -+import net.minecraft.server.dedicated.DedicatedServerProperties; -+import net.minecraft.server.level.DemoMode; -+import net.minecraft.server.level.PlayerRespawnLogic; -+import net.minecraft.server.level.ServerChunkCache; -+import net.minecraft.server.level.ServerLevel; -+import net.minecraft.server.level.ServerPlayer; -+import net.minecraft.server.level.ServerPlayerGameMode; -+import net.minecraft.server.level.progress.ChunkProgressListener; -+import net.minecraft.server.level.progress.ChunkProgressListenerFactory; -+import net.minecraft.server.network.ServerConnectionListener; -+import net.minecraft.server.network.TextFilter; -+import net.minecraft.world.level.levelgen.Heightmap; -+import net.minecraft.world.level.levelgen.PatrolSpawner; -+import net.minecraft.world.level.levelgen.PhantomSpawner; -+import net.minecraft.world.level.levelgen.WorldDimensions; -+import net.minecraft.world.level.levelgen.presets.WorldPresets; - import net.minecraft.world.level.storage.CommandStorage; --import net.minecraft.world.level.storage.DerivedLevelData; - import net.minecraft.world.level.storage.DimensionDataStorage; - import net.minecraft.world.level.storage.LevelData; -+import net.minecraft.world.level.storage.LevelDataAndDimensions; - import net.minecraft.world.level.storage.LevelResource; - import net.minecraft.world.level.storage.LevelStorageSource; -+import net.minecraft.world.level.storage.LevelSummary; - import net.minecraft.world.level.storage.PlayerDataStorage; -+import net.minecraft.world.level.storage.PrimaryLevelData; - import net.minecraft.world.level.storage.ServerLevelData; --import net.minecraft.world.level.storage.WorldData; -+import net.minecraft.world.level.validation.ContentValidationException; - import net.minecraft.world.phys.Vec2; - import net.minecraft.world.phys.Vec3; --import org.slf4j.Logger; -+import org.bukkit.Bukkit; -+import org.bukkit.craftbukkit.CraftRegistry; -+import org.bukkit.event.server.ServerLoadEvent; -+// CraftBukkit end +@@ -174,11 +_,13 @@ + import org.slf4j.Logger; -+ public abstract class MinecraftServer extends ReentrantBlockableEventLoop implements ServerInfo, ChunkIOErrorReporter, CommandSource { - + private static MinecraftServer SERVER; // Paper public static final Logger LOGGER = LogUtils.getLogger(); + public static final net.kyori.adventure.text.logger.slf4j.ComponentLogger COMPONENT_LOGGER = net.kyori.adventure.text.logger.slf4j.ComponentLogger.logger(LOGGER.getName()); // Paper @@ -124,15 +51,30 @@ private static final int OVERLOADED_TICKS_THRESHOLD = 20; private static final long OVERLOADED_WARNING_INTERVAL_NANOS = 10L * TimeUtil.NANOSECONDS_PER_SECOND; private static final int OVERLOADED_TICKS_WARNING_INTERVAL = 100; -@@ -224,6 +250,7 @@ - private Map, ServerLevel> levels; +@@ -204,8 +_,8 @@ + @Nullable + private MinecraftServer.TimeProfiler debugCommandProfiler; + private boolean debugCommandProfilerDelayStart; +- private ServerConnectionListener connection; +- public final ChunkProgressListenerFactory progressListenerFactory; ++ private net.minecraft.server.network.ServerConnectionListener connection; ++ public final net.minecraft.server.level.progress.ChunkProgressListenerFactory progressListenerFactory; + @Nullable + private ServerStatus status; + @Nullable +@@ -215,9 +_,10 @@ + private String localIp; + private int port = -1; + private final LayeredRegistryAccess registries; +- private Map, ServerLevel> levels = Maps.newLinkedHashMap(); ++ private Map, net.minecraft.server.level.ServerLevel> levels = Maps.newLinkedHashMap(); private PlayerList playerList; - private volatile boolean running; + private volatile boolean running = true; + private volatile boolean isRestarting = false; // Paper - flag to signify we're attempting to restart private boolean stopped; private int tickCount; - private int ticksUntilAutosave; -@@ -232,11 +259,15 @@ + private int ticksUntilAutosave = 6000; +@@ -226,11 +_,15 @@ private boolean preventProxyConnections; private boolean pvp; private boolean allowFlight; @@ -140,8 +82,8 @@ - private String motd; + private net.kyori.adventure.text.Component motd; // Paper - Adventure private int playerIdleTimeout; - private final long[] tickTimesNanos; - private long aggregatedTickTimesNanos; + private final long[] tickTimesNanos = new long[100]; + private long aggregatedTickTimesNanos = 0L; + // Paper start - Add tick times API and /mspt command + public final TickTimes tickTimes5s = new TickTimes(100); + public final TickTimes tickTimes10s = new TickTimes(200); @@ -150,14 +92,23 @@ @Nullable private KeyPair keyPair; @Nullable -@@ -277,6 +308,28 @@ - private final SuppressedExceptionCollector suppressedExceptions; +@@ -252,7 +_,7 @@ + private final ServerScoreboard scoreboard = new ServerScoreboard(this); + @Nullable + private CommandStorage commandStorage; +- private final CustomBossEvents customBossEvents = new CustomBossEvents(); ++ private final net.minecraft.server.bossevents.CustomBossEvents customBossEvents = new net.minecraft.server.bossevents.CustomBossEvents(); + private final ServerFunctionManager functionManager; + private boolean enforceWhitelist; + private float smoothedTickTimeMillis; +@@ -271,10 +_,33 @@ + private final SuppressedExceptionCollector suppressedExceptions = new SuppressedExceptionCollector(); private final DiscontinuousFrame tickFrame; + // CraftBukkit start + public final WorldLoader.DataLoadContext worldLoader; + public org.bukkit.craftbukkit.CraftServer server; -+ public OptionSet options; ++ public joptsimple.OptionSet options; + public org.bukkit.command.ConsoleCommandSender console; + public static int currentTick; // Paper - improve tick loop + public java.util.Queue processQueue = new java.util.concurrent.ConcurrentLinkedQueue(); @@ -176,79 +127,51 @@ + public boolean isIteratingOverLevels = false; // Paper - Throw exception on world create while being ticked + private final Set pluginsBlockingSleep = new java.util.HashSet<>(); // Paper - API to allow/disallow tick sleeping + - public static S spin(Function serverFactory) { - AtomicReference atomicreference = new AtomicReference(); - Thread thread = new Thread(() -> { -@@ -286,19 +339,21 @@ - thread.setUncaughtExceptionHandler((thread1, throwable) -> { - MinecraftServer.LOGGER.error("Uncaught exception in server thread", throwable); - }); + public static S spin(Function threadFunction) { + AtomicReference atomicReference = new AtomicReference<>(); + Thread thread = new Thread(() -> atomicReference.get().runServer(), "Server thread"); + thread.setUncaughtExceptionHandler((thread1, exception) -> LOGGER.error("Uncaught exception in server thread", exception)); + thread.setPriority(Thread.NORM_PRIORITY+2); // Paper - Perf: Boost priority if (Runtime.getRuntime().availableProcessors() > 4) { thread.setPriority(8); } - -- S s0 = (MinecraftServer) serverFactory.apply(thread); -+ S s0 = serverFactory.apply(thread); // CraftBukkit - decompile error - - atomicreference.set(s0); - thread.start(); - return s0; +@@ -286,6 +_,10 @@ } -- public MinecraftServer(Thread serverThread, LevelStorageSource.LevelStorageAccess session, PackRepository dataPackManager, WorldStem saveLoader, Proxy proxy, DataFixer dataFixer, Services apiServices, ChunkProgressListenerFactory worldGenerationProgressListenerFactory) { -+ public MinecraftServer(OptionSet options, WorldLoader.DataLoadContext worldLoader, Thread thread, LevelStorageSource.LevelStorageAccess convertable_conversionsession, PackRepository resourcepackrepository, WorldStem worldstem, Proxy proxy, DataFixer datafixer, Services services, ChunkProgressListenerFactory worldloadlistenerfactory) { + public MinecraftServer( ++ // CraftBukkit start ++ joptsimple.OptionSet options, ++ WorldLoader.DataLoadContext worldLoader, ++ // CraftBukkit end + Thread serverThread, + LevelStorageSource.LevelStorageAccess storageSource, + PackRepository packRepository, +@@ -293,12 +_,13 @@ + Proxy proxy, + DataFixer fixerUpper, + Services services, +- ChunkProgressListenerFactory progressListenerFactory ++ net.minecraft.server.level.progress.ChunkProgressListenerFactory progressListenerFactory + ) { super("Server"); + SERVER = this; // Paper - better singleton - this.metricsRecorder = InactiveMetricsRecorder.INSTANCE; - this.onMetricsRecordingStopped = (methodprofilerresults) -> { - this.stopRecordingMetrics(); -@@ -319,36 +374,67 @@ - this.scoreboard = new ServerScoreboard(this); - this.customBossEvents = new CustomBossEvents(); - this.suppressedExceptions = new SuppressedExceptionCollector(); -- this.registries = saveLoader.registries(); -- this.worldData = saveLoader.worldData(); + this.registries = worldStem.registries(); + this.worldData = worldStem.worldData(); - if (!this.registries.compositeAccess().lookupOrThrow(Registries.LEVEL_STEM).containsKey(LevelStem.OVERWORLD)) { -+ this.registries = worldstem.registries(); -+ this.worldData = worldstem.worldData(); + if (false && !this.registries.compositeAccess().lookupOrThrow(Registries.LEVEL_STEM).containsKey(LevelStem.OVERWORLD)) { // CraftBukkit - initialised later throw new IllegalStateException("Missing Overworld dimension data"); } else { this.proxy = proxy; -- this.packRepository = dataPackManager; -- this.resources = new MinecraftServer.ReloadableResources(saveLoader.resourceManager(), saveLoader.dataPackResources()); -- this.services = apiServices; -- if (apiServices.profileCache() != null) { -- apiServices.profileCache().setExecutor(this); -+ this.packRepository = resourcepackrepository; -+ this.resources = new MinecraftServer.ReloadableResources(worldstem.resourceManager(), worldstem.dataPackResources()); -+ this.services = services; -+ if (services.profileCache() != null) { -+ services.profileCache().setExecutor(this); +@@ -309,7 +_,7 @@ + services.profileCache().setExecutor(this); } - this.connection = new ServerConnectionListener(this); -+ // this.connection = new ServerConnection(this); // Spigot ++ // this.connection = new ServerConnectionListener(this); // Spigot this.tickRateManager = new ServerTickRateManager(this); -- this.progressListenerFactory = worldGenerationProgressListenerFactory; -- this.storageSource = session; -- this.playerDataStorage = session.createPlayerStorage(); -- this.fixerUpper = dataFixer; -+ this.progressListenerFactory = worldloadlistenerfactory; -+ this.storageSource = convertable_conversionsession; -+ this.playerDataStorage = convertable_conversionsession.createPlayerStorage(); -+ this.fixerUpper = datafixer; - this.functionManager = new ServerFunctionManager(this, this.resources.managers.getFunctionLibrary()); - HolderGetter holdergetter = this.registries.compositeAccess().lookupOrThrow(Registries.BLOCK).filterFeatures(this.worldData.enabledFeatures()); - -- this.structureTemplateManager = new StructureTemplateManager(saveLoader.resourceManager(), session, dataFixer, holdergetter); -- this.serverThread = serverThread; -+ this.structureTemplateManager = new StructureTemplateManager(worldstem.resourceManager(), convertable_conversionsession, datafixer, holdergetter); -+ this.serverThread = thread; - this.executor = Util.backgroundExecutor(); - this.potionBrewing = PotionBrewing.bootstrap(this.worldData.enabledFeatures()); - this.resources.managers.getRecipeManager().finalizeRecipeLoading(this.worldData.enabledFeatures()); + this.progressListenerFactory = progressListenerFactory; + this.storageSource = storageSource; +@@ -328,6 +_,37 @@ this.fuelValues = FuelValues.vanillaBurnTimes(this.registries.compositeAccess(), this.worldData.enabledFeatures()); this.tickFrame = TracyClient.createDiscontinuousFrame("Server Tick"); } @@ -285,58 +208,59 @@ + this.paperConfigurations = services.paperConfigurations(); // Paper - add paper configuration files } - private void readScoreboard(DimensionDataStorage persistentStateManager) { -@@ -357,7 +443,7 @@ + private void readScoreboard(DimensionDataStorage dataStorage) { +@@ -336,18 +_,13 @@ protected abstract boolean initServer() throws IOException; - protected void loadLevel() { + protected void loadLevel(String s) { // CraftBukkit if (!JvmProfiler.INSTANCE.isRunning()) { - ; } -@@ -365,12 +451,8 @@ + boolean flag = false; - ProfiledDuration profiledduration = JvmProfiler.INSTANCE.onWorldLoadedStarted(); - + ProfiledDuration profiledDuration = JvmProfiler.INSTANCE.onWorldLoadedStarted(); - this.worldData.setModdedInfo(this.getServerModName(), this.getModdedStatus().shouldReportAsModified()); -- ChunkProgressListener worldloadlistener = this.progressListenerFactory.create(this.worldData.getGameRules().getInt(GameRules.RULE_SPAWN_CHUNK_RADIUS)); -+ this.loadWorld0(s); // CraftBukkit - -- this.createLevels(worldloadlistener); +- ChunkProgressListener chunkProgressListener = this.progressListenerFactory +- .create(this.worldData.getGameRules().getInt(GameRules.RULE_SPAWN_CHUNK_RADIUS)); +- this.createLevels(chunkProgressListener); - this.forceDifficulty(); -- this.prepareLevels(worldloadlistener); - if (profiledduration != null) { - profiledduration.finish(true); +- this.prepareLevels(chunkProgressListener); ++ this.loadWorld0(s); // CraftBukkit + if (profiledDuration != null) { + profiledDuration.finish(true); } -@@ -387,23 +469,246 @@ +@@ -364,25 +_,245 @@ + protected void forceDifficulty() { + } - protected void forceDifficulty() {} - -- protected void createLevels(ChunkProgressListener worldGenerationProgressListener) { -- ServerLevelData iworlddataserver = this.worldData.overworldData(); -- boolean flag = this.worldData.isDebugWorld(); -- Registry iregistry = this.registries.compositeAccess().lookupOrThrow(Registries.LEVEL_STEM); -- WorldOptions worldoptions = this.worldData.worldGenOptions(); -- long i = worldoptions.seed(); -- long j = BiomeManager.obfuscateSeed(i); -- List list = ImmutableList.of(new PhantomSpawner(), new PatrolSpawner(), new CatSpawner(), new VillageSiege(), new WanderingTraderSpawner(iworlddataserver)); -- LevelStem worlddimension = (LevelStem) iregistry.getValue(LevelStem.OVERWORLD); -- ServerLevel worldserver = new ServerLevel(this, this.executor, this.storageSource, iworlddataserver, Level.OVERWORLD, worlddimension, worldGenerationProgressListener, flag, j, list, true, (RandomSequences) null); +- protected void createLevels(ChunkProgressListener listener) { +- ServerLevelData serverLevelData = this.worldData.overworldData(); +- boolean isDebugWorld = this.worldData.isDebugWorld(); +- Registry registry = this.registries.compositeAccess().lookupOrThrow(Registries.LEVEL_STEM); +- WorldOptions worldOptions = this.worldData.worldGenOptions(); +- long seed = worldOptions.seed(); +- long l = BiomeManager.obfuscateSeed(seed); +- List list = ImmutableList.of( +- new PhantomSpawner(), new PatrolSpawner(), new CatSpawner(), new VillageSiege(), new WanderingTraderSpawner(serverLevelData) +- ); +- LevelStem levelStem = registry.getValue(LevelStem.OVERWORLD); +- ServerLevel serverLevel = new ServerLevel( +- this, this.executor, this.storageSource, serverLevelData, Level.OVERWORLD, levelStem, listener, isDebugWorld, l, list, true, null +- ); +- this.levels.put(Level.OVERWORLD, serverLevel); +- DimensionDataStorage dataStorage = serverLevel.getDataStorage(); +- this.readScoreboard(dataStorage); +- this.commandStorage = new CommandStorage(dataStorage); +- WorldBorder worldBorder = serverLevel.getWorldBorder(); + // CraftBukkit start + private void loadWorld0(String s) { + LevelStorageSource.LevelStorageAccess worldSession = this.storageSource; - -- this.levels.put(Level.OVERWORLD, worldserver); -- DimensionDataStorage worldpersistentdata = worldserver.getDataStorage(); + RegistryAccess.Frozen iregistrycustom_dimension = this.registries.compositeAccess(); + Registry dimensions = iregistrycustom_dimension.lookupOrThrow(Registries.LEVEL_STEM); + for (LevelStem worldDimension : dimensions) { + ResourceKey dimensionKey = dimensions.getResourceKey(worldDimension).get(); - -- this.readScoreboard(worldpersistentdata); -- this.commandStorage = new CommandStorage(worldpersistentdata); -+ ServerLevel world; ++ net.minecraft.server.level.ServerLevel world; + int dimension = 0; + + if (dimensionKey == LevelStem.NETHER) { @@ -358,9 +282,9 @@ + String worldType = (dimension == -999) ? dimensionKey.location().getNamespace() + "_" + dimensionKey.location().getPath() : org.bukkit.World.Environment.getEnvironment(dimension).toString().toLowerCase(Locale.ROOT); + String name = (dimensionKey == LevelStem.OVERWORLD) ? s : s + "_" + worldType; + if (dimension != 0) { -+ File newWorld = LevelStorageSource.getStorageFolder(new File(name).toPath(), dimensionKey).toFile(); -+ File oldWorld = LevelStorageSource.getStorageFolder(new File(s).toPath(), dimensionKey).toFile(); -+ File oldLevelDat = new File(new File(s), "level.dat"); // The data folders exist on first run as they are created in the PersistentCollection constructor above, but the level.dat won't ++ java.io.File newWorld = LevelStorageSource.getStorageFolder(new java.io.File(name).toPath(), dimensionKey).toFile(); ++ java.io.File oldWorld = LevelStorageSource.getStorageFolder(new java.io.File(s).toPath(), dimensionKey).toFile(); ++ java.io.File oldLevelDat = new java.io.File(new java.io.File(s), "level.dat"); // The data folders exist on first run as they are created in the PersistentCollection constructor above, but the level.dat won't + + if (!newWorld.isDirectory() && oldWorld.isDirectory() && oldLevelDat.isFile()) { + MinecraftServer.LOGGER.info("---- Migration of old " + worldType + " folder required ----"); @@ -376,8 +300,8 @@ + MinecraftServer.LOGGER.info("Success! To restore " + worldType + " in the future, simply move " + newWorld + " to " + oldWorld); + // Migrate world data too. + try { -+ com.google.common.io.Files.copy(oldLevelDat, new File(new File(name), "level.dat")); -+ org.apache.commons.io.FileUtils.copyDirectory(new File(new File(s), "data"), new File(new File(name), "data")); ++ com.google.common.io.Files.copy(oldLevelDat, new java.io.File(new java.io.File(name), "level.dat")); ++ org.apache.commons.io.FileUtils.copyDirectory(new java.io.File(new java.io.File(s), "data"), new java.io.File(new java.io.File(name), "data")); + } catch (IOException exception) { + MinecraftServer.LOGGER.warn("Unable to migrate world data."); + } @@ -394,19 +318,19 @@ + + try { + worldSession = LevelStorageSource.createDefault(this.server.getWorldContainer().toPath()).validateAndCreateAccess(name, dimensionKey); -+ } catch (IOException | ContentValidationException ex) { ++ } catch (IOException | net.minecraft.world.level.validation.ContentValidationException ex) { + throw new RuntimeException(ex); + } + } + -+ Dynamic dynamic; ++ com.mojang.serialization.Dynamic dynamic; + if (worldSession.hasWorldData()) { -+ LevelSummary worldinfo; ++ net.minecraft.world.level.storage.LevelSummary worldinfo; + + try { + dynamic = worldSession.getDataTag(); + worldinfo = worldSession.getSummary(dynamic); -+ } catch (NbtException | ReportedNbtException | IOException ioexception) { ++ } catch (net.minecraft.nbt.NbtException | net.minecraft.nbt.ReportedNbtException | IOException ioexception) { + LevelStorageSource.LevelDirectory convertable_b = worldSession.getLevelDirectory(); + + MinecraftServer.LOGGER.warn("Failed to load world data from {}", convertable_b.dataFile(), ioexception); @@ -415,7 +339,7 @@ + try { + dynamic = worldSession.getDataTagFallback(); + worldinfo = worldSession.getSummary(dynamic); -+ } catch (NbtException | ReportedNbtException | IOException ioexception1) { ++ } catch (net.minecraft.nbt.NbtException | net.minecraft.nbt.ReportedNbtException | IOException ioexception1) { + MinecraftServer.LOGGER.error("Failed to load world data from {}", convertable_b.oldDataFile(), ioexception1); + MinecraftServer.LOGGER.error("Failed to load world data from {} and {}. World files may be corrupted. Shutting down.", convertable_b.dataFile(), convertable_b.oldDataFile()); + return; @@ -440,34 +364,34 @@ + org.bukkit.generator.ChunkGenerator gen = this.server.getGenerator(name); + org.bukkit.generator.BiomeProvider biomeProvider = this.server.getBiomeProvider(name); + -+ PrimaryLevelData worlddata; ++ net.minecraft.world.level.storage.PrimaryLevelData worlddata; + WorldLoader.DataLoadContext worldloader_a = this.worldLoader; + Registry iregistry = worldloader_a.datapackDimensions().lookupOrThrow(Registries.LEVEL_STEM); + if (dynamic != null) { -+ LevelDataAndDimensions leveldataanddimensions = LevelStorageSource.getLevelDataAndDimensions(dynamic, worldloader_a.dataConfiguration(), iregistry, worldloader_a.datapackWorldgen()); ++ net.minecraft.world.level.storage.LevelDataAndDimensions leveldataanddimensions = LevelStorageSource.getLevelDataAndDimensions(dynamic, worldloader_a.dataConfiguration(), iregistry, worldloader_a.datapackWorldgen()); + -+ worlddata = (PrimaryLevelData) leveldataanddimensions.worldData(); ++ worlddata = (net.minecraft.world.level.storage.PrimaryLevelData) leveldataanddimensions.worldData(); + } else { + LevelSettings worldsettings; + WorldOptions worldoptions; -+ WorldDimensions worlddimensions; ++ net.minecraft.world.level.levelgen.WorldDimensions worlddimensions; + + if (this.isDemo()) { + worldsettings = MinecraftServer.DEMO_SETTINGS; + worldoptions = WorldOptions.DEMO_OPTIONS; -+ worlddimensions = WorldPresets.createNormalWorldDimensions(worldloader_a.datapackWorldgen()); ++ worlddimensions = net.minecraft.world.level.levelgen.presets.WorldPresets.createNormalWorldDimensions(worldloader_a.datapackWorldgen()); + } else { -+ DedicatedServerProperties dedicatedserverproperties = ((DedicatedServer) this).getProperties(); ++ net.minecraft.server.dedicated.DedicatedServerProperties dedicatedserverproperties = ((net.minecraft.server.dedicated.DedicatedServer) this).getProperties(); + + worldsettings = new LevelSettings(dedicatedserverproperties.levelName, dedicatedserverproperties.gamemode, dedicatedserverproperties.hardcore, dedicatedserverproperties.difficulty, false, new GameRules(worldloader_a.dataConfiguration().enabledFeatures()), worldloader_a.dataConfiguration()); + worldoptions = this.options.has("bonusChest") ? dedicatedserverproperties.worldOptions.withBonusChest(true) : dedicatedserverproperties.worldOptions; + worlddimensions = dedicatedserverproperties.createDimensions(worldloader_a.datapackWorldgen()); + } + -+ WorldDimensions.Complete worlddimensions_b = worlddimensions.bake(iregistry); -+ Lifecycle lifecycle = worlddimensions_b.lifecycle().add(worldloader_a.datapackWorldgen().allRegistriesLifecycle()); ++ net.minecraft.world.level.levelgen.WorldDimensions.Complete worlddimensions_b = worlddimensions.bake(iregistry); ++ com.mojang.serialization.Lifecycle lifecycle = worlddimensions_b.lifecycle().add(worldloader_a.datapackWorldgen().allRegistriesLifecycle()); + -+ worlddata = new PrimaryLevelData(worldsettings, worldoptions, worlddimensions_b.specialWorldProperty(), lifecycle); ++ worlddata = new net.minecraft.world.level.storage.PrimaryLevelData(worldsettings, worldoptions, worlddimensions_b.specialWorldProperty(), lifecycle); + } + worlddata.checkName(name); // CraftBukkit - Migration did not rewrite the level.dat; This forces 1.8 to take the last loaded world as respawn (in this case the end) + if (this.options.has("forceUpgrade")) { @@ -476,7 +400,7 @@ + }, iregistrycustom_dimension, this.options.has("recreateRegionFiles")); + } + -+ PrimaryLevelData iworlddataserver = worlddata; ++ net.minecraft.world.level.storage.PrimaryLevelData iworlddataserver = worlddata; + boolean flag = worlddata.isDebugWorld(); + WorldOptions worldoptions = worlddata.worldGenOptions(); + long i = worldoptions.seed(); @@ -493,17 +417,17 @@ + + if (dimensionKey == LevelStem.OVERWORLD) { + this.worldData = worlddata; -+ this.worldData.setGameType(((DedicatedServer) this).getProperties().gamemode); // From DedicatedServer.init ++ this.worldData.setGameType(((net.minecraft.server.dedicated.DedicatedServer) this).getProperties().gamemode); // From DedicatedServer.init + -+ ChunkProgressListener worldloadlistener = this.progressListenerFactory.create(this.worldData.getGameRules().getInt(GameRules.RULE_SPAWN_CHUNK_RADIUS)); ++ net.minecraft.server.level.progress.ChunkProgressListener worldloadlistener = this.progressListenerFactory.create(this.worldData.getGameRules().getInt(GameRules.RULE_SPAWN_CHUNK_RADIUS)); + -+ world = new ServerLevel(this, this.executor, worldSession, iworlddataserver, worldKey, worlddimension, worldloadlistener, flag, j, list, true, (RandomSequences) null, org.bukkit.World.Environment.getEnvironment(dimension), gen, biomeProvider); ++ world = new net.minecraft.server.level.ServerLevel(this, this.executor, worldSession, iworlddataserver, worldKey, worlddimension, worldloadlistener, flag, j, list, true, (RandomSequences) null, org.bukkit.World.Environment.getEnvironment(dimension), gen, biomeProvider); + DimensionDataStorage worldpersistentdata = world.getDataStorage(); + this.readScoreboard(worldpersistentdata); + this.server.scoreboardManager = new org.bukkit.craftbukkit.scoreboard.CraftScoreboardManager(this, world.getScoreboard()); + this.commandStorage = new CommandStorage(worldpersistentdata); + } else { -+ ChunkProgressListener worldloadlistener = this.progressListenerFactory.create(this.worldData.getGameRules().getInt(GameRules.RULE_SPAWN_CHUNK_RADIUS)); ++ net.minecraft.server.level.progress.ChunkProgressListener worldloadlistener = this.progressListenerFactory.create(this.worldData.getGameRules().getInt(GameRules.RULE_SPAWN_CHUNK_RADIUS)); + // Paper start - option to use the dimension_type to check if spawners should be added. I imagine mojang will add some datapack-y way of managing this in the future. + final List spawners; + if (io.papermc.paper.configuration.GlobalConfiguration.get().misc.useDimensionTypeForCustomSpawners && this.registryAccess().lookupOrThrow(Registries.DIMENSION_TYPE).getResourceKey(worlddimension.type().value()).orElseThrow() == net.minecraft.world.level.dimension.BuiltinDimensionTypes.OVERWORLD) { @@ -511,7 +435,7 @@ + } else { + spawners = Collections.emptyList(); + } -+ world = new ServerLevel(this, this.executor, worldSession, iworlddataserver, worldKey, worlddimension, worldloadlistener, flag, j, spawners, true, this.overworld().getRandomSequences(), org.bukkit.World.Environment.getEnvironment(dimension), gen, biomeProvider); ++ world = new net.minecraft.server.level.ServerLevel(this, this.executor, worldSession, iworlddataserver, worldKey, worlddimension, worldloadlistener, flag, j, spawners, true, this.overworld().getRandomSequences(), org.bukkit.World.Environment.getEnvironment(dimension), gen, biomeProvider); + // Paper end - option to use the dimension_type to check if spawners should be added + } + @@ -527,10 +451,10 @@ + } + } + this.forceDifficulty(); -+ for (ServerLevel worldserver : this.getAllLevels()) { -+ this.prepareLevels(worldserver.getChunkSource().chunkMap.progressListener, worldserver); -+ 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())); ++ for (net.minecraft.server.level.ServerLevel serverLevel : this.getAllLevels()) { ++ this.prepareLevels(serverLevel.getChunkSource().chunkMap.progressListener, serverLevel); ++ serverLevel.entityManager.tick(); // SPIGOT-6526: Load pending entities so they are available to the API ++ this.server.getPluginManager().callEvent(new org.bukkit.event.world.WorldLoadEvent(serverLevel.getWorld())); + } + + // Paper start - Configurable player collision; Handle collideRule team for player collision toggle @@ -554,168 +478,190 @@ + io.papermc.paper.command.brigadier.PaperCommands.INSTANCE.setValid(); // Paper - reset invalid state for event fire below + io.papermc.paper.plugin.lifecycle.event.LifecycleEventRunner.INSTANCE.callReloadableRegistrarEvent(io.papermc.paper.plugin.lifecycle.event.types.LifecycleEvents.COMMANDS, io.papermc.paper.command.brigadier.PaperCommands.INSTANCE, org.bukkit.plugin.Plugin.class, io.papermc.paper.plugin.lifecycle.event.registrar.ReloadableRegistrarEvent.Cause.INITIAL); // Paper - call commands event for regular plugins + ((org.bukkit.craftbukkit.help.SimpleHelpMap) this.server.getHelpMap()).initializeCommands(); -+ this.server.getPluginManager().callEvent(new ServerLoadEvent(ServerLoadEvent.LoadType.STARTUP)); ++ this.server.getPluginManager().callEvent(new org.bukkit.event.server.ServerLoadEvent(org.bukkit.event.server.ServerLoadEvent.LoadType.STARTUP)); + this.connection.acceptConnections(); + } + -+ public void initWorld(ServerLevel worldserver, ServerLevelData iworlddataserver, WorldData saveData, WorldOptions worldoptions) { -+ boolean flag = saveData.isDebugWorld(); -+ // CraftBukkit start -+ if (worldserver.generator != null) { -+ worldserver.getWorld().getPopulators().addAll(worldserver.generator.getDefaultPopulators(worldserver.getWorld())); ++ public void initWorld(net.minecraft.server.level.ServerLevel serverLevel, ServerLevelData serverLevelData, WorldData saveData, WorldOptions worldOptions) { ++ boolean isDebugWorld = saveData.isDebugWorld(); ++ if (serverLevel.generator != null) { ++ serverLevel.getWorld().getPopulators().addAll(serverLevel.generator.getDefaultPopulators(serverLevel.getWorld())); + } - WorldBorder worldborder = worldserver.getWorldBorder(); -+ worldborder.applySettings(iworlddataserver.getWorldBorder()); // CraftBukkit - move up so that WorldBorder is set during WorldInitEvent -+ this.server.getPluginManager().callEvent(new org.bukkit.event.world.WorldInitEvent(worldserver.getWorld())); // CraftBukkit - SPIGOT-5569: Call WorldInitEvent before any chunks are generated - - if (!iworlddataserver.isInitialized()) { ++ // CraftBukkit start ++ WorldBorder worldborder = serverLevel.getWorldBorder(); ++ worldborder.applySettings(serverLevelData.getWorldBorder()); // CraftBukkit - move up so that WorldBorder is set during WorldInitEvent ++ this.server.getPluginManager().callEvent(new org.bukkit.event.world.WorldInitEvent(serverLevel.getWorld())); // CraftBukkit - SPIGOT-5569: Call WorldInitEvent before any chunks are generated ++ + if (!serverLevelData.isInitialized()) { try { -@@ -427,37 +732,31 @@ - iworlddataserver.setInitialized(true); - } + setInitialSpawn(serverLevel, serverLevelData, worldOptions.generateBonusChest(), isDebugWorld); +@@ -403,47 +_,30 @@ -- this.getPlayerList().addWorldborderListener(worldserver); + serverLevelData.setInitialized(true); + } +- +- this.getPlayerList().addWorldborderListener(serverLevel); - if (this.worldData.getCustomBossEvents() != null) { - this.getCustomBossEvents().load(this.worldData.getCustomBossEvents(), this.registryAccess()); - } - -- RandomSequences randomsequences = worldserver.getRandomSequences(); -- Iterator iterator = iregistry.entrySet().iterator(); +- RandomSequences randomSequences = serverLevel.getRandomSequences(); - -- while (iterator.hasNext()) { -- Entry, LevelStem> entry = (Entry) iterator.next(); -- ResourceKey resourcekey = (ResourceKey) entry.getKey(); -- -- if (resourcekey != LevelStem.OVERWORLD) { -- ResourceKey resourcekey1 = ResourceKey.create(Registries.DIMENSION, resourcekey.location()); -- DerivedLevelData secondaryworlddata = new DerivedLevelData(this.worldData, iworlddataserver); -- ServerLevel worldserver1 = new ServerLevel(this, this.executor, this.storageSource, secondaryworlddata, resourcekey1, (LevelStem) entry.getValue(), worldGenerationProgressListener, flag, j, ImmutableList.of(), false, randomsequences); -- -- worldborder.addListener(new BorderChangeListener.DelegateBorderChangeListener(worldserver1.getWorldBorder())); -- this.levels.put(resourcekey1, worldserver1); +- for (Entry, LevelStem> entry : registry.entrySet()) { +- ResourceKey resourceKey = entry.getKey(); +- if (resourceKey != LevelStem.OVERWORLD) { +- ResourceKey resourceKey1 = ResourceKey.create(Registries.DIMENSION, resourceKey.location()); +- DerivedLevelData derivedLevelData = new DerivedLevelData(this.worldData, serverLevelData); +- ServerLevel serverLevel1 = new ServerLevel( +- this, +- this.executor, +- this.storageSource, +- derivedLevelData, +- resourceKey1, +- entry.getValue(), +- listener, +- isDebugWorld, +- l, +- ImmutableList.of(), +- false, +- randomSequences +- ); +- worldBorder.addListener(new BorderChangeListener.DelegateBorderChangeListener(serverLevel1.getWorldBorder())); +- this.levels.put(resourceKey1, serverLevel1); - } - } - -- worldborder.applySettings(iworlddataserver.getWorldBorder()); +- worldBorder.applySettings(serverLevelData.getWorldBorder()); } + // CraftBukkit end - private static void setInitialSpawn(ServerLevel world, ServerLevelData worldProperties, boolean bonusChest, boolean debugWorld) { - if (debugWorld) { - worldProperties.setSpawn(BlockPos.ZERO.above(80), 0.0F); +- private static void setInitialSpawn(ServerLevel level, ServerLevelData levelData, boolean generateBonusChest, boolean debug) { ++ private static void setInitialSpawn(net.minecraft.server.level.ServerLevel level, ServerLevelData levelData, boolean generateBonusChest, boolean debug) { + if (debug) { + levelData.setSpawn(BlockPos.ZERO.above(80), 0.0F); } else { - ServerChunkCache chunkproviderserver = world.getChunkSource(); -- ChunkPos chunkcoordintpair = new ChunkPos(chunkproviderserver.randomState().sampler().findSpawnPosition()); -+ // ChunkPos chunkcoordintpair = new ChunkPos(chunkproviderserver.randomState().sampler().findSpawnPosition()); // Paper - Move down, only attempt to find spawn position if there isn't a fixed spawn position set +- ServerChunkCache chunkSource = level.getChunkSource(); +- ChunkPos chunkPos = new ChunkPos(chunkSource.randomState().sampler().findSpawnPosition()); ++ net.minecraft.server.level.ServerChunkCache chunkSource = level.getChunkSource(); + // CraftBukkit start -+ if (world.generator != null) { -+ Random rand = new Random(world.getSeed()); -+ org.bukkit.Location spawn = world.generator.getFixedSpawnLocation(world.getWorld(), rand); ++ if (level.generator != null) { ++ java.util.Random rand = new java.util.Random(level.getSeed()); ++ org.bukkit.Location spawn = level.generator.getFixedSpawnLocation(level.getWorld(), rand); + + if (spawn != null) { -+ if (spawn.getWorld() != world.getWorld()) { -+ throw new IllegalStateException("Cannot set spawn point for " + worldProperties.getLevelName() + " to be in another world (" + spawn.getWorld().getName() + ")"); ++ if (spawn.getWorld() != level.getWorld()) { ++ throw new IllegalStateException("Cannot set spawn point for " + levelData.getLevelName() + " to be in another world (" + spawn.getWorld().getName() + ")"); + } else { -+ worldProperties.setSpawn(new BlockPos(spawn.getBlockX(), spawn.getBlockY(), spawn.getBlockZ()), spawn.getYaw()); ++ levelData.setSpawn(new BlockPos(spawn.getBlockX(), spawn.getBlockY(), spawn.getBlockZ()), spawn.getYaw()); + return; + } + } + } + // CraftBukkit end -+ ChunkPos chunkcoordintpair = new ChunkPos(chunkproviderserver.randomState().sampler().findSpawnPosition()); // Paper - Only attempt to find spawn position if there isn't a fixed spawn position set - int i = chunkproviderserver.getGenerator().getSpawnHeight(world); ++ ChunkPos chunkPos = new ChunkPos(chunkSource.randomState().sampler().findSpawnPosition()); // Paper - Only attempt to find spawn position if there isn't a fixed spawn position set + int spawnHeight = chunkSource.getGenerator().getSpawnHeight(level); + if (spawnHeight < level.getMinY()) { + BlockPos worldPosition = chunkPos.getWorldPosition(); +@@ -458,7 +_,7 @@ - if (i < world.getMinY()) { -@@ -516,31 +815,36 @@ - iworlddataserver.setGameType(GameType.SPECTATOR); + for (int i4 = 0; i4 < Mth.square(11); i4++) { + if (i >= -5 && i <= 5 && i1 >= -5 && i1 <= 5) { +- BlockPos spawnPosInChunk = PlayerRespawnLogic.getSpawnPosInChunk(level, new ChunkPos(chunkPos.x + i, chunkPos.z + i1)); ++ BlockPos spawnPosInChunk = net.minecraft.server.level.PlayerRespawnLogic.getSpawnPosInChunk(level, new ChunkPos(chunkPos.x + i, chunkPos.z + i1)); + if (spawnPosInChunk != null) { + levelData.setSpawn(spawnPosInChunk, 0.0F); + break; +@@ -495,26 +_,31 @@ + serverLevelData.setGameType(GameType.SPECTATOR); } -- public void prepareLevels(ChunkProgressListener worldGenerationProgressListener) { -- ServerLevel worldserver = this.overworld(); +- public void prepareLevels(ChunkProgressListener listener) { +- ServerLevel serverLevel = this.overworld(); + // CraftBukkit start -+ public void prepareLevels(ChunkProgressListener worldloadlistener, ServerLevel worldserver) { -+ // WorldServer worldserver = this.overworld(); ++ public void prepareLevels(net.minecraft.server.level.progress.ChunkProgressListener listener, net.minecraft.server.level.ServerLevel serverLevel) { + this.forceTicks = true; + // CraftBukkit end - - MinecraftServer.LOGGER.info("Preparing start region for dimension {}", worldserver.dimension().location()); - BlockPos blockposition = worldserver.getSharedSpawnPos(); - -- worldGenerationProgressListener.updateSpawnPos(new ChunkPos(blockposition)); -+ worldloadlistener.updateSpawnPos(new ChunkPos(blockposition)); - ServerChunkCache chunkproviderserver = worldserver.getChunkSource(); - + LOGGER.info("Preparing start region for dimension {}", serverLevel.dimension().location()); + BlockPos sharedSpawnPos = serverLevel.getSharedSpawnPos(); + listener.updateSpawnPos(new ChunkPos(sharedSpawnPos)); +- ServerChunkCache chunkSource = serverLevel.getChunkSource(); ++ net.minecraft.server.level.ServerChunkCache chunkSource = serverLevel.getChunkSource(); this.nextTickTimeNanos = Util.getNanos(); - worldserver.setDefaultSpawnPos(blockposition, worldserver.getSharedSpawnAngle()); -- int i = this.getGameRules().getInt(GameRules.RULE_SPAWN_CHUNK_RADIUS); -+ int i = worldserver.getGameRules().getInt(GameRules.RULE_SPAWN_CHUNK_RADIUS); // CraftBukkit - per-world - int j = i > 0 ? Mth.square(ChunkProgressListener.calculateDiameter(i)) : 0; + serverLevel.setDefaultSpawnPos(sharedSpawnPos, serverLevel.getSharedSpawnAngle()); +- int _int = this.getGameRules().getInt(GameRules.RULE_SPAWN_CHUNK_RADIUS); +- int i = _int > 0 ? Mth.square(ChunkProgressListener.calculateDiameter(_int)) : 0; ++ int _int = serverLevel.getGameRules().getInt(GameRules.RULE_SPAWN_CHUNK_RADIUS); // CraftBukkit - per-world ++ int i = _int > 0 ? Mth.square(net.minecraft.server.level.progress.ChunkProgressListener.calculateDiameter(_int)) : 0; - while (chunkproviderserver.getTickingGenerated() < j) { -- this.nextTickTimeNanos = Util.getNanos() + MinecraftServer.PREPARE_LEVELS_DEFAULT_DELAY_NANOS; + while (chunkSource.getTickingGenerated() < i) { +- this.nextTickTimeNanos = Util.getNanos() + PREPARE_LEVELS_DEFAULT_DELAY_NANOS; - this.waitUntilNextTick(); + // CraftBukkit start -+ // this.nextTickTimeNanos = SystemUtils.getNanos() + MinecraftServer.PREPARE_LEVELS_DEFAULT_DELAY_NANOS; ++ // this.nextTickTimeNanos = Util.getNanos() + PREPARE_LEVELS_DEFAULT_DELAY_NANOS; + this.executeModerately(); } -- this.nextTickTimeNanos = Util.getNanos() + MinecraftServer.PREPARE_LEVELS_DEFAULT_DELAY_NANOS; +- this.nextTickTimeNanos = Util.getNanos() + PREPARE_LEVELS_DEFAULT_DELAY_NANOS; - this.waitUntilNextTick(); -- Iterator iterator = this.levels.values().iterator(); -+ // this.nextTickTimeNanos = SystemUtils.getNanos() + MinecraftServer.PREPARE_LEVELS_DEFAULT_DELAY_NANOS; ++ // this.nextTickTimeNanos = Util.getNanos() + PREPARE_LEVELS_DEFAULT_DELAY_NANOS; + this.executeModerately(); -+ // Iterator iterator = this.levels.values().iterator(); -- while (iterator.hasNext()) { -- ServerLevel worldserver1 = (ServerLevel) iterator.next(); +- for (ServerLevel serverLevel1 : this.levels.values()) { + if (true) { -+ ServerLevel worldserver1 = worldserver; ++ net.minecraft.server.level.ServerLevel serverLevel1 = serverLevel; + // CraftBukkit end - ForcedChunksSavedData forcedchunk = (ForcedChunksSavedData) worldserver1.getDataStorage().get(ForcedChunksSavedData.factory(), "chunks"); - - if (forcedchunk != null) { -@@ -555,10 +859,17 @@ + ForcedChunksSavedData forcedChunksSavedData = serverLevel1.getDataStorage().get(ForcedChunksSavedData.factory(), "chunks"); + if (forcedChunksSavedData != null) { + LongIterator longIterator = forcedChunksSavedData.getChunks().iterator(); +@@ -527,10 +_,17 @@ } } -- this.nextTickTimeNanos = Util.getNanos() + MinecraftServer.PREPARE_LEVELS_DEFAULT_DELAY_NANOS; +- this.nextTickTimeNanos = Util.getNanos() + PREPARE_LEVELS_DEFAULT_DELAY_NANOS; - this.waitUntilNextTick(); -- worldGenerationProgressListener.stop(); -- this.updateMobSpawningFlags(); + // CraftBukkit start + // this.nextTickTimeNanos = SystemUtils.getNanos() + MinecraftServer.PREPARE_LEVELS_DEFAULT_DELAY_NANOS; + this.executeModerately(); + // CraftBukkit end -+ worldloadlistener.stop(); + listener.stop(); +- this.updateMobSpawningFlags(); + // CraftBukkit start + // this.updateMobSpawningFlags(); -+ worldserver.setSpawnSettings(worldserver.serverLevelData.getDifficulty() != Difficulty.PEACEFUL && ((DedicatedServer) this).settings.getProperties().spawnMonsters); // Paper - per level difficulty (from setDifficulty(ServerLevel, Difficulty, boolean)) ++ serverLevel.setSpawnSettings(serverLevel.serverLevelData.getDifficulty() != Difficulty.PEACEFUL && ((net.minecraft.server.dedicated.DedicatedServer) this).settings.getProperties().spawnMonsters); // Paper - per level difficulty (from setDifficulty(ServerLevel, Difficulty, boolean)) + + this.forceTicks = false; + // CraftBukkit end } public GameType getDefaultGameType() { -@@ -588,12 +899,16 @@ - worldserver.save((ProgressListener) null, flush, worldserver.noSave && !force); +@@ -550,7 +_,7 @@ + public boolean saveAllChunks(boolean suppressLog, boolean flush, boolean forced) { + boolean flag = false; + +- for (ServerLevel serverLevel : this.getAllLevels()) { ++ for (net.minecraft.server.level.ServerLevel serverLevel : this.getAllLevels()) { + if (!suppressLog) { + LOGGER.info("Saving chunks for level '{}'/{}", serverLevel, serverLevel.dimension().location()); + } +@@ -559,13 +_,16 @@ + flag = true; } -- ServerLevel worldserver1 = this.overworld(); -- ServerLevelData iworlddataserver = this.worldData.overworldData(); -+ // CraftBukkit start - moved to WorldServer.save -+ /* -+ WorldServer worldserver1 = this.overworld(); -+ IWorldDataServer iworlddataserver = this.worldData.overworldData(); - - iworlddataserver.setWorldBorder(worldserver1.getWorldBorder().createSettings()); ++ /* // CraftBukkit start - moved to WorldServer.save + ServerLevel serverLevel1 = this.overworld(); + ServerLevelData serverLevelData = this.worldData.overworldData(); + serverLevelData.setWorldBorder(serverLevel1.getWorldBorder().createSettings()); this.worldData.setCustomBossEvents(this.getCustomBossEvents().save(this.registryAccess())); this.storageSource.saveDataTag(this.registryAccess(), this.worldData, this.getPlayerList().getSingleplayerData()); -+ */ ++ */ + // CraftBukkit end if (flush) { - Iterator iterator1 = this.getAllLevels().iterator(); +- for (ServerLevel serverLevel2 : this.getAllLevels()) { ++ for (net.minecraft.server.level.ServerLevel serverLevel2 : this.getAllLevels()) { + LOGGER.info("ThreadedAnvilChunkStorage ({}): All chunks are saved", serverLevel2.getChunkSource().chunkMap.getStorageName()); + } -@@ -628,18 +943,46 @@ +@@ -593,23 +_,51 @@ this.stopServer(); } @@ -742,7 +688,7 @@ this.cancelRecordingMetrics(); } - MinecraftServer.LOGGER.info("Stopping server"); + LOGGER.info("Stopping server"); + Commands.COMMAND_SENDING_POOL.shutdownNow(); // Paper - Perf: Async command map building; Shutdown and don't bother finishing + // CraftBukkit start + if (this.server != null) { @@ -755,17 +701,41 @@ this.getConnection().stop(); this.isSaving = true; if (this.playerList != null) { - MinecraftServer.LOGGER.info("Saving players"); + LOGGER.info("Saving players"); this.playerList.saveAll(); - this.playerList.removeAll(); + this.playerList.removeAll(this.isRestarting); // Paper + try { Thread.sleep(100); } catch (InterruptedException ex) {} // CraftBukkit - SPIGOT-625 - give server at least a chance to send packets } - MinecraftServer.LOGGER.info("Saving worlds"); -@@ -693,6 +1036,15 @@ - } catch (IOException ioexception1) { - MinecraftServer.LOGGER.error("Failed to unlock level {}", this.storageSource.getLevelId(), ioexception1); + LOGGER.info("Saving worlds"); + +- for (ServerLevel serverLevel : this.getAllLevels()) { ++ for (net.minecraft.server.level.ServerLevel serverLevel : this.getAllLevels()) { + if (serverLevel != null) { + serverLevel.noSave = false; + } +@@ -618,7 +_,7 @@ + while (this.levels.values().stream().anyMatch(level -> level.getChunkSource().chunkMap.hasWork())) { + this.nextTickTimeNanos = Util.getNanos() + TimeUtil.NANOSECONDS_PER_MILLISECOND; + +- for (ServerLevel serverLevelx : this.getAllLevels()) { ++ for (net.minecraft.server.level.ServerLevel serverLevelx : this.getAllLevels()) { + serverLevelx.getChunkSource().removeTicketsOnClosing(); + serverLevelx.getChunkSource().tick(() -> true, false); + } +@@ -628,7 +_,7 @@ + + this.saveAllChunks(false, true, false); + +- for (ServerLevel serverLevelx : this.getAllLevels()) { ++ for (net.minecraft.server.level.ServerLevel serverLevelx : this.getAllLevels()) { + if (serverLevelx != null) { + try { + serverLevelx.close(); +@@ -646,6 +_,15 @@ + } catch (IOException var4) { + LOGGER.error("Failed to unlock level {}", this.storageSource.getLevelId(), var4); } + // Spigot start + io.papermc.paper.util.MCUtil.ASYNC_EXECUTOR.shutdown(); // Paper @@ -776,32 +746,31 @@ + this.getProfileCache().save(false); // Paper - Perf: Async GameProfileCache saving + } + // Spigot end - } -@@ -709,6 +1061,14 @@ + public String getLocalIp() { +@@ -661,6 +_,14 @@ } - public void halt(boolean waitForShutdown) { + public void halt(boolean waitForServer) { + // Paper start - allow passing of the intent to restart -+ this.safeShutdown(waitForShutdown, false); ++ this.safeShutdown(waitForServer, false); + } -+ public void safeShutdown(boolean waitForShutdown, boolean isRestarting) { ++ public void safeShutdown(boolean waitForServer, boolean isRestarting) { + this.isRestarting = isRestarting; + this.hasLoggedStop = true; // Paper - Debugging + if (isDebugging()) io.papermc.paper.util.TraceUtil.dumpTraceForThread("Server stopped"); // Paper - Debugging + // Paper end this.running = false; - if (waitForShutdown) { + if (waitForServer) { try { -@@ -720,6 +1080,64 @@ - +@@ -671,6 +_,63 @@ + } } + // Spigot Start -+ private static double calcTps(double avg, double exp, double tps) -+ { -+ return ( avg * exp ) + ( tps * ( 1 - exp ) ); ++ private static double calcTps(double avg, double exp, double tps) { ++ return (avg * exp) + (tps * (1 - exp)); + } + + // Paper start - Further improve server tick loop @@ -859,12 +828,8 @@ protected void runServer() { try { if (!this.initServer()) { -@@ -727,9 +1145,27 @@ - } - - this.nextTickTimeNanos = Util.getNanos(); -- this.statusIcon = (ServerStatus.Favicon) this.loadStatusIcon().orElse((Object) null); -+ this.statusIcon = (ServerStatus.Favicon) this.loadStatusIcon().orElse(null); // CraftBukkit - decompile error +@@ -681,6 +_,24 @@ + this.statusIcon = this.loadStatusIcon().orElse(null); this.status = this.buildServerStatus(); + this.server.spark.enableBeforePlugins(); // Paper - spark @@ -886,18 +851,18 @@ + // Paper end - Add onboarding message for initial server start + while (this.running) { - long i; - -@@ -744,11 +1180,30 @@ - if (j > MinecraftServer.OVERLOADED_THRESHOLD_NANOS + 20L * i && this.nextTickTimeNanos - this.lastOverloadWarningNanos >= MinecraftServer.OVERLOADED_WARNING_INTERVAL_NANOS + 100L * i) { - long k = j / i; - + long l; + if (!this.isPaused() && this.tickRateManager.isSprinting() && this.tickRateManager.checkShouldSprintThisTick()) { +@@ -693,11 +_,30 @@ + if (l1 > OVERLOADED_THRESHOLD_NANOS + 20L * l + && this.nextTickTimeNanos - this.lastOverloadWarningNanos >= OVERLOADED_WARNING_INTERVAL_NANOS + 100L * l) { + long l2 = l1 / l; + if (this.server.getWarnOnOverload()) // CraftBukkit - MinecraftServer.LOGGER.warn("Can't keep up! Is the server overloaded? Running {}ms or {} ticks behind", j / TimeUtil.NANOSECONDS_PER_MILLISECOND, k); - this.nextTickTimeNanos += k * i; + LOGGER.warn("Can't keep up! Is the server overloaded? Running {}ms or {} ticks behind", l1 / TimeUtil.NANOSECONDS_PER_MILLISECOND, l2); + this.nextTickTimeNanos += l2 * l; this.lastOverloadWarningNanos = this.nextTickTimeNanos; } -+ } + } + // Spigot start + // Paper start - further improve server tick loop + currentTime = Util.getNanos(); @@ -913,22 +878,22 @@ + this.recentTps[1] = tps5.getAverage(); + this.recentTps[2] = tps15.getAverage(); + tickSection = currentTime; - } ++ } + // Paper end - further improve server tick loop + // Spigot end - boolean flag = i == 0L; - -@@ -757,6 +1212,8 @@ + boolean flag = l == 0L; + if (this.debugCommandProfilerDelayStart) { +@@ -705,6 +_,8 @@ this.debugCommandProfiler = new MinecraftServer.TimeProfiler(Util.getNanos(), this.tickCount); } + //MinecraftServer.currentTick = (int) (System.currentTimeMillis() / 50); // CraftBukkit // Paper - don't overwrite current tick time + lastTick = currentTime; - this.nextTickTimeNanos += i; + this.nextTickTimeNanos += l; - try { -@@ -830,6 +1287,14 @@ + try (Profiler.Scope scope = Profiler.use(this.createProfiler())) { +@@ -755,6 +_,14 @@ this.services.profileCache().clearExecutor(); } @@ -942,46 +907,32 @@ + io.papermc.paper.log.CustomLogManager.forceReset(); // Paper - Reset loggers after shutdown this.onServerExit(); } - -@@ -889,9 +1354,16 @@ + } +@@ -807,7 +_,14 @@ } private boolean haveTime() { - return this.runningTask() || Util.getNanos() < (this.mayHaveDelayedTasks ? this.delayedTasksMaxNextTickTimeNanos : this.nextTickTimeNanos); + // CraftBukkit start + return this.forceTicks || this.runningTask() || Util.getNanos() < (this.mayHaveDelayedTasks ? this.delayedTasksMaxNextTickTimeNanos : this.nextTickTimeNanos); - } - ++ } ++ + private void executeModerately() { + this.runAllTasks(); + java.util.concurrent.locks.LockSupport.parkNanos("executing tasks", 1000L); + // CraftBukkit end -+ } -+ + } + public static boolean throwIfFatalException() { - RuntimeException runtimeexception = (RuntimeException) MinecraftServer.fatalException.get(); - -@@ -903,7 +1375,7 @@ - } - - public static void setFatalException(RuntimeException exception) { -- MinecraftServer.fatalException.compareAndSet((Object) null, exception); -+ MinecraftServer.fatalException.compareAndSet(null, exception); // CraftBukkit - decompile error - } - - @Override -@@ -961,6 +1433,7 @@ +@@ -871,15 +_,16 @@ if (super.pollTask()) { return true; } else { + boolean ret = false; // Paper - force execution of all worlds, do not just bias the first if (this.tickRateManager.isSprinting() || this.haveTime()) { - Iterator iterator = this.getAllLevels().iterator(); - -@@ -968,16 +1441,16 @@ - ServerLevel worldserver = (ServerLevel) iterator.next(); - - if (worldserver.getChunkSource().pollTask()) { +- for (ServerLevel serverLevel : this.getAllLevels()) { ++ for (net.minecraft.server.level.ServerLevel serverLevel : this.getAllLevels()) { + if (serverLevel.getChunkSource().pollTask()) { - return true; + ret = true; // Paper - force execution of all worlds, do not just bias the first } @@ -993,32 +944,26 @@ } } -- public void doRunTask(TickTask ticktask) { -+ public void doRunTask(TickTask ticktask) { // CraftBukkit - decompile error - Profiler.get().incrementCounter("runTask"); - super.doRunTask(ticktask); - } -@@ -1025,27 +1498,45 @@ +@@ -927,26 +_,44 @@ } - public void tickServer(BooleanSupplier shouldKeepTicking) { + public void tickServer(BooleanSupplier hasTimeLeft) { + org.spigotmc.WatchdogThread.tick(); // Spigot - long i = Util.getNanos(); - int j = this.pauseWhileEmptySeconds() * 20; - + long nanos = Util.getNanos(); + int i = this.pauseWhileEmptySeconds() * 20; + this.removeDisabledPluginsBlockingSleep(); // Paper - API to allow/disallow tick sleeping - if (j > 0) { + if (i > 0) { - if (this.playerList.getPlayerCount() == 0 && !this.tickRateManager.isSprinting()) { + if (this.playerList.getPlayerCount() == 0 && !this.tickRateManager.isSprinting() && this.pluginsBlockingSleep.isEmpty()) { // Paper - API to allow/disallow tick sleeping - ++this.emptyTicks; + this.emptyTicks++; } else { this.emptyTicks = 0; } - if (this.emptyTicks >= j) { + if (this.emptyTicks >= i) { + this.server.spark.tickStart(); // Paper - spark - if (this.emptyTicks == j) { - MinecraftServer.LOGGER.info("Server empty for {} seconds, pausing", this.pauseWhileEmptySeconds()); + if (this.emptyTicks == i) { + LOGGER.info("Server empty for {} seconds, pausing", this.pauseWhileEmptySeconds()); this.autoSave(); } @@ -1028,7 +973,7 @@ + while ((task = this.processQueue.poll()) != null) { + task.run(); + } -+ for (final ServerLevel level : this.levels.values()) { ++ for (final net.minecraft.server.level.ServerLevel level : this.levels.values()) { + // process unloads + level.getChunkSource().tick(() -> true, false); + } @@ -1042,20 +987,19 @@ + this.server.spark.tickStart(); // Paper - spark + new com.destroystokyo.paper.event.server.ServerTickStartEvent(this.tickCount+1).callEvent(); // Paper - Server Tick Events - ++this.tickCount; + this.tickCount++; this.tickRateManager.tick(); - this.tickChildren(shouldKeepTicking); -@@ -1055,12 +1546,20 @@ + this.tickChildren(hasTimeLeft); +@@ -956,11 +_,19 @@ } - --this.ticksUntilAutosave; + this.ticksUntilAutosave--; - if (this.ticksUntilAutosave <= 0) { + if (this.autosavePeriod > 0 && this.ticksUntilAutosave <= 0) { // CraftBukkit this.autoSave(); } - ProfilerFiller gameprofilerfiller = Profiler.get(); - + ProfilerFiller profilerFiller = Profiler.get(); + this.runAllTasks(); // Paper - move runAllTasks() into full server tick (previously for timings) + this.server.spark.executeMainThreadTasks(); // Paper - spark + // Paper start - Server Tick Events @@ -1064,55 +1008,67 @@ + new com.destroystokyo.paper.event.server.ServerTickEndEvent(this.tickCount, ((double)(endTime - lastTick) / 1000000D), remaining).callEvent(); + // Paper end - Server Tick Events + this.server.spark.tickEnd(((double)(endTime - lastTick) / 1000000D)); // Paper - spark - gameprofilerfiller.push("tallying"); - long k = Util.getNanos() - i; - int l = this.tickCount % 100; -@@ -1069,12 +1568,17 @@ - this.aggregatedTickTimesNanos += k; - this.tickTimesNanos[l] = k; - this.smoothedTickTimeMillis = this.smoothedTickTimeMillis * 0.8F + (float) k / (float) TimeUtil.NANOSECONDS_PER_MILLISECOND * 0.19999999F; + profilerFiller.push("tallying"); + long l = Util.getNanos() - nanos; + int i1 = this.tickCount % 100; +@@ -968,12 +_,17 @@ + this.aggregatedTickTimesNanos += l; + this.tickTimesNanos[i1] = l; + this.smoothedTickTimeMillis = this.smoothedTickTimeMillis * 0.8F + (float)l / (float)TimeUtil.NANOSECONDS_PER_MILLISECOND * 0.19999999F; + // Paper start - Add tick times API and /mspt command -+ this.tickTimes5s.add(this.tickCount, k); -+ this.tickTimes10s.add(this.tickCount, k); -+ this.tickTimes60s.add(this.tickCount, k); ++ this.tickTimes5s.add(this.tickCount, l); ++ this.tickTimes10s.add(this.tickCount, l); ++ this.tickTimes60s.add(this.tickCount, l); + // Paper end - Add tick times API and /mspt command - this.logTickMethodTime(i); - gameprofilerfiller.pop(); + this.logTickMethodTime(nanos); + profilerFiller.pop(); } private void autoSave() { - this.ticksUntilAutosave = this.computeNextAutosaveInterval(); + this.ticksUntilAutosave = this.autosavePeriod; // CraftBukkit - MinecraftServer.LOGGER.debug("Autosave started"); - ProfilerFiller gameprofilerfiller = Profiler.get(); - -@@ -1123,7 +1627,7 @@ + LOGGER.debug("Autosave started"); + ProfilerFiller profilerFiller = Profiler.get(); + profilerFiller.push("save"); +@@ -1015,7 +_,7 @@ private ServerStatus buildServerStatus() { - ServerStatus.Players serverping_serverpingplayersample = this.buildPlayerStatus(); - -- return new ServerStatus(Component.nullToEmpty(this.motd), Optional.of(serverping_serverpingplayersample), Optional.of(ServerStatus.Version.current()), Optional.ofNullable(this.statusIcon), this.enforceSecureProfile()); -+ return new ServerStatus(io.papermc.paper.adventure.PaperAdventure.asVanilla(this.motd), Optional.of(serverping_serverpingplayersample), Optional.of(ServerStatus.Version.current()), Optional.ofNullable(this.statusIcon), this.enforceSecureProfile()); // Paper - Adventure + ServerStatus.Players players = this.buildPlayerStatus(); + return new ServerStatus( +- Component.nullToEmpty(this.motd), ++ io.papermc.paper.adventure.PaperAdventure.asVanilla(this.motd), // Paper - Adventure + Optional.of(players), + Optional.of(ServerStatus.Version.current()), + Optional.ofNullable(this.statusIcon), +@@ -1024,17 +_,17 @@ } private ServerStatus.Players buildPlayerStatus() { -@@ -1133,7 +1637,7 @@ +- List players = this.playerList.getPlayers(); ++ List players = this.playerList.getPlayers(); + int maxPlayers = this.getMaxPlayers(); if (this.hidesOnlinePlayers()) { - return new ServerStatus.Players(i, list.size(), List.of()); + return new ServerStatus.Players(maxPlayers, players.size(), List.of()); } else { -- int j = Math.min(list.size(), 12); -+ int j = Math.min(list.size(), org.spigotmc.SpigotConfig.playerSample); // Paper - PaperServerListPingEvent - ObjectArrayList objectarraylist = new ObjectArrayList(j); - int k = Mth.nextInt(this.random, 0, list.size() - j); +- int min = Math.min(players.size(), 12); ++ int min = Math.min(players.size(), org.spigotmc.SpigotConfig.playerSample); // Paper - PaperServerListPingEvent + ObjectArrayList list = new ObjectArrayList<>(min); + int randomInt = Mth.nextInt(this.random, 0, players.size() - min); -@@ -1154,24 +1658,72 @@ - this.getPlayerList().getPlayers().forEach((entityplayer) -> { - entityplayer.connection.suspendFlushing(); - }); + for (int i = 0; i < min; i++) { +- ServerPlayer serverPlayer = players.get(randomInt + i); ++ net.minecraft.server.level.ServerPlayer serverPlayer = players.get(randomInt + i); + list.add(serverPlayer.allowsListing() ? serverPlayer.getGameProfile() : ANONYMOUS_PLAYER_PROFILE); + } + +@@ -1046,17 +_,64 @@ + protected void tickChildren(BooleanSupplier hasTimeLeft) { + ProfilerFiller profilerFiller = Profiler.get(); + this.getPlayerList().getPlayers().forEach(serverPlayer1 -> serverPlayer1.connection.suspendFlushing()); + this.server.getScheduler().mainThreadHeartbeat(); // CraftBukkit + // Paper start - Folia scheduler API -+ ((io.papermc.paper.threadedregions.scheduler.FoliaGlobalRegionScheduler) Bukkit.getGlobalRegionScheduler()).tick(); ++ ((io.papermc.paper.threadedregions.scheduler.FoliaGlobalRegionScheduler) org.bukkit.Bukkit.getGlobalRegionScheduler()).tick(); + getAllLevels().forEach(level -> { -+ for (final Entity entity : level.getEntities().getAll()) { ++ for (final net.minecraft.world.entity.Entity entity : level.getEntities().getAll()) { + if (entity.isRemoved()) { + continue; + } @@ -1124,12 +1080,11 @@ + }); + // Paper end - Folia scheduler API + io.papermc.paper.adventure.providers.ClickCallbackProviderImpl.CALLBACK_MANAGER.handleQueue(this.tickCount); // Paper - gameprofilerfiller.push("commandFunctions"); + profilerFiller.push("commandFunctions"); this.getFunctions().tick(); - gameprofilerfiller.popPush("levels"); -- Iterator iterator = this.getAllLevels().iterator(); -+ //Iterator iterator = this.getAllLevels().iterator(); // Paper - Throw exception on world create while being ticked; moved down + profilerFiller.popPush("levels"); +- for (ServerLevel serverLevel : this.getAllLevels()) { + // CraftBukkit start + // Run tasks that are waiting on processing + while (!this.processQueue.isEmpty()) { @@ -1138,16 +1093,16 @@ + + // Send time updates to everyone, it will get the right time from the world the player is in. + // Paper start - Perf: Optimize time updates -+ for (final ServerLevel level : this.getAllLevels()) { ++ for (final net.minecraft.server.level.ServerLevel level : this.getAllLevels()) { + final boolean doDaylight = level.getGameRules().getBoolean(GameRules.RULE_DAYLIGHT); + final long dayTime = level.getDayTime(); + long worldTime = level.getGameTime(); + final ClientboundSetTimePacket worldPacket = new ClientboundSetTimePacket(worldTime, dayTime, doDaylight); + for (Player entityhuman : level.players()) { -+ if (!(entityhuman instanceof ServerPlayer) || (tickCount + entityhuman.getId()) % 20 != 0) { ++ if (!(entityhuman instanceof net.minecraft.server.level.ServerPlayer) || (tickCount + entityhuman.getId()) % 20 != 0) { + continue; + } -+ ServerPlayer entityplayer = (ServerPlayer) entityhuman; ++ net.minecraft.server.level.ServerPlayer entityplayer = (net.minecraft.server.level.ServerPlayer) entityhuman; + long playerTime = entityplayer.getPlayerTime(); + ClientboundSetTimePacket packet = (playerTime == dayTime) ? worldPacket : + new ClientboundSetTimePacket(worldTime, playerTime, doDaylight); @@ -1157,52 +1112,83 @@ + } + + 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 -+ worldserver.hasEntityMoveEvent = io.papermc.paper.event.entity.EntityMoveEvent.getHandlerList().getRegisteredListeners().length > 0; // Paper - Add EntityMoveEvent - - gameprofilerfiller.push(() -> { - String s = String.valueOf(worldserver); - - return s + " " + String.valueOf(worldserver.dimension().location()); - }); ++ for (net.minecraft.server.level.ServerLevel serverLevel : this.getAllLevels()) { ++ serverLevel.hasPhysicsEvent = org.bukkit.event.block.BlockPhysicsEvent.getHandlerList().getRegisteredListeners().length > 0; // Paper - BlockPhysicsEvent ++ serverLevel.hasEntityMoveEvent = io.papermc.paper.event.entity.EntityMoveEvent.getHandlerList().getRegisteredListeners().length > 0; // Paper - Add EntityMoveEvent + profilerFiller.push(() -> serverLevel + " " + serverLevel.dimension().location()); + /* Drop global time updates if (this.tickCount % 20 == 0) { - gameprofilerfiller.push("timeSync"); - this.synchronizeTime(worldserver); - gameprofilerfiller.pop(); + profilerFiller.push("timeSync"); + this.synchronizeTime(serverLevel); + profilerFiller.pop(); } + // CraftBukkit end */ - gameprofilerfiller.push("tick"); + profilerFiller.push("tick"); -@@ -1186,7 +1738,9 @@ +@@ -1070,7 +_,9 @@ - gameprofilerfiller.pop(); - gameprofilerfiller.pop(); -+ worldserver.explosionDensityCache.clear(); // Paper - Optimize explosions + profilerFiller.pop(); + profilerFiller.pop(); ++ serverLevel.explosionDensityCache.clear(); // Paper - Optimize explosions } + this.isIteratingOverLevels = false; // Paper - Throw exception on world create while being ticked - gameprofilerfiller.popPush("connection"); + profilerFiller.popPush("connection"); this.tickConnection(); -@@ -1267,6 +1821,22 @@ - return (ServerLevel) this.levels.get(key); +@@ -1088,7 +_,7 @@ + + profilerFiller.popPush("send chunks"); + +- for (ServerPlayer serverPlayer : this.playerList.getPlayers()) { ++ for (net.minecraft.server.level.ServerPlayer serverPlayer : this.playerList.getPlayers()) { + serverPlayer.connection.chunkSender.sendNextChunks(serverPlayer); + serverPlayer.connection.resumeFlushing(); + } +@@ -1100,7 +_,7 @@ + this.getConnection().tick(); + } + +- private void synchronizeTime(ServerLevel level) { ++ private void synchronizeTime(net.minecraft.server.level.ServerLevel level) { + this.playerList + .broadcastAll( + new ClientboundSetTimePacket(level.getGameTime(), level.getDayTime(), level.getGameRules().getBoolean(GameRules.RULE_DAYLIGHT)), +@@ -1112,7 +_,7 @@ + ProfilerFiller profilerFiller = Profiler.get(); + profilerFiller.push("timeSync"); + +- for (ServerLevel serverLevel : this.getAllLevels()) { ++ for (net.minecraft.server.level.ServerLevel serverLevel : this.getAllLevels()) { + this.synchronizeTime(serverLevel); + } + +@@ -1139,20 +_,36 @@ + return this.getServerDirectory().resolve(path); + } + +- public final ServerLevel overworld() { ++ public final net.minecraft.server.level.ServerLevel overworld() { + return this.levels.get(Level.OVERWORLD); + } + + @Nullable +- public ServerLevel getLevel(ResourceKey dimension) { ++ public net.minecraft.server.level.ServerLevel getLevel(ResourceKey dimension) { + return this.levels.get(dimension); } + // CraftBukkit start -+ public void addLevel(ServerLevel level) { -+ Map, ServerLevel> oldLevels = this.levels; -+ Map, ServerLevel> newLevels = Maps.newLinkedHashMap(oldLevels); ++ public void addLevel(net.minecraft.server.level.ServerLevel level) { ++ Map, net.minecraft.server.level.ServerLevel> oldLevels = this.levels; ++ Map, net.minecraft.server.level.ServerLevel> newLevels = Maps.newLinkedHashMap(oldLevels); + newLevels.put(level.dimension(), level); + this.levels = Collections.unmodifiableMap(newLevels); + } + -+ public void removeLevel(ServerLevel level) { -+ Map, ServerLevel> oldLevels = this.levels; -+ Map, ServerLevel> newLevels = Maps.newLinkedHashMap(oldLevels); ++ public void removeLevel(net.minecraft.server.level.ServerLevel level) { ++ Map, net.minecraft.server.level.ServerLevel> oldLevels = this.levels; ++ Map, net.minecraft.server.level.ServerLevel> newLevels = Maps.newLinkedHashMap(oldLevels); + newLevels.remove(level.dimension()); + this.levels = Collections.unmodifiableMap(newLevels); + } @@ -1211,7 +1197,13 @@ public Set> levelKeys() { return this.levels.keySet(); } -@@ -1296,7 +1866,7 @@ + +- public Iterable getAllLevels() { ++ public Iterable getAllLevels() { + return this.levels.values(); + } + +@@ -1177,7 +_,7 @@ @DontObfuscate public String getServerModName() { @@ -1219,46 +1211,57 @@ + return io.papermc.paper.ServerBuildInfo.buildInfo().brandName(); // Paper } - public SystemReport fillSystemReport(SystemReport details) { -@@ -1347,7 +1917,7 @@ + public SystemReport fillSystemReport(SystemReport systemReport) { +@@ -1212,7 +_,7 @@ @Override - public void sendSystemMessage(Component message) { -- MinecraftServer.LOGGER.info(message.getString()); -+ MinecraftServer.LOGGER.info(io.papermc.paper.adventure.PaperAdventure.ANSI_SERIALIZER.serialize(io.papermc.paper.adventure.PaperAdventure.asAdventure(message))); // Paper - Log message with colors + public void sendSystemMessage(Component component) { +- LOGGER.info(component.getString()); ++ LOGGER.info(io.papermc.paper.adventure.PaperAdventure.ANSI_SERIALIZER.serialize(io.papermc.paper.adventure.PaperAdventure.asAdventure(component))); // Paper - Log message with colors } public KeyPair getKeyPair() { -@@ -1385,11 +1955,14 @@ +@@ -1250,11 +_,14 @@ } } -- public void setDifficulty(Difficulty difficulty, boolean forceUpdate) { -- if (forceUpdate || !this.worldData.isDifficultyLocked()) { +- public void setDifficulty(Difficulty difficulty, boolean forced) { +- if (forced || !this.worldData.isDifficultyLocked()) { - this.worldData.setDifficulty(this.worldData.isHardcore() ? Difficulty.HARD : difficulty); - this.updateMobSpawningFlags(); - this.getPlayerList().getPlayers().forEach(this::sendDifficultyUpdate); + // Paper start - per level difficulty -+ public void setDifficulty(ServerLevel level, Difficulty difficulty, boolean forceUpdate) { -+ PrimaryLevelData worldData = level.serverLevelData; ++ public void setDifficulty(net.minecraft.server.level.ServerLevel level, Difficulty difficulty, boolean forceUpdate) { ++ net.minecraft.world.level.storage.PrimaryLevelData worldData = level.serverLevelData; + if (forceUpdate || !worldData.isDifficultyLocked()) { + worldData.setDifficulty(worldData.isHardcore() ? Difficulty.HARD : difficulty); -+ level.setSpawnSettings(worldData.getDifficulty() != Difficulty.PEACEFUL && ((DedicatedServer) this).settings.getProperties().spawnMonsters); ++ level.setSpawnSettings(worldData.getDifficulty() != Difficulty.PEACEFUL && ((net.minecraft.server.dedicated.DedicatedServer) this).settings.getProperties().spawnMonsters); + // this.getPlayerList().getPlayers().forEach(this::sendDifficultyUpdate); + // Paper end - per level difficulty } } -@@ -1403,7 +1976,7 @@ - while (iterator.hasNext()) { - ServerLevel worldserver = (ServerLevel) iterator.next(); - -- worldserver.setSpawnSettings(this.isSpawningMonsters()); -+ worldserver.setSpawnSettings(worldserver.serverLevelData.getDifficulty() != Difficulty.PEACEFUL && ((DedicatedServer) this).settings.getProperties().spawnMonsters); // Paper - per level difficulty (from setDifficulty(ServerLevel, Difficulty, boolean)) - } - +@@ -1263,8 +_,8 @@ } -@@ -1481,10 +2054,20 @@ + + private void updateMobSpawningFlags() { +- for (ServerLevel serverLevel : this.getAllLevels()) { +- serverLevel.setSpawnSettings(this.isSpawningMonsters()); ++ for (net.minecraft.server.level.ServerLevel serverLevel : this.getAllLevels()) { ++ serverLevel.setSpawnSettings(serverLevel.serverLevelData.getDifficulty() != Difficulty.PEACEFUL && ((net.minecraft.server.dedicated.DedicatedServer) this).settings.getProperties().spawnMonsters); // Paper - per level difficulty (from setDifficulty(ServerLevel, Difficulty, boolean)) + } + } + +@@ -1273,7 +_,7 @@ + this.getPlayerList().getPlayers().forEach(this::sendDifficultyUpdate); + } + +- private void sendDifficultyUpdate(ServerPlayer player) { ++ private void sendDifficultyUpdate(net.minecraft.server.level.ServerPlayer player) { + LevelData levelData = player.level().getLevelData(); + player.connection.send(new ClientboundChangeDifficultyPacket(levelData.getDifficulty(), levelData.isDifficultyLocked())); + } +@@ -1340,10 +_,20 @@ @Override public String getMotd() { @@ -1280,124 +1283,145 @@ this.motd = motd; } -@@ -1507,7 +2090,7 @@ +@@ -1365,8 +_,8 @@ + this.worldData.setGameType(gameMode); } - public ServerConnectionListener getConnection() { +- public ServerConnectionListener getConnection() { - return this.connection; -+ return this.connection == null ? this.connection = new ServerConnectionListener(this) : this.connection; // Spigot ++ public net.minecraft.server.network.ServerConnectionListener getConnection() { ++ return this.connection == null ? this.connection = new net.minecraft.server.network.ServerConnectionListener(this) : this.connection; // Spigot } public boolean isReady() { -@@ -1593,7 +2176,7 @@ +@@ -1389,7 +_,7 @@ + return 16; + } + +- public boolean isUnderSpawnProtection(ServerLevel level, BlockPos pos, Player player) { ++ public boolean isUnderSpawnProtection(net.minecraft.server.level.ServerLevel level, BlockPos pos, Player player) { + return false; + } + +@@ -1452,7 +_,7 @@ @Override - public void executeIfPossible(Runnable runnable) { + public void executeIfPossible(Runnable task) { if (this.isStopped()) { - throw new RejectedExecutionException("Server already shutting down"); + throw new io.papermc.paper.util.ServerStopRejectedExecutionException("Server already shutting down"); // Paper - do not prematurely disconnect players on stop } else { - super.executeIfPossible(runnable); + super.executeIfPossible(task); } -@@ -1632,16 +2215,22 @@ +@@ -1479,7 +_,7 @@ + return this.fixerUpper; + } + +- public int getSpawnRadius(@Nullable ServerLevel level) { ++ public int getSpawnRadius(@Nullable net.minecraft.server.level.ServerLevel level) { + return level != null ? level.getGameRules().getInt(GameRules.RULE_SPAWN_RADIUS) : 10; + } + +@@ -1491,7 +_,13 @@ return this.functionManager; } + // Paper start - Add ServerResourcesReloadedEvent + @Deprecated @io.papermc.paper.annotation.DoNotUse - public CompletableFuture reloadResources(Collection dataPacks) { -+ return this.reloadResources(dataPacks, io.papermc.paper.event.server.ServerResourcesReloadedEvent.Cause.PLUGIN); + public CompletableFuture reloadResources(Collection selectedIds) { ++ return this.reloadResources(selectedIds, io.papermc.paper.event.server.ServerResourcesReloadedEvent.Cause.PLUGIN); + } -+ public CompletableFuture reloadResources(Collection dataPacks, io.papermc.paper.event.server.ServerResourcesReloadedEvent.Cause cause) { ++ public CompletableFuture reloadResources(Collection selectedIds, io.papermc.paper.event.server.ServerResourcesReloadedEvent.Cause cause) { + // Paper end - Add ServerResourcesReloadedEvent - CompletableFuture completablefuture = CompletableFuture.supplyAsync(() -> { -- Stream stream = dataPacks.stream(); -+ Stream stream = dataPacks.stream(); // CraftBukkit - decompile error - PackRepository resourcepackrepository = this.packRepository; - - Objects.requireNonNull(this.packRepository); -- return (ImmutableList) stream.map(resourcepackrepository::getPack).filter(Objects::nonNull).map(Pack::open).collect(ImmutableList.toImmutableList()); -+ return stream.map(resourcepackrepository::getPack).filter(Objects::nonNull).map(Pack::open).collect(ImmutableList.toImmutableList()); // CraftBukkit - decompile error // Paper - decompile error // todo: is this needed anymore? - }, this).thenCompose((immutablelist) -> { - MultiPackResourceManager resourcemanager = new MultiPackResourceManager(PackType.SERVER_DATA, immutablelist); -- List> list = TagLoader.loadTagsForExistingRegistries(resourcemanager, this.registries.compositeAccess()); -+ List> list = TagLoader.loadTagsForExistingRegistries(resourcemanager, this.registries.compositeAccess(), io.papermc.paper.plugin.lifecycle.event.registrar.ReloadableRegistrarEvent.Cause.RELOAD); // Paper - tag lifecycle - add cause - - return ReloadableServerResources.loadResources(resourcemanager, this.registries, list, this.worldData.enabledFeatures(), this.isDedicatedServer() ? Commands.CommandSelection.DEDICATED : Commands.CommandSelection.INTEGRATED, this.getFunctionCompilationLevel(), this.executor, this).whenComplete((datapackresources, throwable) -> { - if (throwable != null) { -@@ -1652,6 +2241,7 @@ - return new MinecraftServer.ReloadableResources(resourcemanager, datapackresources); - }); - }).thenAcceptAsync((minecraftserver_reloadableresources) -> { -+ io.papermc.paper.command.brigadier.PaperBrigadier.moveBukkitCommands(this.resources.managers().getCommands(), minecraftserver_reloadableresources.managers().commands); // Paper - this.resources.close(); - this.resources = minecraftserver_reloadableresources; - this.packRepository.setSelected(dataPacks); -@@ -1660,11 +2250,23 @@ - this.worldData.setDataConfiguration(worlddataconfiguration); - this.resources.managers.updateStaticRegistryTags(); - this.resources.managers.getRecipeManager().finalizeRecipeLoading(this.worldData.enabledFeatures()); -+ this.potionBrewing = this.potionBrewing.reload(this.worldData.enabledFeatures()); // Paper - Custom Potion Mixes - this.getPlayerList().saveAll(); - this.getPlayerList().reloadResources(); - this.functionManager.replaceLibrary(this.resources.managers.getFunctionLibrary()); - this.structureTemplateManager.onResourceManagerReload(this.resources.resourceManager); - this.fuelValues = FuelValues.vanillaBurnTimes(this.registries.compositeAccess(), this.worldData.enabledFeatures()); -+ org.bukkit.craftbukkit.block.data.CraftBlockData.reloadCache(); // Paper - cache block data strings; they can be defined by datapacks so refresh it here -+ // Paper start - brigadier command API -+ io.papermc.paper.command.brigadier.PaperCommands.INSTANCE.setValid(); // reset invalid state for event fire below -+ io.papermc.paper.plugin.lifecycle.event.LifecycleEventRunner.INSTANCE.callReloadableRegistrarEvent(io.papermc.paper.plugin.lifecycle.event.types.LifecycleEvents.COMMANDS, io.papermc.paper.command.brigadier.PaperCommands.INSTANCE, org.bukkit.plugin.Plugin.class, io.papermc.paper.plugin.lifecycle.event.registrar.ReloadableRegistrarEvent.Cause.RELOAD); // call commands event for regular plugins -+ final org.bukkit.craftbukkit.help.SimpleHelpMap helpMap = (org.bukkit.craftbukkit.help.SimpleHelpMap) this.server.getHelpMap(); -+ helpMap.clear(); -+ helpMap.initializeGeneralTopics(); -+ helpMap.initializeCommands(); -+ this.server.syncCommands(); // Refresh commands after event -+ // Paper end -+ new io.papermc.paper.event.server.ServerResourcesReloadedEvent(cause).callEvent(); // Paper - Add ServerResourcesReloadedEvent; fire after everything has been reloaded - }, this); - - if (this.isSameThread()) { -@@ -1789,14 +2391,15 @@ + CompletableFuture completableFuture = CompletableFuture.supplyAsync( + () -> selectedIds.stream().map(this.packRepository::getPack).filter(Objects::nonNull).map(Pack::open).collect(ImmutableList.toImmutableList()), + this +@@ -1499,7 +_,7 @@ + .thenCompose( + list -> { + CloseableResourceManager closeableResourceManager = new MultiPackResourceManager(PackType.SERVER_DATA, list); +- List> list1 = TagLoader.loadTagsForExistingRegistries(closeableResourceManager, this.registries.compositeAccess()); ++ List> list1 = TagLoader.loadTagsForExistingRegistries(closeableResourceManager, this.registries.compositeAccess(), io.papermc.paper.plugin.lifecycle.event.registrar.ReloadableRegistrarEvent.Cause.RELOAD); // Paper - tag lifecycle - add cause + return ReloadableServerResources.loadResources( + closeableResourceManager, + this.registries, +@@ -1520,6 +_,7 @@ + ) + .thenAcceptAsync( + reloadableResources -> { ++ io.papermc.paper.command.brigadier.PaperBrigadier.moveBukkitCommands(this.resources.managers().getCommands(), reloadableResources.managers().commands); // Paper + this.resources.close(); + this.resources = reloadableResources; + this.packRepository.setSelected(selectedIds); +@@ -1529,11 +_,23 @@ + this.worldData.setDataConfiguration(worldDataConfiguration); + this.resources.managers.updateStaticRegistryTags(); + this.resources.managers.getRecipeManager().finalizeRecipeLoading(this.worldData.enabledFeatures()); ++ this.potionBrewing = this.potionBrewing.reload(this.worldData.enabledFeatures()); // Paper - Custom Potion Mixes + this.getPlayerList().saveAll(); + this.getPlayerList().reloadResources(); + this.functionManager.replaceLibrary(this.resources.managers.getFunctionLibrary()); + this.structureTemplateManager.onResourceManagerReload(this.resources.resourceManager); + this.fuelValues = FuelValues.vanillaBurnTimes(this.registries.compositeAccess(), this.worldData.enabledFeatures()); ++ org.bukkit.craftbukkit.block.data.CraftBlockData.reloadCache(); // Paper - cache block data strings; they can be defined by datapacks so refresh it here ++ // Paper start - brigadier command API ++ io.papermc.paper.command.brigadier.PaperCommands.INSTANCE.setValid(); // reset invalid state for event fire below ++ io.papermc.paper.plugin.lifecycle.event.LifecycleEventRunner.INSTANCE.callReloadableRegistrarEvent(io.papermc.paper.plugin.lifecycle.event.types.LifecycleEvents.COMMANDS, io.papermc.paper.command.brigadier.PaperCommands.INSTANCE, org.bukkit.plugin.Plugin.class, io.papermc.paper.plugin.lifecycle.event.registrar.ReloadableRegistrarEvent.Cause.RELOAD); // call commands event for regular plugins ++ final org.bukkit.craftbukkit.help.SimpleHelpMap helpMap = (org.bukkit.craftbukkit.help.SimpleHelpMap) this.server.getHelpMap(); ++ helpMap.clear(); ++ helpMap.initializeGeneralTopics(); ++ helpMap.initializeCommands(); ++ this.server.syncCommands(); // Refresh commands after event ++ // Paper end ++ new io.papermc.paper.event.server.ServerResourcesReloadedEvent(cause).callEvent(); // Paper - Add ServerResourcesReloadedEvent; fire after everything has been reloaded + }, + this + ); +@@ -1652,10 +_,11 @@ if (this.isEnforceWhitelist()) { - PlayerList playerlist = source.getServer().getPlayerList(); - UserWhiteList whitelist = playerlist.getWhiteList(); -+ if (!((DedicatedServer) getServer()).getProperties().whiteList.get()) return; // Paper - whitelist not enabled - List list = Lists.newArrayList(playerlist.getPlayers()); - Iterator iterator = list.iterator(); + PlayerList playerList = commandSource.getServer().getPlayerList(); + UserWhiteList whiteList = playerList.getWhiteList(); ++ if (!((net.minecraft.server.dedicated.DedicatedServer) getServer()).getProperties().whiteList.get()) return; // Paper - whitelist not enabled - while (iterator.hasNext()) { - ServerPlayer entityplayer = (ServerPlayer) iterator.next(); - -- if (!whitelist.isWhiteListed(entityplayer.getGameProfile())) { -- entityplayer.connection.disconnect((Component) Component.translatable("multiplayer.disconnect.not_whitelisted")); -+ if (!whitelist.isWhiteListed(entityplayer.getGameProfile()) && !this.getPlayerList().isOp(entityplayer.getGameProfile())) { // Paper - Fix kicking ops when whitelist is reloaded (MC-171420) -+ entityplayer.connection.disconnect(net.kyori.adventure.text.Component.text(org.spigotmc.SpigotConfig.whitelistMessage), org.bukkit.event.player.PlayerKickEvent.Cause.WHITELIST); // Paper - use configurable message & kick event cause +- for (ServerPlayer serverPlayer : Lists.newArrayList(playerList.getPlayers())) { +- if (!whiteList.isWhiteListed(serverPlayer.getGameProfile())) { +- serverPlayer.connection.disconnect(Component.translatable("multiplayer.disconnect.not_whitelisted")); ++ for (net.minecraft.server.level.ServerPlayer serverPlayer : Lists.newArrayList(playerList.getPlayers())) { ++ if (!whiteList.isWhiteListed(serverPlayer.getGameProfile()) && !this.getPlayerList().isOp(serverPlayer.getGameProfile())) { // Paper - Fix kicking ops when whitelist is reloaded (MC-171420) ++ serverPlayer.connection.disconnect(net.kyori.adventure.text.Component.text(org.spigotmc.SpigotConfig.whitelistMessage), org.bukkit.event.player.PlayerKickEvent.Cause.WHITELIST); // Paper - use configurable message & kick event cause } } - -@@ -1952,7 +2555,7 @@ - final List list = Lists.newArrayList(); - final GameRules gamerules = this.getGameRules(); - -- gamerules.visitGameRuleTypes(new GameRules.GameRuleTypeVisitor(this) { -+ gamerules.visitGameRuleTypes(new GameRules.GameRuleTypeVisitor() { // CraftBukkit - decompile error - @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 +2661,7 @@ - try { - label51: - { -- ArrayList arraylist; -+ ArrayList arraylist; // CraftBukkit - decompile error - - try { - arraylist = Lists.newArrayList(NativeModuleLister.listModules()); -@@ -2105,8 +2708,23 @@ - if (bufferedwriter != null) { - bufferedwriter.close(); } -+ -+ } +@@ -1670,7 +_,7 @@ + } + + public CommandSourceStack createCommandSourceStack() { +- ServerLevel serverLevel = this.overworld(); ++ net.minecraft.server.level.ServerLevel serverLevel = this.overworld(); + return new CommandSourceStack( + this, + serverLevel == null ? Vec3.ZERO : Vec3.atLowerCornerOf(serverLevel.getSharedSpawnPos()), +@@ -1717,7 +_,7 @@ + return this.overworld().getGameRules(); + } + +- public CustomBossEvents getCustomBossEvents() { ++ public net.minecraft.server.bossevents.CustomBossEvents getCustomBossEvents() { + return this.customBossEvents; + } + +@@ -1771,7 +_,7 @@ + Path path1 = path.resolve("levels"); + + try { +- for (Entry, ServerLevel> entry : this.levels.entrySet()) { ++ for (Entry, net.minecraft.server.level.ServerLevel> entry : this.levels.entrySet()) { + ResourceLocation resourceLocation = entry.getKey().location(); + Path path2 = path1.resolve(resourceLocation.getNamespace()).resolve(resourceLocation.getPath()); + Files.createDirectories(path2); +@@ -1859,6 +_,22 @@ + } + } + + + // CraftBukkit start + public boolean isDebugging() { @@ -1407,47 +1431,71 @@ + public static MinecraftServer getServer() { + return SERVER; // Paper + } - ++ + @Deprecated + public static RegistryAccess getDefaultRegistryAccess() { -+ return CraftRegistry.getMinecraftRegistry(); - } ++ return org.bukkit.craftbukkit.CraftRegistry.getMinecraftRegistry(); ++ } + // CraftBukkit end - ++ private ProfilerFiller createProfiler() { if (this.willStartRecordingMetrics) { -@@ -2225,18 +2843,24 @@ + this.metricsRecorder = ActiveMetricsRecorder.createStarted( +@@ -1936,12 +_,12 @@ + return this.resources.managers.fullRegistries(); } - public void logChatMessage(Component message, ChatType.Bound params, @Nullable String prefix) { -- String s1 = params.decorate(message).getString(); -+ // Paper start -+ net.kyori.adventure.text.Component s1 = io.papermc.paper.adventure.PaperAdventure.asAdventure(params.decorate(message)); +- public TextFilter createTextFilterForPlayer(ServerPlayer player) { +- return TextFilter.DUMMY; ++ public net.minecraft.server.network.TextFilter createTextFilterForPlayer(net.minecraft.server.level.ServerPlayer player) { ++ return net.minecraft.server.network.TextFilter.DUMMY; + } - if (prefix != null) { -- MinecraftServer.LOGGER.info("[{}] {}", prefix, s1); -+ MinecraftServer.COMPONENT_LOGGER.info("[{}] {}", prefix, s1); +- public ServerPlayerGameMode createGameModeForPlayer(ServerPlayer player) { +- return (ServerPlayerGameMode)(this.isDemo() ? new DemoMode(player) : new ServerPlayerGameMode(player)); ++ public net.minecraft.server.level.ServerPlayerGameMode createGameModeForPlayer(net.minecraft.server.level.ServerPlayer player) { ++ return (net.minecraft.server.level.ServerPlayerGameMode)(this.isDemo() ? new net.minecraft.server.level.DemoMode(player) : new net.minecraft.server.level.ServerPlayerGameMode(player)); + } + + @Nullable +@@ -1980,23 +_,29 @@ + } + + public void logChatMessage(Component content, ChatType.Bound boundChatType, @Nullable String header) { +- String string = boundChatType.decorate(content).getString(); ++ // Paper start ++ net.kyori.adventure.text.Component string = io.papermc.paper.adventure.PaperAdventure.asAdventure(boundChatType.decorate(content)); + if (header != null) { +- LOGGER.info("[{}] {}", header, string); ++ COMPONENT_LOGGER.info("[{}] {}", header, string); } else { -- MinecraftServer.LOGGER.info("{}", s1); -+ MinecraftServer.COMPONENT_LOGGER.info("{}", s1); +- LOGGER.info("{}", string); ++ COMPONENT_LOGGER.info("{}", string); + // Paper end } - } - -+ public final java.util.concurrent.ExecutorService chatExecutor = java.util.concurrent.Executors.newCachedThreadPool( -+ new com.google.common.util.concurrent.ThreadFactoryBuilder().setDaemon(true).setNameFormat("Async Chat Thread - #%d").setUncaughtExceptionHandler(new net.minecraft.DefaultUncaughtExceptionHandlerWithName(net.minecraft.server.MinecraftServer.LOGGER)).build()); // Paper + ++ public final java.util.concurrent.ExecutorService chatExecutor = java.util.concurrent.Executors.newCachedThreadPool( ++ new com.google.common.util.concurrent.ThreadFactoryBuilder().setDaemon(true).setNameFormat("Async Chat Thread - #%d").setUncaughtExceptionHandler(new net.minecraft.DefaultUncaughtExceptionHandlerWithName(net.minecraft.server.MinecraftServer.LOGGER)).build()); // Paper + public final ChatDecorator improvedChatDecorator = new io.papermc.paper.adventure.ImprovedChatDecorator(this); // Paper - adventure + public ChatDecorator getChatDecorator() { - return ChatDecorator.PLAIN; + return this.improvedChatDecorator; // Paper - support async chat decoration events } public boolean logIPs() { -@@ -2379,4 +3003,53 @@ - public static record ServerResourcePackInfo(UUID id, String url, String hash, boolean isRequired, @Nullable Component prompt) { + return true; + } +- public void subscribeToDebugSample(ServerPlayer player, RemoteDebugSampleType sampleType) { ++ public void subscribeToDebugSample(net.minecraft.server.level.ServerPlayer player, RemoteDebugSampleType sampleType) { + } + + public boolean acceptsTransfers() { +@@ -2122,4 +_,53 @@ + }; + } } + + // Paper start - Add tick times API and /mspt command diff --git a/paper-server/patches/unapplied/net/minecraft/server/PlayerAdvancements.java.patch b/paper-server/patches/sources/net/minecraft/server/PlayerAdvancements.java.patch similarity index 62% rename from paper-server/patches/unapplied/net/minecraft/server/PlayerAdvancements.java.patch rename to paper-server/patches/sources/net/minecraft/server/PlayerAdvancements.java.patch index 93d25149bd..0c15dfbc32 100644 --- a/paper-server/patches/unapplied/net/minecraft/server/PlayerAdvancements.java.patch +++ b/paper-server/patches/sources/net/minecraft/server/PlayerAdvancements.java.patch @@ -1,52 +1,52 @@ --- a/net/minecraft/server/PlayerAdvancements.java +++ b/net/minecraft/server/PlayerAdvancements.java -@@ -50,7 +50,7 @@ - public class PlayerAdvancements { +@@ -47,7 +_,7 @@ + public class PlayerAdvancements { private static final Logger LOGGER = LogUtils.getLogger(); -- private static final Gson GSON = (new GsonBuilder()).setPrettyPrinting().create(); -+ private static final Gson GSON = (new GsonBuilder()).create(); // Paper - Remove pretty printing from advancements +- private static final Gson GSON = new GsonBuilder().setPrettyPrinting().create(); ++ private static final Gson GSON = new GsonBuilder().create(); // Paper - Remove pretty printing from advancements private final PlayerList playerList; private final Path playerSavePath; private AdvancementTree tree; -@@ -63,6 +63,7 @@ +@@ -60,6 +_,7 @@ private AdvancementHolder lastSelectedTab; private boolean isFirstPacket = true; private final Codec codec; + public final Map, Set>> criterionData = new java.util.IdentityHashMap<>(); // Paper - fix advancement data player leakage - public PlayerAdvancements(DataFixer dataFixer, PlayerList playerManager, ServerAdvancementManager advancementLoader, Path filePath, ServerPlayer owner) { - this.playerList = playerManager; -@@ -162,6 +163,7 @@ + public PlayerAdvancements(DataFixer dataFixer, PlayerList playerList, ServerAdvancementManager manager, Path playerSavePath, ServerPlayer player) { + this.playerList = playerList; +@@ -128,6 +_,7 @@ } public void save() { + if (org.spigotmc.SpigotConfig.disableAdvancementSaving) return; // Spigot - JsonElement jsonelement = (JsonElement) this.codec.encodeStart(JsonOps.INSTANCE, this.asData()).getOrThrow(); + JsonElement jsonElement = this.codec.encodeStart(JsonOps.INSTANCE, this.asData()).getOrThrow(); try { -@@ -196,6 +198,7 @@ - AdvancementHolder advancementholder = loader.get(minecraftkey); - - if (advancementholder == null) { -+ if (!minecraftkey.getNamespace().equals("minecraft")) return; // CraftBukkit - PlayerAdvancements.LOGGER.warn("Ignored advancement '{}' in progress file {} - it doesn't exist anymore?", minecraftkey, this.playerSavePath); +@@ -145,6 +_,7 @@ + data.forEach((path, progress) -> { + AdvancementHolder advancementHolder = advancementManager.get(path); + if (advancementHolder == null) { ++ if (!path.getNamespace().equals(ResourceLocation.DEFAULT_NAMESPACE)) return; // CraftBukkit + LOGGER.warn("Ignored advancement '{}' in progress file {} - it doesn't exist anymore?", path, this.playerSavePath); } else { - this.startProgress(advancementholder, advancementprogress); -@@ -223,14 +226,31 @@ - boolean flag1 = advancementprogress.isDone(); - - if (advancementprogress.grantProgress(criterionName)) { + this.startProgress(advancementHolder, progress); +@@ -169,14 +_,31 @@ + AdvancementProgress orStartProgress = this.getOrStartProgress(advancement); + boolean isDone = orStartProgress.isDone(); + if (orStartProgress.grantProgress(criterionKey)) { + // Paper start - Add PlayerAdvancementCriterionGrantEvent -+ if (!new com.destroystokyo.paper.event.player.PlayerAdvancementCriterionGrantEvent(this.player.getBukkitEntity(), advancement.toBukkit(), criterionName).callEvent()) { -+ advancementprogress.revokeProgress(criterionName); ++ if (!new com.destroystokyo.paper.event.player.PlayerAdvancementCriterionGrantEvent(this.player.getBukkitEntity(), advancement.toBukkit(), criterionKey).callEvent()) { ++ orStartProgress.revokeProgress(criterionKey); + return false; + } + // Paper end - Add PlayerAdvancementCriterionGrantEvent this.unregisterListeners(advancement); this.progressChanged.add(advancement); flag = true; - if (!flag1 && advancementprogress.isDone()) { + if (!isDone && orStartProgress.isDone()) { + // Paper start - Add Adventure message to PlayerAdvancementDoneEvent + final net.kyori.adventure.text.Component message = advancement.value().display().flatMap(info -> { + return java.util.Optional.ofNullable( @@ -57,13 +57,13 @@ + this.player.level().getCraftServer().getPluginManager().callEvent(event); // CraftBukkit + // Paper end advancement.value().rewards().grant(this.player); - advancement.value().display().ifPresent((advancementdisplay) -> { -- if (advancementdisplay.shouldAnnounceChat() && this.player.serverLevel().getGameRules().getBoolean(GameRules.RULE_ANNOUNCE_ADVANCEMENTS)) { -- this.playerList.broadcastSystemMessage(advancementdisplay.getType().createAnnouncement(advancement, this.player), false); + advancement.value().display().ifPresent(displayInfo -> { +- if (displayInfo.shouldAnnounceChat() && this.player.serverLevel().getGameRules().getBoolean(GameRules.RULE_ANNOUNCE_ADVANCEMENTS)) { +- this.playerList.broadcastSystemMessage(displayInfo.getType().createAnnouncement(advancement, this.player), false); + // Paper start - Add Adventure message to PlayerAdvancementDoneEvent + if (event.message() != null && this.player.serverLevel().getGameRules().getBoolean(GameRules.RULE_ANNOUNCE_ADVANCEMENTS)) { + this.playerList.broadcastSystemMessage(io.papermc.paper.adventure.PaperAdventure.asVanilla(event.message()), false); + // Paper end } - }); + } diff --git a/paper-server/patches/sources/net/minecraft/server/ReloadableServerRegistries.java.patch b/paper-server/patches/sources/net/minecraft/server/ReloadableServerRegistries.java.patch new file mode 100644 index 0000000000..4276054d2f --- /dev/null +++ b/paper-server/patches/sources/net/minecraft/server/ReloadableServerRegistries.java.patch @@ -0,0 +1,38 @@ +--- a/net/minecraft/server/ReloadableServerRegistries.java ++++ b/net/minecraft/server/ReloadableServerRegistries.java +@@ -48,8 +_,9 @@ + List> list = TagLoader.buildUpdatedLookups(registryAccess.getAccessForLoading(RegistryLayer.RELOADABLE), postponedTags); + HolderLookup.Provider provider = HolderLookup.Provider.create(list.stream()); + RegistryOps registryOps = provider.createSerializationContext(JsonOps.INSTANCE); ++ final io.papermc.paper.registry.data.util.Conversions conversions = new io.papermc.paper.registry.data.util.Conversions(registryOps.lookupProvider); // Paper + List>> list1 = LootDataType.values() +- .map(lootDataType -> scheduleRegistryLoad((LootDataType)lootDataType, registryOps, resourceManager, backgroundExecutor)) ++ .map(lootDataType -> scheduleRegistryLoad((LootDataType)lootDataType, registryOps, resourceManager, backgroundExecutor, conversions)) // Paper + .toList(); + CompletableFuture>> completableFuture = Util.sequence(list1); + return completableFuture.thenApplyAsync( +@@ -58,19 +_,20 @@ + } + + private static CompletableFuture> scheduleRegistryLoad( +- LootDataType lootDataType, RegistryOps ops, ResourceManager resourceManager, Executor backgroundExecutor ++ LootDataType lootDataType, RegistryOps ops, ResourceManager resourceManager, Executor backgroundExecutor, io.papermc.paper.registry.data.util.Conversions conversions // Paper + ) { + return CompletableFuture.supplyAsync( + () -> { + WritableRegistry writableRegistry = new MappedRegistry<>(lootDataType.registryKey(), Lifecycle.experimental()); ++ io.papermc.paper.registry.PaperRegistryAccess.instance().registerReloadableRegistry(lootDataType.registryKey(), writableRegistry); // Paper - register reloadable registry + Map map = new HashMap<>(); + SimpleJsonResourceReloadListener.scanDirectory(resourceManager, lootDataType.registryKey(), ops, lootDataType.codec(), map); + map.forEach( +- (resourceLocation, object) -> writableRegistry.register( +- ResourceKey.create(lootDataType.registryKey(), resourceLocation), (T)object, DEFAULT_REGISTRATION_INFO ++ (resourceLocation, object) -> io.papermc.paper.registry.PaperRegistryListenerManager.INSTANCE.registerWithListeners(writableRegistry, // Paper - register with listeners ++ ResourceKey.create(lootDataType.registryKey(), resourceLocation), (T)object, DEFAULT_REGISTRATION_INFO, conversions // Paper - register with listeners + ) + ); +- TagLoader.loadTagsForRegistry(resourceManager, writableRegistry); ++ TagLoader.loadTagsForRegistry(resourceManager, writableRegistry, io.papermc.paper.plugin.lifecycle.event.registrar.ReloadableRegistrarEvent.Cause.RELOAD); // Paper - tag life cycle - reload + return writableRegistry; + }, + backgroundExecutor diff --git a/paper-server/patches/unapplied/net/minecraft/server/ReloadableServerResources.java.patch b/paper-server/patches/sources/net/minecraft/server/ReloadableServerResources.java.patch similarity index 79% rename from paper-server/patches/unapplied/net/minecraft/server/ReloadableServerResources.java.patch rename to paper-server/patches/sources/net/minecraft/server/ReloadableServerResources.java.patch index 59120184c0..dd754adca3 100644 --- a/paper-server/patches/unapplied/net/minecraft/server/ReloadableServerResources.java.patch +++ b/paper-server/patches/sources/net/minecraft/server/ReloadableServerResources.java.patch @@ -1,16 +1,16 @@ --- a/net/minecraft/server/ReloadableServerResources.java +++ b/net/minecraft/server/ReloadableServerResources.java -@@ -39,6 +39,7 @@ - this.postponedTags = pendingTagLoads; +@@ -39,6 +_,7 @@ + this.postponedTags = postponedTags; this.recipes = new RecipeManager(registries); - this.commands = new Commands(environment, CommandBuildContext.simple(registries, enabledFeatures)); + this.commands = new Commands(commandSelection, CommandBuildContext.simple(registries, enabledFeatures)); + io.papermc.paper.command.brigadier.PaperCommands.INSTANCE.setDispatcher(this.commands, CommandBuildContext.simple(registries, enabledFeatures)); // Paper - Brigadier Command API this.advancements = new ServerAdvancementManager(registries); - this.functionLibrary = new ServerFunctionLibrary(functionPermissionLevel, this.commands.getDispatcher()); + this.functionLibrary = new ServerFunctionLibrary(functionCompilationLevel, this.commands.getDispatcher()); } -@@ -83,6 +84,14 @@ +@@ -83,6 +_,14 @@ ReloadableServerResources reloadableServerResources = new ReloadableServerResources( - reloadResult.layers(), reloadResult.lookupWithUpdatedTags(), enabledFeatures, environment, pendingTagLoads, functionPermissionLevel + loadResult.layers(), loadResult.lookupWithUpdatedTags(), enabledFeatures, commandSelection, postponedTags, functionCompilationLevel ); + // Paper start - call commands event for bootstraps + //noinspection ConstantValue diff --git a/paper-server/patches/unapplied/net/minecraft/server/ServerAdvancementManager.java.patch b/paper-server/patches/sources/net/minecraft/server/ServerAdvancementManager.java.patch similarity index 50% rename from paper-server/patches/unapplied/net/minecraft/server/ServerAdvancementManager.java.patch rename to paper-server/patches/sources/net/minecraft/server/ServerAdvancementManager.java.patch index 5a5a995288..3be388af55 100644 --- a/paper-server/patches/unapplied/net/minecraft/server/ServerAdvancementManager.java.patch +++ b/paper-server/patches/sources/net/minecraft/server/ServerAdvancementManager.java.patch @@ -1,39 +1,31 @@ --- a/net/minecraft/server/ServerAdvancementManager.java +++ b/net/minecraft/server/ServerAdvancementManager.java -@@ -21,10 +21,14 @@ - import net.minecraft.util.profiling.ProfilerFiller; - import org.slf4j.Logger; +@@ -22,7 +_,7 @@ -+// CraftBukkit start -+import java.util.HashMap; -+// CraftBukkit end -+ public class ServerAdvancementManager extends SimpleJsonResourceReloadListener { - private static final Logger LOGGER = LogUtils.getLogger(); - public Map advancements = Map.of(); -+ public Map advancements = new HashMap<>(); // CraftBukkit - SPIGOT-7734: mutable ++ public Map advancements = new java.util.HashMap<>(); // CraftBukkit - SPIGOT-7734: mutable private AdvancementTree tree = new AdvancementTree(); private final HolderLookup.Provider registries; -@@ -37,13 +41,19 @@ +@@ -35,12 +_,18 @@ + protected void apply(Map object, ResourceManager resourceManager, ProfilerFiller profiler) { Builder builder = ImmutableMap.builder(); - - prepared.forEach((minecraftkey, advancement) -> { + object.forEach((resourceLocation, advancement) -> { + // Spigot start -+ if (org.spigotmc.SpigotConfig.disabledAdvancements != null && (org.spigotmc.SpigotConfig.disabledAdvancements.contains("*") || org.spigotmc.SpigotConfig.disabledAdvancements.contains(minecraftkey.toString()) || org.spigotmc.SpigotConfig.disabledAdvancements.contains(minecraftkey.getNamespace()))) { ++ if (org.spigotmc.SpigotConfig.disabledAdvancements != null && (org.spigotmc.SpigotConfig.disabledAdvancements.contains("*") || org.spigotmc.SpigotConfig.disabledAdvancements.contains(resourceLocation.toString()) || org.spigotmc.SpigotConfig.disabledAdvancements.contains(resourceLocation.getNamespace()))) { + return; + } + // Spigot end - this.validate(minecraftkey, advancement); - builder.put(minecraftkey, new AdvancementHolder(minecraftkey, advancement)); + this.validate(resourceLocation, advancement); + builder.put(resourceLocation, new AdvancementHolder(resourceLocation, advancement)); }); - this.advancements = builder.buildOrThrow(); -+ this.advancements = new HashMap<>(builder.buildOrThrow()); // CraftBukkit - SPIGOT-7734: mutable - AdvancementTree advancementtree = new AdvancementTree(); ++ this.advancements = new java.util.HashMap<>(builder.buildOrThrow()); // CraftBukkit - SPIGOT-7734: mutable + AdvancementTree advancementTree = new AdvancementTree(); + advancementTree.addAll(this.advancements.values()); ++ LOGGER.info("Loaded {} advancements", advancementTree.nodes().size()); // Paper - Improve logging and errors; moved from AdvancementTree#addAll - advancementtree.addAll(this.advancements.values()); -+ LOGGER.info("Loaded {} advancements", advancementtree.nodes().size()); // Paper - Improve logging and errors; moved from AdvancementTree#addAll - Iterator iterator = advancementtree.roots().iterator(); - - while (iterator.hasNext()) { + for (AdvancementNode advancementNode : advancementTree.roots()) { + if (advancementNode.holder().value().display().isPresent()) { diff --git a/paper-server/patches/sources/net/minecraft/server/ServerFunctionLibrary.java.patch b/paper-server/patches/sources/net/minecraft/server/ServerFunctionLibrary.java.patch new file mode 100644 index 0000000000..55bb398552 --- /dev/null +++ b/paper-server/patches/sources/net/minecraft/server/ServerFunctionLibrary.java.patch @@ -0,0 +1,11 @@ +--- a/net/minecraft/server/ServerFunctionLibrary.java ++++ b/net/minecraft/server/ServerFunctionLibrary.java +@@ -113,7 +_,7 @@ + return null; + }).join()); + this.functions = builder.build(); +- this.tags = this.tagsLoader.build((Map>)pair.getFirst()); ++ this.tags = this.tagsLoader.build((Map>)pair.getFirst(), null); // Paper - command function tags are not implemented yet + }, + gameExecutor + ); diff --git a/paper-server/patches/unapplied/net/minecraft/server/ServerFunctionManager.java.patch b/paper-server/patches/sources/net/minecraft/server/ServerFunctionManager.java.patch similarity index 95% rename from paper-server/patches/unapplied/net/minecraft/server/ServerFunctionManager.java.patch rename to paper-server/patches/sources/net/minecraft/server/ServerFunctionManager.java.patch index 45ee083997..f78aa0e5e9 100644 --- a/paper-server/patches/unapplied/net/minecraft/server/ServerFunctionManager.java.patch +++ b/paper-server/patches/sources/net/minecraft/server/ServerFunctionManager.java.patch @@ -1,6 +1,6 @@ --- a/net/minecraft/server/ServerFunctionManager.java +++ b/net/minecraft/server/ServerFunctionManager.java -@@ -37,7 +37,7 @@ +@@ -34,7 +_,7 @@ } public CommandDispatcher getDispatcher() { diff --git a/paper-server/patches/unapplied/net/minecraft/server/ServerScoreboard.java.patch b/paper-server/patches/sources/net/minecraft/server/ServerScoreboard.java.patch similarity index 55% rename from paper-server/patches/unapplied/net/minecraft/server/ServerScoreboard.java.patch rename to paper-server/patches/sources/net/minecraft/server/ServerScoreboard.java.patch index 712e8444b1..32654cff45 100644 --- a/paper-server/patches/unapplied/net/minecraft/server/ServerScoreboard.java.patch +++ b/paper-server/patches/sources/net/minecraft/server/ServerScoreboard.java.patch @@ -1,24 +1,26 @@ --- a/net/minecraft/server/ServerScoreboard.java +++ b/net/minecraft/server/ServerScoreboard.java -@@ -42,7 +42,7 @@ +@@ -39,9 +_,7 @@ protected void onScoreChanged(ScoreHolder scoreHolder, Objective objective, Score score) { super.onScoreChanged(scoreHolder, objective, score); if (this.trackedObjectives.contains(objective)) { -- this.server.getPlayerList().broadcastAll(new ClientboundSetScorePacket(scoreHolder.getScoreboardName(), objective.getName(), score.value(), Optional.ofNullable(score.display()), Optional.ofNullable(score.numberFormat()))); -+ this.broadcastAll(new ClientboundSetScorePacket(scoreHolder.getScoreboardName(), objective.getName(), score.value(), Optional.ofNullable(score.display()), Optional.ofNullable(score.numberFormat()))); // CraftBukkit - } - - this.setDirty(); -@@ -57,7 +57,7 @@ +- this.server +- .getPlayerList() +- .broadcastAll( ++ this.broadcastAll( // CraftBukkit + new ClientboundSetScorePacket( + scoreHolder.getScoreboardName(), + objective.getName(), +@@ -64,7 +_,7 @@ @Override public void onPlayerRemoved(ScoreHolder scoreHolder) { super.onPlayerRemoved(scoreHolder); -- this.server.getPlayerList().broadcastAll(new ClientboundResetScorePacket(scoreHolder.getScoreboardName(), (String) null)); -+ this.broadcastAll(new ClientboundResetScorePacket(scoreHolder.getScoreboardName(), (String) null)); // CraftBukkit +- this.server.getPlayerList().broadcastAll(new ClientboundResetScorePacket(scoreHolder.getScoreboardName(), null)); ++ this.broadcastAll(new ClientboundResetScorePacket(scoreHolder.getScoreboardName(), null)); // CraftBukkit this.setDirty(); } -@@ -65,7 +65,7 @@ +@@ -72,7 +_,7 @@ public void onPlayerScoreRemoved(ScoreHolder scoreHolder, Objective objective) { super.onPlayerScoreRemoved(scoreHolder, objective); if (this.trackedObjectives.contains(objective)) { @@ -27,16 +29,16 @@ } this.setDirty(); -@@ -78,7 +78,7 @@ +@@ -84,7 +_,7 @@ super.setDisplayObjective(slot, objective); - if (scoreboardobjective1 != objective && scoreboardobjective1 != null) { - if (this.getObjectiveDisplaySlotCount(scoreboardobjective1) > 0) { + if (displayObjective != objective && displayObjective != null) { + if (this.getObjectiveDisplaySlotCount(displayObjective) > 0) { - this.server.getPlayerList().broadcastAll(new ClientboundSetDisplayObjectivePacket(slot, objective)); + this.broadcastAll(new ClientboundSetDisplayObjectivePacket(slot, objective)); // CraftBukkit } else { - this.stopTrackingObjective(scoreboardobjective1); + this.stopTrackingObjective(displayObjective); } -@@ -86,7 +86,7 @@ +@@ -92,7 +_,7 @@ if (objective != null) { if (this.trackedObjectives.contains(objective)) { @@ -45,16 +47,7 @@ } else { this.startTrackingObjective(objective); } -@@ -98,7 +98,7 @@ - @Override - public boolean addPlayerToTeam(String scoreHolderName, PlayerTeam team) { - if (super.addPlayerToTeam(scoreHolderName, team)) { -- this.server.getPlayerList().broadcastAll(ClientboundSetPlayerTeamPacket.createPlayerPacket(team, scoreHolderName, ClientboundSetPlayerTeamPacket.Action.ADD)); -+ this.broadcastAll(ClientboundSetPlayerTeamPacket.createPlayerPacket(team, scoreHolderName, ClientboundSetPlayerTeamPacket.Action.ADD)); // CraftBukkit - this.setDirty(); - return true; - } else { -@@ -106,13 +106,43 @@ +@@ -114,14 +_,42 @@ } } @@ -78,13 +71,17 @@ + // Paper end - Multiple Entries with Scoreboards + @Override - public void removePlayerFromTeam(String scoreHolderName, PlayerTeam team) { - super.removePlayerFromTeam(scoreHolderName, team); -- this.server.getPlayerList().broadcastAll(ClientboundSetPlayerTeamPacket.createPlayerPacket(team, scoreHolderName, ClientboundSetPlayerTeamPacket.Action.REMOVE)); -+ this.broadcastAll(ClientboundSetPlayerTeamPacket.createPlayerPacket(team, scoreHolderName, ClientboundSetPlayerTeamPacket.Action.REMOVE)); // CraftBukkit - this.setDirty(); - } - + public void removePlayerFromTeam(String username, PlayerTeam playerTeam) { + super.removePlayerFromTeam(username, playerTeam); +- this.server +- .getPlayerList() +- .broadcastAll(ClientboundSetPlayerTeamPacket.createPlayerPacket(playerTeam, username, ClientboundSetPlayerTeamPacket.Action.REMOVE)); +- this.setDirty(); +- } ++ this.broadcastAll(ClientboundSetPlayerTeamPacket.createPlayerPacket(playerTeam, username, ClientboundSetPlayerTeamPacket.Action.REMOVE)); // CraftBukkit ++ this.setDirty(); ++ } ++ + // Paper start - Multiple Entries with Scoreboards + public void removePlayersFromTeam(java.util.Collection players, PlayerTeam team) { + for (String playerName : players) { @@ -95,11 +92,10 @@ + this.setDirty(); + } + // Paper end - Multiple Entries with Scoreboards -+ + @Override public void onObjectiveAdded(Objective objective) { - super.onObjectiveAdded(objective); -@@ -123,7 +153,7 @@ +@@ -133,7 +_,7 @@ public void onObjectiveChanged(Objective objective) { super.onObjectiveChanged(objective); if (this.trackedObjectives.contains(objective)) { @@ -108,61 +104,61 @@ } this.setDirty(); -@@ -142,21 +172,21 @@ +@@ -152,21 +_,21 @@ @Override - public void onTeamAdded(PlayerTeam team) { - super.onTeamAdded(team); -- this.server.getPlayerList().broadcastAll(ClientboundSetPlayerTeamPacket.createAddOrModifyPacket(team, true)); -+ this.broadcastAll(ClientboundSetPlayerTeamPacket.createAddOrModifyPacket(team, true)); // CraftBukkit + public void onTeamAdded(PlayerTeam playerTeam) { + super.onTeamAdded(playerTeam); +- this.server.getPlayerList().broadcastAll(ClientboundSetPlayerTeamPacket.createAddOrModifyPacket(playerTeam, true)); ++ this.broadcastAll(ClientboundSetPlayerTeamPacket.createAddOrModifyPacket(playerTeam, true)); // CraftBukkit this.setDirty(); } @Override - public void onTeamChanged(PlayerTeam team) { - super.onTeamChanged(team); -- this.server.getPlayerList().broadcastAll(ClientboundSetPlayerTeamPacket.createAddOrModifyPacket(team, false)); -+ this.broadcastAll(ClientboundSetPlayerTeamPacket.createAddOrModifyPacket(team, false)); // CraftBukkit + public void onTeamChanged(PlayerTeam playerTeam) { + super.onTeamChanged(playerTeam); +- this.server.getPlayerList().broadcastAll(ClientboundSetPlayerTeamPacket.createAddOrModifyPacket(playerTeam, false)); ++ this.broadcastAll(ClientboundSetPlayerTeamPacket.createAddOrModifyPacket(playerTeam, false)); // CraftBukkit this.setDirty(); } @Override - public void onTeamRemoved(PlayerTeam team) { - super.onTeamRemoved(team); -- this.server.getPlayerList().broadcastAll(ClientboundSetPlayerTeamPacket.createRemovePacket(team)); -+ this.broadcastAll(ClientboundSetPlayerTeamPacket.createRemovePacket(team)); // CraftBukkit + public void onTeamRemoved(PlayerTeam playerTeam) { + super.onTeamRemoved(playerTeam); +- this.server.getPlayerList().broadcastAll(ClientboundSetPlayerTeamPacket.createRemovePacket(playerTeam)); ++ this.broadcastAll(ClientboundSetPlayerTeamPacket.createRemovePacket(playerTeam)); // CraftBukkit this.setDirty(); } -@@ -207,6 +237,7 @@ +@@ -209,6 +_,7 @@ + List> startTrackingPackets = this.getStartTrackingPackets(objective); - while (iterator.hasNext()) { - ServerPlayer entityplayer = (ServerPlayer) iterator.next(); -+ if (entityplayer.getBukkitEntity().getScoreboard().getHandle() != this) continue; // CraftBukkit - Only players on this board - Iterator iterator1 = list.iterator(); + for (ServerPlayer serverPlayer : this.server.getPlayerList().getPlayers()) { ++ if (serverPlayer.getBukkitEntity().getScoreboard().getHandle() != this) continue; // CraftBukkit - Only players on this board + for (Packet packet : startTrackingPackets) { + serverPlayer.connection.send(packet); + } +@@ -234,6 +_,7 @@ + List> stopTrackingPackets = this.getStopTrackingPackets(objective); - while (iterator1.hasNext()) { -@@ -243,6 +274,7 @@ - - while (iterator.hasNext()) { - ServerPlayer entityplayer = (ServerPlayer) iterator.next(); -+ if (entityplayer.getBukkitEntity().getScoreboard().getHandle() != this) continue; // CraftBukkit - Only players on this board - Iterator iterator1 = list.iterator(); - - while (iterator1.hasNext()) { -@@ -287,6 +319,16 @@ - return this.createData().load(nbt, registries); + for (ServerPlayer serverPlayer : this.server.getPlayerList().getPlayers()) { ++ if (serverPlayer.getBukkitEntity().getScoreboard().getHandle() != this) continue; // CraftBukkit - Only players on this board + for (Packet packet : stopTrackingPackets) { + serverPlayer.connection.send(packet); + } +@@ -267,6 +_,16 @@ + private ScoreboardSaveData createData(CompoundTag tag, HolderLookup.Provider registries) { + return this.createData().load(tag, registries); } - ++ + // CraftBukkit start - Send to players -+ private void broadcastAll(Packet packet) { -+ for (ServerPlayer entityplayer : (List) this.server.getPlayerList().players) { -+ if (entityplayer.getBukkitEntity().getScoreboard().getHandle() == this) { -+ entityplayer.connection.send(packet); ++ private void broadcastAll(Packet packet) { ++ for (ServerPlayer serverPlayer : this.server.getPlayerList().players) { ++ if (serverPlayer.getBukkitEntity().getScoreboard().getHandle() == this) { ++ serverPlayer.connection.send(packet); + } + } + } + // CraftBukkit end -+ - public static enum Method { - CHANGE, REMOVE; + public static enum Method { + CHANGE, diff --git a/paper-server/patches/unapplied/net/minecraft/server/ServerTickRateManager.java.patch b/paper-server/patches/sources/net/minecraft/server/ServerTickRateManager.java.patch similarity index 74% rename from paper-server/patches/unapplied/net/minecraft/server/ServerTickRateManager.java.patch rename to paper-server/patches/sources/net/minecraft/server/ServerTickRateManager.java.patch index 9720b17dc9..d5767c2dab 100644 --- a/paper-server/patches/unapplied/net/minecraft/server/ServerTickRateManager.java.patch +++ b/paper-server/patches/sources/net/minecraft/server/ServerTickRateManager.java.patch @@ -1,6 +1,6 @@ --- a/net/minecraft/server/ServerTickRateManager.java +++ b/net/minecraft/server/ServerTickRateManager.java -@@ -59,8 +59,14 @@ +@@ -58,8 +_,14 @@ } public boolean stopSprinting() { @@ -16,34 +16,31 @@ return true; } else { return false; -@@ -78,7 +84,7 @@ +@@ -76,14 +_,20 @@ return flag; } - private void finishTickSprint() { + private void finishTickSprint(boolean sendLog) { // CraftBukkit - add sendLog parameter - long i = this.scheduledCurrentSprintTicks - this.remainingSprintTicks; - double d0 = Math.max(1.0D, (double) this.sprintTimeSpend) / (double) TimeUtil.NANOSECONDS_PER_MILLISECOND; - int j = (int) ((double) (TimeUtil.MILLISECONDS_PER_SECOND * i) / d0); -@@ -86,9 +92,13 @@ - + long l = this.scheduledCurrentSprintTicks - this.remainingSprintTicks; + double d = Math.max(1.0, (double)this.sprintTimeSpend) / TimeUtil.NANOSECONDS_PER_MILLISECOND; + int i = (int)(TimeUtil.MILLISECONDS_PER_SECOND * l / d); + String string = String.format("%.2f", l == 0L ? this.millisecondsPerTick() : d / l); this.scheduledCurrentSprintTicks = 0L; this.sprintTimeSpend = 0L; -- this.server.createCommandSourceStack().sendSuccess(() -> { -- return Component.translatable("commands.tick.sprint.report", j, s); -- }, true); +- this.server.createCommandSourceStack().sendSuccess(() -> Component.translatable("commands.tick.sprint.report", i, string), true); + // CraftBukkit start - add sendLog parameter + if (sendLog) { + this.server.createCommandSourceStack().sendSuccess(() -> { -+ return Component.translatable("commands.tick.sprint.report", j, s); ++ return Component.translatable("commands.tick.sprint.report", i, string); + }, true); + } + // CraftBukkit end this.remainingSprintTicks = 0L; this.setFrozen(this.previousIsFrozen); this.server.onTickRateChanged(); -@@ -102,7 +112,7 @@ - --this.remainingSprintTicks; +@@ -97,7 +_,7 @@ + this.remainingSprintTicks--; return true; } else { - this.finishTickSprint(); diff --git a/paper-server/patches/unapplied/net/minecraft/server/Services.java.patch b/paper-server/patches/sources/net/minecraft/server/Services.java.patch similarity index 84% rename from paper-server/patches/unapplied/net/minecraft/server/Services.java.patch rename to paper-server/patches/sources/net/minecraft/server/Services.java.patch index c556957aab..86364d06cd 100644 --- a/paper-server/patches/unapplied/net/minecraft/server/Services.java.patch +++ b/paper-server/patches/sources/net/minecraft/server/Services.java.patch @@ -1,38 +1,38 @@ --- a/net/minecraft/server/Services.java +++ b/net/minecraft/server/Services.java -@@ -10,16 +10,32 @@ - import net.minecraft.server.players.GameProfileCache; +@@ -11,15 +_,31 @@ import net.minecraft.util.SignatureValidator; -+ public record Services( - MinecraftSessionService sessionService, ServicesKeySet servicesKeySet, GameProfileRepository profileRepository, GameProfileCache profileCache + MinecraftSessionService sessionService, ServicesKeySet servicesKeySet, GameProfileRepository profileRepository, GameProfileCache profileCache, @javax.annotation.Nullable io.papermc.paper.configuration.PaperConfigurations paperConfigurations // Paper - add paper configuration files ) { - private static final String USERID_CACHE_FILE = "usercache.json"; +- +- public static Services create(YggdrasilAuthenticationService authenticationService, File profileRepository) { ++ public static final String USERID_CACHE_FILE = "usercache.json"; // Paper - private -> public ++ + // Paper start - add paper configuration files + public Services(MinecraftSessionService sessionService, ServicesKeySet servicesKeySet, GameProfileRepository profileRepository, GameProfileCache profileCache) { + this(sessionService, servicesKeySet, profileRepository, profileCache, null); + } - -- public static Services create(YggdrasilAuthenticationService authenticationService, File rootDirectory) { ++ + @Override + public io.papermc.paper.configuration.PaperConfigurations paperConfigurations() { + return java.util.Objects.requireNonNull(this.paperConfigurations); + } + // Paper end - add paper configuration files -+ public static final String USERID_CACHE_FILE = "usercache.json"; // Paper - private -> public + -+ public static Services create(YggdrasilAuthenticationService authenticationService, File rootDirectory, File userCacheFile, joptsimple.OptionSet optionSet) throws Exception { // Paper - add optionset to load paper config files; add userCacheFile parameter ++ public static Services create(YggdrasilAuthenticationService authenticationService, File profileRepository, File userCacheFile, joptsimple.OptionSet optionSet) throws Exception { // Paper - add optionset to load paper config files; add userCacheFile parameter MinecraftSessionService minecraftSessionService = authenticationService.createMinecraftSessionService(); GameProfileRepository gameProfileRepository = authenticationService.createProfileRepository(); -- GameProfileCache gameProfileCache = new GameProfileCache(gameProfileRepository, new File(rootDirectory, "usercache.json")); +- GameProfileCache gameProfileCache = new GameProfileCache(gameProfileRepository, new File(profileRepository, "usercache.json")); - return new Services(minecraftSessionService, authenticationService.getServicesKeySet(), gameProfileRepository, gameProfileCache); + GameProfileCache gameProfileCache = new GameProfileCache(gameProfileRepository, userCacheFile); // Paper - use specified user cache file + // Paper start - load paper config files from cli options + final java.nio.file.Path legacyConfigPath = ((File) optionSet.valueOf("paper-settings")).toPath(); + final java.nio.file.Path configDirPath = ((File) optionSet.valueOf("paper-settings-directory")).toPath(); -+ io.papermc.paper.configuration.PaperConfigurations paperConfigurations = io.papermc.paper.configuration.PaperConfigurations.setup(legacyConfigPath, configDirPath, rootDirectory.toPath(), (File) optionSet.valueOf("spigot-settings")); ++ io.papermc.paper.configuration.PaperConfigurations paperConfigurations = io.papermc.paper.configuration.PaperConfigurations.setup(legacyConfigPath, configDirPath, profileRepository.toPath(), (File) optionSet.valueOf("spigot-settings")); + return new Services(minecraftSessionService, authenticationService.getServicesKeySet(), gameProfileRepository, gameProfileCache, paperConfigurations); + // Paper end - load paper config files from cli options } diff --git a/paper-server/patches/unapplied/net/minecraft/server/WorldLoader.java.patch b/paper-server/patches/sources/net/minecraft/server/WorldLoader.java.patch similarity index 73% rename from paper-server/patches/unapplied/net/minecraft/server/WorldLoader.java.patch rename to paper-server/patches/sources/net/minecraft/server/WorldLoader.java.patch index c95f9d743c..a2c0814152 100644 --- a/paper-server/patches/unapplied/net/minecraft/server/WorldLoader.java.patch +++ b/paper-server/patches/sources/net/minecraft/server/WorldLoader.java.patch @@ -1,11 +1,11 @@ --- a/net/minecraft/server/WorldLoader.java +++ b/net/minecraft/server/WorldLoader.java -@@ -37,7 +37,7 @@ +@@ -37,7 +_,7 @@ CloseableResourceManager closeableResourceManager = pair.getSecond(); LayeredRegistryAccess layeredRegistryAccess = RegistryLayer.createRegistryAccess(); List> list = TagLoader.loadTagsForExistingRegistries( - closeableResourceManager, layeredRegistryAccess.getLayer(RegistryLayer.STATIC) + closeableResourceManager, layeredRegistryAccess.getLayer(RegistryLayer.STATIC), io.papermc.paper.plugin.lifecycle.event.registrar.ReloadableRegistrarEvent.Cause.INITIAL // Paper - tag lifecycle - add cause ); - RegistryAccess.Frozen frozen = layeredRegistryAccess.getAccessForLoading(RegistryLayer.WORLDGEN); - List> list2 = TagLoader.buildUpdatedLookups(frozen, list); + RegistryAccess.Frozen accessForLoading = layeredRegistryAccess.getAccessForLoading(RegistryLayer.WORLDGEN); + List> list1 = TagLoader.buildUpdatedLookups(accessForLoading, list); diff --git a/paper-server/patches/unapplied/net/minecraft/server/Main.java.patch b/paper-server/patches/unapplied/net/minecraft/server/Main.java.patch deleted file mode 100644 index a9ae49e37f..0000000000 --- a/paper-server/patches/unapplied/net/minecraft/server/Main.java.patch +++ /dev/null @@ -1,290 +0,0 @@ ---- a/net/minecraft/server/Main.java -+++ b/net/minecraft/server/Main.java -@@ -38,6 +38,7 @@ - import net.minecraft.server.dedicated.DedicatedServerProperties; - import net.minecraft.server.dedicated.DedicatedServerSettings; - import net.minecraft.server.level.progress.LoggerChunkProgressListener; -+import net.minecraft.server.packs.PackType; - import net.minecraft.server.packs.repository.PackRepository; - import net.minecraft.server.packs.repository.ServerPacksSource; - import net.minecraft.util.Mth; -@@ -55,22 +56,31 @@ - import net.minecraft.world.level.levelgen.WorldOptions; - import net.minecraft.world.level.levelgen.presets.WorldPresets; - import net.minecraft.world.level.storage.LevelDataAndDimensions; -+import net.minecraft.world.level.storage.LevelResource; - import net.minecraft.world.level.storage.LevelStorageSource; - import net.minecraft.world.level.storage.LevelSummary; - import net.minecraft.world.level.storage.PrimaryLevelData; --import net.minecraft.world.level.storage.WorldData; - import org.slf4j.Logger; - -+// CraftBukkit start -+import com.google.common.base.Charsets; -+import java.io.InputStreamReader; -+import java.util.concurrent.atomic.AtomicReference; -+import net.minecraft.SharedConstants; -+import org.bukkit.configuration.file.YamlConfiguration; -+// CraftBukkit end -+ - public class Main { - - private static final Logger LOGGER = LogUtils.getLogger(); - - public Main() {} - -- @SuppressForbidden(a = "System.out needed before bootstrap") -+ @SuppressForbidden(reason = "System.out needed before bootstrap") // CraftBukkit - decompile error - @DontObfuscate -- public static void main(String[] args) { -+ public static void main(final OptionSet optionset) { // CraftBukkit - replaces main(String[] astring) - SharedConstants.tryDetectVersion(); -+ /* CraftBukkit start - Replace everything - OptionParser optionparser = new OptionParser(); - OptionSpec optionspec = optionparser.accepts("nogui"); - OptionSpec optionspec1 = optionparser.accepts("initSettings", "Initializes 'server.properties' and 'eula.txt', then quits"); -@@ -90,50 +100,104 @@ - OptionSpec optionspec15 = optionparser.nonOptions(); - - try { -- OptionSet optionset = optionparser.parse(args); -+ OptionSet optionset = optionparser.parse(astring); - - if (optionset.has(optionspec8)) { - optionparser.printHelpOn(System.err); - return; - } -+ */ // CraftBukkit end - -- Path path = (Path) optionset.valueOf(optionspec14); -+ try { - -+ Path path = (Path) optionset.valueOf("pidFile"); // CraftBukkit -+ - if (path != null) { - Main.writePidFile(path); - } - - CrashReport.preload(); -- if (optionset.has(optionspec13)) { -+ if (optionset.has("jfrProfile")) { // CraftBukkit - JvmProfiler.INSTANCE.start(Environment.SERVER); - } - -+ io.papermc.paper.plugin.PluginInitializerManager.load(optionset); // Paper - Bootstrap.bootStrap(); - Bootstrap.validate(); - Util.startTimerHackThread(); - Path path1 = Paths.get("server.properties"); -- DedicatedServerSettings dedicatedserversettings = new DedicatedServerSettings(path1); -+ DedicatedServerSettings dedicatedserversettings = new DedicatedServerSettings(optionset); // CraftBukkit - CLI argument support - - dedicatedserversettings.forceSave(); - RegionFileVersion.configure(dedicatedserversettings.getProperties().regionFileComression); - Path path2 = Paths.get("eula.txt"); - Eula eula = new Eula(path2); -+ // Paper start - load config files early for access below if needed -+ org.bukkit.configuration.file.YamlConfiguration bukkitConfiguration = io.papermc.paper.configuration.PaperConfigurations.loadLegacyConfigFile((File) optionset.valueOf("bukkit-settings")); -+ org.bukkit.configuration.file.YamlConfiguration spigotConfiguration = io.papermc.paper.configuration.PaperConfigurations.loadLegacyConfigFile((File) optionset.valueOf("spigot-settings")); -+ // Paper end - load config files early for access below if needed - -- if (optionset.has(optionspec1)) { -+ if (optionset.has("initSettings")) { // CraftBukkit -+ // CraftBukkit start - SPIGOT-5761: Create bukkit.yml and commands.yml if not present -+ File configFile = (File) optionset.valueOf("bukkit-settings"); -+ YamlConfiguration configuration = YamlConfiguration.loadConfiguration(configFile); -+ configuration.options().copyDefaults(true); -+ configuration.setDefaults(YamlConfiguration.loadConfiguration(new InputStreamReader(Main.class.getClassLoader().getResourceAsStream("configurations/bukkit.yml"), Charsets.UTF_8))); -+ configuration.save(configFile); -+ -+ File commandFile = (File) optionset.valueOf("commands-settings"); -+ YamlConfiguration commandsConfiguration = YamlConfiguration.loadConfiguration(commandFile); -+ commandsConfiguration.options().copyDefaults(true); -+ commandsConfiguration.setDefaults(YamlConfiguration.loadConfiguration(new InputStreamReader(Main.class.getClassLoader().getResourceAsStream("configurations/commands.yml"), Charsets.UTF_8))); -+ commandsConfiguration.save(commandFile); -+ // CraftBukkit end - Main.LOGGER.info("Initialized '{}' and '{}'", path1.toAbsolutePath(), path2.toAbsolutePath()); - return; - } - -- if (!eula.hasAgreedToEULA()) { -+ // Spigot Start -+ boolean eulaAgreed = Boolean.getBoolean( "com.mojang.eula.agree" ); -+ if ( eulaAgreed ) -+ { -+ System.err.println( "You have used the Spigot command line EULA agreement flag." ); -+ System.err.println( "By using this setting you are indicating your agreement to Mojang's EULA (https://account.mojang.com/documents/minecraft_eula)." ); -+ System.err.println( "If you do not agree to the above EULA please stop your server and remove this flag immediately." ); -+ } -+ // Spigot End -+ if (!eula.hasAgreedToEULA() && !eulaAgreed) { // Spigot - Main.LOGGER.info("You need to agree to the EULA in order to run the server. Go to eula.txt for more info."); - return; - } - -- File file = new File((String) optionset.valueOf(optionspec9)); -- Services services = Services.create(new YggdrasilAuthenticationService(Proxy.NO_PROXY), file); -- String s = (String) Optional.ofNullable((String) optionset.valueOf(optionspec10)).orElse(dedicatedserversettings.getProperties().levelName); -+ // Paper start - Detect headless JRE -+ String awtException = io.papermc.paper.util.ServerEnvironment.awtDependencyCheck(); -+ if (awtException != null) { -+ Main.LOGGER.error("You are using a headless JRE distribution."); -+ Main.LOGGER.error("This distribution is missing certain graphic libraries that the Minecraft server needs to function."); -+ Main.LOGGER.error("For instructions on how to install the non-headless JRE, see https://docs.papermc.io/misc/java-install"); -+ Main.LOGGER.error(""); -+ Main.LOGGER.error(awtException); -+ return; -+ } -+ // Paper end - Detect headless JRE -+ -+ org.spigotmc.SpigotConfig.disabledAdvancements = spigotConfiguration.getStringList("advancements.disabled"); // Paper - fix SPIGOT-5885, must be set early in init -+ // Paper start - fix SPIGOT-5824 -+ File file; -+ File userCacheFile = new File(Services.USERID_CACHE_FILE); -+ if (optionset.has("universe")) { -+ file = (File) optionset.valueOf("universe"); // CraftBukkit -+ userCacheFile = new File(file, Services.USERID_CACHE_FILE); -+ } else { -+ file = new File(bukkitConfiguration.getString("settings.world-container", ".")); -+ } -+ // Paper end - fix SPIGOT-5824 -+ Services services = Services.create(new com.destroystokyo.paper.profile.PaperAuthenticationService(Proxy.NO_PROXY), file, userCacheFile, optionset); // Paper - pass OptionSet to load paper config files; override authentication service; fix world-container -+ // CraftBukkit start -+ String s = (String) Optional.ofNullable((String) optionset.valueOf("world")).orElse(dedicatedserversettings.getProperties().levelName); - LevelStorageSource convertable = LevelStorageSource.createDefault(file.toPath()); -- LevelStorageSource.LevelStorageAccess convertable_conversionsession = convertable.validateAndCreateAccess(s); -+ LevelStorageSource.LevelStorageAccess convertable_conversionsession = convertable.validateAndCreateAccess(s, LevelStem.OVERWORLD); -+ // CraftBukkit end - Dynamic dynamic; - - if (convertable_conversionsession.hasWorldData()) { -@@ -174,13 +238,31 @@ - } - - Dynamic dynamic1 = dynamic; -- boolean flag = optionset.has(optionspec7); -+ boolean flag = optionset.has("safeMode"); // CraftBukkit - - if (flag) { - Main.LOGGER.warn("Safe mode active, only vanilla datapack will be loaded"); - } - - PackRepository resourcepackrepository = ServerPacksSource.createPackRepository(convertable_conversionsession); -+ // CraftBukkit start -+ File bukkitDataPackFolder = new File(convertable_conversionsession.getLevelPath(LevelResource.DATAPACK_DIR).toFile(), "bukkit"); -+ if (!bukkitDataPackFolder.exists()) { -+ bukkitDataPackFolder.mkdirs(); -+ } -+ File mcMeta = new File(bukkitDataPackFolder, "pack.mcmeta"); -+ try { -+ com.google.common.io.Files.write("{\n" -+ + " \"pack\": {\n" -+ + " \"description\": \"Data pack for resources provided by Bukkit plugins\",\n" -+ + " \"pack_format\": " + SharedConstants.getCurrentVersion().getPackVersion(PackType.SERVER_DATA) + "\n" -+ + " }\n" -+ + "}\n", mcMeta, com.google.common.base.Charsets.UTF_8); -+ } catch (java.io.IOException ex) { -+ throw new RuntimeException("Could not initialize Bukkit datapack", ex); -+ } -+ AtomicReference worldLoader = new AtomicReference<>(); -+ // CraftBukkit end - - WorldStem worldstem; - -@@ -189,6 +271,7 @@ - - worldstem = (WorldStem) Util.blockUntilDone((executor) -> { - return WorldLoader.load(worldloader_c, (worldloader_a) -> { -+ worldLoader.set(worldloader_a); // CraftBukkit - Registry iregistry = worldloader_a.datapackDimensions().lookupOrThrow(Registries.LEVEL_STEM); - - if (dynamic1 != null) { -@@ -201,7 +284,7 @@ - WorldOptions worldoptions; - WorldDimensions worlddimensions; - -- if (optionset.has(optionspec2)) { -+ if (optionset.has("demo")) { // CraftBukkit - worldsettings = MinecraftServer.DEMO_SETTINGS; - worldoptions = WorldOptions.DEMO_OPTIONS; - worlddimensions = WorldPresets.createNormalWorldDimensions(worldloader_a.datapackWorldgen()); -@@ -209,7 +292,7 @@ - DedicatedServerProperties dedicatedserverproperties = dedicatedserversettings.getProperties(); - - worldsettings = new LevelSettings(dedicatedserverproperties.levelName, dedicatedserverproperties.gamemode, dedicatedserverproperties.hardcore, dedicatedserverproperties.difficulty, false, new GameRules(worldloader_a.dataConfiguration().enabledFeatures()), worldloader_a.dataConfiguration()); -- worldoptions = optionset.has(optionspec3) ? dedicatedserverproperties.worldOptions.withBonusChest(true) : dedicatedserverproperties.worldOptions; -+ worldoptions = optionset.has("bonusChest") ? dedicatedserverproperties.worldOptions.withBonusChest(true) : dedicatedserverproperties.worldOptions; // CraftBukkit - worlddimensions = dedicatedserverproperties.createDimensions(worldloader_a.datapackWorldgen()); - } - -@@ -225,32 +308,47 @@ - return; - } - -- RegistryAccess.Frozen iregistrycustom_dimension = worldstem.registries().compositeAccess(); -+ /* -+ IRegistryCustom.Dimension iregistrycustom_dimension = worldstem.registries().compositeAccess(); - boolean flag1 = optionset.has(optionspec6); - - if (optionset.has(optionspec4) || flag1) { -- Main.forceUpgrade(convertable_conversionsession, DataFixers.getDataFixer(), optionset.has(optionspec5), () -> { -+ forceUpgrade(convertable_conversionsession, DataConverterRegistry.getDataFixer(), optionset.has(optionspec5), () -> { - return true; - }, iregistrycustom_dimension, flag1); - } - -- WorldData savedata = worldstem.worldData(); -+ SaveData savedata = worldstem.worldData(); - - convertable_conversionsession.saveDataTag(iregistrycustom_dimension, savedata); -+ */ - final DedicatedServer dedicatedserver = (DedicatedServer) MinecraftServer.spin((thread) -> { -- DedicatedServer dedicatedserver1 = new DedicatedServer(thread, convertable_conversionsession, resourcepackrepository, worldstem, dedicatedserversettings, DataFixers.getDataFixer(), services, LoggerChunkProgressListener::createFromGameruleRadius); -+ DedicatedServer dedicatedserver1 = new DedicatedServer(optionset, worldLoader.get(), thread, convertable_conversionsession, resourcepackrepository, worldstem, dedicatedserversettings, DataFixers.getDataFixer(), services, LoggerChunkProgressListener::createFromGameruleRadius); - -+ /* - dedicatedserver1.setPort((Integer) optionset.valueOf(optionspec11)); -- dedicatedserver1.setDemo(optionset.has(optionspec2)); -+ */ -+ dedicatedserver1.setDemo(optionset.has("demo")); // Paper -+ /* - dedicatedserver1.setId((String) optionset.valueOf(optionspec12)); -- boolean flag2 = !optionset.has(optionspec) && !optionset.valuesOf(optionspec15).contains("nogui"); -+ */ -+ boolean flag2 = !optionset.has("nogui") && !optionset.nonOptionArguments().contains("nogui"); - -+ if(!Boolean.parseBoolean(System.getenv().getOrDefault("PAPER_DISABLE_SERVER_GUI", String.valueOf(false)))) // Paper - Add environment variable to disable server gui - if (flag2 && !GraphicsEnvironment.isHeadless()) { - dedicatedserver1.showGui(); - } - -+ if (optionset.has("port")) { -+ int port = (Integer) optionset.valueOf("port"); -+ if (port > 0) { -+ dedicatedserver1.setPort(port); -+ } -+ } -+ - return dedicatedserver1; - }); -+ /* CraftBukkit start - Thread thread = new Thread("Server Shutdown Thread") { - public void run() { - dedicatedserver.halt(true); -@@ -259,6 +357,7 @@ - - thread.setUncaughtExceptionHandler(new DefaultUncaughtExceptionHandler(Main.LOGGER)); - Runtime.getRuntime().addShutdownHook(thread); -+ */ // CraftBukkit end - } catch (Exception exception1) { - Main.LOGGER.error(LogUtils.FATAL_MARKER, "Failed to start the minecraft server", exception1); - } -@@ -295,7 +394,7 @@ - } - - public static void forceUpgrade(LevelStorageSource.LevelStorageAccess session, DataFixer dataFixer, boolean eraseCache, BooleanSupplier continueCheck, RegistryAccess dynamicRegistryManager, boolean recreateRegionFiles) { -- Main.LOGGER.info("Forcing world upgrade!"); -+ Main.LOGGER.info("Forcing world upgrade! {}", session.getLevelId()); // CraftBukkit - WorldUpgrader worldupgrader = new WorldUpgrader(session, dataFixer, dynamicRegistryManager, eraseCache, recreateRegionFiles); - - try { diff --git a/paper-server/patches/unapplied/net/minecraft/server/ReloadableServerRegistries.java.patch b/paper-server/patches/unapplied/net/minecraft/server/ReloadableServerRegistries.java.patch deleted file mode 100644 index 6c906a073c..0000000000 --- a/paper-server/patches/unapplied/net/minecraft/server/ReloadableServerRegistries.java.patch +++ /dev/null @@ -1,32 +0,0 @@ ---- a/net/minecraft/server/ReloadableServerRegistries.java -+++ b/net/minecraft/server/ReloadableServerRegistries.java -@@ -50,8 +50,9 @@ - ); - HolderLookup.Provider provider = HolderLookup.Provider.create(list.stream()); - RegistryOps registryOps = provider.createSerializationContext(JsonOps.INSTANCE); -+ final io.papermc.paper.registry.data.util.Conversions conversions = new io.papermc.paper.registry.data.util.Conversions(registryOps.lookupProvider); // Paper - List>> list2 = LootDataType.values() -- .map(type -> scheduleRegistryLoad((LootDataType)type, registryOps, resourceManager, prepareExecutor)) -+ .map(type -> scheduleRegistryLoad((LootDataType)type, registryOps, resourceManager, prepareExecutor, conversions)) // Paper - .toList(); - CompletableFuture>> completableFuture = Util.sequence(list2); - return completableFuture.thenApplyAsync( -@@ -60,14 +61,15 @@ - } - - private static CompletableFuture> scheduleRegistryLoad( -- LootDataType type, RegistryOps ops, ResourceManager resourceManager, Executor prepareExecutor -+ LootDataType type, RegistryOps ops, ResourceManager resourceManager, Executor prepareExecutor, io.papermc.paper.registry.data.util.Conversions conversions // Paper - ) { - return CompletableFuture.supplyAsync(() -> { - WritableRegistry writableRegistry = new MappedRegistry<>(type.registryKey(), Lifecycle.experimental()); -+ io.papermc.paper.registry.PaperRegistryAccess.instance().registerReloadableRegistry(type.registryKey(), writableRegistry); // Paper - register reloadable registry - Map map = new HashMap<>(); - SimpleJsonResourceReloadListener.scanDirectory(resourceManager, type.registryKey(), ops, type.codec(), map); -- map.forEach((id, value) -> writableRegistry.register(ResourceKey.create(type.registryKey(), id), (T)value, DEFAULT_REGISTRATION_INFO)); -- TagLoader.loadTagsForRegistry(resourceManager, writableRegistry); -+ map.forEach((id, value) -> io.papermc.paper.registry.PaperRegistryListenerManager.INSTANCE.registerWithListeners(writableRegistry, ResourceKey.create(type.registryKey(), id), value, DEFAULT_REGISTRATION_INFO, conversions)); // Paper - register with listeners -+ TagLoader.loadTagsForRegistry(resourceManager, writableRegistry, io.papermc.paper.plugin.lifecycle.event.registrar.ReloadableRegistrarEvent.Cause.RELOAD); // Paper - tag life cycle - reload - return writableRegistry; - }, prepareExecutor); - } diff --git a/paper-server/patches/unapplied/net/minecraft/server/ServerFunctionLibrary.java.patch b/paper-server/patches/unapplied/net/minecraft/server/ServerFunctionLibrary.java.patch deleted file mode 100644 index a5f6fd5796..0000000000 --- a/paper-server/patches/unapplied/net/minecraft/server/ServerFunctionLibrary.java.patch +++ /dev/null @@ -1,11 +0,0 @@ ---- a/net/minecraft/server/ServerFunctionLibrary.java -+++ b/net/minecraft/server/ServerFunctionLibrary.java -@@ -113,7 +113,7 @@ - return null; - }).join()); - this.functions = builder.build(); -- this.tags = this.tagsLoader.build((Map>)intermediate.getFirst()); -+ this.tags = this.tagsLoader.build((Map>)intermediate.getFirst(), null); // Paper - command function tags are not implemented yet - }, - applyExecutor - );