Skip to content
This repository was archived by the owner on Dec 29, 2023. It is now read-only.

Commit c0efbb2

Browse files
committed
Implement [Paper-0009/0019] Version Command 2.0/Implement Paper VersionChecker by Zach Brown
1 parent a1b091e commit c0efbb2

3 files changed

+320
-0
lines changed

README.md

+2
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,9 @@ Titanium implements patches from other engines as well. **All credits go to the
6767
[Spigot-5294] Cancelled EntityPickupItemEvent and PlayerPickupItemEvent alter on-ground stacks by md_5
6868
[Spigot-5428] Better handling of some ItemMeta by Mathias
6969
70+
[Paper-0009] Version Command 2.0 by Zach Brown
7071
[Paper-0008/0013] Add command line option to load extra plugin jars not in the plugins folder by Jason Penilla
72+
[Paper-0019] Implement Paper VersionChecker by Zach Brown
7173
[Paper-0022] Further improve server tick loop by Aikar
7274
[Paper-0044] Use UserCache for player heads
7375
[Paper-0072] Fix Furnace cook time bug when lagging by Aikar
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,166 @@
1+
From e287143a0564758a618d88ef6647087d96d4b784 Mon Sep 17 00:00:00 2001
2+
From: Zach Brown <[email protected]>
3+
Date: Fri, 4 Nov 2022 16:56:56 +0100
4+
Subject: [PATCH] Implement [Paper-0009] Version Command 2.0 by Zach Brown
5+
6+
7+
diff --git a/src/main/java/com/destroystokyo/paper/util/VersionFetcher.java b/src/main/java/com/destroystokyo/paper/util/VersionFetcher.java
8+
new file mode 100644
9+
index 00000000..46af13c9
10+
--- /dev/null
11+
+++ b/src/main/java/com/destroystokyo/paper/util/VersionFetcher.java
12+
@@ -0,0 +1,43 @@
13+
+package com.destroystokyo.paper.util;
14+
+
15+
+import org.bukkit.Bukkit;
16+
+import org.jetbrains.annotations.NotNull;
17+
+
18+
+public interface VersionFetcher {
19+
+ /**
20+
+ * Amount of time to cache results for in milliseconds
21+
+ * <p>
22+
+ * Negative values will never cache.
23+
+ *
24+
+ * @return cache time
25+
+ */
26+
+ long getCacheTime();
27+
+
28+
+ /**
29+
+ * Gets the version message to cache and show to command senders.
30+
+ *
31+
+ * <p>NOTE: This is run in a new thread separate from that of the command processing thread</p>
32+
+ *
33+
+ * @param serverVersion the current version of the server (will match {@link Bukkit#getVersion()})
34+
+ * @return the message to show when requesting a version
35+
+ */
36+
+ @NotNull
37+
+ String getVersionMessage(@NotNull String serverVersion);
38+
+
39+
+ class DummyVersionFetcher implements VersionFetcher {
40+
+
41+
+ @Override
42+
+ public long getCacheTime() {
43+
+ return -1;
44+
+ }
45+
+
46+
+ @NotNull
47+
+ @Override
48+
+ public String getVersionMessage(@NotNull String serverVersion) {
49+
+ Bukkit.getLogger().warning("Version provider has not been set, cannot check for updates!");
50+
+ Bukkit.getLogger().info("Override the default implementation of org.bukkit.UnsafeValues#getVersionFetcher()");
51+
+ new Throwable().printStackTrace();
52+
+ return "Unable to check for updates. No version provider set.";
53+
+ }
54+
+ }
55+
+}
56+
\ No newline at end of file
57+
diff --git a/src/main/java/org/bukkit/UnsafeValues.java b/src/main/java/org/bukkit/UnsafeValues.java
58+
index 73dd599c..a7d571f7 100644
59+
--- a/src/main/java/org/bukkit/UnsafeValues.java
60+
+++ b/src/main/java/org/bukkit/UnsafeValues.java
61+
@@ -36,4 +36,14 @@ public interface UnsafeValues {
62+
63+
ItemStack deserializeItem(byte[] data);
64+
// PandaSpigot end
65+
+
66+
+ // Paper start
67+
+ /**
68+
+ * Called once by the version command on first use, then cached.
69+
+ */
70+
+ default com.destroystokyo.paper.util.VersionFetcher getVersionFetcher() {
71+
+ return new com.destroystokyo.paper.util.VersionFetcher.DummyVersionFetcher();
72+
+ }
73+
+ // Paper end
74+
+
75+
}
76+
diff --git a/src/main/java/org/bukkit/command/defaults/VersionCommand.java b/src/main/java/org/bukkit/command/defaults/VersionCommand.java
77+
index d49d0ded..d4b5c757 100644
78+
--- a/src/main/java/org/bukkit/command/defaults/VersionCommand.java
79+
+++ b/src/main/java/org/bukkit/command/defaults/VersionCommand.java
80+
@@ -1,5 +1,6 @@
81+
package org.bukkit.command.defaults;
82+
83+
+import com.destroystokyo.paper.util.VersionFetcher;
84+
import com.google.common.base.Charsets;
85+
import java.util.ArrayList;
86+
import java.util.Arrays;
87+
@@ -29,6 +30,17 @@ import org.json.simple.parser.JSONParser;
88+
import org.json.simple.parser.ParseException;
89+
90+
public class VersionCommand extends BukkitCommand {
91+
+ // Paper start
92+
+ private VersionFetcher versionFetcher;
93+
+ private VersionFetcher getVersionFetcher() { // lazy load because unsafe isn't available at command registration
94+
+ if (versionFetcher == null) {
95+
+ versionFetcher = Bukkit.getUnsafe().getVersionFetcher();
96+
+ }
97+
+
98+
+ return versionFetcher;
99+
+ }
100+
+ // Paper end
101+
+
102+
public VersionCommand(String name) {
103+
super(name);
104+
105+
@@ -43,7 +55,7 @@ public class VersionCommand extends BukkitCommand {
106+
if (!testPermission(sender)) return true;
107+
108+
if (args.length == 0) {
109+
- sender.sendMessage(ChatColor.translateAlternateColorCodes('&', "&8>> &7This server is running &5Titanium &8(&fMC: 1.8.8&8) - &7Implementing API version &f" + Bukkit.getBukkitVersion()));
110+
+ //sender.sendMessage(ChatColor.translateAlternateColorCodes('&', "&8>> &7This server is running &5Titanium &8(&fMC: 1.8.8&8) - &7Implementing API version &f" + Bukkit.getBukkitVersion())); // Paper - moved to setVersionMessage
111+
sendVersion(sender);
112+
} else {
113+
StringBuilder name = new StringBuilder();
114+
@@ -150,7 +162,7 @@ public class VersionCommand extends BukkitCommand {
115+
116+
private void sendVersion(CommandSender sender) {
117+
if (hasVersion) {
118+
- if (System.currentTimeMillis() - lastCheck > 21600000) {
119+
+ if (System.currentTimeMillis() - lastCheck > getVersionFetcher().getCacheTime()) { // Paper - use version supplier
120+
lastCheck = System.currentTimeMillis();
121+
hasVersion = false;
122+
} else {
123+
@@ -165,7 +177,7 @@ public class VersionCommand extends BukkitCommand {
124+
return;
125+
}
126+
versionWaiters.add(sender);
127+
- sender.sendMessage("Checking version, please wait...");
128+
+ sender.sendMessage(ChatColor.ITALIC + "Checking version, please wait..."); // Paper - Italic
129+
if (!versionTaskStarted) {
130+
versionTaskStarted = true;
131+
new Thread(new Runnable() {
132+
@@ -183,6 +195,13 @@ public class VersionCommand extends BukkitCommand {
133+
134+
private void obtainVersion() {
135+
String version = Bukkit.getVersion();
136+
+ // Paper start
137+
+ if (version == null || version.startsWith("null")) { // running from ide?
138+
+ setVersionMessage(ChatColor.YELLOW + "Unknown version, custom build?");
139+
+ return;
140+
+ }
141+
+ setVersionMessage(getVersionFetcher().getVersionMessage(version));
142+
+ /*
143+
if (version == null) version = "Custom";
144+
// PaperSpigot start
145+
if (version.startsWith("git-PaperSpigot-")) {
146+
@@ -227,11 +246,16 @@ public class VersionCommand extends BukkitCommand {
147+
} else {
148+
setVersionMessage("Unknown version, custom build?");
149+
}
150+
+ */
151+
+ // Paper end
152+
}
153+
154+
private void setVersionMessage(String msg) {
155+
lastCheck = System.currentTimeMillis();
156+
- versionMessage = msg;
157+
+ // Paper start
158+
+ String message = ChatColor.translateAlternateColorCodes('&', "&8>> &7This server is running &5Titanium &8(&fMC: 1.8.8&8) - &7Implementing API version &f" + Bukkit.getBukkitVersion());
159+
+ versionMessage = message + "\n" + msg;
160+
+ // Paper end
161+
versionLock.lock();
162+
try {
163+
hasVersion = true;
164+
--
165+
2.38.1.windows.1
166+
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,152 @@
1+
From a4884e9552f684a4e1ea81f12f79f7c1d620a8e5 Mon Sep 17 00:00:00 2001
2+
From: Zach Brown <[email protected]>
3+
Date: Fri, 4 Nov 2022 16:56:52 +0100
4+
Subject: [PATCH] Implement [Paper-0019] Implement Paper VersionChecker by Zach
5+
Brown
6+
7+
8+
diff --git a/src/main/java/com/destroystokyo/paper/PaperVersionFetcher.java b/src/main/java/com/destroystokyo/paper/PaperVersionFetcher.java
9+
new file mode 100644
10+
index 000000000..2bba71915
11+
--- /dev/null
12+
+++ b/src/main/java/com/destroystokyo/paper/PaperVersionFetcher.java
13+
@@ -0,0 +1,119 @@
14+
+package com.destroystokyo.paper;
15+
+
16+
+import com.destroystokyo.paper.util.VersionFetcher;
17+
+import com.google.common.base.Charsets;
18+
+import com.google.common.io.Resources;
19+
+import com.google.gson.Gson;
20+
+import com.google.gson.JsonObject;
21+
+import com.google.gson.JsonSyntaxException;
22+
+import java.io.BufferedReader;
23+
+import java.io.IOException;
24+
+import java.io.InputStreamReader;
25+
+import java.net.HttpURLConnection;
26+
+import java.net.URL;
27+
+import org.bukkit.ChatColor;
28+
+import org.jetbrains.annotations.NotNull;
29+
+
30+
+public class PaperVersionFetcher implements VersionFetcher {
31+
+
32+
+ @Override
33+
+ public long getCacheTime() {
34+
+ return 720000;
35+
+ }
36+
+
37+
+ @NotNull
38+
+ @Override
39+
+ public String getVersionMessage(@NotNull String serverVersion) {
40+
+ String[] parts = serverVersion.substring("git-Titanium-".length()).split("[-\\s]");
41+
+ return getUpdateStatusMessage("TitaniumMC/Titanium", parts[0], parts[1], parts[2]);
42+
+ }
43+
+
44+
+ private static String getUpdateStatusMessage(@NotNull String repo, @NotNull String source, @NotNull String branch, @NotNull String versionInfo) {
45+
+ int distance;
46+
+ try {
47+
+ // Titanium start
48+
+ if (!source.equalsIgnoreCase("JENKINS")) {
49+
+ throw new NumberFormatException();
50+
+ }
51+
+ // Titanium end
52+
+ int jenkinsBuild = Integer.parseInt(versionInfo);
53+
+ distance = fetchDistanceFromSiteApi(branch, jenkinsBuild);
54+
+ } catch (NumberFormatException ignored) {
55+
+ versionInfo = versionInfo.replace("\"", "");
56+
+ distance = fetchDistanceFromGitHub(repo, branch, versionInfo);
57+
+ }
58+
+
59+
+ switch (distance) {
60+
+ case 0:
61+
+ return ChatColor.translateAlternateColorCodes('&',"&8>> &7You are running the &alatest &7version!");
62+
+ case -1:
63+
+ return ChatColor.translateAlternateColorCodes('&',"&8>> &7Latest version &ccouldn't be &7obtained!");
64+
+ case -2:
65+
+ return ChatColor.translateAlternateColorCodes('&',"&8>> &7Unknown version &e" + versionInfo + " &7detected!");
66+
+ default:
67+
+ // Titanium start
68+
+ String downloadPage = "https://jenkins.titanvale.net/job/Titanium/job/" + branch;
69+
+ return ChatColor.translateAlternateColorCodes('&',"&8>> &7You are &3" + distance + " &7version(s) behind!")
70+
+ + ChatColor.RESET
71+
+ + "\n"
72+
+ + ChatColor.translateAlternateColorCodes('&',"&8>> &7Download the new version at:"
73+
+ + ChatColor.RESET
74+
+ + "\n"
75+
+ + " " + ChatColor.DARK_AQUA + downloadPage);
76+
+ // Titanium end
77+
+ }
78+
+ }
79+
+
80+
+ private static int fetchDistanceFromSiteApi(@NotNull String branch, int jenkinsBuild) {
81+
+ try {
82+
+ try (BufferedReader reader = Resources.asCharSource(
83+
+ new URL("https://jenkins.titanvale.net/job/Titanium/job/" + branch + "/api/json?lastCompletedBuild[number]"),
84+
+ Charsets.UTF_8
85+
+ ).openBufferedStream()) {
86+
+ JsonObject json = new Gson().fromJson(reader, JsonObject.class);
87+
+ JsonObject build = json.getAsJsonObject("lastCompletedBuild");
88+
+ int latest = build.get("number").getAsInt();
89+
+ if (latest < jenkinsBuild) {
90+
+ return -1;
91+
+ }
92+
+ return latest - jenkinsBuild;
93+
+ } catch (JsonSyntaxException ex) {
94+
+ ex.printStackTrace();
95+
+ return -1;
96+
+ }
97+
+ } catch (IOException e) {
98+
+ e.printStackTrace();
99+
+ return -1;
100+
+ }
101+
+ }
102+
+
103+
+ // Contributed by Techcable <[email protected]> in GH-65
104+
+ private static int fetchDistanceFromGitHub(@NotNull String repo, @NotNull String branch, @NotNull String hash) {
105+
+ try {
106+
+ HttpURLConnection connection = (HttpURLConnection) new URL("https://api.github.com/repos/" + repo + "/compare/" + branch + "..." + hash).openConnection();
107+
+ connection.connect();
108+
+ if (connection.getResponseCode() == HttpURLConnection.HTTP_NOT_FOUND) {
109+
+ return -2; // Unknown commit
110+
+ }
111+
+ try (BufferedReader reader = new BufferedReader(new InputStreamReader(connection.getInputStream(), Charsets.UTF_8))) {
112+
+ JsonObject obj = new Gson().fromJson(reader, JsonObject.class);
113+
+ String status = obj.get("status").getAsString();
114+
+ switch (status) {
115+
+ case "identical":
116+
+ return 0;
117+
+ case "behind":
118+
+ return obj.get("behind_by").getAsInt();
119+
+ default:
120+
+ return -1;
121+
+ }
122+
+ } catch (JsonSyntaxException | NumberFormatException e) {
123+
+ e.printStackTrace();
124+
+ return -1;
125+
+ }
126+
+ } catch (IOException e) {
127+
+ e.printStackTrace();
128+
+ return -1;
129+
+ }
130+
+ }
131+
+
132+
+}
133+
diff --git a/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java b/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java
134+
index d2cb30ba1..a97c329bb 100644
135+
--- a/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java
136+
+++ b/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java
137+
@@ -173,4 +173,12 @@ public final class CraftMagicNumbers implements UnsafeValues {
138+
}
139+
}
140+
// PandaSpigot end
141+
+
142+
+ // Paper start
143+
+ @Override
144+
+ public com.destroystokyo.paper.util.VersionFetcher getVersionFetcher() {
145+
+ return new com.destroystokyo.paper.PaperVersionFetcher();
146+
+ }
147+
+ // Paper end
148+
+
149+
}
150+
--
151+
2.38.1.windows.1
152+

0 commit comments

Comments
 (0)