diff --git a/api/src/main/java/us/myles/ViaVersion/api/ViaAPI.java b/api/src/main/java/us/myles/ViaVersion/api/ViaAPI.java index c61109735..01232b81f 100644 --- a/api/src/main/java/us/myles/ViaVersion/api/ViaAPI.java +++ b/api/src/main/java/us/myles/ViaVersion/api/ViaAPI.java @@ -26,6 +26,7 @@ import io.netty.buffer.ByteBuf; import us.myles.ViaVersion.api.boss.BossBar; import us.myles.ViaVersion.api.boss.BossColor; import us.myles.ViaVersion.api.boss.BossStyle; +import us.myles.ViaVersion.api.protocol.ServerProtocolVersion; import java.util.SortedSet; import java.util.UUID; @@ -38,12 +39,11 @@ import java.util.UUID; public interface ViaAPI { /** - * Returns the server's protocol version. - * In the case of a proxy, this is the lowest supported version. + * Returns the server's protocol version info. * - * @return the server's protocol version + * @return the server's protocol version info */ - int getServerVersion(); + ServerProtocolVersion getServerVersion(); /** * Get protocol version number from a player. diff --git a/api/src/main/java/us/myles/ViaVersion/api/platform/ViaInjector.java b/api/src/main/java/us/myles/ViaVersion/api/platform/ViaInjector.java index aea4d2407..a405eea98 100644 --- a/api/src/main/java/us/myles/ViaVersion/api/platform/ViaInjector.java +++ b/api/src/main/java/us/myles/ViaVersion/api/platform/ViaInjector.java @@ -23,8 +23,11 @@ package us.myles.ViaVersion.api.platform; import com.google.gson.JsonObject; +import it.unimi.dsi.fastutil.ints.IntSortedSet; +import it.unimi.dsi.fastutil.ints.IntSortedSets; public interface ViaInjector { + /** * Inject into the current Platform * @@ -40,13 +43,36 @@ public interface ViaInjector { void uninject() throws Exception; /** - * Get the server protocol version + * Returns true if the protocol version cannot be used in the early init. + * Namely, this returns true for forks of Vanilla without extra API to get the protocol version. * - * @return The server protocol integer - * @throws Exception If there is an error with getting this info, eg. not binded. + * @return true if the protocol version cannot be used in the early init + */ + default boolean lateProtocolVersionSetting() { + return false; + } + + /** + * Returns the server protocol version. + * For proxies, this returns the lowest supported protocol version. + * + * @return server protocol version + * @throws Exception if there is an error with getting this info, eg. not binded + * @see ViaPlatform#isProxy() */ int getServerProtocolVersion() throws Exception; + /** + * Returns the supported server protocol versions. + * + * @return server protocol versions + * @throws Exception if there is an error with getting this info, eg. not binded + * @see ViaPlatform#isProxy() + */ + default IntSortedSet getServerProtocolVersions() throws Exception { + return IntSortedSets.singleton(getServerProtocolVersion()); + } + /** * Get the name of the encoder for then netty pipeline for this platform. * diff --git a/api/src/main/java/us/myles/ViaVersion/api/protocol/ProtocolManager.java b/api/src/main/java/us/myles/ViaVersion/api/protocol/ProtocolManager.java index a8aa831ee..b1a85cd87 100644 --- a/api/src/main/java/us/myles/ViaVersion/api/protocol/ProtocolManager.java +++ b/api/src/main/java/us/myles/ViaVersion/api/protocol/ProtocolManager.java @@ -32,12 +32,11 @@ import java.util.concurrent.CompletableFuture; public interface ProtocolManager { /** - * Returns the server protocol version, or -1 if not set. - * In the case of proxies, this returns the lowest supported protocol version. + * Returns the server protocol version. Its methods will return -1 if not set yet. * - * @return server protocol version, or -1 if not set + * @return server protocol version */ - int getServerProtocol(); + ServerProtocolVersion getServerProtocolVersion(); /** * Returns a protocol instance by its class. diff --git a/api/src/main/java/us/myles/ViaVersion/api/protocol/ServerProtocolVersion.java b/api/src/main/java/us/myles/ViaVersion/api/protocol/ServerProtocolVersion.java new file mode 100644 index 000000000..3026ea80b --- /dev/null +++ b/api/src/main/java/us/myles/ViaVersion/api/protocol/ServerProtocolVersion.java @@ -0,0 +1,57 @@ +/* + * This file is part of ViaVersion - https://github.com/ViaVersion/ViaVersion + * Copyright (C) 2016-2021 ViaVersion and contributors + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +package us.myles.ViaVersion.api.protocol; + +import it.unimi.dsi.fastutil.ints.IntSortedSet; + +public interface ServerProtocolVersion { + + /** + * Returns the lowest supported protocol version by this server. + * This and {@link #highestSupportedVersion()} should only differ on proxy servers supporting multiple versions. + * + * @return lowest supported protocol version + */ + int lowestSupportedVersion(); + + /** + * Returns the lowest supported protocol version by this server. + * This and {@link #lowestSupportedVersion()} should only differ on proxy servers supporting multiple versions. + * + * @return highest supported protocol version + */ + int highestSupportedVersion(); + + /** + * Returns a sorted set of all supported protocol version by this server. + * For non-proxy servers, this should return a singleton set. + * + * @return sorted set of supported protocol versions + */ + IntSortedSet supportedVersions(); + + /** + * Returns true if the actual protocol version has not yet been identified. + * In that case, all methods above will returns -1. + * + * @return true if unset + */ + default boolean isKnown() { + return lowestSupportedVersion() != -1 && highestSupportedVersion() != -1; + } +} diff --git a/api/src/main/java/us/myles/ViaVersion/protocols/base/VersionProvider.java b/api/src/main/java/us/myles/ViaVersion/protocols/base/VersionProvider.java index 4e3612796..c2390e34b 100644 --- a/api/src/main/java/us/myles/ViaVersion/protocols/base/VersionProvider.java +++ b/api/src/main/java/us/myles/ViaVersion/protocols/base/VersionProvider.java @@ -27,5 +27,11 @@ import us.myles.ViaVersion.api.platform.providers.Provider; public interface VersionProvider extends Provider { + /** + * Returns the closest server protocol version to the user's protocol version. + * + * @param connection connection + * @return closest server protocol version to the user's protocol version + */ int getServerProtocol(UserConnection connection) throws Exception; } diff --git a/buildSrc/src/main/kotlin/extensions.kt b/buildSrc/src/main/kotlin/extensions.kt index 255f003af..719a7b65e 100644 --- a/buildSrc/src/main/kotlin/extensions.kt +++ b/buildSrc/src/main/kotlin/extensions.kt @@ -70,8 +70,6 @@ private fun ShadowJar.configureExcludes() { exclude("it/unimi/dsi/fastutil/*/*Char*") // Map types exclude("it/unimi/dsi/fastutil/*/*Custom*") - exclude("it/unimi/dsi/fastutil/*/*Linked*") - exclude("it/unimi/dsi/fastutil/*/*Sorted*") exclude("it/unimi/dsi/fastutil/*/*Tree*") exclude("it/unimi/dsi/fastutil/*/*Heap*") exclude("it/unimi/dsi/fastutil/*/*Queue*") diff --git a/bukkit/src/main/java/us/myles/ViaVersion/bukkit/listeners/multiversion/PlayerSneakListener.java b/bukkit/src/main/java/us/myles/ViaVersion/bukkit/listeners/multiversion/PlayerSneakListener.java index 5ddfa0b4a..e97a86fa3 100644 --- a/bukkit/src/main/java/us/myles/ViaVersion/bukkit/listeners/multiversion/PlayerSneakListener.java +++ b/bukkit/src/main/java/us/myles/ViaVersion/bukkit/listeners/multiversion/PlayerSneakListener.java @@ -68,7 +68,7 @@ public class PlayerSneakListener extends ViaBukkitListener { // From 1.9 upwards the server hitbox is set in every entity tick, so we have to reset it everytime - if (Via.getAPI().getServerVersion() >= ProtocolVersion.v1_9.getVersion()) { + if (Via.getAPI().getServerVersion().lowestSupportedVersion() >= ProtocolVersion.v1_9.getVersion()) { sneaking = new WeakHashMap<>(); useCache = true; plugin.getServer().getScheduler().runTaskTimer(plugin, new Runnable() { diff --git a/bukkit/src/main/java/us/myles/ViaVersion/bukkit/platform/BukkitViaInjector.java b/bukkit/src/main/java/us/myles/ViaVersion/bukkit/platform/BukkitViaInjector.java index 7bc71587d..54692259b 100644 --- a/bukkit/src/main/java/us/myles/ViaVersion/bukkit/platform/BukkitViaInjector.java +++ b/bukkit/src/main/java/us/myles/ViaVersion/bukkit/platform/BukkitViaInjector.java @@ -179,6 +179,11 @@ public class BukkitViaInjector implements ViaInjector { injectedLists.clear(); } + @Override + public boolean lateProtocolVersionSetting() { + return true; + } + @Override public int getServerProtocolVersion() throws Exception { try { diff --git a/bukkit/src/main/java/us/myles/ViaVersion/bukkit/platform/BukkitViaLoader.java b/bukkit/src/main/java/us/myles/ViaVersion/bukkit/platform/BukkitViaLoader.java index 9352fb70c..b353f1ea5 100644 --- a/bukkit/src/main/java/us/myles/ViaVersion/bukkit/platform/BukkitViaLoader.java +++ b/bukkit/src/main/java/us/myles/ViaVersion/bukkit/platform/BukkitViaLoader.java @@ -85,9 +85,10 @@ public class BukkitViaLoader implements ViaPlatformLoader { // Add ProtocolSupport ConnectListener if necessary. ClassGenerator.registerPSConnectListener(plugin); + int serverProtocolVersion = Via.getAPI().getServerVersion().lowestSupportedVersion(); /* 1.9 client to 1.8 server */ - if (Via.getAPI().getServerVersion() < ProtocolVersion.v1_9.getVersion()) { + if (serverProtocolVersion < ProtocolVersion.v1_9.getVersion()) { storeListener(new ArmorListener(plugin)).register(); storeListener(new DeathListener(plugin)).register(); storeListener(new BlockListener(plugin)).register(); @@ -98,8 +99,8 @@ public class BukkitViaLoader implements ViaPlatformLoader { } } - if (Via.getAPI().getServerVersion() < ProtocolVersion.v1_14.getVersion()) { - boolean use1_9Fix = plugin.getConf().is1_9HitboxFix() && Via.getAPI().getServerVersion() < ProtocolVersion.v1_9.getVersion(); + if (serverProtocolVersion < ProtocolVersion.v1_14.getVersion()) { + boolean use1_9Fix = plugin.getConf().is1_9HitboxFix() && serverProtocolVersion < ProtocolVersion.v1_9.getVersion(); if (use1_9Fix || plugin.getConf().is1_14HitboxFix()) { try { storeListener(new PlayerSneakListener(plugin, use1_9Fix, plugin.getConf().is1_14HitboxFix())).register(); @@ -110,7 +111,7 @@ public class BukkitViaLoader implements ViaPlatformLoader { } } - if (Via.getAPI().getServerVersion() < ProtocolVersion.v1_15.getVersion()) { + if (serverProtocolVersion < ProtocolVersion.v1_15.getVersion()) { try { Class.forName("org.bukkit.event.entity.EntityToggleGlideEvent"); storeListener(new EntityToggleGlideListener(plugin)).register(); @@ -121,13 +122,13 @@ public class BukkitViaLoader implements ViaPlatformLoader { if ((Bukkit.getVersion().toLowerCase(Locale.ROOT).contains("paper") || Bukkit.getVersion().toLowerCase(Locale.ROOT).contains("taco") || Bukkit.getVersion().toLowerCase(Locale.ROOT).contains("torch")) - && Via.getAPI().getServerVersion() < ProtocolVersion.v1_12.getVersion()) { + && serverProtocolVersion < ProtocolVersion.v1_12.getVersion()) { plugin.getLogger().info("Enabling Paper/TacoSpigot/Torch patch: Fixes block placement."); storeListener(new PaperPatch(plugin)).register(); } /* Providers */ - if (Via.getAPI().getServerVersion() < ProtocolVersion.v1_9.getVersion()) { + if (serverProtocolVersion < ProtocolVersion.v1_9.getVersion()) { Via.getManager().getProviders().use(BulkChunkTranslatorProvider.class, new BukkitViaBulkChunkTranslator()); Via.getManager().getProviders().use(MovementTransmitterProvider.class, new BukkitViaMovementTransmitter()); @@ -156,12 +157,12 @@ public class BukkitViaLoader implements ViaPlatformLoader { }); } - if (Via.getAPI().getServerVersion() < ProtocolVersion.v1_12.getVersion()) { + if (serverProtocolVersion < ProtocolVersion.v1_12.getVersion()) { if (plugin.getConf().is1_12QuickMoveActionFix()) { Via.getManager().getProviders().use(InventoryQuickMoveProvider.class, new BukkitInventoryQuickMoveProvider()); } } - if (Via.getAPI().getServerVersion() < ProtocolVersion.v1_13.getVersion()) { + if (serverProtocolVersion < ProtocolVersion.v1_13.getVersion()) { if (Via.getConfig().getBlockConnectionMethod().equalsIgnoreCase("world")) { BukkitBlockConnectionProvider blockConnectionProvider = new BukkitBlockConnectionProvider(); Via.getManager().getProviders().use(BlockConnectionProvider.class, blockConnectionProvider); diff --git a/bukkit/src/main/java/us/myles/ViaVersion/bukkit/providers/BukkitInventoryQuickMoveProvider.java b/bukkit/src/main/java/us/myles/ViaVersion/bukkit/providers/BukkitInventoryQuickMoveProvider.java index f11722892..2075240be 100644 --- a/bukkit/src/main/java/us/myles/ViaVersion/bukkit/providers/BukkitInventoryQuickMoveProvider.java +++ b/bukkit/src/main/java/us/myles/ViaVersion/bukkit/providers/BukkitInventoryQuickMoveProvider.java @@ -70,7 +70,7 @@ public class BukkitInventoryQuickMoveProvider extends InventoryQuickMoveProvider // windowId is always 0 for player inventory. // This has almost definitely something to do with the offhand slot. if (slotId >= 36 && slotId <= 44) { - int protocolId = Via.getAPI().getServerVersion(); + int protocolId = Via.getAPI().getServerVersion().lowestSupportedVersion(); // this seems to be working just fine. if (protocolId == ProtocolVersion.v1_8.getVersion()) { return false; @@ -102,7 +102,7 @@ public class BukkitInventoryQuickMoveProvider extends InventoryQuickMoveProvider Inventory tinv = inv.getTopInventory(); InventoryType tinvtype = tinv == null ? null : tinv.getType(); // can this even be null? if (tinvtype != null) { - int protocolId = Via.getAPI().getServerVersion(); + int protocolId = Via.getAPI().getServerVersion().lowestSupportedVersion(); if (protocolId == ProtocolVersion.v1_8.getVersion()) { if (tinvtype == InventoryType.BREWING) { // 1.9 added the blaze powder slot to brewing stand fix for 1.8 servers @@ -131,7 +131,7 @@ public class BukkitInventoryQuickMoveProvider extends InventoryQuickMoveProvider ReflectionUtil.set(packet, "button", 0); // shift + left mouse click ReflectionUtil.set(packet, "d", storage.getActionId()); ReflectionUtil.set(packet, "item", nmsItem); - int protocolId = Via.getAPI().getServerVersion(); + int protocolId = Via.getAPI().getServerVersion().lowestSupportedVersion(); if (protocolId == ProtocolVersion.v1_8.getVersion()) { ReflectionUtil.set(packet, "shift", 1); } else if (protocolId >= ProtocolVersion.v1_9.getVersion()) { // 1.9+ @@ -170,7 +170,7 @@ public class BukkitInventoryQuickMoveProvider extends InventoryQuickMoveProvider } try { this.windowClickPacketClass = NMSUtil.nms("PacketPlayInWindowClick"); - int protocolId = Via.getAPI().getServerVersion(); + int protocolId = Via.getAPI().getServerVersion().lowestSupportedVersion(); if (protocolId >= ProtocolVersion.v1_9.getVersion()) { Class eclassz = NMSUtil.nms("InventoryClickType"); Object[] constants = eclassz.getEnumConstants(); @@ -199,7 +199,7 @@ public class BukkitInventoryQuickMoveProvider extends InventoryQuickMoveProvider } private boolean isSupported() { - int protocolId = Via.getAPI().getServerVersion(); + int protocolId = Via.getAPI().getServerVersion().lowestSupportedVersion(); if (protocolId >= ProtocolVersion.v1_8.getVersion() && protocolId <= ProtocolVersion.v1_11_1.getVersion()) { return true; // 1.8-1.11.2 } diff --git a/bungee/src/main/java/us/myles/ViaVersion/BungeePlugin.java b/bungee/src/main/java/us/myles/ViaVersion/BungeePlugin.java index 8cfc5f047..a169ae132 100644 --- a/bungee/src/main/java/us/myles/ViaVersion/BungeePlugin.java +++ b/bungee/src/main/java/us/myles/ViaVersion/BungeePlugin.java @@ -56,7 +56,7 @@ public class BungeePlugin extends Plugin implements ViaPlatform, @Override public void onLoad() { try { - ProtocolConstants.class.getField("MINECRAFT_1_16_3"); + ProtocolConstants.class.getField("MINECRAFT_1_16_4"); } catch (NoSuchFieldException e) { getLogger().warning(" / \\"); getLogger().warning(" / \\"); diff --git a/bungee/src/main/java/us/myles/ViaVersion/bungee/platform/BungeeViaInjector.java b/bungee/src/main/java/us/myles/ViaVersion/bungee/platform/BungeeViaInjector.java index 120826cca..567060af1 100644 --- a/bungee/src/main/java/us/myles/ViaVersion/bungee/platform/BungeeViaInjector.java +++ b/bungee/src/main/java/us/myles/ViaVersion/bungee/platform/BungeeViaInjector.java @@ -20,6 +20,8 @@ package us.myles.ViaVersion.bungee.platform; import com.google.gson.JsonObject; import io.netty.channel.Channel; import io.netty.channel.ChannelInitializer; +import it.unimi.dsi.fastutil.ints.IntLinkedOpenHashSet; +import it.unimi.dsi.fastutil.ints.IntSortedSet; import us.myles.ViaVersion.api.Via; import us.myles.ViaVersion.api.platform.ViaInjector; import us.myles.ViaVersion.bungee.handlers.BungeeChannelInitializer; @@ -77,7 +79,16 @@ public class BungeeViaInjector implements ViaInjector { @Override public int getServerProtocolVersion() throws Exception { - return (int) ReflectionUtil.getStatic(Class.forName("net.md_5.bungee.protocol.ProtocolConstants"), "SUPPORTED_VERSION_IDS", List.class).get(0); + return getBungeeSupportedVersions().get(0); + } + + @Override + public IntSortedSet getServerProtocolVersions() throws Exception { + return new IntLinkedOpenHashSet(getBungeeSupportedVersions()); + } + + private List getBungeeSupportedVersions() throws Exception { + return ReflectionUtil.getStatic(Class.forName("net.md_5.bungee.protocol.ProtocolConstants"), "SUPPORTED_VERSION_IDS", List.class); } @Override diff --git a/bungee/src/main/java/us/myles/ViaVersion/bungee/platform/BungeeViaLoader.java b/bungee/src/main/java/us/myles/ViaVersion/bungee/platform/BungeeViaLoader.java index ab62220cb..45462fff3 100644 --- a/bungee/src/main/java/us/myles/ViaVersion/bungee/platform/BungeeViaLoader.java +++ b/bungee/src/main/java/us/myles/ViaVersion/bungee/platform/BungeeViaLoader.java @@ -65,7 +65,7 @@ public class BungeeViaLoader implements ViaPlatformLoader { registerListener(new UpdateListener()); registerListener(new BungeeServerHandler()); - if (Via.getAPI().getServerVersion() < ProtocolVersion.v1_9.getVersion()) { + if (Via.getAPI().getServerVersion().lowestSupportedVersion() < ProtocolVersion.v1_9.getVersion()) { registerListener(new ElytraPatch()); } @@ -73,7 +73,7 @@ public class BungeeViaLoader implements ViaPlatformLoader { Via.getManager().getProviders().use(VersionProvider.class, new BungeeVersionProvider()); Via.getManager().getProviders().use(EntityIdProvider.class, new BungeeEntityIdProvider()); - if (Via.getAPI().getServerVersion() < ProtocolVersion.v1_9.getVersion()) { + if (Via.getAPI().getServerVersion().lowestSupportedVersion() < ProtocolVersion.v1_9.getVersion()) { Via.getManager().getProviders().use(MovementTransmitterProvider.class, new BungeeMovementTransmitter()); Via.getManager().getProviders().use(BossBarProvider.class, new BungeeBossBarProvider()); Via.getManager().getProviders().use(MainHandProvider.class, new BungeeMainHandProvider()); diff --git a/common/src/main/java/us/myles/ViaVersion/ViaManagerImpl.java b/common/src/main/java/us/myles/ViaVersion/ViaManagerImpl.java index f0aca6e36..9526f0f5b 100644 --- a/common/src/main/java/us/myles/ViaVersion/ViaManagerImpl.java +++ b/common/src/main/java/us/myles/ViaVersion/ViaManagerImpl.java @@ -17,6 +17,7 @@ */ package us.myles.ViaVersion; +import it.unimi.dsi.fastutil.ints.IntSortedSet; import us.myles.ViaVersion.api.Via; import us.myles.ViaVersion.api.platform.TaskId; import us.myles.ViaVersion.api.platform.ViaConnectionManager; @@ -27,12 +28,16 @@ import us.myles.ViaVersion.api.platform.providers.ViaProviders; import us.myles.ViaVersion.api.protocol.ProtocolManager; import us.myles.ViaVersion.api.protocol.ProtocolManagerImpl; import us.myles.ViaVersion.api.protocol.ProtocolVersion; +import us.myles.ViaVersion.api.protocol.ServerProtocolVersion; +import us.myles.ViaVersion.api.protocol.ServerProtocolVersionRange; +import us.myles.ViaVersion.api.protocol.ServerProtocolVersionSingleton; import us.myles.ViaVersion.commands.ViaCommandHandler; import us.myles.ViaVersion.protocols.protocol1_13to1_12_2.TabCompleteThread; import us.myles.ViaVersion.protocols.protocol1_9to1_8.ViaIdleThread; import us.myles.ViaVersion.update.UpdateUtil; import java.util.ArrayList; +import java.util.Arrays; import java.util.HashSet; import java.util.List; import java.util.Set; @@ -71,6 +76,11 @@ public class ViaManagerImpl implements ViaManager { UpdateUtil.sendUpdateMessage(); } + // Load supported protocol versions if we can + if (!injector.lateProtocolVersionSetting()) { + loadServerProtocol(); + } + // Register protocols protocolManager.registerProtocols(); @@ -96,24 +106,33 @@ public class ViaManagerImpl implements ViaManager { } public void onServerLoaded() { - // Load Server Protocol - try { - protocolManager.setServerProtocol(ProtocolVersion.getProtocol(injector.getServerProtocolVersion()).getVersion()); - } catch (Exception e) { - platform.getLogger().severe("ViaVersion failed to get the server protocol!"); - e.printStackTrace(); + if (!protocolManager.getServerProtocolVersion().isKnown()) { + // Try again + loadServerProtocol(); } // Check if there are any pipes to this version - if (protocolManager.getServerProtocol() != -1) { - platform.getLogger().info("ViaVersion detected server version: " + ProtocolVersion.getProtocol(protocolManager.getServerProtocol())); - if (!protocolManager.isWorkingPipe() && !platform.isProxy()) { + ServerProtocolVersion protocolVersion = protocolManager.getServerProtocolVersion(); + if (protocolVersion.isKnown()) { + if (platform.isProxy()) { + platform.getLogger().info("ViaVersion detected lowest supported versions by the proxy: " + + ProtocolVersion.getProtocol(protocolVersion.lowestSupportedVersion()) + + "\nHighest supported version by the proxy: " + + ProtocolVersion.getProtocol(protocolVersion.highestSupportedVersion())); + if (debug) { + platform.getLogger().info("Supported version range: " + Arrays.toString(protocolVersion.supportedVersions().toArray(new int[0]))); + } + } else { + platform.getLogger().info("ViaVersion detected server version: " + ProtocolVersion.getProtocol(protocolVersion.highestSupportedVersion())); + } + + if (!protocolManager.isWorkingPipe()) { platform.getLogger().warning("ViaVersion does not have any compatible versions for this server version!"); platform.getLogger().warning("Please remember that ViaVersion only adds support for versions newer than the server version."); platform.getLogger().warning("If you need support for older versions you may need to use one or more ViaVersion addons too."); platform.getLogger().warning("In that case please read the ViaVersion resource page carefully or use https://jo0001.github.io/ViaSetup"); platform.getLogger().warning("and if you're still unsure, feel free to join our Discord-Server for further assistance."); - } else if (protocolManager.getServerProtocol() <= ProtocolVersion.v1_12_2.getVersion() && !platform.isProxy()) { + } else if (protocolVersion.highestSupportedVersion() <= ProtocolVersion.v1_12_2.getVersion()) { platform.getLogger().warning("This version of Minecraft is extremely outdated and support for it has reached its end of life. " + "You will still be able to run Via on this version, but we are unlikely to provide any further fixes or help with problems specific to legacy versions. " + "Please consider updating to give your players a better experience and to avoid issues that have long been fixed."); @@ -132,12 +151,14 @@ public class ViaManagerImpl implements ViaManager { mappingLoadingTask = null; } }, 10L); - if (protocolManager.getServerProtocol() < ProtocolVersion.v1_9.getVersion()) { + + int serverProtocolVersion = protocolManager.getServerProtocolVersion().lowestSupportedVersion(); + if (serverProtocolVersion < ProtocolVersion.v1_9.getVersion()) { if (Via.getConfig().isSimulatePlayerTick()) { Via.getPlatform().runRepeatingSync(new ViaIdleThread(), 1L); } } - if (protocolManager.getServerProtocol() < ProtocolVersion.v1_13.getVersion()) { + if (serverProtocolVersion < ProtocolVersion.v1_13.getVersion()) { if (Via.getConfig().get1_13TabCompleteDelay() > 0) { Via.getPlatform().runRepeatingSync(new TabCompleteThread(), 1L); } @@ -147,6 +168,24 @@ public class ViaManagerImpl implements ViaManager { protocolManager.refreshVersions(); } + private void loadServerProtocol() { + try { + ProtocolVersion serverProtocolVersion = ProtocolVersion.getProtocol(injector.getServerProtocolVersion()); + ServerProtocolVersion versionInfo; + if (platform.isProxy()) { + IntSortedSet supportedVersions = injector.getServerProtocolVersions(); + versionInfo = new ServerProtocolVersionRange(supportedVersions.firstInt(), supportedVersions.lastInt(), supportedVersions); + } else { + versionInfo = new ServerProtocolVersionSingleton(serverProtocolVersion.getVersion()); + } + + protocolManager.setServerProtocol(versionInfo); + } catch (Exception e) { + platform.getLogger().severe("ViaVersion failed to get the server protocol!"); + e.printStackTrace(); + } + } + public void destroy() { // Uninject platform.getLogger().info("ViaVersion is disabling, if this is a reload and you experience issues consider rebooting."); diff --git a/common/src/main/java/us/myles/ViaVersion/api/ViaAPIBase.java b/common/src/main/java/us/myles/ViaVersion/api/ViaAPIBase.java index b49f45a4f..7a97ce39b 100644 --- a/common/src/main/java/us/myles/ViaVersion/api/ViaAPIBase.java +++ b/common/src/main/java/us/myles/ViaVersion/api/ViaAPIBase.java @@ -19,6 +19,7 @@ package us.myles.ViaVersion.api; import io.netty.buffer.ByteBuf; import us.myles.ViaVersion.api.data.UserConnection; +import us.myles.ViaVersion.api.protocol.ServerProtocolVersion; import java.util.SortedSet; import java.util.TreeSet; @@ -27,8 +28,8 @@ import java.util.UUID; public abstract class ViaAPIBase implements ViaAPI { @Override - public int getServerVersion() { - return Via.getManager().getProtocolManager().getServerProtocol(); + public ServerProtocolVersion getServerVersion() { + return Via.getManager().getProtocolManager().getServerProtocolVersion(); } @Override diff --git a/common/src/main/java/us/myles/ViaVersion/api/protocol/ProtocolManagerImpl.java b/common/src/main/java/us/myles/ViaVersion/api/protocol/ProtocolManagerImpl.java index 32f87a5af..52da7f7c2 100644 --- a/common/src/main/java/us/myles/ViaVersion/api/protocol/ProtocolManagerImpl.java +++ b/common/src/main/java/us/myles/ViaVersion/api/protocol/ProtocolManagerImpl.java @@ -95,8 +95,8 @@ public class ProtocolManagerImpl implements ProtocolManager { private ThreadPoolExecutor mappingLoaderExecutor; private boolean mappingsLoaded; + private ServerProtocolVersion serverProtocolVersion = new ServerProtocolVersionSingleton(-1); private int maxProtocolPathSize = 50; - private int serverProtocol = -1; public ProtocolManagerImpl() { ThreadFactory threadFactory = new ThreadFactoryBuilder().setNameFormat("Via-Mappingloader-%d").build(); @@ -199,9 +199,9 @@ public class ProtocolManagerImpl implements ProtocolManager { public void refreshVersions() { supportedVersions.clear(); - supportedVersions.add(serverProtocol); + supportedVersions.add(serverProtocolVersion.lowestSupportedVersion()); for (ProtocolVersion versions : ProtocolVersion.getProtocols()) { - List paths = getProtocolPath(versions.getVersion(), serverProtocol); + List paths = getProtocolPath(versions.getVersion(), serverProtocolVersion.lowestSupportedVersion()); if (paths == null) continue; supportedVersions.add(versions.getVersion()); for (ProtocolPathEntry path : paths) { @@ -309,19 +309,23 @@ public class ProtocolManagerImpl implements ProtocolManager { } @Override - public int getServerProtocol() { - return serverProtocol; + public ServerProtocolVersion getServerProtocolVersion() { + return serverProtocolVersion; } - public void setServerProtocol(int serverProtocol) { - this.serverProtocol = serverProtocol; - ProtocolRegistry.SERVER_PROTOCOL = serverProtocol; + public void setServerProtocol(ServerProtocolVersion serverProtocolVersion) { + this.serverProtocolVersion = serverProtocolVersion; + ProtocolRegistry.SERVER_PROTOCOL = serverProtocolVersion.lowestSupportedVersion(); } @Override public boolean isWorkingPipe() { for (Int2ObjectMap map : registryMap.values()) { - if (map.containsKey(serverProtocol)) return true; + for (int protocolVersion : serverProtocolVersion.supportedVersions()) { + if (map.containsKey(protocolVersion)) { + return true; + } + } } return false; // No destination for protocol } diff --git a/common/src/main/java/us/myles/ViaVersion/api/protocol/ServerProtocolVersionRange.java b/common/src/main/java/us/myles/ViaVersion/api/protocol/ServerProtocolVersionRange.java new file mode 100644 index 000000000..5a1b69ff0 --- /dev/null +++ b/common/src/main/java/us/myles/ViaVersion/api/protocol/ServerProtocolVersionRange.java @@ -0,0 +1,47 @@ +/* + * This file is part of ViaVersion - https://github.com/ViaVersion/ViaVersion + * Copyright (C) 2016-2021 ViaVersion and contributors + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +package us.myles.ViaVersion.api.protocol; + +import it.unimi.dsi.fastutil.ints.IntSortedSet; + +public class ServerProtocolVersionRange implements ServerProtocolVersion { + private final int lowestSupportedVersion; + private final int highestSupportedVersion; + private final IntSortedSet supportedVersions; + + public ServerProtocolVersionRange(int lowestSupportedVersion, int highestSupportedVersion, IntSortedSet supportedVersions) { + this.lowestSupportedVersion = lowestSupportedVersion; + this.highestSupportedVersion = highestSupportedVersion; + this.supportedVersions = supportedVersions; + } + + @Override + public int lowestSupportedVersion() { + return lowestSupportedVersion; + } + + @Override + public int highestSupportedVersion() { + return highestSupportedVersion; + } + + @Override + public IntSortedSet supportedVersions() { + return supportedVersions; + } +} diff --git a/common/src/main/java/us/myles/ViaVersion/api/protocol/ServerProtocolVersionSingleton.java b/common/src/main/java/us/myles/ViaVersion/api/protocol/ServerProtocolVersionSingleton.java new file mode 100644 index 000000000..1d4a5f9ae --- /dev/null +++ b/common/src/main/java/us/myles/ViaVersion/api/protocol/ServerProtocolVersionSingleton.java @@ -0,0 +1,44 @@ +/* + * This file is part of ViaVersion - https://github.com/ViaVersion/ViaVersion + * Copyright (C) 2016-2021 ViaVersion and contributors + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +package us.myles.ViaVersion.api.protocol; + +import it.unimi.dsi.fastutil.ints.IntSortedSet; +import it.unimi.dsi.fastutil.ints.IntSortedSets; + +public class ServerProtocolVersionSingleton implements ServerProtocolVersion { + private final int protocolVersion; + + public ServerProtocolVersionSingleton(int protocolVersion) { + this.protocolVersion = protocolVersion; + } + + @Override + public int lowestSupportedVersion() { + return protocolVersion; + } + + @Override + public int highestSupportedVersion() { + return protocolVersion; + } + + @Override + public IntSortedSet supportedVersions() { + return IntSortedSets.singleton(protocolVersion); + } +} diff --git a/common/src/main/java/us/myles/ViaVersion/commands/defaultsubs/DumpSubCmd.java b/common/src/main/java/us/myles/ViaVersion/commands/defaultsubs/DumpSubCmd.java index a36b91ae8..5b2088b4c 100644 --- a/common/src/main/java/us/myles/ViaVersion/commands/defaultsubs/DumpSubCmd.java +++ b/common/src/main/java/us/myles/ViaVersion/commands/defaultsubs/DumpSubCmd.java @@ -53,7 +53,7 @@ public class DumpSubCmd extends ViaSubCommand { VersionInfo version = new VersionInfo( System.getProperty("java.version"), System.getProperty("os.name"), - Via.getAPI().getServerVersion(), + Via.getAPI().getServerVersion().lowestSupportedVersion(), Via.getManager().getProtocolManager().getSupportedVersions(), Via.getPlatform().getPlatformName(), Via.getPlatform().getPlatformVersion(), diff --git a/common/src/main/java/us/myles/ViaVersion/protocols/base/BaseProtocol1_7.java b/common/src/main/java/us/myles/ViaVersion/protocols/base/BaseProtocol1_7.java index f6b1070ab..5e130bf4b 100644 --- a/common/src/main/java/us/myles/ViaVersion/protocols/base/BaseProtocol1_7.java +++ b/common/src/main/java/us/myles/ViaVersion/protocols/base/BaseProtocol1_7.java @@ -27,6 +27,7 @@ import us.myles.ViaVersion.api.Via; import us.myles.ViaVersion.api.protocol.ProtocolManagerImpl; import us.myles.ViaVersion.api.protocol.ProtocolPathEntry; import us.myles.ViaVersion.api.protocol.ProtocolVersion; +import us.myles.ViaVersion.api.protocol.ServerProtocolVersionSingleton; import us.myles.ViaVersion.api.protocol.SimpleProtocol; import us.myles.ViaVersion.api.remapper.PacketHandler; import us.myles.ViaVersion.api.remapper.PacketRemapper; @@ -80,9 +81,9 @@ public class BaseProtocol1_7 extends SimpleProtocol { version.add("supportedVersions", GsonUtil.getGson().toJsonTree(Via.getAPI().getSupportedVersions())); } - if (Via.getAPI().getServerVersion() == -1) { // Set the Server protocol if the detection on startup failed + if (!Via.getAPI().getServerVersion().isKnown()) { // Set the Server protocol if the detection on startup failed ProtocolManagerImpl protocolManager = (ProtocolManagerImpl) Via.getManager().getProtocolManager(); - protocolManager.setServerProtocol(ProtocolVersion.getProtocol(protocolVersion).getVersion()); + protocolManager.setServerProtocol(new ServerProtocolVersionSingleton(ProtocolVersion.getProtocol(protocolVersion).getVersion())); } // Ensure the server has a version provider @@ -92,16 +93,14 @@ public class BaseProtocol1_7 extends SimpleProtocol { return; } - int protocol = versionProvider.getServerProtocol(wrapper.user()); + int closestServerProtocol = versionProvider.getServerProtocol(wrapper.user()); List protocols = null; - - // Only allow newer clients or (1.9.2 on 1.9.4 server if the server supports it) - if (info.getProtocolVersion() >= protocol || Via.getPlatform().isOldClientsAllowed()) { - protocols = Via.getManager().getProtocolManager().getProtocolPath(info.getProtocolVersion(), protocol); + if (info.getProtocolVersion() >= closestServerProtocol || Via.getPlatform().isOldClientsAllowed()) { + protocols = Via.getManager().getProtocolManager().getProtocolPath(info.getProtocolVersion(), closestServerProtocol); } if (protocols != null) { - if (protocolVersion == protocol || protocolVersion == 0) { // Fix ServerListPlus + if (protocolVersion == closestServerProtocol || protocolVersion == 0) { // Fix ServerListPlus ProtocolVersion prot = ProtocolVersion.getProtocol(info.getProtocolVersion()); version.addProperty("protocol", prot.getOriginalVersion()); } diff --git a/common/src/main/java/us/myles/ViaVersion/protocols/base/BaseVersionProvider.java b/common/src/main/java/us/myles/ViaVersion/protocols/base/BaseVersionProvider.java index 67d6d6613..60c227e3b 100644 --- a/common/src/main/java/us/myles/ViaVersion/protocols/base/BaseVersionProvider.java +++ b/common/src/main/java/us/myles/ViaVersion/protocols/base/BaseVersionProvider.java @@ -23,6 +23,6 @@ import us.myles.ViaVersion.api.data.UserConnection; public class BaseVersionProvider implements VersionProvider { public int getServerProtocol(UserConnection connection) throws Exception { - return Via.getAPI().getServerVersion(); + return Via.getAPI().getServerVersion().lowestSupportedVersion(); } } diff --git a/sponge/src/main/java/us/myles/ViaVersion/sponge/handlers/SpongeChannelInitializer.java b/sponge/src/main/java/us/myles/ViaVersion/sponge/handlers/SpongeChannelInitializer.java index 5ac1044b6..c32dcafa7 100644 --- a/sponge/src/main/java/us/myles/ViaVersion/sponge/handlers/SpongeChannelInitializer.java +++ b/sponge/src/main/java/us/myles/ViaVersion/sponge/handlers/SpongeChannelInitializer.java @@ -47,7 +47,7 @@ public class SpongeChannelInitializer extends ChannelInitializer { @Override protected void initChannel(Channel channel) throws Exception { // Ensure ViaVersion is loaded - if (Via.getAPI().getServerVersion() != -1 + if (Via.getAPI().getServerVersion().isKnown() && channel instanceof SocketChannel) { // channel can be LocalChannel on internal server UserConnection info = new UserConnection((SocketChannel) channel); // init protocol diff --git a/sponge/src/main/java/us/myles/ViaVersion/sponge/platform/SpongeViaInjector.java b/sponge/src/main/java/us/myles/ViaVersion/sponge/platform/SpongeViaInjector.java index 656a18ce4..de977a356 100644 --- a/sponge/src/main/java/us/myles/ViaVersion/sponge/platform/SpongeViaInjector.java +++ b/sponge/src/main/java/us/myles/ViaVersion/sponge/platform/SpongeViaInjector.java @@ -120,6 +120,11 @@ public class SpongeViaInjector implements ViaInjector { } } + @Override + public boolean lateProtocolVersionSetting() { + return true; + } + @Override public void uninject() { // TODO: Uninject from players currently online diff --git a/sponge/src/main/java/us/myles/ViaVersion/sponge/platform/SpongeViaLoader.java b/sponge/src/main/java/us/myles/ViaVersion/sponge/platform/SpongeViaLoader.java index d3ec83dee..aa68e92dc 100644 --- a/sponge/src/main/java/us/myles/ViaVersion/sponge/platform/SpongeViaLoader.java +++ b/sponge/src/main/java/us/myles/ViaVersion/sponge/platform/SpongeViaLoader.java @@ -66,7 +66,7 @@ public class SpongeViaLoader implements ViaPlatformLoader { registerListener(new UpdateListener()); /* 1.9 client to 1.8 server */ - if (Via.getAPI().getServerVersion() < ProtocolVersion.v1_9.getVersion()) { + if (Via.getAPI().getServerVersion().lowestSupportedVersion() < ProtocolVersion.v1_9.getVersion()) { try { Class.forName("org.spongepowered.api.event.entity.DisplaceEntityEvent"); storeListener(new Sponge4ArmorListener()).register(); @@ -83,7 +83,7 @@ public class SpongeViaLoader implements ViaPlatformLoader { } /* Providers */ - if (Via.getAPI().getServerVersion() < ProtocolVersion.v1_9.getVersion()) { + if (Via.getAPI().getServerVersion().lowestSupportedVersion() < ProtocolVersion.v1_9.getVersion()) { Via.getManager().getProviders().use(BulkChunkTranslatorProvider.class, new SpongeViaBulkChunkTranslator()); Via.getManager().getProviders().use(MovementTransmitterProvider.class, new SpongeViaMovementTransmitter()); diff --git a/velocity/src/main/java/us/myles/ViaVersion/velocity/platform/VelocityViaInjector.java b/velocity/src/main/java/us/myles/ViaVersion/velocity/platform/VelocityViaInjector.java index 43a8d3f55..61d2d4e04 100644 --- a/velocity/src/main/java/us/myles/ViaVersion/velocity/platform/VelocityViaInjector.java +++ b/velocity/src/main/java/us/myles/ViaVersion/velocity/platform/VelocityViaInjector.java @@ -19,6 +19,8 @@ package us.myles.ViaVersion.velocity.platform; import com.google.gson.JsonObject; import io.netty.channel.ChannelInitializer; +import it.unimi.dsi.fastutil.ints.IntLinkedOpenHashSet; +import it.unimi.dsi.fastutil.ints.IntSortedSet; import us.myles.ViaVersion.VelocityPlugin; import us.myles.ViaVersion.api.Via; import us.myles.ViaVersion.api.platform.ViaInjector; @@ -44,7 +46,7 @@ public class VelocityViaInjector implements ViaInjector { private ChannelInitializer getInitializer() throws Exception { Object connectionManager = ReflectionUtil.get(VelocityPlugin.PROXY, "cm", Object.class); Object channelInitializerHolder = ReflectionUtil.invoke(connectionManager, "getServerChannelInitializer"); - return (ChannelInitializer) ReflectionUtil.invoke(channelInitializerHolder, "get"); + return (ChannelInitializer) ReflectionUtil.invoke(channelInitializerHolder, "get"); } private ChannelInitializer getBackendInitializer() throws Exception { @@ -65,7 +67,7 @@ public class VelocityViaInjector implements ViaInjector { Object backendInitializerHolder = ReflectionUtil.invoke(connectionManager, "getBackendChannelInitializer"); ChannelInitializer backendInitializer = getBackendInitializer(); backendInitializerHolder.getClass().getMethod("set", ChannelInitializer.class) - .invoke(backendInitializerHolder, new VelocityChannelInitializer(backendInitializer, true)); + .invoke(backendInitializerHolder, new VelocityChannelInitializer(backendInitializer, true)); } @Override @@ -79,11 +81,26 @@ public class VelocityViaInjector implements ViaInjector { return getLowestSupportedProtocolVersion(); } + @Override + public IntSortedSet getServerProtocolVersions() throws Exception { + int lowestSupportedProtocolVersion = getLowestSupportedProtocolVersion(); + + IntSortedSet set = new IntLinkedOpenHashSet(); + for (com.velocitypowered.api.network.ProtocolVersion version : com.velocitypowered.api.network.ProtocolVersion.SUPPORTED_VERSIONS) { + if (version.getProtocol() >= lowestSupportedProtocolVersion) { + set.add(version.getProtocol()); + } + } + return set; + } + public static int getLowestSupportedProtocolVersion() { try { if (getPlayerInfoForwardingMode != null && ((Enum) getPlayerInfoForwardingMode.invoke(VelocityPlugin.PROXY.getConfiguration())) - .name().equals("MODERN")) return ProtocolVersion.v1_13.getVersion(); + .name().equals("MODERN")) { + return ProtocolVersion.v1_13.getVersion(); + } } catch (IllegalAccessException | InvocationTargetException ignored) { } return com.velocitypowered.api.network.ProtocolVersion.MINIMUM_VERSION.getProtocol(); diff --git a/velocity/src/main/java/us/myles/ViaVersion/velocity/platform/VelocityViaLoader.java b/velocity/src/main/java/us/myles/ViaVersion/velocity/platform/VelocityViaLoader.java index aecf15fa3..b13453db1 100644 --- a/velocity/src/main/java/us/myles/ViaVersion/velocity/platform/VelocityViaLoader.java +++ b/velocity/src/main/java/us/myles/ViaVersion/velocity/platform/VelocityViaLoader.java @@ -37,7 +37,7 @@ public class VelocityViaLoader implements ViaPlatformLoader { Object plugin = VelocityPlugin.PROXY.getPluginManager() .getPlugin("viaversion").flatMap(PluginContainer::getInstance).get(); - if (Via.getAPI().getServerVersion() < ProtocolVersion.v1_9.getVersion()) { + if (Via.getAPI().getServerVersion().lowestSupportedVersion() < ProtocolVersion.v1_9.getVersion()) { Via.getManager().getProviders().use(MovementTransmitterProvider.class, new VelocityMovementTransmitter()); Via.getManager().getProviders().use(BossBarProvider.class, new VelocityBossBarProvider()); }