From 56a7d4627979e97f2676a7cd6afe0a7ffec61c23 Mon Sep 17 00:00:00 2001 From: granny Date: Sat, 3 Jan 2026 18:30:46 -0800 Subject: [PATCH] Updated Upstream (Paper) Upstream has released updates that appear to apply and compile correctly Paper Changes: PaperMC/Paper@8f736dbf Improve outdated version check (#12589) PaperMC/Paper@3ebc5b33 Don't apply oversized sanitizers in components disabled by config (#13466) --- gradle.properties | 4 +- .../features/0001-Ridables.patch | 4 +- ...etting-to-reintroduce-end-void-rings.patch | 4 +- .../server/MinecraftServer.java.patch | 14 +- ...etting-to-reintroduce-end-void-rings.patch | 6 +- .../paper/PaperVersionFetcher.java.patch | 78 --------- .../org/bukkit/craftbukkit/Main.java.patch | 11 +- .../util/CraftMagicNumbers.java.patch | 11 ++ .../purpurmc/purpur/PurpurVersionFetcher.java | 157 ++++++++++++++++++ 9 files changed, 188 insertions(+), 101 deletions(-) delete mode 100644 purpur-server/paper-patches/files/src/main/java/com/destroystokyo/paper/PaperVersionFetcher.java.patch create mode 100644 purpur-server/paper-patches/files/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java.patch create mode 100644 purpur-server/src/main/java/org/purpurmc/purpur/PurpurVersionFetcher.java diff --git a/gradle.properties b/gradle.properties index 1c1a0ccaa..fd29c2ce4 100644 --- a/gradle.properties +++ b/gradle.properties @@ -2,8 +2,8 @@ group = org.purpurmc.purpur version = 1.21.11-R0.1-SNAPSHOT mcVersion = 1.21.11 -apiVersion=1.21.11 -paperCommit = cd445fdb26d7b159f5c2726acee5db113a3bbff9 +apiVersion = 1.21.11 +paperCommit = 3ebc5b3320924e9122903dfd1f11abcf897300e6 org.gradle.configuration-cache = true org.gradle.caching = true diff --git a/purpur-server/minecraft-patches/features/0001-Ridables.patch b/purpur-server/minecraft-patches/features/0001-Ridables.patch index 2f88e7a36..3230320c5 100644 --- a/purpur-server/minecraft-patches/features/0001-Ridables.patch +++ b/purpur-server/minecraft-patches/features/0001-Ridables.patch @@ -18,10 +18,10 @@ index 05eb0c3273ffa1b5a1ebd8f8ae42c11830d755c7..49d3154afe2ca5789e63bdf972c79196 public boolean isClientAuthoritative() { return false; diff --git a/net/minecraft/server/MinecraftServer.java b/net/minecraft/server/MinecraftServer.java -index 3b773fc2a357811cb63f48b0ae351efbcd3878b0..5acc46e0d16c365d67c14d0c2bfc4346d4f46f21 100644 +index 2e7dd34a7ba74b6545ccc92ba109def077c2618f..e842e82e8915f8e0d95013f7f731914202dc6b7b 100644 --- a/net/minecraft/server/MinecraftServer.java +++ b/net/minecraft/server/MinecraftServer.java -@@ -1833,6 +1833,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop 0; // Paper - Add EntityMoveEvent serverLevel.updateLagCompensationTick(); // Paper - lag compensation net.minecraft.world.level.block.entity.HopperBlockEntity.skipHopperEvents = serverLevel.paperConfig().hopper.disableMoveEvent || org.bukkit.event.inventory.InventoryMoveItemEvent.getHandlerList().getRegisteredListeners().length == 0; // Paper - Perf: Optimize Hoppers diff --git a/purpur-server/minecraft-patches/features/0020-Setting-to-reintroduce-end-void-rings.patch b/purpur-server/minecraft-patches/features/0020-Setting-to-reintroduce-end-void-rings.patch index 0c35dd916..0ff6100f4 100644 --- a/purpur-server/minecraft-patches/features/0020-Setting-to-reintroduce-end-void-rings.patch +++ b/purpur-server/minecraft-patches/features/0020-Setting-to-reintroduce-end-void-rings.patch @@ -5,10 +5,10 @@ Subject: [PATCH] Setting to reintroduce end void rings diff --git a/net/minecraft/server/MinecraftServer.java b/net/minecraft/server/MinecraftServer.java -index cfd9596246713030f7c0f28a65abeed6dcc8d81b..952444a26fd13ae0b385b2b7f717d965b4c76d19 100644 +index e842e82e8915f8e0d95013f7f731914202dc6b7b..fc56c5cace242821b8d40847e01081ee41c61ef6 100644 --- a/net/minecraft/server/MinecraftServer.java +++ b/net/minecraft/server/MinecraftServer.java -@@ -1315,6 +1315,15 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop catchup) { -@@ -1787,7 +_,7 @@ +@@ -1792,7 +_,7 @@ long worldTime = level.getGameTime(); final ClientboundSetTimePacket worldPacket = new ClientboundSetTimePacket(worldTime, dayTime, doDaylight); for (Player entityhuman : level.players()) { @@ -88,7 +94,7 @@ continue; } ServerPlayer entityplayer = (ServerPlayer) entityhuman; -@@ -1954,7 +_,7 @@ +@@ -1959,7 +_,7 @@ @DontObfuscate public String getServerModName() { diff --git a/purpur-server/paper-patches/features/0005-Setting-to-reintroduce-end-void-rings.patch b/purpur-server/paper-patches/features/0005-Setting-to-reintroduce-end-void-rings.patch index b7cc77220..20fbd8064 100644 --- a/purpur-server/paper-patches/features/0005-Setting-to-reintroduce-end-void-rings.patch +++ b/purpur-server/paper-patches/features/0005-Setting-to-reintroduce-end-void-rings.patch @@ -5,10 +5,10 @@ Subject: [PATCH] Setting to reintroduce end void rings diff --git a/src/main/java/io/papermc/paper/configuration/GlobalConfiguration.java b/src/main/java/io/papermc/paper/configuration/GlobalConfiguration.java -index c52d2530f6bfd601e8af8fd6713e6870cf5611d3..c95bca1a3100952fb02a7bff46fcf9155b185a80 100644 +index e47f279b66b169e2cdf762bb739a261f2acebeb1..cc1906ef871de6a4ff82039d8ddfcd764139f37d 100644 --- a/src/main/java/io/papermc/paper/configuration/GlobalConfiguration.java +++ b/src/main/java/io/papermc/paper/configuration/GlobalConfiguration.java -@@ -300,6 +300,7 @@ public class GlobalConfiguration extends ConfigurationPart { +@@ -303,6 +303,7 @@ public class GlobalConfiguration extends ConfigurationPart { } } @@ -16,7 +16,7 @@ index c52d2530f6bfd601e8af8fd6713e6870cf5611d3..c95bca1a3100952fb02a7bff46fcf915 public Misc misc; public class Misc extends ConfigurationPart { -@@ -346,6 +347,7 @@ public class GlobalConfiguration extends ConfigurationPart { +@@ -349,6 +350,7 @@ public class GlobalConfiguration extends ConfigurationPart { @Comment("Whether the nether dimension is enabled and will be loaded.") public boolean enableNether = true; @Comment("Keeps Paper's fix for MC-159283 enabled. Disable to use vanilla End ring terrain.") diff --git a/purpur-server/paper-patches/files/src/main/java/com/destroystokyo/paper/PaperVersionFetcher.java.patch b/purpur-server/paper-patches/files/src/main/java/com/destroystokyo/paper/PaperVersionFetcher.java.patch deleted file mode 100644 index 8440b425a..000000000 --- a/purpur-server/paper-patches/files/src/main/java/com/destroystokyo/paper/PaperVersionFetcher.java.patch +++ /dev/null @@ -1,78 +0,0 @@ ---- a/src/main/java/com/destroystokyo/paper/PaperVersionFetcher.java -+++ b/src/main/java/com/destroystokyo/paper/PaperVersionFetcher.java -@@ -35,7 +_,10 @@ - private static final Logger LOGGER = LogUtils.getClassLogger(); - private static final int DISTANCE_ERROR = -1; - private static final int DISTANCE_UNKNOWN = -2; -- private static final String DOWNLOAD_PAGE = "https://papermc.io/downloads/paper"; -+ // Purpur start - Rebrand -+ private static final String DOWNLOAD_PAGE = "https://purpurmc.org/downloads"; -+ private static int distance = DISTANCE_UNKNOWN; public int distance() { return distance; } -+ // Purpur end - Rebrand - - @Override - public long getCacheTime() { -@@ -49,7 +_,7 @@ - if (build.buildNumber().isEmpty() && build.gitCommit().isEmpty()) { - updateMessage = text("You are running a development version without access to version information", color(0xFF5300)); - } else { -- updateMessage = getUpdateStatusMessage("PaperMC/Paper", build); -+ updateMessage = getUpdateStatusMessage("PurpurMC/Purpur", build); // Purpur - Rebrand - } - final @Nullable Component history = this.getHistory(); - -@@ -57,7 +_,7 @@ - } - - private static Component getUpdateStatusMessage(final String repo, final ServerBuildInfo build) { -- int distance = DISTANCE_ERROR; -+ //int distance = DISTANCE_ERROR; // Purpur - use field - Rebrand - - final OptionalInt buildNumber = build.buildNumber(); - if (buildNumber.isPresent()) { -@@ -71,10 +_,10 @@ - } - - return switch (distance) { -- case DISTANCE_ERROR -> text("Error obtaining version information", NamedTextColor.YELLOW); -- case 0 -> text("You are running the latest version", NamedTextColor.GREEN); -- case DISTANCE_UNKNOWN -> text("Unknown version", NamedTextColor.YELLOW); -- default -> text("You are " + distance + " version(s) behind", NamedTextColor.YELLOW) -+ case DISTANCE_ERROR -> text("* Error obtaining version information", NamedTextColor.RED); // Purpur - Rebrand -+ case 0 -> text("* You are running the latest version", NamedTextColor.GREEN); // Purpur - Rebrand -+ case DISTANCE_UNKNOWN -> text("* Unknown version", NamedTextColor.YELLOW); // Purpur - Rebrand -+ default -> text("* You are " + distance + " version(s) behind", NamedTextColor.YELLOW) // Purpur - Rebrand - .append(Component.newline()) - .append(text("Download the new version at: ") - .append(text(DOWNLOAD_PAGE, NamedTextColor.GOLD) -@@ -86,18 +_,15 @@ - private static int fetchDistanceFromSiteApi(final ServerBuildInfo build, final int jenkinsBuild) { - try { - try (final BufferedReader reader = Resources.asCharSource( -- URI.create("https://api.papermc.io/v2/projects/paper/versions/" + build.minecraftVersionId()).toURL(), -+ URI.create("https://api.purpurmc.org/v2/purpur/" + build.minecraftVersionId()).toURL(), // Purpur - Rebrand - StandardCharsets.UTF_8 - ).openBufferedStream()) { - final JsonObject json = new Gson().fromJson(reader, JsonObject.class); -- final JsonArray builds = json.getAsJsonArray("builds"); -- final int latest = StreamSupport.stream(builds.spliterator(), false) -- .mapToInt(JsonElement::getAsInt) -- .max() -- .orElseThrow(); -+ //final JsonArray builds = json.getAsJsonArray("builds"); // Purpur - Rebrand -+ final int latest = json.getAsJsonObject("builds").getAsJsonPrimitive("latest").getAsInt(); // Purpur - Rebrand - return latest - jenkinsBuild; - } catch (final JsonSyntaxException ex) { -- LOGGER.error("Error parsing json from Paper's downloads API", ex); -+ LOGGER.error("Error parsing json from Purpur's downloads API", ex); // Purpur - Rebrand - return DISTANCE_ERROR; - } - } catch (final IOException e) { -@@ -141,6 +_,6 @@ - return null; - } - -- return text("Previous version: " + oldVersion, NamedTextColor.GRAY, TextDecoration.ITALIC); -+ return text("Previous: " + oldVersion, NamedTextColor.GRAY); // Purpur - Rebrand - } - } diff --git a/purpur-server/paper-patches/files/src/main/java/org/bukkit/craftbukkit/Main.java.patch b/purpur-server/paper-patches/files/src/main/java/org/bukkit/craftbukkit/Main.java.patch index 5de962abf..e119ec6c7 100644 --- a/purpur-server/paper-patches/files/src/main/java/org/bukkit/craftbukkit/Main.java.patch +++ b/purpur-server/paper-patches/files/src/main/java/org/bukkit/craftbukkit/Main.java.patch @@ -1,6 +1,6 @@ --- a/src/main/java/org/bukkit/craftbukkit/Main.java +++ b/src/main/java/org/bukkit/craftbukkit/Main.java -@@ -164,6 +_,14 @@ +@@ -162,6 +_,14 @@ .defaultsTo(new File[] {}) .describedAs("Jar file"); @@ -15,12 +15,3 @@ this.accepts("server-name", "Name of the server") .withRequiredArg() .ofType(String.class) -@@ -223,7 +_,7 @@ - System.setProperty(net.minecrell.terminalconsole.TerminalConsoleAppender.JLINE_OVERRIDE_PROPERTY, "false"); // Paper - } - -- if (Main.class.getPackage().getImplementationVendor() != null && System.getProperty("IReallyKnowWhatIAmDoingISwear") == null) { -+ if (false && Main.class.getPackage().getImplementationVendor() != null && System.getProperty("IReallyKnowWhatIAmDoingISwear") == null) { // Purpur - Disable outdated build check - Date buildDate = new java.text.SimpleDateFormat("yyyy-MM-dd HH:mm:ss Z").parse(Main.class.getPackage().getImplementationVendor()); // Paper - - Calendar deadline = Calendar.getInstance(); diff --git a/purpur-server/paper-patches/files/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java.patch b/purpur-server/paper-patches/files/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java.patch new file mode 100644 index 000000000..8d4551161 --- /dev/null +++ b/purpur-server/paper-patches/files/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java.patch @@ -0,0 +1,11 @@ +--- a/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java ++++ b/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java +@@ -487,7 +_,7 @@ + + @Override + public com.destroystokyo.paper.util.VersionFetcher getVersionFetcher() { +- return new com.destroystokyo.paper.PaperVersionFetcher(); ++ return new org.purpurmc.purpur.PurpurVersionFetcher(); // Purpur - use old Paper version checker + } + + @Override diff --git a/purpur-server/src/main/java/org/purpurmc/purpur/PurpurVersionFetcher.java b/purpur-server/src/main/java/org/purpurmc/purpur/PurpurVersionFetcher.java new file mode 100644 index 000000000..f2c22af96 --- /dev/null +++ b/purpur-server/src/main/java/org/purpurmc/purpur/PurpurVersionFetcher.java @@ -0,0 +1,157 @@ +package org.purpurmc.purpur; + +import com.destroystokyo.paper.VersionHistoryManager; +import com.destroystokyo.paper.util.VersionFetcher; +import com.google.common.io.Resources; +import com.google.gson.Gson; +import com.google.gson.JsonObject; +import com.google.gson.JsonSyntaxException; +import com.mojang.logging.LogUtils; +import io.papermc.paper.ServerBuildInfo; +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStreamReader; +import java.net.HttpURLConnection; +import java.net.URI; +import java.nio.charset.StandardCharsets; +import java.util.Optional; +import java.util.OptionalInt; +import net.kyori.adventure.text.Component; +import net.kyori.adventure.text.event.ClickEvent; +import net.kyori.adventure.text.format.NamedTextColor; +import org.checkerframework.checker.nullness.qual.NonNull; +import org.checkerframework.checker.nullness.qual.Nullable; +import org.checkerframework.framework.qual.DefaultQualifier; +import org.slf4j.Logger; + +import static net.kyori.adventure.text.Component.text; +import static net.kyori.adventure.text.format.TextColor.color; +import static io.papermc.paper.ServerBuildInfo.StringRepresentation.VERSION_SIMPLE; + +/** + * Modified version of Paper's Version Fetcher before Fill API implementation. + */ +@DefaultQualifier(NonNull.class) +public class PurpurVersionFetcher implements VersionFetcher { + private static final Logger LOGGER = LogUtils.getClassLogger(); + private static final int DISTANCE_ERROR = -1; + private static final int DISTANCE_UNKNOWN = -2; + private static final String DOWNLOAD_PAGE = "https://purpurmc.org/downloads"; + private static final String REPOSITORY = "PurpurMC/Purpur"; + private static final ServerBuildInfo BUILD_INFO; + private static final String USER_AGENT; + private static final Gson GSON = new Gson(); + + static { + BUILD_INFO = ServerBuildInfo.buildInfo(); + USER_AGENT = BUILD_INFO.brandName() + "/" + BUILD_INFO.asString(VERSION_SIMPLE) + " (https://purpurmc.org)"; + } + + private static int distance = DISTANCE_UNKNOWN; + public int distance() { + return distance; + } + + @Override + public long getCacheTime() { + return 720000; + } + + @Override + public Component getVersionMessage() { + final Component updateMessage; + if (BUILD_INFO.buildNumber().isEmpty() && BUILD_INFO.gitCommit().isEmpty()) { + updateMessage = text("You are running a development version without access to version information", color(0xFF5300)); + } else { + updateMessage = getUpdateStatusMessage(); + } + final @Nullable Component history = this.getHistory(); + + return history != null ? Component.textOfChildren(updateMessage, Component.newline(), history) : updateMessage; + } + + private static Component getUpdateStatusMessage() { + final OptionalInt buildNumber = BUILD_INFO.buildNumber(); + if (buildNumber.isPresent()) { + distance = fetchDistanceFromSiteApi(buildNumber.getAsInt()); + } else { + final Optional gitBranch = BUILD_INFO.gitBranch(); + final Optional gitCommit = BUILD_INFO.gitCommit(); + if (gitBranch.isPresent() && gitCommit.isPresent()) { + distance = fetchDistanceFromGitHub(gitBranch.get(), gitCommit.get()); + } + } + + return switch (distance) { + case DISTANCE_ERROR -> text("* Error obtaining version information", NamedTextColor.RED); + case 0 -> text("* You are running the latest version", NamedTextColor.GREEN); + case DISTANCE_UNKNOWN -> text("* Unknown version", NamedTextColor.YELLOW); + default -> text("* You are " + distance + " version(s) behind", NamedTextColor.YELLOW) + .append(Component.newline()) + .append(text("Download the new version at: ") + .append(text(DOWNLOAD_PAGE, NamedTextColor.GOLD) + .hoverEvent(text("Click to open", NamedTextColor.WHITE)) + .clickEvent(ClickEvent.openUrl(DOWNLOAD_PAGE)))); + }; + } + + private static int fetchDistanceFromSiteApi(final int jenkinsBuild) { + try { + try (final BufferedReader reader = Resources.asCharSource( + URI.create("https://api.purpurmc.org/v2/purpur/" + BUILD_INFO.minecraftVersionId()).toURL(), + StandardCharsets.UTF_8 + ).openBufferedStream()) { + final JsonObject json = new Gson().fromJson(reader, JsonObject.class); + final int latest = json.getAsJsonObject("builds").getAsJsonPrimitive("latest").getAsInt(); + return latest - jenkinsBuild; + } catch (final JsonSyntaxException ex) { + LOGGER.error("Error parsing json from Purpur's downloads API", ex); + return DISTANCE_ERROR; + } + } catch (final IOException e) { + LOGGER.error("Error while parsing version", e); + return DISTANCE_ERROR; + } + } + + // Contributed by Techcable in PaperMC/Paper GH-65 + private static int fetchDistanceFromGitHub(final String branch, final String hash) { + try { + final HttpURLConnection connection = (HttpURLConnection) URI.create("https://api.github.com/repos/%s/compare/%s...%s".formatted(REPOSITORY, branch, hash)).toURL().openConnection(); + connection.setConnectTimeout(5000); + connection.setReadTimeout(5000); + connection.setRequestProperty("User-Agent", USER_AGENT); + connection.connect(); + if (connection.getResponseCode() == HttpURLConnection.HTTP_NOT_FOUND) return DISTANCE_UNKNOWN; // Unknown commit + try (final BufferedReader reader = new BufferedReader(new InputStreamReader(connection.getInputStream(), StandardCharsets.UTF_8))) { + final JsonObject obj = GSON.fromJson(reader, JsonObject.class); + final String status = obj.get("status").getAsString(); + return switch (status) { + case "identical" -> 0; + case "behind" -> obj.get("behind_by").getAsInt(); + default -> DISTANCE_ERROR; + }; + } catch (final JsonSyntaxException | NumberFormatException e) { + LOGGER.error("Error parsing json from GitHub's API", e); + return DISTANCE_ERROR; + } + } catch (final IOException e) { + LOGGER.error("Error while parsing version", e); + return DISTANCE_ERROR; + } + } + + private @Nullable Component getHistory() { + final VersionHistoryManager.@Nullable VersionData data = VersionHistoryManager.INSTANCE.getVersionData(); + if (data == null) { + return null; + } + + final @Nullable String oldVersion = data.getOldVersion(); + if (oldVersion == null) { + return null; + } + + return text("Previous: " + oldVersion, NamedTextColor.GRAY); + } +}