diff --git a/bukkit/src/main/java/us/myles/ViaVersion/bukkit/platform/BukkitConfigAPI.java b/bukkit/src/main/java/us/myles/ViaVersion/bukkit/platform/BukkitConfigAPI.java index c7141606f..54820614e 100644 --- a/bukkit/src/main/java/us/myles/ViaVersion/bukkit/platform/BukkitConfigAPI.java +++ b/bukkit/src/main/java/us/myles/ViaVersion/bukkit/platform/BukkitConfigAPI.java @@ -8,9 +8,10 @@ import us.myles.ViaVersion.util.Config; import java.io.File; import java.util.Arrays; import java.util.List; +import java.util.Map; public class BukkitConfigAPI extends Config implements ViaVersionConfig { - private static List UNSUPPORTED = Arrays.asList(); + private static List UNSUPPORTED = Arrays.asList("bungee-ping-interval", "bungee-ping-save", "bungee-servers"); public BukkitConfigAPI() { super(new File(((ViaVersionPlugin) Via.getPlatform()).getDataFolder(), "config.yml")); @@ -166,6 +167,11 @@ public class BukkitConfigAPI extends Config implements ViaVersionConfig { return getString("reload-disconnect-msg", "Server reload, please rejoin!"); } + @Override + protected void handleConfig(Map config) { + // Nothing currently + } + @Override public List getUnsupportedOptions() { return UNSUPPORTED; diff --git a/bungee/src/main/java/us/myles/ViaVersion/BungeePlugin.java b/bungee/src/main/java/us/myles/ViaVersion/BungeePlugin.java index 48e8faa27..96144322d 100644 --- a/bungee/src/main/java/us/myles/ViaVersion/BungeePlugin.java +++ b/bungee/src/main/java/us/myles/ViaVersion/BungeePlugin.java @@ -58,8 +58,6 @@ public class BungeePlugin extends Plugin implements ViaPlatform, Listener { .loader(new BungeeViaLoader(this)) .commandHandler(commandHandler) .build()); - - getProxy().getPluginManager().registerListener(this, this); } @Override @@ -137,7 +135,7 @@ public class BungeePlugin extends Plugin implements ViaPlatform, Listener { } @Override - public ViaVersionConfig getConf() { + public BungeeConfigAPI getConf() { return config; } @@ -160,7 +158,7 @@ public class BungeePlugin extends Plugin implements ViaPlatform, Listener { plugins.add(new PluginInfo(true, p.getDescription().getName(), p.getDescription().getVersion(), p.getDescription().getMain(), Arrays.asList(p.getDescription().getAuthor()))); platformSpecific.add("plugins", GsonUtil.getGson().toJsonTree(plugins)); - platformSpecific.add("servers", GsonUtil.getGson().toJsonTree(ProtocolDetectorService.getProtocolIds())); + platformSpecific.add("servers", GsonUtil.getGson().toJsonTree(ProtocolDetectorService.getDetectedIds())); return platformSpecific; } diff --git a/bungee/src/main/java/us/myles/ViaVersion/bungee/handlers/BungeeEncodeHandler.java b/bungee/src/main/java/us/myles/ViaVersion/bungee/handlers/BungeeEncodeHandler.java index 2618e8b26..8bc30020d 100644 --- a/bungee/src/main/java/us/myles/ViaVersion/bungee/handlers/BungeeEncodeHandler.java +++ b/bungee/src/main/java/us/myles/ViaVersion/bungee/handlers/BungeeEncodeHandler.java @@ -102,12 +102,6 @@ public class BungeeEncodeHandler extends MessageToMessageEncoder { storage.setCurrentServer(serverName); - // TODO HANDLE - if (!ProtocolDetectorService.hasProtocolId(serverName)) { - Via.getPlatform().getLogger().severe("Could not find the protocol id for server " + serverName); - return; - } - int protocolId = ProtocolDetectorService.getProtocolId(serverName); UserConnection viaConnection = Via.getManager().getConnection(player.getUniqueId()); @@ -124,7 +118,6 @@ public class BungeeEncodeHandler extends MessageToMessageEncoder { pipeline.add(prot.getValue()); } - viaConnection.put(info); viaConnection.put(storage); @@ -137,7 +130,6 @@ public class BungeeEncodeHandler extends MessageToMessageEncoder { Object wrapper = ReflectionUtil.get(player, "ch", Object.class); wrapper.getClass().getDeclaredMethod("setVersion", int.class).invoke(wrapper, protocolId); -// ReflectionUtil.invoke(player, "init"); Object entityMap = Class.forName("net.md_5.bungee.entitymap.EntityMap").getDeclaredMethod("getEntityMap", int.class).invoke(null, protocolId); ReflectionUtil.set(player, "entityRewrite", entityMap); diff --git a/bungee/src/main/java/us/myles/ViaVersion/bungee/platform/BungeeConfigAPI.java b/bungee/src/main/java/us/myles/ViaVersion/bungee/platform/BungeeConfigAPI.java index 6b94997ac..fba410c80 100644 --- a/bungee/src/main/java/us/myles/ViaVersion/bungee/platform/BungeeConfigAPI.java +++ b/bungee/src/main/java/us/myles/ViaVersion/bungee/platform/BungeeConfigAPI.java @@ -1,11 +1,12 @@ package us.myles.ViaVersion.bungee.platform; import us.myles.ViaVersion.api.ViaVersionConfig; +import us.myles.ViaVersion.api.protocol.ProtocolVersion; +import us.myles.ViaVersion.bungee.providers.BungeeVersionProvider; import us.myles.ViaVersion.util.Config; import java.io.File; -import java.util.Arrays; -import java.util.List; +import java.util.*; public class BungeeConfigAPI extends Config implements ViaVersionConfig { private static List UNSUPPORTED = Arrays.asList("nms-player-ticking", "item-cache", "anti-xray-patch"); @@ -14,6 +15,38 @@ public class BungeeConfigAPI extends Config implements ViaVersionConfig { super(new File(configFile, "config.yml")); } + @Override + protected void handleConfig(Map config) { + // Parse servers + Map servers; + if (!(config.get("bungee-servers") instanceof Map)) { + servers = new HashMap<>(); + } else { + servers = (Map) config.get("bungee-servers"); + } + // Convert any bad Protocol Ids + for (Map.Entry entry : new HashSet<>(servers.entrySet())) { + if (!(entry.getValue() instanceof Integer)) { + if (entry.getValue() instanceof String) { + ProtocolVersion found = ProtocolVersion.getClosest((String) entry.getValue()); + if (found != null) { + servers.put(entry.getKey(), found.getId()); + } else { + servers.remove(entry.getKey()); // Remove! + } + } else { + servers.remove(entry.getKey()); // Remove! + } + } + } + // Ensure default exists + if (!servers.containsKey("default")) { + servers.put("default", BungeeVersionProvider.getLowestSupportedVersion()); + } + // Put back + config.put("bungee-servers", servers); + } + @Override public List getUnsupportedOptions() { return UNSUPPORTED; @@ -167,4 +200,33 @@ public class BungeeConfigAPI extends Config implements ViaVersionConfig { public String getReloadDisconnectMsg() { return getString("reload-disconnect-msg", "Server reload, please rejoin!"); } + + /** + * What is the interval for checking servers via ping + * -1 for disabled + * + * @return Ping interval in seconds + */ + public int getBungeePingInterval() { + return getInt("bungee-ping-interval", 60); + } + + /** + * Should the bungee ping be saved to the config on change. + * + * @return True if it should save + */ + public boolean isBungeePingSave() { + return getBoolean("bungee-ping-save", true); + } + + /** + * Get the listed server protocols in the config. + * default will be listed as default. + * + * @return Map of String, Integer + */ + public Map getBungeeServerProtocols() { + return get("bungee-servers", Map.class, new HashMap<>()); + } } 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 fe2a16b32..3348535e3 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 @@ -1,6 +1,7 @@ package us.myles.ViaVersion.bungee.platform; import lombok.AllArgsConstructor; +import net.md_5.bungee.api.ProxyServer; import us.myles.ViaVersion.BungeePlugin; import us.myles.ViaVersion.api.Via; import us.myles.ViaVersion.api.platform.ViaPlatformLoader; @@ -18,9 +19,13 @@ public class BungeeViaLoader implements ViaPlatformLoader { @Override public void load() { + // Listeners + ProxyServer.getInstance().getPluginManager().registerListener(plugin, plugin); + // Providers Via.getManager().getProviders().use(MovementTransmitterProvider.class, new BungeeMovementTransmitter()); Via.getManager().getProviders().use(VersionProvider.class, new BungeeVersionProvider()); - - plugin.getProxy().getScheduler().schedule(plugin, new ProtocolDetectorService(plugin), 0, 1, TimeUnit.MINUTES); + if (plugin.getConf().getBungeePingInterval() > 0) { + plugin.getProxy().getScheduler().schedule(plugin, new ProtocolDetectorService(plugin), 0, plugin.getConf().getBungeePingInterval(), TimeUnit.SECONDS); + } } } diff --git a/bungee/src/main/java/us/myles/ViaVersion/bungee/providers/BungeeVersionProvider.java b/bungee/src/main/java/us/myles/ViaVersion/bungee/providers/BungeeVersionProvider.java index 699692e31..3dc9be3a1 100644 --- a/bungee/src/main/java/us/myles/ViaVersion/bungee/providers/BungeeVersionProvider.java +++ b/bungee/src/main/java/us/myles/ViaVersion/bungee/providers/BungeeVersionProvider.java @@ -1,6 +1,7 @@ package us.myles.ViaVersion.bungee.providers; import com.google.common.collect.Lists; +import net.md_5.bungee.api.ProxyServer; import us.myles.ViaVersion.api.data.UserConnection; import us.myles.ViaVersion.protocols.base.ProtocolInfo; import us.myles.ViaVersion.protocols.base.VersionProvider; @@ -11,7 +12,7 @@ import java.util.List; public class BungeeVersionProvider extends VersionProvider { private static Class ref; - public BungeeVersionProvider() { + static { try { ref = Class.forName("net.md_5.bungee.protocol.ProtocolConstants"); } catch (Exception e) { @@ -35,7 +36,7 @@ public class BungeeVersionProvider extends VersionProvider { // Older than bungee supports, get the lowest version if (info.getProtocolVersion() < list.get(0)) { - return list.get(0); + return getLowestSupportedVersion(); } // Loop through all protocols to get the closest protocol id that bungee supports @@ -47,4 +48,18 @@ public class BungeeVersionProvider extends VersionProvider { System.out.println("Panic, no protocol id found for " + info.getProtocolVersion()); return info.getProtocolVersion(); } + + public static int getLowestSupportedVersion() { + List list; + try { + list = ReflectionUtil.getStatic(ref, "SUPPORTED_VERSION_IDS", List.class); + return list.get(0); + } catch (NoSuchFieldException e) { + e.printStackTrace(); + } catch (IllegalAccessException e) { + e.printStackTrace(); + } + // Fallback + return ProxyServer.getInstance().getProtocolVersion(); + } } diff --git a/bungee/src/main/java/us/myles/ViaVersion/bungee/service/ProtocolDetectorService.java b/bungee/src/main/java/us/myles/ViaVersion/bungee/service/ProtocolDetectorService.java index f0bc5fe55..f883e82aa 100644 --- a/bungee/src/main/java/us/myles/ViaVersion/bungee/service/ProtocolDetectorService.java +++ b/bungee/src/main/java/us/myles/ViaVersion/bungee/service/ProtocolDetectorService.java @@ -2,16 +2,22 @@ package us.myles.ViaVersion.bungee.service; import lombok.Getter; import net.md_5.bungee.api.Callback; +import net.md_5.bungee.api.ProxyServer; import net.md_5.bungee.api.ServerPing; import net.md_5.bungee.api.config.ServerInfo; import us.myles.ViaVersion.BungeePlugin; +import us.myles.ViaVersion.api.Via; +import us.myles.ViaVersion.bungee.platform.BungeeConfigAPI; +import us.myles.ViaVersion.bungee.providers.BungeeVersionProvider; +import us.myles.ViaVersion.util.ReflectionUtil; import java.util.HashMap; +import java.util.List; import java.util.Map; import java.util.concurrent.ConcurrentHashMap; public class ProtocolDetectorService implements Runnable { - private static final Map protocolIds = new ConcurrentHashMap<>(); + private static final Map detectedProtocolIds = new ConcurrentHashMap<>(); private BungeePlugin plugin; @Getter private static ProtocolDetectorService instance; @@ -22,13 +28,21 @@ public class ProtocolDetectorService implements Runnable { } public static Integer getProtocolId(String serverName) { - if (!hasProtocolId(serverName)) - return -1; - return protocolIds.get(serverName); - } - - public static boolean hasProtocolId(String serverName) { - return protocolIds.containsKey(serverName); + // Step 1. Check Config + Map servers = ((BungeeConfigAPI) Via.getConfig()).getBungeeServerProtocols(); + if (servers.containsKey(serverName)) { + return servers.get(serverName); + } + // Step 2. Check Detected + if (detectedProtocolIds.containsKey(serverName)) { + return detectedProtocolIds.get(serverName); + } + // Step 3. Use Default + if (servers.containsKey("default")) { + return servers.get("default"); + } + // Step 4: Use bungee lowest supported... *cries* + return BungeeVersionProvider.getLowestSupportedVersion(); } @Override @@ -42,14 +56,27 @@ public class ProtocolDetectorService implements Runnable { value.ping(new Callback() { @Override public void done(ServerPing serverPing, Throwable throwable) { - if (throwable == null) - protocolIds.put(key, serverPing.getVersion().getProtocol()); + if (throwable == null) { + detectedProtocolIds.put(key, serverPing.getVersion().getProtocol()); + if (((BungeeConfigAPI) Via.getConfig()).isBungeePingSave()) { + Map servers = ((BungeeConfigAPI) Via.getConfig()).getBungeeServerProtocols(); + if (servers.containsKey(key)) { + if (servers.get(key) == serverPing.getVersion().getProtocol()) { + return; + } + } + // Save Server + servers.put(key, serverPing.getVersion().getProtocol()); + // Save + Via.getPlatform().getConfigurationProvider().saveConfig(); + } + } } }); } - public static Map getProtocolIds() { - return new HashMap<>(protocolIds); + public static Map getDetectedIds() { + return new HashMap<>(detectedProtocolIds); } } diff --git a/common/src/main/java/us/myles/ViaVersion/api/protocol/ProtocolVersion.java b/common/src/main/java/us/myles/ViaVersion/api/protocol/ProtocolVersion.java index 98ec33ab3..735b5814f 100644 --- a/common/src/main/java/us/myles/ViaVersion/api/protocol/ProtocolVersion.java +++ b/common/src/main/java/us/myles/ViaVersion/api/protocol/ProtocolVersion.java @@ -51,7 +51,8 @@ public class ProtocolVersion { register(v1_9_2 = new ProtocolVersion(109, "1.9.2")); register(v1_9_3 = new ProtocolVersion(110, "1.9.3/4")); register(v1_10 = new ProtocolVersion(210, "1.10")); - register(vSNAPSHOT = new ProtocolVersion(309, "1.11-SNAPSHOT")); + // Snapshot uses colon as dashes are used other places... + register(vSNAPSHOT = new ProtocolVersion(309, "1.11:SNAPSHOT")); register(unknown = new ProtocolVersion(-1, "UNKNOWN")); } @@ -80,6 +81,24 @@ public class ProtocolVersion { return Collections.unmodifiableList(new ArrayList<>(versions.values())); } + public static ProtocolVersion getClosest(String protocol) { + for (ProtocolVersion version : versions.values()) { + if (version.getName().equals(protocol)) + return version; + if (version.getName().equals(protocol + ".x")) + return version; + String[] parts = version.getName().split("-"); + for (String part : parts) { + if (part.equalsIgnoreCase(protocol)) { + return version; + } + if (part.equals(protocol + ".x")) + return version; + } + } + return null; + } + @Override public boolean equals(Object o) { if (this == o) return true; diff --git a/common/src/main/java/us/myles/ViaVersion/util/Config.java b/common/src/main/java/us/myles/ViaVersion/util/Config.java index 0ba117dec..edb22a677 100644 --- a/common/src/main/java/us/myles/ViaVersion/util/Config.java +++ b/common/src/main/java/us/myles/ViaVersion/util/Config.java @@ -1,5 +1,6 @@ package us.myles.ViaVersion.util; +import org.yaml.snakeyaml.DumperOptions; import org.yaml.snakeyaml.Yaml; import us.myles.ViaVersion.api.configuration.ConfigurationProvider; @@ -9,17 +10,21 @@ import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; public abstract class Config implements ConfigurationProvider { private static ThreadLocal yaml = new ThreadLocal() { @Override protected Yaml initialValue() { - return new Yaml(); + DumperOptions options = new DumperOptions(); +// options.setPrettyFlow(true); + options.setDefaultFlowStyle(DumperOptions.FlowStyle.BLOCK); + return new Yaml(options); } }; private CommentStore commentStore = new CommentStore('.', 2); private final File configFile; - private Map config; + private ConcurrentHashMap config; public Config(File configFile) { this.configFile = configFile; @@ -70,12 +75,16 @@ public abstract class Config implements ConfigurationProvider { } catch (IOException e) { e.printStackTrace(); } + // Call Handler + handleConfig(defaults); // Save saveConfig(location, defaults); return defaults; } + protected abstract void handleConfig(Map config); + public void saveConfig(File location, Map config) { try { commentStore.writeComments(yaml.get().dump(config), location); @@ -100,7 +109,7 @@ public abstract class Config implements ConfigurationProvider { @Override public void reloadConfig() { this.configFile.getParentFile().mkdirs(); - this.config = loadConfig(this.configFile); + this.config = new ConcurrentHashMap<>(loadConfig(this.configFile)); } @Override @@ -108,6 +117,14 @@ public abstract class Config implements ConfigurationProvider { return this.config; } + public T get(String key, Class clazz, T def) { + if (this.config.containsKey(key)) { + return (T) this.config.get(key); + } else { + return def; + } + } + public boolean getBoolean(String key, boolean def) { if (this.config.containsKey(key)) { return (boolean) this.config.get(key); diff --git a/common/src/main/resources/config.yml b/common/src/main/resources/config.yml index f3dcb8737..ff47962aa 100644 --- a/common/src/main/resources/config.yml +++ b/common/src/main/resources/config.yml @@ -3,9 +3,10 @@ # If you need help: # viaversion.com - Discussion tab # IRC - https://elmer.spi.gt/iris/?nick=&channels=viaversion #viaversion on irc.spi.gt +# Docs - https://docs.viaversion.com/display/VIAVERSION/Configuration # #----------------------------------------------------------# -# GLOBAL OPTIONS # +# GLOBAL OPTIONS # #----------------------------------------------------------# # # Should ViaVersion check for updates? @@ -23,7 +24,29 @@ block-disconnect-msg: "You are using an unsupported Minecraft version!" reload-disconnect-msg: "Server reload, please rejoin!" # #----------------------------------------------------------# -# GLOBAL PACKET LIMITER # +# BUNGEE OPTIONS # +#----------------------------------------------------------# +# +# BungeeCord allows you to have different server versions inside. +# Instead of you entering all the versions of these servers, we can ping them. +# +# What interval would you like us to ping at? (in seconds) +# Use -1 to disable. +bungee-ping-interval: 60 +# If the above is enabled, should we save the info to the config (in the section below) +bungee-ping-save: true +# To get a servers protocol, ViaVersion will do the following: +# Look for the server in the following section, then look for the last ping if bungee-ping is enabled +# otherwise use default. +# +# The format for the following is: +# servername: protocolversion +# You can find protocol ids on http://wiki.vg/Protocol_version_numbers +# It will fallback to the default option if none found. +bungee-servers: {} +# +#----------------------------------------------------------# +# GLOBAL PACKET LIMITER # #----------------------------------------------------------# # # diff --git a/sponge/src/main/java/us/myles/ViaVersion/SpongePlugin.java b/sponge/src/main/java/us/myles/ViaVersion/SpongePlugin.java index fd0b9b18a..78df27c07 100644 --- a/sponge/src/main/java/us/myles/ViaVersion/SpongePlugin.java +++ b/sponge/src/main/java/us/myles/ViaVersion/SpongePlugin.java @@ -13,7 +13,6 @@ import org.spongepowered.api.scheduler.SpongeExecutorService; import org.spongepowered.api.text.serializer.TextSerializers; import us.myles.ViaVersion.api.Via; import us.myles.ViaVersion.api.ViaAPI; -import us.myles.ViaVersion.api.ViaVersionConfig; import us.myles.ViaVersion.api.command.ViaCommandSender; import us.myles.ViaVersion.api.configuration.ConfigurationProvider; import us.myles.ViaVersion.api.platform.TaskId; @@ -162,7 +161,7 @@ public class SpongePlugin implements ViaPlatform { } @Override - public ViaVersionConfig getConf() { + public SpongeConfigAPI getConf() { return conf; } diff --git a/sponge/src/main/java/us/myles/ViaVersion/sponge/platform/SpongeConfigAPI.java b/sponge/src/main/java/us/myles/ViaVersion/sponge/platform/SpongeConfigAPI.java index 6bd2562fb..b7e4df980 100644 --- a/sponge/src/main/java/us/myles/ViaVersion/sponge/platform/SpongeConfigAPI.java +++ b/sponge/src/main/java/us/myles/ViaVersion/sponge/platform/SpongeConfigAPI.java @@ -6,14 +6,20 @@ import us.myles.ViaVersion.util.Config; import java.io.File; import java.util.Arrays; import java.util.List; +import java.util.Map; public class SpongeConfigAPI extends Config implements ViaVersionConfig { - private static List UNSUPPORTED = Arrays.asList("anti-xray-patch"); + private static List UNSUPPORTED = Arrays.asList("anti-xray-patch", "bungee-ping-interval", "bungee-ping-save", "bungee-servers"); public SpongeConfigAPI(File configFile) { super(new File(configFile, "config.yml")); } + @Override + protected void handleConfig(Map config) { + // Nothing Currently + } + @Override public List getUnsupportedOptions() { return UNSUPPORTED;