diff --git a/bootstrap/spigot/pom.xml b/bootstrap/spigot/pom.xml index 5d17d2619..5aa2c59cf 100644 --- a/bootstrap/spigot/pom.xml +++ b/bootstrap/spigot/pom.xml @@ -11,6 +11,10 @@ bootstrap-spigot + + papermc + https://papermc.io/repo/repository/maven-public/ + viaversion-repo https://repo.viaversion.com @@ -25,9 +29,9 @@ compile - org.spigotmc - spigot-api - 1.15.2-R0.1-SNAPSHOT + io.papermc.paper + paper-api + 1.18.1-R0.1-SNAPSHOT provided diff --git a/bootstrap/spigot/src/main/java/org/geysermc/geyser/platform/spigot/GeyserSpigotPlugin.java b/bootstrap/spigot/src/main/java/org/geysermc/geyser/platform/spigot/GeyserSpigotPlugin.java index 12a27190d..6b6344bd8 100644 --- a/bootstrap/spigot/src/main/java/org/geysermc/geyser/platform/spigot/GeyserSpigotPlugin.java +++ b/bootstrap/spigot/src/main/java/org/geysermc/geyser/platform/spigot/GeyserSpigotPlugin.java @@ -168,8 +168,7 @@ public class GeyserSpigotPlugin extends JavaPlugin implements GeyserBootstrap { // Ensure that we have the latest 4.0.0 changes and not an older ViaVersion version Class.forName("com.viaversion.viaversion.api.ViaManager"); } catch (ClassNotFoundException e) { - geyserLogger.warning(GeyserLocale.getLocaleStringLog("geyser.bootstrap.viaversion.too_old", - "https://ci.viaversion.com/job/ViaVersion/")); + GeyserSpigotVersionChecker.sendOutdatedViaVersionMessage(geyserLogger); isViaVersion = false; if (this.geyserConfig.isDebugMode()) { e.printStackTrace(); @@ -242,6 +241,9 @@ public class GeyserSpigotPlugin extends JavaPlugin implements GeyserBootstrap { } this.getCommand("geyser").setExecutor(new GeyserSpigotCommandExecutor(geyser)); + + // Check to ensure the current setup can support the protocol version Geyser uses + GeyserSpigotVersionChecker.checkForSupportedProtocol(geyserLogger, isViaVersion); } @Override diff --git a/bootstrap/spigot/src/main/java/org/geysermc/geyser/platform/spigot/GeyserSpigotVersionChecker.java b/bootstrap/spigot/src/main/java/org/geysermc/geyser/platform/spigot/GeyserSpigotVersionChecker.java new file mode 100644 index 000000000..749323a1f --- /dev/null +++ b/bootstrap/spigot/src/main/java/org/geysermc/geyser/platform/spigot/GeyserSpigotVersionChecker.java @@ -0,0 +1,122 @@ +/* + * Copyright (c) 2019-2021 GeyserMC. http://geysermc.org + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + * @author GeyserMC + * @link https://github.com/GeyserMC/Geyser + */ + +package org.geysermc.geyser.platform.spigot; + +import com.viaversion.viaversion.api.Via; +import org.bukkit.Bukkit; +import org.bukkit.UnsafeValues; +import org.geysermc.geyser.GeyserLogger; +import org.geysermc.geyser.network.MinecraftProtocol; +import org.geysermc.geyser.text.GeyserLocale; + +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; +import java.lang.reflect.Modifier; + +public final class GeyserSpigotVersionChecker { + private static final String VIAVERSION_DOWNLOAD_URL = "https://ci.viaversion.com/job/ViaVersion/"; + + public static void checkForSupportedProtocol(GeyserLogger logger, boolean viaversion) { + if (viaversion) { + checkViaVersionSupportedVersions(logger); + return; + } + + try { + // This method is only present on later versions of Paper + UnsafeValues.class.getMethod("getProtocolVersion"); + if (Bukkit.getUnsafe().getProtocolVersion() != MinecraftProtocol.getJavaProtocolVersion()) { + sendOutdatedMessage(logger); + } + return; + } catch (NoSuchMethodException ignored) { + } + + // Otherwise, we can just try to find the SharedConstants class + // It isn't present in all server versions, but if we can't find it, then we're probably not in the latest version + Class sharedConstants; + try { + sharedConstants = Class.forName("net.minecraft.SharedConstants"); + } catch (ClassNotFoundException e) { + // We're using pre-1.17 + String prefix = Bukkit.getServer().getClass().getPackage().getName().replace("org.bukkit.craftbukkit", "net.minecraft.server"); + try { + sharedConstants = Class.forName(prefix + ".SharedConstants"); + } catch (ClassNotFoundException e2) { + sendOutdatedMessage(logger); + return; + } + } + for (Method method : sharedConstants.getMethods()) { + if (method.getReturnType() == int.class && Modifier.isStatic(method.getModifiers())) { + int protocolVersion; + try { + protocolVersion = (int) method.invoke(null); + } catch (IllegalAccessException | InvocationTargetException e) { + logger.warning("Could not determine server version! This is safe to ignore, but please report to the developers: " + e.getMessage()); + if (logger.isDebug()) { + e.printStackTrace(); + } + return; + } + if (protocolVersion != MinecraftProtocol.getJavaProtocolVersion()) { + sendOutdatedMessage(logger); + } + return; + } + } + sendOutdatedMessage(logger); + } + + private static void checkViaVersionSupportedVersions(GeyserLogger logger) { + // Run after ViaVersion has obtained the server protocol version + Via.getPlatform().runSync(() -> { + if (Via.getAPI().getSupportedVersions().contains(MinecraftProtocol.getJavaProtocolVersion())) { + // Via supports this protocol version; we will be able to connect. + return; + } + if (Via.getAPI().getFullSupportedVersions().contains(MinecraftProtocol.getJavaProtocolVersion())) { + // ViaVersion supports our protocol, but the user has blocked them from connecting. + logger.warning(GeyserLocale.getLocaleStringLog("geyser.bootstrap.viaversion.blocked", MinecraftProtocol.getAllSupportedJavaVersions())); + return; + } + // Else, presumably, ViaVersion is not updated. + sendOutdatedViaVersionMessage(logger); + }); + } + + public static void sendOutdatedViaVersionMessage(GeyserLogger logger) { + logger.warning(GeyserLocale.getLocaleStringLog("geyser.bootstrap.viaversion.too_old", + VIAVERSION_DOWNLOAD_URL)); + } + + private static void sendOutdatedMessage(GeyserLogger logger) { + logger.warning(GeyserLocale.getLocaleStringLog("geyser.bootstrap.no_supported_protocol", MinecraftProtocol.getAllSupportedJavaVersions(), VIAVERSION_DOWNLOAD_URL)); + } + + private GeyserSpigotVersionChecker() { + } +}