Skip to content

Commit b2b866d

Browse files
committed
✨ feat(rebrand): rebrand project to SurfCanvas
- update brand identifiers and repository links to SurfCanvas - modify download page and user agent to reflect new branding - adjust console messages for version updates to reference SurfCanvas
1 parent 97d56bf commit b2b866d

2 files changed

Lines changed: 328 additions & 0 deletions

File tree

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
2+
From: twisti <76837088+twisti-dev@users.noreply.github.com>
3+
Date: Fri, 8 May 2026 17:03:14 +0200
4+
Subject: [PATCH] Rebrand to SurfCanvas
5+
6+
7+
diff --git a/src/main/java/io/papermc/paper/ServerBuildInfo.java b/src/main/java/io/papermc/paper/ServerBuildInfo.java
8+
index e394a3643ad582cd823ac61b8ce56b8b069c3ab4..4771b17f585bca8521da90389bf238de15f30770 100644
9+
--- a/src/main/java/io/papermc/paper/ServerBuildInfo.java
10+
+++ b/src/main/java/io/papermc/paper/ServerBuildInfo.java
11+
@@ -28,6 +28,12 @@ public interface ServerBuildInfo {
12+
*/
13+
Key BRAND_CANVAS_ID = Key.key("canvasmc", "canvas");
14+
// Canvas end - Rebrand
15+
+ // SurfCanvas start - Rebrand
16+
+ /**
17+
+ * The brand id for SurfCanvas
18+
+ */
19+
+ Key BRAND_SURF_CANVAS_ID = Key.key("slne", "surfcanvas");
20+
+ // SurfCanvas end - Rebrand
21+
22+
/**
23+
* Gets the {@code ServerBuildInfo}.
Lines changed: 305 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,305 @@
1+
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
2+
From: twisti <76837088+twisti-dev@users.noreply.github.com>
3+
Date: Fri, 8 May 2026 17:02:40 +0200
4+
Subject: [PATCH] Rebrand to SurfCanvas
5+
6+
7+
diff --git a/src/main/java/com/destroystokyo/paper/PaperVersionFetcher.java b/src/main/java/com/destroystokyo/paper/PaperVersionFetcher.java
8+
index 4d2936f6818c38e2844cba78ffad339e93ff29ab..7ca316df27c4f33750300c241107fae735e79e31 100644
9+
--- a/src/main/java/com/destroystokyo/paper/PaperVersionFetcher.java
10+
+++ b/src/main/java/com/destroystokyo/paper/PaperVersionFetcher.java
11+
@@ -40,10 +40,11 @@ public class PaperVersionFetcher implements VersionFetcher {
12+
private static final ComponentLogger COMPONENT_LOGGER = ComponentLogger.logger(LogManager.getRootLogger().getName());
13+
private static final int DISTANCE_ERROR = -1;
14+
private static final int DISTANCE_UNKNOWN = -2;
15+
- private static final String DOWNLOAD_PAGE = "https://papermc.io/downloads/folia"; // Folia
16+
- private static final String REPOSITORY = "PaperMC/Folia"; // Folia
17+
+ // SurfCanvas - replace Paper download page and repository
18+
+ private static final String DOWNLOAD_PAGE = "https://github.com/SLNE-Development/surf-canvas/releases";
19+
+ private static final String REPOSITORY = "SLNE-Development/surf-canvas";
20+
private static final ServerBuildInfo BUILD_INFO = ServerBuildInfo.buildInfo();
21+
- private static final String USER_AGENT = BUILD_INFO.brandName() + "/" + BUILD_INFO.asString(VERSION_SIMPLE) + " (https://papermc.io)";
22+
+ private static final String USER_AGENT = BUILD_INFO.brandName() + "/" + BUILD_INFO.asString(VERSION_SIMPLE) + " (https://github.com/SLNE-Development/surf-canvas)";
23+
private static final Gson GSON = new Gson();
24+
25+
@Override
26+
@@ -65,66 +66,39 @@ public class PaperVersionFetcher implements VersionFetcher {
27+
}
28+
29+
public static void getUpdateStatusStartupMessage() {
30+
- int distance = DISTANCE_ERROR;
31+
-
32+
final OptionalInt buildNumber = BUILD_INFO.buildNumber();
33+
if (buildNumber.isEmpty() && BUILD_INFO.gitCommit().isEmpty()) {
34+
COMPONENT_LOGGER.warn(text("*** You are running a development version without access to version information ***"));
35+
- } else {
36+
- final Optional<MinecraftVersionFetcher> apiResult = fetchMinecraftVersionList();
37+
- if (buildNumber.isPresent()) {
38+
- distance = fetchDistanceFromSiteApi(buildNumber.getAsInt());
39+
- } else {
40+
- final Optional<String> gitBranch = BUILD_INFO.gitBranch();
41+
- final Optional<String> gitCommit = BUILD_INFO.gitCommit();
42+
- if (gitBranch.isPresent() && gitCommit.isPresent()) {
43+
- distance = fetchDistanceFromGitHub(gitBranch.get(), gitCommit.get());
44+
- }
45+
- }
46+
+ return;
47+
+ }
48+
49+
- switch (distance) {
50+
- case DISTANCE_ERROR -> COMPONENT_LOGGER.error(text("*** Error obtaining version information! Cannot fetch version info ***"));
51+
- case 0 -> apiResult.ifPresent(result -> {
52+
- COMPONENT_LOGGER.warn(text("*************************************************************************************"));
53+
- COMPONENT_LOGGER.warn(text("You are running the latest build for your Minecraft version (" + BUILD_INFO.minecraftVersionId() + ")"));
54+
- COMPONENT_LOGGER.warn(text("However, you are " + result.distance() + " release(s) behind the latest stable release (" + result.latestVersion() + ")!"));
55+
- COMPONENT_LOGGER.warn(text("It is recommended that you update as soon as possible"));
56+
- COMPONENT_LOGGER.warn(text(DOWNLOAD_PAGE));
57+
- COMPONENT_LOGGER.warn(text("*************************************************************************************"));
58+
- });
59+
- case DISTANCE_UNKNOWN -> COMPONENT_LOGGER.warn(text("*** You are running an unknown version! Cannot fetch version info ***"));
60+
- default -> {
61+
- if (apiResult.isPresent()) {
62+
- COMPONENT_LOGGER.warn(text("*** You are running an outdated version of Minecraft, which is " + apiResult.get().distance() + " release(s) and " + distance + " build(s) behind!"));
63+
- COMPONENT_LOGGER.warn(text("*** Please update to the latest stable version on " + DOWNLOAD_PAGE + " ***"));
64+
- } else {
65+
- COMPONENT_LOGGER.info(text("*** Currently you are " + distance + " build(s) behind ***"));
66+
- COMPONENT_LOGGER.info(text("*** It is highly recommended to download the latest build from " + DOWNLOAD_PAGE + " ***"));
67+
- }
68+
- }
69+
+ int distance = buildNumber.isPresent()
70+
+ ? fetchDistanceFromGitHubReleases(buildNumber.getAsInt())
71+
+ : DISTANCE_UNKNOWN;
72+
+
73+
+ switch (distance) {
74+
+ case DISTANCE_ERROR -> COMPONENT_LOGGER.error(text("*** Error obtaining version information! Cannot fetch version info ***"));
75+
+ case 0 -> COMPONENT_LOGGER.info(text("You are running the latest version of SurfCanvas (" + BUILD_INFO.minecraftVersionId() + ")"));
76+
+ case DISTANCE_UNKNOWN -> COMPONENT_LOGGER.warn(text("*** You are running an unknown version of SurfCanvas! Cannot fetch version info ***"));
77+
+ default -> {
78+
+ COMPONENT_LOGGER.warn(text("*** You are " + distance + " build(s) behind the latest SurfCanvas release! ***"));
79+
+ COMPONENT_LOGGER.warn(text("*** Download the latest build from " + DOWNLOAD_PAGE + " ***"));
80+
}
81+
}
82+
}
83+
84+
private static Component getUpdateStatusMessage() {
85+
- int distance = DISTANCE_ERROR;
86+
+ final OptionalInt buildNumber = BUILD_INFO.buildNumber();
87+
88+
- final OptionalInt buildNumber = PaperVersionFetcher.BUILD_INFO.buildNumber();
89+
- if (buildNumber.isPresent()) {
90+
- distance = fetchDistanceFromSiteApi(buildNumber.getAsInt());
91+
- } else {
92+
- final Optional<String> gitBranch = PaperVersionFetcher.BUILD_INFO.gitBranch();
93+
- final Optional<String> gitCommit = PaperVersionFetcher.BUILD_INFO.gitCommit();
94+
- if (gitBranch.isPresent() && gitCommit.isPresent()) {
95+
- distance = fetchDistanceFromGitHub(gitBranch.get(), gitCommit.get());
96+
- }
97+
- }
98+
+ int distance = buildNumber.isPresent()
99+
+ ? fetchDistanceFromGitHubReleases(buildNumber.getAsInt())
100+
+ : DISTANCE_UNKNOWN;
101+
102+
return switch (distance) {
103+
case DISTANCE_ERROR -> text("Error obtaining version information", NamedTextColor.YELLOW);
104+
case 0 -> text("You are running the latest version", NamedTextColor.GREEN);
105+
case DISTANCE_UNKNOWN -> text("Unknown version", NamedTextColor.YELLOW);
106+
- default -> text("You are " + distance + " version(s) behind", NamedTextColor.YELLOW)
107+
+ default -> text("You are " + distance + " build(s) behind", NamedTextColor.YELLOW)
108+
.append(Component.newline())
109+
.append(text("Download the new version at: ")
110+
.append(text(DOWNLOAD_PAGE, NamedTextColor.GOLD)
111+
@@ -133,114 +107,60 @@ public class PaperVersionFetcher implements VersionFetcher {
112+
};
113+
}
114+
115+
- private record MinecraftVersionFetcher(String latestVersion, int distance) {}
116+
-
117+
- private static Optional<MinecraftVersionFetcher> fetchMinecraftVersionList() {
118+
- final String currentVersion = PaperVersionFetcher.BUILD_INFO.minecraftVersionId();
119+
-
120+
+ // SurfCanvas - check against our own GitHub releases instead of Paper's API
121+
+ private static int fetchDistanceFromGitHubReleases(final int currentBuild) {
122+
try {
123+
- final URL versionsUrl = URI.create("https://fill.papermc.io/v3/projects/folia").toURL(); // Folia
124+
- final HttpURLConnection connection = (HttpURLConnection) versionsUrl.openConnection();
125+
+ final URL url = URI.create("https://api.github.com/repos/" + REPOSITORY + "/releases").toURL();
126+
+ final HttpURLConnection connection = (HttpURLConnection) url.openConnection();
127+
connection.setConnectTimeout(5000);
128+
connection.setReadTimeout(5000);
129+
- connection.setRequestProperty("User-Agent", PaperVersionFetcher.USER_AGENT);
130+
- connection.setRequestProperty("Accept", "application/json");
131+
+ connection.setRequestProperty("User-Agent", USER_AGENT);
132+
+ connection.setRequestProperty("Accept", "application/vnd.github+json");
133+
+
134+
+ if (connection.getResponseCode() != HttpURLConnection.HTTP_OK) {
135+
+ return DISTANCE_ERROR;
136+
+ }
137+
138+
try (final BufferedReader reader = new BufferedReader(new InputStreamReader(connection.getInputStream(), StandardCharsets.UTF_8))) {
139+
- final JsonObject json = GSON.fromJson(reader, JsonObject.class);
140+
- final JsonObject versions = json.getAsJsonObject("versions");
141+
- final List<String> versionList = versions.keySet().stream()
142+
- .map(versions::getAsJsonArray)
143+
- .flatMap(array -> StreamSupport.stream(array.spliterator(), false))
144+
- .map(JsonElement::getAsString)
145+
- .toList();
146+
+ final JsonArray releases = GSON.fromJson(reader, JsonArray.class);
147+
148+
- for (final String latestVersion : versionList) {
149+
- if (latestVersion.equals(currentVersion)) {
150+
- return Optional.empty();
151+
+ int latestBuild = -1;
152+
+ for (final JsonElement element : releases) {
153+
+ final JsonObject release = element.getAsJsonObject();
154+
+ if (release.get("prerelease").getAsBoolean() || release.get("draft").getAsBoolean()) {
155+
+ continue;
156+
}
157+
-
158+
- try {
159+
- final URL buildsUrl = URI.create("https://fill.papermc.io/v3/projects/folia/versions/" + latestVersion + "/builds/latest").toURL(); // Folia
160+
- final HttpURLConnection connection2 = (HttpURLConnection) buildsUrl.openConnection();
161+
- connection2.setConnectTimeout(5000);
162+
- connection2.setReadTimeout(5000);
163+
- connection2.setRequestProperty("User-Agent", PaperVersionFetcher.USER_AGENT);
164+
- connection2.setRequestProperty("Accept", "application/json");
165+
-
166+
- try (final BufferedReader buildReader = new BufferedReader(new InputStreamReader(connection2.getInputStream(), StandardCharsets.UTF_8))) {
167+
- final JsonObject buildJson = GSON.fromJson(buildReader, JsonObject.class);
168+
- if ("STABLE".equals(buildJson.get("channel").getAsString())) {
169+
- final int currentIndex = versionList.indexOf(currentVersion);
170+
- final int latestIndex = versionList.indexOf(latestVersion);
171+
- final int distance = currentIndex - latestIndex;
172+
- return Optional.of(new MinecraftVersionFetcher(latestVersion, distance));
173+
- }
174+
- } catch (final JsonSyntaxException ex) {
175+
- LOGGER.error("Error parsing json from Paper's downloads API", ex);
176+
- }
177+
- } catch (final IOException e) {
178+
- LOGGER.error("Error while parsing latest build", e);
179+
+ // Tag format: v1.21.11.build.42-stable
180+
+ final String tag = release.get("tag_name").getAsString();
181+
+ final int buildNum = parseBuildNumber(tag);
182+
+ if (buildNum > latestBuild) {
183+
+ latestBuild = buildNum;
184+
}
185+
}
186+
- } catch (final JsonSyntaxException ex) {
187+
- LOGGER.error("Error parsing json from Paper's downloads API", ex);
188+
- }
189+
- } catch (final IOException e) {
190+
- LOGGER.error("Error while parsing version list", e);
191+
- }
192+
- return Optional.empty();
193+
- }
194+
195+
- private static int fetchDistanceFromSiteApi(final int jenkinsBuild) {
196+
- try {
197+
- final URL buildsUrl = URI.create("https://fill.papermc.io/v3/projects/folia/versions/" + PaperVersionFetcher.BUILD_INFO.minecraftVersionId() + "/builds").toURL(); // Folia
198+
- final HttpURLConnection connection = (HttpURLConnection) buildsUrl.openConnection();
199+
- connection.setConnectTimeout(5000);
200+
- connection.setReadTimeout(5000);
201+
- connection.setRequestProperty("User-Agent", PaperVersionFetcher.USER_AGENT);
202+
- connection.setRequestProperty("Accept", "application/json");
203+
- try (final BufferedReader reader = new BufferedReader(new InputStreamReader(connection.getInputStream(), StandardCharsets.UTF_8))) {
204+
- final JsonArray builds = GSON.fromJson(reader, JsonArray.class);
205+
- final int latest = StreamSupport.stream(builds.spliterator(), false)
206+
- .mapToInt(build -> build.getAsJsonObject().get("id").getAsInt())
207+
- .max()
208+
- .orElseThrow();
209+
- return Math.max(latest - jenkinsBuild, 0);
210+
+ if (latestBuild < 0) {
211+
+ return DISTANCE_UNKNOWN;
212+
+ }
213+
+
214+
+ return Math.max(latestBuild - currentBuild, 0);
215+
} catch (final JsonSyntaxException ex) {
216+
- LOGGER.error("Error parsing json from Paper's downloads API", ex);
217+
+ LOGGER.error("Error parsing JSON from GitHub releases API", ex);
218+
return DISTANCE_ERROR;
219+
}
220+
} catch (final IOException e) {
221+
- LOGGER.error("Error while parsing version", e);
222+
+ LOGGER.error("Error fetching SurfCanvas release info", e);
223+
return DISTANCE_ERROR;
224+
}
225+
}
226+
227+
- // Contributed by Techcable <Techcable@outlook.com> in GH-65
228+
- private static int fetchDistanceFromGitHub(final String branch, final String hash) {
229+
+ // Parses build number from tag like "v1.21.11.build.42-stable" → 42
230+
+ private static int parseBuildNumber(final String tag) {
231+
try {
232+
- final HttpURLConnection connection = (HttpURLConnection) URI.create("https://api.github.com/repos/%s/compare/%s...%s".formatted(PaperVersionFetcher.REPOSITORY, branch, hash)).toURL().openConnection();
233+
- connection.setConnectTimeout(5000);
234+
- connection.setReadTimeout(5000);
235+
- connection.setRequestProperty("User-Agent", PaperVersionFetcher.USER_AGENT);
236+
- connection.connect();
237+
- if (connection.getResponseCode() == HttpURLConnection.HTTP_NOT_FOUND) return DISTANCE_UNKNOWN; // Unknown commit
238+
- try (final BufferedReader reader = new BufferedReader(new InputStreamReader(connection.getInputStream(), StandardCharsets.UTF_8))) {
239+
- final JsonObject obj = GSON.fromJson(reader, JsonObject.class);
240+
- final String status = obj.get("status").getAsString();
241+
- return switch (status) {
242+
- case "identical" -> 0;
243+
- case "behind" -> obj.get("behind_by").getAsInt();
244+
- default -> DISTANCE_ERROR;
245+
- };
246+
- } catch (final JsonSyntaxException | NumberFormatException e) {
247+
- LOGGER.error("Error parsing json from GitHub's API", e);
248+
- return DISTANCE_ERROR;
249+
- }
250+
- } catch (final IOException e) {
251+
- LOGGER.error("Error while parsing version", e);
252+
- return DISTANCE_ERROR;
253+
+ // Pattern: v{mcVersion}.build.{number}-{channel}
254+
+ final String buildPart = tag.replaceAll(".*\\.build\\.(\\d+)-.*", "$1");
255+
+ return Integer.parseInt(buildPart);
256+
+ } catch (final NumberFormatException e) {
257+
+ return -1;
258+
}
259+
}
260+
261+
diff --git a/src/main/java/io/papermc/paper/ServerBuildInfoImpl.java b/src/main/java/io/papermc/paper/ServerBuildInfoImpl.java
262+
index 55ebf9c9036468418128501fb192eeb3658194d0..b6d918667444863b29466e0c0fdee82d49ca851b 100644
263+
--- a/src/main/java/io/papermc/paper/ServerBuildInfoImpl.java
264+
+++ b/src/main/java/io/papermc/paper/ServerBuildInfoImpl.java
265+
@@ -32,6 +32,7 @@ public record ServerBuildInfoImpl(
266+
267+
private static final String BRAND_PAPER_NAME = "Paper";
268+
private static final String BRAND_CANVAS_NAME = "Canvas"; // Canvas - Rebrand
269+
+ private static final String BRAND_SURF_CANVAS = "SurfCanvas"; // SurfCanvas - Rebrand
270+
271+
private static final String BUILD_DEV = "DEV";
272+
273+
@@ -43,9 +44,9 @@ public record ServerBuildInfoImpl(
274+
this(
275+
getManifestAttribute(manifest, ATTRIBUTE_BRAND_ID)
276+
.map(Key::key)
277+
- .orElse(BRAND_CANVAS_ID), // Folia // Canvas - Rebrand
278+
+ .orElse(BRAND_SURF_CANVAS_ID), // Folia // Canvas - Rebrand // SurfCanvas - Rebrand
279+
getManifestAttribute(manifest, ATTRIBUTE_BRAND_NAME)
280+
- .orElse(BRAND_CANVAS_NAME), // Folia // Canvas - Rebrand
281+
+ .orElse(BRAND_SURF_CANVAS), // Folia // Canvas - Rebrand // SurfCanvas - Rebrand
282+
SharedConstants.getCurrentVersion().id(),
283+
SharedConstants.getCurrentVersion().name(),
284+
getManifestAttribute(manifest, ATTRIBUTE_BUILD_NUMBER)
285+
diff --git a/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java b/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java
286+
index d3df5057059ce22ea97a62954d0607f717dc2c96..6c98c7186c77b6f2ee43afdbf5caced3cde16fa9 100644
287+
--- a/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java
288+
+++ b/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java
289+
@@ -1,6 +1,7 @@
290+
package org.bukkit.craftbukkit.util;
291+
292+
import ca.spottedleaf.moonrise.common.PlatformHooks;
293+
+import com.destroystokyo.paper.PaperVersionFetcher;
294+
import com.google.common.base.Preconditions;
295+
import com.google.common.collect.Multimap;
296+
import com.google.common.io.Files;
297+
@@ -491,7 +492,7 @@ public final class CraftMagicNumbers implements UnsafeValues {
298+
299+
@Override
300+
public com.destroystokyo.paper.util.VersionFetcher getVersionFetcher() {
301+
- return new io.canvasmc.canvas.util.version.CanvasVersionFetcher(); // Canvas - Rebrand
302+
+ return new PaperVersionFetcher(); // Canvas - Rebrand // SurfCanvas - Rebrand
303+
}
304+
305+
@Override

0 commit comments

Comments
 (0)