This commit is contained in:
masmc05 2024-04-29 07:48:38 +02:00 committed by GitHub
commit c8a56af32a
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 401 additions and 0 deletions

View File

@ -0,0 +1,188 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: masmc05 <masmc05@gmail.com>
Date: Fri, 16 Feb 2024 14:13:30 +0200
Subject: [PATCH] Add paper version util class
diff --git a/src/main/java/io/papermc/paper/util/ServerInfo.java b/src/main/java/io/papermc/paper/util/ServerInfo.java
new file mode 100644
index 0000000000000000000000000000000000000000..cf39052c7d9f152313762e928fb49c5e3cd22dbc
--- /dev/null
+++ b/src/main/java/io/papermc/paper/util/ServerInfo.java
@@ -0,0 +1,98 @@
+package io.papermc.paper.util;
+
+import net.kyori.adventure.key.Key;
+import net.kyori.adventure.util.Services;
+import org.bukkit.UnsafeValues;
+import org.jetbrains.annotations.NotNull;
+
+/**
+ * A utility class to get information about the server
+ * Works even before Bukkit is initialized (e.g. on bootstrap)
+ */
+public class ServerInfo {
+ private ServerInfo() {
+ throw new UnsupportedOperationException("This class cannot be instantiated");
+ }
+ private static final ServerInfoProvider provider = Services.service(ServerInfoProvider.class).orElseThrow();
+
+ /**
+ * Get the version of the server
+ * @return the version of the server (e.g. "1.20.4", "1.20.2 Pre-release 2", "23w31a")
+ */
+ public static @NotNull String version() {
+ return provider.version();
+ }
+
+ /**
+ * Get the api version of the server
+ * @return the api version of the server (e.g. "1.20.4-R0.1-SNAPSHOT")
+ */
+ public static @NotNull String apiVersion() {
+ return provider.apiVersion();
+ }
+
+ /**
+ * Get the name of the server
+ * @return the name of the server (e.g. "Paper")
+ */
+ public static @NotNull String serverName() {
+ return provider.serverName();
+ }
+
+ /**
+ * Returns true if the server is a minecraft release version,
+ * false is it's a snapshot, pre-release, etc
+ * @return if the server is stable
+ */
+ public static boolean isStable() {
+ return provider.isStable();
+ }
+
+ /**
+ * Returns the unsafe values for the server for unsafe version values
+ * @return the unsafe values for the server
+ */
+ @Deprecated
+ @NotNull
+ public static UnsafeValues unsafe() {
+ return provider.unsafe();
+ }
+
+ /**
+ * Checks if the server runs exactly the specified version
+ * <p>
+ * Note: Will always return false on non release versions
+ * @param version the version to check (e.g. 1, 20, 4)
+ * @return true if the server runs exactly the specified version
+ */
+ public static boolean is(int @NotNull... version) {
+ return provider.is(version);
+ }
+
+ /**
+ * Checks if the server runs exactly the specified version
+ * @param version the version to check (e.g. "1.20.4", "1.20.2 Pre-release 2", "1.20.2-pre2", "23w31a")
+ * @return true if the server runs exactly the specified version
+ */
+ public static boolean is(@NotNull String version) {
+ return provider.is(version);
+ }
+
+ /**
+ * Checks if the server runs a version which is after this version or the same
+ * @param version the version to check (e.g. 1, 20, 4)
+ * @return true if the server runs on this version or a newer version
+ */
+ public static boolean isAtLeast(int @NotNull... version) {
+ return provider.isAtLeast(version);
+ }
+
+ /**
+ * Checks if the server is implementing the specified API
+ * @param api the API to check (e.g. "papermc:folia")
+ * @return true if the server is implementing the specified API
+ */
+ public static boolean isImplementing(@NotNull Key api) {
+ return provider.isImplementing(api);
+ }
+}
diff --git a/src/main/java/io/papermc/paper/util/ServerInfoProvider.java b/src/main/java/io/papermc/paper/util/ServerInfoProvider.java
new file mode 100644
index 0000000000000000000000000000000000000000..cee83c849668c79d0aca1e4e2b38698b67f5e948
--- /dev/null
+++ b/src/main/java/io/papermc/paper/util/ServerInfoProvider.java
@@ -0,0 +1,72 @@
+package io.papermc.paper.util;
+
+import net.kyori.adventure.key.Key;
+import org.bukkit.UnsafeValues;
+import org.jetbrains.annotations.NotNull;
+
+/**
+ * A utility class to get information about the server
+ */
+public interface ServerInfoProvider {
+ /**
+ * Get the version of the server
+ * @return the version of the server (e.g. "1.20.4", "1.20.2 Pre-release 2", "23w31a")
+ */
+ @NotNull String version();
+
+ /**
+ * Get the api version of the server
+ * @return the api version of the server (e.g. "1.20.4-R0.1-SNAPSHOT")
+ */
+ @NotNull String apiVersion();
+
+ /**
+ * Get the name of the server
+ * @return the name of the server (e.g. "Paper")
+ */
+ @NotNull String serverName();
+
+ /**
+ * Returns the unsafe values for the server for unsafe data values
+ * @return the unsafe values for the server
+ */
+ @Deprecated
+ @NotNull
+ UnsafeValues unsafe();
+
+ /**
+ * Returns true if the server is a release version, false otherwise
+ * @return if the server is stable
+ */
+ boolean isStable();
+
+ /**
+ * Checks if the server runs exactly the specified version
+ * <p>
+ * Note: Will always return false on non release versions
+ * @param version the version to check (e.g. 1, 20, 4)
+ * @return true if the server runs exactly the specified version
+ */
+ boolean is(int @NotNull... version);
+
+ /**
+ * Checks if the server runs exactly the specified version
+ * @param version the version to check (e.g. "1.20.4", "1.20.2 Pre-release 2", "1.20.2-pre2", "23w31a")
+ * @return true if the server runs exactly the specified version
+ */
+ boolean is(@NotNull String version);
+
+ /**
+ * Checks if the server runs a version which is after this version or the same
+ * @param version the version to check (e.g. 1, 20, 4)
+ * @return true if the server runs on this version or a newer version
+ */
+ boolean isAtLeast(int @NotNull... version);
+
+ /**
+ * Checks if the server is implementing the specified API
+ * @param api the API to check (e.g. "papermc:folia")
+ * @return true if the server is implementing the specified API
+ */
+ boolean isImplementing(@NotNull Key api);
+}

View File

@ -0,0 +1,213 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: masmc05 <masmc05@gmail.com>
Date: Fri, 16 Feb 2024 14:13:29 +0200
Subject: [PATCH] Add paper version util class
diff --git a/src/main/java/io/papermc/paper/util/misc/ServerInfoProviderImpl.java b/src/main/java/io/papermc/paper/util/misc/ServerInfoProviderImpl.java
new file mode 100644
index 0000000000000000000000000000000000000000..40ea612034c21fc4abc95cc4dcd7439b56fd9033
--- /dev/null
+++ b/src/main/java/io/papermc/paper/util/misc/ServerInfoProviderImpl.java
@@ -0,0 +1,194 @@
+package io.papermc.paper.util.misc;
+
+import com.google.common.base.Preconditions;
+import com.google.common.collect.ImmutableList;
+import com.google.gson.JsonParser;
+import com.mojang.logging.LogUtils;
+import io.papermc.paper.util.ServerInfoProvider;
+import net.kyori.adventure.key.Key;
+import net.kyori.adventure.key.KeyPattern;
+import net.minecraft.SharedConstants;
+import org.bukkit.UnsafeValues;
+import org.bukkit.craftbukkit.util.CraftMagicNumbers;
+import org.bukkit.craftbukkit.util.Versioning;
+import org.jetbrains.annotations.NotNull;
+import org.slf4j.Logger;
+import java.io.IOException;
+import java.net.URI;
+import java.net.http.HttpClient;
+import java.net.http.HttpRequest;
+import java.net.http.HttpResponse;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Locale;
+import java.util.Objects;
+import java.util.Optional;
+import java.util.Set;
+import java.util.concurrent.CompletableFuture;
+import java.util.stream.Stream;
+
+public class ServerInfoProviderImpl implements ServerInfoProvider {
+ private final String bukkitVersion = Versioning.getBukkitVersion();
+ private final Set<Key> implementedAPIs;
+ private final String serverName;
+ private final VersionInfo version;
+ public ServerInfoProviderImpl() {
+ ServerImplementationInfo info = new ServerImplementationInfo();
+ this.serverName = info.latestName;
+ this.implementedAPIs = info.implementedAPIs;
+ if (SharedConstants.getCurrentVersion().isStable()) {
+ // Release versions, best supported
+ this.version = new StableVersionInfo();
+ } else {
+ // Snapshot, pre-release, etc
+ // Supported the best we can
+ this.version = new NonStableVersionInfo();
+ }
+ }
+ @Override
+ public @NotNull String version() {
+ return SharedConstants.getCurrentVersion().getName();
+ }
+
+ @Override
+ public @NotNull String apiVersion() {
+ return this.bukkitVersion;
+ }
+
+ @Override
+ public @NotNull String serverName() {
+ return this.serverName;
+ }
+
+ @Override
+ @Deprecated
+ public @NotNull UnsafeValues unsafe() {
+ return CraftMagicNumbers.INSTANCE;
+ }
+
+ @Override
+ public boolean isStable() {
+ return SharedConstants.getCurrentVersion().isStable();
+ }
+
+ @Override
+ public boolean is(final int @NotNull ... version) {
+ return this.version.is(version);
+ }
+
+ @Override
+ public boolean is(@NotNull final String version) {
+ Preconditions.checkNotNull(version, "The version cannot be null");
+ return this.version.is(version);
+ }
+
+ @Override
+ public boolean isAtLeast(final int @NotNull ... version) {
+ return this.version.isAtLeast(version);
+ }
+
+ @Override
+ public boolean isImplementing(final @NotNull Key api) {
+ Preconditions.checkNotNull(api, "The API cannot be null");
+ return this.implementedAPIs.contains(api);
+ }
+ private static class ServerImplementationInfo {
+ private final Set<Key> implementedAPIs = new HashSet<>();
+ private String latestName;
+ private ServerImplementationInfo() {
+ this.add("minecraft", "Vanilla");
+ this.add("papermc", "Paper");
+ }
+ @SuppressWarnings("PatternValidation")
+ private void add(@KeyPattern.Namespace String namespace, String name) {
+ this.implementedAPIs.add(Key.key(namespace, name.toLowerCase(Locale.ROOT)));
+ this.latestName = name;
+ }
+ }
+ private interface VersionInfo {
+
+ boolean is(int @NotNull ... version);
+
+ boolean is(@NotNull String version);
+
+ boolean isAtLeast(int @NotNull ... version);
+ }
+ private static class StableVersionInfo implements VersionInfo {
+ private final String version = SharedConstants.getCurrentVersion().getId();
+ private final int[] versionArr = Stream.of(this.version.split("\\.")).mapToInt(Integer::parseInt).toArray();
+ @Override
+ public boolean is(final int @NotNull ... version) {
+ return Arrays.equals(this.versionArr, version);
+ }
+
+ @Override
+ public boolean is(@NotNull final String version) {
+ return Objects.equals(this.version, version);
+ }
+
+ @Override
+ public boolean isAtLeast(final int @NotNull ... version) {
+ int maxLen = Math.max(this.versionArr.length, version.length);
+ for (int i = 0; i < maxLen; i++) {
+ int our = i < this.versionArr.length ? this.versionArr[i] : 0;
+ int requested = i < version.length ? version[i] : 0;
+ if (our != requested) {
+ return our > requested;
+ }
+ }
+ return true;
+ }
+ }
+ private static class NonStableVersionInfo implements VersionInfo {
+ private static final Logger LOGGER = LogUtils.getClassLogger();
+ private static final String manifestURL = Optional.ofNullable(System.getProperty("paper.api.manifest-url"))
+ .orElse("https://piston-meta.mojang.com/mc/game/version_manifest_v2.json");
+ private final String version = SharedConstants.getCurrentVersion().getName();
+ private final String id = SharedConstants.getCurrentVersion().getId();
+ private final CompletableFuture<List<String>> versionList = CompletableFuture.supplyAsync(this::fetchVersionList);
+
+ private List<String> fetchVersionList() {
+ List<String> versionList = new ArrayList<>();
+ try (HttpClient client = HttpClient.newHttpClient()) {
+ HttpRequest request = HttpRequest.newBuilder()
+ .uri(URI.create(manifestURL))
+ .build();
+ HttpResponse<String> response = client.send(request, HttpResponse.BodyHandlers.ofString());
+ var parsed = JsonParser.parseString(response.body());
+ var versionArray = parsed.getAsJsonObject().getAsJsonArray("versions");
+ for (var version : versionArray) {
+ versionList.add(version.getAsJsonObject().get("id").getAsString());
+ }
+ } catch (IOException | InterruptedException e) {
+ LOGGER.error("Failed to fetch version manifest, plugins depending on version check may not work correctly", e);
+ throw new IllegalStateException("Failed to fetch the version manifest", e);
+ }
+ return ImmutableList.copyOf(versionList);
+ }
+ @Override
+ public boolean is(final int @NotNull ... version) {
+ return false;
+ }
+
+ @Override
+ public boolean is(@NotNull final String version) {
+ return this.version.equals(version) || this.id.equals(version);
+ }
+
+ @Override
+ public boolean isAtLeast(final int @NotNull ... version) {
+ if (version.length == 0) {
+ return true;
+ }
+ var builder = new StringBuilder();
+ builder.append(version[0]);
+ for (int i = 1; i < version.length; i++) {
+ builder.append('.').append(version[i]);
+ }
+ var versionString = builder.toString();
+ return this.versionList.join().indexOf(versionString) > this.versionList.join().indexOf(this.id);
+ }
+ }
+}
diff --git a/src/main/resources/META-INF/services/io.papermc.paper.util.ServerInfoProvider b/src/main/resources/META-INF/services/io.papermc.paper.util.ServerInfoProvider
new file mode 100644
index 0000000000000000000000000000000000000000..fa7c03ecb88d4c5922af54ebfb32460ec39d70d2
--- /dev/null
+++ b/src/main/resources/META-INF/services/io.papermc.paper.util.ServerInfoProvider
@@ -0,0 +1 @@
+io.papermc.paper.util.misc.ServerInfoProviderImpl