From 05930ad7917fa3e4e1d1ca32451379e33951834b Mon Sep 17 00:00:00 2001 From: Myles Date: Sun, 25 Sep 2016 14:39:37 +0100 Subject: [PATCH] Add ViaManager and abstraction / Add todo list --- TODOLIST | 14 + .../us/myles/ViaVersion/ViaVersionPlugin.java | 423 ++---------------- .../myles/ViaVersion/api/ViaVersionAPI.java | 3 +- .../us/myles/ViaVersion/boss/ViaBossBar.java | 1 + .../myles/ViaVersion/bukkit/BukkitViaAPI.java | 127 ++++++ .../ViaVersion/bukkit/BukkitViaInjector.java | 233 ++++++++++ .../ViaVersion/handlers/ViaDecodeHandler.java | 1 - .../ViaVersion/listeners/UpdateListener.java | 1 - .../protocol1_9to1_8}/ArmorListener.java | 2 +- .../protocol1_9to1_8}/BlockListener.java | 2 +- .../CommandBlockListener.java | 2 +- .../protocol1_9to1_8}/DeathListener.java | 2 +- .../protocol1_9to1_8}/HandItemCache.java | 2 +- .../protocol1_9to1_8}/PaperPatch.java | 2 +- common/pom.xml | 1 + .../java/us/myles/ViaVersion/ViaManager.java | 84 ++++ .../myles/ViaVersion/api/PacketWrapper.java | 5 +- .../java/us/myles/ViaVersion/api/Via.java | 9 + .../java/us/myles/ViaVersion/api/ViaAPI.java | 100 +++++ .../ViaVersion/api/data/UserConnection.java | 1 - .../ViaVersion/api/platform/ViaInjector.java | 9 + .../ViaVersion/api/platform/ViaPlatform.java | 16 +- .../api/protocol/ProtocolPipeline.java | 6 +- .../api/protocol/ProtocolRegistry.java | 4 +- .../protocol1_9to1_8/Protocol1_9TO1_8.java | 2 +- .../storage/ClientChunks.java | 7 +- .../protocol1_9to1_8/types/ChunkType.java | 4 +- .../protocolsnapshotto1_10/ItemRewriter.java | 3 +- .../myles/ViaVersion/update/UpdateUtil.java | 20 +- .../us/myles/ViaVersion/util/ListWrapper.java | 1 - 30 files changed, 662 insertions(+), 425 deletions(-) create mode 100644 TODOLIST create mode 100644 bukkit/src/main/java/us/myles/ViaVersion/bukkit/BukkitViaAPI.java create mode 100644 bukkit/src/main/java/us/myles/ViaVersion/bukkit/BukkitViaInjector.java rename {common/src/main/java/us/myles/ViaVersion/protocols/protocol1_9to1_8/listeners => bukkit/src/main/java/us/myles/ViaVersion/listeners/protocol1_9to1_8}/ArmorListener.java (98%) rename {common/src/main/java/us/myles/ViaVersion/protocols/protocol1_9to1_8/listeners => bukkit/src/main/java/us/myles/ViaVersion/listeners/protocol1_9to1_8}/BlockListener.java (93%) rename {common/src/main/java/us/myles/ViaVersion/protocols/protocol1_9to1_8/listeners => bukkit/src/main/java/us/myles/ViaVersion/listeners/protocol1_9to1_8}/CommandBlockListener.java (98%) rename {common/src/main/java/us/myles/ViaVersion/protocols/protocol1_9to1_8/listeners => bukkit/src/main/java/us/myles/ViaVersion/listeners/protocol1_9to1_8}/DeathListener.java (96%) rename {common/src/main/java/us/myles/ViaVersion/protocols/protocol1_9to1_8/listeners => bukkit/src/main/java/us/myles/ViaVersion/listeners/protocol1_9to1_8}/HandItemCache.java (94%) rename {common/src/main/java/us/myles/ViaVersion/protocols/protocol1_9to1_8/listeners => bukkit/src/main/java/us/myles/ViaVersion/listeners/protocol1_9to1_8}/PaperPatch.java (97%) create mode 100644 common/src/main/java/us/myles/ViaVersion/ViaManager.java create mode 100644 common/src/main/java/us/myles/ViaVersion/api/ViaAPI.java create mode 100644 common/src/main/java/us/myles/ViaVersion/api/platform/ViaInjector.java diff --git a/TODOLIST b/TODOLIST new file mode 100644 index 000000000..dcf12e9aa --- /dev/null +++ b/TODOLIST @@ -0,0 +1,14 @@ +Migrate EntityUtil to be cool +Fix 1.9to1.8 +Fix 1.9.3to1.9.1/2 +Fix 1.9.1/2to1.9.3/4 +Fix snapshot to 1.10 +Fix BaseProtocol +Fix BossBar to use Generics +Register Listeners Properly +Fix commands +Handle injector errors +Add new info to dump for platform +Migrate Bukkit types to our own :D + +Important: Create builder for ViaManager which allows supplying on the command exectutor, injector, platform :D \ No newline at end of file diff --git a/bukkit/src/main/java/us/myles/ViaVersion/ViaVersionPlugin.java b/bukkit/src/main/java/us/myles/ViaVersion/ViaVersionPlugin.java index 0b72d9560..159e8d59d 100644 --- a/bukkit/src/main/java/us/myles/ViaVersion/ViaVersionPlugin.java +++ b/bukkit/src/main/java/us/myles/ViaVersion/ViaVersionPlugin.java @@ -1,71 +1,55 @@ package us.myles.ViaVersion; -import io.netty.buffer.ByteBuf; -import io.netty.channel.ChannelFuture; -import io.netty.channel.ChannelHandler; -import io.netty.channel.ChannelInitializer; -import io.netty.channel.socket.SocketChannel; import lombok.Getter; -import lombok.NonNull; import org.bukkit.Bukkit; import org.bukkit.ChatColor; import org.bukkit.entity.Player; -import org.bukkit.plugin.PluginDescriptionFile; import org.bukkit.plugin.java.JavaPlugin; -import us.myles.ViaVersion.api.Pair; import us.myles.ViaVersion.api.Via; +import us.myles.ViaVersion.api.ViaAPI; import us.myles.ViaVersion.api.ViaVersion; -import us.myles.ViaVersion.api.ViaVersionAPI; -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.command.ViaVersionCommand; import us.myles.ViaVersion.api.data.UserConnection; import us.myles.ViaVersion.api.platform.ViaPlatform; import us.myles.ViaVersion.api.protocol.ProtocolRegistry; -import us.myles.ViaVersion.api.protocol.ProtocolVersion; -import us.myles.ViaVersion.boss.ViaBossBar; import us.myles.ViaVersion.bukkit.BukkitCommandHandler; +import us.myles.ViaVersion.bukkit.BukkitViaAPI; +import us.myles.ViaVersion.bukkit.BukkitViaInjector; import us.myles.ViaVersion.classgenerator.ClassGenerator; -import us.myles.ViaVersion.handlers.ViaVersionInitializer; import us.myles.ViaVersion.listeners.UpdateListener; -import us.myles.ViaVersion.protocols.base.ProtocolInfo; -import us.myles.ViaVersion.update.UpdateUtil; -import us.myles.ViaVersion.util.ConcurrentList; -import us.myles.ViaVersion.util.ListWrapper; -import us.myles.ViaVersion.util.ProtocolSupportUtil; import us.myles.ViaVersion.util.ReflectionUtil; -import java.lang.reflect.Field; -import java.lang.reflect.Method; -import java.util.*; +import java.util.UUID; import java.util.concurrent.Callable; -import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.Future; import java.util.concurrent.TimeUnit; -public class ViaVersionPlugin extends JavaPlugin implements ViaVersionAPI, ViaPlatform { +public class ViaVersionPlugin extends JavaPlugin implements ViaPlatform { - private final Map portedPlayers = new ConcurrentHashMap<>(); - private List injectedFutures = new ArrayList<>(); - private List> injectedLists = new ArrayList<>(); private BukkitCommandHandler commandHandler; - private boolean debug = false; private boolean compatSpigotBuild = false; private boolean spigot = true; private boolean lateBind = false; private boolean protocolSupport = false; @Getter private ViaConfig conf; + @Getter + private ViaAPI api = new BukkitViaAPI(this); public ViaVersionPlugin() { + // Config magic + conf = new ViaConfig(this); + // Init platform + Via.init(this); + // For compatibility + ViaVersion.setInstance(this); + // Check if we're using protocol support too protocolSupport = Bukkit.getPluginManager().getPlugin("ProtocolSupport") != null; if (protocolSupport) { getLogger().info("Hooking into ProtocolSupport, to prevent issues!"); try { - patchLists(); + BukkitViaInjector.patchLists(); } catch (Exception e) { e.printStackTrace(); } @@ -74,27 +58,6 @@ public class ViaVersionPlugin extends JavaPlugin implements ViaVersionAPI, ViaPl @Override public void onLoad() { - // Config magic - conf = new ViaConfig(this); - // Init platform - Via.init(this); - // For compatibility - ViaVersion.setInstance(this); - - // Handle reloads - if (System.getProperty("ViaVersion") != null) { - if (Bukkit.getPluginManager().getPlugin("ProtocolLib") != null) { - getLogger().severe("ViaVersion is already loaded, we're going to kick all the players... because otherwise we'll crash because of ProtocolLib."); - for (Player player : Bukkit.getOnlinePlayers()) { - player.kickPlayer(ChatColor.translateAlternateColorCodes('&', getConf().getReloadDisconnectMsg())); - } - - } else { - getLogger().severe("ViaVersion is already loaded, this should work fine. If you get any console errors, try rebooting."); - - } - } - // Spigot detector try { Class.forName("org.spigotmc.SpigotConfig"); @@ -111,35 +74,19 @@ public class ViaVersionPlugin extends JavaPlugin implements ViaVersionAPI, ViaPl // Generate classes needed (only works if it's compat or ps) ClassGenerator.generate(); - lateBind = !isBinded(); + lateBind = !BukkitViaInjector.isBinded(); getLogger().info("ViaVersion " + getDescription().getVersion() + (compatSpigotBuild ? "compat" : "") + " is now loaded" + (lateBind ? ", waiting for boot. (late-bind)" : ", injecting!")); - if (!lateBind) - injectPacketHandler(); + if (!lateBind) { + Via.getManager().init(); + } } @Override public void onEnable() { - if (lateBind) - injectPacketHandler(); - if (conf.isCheckForUpdates()) - UpdateUtil.sendUpdateMessage(); - // Gather version :) - Bukkit.getScheduler().scheduleSyncDelayedTask(this, new Runnable() { - @Override - public void run() { - gatherProtocolVersion(); - // Check if there are any pipes to this version - if (ProtocolRegistry.SERVER_PROTOCOL != -1) { - getLogger().info("ViaVersion detected server version: " + ProtocolVersion.getProtocol(ProtocolRegistry.SERVER_PROTOCOL)); - if (!ProtocolRegistry.isWorkingPipe()) { - getLogger().warning("ViaVersion does not have any compatible versions for this server version, please read our resource page carefully."); - } - } - ProtocolRegistry.refreshVersions(); - } - }); - + if (lateBind) { + Via.getManager().init(); + } Bukkit.getPluginManager().registerEvents(new UpdateListener(), this); @@ -157,325 +104,18 @@ public class ViaVersionPlugin extends JavaPlugin implements ViaVersionAPI, ViaPl @Override public void onDisable() { - getLogger().info("ViaVersion is disabling, if this is a reload and you experience issues consider rebooting."); - uninject(); + // TODO: Call ViaManager.destroy() } - public void gatherProtocolVersion() { - try { - Class serverClazz = ReflectionUtil.nms("MinecraftServer"); - Object server = ReflectionUtil.invokeStatic(serverClazz, "getServer"); - Class pingClazz = ReflectionUtil.nms("ServerPing"); - Object ping = null; - // Search for ping method - for (Field f : serverClazz.getDeclaredFields()) { - if (f.getType() != null) { - if (f.getType().getSimpleName().equals("ServerPing")) { - f.setAccessible(true); - ping = f.get(server); - } - } - } - if (ping != null) { - Object serverData = null; - for (Field f : pingClazz.getDeclaredFields()) { - if (f.getType() != null) { - if (f.getType().getSimpleName().endsWith("ServerData")) { - f.setAccessible(true); - serverData = f.get(ping); - } - } - } - if (serverData != null) { - int protocolVersion = -1; - for (Field f : serverData.getClass().getDeclaredFields()) { - if (f.getType() != null) { - if (f.getType() == int.class) { - f.setAccessible(true); - protocolVersion = (int) f.get(serverData); - } - } - } - if (protocolVersion != -1) { - ProtocolRegistry.SERVER_PROTOCOL = protocolVersion; - return; - } - } - } - } catch (Exception e) { - e.printStackTrace(); - // We couldn't work it out... We'll just use ping and hope for the best... - } - } - - public Object getServerConnection() throws Exception { - Class serverClazz = ReflectionUtil.nms("MinecraftServer"); - Object server = ReflectionUtil.invokeStatic(serverClazz, "getServer"); - Object connection = null; - for (Method m : serverClazz.getDeclaredMethods()) { - if (m.getReturnType() != null) { - if (m.getReturnType().getSimpleName().equals("ServerConnection")) { - if (m.getParameterTypes().length == 0) { - connection = m.invoke(server); - } - } - } - } - return connection; - } - - public void injectPacketHandler() { - try { - Object connection = getServerConnection(); - if (connection == null) { - getLogger().warning("We failed to find the core component 'ServerConnection', please file an issue on our GitHub."); - return; - } - for (Field field : connection.getClass().getDeclaredFields()) { - field.setAccessible(true); - final Object value = field.get(connection); - if (value instanceof List) { - // Inject the list - List wrapper = new ListWrapper((List) value) { - @Override - public synchronized void handleAdd(Object o) { - synchronized (this) { - if (o instanceof ChannelFuture) { - inject((ChannelFuture) o); - } - } - } - }; - injectedLists.add(new Pair<>(field, connection)); - field.set(connection, wrapper); - // Iterate through current list - synchronized (wrapper) { - for (Object o : (List) value) { - if (o instanceof ChannelFuture) { - inject((ChannelFuture) o); - } else { - break; // not the right list. - } - } - } - } - } - System.setProperty("ViaVersion", getDescription().getVersion()); - } catch (Exception e) { - getLogger().severe("Unable to inject ViaVersion, please post these details on our GitHub and ensure you're using a compatible server version."); - e.printStackTrace(); - } - } - - - public void patchLists() throws Exception { - Object connection = getServerConnection(); - if (connection == null) { - getLogger().warning("We failed to find the core component 'ServerConnection', please file an issue on our GitHub."); - return; - } - for (Field field : connection.getClass().getDeclaredFields()) { - field.setAccessible(true); - final Object value = field.get(connection); - if (value instanceof List) { - if (!(value instanceof ConcurrentList)) { - ConcurrentList list = new ConcurrentList(); - list.addAll((List) value); - field.set(connection, list); - } - } - } - } - - - public boolean isBinded() { - try { - Object connection = getServerConnection(); - if (connection == null) { - return false; - } - for (Field field : connection.getClass().getDeclaredFields()) { - field.setAccessible(true); - final Object value = field.get(connection); - if (value instanceof List) { - // Inject the list - synchronized (value) { - for (Object o : (List) value) { - if (o instanceof ChannelFuture) { - return true; - } else { - break; // not the right list. - } - } - } - } - } - } catch (Exception e) { - } - return false; - } - - private void inject(ChannelFuture future) { - try { - ChannelHandler bootstrapAcceptor = future.channel().pipeline().first(); - try { - ChannelInitializer oldInit = ReflectionUtil.get(bootstrapAcceptor, "childHandler", ChannelInitializer.class); - ChannelInitializer newInit = new ViaVersionInitializer(oldInit); - - ReflectionUtil.set(bootstrapAcceptor, "childHandler", newInit); - injectedFutures.add(future); - } catch (NoSuchFieldException e) { - // let's find who to blame! - ClassLoader cl = bootstrapAcceptor.getClass().getClassLoader(); - if (cl.getClass().getName().equals("org.bukkit.plugin.java.PluginClassLoader")) { - PluginDescriptionFile yaml = ReflectionUtil.get(cl, "description", PluginDescriptionFile.class); - throw new Exception("Unable to inject, due to " + bootstrapAcceptor.getClass().getName() + ", try without the plugin " + yaml.getName() + "?"); - } else { - throw new Exception("Unable to find core component 'childHandler', please check your plugins. issue: " + bootstrapAcceptor.getClass().getName()); - } - - } - } catch (Exception e) { - getLogger().severe("We failed to inject ViaVersion, have you got late-bind enabled with something else?"); - e.printStackTrace(); - } - } - - private void uninject() { - // TODO: Uninject from players currently online to prevent protocol lib issues. - for (ChannelFuture future : injectedFutures) { - ChannelHandler bootstrapAcceptor = future.channel().pipeline().first(); - try { - ChannelInitializer oldInit = ReflectionUtil.get(bootstrapAcceptor, "childHandler", ChannelInitializer.class); - if (oldInit instanceof ViaVersionInitializer) { - ReflectionUtil.set(bootstrapAcceptor, "childHandler", ((ViaVersionInitializer) oldInit).getOriginal()); - } - } catch (Exception e) { - System.out.println("Failed to remove injection handler, reload won't work with connections, please reboot!"); - } - } - injectedFutures.clear(); - - for (Pair pair : injectedLists) { - try { - Object o = pair.getKey().get(pair.getValue()); - if (o instanceof ListWrapper) { - pair.getKey().set(pair.getValue(), ((ListWrapper) o).getOriginalList()); - } - } catch (IllegalAccessException e) { - System.out.println("Failed to remove injection, reload won't work with connections, please reboot!"); - } - } - - injectedLists.clear(); - } - - @Override - public boolean isPorted(Player player) { - return isPorted(player.getUniqueId()); - } - - @Override - public int getPlayerVersion(@NonNull Player player) { - if (!isPorted(player)) - return getExternalVersion(player); - return portedPlayers.get(player.getUniqueId()).get(ProtocolInfo.class).getProtocolVersion(); - } - - @Override - public int getPlayerVersion(@NonNull UUID uuid) { - if (!isPorted(uuid)) - return getExternalVersion(Bukkit.getPlayer(uuid)); - return portedPlayers.get(uuid).get(ProtocolInfo.class).getProtocolVersion(); - } - - private int getExternalVersion(Player player) { - if (!isProtocolSupport()) { - return ProtocolRegistry.SERVER_PROTOCOL; - } else { - return ProtocolSupportUtil.getProtocolVersion(player); - } - } - - @Override - public boolean isPorted(UUID playerUUID) { - return portedPlayers.containsKey(playerUUID); - } - - @Override - public String getVersion() { - return getDescription().getVersion(); - } - - public UserConnection getConnection(UUID playerUUID) { - return portedPlayers.get(playerUUID); - } - - public UserConnection getConnection(Player player) { - return portedPlayers.get(player.getUniqueId()); - } - - public void sendRawPacket(Player player, ByteBuf packet) throws IllegalArgumentException { - sendRawPacket(player.getUniqueId(), packet); - } - - @Override - public void sendRawPacket(UUID uuid, ByteBuf packet) throws IllegalArgumentException { - if (!isPorted(uuid)) throw new IllegalArgumentException("This player is not controlled by ViaVersion!"); - UserConnection ci = portedPlayers.get(uuid); - ci.sendRawPacket(packet); - } - - @Override - public BossBar createBossBar(String title, BossColor color, BossStyle style) { - return new ViaBossBar(title, 1F, color, style); - } - - @Override - public BossBar createBossBar(String title, float health, BossColor color, BossStyle style) { - return new ViaBossBar(title, health, color, style); - } - - @Override - public boolean isDebug() { - return this.debug; - } - - public void setDebug(boolean value) { - this.debug = value; - } - - @Override - public ViaVersionCommand getCommandHandler() { - return commandHandler; - } - - @Override public boolean isCompatSpigotBuild() { return compatSpigotBuild; } - @Override - public SortedSet getSupportedVersions() { - SortedSet outputSet = new TreeSet<>(ProtocolRegistry.getSupportedVersions()); - outputSet.removeAll(getConf().getBlockedProtocols()); - return outputSet; - } - - @Override public boolean isSpigot() { return this.spigot; } - public void addPortedClient(UserConnection info) { - portedPlayers.put(info.get(ProtocolInfo.class).getUuid(), info); - } - - public void removePortedClient(UUID clientID) { - portedPlayers.remove(clientID); - } - public void run(final Runnable runnable, boolean wait) { try { Future f = Bukkit.getScheduler().callSyncMethod(Bukkit.getPluginManager().getPlugin("ViaVersion"), new Callable() { @@ -499,10 +139,6 @@ public class ViaVersionPlugin extends JavaPlugin implements ViaVersionAPI, ViaPl return protocolSupport; } - public Map getPortedPlayers() { - return portedPlayers; - } - public boolean handlePPS(UserConnection info) { // Max PPS Checker if (conf.getMaxPPS() > 0) { @@ -576,4 +212,17 @@ public class ViaVersionPlugin extends JavaPlugin implements ViaVersionAPI, ViaPl public boolean isPluginEnabled() { return Bukkit.getPluginManager().getPlugin("ViaVersion").isEnabled(); } + + @Override + public void onReload() { + if (Bukkit.getPluginManager().getPlugin("ProtocolLib") != null) { + getLogger().severe("ViaVersion is already loaded, we're going to kick all the players... because otherwise we'll crash because of ProtocolLib."); + for (Player player : Bukkit.getOnlinePlayers()) { + player.kickPlayer(ChatColor.translateAlternateColorCodes('&', getConf().getReloadDisconnectMsg())); + } + + } else { + getLogger().severe("ViaVersion is already loaded, this should work fine. If you get any console errors, try rebooting."); + } + } } diff --git a/bukkit/src/main/java/us/myles/ViaVersion/api/ViaVersionAPI.java b/bukkit/src/main/java/us/myles/ViaVersion/api/ViaVersionAPI.java index 124bd33bf..a962fd924 100644 --- a/bukkit/src/main/java/us/myles/ViaVersion/api/ViaVersionAPI.java +++ b/bukkit/src/main/java/us/myles/ViaVersion/api/ViaVersionAPI.java @@ -7,13 +7,12 @@ import us.myles.ViaVersion.api.boss.BossColor; import us.myles.ViaVersion.api.boss.BossStyle; import us.myles.ViaVersion.api.command.ViaVersionCommand; import us.myles.ViaVersion.api.protocol.ProtocolRegistry; -import us.myles.ViaVersion.boss.ViaBossBar; import java.util.SortedSet; import java.util.UUID; @Deprecated -public interface ViaVersionAPI { +public interface ViaVersionAPI extends ViaAPI { /** * Is the player connection modified by ViaVersion? * diff --git a/bukkit/src/main/java/us/myles/ViaVersion/boss/ViaBossBar.java b/bukkit/src/main/java/us/myles/ViaVersion/boss/ViaBossBar.java index 6ec57ceb9..519c42fcd 100644 --- a/bukkit/src/main/java/us/myles/ViaVersion/boss/ViaBossBar.java +++ b/bukkit/src/main/java/us/myles/ViaVersion/boss/ViaBossBar.java @@ -8,6 +8,7 @@ import us.myles.ViaVersion.api.boss.BossStyle; @Getter public class ViaBossBar extends CommonBoss { + // TODO: Fix to use generics public ViaBossBar(String title, float health, BossColor color, BossStyle style) { super(title, health, color, style); diff --git a/bukkit/src/main/java/us/myles/ViaVersion/bukkit/BukkitViaAPI.java b/bukkit/src/main/java/us/myles/ViaVersion/bukkit/BukkitViaAPI.java new file mode 100644 index 000000000..3c833a92f --- /dev/null +++ b/bukkit/src/main/java/us/myles/ViaVersion/bukkit/BukkitViaAPI.java @@ -0,0 +1,127 @@ +package us.myles.ViaVersion.bukkit; + +import io.netty.buffer.ByteBuf; +import lombok.AllArgsConstructor; +import lombok.NonNull; +import org.bukkit.Bukkit; +import org.bukkit.entity.Player; +import us.myles.ViaVersion.ViaVersionPlugin; +import us.myles.ViaVersion.api.Via; +import us.myles.ViaVersion.api.ViaAPI; +import us.myles.ViaVersion.api.ViaVersionAPI; +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.command.ViaVersionCommand; +import us.myles.ViaVersion.api.data.UserConnection; +import us.myles.ViaVersion.api.protocol.ProtocolRegistry; +import us.myles.ViaVersion.boss.ViaBossBar; +import us.myles.ViaVersion.protocols.base.ProtocolInfo; +import us.myles.ViaVersion.util.ProtocolSupportUtil; + +import java.util.Map; +import java.util.SortedSet; +import java.util.TreeSet; +import java.util.UUID; + +@AllArgsConstructor +public class BukkitViaAPI implements ViaAPI, ViaVersionAPI { + public ViaVersionPlugin plugin; + + @Override + public int getPlayerVersion(@NonNull Player player) { + if (!isPorted(player)) + return getExternalVersion(player); + return getPortedPlayers().get(player.getUniqueId()).get(ProtocolInfo.class).getProtocolVersion(); + } + + @Override + public int getPlayerVersion(@NonNull UUID uuid) { + if (!isPorted(uuid)) + return getExternalVersion(Bukkit.getPlayer(uuid)); + return getPortedPlayers().get(uuid).get(ProtocolInfo.class).getProtocolVersion(); + } + + private int getExternalVersion(Player player) { + if (!isProtocolSupport()) { + return ProtocolRegistry.SERVER_PROTOCOL; + } else { + return ProtocolSupportUtil.getProtocolVersion(player); + } + } + + @Override + public boolean isPorted(Player player) { + return isPorted(player.getUniqueId()); + } + + @Override + public boolean isPorted(UUID playerUUID) { + return getPortedPlayers().containsKey(playerUUID); + } + + @Override + public String getVersion() { + return plugin.getDescription().getVersion(); + } + + @Override + public void sendRawPacket(UUID uuid, ByteBuf packet) throws IllegalArgumentException { + if (!isPorted(uuid)) throw new IllegalArgumentException("This player is not controlled by ViaVersion!"); + UserConnection ci = getPortedPlayers().get(uuid); + ci.sendRawPacket(packet); + } + + @Override + public void sendRawPacket(Player player, ByteBuf packet) throws IllegalArgumentException { + sendRawPacket(player.getUniqueId(), packet); + } + + @Override + public BossBar createBossBar(String title, BossColor color, BossStyle style) { + return new ViaBossBar(title, 1F, color, style); + } + + @Override + public BossBar createBossBar(String title, float health, BossColor color, BossStyle style) { + return new ViaBossBar(title, health, color, style); + } + + @Override + public boolean isDebug() { + return Via.getManager().isDebug(); + } + + @Override + public ViaVersionCommand getCommandHandler() { + return Via.getManager().getCommandHandler(); + } + + @Override + public SortedSet getSupportedVersions() { + SortedSet outputSet = new TreeSet<>(ProtocolRegistry.getSupportedVersions()); + outputSet.removeAll(Via.getPlatform().getConf().getBlockedProtocols()); + + return outputSet; + } + + @Override + public boolean isCompatSpigotBuild() { + return plugin.isCompatSpigotBuild(); + } + + + @Override + public boolean isSpigot() { + return plugin.isSpigot(); + } + + @Override + public boolean isProtocolSupport() { + return plugin.isProtocolSupport(); + } + + public Map getPortedPlayers() { + return Via.getManager().getPortedPlayers(); + } +} diff --git a/bukkit/src/main/java/us/myles/ViaVersion/bukkit/BukkitViaInjector.java b/bukkit/src/main/java/us/myles/ViaVersion/bukkit/BukkitViaInjector.java new file mode 100644 index 000000000..f53ece720 --- /dev/null +++ b/bukkit/src/main/java/us/myles/ViaVersion/bukkit/BukkitViaInjector.java @@ -0,0 +1,233 @@ +package us.myles.ViaVersion.bukkit; + +import io.netty.channel.ChannelFuture; +import io.netty.channel.ChannelHandler; +import io.netty.channel.ChannelInitializer; +import io.netty.channel.socket.SocketChannel; +import org.bukkit.plugin.PluginDescriptionFile; +import us.myles.ViaVersion.api.Pair; +import us.myles.ViaVersion.api.platform.ViaInjector; +import us.myles.ViaVersion.api.protocol.ProtocolRegistry; +import us.myles.ViaVersion.handlers.ViaVersionInitializer; +import us.myles.ViaVersion.util.ConcurrentList; +import us.myles.ViaVersion.util.ListWrapper; +import us.myles.ViaVersion.util.ReflectionUtil; + +import java.lang.reflect.Field; +import java.lang.reflect.Method; +import java.util.ArrayList; +import java.util.List; + +public class BukkitViaInjector implements ViaInjector { + private List injectedFutures = new ArrayList<>(); + private List> injectedLists = new ArrayList<>(); + + @Override + public void inject() { + try { + Object connection = getServerConnection(); + if (connection == null) { + getLogger().warning("We failed to find the core component 'ServerConnection', please file an issue on our GitHub."); + return; + } + for (Field field : connection.getClass().getDeclaredFields()) { + field.setAccessible(true); + final Object value = field.get(connection); + if (value instanceof List) { + // Inject the list + List wrapper = new ListWrapper((List) value) { + @Override + public synchronized void handleAdd(Object o) { + synchronized (this) { + if (o instanceof ChannelFuture) { + injectChannelFuture((ChannelFuture) o); + } + } + } + }; + injectedLists.add(new Pair<>(field, connection)); + field.set(connection, wrapper); + // Iterate through current list + synchronized (wrapper) { + for (Object o : (List) value) { + if (o instanceof ChannelFuture) { + injectChannelFuture((ChannelFuture) o); + } else { + break; // not the right list. + } + } + } + } + } + + } catch (Exception e) { + getLogger().severe("Unable to inject ViaVersion, please post these details on our GitHub and ensure you're using a compatible server version."); + e.printStackTrace(); + } + } + + private void injectChannelFuture(ChannelFuture future) { + try { + ChannelHandler bootstrapAcceptor = future.channel().pipeline().first(); + try { + ChannelInitializer oldInit = ReflectionUtil.get(bootstrapAcceptor, "childHandler", ChannelInitializer.class); + ChannelInitializer newInit = new ViaVersionInitializer(oldInit); + + ReflectionUtil.set(bootstrapAcceptor, "childHandler", newInit); + injectedFutures.add(future); + } catch (NoSuchFieldException e) { + // let's find who to blame! + ClassLoader cl = bootstrapAcceptor.getClass().getClassLoader(); + if (cl.getClass().getName().equals("org.bukkit.plugin.java.PluginClassLoader")) { + PluginDescriptionFile yaml = ReflectionUtil.get(cl, "description", PluginDescriptionFile.class); + throw new Exception("Unable to inject, due to " + bootstrapAcceptor.getClass().getName() + ", try without the plugin " + yaml.getName() + "?"); + } else { + throw new Exception("Unable to find core component 'childHandler', please check your plugins. issue: " + bootstrapAcceptor.getClass().getName()); + } + + } + } catch (Exception e) { + getLogger().severe("We failed to inject ViaVersion, have you got late-bind enabled with something else?"); + e.printStackTrace(); + } + } + + @Override + public void uninject() { + // TODO: Uninject from players currently online to prevent protocol lib issues. + for (ChannelFuture future : injectedFutures) { + ChannelHandler bootstrapAcceptor = future.channel().pipeline().first(); + try { + ChannelInitializer oldInit = ReflectionUtil.get(bootstrapAcceptor, "childHandler", ChannelInitializer.class); + if (oldInit instanceof ViaVersionInitializer) { + ReflectionUtil.set(bootstrapAcceptor, "childHandler", ((ViaVersionInitializer) oldInit).getOriginal()); + } + } catch (Exception e) { + System.out.println("Failed to remove injection handler, reload won't work with connections, please reboot!"); + } + } + injectedFutures.clear(); + + for (Pair pair : injectedLists) { + try { + Object o = pair.getKey().get(pair.getValue()); + if (o instanceof ListWrapper) { + pair.getKey().set(pair.getValue(), ((ListWrapper) o).getOriginalList()); + } + } catch (IllegalAccessException e) { + System.out.println("Failed to remove injection, reload won't work with connections, please reboot!"); + } + } + + injectedLists.clear(); + } + + @Override + public int getServerProtocolVersion() { + try { + Class serverClazz = ReflectionUtil.nms("MinecraftServer"); + Object server = ReflectionUtil.invokeStatic(serverClazz, "getServer"); + Class pingClazz = ReflectionUtil.nms("ServerPing"); + Object ping = null; + // Search for ping method + for (Field f : serverClazz.getDeclaredFields()) { + if (f.getType() != null) { + if (f.getType().getSimpleName().equals("ServerPing")) { + f.setAccessible(true); + ping = f.get(server); + } + } + } + if (ping != null) { + Object serverData = null; + for (Field f : pingClazz.getDeclaredFields()) { + if (f.getType() != null) { + if (f.getType().getSimpleName().endsWith("ServerData")) { + f.setAccessible(true); + serverData = f.get(ping); + } + } + } + if (serverData != null) { + int protocolVersion = -1; + for (Field f : serverData.getClass().getDeclaredFields()) { + if (f.getType() != null) { + if (f.getType() == int.class) { + f.setAccessible(true); + protocolVersion = (int) f.get(serverData); + } + } + } + if (protocolVersion != -1) { + return protocolVersion; + } + } + } + } catch (Exception e) { + e.printStackTrace(); + // We couldn't work it out... We'll just use ping and hope for the best... + } + } + + public static Object getServerConnection() throws Exception { + Class serverClazz = ReflectionUtil.nms("MinecraftServer"); + Object server = ReflectionUtil.invokeStatic(serverClazz, "getServer"); + Object connection = null; + for (Method m : serverClazz.getDeclaredMethods()) { + if (m.getReturnType() != null) { + if (m.getReturnType().getSimpleName().equals("ServerConnection")) { + if (m.getParameterTypes().length == 0) { + connection = m.invoke(server); + } + } + } + } + return connection; + } + + public static void patchLists() throws Exception { + Object connection = getServerConnection(); + if (connection == null) { + getLogger().warning("We failed to find the core component 'ServerConnection', please file an issue on our GitHub."); + return; + } + for (Field field : connection.getClass().getDeclaredFields()) { + field.setAccessible(true); + final Object value = field.get(connection); + if (value instanceof List) { + if (!(value instanceof ConcurrentList)) { + ConcurrentList list = new ConcurrentList(); + list.addAll((List) value); + field.set(connection, list); + } + } + } + } + + public static boolean isBinded() { + try { + Object connection = getServerConnection(); + if (connection == null) { + return false; + } + for (Field field : connection.getClass().getDeclaredFields()) { + field.setAccessible(true); + final Object value = field.get(connection); + if (value instanceof List) { + // Inject the list + synchronized (value) { + for (Object o : (List) value) { + if (o instanceof ChannelFuture) { + return true; + } else { + break; // not the right list. + } + } + } + } + } + } catch (Exception e) { + } + return false; + } +} diff --git a/bukkit/src/main/java/us/myles/ViaVersion/handlers/ViaDecodeHandler.java b/bukkit/src/main/java/us/myles/ViaVersion/handlers/ViaDecodeHandler.java index c7122233e..a947ee757 100644 --- a/bukkit/src/main/java/us/myles/ViaVersion/handlers/ViaDecodeHandler.java +++ b/bukkit/src/main/java/us/myles/ViaVersion/handlers/ViaDecodeHandler.java @@ -20,7 +20,6 @@ public class ViaDecodeHandler extends ByteToMessageDecoder { private final ByteToMessageDecoder minecraftDecoder; private final UserConnection info; - public static int PASSTHROUGH_ID = 1000; public ViaDecodeHandler(UserConnection info, ByteToMessageDecoder minecraftDecoder) { this.info = info; diff --git a/bukkit/src/main/java/us/myles/ViaVersion/listeners/UpdateListener.java b/bukkit/src/main/java/us/myles/ViaVersion/listeners/UpdateListener.java index c71921d88..c7c9c044c 100644 --- a/bukkit/src/main/java/us/myles/ViaVersion/listeners/UpdateListener.java +++ b/bukkit/src/main/java/us/myles/ViaVersion/listeners/UpdateListener.java @@ -15,5 +15,4 @@ public class UpdateListener implements Listener { UpdateUtil.sendUpdateMessage(e.getPlayer().getUniqueId()); } } - } diff --git a/common/src/main/java/us/myles/ViaVersion/protocols/protocol1_9to1_8/listeners/ArmorListener.java b/bukkit/src/main/java/us/myles/ViaVersion/listeners/protocol1_9to1_8/ArmorListener.java similarity index 98% rename from common/src/main/java/us/myles/ViaVersion/protocols/protocol1_9to1_8/listeners/ArmorListener.java rename to bukkit/src/main/java/us/myles/ViaVersion/listeners/protocol1_9to1_8/ArmorListener.java index 36e012132..9e31d4c27 100644 --- a/common/src/main/java/us/myles/ViaVersion/protocols/protocol1_9to1_8/listeners/ArmorListener.java +++ b/bukkit/src/main/java/us/myles/ViaVersion/listeners/protocol1_9to1_8/ArmorListener.java @@ -1,4 +1,4 @@ -package us.myles.ViaVersion.protocols.protocol1_9to1_8.listeners; +package us.myles.ViaVersion.listeners.protocol1_9to1_8; import org.bukkit.Bukkit; import org.bukkit.entity.HumanEntity; diff --git a/common/src/main/java/us/myles/ViaVersion/protocols/protocol1_9to1_8/listeners/BlockListener.java b/bukkit/src/main/java/us/myles/ViaVersion/listeners/protocol1_9to1_8/BlockListener.java similarity index 93% rename from common/src/main/java/us/myles/ViaVersion/protocols/protocol1_9to1_8/listeners/BlockListener.java rename to bukkit/src/main/java/us/myles/ViaVersion/listeners/protocol1_9to1_8/BlockListener.java index 8143caa91..1c4319021 100644 --- a/common/src/main/java/us/myles/ViaVersion/protocols/protocol1_9to1_8/listeners/BlockListener.java +++ b/bukkit/src/main/java/us/myles/ViaVersion/listeners/protocol1_9to1_8/BlockListener.java @@ -1,4 +1,4 @@ -package us.myles.ViaVersion.protocols.protocol1_9to1_8.listeners; +package us.myles.ViaVersion.listeners.protocol1_9to1_8; import org.bukkit.block.Block; import org.bukkit.event.EventHandler; diff --git a/common/src/main/java/us/myles/ViaVersion/protocols/protocol1_9to1_8/listeners/CommandBlockListener.java b/bukkit/src/main/java/us/myles/ViaVersion/listeners/protocol1_9to1_8/CommandBlockListener.java similarity index 98% rename from common/src/main/java/us/myles/ViaVersion/protocols/protocol1_9to1_8/listeners/CommandBlockListener.java rename to bukkit/src/main/java/us/myles/ViaVersion/listeners/protocol1_9to1_8/CommandBlockListener.java index a18ec4f27..5f5c713b6 100644 --- a/common/src/main/java/us/myles/ViaVersion/protocols/protocol1_9to1_8/listeners/CommandBlockListener.java +++ b/bukkit/src/main/java/us/myles/ViaVersion/listeners/protocol1_9to1_8/CommandBlockListener.java @@ -1,4 +1,4 @@ -package us.myles.ViaVersion.protocols.protocol1_9to1_8.listeners; +package us.myles.ViaVersion.listeners.protocol1_9to1_8; import io.netty.buffer.ByteBuf; import io.netty.buffer.ByteBufOutputStream; diff --git a/common/src/main/java/us/myles/ViaVersion/protocols/protocol1_9to1_8/listeners/DeathListener.java b/bukkit/src/main/java/us/myles/ViaVersion/listeners/protocol1_9to1_8/DeathListener.java similarity index 96% rename from common/src/main/java/us/myles/ViaVersion/protocols/protocol1_9to1_8/listeners/DeathListener.java rename to bukkit/src/main/java/us/myles/ViaVersion/listeners/protocol1_9to1_8/DeathListener.java index 51f91e4d0..07760f598 100644 --- a/common/src/main/java/us/myles/ViaVersion/protocols/protocol1_9to1_8/listeners/DeathListener.java +++ b/bukkit/src/main/java/us/myles/ViaVersion/listeners/protocol1_9to1_8/DeathListener.java @@ -1,4 +1,4 @@ -package us.myles.ViaVersion.protocols.protocol1_9to1_8.listeners; +package us.myles.ViaVersion.listeners.protocol1_9to1_8; import org.bukkit.Bukkit; import org.bukkit.World; diff --git a/common/src/main/java/us/myles/ViaVersion/protocols/protocol1_9to1_8/listeners/HandItemCache.java b/bukkit/src/main/java/us/myles/ViaVersion/listeners/protocol1_9to1_8/HandItemCache.java similarity index 94% rename from common/src/main/java/us/myles/ViaVersion/protocols/protocol1_9to1_8/listeners/HandItemCache.java rename to bukkit/src/main/java/us/myles/ViaVersion/listeners/protocol1_9to1_8/HandItemCache.java index ed1791ca7..81abed547 100644 --- a/common/src/main/java/us/myles/ViaVersion/protocols/protocol1_9to1_8/listeners/HandItemCache.java +++ b/bukkit/src/main/java/us/myles/ViaVersion/listeners/protocol1_9to1_8/HandItemCache.java @@ -1,4 +1,4 @@ -package us.myles.ViaVersion.protocols.protocol1_9to1_8.listeners; +package us.myles.ViaVersion.listeners.protocol1_9to1_8; import org.bukkit.Bukkit; import org.bukkit.entity.Player; diff --git a/common/src/main/java/us/myles/ViaVersion/protocols/protocol1_9to1_8/listeners/PaperPatch.java b/bukkit/src/main/java/us/myles/ViaVersion/listeners/protocol1_9to1_8/PaperPatch.java similarity index 97% rename from common/src/main/java/us/myles/ViaVersion/protocols/protocol1_9to1_8/listeners/PaperPatch.java rename to bukkit/src/main/java/us/myles/ViaVersion/listeners/protocol1_9to1_8/PaperPatch.java index bd59d0f2e..5a1e36371 100644 --- a/common/src/main/java/us/myles/ViaVersion/protocols/protocol1_9to1_8/listeners/PaperPatch.java +++ b/bukkit/src/main/java/us/myles/ViaVersion/listeners/protocol1_9to1_8/PaperPatch.java @@ -1,4 +1,4 @@ -package us.myles.ViaVersion.protocols.protocol1_9to1_8.listeners; +package us.myles.ViaVersion.listeners.protocol1_9to1_8; import org.bukkit.Location; import org.bukkit.Material; diff --git a/common/pom.xml b/common/pom.xml index a8efbad02..427ec7ce4 100644 --- a/common/pom.xml +++ b/common/pom.xml @@ -7,6 +7,7 @@ us.myles 1.0.0-ALPHA-16w38a + 4.0.0 viaversion-common diff --git a/common/src/main/java/us/myles/ViaVersion/ViaManager.java b/common/src/main/java/us/myles/ViaVersion/ViaManager.java new file mode 100644 index 000000000..e891e04c4 --- /dev/null +++ b/common/src/main/java/us/myles/ViaVersion/ViaManager.java @@ -0,0 +1,84 @@ +package us.myles.ViaVersion; + +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.Setter; +import us.myles.ViaVersion.api.command.ViaVersionCommand; +import us.myles.ViaVersion.api.data.UserConnection; +import us.myles.ViaVersion.api.platform.ViaInjector; +import us.myles.ViaVersion.api.platform.ViaPlatform; +import us.myles.ViaVersion.api.protocol.ProtocolRegistry; +import us.myles.ViaVersion.api.protocol.ProtocolVersion; +import us.myles.ViaVersion.protocols.base.ProtocolInfo; +import us.myles.ViaVersion.update.UpdateUtil; + +import java.util.Map; +import java.util.UUID; +import java.util.concurrent.ConcurrentHashMap; + +@Getter +public class ViaManager { + private ViaPlatform platform; + private final Map portedPlayers = new ConcurrentHashMap<>(); + @Setter + private boolean debug = false; + // Internals + private ViaInjector injector; + private ViaVersionCommand commandHandler; + + public ViaManager(ViaPlatform platform) { + this.platform = platform; + } + + public void init() { + if (System.getProperty("ViaVersion") != null) { + // Reload? + platform.onReload(); + } + // Check for updates + if (platform.getConf().isCheckForUpdates()) + UpdateUtil.sendUpdateMessage(); + // Inject + // TODO: Get errors + injector.inject(); + // Mark as injected + System.setProperty("ViaVersion", getPlatform().getPluginVersion()); + // If successful + // TODO: This method might run in onLoad, ensure sync tasks can still run if plugin not enabled. + platform.runSync(new Runnable() { + @Override + public void run() { + ProtocolRegistry.SERVER_PROTOCOL = injector.getServerProtocolVersion(); + + // Check if there are any pipes to this version + if (ProtocolRegistry.SERVER_PROTOCOL != -1) { + getPlatform().getLogger().info("ViaVersion detected server version: " + ProtocolVersion.getProtocol(ProtocolRegistry.SERVER_PROTOCOL)); + if (!ProtocolRegistry.isWorkingPipe()) { + getPlatform().getLogger().warning("ViaVersion does not have any compatible versions for this server version, please read our resource page carefully."); + } + } + ProtocolRegistry.refreshVersions(); + } + }); + + } + + public void destroy() { + // Uninject + getPlatform().getLogger().info("ViaVersion is disabling, if this is a reload and you experience issues consider rebooting."); + injector.uninject(); + } + + public void addPortedClient(UserConnection info) { + portedPlayers.put(info.get(ProtocolInfo.class).getUuid(), info); + } + + public void removePortedClient(UUID clientID) { + portedPlayers.remove(clientID); + } + + public UserConnection getConnection(UUID playerUUID) { + return portedPlayers.get(playerUUID); + } + +} diff --git a/common/src/main/java/us/myles/ViaVersion/api/PacketWrapper.java b/common/src/main/java/us/myles/ViaVersion/api/PacketWrapper.java index 18d631225..10347f2ce 100644 --- a/common/src/main/java/us/myles/ViaVersion/api/PacketWrapper.java +++ b/common/src/main/java/us/myles/ViaVersion/api/PacketWrapper.java @@ -12,7 +12,6 @@ import us.myles.ViaVersion.api.remapper.ValueCreator; import us.myles.ViaVersion.api.type.Type; import us.myles.ViaVersion.api.type.TypeConverter; import us.myles.ViaVersion.exception.InformativeException; -import us.myles.ViaVersion.handlers.ViaDecodeHandler; import us.myles.ViaVersion.packets.Direction; import us.myles.ViaVersion.packets.State; import us.myles.ViaVersion.protocols.base.ProtocolInfo; @@ -25,6 +24,8 @@ import java.util.LinkedList; import java.util.List; public class PacketWrapper { + public static int PASSTHROUGH_ID = 1000; + private final ByteBuf inputBuffer; private final UserConnection userConnection; private boolean send = true; @@ -461,7 +462,7 @@ public class PacketWrapper { public void sendToServer() throws Exception { if (!isCancelled()) { ByteBuf output = inputBuffer == null ? Unpooled.buffer() : inputBuffer.alloc().buffer(); - Type.VAR_INT.write(output, ViaDecodeHandler.PASSTHROUGH_ID); // Pass through + Type.VAR_INT.write(output, PacketWrapper.PASSTHROUGH_ID); // Pass through writeToBuffer(output); diff --git a/common/src/main/java/us/myles/ViaVersion/api/Via.java b/common/src/main/java/us/myles/ViaVersion/api/Via.java index 06d2461d6..30983d426 100644 --- a/common/src/main/java/us/myles/ViaVersion/api/Via.java +++ b/common/src/main/java/us/myles/ViaVersion/api/Via.java @@ -2,14 +2,23 @@ package us.myles.ViaVersion.api; import lombok.Getter; import org.apache.commons.lang.Validate; +import us.myles.ViaVersion.ViaManager; import us.myles.ViaVersion.api.platform.ViaPlatform; public class Via { @Getter private static ViaPlatform platform; + @Getter + private static ViaManager manager; public static void init(ViaPlatform platform) { Validate.isTrue(platform == null, "Platform is already set"); Via.platform = platform; + Via.manager = new ViaManager(platform); + } + + public static ViaAPI getAPI() { + Validate.isTrue(platform != null, "ViaVersion has not loaded the Platform"); + return Via.platform.getApi(); } } diff --git a/common/src/main/java/us/myles/ViaVersion/api/ViaAPI.java b/common/src/main/java/us/myles/ViaVersion/api/ViaAPI.java new file mode 100644 index 000000000..f98eeaa3b --- /dev/null +++ b/common/src/main/java/us/myles/ViaVersion/api/ViaAPI.java @@ -0,0 +1,100 @@ +package us.myles.ViaVersion.api; + +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.command.ViaVersionCommand; +import us.myles.ViaVersion.api.protocol.ProtocolRegistry; + +import java.util.SortedSet; +import java.util.UUID; + +/** + * Represents the ViaAPI + * + * @param The player type for the specific platform, for bukkit it's {@code ViaAPI} + */ +public interface ViaAPI { + /** + * Get protocol number from a player + * Will also retrieve version from ProtocolSupport if it's being used. + * + * @param player Platform player object, eg. Bukkit this is Player + * @return Protocol ID, For example (47=1.8-1.8.8, 107=1.9, 108=1.9.1) + */ + int getPlayerVersion(T player); + + /** + * Get protocol number from a player + * + * @param uuid UUID of a player + * @return Protocol ID, For example (47=1.8-1.8.8, 107=1.9, 108=1.9.1) + */ + int getPlayerVersion(UUID uuid); + + /** + * Is player using 1.9? + * + * @param playerUUID UUID of a player + * @return True if the client is on 1.9 + * @deprecated As of 0.9.9, because all players are ported use {@link #getPlayerVersion(UUID)} + */ + @Deprecated + boolean isPorted(UUID playerUUID); + + /** + * Get the version of the plugin + * + * @return Plugin version + */ + String getVersion(); + + /** + * Send a raw packet to the player (Use new IDs) + * + * @param player Platform player object, eg. Bukkit this is Player + * @param packet The packet, you need a VarInt ID then the packet contents. + * @throws IllegalArgumentException If not on 1.9 throws IllegalArg + */ + void sendRawPacket(T player, ByteBuf packet) throws IllegalArgumentException; + + /** + * Send a raw packet to the player (Use new IDs) + * + * @param uuid The uuid from the player to send packet + * @param packet The packet, you need a VarInt ID then the packet contents. + * @throws IllegalArgumentException If not on 1.9 throws IllegalArg + */ + void sendRawPacket(UUID uuid, ByteBuf packet) throws IllegalArgumentException; + + /** + * Create a new bossbar instance + * + * @param title The title + * @param color The color + * @param style The style + * @return BossBar instance + */ + BossBar createBossBar(String title, BossColor color, BossStyle style); + + /** + * Create a new bossbar instance + * + * @param title The title + * @param health Number between 0 and 1 + * @param color The color + * @param style The style + * @return BossBar instance + */ + BossBar createBossBar(String title, float health, BossColor color, BossStyle style); + + /** + * Get the supported protocol versions + * This method removes any blocked protocol versions. + * + * @return a list of protocol versions + * @see ProtocolRegistry#getSupportedVersions() for full list. + */ + SortedSet getSupportedVersions(); +} diff --git a/common/src/main/java/us/myles/ViaVersion/api/data/UserConnection.java b/common/src/main/java/us/myles/ViaVersion/api/data/UserConnection.java index badb3b9e9..656e23980 100644 --- a/common/src/main/java/us/myles/ViaVersion/api/data/UserConnection.java +++ b/common/src/main/java/us/myles/ViaVersion/api/data/UserConnection.java @@ -7,7 +7,6 @@ import io.netty.channel.socket.SocketChannel; import lombok.Data; import net.md_5.bungee.api.ChatColor; import us.myles.ViaVersion.api.Via; -import us.myles.ViaVersion.api.ViaVersion; import us.myles.ViaVersion.protocols.base.ProtocolInfo; import java.util.Map; diff --git a/common/src/main/java/us/myles/ViaVersion/api/platform/ViaInjector.java b/common/src/main/java/us/myles/ViaVersion/api/platform/ViaInjector.java new file mode 100644 index 000000000..e39b73cab --- /dev/null +++ b/common/src/main/java/us/myles/ViaVersion/api/platform/ViaInjector.java @@ -0,0 +1,9 @@ +package us.myles.ViaVersion.api.platform; + +public interface ViaInjector { + public void inject(); + + public void uninject(); + + public int getServerProtocolVersion(); +} diff --git a/common/src/main/java/us/myles/ViaVersion/api/platform/ViaPlatform.java b/common/src/main/java/us/myles/ViaVersion/api/platform/ViaPlatform.java index f72e85438..749db27f0 100644 --- a/common/src/main/java/us/myles/ViaVersion/api/platform/ViaPlatform.java +++ b/common/src/main/java/us/myles/ViaVersion/api/platform/ViaPlatform.java @@ -1,9 +1,17 @@ package us.myles.ViaVersion.api.platform; +import us.myles.ViaVersion.api.ViaAPI; +import us.myles.ViaVersion.api.ViaVersionConfig; + import java.util.UUID; import java.util.logging.Logger; -public interface ViaPlatform { +/** + * ViaPlatform represents a platform ViaVersion runs on + * + * @param - The player type for the platform, used for API related methods + */ +public interface ViaPlatform { public Logger getLogger(); public String getPlatformName(); @@ -19,4 +27,10 @@ public interface ViaPlatform { public boolean kickPlayer(UUID uuid, String message); public boolean isPluginEnabled(); + + public ViaAPI getApi(); + + public ViaVersionConfig getConf(); + + public void onReload(); } diff --git a/common/src/main/java/us/myles/ViaVersion/api/protocol/ProtocolPipeline.java b/common/src/main/java/us/myles/ViaVersion/api/protocol/ProtocolPipeline.java index fc43208df..1525cfee8 100644 --- a/common/src/main/java/us/myles/ViaVersion/api/protocol/ProtocolPipeline.java +++ b/common/src/main/java/us/myles/ViaVersion/api/protocol/ProtocolPipeline.java @@ -1,7 +1,7 @@ package us.myles.ViaVersion.api.protocol; import us.myles.ViaVersion.api.PacketWrapper; -import us.myles.ViaVersion.api.ViaVersion; +import us.myles.ViaVersion.api.Via; import us.myles.ViaVersion.api.data.UserConnection; import us.myles.ViaVersion.api.platform.ViaPlatform; import us.myles.ViaVersion.packets.Direction; @@ -74,7 +74,7 @@ public class ProtocolPipeline extends Protocol { super.transform(direction, state, packetWrapper); - if (ViaVersion.getInstance().isDebug()) { + if (Via.getManager().isDebug()) { // Debug packet String packet = "UNKNOWN"; @@ -109,7 +109,7 @@ public class ProtocolPipeline extends Protocol { } } String name = packet + "[" + userConnection.get(ProtocolInfo.class).getProtocolVersion() + "]"; - ViaPlatform platform = ViaVersion.getPlatform(); + ViaPlatform platform = Via.getPlatform(); String actualUsername = packetWrapper.user().get(ProtocolInfo.class).getUsername(); String username = actualUsername != null ? actualUsername + " " : ""; diff --git a/common/src/main/java/us/myles/ViaVersion/api/protocol/ProtocolRegistry.java b/common/src/main/java/us/myles/ViaVersion/api/protocol/ProtocolRegistry.java index 59016e270..9f57a93fa 100644 --- a/common/src/main/java/us/myles/ViaVersion/api/protocol/ProtocolRegistry.java +++ b/common/src/main/java/us/myles/ViaVersion/api/protocol/ProtocolRegistry.java @@ -3,7 +3,7 @@ package us.myles.ViaVersion.api.protocol; import com.google.common.collect.Lists; import com.google.common.collect.Sets; import us.myles.ViaVersion.api.Pair; -import us.myles.ViaVersion.api.ViaVersion; +import us.myles.ViaVersion.api.Via; import us.myles.ViaVersion.protocols.base.BaseProtocol; import us.myles.ViaVersion.protocols.protocol1_10to1_9_3.Protocol1_10To1_9_3_4; import us.myles.ViaVersion.protocols.protocol1_9_1_2to1_9_3_4.Protocol1_9_1_2TO1_9_3_4; @@ -61,7 +61,7 @@ public class ProtocolRegistry { registryMap.get(version).put(output, protocol); } - if (ViaVersion.getPlatform().isPluginEnabled()) { + if (Via.getPlatform().isPluginEnabled()) { protocol.registerListeners(); refreshVersions(); } else { diff --git a/common/src/main/java/us/myles/ViaVersion/protocols/protocol1_9to1_8/Protocol1_9TO1_8.java b/common/src/main/java/us/myles/ViaVersion/protocols/protocol1_9to1_8/Protocol1_9TO1_8.java index 05cc8bcb8..4db6a2fdb 100644 --- a/common/src/main/java/us/myles/ViaVersion/protocols/protocol1_9to1_8/Protocol1_9TO1_8.java +++ b/common/src/main/java/us/myles/ViaVersion/protocols/protocol1_9to1_8/Protocol1_9TO1_8.java @@ -15,8 +15,8 @@ import us.myles.ViaVersion.api.remapper.ValueTransformer; import us.myles.ViaVersion.api.type.Type; import us.myles.ViaVersion.api.type.types.version.Metadata1_8Type; import us.myles.ViaVersion.api.type.types.version.MetadataList1_8Type; +import us.myles.ViaVersion.listeners.protocol1_9to1_8.*; import us.myles.ViaVersion.protocols.base.ProtocolInfo; -import us.myles.ViaVersion.protocols.protocol1_9to1_8.listeners.*; import us.myles.ViaVersion.protocols.protocol1_9to1_8.packets.*; import us.myles.ViaVersion.protocols.protocol1_9to1_8.storage.*; diff --git a/common/src/main/java/us/myles/ViaVersion/protocols/protocol1_9to1_8/storage/ClientChunks.java b/common/src/main/java/us/myles/ViaVersion/protocols/protocol1_9to1_8/storage/ClientChunks.java index bb0395ece..a18514b5e 100644 --- a/common/src/main/java/us/myles/ViaVersion/protocols/protocol1_9to1_8/storage/ClientChunks.java +++ b/common/src/main/java/us/myles/ViaVersion/protocols/protocol1_9to1_8/storage/ClientChunks.java @@ -3,7 +3,7 @@ package us.myles.ViaVersion.protocols.protocol1_9to1_8.storage; import com.google.common.collect.Lists; import com.google.common.collect.Sets; import lombok.Getter; -import org.bukkit.Bukkit; +import us.myles.ViaVersion.api.Via; import us.myles.ViaVersion.api.ViaVersion; import us.myles.ViaVersion.api.data.StoredObject; import us.myles.ViaVersion.api.data.UserConnection; @@ -24,6 +24,7 @@ public class ClientChunks extends StoredObject { static { try { + // TODO: Abstract this ? mapChunkBulkRef = new ReflectionUtil.ClassReflection(ReflectionUtil.nms("PacketPlayOutMapChunkBulk")); mapChunkRef = new ReflectionUtil.ClassReflection(ReflectionUtil.nms("PacketPlayOutMapChunk")); if (ViaVersion.getInstance().isSpigot()) { @@ -31,7 +32,7 @@ public class ClientChunks extends StoredObject { worldRef = ReflectionUtil.nms("World"); } } catch (Exception e) { - Bukkit.getLogger().log(Level.WARNING, "Failed to initialise chunks reflection", e); + Via.getPlatform().getLogger().log(Level.WARNING, "Failed to initialise chunks reflection", e); } } @@ -83,7 +84,7 @@ public class ClientChunks extends StoredObject { list.add(chunkPacket); } } catch (Exception e) { - Bukkit.getLogger().log(Level.WARNING, "Failed to transform chunks bulk", e); + Via.getPlatform().getLogger().log(Level.WARNING, "Failed to transform chunks bulk", e); } return list; } diff --git a/common/src/main/java/us/myles/ViaVersion/protocols/protocol1_9to1_8/types/ChunkType.java b/common/src/main/java/us/myles/ViaVersion/protocols/protocol1_9to1_8/types/ChunkType.java index 63c57a9ca..cf0d1e322 100644 --- a/common/src/main/java/us/myles/ViaVersion/protocols/protocol1_9to1_8/types/ChunkType.java +++ b/common/src/main/java/us/myles/ViaVersion/protocols/protocol1_9to1_8/types/ChunkType.java @@ -2,7 +2,7 @@ package us.myles.ViaVersion.protocols.protocol1_9to1_8.types; import io.netty.buffer.ByteBuf; import io.netty.buffer.Unpooled; -import org.bukkit.Bukkit; +import us.myles.ViaVersion.api.Via; import us.myles.ViaVersion.api.ViaVersion; import us.myles.ViaVersion.api.minecraft.chunks.Chunk; import us.myles.ViaVersion.api.type.PartialType; @@ -134,7 +134,7 @@ public class ChunkType extends PartialType { // Check remaining bytes if (bytesLeft > 0) { - Bukkit.getLogger().log(Level.WARNING, bytesLeft + " Bytes left after reading chunks! (" + groundUp + ")"); + Via.getPlatform().getLogger().log(Level.WARNING, bytesLeft + " Bytes left after reading chunks! (" + groundUp + ")"); } // Return chunks diff --git a/common/src/main/java/us/myles/ViaVersion/protocols/protocolsnapshotto1_10/ItemRewriter.java b/common/src/main/java/us/myles/ViaVersion/protocols/protocolsnapshotto1_10/ItemRewriter.java index b684a7f37..ada23508d 100644 --- a/common/src/main/java/us/myles/ViaVersion/protocols/protocolsnapshotto1_10/ItemRewriter.java +++ b/common/src/main/java/us/myles/ViaVersion/protocols/protocolsnapshotto1_10/ItemRewriter.java @@ -1,6 +1,5 @@ package us.myles.ViaVersion.protocols.protocolsnapshotto1_10; -import org.bukkit.Material; import org.spacehq.opennbt.tag.builtin.CompoundTag; import org.spacehq.opennbt.tag.builtin.StringTag; import us.myles.ViaVersion.api.minecraft.item.Item; @@ -31,7 +30,7 @@ public class ItemRewriter { } private static boolean hasEntityTag(Item item) { - if (item != null && item.getId() == Material.MONSTER_EGG.getId()) { + if (item != null && item.getId() == 383) { // Monster Egg CompoundTag tag = item.getTag(); if (tag != null && tag.contains("EntityTag") && tag.get("EntityTag") instanceof CompoundTag) { if (((CompoundTag) tag.get("EntityTag")).get("id") instanceof StringTag) { diff --git a/common/src/main/java/us/myles/ViaVersion/update/UpdateUtil.java b/common/src/main/java/us/myles/ViaVersion/update/UpdateUtil.java index 03d2fc917..254d5919b 100644 --- a/common/src/main/java/us/myles/ViaVersion/update/UpdateUtil.java +++ b/common/src/main/java/us/myles/ViaVersion/update/UpdateUtil.java @@ -5,7 +5,7 @@ import com.google.gson.GsonBuilder; import com.google.gson.JsonObject; import com.google.gson.JsonParseException; import net.md_5.bungee.api.ChatColor; -import us.myles.ViaVersion.api.ViaVersion; +import us.myles.ViaVersion.api.Via; import java.io.BufferedReader; import java.io.IOException; @@ -24,16 +24,16 @@ public class UpdateUtil { private final static Gson gson = new GsonBuilder().create(); public static void sendUpdateMessage(final UUID uuid) { - ViaVersion.getPlatform().runAsync(new Runnable() { + Via.getPlatform().runAsync(new Runnable() { @Override public void run() { final String message = getUpdateMessage(false); if (message != null) { - ViaVersion.getPlatform().runSync( + Via.getPlatform().runSync( new Runnable() { @Override public void run() { - ViaVersion.getPlatform().sendMessage(uuid, PREFIX + message); + Via.getPlatform().sendMessage(uuid, PREFIX + message); } } ); @@ -43,16 +43,16 @@ public class UpdateUtil { } public static void sendUpdateMessage() { - ViaVersion.getPlatform().runAsync(new Runnable() { + Via.getPlatform().runAsync(new Runnable() { @Override public void run() { final String message = getUpdateMessage(true); if (message != null) { - ViaVersion.getPlatform().runSync( + Via.getPlatform().runSync( new Runnable() { @Override public void run() { - ViaVersion.getPlatform().getLogger().warning(message); + Via.getPlatform().getLogger().warning(message); } } ); @@ -62,7 +62,7 @@ public class UpdateUtil { } private static String getUpdateMessage(boolean console) { - if (ViaVersion.getInstance().getVersion().equals("${project.version}")) { + if (Via.getPlatform().getPluginVersion().equals("${project.version}")) { return "You are using a debug/custom version, consider updating."; } String newestString = getNewestVersion(); @@ -75,7 +75,7 @@ public class UpdateUtil { } Version current; try { - current = new Version(ViaVersion.getInstance().getVersion()); + current = new Version(Via.getPlatform().getPluginVersion()); } catch (IllegalArgumentException e) { return "You are using a custom version, consider updating."; } @@ -97,7 +97,7 @@ public class UpdateUtil { URL url = new URL(URL + PLUGIN + LATEST_VERSION + "?" + System.currentTimeMillis()); HttpURLConnection connection = (HttpURLConnection) url.openConnection(); connection.setUseCaches(true); - connection.addRequestProperty("User-Agent", "ViaVersion " + ViaVersion.getInstance().getVersion()); + connection.addRequestProperty("User-Agent", "ViaVersion " + Via.getPlatform().getPluginVersion()); connection.setDoOutput(true); BufferedReader br = new BufferedReader(new InputStreamReader(connection.getInputStream())); String input; diff --git a/common/src/main/java/us/myles/ViaVersion/util/ListWrapper.java b/common/src/main/java/us/myles/ViaVersion/util/ListWrapper.java index 7b19c96cf..f276d0eed 100644 --- a/common/src/main/java/us/myles/ViaVersion/util/ListWrapper.java +++ b/common/src/main/java/us/myles/ViaVersion/util/ListWrapper.java @@ -6,7 +6,6 @@ import java.util.List; import java.util.ListIterator; public abstract class ListWrapper implements List { - public final Object lock = new Object(); private final List list; public ListWrapper(List inputList) {