diff --git a/.travis.yml b/.travis.yml index 74e44a99b..f87395083 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,7 +1,7 @@ sudo: false language: java -jdk: oraclejdk7 +jdk: oraclejdk8 cache: directories: diff --git a/bukkit/pom.xml b/bukkit/pom.xml new file mode 100644 index 000000000..62680b6dd --- /dev/null +++ b/bukkit/pom.xml @@ -0,0 +1,64 @@ + + + + viaversion-parent + us.myles + 1.0.0-ALPHA-modules + + 4.0.0 + + viaversion-bukkit + + + + 1.8.8-R0.1-SNAPSHOT + + + + + + . + true + src/main/resources/ + + * + + + + + + + + + us.myles + viaversion-common + ${project.parent.version} + provided + + + + + org.bukkit + bukkit + ${bukkitVersion} + provided + true + + + junit + junit + + + gson + com.google.code.gson + + + persistence-api + javax.persistence + + + + + \ 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 new file mode 100644 index 000000000..a85fba03a --- /dev/null +++ b/bukkit/src/main/java/us/myles/ViaVersion/ViaVersionPlugin.java @@ -0,0 +1,251 @@ +package us.myles.ViaVersion; + +import com.google.gson.JsonObject; +import lombok.Getter; +import org.bukkit.Bukkit; +import org.bukkit.ChatColor; +import org.bukkit.entity.Player; +import org.bukkit.plugin.Plugin; +import org.bukkit.plugin.java.JavaPlugin; +import us.myles.ViaVersion.api.Via; +import us.myles.ViaVersion.api.ViaAPI; +import us.myles.ViaVersion.api.ViaVersion; +import us.myles.ViaVersion.api.command.ViaCommandSender; +import us.myles.ViaVersion.api.configuration.ConfigurationProvider; +import us.myles.ViaVersion.api.platform.TaskId; +import us.myles.ViaVersion.api.platform.ViaPlatform; +import us.myles.ViaVersion.bukkit.classgenerator.ClassGenerator; +import us.myles.ViaVersion.bukkit.commands.BukkitCommandHandler; +import us.myles.ViaVersion.bukkit.commands.BukkitCommandSender; +import us.myles.ViaVersion.bukkit.platform.*; +import us.myles.ViaVersion.bukkit.util.NMSUtil; +import us.myles.ViaVersion.dump.PluginInfo; +import us.myles.ViaVersion.util.GsonUtil; + +import java.util.ArrayList; +import java.util.List; +import java.util.UUID; + +public class ViaVersionPlugin extends JavaPlugin implements ViaPlatform { + + private BukkitCommandHandler commandHandler; + private boolean compatSpigotBuild = false; + private boolean spigot = true; + private boolean lateBind = false; + private boolean protocolSupport = false; + @Getter + private BukkitConfigAPI conf; + @Getter + private ViaAPI api = new BukkitViaAPI(this); + private List queuedTasks = new ArrayList<>(); + private List asyncQueuedTasks = new ArrayList<>(); + + public ViaVersionPlugin() { + // Command handler + commandHandler = new BukkitCommandHandler(); + // Init platform + Via.init(ViaManager.builder() + .platform(this) + .commandHandler(commandHandler) + .injector(new BukkitViaInjector()) + .loader(new BukkitViaLoader(this)) + .build()); + // Config magic + conf = new BukkitConfigAPI(); + // 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 { + BukkitViaInjector.patchLists(); + } catch (Exception e) { + e.printStackTrace(); + } + } + } + + @Override + public void onLoad() { + // Spigot detector + try { + Class.forName("org.spigotmc.SpigotConfig"); + } catch (ClassNotFoundException e) { + spigot = false; + } + + // Check if it's a spigot build with a protocol mod + try { + compatSpigotBuild = NMSUtil.nms("PacketEncoder").getDeclaredField("version") != null; + } catch (Exception e) { + compatSpigotBuild = false; + } + + // Generate classes needed (only works if it's compat or ps) + ClassGenerator.generate(); + lateBind = !BukkitViaInjector.isBinded(); + + getLogger().info("ViaVersion " + getDescription().getVersion() + (compatSpigotBuild ? "compat" : "") + " is now loaded" + (lateBind ? ", waiting for boot. (late-bind)" : ", injecting!")); + if (!lateBind) { + Via.getManager().init(); + } + } + + @Override + public void onEnable() { + if (lateBind) { + Via.getManager().init(); + } + + getCommand("viaversion").setExecutor(commandHandler); + getCommand("viaversion").setTabCompleter(commandHandler); + + // Warn them if they have anti-xray on and they aren't using spigot + if (conf.isAntiXRay() && !spigot) { + getLogger().info("You have anti-xray on in your config, since you're not using spigot it won't fix xray!"); + } + + // Run queued tasks + for (Runnable r : queuedTasks) { + Bukkit.getScheduler().runTask(this, r); + } + queuedTasks.clear(); + + // Run async queued tasks + for (Runnable r : asyncQueuedTasks) { + Bukkit.getScheduler().runTaskAsynchronously(this, r); + } + asyncQueuedTasks.clear(); + } + + @Override + public void onDisable() { + Via.getManager().destroy(); + } + + public boolean isCompatSpigotBuild() { + return compatSpigotBuild; + } + + + public boolean isSpigot() { + return this.spigot; + } + + public boolean isProtocolSupport() { + return protocolSupport; + } + + @Override + public String getPlatformName() { + return "Bukkit"; + } + + @Override + public String getPluginVersion() { + return getDescription().getVersion(); + } + + @Override + public TaskId runAsync(Runnable runnable) { + if (isPluginEnabled()) { + return new BukkitTaskId(getServer().getScheduler().runTaskAsynchronously(this, runnable).getTaskId()); + } else { + asyncQueuedTasks.add(runnable); + return new BukkitTaskId(null); + } + } + + @Override + public TaskId runSync(Runnable runnable) { + if (isPluginEnabled()) { + return new BukkitTaskId(getServer().getScheduler().runTask(this, runnable).getTaskId()); + } else { + queuedTasks.add(runnable); + return new BukkitTaskId(null); + } + } + + @Override + public TaskId runRepeatingSync(Runnable runnable, Long ticks) { + return new BukkitTaskId(getServer().getScheduler().runTaskTimer(this, runnable, ticks, 0).getTaskId()); + } + + @Override + public void cancelTask(TaskId taskId) { + if (taskId == null) return; + if (taskId.getObject() == null) return; + if (taskId instanceof BukkitTaskId) { + getServer().getScheduler().cancelTask((Integer) taskId.getObject()); + } + } + + @Override + public ViaCommandSender[] getOnlinePlayers() { + ViaCommandSender[] array = new ViaCommandSender[Bukkit.getOnlinePlayers().size()]; + int i = 0; + for (Player player : Bukkit.getOnlinePlayers()) { + array[i++] = new BukkitCommandSender(player); + } + return array; + } + + @Override + public void sendMessage(UUID uuid, String message) { + Player player = Bukkit.getPlayer(uuid); + if (player != null) { + player.sendMessage(message); + } + } + + @Override + public boolean kickPlayer(UUID uuid, String message) { + Player player = Bukkit.getPlayer(uuid); + if (player != null) { + player.kickPlayer(message); + return true; + } else { + return false; + } + } + + @Override + public boolean isPluginEnabled() { + return Bukkit.getPluginManager().getPlugin("ViaVersion").isEnabled(); + } + + @Override + public ConfigurationProvider getConfigurationProvider() { + return conf; + } + + @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."); + } + } + + @Override + public JsonObject getDump() { + JsonObject platformSpecific = new JsonObject(); + + List plugins = new ArrayList<>(); + for (Plugin p : Bukkit.getPluginManager().getPlugins()) + plugins.add(new PluginInfo(p.isEnabled(), p.getDescription().getName(), p.getDescription().getVersion(), p.getDescription().getMain(), p.getDescription().getAuthors())); + + platformSpecific.add("plugins", GsonUtil.getGson().toJsonTree(plugins)); + // TODO more? ProtocolLib things etc? + + return platformSpecific; + } +} diff --git a/src/main/java/us/myles/ViaVersion/api/ViaVersion.java b/bukkit/src/main/java/us/myles/ViaVersion/api/ViaVersion.java similarity index 86% rename from src/main/java/us/myles/ViaVersion/api/ViaVersion.java rename to bukkit/src/main/java/us/myles/ViaVersion/api/ViaVersion.java index a6fee1ad8..c6dff9729 100644 --- a/src/main/java/us/myles/ViaVersion/api/ViaVersion.java +++ b/bukkit/src/main/java/us/myles/ViaVersion/api/ViaVersion.java @@ -1,19 +1,19 @@ -package us.myles.ViaVersion.api; - -import lombok.Getter; -import org.apache.commons.lang.Validate; -import us.myles.ViaVersion.ViaVersionPlugin; - -public class ViaVersion { - - @Getter - private static ViaVersionAPI instance; - @Getter - private static ViaVersionConfig config; - - public static void setInstance(ViaVersionPlugin plugin) { - Validate.isTrue(instance == null, "Instance is already set"); - ViaVersion.instance = plugin; - ViaVersion.config = plugin.getConf(); - } -} +package us.myles.ViaVersion.api; + +import lombok.Getter; +import org.apache.commons.lang.Validate; +import us.myles.ViaVersion.ViaVersionPlugin; + +@Deprecated +public class ViaVersion { + @Getter + private static ViaVersionAPI instance; + @Getter + private static ViaVersionConfig config; + + public static void setInstance(ViaVersionPlugin plugin) { + Validate.isTrue(instance == null, "Instance is already set"); + ViaVersion.instance = (ViaVersionAPI) plugin.getApi(); + ViaVersion.config = plugin.getConf(); + } +} diff --git a/src/main/java/us/myles/ViaVersion/api/ViaVersionAPI.java b/bukkit/src/main/java/us/myles/ViaVersion/api/ViaVersionAPI.java similarity index 92% rename from src/main/java/us/myles/ViaVersion/api/ViaVersionAPI.java rename to bukkit/src/main/java/us/myles/ViaVersion/api/ViaVersionAPI.java index fb3d77466..a1dfcf212 100644 --- a/src/main/java/us/myles/ViaVersion/api/ViaVersionAPI.java +++ b/bukkit/src/main/java/us/myles/ViaVersion/api/ViaVersionAPI.java @@ -1,143 +1,144 @@ -package us.myles.ViaVersion.api; - -import io.netty.buffer.ByteBuf; -import org.bukkit.entity.Player; -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; - -public interface ViaVersionAPI { - /** - * Is the player connection modified by ViaVersion? - * - * @param player Bukkit player object - * @return True if the client is modified (At the moment it also means version 1.9 and higher) - * @deprecated As of 0.9.9, because all players are ported use {@link #getPlayerVersion(Player)} - */ - boolean isPorted(Player player); - - /** - * Get protocol number from a player - * Will also retrieve version from ProtocolSupport if it's being used. - * - * @param player Bukkit player object - * @return Protocol ID, For example (47=1.8-1.8.8, 107=1.9, 108=1.9.1) - */ - int getPlayerVersion(Player 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 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(Player 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 if global debug is enabled - * - * @return true if debug is enabled - */ - boolean isDebug(); - - /** - * Get ViaVersions command handler - * - * @return command handler - */ - ViaVersionCommand getCommandHandler(); - - /** - * Get if this version is a compatibility build for spigot. - * Eg. 1.9.1 / 1.9.2 allow certain versions to connect - * - * @return True if it is - */ - boolean isCompatSpigotBuild(); - - /** - * 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(); - - /** - * Gets if the server uses spigot - *

- * Note: Will only work after ViaVersion load - * - * @return True if spigot - */ - boolean isSpigot(); - - /** - * Gets if protocol support is also being used. - * - * @return True if it is being used. - */ - boolean isProtocolSupport(); -} +package us.myles.ViaVersion.api; + +import io.netty.buffer.ByteBuf; +import org.bukkit.entity.Player; +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; + +@Deprecated +public interface ViaVersionAPI extends ViaAPI { + /** + * Is the player connection modified by ViaVersion? + * + * @param player Bukkit player object + * @return True if the client is modified (At the moment it also means version 1.9 and higher) + * @deprecated As of 0.9.9, because all players are ported use {@link #getPlayerVersion(Player)} + */ + boolean isPorted(Player player); + + /** + * Get protocol number from a player + * Will also retrieve version from ProtocolSupport if it's being used. + * + * @param player Bukkit player object + * @return Protocol ID, For example (47=1.8-1.8.8, 107=1.9, 108=1.9.1) + */ + int getPlayerVersion(Player 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 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(Player 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 if global debug is enabled + * + * @return true if debug is enabled + */ + boolean isDebug(); + + /** + * Get ViaVersions commands handler + * + * @return commands handler + */ + ViaVersionCommand getCommandHandler(); + + /** + * Get if this version is a compatibility build for spigot. + * Eg. 1.9.1 / 1.9.2 allow certain versions to connect + * + * @return True if it is + */ + boolean isCompatSpigotBuild(); + + /** + * 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(); + + /** + * Gets if the server uses spigot + *

+ * Note: Will only work after ViaVersion load + * + * @return True if spigot + */ + boolean isSpigot(); + + /** + * Gets if protocol support is also being used. + * + * @return True if it is being used. + */ + boolean isProtocolSupport(); +} diff --git a/bukkit/src/main/java/us/myles/ViaVersion/boss/ViaBossBar.java b/bukkit/src/main/java/us/myles/ViaVersion/boss/ViaBossBar.java new file mode 100644 index 000000000..7083ac7d8 --- /dev/null +++ b/bukkit/src/main/java/us/myles/ViaVersion/boss/ViaBossBar.java @@ -0,0 +1,34 @@ +package us.myles.ViaVersion.boss; + +import lombok.Getter; +import org.bukkit.entity.Player; +import us.myles.ViaVersion.api.boss.BossBar; +import us.myles.ViaVersion.api.boss.BossColor; +import us.myles.ViaVersion.api.boss.BossStyle; + +@Getter +public class ViaBossBar extends CommonBoss { + + public ViaBossBar(String title, float health, BossColor color, BossStyle style) { + super(title, health, color, style); + } + + @Override + public BossBar addPlayer(Player player) { + addPlayer(player.getUniqueId()); + return this; + } + + @Override + public BossBar addPlayers(Player... players) { + for (Player p : players) + addPlayer(p); + return this; + } + + @Override + public BossBar removePlayer(Player player) { + removePlayer(player.getUniqueId()); + return this; + } +} diff --git a/bukkit/src/main/java/us/myles/ViaVersion/bukkit/classgenerator/BasicHandlerConstructor.java b/bukkit/src/main/java/us/myles/ViaVersion/bukkit/classgenerator/BasicHandlerConstructor.java new file mode 100644 index 000000000..d7908de01 --- /dev/null +++ b/bukkit/src/main/java/us/myles/ViaVersion/bukkit/classgenerator/BasicHandlerConstructor.java @@ -0,0 +1,19 @@ +package us.myles.ViaVersion.bukkit.classgenerator; + +import io.netty.handler.codec.ByteToMessageDecoder; +import io.netty.handler.codec.MessageToByteEncoder; +import us.myles.ViaVersion.api.data.UserConnection; +import us.myles.ViaVersion.bukkit.handlers.BukkitDecodeHandler; +import us.myles.ViaVersion.bukkit.handlers.BukkitEncodeHandler; + +public class BasicHandlerConstructor implements HandlerConstructor { + @Override + public BukkitEncodeHandler newEncodeHandler(UserConnection info, MessageToByteEncoder minecraftEncoder) { + return new BukkitEncodeHandler(info, minecraftEncoder); + } + + @Override + public BukkitDecodeHandler newDecodeHandler(UserConnection info, ByteToMessageDecoder minecraftDecoder) { + return new BukkitDecodeHandler(info, minecraftDecoder); + } +} diff --git a/src/main/java/us/myles/ViaVersion/classgenerator/ClassGenerator.java b/bukkit/src/main/java/us/myles/ViaVersion/bukkit/classgenerator/ClassGenerator.java similarity index 88% rename from src/main/java/us/myles/ViaVersion/classgenerator/ClassGenerator.java rename to bukkit/src/main/java/us/myles/ViaVersion/bukkit/classgenerator/ClassGenerator.java index d29089d02..ea4137a0a 100644 --- a/src/main/java/us/myles/ViaVersion/classgenerator/ClassGenerator.java +++ b/bukkit/src/main/java/us/myles/ViaVersion/bukkit/classgenerator/ClassGenerator.java @@ -1,4 +1,4 @@ -package us.myles.ViaVersion.classgenerator; +package us.myles.ViaVersion.bukkit.classgenerator; import javassist.*; import javassist.expr.ConstructorCall; @@ -6,9 +6,9 @@ import javassist.expr.ExprEditor; import org.bukkit.Bukkit; import org.bukkit.plugin.Plugin; import us.myles.ViaVersion.api.ViaVersion; -import us.myles.ViaVersion.handlers.ViaDecodeHandler; -import us.myles.ViaVersion.handlers.ViaEncodeHandler; -import us.myles.ViaVersion.util.ReflectionUtil; +import us.myles.ViaVersion.bukkit.handlers.BukkitDecodeHandler; +import us.myles.ViaVersion.bukkit.handlers.BukkitEncodeHandler; +import us.myles.ViaVersion.bukkit.util.NMSUtil; public class ClassGenerator { private static HandlerConstructor constructor = new BasicHandlerConstructor(); @@ -27,17 +27,17 @@ public class ClassGenerator { } if (ViaVersion.getInstance().isCompatSpigotBuild()) { - Class decodeSuper = ReflectionUtil.nms("PacketDecoder"); - Class encodeSuper = ReflectionUtil.nms("PacketEncoder"); + Class decodeSuper = NMSUtil.nms("PacketDecoder"); + Class encodeSuper = NMSUtil.nms("PacketEncoder"); // Generate the classes - addSpigotCompatibility(pool, ViaDecodeHandler.class, decodeSuper); - addSpigotCompatibility(pool, ViaEncodeHandler.class, encodeSuper); + addSpigotCompatibility(pool, BukkitDecodeHandler.class, decodeSuper); + addSpigotCompatibility(pool, BukkitEncodeHandler.class, encodeSuper); } else { Class decodeSuper = Class.forName(getPSPackage() + ".wrapped.WrappedDecoder"); Class encodeSuper = Class.forName(getPSPackage() + ".wrapped.WrappedEncoder"); // Generate the classes - addPSCompatibility(pool, ViaDecodeHandler.class, decodeSuper); - addPSCompatibility(pool, ViaEncodeHandler.class, encodeSuper); + addPSCompatibility(pool, BukkitDecodeHandler.class, decodeSuper); + addPSCompatibility(pool, BukkitEncodeHandler.class, encodeSuper); } @@ -53,10 +53,10 @@ public class ClassGenerator { pool.importPackage("io.netty.handler.codec"); // Implement Methods generated.addMethod(CtMethod.make("public MessageToByteEncoder newEncodeHandler(UserConnection info, MessageToByteEncoder minecraftEncoder) {\n" + - " return new ViaEncodeHandler(info, minecraftEncoder);\n" + + " return new BukkitEncodeHandler(info, minecraftEncoder);\n" + " }", generated)); generated.addMethod(CtMethod.make("public ByteToMessageDecoder newDecodeHandler(UserConnection info, ByteToMessageDecoder minecraftDecoder) {\n" + - " return new ViaDecodeHandler(info, minecraftDecoder);\n" + + " return new BukkitDecodeHandler(info, minecraftDecoder);\n" + " }", generated)); constructor = (HandlerConstructor) generated.toClass(HandlerConstructor.class.getClassLoader()).newInstance(); diff --git a/src/main/java/us/myles/ViaVersion/classgenerator/HandlerConstructor.java b/bukkit/src/main/java/us/myles/ViaVersion/bukkit/classgenerator/HandlerConstructor.java similarity index 89% rename from src/main/java/us/myles/ViaVersion/classgenerator/HandlerConstructor.java rename to bukkit/src/main/java/us/myles/ViaVersion/bukkit/classgenerator/HandlerConstructor.java index 19a5423c4..ab16e9967 100644 --- a/src/main/java/us/myles/ViaVersion/classgenerator/HandlerConstructor.java +++ b/bukkit/src/main/java/us/myles/ViaVersion/bukkit/classgenerator/HandlerConstructor.java @@ -1,4 +1,4 @@ -package us.myles.ViaVersion.classgenerator; +package us.myles.ViaVersion.bukkit.classgenerator; import io.netty.handler.codec.ByteToMessageDecoder; import io.netty.handler.codec.MessageToByteEncoder; diff --git a/bukkit/src/main/java/us/myles/ViaVersion/bukkit/commands/BukkitCommandHandler.java b/bukkit/src/main/java/us/myles/ViaVersion/bukkit/commands/BukkitCommandHandler.java new file mode 100644 index 000000000..11bf9771f --- /dev/null +++ b/bukkit/src/main/java/us/myles/ViaVersion/bukkit/commands/BukkitCommandHandler.java @@ -0,0 +1,21 @@ +package us.myles.ViaVersion.bukkit.commands; + +import org.bukkit.command.Command; +import org.bukkit.command.CommandExecutor; +import org.bukkit.command.CommandSender; +import org.bukkit.command.TabExecutor; +import us.myles.ViaVersion.commands.ViaCommandHandler; + +import java.util.List; + +public class BukkitCommandHandler extends ViaCommandHandler implements CommandExecutor, TabExecutor { + @Override + public boolean onCommand(CommandSender sender, Command command, String label, String[] args) { + return onCommand(new BukkitCommandSender(sender), args); + } + + @Override + public List onTabComplete(CommandSender sender, Command command, String alias, String[] args) { + return onTabComplete(new BukkitCommandSender(sender), args); + } +} diff --git a/bukkit/src/main/java/us/myles/ViaVersion/bukkit/commands/BukkitCommandSender.java b/bukkit/src/main/java/us/myles/ViaVersion/bukkit/commands/BukkitCommandSender.java new file mode 100644 index 000000000..e1288ca29 --- /dev/null +++ b/bukkit/src/main/java/us/myles/ViaVersion/bukkit/commands/BukkitCommandSender.java @@ -0,0 +1,37 @@ +package us.myles.ViaVersion.bukkit.commands; + +import lombok.AllArgsConstructor; +import org.bukkit.command.CommandSender; +import org.bukkit.entity.Player; +import us.myles.ViaVersion.api.command.ViaCommandSender; + +import java.util.UUID; + +@AllArgsConstructor +public class BukkitCommandSender implements ViaCommandSender { + private CommandSender sender; + + @Override + public boolean hasPermission(String permission) { + return sender.hasPermission(permission); + } + + @Override + public void sendMessage(String msg) { + sender.sendMessage(msg); + } + + @Override + public UUID getUUID() { + if (sender instanceof Player) { + return ((Player) sender).getUniqueId(); + } else { + return UUID.fromString(getName()); + } + } + + @Override + public String getName() { + return sender.getName(); + } +} diff --git a/src/main/java/us/myles/ViaVersion/handlers/ViaVersionInitializer.java b/bukkit/src/main/java/us/myles/ViaVersion/bukkit/handlers/BukkitChannelInitializer.java similarity index 81% rename from src/main/java/us/myles/ViaVersion/handlers/ViaVersionInitializer.java rename to bukkit/src/main/java/us/myles/ViaVersion/bukkit/handlers/BukkitChannelInitializer.java index ccd70da1e..a4529ad3a 100644 --- a/src/main/java/us/myles/ViaVersion/handlers/ViaVersionInitializer.java +++ b/bukkit/src/main/java/us/myles/ViaVersion/bukkit/handlers/BukkitChannelInitializer.java @@ -1,4 +1,4 @@ -package us.myles.ViaVersion.handlers; +package us.myles.ViaVersion.bukkit.handlers; import io.netty.channel.Channel; import io.netty.channel.ChannelInitializer; @@ -7,17 +7,17 @@ import io.netty.handler.codec.ByteToMessageDecoder; import io.netty.handler.codec.MessageToByteEncoder; import us.myles.ViaVersion.api.data.UserConnection; import us.myles.ViaVersion.api.protocol.ProtocolPipeline; -import us.myles.ViaVersion.classgenerator.ClassGenerator; -import us.myles.ViaVersion.classgenerator.HandlerConstructor; +import us.myles.ViaVersion.bukkit.classgenerator.ClassGenerator; +import us.myles.ViaVersion.bukkit.classgenerator.HandlerConstructor; import java.lang.reflect.Method; -public class ViaVersionInitializer extends ChannelInitializer { +public class BukkitChannelInitializer extends ChannelInitializer { private final ChannelInitializer original; private Method method; - public ViaVersionInitializer(ChannelInitializer oldInit) { + public BukkitChannelInitializer(ChannelInitializer oldInit) { this.original = oldInit; try { this.method = ChannelInitializer.class.getDeclaredMethod("initChannel", Channel.class); @@ -43,7 +43,7 @@ public class ViaVersionInitializer extends ChannelInitializer { // Add our transformers MessageToByteEncoder encoder = constructor.newEncodeHandler(info, (MessageToByteEncoder) socketChannel.pipeline().get("encoder")); ByteToMessageDecoder decoder = constructor.newDecodeHandler(info, (ByteToMessageDecoder) socketChannel.pipeline().get("decoder")); - ViaPacketHandler chunkHandler = new ViaPacketHandler(info); + BukkitPacketHandler chunkHandler = new BukkitPacketHandler(info); socketChannel.pipeline().replace("encoder", "encoder", encoder); socketChannel.pipeline().replace("decoder", "decoder", decoder); diff --git a/src/main/java/us/myles/ViaVersion/handlers/ViaDecodeHandler.java b/bukkit/src/main/java/us/myles/ViaVersion/bukkit/handlers/BukkitDecodeHandler.java similarity index 86% rename from src/main/java/us/myles/ViaVersion/handlers/ViaDecodeHandler.java rename to bukkit/src/main/java/us/myles/ViaVersion/bukkit/handlers/BukkitDecodeHandler.java index c7122233e..59f2f3e18 100644 --- a/src/main/java/us/myles/ViaVersion/handlers/ViaDecodeHandler.java +++ b/bukkit/src/main/java/us/myles/ViaVersion/bukkit/handlers/BukkitDecodeHandler.java @@ -1,11 +1,9 @@ -package us.myles.ViaVersion.handlers; +package us.myles.ViaVersion.bukkit.handlers; import io.netty.buffer.ByteBuf; import io.netty.channel.ChannelHandlerContext; import io.netty.handler.codec.ByteToMessageDecoder; -import us.myles.ViaVersion.ViaVersionPlugin; import us.myles.ViaVersion.api.PacketWrapper; -import us.myles.ViaVersion.api.ViaVersion; import us.myles.ViaVersion.api.data.UserConnection; import us.myles.ViaVersion.api.type.Type; import us.myles.ViaVersion.exception.CancelException; @@ -16,13 +14,12 @@ import us.myles.ViaVersion.util.PipelineUtil; import java.lang.reflect.InvocationTargetException; import java.util.List; -public class ViaDecodeHandler extends ByteToMessageDecoder { +public class BukkitDecodeHandler extends ByteToMessageDecoder { private final ByteToMessageDecoder minecraftDecoder; private final UserConnection info; - public static int PASSTHROUGH_ID = 1000; - public ViaDecodeHandler(UserConnection info, ByteToMessageDecoder minecraftDecoder) { + public BukkitDecodeHandler(UserConnection info, ByteToMessageDecoder minecraftDecoder) { this.info = info; this.minecraftDecoder = minecraftDecoder; } @@ -39,7 +36,7 @@ public class ViaDecodeHandler extends ByteToMessageDecoder { boolean second = info.incrementReceived(); // Check PPS if (second) { - if (((ViaVersionPlugin) ViaVersion.getInstance()).handlePPS(info)) + if (info.handlePPS()) return; } @@ -49,7 +46,7 @@ public class ViaDecodeHandler extends ByteToMessageDecoder { // Transform ByteBuf newPacket = ctx.alloc().buffer(); try { - if (id == ViaDecodeHandler.PASSTHROUGH_ID) { + if (id == PacketWrapper.PASSTHROUGH_ID) { newPacket.writeBytes(bytebuf); } else { PacketWrapper wrapper = new PacketWrapper(id, bytebuf, info); diff --git a/src/main/java/us/myles/ViaVersion/handlers/ViaEncodeHandler.java b/bukkit/src/main/java/us/myles/ViaVersion/bukkit/handlers/BukkitEncodeHandler.java similarity index 87% rename from src/main/java/us/myles/ViaVersion/handlers/ViaEncodeHandler.java rename to bukkit/src/main/java/us/myles/ViaVersion/bukkit/handlers/BukkitEncodeHandler.java index fd0f5d2e2..e22a8b359 100644 --- a/src/main/java/us/myles/ViaVersion/handlers/ViaEncodeHandler.java +++ b/bukkit/src/main/java/us/myles/ViaVersion/bukkit/handlers/BukkitEncodeHandler.java @@ -1,10 +1,11 @@ -package us.myles.ViaVersion.handlers; +package us.myles.ViaVersion.bukkit.handlers; import io.netty.buffer.ByteBuf; import io.netty.channel.ChannelHandlerContext; import io.netty.handler.codec.MessageToByteEncoder; +import us.myles.ViaVersion.ViaVersionPlugin; 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.type.Type; import us.myles.ViaVersion.exception.CancelException; @@ -15,11 +16,11 @@ import us.myles.ViaVersion.util.PipelineUtil; import java.lang.reflect.Field; import java.lang.reflect.InvocationTargetException; -public class ViaEncodeHandler extends MessageToByteEncoder { +public class BukkitEncodeHandler extends MessageToByteEncoder { private final UserConnection info; private final MessageToByteEncoder minecraftEncoder; - public ViaEncodeHandler(UserConnection info, MessageToByteEncoder minecraftEncoder) { + public BukkitEncodeHandler(UserConnection info, MessageToByteEncoder minecraftEncoder) { this.info = info; this.minecraftEncoder = minecraftEncoder; } @@ -27,7 +28,7 @@ public class ViaEncodeHandler extends MessageToByteEncoder { @Override protected void encode(final ChannelHandlerContext ctx, Object o, final ByteBuf bytebuf) throws Exception { - if (ViaVersion.getInstance().isCompatSpigotBuild()) { + if (((ViaVersionPlugin) Via.getPlatform()).isCompatSpigotBuild()) { Field ver = minecraftEncoder.getClass().getDeclaredField("version"); ver.setAccessible(true); ver.set(minecraftEncoder, ver.get(this)); diff --git a/src/main/java/us/myles/ViaVersion/handlers/ViaPacketHandler.java b/bukkit/src/main/java/us/myles/ViaVersion/bukkit/handlers/BukkitPacketHandler.java similarity index 87% rename from src/main/java/us/myles/ViaVersion/handlers/ViaPacketHandler.java rename to bukkit/src/main/java/us/myles/ViaVersion/bukkit/handlers/BukkitPacketHandler.java index a0205a8b5..d3b352dac 100644 --- a/src/main/java/us/myles/ViaVersion/handlers/ViaPacketHandler.java +++ b/bukkit/src/main/java/us/myles/ViaVersion/bukkit/handlers/BukkitPacketHandler.java @@ -1,4 +1,4 @@ -package us.myles.ViaVersion.handlers; +package us.myles.ViaVersion.bukkit.handlers; import io.netty.buffer.ByteBuf; import io.netty.channel.ChannelHandlerContext; @@ -8,10 +8,10 @@ import us.myles.ViaVersion.protocols.base.ProtocolInfo; import java.util.List; -public class ViaPacketHandler extends MessageToMessageEncoder { +public class BukkitPacketHandler extends MessageToMessageEncoder { private final UserConnection info; - public ViaPacketHandler(UserConnection info) { + public BukkitPacketHandler(UserConnection info) { this.info = info; } diff --git a/src/main/java/us/myles/ViaVersion/update/UpdateListener.java b/bukkit/src/main/java/us/myles/ViaVersion/bukkit/listeners/UpdateListener.java similarity index 52% rename from src/main/java/us/myles/ViaVersion/update/UpdateListener.java rename to bukkit/src/main/java/us/myles/ViaVersion/bukkit/listeners/UpdateListener.java index 965e142ac..3d7f74eb9 100644 --- a/src/main/java/us/myles/ViaVersion/update/UpdateListener.java +++ b/bukkit/src/main/java/us/myles/ViaVersion/bukkit/listeners/UpdateListener.java @@ -1,23 +1,18 @@ -package us.myles.ViaVersion.update; - -import lombok.RequiredArgsConstructor; -import org.bukkit.event.EventHandler; -import org.bukkit.event.Listener; -import org.bukkit.event.player.PlayerJoinEvent; -import us.myles.ViaVersion.ViaVersionPlugin; -import us.myles.ViaVersion.api.ViaVersion; - -@RequiredArgsConstructor -public class UpdateListener implements Listener { - - private final ViaVersionPlugin plugin; - - @EventHandler - public void onJoin(PlayerJoinEvent e) { - if (e.getPlayer().hasPermission("viaversion.update") - && ViaVersion.getConfig().isCheckForUpdates()) { - UpdateUtil.sendUpdateMessage(e.getPlayer().getUniqueId(), plugin); - } - } - -} +package us.myles.ViaVersion.bukkit.listeners; + +import org.bukkit.event.EventHandler; +import org.bukkit.event.Listener; +import org.bukkit.event.player.PlayerJoinEvent; +import us.myles.ViaVersion.api.Via; +import us.myles.ViaVersion.update.UpdateUtil; + +public class UpdateListener implements Listener { + + @EventHandler + public void onJoin(PlayerJoinEvent e) { + if (e.getPlayer().hasPermission("viaversion.update") + && Via.getConfig().isCheckForUpdates()) { + UpdateUtil.sendUpdateMessage(e.getPlayer().getUniqueId()); + } + } +} diff --git a/bukkit/src/main/java/us/myles/ViaVersion/bukkit/listeners/ViaBukkitListener.java b/bukkit/src/main/java/us/myles/ViaVersion/bukkit/listeners/ViaBukkitListener.java new file mode 100644 index 000000000..a94bca5d3 --- /dev/null +++ b/bukkit/src/main/java/us/myles/ViaVersion/bukkit/listeners/ViaBukkitListener.java @@ -0,0 +1,53 @@ +package us.myles.ViaVersion.bukkit.listeners; + +import lombok.AccessLevel; +import lombok.Getter; +import lombok.NonNull; +import org.bukkit.entity.Player; +import org.bukkit.event.Listener; +import org.bukkit.plugin.Plugin; +import us.myles.ViaVersion.ViaVersionPlugin; +import us.myles.ViaVersion.api.ViaListener; +import us.myles.ViaVersion.api.data.UserConnection; +import us.myles.ViaVersion.api.protocol.Protocol; + +@Getter(AccessLevel.PROTECTED) +public class ViaBukkitListener extends ViaListener implements Listener { + private final Plugin plugin; + + public ViaBukkitListener(ViaVersionPlugin plugin, Class requiredPipeline) { + super(requiredPipeline); + this.plugin = plugin; + } + + /** + * Get the UserConnection from a player + * + * @param player Player object + * @return The UserConnection + */ + protected UserConnection getUserConnection(@NonNull Player player) { + return getUserConnection(player.getUniqueId()); + } + + /** + * Checks if the player is on the selected pipe + * + * @param player Player Object + * @return True if on pipe + */ + protected boolean isOnPipe(Player player) { + return isOnPipe(player.getUniqueId()); + } + + /** + * Register as Bukkit event + */ + @Override + public void register() { + if (isRegistered()) return; + + plugin.getServer().getPluginManager().registerEvents(this, plugin); + setRegistered(true); + } +} diff --git a/src/main/java/us/myles/ViaVersion/protocols/protocol1_9to1_8/listeners/ArmorListener.java b/bukkit/src/main/java/us/myles/ViaVersion/bukkit/listeners/protocol1_9to1_8/ArmorListener.java similarity index 89% rename from src/main/java/us/myles/ViaVersion/protocols/protocol1_9to1_8/listeners/ArmorListener.java rename to bukkit/src/main/java/us/myles/ViaVersion/bukkit/listeners/protocol1_9to1_8/ArmorListener.java index 36e012132..2880f47e4 100644 --- a/src/main/java/us/myles/ViaVersion/protocols/protocol1_9to1_8/listeners/ArmorListener.java +++ b/bukkit/src/main/java/us/myles/ViaVersion/bukkit/listeners/protocol1_9to1_8/ArmorListener.java @@ -1,4 +1,4 @@ -package us.myles.ViaVersion.protocols.protocol1_9to1_8.listeners; +package us.myles.ViaVersion.bukkit.listeners.protocol1_9to1_8; import org.bukkit.Bukkit; import org.bukkit.entity.HumanEntity; @@ -12,16 +12,18 @@ import org.bukkit.event.player.PlayerInteractEvent; import org.bukkit.event.player.PlayerJoinEvent; import org.bukkit.event.player.PlayerRespawnEvent; import org.bukkit.inventory.CraftingInventory; +import org.bukkit.inventory.ItemStack; import us.myles.ViaVersion.ViaVersionPlugin; import us.myles.ViaVersion.api.PacketWrapper; -import us.myles.ViaVersion.api.ViaListener; +import us.myles.ViaVersion.api.Via; import us.myles.ViaVersion.api.type.Type; +import us.myles.ViaVersion.bukkit.listeners.ViaBukkitListener; import us.myles.ViaVersion.protocols.protocol1_9to1_8.ArmorType; import us.myles.ViaVersion.protocols.protocol1_9to1_8.Protocol1_9TO1_8; import java.util.UUID; -public class ArmorListener extends ViaListener { +public class ArmorListener extends ViaBukkitListener { private static final UUID ARMOR_ATTRIBUTE = UUID.fromString("2AD3F246-FEE1-4E67-B886-69FD380BB150"); @@ -33,7 +35,11 @@ public class ArmorListener extends ViaListener { // Ensure that the player is on our pipe if (!isOnPipe(player)) return; - int armor = ArmorType.calculateArmorPoints(player.getInventory().getArmorContents()); + + int armor = 0; + for (ItemStack stack : player.getInventory().getArmorContents()) { + armor += ArmorType.findById(stack.getTypeId()).getArmorPoints(); + } PacketWrapper wrapper = new PacketWrapper(0x4B, null, getUserConnection(player)); try { @@ -58,7 +64,7 @@ public class ArmorListener extends ViaListener { if (human instanceof Player && e.getInventory() instanceof CraftingInventory) { final Player player = (Player) human; if (e.getCurrentItem() != null) { - if (ArmorType.isArmor(e.getCurrentItem().getType())) { + if (ArmorType.isArmor(e.getCurrentItem().getTypeId())) { sendDelayedArmorUpdate(player); return; } @@ -102,7 +108,7 @@ public class ArmorListener extends ViaListener { public void sendDelayedArmorUpdate(final Player player) { if (!isOnPipe(player)) return; // Don't start a task if the player is not on the pipe - Bukkit.getScheduler().scheduleSyncDelayedTask(getPlugin(), new Runnable() { + Via.getPlatform().runSync(new Runnable() { @Override public void run() { sendArmorUpdate(player); diff --git a/src/main/java/us/myles/ViaVersion/protocols/protocol1_9to1_8/listeners/BlockListener.java b/bukkit/src/main/java/us/myles/ViaVersion/bukkit/listeners/protocol1_9to1_8/BlockListener.java similarity index 83% rename from src/main/java/us/myles/ViaVersion/protocols/protocol1_9to1_8/listeners/BlockListener.java rename to bukkit/src/main/java/us/myles/ViaVersion/bukkit/listeners/protocol1_9to1_8/BlockListener.java index 8143caa91..801e406cd 100644 --- a/src/main/java/us/myles/ViaVersion/protocols/protocol1_9to1_8/listeners/BlockListener.java +++ b/bukkit/src/main/java/us/myles/ViaVersion/bukkit/listeners/protocol1_9to1_8/BlockListener.java @@ -1,16 +1,16 @@ -package us.myles.ViaVersion.protocols.protocol1_9to1_8.listeners; +package us.myles.ViaVersion.bukkit.listeners.protocol1_9to1_8; import org.bukkit.block.Block; import org.bukkit.event.EventHandler; import org.bukkit.event.EventPriority; import org.bukkit.event.block.BlockPlaceEvent; import us.myles.ViaVersion.ViaVersionPlugin; -import us.myles.ViaVersion.api.ViaListener; import us.myles.ViaVersion.api.minecraft.Position; +import us.myles.ViaVersion.bukkit.listeners.ViaBukkitListener; import us.myles.ViaVersion.protocols.protocol1_9to1_8.Protocol1_9TO1_8; import us.myles.ViaVersion.protocols.protocol1_9to1_8.storage.EntityTracker; -public class BlockListener extends ViaListener { +public class BlockListener extends ViaBukkitListener { public BlockListener(ViaVersionPlugin plugin) { super(plugin, Protocol1_9TO1_8.class); diff --git a/src/main/java/us/myles/ViaVersion/protocols/protocol1_9to1_8/listeners/CommandBlockListener.java b/bukkit/src/main/java/us/myles/ViaVersion/bukkit/listeners/protocol1_9to1_8/CommandBlockListener.java similarity index 90% rename from src/main/java/us/myles/ViaVersion/protocols/protocol1_9to1_8/listeners/CommandBlockListener.java rename to bukkit/src/main/java/us/myles/ViaVersion/bukkit/listeners/protocol1_9to1_8/CommandBlockListener.java index a18ec4f27..e75aa3af8 100644 --- a/src/main/java/us/myles/ViaVersion/protocols/protocol1_9to1_8/listeners/CommandBlockListener.java +++ b/bukkit/src/main/java/us/myles/ViaVersion/bukkit/listeners/protocol1_9to1_8/CommandBlockListener.java @@ -1,4 +1,4 @@ -package us.myles.ViaVersion.protocols.protocol1_9to1_8.listeners; +package us.myles.ViaVersion.bukkit.listeners.protocol1_9to1_8; import io.netty.buffer.ByteBuf; import io.netty.buffer.ByteBufOutputStream; @@ -18,10 +18,11 @@ import org.spacehq.opennbt.tag.builtin.ByteTag; import org.spacehq.opennbt.tag.builtin.CompoundTag; import us.myles.ViaVersion.ViaVersionPlugin; import us.myles.ViaVersion.api.PacketWrapper; -import us.myles.ViaVersion.api.ViaListener; import us.myles.ViaVersion.api.data.UserConnection; import us.myles.ViaVersion.api.minecraft.Position; import us.myles.ViaVersion.api.type.Type; +import us.myles.ViaVersion.bukkit.listeners.ViaBukkitListener; +import us.myles.ViaVersion.bukkit.util.NMSUtil; import us.myles.ViaVersion.protocols.protocol1_9to1_8.Protocol1_9TO1_8; import us.myles.ViaVersion.util.ReflectionUtil; @@ -29,7 +30,7 @@ import java.io.DataOutput; import java.io.DataOutputStream; import java.lang.reflect.Method; -public class CommandBlockListener extends ViaListener { +public class CommandBlockListener extends ViaBukkitListener { public CommandBlockListener(ViaVersionPlugin plugin) { super(plugin, Protocol1_9TO1_8.class); @@ -88,7 +89,7 @@ public class CommandBlockListener extends ViaListener { return; CommandBlock cmd = (CommandBlock) b.getState(); - Object tileEntityCommand = ReflectionUtil.get(cmd, "commandBlock", ReflectionUtil.nms("TileEntityCommand")); + Object tileEntityCommand = ReflectionUtil.get(cmd, "commandBlock", NMSUtil.nms("TileEntityCommand")); Object updatePacket = ReflectionUtil.invoke(tileEntityCommand, "getUpdatePacket"); PacketWrapper wrapper = generatePacket(updatePacket, getUserConnection(player)); @@ -98,12 +99,12 @@ public class CommandBlockListener extends ViaListener { private PacketWrapper generatePacket(Object updatePacket, UserConnection usr) throws Exception { PacketWrapper wrapper = new PacketWrapper(0x09, null, usr); // Update block entity - long[] pos = getPosition(ReflectionUtil.get(updatePacket, "a", ReflectionUtil.nms("BlockPosition"))); + long[] pos = getPosition(ReflectionUtil.get(updatePacket, "a", NMSUtil.nms("BlockPosition"))); wrapper.write(Type.POSITION, new Position(pos[0], pos[1], pos[2])); //Block position wrapper.write(Type.BYTE, (byte) 2); // Action id always 2 - CompoundTag nbt = getNBT(ReflectionUtil.get(updatePacket, "c", ReflectionUtil.nms("NBTTagCompound"))); + CompoundTag nbt = getNBT(ReflectionUtil.get(updatePacket, "c", NMSUtil.nms("NBTTagCompound"))); if (nbt == null) { wrapper.write(Type.BYTE, (byte) 0); //If nbt is null. Use 0 as nbt return wrapper; @@ -125,12 +126,12 @@ public class CommandBlockListener extends ViaListener { } private boolean isR1() { - return ReflectionUtil.getVersion().equals("v1_8_R1"); + return NMSUtil.getVersion().equals("v1_8_R1"); } private CompoundTag getNBT(Object obj) throws Exception { ByteBuf buf = Unpooled.buffer(); - Method m = ReflectionUtil.nms("NBTCompressedStreamTools").getMethod("a", ReflectionUtil.nms("NBTTagCompound"), DataOutput.class); + Method m = NMSUtil.nms("NBTCompressedStreamTools").getMethod("a", NMSUtil.nms("NBTTagCompound"), DataOutput.class); m.invoke(null, obj, new DataOutputStream(new ByteBufOutputStream(buf))); try { return Type.NBT.read(buf); diff --git a/src/main/java/us/myles/ViaVersion/protocols/protocol1_9to1_8/listeners/DeathListener.java b/bukkit/src/main/java/us/myles/ViaVersion/bukkit/listeners/protocol1_9to1_8/DeathListener.java similarity index 87% rename from src/main/java/us/myles/ViaVersion/protocols/protocol1_9to1_8/listeners/DeathListener.java rename to bukkit/src/main/java/us/myles/ViaVersion/bukkit/listeners/protocol1_9to1_8/DeathListener.java index 51f91e4d0..5ac730080 100644 --- a/src/main/java/us/myles/ViaVersion/protocols/protocol1_9to1_8/listeners/DeathListener.java +++ b/bukkit/src/main/java/us/myles/ViaVersion/bukkit/listeners/protocol1_9to1_8/DeathListener.java @@ -1,6 +1,5 @@ -package us.myles.ViaVersion.protocols.protocol1_9to1_8.listeners; +package us.myles.ViaVersion.bukkit.listeners.protocol1_9to1_8; -import org.bukkit.Bukkit; import org.bukkit.World; import org.bukkit.entity.Player; import org.bukkit.event.EventHandler; @@ -8,12 +7,13 @@ import org.bukkit.event.EventPriority; import org.bukkit.event.entity.PlayerDeathEvent; import us.myles.ViaVersion.ViaVersionPlugin; import us.myles.ViaVersion.api.PacketWrapper; -import us.myles.ViaVersion.api.ViaListener; +import us.myles.ViaVersion.api.Via; import us.myles.ViaVersion.api.ViaVersion; import us.myles.ViaVersion.api.type.Type; +import us.myles.ViaVersion.bukkit.listeners.ViaBukkitListener; import us.myles.ViaVersion.protocols.protocol1_9to1_8.Protocol1_9TO1_8; -public class DeathListener extends ViaListener { +public class DeathListener extends ViaBukkitListener { public DeathListener(ViaVersionPlugin plugin) { super(plugin, Protocol1_9TO1_8.class); } @@ -34,7 +34,7 @@ public class DeathListener extends ViaListener { } private void sendPacket(final Player p, final String msg) { - Bukkit.getScheduler().runTask(getPlugin(), new Runnable() { + Via.getPlatform().runSync(new Runnable() { @Override public void run() { PacketWrapper wrapper = new PacketWrapper(0x2C, null, getUserConnection(p)); diff --git a/src/main/java/us/myles/ViaVersion/protocols/protocol1_9to1_8/listeners/HandItemCache.java b/bukkit/src/main/java/us/myles/ViaVersion/bukkit/listeners/protocol1_9to1_8/HandItemCache.java similarity index 68% rename from src/main/java/us/myles/ViaVersion/protocols/protocol1_9to1_8/listeners/HandItemCache.java rename to bukkit/src/main/java/us/myles/ViaVersion/bukkit/listeners/protocol1_9to1_8/HandItemCache.java index ed1791ca7..a7a288982 100644 --- a/src/main/java/us/myles/ViaVersion/protocols/protocol1_9to1_8/listeners/HandItemCache.java +++ b/bukkit/src/main/java/us/myles/ViaVersion/bukkit/listeners/protocol1_9to1_8/HandItemCache.java @@ -1,7 +1,8 @@ -package us.myles.ViaVersion.protocols.protocol1_9to1_8.listeners; +package us.myles.ViaVersion.bukkit.listeners.protocol1_9to1_8; import org.bukkit.Bukkit; import org.bukkit.entity.Player; +import org.bukkit.inventory.ItemStack; import org.bukkit.scheduler.BukkitRunnable; import us.myles.ViaVersion.api.minecraft.item.Item; @@ -25,7 +26,7 @@ public class HandItemCache extends BukkitRunnable { List players = new ArrayList<>(handCache.keySet()); for (Player p : Bukkit.getOnlinePlayers()) { - handCache.put(p.getUniqueId(), Item.getItem(p.getItemInHand())); + handCache.put(p.getUniqueId(), convert(p.getItemInHand())); players.remove(p.getUniqueId()); } // Remove offline players @@ -33,4 +34,9 @@ public class HandItemCache extends BukkitRunnable { handCache.remove(uuid); } } + + public static Item convert(ItemStack itemInHand) { + if (itemInHand == null) return new Item((short) 0, (byte) 0, (short) 0, null); + return new Item((short) itemInHand.getTypeId(), (byte) itemInHand.getAmount(), itemInHand.getDurability(), null); + } } diff --git a/src/main/java/us/myles/ViaVersion/protocols/protocol1_9to1_8/listeners/PaperPatch.java b/bukkit/src/main/java/us/myles/ViaVersion/bukkit/listeners/protocol1_9to1_8/PaperPatch.java similarity index 92% rename from src/main/java/us/myles/ViaVersion/protocols/protocol1_9to1_8/listeners/PaperPatch.java rename to bukkit/src/main/java/us/myles/ViaVersion/bukkit/listeners/protocol1_9to1_8/PaperPatch.java index bd59d0f2e..5fbd1562a 100644 --- a/src/main/java/us/myles/ViaVersion/protocols/protocol1_9to1_8/listeners/PaperPatch.java +++ b/bukkit/src/main/java/us/myles/ViaVersion/bukkit/listeners/protocol1_9to1_8/PaperPatch.java @@ -1,4 +1,4 @@ -package us.myles.ViaVersion.protocols.protocol1_9to1_8.listeners; +package us.myles.ViaVersion.bukkit.listeners.protocol1_9to1_8; import org.bukkit.Location; import org.bukkit.Material; @@ -6,10 +6,10 @@ import org.bukkit.block.BlockFace; import org.bukkit.event.EventHandler; import org.bukkit.event.block.BlockPlaceEvent; import us.myles.ViaVersion.ViaVersionPlugin; -import us.myles.ViaVersion.api.ViaListener; +import us.myles.ViaVersion.bukkit.listeners.ViaBukkitListener; import us.myles.ViaVersion.protocols.protocol1_9to1_8.Protocol1_9TO1_8; -public class PaperPatch extends ViaListener { +public class PaperPatch extends ViaBukkitListener { public PaperPatch(ViaVersionPlugin plugin) { super(plugin, Protocol1_9TO1_8.class); 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 new file mode 100644 index 000000000..54820614e --- /dev/null +++ b/bukkit/src/main/java/us/myles/ViaVersion/bukkit/platform/BukkitConfigAPI.java @@ -0,0 +1,179 @@ +package us.myles.ViaVersion.bukkit.platform; + +import us.myles.ViaVersion.ViaVersionPlugin; +import us.myles.ViaVersion.api.Via; +import us.myles.ViaVersion.api.ViaVersionConfig; +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("bungee-ping-interval", "bungee-ping-save", "bungee-servers"); + + public BukkitConfigAPI() { + super(new File(((ViaVersionPlugin) Via.getPlatform()).getDataFolder(), "config.yml")); + } + + @Override + public boolean isCheckForUpdates() { + return getBoolean("checkforupdates", true); + } + + @Override + public boolean isPreventCollision() { + return getBoolean("prevent-collision", true); + } + + @Override + public boolean isNewEffectIndicator() { + return getBoolean("use-new-effect-indicator", true); + } + + @Override + public boolean isShowNewDeathMessages() { + return getBoolean("use-new-deathmessages", true); + } + + @Override + public boolean isSuppressMetadataErrors() { + return getBoolean("suppress-metadata-errors", false); + } + + @Override + public boolean isShieldBlocking() { + return getBoolean("shield-blocking", true); + } + + @Override + public boolean isHologramPatch() { + return getBoolean("hologram-patch", false); + } + + @Override + public boolean isBossbarPatch() { + return getBoolean("bossbar-patch", true); + } + + @Override + public boolean isBossbarAntiflicker() { + return getBoolean("bossbar-anti-flicker", false); + } + + @Override + public boolean isUnknownEntitiesSuppressed() { + return false; + } + + @Override + public double getHologramYOffset() { + return getDouble("hologram-y", -0.96D); + } + + @Override + public boolean isBlockBreakPatch() { + return false; + } + + @Override + public int getMaxPPS() { + return getInt("max-pps", 800); + } + + @Override + public String getMaxPPSKickMessage() { + return getString("max-pps-kick-msg", "Sending packets too fast? lag?"); + } + + @Override + public int getTrackingPeriod() { + return getInt("tracking-period", 6); + } + + @Override + public int getWarningPPS() { + return getInt("tracking-warning-pps", 120); + } + + @Override + public int getMaxWarnings() { + return getInt("tracking-max-warnings", 3); + } + + @Override + public String getMaxWarningsKickMessage() { + return getString("tracking-max-kick-msg", "You are sending too many packets, :("); + } + + @Override + public boolean isAntiXRay() { + return getBoolean("anti-xray-patch", true); + } + + @Override + public boolean isSendSupportedVersions() { + return getBoolean("send-supported-versions", false); + } + + @Override + public boolean isStimulatePlayerTick() { + return getBoolean("simulate-pt", true); + } + + @Override + public boolean isItemCache() { + return getBoolean("item-cache", true); + } + + @Override + public boolean isNMSPlayerTicking() { + return getBoolean("nms-player-ticking", true); + } + + @Override + public boolean isReplacePistons() { + return getBoolean("replace-pistons", false); + } + + @Override + public int getPistonReplacementId() { + return getInt("replacement-piston-id", 0); + } + + public boolean isAutoTeam() { + // Collision has to be enabled first + return isPreventCollision() && getBoolean("auto-team", true); + } + + @Override + public boolean isForceJsonTransform() { + return getBoolean("force-json-transform", false); + } + + @Override + public List getBlockedProtocols() { + return getIntegerList("block-protocols"); + } + + @Override + public String getBlockedDisconnectMsg() { + return getString("block-disconnect-msg", "You are using an unsupported Minecraft version!"); + } + + @Override + public String getReloadDisconnectMsg() { + 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/bukkit/src/main/java/us/myles/ViaVersion/bukkit/platform/BukkitTaskId.java b/bukkit/src/main/java/us/myles/ViaVersion/bukkit/platform/BukkitTaskId.java new file mode 100644 index 000000000..50685a297 --- /dev/null +++ b/bukkit/src/main/java/us/myles/ViaVersion/bukkit/platform/BukkitTaskId.java @@ -0,0 +1,11 @@ +package us.myles.ViaVersion.bukkit.platform; + +import lombok.AllArgsConstructor; +import lombok.Getter; +import us.myles.ViaVersion.api.platform.TaskId; + +@Getter +@AllArgsConstructor +public class BukkitTaskId implements TaskId { + private Integer object; +} diff --git a/bukkit/src/main/java/us/myles/ViaVersion/bukkit/platform/BukkitViaAPI.java b/bukkit/src/main/java/us/myles/ViaVersion/bukkit/platform/BukkitViaAPI.java new file mode 100644 index 000000000..d76cece62 --- /dev/null +++ b/bukkit/src/main/java/us/myles/ViaVersion/bukkit/platform/BukkitViaAPI.java @@ -0,0 +1,127 @@ +package us.myles.ViaVersion.bukkit.platform; + +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.bukkit.util.ProtocolSupportUtil; +import us.myles.ViaVersion.protocols.base.ProtocolInfo; + +import java.util.Map; +import java.util.SortedSet; +import java.util.TreeSet; +import java.util.UUID; + +@AllArgsConstructor +public class BukkitViaAPI implements ViaAPI, ViaVersionAPI { + private 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/platform/BukkitViaInjector.java b/bukkit/src/main/java/us/myles/ViaVersion/bukkit/platform/BukkitViaInjector.java new file mode 100644 index 000000000..ef06a642e --- /dev/null +++ b/bukkit/src/main/java/us/myles/ViaVersion/bukkit/platform/BukkitViaInjector.java @@ -0,0 +1,247 @@ +package us.myles.ViaVersion.bukkit.platform; + +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.Via; +import us.myles.ViaVersion.api.platform.ViaInjector; +import us.myles.ViaVersion.bukkit.handlers.BukkitChannelInitializer; +import us.myles.ViaVersion.bukkit.util.NMSUtil; +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() throws Exception { + try { + Object connection = getServerConnection(); + if (connection == null) { + throw new Exception("We failed to find the core component 'ServerConnection', please file an issue on our GitHub."); + } + 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) { + try { + injectChannelFuture((ChannelFuture) o); + } catch (Exception e) { + e.printStackTrace(); + } + } + } + } + }; + 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) { + Via.getPlatform().getLogger().severe("Unable to inject ViaVersion, please post these details on our GitHub and ensure you're using a compatible server version."); + throw e; + } + } + + private void injectChannelFuture(ChannelFuture future) throws Exception { + try { + ChannelHandler bootstrapAcceptor = future.channel().pipeline().first(); + try { + ChannelInitializer oldInit = ReflectionUtil.get(bootstrapAcceptor, "childHandler", ChannelInitializer.class); + ChannelInitializer newInit = new BukkitChannelInitializer(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) { + Via.getPlatform().getLogger().severe("We failed to inject ViaVersion, have you got late-bind enabled with something else?"); + throw e; + } + } + + @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 BukkitChannelInitializer) { + ReflectionUtil.set(bootstrapAcceptor, "childHandler", ((BukkitChannelInitializer) 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() throws Exception { + try { + Class serverClazz = NMSUtil.nms("MinecraftServer"); + Object server = ReflectionUtil.invokeStatic(serverClazz, "getServer"); + Class pingClazz = NMSUtil.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) { + throw new Exception("Failed to get server", e); + } + throw new Exception("Failed to get server"); + } + + @Override + public String getEncoderName() { + return "encoder"; + } + + @Override + public String getDecoderName() { + return "decoder"; + } + + public static Object getServerConnection() throws Exception { + Class serverClazz = NMSUtil.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) { + Via.getPlatform().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/bukkit/platform/BukkitViaLoader.java b/bukkit/src/main/java/us/myles/ViaVersion/bukkit/platform/BukkitViaLoader.java new file mode 100644 index 000000000..28b6f23cf --- /dev/null +++ b/bukkit/src/main/java/us/myles/ViaVersion/bukkit/platform/BukkitViaLoader.java @@ -0,0 +1,92 @@ +package us.myles.ViaVersion.bukkit.platform; + +import lombok.AllArgsConstructor; +import org.bukkit.Bukkit; +import org.bukkit.event.EventHandler; +import org.bukkit.event.Listener; +import org.bukkit.event.player.PlayerQuitEvent; +import us.myles.ViaVersion.ViaVersionPlugin; +import us.myles.ViaVersion.api.Via; +import us.myles.ViaVersion.api.data.UserConnection; +import us.myles.ViaVersion.api.minecraft.item.Item; +import us.myles.ViaVersion.api.platform.ViaPlatformLoader; +import us.myles.ViaVersion.bukkit.listeners.UpdateListener; +import us.myles.ViaVersion.bukkit.listeners.protocol1_9to1_8.*; +import us.myles.ViaVersion.bukkit.providers.BukkitViaBulkChunkTranslator; +import us.myles.ViaVersion.bukkit.providers.BukkitViaMovementTransmitter; +import us.myles.ViaVersion.protocols.base.ProtocolInfo; +import us.myles.ViaVersion.protocols.protocol1_9to1_8.providers.BulkChunkTranslatorProvider; +import us.myles.ViaVersion.protocols.protocol1_9to1_8.providers.HandItemProvider; +import us.myles.ViaVersion.protocols.protocol1_9to1_8.providers.MovementTransmitterProvider; + +import java.util.UUID; +import java.util.concurrent.Callable; +import java.util.concurrent.TimeUnit; + +@AllArgsConstructor +public class BukkitViaLoader implements ViaPlatformLoader { + private ViaVersionPlugin plugin; + + @Override + public void load() { + // Update Listener + Bukkit.getPluginManager().registerEvents(new UpdateListener(), plugin); + + /* Base Protocol */ + final ViaVersionPlugin plugin = (ViaVersionPlugin) Bukkit.getPluginManager().getPlugin("ViaVersion"); + + Bukkit.getPluginManager().registerEvents(new Listener() { + @EventHandler + public void onPlayerQuit(PlayerQuitEvent e) { + Via.getManager().removePortedClient(e.getPlayer().getUniqueId()); + } + }, plugin); + + /* 1.9 client to 1.8 server */ + + new ArmorListener(plugin).register(); + new CommandBlockListener(plugin).register(); + new DeathListener(plugin).register(); + new BlockListener(plugin).register(); + + if (Bukkit.getVersion().toLowerCase().contains("paper") || Bukkit.getVersion().toLowerCase().contains("taco")) { + plugin.getLogger().info("Enabling PaperSpigot/TacoSpigot patch: Fixes block placement."); + new PaperPatch(plugin).register(); + } + if (plugin.getConf().isItemCache()) { + new HandItemCache().runTaskTimerAsynchronously(plugin, 2L, 2L); // Updates player's items :) + HandItemCache.CACHE = true; + } + + /* Providers */ + Via.getManager().getProviders().use(BulkChunkTranslatorProvider.class, new BukkitViaBulkChunkTranslator()); + Via.getManager().getProviders().use(MovementTransmitterProvider.class, new BukkitViaMovementTransmitter()); + Via.getManager().getProviders().use(HandItemProvider.class, new HandItemProvider() { + @Override + public Item getHandItem(final UserConnection info) { + if (HandItemCache.CACHE) { + return HandItemCache.getHandItem(info.get(ProtocolInfo.class).getUuid()); + } else { + try { + return Bukkit.getScheduler().callSyncMethod(Bukkit.getPluginManager().getPlugin("ViaVersion"), new Callable() { + @Override + public Item call() throws Exception { + UUID playerUUID = info.get(ProtocolInfo.class).getUuid(); + if (Bukkit.getPlayer(playerUUID) != null) { + return HandItemCache.convert(Bukkit.getPlayer(playerUUID).getItemInHand()); + } + return null; + } + }).get(10, TimeUnit.SECONDS); + } catch (Exception e) { + System.out.println("Error fetching hand item: " + e.getClass().getName()); + if (Via.getManager().isDebug()) + e.printStackTrace(); + return null; + } + } + } + }); + + } +} diff --git a/src/main/java/us/myles/ViaVersion/protocols/protocol1_9to1_8/storage/ClientChunks.java b/bukkit/src/main/java/us/myles/ViaVersion/bukkit/providers/BukkitViaBulkChunkTranslator.java similarity index 62% rename from src/main/java/us/myles/ViaVersion/protocols/protocol1_9to1_8/storage/ClientChunks.java rename to bukkit/src/main/java/us/myles/ViaVersion/bukkit/providers/BukkitViaBulkChunkTranslator.java index bb0395ece..fd4a3a271 100644 --- a/src/main/java/us/myles/ViaVersion/protocols/protocol1_9to1_8/storage/ClientChunks.java +++ b/bukkit/src/main/java/us/myles/ViaVersion/bukkit/providers/BukkitViaBulkChunkTranslator.java @@ -1,59 +1,46 @@ -package us.myles.ViaVersion.protocols.protocol1_9to1_8.storage; +package us.myles.ViaVersion.bukkit.providers; import com.google.common.collect.Lists; -import com.google.common.collect.Sets; -import lombok.Getter; -import org.bukkit.Bukkit; -import us.myles.ViaVersion.api.ViaVersion; -import us.myles.ViaVersion.api.data.StoredObject; -import us.myles.ViaVersion.api.data.UserConnection; +import us.myles.ViaVersion.ViaVersionPlugin; +import us.myles.ViaVersion.api.Via; +import us.myles.ViaVersion.bukkit.util.NMSUtil; +import us.myles.ViaVersion.protocols.protocol1_9to1_8.providers.BulkChunkTranslatorProvider; +import us.myles.ViaVersion.protocols.protocol1_9to1_8.storage.ClientChunks; import us.myles.ViaVersion.util.ReflectionUtil; import java.lang.reflect.Method; import java.util.List; -import java.util.Set; import java.util.logging.Level; -@Getter -public class ClientChunks extends StoredObject { +public class BukkitViaBulkChunkTranslator extends BulkChunkTranslatorProvider { // Reflection private static ReflectionUtil.ClassReflection mapChunkBulkRef; private static ReflectionUtil.ClassReflection mapChunkRef; private static Method obfuscateRef; - private static Class worldRef; static { try { - mapChunkBulkRef = new ReflectionUtil.ClassReflection(ReflectionUtil.nms("PacketPlayOutMapChunkBulk")); - mapChunkRef = new ReflectionUtil.ClassReflection(ReflectionUtil.nms("PacketPlayOutMapChunk")); - if (ViaVersion.getInstance().isSpigot()) { - obfuscateRef = Class.forName("org.spigotmc.AntiXray").getMethod("obfuscate", int.class, int.class, int.class, byte[].class, ReflectionUtil.nms("World")); - worldRef = ReflectionUtil.nms("World"); + mapChunkBulkRef = new ReflectionUtil.ClassReflection(NMSUtil.nms("PacketPlayOutMapChunkBulk")); + mapChunkRef = new ReflectionUtil.ClassReflection(NMSUtil.nms("PacketPlayOutMapChunk")); + if (((ViaVersionPlugin) Via.getPlatform()).isSpigot()) { + obfuscateRef = Class.forName("org.spigotmc.AntiXray").getMethod("obfuscate", int.class, int.class, int.class, byte[].class, NMSUtil.nms("World")); } + } catch (ClassNotFoundException e) { + // Ignore as server is probably 1.9+ } 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); } } - private final Set loadedChunks = Sets.newConcurrentHashSet(); - private final Set bulkChunks = Sets.newConcurrentHashSet(); - - public ClientChunks(UserConnection user) { - super(user); - } - - private static long toLong(int msw, int lsw) { - return ((long) msw << 32) + lsw - -2147483648L; - } - - public List transformMapChunkBulk(Object packet) { + @Override + public List transformMapChunkBulk(Object packet, ClientChunks clientChunks) { List list = Lists.newArrayList(); try { int[] xcoords = mapChunkBulkRef.getFieldValue("a", packet, int[].class); int[] zcoords = mapChunkBulkRef.getFieldValue("b", packet, int[].class); Object[] chunkMaps = mapChunkBulkRef.getFieldValue("c", packet, Object[].class); - if (ViaVersion.getConfig().isAntiXRay() && ViaVersion.getInstance().isSpigot()) { //Spigot anti-xray patch + if (Via.getConfig().isAntiXRay() && ((ViaVersionPlugin) Via.getPlatform()).isSpigot()) { //Spigot anti-xray patch try { Object world = mapChunkBulkRef.getFieldValue("world", packet, Object.class); @@ -79,12 +66,22 @@ public class ClientChunks extends StoredObject { mapChunkRef.setFieldValue("b", chunkPacket, z); mapChunkRef.setFieldValue("c", chunkPacket, chunkMap); mapChunkRef.setFieldValue("d", chunkPacket, true); // Chunk bulk chunks are always ground-up - bulkChunks.add(toLong(x, z)); // Store for later + clientChunks.getBulkChunks().add(ClientChunks.toLong(x, z)); // Store for later 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; } + + @Override + public boolean isFiltered(Class packetClass) { + return packetClass.getName().endsWith("PacketPlayOutMapChunkBulk"); + } + + @Override + public boolean isPacketLevel() { + return false; + } } diff --git a/bukkit/src/main/java/us/myles/ViaVersion/bukkit/providers/BukkitViaMovementTransmitter.java b/bukkit/src/main/java/us/myles/ViaVersion/bukkit/providers/BukkitViaMovementTransmitter.java new file mode 100644 index 000000000..4c9147d98 --- /dev/null +++ b/bukkit/src/main/java/us/myles/ViaVersion/bukkit/providers/BukkitViaMovementTransmitter.java @@ -0,0 +1,103 @@ +package us.myles.ViaVersion.bukkit.providers; + +import org.bukkit.Bukkit; +import org.bukkit.entity.Player; +import us.myles.ViaVersion.api.Via; +import us.myles.ViaVersion.api.data.UserConnection; +import us.myles.ViaVersion.bukkit.util.NMSUtil; +import us.myles.ViaVersion.protocols.base.ProtocolInfo; +import us.myles.ViaVersion.protocols.protocol1_9to1_8.providers.MovementTransmitterProvider; +import us.myles.ViaVersion.protocols.protocol1_9to1_8.storage.MovementTracker; + +import java.lang.reflect.Field; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; + +public class BukkitViaMovementTransmitter extends MovementTransmitterProvider { + private static boolean USE_NMS = true; + // Used for packet mode + private Object idlePacket; + private Object idlePacket2; + // Use for nms + private Method getHandle; + private Field connection; + private Method handleFlying; + + public BukkitViaMovementTransmitter() { + USE_NMS = Via.getConfig().isNMSPlayerTicking(); + + Class idlePacketClass; + try { + idlePacketClass = NMSUtil.nms("PacketPlayInFlying"); + } catch (ClassNotFoundException e) { + return; // We'll hope this is 1.9.4+ + } + try { + idlePacket = idlePacketClass.newInstance(); + idlePacket2 = idlePacketClass.newInstance(); + + Field flying = idlePacketClass.getDeclaredField("f"); + flying.setAccessible(true); + + flying.set(idlePacket2, true); + } catch (NoSuchFieldException | InstantiationException | IllegalArgumentException | IllegalAccessException e) { + throw new RuntimeException("Couldn't make player idle packet, help!", e); + } + if (USE_NMS) { + try { + getHandle = NMSUtil.obc("entity.CraftPlayer").getDeclaredMethod("getHandle"); + } catch (NoSuchMethodException | ClassNotFoundException e) { + throw new RuntimeException("Couldn't find CraftPlayer", e); + } + + try { + connection = NMSUtil.nms("EntityPlayer").getDeclaredField("playerConnection"); + } catch (NoSuchFieldException | ClassNotFoundException e) { + throw new RuntimeException("Couldn't find Player Connection", e); + } + + try { + handleFlying = NMSUtil.nms("PlayerConnection").getDeclaredMethod("a", idlePacketClass); + } catch (NoSuchMethodException | ClassNotFoundException e) { + throw new RuntimeException("Couldn't find CraftPlayer", e); + } + } + } + + @Override + public Object getFlyingPacket() { + if (idlePacket == null) + throw new NullPointerException("Could not locate flying packet"); + return idlePacket2; + } + + @Override + public Object getGroundPacket() { + if (idlePacket == null) + throw new NullPointerException("Could not locate flying packet"); + return idlePacket; + } + + @Override + public void sendPlayer(UserConnection info) { + if (USE_NMS) { + Player player = Bukkit.getPlayer(info.get(ProtocolInfo.class).getUuid()); + if (player != null) { + try { + // Tick player + Object entityPlayer = getHandle.invoke(player); + Object pc = connection.get(entityPlayer); + if (pc != null) { + handleFlying.invoke(pc, (info.get(MovementTracker.class).isGround() ? idlePacket2 : idlePacket)); + // Tick world + info.get(MovementTracker.class).incrementIdlePacket(); + } + } catch (IllegalAccessException | InvocationTargetException e) { + e.printStackTrace(); + } + } + } else { + super.sendPlayer(info); + } + } +} diff --git a/bukkit/src/main/java/us/myles/ViaVersion/bukkit/util/NMSUtil.java b/bukkit/src/main/java/us/myles/ViaVersion/bukkit/util/NMSUtil.java new file mode 100644 index 000000000..d01884ecb --- /dev/null +++ b/bukkit/src/main/java/us/myles/ViaVersion/bukkit/util/NMSUtil.java @@ -0,0 +1,20 @@ +package us.myles.ViaVersion.bukkit.util; + +import org.bukkit.Bukkit; + +public class NMSUtil { + private static String BASE = Bukkit.getServer().getClass().getPackage().getName(); + private static String NMS = BASE.replace("org.bukkit.craftbukkit", "net.minecraft.server"); + + public static Class nms(String className) throws ClassNotFoundException { + return Class.forName(NMS + "." + className); + } + + public static Class obc(String className) throws ClassNotFoundException { + return Class.forName(BASE + "." + className); + } + + public static String getVersion() { + return BASE.substring(BASE.lastIndexOf('.') + 1); + } +} diff --git a/src/main/java/us/myles/ViaVersion/util/ProtocolSupportUtil.java b/bukkit/src/main/java/us/myles/ViaVersion/bukkit/util/ProtocolSupportUtil.java similarity index 96% rename from src/main/java/us/myles/ViaVersion/util/ProtocolSupportUtil.java rename to bukkit/src/main/java/us/myles/ViaVersion/bukkit/util/ProtocolSupportUtil.java index 66458a0a5..f740893f8 100644 --- a/src/main/java/us/myles/ViaVersion/util/ProtocolSupportUtil.java +++ b/bukkit/src/main/java/us/myles/ViaVersion/bukkit/util/ProtocolSupportUtil.java @@ -1,4 +1,4 @@ -package us.myles.ViaVersion.util; +package us.myles.ViaVersion.bukkit.util; import org.bukkit.entity.Player; diff --git a/src/main/resources/plugin.yml b/bukkit/src/main/resources/plugin.yml similarity index 73% rename from src/main/resources/plugin.yml rename to bukkit/src/main/resources/plugin.yml index 764d152a8..d2cf3947c 100644 --- a/src/main/resources/plugin.yml +++ b/bukkit/src/main/resources/plugin.yml @@ -2,10 +2,11 @@ name: ViaVersion main: us.myles.ViaVersion.ViaVersionPlugin authors: [_MylesC, Matsv] version: ${project.version} +description: Allow newer Minecraft versions to connect to an older server version. load: postworld loadbefore: [ProtocolLib, ProxyPipe, SpigotLib, SkinRestorer] softdepend: [ProtocolSupport, PacketListenerApi] commands: viaversion: description: Shows ViaVersion Version and more. - aliases: [viaver] \ No newline at end of file + aliases: [viaver, vvbukkit] \ No newline at end of file diff --git a/bungee/pom.xml b/bungee/pom.xml new file mode 100644 index 000000000..75dfd9844 --- /dev/null +++ b/bungee/pom.xml @@ -0,0 +1,43 @@ + + + + viaversion-parent + us.myles + 1.0.0-ALPHA-modules + + 4.0.0 + + viaversion-bungee + + + + + . + true + src/main/resources/ + + * + + + + + + + + + net.md-5 + bungeecord-api + 1.10-SNAPSHOT + provided + + + + + us.myles + viaversion-common + 1.0.0-ALPHA-modules + + + \ No newline at end of file diff --git a/bungee/src/main/java/us/myles/ViaVersion/BungeePlugin.java b/bungee/src/main/java/us/myles/ViaVersion/BungeePlugin.java new file mode 100644 index 000000000..544f4936a --- /dev/null +++ b/bungee/src/main/java/us/myles/ViaVersion/BungeePlugin.java @@ -0,0 +1,191 @@ +package us.myles.ViaVersion; + +import com.google.gson.JsonObject; +import net.md_5.bungee.api.ProxyServer; +import net.md_5.bungee.api.chat.TextComponent; +import net.md_5.bungee.api.connection.ProxiedPlayer; +import net.md_5.bungee.api.event.PlayerDisconnectEvent; +import net.md_5.bungee.api.event.ServerConnectEvent; +import net.md_5.bungee.api.plugin.Listener; +import net.md_5.bungee.api.plugin.Plugin; +import net.md_5.bungee.event.EventHandler; +import us.myles.ViaVersion.api.Pair; +import us.myles.ViaVersion.api.Via; +import us.myles.ViaVersion.api.ViaAPI; +import us.myles.ViaVersion.api.command.ViaCommandSender; +import us.myles.ViaVersion.api.configuration.ConfigurationProvider; +import us.myles.ViaVersion.api.data.UserConnection; +import us.myles.ViaVersion.api.platform.TaskId; +import us.myles.ViaVersion.api.platform.ViaPlatform; +import us.myles.ViaVersion.api.protocol.Protocol; +import us.myles.ViaVersion.api.protocol.ProtocolRegistry; +import us.myles.ViaVersion.bungee.commands.BungeeCommand; +import us.myles.ViaVersion.bungee.commands.BungeeCommandHandler; +import us.myles.ViaVersion.bungee.commands.BungeeCommandSender; +import us.myles.ViaVersion.bungee.platform.*; +import us.myles.ViaVersion.bungee.service.ProtocolDetectorService; +import us.myles.ViaVersion.bungee.storage.BungeeStorage; +import us.myles.ViaVersion.dump.PluginInfo; +import us.myles.ViaVersion.protocols.base.ProtocolInfo; +import us.myles.ViaVersion.util.GsonUtil; +import us.myles.ViaVersion.util.ReflectionUtil; + +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import java.util.UUID; +import java.util.concurrent.TimeUnit; + +public class BungeePlugin extends Plugin implements ViaPlatform, Listener { + + private BungeeViaAPI api; + private BungeeConfigAPI config; + private BungeeCommandHandler commandHandler; + + @Override + public void onLoad() { + api = new BungeeViaAPI(); + config = new BungeeConfigAPI(getDataFolder()); + commandHandler = new BungeeCommandHandler(); + ProxyServer.getInstance().getPluginManager().registerCommand(this, new BungeeCommand(commandHandler)); + // Init platform + Via.init(ViaManager.builder() + .platform(this) + .injector(new BungeeViaInjector()) + .loader(new BungeeViaLoader(this)) + .commandHandler(commandHandler) + .build()); + } + + @Override + public void onEnable() { + // Inject + Via.getManager().init(); + } + + @Override + public String getPlatformName() { + return "BungeeCord"; + } + + @Override + public String getPluginVersion() { + return getDescription().getVersion(); + } + + @Override + public TaskId runAsync(Runnable runnable) { + return new BungeeTaskId(getProxy().getScheduler().runAsync(this, runnable).getId()); + } + + @Override + public TaskId runSync(Runnable runnable) { + return runAsync(runnable); + } + + @Override + public TaskId runRepeatingSync(Runnable runnable, Long ticks) { + return new BungeeTaskId(getProxy().getScheduler().schedule(this, runnable, 0, ticks * 50, TimeUnit.MILLISECONDS).getId()); + } + + @Override + public void cancelTask(TaskId taskId) { + if (taskId == null) return; + if (taskId.getObject() == null) return; + if (taskId instanceof BungeeTaskId) { + getProxy().getScheduler().cancel((Integer) taskId.getObject()); + } + } + + @Override + public ViaCommandSender[] getOnlinePlayers() { + ViaCommandSender[] array = new ViaCommandSender[getProxy().getPlayers().size()]; + int i = 0; + for (ProxiedPlayer player : getProxy().getPlayers()) { + array[i++] = new BungeeCommandSender(player); + } + return array; + } + + @Override + public void sendMessage(UUID uuid, String message) { + getProxy().getPlayer(uuid).sendMessage(TextComponent.fromLegacyText(message)); + } + + @Override + public boolean kickPlayer(UUID uuid, String message) { + if (getProxy().getPlayer(uuid) != null) { + getProxy().getPlayer(uuid).disconnect(TextComponent.fromLegacyText(message)); + return true; + } + return false; + } + + @Override + public boolean isPluginEnabled() { + return true; + } + + @Override + public ViaAPI getApi() { + return api; + } + + @Override + public BungeeConfigAPI getConf() { + return config; + } + + @Override + public ConfigurationProvider getConfigurationProvider() { + return config; + } + + @Override + public void onReload() { + // Injector prints a message <3 + } + + @Override + public JsonObject getDump() { + JsonObject platformSpecific = new JsonObject(); + + List plugins = new ArrayList<>(); + for (Plugin p : ProxyServer.getInstance().getPluginManager().getPlugins()) + 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.getDetectedIds())); + return platformSpecific; + } + + @EventHandler + public void onQuit(PlayerDisconnectEvent e) { + Via.getManager().removePortedClient(e.getPlayer().getUniqueId()); + } + + // Set the handshake version every time someone connects to any server + @EventHandler + public void onServerConnect(ServerConnectEvent e) throws NoSuchFieldException, IllegalAccessException { + UserConnection user = Via.getManager().getConnection(e.getPlayer().getUniqueId()); + if (!user.has(BungeeStorage.class)) { + user.put(new BungeeStorage(user, e.getPlayer())); + } + + int protocolId = ProtocolDetectorService.getProtocolId(e.getTarget().getName()); + List> protocols = ProtocolRegistry.getProtocolPath(user.get(ProtocolInfo.class).getProtocolVersion(), protocolId); + + // Check if ViaVersion can support that version + try { + Object pendingConnection = ReflectionUtil.invoke(e.getPlayer(), "getPendingConnection"); + Object handshake = ReflectionUtil.invoke(pendingConnection, "getHandshake"); + Method setProtocol = handshake.getClass().getDeclaredMethod("setProtocolVersion", int.class); + setProtocol.invoke(handshake, protocols == null ? user.get(ProtocolInfo.class).getProtocolVersion() : protocolId); + } catch (NoSuchMethodException | InvocationTargetException e1) { + e1.printStackTrace(); + } + } + +} diff --git a/bungee/src/main/java/us/myles/ViaVersion/bungee/commands/BungeeCommand.java b/bungee/src/main/java/us/myles/ViaVersion/bungee/commands/BungeeCommand.java new file mode 100644 index 000000000..bdb4cbd51 --- /dev/null +++ b/bungee/src/main/java/us/myles/ViaVersion/bungee/commands/BungeeCommand.java @@ -0,0 +1,24 @@ +package us.myles.ViaVersion.bungee.commands; + +import net.md_5.bungee.api.CommandSender; +import net.md_5.bungee.api.plugin.Command; +import net.md_5.bungee.api.plugin.TabExecutor; + +public class BungeeCommand extends Command implements TabExecutor{ + private final BungeeCommandHandler handler; + + public BungeeCommand(BungeeCommandHandler handler) { + super("viaversion", "", "viaver", "vvbungee"); // The CommandHandler will handle the permission + this.handler = handler; + } + + @Override + public void execute(CommandSender commandSender, String[] strings) { + handler.onCommand(new BungeeCommandSender(commandSender), strings); + } + + @Override + public Iterable onTabComplete(CommandSender commandSender, String[] strings) { + return handler.onTabComplete(new BungeeCommandSender(commandSender), strings); + } +} diff --git a/bungee/src/main/java/us/myles/ViaVersion/bungee/commands/BungeeCommandHandler.java b/bungee/src/main/java/us/myles/ViaVersion/bungee/commands/BungeeCommandHandler.java new file mode 100644 index 000000000..44c7c5eb0 --- /dev/null +++ b/bungee/src/main/java/us/myles/ViaVersion/bungee/commands/BungeeCommandHandler.java @@ -0,0 +1,15 @@ +package us.myles.ViaVersion.bungee.commands; + +import us.myles.ViaVersion.bungee.commands.subs.ProbeSubCmd; +import us.myles.ViaVersion.commands.ViaCommandHandler; + +public class BungeeCommandHandler extends ViaCommandHandler { + public BungeeCommandHandler() { + try { + registerSubCommand(new ProbeSubCmd()); + } catch (Exception e) { + System.out.println("Failed to register Bungee subcommands"); + e.printStackTrace(); + } + } +} diff --git a/bungee/src/main/java/us/myles/ViaVersion/bungee/commands/BungeeCommandSender.java b/bungee/src/main/java/us/myles/ViaVersion/bungee/commands/BungeeCommandSender.java new file mode 100644 index 000000000..d80a8702e --- /dev/null +++ b/bungee/src/main/java/us/myles/ViaVersion/bungee/commands/BungeeCommandSender.java @@ -0,0 +1,38 @@ +package us.myles.ViaVersion.bungee.commands; + +import lombok.AllArgsConstructor; +import net.md_5.bungee.api.CommandSender; +import net.md_5.bungee.api.chat.TextComponent; +import net.md_5.bungee.api.connection.ProxiedPlayer; +import us.myles.ViaVersion.api.command.ViaCommandSender; + +import java.util.UUID; + +@AllArgsConstructor +public class BungeeCommandSender implements ViaCommandSender { + private CommandSender sender; + + @Override + public boolean hasPermission(String permission) { + return sender.hasPermission(permission); + } + + @Override + public void sendMessage(String msg) { + sender.sendMessage(new TextComponent(msg)); + } + + @Override + public UUID getUUID() { + if (sender instanceof ProxiedPlayer) { + return ((ProxiedPlayer) sender).getUniqueId(); + } else { + return UUID.fromString(getName()); + } + } + + @Override + public String getName() { + return sender.getName(); + } +} diff --git a/bungee/src/main/java/us/myles/ViaVersion/bungee/commands/subs/ProbeSubCmd.java b/bungee/src/main/java/us/myles/ViaVersion/bungee/commands/subs/ProbeSubCmd.java new file mode 100644 index 000000000..fda215417 --- /dev/null +++ b/bungee/src/main/java/us/myles/ViaVersion/bungee/commands/subs/ProbeSubCmd.java @@ -0,0 +1,28 @@ +package us.myles.ViaVersion.bungee.commands.subs; + +import us.myles.ViaVersion.api.Via; +import us.myles.ViaVersion.api.command.ViaCommandSender; +import us.myles.ViaVersion.api.command.ViaSubCommand; +import us.myles.ViaVersion.bungee.platform.BungeeConfigAPI; +import us.myles.ViaVersion.bungee.service.ProtocolDetectorService; + +public class ProbeSubCmd extends ViaSubCommand { + @Override + public String name() { + return "probe"; + } + + @Override + public String description() { + return "Forces ViaVersion to scan server protocol versions " + + (((BungeeConfigAPI) Via.getConfig()).getBungeePingInterval() == -1 ? + "" : "(Also happens at an interval)"); + } + + @Override + public boolean execute(ViaCommandSender sender, String[] args) { + ProtocolDetectorService.getInstance().run(); + sendMessage(sender, "&6Started searching for protocol versions"); + return true; + } +} diff --git a/bungee/src/main/java/us/myles/ViaVersion/bungee/handlers/BungeeChannelInitializer.java b/bungee/src/main/java/us/myles/ViaVersion/bungee/handlers/BungeeChannelInitializer.java new file mode 100644 index 000000000..ceea247f9 --- /dev/null +++ b/bungee/src/main/java/us/myles/ViaVersion/bungee/handlers/BungeeChannelInitializer.java @@ -0,0 +1,41 @@ +package us.myles.ViaVersion.bungee.handlers; + +import io.netty.channel.Channel; +import io.netty.channel.ChannelInitializer; +import io.netty.channel.socket.SocketChannel; +import us.myles.ViaVersion.api.data.UserConnection; +import us.myles.ViaVersion.api.protocol.ProtocolPipeline; + +import java.lang.reflect.Method; + +public class BungeeChannelInitializer extends ChannelInitializer { + + private final ChannelInitializer original; + private Method method; + + public BungeeChannelInitializer(ChannelInitializer oldInit) { + this.original = oldInit; + try { + this.method = ChannelInitializer.class.getDeclaredMethod("initChannel", Channel.class); + this.method.setAccessible(true); + } catch (NoSuchMethodException e) { + e.printStackTrace(); + } + } + + @Override + protected void initChannel(SocketChannel socketChannel) throws Exception { + UserConnection info = new UserConnection(socketChannel); + // init protocol + new ProtocolPipeline(info); + // Add originals + this.method.invoke(this.original, socketChannel); + // Add our transformers + BungeeEncodeHandler encoder = new BungeeEncodeHandler(info); + BungeeDecodeHandler decoder = new BungeeDecodeHandler(info); + + socketChannel.pipeline().addBefore("packet-encoder", "via-encoder", encoder); + socketChannel.pipeline().addBefore("packet-decoder", "via-decoder", decoder); + + } +} diff --git a/bungee/src/main/java/us/myles/ViaVersion/bungee/handlers/BungeeDecodeHandler.java b/bungee/src/main/java/us/myles/ViaVersion/bungee/handlers/BungeeDecodeHandler.java new file mode 100644 index 000000000..898df7d11 --- /dev/null +++ b/bungee/src/main/java/us/myles/ViaVersion/bungee/handlers/BungeeDecodeHandler.java @@ -0,0 +1,79 @@ +package us.myles.ViaVersion.bungee.handlers; + +import io.netty.buffer.ByteBuf; +import io.netty.channel.ChannelHandler; +import io.netty.channel.ChannelHandlerContext; +import io.netty.handler.codec.MessageToMessageDecoder; +import us.myles.ViaVersion.api.PacketWrapper; +import us.myles.ViaVersion.api.data.UserConnection; +import us.myles.ViaVersion.api.type.Type; +import us.myles.ViaVersion.exception.CancelException; +import us.myles.ViaVersion.packets.Direction; +import us.myles.ViaVersion.protocols.base.ProtocolInfo; +import us.myles.ViaVersion.util.PipelineUtil; + +import java.util.List; + +@ChannelHandler.Sharable +public class BungeeDecodeHandler extends MessageToMessageDecoder { + + private final UserConnection info; + + public BungeeDecodeHandler(UserConnection info) { + this.info = info; + } + + @Override + protected void decode(final ChannelHandlerContext ctx, ByteBuf bytebuf, List out) throws Exception { + // use transformers + if (bytebuf.readableBytes() > 0) { + // Ignore if pending disconnect + if (info.isPendingDisconnect()) { + return; + } + // Increment received + boolean second = info.incrementReceived(); + // Check PPS + if (second) { + if (info.handlePPS()) + return; + } + + if (info.isActive()) { + // Handle ID + int id = Type.VAR_INT.read(bytebuf); + // Transform + ByteBuf newPacket = ctx.alloc().buffer(); + try { + if (id == PacketWrapper.PASSTHROUGH_ID) { + newPacket.writeBytes(bytebuf); + } else { + PacketWrapper wrapper = new PacketWrapper(id, bytebuf, info); + ProtocolInfo protInfo = info.get(ProtocolInfo.class); + protInfo.getPipeline().transform(Direction.INCOMING, protInfo.getState(), wrapper); + wrapper.writeToBuffer(newPacket); + } + + bytebuf.clear(); + bytebuf = newPacket; + } catch (Exception e) { + // Clear Buffer + bytebuf.clear(); + // Release Packet, be free! + newPacket.release(); + throw e; + } + } else { + bytebuf.retain(); + } + + out.add(bytebuf); + } + } + + @Override + public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception { + if (PipelineUtil.containsCause(cause, CancelException.class)) return; + super.exceptionCaught(ctx, cause); + } +} 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 new file mode 100644 index 000000000..8bc30020d --- /dev/null +++ b/bungee/src/main/java/us/myles/ViaVersion/bungee/handlers/BungeeEncodeHandler.java @@ -0,0 +1,140 @@ +package us.myles.ViaVersion.bungee.handlers; + +import io.netty.buffer.ByteBuf; +import io.netty.channel.ChannelHandler; +import io.netty.channel.ChannelHandlerContext; +import io.netty.handler.codec.MessageToMessageEncoder; +import net.md_5.bungee.api.connection.ProxiedPlayer; +import us.myles.ViaVersion.api.PacketWrapper; +import us.myles.ViaVersion.api.Pair; +import us.myles.ViaVersion.api.Via; +import us.myles.ViaVersion.api.data.UserConnection; +import us.myles.ViaVersion.api.protocol.Protocol; +import us.myles.ViaVersion.api.protocol.ProtocolPipeline; +import us.myles.ViaVersion.api.protocol.ProtocolRegistry; +import us.myles.ViaVersion.api.type.Type; +import us.myles.ViaVersion.bungee.service.ProtocolDetectorService; +import us.myles.ViaVersion.bungee.storage.BungeeStorage; +import us.myles.ViaVersion.bungee.util.BungeePipelineUtil; +import us.myles.ViaVersion.exception.CancelException; +import us.myles.ViaVersion.packets.Direction; +import us.myles.ViaVersion.protocols.base.ProtocolInfo; +import us.myles.ViaVersion.util.PipelineUtil; +import us.myles.ViaVersion.util.ReflectionUtil; + +import java.util.List; + +@ChannelHandler.Sharable +public class BungeeEncodeHandler extends MessageToMessageEncoder { + private final UserConnection info; + private boolean handledCompression = false; + + public BungeeEncodeHandler(UserConnection info) { + this.info = info; + } + + + @Override + protected void encode(final ChannelHandlerContext ctx, ByteBuf bytebuf, List out) throws Exception { + if (bytebuf.readableBytes() == 0) { + throw new CancelException(); + } + boolean needsCompress = false; + if (!handledCompression) { + if (ctx.pipeline().names().indexOf("compress") > ctx.pipeline().names().indexOf("via-encoder")) { + // Need to decompress this packet due to bad order + bytebuf = BungeePipelineUtil.decompress(ctx, bytebuf); + ChannelHandler encoder = ctx.pipeline().get("via-decoder"); + ChannelHandler decoder = ctx.pipeline().get("via-encoder"); + ctx.pipeline().remove(encoder); + ctx.pipeline().remove(decoder); + ctx.pipeline().addAfter("decompress", "via-decoder", encoder); + ctx.pipeline().addAfter("compress", "via-encoder", decoder); + needsCompress = true; + handledCompression = true; + } + } + // Increment sent + info.incrementSent(); + + if (info.isActive()) { + // Handle ID + int id = Type.VAR_INT.read(bytebuf); + // Transform + ByteBuf oldPacket = bytebuf.copy(); + bytebuf.clear(); + + try { + PacketWrapper wrapper = new PacketWrapper(id, oldPacket, info); + ProtocolInfo protInfo = info.get(ProtocolInfo.class); + protInfo.getPipeline().transform(Direction.OUTGOING, protInfo.getState(), wrapper); + wrapper.writeToBuffer(bytebuf); + } catch (Exception e) { + bytebuf.clear(); + throw e; + } finally { + oldPacket.release(); + } + } + + if (needsCompress) { + bytebuf = BungeePipelineUtil.compress(ctx, bytebuf); + } + out.add(bytebuf.retain()); + + checkServerChange(); + } + + @Override + public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception { + if (PipelineUtil.containsCause(cause, CancelException.class)) return; + super.exceptionCaught(ctx, cause); + } + + public void checkServerChange() throws Exception { + if (info.has(BungeeStorage.class)) { + BungeeStorage storage = info.get(BungeeStorage.class); + ProxiedPlayer player = storage.getPlayer(); + + if (player.getServer() != null) { + if (player.getServer() != null && !player.getServer().getInfo().getName().equals(storage.getCurrentServer())) { + String serverName = player.getServer().getInfo().getName(); + + storage.setCurrentServer(serverName); + + int protocolId = ProtocolDetectorService.getProtocolId(serverName); + + UserConnection viaConnection = Via.getManager().getConnection(player.getUniqueId()); + ProtocolInfo info = viaConnection.get(ProtocolInfo.class); + // Refresh the pipes + List> protocols = ProtocolRegistry.getProtocolPath(info.getProtocolVersion(), protocolId); + ProtocolPipeline pipeline = viaConnection.get(ProtocolInfo.class).getPipeline(); + + viaConnection.clearStoredObjects(); + pipeline.cleanPipes(); + + if (protocols != null) + for (Pair prot : protocols) { + pipeline.add(prot.getValue()); + } + + viaConnection.put(info); + viaConnection.put(storage); + + viaConnection.setActive(protocols != null); + + // Init all protocols TODO check if this can get moved up to the previous for loop, and doesn't require the pipeline to already exist. + for (Protocol protocol : pipeline.pipes()) { + protocol.init(viaConnection); + } + + Object wrapper = ReflectionUtil.get(player, "ch", Object.class); + wrapper.getClass().getDeclaredMethod("setVersion", int.class).invoke(wrapper, protocolId); + + 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/listeners/UpdateListener.java b/bungee/src/main/java/us/myles/ViaVersion/bungee/listeners/UpdateListener.java new file mode 100644 index 000000000..b27ba57e8 --- /dev/null +++ b/bungee/src/main/java/us/myles/ViaVersion/bungee/listeners/UpdateListener.java @@ -0,0 +1,18 @@ +package us.myles.ViaVersion.bungee.listeners; + +import net.md_5.bungee.api.event.PostLoginEvent; +import net.md_5.bungee.api.plugin.Listener; +import net.md_5.bungee.event.EventHandler; +import us.myles.ViaVersion.api.Via; +import us.myles.ViaVersion.update.UpdateUtil; + +public class UpdateListener implements Listener { + + @EventHandler + public void onJoin(PostLoginEvent e) { + if (e.getPlayer().hasPermission("viaversion.update") + && Via.getConfig().isCheckForUpdates()) { + UpdateUtil.sendUpdateMessage(e.getPlayer().getUniqueId()); + } + } +} diff --git a/bungee/src/main/java/us/myles/ViaVersion/bungee/platform/BungeeBossBar.java b/bungee/src/main/java/us/myles/ViaVersion/bungee/platform/BungeeBossBar.java new file mode 100644 index 000000000..538246ec2 --- /dev/null +++ b/bungee/src/main/java/us/myles/ViaVersion/bungee/platform/BungeeBossBar.java @@ -0,0 +1,34 @@ +package us.myles.ViaVersion.bungee.platform; + +import net.md_5.bungee.api.connection.ProxiedPlayer; +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.boss.CommonBoss; + +public class BungeeBossBar extends CommonBoss { + + public BungeeBossBar(String title, float health, BossColor color, BossStyle style) { + super(title, health, color, style); + } + + + @Override + public BossBar addPlayer(ProxiedPlayer player) { + addPlayer(player.getUniqueId()); + return this; + } + + @Override + public BossBar addPlayers(ProxiedPlayer... players) { + for (ProxiedPlayer p : players) + addPlayer(p); + return this; + } + + @Override + public BossBar removePlayer(ProxiedPlayer player) { + removePlayer(player.getUniqueId()); + return this; + } +} 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 new file mode 100644 index 000000000..fba410c80 --- /dev/null +++ b/bungee/src/main/java/us/myles/ViaVersion/bungee/platform/BungeeConfigAPI.java @@ -0,0 +1,232 @@ +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.*; + +public class BungeeConfigAPI extends Config implements ViaVersionConfig { + private static List UNSUPPORTED = Arrays.asList("nms-player-ticking", "item-cache", "anti-xray-patch"); + + public BungeeConfigAPI(File configFile) { + 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; + } + + public boolean isCheckForUpdates() { + return getBoolean("checkforupdates", true); + } + + @Override + public boolean isPreventCollision() { + return getBoolean("prevent-collision", true); + } + + @Override + public boolean isNewEffectIndicator() { + return getBoolean("use-new-effect-indicator", true); + } + + @Override + public boolean isShowNewDeathMessages() { + return getBoolean("use-new-deathmessages", true); + } + + @Override + public boolean isSuppressMetadataErrors() { + return getBoolean("suppress-metadata-errors", false); + } + + @Override + public boolean isShieldBlocking() { + return getBoolean("shield-blocking", true); + } + + @Override + public boolean isHologramPatch() { + return getBoolean("hologram-patch", false); + } + + @Override + public boolean isBossbarPatch() { + return getBoolean("bossbar-patch", true); + } + + @Override + public boolean isBossbarAntiflicker() { + return getBoolean("bossbar-anti-flicker", false); + } + + @Override + public boolean isUnknownEntitiesSuppressed() { + return false; + } + + @Override + public double getHologramYOffset() { + return getDouble("hologram-y", -0.96D); + } + + @Override + public boolean isBlockBreakPatch() { + return false; + } + + @Override + public int getMaxPPS() { + return getInt("max-pps", 800); + } + + @Override + public String getMaxPPSKickMessage() { + return getString("max-pps-kick-msg", "Sending packets too fast? lag?"); + } + + @Override + public int getTrackingPeriod() { + return getInt("tracking-period", 6); + } + + @Override + public int getWarningPPS() { + return getInt("tracking-warning-pps", 120); + } + + @Override + public int getMaxWarnings() { + return getInt("tracking-max-warnings", 3); + } + + @Override + public String getMaxWarningsKickMessage() { + return getString("tracking-max-kick-msg", "You are sending too many packets, :("); + } + + @Override + public boolean isAntiXRay() { + return false; + } + + @Override + public boolean isSendSupportedVersions() { + return getBoolean("send-supported-versions", false); + } + + @Override + public boolean isStimulatePlayerTick() { + return getBoolean("simulate-pt", true); + } + + @Override + public boolean isItemCache() { + return false; + } + + @Override + public boolean isNMSPlayerTicking() { + return false; + } + + @Override + public boolean isReplacePistons() { + return getBoolean("replace-pistons", false); + } + + @Override + public int getPistonReplacementId() { + return getInt("replacement-piston-id", 0); + } + + public boolean isAutoTeam() { + // Collision has to be enabled first + return isPreventCollision() && getBoolean("auto-team", true); + } + + @Override + public boolean isForceJsonTransform() { + return getBoolean("force-json-transform", false); + } + + @Override + public List getBlockedProtocols() { + return getIntegerList("block-protocols"); + } + + @Override + public String getBlockedDisconnectMsg() { + return getString("block-disconnect-msg", "You are using an unsupported Minecraft version!"); + } + + @Override + 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/BungeeTaskId.java b/bungee/src/main/java/us/myles/ViaVersion/bungee/platform/BungeeTaskId.java new file mode 100644 index 000000000..cde0c6098 --- /dev/null +++ b/bungee/src/main/java/us/myles/ViaVersion/bungee/platform/BungeeTaskId.java @@ -0,0 +1,11 @@ +package us.myles.ViaVersion.bungee.platform; + +import lombok.AllArgsConstructor; +import lombok.Getter; +import us.myles.ViaVersion.api.platform.TaskId; + +@Getter +@AllArgsConstructor +public class BungeeTaskId implements TaskId { + private Integer object; +} diff --git a/bungee/src/main/java/us/myles/ViaVersion/bungee/platform/BungeeViaAPI.java b/bungee/src/main/java/us/myles/ViaVersion/bungee/platform/BungeeViaAPI.java new file mode 100644 index 000000000..51b7a9c3e --- /dev/null +++ b/bungee/src/main/java/us/myles/ViaVersion/bungee/platform/BungeeViaAPI.java @@ -0,0 +1,78 @@ +package us.myles.ViaVersion.bungee.platform; + +import io.netty.buffer.ByteBuf; +import lombok.NonNull; +import net.md_5.bungee.api.connection.ProxiedPlayer; +import us.myles.ViaVersion.api.Via; +import us.myles.ViaVersion.api.ViaAPI; +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.data.UserConnection; +import us.myles.ViaVersion.api.protocol.ProtocolRegistry; +import us.myles.ViaVersion.protocols.base.ProtocolInfo; + +import java.util.Map; +import java.util.SortedSet; +import java.util.TreeSet; +import java.util.UUID; + +public class BungeeViaAPI implements ViaAPI { + @Override + public int getPlayerVersion(@NonNull ProxiedPlayer player) { + if (!isPorted(player.getUniqueId())) + return ProtocolRegistry.SERVER_PROTOCOL; + return getPortedPlayers().get(player.getUniqueId()).get(ProtocolInfo.class).getProtocolVersion(); + } + + @Override + public int getPlayerVersion(@NonNull UUID uuid) { + if (!isPorted(uuid)) + return ProtocolRegistry.SERVER_PROTOCOL; + return getPortedPlayers().get(uuid).get(ProtocolInfo.class).getProtocolVersion(); + } + + @Override + public boolean isPorted(UUID playerUUID) { + return getPortedPlayers().containsKey(playerUUID); + } + + @Override + public String getVersion() { + return Via.getPlatform().getPluginVersion(); + } + + @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(ProxiedPlayer player, ByteBuf packet) throws IllegalArgumentException { + sendRawPacket(player.getUniqueId(), packet); + } + + @Override + public BossBar createBossBar(String title, BossColor color, BossStyle style) { + return new BungeeBossBar(title, 1F, color, style); + } + + @Override + public BossBar createBossBar(String title, float health, BossColor color, BossStyle style) { + return new BungeeBossBar(title, health, color, style); + } + + @Override + public SortedSet getSupportedVersions() { + SortedSet outputSet = new TreeSet<>(ProtocolRegistry.getSupportedVersions()); + outputSet.removeAll(Via.getPlatform().getConf().getBlockedProtocols()); + + return outputSet; + } + + public Map getPortedPlayers() { + return Via.getManager().getPortedPlayers(); + } +} 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 new file mode 100644 index 000000000..d8efb2627 --- /dev/null +++ b/bungee/src/main/java/us/myles/ViaVersion/bungee/platform/BungeeViaInjector.java @@ -0,0 +1,59 @@ +package us.myles.ViaVersion.bungee.platform; + +import io.netty.channel.Channel; +import io.netty.channel.ChannelInitializer; +import us.myles.ViaVersion.api.Via; +import us.myles.ViaVersion.api.platform.ViaInjector; +import us.myles.ViaVersion.bungee.handlers.BungeeChannelInitializer; +import us.myles.ViaVersion.util.ReflectionUtil; + +import java.lang.reflect.Field; +import java.lang.reflect.Modifier; +import java.util.List; + +public class BungeeViaInjector implements ViaInjector { + @Override + public void inject() throws Exception { + try { + try { + + Class pipelineUtils = Class.forName("net.md_5.bungee.netty.PipelineUtils"); + Field field = pipelineUtils.getDeclaredField("SERVER_CHILD"); + field.setAccessible(true); + // Remove any final stuff + Field modifiersField = Field.class.getDeclaredField("modifiers"); + modifiersField.setAccessible(true); + modifiersField.setInt(field, field.getModifiers() & ~Modifier.FINAL); + + BungeeChannelInitializer newInit = new BungeeChannelInitializer((ChannelInitializer) field.get(null)); + field.set(null, newInit); + } catch (NoSuchFieldException e) { + throw new Exception("Unable to find core component 'childHandler', please check your plugins. issue: "); + } + } catch (Exception e) { + Via.getPlatform().getLogger().severe("Unable to inject ViaVersion, please post these details on our GitHub and ensure you're using a compatible server version."); + throw e; + } + } + + @Override + public void uninject() { + Via.getPlatform().getLogger().severe("ViaVersion cannot remove itself from Bungee without a reboot!"); + } + + + @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); + } + + @Override + public String getEncoderName() { + return "via-encoder"; + } + + @Override + public String getDecoderName() { + return "via-decoder"; + } +} 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 new file mode 100644 index 000000000..9ba4e250e --- /dev/null +++ b/bungee/src/main/java/us/myles/ViaVersion/bungee/platform/BungeeViaLoader.java @@ -0,0 +1,34 @@ +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; +import us.myles.ViaVersion.bungee.listeners.UpdateListener; +import us.myles.ViaVersion.bungee.providers.BungeeMovementTransmitter; +import us.myles.ViaVersion.bungee.providers.BungeeVersionProvider; +import us.myles.ViaVersion.bungee.service.ProtocolDetectorService; +import us.myles.ViaVersion.protocols.base.VersionProvider; +import us.myles.ViaVersion.protocols.protocol1_9to1_8.providers.MovementTransmitterProvider; + +import java.util.concurrent.TimeUnit; + +@AllArgsConstructor +public class BungeeViaLoader implements ViaPlatformLoader { + private BungeePlugin plugin; + + @Override + public void load() { + // Listeners + ProxyServer.getInstance().getPluginManager().registerListener(plugin, plugin); + ProxyServer.getInstance().getPluginManager().registerListener(plugin, new UpdateListener()); + + // Providers + Via.getManager().getProviders().use(MovementTransmitterProvider.class, new BungeeMovementTransmitter()); + Via.getManager().getProviders().use(VersionProvider.class, new BungeeVersionProvider()); + 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/BungeeMovementTransmitter.java b/bungee/src/main/java/us/myles/ViaVersion/bungee/providers/BungeeMovementTransmitter.java new file mode 100644 index 000000000..7f1d37206 --- /dev/null +++ b/bungee/src/main/java/us/myles/ViaVersion/bungee/providers/BungeeMovementTransmitter.java @@ -0,0 +1,34 @@ +package us.myles.ViaVersion.bungee.providers; + +import us.myles.ViaVersion.api.PacketWrapper; +import us.myles.ViaVersion.api.data.UserConnection; +import us.myles.ViaVersion.api.type.Type; +import us.myles.ViaVersion.packets.State; +import us.myles.ViaVersion.protocols.base.ProtocolInfo; +import us.myles.ViaVersion.protocols.protocol1_9to1_8.providers.MovementTransmitterProvider; +import us.myles.ViaVersion.protocols.protocol1_9to1_8.storage.MovementTracker; + +public class BungeeMovementTransmitter extends MovementTransmitterProvider { + @Override + public Object getFlyingPacket() { + return null; + } + + @Override + public Object getGroundPacket() { + return null; + } + + public void sendPlayer(UserConnection userConnection) { + if (userConnection.get(ProtocolInfo.class).getState() == State.PLAY) { + PacketWrapper wrapper = new PacketWrapper(0x03, null, userConnection); + wrapper.write(Type.BOOLEAN, userConnection.get(MovementTracker.class).isGround()); + try { + wrapper.sendToServer(); + } catch (Exception e) { + e.printStackTrace(); + } + // PlayerPackets will increment idle + } + } +} 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 new file mode 100644 index 000000000..3dc9be3a1 --- /dev/null +++ b/bungee/src/main/java/us/myles/ViaVersion/bungee/providers/BungeeVersionProvider.java @@ -0,0 +1,65 @@ +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; +import us.myles.ViaVersion.util.ReflectionUtil; + +import java.util.List; + +public class BungeeVersionProvider extends VersionProvider { + private static Class ref; + + static { + try { + ref = Class.forName("net.md_5.bungee.protocol.ProtocolConstants"); + } catch (Exception e) { + System.out.println("Could not detect the ProtocolConstants class"); + e.printStackTrace(); + } + } + + @Override + public int getServerProtocol(UserConnection user) throws Exception { + if (ref == null) + return super.getServerProtocol(user); + // TODO Have one constant list forever until restart? (Might limit plugins if they change this) + List list = ReflectionUtil.getStatic(ref, "SUPPORTED_VERSION_IDS", List.class); + + ProtocolInfo info = user.get(ProtocolInfo.class); + + // Bungee supports it + if (list.contains(info.getProtocolVersion())) + return info.getProtocolVersion(); + + // Older than bungee supports, get the lowest version + if (info.getProtocolVersion() < list.get(0)) { + return getLowestSupportedVersion(); + } + + // Loop through all protocols to get the closest protocol id that bungee supports + for (Integer protocol : Lists.reverse(list)) { + if (info.getProtocolVersion() > protocol) + return protocol; + } + + 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 new file mode 100644 index 000000000..f883e82aa --- /dev/null +++ b/bungee/src/main/java/us/myles/ViaVersion/bungee/service/ProtocolDetectorService.java @@ -0,0 +1,82 @@ +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 detectedProtocolIds = new ConcurrentHashMap<>(); + private BungeePlugin plugin; + @Getter + private static ProtocolDetectorService instance; + + public ProtocolDetectorService(BungeePlugin plugin) { + this.plugin = plugin; + instance = this; + } + + public static Integer getProtocolId(String 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 + public void run() { + for (final Map.Entry lists : plugin.getProxy().getServers().entrySet()) { + updateProtocolInfo(lists.getKey(), lists.getValue()); + } + } + + private void updateProtocolInfo(final String key, ServerInfo value) { + value.ping(new Callback() { + @Override + public void done(ServerPing serverPing, Throwable throwable) { + 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 getDetectedIds() { + return new HashMap<>(detectedProtocolIds); + } + +} diff --git a/bungee/src/main/java/us/myles/ViaVersion/bungee/storage/BungeeStorage.java b/bungee/src/main/java/us/myles/ViaVersion/bungee/storage/BungeeStorage.java new file mode 100644 index 000000000..683b8230d --- /dev/null +++ b/bungee/src/main/java/us/myles/ViaVersion/bungee/storage/BungeeStorage.java @@ -0,0 +1,20 @@ +package us.myles.ViaVersion.bungee.storage; + +import lombok.Data; +import lombok.EqualsAndHashCode; +import net.md_5.bungee.api.connection.ProxiedPlayer; +import us.myles.ViaVersion.api.data.StoredObject; +import us.myles.ViaVersion.api.data.UserConnection; + +@Data +@EqualsAndHashCode(callSuper = true) +public class BungeeStorage extends StoredObject { + private ProxiedPlayer player; + private String currentServer; + + public BungeeStorage(UserConnection user, ProxiedPlayer player) { + super(user); + this.player = player; + this.currentServer = ""; + } +} diff --git a/bungee/src/main/java/us/myles/ViaVersion/bungee/util/BungeePipelineUtil.java b/bungee/src/main/java/us/myles/ViaVersion/bungee/util/BungeePipelineUtil.java new file mode 100644 index 000000000..5d81f876a --- /dev/null +++ b/bungee/src/main/java/us/myles/ViaVersion/bungee/util/BungeePipelineUtil.java @@ -0,0 +1,71 @@ +package us.myles.ViaVersion.bungee.util; + +import io.netty.buffer.ByteBuf; +import io.netty.channel.ChannelHandlerContext; +import io.netty.handler.codec.MessageToByteEncoder; +import io.netty.handler.codec.MessageToMessageDecoder; + +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; +import java.util.ArrayList; +import java.util.List; + +public class BungeePipelineUtil { + private static Method DECODE_METHOD; + private static Method ENCODE_METHOD; + + static { + try { + DECODE_METHOD = MessageToMessageDecoder.class.getDeclaredMethod("decode", ChannelHandlerContext.class, Object.class, List.class); + DECODE_METHOD.setAccessible(true); + } catch (NoSuchMethodException e) { + e.printStackTrace(); + System.out.println("Netty issue?"); + } + try { + ENCODE_METHOD = MessageToByteEncoder.class.getDeclaredMethod("encode", ChannelHandlerContext.class, Object.class, ByteBuf.class); + ENCODE_METHOD.setAccessible(true); + } catch (NoSuchMethodException e) { + e.printStackTrace(); + System.out.println("Netty issue?"); + } + } + + public static List callDecode(MessageToMessageDecoder decoder, ChannelHandlerContext ctx, ByteBuf input) throws InvocationTargetException { + List output = new ArrayList<>(); + try { + BungeePipelineUtil.DECODE_METHOD.invoke(decoder, ctx, input, output); + } catch (IllegalAccessException e) { + e.printStackTrace(); + } + return output; + } + + public static ByteBuf callEncode(MessageToByteEncoder encoder, ChannelHandlerContext ctx, ByteBuf input) throws InvocationTargetException { + ByteBuf output = ctx.alloc().buffer(); + try { + BungeePipelineUtil.ENCODE_METHOD.invoke(encoder, ctx, input, output); + } catch (IllegalAccessException e) { + e.printStackTrace(); + } + return output; + } + + public static ByteBuf decompress(ChannelHandlerContext ctx, ByteBuf bytebuf) { + try { + return (ByteBuf) callDecode((MessageToMessageDecoder) ctx.pipeline().get("decompress"), ctx.pipeline().context("decompress"), bytebuf).get(0); + } catch (InvocationTargetException e) { + e.printStackTrace(); + return ctx.alloc().buffer(); + } + } + + public static ByteBuf compress(ChannelHandlerContext ctx, ByteBuf bytebuf) { + try { + return callEncode((MessageToByteEncoder) ctx.pipeline().get("compress"), ctx.pipeline().context("compress"), bytebuf); + } catch (InvocationTargetException e) { + e.printStackTrace(); + return ctx.alloc().buffer(); + } + } +} diff --git a/bungee/src/main/resources/bungee.yml b/bungee/src/main/resources/bungee.yml new file mode 100644 index 000000000..37b6dc108 --- /dev/null +++ b/bungee/src/main/resources/bungee.yml @@ -0,0 +1,4 @@ +name: ViaVersion +main: us.myles.ViaVersion.BungeePlugin +author: _MylesC, Matsv +version: ${project.version} \ No newline at end of file diff --git a/common/pom.xml b/common/pom.xml new file mode 100644 index 000000000..fa13a94c6 --- /dev/null +++ b/common/pom.xml @@ -0,0 +1,24 @@ + + + + viaversion-parent + us.myles + 1.0.0-ALPHA-modules + + + 4.0.0 + + viaversion-common + + + + + org.yaml + snakeyaml + 1.18-SNAPSHOT + provided + + + \ No newline at end of file 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..60a9254aa --- /dev/null +++ b/common/src/main/java/us/myles/ViaVersion/ViaManager.java @@ -0,0 +1,117 @@ +package us.myles.ViaVersion; + +import lombok.Builder; +import lombok.Getter; +import lombok.Setter; +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.platform.ViaPlatformLoader; +import us.myles.ViaVersion.api.platform.providers.ViaProviders; +import us.myles.ViaVersion.api.protocol.ProtocolRegistry; +import us.myles.ViaVersion.api.protocol.ProtocolVersion; +import us.myles.ViaVersion.commands.ViaCommandHandler; +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 final Map portedPlayers = new ConcurrentHashMap<>(); + private ViaPlatform platform; + private ViaProviders providers = new ViaProviders(); + @Setter + private boolean debug = false; + // Internals + private ViaInjector injector; + private ViaCommandHandler commandHandler; + private ViaPlatformLoader loader; + + @Builder + public ViaManager(ViaPlatform platform, ViaInjector injector, ViaCommandHandler commandHandler, ViaPlatformLoader loader) { + this.platform = platform; + this.injector = injector; + this.commandHandler = commandHandler; + this.loader = loader; + } + + public void init() { + if (System.getProperty("ViaVersion") != null) { + // Reload? + platform.onReload(); + } + // Check for updates + if (platform.getConf().isCheckForUpdates()) + UpdateUtil.sendUpdateMessage(); + // Inject + try { + injector.inject(); + } catch (Exception e) { + getPlatform().getLogger().severe("ViaVersion failed to inject:"); + e.printStackTrace(); + return; + } + // Mark as injected + System.setProperty("ViaVersion", getPlatform().getPluginVersion()); + // If successful + platform.runSync(new Runnable() { + @Override + public void run() { + onServerLoaded(); + } + }); + + } + + public void onServerLoaded() { + // Load Server Protocol + try { + ProtocolRegistry.SERVER_PROTOCOL = injector.getServerProtocolVersion(); + } catch (Exception e) { + getPlatform().getLogger().severe("ViaVersion failed to get the server protocol!"); + e.printStackTrace(); + } + // 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."); + } + } + // Load Listeners / Tasks + ProtocolRegistry.onServerLoaded(); + + // Load Platform + loader.load(); + + // Refresh Versions + ProtocolRegistry.refreshVersions(); + } + + public void destroy() { + // Uninject + getPlatform().getLogger().info("ViaVersion is disabling, if this is a reload and you experience issues consider rebooting."); + try { + injector.uninject(); + } catch (Exception e) { + getPlatform().getLogger().severe("ViaVersion failed to uninject:"); + e.printStackTrace(); + } + } + + 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/src/main/java/us/myles/ViaVersion/api/PacketWrapper.java b/common/src/main/java/us/myles/ViaVersion/api/PacketWrapper.java similarity index 96% rename from src/main/java/us/myles/ViaVersion/api/PacketWrapper.java rename to common/src/main/java/us/myles/ViaVersion/api/PacketWrapper.java index 18d631225..7d4f7730d 100644 --- a/src/main/java/us/myles/ViaVersion/api/PacketWrapper.java +++ b/common/src/main/java/us/myles/ViaVersion/api/PacketWrapper.java @@ -12,11 +12,9 @@ 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; -import us.myles.ViaVersion.util.PipelineUtil; import java.io.IOException; import java.util.ArrayList; @@ -25,14 +23,16 @@ import java.util.LinkedList; import java.util.List; public class PacketWrapper { + public static final int PASSTHROUGH_ID = 1000; + private final ByteBuf inputBuffer; private final UserConnection userConnection; private boolean send = true; @Setter @Getter private int id = -1; - private LinkedList> readableObjects = new LinkedList<>(); - private List> packetValues = new ArrayList<>(); + private final LinkedList> readableObjects = new LinkedList<>(); + private final List> packetValues = new ArrayList<>(); public PacketWrapper(int packetID, ByteBuf inputBuffer, UserConnection userConnection) { this.id = packetID; @@ -357,7 +357,7 @@ public class PacketWrapper { * Be careful not to send packets twice. * (Sends it after current) *
- * This method is no longer used, it's favoured to use send(Protocol) as it will handle the pipeline properly. + * This method is no longer used, it's favoured to use {@link #send(Class)} as it will handle the pipeline properly. * * @throws Exception if it fails to write */ @@ -403,7 +403,7 @@ public class PacketWrapper { * @param index The index to start from * @param pipeline The pipeline * @return The current packetwrapper - * @throws Exception + * @throws Exception If it fails to transform a packet, exception will be thrown */ public PacketWrapper apply(Direction direction, State state, int index, List pipeline) throws Exception { for (int i = index; i < pipeline.size(); i++) { // Copy to prevent from removal. @@ -454,18 +454,16 @@ public class PacketWrapper { /** * Send the current packet to the server. - * (Ensure the ID is suitable for the server version) + * (Ensure the ID is suitable for viaversion) * * @throws Exception If it failed to write */ 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 - writeToBuffer(output); - PipelineUtil.getContextBefore("decompress", user().getChannel().pipeline()).fireChannelRead(output); + user().getChannel().pipeline().context(Via.getManager().getInjector().getDecoderName()).fireChannelRead(output); } } diff --git a/src/main/java/us/myles/ViaVersion/api/Pair.java b/common/src/main/java/us/myles/ViaVersion/api/Pair.java similarity index 100% rename from src/main/java/us/myles/ViaVersion/api/Pair.java rename to common/src/main/java/us/myles/ViaVersion/api/Pair.java diff --git a/common/src/main/java/us/myles/ViaVersion/api/Via.java b/common/src/main/java/us/myles/ViaVersion/api/Via.java new file mode 100644 index 000000000..6339ef84e --- /dev/null +++ b/common/src/main/java/us/myles/ViaVersion/api/Via.java @@ -0,0 +1,45 @@ +package us.myles.ViaVersion.api; + +import com.google.common.base.Preconditions; +import lombok.Getter; +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; + + /** + * Register the ViaManager associated with the platform. + * + * @param viaManager The ViaManager + */ + public static void init(ViaManager viaManager) { + Preconditions.checkArgument(manager == null, "ViaManager is already set"); + + Via.platform = viaManager.getPlatform(); + Via.manager = viaManager; + } + + /** + * Get the API associated with the current platform. + * + * @return API instance + */ + public static ViaAPI getAPI() { + Preconditions.checkArgument(platform != null, "ViaVersion has not loaded the Platform"); + return Via.platform.getApi(); + } + + /** + * Get the config associated with the current platform. + * + * @return Config instance + */ + public static ViaVersionConfig getConfig() { + Preconditions.checkArgument(platform != null, "ViaVersion has not loaded the Platform"); + return Via.platform.getConf(); + } +} 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..39d58bf01 --- /dev/null +++ b/common/src/main/java/us/myles/ViaVersion/api/ViaAPI.java @@ -0,0 +1,99 @@ +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.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/ViaListener.java b/common/src/main/java/us/myles/ViaVersion/api/ViaListener.java new file mode 100644 index 000000000..243a00212 --- /dev/null +++ b/common/src/main/java/us/myles/ViaVersion/api/ViaListener.java @@ -0,0 +1,43 @@ +package us.myles.ViaVersion.api; + +import lombok.*; +import us.myles.ViaVersion.api.data.UserConnection; +import us.myles.ViaVersion.api.protocol.Protocol; +import us.myles.ViaVersion.protocols.base.ProtocolInfo; + +import java.util.UUID; + +@Getter(AccessLevel.PROTECTED) +@Setter(AccessLevel.PROTECTED) +@RequiredArgsConstructor +public abstract class ViaListener { + private final Class requiredPipeline; + private boolean registered = false; + + /** + * Get the UserConnection from an UUID + * + * @param uuid UUID object + * @return The UserConnection + */ + protected UserConnection getUserConnection(@NonNull UUID uuid) { + return Via.getManager().getConnection(uuid); + } + + /** + * Checks if the UUID is on the selected pipe + * + * @param uuid UUID Object + * @return True if on pipe + */ + protected boolean isOnPipe(UUID uuid) { + UserConnection userConnection = getUserConnection(uuid); + return userConnection != null && + userConnection.get(ProtocolInfo.class).getPipeline().contains(requiredPipeline); + } + + /** + * Register the event + */ + public abstract void register(); +} diff --git a/src/main/java/us/myles/ViaVersion/api/ViaVersionConfig.java b/common/src/main/java/us/myles/ViaVersion/api/ViaVersionConfig.java similarity index 100% rename from src/main/java/us/myles/ViaVersion/api/ViaVersionConfig.java rename to common/src/main/java/us/myles/ViaVersion/api/ViaVersionConfig.java diff --git a/src/main/java/us/myles/ViaVersion/api/boss/BossBar.java b/common/src/main/java/us/myles/ViaVersion/api/boss/BossBar.java similarity index 53% rename from src/main/java/us/myles/ViaVersion/api/boss/BossBar.java rename to common/src/main/java/us/myles/ViaVersion/api/boss/BossBar.java index fe9d20489..76737c23b 100644 --- a/src/main/java/us/myles/ViaVersion/api/boss/BossBar.java +++ b/common/src/main/java/us/myles/ViaVersion/api/boss/BossBar.java @@ -1,17 +1,17 @@ package us.myles.ViaVersion.api.boss; -import org.bukkit.entity.Player; +import us.myles.ViaVersion.api.Via; import java.util.Set; import java.util.UUID; -public interface BossBar { +public abstract class BossBar { /** * Get the current title * * @return the title */ - String getTitle(); + public abstract String getTitle(); /** * Change the title @@ -19,14 +19,14 @@ public interface BossBar { * @param title Title can be in either JSON or just text * @return The BossBar object */ - BossBar setTitle(String title); + public abstract BossBar setTitle(String title); /** * Get the health * * @return float between 0F - 1F */ - float getHealth(); + public abstract float getHealth(); /** * Change the health @@ -34,14 +34,14 @@ public interface BossBar { * @param health this float has to be between 0F - 1F * @return The BossBar object */ - BossBar setHealth(float health); + public abstract BossBar setHealth(float health); /** * Get the bossbar color * * @return The colour */ - BossColor getColor(); + public abstract BossColor getColor(); /** * Yay colors! @@ -49,14 +49,14 @@ public interface BossBar { * @param color Whatever color you want! * @return The BossBar object */ - BossBar setColor(BossColor color); + public abstract BossBar setColor(BossColor color); /** * Get the bosbar style * * @return BossStyle */ - BossStyle getStyle(); + public abstract BossStyle getStyle(); /** * Change the bosbar style @@ -64,15 +64,19 @@ public interface BossBar { * @param style BossStyle * @return The BossBar object */ - BossBar setStyle(BossStyle style); + public abstract BossBar setStyle(BossStyle style); /** * Show the bossbar to a player. * * @param player The player * @return The BossBar object + * @deprecated Deprecated use UUID's instead of Player objects {@link #addPlayer(UUID)} */ - BossBar addPlayer(Player player); + @Deprecated + public BossBar addPlayer(T player) { + throw new UnsupportedOperationException("This method is not implemented for the platform " + Via.getPlatform().getPlatformName()); + } /** * Show the bossbar to a player (uuid) @@ -80,23 +84,39 @@ public interface BossBar { * @param player uuid of the player * @return The BossBar object */ - BossBar addPlayer(UUID player); + public abstract BossBar addPlayer(UUID player); /** * add multiple players * * @param players list of players * @return The BossBar object + * @deprecated Deprecated use UUID's instead of Player objects {@link #addPlayer(UUID)} */ - BossBar addPlayers(Player... players); + @Deprecated + public BossBar addPlayers(T... players) { + throw new UnsupportedOperationException("This method is not implemented for the platform " + Via.getPlatform().getPlatformName()); + } /** * Remove the bossbar from a player * * @param player The player * @return The BossBar object + * @deprecated Deprecated use UUID's instead of Player objects {@link #removePlayer(UUID)} */ - BossBar removePlayer(Player player); + @Deprecated + public BossBar removePlayer(T player) { + throw new UnsupportedOperationException("This method is not implemented for the platform " + Via.getPlatform().getPlatformName()); + } + + /** + * Removes the bossbar from a player + * + * @param uuid The platers YYUD + * @return The BossBar object + */ + public abstract BossBar removePlayer(UUID uuid); /** * Add flags @@ -104,7 +124,7 @@ public interface BossBar { * @param flag The flag to add * @return The BossBar object */ - BossBar addFlag(BossFlag flag); + public abstract BossBar addFlag(BossFlag flag); /** * Remove flags. @@ -112,39 +132,39 @@ public interface BossBar { * @param flag The flag to remove * @return The BossBar object */ - BossBar removeFlag(BossFlag flag); + public abstract BossBar removeFlag(BossFlag flag); /** * @param flag The flag to check against * @return True if it has the flag */ - boolean hasFlag(BossFlag flag); + public abstract boolean hasFlag(BossFlag flag); /** * Get players * * @return UUIDS from players (sorry I lied) */ - Set getPlayers(); + public abstract Set getPlayers(); /** * Show the bossbar to everyone (In the getPlayer set) * * @return The BossBar object */ - BossBar show(); + public abstract BossBar show(); /** * Hide the bossbar from everyone (In the getPlayer set) * * @return The BossBar object */ - BossBar hide(); + public abstract BossBar hide(); /** * Is it visible? * * @return visibility changable with show() and hide() */ - boolean isVisible(); + public abstract boolean isVisible(); } diff --git a/src/main/java/us/myles/ViaVersion/api/boss/BossColor.java b/common/src/main/java/us/myles/ViaVersion/api/boss/BossColor.java similarity index 100% rename from src/main/java/us/myles/ViaVersion/api/boss/BossColor.java rename to common/src/main/java/us/myles/ViaVersion/api/boss/BossColor.java diff --git a/src/main/java/us/myles/ViaVersion/api/boss/BossFlag.java b/common/src/main/java/us/myles/ViaVersion/api/boss/BossFlag.java similarity index 100% rename from src/main/java/us/myles/ViaVersion/api/boss/BossFlag.java rename to common/src/main/java/us/myles/ViaVersion/api/boss/BossFlag.java diff --git a/src/main/java/us/myles/ViaVersion/api/boss/BossStyle.java b/common/src/main/java/us/myles/ViaVersion/api/boss/BossStyle.java similarity index 100% rename from src/main/java/us/myles/ViaVersion/api/boss/BossStyle.java rename to common/src/main/java/us/myles/ViaVersion/api/boss/BossStyle.java diff --git a/common/src/main/java/us/myles/ViaVersion/api/command/ViaCommandSender.java b/common/src/main/java/us/myles/ViaVersion/api/command/ViaCommandSender.java new file mode 100644 index 000000000..78cf19f7a --- /dev/null +++ b/common/src/main/java/us/myles/ViaVersion/api/command/ViaCommandSender.java @@ -0,0 +1,34 @@ +package us.myles.ViaVersion.api.command; + +import java.util.UUID; + +public interface ViaCommandSender { + /** + * Check if the sender has a permission. + * + * @param permission Permission string eg. viaversion.admin + * @return True if the sender has the permission + */ + boolean hasPermission(String permission); + + /** + * Send a message to the sender + * + * @param msg The message to send + */ + void sendMessage(String msg); + + /** + * Get the senders UUID. + * + * @return The senders UUID + */ + UUID getUUID(); + + /** + * Get the senders name. + * + * @return The senders name + */ + String getName(); +} diff --git a/src/main/java/us/myles/ViaVersion/api/command/ViaSubCommand.java b/common/src/main/java/us/myles/ViaVersion/api/command/ViaSubCommand.java similarity index 70% rename from src/main/java/us/myles/ViaVersion/api/command/ViaSubCommand.java rename to common/src/main/java/us/myles/ViaVersion/api/command/ViaSubCommand.java index 000b97d6e..0c206fd10 100644 --- a/src/main/java/us/myles/ViaVersion/api/command/ViaSubCommand.java +++ b/common/src/main/java/us/myles/ViaVersion/api/command/ViaSubCommand.java @@ -1,6 +1,5 @@ package us.myles.ViaVersion.api.command; -import org.bukkit.command.CommandSender; import us.myles.ViaVersion.commands.ViaCommandHandler; import java.util.Collections; @@ -10,14 +9,14 @@ public abstract class ViaSubCommand { /** * Subcommand name * - * @return The command name + * @return The commands name */ public abstract String name(); /** * subcommand description, this'll show in /viaversion list * - * @return The command description + * @return The commands description */ public abstract String description(); @@ -25,7 +24,7 @@ public abstract class ViaSubCommand { * Usage example: * "playerversion [name]" * - * @return The command usage + * @return The commands usage */ public String usage() { return name(); @@ -34,7 +33,7 @@ public abstract class ViaSubCommand { /** * Permission, null for everyone * - * @return The permission required to use the command + * @return The permission required to use the commands */ public String permission() { return "viaversion.admin"; @@ -45,9 +44,9 @@ public abstract class ViaSubCommand { * * @param sender Command sender * @param args Arguments - * @return command executed succesfully if false, show usage + * @return commands executed succesfully if false, show usage */ - public abstract boolean execute(CommandSender sender, String[] args); + public abstract boolean execute(ViaCommandSender sender, String[] args); /** * Yay, possibility to implement tab-completion @@ -56,7 +55,7 @@ public abstract class ViaSubCommand { * @param args args * @return tab complete possibilities */ - public List onTabComplete(CommandSender sender, String[] args) { + public List onTabComplete(ViaCommandSender sender, String[] args) { return Collections.emptyList(); } @@ -67,11 +66,11 @@ public abstract class ViaSubCommand { /** * Send message formatted / colored * - * @param sender command sender + * @param sender commands sender * @param message string message * @param args optional objects */ - public void sendMessage(CommandSender sender, String message, Object... args) { + public void sendMessage(ViaCommandSender sender, String message, Object... args) { ViaCommandHandler.sendMessage(sender, message, args); } } diff --git a/src/main/java/us/myles/ViaVersion/api/command/ViaVersionCommand.java b/common/src/main/java/us/myles/ViaVersion/api/command/ViaVersionCommand.java similarity index 59% rename from src/main/java/us/myles/ViaVersion/api/command/ViaVersionCommand.java rename to common/src/main/java/us/myles/ViaVersion/api/command/ViaVersionCommand.java index 707cac6b7..c60037af0 100644 --- a/src/main/java/us/myles/ViaVersion/api/command/ViaVersionCommand.java +++ b/common/src/main/java/us/myles/ViaVersion/api/command/ViaVersionCommand.java @@ -1,5 +1,7 @@ package us.myles.ViaVersion.api.command; +import java.util.List; + public interface ViaVersionCommand { /** * Register your own subcommand inside ViaVersion @@ -24,4 +26,22 @@ public interface ViaVersionCommand { * @return ViaSubCommand instance */ ViaSubCommand getSubCommand(String name); + + /** + * Executed when the Command sender executes the commands + * + * @param sender Sender object + * @param args arguments provided + * @return was successful + */ + boolean onCommand(ViaCommandSender sender, String[] args); + + /** + * Executed when the Command sender tab-completes + * + * @param sender Sender object + * @param args arguments provided + * @return was successful + */ + List onTabComplete(ViaCommandSender sender, String[] args); } diff --git a/common/src/main/java/us/myles/ViaVersion/api/configuration/ConfigurationProvider.java b/common/src/main/java/us/myles/ViaVersion/api/configuration/ConfigurationProvider.java new file mode 100644 index 000000000..1566598eb --- /dev/null +++ b/common/src/main/java/us/myles/ViaVersion/api/configuration/ConfigurationProvider.java @@ -0,0 +1,31 @@ +package us.myles.ViaVersion.api.configuration; + +import java.util.Map; + +public interface ConfigurationProvider { + + /** + * Sets the specified path to the given value. + * + * @param path Path of the object to set. + * @param value New value to set the path to + */ + void set(String path, Object value); + + /** + * Saves the config + */ + void saveConfig(); + + /** + * Reloads the config + */ + void reloadConfig(); + + /** + * Get all the configuration values + * + * @return Map with key->values + */ + Map getValues(); +} diff --git a/src/main/java/us/myles/ViaVersion/api/data/StoredObject.java b/common/src/main/java/us/myles/ViaVersion/api/data/StoredObject.java similarity index 100% rename from src/main/java/us/myles/ViaVersion/api/data/StoredObject.java rename to common/src/main/java/us/myles/ViaVersion/api/data/StoredObject.java diff --git a/src/main/java/us/myles/ViaVersion/api/data/UserConnection.java b/common/src/main/java/us/myles/ViaVersion/api/data/UserConnection.java similarity index 67% rename from src/main/java/us/myles/ViaVersion/api/data/UserConnection.java rename to common/src/main/java/us/myles/ViaVersion/api/data/UserConnection.java index 28ddac8c1..f6cb5d4f8 100644 --- a/src/main/java/us/myles/ViaVersion/api/data/UserConnection.java +++ b/common/src/main/java/us/myles/ViaVersion/api/data/UserConnection.java @@ -5,9 +5,9 @@ import io.netty.channel.ChannelFuture; import io.netty.channel.ChannelHandler; import io.netty.channel.socket.SocketChannel; import lombok.Data; -import org.bukkit.Bukkit; -import org.bukkit.ChatColor; -import org.bukkit.entity.Player; +import net.md_5.bungee.api.ChatColor; +import us.myles.ViaVersion.api.Via; +import us.myles.ViaVersion.api.ViaVersionConfig; import us.myles.ViaVersion.protocols.base.ProtocolInfo; import java.util.Map; @@ -66,6 +66,14 @@ public class UserConnection { storedObjects.put(object.getClass(), object); } + /** + * Clear all the stored objects + * Used for bungee when switching servers. + */ + public void clearStoredObjects() { + storedObjects.clear(); + } + /** * Send a raw packet to the player * @@ -73,7 +81,7 @@ public class UserConnection { * @param currentThread Should it run in the same thread */ public void sendRawPacket(final ByteBuf packet, boolean currentThread) { - final ChannelHandler handler = channel.pipeline().get("encoder"); + final ChannelHandler handler = channel.pipeline().get(Via.getManager().getInjector().getEncoderName()); if (currentThread) { channel.pipeline().context(handler).writeAndFlush(packet); } else { @@ -93,7 +101,7 @@ public class UserConnection { * @return ChannelFuture of the packet being sent */ public ChannelFuture sendRawPacketFuture(final ByteBuf packet) { - final ChannelHandler handler = channel.pipeline().get("encoder"); + final ChannelHandler handler = channel.pipeline().get(Via.getManager().getInjector().getEncoderName()); return channel.pipeline().context(handler).writeAndFlush(packet); } @@ -134,6 +142,37 @@ public class UserConnection { return false; } + public boolean handlePPS() { + ViaVersionConfig conf = Via.getConfig(); + // Max PPS Checker + if (conf.getMaxPPS() > 0) { + if (getPacketsPerSecond() >= conf.getMaxPPS()) { + disconnect(conf.getMaxPPSKickMessage().replace("%pps", ((Long) getPacketsPerSecond()).intValue() + "")); + return true; // don't send current packet + } + } + + // Tracking PPS Checker + if (conf.getMaxWarnings() > 0 && conf.getTrackingPeriod() > 0) { + if (getSecondsObserved() > conf.getTrackingPeriod()) { + // Reset + setWarnings(0); + setSecondsObserved(1); + } else { + setSecondsObserved(getSecondsObserved() + 1); + if (getPacketsPerSecond() >= conf.getWarningPPS()) { + setWarnings(getWarnings() + 1); + } + + if (getWarnings() >= conf.getMaxWarnings()) { + disconnect(conf.getMaxWarningsKickMessage().replace("%pps", ((Long) getPacketsPerSecond()).intValue() + "")); + return true; // don't send current packet + } + } + } + return false; + } + /** * Disconnect a connection * @@ -145,18 +184,15 @@ public class UserConnection { pendingDisconnect = true; if (get(ProtocolInfo.class).getUuid() != null) { final UUID uuid = get(ProtocolInfo.class).getUuid(); - if (Bukkit.getPlayer(uuid) != null) { - Bukkit.getScheduler().runTask(Bukkit.getPluginManager().getPlugin("ViaVersion"), new Runnable() { - @Override - public void run() { - Player player = Bukkit.getPlayer(uuid); - if (player != null) - player.kickPlayer(ChatColor.translateAlternateColorCodes('&', reason)); + Via.getPlatform().runSync(new Runnable() { + @Override + public void run() { + if (!Via.getPlatform().kickPlayer(uuid, ChatColor.translateAlternateColorCodes('&', reason))) { + getChannel().close(); // =) } - }); - return; - } + } + }); } - getChannel().close(); // =) + } } diff --git a/common/src/main/java/us/myles/ViaVersion/api/entities/Entity1_10Types.java b/common/src/main/java/us/myles/ViaVersion/api/entities/Entity1_10Types.java new file mode 100644 index 000000000..5eb990872 --- /dev/null +++ b/common/src/main/java/us/myles/ViaVersion/api/entities/Entity1_10Types.java @@ -0,0 +1,187 @@ +package us.myles.ViaVersion.api.entities; + +import com.google.common.base.Optional; +import lombok.AllArgsConstructor; +import lombok.Getter; +import us.myles.ViaVersion.api.Via; + +// 1.10 Entity / Object ids +public class Entity1_10Types { + + public static EntityType getTypeFromId(int typeID, boolean isObject) { + Optional type; + + if (isObject) + type = ObjectTypes.getPCEntity(typeID); + else + type = EntityType.findById(typeID); + + if (!type.isPresent()) { + Via.getPlatform().getLogger().severe("Could not find type id " + typeID + " isObject=" + isObject); + return EntityType.ENTITY; // Fall back to the basic ENTITY + } + + return type.get(); + } + + @AllArgsConstructor + @Getter + public enum EntityType { + ENTITY(-1), + DROPPED_ITEM(1, EntityType.ENTITY), + EXPERIENCE_ORB(2, EntityType.ENTITY), + LEASH_HITCH(8, EntityType.ENTITY), // Actually entity hanging but it doesn't make a lot of difference for metadata + PAINTING(9, EntityType.ENTITY), // Actually entity hanging but it doesn't make a lot of difference for metadata + ARROW(10, EntityType.ENTITY), + SNOWBALL(11, EntityType.ENTITY), // Actually EntityProjectile + FIREBALL(12, EntityType.ENTITY), + SMALL_FIREBALL(13, EntityType.ENTITY), + ENDER_PEARL(14, EntityType.ENTITY), // Actually EntityProjectile + ENDER_SIGNAL(15, EntityType.ENTITY), + THROWN_EXP_BOTTLE(17, EntityType.ENTITY), + ITEM_FRAME(18, EntityType.ENTITY), // Actually EntityHanging + WITHER_SKULL(19, EntityType.ENTITY), + PRIMED_TNT(20, EntityType.ENTITY), + FALLING_BLOCK(21, EntityType.ENTITY), + FIREWORK(22, EntityType.ENTITY), + TIPPED_ARROW(23, EntityType.ARROW), + SPECTRAL_ARROW(24, EntityType.ARROW), + SHULKER_BULLET(25, EntityType.ENTITY), + DRAGON_FIREBALL(26, EntityType.FIREBALL), + + ENTITY_LIVING(-1, ENTITY), + ENTITY_INSENTIENT(-1, ENTITY_LIVING), + ENTITY_AGEABLE(-1, ENTITY_INSENTIENT), + ENTITY_TAMEABLE_ANIMAL(-1, ENTITY_AGEABLE), + ENTITY_HUMAN(-1, ENTITY_LIVING), + + ARMOR_STAND(30, EntityType.ENTITY_LIVING), + + // Vehicles + MINECART_ABSTRACT(-1, ENTITY), + MINECART_COMMAND(40, MINECART_ABSTRACT), + BOAT(41, ENTITY), + MINECART_RIDEABLE(42, MINECART_ABSTRACT), + MINECART_CHEST(43, MINECART_ABSTRACT), + MINECART_FURNACE(44, MINECART_ABSTRACT), + MINECART_TNT(45, MINECART_ABSTRACT), + MINECART_HOPPER(46, MINECART_ABSTRACT), + MINECART_MOB_SPAWNER(47, MINECART_ABSTRACT), + + CREEPER(50, ENTITY_INSENTIENT), + SKELETON(51, ENTITY_INSENTIENT), + SPIDER(52, ENTITY_INSENTIENT), + GIANT(53, ENTITY_INSENTIENT), + ZOMBIE(54, ENTITY_INSENTIENT), + SLIME(55, ENTITY_INSENTIENT), + GHAST(56, ENTITY_INSENTIENT), + PIG_ZOMBIE(57, ZOMBIE), + ENDERMAN(58, ENTITY_INSENTIENT), + CAVE_SPIDER(59, SPIDER), + SILVERFISH(60, ENTITY_INSENTIENT), + BLAZE(61, ENTITY_INSENTIENT), + MAGMA_CUBE(62, SLIME), + ENDER_DRAGON(63, ENTITY_INSENTIENT), + WITHER(64, ENTITY_INSENTIENT), + BAT(65, ENTITY_INSENTIENT), + WITCH(66, ENTITY_INSENTIENT), + ENDERMITE(67, ENTITY_INSENTIENT), + GUARDIAN(68, ENTITY_INSENTIENT), + IRON_GOLEM(99, ENTITY_INSENTIENT), // moved up to avoid illegal forward references + SHULKER(69, EntityType.IRON_GOLEM), + PIG(90, ENTITY_AGEABLE), + SHEEP(91, ENTITY_AGEABLE), + COW(92, ENTITY_AGEABLE), + CHICKEN(93, ENTITY_AGEABLE), + SQUID(94, ENTITY_INSENTIENT), + WOLF(95, ENTITY_TAMEABLE_ANIMAL), + MUSHROOM_COW(96, COW), + SNOWMAN(97, EntityType.IRON_GOLEM), + OCELOT(98, ENTITY_TAMEABLE_ANIMAL), + HORSE(100, ENTITY_AGEABLE), + RABBIT(101, ENTITY_AGEABLE), + POLAR_BEAR(102, ENTITY_AGEABLE), + VILLAGER(120, ENTITY_AGEABLE), + ENDER_CRYSTAL(200, ENTITY), + SPLASH_POTION(-1, ENTITY), + LINGERING_POTION(-1, SPLASH_POTION), + AREA_EFFECT_CLOUD(-1, ENTITY), + EGG(-1, ENTITY), + FISHING_HOOK(-1, ENTITY), + LIGHTNING(-1, ENTITY), + WEATHER(-1, ENTITY), + PLAYER(-1, ENTITY_HUMAN), + COMPLEX_PART(-1, ENTITY); + + private final int id; + private final EntityType parent; + + EntityType(int id) { + this.id = id; + this.parent = null; + } + + public static Optional findById(int id) { + if (id == -1) // Check if this is called + return Optional.absent(); + + for (EntityType ent : EntityType.values()) + if (ent.getId() == id) + return Optional.of(ent); + + return Optional.absent(); + } + } + + @AllArgsConstructor + @Getter + public enum ObjectTypes { + BOAT(1, EntityType.BOAT), + ITEM(2, EntityType.DROPPED_ITEM), + AREA_EFFECT_CLOUD(3, EntityType.AREA_EFFECT_CLOUD), + MINECART(10, EntityType.MINECART_ABSTRACT), + TNT_PRIMED(50, EntityType.PRIMED_TNT), + ENDER_CRYSTAL(51, EntityType.ENDER_CRYSTAL), + TIPPED_ARROW(60, EntityType.TIPPED_ARROW), + SNOWBALL(61, EntityType.SNOWBALL), + EGG(62, EntityType.EGG), + FIREBALL(63, EntityType.FIREBALL), + SMALL_FIREBALL(64, EntityType.SMALL_FIREBALL), + ENDER_PEARL(65, EntityType.ENDER_PEARL), + WITHER_SKULL(66, EntityType.WITHER_SKULL), + SHULKER_BULLET(67, EntityType.SHULKER_BULLET), + FALLING_BLOCK(70, EntityType.FALLING_BLOCK), + ITEM_FRAME(71, EntityType.ITEM_FRAME), + ENDER_SIGNAL(72, EntityType.ENDER_SIGNAL), + POTION(73, EntityType.SPLASH_POTION), + THROWN_EXP_BOTTLE(75, EntityType.THROWN_EXP_BOTTLE), + FIREWORK(76, EntityType.FIREWORK), + LEASH(77, EntityType.LEASH_HITCH), + ARMOR_STAND(78, EntityType.ARMOR_STAND), + FISHIHNG_HOOK(90, EntityType.FISHING_HOOK), + SPECTRAL_ARROW(91, EntityType.SPECTRAL_ARROW), + DRAGON_FIREBALL(93, EntityType.DRAGON_FIREBALL); + + private final int id; + private final EntityType type; + + public static Optional findById(int id) { + if (id == -1) + return Optional.absent(); + + for (ObjectTypes ent : ObjectTypes.values()) + if (ent.getId() == id) + return Optional.of(ent); + + return Optional.absent(); + } + + public static Optional getPCEntity(int id) { + Optional output = findById(id); + + if (!output.isPresent()) + return Optional.absent(); + return Optional.of(output.get().getType()); + } + } +} diff --git a/common/src/main/java/us/myles/ViaVersion/api/entities/Entity1_11Types.java b/common/src/main/java/us/myles/ViaVersion/api/entities/Entity1_11Types.java new file mode 100644 index 000000000..d091f9ba0 --- /dev/null +++ b/common/src/main/java/us/myles/ViaVersion/api/entities/Entity1_11Types.java @@ -0,0 +1,241 @@ +package us.myles.ViaVersion.api.entities; + +import com.google.common.base.Optional; +import lombok.AllArgsConstructor; +import lombok.Getter; +import us.myles.ViaVersion.api.Via; + +// 1.11 Entity / Object ids TODO maybe in the future instead of copying it, some api. +public class Entity1_11Types { + public static EntityType getTypeFromId(int typeID, boolean isObject) { + Optional type; + + if (isObject) + type = ObjectTypes.getPCEntity(typeID); + else + type = EntityType.findById(typeID); + + if (!type.isPresent()) { + Via.getPlatform().getLogger().severe("Could not find type id " + typeID + " isObject=" + isObject); + return EntityType.ENTITY; // Fall back to the basic ENTITY + } + + return type.get(); + } + + @AllArgsConstructor + @Getter + public enum EntityType { + ENTITY(-1), + DROPPED_ITEM(1, ENTITY), + EXPERIENCE_ORB(2, ENTITY), + LEASH_HITCH(8, ENTITY), // Actually entity hanging but it doesn't make a lot of difference for metadata + PAINTING(9, ENTITY), // Actually entity hanging but it doesn't make a lot of difference for metadata + ARROW(10, ENTITY), + SNOWBALL(11, ENTITY), // Actually EntityProjectile + FIREBALL(12, ENTITY), + SMALL_FIREBALL(13, ENTITY), + ENDER_PEARL(14, ENTITY), // Actually EntityProjectile + ENDER_SIGNAL(15, ENTITY), + THROWN_EXP_BOTTLE(17, ENTITY), + ITEM_FRAME(18, ENTITY), // Actually EntityHanging + WITHER_SKULL(19, ENTITY), + PRIMED_TNT(20, ENTITY), + FALLING_BLOCK(21, ENTITY), + FIREWORK(22, ENTITY), + TIPPED_ARROW(23, ARROW), + SPECTRAL_ARROW(24, ARROW), + SHULKER_BULLET(25, ENTITY), + DRAGON_FIREBALL(26, FIREBALL), + EVOCATION_FANGS(33, ENTITY), + + + ENTITY_LIVING(-1, ENTITY), + ENTITY_INSENTIENT(-1, ENTITY_LIVING), + ENTITY_AGEABLE(-1, ENTITY_INSENTIENT), + ENTITY_TAMEABLE_ANIMAL(-1, ENTITY_AGEABLE), + ENTITY_HUMAN(-1, ENTITY_LIVING), + + ARMOR_STAND(30, ENTITY_LIVING), + EVOCATION_ILLAGER(34, ENTITY_INSENTIENT), + VEX(35, ENTITY_INSENTIENT), + VINDICATION_ILLAGER(36, ENTITY_INSENTIENT), + + // Vehicles + MINECART_ABSTRACT(-1, ENTITY), + MINECART_COMMAND(40, MINECART_ABSTRACT), + BOAT(41, ENTITY), + MINECART_RIDEABLE(42, MINECART_ABSTRACT), + MINECART_CHEST(43, MINECART_ABSTRACT), + MINECART_FURNACE(44, MINECART_ABSTRACT), + MINECART_TNT(45, MINECART_ABSTRACT), + MINECART_HOPPER(46, MINECART_ABSTRACT), + MINECART_MOB_SPAWNER(47, MINECART_ABSTRACT), + + CREEPER(50, ENTITY_INSENTIENT), + + ABSTRACT_SKELETON(-1, ENTITY_INSENTIENT), + SKELETON(51, ABSTRACT_SKELETON), + WITHER_SKELETON(5, ABSTRACT_SKELETON), + STRAY(6, ABSTRACT_SKELETON), + + SPIDER(52, ENTITY_INSENTIENT), + GIANT(53, ENTITY_INSENTIENT), + + ZOMBIE(54, ENTITY_INSENTIENT), + HUSK(23, ZOMBIE), + ZOMBIE_VILLAGER(27, ZOMBIE), + + SLIME(55, ENTITY_INSENTIENT), + GHAST(56, ENTITY_INSENTIENT), + PIG_ZOMBIE(57, ZOMBIE), + ENDERMAN(58, ENTITY_INSENTIENT), + CAVE_SPIDER(59, SPIDER), + SILVERFISH(60, ENTITY_INSENTIENT), + BLAZE(61, ENTITY_INSENTIENT), + MAGMA_CUBE(62, SLIME), + ENDER_DRAGON(63, ENTITY_INSENTIENT), + WITHER(64, ENTITY_INSENTIENT), + BAT(65, ENTITY_INSENTIENT), + WITCH(66, ENTITY_INSENTIENT), + ENDERMITE(67, ENTITY_INSENTIENT), + + GUARDIAN(68, ENTITY_INSENTIENT), + ELDER_GUARDIAN(4, EntityType.GUARDIAN), // Moved down to avoid illegal forward reference + + IRON_GOLEM(99, ENTITY_INSENTIENT), // moved up to avoid illegal forward references + SHULKER(69, EntityType.IRON_GOLEM), + PIG(90, ENTITY_AGEABLE), + SHEEP(91, ENTITY_AGEABLE), + COW(92, ENTITY_AGEABLE), + CHICKEN(93, ENTITY_AGEABLE), + SQUID(94, ENTITY_INSENTIENT), + WOLF(95, ENTITY_TAMEABLE_ANIMAL), + MUSHROOM_COW(96, COW), + SNOWMAN(97, EntityType.IRON_GOLEM), + OCELOT(98, ENTITY_TAMEABLE_ANIMAL), + + ABSTRACT_HORSE(-1, ENTITY_AGEABLE), + HORSE(100, ABSTRACT_HORSE), + SKELETON_HORSE(28, ABSTRACT_HORSE), + ZOMBIE_HORSE(29, ABSTRACT_HORSE), + + CHESTED_HORSE(-1, ABSTRACT_HORSE), + DONKEY(31, CHESTED_HORSE), + MULE(32, CHESTED_HORSE), + LIAMA(103, CHESTED_HORSE), + + + RABBIT(101, ENTITY_AGEABLE), + POLAR_BEAR(102, ENTITY_AGEABLE), + VILLAGER(120, ENTITY_AGEABLE), + ENDER_CRYSTAL(200, ENTITY), + SPLASH_POTION(-1, ENTITY), + LINGERING_POTION(-1, SPLASH_POTION), + AREA_EFFECT_CLOUD(-1, ENTITY), + EGG(-1, ENTITY), + FISHING_HOOK(-1, ENTITY), + LIGHTNING(-1, ENTITY), + WEATHER(-1, ENTITY), + PLAYER(-1, ENTITY_HUMAN), + COMPLEX_PART(-1, ENTITY), + LIAMA_SPIT(-1, ENTITY); + + private final int id; + private final EntityType parent; + + EntityType(int id) { + this.id = id; + this.parent = null; + } + + public static Optional findById(int id) { + if (id == -1) // Check if this is called + return Optional.absent(); + + for (EntityType ent : EntityType.values()) + if (ent.getId() == id) + return Optional.of(ent); + + return Optional.absent(); + } + + public boolean is(EntityType... types) { + for (EntityType type : types) + if (is(type)) + return true; + return false; + } + + public boolean is(EntityType type) { + return this == type; + } + + public boolean isOrHasParent(EntityType type) { + EntityType parent = this; + + do { + if (parent.equals(type)) + return true; + + parent = parent.getParent(); + } while (parent != null); + + return false; + } + } + + @AllArgsConstructor + @Getter + public enum ObjectTypes { + BOAT(1, EntityType.BOAT), + ITEM(2, EntityType.DROPPED_ITEM), + AREA_EFFECT_CLOUD(3, EntityType.AREA_EFFECT_CLOUD), + MINECART(10, EntityType.MINECART_ABSTRACT), + TNT_PRIMED(50, EntityType.PRIMED_TNT), + ENDER_CRYSTAL(51, EntityType.ENDER_CRYSTAL), + TIPPED_ARROW(60, EntityType.TIPPED_ARROW), + SNOWBALL(61, EntityType.SNOWBALL), + EGG(62, EntityType.EGG), + FIREBALL(63, EntityType.FIREBALL), + SMALL_FIREBALL(64, EntityType.SMALL_FIREBALL), + ENDER_PEARL(65, EntityType.ENDER_PEARL), + WITHER_SKULL(66, EntityType.WITHER_SKULL), + SHULKER_BULLET(67, EntityType.SHULKER_BULLET), + LIAMA_SPIT(68, EntityType.LIAMA_SPIT), + FALLING_BLOCK(70, EntityType.FALLING_BLOCK), + ITEM_FRAME(71, EntityType.ITEM_FRAME), + ENDER_SIGNAL(72, EntityType.ENDER_SIGNAL), + POTION(73, EntityType.SPLASH_POTION), + THROWN_EXP_BOTTLE(75, EntityType.THROWN_EXP_BOTTLE), + FIREWORK(76, EntityType.FIREWORK), + LEASH(77, EntityType.LEASH_HITCH), + ARMOR_STAND(78, EntityType.ARMOR_STAND), + EVOCATION_FANGS(39, EntityType.EVOCATION_FANGS), + FISHIHNG_HOOK(90, EntityType.FISHING_HOOK), + SPECTRAL_ARROW(91, EntityType.SPECTRAL_ARROW), + DRAGON_FIREBALL(93, EntityType.DRAGON_FIREBALL); + + private final int id; + private final EntityType type; + + public static Optional findById(int id) { + if (id == -1) + return Optional.absent(); + + for (ObjectTypes ent : ObjectTypes.values()) + if (ent.getId() == id) + return Optional.of(ent); + + return Optional.absent(); + } + + public static Optional getPCEntity(int id) { + Optional output = findById(id); + + if (!output.isPresent()) + return Optional.absent(); + return Optional.of(output.get().getType()); + } + } +} diff --git a/common/src/main/java/us/myles/ViaVersion/api/minecraft/Environment.java b/common/src/main/java/us/myles/ViaVersion/api/minecraft/Environment.java new file mode 100644 index 000000000..fb098741a --- /dev/null +++ b/common/src/main/java/us/myles/ViaVersion/api/minecraft/Environment.java @@ -0,0 +1,32 @@ +package us.myles.ViaVersion.api.minecraft; + +import java.util.HashMap; +import java.util.Map; + +public enum Environment { + NORMAL(0), + NETHER(-1), + END(1); + + private final int id; + private static final Map lookup = new HashMap<>(); + + static { + for (Environment env : values()) { + lookup.put(env.getId(), env); + } + } + + Environment(int id) { + this.id = id; + } + + public int getId() { + return id; + } + + + public static Environment getEnvironmentById(int id) { + return lookup.get(id); + } +} diff --git a/common/src/main/java/us/myles/ViaVersion/api/minecraft/EulerAngle.java b/common/src/main/java/us/myles/ViaVersion/api/minecraft/EulerAngle.java new file mode 100644 index 000000000..607d41e56 --- /dev/null +++ b/common/src/main/java/us/myles/ViaVersion/api/minecraft/EulerAngle.java @@ -0,0 +1,12 @@ +package us.myles.ViaVersion.api.minecraft; + +import lombok.AllArgsConstructor; +import lombok.Data; + +@Data +@AllArgsConstructor +public class EulerAngle { + private float x; + private float y; + private float z; +} diff --git a/src/main/java/us/myles/ViaVersion/api/minecraft/Position.java b/common/src/main/java/us/myles/ViaVersion/api/minecraft/Position.java similarity index 100% rename from src/main/java/us/myles/ViaVersion/api/minecraft/Position.java rename to common/src/main/java/us/myles/ViaVersion/api/minecraft/Position.java diff --git a/common/src/main/java/us/myles/ViaVersion/api/minecraft/Vector.java b/common/src/main/java/us/myles/ViaVersion/api/minecraft/Vector.java new file mode 100644 index 000000000..78b6b5bdc --- /dev/null +++ b/common/src/main/java/us/myles/ViaVersion/api/minecraft/Vector.java @@ -0,0 +1,12 @@ +package us.myles.ViaVersion.api.minecraft; + +import lombok.AllArgsConstructor; +import lombok.Data; + +@Data +@AllArgsConstructor +public class Vector { + private int blockX; + private int blockY; + private int blockZ; +} diff --git a/src/main/java/us/myles/ViaVersion/api/minecraft/chunks/Chunk.java b/common/src/main/java/us/myles/ViaVersion/api/minecraft/chunks/Chunk.java similarity index 100% rename from src/main/java/us/myles/ViaVersion/api/minecraft/chunks/Chunk.java rename to common/src/main/java/us/myles/ViaVersion/api/minecraft/chunks/Chunk.java diff --git a/src/main/java/us/myles/ViaVersion/api/minecraft/chunks/ChunkSection.java b/common/src/main/java/us/myles/ViaVersion/api/minecraft/chunks/ChunkSection.java similarity index 100% rename from src/main/java/us/myles/ViaVersion/api/minecraft/chunks/ChunkSection.java rename to common/src/main/java/us/myles/ViaVersion/api/minecraft/chunks/ChunkSection.java diff --git a/src/main/java/us/myles/ViaVersion/api/minecraft/chunks/NibbleArray.java b/common/src/main/java/us/myles/ViaVersion/api/minecraft/chunks/NibbleArray.java similarity index 100% rename from src/main/java/us/myles/ViaVersion/api/minecraft/chunks/NibbleArray.java rename to common/src/main/java/us/myles/ViaVersion/api/minecraft/chunks/NibbleArray.java diff --git a/common/src/main/java/us/myles/ViaVersion/api/minecraft/item/Item.java b/common/src/main/java/us/myles/ViaVersion/api/minecraft/item/Item.java new file mode 100644 index 000000000..9bb8df568 --- /dev/null +++ b/common/src/main/java/us/myles/ViaVersion/api/minecraft/item/Item.java @@ -0,0 +1,16 @@ +package us.myles.ViaVersion.api.minecraft.item; + +import lombok.*; +import org.spacehq.opennbt.tag.builtin.CompoundTag; + +@Getter +@Setter +@NoArgsConstructor +@AllArgsConstructor +@ToString +public class Item { + private short id; + private byte amount; + private short data; + private CompoundTag tag; +} diff --git a/common/src/main/java/us/myles/ViaVersion/api/minecraft/metadata/MetaType.java b/common/src/main/java/us/myles/ViaVersion/api/minecraft/metadata/MetaType.java new file mode 100644 index 000000000..31f2c40e8 --- /dev/null +++ b/common/src/main/java/us/myles/ViaVersion/api/minecraft/metadata/MetaType.java @@ -0,0 +1,20 @@ +package us.myles.ViaVersion.api.minecraft.metadata; + +import us.myles.ViaVersion.api.type.Type; + +public interface MetaType { + + /** + * Get the write/read type + * + * @return Type instance + */ + Type getType(); + + /** + * Get type id from the specific MetaDataType + * + * @return Type id as an integer + */ + int getTypeID(); +} diff --git a/common/src/main/java/us/myles/ViaVersion/api/minecraft/metadata/Metadata.java b/common/src/main/java/us/myles/ViaVersion/api/minecraft/metadata/Metadata.java new file mode 100644 index 000000000..68fdeca43 --- /dev/null +++ b/common/src/main/java/us/myles/ViaVersion/api/minecraft/metadata/Metadata.java @@ -0,0 +1,12 @@ +package us.myles.ViaVersion.api.minecraft.metadata; + +import lombok.AllArgsConstructor; +import lombok.Data; + +@AllArgsConstructor +@Data +public class Metadata { + private int id; + private MetaType metaType; + private Object value; +} diff --git a/src/main/java/us/myles/ViaVersion/protocols/protocol1_9to1_8/metadata/MetadataTypes.java b/common/src/main/java/us/myles/ViaVersion/api/minecraft/metadata/types/MetaType1_8.java similarity index 69% rename from src/main/java/us/myles/ViaVersion/protocols/protocol1_9to1_8/metadata/MetadataTypes.java rename to common/src/main/java/us/myles/ViaVersion/api/minecraft/metadata/types/MetaType1_8.java index 36060f9bd..7d75b39fe 100644 --- a/src/main/java/us/myles/ViaVersion/protocols/protocol1_9to1_8/metadata/MetadataTypes.java +++ b/common/src/main/java/us/myles/ViaVersion/api/minecraft/metadata/types/MetaType1_8.java @@ -1,12 +1,13 @@ -package us.myles.ViaVersion.protocols.protocol1_9to1_8.metadata; +package us.myles.ViaVersion.api.minecraft.metadata.types; import lombok.Getter; import lombok.RequiredArgsConstructor; +import us.myles.ViaVersion.api.minecraft.metadata.MetaType; import us.myles.ViaVersion.api.type.Type; @RequiredArgsConstructor @Getter -public enum MetadataTypes { +public enum MetaType1_8 implements MetaType { Byte(0, Type.BYTE), Short(1, Type.SHORT), Int(2, Type.INT), @@ -20,7 +21,7 @@ public enum MetadataTypes { private final int typeID; private final Type type; - public static MetadataTypes byId(int id) { + public static MetaType1_8 byId(int id) { return values()[id]; } } diff --git a/src/main/java/us/myles/ViaVersion/protocols/protocol1_9to1_8/metadata/NewType.java b/common/src/main/java/us/myles/ViaVersion/api/minecraft/metadata/types/MetaType1_9.java similarity index 75% rename from src/main/java/us/myles/ViaVersion/protocols/protocol1_9to1_8/metadata/NewType.java rename to common/src/main/java/us/myles/ViaVersion/api/minecraft/metadata/types/MetaType1_9.java index 53ae361f2..30be6bef2 100644 --- a/src/main/java/us/myles/ViaVersion/protocols/protocol1_9to1_8/metadata/NewType.java +++ b/common/src/main/java/us/myles/ViaVersion/api/minecraft/metadata/types/MetaType1_9.java @@ -1,12 +1,13 @@ -package us.myles.ViaVersion.protocols.protocol1_9to1_8.metadata; +package us.myles.ViaVersion.api.minecraft.metadata.types; import lombok.Getter; import lombok.RequiredArgsConstructor; +import us.myles.ViaVersion.api.minecraft.metadata.MetaType; import us.myles.ViaVersion.api.type.Type; @RequiredArgsConstructor @Getter -public enum NewType { +public enum MetaType1_9 implements MetaType { Byte(0, Type.BYTE), VarInt(1, Type.VAR_INT), Float(2, Type.FLOAT), @@ -25,7 +26,7 @@ public enum NewType { private final int typeID; private final Type type; - public static NewType byId(int id) { + public static MetaType1_9 byId(int id) { return values()[id]; } diff --git a/common/src/main/java/us/myles/ViaVersion/api/platform/TaskId.java b/common/src/main/java/us/myles/ViaVersion/api/platform/TaskId.java new file mode 100644 index 000000000..44993bc2c --- /dev/null +++ b/common/src/main/java/us/myles/ViaVersion/api/platform/TaskId.java @@ -0,0 +1,11 @@ +package us.myles.ViaVersion.api.platform; + +public interface TaskId { + /** + * Returns the actual object represented by this TaskId + * Null if task cannot be cancelled. + * + * @return Platform based Object (don't assume) + */ + Object getObject(); +} 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..14f853a2b --- /dev/null +++ b/common/src/main/java/us/myles/ViaVersion/api/platform/ViaInjector.java @@ -0,0 +1,39 @@ +package us.myles.ViaVersion.api.platform; + +public interface ViaInjector { + /** + * Inject into the current Platform + * + * @throws Exception If there is an error with injecting + */ + void inject() throws Exception; + + /** + * Uninject into the current Platform + * + * @throws Exception If there is an error with uninjecting + */ + void uninject() throws Exception; + + /** + * Get the server protocol version + * + * @return The server protocol integer + * @throws Exception If there is an error with getting this info, eg. not binded. + */ + int getServerProtocolVersion() throws Exception; + + /** + * Get the name of the encoder for then netty pipeline for this platform. + * + * @return The name + */ + String getEncoderName(); + + /** + * Get the name of the decoder for then netty pipeline for this platform. + * + * @return The name + */ + String getDecoderName(); +} 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 new file mode 100644 index 000000000..3a92e7f18 --- /dev/null +++ b/common/src/main/java/us/myles/ViaVersion/api/platform/ViaPlatform.java @@ -0,0 +1,136 @@ +package us.myles.ViaVersion.api.platform; + +import com.google.gson.JsonObject; +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 java.util.UUID; +import java.util.logging.Logger; + +/** + * ViaPlatform represents a platform ViaVersion runs on + * + * @param - The player type for the platform, used for API related methods + */ +public interface ViaPlatform { + /** + * Get the logger for this platform + * + * @return Java Logger (may be a wrapper) + */ + Logger getLogger(); + + /** + * Get the platform name + * + * @return Platform Name (simply its name) + */ + String getPlatformName(); + + /** + * Get the plugin version + * + * @return Plugin version as a semver string + */ + String getPluginVersion(); + + /** + * Run a task Async + * + * @param runnable The task to run + * @return The Task ID + */ + TaskId runAsync(Runnable runnable); + + /** + * Run a task Sync + * + * @param runnable The task to run + * @return The Task ID + */ + TaskId runSync(Runnable runnable); + + /** + * Run a task at a repeating interval. + * Initial interval is the same as repeat. + * + * @param runnable The task to run + * @param ticks The interval to run it at + * @return The Task ID + */ + TaskId runRepeatingSync(Runnable runnable, Long ticks); + + /** + * Cancel a task + * + * @param taskId The task ID to cancel + */ + void cancelTask(TaskId taskId); + + /** + * Get the online players + * + * @return Array of ViaCommandSender + */ + ViaCommandSender[] getOnlinePlayers(); + + /** + * Send a message to a player + * + * @param uuid The player's UUID + * @param message The message to send + */ + void sendMessage(UUID uuid, String message); + + /** + * Kick a player for a reason + * + * @param uuid The player's UUID + * @param message The message to kick them with + * @return True if it was successful + */ + boolean kickPlayer(UUID uuid, String message); + + /** + * Check if the plugin is enabled. + * + * @return True if it is enabled + */ + boolean isPluginEnabled(); + + /** + * Get the API for this platform + * + * @return The API for the platform + */ + ViaAPI getApi(); + + /** + * Get the config API for this platform + * + * @return The config API + */ + ViaVersionConfig getConf(); + + /** + * Get the backend configuration provider for this platform. + * (On some platforms this returns the same as getConf()) + * + * @return The configuration provider + */ + ConfigurationProvider getConfigurationProvider(); + + /** + * Called when a reload happens + */ + void onReload(); + + /** + * Get the JSON data required for /viaversion dump + * + * @return The json data + */ + JsonObject getDump(); +} diff --git a/common/src/main/java/us/myles/ViaVersion/api/platform/ViaPlatformLoader.java b/common/src/main/java/us/myles/ViaVersion/api/platform/ViaPlatformLoader.java new file mode 100644 index 000000000..e8c4503bf --- /dev/null +++ b/common/src/main/java/us/myles/ViaVersion/api/platform/ViaPlatformLoader.java @@ -0,0 +1,8 @@ +package us.myles.ViaVersion.api.platform; + +public interface ViaPlatformLoader { + /** + * Initialise the loading for a platform, eg. registering listeners / providers / events etc. + */ + void load(); +} diff --git a/common/src/main/java/us/myles/ViaVersion/api/platform/providers/Provider.java b/common/src/main/java/us/myles/ViaVersion/api/platform/providers/Provider.java new file mode 100644 index 000000000..f9a6c4d77 --- /dev/null +++ b/common/src/main/java/us/myles/ViaVersion/api/platform/providers/Provider.java @@ -0,0 +1,4 @@ +package us.myles.ViaVersion.api.platform.providers; + +public interface Provider { +} diff --git a/common/src/main/java/us/myles/ViaVersion/api/platform/providers/ViaProviders.java b/common/src/main/java/us/myles/ViaVersion/api/platform/providers/ViaProviders.java new file mode 100644 index 000000000..6911a5217 --- /dev/null +++ b/common/src/main/java/us/myles/ViaVersion/api/platform/providers/ViaProviders.java @@ -0,0 +1,37 @@ +package us.myles.ViaVersion.api.platform.providers; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +public class ViaProviders { + private final Map, Provider> providers = new HashMap<>(); + private final List> lonelyProviders = new ArrayList<>(); + + public void require(Class provider) { + lonelyProviders.add(provider); + } + + public void register(Class provider, T value) { + providers.put(provider, value); + } + + public void use(Class provider, T value) { + if (lonelyProviders.contains(provider)) { + lonelyProviders.remove(provider); + } + providers.put(provider, value); + } + + public T get(Class provider) { + if (providers.containsKey(provider)) { + return (T) providers.get(provider); + } else { + if (lonelyProviders.contains(provider)) { + throw new IllegalStateException("There was no provider for " + provider + ", one is required!"); + } + return null; + } + } +} diff --git a/src/main/java/us/myles/ViaVersion/api/protocol/Protocol.java b/common/src/main/java/us/myles/ViaVersion/api/protocol/Protocol.java similarity index 89% rename from src/main/java/us/myles/ViaVersion/api/protocol/Protocol.java rename to common/src/main/java/us/myles/ViaVersion/api/protocol/Protocol.java index 075063c2b..c2c5a8711 100644 --- a/src/main/java/us/myles/ViaVersion/api/protocol/Protocol.java +++ b/common/src/main/java/us/myles/ViaVersion/api/protocol/Protocol.java @@ -5,6 +5,7 @@ import lombok.Getter; import us.myles.ViaVersion.api.PacketWrapper; import us.myles.ViaVersion.api.Pair; import us.myles.ViaVersion.api.data.UserConnection; +import us.myles.ViaVersion.api.platform.providers.ViaProviders; import us.myles.ViaVersion.api.remapper.PacketRemapper; import us.myles.ViaVersion.exception.CancelException; import us.myles.ViaVersion.packets.Direction; @@ -15,8 +16,8 @@ import java.util.List; import java.util.Map; public abstract class Protocol { - private Map, ProtocolPacket> incoming = new HashMap<>(); - private Map, ProtocolPacket> outgoing = new HashMap<>(); + private final Map, ProtocolPacket> incoming = new HashMap<>(); + private final Map, ProtocolPacket> outgoing = new HashMap<>(); public Protocol() { registerPackets(); @@ -47,11 +48,23 @@ public abstract class Protocol { /** * Register listeners for this protocol + * + * @deprecated No longer used as listeners are registered in {@link us.myles.ViaVersion.api.platform.ViaPlatformLoader#load} */ + @Deprecated protected void registerListeners() { } + /** + * Handle protocol registration phase, use this to register providers / tasks. + * + * @param providers The current providers + */ + protected void register(ViaProviders providers) { + + } + /** * Register the packets for this protocol */ diff --git a/src/main/java/us/myles/ViaVersion/api/protocol/ProtocolPipeline.java b/common/src/main/java/us/myles/ViaVersion/api/protocol/ProtocolPipeline.java similarity index 94% rename from src/main/java/us/myles/ViaVersion/api/protocol/ProtocolPipeline.java rename to common/src/main/java/us/myles/ViaVersion/api/protocol/ProtocolPipeline.java index cf0b03385..f8226a775 100644 --- a/src/main/java/us/myles/ViaVersion/api/protocol/ProtocolPipeline.java +++ b/common/src/main/java/us/myles/ViaVersion/api/protocol/ProtocolPipeline.java @@ -1,9 +1,9 @@ package us.myles.ViaVersion.api.protocol; -import us.myles.ViaVersion.ViaVersionPlugin; 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; import us.myles.ViaVersion.packets.PacketType; import us.myles.ViaVersion.packets.State; @@ -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,12 +109,12 @@ public class ProtocolPipeline extends Protocol { } } String name = packet + "[" + userConnection.get(ProtocolInfo.class).getProtocolVersion() + "]"; - ViaVersionPlugin plugin = (ViaVersionPlugin) ViaVersion.getInstance(); + ViaPlatform platform = Via.getPlatform(); String actualUsername = packetWrapper.user().get(ProtocolInfo.class).getUsername(); String username = actualUsername != null ? actualUsername + " " : ""; - plugin.getLogger().log(Level.INFO, "{0}{1}: {2} {3} -> {4} [{5}] Value: {6}", + platform.getLogger().log(Level.INFO, "{0}{1}: {2} {3} -> {4} [{5}] Value: {6}", new Object[]{ username, direction, @@ -162,4 +162,9 @@ public class ProtocolPipeline extends Protocol { public List pipes() { return protocolList; } + + public void cleanPipes() { + pipes().clear(); + registerPackets(); + } } diff --git a/src/main/java/us/myles/ViaVersion/api/protocol/ProtocolRegistry.java b/common/src/main/java/us/myles/ViaVersion/api/protocol/ProtocolRegistry.java similarity index 88% rename from src/main/java/us/myles/ViaVersion/api/protocol/ProtocolRegistry.java rename to common/src/main/java/us/myles/ViaVersion/api/protocol/ProtocolRegistry.java index d8349fc25..51f32af25 100644 --- a/src/main/java/us/myles/ViaVersion/api/protocol/ProtocolRegistry.java +++ b/common/src/main/java/us/myles/ViaVersion/api/protocol/ProtocolRegistry.java @@ -2,8 +2,8 @@ package us.myles.ViaVersion.api.protocol; import com.google.common.collect.Lists; import com.google.common.collect.Sets; -import org.bukkit.Bukkit; import us.myles.ViaVersion.api.Pair; +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; @@ -20,20 +20,20 @@ public class ProtocolRegistry { public static final Protocol BASE_PROTOCOL = new BaseProtocol(); public static int SERVER_PROTOCOL = -1; // Input Version -> Output Version & Protocol (Allows fast lookup) - private static Map> registryMap = new ConcurrentHashMap<>(); - private static Map, List>> pathCache = new ConcurrentHashMap<>(); - private static List registerList = Lists.newCopyOnWriteArrayList(); - private static Set supportedVersions = Sets.newConcurrentHashSet(); + private static final Map> registryMap = new ConcurrentHashMap<>(); + private static final Map, List>> pathCache = new ConcurrentHashMap<>(); + private static final List registerList = Lists.newCopyOnWriteArrayList(); + private static final Set supportedVersions = Sets.newConcurrentHashSet(); static { // Base Protocol - registerProtocol(BASE_PROTOCOL, Arrays.asList(), -1); + registerProtocol(BASE_PROTOCOL, Collections.emptyList(), -1); // Register built in protocols registerProtocol(new Protocol1_9TO1_8(), Collections.singletonList(ProtocolVersion.v1_9.getId()), ProtocolVersion.v1_8.getId()); registerProtocol(new Protocol1_9_1TO1_9(), Arrays.asList(ProtocolVersion.v1_9_1.getId(), ProtocolVersion.v1_9_2.getId()), ProtocolVersion.v1_9.getId()); - registerProtocol(new Protocol1_9_3TO1_9_1_2(), Arrays.asList(ProtocolVersion.v1_9_3.getId()), ProtocolVersion.v1_9_2.getId()); + registerProtocol(new Protocol1_9_3TO1_9_1_2(), Collections.singletonList(ProtocolVersion.v1_9_3.getId()), ProtocolVersion.v1_9_2.getId()); // Only supported for 1.9.4 server to 1.9 (nothing else) - registerProtocol(new Protocol1_9TO1_9_1(), Arrays.asList(ProtocolVersion.v1_9.getId()), ProtocolVersion.v1_9_2.getId()); + registerProtocol(new Protocol1_9TO1_9_1(), Collections.singletonList(ProtocolVersion.v1_9.getId()), ProtocolVersion.v1_9_2.getId()); registerProtocol(new Protocol1_9_1_2TO1_9_3_4(), Arrays.asList(ProtocolVersion.v1_9_1.getId(), ProtocolVersion.v1_9_2.getId()), ProtocolVersion.v1_9_3.getId()); registerProtocol(new Protocol1_10To1_9_3_4(), Collections.singletonList(ProtocolVersion.v1_10.getId()), ProtocolVersion.v1_9_3.getId()); @@ -61,8 +61,9 @@ public class ProtocolRegistry { registryMap.get(version).put(output, protocol); } - if (Bukkit.getPluginManager().getPlugin("ViaVersion").isEnabled()) { + if (Via.getPlatform().isPluginEnabled()) { protocol.registerListeners(); + protocol.register(Via.getManager().getProviders()); refreshVersions(); } else { registerList.add(protocol); @@ -106,9 +107,10 @@ public class ProtocolRegistry { /** * Called when the server is enabled, to register any non registered listeners. */ - public static void registerListeners() { + public static void onServerLoaded() { for (Protocol protocol : registerList) { protocol.registerListeners(); + protocol.register(Via.getManager().getProviders()); } registerList.clear(); } diff --git a/src/main/java/us/myles/ViaVersion/api/protocol/ProtocolVersion.java b/common/src/main/java/us/myles/ViaVersion/api/protocol/ProtocolVersion.java similarity index 81% rename from src/main/java/us/myles/ViaVersion/api/protocol/ProtocolVersion.java rename to common/src/main/java/us/myles/ViaVersion/api/protocol/ProtocolVersion.java index 98ec33ab3..735b5814f 100644 --- a/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/src/main/java/us/myles/ViaVersion/api/remapper/PacketHandler.java b/common/src/main/java/us/myles/ViaVersion/api/remapper/PacketHandler.java similarity index 100% rename from src/main/java/us/myles/ViaVersion/api/remapper/PacketHandler.java rename to common/src/main/java/us/myles/ViaVersion/api/remapper/PacketHandler.java diff --git a/src/main/java/us/myles/ViaVersion/api/remapper/PacketRemapper.java b/common/src/main/java/us/myles/ViaVersion/api/remapper/PacketRemapper.java similarity index 97% rename from src/main/java/us/myles/ViaVersion/api/remapper/PacketRemapper.java rename to common/src/main/java/us/myles/ViaVersion/api/remapper/PacketRemapper.java index c323e8aea..354f05614 100644 --- a/src/main/java/us/myles/ViaVersion/api/remapper/PacketRemapper.java +++ b/common/src/main/java/us/myles/ViaVersion/api/remapper/PacketRemapper.java @@ -9,7 +9,7 @@ import java.util.ArrayList; import java.util.List; public abstract class PacketRemapper { - private List> valueRemappers = new ArrayList<>(); + private final List> valueRemappers = new ArrayList<>(); public PacketRemapper() { registerMap(); diff --git a/src/main/java/us/myles/ViaVersion/api/remapper/TypeRemapper.java b/common/src/main/java/us/myles/ViaVersion/api/remapper/TypeRemapper.java similarity index 100% rename from src/main/java/us/myles/ViaVersion/api/remapper/TypeRemapper.java rename to common/src/main/java/us/myles/ViaVersion/api/remapper/TypeRemapper.java diff --git a/src/main/java/us/myles/ViaVersion/api/remapper/ValueCreator.java b/common/src/main/java/us/myles/ViaVersion/api/remapper/ValueCreator.java similarity index 100% rename from src/main/java/us/myles/ViaVersion/api/remapper/ValueCreator.java rename to common/src/main/java/us/myles/ViaVersion/api/remapper/ValueCreator.java diff --git a/src/main/java/us/myles/ViaVersion/api/remapper/ValueReader.java b/common/src/main/java/us/myles/ViaVersion/api/remapper/ValueReader.java similarity index 100% rename from src/main/java/us/myles/ViaVersion/api/remapper/ValueReader.java rename to common/src/main/java/us/myles/ViaVersion/api/remapper/ValueReader.java diff --git a/src/main/java/us/myles/ViaVersion/api/remapper/ValueTransformer.java b/common/src/main/java/us/myles/ViaVersion/api/remapper/ValueTransformer.java similarity index 100% rename from src/main/java/us/myles/ViaVersion/api/remapper/ValueTransformer.java rename to common/src/main/java/us/myles/ViaVersion/api/remapper/ValueTransformer.java diff --git a/src/main/java/us/myles/ViaVersion/api/remapper/ValueWriter.java b/common/src/main/java/us/myles/ViaVersion/api/remapper/ValueWriter.java similarity index 100% rename from src/main/java/us/myles/ViaVersion/api/remapper/ValueWriter.java rename to common/src/main/java/us/myles/ViaVersion/api/remapper/ValueWriter.java diff --git a/src/main/java/us/myles/ViaVersion/api/type/ByteBufReader.java b/common/src/main/java/us/myles/ViaVersion/api/type/ByteBufReader.java similarity index 100% rename from src/main/java/us/myles/ViaVersion/api/type/ByteBufReader.java rename to common/src/main/java/us/myles/ViaVersion/api/type/ByteBufReader.java diff --git a/src/main/java/us/myles/ViaVersion/api/type/ByteBufWriter.java b/common/src/main/java/us/myles/ViaVersion/api/type/ByteBufWriter.java similarity index 100% rename from src/main/java/us/myles/ViaVersion/api/type/ByteBufWriter.java rename to common/src/main/java/us/myles/ViaVersion/api/type/ByteBufWriter.java diff --git a/src/main/java/us/myles/ViaVersion/api/type/PartialType.java b/common/src/main/java/us/myles/ViaVersion/api/type/PartialType.java similarity index 100% rename from src/main/java/us/myles/ViaVersion/api/type/PartialType.java rename to common/src/main/java/us/myles/ViaVersion/api/type/PartialType.java diff --git a/src/main/java/us/myles/ViaVersion/api/type/Type.java b/common/src/main/java/us/myles/ViaVersion/api/type/Type.java similarity index 97% rename from src/main/java/us/myles/ViaVersion/api/type/Type.java rename to common/src/main/java/us/myles/ViaVersion/api/type/Type.java index 938ed4da9..be9d577ec 100644 --- a/src/main/java/us/myles/ViaVersion/api/type/Type.java +++ b/common/src/main/java/us/myles/ViaVersion/api/type/Type.java @@ -2,10 +2,10 @@ package us.myles.ViaVersion.api.type; import lombok.Getter; -import org.bukkit.util.EulerAngle; -import org.bukkit.util.Vector; import org.spacehq.opennbt.tag.builtin.CompoundTag; +import us.myles.ViaVersion.api.minecraft.EulerAngle; import us.myles.ViaVersion.api.minecraft.Position; +import us.myles.ViaVersion.api.minecraft.Vector; import us.myles.ViaVersion.api.minecraft.item.Item; import us.myles.ViaVersion.api.type.types.*; import us.myles.ViaVersion.api.type.types.minecraft.*; diff --git a/src/main/java/us/myles/ViaVersion/api/type/TypeConverter.java b/common/src/main/java/us/myles/ViaVersion/api/type/TypeConverter.java similarity index 100% rename from src/main/java/us/myles/ViaVersion/api/type/TypeConverter.java rename to common/src/main/java/us/myles/ViaVersion/api/type/TypeConverter.java diff --git a/src/main/java/us/myles/ViaVersion/api/type/types/ArrayType.java b/common/src/main/java/us/myles/ViaVersion/api/type/types/ArrayType.java similarity index 100% rename from src/main/java/us/myles/ViaVersion/api/type/types/ArrayType.java rename to common/src/main/java/us/myles/ViaVersion/api/type/types/ArrayType.java diff --git a/src/main/java/us/myles/ViaVersion/api/type/types/BooleanType.java b/common/src/main/java/us/myles/ViaVersion/api/type/types/BooleanType.java similarity index 100% rename from src/main/java/us/myles/ViaVersion/api/type/types/BooleanType.java rename to common/src/main/java/us/myles/ViaVersion/api/type/types/BooleanType.java diff --git a/src/main/java/us/myles/ViaVersion/api/type/types/ByteType.java b/common/src/main/java/us/myles/ViaVersion/api/type/types/ByteType.java similarity index 100% rename from src/main/java/us/myles/ViaVersion/api/type/types/ByteType.java rename to common/src/main/java/us/myles/ViaVersion/api/type/types/ByteType.java diff --git a/common/src/main/java/us/myles/ViaVersion/api/type/types/CustomByteType.java b/common/src/main/java/us/myles/ViaVersion/api/type/types/CustomByteType.java new file mode 100644 index 000000000..097209490 --- /dev/null +++ b/common/src/main/java/us/myles/ViaVersion/api/type/types/CustomByteType.java @@ -0,0 +1,26 @@ +package us.myles.ViaVersion.api.type.types; + +import io.netty.buffer.ByteBuf; +import us.myles.ViaVersion.api.type.PartialType; + +public class CustomByteType extends PartialType { + + public CustomByteType(Integer param) { + super(param, byte[].class); + } + + @Override + public byte[] read(ByteBuf byteBuf, Integer integer) throws Exception { + if (byteBuf.readableBytes() < integer) throw new RuntimeException("Readable bytes does not match expected!"); + + byte[] byteArray = new byte[integer]; + byteBuf.readBytes(byteArray); + + return byteArray; + } + + @Override + public void write(ByteBuf byteBuf, Integer integer, byte[] bytes) throws Exception { + byteBuf.writeBytes(bytes); + } +} \ No newline at end of file diff --git a/src/main/java/us/myles/ViaVersion/api/type/types/DoubleType.java b/common/src/main/java/us/myles/ViaVersion/api/type/types/DoubleType.java similarity index 100% rename from src/main/java/us/myles/ViaVersion/api/type/types/DoubleType.java rename to common/src/main/java/us/myles/ViaVersion/api/type/types/DoubleType.java diff --git a/src/main/java/us/myles/ViaVersion/api/type/types/FloatType.java b/common/src/main/java/us/myles/ViaVersion/api/type/types/FloatType.java similarity index 100% rename from src/main/java/us/myles/ViaVersion/api/type/types/FloatType.java rename to common/src/main/java/us/myles/ViaVersion/api/type/types/FloatType.java diff --git a/src/main/java/us/myles/ViaVersion/api/type/types/IntType.java b/common/src/main/java/us/myles/ViaVersion/api/type/types/IntType.java similarity index 100% rename from src/main/java/us/myles/ViaVersion/api/type/types/IntType.java rename to common/src/main/java/us/myles/ViaVersion/api/type/types/IntType.java diff --git a/src/main/java/us/myles/ViaVersion/api/type/types/LongType.java b/common/src/main/java/us/myles/ViaVersion/api/type/types/LongType.java similarity index 100% rename from src/main/java/us/myles/ViaVersion/api/type/types/LongType.java rename to common/src/main/java/us/myles/ViaVersion/api/type/types/LongType.java diff --git a/src/main/java/us/myles/ViaVersion/api/type/types/RemainingBytesType.java b/common/src/main/java/us/myles/ViaVersion/api/type/types/RemainingBytesType.java similarity index 100% rename from src/main/java/us/myles/ViaVersion/api/type/types/RemainingBytesType.java rename to common/src/main/java/us/myles/ViaVersion/api/type/types/RemainingBytesType.java diff --git a/src/main/java/us/myles/ViaVersion/api/type/types/ShortType.java b/common/src/main/java/us/myles/ViaVersion/api/type/types/ShortType.java similarity index 100% rename from src/main/java/us/myles/ViaVersion/api/type/types/ShortType.java rename to common/src/main/java/us/myles/ViaVersion/api/type/types/ShortType.java diff --git a/src/main/java/us/myles/ViaVersion/api/type/types/StringType.java b/common/src/main/java/us/myles/ViaVersion/api/type/types/StringType.java similarity index 100% rename from src/main/java/us/myles/ViaVersion/api/type/types/StringType.java rename to common/src/main/java/us/myles/ViaVersion/api/type/types/StringType.java diff --git a/src/main/java/us/myles/ViaVersion/api/type/types/UUIDType.java b/common/src/main/java/us/myles/ViaVersion/api/type/types/UUIDType.java similarity index 100% rename from src/main/java/us/myles/ViaVersion/api/type/types/UUIDType.java rename to common/src/main/java/us/myles/ViaVersion/api/type/types/UUIDType.java diff --git a/src/main/java/us/myles/ViaVersion/api/type/types/UnsignedByteType.java b/common/src/main/java/us/myles/ViaVersion/api/type/types/UnsignedByteType.java similarity index 100% rename from src/main/java/us/myles/ViaVersion/api/type/types/UnsignedByteType.java rename to common/src/main/java/us/myles/ViaVersion/api/type/types/UnsignedByteType.java diff --git a/src/main/java/us/myles/ViaVersion/api/type/types/UnsignedShortType.java b/common/src/main/java/us/myles/ViaVersion/api/type/types/UnsignedShortType.java similarity index 100% rename from src/main/java/us/myles/ViaVersion/api/type/types/UnsignedShortType.java rename to common/src/main/java/us/myles/ViaVersion/api/type/types/UnsignedShortType.java diff --git a/src/main/java/us/myles/ViaVersion/api/type/types/VarIntType.java b/common/src/main/java/us/myles/ViaVersion/api/type/types/VarIntType.java similarity index 100% rename from src/main/java/us/myles/ViaVersion/api/type/types/VarIntType.java rename to common/src/main/java/us/myles/ViaVersion/api/type/types/VarIntType.java diff --git a/src/main/java/us/myles/ViaVersion/api/type/types/VoidType.java b/common/src/main/java/us/myles/ViaVersion/api/type/types/VoidType.java similarity index 100% rename from src/main/java/us/myles/ViaVersion/api/type/types/VoidType.java rename to common/src/main/java/us/myles/ViaVersion/api/type/types/VoidType.java diff --git a/src/main/java/us/myles/ViaVersion/api/type/types/minecraft/BaseChunkType.java b/common/src/main/java/us/myles/ViaVersion/api/type/types/minecraft/BaseChunkType.java similarity index 100% rename from src/main/java/us/myles/ViaVersion/api/type/types/minecraft/BaseChunkType.java rename to common/src/main/java/us/myles/ViaVersion/api/type/types/minecraft/BaseChunkType.java diff --git a/src/main/java/us/myles/ViaVersion/api/type/types/minecraft/EulerAngleType.java b/common/src/main/java/us/myles/ViaVersion/api/type/types/minecraft/EulerAngleType.java similarity index 74% rename from src/main/java/us/myles/ViaVersion/api/type/types/minecraft/EulerAngleType.java rename to common/src/main/java/us/myles/ViaVersion/api/type/types/minecraft/EulerAngleType.java index 5d324dd62..f4287769a 100644 --- a/src/main/java/us/myles/ViaVersion/api/type/types/minecraft/EulerAngleType.java +++ b/common/src/main/java/us/myles/ViaVersion/api/type/types/minecraft/EulerAngleType.java @@ -1,7 +1,7 @@ package us.myles.ViaVersion.api.type.types.minecraft; import io.netty.buffer.ByteBuf; -import org.bukkit.util.EulerAngle; +import us.myles.ViaVersion.api.minecraft.EulerAngle; import us.myles.ViaVersion.api.type.Type; public class EulerAngleType extends Type { @@ -20,8 +20,8 @@ public class EulerAngleType extends Type { @Override public void write(ByteBuf buffer, EulerAngle object) throws Exception { - Type.FLOAT.write(buffer, (float) object.getX()); - Type.FLOAT.write(buffer, (float) object.getY()); - Type.FLOAT.write(buffer, (float) object.getZ()); + Type.FLOAT.write(buffer, object.getX()); + Type.FLOAT.write(buffer, object.getY()); + Type.FLOAT.write(buffer, object.getZ()); } } \ No newline at end of file diff --git a/src/main/java/us/myles/ViaVersion/api/type/types/minecraft/ItemArrayType.java b/common/src/main/java/us/myles/ViaVersion/api/type/types/minecraft/ItemArrayType.java similarity index 100% rename from src/main/java/us/myles/ViaVersion/api/type/types/minecraft/ItemArrayType.java rename to common/src/main/java/us/myles/ViaVersion/api/type/types/minecraft/ItemArrayType.java diff --git a/src/main/java/us/myles/ViaVersion/api/type/types/minecraft/ItemType.java b/common/src/main/java/us/myles/ViaVersion/api/type/types/minecraft/ItemType.java similarity index 100% rename from src/main/java/us/myles/ViaVersion/api/type/types/minecraft/ItemType.java rename to common/src/main/java/us/myles/ViaVersion/api/type/types/minecraft/ItemType.java diff --git a/src/main/java/us/myles/ViaVersion/api/type/types/minecraft/MetaListTypeTemplate.java b/common/src/main/java/us/myles/ViaVersion/api/type/types/minecraft/MetaListTypeTemplate.java similarity index 100% rename from src/main/java/us/myles/ViaVersion/api/type/types/minecraft/MetaListTypeTemplate.java rename to common/src/main/java/us/myles/ViaVersion/api/type/types/minecraft/MetaListTypeTemplate.java diff --git a/src/main/java/us/myles/ViaVersion/api/type/types/minecraft/MetaTypeTemplate.java b/common/src/main/java/us/myles/ViaVersion/api/type/types/minecraft/MetaTypeTemplate.java similarity index 100% rename from src/main/java/us/myles/ViaVersion/api/type/types/minecraft/MetaTypeTemplate.java rename to common/src/main/java/us/myles/ViaVersion/api/type/types/minecraft/MetaTypeTemplate.java diff --git a/src/main/java/us/myles/ViaVersion/api/type/types/minecraft/NBTType.java b/common/src/main/java/us/myles/ViaVersion/api/type/types/minecraft/NBTType.java similarity index 100% rename from src/main/java/us/myles/ViaVersion/api/type/types/minecraft/NBTType.java rename to common/src/main/java/us/myles/ViaVersion/api/type/types/minecraft/NBTType.java diff --git a/src/main/java/us/myles/ViaVersion/api/type/types/minecraft/OptPositionType.java b/common/src/main/java/us/myles/ViaVersion/api/type/types/minecraft/OptPositionType.java similarity index 100% rename from src/main/java/us/myles/ViaVersion/api/type/types/minecraft/OptPositionType.java rename to common/src/main/java/us/myles/ViaVersion/api/type/types/minecraft/OptPositionType.java diff --git a/src/main/java/us/myles/ViaVersion/api/type/types/minecraft/OptUUIDType.java b/common/src/main/java/us/myles/ViaVersion/api/type/types/minecraft/OptUUIDType.java similarity index 100% rename from src/main/java/us/myles/ViaVersion/api/type/types/minecraft/OptUUIDType.java rename to common/src/main/java/us/myles/ViaVersion/api/type/types/minecraft/OptUUIDType.java diff --git a/src/main/java/us/myles/ViaVersion/api/type/types/minecraft/PositionType.java b/common/src/main/java/us/myles/ViaVersion/api/type/types/minecraft/PositionType.java similarity index 100% rename from src/main/java/us/myles/ViaVersion/api/type/types/minecraft/PositionType.java rename to common/src/main/java/us/myles/ViaVersion/api/type/types/minecraft/PositionType.java diff --git a/src/main/java/us/myles/ViaVersion/api/type/types/minecraft/VectorType.java b/common/src/main/java/us/myles/ViaVersion/api/type/types/minecraft/VectorType.java similarity index 93% rename from src/main/java/us/myles/ViaVersion/api/type/types/minecraft/VectorType.java rename to common/src/main/java/us/myles/ViaVersion/api/type/types/minecraft/VectorType.java index 968e4413e..17299241d 100644 --- a/src/main/java/us/myles/ViaVersion/api/type/types/minecraft/VectorType.java +++ b/common/src/main/java/us/myles/ViaVersion/api/type/types/minecraft/VectorType.java @@ -1,7 +1,7 @@ package us.myles.ViaVersion.api.type.types.minecraft; import io.netty.buffer.ByteBuf; -import org.bukkit.util.Vector; +import us.myles.ViaVersion.api.minecraft.Vector; import us.myles.ViaVersion.api.type.Type; public class VectorType extends Type { diff --git a/src/main/java/us/myles/ViaVersion/api/type/types/version/Metadata1_8Type.java b/common/src/main/java/us/myles/ViaVersion/api/type/types/version/Metadata1_8Type.java similarity index 64% rename from src/main/java/us/myles/ViaVersion/api/type/types/version/Metadata1_8Type.java rename to common/src/main/java/us/myles/ViaVersion/api/type/types/version/Metadata1_8Type.java index cb46b8256..6f3ad63e7 100644 --- a/src/main/java/us/myles/ViaVersion/api/type/types/version/Metadata1_8Type.java +++ b/common/src/main/java/us/myles/ViaVersion/api/type/types/version/Metadata1_8Type.java @@ -3,8 +3,8 @@ package us.myles.ViaVersion.api.type.types.version; import io.netty.buffer.ByteBuf; import us.myles.ViaVersion.api.minecraft.metadata.Metadata; +import us.myles.ViaVersion.api.minecraft.metadata.types.MetaType1_8; import us.myles.ViaVersion.api.type.types.minecraft.MetaTypeTemplate; -import us.myles.ViaVersion.protocols.protocol1_9to1_8.metadata.MetadataTypes; public class Metadata1_8Type extends MetaTypeTemplate { @@ -13,15 +13,15 @@ public class Metadata1_8Type extends MetaTypeTemplate { byte item = buffer.readByte(); if (item == 127) return null; // end of metadata int typeID = (item & 0xE0) >> 5; - MetadataTypes type = MetadataTypes.byId(typeID); + MetaType1_8 type = MetaType1_8.byId(typeID); int id = item & 0x1F; - return new Metadata(id, typeID, type.getType(), type.getType().read(buffer)); + return new Metadata(id, type, type.getType().read(buffer)); } @Override public void write(ByteBuf buffer, Metadata meta) throws Exception { - byte item = (byte) (meta.getTypeID() << 5 | meta.getId() & 0x1F); + byte item = (byte) (meta.getMetaType().getTypeID() << 5 | meta.getId() & 0x1F); buffer.writeByte(item); - meta.getType().write(buffer, meta.getValue()); + meta.getMetaType().getType().write(buffer, meta.getValue()); } } diff --git a/src/main/java/us/myles/ViaVersion/api/type/types/version/Metadata1_9Type.java b/common/src/main/java/us/myles/ViaVersion/api/type/types/version/Metadata1_9Type.java similarity index 66% rename from src/main/java/us/myles/ViaVersion/api/type/types/version/Metadata1_9Type.java rename to common/src/main/java/us/myles/ViaVersion/api/type/types/version/Metadata1_9Type.java index fb541263c..7d87f7931 100644 --- a/src/main/java/us/myles/ViaVersion/api/type/types/version/Metadata1_9Type.java +++ b/common/src/main/java/us/myles/ViaVersion/api/type/types/version/Metadata1_9Type.java @@ -2,8 +2,8 @@ package us.myles.ViaVersion.api.type.types.version; import io.netty.buffer.ByteBuf; import us.myles.ViaVersion.api.minecraft.metadata.Metadata; +import us.myles.ViaVersion.api.minecraft.metadata.types.MetaType1_9; import us.myles.ViaVersion.api.type.types.minecraft.MetaTypeTemplate; -import us.myles.ViaVersion.protocols.protocol1_9to1_8.metadata.NewType; public class Metadata1_9Type extends MetaTypeTemplate { @@ -12,9 +12,9 @@ public class Metadata1_9Type extends MetaTypeTemplate { short index = buffer.readUnsignedByte(); if (index == 0xff) return null; //End of metadata - NewType type = NewType.byId(buffer.readByte()); + MetaType1_9 type = MetaType1_9.byId(buffer.readByte()); - return new Metadata(index, type.getTypeID(), type.getType(), type.getType().read(buffer)); + return new Metadata(index, type, type.getType().read(buffer)); } @Override @@ -23,8 +23,8 @@ public class Metadata1_9Type extends MetaTypeTemplate { buffer.writeByte(255); } else { buffer.writeByte(object.getId()); - buffer.writeByte(object.getTypeID()); - object.getType().write(buffer, object.getValue()); + buffer.writeByte(object.getMetaType().getTypeID()); + object.getMetaType().getType().write(buffer, object.getValue()); } } } diff --git a/src/main/java/us/myles/ViaVersion/api/type/types/version/MetadataList1_8Type.java b/common/src/main/java/us/myles/ViaVersion/api/type/types/version/MetadataList1_8Type.java similarity index 100% rename from src/main/java/us/myles/ViaVersion/api/type/types/version/MetadataList1_8Type.java rename to common/src/main/java/us/myles/ViaVersion/api/type/types/version/MetadataList1_8Type.java diff --git a/src/main/java/us/myles/ViaVersion/api/type/types/version/MetadataList1_9Type.java b/common/src/main/java/us/myles/ViaVersion/api/type/types/version/MetadataList1_9Type.java similarity index 100% rename from src/main/java/us/myles/ViaVersion/api/type/types/version/MetadataList1_9Type.java rename to common/src/main/java/us/myles/ViaVersion/api/type/types/version/MetadataList1_9Type.java diff --git a/src/main/java/us/myles/ViaVersion/api/type/types/version/Types1_8.java b/common/src/main/java/us/myles/ViaVersion/api/type/types/version/Types1_8.java similarity index 65% rename from src/main/java/us/myles/ViaVersion/api/type/types/version/Types1_8.java rename to common/src/main/java/us/myles/ViaVersion/api/type/types/version/Types1_8.java index cb0241801..49ca88fae 100644 --- a/src/main/java/us/myles/ViaVersion/api/type/types/version/Types1_8.java +++ b/common/src/main/java/us/myles/ViaVersion/api/type/types/version/Types1_8.java @@ -9,10 +9,10 @@ public class Types1_8 { /** * Metadata list type for 1.8 */ - public static Type> METADATA_LIST = new MetadataList1_8Type(); + public static final Type> METADATA_LIST = new MetadataList1_8Type(); /** * Metadata type for 1.8 */ - public static Type METADATA = new Metadata1_8Type(); + public static final Type METADATA = new Metadata1_8Type(); } diff --git a/src/main/java/us/myles/ViaVersion/api/type/types/version/Types1_9.java b/common/src/main/java/us/myles/ViaVersion/api/type/types/version/Types1_9.java similarity index 100% rename from src/main/java/us/myles/ViaVersion/api/type/types/version/Types1_9.java rename to common/src/main/java/us/myles/ViaVersion/api/type/types/version/Types1_9.java diff --git a/src/main/java/us/myles/ViaVersion/boss/ViaBossBar.java b/common/src/main/java/us/myles/ViaVersion/boss/CommonBoss.java similarity index 76% rename from src/main/java/us/myles/ViaVersion/boss/ViaBossBar.java rename to common/src/main/java/us/myles/ViaVersion/boss/CommonBoss.java index eacbbfa86..7cc89d0c5 100644 --- a/src/main/java/us/myles/ViaVersion/boss/ViaBossBar.java +++ b/common/src/main/java/us/myles/ViaVersion/boss/CommonBoss.java @@ -1,13 +1,12 @@ package us.myles.ViaVersion.boss; +import com.google.common.base.Preconditions; import io.netty.buffer.ByteBuf; import io.netty.buffer.Unpooled; import lombok.Getter; import lombok.NonNull; import lombok.RequiredArgsConstructor; -import org.apache.commons.lang.Validate; -import org.bukkit.entity.Player; -import us.myles.ViaVersion.api.ViaVersion; +import us.myles.ViaVersion.api.Via; import us.myles.ViaVersion.api.boss.BossBar; import us.myles.ViaVersion.api.boss.BossColor; import us.myles.ViaVersion.api.boss.BossFlag; @@ -19,7 +18,7 @@ import us.myles.ViaVersion.protocols.protocol1_9to1_8.Protocol1_9TO1_8; import java.util.*; @Getter -public class ViaBossBar implements BossBar { +public abstract class CommonBoss extends BossBar { private UUID uuid; private String title; private float health; @@ -29,9 +28,10 @@ public class ViaBossBar implements BossBar { private boolean visible; private Set flags; - public ViaBossBar(String title, float health, BossColor color, BossStyle style) { - Validate.notNull(title, "Title cannot be null"); - Validate.isTrue((health >= 0 && health <= 1), "Health must be between 0 and 1"); + public CommonBoss(String title, float health, BossColor color, BossStyle style) { + Preconditions.checkNotNull(title, "Title cannot be null"); + Preconditions.checkArgument((health >= 0 && health <= 1), "Health must be between 0 and 1"); + this.uuid = UUID.randomUUID(); this.title = title; this.health = health; @@ -45,15 +45,15 @@ public class ViaBossBar implements BossBar { @Override public BossBar setTitle(@NonNull String title) { this.title = title; - sendPacket(UpdateAction.UPDATE_TITLE); + sendPacket(CommonBoss.UpdateAction.UPDATE_TITLE); return this; } @Override public BossBar setHealth(float health) { - Validate.isTrue((health >= 0 && health <= 1), "Health must be between 0 and 1"); + Preconditions.checkArgument((health >= 0 && health <= 1), "Health must be between 0 and 1"); this.health = health; - sendPacket(UpdateAction.UPDATE_HEALTH); + sendPacket(CommonBoss.UpdateAction.UPDATE_HEALTH); return this; } @@ -65,53 +65,41 @@ public class ViaBossBar implements BossBar { @Override public BossBar setColor(@NonNull BossColor color) { this.color = color; - sendPacket(UpdateAction.UPDATE_STYLE); + sendPacket(CommonBoss.UpdateAction.UPDATE_STYLE); return this; } @Override public BossBar setStyle(@NonNull BossStyle style) { this.style = style; - sendPacket(UpdateAction.UPDATE_STYLE); + sendPacket(CommonBoss.UpdateAction.UPDATE_STYLE); return this; } - @Override - public BossBar addPlayer(@NonNull Player player) { - return addPlayer(player.getUniqueId()); - } - @Override public BossBar addPlayer(UUID player) { if (!players.contains(player)) { players.add(player); if (visible) - sendPacket(player, getPacket(UpdateAction.ADD)); + sendPacket(player, getPacket(CommonBoss.UpdateAction.ADD)); } return this; } @Override - public BossBar removePlayer(@NonNull Player player) { - if (players.contains(player.getUniqueId())) { - players.remove(player.getUniqueId()); - sendPacket(player.getUniqueId(), getPacket(UpdateAction.REMOVE)); + public BossBar removePlayer(UUID uuid) { + if (players.contains(uuid)) { + players.remove(uuid); + sendPacket(uuid, getPacket(UpdateAction.REMOVE)); } return this; } - @Override - public BossBar addPlayers(@NonNull Player... players) { - for (Player p : players) - addPlayer(p); - return this; - } - @Override public BossBar addFlag(@NonNull BossFlag flag) { if (!hasFlag(flag)) flags.add(flag); - sendPacket(UpdateAction.UPDATE_FLAGS); + sendPacket(CommonBoss.UpdateAction.UPDATE_FLAGS); return this; } @@ -119,7 +107,7 @@ public class ViaBossBar implements BossBar { public BossBar removeFlag(@NonNull BossFlag flag) { if (hasFlag(flag)) flags.remove(flag); - sendPacket(UpdateAction.UPDATE_FLAGS); + sendPacket(CommonBoss.UpdateAction.UPDATE_FLAGS); return this; } @@ -153,7 +141,7 @@ public class ViaBossBar implements BossBar { private void setVisible(boolean value) { if (visible != value) { visible = value; - sendPacket(value ? UpdateAction.ADD : UpdateAction.REMOVE); + sendPacket(value ? CommonBoss.UpdateAction.ADD : CommonBoss.UpdateAction.REMOVE); } } @@ -165,12 +153,12 @@ public class ViaBossBar implements BossBar { } private void sendPacket(UUID uuid, ByteBuf buf) { - if (!ViaVersion.getInstance().isPorted(uuid) || !(ViaVersion.getInstance().getPlayerVersion(uuid) >= ProtocolVersion.v1_9.getId())) { + if (!Via.getAPI().isPorted(uuid) || !(Via.getAPI().getPlayerVersion(uuid) >= ProtocolVersion.v1_9.getId())) { players.remove(uuid); buf.release(); return; } - ViaVersion.getInstance().sendRawPacket(uuid, buf); + Via.getAPI().sendRawPacket(uuid, buf); } private ByteBuf getPacket(UpdateAction action) { diff --git a/src/main/java/us/myles/ViaVersion/commands/ViaCommandHandler.java b/common/src/main/java/us/myles/ViaVersion/commands/ViaCommandHandler.java similarity index 73% rename from src/main/java/us/myles/ViaVersion/commands/ViaCommandHandler.java rename to common/src/main/java/us/myles/ViaVersion/commands/ViaCommandHandler.java index c67230529..00ac8421b 100644 --- a/src/main/java/us/myles/ViaVersion/commands/ViaCommandHandler.java +++ b/common/src/main/java/us/myles/ViaVersion/commands/ViaCommandHandler.java @@ -1,21 +1,18 @@ package us.myles.ViaVersion.commands; +import com.google.common.base.Preconditions; import lombok.NonNull; -import org.apache.commons.lang.Validate; -import org.bukkit.ChatColor; -import org.bukkit.command.Command; -import org.bukkit.command.CommandExecutor; -import org.bukkit.command.CommandSender; -import org.bukkit.command.TabCompleter; -import us.myles.ViaVersion.api.ViaVersion; +import net.md_5.bungee.api.ChatColor; +import us.myles.ViaVersion.api.Via; +import us.myles.ViaVersion.api.command.ViaCommandSender; import us.myles.ViaVersion.api.command.ViaSubCommand; import us.myles.ViaVersion.api.command.ViaVersionCommand; import us.myles.ViaVersion.commands.defaultsubs.*; import java.util.*; -public class ViaCommandHandler implements ViaVersionCommand, CommandExecutor, TabCompleter { - private Map commandMap; +public abstract class ViaCommandHandler implements ViaVersionCommand { + private final Map commandMap; public ViaCommandHandler() { commandMap = new HashMap<>(); @@ -28,7 +25,7 @@ public class ViaCommandHandler implements ViaVersionCommand, CommandExecutor, Ta @Override public void registerSubCommand(@NonNull ViaSubCommand command) throws Exception { - Validate.isTrue(command.name().matches("^[a-z0-9_-]{3,15}$"), command.name() + " is not a valid subcommand name"); + Preconditions.checkArgument(command.name().matches("^[a-z0-9_-]{3,15}$"), command.name() + " is not a valid subcommand name"); if (hasSubCommand(command.name())) throw new Exception("ViaSubCommand " + command.name() + " does already exists!"); //Maybe another exception later. commandMap.put(command.name().toLowerCase(), command); @@ -45,21 +42,21 @@ public class ViaCommandHandler implements ViaVersionCommand, CommandExecutor, Ta } @Override - public boolean onCommand(CommandSender sender, Command cmd, String arg, String[] args) { + public boolean onCommand(ViaCommandSender sender, String[] args) { if (args.length == 0) { showHelp(sender); return false; } if (!hasSubCommand(args[0])) { - sender.sendMessage(color("&cThis command is not found")); + sender.sendMessage(color("&cThis commands is not found")); showHelp(sender); return false; } ViaSubCommand handler = getSubCommand(args[0]); if (!hasPermission(sender, handler.permission())) { - sender.sendMessage(color("&cYou are not allowed to use this command!")); + sender.sendMessage(color("&cYou are not allowed to use this commands!")); return false; } @@ -71,7 +68,7 @@ public class ViaCommandHandler implements ViaVersionCommand, CommandExecutor, Ta } @Override - public List onTabComplete(CommandSender sender, Command command, String arg, String[] args) { + public List onTabComplete(ViaCommandSender sender, String[] args) { Set allowed = calculateAllowedCommands(sender); List output = new ArrayList<>(); @@ -103,20 +100,25 @@ public class ViaCommandHandler implements ViaVersionCommand, CommandExecutor, Ta return output; } - public void showHelp(CommandSender sender) { + /** + * Shows the ViaVersion help to a sender + * + * @param sender The sender to send the help to + */ + public void showHelp(ViaCommandSender sender) { Set allowed = calculateAllowedCommands(sender); if (allowed.size() == 0) { - sender.sendMessage(color("&cYou are not allowed to use this command!")); + sender.sendMessage(color("&cYou are not allowed to use this commands!")); return; } - sender.sendMessage(color("&aViaVersion &c" + ViaVersion.getInstance().getVersion())); + sender.sendMessage(color("&aViaVersion &c" + Via.getPlatform().getPluginVersion())); sender.sendMessage(color("&6Commands:")); for (ViaSubCommand cmd : allowed) sender.sendMessage(color(String.format("&2/viaversion %s &7- &6%s", cmd.usage(), cmd.description()))); allowed.clear(); } - private Set calculateAllowedCommands(CommandSender sender) { + private Set calculateAllowedCommands(ViaCommandSender sender) { Set cmds = new HashSet<>(); for (ViaSubCommand sub : commandMap.values()) if (hasPermission(sender, sub.permission())) @@ -124,7 +126,7 @@ public class ViaCommandHandler implements ViaVersionCommand, CommandExecutor, Ta return cmds; } - private boolean hasPermission(CommandSender sender, String permission) { + private boolean hasPermission(ViaCommandSender sender, String permission) { return permission == null || sender.hasPermission(permission); } @@ -140,6 +142,12 @@ public class ViaCommandHandler implements ViaVersionCommand, CommandExecutor, Ta registerSubCommand(new ReloadSubCmd()); } + /** + * Replaces colour codes in a string + * + * @param string String to replace + * @return The output String + */ public static String color(String string) { try { string = ChatColor.translateAlternateColorCodes('&', string); //Dont replace all & with $ like we did before. @@ -148,7 +156,14 @@ public class ViaCommandHandler implements ViaVersionCommand, CommandExecutor, Ta return string; } - public static void sendMessage(@NonNull CommandSender sender, String message, Object... args) { + /** + * Send a colour coded string with replacements to a user + * + * @param sender The target to send the message to + * @param message The message + * @param args The objects to replace + */ + public static void sendMessage(@NonNull ViaCommandSender sender, String message, Object... args) { sender.sendMessage(color(args == null ? message : String.format(message, args))); } } diff --git a/src/main/java/us/myles/ViaVersion/commands/defaultsubs/AutoTeamSubCmd.java b/common/src/main/java/us/myles/ViaVersion/commands/defaultsubs/AutoTeamSubCmd.java similarity index 58% rename from src/main/java/us/myles/ViaVersion/commands/defaultsubs/AutoTeamSubCmd.java rename to common/src/main/java/us/myles/ViaVersion/commands/defaultsubs/AutoTeamSubCmd.java index 0217f12d8..eeecc9188 100644 --- a/src/main/java/us/myles/ViaVersion/commands/defaultsubs/AutoTeamSubCmd.java +++ b/common/src/main/java/us/myles/ViaVersion/commands/defaultsubs/AutoTeamSubCmd.java @@ -1,9 +1,9 @@ package us.myles.ViaVersion.commands.defaultsubs; -import org.bukkit.command.CommandSender; -import us.myles.ViaVersion.ViaVersionPlugin; -import us.myles.ViaVersion.api.ViaVersion; +import us.myles.ViaVersion.api.Via; +import us.myles.ViaVersion.api.command.ViaCommandSender; import us.myles.ViaVersion.api.command.ViaSubCommand; +import us.myles.ViaVersion.api.configuration.ConfigurationProvider; public class AutoTeamSubCmd extends ViaSubCommand { @Override @@ -17,12 +17,12 @@ public class AutoTeamSubCmd extends ViaSubCommand { } @Override - public boolean execute(CommandSender sender, String[] args) { - ViaVersionPlugin plugin = (ViaVersionPlugin) ViaVersion.getInstance(); + public boolean execute(ViaCommandSender sender, String[] args) { + ConfigurationProvider provider = Via.getPlatform().getConfigurationProvider(); + boolean newValue = !Via.getConfig().isAutoTeam(); - boolean newValue = !ViaVersion.getConfig().isAutoTeam(); - plugin.getConfig().set("auto-team", newValue); - plugin.saveConfig(); + provider.set("auto-team", newValue); + provider.saveConfig(); sendMessage(sender, "&6We will %s", (newValue ? "&aautomatically team players" : "&cno longer auto team players")); sendMessage(sender, "&6All players will need to re-login for the change to take place."); diff --git a/common/src/main/java/us/myles/ViaVersion/commands/defaultsubs/DebugSubCmd.java b/common/src/main/java/us/myles/ViaVersion/commands/defaultsubs/DebugSubCmd.java new file mode 100644 index 000000000..47396264c --- /dev/null +++ b/common/src/main/java/us/myles/ViaVersion/commands/defaultsubs/DebugSubCmd.java @@ -0,0 +1,24 @@ +package us.myles.ViaVersion.commands.defaultsubs; + +import us.myles.ViaVersion.api.Via; +import us.myles.ViaVersion.api.command.ViaCommandSender; +import us.myles.ViaVersion.api.command.ViaSubCommand; + +public class DebugSubCmd extends ViaSubCommand { + @Override + public String name() { + return "debug"; + } + + @Override + public String description() { + return "Toggle debug mode"; + } + + @Override + public boolean execute(ViaCommandSender sender, String[] args) { + Via.getManager().setDebug(!Via.getManager().isDebug()); + sendMessage(sender, "&6Debug mode is now %s", (Via.getManager().isDebug() ? "&aenabled" : "&cdisabled")); + return true; + } +} diff --git a/src/main/java/us/myles/ViaVersion/commands/defaultsubs/DisplayLeaksSubCmd.java b/common/src/main/java/us/myles/ViaVersion/commands/defaultsubs/DisplayLeaksSubCmd.java similarity index 87% rename from src/main/java/us/myles/ViaVersion/commands/defaultsubs/DisplayLeaksSubCmd.java rename to common/src/main/java/us/myles/ViaVersion/commands/defaultsubs/DisplayLeaksSubCmd.java index 8701d9f6f..5710105db 100644 --- a/src/main/java/us/myles/ViaVersion/commands/defaultsubs/DisplayLeaksSubCmd.java +++ b/common/src/main/java/us/myles/ViaVersion/commands/defaultsubs/DisplayLeaksSubCmd.java @@ -1,7 +1,7 @@ package us.myles.ViaVersion.commands.defaultsubs; import io.netty.util.ResourceLeakDetector; -import org.bukkit.command.CommandSender; +import us.myles.ViaVersion.api.command.ViaCommandSender; import us.myles.ViaVersion.api.command.ViaSubCommand; public class DisplayLeaksSubCmd extends ViaSubCommand { @@ -16,7 +16,7 @@ public class DisplayLeaksSubCmd extends ViaSubCommand { } @Override - public boolean execute(CommandSender sender, String[] args) { + public boolean execute(ViaCommandSender sender, String[] args) { if (ResourceLeakDetector.getLevel() != ResourceLeakDetector.Level.ADVANCED) ResourceLeakDetector.setLevel(ResourceLeakDetector.Level.ADVANCED); else diff --git a/src/main/java/us/myles/ViaVersion/commands/defaultsubs/DontBugMeSubCmd.java b/common/src/main/java/us/myles/ViaVersion/commands/defaultsubs/DontBugMeSubCmd.java similarity index 50% rename from src/main/java/us/myles/ViaVersion/commands/defaultsubs/DontBugMeSubCmd.java rename to common/src/main/java/us/myles/ViaVersion/commands/defaultsubs/DontBugMeSubCmd.java index f99936c0d..95d92d27d 100644 --- a/src/main/java/us/myles/ViaVersion/commands/defaultsubs/DontBugMeSubCmd.java +++ b/common/src/main/java/us/myles/ViaVersion/commands/defaultsubs/DontBugMeSubCmd.java @@ -1,9 +1,9 @@ package us.myles.ViaVersion.commands.defaultsubs; -import org.bukkit.command.CommandSender; -import us.myles.ViaVersion.ViaVersionPlugin; -import us.myles.ViaVersion.api.ViaVersion; +import us.myles.ViaVersion.api.Via; +import us.myles.ViaVersion.api.command.ViaCommandSender; import us.myles.ViaVersion.api.command.ViaSubCommand; +import us.myles.ViaVersion.api.configuration.ConfigurationProvider; public class DontBugMeSubCmd extends ViaSubCommand { @Override @@ -17,12 +17,12 @@ public class DontBugMeSubCmd extends ViaSubCommand { } @Override - public boolean execute(CommandSender sender, String[] args) { - ViaVersionPlugin plugin = (ViaVersionPlugin) ViaVersion.getInstance(); + public boolean execute(ViaCommandSender sender, String[] args) { + ConfigurationProvider provider = Via.getPlatform().getConfigurationProvider(); + boolean newValue = !Via.getConfig().isCheckForUpdates(); - boolean newValue = !ViaVersion.getConfig().isCheckForUpdates(); - plugin.getConfig().set("checkforupdates", newValue); - plugin.saveConfig(); + provider.set("checkforupdates", newValue); + provider.saveConfig(); sendMessage(sender, "&6We will %snotify you about updates.", (newValue ? "&a" : "&cnot ")); return true; diff --git a/src/main/java/us/myles/ViaVersion/commands/defaultsubs/DumpSubCmd.java b/common/src/main/java/us/myles/ViaVersion/commands/defaultsubs/DumpSubCmd.java similarity index 58% rename from src/main/java/us/myles/ViaVersion/commands/defaultsubs/DumpSubCmd.java rename to common/src/main/java/us/myles/ViaVersion/commands/defaultsubs/DumpSubCmd.java index 03ad3472d..6c99ee559 100644 --- a/src/main/java/us/myles/ViaVersion/commands/defaultsubs/DumpSubCmd.java +++ b/common/src/main/java/us/myles/ViaVersion/commands/defaultsubs/DumpSubCmd.java @@ -1,19 +1,14 @@ package us.myles.ViaVersion.commands.defaultsubs; -import com.google.gson.Gson; -import com.google.gson.GsonBuilder; import com.google.gson.JsonObject; -import org.bukkit.Bukkit; -import org.bukkit.ChatColor; -import org.bukkit.command.CommandSender; -import org.bukkit.plugin.Plugin; -import us.myles.ViaVersion.ViaVersionPlugin; -import us.myles.ViaVersion.api.ViaVersion; +import net.md_5.bungee.api.ChatColor; +import us.myles.ViaVersion.api.Via; +import us.myles.ViaVersion.api.command.ViaCommandSender; import us.myles.ViaVersion.api.command.ViaSubCommand; import us.myles.ViaVersion.api.protocol.ProtocolRegistry; import us.myles.ViaVersion.dump.DumpTemplate; -import us.myles.ViaVersion.dump.PluginInfo; import us.myles.ViaVersion.dump.VersionInfo; +import us.myles.ViaVersion.util.GsonUtil; import java.io.InputStreamReader; import java.io.InvalidObjectException; @@ -21,13 +16,10 @@ import java.io.OutputStream; import java.net.HttpURLConnection; import java.net.URL; import java.nio.charset.Charset; -import java.util.ArrayList; -import java.util.List; import java.util.Map; import java.util.logging.Level; public class DumpSubCmd extends ViaSubCommand { - private final Gson gson = new GsonBuilder().setPrettyPrinting().create(); @Override public String name() { @@ -40,24 +32,21 @@ public class DumpSubCmd extends ViaSubCommand { } @Override - public boolean execute(final CommandSender sender, String[] args) { + public boolean execute(final ViaCommandSender sender, String[] args) { VersionInfo version = new VersionInfo( - Bukkit.getServer().getVersion(), - Bukkit.getServer().getBukkitVersion(), System.getProperty("java.version"), System.getProperty("os.name"), ProtocolRegistry.SERVER_PROTOCOL, - ProtocolRegistry.getSupportedVersions()); + ProtocolRegistry.getSupportedVersions(), + Via.getPlatform().getPlatformName(), + Via.getPlatform().getPluginVersion() + ); - List plugins = new ArrayList<>(); - for (Plugin p : Bukkit.getPluginManager().getPlugins()) - plugins.add(new PluginInfo(p.isEnabled(), p.getDescription().getName(), p.getDescription().getVersion(), p.getDescription().getMain(), p.getDescription().getAuthors())); + Map configuration = Via.getPlatform().getConfigurationProvider().getValues(); - Map configuration = ((ViaVersionPlugin) ViaVersion.getInstance()).getConfig().getValues(false); + final DumpTemplate template = new DumpTemplate(version, configuration, Via.getPlatform().getDump()); - final DumpTemplate template = new DumpTemplate(version, configuration, plugins); - - Bukkit.getScheduler().runTaskAsynchronously((ViaVersionPlugin) ViaVersion.getInstance(), new Runnable() { + Via.getPlatform().runAsync(new Runnable() { @Override public void run() { try { @@ -68,10 +57,10 @@ public class DumpSubCmd extends ViaSubCommand { con.setDoOutput(true); OutputStream out = con.getOutputStream(); - out.write(gson.toJson(template).getBytes(Charset.forName("UTF-8"))); + out.write(GsonUtil.getGsonBuilder().setPrettyPrinting().create().toJson(template).getBytes(Charset.forName("UTF-8"))); out.close(); - JsonObject output = gson.fromJson(new InputStreamReader(con.getInputStream()), JsonObject.class); + JsonObject output = GsonUtil.getGson().fromJson(new InputStreamReader(con.getInputStream()), JsonObject.class); con.getInputStream().close(); if (!output.has("key")) @@ -80,7 +69,7 @@ public class DumpSubCmd extends ViaSubCommand { sender.sendMessage(ChatColor.GREEN + "We've made a dump with useful information, report your issue and provide this url: " + getUrl(output.get("key").getAsString())); } catch (Exception e) { sender.sendMessage(ChatColor.RED + "Failed to dump, please check the console for more information"); - ((ViaVersionPlugin) ViaVersion.getInstance()).getLogger().log(Level.WARNING, "Could not paste ViaVersion dump to Hastebin", e); + Via.getPlatform().getLogger().log(Level.WARNING, "Could not paste ViaVersion dump to Hastebin", e); } } }); diff --git a/common/src/main/java/us/myles/ViaVersion/commands/defaultsubs/HelpSubCmd.java b/common/src/main/java/us/myles/ViaVersion/commands/defaultsubs/HelpSubCmd.java new file mode 100644 index 000000000..96983349a --- /dev/null +++ b/common/src/main/java/us/myles/ViaVersion/commands/defaultsubs/HelpSubCmd.java @@ -0,0 +1,23 @@ +package us.myles.ViaVersion.commands.defaultsubs; + +import us.myles.ViaVersion.api.Via; +import us.myles.ViaVersion.api.command.ViaCommandSender; +import us.myles.ViaVersion.api.command.ViaSubCommand; + +public class HelpSubCmd extends ViaSubCommand { + @Override + public String name() { + return "help"; + } + + @Override + public String description() { + return "You are looking at it right now!"; + } + + @Override + public boolean execute(ViaCommandSender sender, String[] args) { + Via.getManager().getCommandHandler().showHelp(sender); + return true; + } +} diff --git a/src/main/java/us/myles/ViaVersion/commands/defaultsubs/ListSubCmd.java b/common/src/main/java/us/myles/ViaVersion/commands/defaultsubs/ListSubCmd.java similarity index 79% rename from src/main/java/us/myles/ViaVersion/commands/defaultsubs/ListSubCmd.java rename to common/src/main/java/us/myles/ViaVersion/commands/defaultsubs/ListSubCmd.java index 2c85a6de6..c1e8e8458 100644 --- a/src/main/java/us/myles/ViaVersion/commands/defaultsubs/ListSubCmd.java +++ b/common/src/main/java/us/myles/ViaVersion/commands/defaultsubs/ListSubCmd.java @@ -1,9 +1,7 @@ package us.myles.ViaVersion.commands.defaultsubs; -import org.bukkit.Bukkit; -import org.bukkit.command.CommandSender; -import org.bukkit.entity.Player; -import us.myles.ViaVersion.api.ViaVersion; +import us.myles.ViaVersion.api.Via; +import us.myles.ViaVersion.api.command.ViaCommandSender; import us.myles.ViaVersion.api.command.ViaSubCommand; import us.myles.ViaVersion.api.protocol.ProtocolVersion; @@ -26,7 +24,7 @@ public class ListSubCmd extends ViaSubCommand { } @Override - public boolean execute(CommandSender sender, String[] args) { + public boolean execute(ViaCommandSender sender, String[] args) { Map> playerVersions = new TreeMap<>(new Comparator() { @Override public int compare(ProtocolVersion o1, ProtocolVersion o2) { @@ -34,8 +32,8 @@ public class ListSubCmd extends ViaSubCommand { } }); - for (Player p : Bukkit.getOnlinePlayers()) { - int playerVersion = ViaVersion.getInstance().getPlayerVersion(p); + for (ViaCommandSender p : Via.getPlatform().getOnlinePlayers()) { + int playerVersion = Via.getAPI().getPlayerVersion(p.getUUID()); ProtocolVersion key = ProtocolVersion.getProtocol(playerVersion); if (!playerVersions.containsKey(key)) playerVersions.put(key, new HashSet()); diff --git a/src/main/java/us/myles/ViaVersion/commands/defaultsubs/PPSSubCmd.java b/common/src/main/java/us/myles/ViaVersion/commands/defaultsubs/PPSSubCmd.java similarity index 77% rename from src/main/java/us/myles/ViaVersion/commands/defaultsubs/PPSSubCmd.java rename to common/src/main/java/us/myles/ViaVersion/commands/defaultsubs/PPSSubCmd.java index d2e7bc186..69890b3b5 100644 --- a/src/main/java/us/myles/ViaVersion/commands/defaultsubs/PPSSubCmd.java +++ b/common/src/main/java/us/myles/ViaVersion/commands/defaultsubs/PPSSubCmd.java @@ -1,10 +1,7 @@ package us.myles.ViaVersion.commands.defaultsubs; -import org.bukkit.Bukkit; -import org.bukkit.command.CommandSender; -import org.bukkit.entity.Player; -import us.myles.ViaVersion.ViaVersionPlugin; -import us.myles.ViaVersion.api.ViaVersion; +import us.myles.ViaVersion.api.Via; +import us.myles.ViaVersion.api.command.ViaCommandSender; import us.myles.ViaVersion.api.command.ViaSubCommand; import us.myles.ViaVersion.api.data.UserConnection; import us.myles.ViaVersion.api.protocol.ProtocolVersion; @@ -28,19 +25,17 @@ public class PPSSubCmd extends ViaSubCommand { } @Override - public boolean execute(CommandSender sender, String[] args) { + public boolean execute(ViaCommandSender sender, String[] args) { Map> playerVersions = new HashMap<>(); int totalPackets = 0; int clients = 0; long max = 0; - for (Player p : Bukkit.getOnlinePlayers()) { - if (!ViaVersion.getInstance().isPorted(p)) - continue; - int playerVersion = ViaVersion.getInstance().getPlayerVersion(p); + for (ViaCommandSender p : Via.getPlatform().getOnlinePlayers()) { + int playerVersion = Via.getAPI().getPlayerVersion(p.getUUID()); if (!playerVersions.containsKey(playerVersion)) playerVersions.put(playerVersion, new HashSet()); - UserConnection uc = ((ViaVersionPlugin) ViaVersion.getInstance()).getConnection(p); + UserConnection uc = Via.getManager().getConnection(p.getUUID()); if (uc.getPacketsPerSecond() > -1) { playerVersions.get(playerVersion).add(p.getName() + " (" + uc.getPacketsPerSecond() + " PPS)"); totalPackets += uc.getPacketsPerSecond(); diff --git a/src/main/java/us/myles/ViaVersion/commands/defaultsubs/ReloadSubCmd.java b/common/src/main/java/us/myles/ViaVersion/commands/defaultsubs/ReloadSubCmd.java similarity index 60% rename from src/main/java/us/myles/ViaVersion/commands/defaultsubs/ReloadSubCmd.java rename to common/src/main/java/us/myles/ViaVersion/commands/defaultsubs/ReloadSubCmd.java index 9a25e6c13..8a1bf109c 100644 --- a/src/main/java/us/myles/ViaVersion/commands/defaultsubs/ReloadSubCmd.java +++ b/common/src/main/java/us/myles/ViaVersion/commands/defaultsubs/ReloadSubCmd.java @@ -1,8 +1,7 @@ package us.myles.ViaVersion.commands.defaultsubs; -import org.bukkit.command.CommandSender; -import us.myles.ViaVersion.ViaVersionPlugin; -import us.myles.ViaVersion.api.ViaVersion; +import us.myles.ViaVersion.api.Via; +import us.myles.ViaVersion.api.command.ViaCommandSender; import us.myles.ViaVersion.api.command.ViaSubCommand; public class ReloadSubCmd extends ViaSubCommand { @@ -17,10 +16,8 @@ public class ReloadSubCmd extends ViaSubCommand { } @Override - public boolean execute(CommandSender sender, String[] args) { - ViaVersionPlugin plugin = (ViaVersionPlugin) ViaVersion.getInstance(); - - plugin.getConf().generateConfig(); + public boolean execute(ViaCommandSender sender, String[] args) { + Via.getPlatform().getConfigurationProvider().reloadConfig(); sendMessage(sender, "&6Configuration successfully reloaded! Some features may need a restart."); return true; } diff --git a/src/main/java/us/myles/ViaVersion/dump/DumpTemplate.java b/common/src/main/java/us/myles/ViaVersion/dump/DumpTemplate.java similarity index 77% rename from src/main/java/us/myles/ViaVersion/dump/DumpTemplate.java rename to common/src/main/java/us/myles/ViaVersion/dump/DumpTemplate.java index e6b5451ba..6c35344a6 100644 --- a/src/main/java/us/myles/ViaVersion/dump/DumpTemplate.java +++ b/common/src/main/java/us/myles/ViaVersion/dump/DumpTemplate.java @@ -1,9 +1,9 @@ package us.myles.ViaVersion.dump; +import com.google.gson.JsonObject; import lombok.AllArgsConstructor; import lombok.Data; -import java.util.List; import java.util.Map; @Data @@ -11,5 +11,5 @@ import java.util.Map; public class DumpTemplate { private VersionInfo versionInfo; private Map configuration; - private List plugins; + private JsonObject platformDump; } diff --git a/src/main/java/us/myles/ViaVersion/dump/PluginInfo.java b/common/src/main/java/us/myles/ViaVersion/dump/PluginInfo.java similarity index 100% rename from src/main/java/us/myles/ViaVersion/dump/PluginInfo.java rename to common/src/main/java/us/myles/ViaVersion/dump/PluginInfo.java diff --git a/src/main/java/us/myles/ViaVersion/dump/VersionInfo.java b/common/src/main/java/us/myles/ViaVersion/dump/VersionInfo.java similarity index 81% rename from src/main/java/us/myles/ViaVersion/dump/VersionInfo.java rename to common/src/main/java/us/myles/ViaVersion/dump/VersionInfo.java index 75dcef344..9e0da92de 100644 --- a/src/main/java/us/myles/ViaVersion/dump/VersionInfo.java +++ b/common/src/main/java/us/myles/ViaVersion/dump/VersionInfo.java @@ -8,11 +8,11 @@ import java.util.Set; @Data @AllArgsConstructor public class VersionInfo { - private String version; - private String bukkitVersion; private String javaVersion; private String operatingSystem; private int serverProtocol; private Set enabledPipelines; + private String platformName; + private String platformVersion; } diff --git a/src/main/java/us/myles/ViaVersion/exception/CancelException.java b/common/src/main/java/us/myles/ViaVersion/exception/CancelException.java similarity index 100% rename from src/main/java/us/myles/ViaVersion/exception/CancelException.java rename to common/src/main/java/us/myles/ViaVersion/exception/CancelException.java diff --git a/src/main/java/us/myles/ViaVersion/exception/InformativeException.java b/common/src/main/java/us/myles/ViaVersion/exception/InformativeException.java similarity index 96% rename from src/main/java/us/myles/ViaVersion/exception/InformativeException.java rename to common/src/main/java/us/myles/ViaVersion/exception/InformativeException.java index 6599eb0a0..3cad1f55a 100644 --- a/src/main/java/us/myles/ViaVersion/exception/InformativeException.java +++ b/common/src/main/java/us/myles/ViaVersion/exception/InformativeException.java @@ -4,7 +4,7 @@ import java.util.HashMap; import java.util.Map; public class InformativeException extends Exception { - Map info = new HashMap<>(); + final Map info = new HashMap<>(); int sources = 0; public InformativeException(Throwable cause) { diff --git a/src/main/java/us/myles/ViaVersion/packets/Direction.java b/common/src/main/java/us/myles/ViaVersion/packets/Direction.java similarity index 100% rename from src/main/java/us/myles/ViaVersion/packets/Direction.java rename to common/src/main/java/us/myles/ViaVersion/packets/Direction.java diff --git a/src/main/java/us/myles/ViaVersion/packets/PacketType.java b/common/src/main/java/us/myles/ViaVersion/packets/PacketType.java similarity index 97% rename from src/main/java/us/myles/ViaVersion/packets/PacketType.java rename to common/src/main/java/us/myles/ViaVersion/packets/PacketType.java index 43bb5cf0c..b3077806b 100644 --- a/src/main/java/us/myles/ViaVersion/packets/PacketType.java +++ b/common/src/main/java/us/myles/ViaVersion/packets/PacketType.java @@ -1,208 +1,208 @@ -package us.myles.ViaVersion.packets; - -import java.util.HashMap; - -@Deprecated -public enum PacketType { - /* Handshake serverbound */ - HANDSHAKE(State.HANDSHAKE, Direction.INCOMING, 0x00), // Mapped - /* Login serverbound */ - LOGIN_START(State.LOGIN, Direction.INCOMING, 0x00), // Mapped - LOGIN_ENCRYPTION_RESPONSE(State.LOGIN, Direction.INCOMING, 0x01), // Mapped - /* Login clientbound */ - LOGIN_DISCONNECT(State.LOGIN, Direction.OUTGOING, 0x00), // Mapped - LOGIN_ENCRYPTION_REQUEST(State.LOGIN, Direction.OUTGOING, 0x01), // Mapped - LOGIN_SUCCESS(State.LOGIN, Direction.OUTGOING, 0x02), // Mapped - LOGIN_SETCOMPRESSION(State.LOGIN, Direction.OUTGOING, 0x03), // Mapped - - /* Status serverbound */ - STATUS_REQUEST(State.STATUS, Direction.INCOMING, 0x00), // Mapped - STATUS_PING(State.STATUS, Direction.INCOMING, 0x01), // Mapped - /* Status clientbound */ - STATUS_RESPONSE(State.STATUS, Direction.OUTGOING, 0x00), - STATUS_PONG(State.STATUS, Direction.OUTGOING, 0x01), - /* Play serverbound */ - PLAY_TP_CONFIRM(State.PLAY, Direction.INCOMING, -1, 0x00), // Mapped - PLAY_TAB_COMPLETE_REQUEST(State.PLAY, Direction.INCOMING, 0x14, 0x01), // Mapped - PLAY_CHAT_MESSAGE_CLIENT(State.PLAY, Direction.INCOMING, 0x01, 0x02), // Mapped - PLAY_CLIENT_STATUS(State.PLAY, Direction.INCOMING, 0x16, 0x03), // Mapped - PLAY_CLIENT_SETTINGS(State.PLAY, Direction.INCOMING, 0x15, 0x04), // Mapped - PLAY_CONFIRM_TRANS(State.PLAY, Direction.INCOMING, 0x0F, 0x05), // Mapped - PLAY_ENCHANT_ITEM(State.PLAY, Direction.INCOMING, 0x11, 0x06), // Mapped - PLAY_CLICK_WINDOW(State.PLAY, Direction.INCOMING, 0x0E, 0x07), // Mapped - PLAY_CLOSE_WINDOW_REQUEST(State.PLAY, Direction.INCOMING, 0x0D, 0x08), // Mapped - PLAY_PLUGIN_MESSAGE_REQUEST(State.PLAY, Direction.INCOMING, 0x17, 0x09), - PLAY_USE_ENTITY(State.PLAY, Direction.INCOMING, 0x02, 0x0A), // Mapped - PLAY_KEEP_ALIVE_REQUEST(State.PLAY, Direction.INCOMING, 0x00, 0x0B), // Mapped - PLAY_PLAYER_POSITION_REQUEST(State.PLAY, Direction.INCOMING, 0x04, 0x0C), // Mapped - PLAY_PLAYER_POSITION_LOOK_REQUEST(State.PLAY, Direction.INCOMING, 0x06, 0x0D), // Mapped - PLAY_PLAYER_LOOK_REQUEST(State.PLAY, Direction.INCOMING, 0x05, 0x0E), // Mapped - PLAY_PLAYER(State.PLAY, Direction.INCOMING, 0x03, 0x0F), // Mapped - PLAY_VEHICLE_MOVE_REQUEST(State.PLAY, Direction.INCOMING, -1, 0x10), // Mapped - PLAY_STEER_BOAT(State.PLAY, Direction.INCOMING, -1, 0x11), // Mapped - PLAY_PLAYER_ABILITIES_REQUEST(State.PLAY, Direction.INCOMING, 0x13, 0x12), // Mapped - PLAY_PLAYER_DIGGING(State.PLAY, Direction.INCOMING, 0x07, 0x13), // Mapped - PLAY_ENTITY_ACTION(State.PLAY, Direction.INCOMING, 0x0B, 0x14), // Mapped - PLAY_STEER_VEHICLE(State.PLAY, Direction.INCOMING, 0x0C, 0x15), // Mapped - - PLAY_RESOURCE_PACK_STATUS(State.PLAY, Direction.INCOMING, 0x19, 0x16), // Mapped - PLAY_HELD_ITEM_CHANGE_REQUEST(State.PLAY, Direction.INCOMING, 0x09, 0x17), // Mapped - - PLAY_CREATIVE_INVENTORY_ACTION(State.PLAY, Direction.INCOMING, 0x10, 0x18), // Mapped - PLAY_UPDATE_SIGN_REQUEST(State.PLAY, Direction.INCOMING, 0x12, 0x19), // Mapped - PLAY_ANIMATION_REQUEST(State.PLAY, Direction.INCOMING, 0x0A, 0x1A), // Mapped - PLAY_SPECTATE(State.PLAY, Direction.INCOMING, 0x18, 0x1B), // Mapped - PLAY_PLAYER_BLOCK_PLACEMENT(State.PLAY, Direction.INCOMING, 0x08, 0x1C), // Mapped - PLAY_USE_ITEM(State.PLAY, Direction.INCOMING, -1, 0x1D), // Mapped - /* Play clientbound */ - PLAY_SPAWN_OBJECT(State.PLAY, Direction.OUTGOING, 0x0E, 0x00), // Mapped - PLAY_SPAWN_XP_ORB(State.PLAY, Direction.OUTGOING, 0x11, 0x01), // Mapped - PLAY_SPAWN_GLOBAL_ENTITY(State.PLAY, Direction.OUTGOING, 0x2C, 0x02), // Mapped - PLAY_SPAWN_MOB(State.PLAY, Direction.OUTGOING, 0x0F, 0x03), // Mapped - PLAY_SPAWN_PAINTING(State.PLAY, Direction.OUTGOING, 0x10, 0x04), // Mapped - PLAY_SPAWN_PLAYER(State.PLAY, Direction.OUTGOING, 0x0C, 0x05), // Mapped - - PLAY_ANIMATION(State.PLAY, Direction.OUTGOING, 0x0B, 0x06), // Mapped - PLAY_STATS(State.PLAY, Direction.OUTGOING, 0x37, 0x07), // Mapped - - PLAY_BLOCK_BREAK_ANIMATION(State.PLAY, Direction.OUTGOING, 0x25, 0x08), // Mapped - PLAY_UPDATE_BLOCK_ENTITY(State.PLAY, Direction.OUTGOING, 0x35, 0x09), // Mapped - PLAY_BLOCK_ACTION(State.PLAY, Direction.OUTGOING, 0x24, 0x0A), // Mapped - PLAY_BLOCK_CHANGE(State.PLAY, Direction.OUTGOING, 0x23, 0x0B), // Mapped - - PLAY_BOSS_BAR(State.PLAY, Direction.OUTGOING, -1, 0x0C), - PLAY_SERVER_DIFFICULTY(State.PLAY, Direction.OUTGOING, 0x41, 0x0D), // Mapped - PLAY_TAB_COMPLETE(State.PLAY, Direction.OUTGOING, 0x3A, 0x0E), // Mapped - PLAY_CHAT_MESSAGE(State.PLAY, Direction.OUTGOING, 0x02, 0x0F), // Mapped - PLAY_MULTI_BLOCK_CHANGE(State.PLAY, Direction.OUTGOING, 0x22, 0x10), // Mapped - PLAY_CONFIRM_TRANSACTION(State.PLAY, Direction.OUTGOING, 0x32, 0x11), // Mapped - PLAY_CLOSE_WINDOW(State.PLAY, Direction.OUTGOING, 0x2E, 0x12), // Mapped - PLAY_OPEN_WINDOW(State.PLAY, Direction.OUTGOING, 0x2D, 0x13), // Mapped - PLAY_WINDOW_ITEMS(State.PLAY, Direction.OUTGOING, 0x30, 0x14), // Mapped - PLAY_WINDOW_PROPERTY(State.PLAY, Direction.OUTGOING, 0x31, 0x15), // Mapped - PLAY_SET_SLOT(State.PLAY, Direction.OUTGOING, 0x2F, 0x16), // Mapped - PLAY_SET_COOLDOWN(State.PLAY, Direction.OUTGOING, -1, 0x17), - PLAY_PLUGIN_MESSAGE(State.PLAY, Direction.OUTGOING, 0x3F, 0x18), // Mapped - PLAY_NAMED_SOUND_EFFECT(State.PLAY, Direction.OUTGOING, 0x29, 0x19), // Mapped - PLAY_DISCONNECT(State.PLAY, Direction.OUTGOING, 0x40, 0x1A), // Mapped - PLAY_ENTITY_STATUS(State.PLAY, Direction.OUTGOING, 0x1A, 0x1B), // Mapped - PLAY_EXPLOSION(State.PLAY, Direction.OUTGOING, 0x27, 0x1C), // Mapped - PLAY_UNLOAD_CHUNK(State.PLAY, Direction.OUTGOING, -1, 0x1D), - PLAY_CHANGE_GAME_STATE(State.PLAY, Direction.OUTGOING, 0x2B, 0x1E), - PLAY_KEEP_ALIVE(State.PLAY, Direction.OUTGOING, 0x00, 0x1F), // Mapped - PLAY_CHUNK_DATA(State.PLAY, Direction.OUTGOING, 0x21, 0x20), // Mapped - PLAY_EFFECT(State.PLAY, Direction.OUTGOING, 0x28, 0x21), // Mapped - PLAY_PARTICLE(State.PLAY, Direction.OUTGOING, 0x2A, 0x22), // Mapped - PLAY_JOIN_GAME(State.PLAY, Direction.OUTGOING, 0x01, 0x23), // Mapped - PLAY_MAP(State.PLAY, Direction.OUTGOING, 0x34, 0x24), // Mapped - PLAY_ENTITY_RELATIVE_MOVE(State.PLAY, Direction.OUTGOING, 0x15, 0x25), // Mapped - PLAY_ENTITY_LOOK_MOVE(State.PLAY, Direction.OUTGOING, 0x17, 0x26), // Mapped - PLAY_ENTITY_LOOK(State.PLAY, Direction.OUTGOING, 0x16, 0x27), // Mapped - PLAY_ENTITY(State.PLAY, Direction.OUTGOING, 0x14, 0x28), // Mapped - PLAY_VEHICLE_MOVE(State.PLAY, Direction.OUTGOING, -1, 0x29), - PLAY_OPEN_SIGN_EDITOR(State.PLAY, Direction.OUTGOING, 0x36, 0x2A), // Mapped - PLAY_PLAYER_ABILITIES(State.PLAY, Direction.OUTGOING, 0x39, 0x2B), // Mapped - PLAY_COMBAT_EVENT(State.PLAY, Direction.OUTGOING, 0x42, 0x2C), // Mapped - PLAY_PLAYER_LIST_ITEM(State.PLAY, Direction.OUTGOING, 0x38, 0x2D), // Mapped - PLAY_PLAYER_POSITION_LOOK(State.PLAY, Direction.OUTGOING, 0x08, 0x2E), // Mapped - PLAY_USE_BED(State.PLAY, Direction.OUTGOING, 0x0A, 0x2F), // Mapped - PLAY_DESTROY_ENTITIES(State.PLAY, Direction.OUTGOING, 0x13, 0x30), // Mapped - PLAY_REMOVE_ENTITY_EFFECT(State.PLAY, Direction.OUTGOING, 0x1E, 0x31), // Mapped - PLAY_RESOURCE_PACK_SEND(State.PLAY, Direction.OUTGOING, 0x48, 0x32), // Mapped - PLAY_RESPAWN(State.PLAY, Direction.OUTGOING, 0x07, 0x33), // Mapped - PLAY_ENTITY_HEAD_LOOK(State.PLAY, Direction.OUTGOING, 0x19, 0x34), // Mapped - PLAY_WORLD_BORDER(State.PLAY, Direction.OUTGOING, 0x44, 0x35), // Mapped - PLAY_CAMERA(State.PLAY, Direction.OUTGOING, 0x43, 0x36), // Mapped - PLAY_HELD_ITEM_CHANGE(State.PLAY, Direction.OUTGOING, 0x09, 0x37), // Mapped - PLAY_DISPLAY_SCOREBOARD(State.PLAY, Direction.OUTGOING, 0x3D, 0x38), // Mapped - PLAY_ENTITY_METADATA(State.PLAY, Direction.OUTGOING, 0x1C, 0x39), // Mapped - PLAY_ATTACH_ENTITY(State.PLAY, Direction.OUTGOING, 0x1B, 0x3A), // Mapped - PLAY_ENTITY_VELOCITY(State.PLAY, Direction.OUTGOING, 0x12, 0x3B), // Mapped - PLAY_ENTITY_EQUIPMENT(State.PLAY, Direction.OUTGOING, 0x04, 0x3C), // Mapped - PLAY_SET_XP(State.PLAY, Direction.OUTGOING, 0x1F, 0x3D), // Mapped - PLAY_UPDATE_HEALTH(State.PLAY, Direction.OUTGOING, 0x06, 0x3E), // Mapped - PLAY_SCOREBOARD_OBJ(State.PLAY, Direction.OUTGOING, 0x3B, 0x3F), // Mapped - PLAY_SET_PASSENGERS(State.PLAY, Direction.OUTGOING, -1, 0x40), - PLAY_TEAM(State.PLAY, Direction.OUTGOING, 0x3E, 0x41), // Mapped - PLAY_UPDATE_SCORE(State.PLAY, Direction.OUTGOING, 0x3C, 0x42), // Mapped - PLAY_SPAWN_POSITION(State.PLAY, Direction.OUTGOING, 0x05, 0x43), // Mapped - PLAY_TIME_UPDATE(State.PLAY, Direction.OUTGOING, 0x03, 0x44), // Mapped - PLAY_TITLE(State.PLAY, Direction.OUTGOING, 0x45, 0x45), // Mapped - PLAY_UPDATE_SIGN(State.PLAY, Direction.OUTGOING, 0x33, 0x46), // Mapped - PLAY_SOUND_EFFECT(State.PLAY, Direction.OUTGOING, -1, 0x47), - PLAY_PLAYER_LIST_HEADER_FOOTER(State.PLAY, Direction.OUTGOING, 0x47, 0x48), // Mapped - PLAY_COLLECT_ITEM(State.PLAY, Direction.OUTGOING, 0x0D, 0x49), // Mapped - PLAY_ENTITY_TELEPORT(State.PLAY, Direction.OUTGOING, 0x18, 0x4A), // Mapped - PLAY_ENTITY_PROPERTIES(State.PLAY, Direction.OUTGOING, 0x20, 0x4B), // Mapped - PLAY_ENTITY_EFFECT(State.PLAY, Direction.OUTGOING, 0x1D, 0x4C), // Mapped - - PLAY_MAP_CHUNK_BULK(State.PLAY, Direction.OUTGOING, 0x26, -1), - PLAY_SET_COMPRESSION(State.PLAY, Direction.OUTGOING, 0x46, -1), - PLAY_UPDATE_ENTITY_NBT(State.PLAY, Direction.OUTGOING, 0x49, -1); - - private static HashMap oldids = new HashMap<>(); - private static HashMap newids = new HashMap<>(); - - static { - for (PacketType pt : PacketType.values()) { - oldids.put(toShort((short) pt.getPacketID(), (short) pt.getDirection().ordinal(), (short) pt.getState().ordinal()), pt); - newids.put(toShort((short) pt.getNewPacketID(), (short) pt.getDirection().ordinal(), (short) pt.getState().ordinal()), pt); - } - } - - private State state; - private Direction direction; - private int packetID; - private int newPacketID = -1; - - PacketType(State state, Direction direction, int packetID) { - this.state = state; - this.direction = direction; - this.packetID = packetID; - this.newPacketID = packetID; - } - - PacketType(State state, Direction direction, int packetID, int newPacketID) { - this.state = state; - this.direction = direction; - this.packetID = packetID; - this.newPacketID = newPacketID; - } - - public static PacketType findNewPacket(State state, Direction direction, int id) { - return newids.get(toShort((short) id, (short) direction.ordinal(), (short) state.ordinal())); - } - - public static PacketType findOldPacket(State state, Direction direction, int id) { - return oldids.get(toShort((short) id, (short) direction.ordinal(), (short) state.ordinal())); - } - - public static PacketType getIncomingPacket(State state, int id) { - return findNewPacket(state, Direction.INCOMING, id); - } - - public static PacketType getOutgoingPacket(State state, int id) { - return findOldPacket(state, Direction.OUTGOING, id); - } - - private static short toShort(short id, short direction, short state) { - return (short) ((id & 0x00FF) | (direction << 8) & 0x0F00 | (state << 12) & 0xF000); - } - - public State getState() { - return state; - } - - public Direction getDirection() { - return direction; - } - - public int getPacketID() { - return packetID; - } - - public int getNewPacketID() { - return newPacketID; - } - -} +package us.myles.ViaVersion.packets; + +import java.util.HashMap; + +@Deprecated +public enum PacketType { + /* Handshake serverbound */ + HANDSHAKE(State.HANDSHAKE, Direction.INCOMING, 0x00), // Mapped + /* Login serverbound */ + LOGIN_START(State.LOGIN, Direction.INCOMING, 0x00), // Mapped + LOGIN_ENCRYPTION_RESPONSE(State.LOGIN, Direction.INCOMING, 0x01), // Mapped + /* Login clientbound */ + LOGIN_DISCONNECT(State.LOGIN, Direction.OUTGOING, 0x00), // Mapped + LOGIN_ENCRYPTION_REQUEST(State.LOGIN, Direction.OUTGOING, 0x01), // Mapped + LOGIN_SUCCESS(State.LOGIN, Direction.OUTGOING, 0x02), // Mapped + LOGIN_SETCOMPRESSION(State.LOGIN, Direction.OUTGOING, 0x03), // Mapped + + /* Status serverbound */ + STATUS_REQUEST(State.STATUS, Direction.INCOMING, 0x00), // Mapped + STATUS_PING(State.STATUS, Direction.INCOMING, 0x01), // Mapped + /* Status clientbound */ + STATUS_RESPONSE(State.STATUS, Direction.OUTGOING, 0x00), + STATUS_PONG(State.STATUS, Direction.OUTGOING, 0x01), + /* Play serverbound */ + PLAY_TP_CONFIRM(State.PLAY, Direction.INCOMING, -1, 0x00), // Mapped + PLAY_TAB_COMPLETE_REQUEST(State.PLAY, Direction.INCOMING, 0x14, 0x01), // Mapped + PLAY_CHAT_MESSAGE_CLIENT(State.PLAY, Direction.INCOMING, 0x01, 0x02), // Mapped + PLAY_CLIENT_STATUS(State.PLAY, Direction.INCOMING, 0x16, 0x03), // Mapped + PLAY_CLIENT_SETTINGS(State.PLAY, Direction.INCOMING, 0x15, 0x04), // Mapped + PLAY_CONFIRM_TRANS(State.PLAY, Direction.INCOMING, 0x0F, 0x05), // Mapped + PLAY_ENCHANT_ITEM(State.PLAY, Direction.INCOMING, 0x11, 0x06), // Mapped + PLAY_CLICK_WINDOW(State.PLAY, Direction.INCOMING, 0x0E, 0x07), // Mapped + PLAY_CLOSE_WINDOW_REQUEST(State.PLAY, Direction.INCOMING, 0x0D, 0x08), // Mapped + PLAY_PLUGIN_MESSAGE_REQUEST(State.PLAY, Direction.INCOMING, 0x17, 0x09), + PLAY_USE_ENTITY(State.PLAY, Direction.INCOMING, 0x02, 0x0A), // Mapped + PLAY_KEEP_ALIVE_REQUEST(State.PLAY, Direction.INCOMING, 0x00, 0x0B), // Mapped + PLAY_PLAYER_POSITION_REQUEST(State.PLAY, Direction.INCOMING, 0x04, 0x0C), // Mapped + PLAY_PLAYER_POSITION_LOOK_REQUEST(State.PLAY, Direction.INCOMING, 0x06, 0x0D), // Mapped + PLAY_PLAYER_LOOK_REQUEST(State.PLAY, Direction.INCOMING, 0x05, 0x0E), // Mapped + PLAY_PLAYER(State.PLAY, Direction.INCOMING, 0x03, 0x0F), // Mapped + PLAY_VEHICLE_MOVE_REQUEST(State.PLAY, Direction.INCOMING, -1, 0x10), // Mapped + PLAY_STEER_BOAT(State.PLAY, Direction.INCOMING, -1, 0x11), // Mapped + PLAY_PLAYER_ABILITIES_REQUEST(State.PLAY, Direction.INCOMING, 0x13, 0x12), // Mapped + PLAY_PLAYER_DIGGING(State.PLAY, Direction.INCOMING, 0x07, 0x13), // Mapped + PLAY_ENTITY_ACTION(State.PLAY, Direction.INCOMING, 0x0B, 0x14), // Mapped + PLAY_STEER_VEHICLE(State.PLAY, Direction.INCOMING, 0x0C, 0x15), // Mapped + + PLAY_RESOURCE_PACK_STATUS(State.PLAY, Direction.INCOMING, 0x19, 0x16), // Mapped + PLAY_HELD_ITEM_CHANGE_REQUEST(State.PLAY, Direction.INCOMING, 0x09, 0x17), // Mapped + + PLAY_CREATIVE_INVENTORY_ACTION(State.PLAY, Direction.INCOMING, 0x10, 0x18), // Mapped + PLAY_UPDATE_SIGN_REQUEST(State.PLAY, Direction.INCOMING, 0x12, 0x19), // Mapped + PLAY_ANIMATION_REQUEST(State.PLAY, Direction.INCOMING, 0x0A, 0x1A), // Mapped + PLAY_SPECTATE(State.PLAY, Direction.INCOMING, 0x18, 0x1B), // Mapped + PLAY_PLAYER_BLOCK_PLACEMENT(State.PLAY, Direction.INCOMING, 0x08, 0x1C), // Mapped + PLAY_USE_ITEM(State.PLAY, Direction.INCOMING, -1, 0x1D), // Mapped + /* Play clientbound */ + PLAY_SPAWN_OBJECT(State.PLAY, Direction.OUTGOING, 0x0E, 0x00), // Mapped + PLAY_SPAWN_XP_ORB(State.PLAY, Direction.OUTGOING, 0x11, 0x01), // Mapped + PLAY_SPAWN_GLOBAL_ENTITY(State.PLAY, Direction.OUTGOING, 0x2C, 0x02), // Mapped + PLAY_SPAWN_MOB(State.PLAY, Direction.OUTGOING, 0x0F, 0x03), // Mapped + PLAY_SPAWN_PAINTING(State.PLAY, Direction.OUTGOING, 0x10, 0x04), // Mapped + PLAY_SPAWN_PLAYER(State.PLAY, Direction.OUTGOING, 0x0C, 0x05), // Mapped + + PLAY_ANIMATION(State.PLAY, Direction.OUTGOING, 0x0B, 0x06), // Mapped + PLAY_STATS(State.PLAY, Direction.OUTGOING, 0x37, 0x07), // Mapped + + PLAY_BLOCK_BREAK_ANIMATION(State.PLAY, Direction.OUTGOING, 0x25, 0x08), // Mapped + PLAY_UPDATE_BLOCK_ENTITY(State.PLAY, Direction.OUTGOING, 0x35, 0x09), // Mapped + PLAY_BLOCK_ACTION(State.PLAY, Direction.OUTGOING, 0x24, 0x0A), // Mapped + PLAY_BLOCK_CHANGE(State.PLAY, Direction.OUTGOING, 0x23, 0x0B), // Mapped + + PLAY_BOSS_BAR(State.PLAY, Direction.OUTGOING, -1, 0x0C), + PLAY_SERVER_DIFFICULTY(State.PLAY, Direction.OUTGOING, 0x41, 0x0D), // Mapped + PLAY_TAB_COMPLETE(State.PLAY, Direction.OUTGOING, 0x3A, 0x0E), // Mapped + PLAY_CHAT_MESSAGE(State.PLAY, Direction.OUTGOING, 0x02, 0x0F), // Mapped + PLAY_MULTI_BLOCK_CHANGE(State.PLAY, Direction.OUTGOING, 0x22, 0x10), // Mapped + PLAY_CONFIRM_TRANSACTION(State.PLAY, Direction.OUTGOING, 0x32, 0x11), // Mapped + PLAY_CLOSE_WINDOW(State.PLAY, Direction.OUTGOING, 0x2E, 0x12), // Mapped + PLAY_OPEN_WINDOW(State.PLAY, Direction.OUTGOING, 0x2D, 0x13), // Mapped + PLAY_WINDOW_ITEMS(State.PLAY, Direction.OUTGOING, 0x30, 0x14), // Mapped + PLAY_WINDOW_PROPERTY(State.PLAY, Direction.OUTGOING, 0x31, 0x15), // Mapped + PLAY_SET_SLOT(State.PLAY, Direction.OUTGOING, 0x2F, 0x16), // Mapped + PLAY_SET_COOLDOWN(State.PLAY, Direction.OUTGOING, -1, 0x17), + PLAY_PLUGIN_MESSAGE(State.PLAY, Direction.OUTGOING, 0x3F, 0x18), // Mapped + PLAY_NAMED_SOUND_EFFECT(State.PLAY, Direction.OUTGOING, 0x29, 0x19), // Mapped + PLAY_DISCONNECT(State.PLAY, Direction.OUTGOING, 0x40, 0x1A), // Mapped + PLAY_ENTITY_STATUS(State.PLAY, Direction.OUTGOING, 0x1A, 0x1B), // Mapped + PLAY_EXPLOSION(State.PLAY, Direction.OUTGOING, 0x27, 0x1C), // Mapped + PLAY_UNLOAD_CHUNK(State.PLAY, Direction.OUTGOING, -1, 0x1D), + PLAY_CHANGE_GAME_STATE(State.PLAY, Direction.OUTGOING, 0x2B, 0x1E), + PLAY_KEEP_ALIVE(State.PLAY, Direction.OUTGOING, 0x00, 0x1F), // Mapped + PLAY_CHUNK_DATA(State.PLAY, Direction.OUTGOING, 0x21, 0x20), // Mapped + PLAY_EFFECT(State.PLAY, Direction.OUTGOING, 0x28, 0x21), // Mapped + PLAY_PARTICLE(State.PLAY, Direction.OUTGOING, 0x2A, 0x22), // Mapped + PLAY_JOIN_GAME(State.PLAY, Direction.OUTGOING, 0x01, 0x23), // Mapped + PLAY_MAP(State.PLAY, Direction.OUTGOING, 0x34, 0x24), // Mapped + PLAY_ENTITY_RELATIVE_MOVE(State.PLAY, Direction.OUTGOING, 0x15, 0x25), // Mapped + PLAY_ENTITY_LOOK_MOVE(State.PLAY, Direction.OUTGOING, 0x17, 0x26), // Mapped + PLAY_ENTITY_LOOK(State.PLAY, Direction.OUTGOING, 0x16, 0x27), // Mapped + PLAY_ENTITY(State.PLAY, Direction.OUTGOING, 0x14, 0x28), // Mapped + PLAY_VEHICLE_MOVE(State.PLAY, Direction.OUTGOING, -1, 0x29), + PLAY_OPEN_SIGN_EDITOR(State.PLAY, Direction.OUTGOING, 0x36, 0x2A), // Mapped + PLAY_PLAYER_ABILITIES(State.PLAY, Direction.OUTGOING, 0x39, 0x2B), // Mapped + PLAY_COMBAT_EVENT(State.PLAY, Direction.OUTGOING, 0x42, 0x2C), // Mapped + PLAY_PLAYER_LIST_ITEM(State.PLAY, Direction.OUTGOING, 0x38, 0x2D), // Mapped + PLAY_PLAYER_POSITION_LOOK(State.PLAY, Direction.OUTGOING, 0x08, 0x2E), // Mapped + PLAY_USE_BED(State.PLAY, Direction.OUTGOING, 0x0A, 0x2F), // Mapped + PLAY_DESTROY_ENTITIES(State.PLAY, Direction.OUTGOING, 0x13, 0x30), // Mapped + PLAY_REMOVE_ENTITY_EFFECT(State.PLAY, Direction.OUTGOING, 0x1E, 0x31), // Mapped + PLAY_RESOURCE_PACK_SEND(State.PLAY, Direction.OUTGOING, 0x48, 0x32), // Mapped + PLAY_RESPAWN(State.PLAY, Direction.OUTGOING, 0x07, 0x33), // Mapped + PLAY_ENTITY_HEAD_LOOK(State.PLAY, Direction.OUTGOING, 0x19, 0x34), // Mapped + PLAY_WORLD_BORDER(State.PLAY, Direction.OUTGOING, 0x44, 0x35), // Mapped + PLAY_CAMERA(State.PLAY, Direction.OUTGOING, 0x43, 0x36), // Mapped + PLAY_HELD_ITEM_CHANGE(State.PLAY, Direction.OUTGOING, 0x09, 0x37), // Mapped + PLAY_DISPLAY_SCOREBOARD(State.PLAY, Direction.OUTGOING, 0x3D, 0x38), // Mapped + PLAY_ENTITY_METADATA(State.PLAY, Direction.OUTGOING, 0x1C, 0x39), // Mapped + PLAY_ATTACH_ENTITY(State.PLAY, Direction.OUTGOING, 0x1B, 0x3A), // Mapped + PLAY_ENTITY_VELOCITY(State.PLAY, Direction.OUTGOING, 0x12, 0x3B), // Mapped + PLAY_ENTITY_EQUIPMENT(State.PLAY, Direction.OUTGOING, 0x04, 0x3C), // Mapped + PLAY_SET_XP(State.PLAY, Direction.OUTGOING, 0x1F, 0x3D), // Mapped + PLAY_UPDATE_HEALTH(State.PLAY, Direction.OUTGOING, 0x06, 0x3E), // Mapped + PLAY_SCOREBOARD_OBJ(State.PLAY, Direction.OUTGOING, 0x3B, 0x3F), // Mapped + PLAY_SET_PASSENGERS(State.PLAY, Direction.OUTGOING, -1, 0x40), + PLAY_TEAM(State.PLAY, Direction.OUTGOING, 0x3E, 0x41), // Mapped + PLAY_UPDATE_SCORE(State.PLAY, Direction.OUTGOING, 0x3C, 0x42), // Mapped + PLAY_SPAWN_POSITION(State.PLAY, Direction.OUTGOING, 0x05, 0x43), // Mapped + PLAY_TIME_UPDATE(State.PLAY, Direction.OUTGOING, 0x03, 0x44), // Mapped + PLAY_TITLE(State.PLAY, Direction.OUTGOING, 0x45, 0x45), // Mapped + PLAY_UPDATE_SIGN(State.PLAY, Direction.OUTGOING, 0x33, 0x46), // Mapped + PLAY_SOUND_EFFECT(State.PLAY, Direction.OUTGOING, -1, 0x47), + PLAY_PLAYER_LIST_HEADER_FOOTER(State.PLAY, Direction.OUTGOING, 0x47, 0x48), // Mapped + PLAY_COLLECT_ITEM(State.PLAY, Direction.OUTGOING, 0x0D, 0x49), // Mapped + PLAY_ENTITY_TELEPORT(State.PLAY, Direction.OUTGOING, 0x18, 0x4A), // Mapped + PLAY_ENTITY_PROPERTIES(State.PLAY, Direction.OUTGOING, 0x20, 0x4B), // Mapped + PLAY_ENTITY_EFFECT(State.PLAY, Direction.OUTGOING, 0x1D, 0x4C), // Mapped + + PLAY_MAP_CHUNK_BULK(State.PLAY, Direction.OUTGOING, 0x26, -1), + PLAY_SET_COMPRESSION(State.PLAY, Direction.OUTGOING, 0x46, -1), + PLAY_UPDATE_ENTITY_NBT(State.PLAY, Direction.OUTGOING, 0x49, -1); + + private static final HashMap oldids = new HashMap<>(); + private static final HashMap newids = new HashMap<>(); + + static { + for (PacketType pt : PacketType.values()) { + oldids.put(toShort((short) pt.getPacketID(), (short) pt.getDirection().ordinal(), (short) pt.getState().ordinal()), pt); + newids.put(toShort((short) pt.getNewPacketID(), (short) pt.getDirection().ordinal(), (short) pt.getState().ordinal()), pt); + } + } + + private State state; + private Direction direction; + private int packetID; + private int newPacketID = -1; + + PacketType(State state, Direction direction, int packetID) { + this.state = state; + this.direction = direction; + this.packetID = packetID; + this.newPacketID = packetID; + } + + PacketType(State state, Direction direction, int packetID, int newPacketID) { + this.state = state; + this.direction = direction; + this.packetID = packetID; + this.newPacketID = newPacketID; + } + + public static PacketType findNewPacket(State state, Direction direction, int id) { + return newids.get(toShort((short) id, (short) direction.ordinal(), (short) state.ordinal())); + } + + public static PacketType findOldPacket(State state, Direction direction, int id) { + return oldids.get(toShort((short) id, (short) direction.ordinal(), (short) state.ordinal())); + } + + public static PacketType getIncomingPacket(State state, int id) { + return findNewPacket(state, Direction.INCOMING, id); + } + + public static PacketType getOutgoingPacket(State state, int id) { + return findOldPacket(state, Direction.OUTGOING, id); + } + + private static short toShort(short id, short direction, short state) { + return (short) ((id & 0x00FF) | (direction << 8) & 0x0F00 | (state << 12) & 0xF000); + } + + public State getState() { + return state; + } + + public Direction getDirection() { + return direction; + } + + public int getPacketID() { + return packetID; + } + + public int getNewPacketID() { + return newPacketID; + } + +} diff --git a/src/main/java/us/myles/ViaVersion/packets/State.java b/common/src/main/java/us/myles/ViaVersion/packets/State.java similarity index 100% rename from src/main/java/us/myles/ViaVersion/packets/State.java rename to common/src/main/java/us/myles/ViaVersion/packets/State.java diff --git a/src/main/java/us/myles/ViaVersion/protocols/base/BaseProtocol.java b/common/src/main/java/us/myles/ViaVersion/protocols/base/BaseProtocol.java similarity index 75% rename from src/main/java/us/myles/ViaVersion/protocols/base/BaseProtocol.java rename to common/src/main/java/us/myles/ViaVersion/protocols/base/BaseProtocol.java index 8de79782d..f949d6944 100644 --- a/src/main/java/us/myles/ViaVersion/protocols/base/BaseProtocol.java +++ b/common/src/main/java/us/myles/ViaVersion/protocols/base/BaseProtocol.java @@ -1,22 +1,17 @@ package us.myles.ViaVersion.protocols.base; +import com.google.common.base.Joiner; +import com.google.gson.JsonObject; +import com.google.gson.JsonParseException; import io.netty.channel.ChannelFuture; import io.netty.util.concurrent.Future; import io.netty.util.concurrent.GenericFutureListener; import net.md_5.bungee.api.ChatColor; -import org.apache.commons.lang.StringUtils; -import org.bukkit.Bukkit; -import org.bukkit.event.EventHandler; -import org.bukkit.event.Listener; -import org.bukkit.event.player.PlayerQuitEvent; -import org.json.simple.JSONObject; -import org.json.simple.parser.JSONParser; -import org.json.simple.parser.ParseException; -import us.myles.ViaVersion.ViaVersionPlugin; import us.myles.ViaVersion.api.PacketWrapper; import us.myles.ViaVersion.api.Pair; -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.providers.ViaProviders; import us.myles.ViaVersion.api.protocol.Protocol; import us.myles.ViaVersion.api.protocol.ProtocolPipeline; import us.myles.ViaVersion.api.protocol.ProtocolRegistry; @@ -26,6 +21,7 @@ import us.myles.ViaVersion.api.type.Type; import us.myles.ViaVersion.packets.Direction; import us.myles.ViaVersion.packets.State; import us.myles.ViaVersion.protocols.protocol1_9to1_8.Protocol1_9TO1_8; +import us.myles.ViaVersion.util.GsonUtil; import java.util.List; import java.util.UUID; @@ -48,30 +44,34 @@ public class BaseProtocol extends Protocol { ProtocolInfo info = wrapper.user().get(ProtocolInfo.class); String originalStatus = wrapper.get(Type.STRING, 0); try { - JSONObject json = (JSONObject) new JSONParser().parse(originalStatus); - JSONObject version = (JSONObject) json.get("version"); - int protocolVersion = ((Long) version.get("protocol")).intValue(); + JsonObject json = GsonUtil.getGson().fromJson(originalStatus, JsonObject.class); + JsonObject version = json.get("version").getAsJsonObject(); + int protocolVersion = ((Long) version.get("protocol").getAsLong()).intValue(); - if (ViaVersion.getConfig().isSendSupportedVersions()) //Send supported versions - version.put("supportedVersions", ViaVersion.getInstance().getSupportedVersions()); + if (Via.getConfig().isSendSupportedVersions()) //Send supported versions + version.add("supportedVersions", GsonUtil.getGson().toJsonTree(Via.getAPI().getSupportedVersions())); if (ProtocolRegistry.SERVER_PROTOCOL == -1) // Set the Server protocol if the detection on startup failed ProtocolRegistry.SERVER_PROTOCOL = protocolVersion; - List> protocols = ProtocolRegistry.getProtocolPath(info.getProtocolVersion(), ProtocolRegistry.SERVER_PROTOCOL); + int protocol = Via.getManager().getProviders().get(VersionProvider.class).getServerProtocol(wrapper.user()); + List> protocols = ProtocolRegistry.getProtocolPath(info.getProtocolVersion(), protocol); + if (protocols != null) { - if (protocolVersion != 9999) //Fix ServerListPlus - version.put("protocol", info.getProtocolVersion()); + if (protocolVersion != 9999) { + //Fix ServerListPlus + version.addProperty("protocol", info.getProtocolVersion()); + } } else { // not compatible :(, *plays very sad violin* wrapper.user().setActive(false); } - if (ViaVersion.getConfig().getBlockedProtocols().contains(info.getProtocolVersion())) - version.put("protocol", -1); // Show blocked versions as outdated + if (Via.getConfig().getBlockedProtocols().contains(info.getProtocolVersion())) + version.addProperty("protocol", -1); // Show blocked versions as outdated - wrapper.set(Type.STRING, 0, json.toJSONString()); // Update value - } catch (ParseException e) { + wrapper.set(Type.STRING, 0, GsonUtil.getGson().toJson(json)); // Update value + } catch (JsonParseException e) { e.printStackTrace(); } } @@ -100,18 +100,18 @@ public class BaseProtocol extends Protocol { info.setUuid(uuid); info.setUsername(wrapper.get(Type.STRING, 1)); // Add to ported clients - ((ViaVersionPlugin) ViaVersion.getInstance()).addPortedClient(wrapper.user()); + Via.getManager().addPortedClient(wrapper.user()); if (info.getPipeline().pipes().size() == 1 && info.getPipeline().pipes().get(0).getClass() == BaseProtocol.class) // Only base protocol wrapper.user().setActive(false); - if (ViaVersion.getInstance().isDebug()) { + if (Via.getManager().isDebug()) { // Print out the route to console - ((ViaVersionPlugin) ViaVersion.getInstance()).getLogger().log(Level.INFO, "{0} logged in with protocol {1}, Route: {2}", + Via.getPlatform().getLogger().log(Level.INFO, "{0} logged in with protocol {1}, Route: {2}", new Object[]{ wrapper.get(Type.STRING, 1), info.getProtocolVersion(), - StringUtils.join(info.getPipeline().pipes(), ", ") + Joiner.on(", ").join(info.getPipeline().pipes(), ", ") }); } } @@ -140,13 +140,14 @@ public class BaseProtocol extends Protocol { ProtocolInfo info = wrapper.user().get(ProtocolInfo.class); info.setProtocolVersion(protVer); // Choose the pipe - List> protocols = ProtocolRegistry.getProtocolPath(info.getProtocolVersion(), ProtocolRegistry.SERVER_PROTOCOL); + int protocol = Via.getManager().getProviders().get(VersionProvider.class).getServerProtocol(wrapper.user()); + List> protocols = ProtocolRegistry.getProtocolPath(info.getProtocolVersion(), protocol); ProtocolPipeline pipeline = wrapper.user().get(ProtocolInfo.class).getPipeline(); if (protocols != null) { for (Pair prot : protocols) { pipeline.add(prot.getValue()); } - wrapper.set(Type.VAR_INT, 0, ProtocolRegistry.SERVER_PROTOCOL); + wrapper.set(Type.VAR_INT, 0, protocol); } // Change state @@ -171,11 +172,11 @@ public class BaseProtocol extends Protocol { @Override public void handle(final PacketWrapper wrapper) throws Exception { int protocol = wrapper.user().get(ProtocolInfo.class).getProtocolVersion(); - if (ViaVersion.getConfig().getBlockedProtocols().contains(protocol)) { + if (Via.getConfig().getBlockedProtocols().contains(protocol)) { if (!wrapper.user().getChannel().isOpen()) return; PacketWrapper disconnectPacket = new PacketWrapper(0x00, null, wrapper.user()); // Disconnect Packet - Protocol1_9TO1_8.FIX_JSON.write(disconnectPacket, ChatColor.translateAlternateColorCodes('&', ViaVersion.getConfig().getBlockedDisconnectMsg())); + Protocol1_9TO1_8.FIX_JSON.write(disconnectPacket, ChatColor.translateAlternateColorCodes('&', Via.getConfig().getBlockedDisconnectMsg())); wrapper.cancel(); // cancel current // Send and close @@ -200,15 +201,8 @@ public class BaseProtocol extends Protocol { } @Override - protected void registerListeners() { - final ViaVersionPlugin plugin = (ViaVersionPlugin) Bukkit.getPluginManager().getPlugin("ViaVersion"); - - Bukkit.getPluginManager().registerEvents(new Listener() { - @EventHandler - public void onPlayerQuit(PlayerQuitEvent e) { - plugin.removePortedClient(e.getPlayer().getUniqueId()); - } - }, plugin); + protected void register(ViaProviders providers) { + providers.register(VersionProvider.class, new VersionProvider()); } @Override diff --git a/src/main/java/us/myles/ViaVersion/protocols/base/ProtocolInfo.java b/common/src/main/java/us/myles/ViaVersion/protocols/base/ProtocolInfo.java similarity index 100% rename from src/main/java/us/myles/ViaVersion/protocols/base/ProtocolInfo.java rename to common/src/main/java/us/myles/ViaVersion/protocols/base/ProtocolInfo.java diff --git a/common/src/main/java/us/myles/ViaVersion/protocols/base/VersionProvider.java b/common/src/main/java/us/myles/ViaVersion/protocols/base/VersionProvider.java new file mode 100644 index 000000000..ec30cf4b1 --- /dev/null +++ b/common/src/main/java/us/myles/ViaVersion/protocols/base/VersionProvider.java @@ -0,0 +1,12 @@ +package us.myles.ViaVersion.protocols.base; + +import us.myles.ViaVersion.api.data.UserConnection; +import us.myles.ViaVersion.api.platform.providers.Provider; +import us.myles.ViaVersion.api.protocol.ProtocolRegistry; + +public class VersionProvider implements Provider { + + public int getServerProtocol(UserConnection connection) throws Exception { + return ProtocolRegistry.SERVER_PROTOCOL; + } +} diff --git a/src/main/java/us/myles/ViaVersion/protocols/protocol1_10to1_9_3/Protocol1_10To1_9_3_4.java b/common/src/main/java/us/myles/ViaVersion/protocols/protocol1_10to1_9_3/Protocol1_10To1_9_3_4.java similarity index 95% rename from src/main/java/us/myles/ViaVersion/protocols/protocol1_10to1_9_3/Protocol1_10To1_9_3_4.java rename to common/src/main/java/us/myles/ViaVersion/protocols/protocol1_10to1_9_3/Protocol1_10To1_9_3_4.java index 70fbf44df..7d05cadc6 100644 --- a/src/main/java/us/myles/ViaVersion/protocols/protocol1_10to1_9_3/Protocol1_10To1_9_3_4.java +++ b/common/src/main/java/us/myles/ViaVersion/protocols/protocol1_10to1_9_3/Protocol1_10To1_9_3_4.java @@ -23,13 +23,13 @@ public class Protocol1_10To1_9_3_4 extends Protocol { @Deprecated public static final Type METADATA = new Metadata1_9Type(); - public static ValueTransformer toNewPitch = new ValueTransformer(Type.FLOAT) { + public static final ValueTransformer toNewPitch = new ValueTransformer(Type.FLOAT) { @Override public Float transform(PacketWrapper wrapper, Short inputValue) throws Exception { return inputValue / 63.5F; } }; - public static ValueTransformer, List> transformMetadata = new ValueTransformer, List>(Types1_9.METADATA_LIST) { + public static final ValueTransformer, List> transformMetadata = new ValueTransformer, List>(Types1_9.METADATA_LIST) { @Override public List transform(PacketWrapper wrapper, List inputValue) throws Exception { List metaList = new CopyOnWriteArrayList<>(inputValue); diff --git a/src/main/java/us/myles/ViaVersion/protocols/protocol1_10to1_9_3/storage/ResourcePackTracker.java b/common/src/main/java/us/myles/ViaVersion/protocols/protocol1_10to1_9_3/storage/ResourcePackTracker.java similarity index 100% rename from src/main/java/us/myles/ViaVersion/protocols/protocol1_10to1_9_3/storage/ResourcePackTracker.java rename to common/src/main/java/us/myles/ViaVersion/protocols/protocol1_10to1_9_3/storage/ResourcePackTracker.java diff --git a/src/main/java/us/myles/ViaVersion/protocols/protocol1_9_1_2to1_9_3_4/Protocol1_9_1_2TO1_9_3_4.java b/common/src/main/java/us/myles/ViaVersion/protocols/protocol1_9_1_2to1_9_3_4/Protocol1_9_1_2TO1_9_3_4.java similarity index 100% rename from src/main/java/us/myles/ViaVersion/protocols/protocol1_9_1_2to1_9_3_4/Protocol1_9_1_2TO1_9_3_4.java rename to common/src/main/java/us/myles/ViaVersion/protocols/protocol1_9_1_2to1_9_3_4/Protocol1_9_1_2TO1_9_3_4.java diff --git a/src/main/java/us/myles/ViaVersion/protocols/protocol1_9_1_2to1_9_3_4/chunks/BlockEntity.java b/common/src/main/java/us/myles/ViaVersion/protocols/protocol1_9_1_2to1_9_3_4/chunks/BlockEntity.java similarity index 95% rename from src/main/java/us/myles/ViaVersion/protocols/protocol1_9_1_2to1_9_3_4/chunks/BlockEntity.java rename to common/src/main/java/us/myles/ViaVersion/protocols/protocol1_9_1_2to1_9_3_4/chunks/BlockEntity.java index 96ca9f985..bda4b1731 100644 --- a/src/main/java/us/myles/ViaVersion/protocols/protocol1_9_1_2to1_9_3_4/chunks/BlockEntity.java +++ b/common/src/main/java/us/myles/ViaVersion/protocols/protocol1_9_1_2to1_9_3_4/chunks/BlockEntity.java @@ -3,7 +3,7 @@ package us.myles.ViaVersion.protocols.protocol1_9_1_2to1_9_3_4.chunks; import lombok.Getter; import org.spacehq.opennbt.tag.builtin.CompoundTag; 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.minecraft.Position; import us.myles.ViaVersion.api.type.Type; @@ -51,7 +51,7 @@ public class BlockEntity { updateBlockEntity(pos, (short) newId, tag, connection); } catch (Exception e) { - if (ViaVersion.getInstance().isDebug()) { + if (Via.getManager().isDebug()) { System.out.println("Block Entity: " + e.getMessage() + ": " + tag); } } diff --git a/src/main/java/us/myles/ViaVersion/protocols/protocol1_9_1_2to1_9_3_4/chunks/Chunk1_9_3_4.java b/common/src/main/java/us/myles/ViaVersion/protocols/protocol1_9_1_2to1_9_3_4/chunks/Chunk1_9_3_4.java similarity index 100% rename from src/main/java/us/myles/ViaVersion/protocols/protocol1_9_1_2to1_9_3_4/chunks/Chunk1_9_3_4.java rename to common/src/main/java/us/myles/ViaVersion/protocols/protocol1_9_1_2to1_9_3_4/chunks/Chunk1_9_3_4.java diff --git a/src/main/java/us/myles/ViaVersion/protocols/protocol1_9_1_2to1_9_3_4/chunks/ChunkSection1_9_3_4.java b/common/src/main/java/us/myles/ViaVersion/protocols/protocol1_9_1_2to1_9_3_4/chunks/ChunkSection1_9_3_4.java similarity index 99% rename from src/main/java/us/myles/ViaVersion/protocols/protocol1_9_1_2to1_9_3_4/chunks/ChunkSection1_9_3_4.java rename to common/src/main/java/us/myles/ViaVersion/protocols/protocol1_9_1_2to1_9_3_4/chunks/ChunkSection1_9_3_4.java index 4ea0b0afb..ff3d9a9a0 100644 --- a/src/main/java/us/myles/ViaVersion/protocols/protocol1_9_1_2to1_9_3_4/chunks/ChunkSection1_9_3_4.java +++ b/common/src/main/java/us/myles/ViaVersion/protocols/protocol1_9_1_2to1_9_3_4/chunks/ChunkSection1_9_3_4.java @@ -103,7 +103,7 @@ public class ChunkSection1_9_3_4 implements ChunkSection { * * * @param input The buffer to read from. - * @throws Exception + * @throws Exception If it fails to read */ public void readBlocks(ByteBuf input) throws Exception { palette.clear(); diff --git a/src/main/java/us/myles/ViaVersion/protocols/protocol1_9_1_2to1_9_3_4/types/Chunk1_9_3_4Type.java b/common/src/main/java/us/myles/ViaVersion/protocols/protocol1_9_1_2to1_9_3_4/types/Chunk1_9_3_4Type.java similarity index 96% rename from src/main/java/us/myles/ViaVersion/protocols/protocol1_9_1_2to1_9_3_4/types/Chunk1_9_3_4Type.java rename to common/src/main/java/us/myles/ViaVersion/protocols/protocol1_9_1_2to1_9_3_4/types/Chunk1_9_3_4Type.java index 684f1e4a3..c1552692e 100644 --- a/src/main/java/us/myles/ViaVersion/protocols/protocol1_9_1_2to1_9_3_4/types/Chunk1_9_3_4Type.java +++ b/common/src/main/java/us/myles/ViaVersion/protocols/protocol1_9_1_2to1_9_3_4/types/Chunk1_9_3_4Type.java @@ -2,8 +2,8 @@ package us.myles.ViaVersion.protocols.protocol1_9_1_2to1_9_3_4.types; import io.netty.buffer.ByteBuf; import io.netty.buffer.Unpooled; -import org.bukkit.World; import org.spacehq.opennbt.tag.builtin.CompoundTag; +import us.myles.ViaVersion.api.minecraft.Environment; import us.myles.ViaVersion.api.minecraft.chunks.Chunk; import us.myles.ViaVersion.api.minecraft.chunks.ChunkSection; import us.myles.ViaVersion.api.type.PartialType; @@ -48,7 +48,7 @@ public class Chunk1_9_3_4Type extends PartialType { sections[i] = section; section.readBlocks(input); section.readBlockLight(input); - if (world.getEnvironment() == World.Environment.NORMAL) { + if (world.getEnvironment() == Environment.NORMAL) { section.readSkyLight(input); } } diff --git a/src/main/java/us/myles/ViaVersion/protocols/protocol1_9_1to1_9/Protocol1_9_1TO1_9.java b/common/src/main/java/us/myles/ViaVersion/protocols/protocol1_9_1to1_9/Protocol1_9_1TO1_9.java similarity index 100% rename from src/main/java/us/myles/ViaVersion/protocols/protocol1_9_1to1_9/Protocol1_9_1TO1_9.java rename to common/src/main/java/us/myles/ViaVersion/protocols/protocol1_9_1to1_9/Protocol1_9_1TO1_9.java diff --git a/src/main/java/us/myles/ViaVersion/protocols/protocol1_9_3to1_9_1_2/Protocol1_9_3TO1_9_1_2.java b/common/src/main/java/us/myles/ViaVersion/protocols/protocol1_9_3to1_9_1_2/Protocol1_9_3TO1_9_1_2.java similarity index 100% rename from src/main/java/us/myles/ViaVersion/protocols/protocol1_9_3to1_9_1_2/Protocol1_9_3TO1_9_1_2.java rename to common/src/main/java/us/myles/ViaVersion/protocols/protocol1_9_3to1_9_1_2/Protocol1_9_3TO1_9_1_2.java diff --git a/src/main/java/us/myles/ViaVersion/protocols/protocol1_9_3to1_9_1_2/chunks/Chunk1_9_1_2.java b/common/src/main/java/us/myles/ViaVersion/protocols/protocol1_9_3to1_9_1_2/chunks/Chunk1_9_1_2.java similarity index 100% rename from src/main/java/us/myles/ViaVersion/protocols/protocol1_9_3to1_9_1_2/chunks/Chunk1_9_1_2.java rename to common/src/main/java/us/myles/ViaVersion/protocols/protocol1_9_3to1_9_1_2/chunks/Chunk1_9_1_2.java diff --git a/src/main/java/us/myles/ViaVersion/protocols/protocol1_9_3to1_9_1_2/chunks/ChunkSection1_9_1_2.java b/common/src/main/java/us/myles/ViaVersion/protocols/protocol1_9_3to1_9_1_2/chunks/ChunkSection1_9_1_2.java similarity index 99% rename from src/main/java/us/myles/ViaVersion/protocols/protocol1_9_3to1_9_1_2/chunks/ChunkSection1_9_1_2.java rename to common/src/main/java/us/myles/ViaVersion/protocols/protocol1_9_3to1_9_1_2/chunks/ChunkSection1_9_1_2.java index 17993598f..0e7ed30d9 100644 --- a/src/main/java/us/myles/ViaVersion/protocols/protocol1_9_3to1_9_1_2/chunks/ChunkSection1_9_1_2.java +++ b/common/src/main/java/us/myles/ViaVersion/protocols/protocol1_9_3to1_9_1_2/chunks/ChunkSection1_9_1_2.java @@ -103,7 +103,7 @@ public class ChunkSection1_9_1_2 implements ChunkSection { * * * @param input The buffer to read from. - * @throws Exception + * @throws Exception If it failed to read properly */ public void readBlocks(ByteBuf input) throws Exception { palette.clear(); diff --git a/common/src/main/java/us/myles/ViaVersion/protocols/protocol1_9_3to1_9_1_2/chunks/FakeTileEntity.java b/common/src/main/java/us/myles/ViaVersion/protocols/protocol1_9_3to1_9_1_2/chunks/FakeTileEntity.java new file mode 100644 index 000000000..62250aff1 --- /dev/null +++ b/common/src/main/java/us/myles/ViaVersion/protocols/protocol1_9_3to1_9_1_2/chunks/FakeTileEntity.java @@ -0,0 +1,69 @@ +package us.myles.ViaVersion.protocols.protocol1_9_3to1_9_1_2.chunks; + +import org.spacehq.opennbt.tag.builtin.CompoundTag; +import org.spacehq.opennbt.tag.builtin.IntTag; +import org.spacehq.opennbt.tag.builtin.StringTag; + +import java.util.Arrays; +import java.util.List; +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; + +/** + * Mojang changed the way how tile entities inside chunk packets work in 1.10.1 + * It requires now to have all tile entity data included in the chunk packet, otherwise it'll crash. + */ +public class FakeTileEntity { + private static final Map tileEntities = new ConcurrentHashMap<>(); + + static { + register(Arrays.asList(61, 62), "Furnace"); + register(Arrays.asList(54, 146), "Chest"); + register(130, "EnderChest"); + register(84, "RecordPlayer"); + register(23, "Trap"); // Dispenser + register(158, "Dropper"); + register(Arrays.asList(63, 68), "Sign"); + register(52, "MobSpawner"); + register(25, "Music"); // Note Block + register(Arrays.asList(33, 34, 29, 36), "Piston"); + register(117, "Cauldron"); // Brewing stand + register(116, "EnchantTable"); + register(Arrays.asList(119, 120), "Airportal"); // End portal + register(138, "Beacon"); + register(144, "Skull"); + register(Arrays.asList(178, 151), "DLDetector"); + register(154, "Hopper"); + register(Arrays.asList(149, 150), "Comparator"); + register(140, "FlowerPot"); + register(Arrays.asList(176, 177), "Banner"); + register(209, "EndGateway"); + register(137, "Control"); + } + + private static void register(Integer material, String name) { + CompoundTag comp = new CompoundTag(""); + comp.put(new StringTag(name)); + tileEntities.put(material, comp); + } + + private static void register(List materials, String name) { + for (int m : materials) + register(m, name); + } + + public static boolean hasBlock(int block) { + return tileEntities.containsKey(block); + } + + public static CompoundTag getFromBlock(int x, int y, int z, int block) { + if (tileEntities.containsKey(block)) { + CompoundTag tag = tileEntities.get(block).clone(); + tag.put(new IntTag("x", x)); + tag.put(new IntTag("y", y)); + tag.put(new IntTag("z", z)); + return tag; + } + return null; + } +} diff --git a/common/src/main/java/us/myles/ViaVersion/protocols/protocol1_9_3to1_9_1_2/storage/ClientWorld.java b/common/src/main/java/us/myles/ViaVersion/protocols/protocol1_9_3to1_9_1_2/storage/ClientWorld.java new file mode 100644 index 000000000..9dcca3354 --- /dev/null +++ b/common/src/main/java/us/myles/ViaVersion/protocols/protocol1_9_3to1_9_1_2/storage/ClientWorld.java @@ -0,0 +1,25 @@ +package us.myles.ViaVersion.protocols.protocol1_9_3to1_9_1_2.storage; + +import lombok.Getter; +import us.myles.ViaVersion.api.data.StoredObject; +import us.myles.ViaVersion.api.data.UserConnection; +import us.myles.ViaVersion.api.minecraft.Environment; + +@Getter +public class ClientWorld extends StoredObject { + private Environment environment; + + public ClientWorld(UserConnection user) { + super(user); + } + + public void setEnvironment(int environmentId) { + this.environment = getEnvFromId(environmentId); + } + + private Environment getEnvFromId(int id) { + Environment output = Environment.getEnvironmentById(id); + if (output == null) return Environment.NETHER; + return output; + } +} diff --git a/src/main/java/us/myles/ViaVersion/protocols/protocol1_9_3to1_9_1_2/types/Chunk1_9_1_2Type.java b/common/src/main/java/us/myles/ViaVersion/protocols/protocol1_9_3to1_9_1_2/types/Chunk1_9_1_2Type.java similarity index 90% rename from src/main/java/us/myles/ViaVersion/protocols/protocol1_9_3to1_9_1_2/types/Chunk1_9_1_2Type.java rename to common/src/main/java/us/myles/ViaVersion/protocols/protocol1_9_3to1_9_1_2/types/Chunk1_9_1_2Type.java index cb5d31c10..a1459db83 100644 --- a/src/main/java/us/myles/ViaVersion/protocols/protocol1_9_3to1_9_1_2/types/Chunk1_9_1_2Type.java +++ b/common/src/main/java/us/myles/ViaVersion/protocols/protocol1_9_3to1_9_1_2/types/Chunk1_9_1_2Type.java @@ -2,9 +2,9 @@ package us.myles.ViaVersion.protocols.protocol1_9_3to1_9_1_2.types; import io.netty.buffer.ByteBuf; import io.netty.buffer.Unpooled; -import org.bukkit.World; import org.spacehq.opennbt.tag.builtin.CompoundTag; -import us.myles.ViaVersion.api.ViaVersion; +import us.myles.ViaVersion.api.Via; +import us.myles.ViaVersion.api.minecraft.Environment; import us.myles.ViaVersion.api.minecraft.chunks.Chunk; import us.myles.ViaVersion.api.minecraft.chunks.ChunkSection; import us.myles.ViaVersion.api.type.PartialType; @@ -27,8 +27,8 @@ public class Chunk1_9_1_2Type extends PartialType { @Override public Chunk read(ByteBuf input, ClientWorld world) throws Exception { - boolean replacePistons = world.getUser().get(ProtocolInfo.class).getPipeline().contains(Protocol1_10To1_9_3_4.class) && ViaVersion.getConfig().isReplacePistons(); - int replacementId = ViaVersion.getConfig().getPistonReplacementId(); + boolean replacePistons = world.getUser().get(ProtocolInfo.class).getPipeline().contains(Protocol1_10To1_9_3_4.class) && Via.getConfig().isReplacePistons(); + int replacementId = Via.getConfig().getPistonReplacementId(); int chunkX = input.readInt(); int chunkZ = input.readInt(); @@ -53,7 +53,7 @@ public class Chunk1_9_1_2Type extends PartialType { sections[i] = section; section.readBlocks(input); section.readBlockLight(input); - if (world.getEnvironment() == World.Environment.NORMAL) { + if (world.getEnvironment() == Environment.NORMAL) { section.readSkyLight(input); } if (replacePistons) { @@ -72,9 +72,7 @@ public class Chunk1_9_1_2Type extends PartialType { } @Override - public void write(ByteBuf output, ClientWorld world, Chunk input) throws Exception { - Chunk chunk = input; - + public void write(ByteBuf output, ClientWorld world, Chunk chunk) throws Exception { output.writeInt(chunk.getX()); output.writeInt(chunk.getZ()); diff --git a/common/src/main/java/us/myles/ViaVersion/protocols/protocol1_9to1_8/ArmorType.java b/common/src/main/java/us/myles/ViaVersion/protocols/protocol1_9to1_8/ArmorType.java new file mode 100644 index 000000000..b4f830521 --- /dev/null +++ b/common/src/main/java/us/myles/ViaVersion/protocols/protocol1_9to1_8/ArmorType.java @@ -0,0 +1,107 @@ +package us.myles.ViaVersion.protocols.protocol1_9to1_8; + +import lombok.Getter; +import lombok.RequiredArgsConstructor; + +import java.util.HashMap; + +@RequiredArgsConstructor +@Getter +public enum ArmorType { + + LEATHER_HELMET(1, 298, "minecraft:leather_helmet"), + LEATHER_CHESTPLATE(3, 299, "minecraft:leather_chestplate"), + LEATHER_LEGGINGS(2, 300, "minecraft:leather_leggings"), + LEATHER_BOOTS(1, 301, "minecraft:leather_boots"), + CHAINMAIL_HELMET(2, 302, "minecraft:chainmail_helmet"), + CHAINMAIL_CHESTPLATE(5, 303, "minecraft:chainmail_chestplate"), + CHAINMAIL_LEGGINGS(4, 304, "minecraft:chainmail_leggings"), + CHAINMAIL_BOOTS(1, 305, "minecraft:chainmail_boots"), + IRON_HELMET(2, 306, "minecraft:iron_helmet"), + IRON_CHESTPLATE(6, 307, "minecraft:iron_chestplate"), + IRON_LEGGINGS(5, 308, "minecraft:iron_leggings"), + IRON_BOOTS(2, 309, "minecraft:iron_boots"), + DIAMOND_HELMET(3, 310, "minecraft:diamond_helmet"), + DIAMOND_CHESTPLATE(8, 311, "minecraft:diamond_chestplate"), + DIAMOND_LEGGINGS(6, 312, "minecraft:diamond_leggings"), + DIAMOND_BOOTS(3, 313, "minecraft:diamond_boots"), + GOLD_HELMET(2, 314, "minecraft:gold_helmet"), + GOLD_CHESTPLATE(5, 315, "minecraft:gold_chestplate"), + GOLD_LEGGINGS(3, 316, "minecraft:gold_leggings"), + GOLD_BOOTS(1, 317, "minecraft:gold_boots"), + NONE(0, 0, "none"); + + private static HashMap armor; + + static { + armor = new HashMap<>(); + for (ArmorType a : ArmorType.values()) { + armor.put(a.getId(), a); + } + } + + private final int armorPoints; + private final int id; + private final String type; + + /** + * Find an armour type by the item id + * + * @param id ID of the item + * @return Return the ArmourType, ArmourType.NONE if not found + */ + public static ArmorType findById(int id) { + for (ArmorType a : ArmorType.values()) + if (a.getId() == id) + return a; + return ArmorType.NONE; + } + + /** + * Find an armour type by the item string + * + * @param type String name for the item + * @return Return the ArmourType, ArmourType.NONE if not found + */ + public static ArmorType findByType(String type) { + for (ArmorType a : ArmorType.values()) + if (a.getType().equals(type)) + return a; + return NONE; + } + + /** + * Check if an item id is armour + * + * @param id The item ID + * @return True if the item is a piece of armour + */ + public static boolean isArmor(int id) { + for (ArmorType a : ArmorType.values()) + if (a.getId() == id) + return true; + return false; + } + + /** + * Check if an item id is armour + * + * @param type The item material name + * @return True if the item is a piece of armour + */ + public static boolean isArmor(String type) { + for (ArmorType a : ArmorType.values()) + if (a.getType().equals(type)) + return true; + return false; + } + + /** + * Get the Minecraft ID for the Armour Type + * + * @return The ID + */ + public int getId() { + return this.id; + } +} \ No newline at end of file diff --git a/src/main/java/us/myles/ViaVersion/protocols/protocol1_9to1_8/ItemRewriter.java b/common/src/main/java/us/myles/ViaVersion/protocols/protocol1_9to1_8/ItemRewriter.java similarity index 96% rename from src/main/java/us/myles/ViaVersion/protocols/protocol1_9to1_8/ItemRewriter.java rename to common/src/main/java/us/myles/ViaVersion/protocols/protocol1_9to1_8/ItemRewriter.java index 3d3b7b30b..6f663e37f 100644 --- a/src/main/java/us/myles/ViaVersion/protocols/protocol1_9to1_8/ItemRewriter.java +++ b/common/src/main/java/us/myles/ViaVersion/protocols/protocol1_9to1_8/ItemRewriter.java @@ -1,6 +1,5 @@ package us.myles.ViaVersion.protocols.protocol1_9to1_8; -import org.bukkit.Material; import org.spacehq.opennbt.tag.builtin.CompoundTag; import org.spacehq.opennbt.tag.builtin.ListTag; import org.spacehq.opennbt.tag.builtin.StringTag; @@ -140,7 +139,7 @@ public class ItemRewriter { public static void toServer(Item item) { if (item != null) { - if (item.getId() == Material.MONSTER_EGG.getId() && item.getData() == 0) { + if (item.getId() == 383 && item.getData() == 0) { // Monster Egg CompoundTag tag = item.getTag(); int data = 0; if (tag != null && tag.get("EntityTag") instanceof CompoundTag) { @@ -155,7 +154,7 @@ public class ItemRewriter { item.setTag(tag); item.setData((short) data); } - if (item.getId() == Material.POTION.getId()) { + if (item.getId() == 373) { // Potion CompoundTag tag = item.getTag(); int data = 0; if (tag != null && tag.get("Potion") instanceof StringTag) { @@ -169,11 +168,11 @@ public class ItemRewriter { item.setTag(tag); item.setData((short) data); } - //Splash potion + // Splash potion if (item.getId() == 438) { CompoundTag tag = item.getTag(); int data = 0; - item.setId((short) Material.POTION.getId()); + item.setId((short) 373); // Potion if (tag != null && tag.get("Potion") instanceof StringTag) { StringTag potion = tag.get("Potion"); String potionName = potion.getValue().replace("minecraft:", ""); @@ -190,7 +189,7 @@ public class ItemRewriter { public static void toClient(Item item) { if (item != null) { - if (item.getId() == Material.MONSTER_EGG.getId() && item.getData() != 0) { + if (item.getId() == 383 && item.getData() != 0) { // Monster Egg CompoundTag tag = item.getTag(); if (tag == null) { tag = new CompoundTag("tag"); @@ -204,7 +203,7 @@ public class ItemRewriter { item.setTag(tag); item.setData((short) 0); } - if (item.getId() == Material.POTION.getId()) { + if (item.getId() == 373) { // Potion CompoundTag tag = item.getTag(); if (tag == null) { tag = new CompoundTag("tag"); @@ -219,7 +218,7 @@ public class ItemRewriter { item.setTag(tag); item.setData((short) 0); } - if (item.getId() == Material.WRITTEN_BOOK.getId()) { + if (item.getId() == 387) { // WRITTEN_BOOK CompoundTag tag = item.getTag(); if (tag == null) { tag = new CompoundTag("tag"); diff --git a/src/main/java/us/myles/ViaVersion/protocols/protocol1_9to1_8/PlayerMovementMapper.java b/common/src/main/java/us/myles/ViaVersion/protocols/protocol1_9to1_8/PlayerMovementMapper.java similarity index 100% rename from src/main/java/us/myles/ViaVersion/protocols/protocol1_9to1_8/PlayerMovementMapper.java rename to common/src/main/java/us/myles/ViaVersion/protocols/protocol1_9to1_8/PlayerMovementMapper.java diff --git a/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 similarity index 53% rename from src/main/java/us/myles/ViaVersion/protocols/protocol1_9to1_8/Protocol1_9TO1_8.java rename to common/src/main/java/us/myles/ViaVersion/protocols/protocol1_9to1_8/Protocol1_9TO1_8.java index 05cc8bcb8..ed8a0e456 100644 --- a/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 @@ -1,43 +1,37 @@ package us.myles.ViaVersion.protocols.protocol1_9to1_8; -import com.google.gson.Gson; -import com.google.gson.GsonBuilder; import com.google.gson.JsonObject; -import org.bukkit.Bukkit; -import us.myles.ViaVersion.ViaVersionPlugin; 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.minecraft.item.Item; import us.myles.ViaVersion.api.minecraft.metadata.Metadata; +import us.myles.ViaVersion.api.platform.providers.ViaProviders; import us.myles.ViaVersion.api.protocol.Protocol; 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.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.providers.BulkChunkTranslatorProvider; +import us.myles.ViaVersion.protocols.protocol1_9to1_8.providers.HandItemProvider; +import us.myles.ViaVersion.protocols.protocol1_9to1_8.providers.MovementTransmitterProvider; import us.myles.ViaVersion.protocols.protocol1_9to1_8.storage.*; +import us.myles.ViaVersion.util.GsonUtil; import java.util.List; -import java.util.UUID; -import java.util.concurrent.Callable; -import java.util.concurrent.TimeUnit; public class Protocol1_9TO1_8 extends Protocol { - @Deprecated - public static Type> METADATA_LIST = new MetadataList1_8Type(); - @Deprecated - public static Type METADATA = new Metadata1_8Type(); - - private static Gson gson = new GsonBuilder().create(); - public static ValueTransformer FIX_JSON = new ValueTransformer(Type.STRING) { + public static final ValueTransformer FIX_JSON = new ValueTransformer(Type.STRING) { @Override public String transform(PacketWrapper wrapper, String line) { return fixJson(line); } }; + @Deprecated + public static Type> METADATA_LIST = new MetadataList1_8Type(); + @Deprecated + public static Type METADATA = new Metadata1_8Type(); public static String fixJson(String line) { if (line == null || line.equalsIgnoreCase("null")) { @@ -51,9 +45,9 @@ public class Protocol1_9TO1_8 extends Protocol { } } try { - gson.fromJson(line, JsonObject.class); + GsonUtil.getGson().fromJson(line, JsonObject.class); } catch (Exception e) { - if (ViaVersion.getConfig().isForceJsonTransform()) { + if (Via.getConfig().isForceJsonTransform()) { return constructJson(line); } else { System.out.println("Invalid JSON String: \"" + line + "\" Please report this issue to the ViaVersion Github: " + e.getMessage()); @@ -66,31 +60,21 @@ public class Protocol1_9TO1_8 extends Protocol { private static String constructJson(String text) { JsonObject jsonObject = new JsonObject(); jsonObject.addProperty("text", text); - return gson.toJson(jsonObject); + return GsonUtil.getGson().toJson(jsonObject); } public static Item getHandItem(final UserConnection info) { - if (HandItemCache.CACHE) { - return HandItemCache.getHandItem(info.get(ProtocolInfo.class).getUuid()); - } else { - try { - return Bukkit.getScheduler().callSyncMethod(Bukkit.getPluginManager().getPlugin("ViaVersion"), new Callable() { - @Override - public Item call() throws Exception { - UUID playerUUID = info.get(ProtocolInfo.class).getUuid(); - if (Bukkit.getPlayer(playerUUID) != null) { - return Item.getItem(Bukkit.getPlayer(playerUUID).getItemInHand()); - } - return null; - } - }).get(10, TimeUnit.SECONDS); - } catch (Exception e) { - System.out.println("Error fetching hand item: " + e.getClass().getName()); - if (ViaVersion.getInstance().isDebug()) - e.printStackTrace(); - return null; - } - } + return Via.getManager().getProviders().get(HandItemProvider.class).getHandItem(info); + } + + public static boolean isSword(int id) { + if (id == 267) return true; // Iron + if (id == 268) return true; // Wood + if (id == 272) return true; // Stone + if (id == 276) return true; // Diamond + if (id == 283) return true; // Gold + + return false; } @Override @@ -103,29 +87,19 @@ public class Protocol1_9TO1_8 extends Protocol { } @Override - protected void registerListeners() { - ViaVersionPlugin plugin = (ViaVersionPlugin) Bukkit.getPluginManager().getPlugin("ViaVersion"); - - new ArmorListener(plugin).register(); - new CommandBlockListener(plugin).register(); - new DeathListener(plugin).register(); - new BlockListener(plugin).register(); - - if (Bukkit.getVersion().toLowerCase().contains("paper") || Bukkit.getVersion().toLowerCase().contains("taco")) { - plugin.getLogger().info("Enabling PaperSpigot/TacoSpigot patch: Fixes block placement."); - new PaperPatch(plugin).register(); - } - if (plugin.getConf().isStimulatePlayerTick()) - new ViaIdleThread(plugin.getPortedPlayers()).runTaskTimer(plugin, 1L, 1L); // Updates player's idle status - if (plugin.getConf().isItemCache()) { - new HandItemCache().runTaskTimerAsynchronously(plugin, 2L, 2L); // Updates player's items :) - HandItemCache.CACHE = true; + protected void register(ViaProviders providers) { + providers.register(HandItemProvider.class, new HandItemProvider()); + providers.register(BulkChunkTranslatorProvider.class, new BulkChunkTranslatorProvider()); + providers.require(MovementTransmitterProvider.class); + if (Via.getConfig().isStimulatePlayerTick()) { + Via.getPlatform().runRepeatingSync(new ViaIdleThread(), 1L); } } @Override public boolean isFiltered(Class packetClass) { - return packetClass.getName().endsWith("PacketPlayOutMapChunkBulk"); + return Via.getManager().getProviders().get(BulkChunkTranslatorProvider.class).isFiltered(packetClass); + } @Override diff --git a/common/src/main/java/us/myles/ViaVersion/protocols/protocol1_9to1_8/ViaIdleThread.java b/common/src/main/java/us/myles/ViaVersion/protocols/protocol1_9to1_8/ViaIdleThread.java new file mode 100644 index 000000000..675df3a22 --- /dev/null +++ b/common/src/main/java/us/myles/ViaVersion/protocols/protocol1_9to1_8/ViaIdleThread.java @@ -0,0 +1,23 @@ +package us.myles.ViaVersion.protocols.protocol1_9to1_8; + +import us.myles.ViaVersion.api.Via; +import us.myles.ViaVersion.api.data.UserConnection; +import us.myles.ViaVersion.protocols.base.ProtocolInfo; +import us.myles.ViaVersion.protocols.protocol1_9to1_8.providers.MovementTransmitterProvider; +import us.myles.ViaVersion.protocols.protocol1_9to1_8.storage.MovementTracker; + +public class ViaIdleThread implements Runnable { + @Override + public void run() { + for (UserConnection info : Via.getManager().getPortedPlayers().values()) { + if (info.has(ProtocolInfo.class) && info.get(ProtocolInfo.class).getPipeline().contains(Protocol1_9TO1_8.class)) { + long nextIdleUpdate = info.get(MovementTracker.class).getNextIdlePacket(); + if (nextIdleUpdate <= System.currentTimeMillis()) { + if (info.getChannel().isOpen()) { + Via.getManager().getProviders().get(MovementTransmitterProvider.class).sendPlayer(info); + } + } + } + } + } +} diff --git a/src/main/java/us/myles/ViaVersion/protocols/protocol1_9to1_8/chat/ChatRewriter.java b/common/src/main/java/us/myles/ViaVersion/protocols/protocol1_9to1_8/chat/ChatRewriter.java similarity index 80% rename from src/main/java/us/myles/ViaVersion/protocols/protocol1_9to1_8/chat/ChatRewriter.java rename to common/src/main/java/us/myles/ViaVersion/protocols/protocol1_9to1_8/chat/ChatRewriter.java index ad757c201..c26b460ef 100644 --- a/src/main/java/us/myles/ViaVersion/protocols/protocol1_9to1_8/chat/ChatRewriter.java +++ b/common/src/main/java/us/myles/ViaVersion/protocols/protocol1_9to1_8/chat/ChatRewriter.java @@ -6,6 +6,12 @@ import us.myles.ViaVersion.api.data.UserConnection; import us.myles.ViaVersion.protocols.protocol1_9to1_8.storage.EntityTracker; public class ChatRewriter { + /** + * Rewrite chat being sent to the client so that gamemode issues don't occur. + * + * @param obj The json object being sent by the server + * @param user The player involved. (Required for Gamemode info) + */ public static void toClient(JsonObject obj, UserConnection user) { //Check gamemode change if (obj.get("translate") != null && obj.get("translate").getAsString().equals("gameMode.changed")) { diff --git a/src/main/java/us/myles/ViaVersion/protocols/protocol1_9to1_8/chat/GameMode.java b/common/src/main/java/us/myles/ViaVersion/protocols/protocol1_9to1_8/chat/GameMode.java similarity index 100% rename from src/main/java/us/myles/ViaVersion/protocols/protocol1_9to1_8/chat/GameMode.java rename to common/src/main/java/us/myles/ViaVersion/protocols/protocol1_9to1_8/chat/GameMode.java diff --git a/src/main/java/us/myles/ViaVersion/protocols/protocol1_9to1_8/chunks/Chunk1_9to1_8.java b/common/src/main/java/us/myles/ViaVersion/protocols/protocol1_9to1_8/chunks/Chunk1_9to1_8.java similarity index 100% rename from src/main/java/us/myles/ViaVersion/protocols/protocol1_9to1_8/chunks/Chunk1_9to1_8.java rename to common/src/main/java/us/myles/ViaVersion/protocols/protocol1_9to1_8/chunks/Chunk1_9to1_8.java diff --git a/src/main/java/us/myles/ViaVersion/protocols/protocol1_9to1_8/chunks/ChunkSection1_9to1_8.java b/common/src/main/java/us/myles/ViaVersion/protocols/protocol1_9to1_8/chunks/ChunkSection1_9to1_8.java similarity index 99% rename from src/main/java/us/myles/ViaVersion/protocols/protocol1_9to1_8/chunks/ChunkSection1_9to1_8.java rename to common/src/main/java/us/myles/ViaVersion/protocols/protocol1_9to1_8/chunks/ChunkSection1_9to1_8.java index 0953941ed..8d837a37f 100644 --- a/src/main/java/us/myles/ViaVersion/protocols/protocol1_9to1_8/chunks/ChunkSection1_9to1_8.java +++ b/common/src/main/java/us/myles/ViaVersion/protocols/protocol1_9to1_8/chunks/ChunkSection1_9to1_8.java @@ -46,7 +46,7 @@ public class ChunkSection1_9to1_8 implements ChunkSection { setBlock(index(x, y, z), type, data); } - public int getBlockId(int x, int y, int z){ + public int getBlockId(int x, int y, int z) { int index = blocks[index(x, y, z)]; return palette.get(index) >> 4; } diff --git a/common/src/main/java/us/myles/ViaVersion/protocols/protocol1_9to1_8/metadata/MetaIndex.java b/common/src/main/java/us/myles/ViaVersion/protocols/protocol1_9to1_8/metadata/MetaIndex.java new file mode 100644 index 000000000..ffe476089 --- /dev/null +++ b/common/src/main/java/us/myles/ViaVersion/protocols/protocol1_9to1_8/metadata/MetaIndex.java @@ -0,0 +1,199 @@ +package us.myles.ViaVersion.protocols.protocol1_9to1_8.metadata; + +import com.google.common.base.Optional; +import lombok.Getter; +import us.myles.ViaVersion.api.Pair; +import us.myles.ViaVersion.api.entities.Entity1_10Types; +import us.myles.ViaVersion.api.minecraft.metadata.types.MetaType1_8; +import us.myles.ViaVersion.api.minecraft.metadata.types.MetaType1_9; + +import java.util.HashMap; + +import static us.myles.ViaVersion.api.entities.Entity1_10Types.EntityType.*; + +@Getter +public enum MetaIndex { + + // entity + ENTITY_STATUS(ENTITY, 0, MetaType1_8.Byte, MetaType1_9.Byte), + ENTITY_AIR(ENTITY, 1, MetaType1_8.Short, MetaType1_9.VarInt), + ENTITY_NAMETAG(ENTITY, 2, MetaType1_8.String, MetaType1_9.String), // in the entity class @ spigot 1.8.8, blame wiki.vg + ENTITY_ALWAYS_SHOW_NAMETAG(ENTITY, 3, MetaType1_8.Byte, MetaType1_9.Boolean), // in the entity class @ Spigot 1.8.8, blame wiki.vg + ENTITY_SILENT(ENTITY, 4, MetaType1_8.Byte, MetaType1_9.Boolean), + // living entity + LIVINGENTITY_HEALTH(ENTITY_LIVING, 6, MetaType1_8.Float, MetaType1_9.Float), + LIVINGENTITY_POTION_EFFECT_COLOR(ENTITY_LIVING, 7, MetaType1_8.Int, MetaType1_9.VarInt), + LIVINGENTITY_IS_POTION_AMBIENT(ENTITY_LIVING, 8, MetaType1_8.Byte, MetaType1_9.Boolean), + LIVINGENTITY_NUMBER_OF_ARROWS_IN(ENTITY_LIVING, 9, MetaType1_8.Byte, MetaType1_9.VarInt), + LIVINGENTITY_NO_AI(ENTITY_LIVING, 15, MetaType1_8.Byte, 10, MetaType1_9.Byte), // in 1.9 this is combined with Left handed, oh. + // ageable + AGEABLE_AGE(ENTITY_AGEABLE, 12, MetaType1_8.Byte, 11, MetaType1_9.Boolean), + // armour stand + STAND_INFO(ARMOR_STAND, 10, MetaType1_8.Byte, MetaType1_9.Byte), + STAND_HEAD_POS(ARMOR_STAND, 11, MetaType1_8.Rotation, MetaType1_9.Vector3F), + STAND_BODY_POS(ARMOR_STAND, 12, MetaType1_8.Rotation, MetaType1_9.Vector3F), + STAND_LA_POS(ARMOR_STAND, 13, MetaType1_8.Rotation, MetaType1_9.Vector3F), + STAND_RA_POS(ARMOR_STAND, 14, MetaType1_8.Rotation, MetaType1_9.Vector3F), + STAND_LL_POS(ARMOR_STAND, 15, MetaType1_8.Rotation, MetaType1_9.Vector3F), + STAND_RL_POS(ARMOR_STAND, 16, MetaType1_8.Rotation, MetaType1_9.Vector3F), + // human, discountined? + PLAYER_SKIN_FLAGS(ENTITY_HUMAN, 10, MetaType1_8.Byte, 12, MetaType1_9.Byte), // unsigned on 1.8 + PLAYER_HUMAN_BYTE(ENTITY_HUMAN, 16, MetaType1_8.Byte, MetaType1_9.Discontinued), // unused on 1.8 + PLAYER_ADDITIONAL_HEARTS(ENTITY_HUMAN, 17, MetaType1_8.Float, 10, MetaType1_9.Float), + PLAYER_SCORE(ENTITY_HUMAN, 18, MetaType1_8.Int, 11, MetaType1_9.VarInt), + PLAYER_HAND(ENTITY_HUMAN, -1, MetaType1_8.NonExistent, 5, MetaType1_9.Byte), // new in 1.9 + SOMETHING_ANTICHEAT_PLUGINS_FOR_SOME_REASON_USE(ENTITY_HUMAN, 11, MetaType1_8.Byte, MetaType1_9.Discontinued), //For what we know, This doesn't exists. If you think it exists and knows what it does. Please tell us. + // horse + HORSE_INFO(HORSE, 16, MetaType1_8.Int, 12, MetaType1_9.Byte), + HORSE_TYPE(HORSE, 19, MetaType1_8.Byte, 13, MetaType1_9.VarInt), + HORSE_SUBTYPE(HORSE, 20, MetaType1_8.Int, 14, MetaType1_9.VarInt), + HORSE_OWNER(HORSE, 21, MetaType1_8.String, 15, MetaType1_9.OptUUID), + HORSE_ARMOR(HORSE, 22, MetaType1_8.Int, 16, MetaType1_9.VarInt), + // bat + BAT_ISHANGING(BAT, 16, MetaType1_8.Byte, 11, MetaType1_9.Byte), + // tameable + TAMING_INFO(ENTITY_TAMEABLE_ANIMAL, 16, MetaType1_8.Byte, 12, MetaType1_9.Byte), + TAMING_OWNER(ENTITY_TAMEABLE_ANIMAL, 17, MetaType1_8.String, 13, MetaType1_9.OptUUID), + // ocelot + OCELOT_TYPE(OCELOT, 18, MetaType1_8.Byte, 14, MetaType1_9.VarInt), + // wolf + WOLF_HEALTH(WOLF, 18, MetaType1_8.Float, 14, MetaType1_9.Float), + WOLF_BEGGING(WOLF, 19, MetaType1_8.Byte, 15, MetaType1_9.Boolean), + WOLF_COLLAR(WOLF, 20, MetaType1_8.Byte, 16, MetaType1_9.VarInt), + // pig + PIG_SADDLE(PIG, 16, MetaType1_8.Byte, 12, MetaType1_9.Boolean), + // rabbit + RABBIT_TYPE(RABBIT, 18, MetaType1_8.Byte, 12, MetaType1_9.VarInt), + // sheep + SHEEP_COLOR(SHEEP, 16, MetaType1_8.Byte, 12, MetaType1_9.Byte), + // villager + VILLAGER_PROFESSION(VILLAGER, 16, MetaType1_8.Int, 12, MetaType1_9.VarInt), + // enderman + ENDERMAN_BLOCK(ENDERMAN, 16, MetaType1_8.Short, 11, MetaType1_9.BlockID), // special case + ENDERMAN_BLOCKDATA(ENDERMAN, 17, MetaType1_8.Byte, 11, MetaType1_9.BlockID), // special case + ENDERMAN_ISSCREAMING(ENDERMAN, 18, MetaType1_8.Byte, 12, MetaType1_9.Boolean), + // zombie + ZOMBIE_ISCHILD(ZOMBIE, 12, MetaType1_8.Byte, 11, MetaType1_9.Boolean), + ZOMBIE_ISVILLAGER(ZOMBIE, 13, MetaType1_8.Byte, 12, MetaType1_9.VarInt), + ZOMBIE_ISCONVERTING(ZOMBIE, 14, MetaType1_8.Byte, 13, MetaType1_9.Boolean), + // ZOMBIE_RISINGHANDS added in 1.9 + // blaze + BLAZE_ONFIRE(BLAZE, 16, MetaType1_8.Byte, 11, MetaType1_9.Byte), + // spider + SPIDER_CIMBING(SPIDER, 16, MetaType1_8.Byte, 11, MetaType1_9.Byte), + // creeper + CREEPER_FUSE(CREEPER, 16, MetaType1_8.Byte, 11, MetaType1_9.VarInt), // -1 idle, 1 is fuse + CREEPER_ISPOWERED(CREEPER, 17, MetaType1_8.Byte, 12, MetaType1_9.Boolean), + CREEPER_ISIGNITED(CREEPER, 18, MetaType1_8.Byte, 13, MetaType1_9.Boolean), + // ghast + GHAST_ISATTACKING(GHAST, 16, MetaType1_8.Byte, 11, MetaType1_9.Boolean), + // slime + SLIME_SIZE(SLIME, 16, MetaType1_8.Byte, 11, MetaType1_9.VarInt), + // skeleton + SKELETON_TYPE(SKELETON, 13, MetaType1_8.Byte, 11, MetaType1_9.VarInt), + // witch + WITCH_AGGRO(WITCH, 21, MetaType1_8.Byte, 11, MetaType1_9.Boolean), + // iron golem + IRON_PLAYERMADE(IRON_GOLEM, 16, MetaType1_8.Byte, 11, MetaType1_9.Byte), + // wither + WITHER_TARGET1(WITHER, 17, MetaType1_8.Int, 11, MetaType1_9.VarInt), + WITHER_TARGET2(WITHER, 18, MetaType1_8.Int, 12, MetaType1_9.VarInt), + WITHER_TARGET3(WITHER, 19, MetaType1_8.Int, 13, MetaType1_9.VarInt), + WITHER_INVULN_TIME(WITHER, 20, MetaType1_8.Int, 14, MetaType1_9.VarInt), + WITHER_PROPERTIES(WITHER, 10, MetaType1_8.Byte, MetaType1_9.Byte), + WITHER_UNKNOWN(WITHER, 11, MetaType1_8.Byte, MetaType1_9.Discontinued), + // wither skull + WITHERSKULL_INVULN(WITHER_SKULL, 10, MetaType1_8.Byte, 5, MetaType1_9.Boolean), + // guardian + GUARDIAN_INFO(GUARDIAN, 16, MetaType1_8.Int, 11, MetaType1_9.Byte), + GUARDIAN_TARGET(GUARDIAN, 17, MetaType1_8.Int, 12, MetaType1_9.VarInt), + // boat + BOAT_SINCEHIT(BOAT, 17, MetaType1_8.Int, 5, MetaType1_9.VarInt), + BOAT_FORWARDDIR(BOAT, 18, MetaType1_8.Int, 6, MetaType1_9.VarInt), + BOAT_DMGTAKEN(BOAT, 19, MetaType1_8.Float, 7, MetaType1_9.Float), + // BOAT_TYPE in 1.9 + // minecart + MINECART_SHAKINGPOWER(MINECART_ABSTRACT, 17, MetaType1_8.Int, 5, MetaType1_9.VarInt), + MINECART_SHAKINGDIRECTION(MINECART_ABSTRACT, 18, MetaType1_8.Int, 6, MetaType1_9.VarInt), + MINECART_DAMAGETAKEN(MINECART_ABSTRACT, 19, MetaType1_8.Float, 7, MetaType1_9.Float), // also shaking modifier :P + MINECART_BLOCK(MINECART_ABSTRACT, 20, MetaType1_8.Int, 8, MetaType1_9.VarInt), + MINECART_BLOCK_Y(MINECART_ABSTRACT, 21, MetaType1_8.Int, 9, MetaType1_9.VarInt), + MINECART_SHOWBLOCK(MINECART_ABSTRACT, 22, MetaType1_8.Byte, 10, MetaType1_9.Boolean), + // Command minecart (they are still broken) + MINECART_COMMANDBLOCK_COMMAND(MINECART_ABSTRACT, 23, MetaType1_8.String, 11, MetaType1_9.String), + MINECART_COMMANDBLOCK_OUTPUT(MINECART_ABSTRACT, 24, MetaType1_8.String, 12, MetaType1_9.Chat), + // furnace cart + FURNACECART_ISPOWERED(MINECART_ABSTRACT, 16, MetaType1_8.Byte, 11, MetaType1_9.Boolean), + // item drop + ITEM_ITEM(DROPPED_ITEM, 10, MetaType1_8.Slot, 5, MetaType1_9.Slot), + // arrow + ARROW_ISCRIT(ARROW, 16, MetaType1_8.Byte, 5, MetaType1_9.Byte), + // firework + FIREWORK_INFO(FIREWORK, 8, MetaType1_8.Slot, 5, MetaType1_9.Slot), + // item frame + ITEMFRAME_ITEM(ITEM_FRAME, 8, MetaType1_8.Slot, 5, MetaType1_9.Slot), + ITEMFRAME_ROTATION(ITEM_FRAME, 9, MetaType1_8.Byte, 6, MetaType1_9.VarInt), + // ender crystal + ENDERCRYSTAL_HEALTH(ENDER_CRYSTAL, 8, MetaType1_8.Int, MetaType1_9.Discontinued), + // Ender dragon boss bar issues + ENDERDRAGON_UNKNOWN(ENDER_DRAGON, 5, MetaType1_8.Byte, MetaType1_9.Discontinued), + ENDERDRAGON_NAME(ENDER_DRAGON, 10, MetaType1_8.String, MetaType1_9.Discontinued), + // Normal Ender dragon + ENDERDRAGON_FLAG(ENDER_DRAGON, 15, MetaType1_8.Byte, MetaType1_9.Discontinued), + ENDERDRAGON_PHASE(ENDER_DRAGON, 11, MetaType1_8.Byte, MetaType1_9.VarInt); + + private static final HashMap, MetaIndex> metadataRewrites = new HashMap<>(); + + static { + for (MetaIndex index : MetaIndex.values()) + metadataRewrites.put(new Pair<>(index.getClazz(), index.getIndex()), index); + } + + private Entity1_10Types.EntityType clazz; + private int newIndex; + private MetaType1_9 newType; + private MetaType1_8 oldType; + private int index; + + MetaIndex(Entity1_10Types.EntityType type, int index, MetaType1_8 oldType, MetaType1_9 newType) { + this.clazz = type; + this.index = index; + this.newIndex = index; + this.oldType = oldType; + this.newType = newType; + } + + MetaIndex(Entity1_10Types.EntityType type, int index, MetaType1_8 oldType, int newIndex, MetaType1_9 newType) { + this.clazz = type; + this.index = index; + this.oldType = oldType; + this.newIndex = newIndex; + this.newType = newType; + } + + private static Optional getIndex(Entity1_10Types.EntityType type, int index) { + Pair pair = new Pair<>(type, index); + if (metadataRewrites.containsKey(pair)) { + return Optional.of(metadataRewrites.get(pair)); + } + + return Optional.absent(); + } + + public static MetaIndex searchIndex(Entity1_10Types.EntityType type, int index) { + Entity1_10Types.EntityType currentType = type; + do { + Optional optMeta = getIndex(currentType, index); + + if (optMeta.isPresent()) { + return optMeta.get(); + } + + currentType = currentType.getParent(); + } while (currentType != null); + + return null; + } + +} + diff --git a/src/main/java/us/myles/ViaVersion/protocols/protocol1_9to1_8/metadata/MetadataRewriter.java b/common/src/main/java/us/myles/ViaVersion/protocols/protocol1_9to1_8/metadata/MetadataRewriter.java similarity index 72% rename from src/main/java/us/myles/ViaVersion/protocols/protocol1_9to1_8/metadata/MetadataRewriter.java rename to common/src/main/java/us/myles/ViaVersion/protocols/protocol1_9to1_8/metadata/MetadataRewriter.java index 5783a0cc7..1fecbb7d8 100644 --- a/src/main/java/us/myles/ViaVersion/protocols/protocol1_9to1_8/metadata/MetadataRewriter.java +++ b/common/src/main/java/us/myles/ViaVersion/protocols/protocol1_9to1_8/metadata/MetadataRewriter.java @@ -1,11 +1,14 @@ package us.myles.ViaVersion.protocols.protocol1_9to1_8.metadata; -import org.bukkit.entity.EntityType; -import org.bukkit.util.EulerAngle; -import org.bukkit.util.Vector; -import us.myles.ViaVersion.api.ViaVersion; +import us.myles.ViaVersion.api.Via; +import us.myles.ViaVersion.api.entities.Entity1_10Types; +import us.myles.ViaVersion.api.minecraft.EulerAngle; +import us.myles.ViaVersion.api.minecraft.Vector; import us.myles.ViaVersion.api.minecraft.item.Item; +import us.myles.ViaVersion.api.minecraft.metadata.MetaType; import us.myles.ViaVersion.api.minecraft.metadata.Metadata; +import us.myles.ViaVersion.api.minecraft.metadata.types.MetaType1_8; +import us.myles.ViaVersion.api.minecraft.metadata.types.MetaType1_9; import us.myles.ViaVersion.protocols.protocol1_9to1_8.ItemRewriter; import us.myles.ViaVersion.protocols.protocol1_9to1_8.Protocol1_9TO1_8; @@ -14,43 +17,41 @@ import java.util.List; import java.util.UUID; public class MetadataRewriter { - public static void transform(EntityType type, List list) { + public static void transform(Entity1_10Types.EntityType type, List list) { short id = -1; int data = -1; for (Metadata entry : new ArrayList<>(list)) { - MetaIndex metaIndex = MetaIndex.getIndex(type, entry.getId()); + MetaIndex metaIndex = MetaIndex.searchIndex(type, entry.getId()); try { if (metaIndex != null) { - if (metaIndex.getNewType() != NewType.Discontinued) { - if (metaIndex.getNewType() != NewType.BlockID || id != -1 && data == -1 || id == -1 && data != -1) { // block ID is only written if we have both parts + if (metaIndex.getNewType() != MetaType1_9.Discontinued) { + if (metaIndex.getNewType() != MetaType1_9.BlockID || id != -1 && data == -1 || id == -1 && data != -1) { // block ID is only written if we have both parts entry.setId(metaIndex.getNewIndex()); - entry.setTypeID(metaIndex.getNewType().getTypeID()); + entry.setMetaType(metaIndex.getNewType()); } Object value = entry.getValue(); switch (metaIndex.getNewType()) { case Byte: - entry.setType(us.myles.ViaVersion.api.type.Type.BYTE); // convert from int, byte - if (metaIndex.getOldType() == Type.Byte) { + if (metaIndex.getOldType() == MetaType1_8.Byte) { entry.setValue(value); } - if (metaIndex.getOldType() == Type.Int) { + if (metaIndex.getOldType() == MetaType1_8.Int) { entry.setValue(((Integer) value).byteValue()); } // After writing the last one - if (metaIndex == MetaIndex.ENTITY_STATUS && type == EntityType.PLAYER) { + if (metaIndex == MetaIndex.ENTITY_STATUS && type == Entity1_10Types.EntityType.PLAYER) { Byte val = 0; if ((((Byte) value) & 0x10) == 0x10) { // Player eating/aiming/drinking val = 1; } int newIndex = MetaIndex.PLAYER_HAND.getNewIndex(); - int typeID = MetaIndex.PLAYER_HAND.getNewType().getTypeID(); - Metadata metadata = new Metadata(newIndex, typeID, us.myles.ViaVersion.api.type.Type.BYTE, val); + MetaType metaType = MetaIndex.PLAYER_HAND.getNewType(); + Metadata metadata = new Metadata(newIndex, metaType, val); list.add(metadata); } break; case OptUUID: - entry.setType(us.myles.ViaVersion.api.type.Type.OPTIONAL_UUID); String owner = (String) value; UUID toWrite = null; if (owner.length() != 0) { @@ -62,12 +63,11 @@ public class MetadataRewriter { entry.setValue(toWrite); break; case BlockID: - entry.setType(us.myles.ViaVersion.api.type.Type.VAR_INT); // if we have both sources :)) - if (metaIndex.getOldType() == Type.Byte) { + if (metaIndex.getOldType() == MetaType1_8.Byte) { data = (Byte) value; } - if (metaIndex.getOldType() == Type.Short) { + if (metaIndex.getOldType() == MetaType1_8.Short) { id = (Short) value; } if (id != -1 && data != -1) { @@ -80,50 +80,42 @@ public class MetadataRewriter { } break; case VarInt: - entry.setType(us.myles.ViaVersion.api.type.Type.VAR_INT); // convert from int, short, byte - if (metaIndex.getOldType() == Type.Byte) { + if (metaIndex.getOldType() == MetaType1_8.Byte) { entry.setValue(((Byte) value).intValue()); } - if (metaIndex.getOldType() == Type.Short) { + if (metaIndex.getOldType() == MetaType1_8.Short) { entry.setValue(((Short) value).intValue()); } - if (metaIndex.getOldType() == Type.Int) { + if (metaIndex.getOldType() == MetaType1_8.Int) { entry.setValue(value); } break; case Float: - entry.setType(us.myles.ViaVersion.api.type.Type.FLOAT); entry.setValue(value); break; case String: - entry.setType(us.myles.ViaVersion.api.type.Type.STRING); entry.setValue(value); break; case Boolean: - entry.setType(us.myles.ViaVersion.api.type.Type.BOOLEAN); if (metaIndex == MetaIndex.AGEABLE_AGE) entry.setValue((Byte) value < 0); else entry.setValue((Byte) value != 0); break; case Slot: - entry.setType(us.myles.ViaVersion.api.type.Type.ITEM); entry.setValue(value); ItemRewriter.toClient((Item) entry.getValue()); break; case Position: - entry.setType(us.myles.ViaVersion.api.type.Type.VECTOR); Vector vector = (Vector) value; entry.setValue(vector); break; case Vector3F: - entry.setType(us.myles.ViaVersion.api.type.Type.ROTATION); EulerAngle angle = (EulerAngle) value; entry.setValue(angle); break; case Chat: - entry.setType(us.myles.ViaVersion.api.type.Type.STRING); value = Protocol1_9TO1_8.fixJson((String) value); entry.setValue(value); break; @@ -140,7 +132,7 @@ public class MetadataRewriter { } } catch (Exception e) { list.remove(entry); - if (!ViaVersion.getConfig().isSuppressMetadataErrors() || ViaVersion.getInstance().isDebug()) { + if (!Via.getConfig().isSuppressMetadataErrors() || Via.getManager().isDebug()) { System.out.println("INCLUDE THIS IN YOUR ERROR LOG!"); if (type != null) System.out.println("An error occurred with entity meta data for " + type + " OldID: " + entry.getId()); diff --git a/src/main/java/us/myles/ViaVersion/protocols/protocol1_9to1_8/packets/EntityPackets.java b/common/src/main/java/us/myles/ViaVersion/protocols/protocol1_9to1_8/packets/EntityPackets.java similarity index 94% rename from src/main/java/us/myles/ViaVersion/protocols/protocol1_9to1_8/packets/EntityPackets.java rename to common/src/main/java/us/myles/ViaVersion/protocols/protocol1_9to1_8/packets/EntityPackets.java index 45d77585a..e36317a60 100644 --- a/src/main/java/us/myles/ViaVersion/protocols/protocol1_9to1_8/packets/EntityPackets.java +++ b/common/src/main/java/us/myles/ViaVersion/protocols/protocol1_9to1_8/packets/EntityPackets.java @@ -1,8 +1,7 @@ package us.myles.ViaVersion.protocols.protocol1_9to1_8.packets; -import org.bukkit.Material; import us.myles.ViaVersion.api.PacketWrapper; -import us.myles.ViaVersion.api.ViaVersion; +import us.myles.ViaVersion.api.Via; import us.myles.ViaVersion.api.minecraft.item.Item; import us.myles.ViaVersion.api.minecraft.metadata.Metadata; import us.myles.ViaVersion.api.protocol.Protocol; @@ -21,7 +20,7 @@ import us.myles.ViaVersion.protocols.protocol1_9to1_8.storage.EntityTracker; import java.util.List; public class EntityPackets { - public static ValueTransformer toNewShort = new ValueTransformer(Type.SHORT) { + public static final ValueTransformer toNewShort = new ValueTransformer(Type.SHORT) { @Override public Short transform(PacketWrapper wrapper, Byte inputValue) { return (short) (inputValue * 128); @@ -85,11 +84,11 @@ public class EntityPackets { @Override public void handle(PacketWrapper wrapper) throws Exception { int entityID = wrapper.get(Type.VAR_INT, 0); - if (ViaVersion.getConfig().isHologramPatch()) { + if (Via.getConfig().isHologramPatch()) { EntityTracker tracker = wrapper.user().get(EntityTracker.class); if (tracker.getKnownHolograms().contains(entityID)) { Double newValue = wrapper.get(Type.DOUBLE, 1); - newValue += (ViaVersion.getConfig().getHologramYOffset()); + newValue += (Via.getConfig().getHologramYOffset()); wrapper.set(Type.DOUBLE, 1, newValue); } } @@ -159,11 +158,9 @@ public class EntityPackets { Item stack = wrapper.get(Type.ITEM, 0); if (stack != null) { - if (Material.getMaterial(stack.getId()) != null) { - if (Material.getMaterial(stack.getId()).name().endsWith("SWORD")) { - entityTracker.getValidBlocking().add(entityID); - return; - } + if (Protocol1_9TO1_8.isSword(stack.getId())) { + entityTracker.getValidBlocking().add(entityID); + return; } } entityTracker.getValidBlocking().remove(entityID); @@ -231,7 +228,7 @@ public class EntityPackets { @Override public void handle(PacketWrapper wrapper) throws Exception { boolean showParticles = wrapper.read(Type.BOOLEAN); //In 1.8 = true->Show particles : false->Hide particles - boolean newEffect = ViaVersion.getConfig().isNewEffectIndicator(); + boolean newEffect = Via.getConfig().isNewEffectIndicator(); //0: hide, 1: shown without indictator, 2: shown with indicator, 3: hide with beacon indicator but we don't use it. wrapper.write(Type.BYTE, (byte) (showParticles ? newEffect ? 2 : 1 : 0)); } diff --git a/src/main/java/us/myles/ViaVersion/protocols/protocol1_9to1_8/packets/InventoryPackets.java b/common/src/main/java/us/myles/ViaVersion/protocols/protocol1_9to1_8/packets/InventoryPackets.java similarity index 100% rename from src/main/java/us/myles/ViaVersion/protocols/protocol1_9to1_8/packets/InventoryPackets.java rename to common/src/main/java/us/myles/ViaVersion/protocols/protocol1_9to1_8/packets/InventoryPackets.java diff --git a/src/main/java/us/myles/ViaVersion/protocols/protocol1_9to1_8/packets/PlayerPackets.java b/common/src/main/java/us/myles/ViaVersion/protocols/protocol1_9to1_8/packets/PlayerPackets.java similarity index 97% rename from src/main/java/us/myles/ViaVersion/protocols/protocol1_9to1_8/packets/PlayerPackets.java rename to common/src/main/java/us/myles/ViaVersion/protocols/protocol1_9to1_8/packets/PlayerPackets.java index 6e14bae8f..aa8559ad0 100644 --- a/src/main/java/us/myles/ViaVersion/protocols/protocol1_9to1_8/packets/PlayerPackets.java +++ b/common/src/main/java/us/myles/ViaVersion/protocols/protocol1_9to1_8/packets/PlayerPackets.java @@ -2,11 +2,9 @@ package us.myles.ViaVersion.protocols.protocol1_9to1_8.packets; import com.google.gson.JsonObject; import com.google.gson.JsonParser; -import org.bukkit.Material; -import org.bukkit.entity.EntityType; -import us.myles.ViaVersion.ViaVersionPlugin; import us.myles.ViaVersion.api.PacketWrapper; -import us.myles.ViaVersion.api.ViaVersion; +import us.myles.ViaVersion.api.Via; +import us.myles.ViaVersion.api.entities.Entity1_10Types; import us.myles.ViaVersion.api.minecraft.item.Item; import us.myles.ViaVersion.api.protocol.Protocol; import us.myles.ViaVersion.api.remapper.PacketHandler; @@ -124,7 +122,7 @@ public class PlayerPackets { wrapper.passthrough(Type.STRING); // Name tag visibility - wrapper.write(Type.STRING, ViaVersion.getConfig().isPreventCollision() ? "never" : ""); + wrapper.write(Type.STRING, Via.getConfig().isPreventCollision() ? "never" : ""); wrapper.passthrough(Type.BYTE); // Colour } @@ -137,12 +135,12 @@ public class PlayerPackets { if (entityTracker.isAutoTeam() && player.equalsIgnoreCase(myName)) { if (mode == 4) { // since removing add to auto team - ((ViaVersionPlugin) ViaVersion.getInstance()).run(new Runnable() { + Via.getPlatform().runSync(new Runnable() { @Override public void run() { entityTracker.sendTeamPacket(true); } - }, false); + }); } else { // since adding remove from auto team entityTracker.sendTeamPacket(false); @@ -167,7 +165,7 @@ public class PlayerPackets { public void handle(PacketWrapper wrapper) throws Exception { int entityID = wrapper.get(Type.INT, 0); EntityTracker tracker = wrapper.user().get(EntityTracker.class); - tracker.getClientEntityTypes().put(entityID, EntityType.PLAYER); + tracker.getClientEntityTypes().put(entityID, Entity1_10Types.EntityType.PLAYER); tracker.setEntityID(entityID); } }); @@ -477,7 +475,7 @@ public class PlayerPackets { if (name.equalsIgnoreCase("MC|BSign")) { Item item = wrapper.passthrough(Type.ITEM); if (item != null) { - item.setId((short) Material.WRITTEN_BOOK.getId()); + item.setId((short) 387); // Written Book } } if (name.equalsIgnoreCase("MC|AutoCmd")) { diff --git a/src/main/java/us/myles/ViaVersion/protocols/protocol1_9to1_8/packets/SpawnPackets.java b/common/src/main/java/us/myles/ViaVersion/protocols/protocol1_9to1_8/packets/SpawnPackets.java similarity index 95% rename from src/main/java/us/myles/ViaVersion/protocols/protocol1_9to1_8/packets/SpawnPackets.java rename to common/src/main/java/us/myles/ViaVersion/protocols/protocol1_9to1_8/packets/SpawnPackets.java index 0ae3c7e70..e868c427a 100644 --- a/src/main/java/us/myles/ViaVersion/protocols/protocol1_9to1_8/packets/SpawnPackets.java +++ b/common/src/main/java/us/myles/ViaVersion/protocols/protocol1_9to1_8/packets/SpawnPackets.java @@ -1,10 +1,10 @@ package us.myles.ViaVersion.protocols.protocol1_9to1_8.packets; -import org.bukkit.Material; -import org.bukkit.entity.EntityType; import us.myles.ViaVersion.api.PacketWrapper; +import us.myles.ViaVersion.api.entities.Entity1_10Types; import us.myles.ViaVersion.api.minecraft.item.Item; import us.myles.ViaVersion.api.minecraft.metadata.Metadata; +import us.myles.ViaVersion.api.minecraft.metadata.types.MetaType1_9; import us.myles.ViaVersion.api.protocol.Protocol; import us.myles.ViaVersion.api.remapper.PacketHandler; import us.myles.ViaVersion.api.remapper.PacketRemapper; @@ -17,15 +17,13 @@ import us.myles.ViaVersion.packets.State; import us.myles.ViaVersion.protocols.protocol1_9to1_8.ItemRewriter; import us.myles.ViaVersion.protocols.protocol1_9to1_8.Protocol1_9TO1_8; import us.myles.ViaVersion.protocols.protocol1_9to1_8.metadata.MetadataRewriter; -import us.myles.ViaVersion.protocols.protocol1_9to1_8.metadata.NewType; import us.myles.ViaVersion.protocols.protocol1_9to1_8.storage.EntityTracker; -import us.myles.ViaVersion.util.EntityUtil; import java.util.ArrayList; import java.util.List; public class SpawnPackets { - public static ValueTransformer toNewDouble = new ValueTransformer(Type.DOUBLE) { + public static final ValueTransformer toNewDouble = new ValueTransformer(Type.DOUBLE) { @Override public Double transform(PacketWrapper wrapper, Integer inputValue) { return inputValue / 32D; @@ -56,7 +54,7 @@ public class SpawnPackets { int entityID = wrapper.get(Type.VAR_INT, 0); int typeID = wrapper.get(Type.BYTE, 0); EntityTracker tracker = wrapper.user().get(EntityTracker.class); - tracker.getClientEntityTypes().put(entityID, EntityUtil.getTypeFromID(typeID, true)); + tracker.getClientEntityTypes().put(entityID, Entity1_10Types.getTypeFromId(typeID, true)); tracker.sendMetadataBuffer(entityID); } }); @@ -97,17 +95,17 @@ public class SpawnPackets { final int data = wrapper.get(Type.INT, 0); // Data int typeID = wrapper.get(Type.BYTE, 0); - if (EntityUtil.getTypeFromID(typeID, true) == EntityType.SPLASH_POTION) { + if (Entity1_10Types.getTypeFromId(typeID, true) == Entity1_10Types.EntityType.SPLASH_POTION) { // Convert this to meta data, woo! PacketWrapper metaPacket = wrapper.create(0x39, new ValueCreator() { @Override public void write(PacketWrapper wrapper) throws Exception { wrapper.write(Type.VAR_INT, entityID); List meta = new ArrayList<>(); - Item item = new Item((short) Material.POTION.getId(), (byte) 1, (short) data, null); + Item item = new Item((short) 373, (byte) 1, (short) data, null); // Potion ItemRewriter.toClient(item); // Rewrite so that it gets the right nbt // TEMP FIX FOR POTIONS UNTIL WE FIGURE OUT HOW TO TRANSFORM SENT PACKETS - Metadata potion = new Metadata(5, NewType.Slot.getTypeID(), Type.ITEM, item); + Metadata potion = new Metadata(5, MetaType1_9.Slot, item); meta.add(potion); wrapper.write(Types1_9.METADATA_LIST, meta); } @@ -131,7 +129,7 @@ public class SpawnPackets { public void handle(PacketWrapper wrapper) throws Exception { int entityID = wrapper.get(Type.VAR_INT, 0); EntityTracker tracker = wrapper.user().get(EntityTracker.class); - tracker.getClientEntityTypes().put(entityID, EntityType.EXPERIENCE_ORB); + tracker.getClientEntityTypes().put(entityID, Entity1_10Types.EntityType.EXPERIENCE_ORB); tracker.sendMetadataBuffer(entityID); } }); @@ -157,7 +155,7 @@ public class SpawnPackets { // Currently only lightning uses this int entityID = wrapper.get(Type.VAR_INT, 0); EntityTracker tracker = wrapper.user().get(EntityTracker.class); - tracker.getClientEntityTypes().put(entityID, EntityType.LIGHTNING); + tracker.getClientEntityTypes().put(entityID, Entity1_10Types.EntityType.LIGHTNING); tracker.sendMetadataBuffer(entityID); } }); @@ -191,7 +189,7 @@ public class SpawnPackets { int entityID = wrapper.get(Type.VAR_INT, 0); int typeID = wrapper.get(Type.UNSIGNED_BYTE, 0); EntityTracker tracker = wrapper.user().get(EntityTracker.class); - tracker.getClientEntityTypes().put(entityID, EntityUtil.getTypeFromID(typeID, false)); + tracker.getClientEntityTypes().put(entityID, Entity1_10Types.getTypeFromId(typeID, false)); tracker.sendMetadataBuffer(entityID); } }); @@ -248,7 +246,7 @@ public class SpawnPackets { public void handle(PacketWrapper wrapper) throws Exception { int entityID = wrapper.get(Type.VAR_INT, 0); EntityTracker tracker = wrapper.user().get(EntityTracker.class); - tracker.getClientEntityTypes().put(entityID, EntityType.PAINTING); + tracker.getClientEntityTypes().put(entityID, Entity1_10Types.EntityType.PAINTING); tracker.sendMetadataBuffer(entityID); } }); @@ -282,7 +280,7 @@ public class SpawnPackets { public void handle(PacketWrapper wrapper) throws Exception { int entityID = wrapper.get(Type.VAR_INT, 0); EntityTracker tracker = wrapper.user().get(EntityTracker.class); - tracker.getClientEntityTypes().put(entityID, EntityType.PLAYER); + tracker.getClientEntityTypes().put(entityID, Entity1_10Types.EntityType.PLAYER); tracker.sendMetadataBuffer(entityID); } }); diff --git a/src/main/java/us/myles/ViaVersion/protocols/protocol1_9to1_8/packets/WorldPackets.java b/common/src/main/java/us/myles/ViaVersion/protocols/protocol1_9to1_8/packets/WorldPackets.java similarity index 86% rename from src/main/java/us/myles/ViaVersion/protocols/protocol1_9to1_8/packets/WorldPackets.java rename to common/src/main/java/us/myles/ViaVersion/protocols/protocol1_9to1_8/packets/WorldPackets.java index a9add7c8d..b4552defd 100644 --- a/src/main/java/us/myles/ViaVersion/protocols/protocol1_9to1_8/packets/WorldPackets.java +++ b/common/src/main/java/us/myles/ViaVersion/protocols/protocol1_9to1_8/packets/WorldPackets.java @@ -1,10 +1,11 @@ package us.myles.ViaVersion.protocols.protocol1_9to1_8.packets; -import org.bukkit.Material; +import io.netty.buffer.ByteBuf; +import io.netty.buffer.Unpooled; import org.spacehq.opennbt.tag.builtin.CompoundTag; import org.spacehq.opennbt.tag.builtin.StringTag; import us.myles.ViaVersion.api.PacketWrapper; -import us.myles.ViaVersion.api.ViaVersion; +import us.myles.ViaVersion.api.Via; import us.myles.ViaVersion.api.minecraft.Position; import us.myles.ViaVersion.api.minecraft.item.Item; import us.myles.ViaVersion.api.protocol.Protocol; @@ -16,6 +17,7 @@ import us.myles.ViaVersion.packets.State; import us.myles.ViaVersion.protocols.protocol1_9to1_8.ItemRewriter; import us.myles.ViaVersion.protocols.protocol1_9to1_8.Protocol1_9TO1_8; import us.myles.ViaVersion.protocols.protocol1_9to1_8.chunks.Chunk1_9to1_8; +import us.myles.ViaVersion.protocols.protocol1_9to1_8.providers.BulkChunkTranslatorProvider; import us.myles.ViaVersion.protocols.protocol1_9to1_8.sounds.Effect; import us.myles.ViaVersion.protocols.protocol1_9to1_8.sounds.SoundEffect; import us.myles.ViaVersion.protocols.protocol1_9to1_8.storage.ClientChunks; @@ -23,6 +25,9 @@ import us.myles.ViaVersion.protocols.protocol1_9to1_8.storage.EntityTracker; import us.myles.ViaVersion.protocols.protocol1_9to1_8.storage.PlaceBlockTracker; import us.myles.ViaVersion.protocols.protocol1_9to1_8.types.ChunkType; +import java.io.IOException; +import java.util.List; + public class WorldPackets { public static void register(Protocol protocol) { // Sign Update Packet @@ -126,6 +131,37 @@ public class WorldPackets { } }); + // Bulk Chunk Packet + protocol.registerOutgoing(State.PLAY, 0x26, -1, new PacketRemapper() { + @Override + public void registerMap() { + handler(new PacketHandler() { + @Override + public void handle(PacketWrapper wrapper) throws Exception { + wrapper.cancel(); // Cancel the packet from being sent + BulkChunkTranslatorProvider provider = Via.getManager().getProviders().get(BulkChunkTranslatorProvider.class); + + // Don't read the packet + if (!provider.isPacketLevel()) + return; + + List list = provider.transformMapChunkBulk(wrapper, wrapper.user().get(ClientChunks.class)); + for (Object obj : list) { + if (!(obj instanceof PacketWrapper)) + throw new IOException("transformMapChunkBulk returned the wrong object type"); + + PacketWrapper output = (PacketWrapper) obj; + ByteBuf buffer = Unpooled.buffer(); + output.setId(-1); // -1 for no writing of id + output.writeToBuffer(buffer); + PacketWrapper chunkPacket = new PacketWrapper(0x21, buffer, wrapper.user()); + chunkPacket.send(Protocol1_9TO1_8.class, false); + } + } + }); + } + }); + // Update Block Entity Packet protocol.registerOutgoing(State.PLAY, 0x35, 0x09, new PacketRemapper() { @Override @@ -168,7 +204,7 @@ public class WorldPackets { handler(new PacketHandler() { @Override public void handle(PacketWrapper wrapper) throws Exception { - if (ViaVersion.getConfig().isAutoTeam()) { + if (Via.getConfig().isAutoTeam()) { EntityTracker entityTracker = wrapper.user().get(EntityTracker.class); entityTracker.setAutoTeam(true); entityTracker.sendTeamPacket(true); @@ -259,19 +295,17 @@ public class WorldPackets { // Write item in hand Item item = Protocol1_9TO1_8.getHandItem(wrapper.user()); // Blocking patch - if (ViaVersion.getConfig().isShieldBlocking()) { + if (Via.getConfig().isShieldBlocking()) { if (item != null) { - if (Material.getMaterial(item.getId()) != null) { - if (Material.getMaterial(item.getId()).name().endsWith("SWORD")) { - if (hand == 0) { - EntityTracker tracker = wrapper.user().get(EntityTracker.class); - if (!tracker.isBlocking()) { - tracker.setBlocking(true); - Item shield = new Item((short) 442, (byte) 1, (short) 0, null); - tracker.setSecondHand(shield); - } - wrapper.cancel(); + if (Protocol1_9TO1_8.isSword(item.getId())) { + if (hand == 0) { + EntityTracker tracker = wrapper.user().get(EntityTracker.class); + if (!tracker.isBlocking()) { + tracker.setBlocking(true); + Item shield = new Item((short) 442, (byte) 1, (short) 0, null); + tracker.setSecondHand(shield); } + wrapper.cancel(); } } } diff --git a/common/src/main/java/us/myles/ViaVersion/protocols/protocol1_9to1_8/providers/BulkChunkTranslatorProvider.java b/common/src/main/java/us/myles/ViaVersion/protocols/protocol1_9to1_8/providers/BulkChunkTranslatorProvider.java new file mode 100644 index 000000000..3d06352fa --- /dev/null +++ b/common/src/main/java/us/myles/ViaVersion/protocols/protocol1_9to1_8/providers/BulkChunkTranslatorProvider.java @@ -0,0 +1,96 @@ +package us.myles.ViaVersion.protocols.protocol1_9to1_8.providers; + +import lombok.Data; +import us.myles.ViaVersion.api.PacketWrapper; +import us.myles.ViaVersion.api.platform.providers.Provider; +import us.myles.ViaVersion.api.type.Type; +import us.myles.ViaVersion.api.type.types.CustomByteType; +import us.myles.ViaVersion.protocols.protocol1_9to1_8.storage.ClientChunks; + +import java.util.ArrayList; +import java.util.List; + +public class BulkChunkTranslatorProvider implements Provider { + /** + * Transforms a Bulk Chunk packet into Chunk Packets + * + * @param packet The NMS Packet + * @param clientChunks The ClientChunks object for the current player + * @return A List of all the output packets + */ + public List transformMapChunkBulk(Object packet, ClientChunks clientChunks) throws Exception { + if (!(packet instanceof PacketWrapper)) + throw new IllegalArgumentException("The default packet has to be a PacketWrapper for transformMapChunkBulk, unexpected " + packet.getClass()); + + List packets = new ArrayList<>(); + PacketWrapper wrapper = (PacketWrapper) packet; + + boolean skyLight = wrapper.read(Type.BOOLEAN); + int count = wrapper.read(Type.VAR_INT); + + ChunkBulkSection[] metas = new ChunkBulkSection[count]; + for (int i = 0; i < count; i++) { + metas[i] = ChunkBulkSection.read(wrapper, skyLight); + } + + for (ChunkBulkSection meta : metas) { + CustomByteType customByteType = new CustomByteType(meta.getLength()); + meta.setData(wrapper.read(customByteType)); + + // Construct chunk packet + PacketWrapper chunkPacket = new PacketWrapper(0x21, null, wrapper.user()); + chunkPacket.write(Type.INT, meta.getX()); + chunkPacket.write(Type.INT, meta.getZ()); + chunkPacket.write(Type.BOOLEAN, true); // Always ground-up + chunkPacket.write(Type.UNSIGNED_SHORT, meta.getBitMask()); + chunkPacket.write(Type.VAR_INT, meta.getLength()); + chunkPacket.write(customByteType, meta.getData()); + + clientChunks.getBulkChunks().add(ClientChunks.toLong(meta.getX(), meta.getZ())); // Store for later + packets.add(chunkPacket); + } + + return packets; + } + + + /** + * Check if a packet of a class should be filtered + * + * @param packet NMS Packet + * @return True if it should be filtered into transformmapChunkBulk + */ + public boolean isFiltered(Class packet) { + return false; + } + + /** + * Check if the packet should be provided as PacketWrapper + * + * @return True if enabled + */ + public boolean isPacketLevel() { + return true; + } + + @Data + private static class ChunkBulkSection { + private int x; + private int z; + private int bitMask; + private int length; + private byte[] data; + + public static ChunkBulkSection read(PacketWrapper wrapper, boolean skylight) throws Exception { + ChunkBulkSection bulkSection = new ChunkBulkSection(); + bulkSection.setX(wrapper.read(Type.INT)); + bulkSection.setZ(wrapper.read(Type.INT)); + bulkSection.setBitMask(wrapper.read(Type.UNSIGNED_SHORT)); + + int bitCount = Integer.bitCount(bulkSection.getBitMask()); + bulkSection.setLength((bitCount * ((4096 * 2) + 2048)) + (skylight ? bitCount * 2048 : 0) + 256); // Thanks MCProtocolLib + + return bulkSection; + } + } +} diff --git a/common/src/main/java/us/myles/ViaVersion/protocols/protocol1_9to1_8/providers/HandItemProvider.java b/common/src/main/java/us/myles/ViaVersion/protocols/protocol1_9to1_8/providers/HandItemProvider.java new file mode 100644 index 000000000..a839dc353 --- /dev/null +++ b/common/src/main/java/us/myles/ViaVersion/protocols/protocol1_9to1_8/providers/HandItemProvider.java @@ -0,0 +1,11 @@ +package us.myles.ViaVersion.protocols.protocol1_9to1_8.providers; + +import us.myles.ViaVersion.api.data.UserConnection; +import us.myles.ViaVersion.api.minecraft.item.Item; +import us.myles.ViaVersion.api.platform.providers.Provider; + +public class HandItemProvider implements Provider { + public Item getHandItem(final UserConnection info) { + return new Item((short) 0, (byte) 0, (short) 0, null); + } +} diff --git a/common/src/main/java/us/myles/ViaVersion/protocols/protocol1_9to1_8/providers/MovementTransmitterProvider.java b/common/src/main/java/us/myles/ViaVersion/protocols/protocol1_9to1_8/providers/MovementTransmitterProvider.java new file mode 100644 index 000000000..311859e90 --- /dev/null +++ b/common/src/main/java/us/myles/ViaVersion/protocols/protocol1_9to1_8/providers/MovementTransmitterProvider.java @@ -0,0 +1,26 @@ +package us.myles.ViaVersion.protocols.protocol1_9to1_8.providers; + +import io.netty.channel.ChannelHandlerContext; +import us.myles.ViaVersion.api.data.UserConnection; +import us.myles.ViaVersion.api.platform.providers.Provider; +import us.myles.ViaVersion.protocols.protocol1_9to1_8.storage.MovementTracker; +import us.myles.ViaVersion.util.PipelineUtil; + +public abstract class MovementTransmitterProvider implements Provider { + public abstract Object getFlyingPacket(); + + public abstract Object getGroundPacket(); + + public void sendPlayer(UserConnection userConnection) { + // Old method using packets. + ChannelHandlerContext context = PipelineUtil.getContextBefore("decoder", userConnection.getChannel().pipeline()); + if (context != null) { + if (userConnection.get(MovementTracker.class).isGround()) { + context.fireChannelRead(getGroundPacket()); + } else { + context.fireChannelRead(getFlyingPacket()); + } + userConnection.get(MovementTracker.class).incrementIdlePacket(); + } + } +} diff --git a/src/main/java/us/myles/ViaVersion/protocols/protocol1_9to1_8/sounds/Effect.java b/common/src/main/java/us/myles/ViaVersion/protocols/protocol1_9to1_8/sounds/Effect.java similarity index 95% rename from src/main/java/us/myles/ViaVersion/protocols/protocol1_9to1_8/sounds/Effect.java rename to common/src/main/java/us/myles/ViaVersion/protocols/protocol1_9to1_8/sounds/Effect.java index b6a348e57..964ef9611 100644 --- a/src/main/java/us/myles/ViaVersion/protocols/protocol1_9to1_8/sounds/Effect.java +++ b/common/src/main/java/us/myles/ViaVersion/protocols/protocol1_9to1_8/sounds/Effect.java @@ -4,7 +4,7 @@ import java.util.HashMap; public class Effect { - private static HashMap effects; + private final static HashMap effects; static { effects = new HashMap<>(); diff --git a/src/main/java/us/myles/ViaVersion/protocols/protocol1_9to1_8/sounds/SoundCategory.java b/common/src/main/java/us/myles/ViaVersion/protocols/protocol1_9to1_8/sounds/SoundCategory.java similarity index 100% rename from src/main/java/us/myles/ViaVersion/protocols/protocol1_9to1_8/sounds/SoundCategory.java rename to common/src/main/java/us/myles/ViaVersion/protocols/protocol1_9to1_8/sounds/SoundCategory.java diff --git a/src/main/java/us/myles/ViaVersion/protocols/protocol1_9to1_8/sounds/SoundEffect.java b/common/src/main/java/us/myles/ViaVersion/protocols/protocol1_9to1_8/sounds/SoundEffect.java similarity index 100% rename from src/main/java/us/myles/ViaVersion/protocols/protocol1_9to1_8/sounds/SoundEffect.java rename to common/src/main/java/us/myles/ViaVersion/protocols/protocol1_9to1_8/sounds/SoundEffect.java 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 new file mode 100644 index 000000000..e4149ef73 --- /dev/null +++ b/common/src/main/java/us/myles/ViaVersion/protocols/protocol1_9to1_8/storage/ClientChunks.java @@ -0,0 +1,29 @@ +package us.myles.ViaVersion.protocols.protocol1_9to1_8.storage; + +import com.google.common.collect.Sets; +import lombok.Getter; +import us.myles.ViaVersion.api.Via; +import us.myles.ViaVersion.api.data.StoredObject; +import us.myles.ViaVersion.api.data.UserConnection; +import us.myles.ViaVersion.protocols.protocol1_9to1_8.providers.BulkChunkTranslatorProvider; + +import java.util.List; +import java.util.Set; + +@Getter +public class ClientChunks extends StoredObject { + private final Set loadedChunks = Sets.newConcurrentHashSet(); + private final Set bulkChunks = Sets.newConcurrentHashSet(); + + public ClientChunks(UserConnection user) { + super(user); + } + + public static long toLong(int msw, int lsw) { + return ((long) msw << 32) + lsw - -2147483648L; + } + + public List transformMapChunkBulk(Object packet) throws Exception { + return Via.getManager().getProviders().get(BulkChunkTranslatorProvider.class).transformMapChunkBulk(packet, this); + } +} diff --git a/src/main/java/us/myles/ViaVersion/protocols/protocol1_9to1_8/storage/EntityTracker.java b/common/src/main/java/us/myles/ViaVersion/protocols/protocol1_9to1_8/storage/EntityTracker.java similarity index 84% rename from src/main/java/us/myles/ViaVersion/protocols/protocol1_9to1_8/storage/EntityTracker.java rename to common/src/main/java/us/myles/ViaVersion/protocols/protocol1_9to1_8/storage/EntityTracker.java index 298da7263..b1521fc18 100644 --- a/src/main/java/us/myles/ViaVersion/protocols/protocol1_9to1_8/storage/EntityTracker.java +++ b/common/src/main/java/us/myles/ViaVersion/protocols/protocol1_9to1_8/storage/EntityTracker.java @@ -6,25 +6,24 @@ import com.google.common.collect.Sets; import io.netty.buffer.ByteBuf; import lombok.Getter; import lombok.Setter; -import org.bukkit.Material; -import org.bukkit.entity.EntityType; import us.myles.ViaVersion.api.PacketWrapper; -import us.myles.ViaVersion.api.ViaVersion; +import us.myles.ViaVersion.api.Via; 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.data.StoredObject; import us.myles.ViaVersion.api.data.UserConnection; +import us.myles.ViaVersion.api.entities.Entity1_10Types; import us.myles.ViaVersion.api.minecraft.Position; import us.myles.ViaVersion.api.minecraft.item.Item; import us.myles.ViaVersion.api.minecraft.metadata.Metadata; +import us.myles.ViaVersion.api.minecraft.metadata.types.MetaType1_9; import us.myles.ViaVersion.api.type.Type; import us.myles.ViaVersion.api.type.types.version.Types1_9; import us.myles.ViaVersion.protocols.base.ProtocolInfo; import us.myles.ViaVersion.protocols.protocol1_9to1_8.Protocol1_9TO1_8; import us.myles.ViaVersion.protocols.protocol1_9to1_8.chat.GameMode; import us.myles.ViaVersion.protocols.protocol1_9to1_8.metadata.MetadataRewriter; -import us.myles.ViaVersion.protocols.protocol1_9to1_8.metadata.NewType; import java.util.*; import java.util.concurrent.ConcurrentHashMap; @@ -33,13 +32,13 @@ import java.util.concurrent.TimeUnit; @Getter public class EntityTracker extends StoredObject { private final Map uuidMap = new ConcurrentHashMap<>(); - private final Map clientEntityTypes = new ConcurrentHashMap<>(); + private final Map clientEntityTypes = new ConcurrentHashMap<>(); private final Map> metadataBuffer = new ConcurrentHashMap<>(); private final Map vehicleMap = new ConcurrentHashMap<>(); private final Map bossBarMap = new ConcurrentHashMap<>(); private final Set validBlocking = Sets.newConcurrentHashSet(); private final Set knownHolograms = Sets.newConcurrentHashSet(); - private final Cache blockInteractions = CacheBuilder.newBuilder().maximumSize(10).expireAfterAccess(250, TimeUnit.MILLISECONDS).build(); + private final Cache blockInteractions = CacheBuilder.newBuilder().maximumSize(10).expireAfterAccess(250, TimeUnit.MILLISECONDS).build(); @Setter private boolean blocking = false; @Setter @@ -99,9 +98,7 @@ public class EntityTracker extends StoredObject { public boolean interactedBlockRecently(int x, int y, int z) { if (blockInteractions.size() == 0) return false; - Iterator it = blockInteractions.asMap().keySet().iterator(); - while (it.hasNext()) { - Position p = it.next(); + for (Position p : blockInteractions.asMap().keySet()) { if (p.getX() == x) if (p.getY() == y) if (p.getZ() == z) @@ -111,7 +108,7 @@ public class EntityTracker extends StoredObject { } public void addBlockInteraction(Position p) { - blockInteractions.put(p, Material.AIR); + blockInteractions.put(p, 0); } public void handleMetadata(int entityID, List metadataList) { @@ -119,41 +116,41 @@ public class EntityTracker extends StoredObject { return; } - EntityType type = clientEntityTypes.get(entityID); + Entity1_10Types.EntityType type = clientEntityTypes.get(entityID); for (Metadata metadata : new ArrayList<>(metadataList)) { // Fix: wither (crash fix) - if (type == EntityType.WITHER) { + if (type == Entity1_10Types.EntityType.WITHER) { if (metadata.getId() == 10) { metadataList.remove(metadata); //metadataList.add(new Metadata(10, NewType.Byte.getTypeID(), Type.BYTE, 0)); } } // Fix: enderdragon (crash fix) - if (type == EntityType.ENDER_DRAGON) { + if (type == Entity1_10Types.EntityType.ENDER_DRAGON) { if (metadata.getId() == 11) { metadataList.remove(metadata); // metadataList.add(new Metadata(11, NewType.Byte.getTypeID(), Type.VAR_INT, 0)); } } - if (type == EntityType.SKELETON) { + if (type == Entity1_10Types.EntityType.SKELETON) { if ((getMetaByIndex(metadataList, 12)) == null) { - metadataList.add(new Metadata(12, NewType.Boolean.getTypeID(), Type.BOOLEAN, true)); + metadataList.add(new Metadata(12, MetaType1_9.Boolean, true)); } } //ECHOPET Patch - if (type == EntityType.HORSE) { + if (type == Entity1_10Types.EntityType.HORSE) { // Wrong metadata value from EchoPet, patch since it's discontinued. (https://github.com/DSH105/EchoPet/blob/06947a8b08ce40be9a518c2982af494b3b99d140/modules/API/src/main/java/com/dsh105/echopet/compat/api/entity/HorseArmour.java#L22) if (metadata.getId() == 16 && (int) metadata.getValue() == Integer.MIN_VALUE) metadata.setValue(0); } - if (type == EntityType.PLAYER) { + if (type == Entity1_10Types.EntityType.PLAYER) { if (metadata.getId() == 0) { // Byte byte data = (byte) metadata.getValue(); - if (entityID != getEntityID() && ViaVersion.getConfig().isShieldBlocking()) { + if (entityID != getEntityID() && Via.getConfig().isShieldBlocking()) { if ((data & 0x10) == 0x10) { if (validBlocking.contains(entityID)) { Item shield = new Item((short) 442, (byte) 1, (short) 0, null); @@ -165,7 +162,7 @@ public class EntityTracker extends StoredObject { } } } - if (type == EntityType.ARMOR_STAND && ViaVersion.getConfig().isHologramPatch()) { + if (type == Entity1_10Types.EntityType.ARMOR_STAND && Via.getConfig().isHologramPatch()) { if (metadata.getId() == 0 && getMetaByIndex(metadataList, 10) != null) { Metadata meta = getMetaByIndex(metadataList, 10); //Only happens if the armorstand is small byte data = (byte) metadata.getValue(); @@ -180,7 +177,7 @@ public class EntityTracker extends StoredObject { Type.VAR_INT.write(buf, 0x25); // Relative Move Packet Type.VAR_INT.write(buf, entityID); buf.writeShort(0); - buf.writeShort((short) (128D * (ViaVersion.getConfig().getHologramYOffset() * 32D))); + buf.writeShort((short) (128D * (Via.getConfig().getHologramYOffset() * 32D))); buf.writeShort(0); buf.writeBoolean(true); getUser().sendRawPacket(buf, false); @@ -192,28 +189,28 @@ public class EntityTracker extends StoredObject { } UUID uuid = getUser().get(ProtocolInfo.class).getUuid(); // Boss bar - if (ViaVersion.getConfig().isBossbarPatch()) { - if (type == EntityType.ENDER_DRAGON || type == EntityType.WITHER) { + if (Via.getConfig().isBossbarPatch()) { + if (type == Entity1_10Types.EntityType.ENDER_DRAGON || type == Entity1_10Types.EntityType.WITHER) { if (metadata.getId() == 2) { BossBar bar = bossBarMap.get(entityID); String title = (String) metadata.getValue(); - title = title.isEmpty() ? (type == EntityType.ENDER_DRAGON ? "Ender Dragon" : "Wither") : title; + title = title.isEmpty() ? (type == Entity1_10Types.EntityType.ENDER_DRAGON ? "Ender Dragon" : "Wither") : title; if (bar == null) { - bar = ViaVersion.getInstance().createBossBar(title, BossColor.PINK, BossStyle.SOLID); + bar = Via.getAPI().createBossBar(title, BossColor.PINK, BossStyle.SOLID); bossBarMap.put(entityID, bar); bar.addPlayer(uuid); bar.show(); } else { bar.setTitle(title); } - } else if (metadata.getId() == 6 && !ViaVersion.getConfig().isBossbarAntiflicker()) { // If anti flicker is enabled, don't update health + } else if (metadata.getId() == 6 && !Via.getConfig().isBossbarAntiflicker()) { // If anti flicker is enabled, don't update health BossBar bar = bossBarMap.get(entityID); // Make health range between 0 and 1 - float maxHealth = type == EntityType.ENDER_DRAGON ? 200.0f : 300.0f; + float maxHealth = type == Entity1_10Types.EntityType.ENDER_DRAGON ? 200.0f : 300.0f; float health = Math.max(0.0f, Math.min(((float) metadata.getValue()) / maxHealth, 1.0f)); if (bar == null) { - String title = type == EntityType.ENDER_DRAGON ? "Ender Dragon" : "Wither"; - bar = ViaVersion.getInstance().createBossBar(title, health, BossColor.PINK, BossStyle.SOLID); + String title = type == Entity1_10Types.EntityType.ENDER_DRAGON ? "Ender Dragon" : "Wither"; + bar = Via.getAPI().createBossBar(title, health, BossColor.PINK, BossStyle.SOLID); bossBarMap.put(entityID, bar); bar.addPlayer(uuid); bar.show(); diff --git a/src/main/java/us/myles/ViaVersion/protocols/protocol1_9to1_8/storage/InventoryTracker.java b/common/src/main/java/us/myles/ViaVersion/protocols/protocol1_9to1_8/storage/InventoryTracker.java similarity index 100% rename from src/main/java/us/myles/ViaVersion/protocols/protocol1_9to1_8/storage/InventoryTracker.java rename to common/src/main/java/us/myles/ViaVersion/protocols/protocol1_9to1_8/storage/InventoryTracker.java diff --git a/src/main/java/us/myles/ViaVersion/protocols/protocol1_9to1_8/storage/MovementTracker.java b/common/src/main/java/us/myles/ViaVersion/protocols/protocol1_9to1_8/storage/MovementTracker.java similarity index 100% rename from src/main/java/us/myles/ViaVersion/protocols/protocol1_9to1_8/storage/MovementTracker.java rename to common/src/main/java/us/myles/ViaVersion/protocols/protocol1_9to1_8/storage/MovementTracker.java diff --git a/src/main/java/us/myles/ViaVersion/protocols/protocol1_9to1_8/storage/PlaceBlockTracker.java b/common/src/main/java/us/myles/ViaVersion/protocols/protocol1_9to1_8/storage/PlaceBlockTracker.java similarity index 76% rename from src/main/java/us/myles/ViaVersion/protocols/protocol1_9to1_8/storage/PlaceBlockTracker.java rename to common/src/main/java/us/myles/ViaVersion/protocols/protocol1_9to1_8/storage/PlaceBlockTracker.java index a8ea3fe73..d3e5d718f 100644 --- a/src/main/java/us/myles/ViaVersion/protocols/protocol1_9to1_8/storage/PlaceBlockTracker.java +++ b/common/src/main/java/us/myles/ViaVersion/protocols/protocol1_9to1_8/storage/PlaceBlockTracker.java @@ -16,10 +16,19 @@ public class PlaceBlockTracker extends StoredObject { super(user); } + /** + * Check if a certain amount of time has passed + * + * @param ms The amount of time in MS + * @return True if it has passed + */ public boolean isExpired(int ms) { return System.currentTimeMillis() > (lastPlaceTimestamp + ms); } + /** + * Set the last place time to the current time + */ public void updateTime() { lastPlaceTimestamp = System.currentTimeMillis(); } diff --git a/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 similarity index 95% rename from src/main/java/us/myles/ViaVersion/protocols/protocol1_9to1_8/types/ChunkType.java rename to common/src/main/java/us/myles/ViaVersion/protocols/protocol1_9to1_8/types/ChunkType.java index 63c57a9ca..8ac1c6303 100644 --- a/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,8 +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.ViaVersion; +import us.myles.ViaVersion.api.Via; import us.myles.ViaVersion.api.minecraft.chunks.Chunk; import us.myles.ViaVersion.api.type.PartialType; import us.myles.ViaVersion.api.type.Type; @@ -49,8 +48,8 @@ public class ChunkType extends PartialType { @Override public Chunk read(ByteBuf input, ClientChunks param) throws Exception { - boolean replacePistons = param.getUser().get(ProtocolInfo.class).getPipeline().contains(Protocol1_10To1_9_3_4.class) && ViaVersion.getConfig().isReplacePistons(); - int replacementId = ViaVersion.getConfig().getPistonReplacementId(); + boolean replacePistons = param.getUser().get(ProtocolInfo.class).getPipeline().contains(Protocol1_10To1_9_3_4.class) && Via.getConfig().isReplacePistons(); + int replacementId = Via.getConfig().getPistonReplacementId(); int chunkX = input.readInt(); int chunkZ = input.readInt(); @@ -134,7 +133,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/src/main/java/us/myles/ViaVersion/protocols/protocol1_9to1_9_1/Protocol1_9TO1_9_1.java b/common/src/main/java/us/myles/ViaVersion/protocols/protocol1_9to1_9_1/Protocol1_9TO1_9_1.java similarity index 100% rename from src/main/java/us/myles/ViaVersion/protocols/protocol1_9to1_9_1/Protocol1_9TO1_9_1.java rename to common/src/main/java/us/myles/ViaVersion/protocols/protocol1_9to1_9_1/Protocol1_9TO1_9_1.java diff --git a/src/main/java/us/myles/ViaVersion/protocols/protocolsnapshotto1_10/ItemRewriter.java b/common/src/main/java/us/myles/ViaVersion/protocols/protocolsnapshotto1_10/ItemRewriter.java similarity index 93% rename from src/main/java/us/myles/ViaVersion/protocols/protocolsnapshotto1_10/ItemRewriter.java rename to common/src/main/java/us/myles/ViaVersion/protocols/protocolsnapshotto1_10/ItemRewriter.java index b684a7f37..ada23508d 100644 --- a/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/src/main/java/us/myles/ViaVersion/protocols/protocolsnapshotto1_10/MetadataRewriter.java b/common/src/main/java/us/myles/ViaVersion/protocols/protocolsnapshotto1_10/MetadataRewriter.java similarity index 50% rename from src/main/java/us/myles/ViaVersion/protocols/protocolsnapshotto1_10/MetadataRewriter.java rename to common/src/main/java/us/myles/ViaVersion/protocols/protocolsnapshotto1_10/MetadataRewriter.java index 16d3c6114..e4aa98f6f 100644 --- a/src/main/java/us/myles/ViaVersion/protocols/protocolsnapshotto1_10/MetadataRewriter.java +++ b/common/src/main/java/us/myles/ViaVersion/protocols/protocolsnapshotto1_10/MetadataRewriter.java @@ -1,55 +1,67 @@ package us.myles.ViaVersion.protocols.protocolsnapshotto1_10; import com.google.common.base.Optional; -import us.myles.ViaVersion.api.ViaVersion; +import us.myles.ViaVersion.api.PacketWrapper; +import us.myles.ViaVersion.api.Via; +import us.myles.ViaVersion.api.data.UserConnection; +import us.myles.ViaVersion.api.entities.Entity1_11Types.EntityType; import us.myles.ViaVersion.api.minecraft.metadata.Metadata; +import us.myles.ViaVersion.api.minecraft.metadata.types.MetaType1_9; import us.myles.ViaVersion.api.type.Type; -import us.myles.ViaVersion.protocols.protocol1_9to1_8.metadata.NewType; +import us.myles.ViaVersion.protocols.protocolsnapshotto1_10.storage.EntityTracker; import java.util.ArrayList; import java.util.List; public class MetadataRewriter { - public static int rewriteEntityType(int currentType, List metadata) { + public static EntityType rewriteEntityType(int numType, List metadata) { + Optional optType = EntityType.findById(numType); + if (!optType.isPresent()) { + Via.getManager().getPlatform().getLogger().severe("Error: could not find Entity type " + numType + " with metadata: " + metadata); + return null; + } + + EntityType type = optType.get(); + try { - if (currentType == 68) { + if (type.is(EntityType.GUARDIAN)) { // ElderGuardian - 4 Optional options = getById(metadata, 12); if (options.isPresent()) { if ((((byte) options.get().getValue()) & 0x04) == 0x04) { - return 4; + return EntityType.ELDER_GUARDIAN; } } } - if (currentType == 51) { + if (type.is(EntityType.SKELETON)) { // WitherSkeleton - 5 // Stray - 6 Optional options = getById(metadata, 12); if (options.isPresent()) { if (((int) options.get().getValue()) == 1) { - return 5; + return EntityType.WITHER_SKELETON; } if (((int) options.get().getValue()) == 2) { - return 6; + return EntityType.STRAY; } } } - if (currentType == 54) { + if (type.is(EntityType.ZOMBIE)) { // ZombieVillager - 27 // Husk - 23 Optional options = getById(metadata, 13); if (options.isPresent()) { int value = (int) options.get().getValue(); if (value > 0 && value < 6) { - metadata.add(new Metadata(16, NewType.VarInt.getTypeID(), Type.VAR_INT, value - 1)); // Add profession type to new metadata - return 27; + metadata.add(new Metadata(16, MetaType1_9.VarInt, value - 1)); // Add profession type to new metadata + return EntityType.ZOMBIE_VILLAGER; } if (value == 6) { - return 23; + return EntityType.HUSK; } } } - if (currentType == 100) { + if (type.is(EntityType.HORSE)) { // SkeletonHorse - 28 // ZombieHorse - 29 // Donkey - 31 @@ -57,47 +69,45 @@ public class MetadataRewriter { Optional options = getById(metadata, 14); if (options.isPresent()) { if (((int) options.get().getValue()) == 0) { - return currentType; + return EntityType.HORSE; } if (((int) options.get().getValue()) == 1) { - return 31; + return EntityType.DONKEY; } if (((int) options.get().getValue()) == 2) { - return 32; + return EntityType.MULE; } if (((int) options.get().getValue()) == 3) { - return 29; + return EntityType.ZOMBIE_HORSE; } if (((int) options.get().getValue()) == 4) { - return 28; + return EntityType.SKELETON_HORSE; } } } - return currentType; } catch (Exception e) { - ; - if (!ViaVersion.getConfig().isSuppressMetadataErrors() || ViaVersion.getInstance().isDebug()) { + if (!Via.getConfig().isSuppressMetadataErrors() || Via.getManager().isDebug()) { System.out.println("An error occurred with entity type rewriter"); System.out.println("Metadata: " + metadata); e.printStackTrace(); } } - return currentType; + + return type; } - public static void handleMetadata(int type, List metadatas) { + public static void handleMetadata(int entityId, EntityType type, List metadatas, UserConnection connection) { for (Metadata metadata : new ArrayList<>(metadatas)) { try { - if (type == 4 || type == 68) { // Guardians + if (type.is(EntityType.ELDER_GUARDIAN) || type.is(EntityType.GUARDIAN)) { // Guardians int oldid = metadata.getId(); if (oldid == 12) { - metadata.setType(Type.BOOLEAN); - metadata.setTypeID(NewType.Boolean.getTypeID()); + metadata.setMetaType(MetaType1_9.Boolean); boolean val = (((byte) metadata.getValue()) & 0x02) == 0x02; metadata.setValue(val); } } - if (type == 51 || type == 5 || type == 6) { // Skeletons + if (type.isOrHasParent(EntityType.ABSTRACT_SKELETON)) { // Skeletons int oldid = metadata.getId(); if (oldid == 12) { metadatas.remove(metadata); @@ -106,8 +116,8 @@ public class MetadataRewriter { metadata.setId(12); } } - if (type == 54 || type == 27) { // Zombie | Zombie Villager - if (type == 54 && metadata.getId() == 14) { + if (type.isOrHasParent(EntityType.ZOMBIE)) { // Zombie | Zombie Villager | Husk + if (type.is(EntityType.ZOMBIE, EntityType.HUSK) && metadata.getId() == 14) { metadatas.remove(metadata); } else { if (metadata.getId() == 15) { @@ -119,7 +129,7 @@ public class MetadataRewriter { } } } - if (type == 100 || type == 31 || type == 32 || type == 29 || type == 28) { // Horses + if (type.isOrHasParent(EntityType.ABSTRACT_HORSE)) { // Horses // Remap metadata id int oldid = metadata.getId(); if (oldid == 14) { // Type @@ -133,7 +143,7 @@ public class MetadataRewriter { } // Process per type - if (type == 100) { + if (type.is(EntityType.HORSE)) { // Normal Horse } else { // Remove 15, 16 @@ -141,26 +151,57 @@ public class MetadataRewriter { metadatas.remove(metadata); } } - if (type == 31 || type == 32) { + if (type.is(EntityType.DONKEY, EntityType.MULE)) { // Chested Horse if (metadata.getId() == 13) { if ((((byte) metadata.getValue()) & 0x08) == 0x08) { - metadatas.add(new Metadata(15, NewType.Boolean.getTypeID(), Type.BOOLEAN, true)); + metadatas.add(new Metadata(15, MetaType1_9.Boolean, true)); } else { - metadatas.add(new Metadata(15, NewType.Boolean.getTypeID(), Type.BOOLEAN, false)); + metadatas.add(new Metadata(15, MetaType1_9.Boolean, false)); + } + } + } + } + if (type.is(EntityType.ARMOR_STAND) && Via.getConfig().isHologramPatch()) { + Optional flags = getById(metadatas, 11); + Optional customName = getById(metadatas, 2); + Optional customNameVisible = getById(metadatas, 3); + if (metadata.getId() == 0 && flags.isPresent() && customName.isPresent() && customNameVisible.isPresent()) { + Metadata meta = flags.get(); + byte data = (byte) metadata.getValue(); + // Check invisible | Check small | Check if custom name is empty | Check if custom name visible is true + if ((data & 0x20) == 0x20 && ((byte) meta.getValue() & 0x01) == 0x01 + && ((String) customName.get().getValue()).length() != 0 && (boolean) customNameVisible.get().getValue()) { + EntityTracker tracker = connection.get(EntityTracker.class); + if (!tracker.isHologram(entityId)) { + tracker.addHologram(entityId); + try { + // Send movement + PacketWrapper wrapper = new PacketWrapper(0x25, null, connection); + wrapper.write(Type.VAR_INT, entityId); + wrapper.write(Type.SHORT, (short) 0); + wrapper.write(Type.SHORT, (short) (128D * (-Via.getConfig().getHologramYOffset() * 32D))); + wrapper.write(Type.SHORT, (short) 0); + wrapper.write(Type.BOOLEAN, true); + + wrapper.send(ProtocolSnapshotTo1_10.class); + } catch (Exception e) { + e.printStackTrace(); + } } } } } } catch (Exception e) { metadatas.remove(metadata); - if (!ViaVersion.getConfig().isSuppressMetadataErrors() || ViaVersion.getInstance().isDebug()) { + if (!Via.getConfig().isSuppressMetadataErrors() || Via.getManager().isDebug()) { System.out.println("An error occurred with entity metadata handler"); System.out.println("Metadata: " + metadata); e.printStackTrace(); } } } + } public static Optional getById(List metadatas, int id) { diff --git a/src/main/java/us/myles/ViaVersion/protocols/protocolsnapshotto1_10/ProtocolSnapshotTo1_10.java b/common/src/main/java/us/myles/ViaVersion/protocols/protocolsnapshotto1_10/ProtocolSnapshotTo1_10.java similarity index 68% rename from src/main/java/us/myles/ViaVersion/protocols/protocolsnapshotto1_10/ProtocolSnapshotTo1_10.java rename to common/src/main/java/us/myles/ViaVersion/protocols/protocolsnapshotto1_10/ProtocolSnapshotTo1_10.java index 750127ed7..4ee87a699 100644 --- a/src/main/java/us/myles/ViaVersion/protocols/protocolsnapshotto1_10/ProtocolSnapshotTo1_10.java +++ b/common/src/main/java/us/myles/ViaVersion/protocols/protocolsnapshotto1_10/ProtocolSnapshotTo1_10.java @@ -1,7 +1,10 @@ package us.myles.ViaVersion.protocols.protocolsnapshotto1_10; +import com.google.common.base.Optional; import us.myles.ViaVersion.api.PacketWrapper; +import us.myles.ViaVersion.api.Via; import us.myles.ViaVersion.api.data.UserConnection; +import us.myles.ViaVersion.api.entities.Entity1_11Types; import us.myles.ViaVersion.api.protocol.Protocol; import us.myles.ViaVersion.api.remapper.PacketHandler; import us.myles.ViaVersion.api.remapper.PacketRemapper; @@ -25,6 +28,31 @@ public class ProtocolSnapshotTo1_10 extends Protocol { protected void registerPackets() { InventoryPackets.register(this); + // Spawn Object + registerOutgoing(State.PLAY, 0x00, 0x00, new PacketRemapper() { + @Override + public void registerMap() { + map(Type.VAR_INT); // 0 - Entity id + map(Type.UUID); // 1 - UUID + map(Type.BYTE); // 2 - Type + + // Track Entity + handler(new PacketHandler() { + @Override + public void handle(PacketWrapper wrapper) throws Exception { + + int entityId = wrapper.get(Type.VAR_INT, 0); + byte type = wrapper.get(Type.BYTE, 0); + + Entity1_11Types.EntityType entType = Entity1_11Types.getTypeFromId(type, true); + + // Register Type ID + wrapper.user().get(EntityTracker.class).addEntity(entityId, entType); + } + }); + } + }); + // Spawn mob packet registerOutgoing(State.PLAY, 0x03, 0x03, new PacketRemapper() { @Override @@ -46,13 +74,17 @@ public class ProtocolSnapshotTo1_10 extends Protocol { handler(new PacketHandler() { @Override public void handle(PacketWrapper wrapper) throws Exception { + int entityId = wrapper.get(Type.VAR_INT, 0); // Change Type :) int type = wrapper.get(Type.VAR_INT, 1); - type = MetadataRewriter.rewriteEntityType(type, wrapper.get(Types1_9.METADATA_LIST, 0)); - wrapper.set(Type.VAR_INT, 1, type); + + Entity1_11Types.EntityType entType = MetadataRewriter.rewriteEntityType(type, wrapper.get(Types1_9.METADATA_LIST, 0)); + if (entType != null) + wrapper.set(Type.VAR_INT, 1, entType.getId()); + // Register Type ID - wrapper.user().get(EntityTracker.class).getClientEntityTypes().put(wrapper.get(Type.VAR_INT, 0), type); - MetadataRewriter.handleMetadata(type, wrapper.get(Types1_9.METADATA_LIST, 0)); + wrapper.user().get(EntityTracker.class).addEntity(entityId, entType); + MetadataRewriter.handleMetadata(entityId, entType, wrapper.get(Types1_9.METADATA_LIST, 0), wrapper.user()); } }); } @@ -110,11 +142,41 @@ public class ProtocolSnapshotTo1_10 extends Protocol { @Override public void handle(PacketWrapper wrapper) throws Exception { int entityId = wrapper.get(Type.VAR_INT, 0); - if (!wrapper.user().get(EntityTracker.class).getClientEntityTypes().containsKey(entityId)) { + + Optional type = wrapper.user().get(EntityTracker.class).get(entityId); + if (!type.isPresent()) return; + + MetadataRewriter.handleMetadata(entityId, type.get(), wrapper.get(Types1_9.METADATA_LIST, 0), wrapper.user()); + } + }); + } + }); + + // Entity teleport + registerOutgoing(State.PLAY, 0x49, 0x49, new PacketRemapper() { + @Override + public void registerMap() { + map(Type.VAR_INT); // 0 - Entity id + map(Type.DOUBLE); // 1 - x + map(Type.DOUBLE); // 2 - y + map(Type.DOUBLE); // 3 - z + map(Type.BYTE); // 4 - yaw + map(Type.BYTE); // 5 - pitch + map(Type.BOOLEAN); // 6 - onGround + + handler(new PacketHandler() { + @Override + public void handle(PacketWrapper wrapper) throws Exception { + int entityID = wrapper.get(Type.VAR_INT, 0); + if (Via.getConfig().isHologramPatch()) { + EntityTracker tracker = wrapper.user().get(EntityTracker.class); + if (tracker.isHologram(entityID)) { + Double newValue = wrapper.get(Type.DOUBLE, 1); + newValue -= (Via.getConfig().getHologramYOffset()); + wrapper.set(Type.DOUBLE, 1, newValue); + } } - int type = wrapper.user().get(EntityTracker.class).getClientEntityTypes().get(entityId); - MetadataRewriter.handleMetadata(type, wrapper.get(Types1_9.METADATA_LIST, 0)); } }); } diff --git a/src/main/java/us/myles/ViaVersion/protocols/protocolsnapshotto1_10/packets/InventoryPackets.java b/common/src/main/java/us/myles/ViaVersion/protocols/protocolsnapshotto1_10/packets/InventoryPackets.java similarity index 100% rename from src/main/java/us/myles/ViaVersion/protocols/protocolsnapshotto1_10/packets/InventoryPackets.java rename to common/src/main/java/us/myles/ViaVersion/protocols/protocolsnapshotto1_10/packets/InventoryPackets.java diff --git a/common/src/main/java/us/myles/ViaVersion/protocols/protocolsnapshotto1_10/storage/EntityTracker.java b/common/src/main/java/us/myles/ViaVersion/protocols/protocolsnapshotto1_10/storage/EntityTracker.java new file mode 100644 index 000000000..f01bc9c68 --- /dev/null +++ b/common/src/main/java/us/myles/ViaVersion/protocols/protocolsnapshotto1_10/storage/EntityTracker.java @@ -0,0 +1,52 @@ +package us.myles.ViaVersion.protocols.protocolsnapshotto1_10.storage; + +import com.google.common.base.Optional; +import com.google.common.collect.Sets; +import us.myles.ViaVersion.api.data.StoredObject; +import us.myles.ViaVersion.api.data.UserConnection; +import us.myles.ViaVersion.api.entities.Entity1_11Types; + +import java.util.Map; +import java.util.Set; +import java.util.concurrent.ConcurrentHashMap; + +public class EntityTracker extends StoredObject { + private final Map clientEntityTypes = new ConcurrentHashMap<>(); + private final Set holograms = Sets.newConcurrentHashSet(); + + public EntityTracker(UserConnection user) { + super(user); + } + + public void removeEntity(int entityId) { + clientEntityTypes.remove(entityId); + if (isHologram(entityId)) + removeHologram(entityId); + } + + public void addEntity(int entityId, Entity1_11Types.EntityType type) { + clientEntityTypes.put(entityId, type); + } + + public boolean has(int entityId) { + return clientEntityTypes.containsKey(entityId); + } + + public Optional get(int id) { + if (!has(id)) + return Optional.absent(); + return Optional.of(clientEntityTypes.get(id)); + } + + public void addHologram(int entId) { + holograms.add(entId); + } + + public boolean isHologram(int entId) { + return holograms.contains(entId); + } + + public void removeHologram(int entId) { + holograms.remove(entId); + } +} diff --git a/src/main/java/us/myles/ViaVersion/update/UpdateUtil.java b/common/src/main/java/us/myles/ViaVersion/update/UpdateUtil.java similarity index 63% rename from src/main/java/us/myles/ViaVersion/update/UpdateUtil.java rename to common/src/main/java/us/myles/ViaVersion/update/UpdateUtil.java index fa06fe35f..cfcc67ff5 100644 --- a/src/main/java/us/myles/ViaVersion/update/UpdateUtil.java +++ b/common/src/main/java/us/myles/ViaVersion/update/UpdateUtil.java @@ -1,129 +1,121 @@ -package us.myles.ViaVersion.update; - -import org.bukkit.Bukkit; -import org.bukkit.ChatColor; -import org.bukkit.entity.Player; -import org.bukkit.plugin.Plugin; -import org.bukkit.scheduler.BukkitRunnable; -import org.json.simple.JSONObject; -import org.json.simple.parser.JSONParser; -import org.json.simple.parser.ParseException; -import us.myles.ViaVersion.api.ViaVersion; - -import java.io.BufferedReader; -import java.io.IOException; -import java.io.InputStreamReader; -import java.net.HttpURLConnection; -import java.net.MalformedURLException; -import java.net.URL; -import java.util.UUID; - -public class UpdateUtil { - - public final static String PREFIX = ChatColor.GREEN + "" + ChatColor.BOLD + "[ViaVersion] " + ChatColor.GREEN; - private final static String URL = "http://api.spiget.org/v2/resources/"; - private final static int PLUGIN = 19254; - private final static String LATEST_VERSION = "/versions/latest"; - - public static void sendUpdateMessage(final UUID uuid, final Plugin plugin) { - new BukkitRunnable() { - - @Override - public void run() { - final String message = getUpdateMessage(false); - if (message != null) { - new BukkitRunnable() { - - @Override - public void run() { - Player p = Bukkit.getPlayer(uuid); - if (p != null) { - p.sendMessage(PREFIX + message); - } - } - }.runTask(plugin); - } - } - }.runTaskAsynchronously(plugin); - } - - public static void sendUpdateMessage(final Plugin plugin) { - new BukkitRunnable() { - - @Override - public void run() { - final String message = getUpdateMessage(true); - if (message != null) { - new BukkitRunnable() { - - @Override - public void run() { - plugin.getLogger().warning(message); - } - }.runTask(plugin); - } - } - }.runTaskAsynchronously(plugin); - } - - private static String getUpdateMessage(boolean console) { - if (ViaVersion.getInstance().getVersion().equals("${project.version}")) { - return "You are using a debug/custom version, consider updating."; - } - String newestString = getNewestVersion(); - if (newestString == null) { - if (console) { - return "Could not check for updates, check your connection."; - } else { - return null; - } - } - Version current; - try { - current = new Version(ViaVersion.getInstance().getVersion()); - } catch (IllegalArgumentException e) { - return "You are using a custom version, consider updating."; - } - Version newest = new Version(newestString); - if (current.compareTo(newest) < 0) - return "There is a newer version available: " + newest.toString() + ", you're on: " + current.toString(); - else if (console && current.compareTo(newest) != 0) { - if (current.getTag().toLowerCase().startsWith("dev") || current.getTag().toLowerCase().startsWith("snapshot")) { - return "You are running a development version, please report any bugs to GitHub."; - } else { - return "You are running a newer version than is released!"; - } - } - return null; - } - - private static String getNewestVersion() { - try { - 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.setDoOutput(true); - BufferedReader br = new BufferedReader(new InputStreamReader(connection.getInputStream())); - String input; - String content = ""; - while ((input = br.readLine()) != null) { - content = content + input; - } - br.close(); - JSONParser parser = new JSONParser(); - JSONObject statistics; - try { - statistics = (JSONObject) parser.parse(content); - } catch (ParseException e) { - e.printStackTrace(); - return null; - } - return (String) statistics.get("name"); - } catch (MalformedURLException e) { - return null; - } catch (IOException e) { - return null; - } - } -} +package us.myles.ViaVersion.update; + +import com.google.gson.JsonObject; +import com.google.gson.JsonParseException; +import net.md_5.bungee.api.ChatColor; +import us.myles.ViaVersion.api.Via; +import us.myles.ViaVersion.util.GsonUtil; + +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStreamReader; +import java.net.HttpURLConnection; +import java.net.MalformedURLException; +import java.net.URL; +import java.util.UUID; + +public class UpdateUtil { + + public final static String PREFIX = ChatColor.GREEN + "" + ChatColor.BOLD + "[ViaVersion] " + ChatColor.GREEN; + private final static String URL = "http://api.spiget.org/v2/resources/"; + private final static int PLUGIN = 19254; + private final static String LATEST_VERSION = "/versions/latest"; + + public static void sendUpdateMessage(final UUID uuid) { + Via.getPlatform().runAsync(new Runnable() { + @Override + public void run() { + final String message = getUpdateMessage(false); + if (message != null) { + Via.getPlatform().runSync( + new Runnable() { + @Override + public void run() { + Via.getPlatform().sendMessage(uuid, PREFIX + message); + } + } + ); + } + } + }); + } + + public static void sendUpdateMessage() { + Via.getPlatform().runAsync(new Runnable() { + @Override + public void run() { + final String message = getUpdateMessage(true); + if (message != null) { + Via.getPlatform().runSync( + new Runnable() { + @Override + public void run() { + Via.getPlatform().getLogger().warning(message); + } + } + ); + } + } + }); + } + + private static String getUpdateMessage(boolean console) { + if (Via.getPlatform().getPluginVersion().equals("${project.version}")) { + return "You are using a debug/custom version, consider updating."; + } + String newestString = getNewestVersion(); + if (newestString == null) { + if (console) { + return "Could not check for updates, check your connection."; + } else { + return null; + } + } + Version current; + try { + current = new Version(Via.getPlatform().getPluginVersion()); + } catch (IllegalArgumentException e) { + return "You are using a custom version, consider updating."; + } + Version newest = new Version(newestString); + if (current.compareTo(newest) < 0) + return "There is a newer version available: " + newest.toString() + ", you're on: " + current.toString(); + else if (console && current.compareTo(newest) != 0) { + if (current.getTag().toLowerCase().startsWith("dev") || current.getTag().toLowerCase().startsWith("snapshot")) { + return "You are running a development version, please report any bugs to GitHub."; + } else { + return "You are running a newer version than is released!"; + } + } + return null; + } + + private static String getNewestVersion() { + try { + URL url = new URL(URL + PLUGIN + LATEST_VERSION + "?" + System.currentTimeMillis()); + HttpURLConnection connection = (HttpURLConnection) url.openConnection(); + connection.setUseCaches(true); + connection.addRequestProperty("User-Agent", "ViaVersion " + Via.getPlatform().getPluginVersion() + " " + Via.getPlatform().getPlatformName()); + connection.setDoOutput(true); + BufferedReader br = new BufferedReader(new InputStreamReader(connection.getInputStream())); + String input; + String content = ""; + while ((input = br.readLine()) != null) { + content = content + input; + } + br.close(); + JsonObject statistics; + try { + statistics = GsonUtil.getGson().fromJson(content, JsonObject.class); + } catch (JsonParseException e) { + e.printStackTrace(); + return null; + } + return statistics.get("name").getAsString(); + } catch (MalformedURLException e) { + return null; + } catch (IOException e) { + return null; + } + } +} diff --git a/src/main/java/us/myles/ViaVersion/update/Version.java b/common/src/main/java/us/myles/ViaVersion/update/Version.java similarity index 73% rename from src/main/java/us/myles/ViaVersion/update/Version.java rename to common/src/main/java/us/myles/ViaVersion/update/Version.java index d96f4800a..c15609523 100644 --- a/src/main/java/us/myles/ViaVersion/update/Version.java +++ b/common/src/main/java/us/myles/ViaVersion/update/Version.java @@ -1,77 +1,96 @@ -package us.myles.ViaVersion.update; - -import org.apache.commons.lang.StringUtils; - -import java.util.regex.Matcher; -import java.util.regex.Pattern; - -public class Version implements Comparable { - private static Pattern semVer = Pattern.compile("(?0|[1-9]\\d*)\\.(?0|[1-9]\\d*)(?:\\.(?0|[1-9]\\d*))?(?:-(?[A-z0-9.-]*))?"); - private int[] parts = new int[3]; - private String tag; - - public Version(String value) { - if (value == null) - throw new IllegalArgumentException("Version can not be null"); - - Matcher matcher = semVer.matcher(value); - if (!matcher.matches()) - throw new IllegalArgumentException("Invalid version format"); - parts[0] = Integer.parseInt(matcher.group("a")); - parts[1] = Integer.parseInt(matcher.group("b")); - parts[2] = matcher.group("c") == null ? 0 : Integer.parseInt(matcher.group("c")); - - tag = matcher.group("tag") == null ? "" : matcher.group("tag"); - } - - public static int compare(Version verA, Version verB) { - if (verA == verB) return 0; - if (verA == null) return -1; - if (verB == null) return 1; - - int max = Math.max(verA.parts.length, verB.parts.length); - - for (int i = 0; i < max; i += 1) { - int partA = i < verA.parts.length ? verA.parts[i] : 0; - int partB = i < verB.parts.length ? verB.parts[i] : 0; - if (partA < partB) return -1; - if (partA > partB) return 1; - } - - // Simple tag check - if (verA.tag.length() == 0 && verB.tag.length() > 0) - return 1; - if (verA.tag.length() > 0 && verB.tag.length() == 0) - return -1; - - return 0; - } - - public static boolean equals(Version verA, Version verB) { - return verA == verB || verA != null && verB != null && compare(verA, verB) == 0; - } - - @Override - public String toString() { - String[] split = new String[parts.length]; - - for (int i = 0; i < parts.length; i += 1) - split[i] = String.valueOf(parts[i]); - - return StringUtils.join(split, ".") + (tag.length() != 0 ? "-" + tag : ""); - } - - @Override - public int compareTo(Version that) { - return compare(this, that); - } - - @Override - public boolean equals(Object that) { - return that instanceof Version && equals(this, (Version) that); - } - - public String getTag() { - return tag; - } +package us.myles.ViaVersion.update; + +import com.google.common.base.Joiner; + +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +public class Version implements Comparable { + private static final Pattern semVer = Pattern.compile("(?0|[1-9]\\d*)\\.(?0|[1-9]\\d*)(?:\\.(?0|[1-9]\\d*))?(?:-(?[A-z0-9.-]*))?"); + private final int[] parts = new int[3]; + private String tag; + + public Version(String value) { + if (value == null) + throw new IllegalArgumentException("Version can not be null"); + + Matcher matcher = semVer.matcher(value); + if (!matcher.matches()) + throw new IllegalArgumentException("Invalid version format"); + parts[0] = Integer.parseInt(matcher.group("a")); + parts[1] = Integer.parseInt(matcher.group("b")); + parts[2] = matcher.group("c") == null ? 0 : Integer.parseInt(matcher.group("c")); + + tag = matcher.group("tag") == null ? "" : matcher.group("tag"); + } + + /** + * Compare two versions + * + * @param verA The first version + * @param verB The second + * @return 0 if they are the same, 1 if versionA is newer, -1 if versionA is older + */ + public static int compare(Version verA, Version verB) { + if (verA == verB) return 0; + if (verA == null) return -1; + if (verB == null) return 1; + + int max = Math.max(verA.parts.length, verB.parts.length); + + for (int i = 0; i < max; i += 1) { + int partA = i < verA.parts.length ? verA.parts[i] : 0; + int partB = i < verB.parts.length ? verB.parts[i] : 0; + if (partA < partB) return -1; + if (partA > partB) return 1; + } + + // Simple tag check + if (verA.tag.length() == 0 && verB.tag.length() > 0) + return 1; + if (verA.tag.length() > 0 && verB.tag.length() == 0) + return -1; + + return 0; + } + + /** + * Check if a version is the same + * + * @param verA The first + * @param verB The second + * @return True if they are the same + */ + public static boolean equals(Version verA, Version verB) { + return verA == verB || verA != null && verB != null && compare(verA, verB) == 0; + } + + @Override + public String toString() { + String[] split = new String[parts.length]; + + for (int i = 0; i < parts.length; i += 1) + split[i] = String.valueOf(parts[i]); + + return Joiner.on(".").join(split) + (tag.length() != 0 ? "-" + tag : ""); + } + + @Override + public int compareTo(Version that) { + return compare(this, that); + } + + @Override + public boolean equals(Object that) { + return that instanceof Version && equals(this, (Version) that); + } + + /** + * Get the tag, eg. -ALPHA + * + * @return The version tag + */ + public String getTag() { + return tag; + } } \ No newline at end of file diff --git a/src/main/java/us/myles/ViaVersion/util/Configuration.java b/common/src/main/java/us/myles/ViaVersion/util/CommentStore.java similarity index 68% rename from src/main/java/us/myles/ViaVersion/util/Configuration.java rename to common/src/main/java/us/myles/ViaVersion/util/CommentStore.java index 447f53f1e..33acbe4c8 100644 --- a/src/main/java/us/myles/ViaVersion/util/Configuration.java +++ b/common/src/main/java/us/myles/ViaVersion/util/CommentStore.java @@ -3,27 +3,23 @@ package us.myles.ViaVersion.util; import com.google.common.base.Joiner; import com.google.common.collect.Lists; import com.google.common.collect.Maps; -import org.bukkit.Bukkit; -import org.bukkit.configuration.InvalidConfigurationException; -import org.bukkit.configuration.file.YamlConfiguration; +import com.google.common.io.CharStreams; -import java.io.File; -import java.io.FileWriter; -import java.io.IOException; +import java.io.*; import java.util.Arrays; import java.util.List; import java.util.Map; -import java.util.logging.Level; import java.util.regex.Pattern; -public class Configuration extends YamlConfiguration { +public class CommentStore { private final Map> headers = Maps.newConcurrentMap(); - private final File file; + private final char pathSeperator; + private final int indents; private List mainHeader = Lists.newArrayList(); - private boolean loadHeaders; - public Configuration(File file) { - this.file = file; + public CommentStore(char pathSeperator, int indents) { + this.pathSeperator = pathSeperator; + this.indents = indents; } /** @@ -65,43 +61,17 @@ public class Configuration extends YamlConfiguration { return headers.get(key); } - public T get(String key, Class type) { - return type.cast(get(key)); - } - - /** - * Reload config from file. - */ - public void reload() { - reload(headers.isEmpty()); - } - - /** - * Reload config from file. - * - * @param loadHeaders Whether or not to load headers. - */ - public void reload(boolean loadHeaders) { - this.loadHeaders = loadHeaders; + public void storeComments(InputStream inputStream) throws IOException { + InputStreamReader reader = new InputStreamReader(inputStream); + String contents; try { - load(file); - } catch (Exception e) { - Bukkit.getLogger().log(Level.WARNING, "failed to reload file", e); + contents = CharStreams.toString(reader); + } finally { + reader.close(); } - } - - @Override - public void loadFromString(String contents) throws InvalidConfigurationException { - if (!loadHeaders) { - super.loadFromString(contents); - return; - } - StringBuilder memoryData = new StringBuilder(); - // Parse headers - final int indentLength = options().indent(); - final String pathSeparator = Character.toString(options().pathSeparator()); + final String pathSeparator = Character.toString(this.pathSeperator); int currentIndents = 0; String key = ""; List headers = Lists.newArrayList(); @@ -122,12 +92,12 @@ public class Configuration extends YamlConfiguration { continue; } - int indents = indent / indentLength; + int indents = indent / this.indents; if (indents <= currentIndents) { // Remove last section of key String[] array = key.split(Pattern.quote(pathSeparator)); int backspace = currentIndents - indents + 1; - key = join(array, options().pathSeparator(), 0, array.length - backspace); + key = join(array, this.pathSeperator, 0, array.length - backspace); } // Add new section to key @@ -143,32 +113,13 @@ public class Configuration extends YamlConfiguration { headers = Lists.newArrayList(); } } - - // Parse remaining text - super.loadFromString(memoryData.toString()); - - // Clear bukkit header - options().header(null); } - /** - * Save config to file - */ - public void save() { - if (headers.isEmpty() && mainHeader.isEmpty()) { - try { - super.save(file); - } catch (IOException e) { - Bukkit.getLogger().log(Level.WARNING, "Failed to save file", e); - } - return; - } - + public void writeComments(String yaml, File output) throws IOException { // Custom save - final int indentLength = options().indent(); - final String pathSeparator = Character.toString(options().pathSeparator()); - String content = saveToString(); - StringBuilder fileData = new StringBuilder(buildHeader()); + final int indentLength = this.indents; + final String pathSeparator = Character.toString(this.pathSeperator); + StringBuilder fileData = new StringBuilder(); int currentIndents = 0; String key = ""; for (String h : mainHeader) { @@ -176,7 +127,7 @@ public class Configuration extends YamlConfiguration { fileData.append("#> ").append(h).append('\n'); } - for (String line : content.split("\n")) { + for (String line : yaml.split("\n")) { if (line.isEmpty()) continue; // Skip empty lines int indent = getSuccessiveCharCount(line, ' '); int indents = indent / indentLength; @@ -185,7 +136,7 @@ public class Configuration extends YamlConfiguration { // Remove last section of key String[] array = key.split(Pattern.quote(pathSeparator)); int backspace = currentIndents - indents + 1; - key = join(array, options().pathSeparator(), 0, array.length - backspace); + key = join(array, this.pathSeperator, 0, array.length - backspace); } // Add new section to key @@ -203,11 +154,9 @@ public class Configuration extends YamlConfiguration { // Write data to file FileWriter writer = null; try { - writer = new FileWriter(file); + writer = new FileWriter(output); writer.write(fileData.toString()); writer.flush(); - } catch (IOException e) { - Bukkit.getLogger().log(Level.WARNING, "Failed to save file", e); } finally { if (writer != null) { try { diff --git a/src/main/java/us/myles/ViaVersion/util/ConcurrentList.java b/common/src/main/java/us/myles/ViaVersion/util/ConcurrentList.java similarity index 99% rename from src/main/java/us/myles/ViaVersion/util/ConcurrentList.java rename to common/src/main/java/us/myles/ViaVersion/util/ConcurrentList.java index 39d3f8f2e..524b9145f 100644 --- a/src/main/java/us/myles/ViaVersion/util/ConcurrentList.java +++ b/common/src/main/java/us/myles/ViaVersion/util/ConcurrentList.java @@ -8,9 +8,10 @@ import java.util.*; /** * Created by wea_ondara licensed under MIT * Same license as in LICENSE - * + *

* Taken from: * https://github.com/weaondara/BungeePerms/blob/master/src/main/java/net/alpenblock/bungeeperms/util/ConcurrentList.java + * * @param List Type */ public class ConcurrentList extends ArrayList { diff --git a/common/src/main/java/us/myles/ViaVersion/util/Config.java b/common/src/main/java/us/myles/ViaVersion/util/Config.java new file mode 100644 index 000000000..7d6e1edca --- /dev/null +++ b/common/src/main/java/us/myles/ViaVersion/util/Config.java @@ -0,0 +1,169 @@ +package us.myles.ViaVersion.util; + +import org.yaml.snakeyaml.DumperOptions; +import org.yaml.snakeyaml.Yaml; +import org.yaml.snakeyaml.representer.Representer; +import us.myles.ViaVersion.api.configuration.ConfigurationProvider; + +import java.io.*; +import java.net.URL; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.concurrent.ConcurrentSkipListMap; + +public abstract class Config implements ConfigurationProvider { + private static ThreadLocal yaml = new ThreadLocal() { + @Override + protected Yaml initialValue() { + DumperOptions options = new DumperOptions(); + options.setDefaultFlowStyle(DumperOptions.FlowStyle.BLOCK); + options.setPrettyFlow(false); + options.setIndent(2); + return new Yaml(new YamlConstructor(), new Representer(), options); + } + }; + private CommentStore commentStore = new CommentStore('.', 2); + private final File configFile; + private ConcurrentSkipListMap config; + + public Config(File configFile) { + this.configFile = configFile; + reloadConfig(); + } + + public Map loadConfig(File location) { + List unsupported = getUnsupportedOptions(); + URL jarConfigFile = Config.class.getClassLoader().getResource("config.yml"); + try { + commentStore.storeComments(jarConfigFile.openStream()); + for (String option : unsupported) { + List comments = commentStore.header(option); + if (comments != null) { + comments.clear(); + } + } + } catch (IOException e) { + e.printStackTrace(); + } + Map config = null; + if (location.exists()) { + try (FileInputStream input = new FileInputStream(location)) { + config = (Map) yaml.get().load(input); + } catch (FileNotFoundException e) { + e.printStackTrace(); + } catch (IOException e) { + e.printStackTrace(); + } + } + if (config == null) { + config = new HashMap<>(); + } + + Map defaults = config; + try (InputStream stream = jarConfigFile.openStream()) { + defaults = (Map) yaml.get().load(stream); + for (String option : unsupported) { + defaults.remove(option); + } + // Merge with defaultLoader + for (Object key : config.keySet()) { + // Set option in new conf if exists + if (defaults.containsKey(key) && !unsupported.contains(key.toString())) { + defaults.put((String) key, config.get(key)); + } + } + } 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); + } catch (IOException e) { + e.printStackTrace(); + } + } + + public abstract List getUnsupportedOptions(); + + @Override + public void set(String path, Object value) { + config.put(path, value); + } + + @Override + public void saveConfig() { + this.configFile.getParentFile().mkdirs(); + saveConfig(this.configFile, this.config); + } + + @Override + public void reloadConfig() { + this.configFile.getParentFile().mkdirs(); + this.config = new ConcurrentSkipListMap<>(loadConfig(this.configFile)); + } + + @Override + public Map getValues() { + 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); + } else { + return def; + } + } + + public String getString(String key, String def) { + if (this.config.containsKey(key)) { + return (String) this.config.get(key); + } else { + return def; + } + } + + public int getInt(String key, int def) { + if (this.config.containsKey(key)) { + return (int) this.config.get(key); + } else { + return def; + } + } + + public double getDouble(String key, double def) { + if (this.config.containsKey(key)) { + return (double) this.config.get(key); + } else { + return def; + } + } + + public List getIntegerList(String key) { + if (this.config.containsKey(key)) { + return (List) this.config.get(key); + } else { + return new ArrayList<>(); + } + } +} diff --git a/common/src/main/java/us/myles/ViaVersion/util/GsonUtil.java b/common/src/main/java/us/myles/ViaVersion/util/GsonUtil.java new file mode 100644 index 000000000..38af3892e --- /dev/null +++ b/common/src/main/java/us/myles/ViaVersion/util/GsonUtil.java @@ -0,0 +1,29 @@ +package us.myles.ViaVersion.util; + +import com.google.gson.Gson; +import com.google.gson.GsonBuilder; +import lombok.experimental.UtilityClass; + +@UtilityClass +public class GsonUtil { + private final Gson gson = getGsonBuilder().create(); + + /** + * Get google's Gson magic + * + * @return Gson instance + */ + public Gson getGson() { + return gson; + } + + /** + * Get the GsonBuilder in case you want to add other stuff + * + * @return GsonBuilder instance + */ + public GsonBuilder getGsonBuilder() { + return new GsonBuilder(); + } + +} diff --git a/src/main/java/us/myles/ViaVersion/util/ListWrapper.java b/common/src/main/java/us/myles/ViaVersion/util/ListWrapper.java similarity index 98% rename from src/main/java/us/myles/ViaVersion/util/ListWrapper.java rename to common/src/main/java/us/myles/ViaVersion/util/ListWrapper.java index 7b19c96cf..f276d0eed 100644 --- a/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) { diff --git a/src/main/java/us/myles/ViaVersion/util/PipelineUtil.java b/common/src/main/java/us/myles/ViaVersion/util/PipelineUtil.java similarity index 69% rename from src/main/java/us/myles/ViaVersion/util/PipelineUtil.java rename to common/src/main/java/us/myles/ViaVersion/util/PipelineUtil.java index 84449596c..05b92e9d5 100644 --- a/src/main/java/us/myles/ViaVersion/util/PipelineUtil.java +++ b/common/src/main/java/us/myles/ViaVersion/util/PipelineUtil.java @@ -32,6 +32,15 @@ public class PipelineUtil { } } + /** + * Call the decode method on a netty ByteToMessageDecoder + * + * @param decoder The decoder + * @param ctx The current context + * @param input The packet to decode + * @return A list of the decoders output + * @throws InvocationTargetException If an exception happens while executing + */ public static List callDecode(ByteToMessageDecoder decoder, ChannelHandlerContext ctx, Object input) throws InvocationTargetException { List output = new ArrayList<>(); try { @@ -42,6 +51,15 @@ public class PipelineUtil { return output; } + /** + * Call the encode method on a netty MessageToByteEncoder + * + * @param encoder The encoder + * @param ctx The current context + * @param msg The packet to encode + * @param output The bytebuf to write the output to + * @throws InvocationTargetException If an exception happens while executing + */ public static void callEncode(MessageToByteEncoder encoder, ChannelHandlerContext ctx, Object msg, ByteBuf output) throws InvocationTargetException { try { PipelineUtil.ENCODE_METHOD.invoke(encoder, ctx, msg, output); @@ -50,6 +68,13 @@ public class PipelineUtil { } } + /** + * Check if a stack trace contains a certain exception + * + * @param t The throwable + * @param c The exception to look for + * @return True if the stack trace contained it as its cause. + */ public static boolean containsCause(Throwable t, Class c) { while (t != null) { t = t.getCause(); @@ -59,6 +84,13 @@ public class PipelineUtil { return false; } + /** + * Get the context for a the channel handler before a certain name. + * + * @param name The name of the channel handler + * @param pipeline The pipeline to target + * @return The ChannelHandler before the one requested. + */ public static ChannelHandlerContext getContextBefore(String name, ChannelPipeline pipeline) { boolean mark = false; for (String s : pipeline.names()) { diff --git a/src/main/java/us/myles/ViaVersion/util/ReflectionUtil.java b/common/src/main/java/us/myles/ViaVersion/util/ReflectionUtil.java similarity index 89% rename from src/main/java/us/myles/ViaVersion/util/ReflectionUtil.java rename to common/src/main/java/us/myles/ViaVersion/util/ReflectionUtil.java index 307ae2601..f44622297 100644 --- a/src/main/java/us/myles/ViaVersion/util/ReflectionUtil.java +++ b/common/src/main/java/us/myles/ViaVersion/util/ReflectionUtil.java @@ -1,7 +1,6 @@ package us.myles.ViaVersion.util; import com.google.common.collect.Maps; -import org.bukkit.Bukkit; import java.lang.reflect.Field; import java.lang.reflect.InvocationTargetException; @@ -11,20 +10,6 @@ import java.util.Collections; import java.util.Map; public class ReflectionUtil { - private static String BASE = Bukkit.getServer().getClass().getPackage().getName(); - private static String NMS = BASE.replace("org.bukkit.craftbukkit", "net.minecraft.server"); - - public static Class nms(String className) throws ClassNotFoundException { - return Class.forName(NMS + "." + className); - } - - public static Class obc(String className) throws ClassNotFoundException { - return Class.forName(BASE + "." + className); - } - - public static String getVersion() { - return BASE.substring(BASE.lastIndexOf('.') + 1); - } public static Object invokeStatic(Class clazz, String method) throws NoSuchMethodException, InvocationTargetException, IllegalAccessException { Method m = clazz.getDeclaredMethod(method); @@ -42,6 +27,12 @@ public class ReflectionUtil { return (T) field.get(null); } + public static void setStatic(Class clazz, String f, Object value) throws NoSuchFieldException, IllegalAccessException { + Field field = clazz.getDeclaredField(f); + field.setAccessible(true); + field.set(null, value); + } + public static T getSuper(Object o, String f, Class t) throws NoSuchFieldException, IllegalAccessException { Field field = o.getClass().getSuperclass().getDeclaredField(f); field.setAccessible(true); @@ -73,6 +64,7 @@ public class ReflectionUtil { field.set(o, value); } + public static final class ClassReflection { private final Class handle; private final Map fields = Maps.newConcurrentMap(); diff --git a/common/src/main/java/us/myles/ViaVersion/util/YamlConstructor.java b/common/src/main/java/us/myles/ViaVersion/util/YamlConstructor.java new file mode 100644 index 000000000..4bc53061a --- /dev/null +++ b/common/src/main/java/us/myles/ViaVersion/util/YamlConstructor.java @@ -0,0 +1,38 @@ +package us.myles.ViaVersion.util; + +import org.yaml.snakeyaml.constructor.Constructor; +import org.yaml.snakeyaml.constructor.SafeConstructor; +import org.yaml.snakeyaml.nodes.Node; +import org.yaml.snakeyaml.nodes.NodeId; +import org.yaml.snakeyaml.nodes.Tag; + +import java.util.concurrent.ConcurrentSkipListMap; + +public class YamlConstructor extends SafeConstructor { + public YamlConstructor() { + super(); + yamlClassConstructors.put(NodeId.mapping, new YamlConstructor.ConstructYamlMap()); + yamlConstructors.put(Tag.OMAP, new YamlConstructor.ConstructYamlOmap()); + } + + class Map extends Constructor.ConstructYamlMap { + @Override + public Object construct(Node node) { + Object o = super.construct(node); + if (o instanceof Map && !(o instanceof ConcurrentSkipListMap)) { + return new ConcurrentSkipListMap<>((java.util.Map) o); + } + return o; + } + } + + class ConstructYamlOmap extends Constructor.ConstructYamlOmap { + public Object construct(Node node) { + Object o = super.construct(node); + if (o instanceof Map && !(o instanceof ConcurrentSkipListMap)) { + return new ConcurrentSkipListMap<>((java.util.Map) o); + } + return o; + } + } +} diff --git a/src/main/resources/config.yml b/common/src/main/resources/config.yml similarity index 73% rename from src/main/resources/config.yml rename to common/src/main/resources/config.yml index aac3ad695..ff47962aa 100644 --- a/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 # #----------------------------------------------------------# # # @@ -32,7 +55,7 @@ reload-disconnect-msg: "Server reload, please rejoin!" # # What is the maximum per second a client can send (Use %pps to display their pps) # Use -1 to disable. -max-pps: 600 +max-pps: 800 max-pps-kick-msg: "You are sending too many packets!" # # We can also kick them if over a period they send over a threshold a certain amount of times. @@ -48,6 +71,16 @@ tracking-max-warnings: 4 tracking-max-kick-msg: "You are sending too many packets, :(" # #----------------------------------------------------------# +# MULTIPLE VERSIONS OPTIONS # +#----------------------------------------------------------# +# +# Should we enable our hologram patch? +# If they're in the wrong place enable this +hologram-patch: false +# This is the offset, should work as default when enabled. +hologram-y: -0.96 +# +#----------------------------------------------------------# # 1.9 & 1.10 CLIENTS ON 1.8 SERVERS OPTIONS # #----------------------------------------------------------# # @@ -60,11 +93,6 @@ auto-team: true suppress-metadata-errors: false # When enabled 1.9 & 1.10 will be able to block by using shields shield-blocking: true -# Should we enable our hologram patch? -# If they're in the wrong place enable this -hologram-patch: false -# This is the offset, should work as default when enabled. -hologram-y: -0.96 # Enable player tick simulation, this fixes eating, drinking, nether portals. simulate-pt: true # Should we use nms player to simulate packets, (may fix anti-cheat issues) @@ -76,7 +104,7 @@ bossbar-anti-flicker: false # This will show the new effect indicator in the top-right corner for 1.9 & 1.10 players. use-new-effect-indicator: true # Show the new death messages for 1.9 & 1.10 on the death screen -use-new-deathmessages: false +use-new-deathmessages: true # Should we cache our items, this will prevent server from being lagged out, however the cost is a constant task caching items item-cache: true # Patch the Anti xray to work on 1.9 & 1.10 (If your server is 1.8) This can cost more performance, so disable it if you don't use it. diff --git a/jar/pom.xml b/jar/pom.xml new file mode 100644 index 000000000..8a13e4d97 --- /dev/null +++ b/jar/pom.xml @@ -0,0 +1,97 @@ + + + + viaversion-parent + us.myles + 1.0.0-ALPHA-modules + + 4.0.0 + viaversion-jar + viaversion + + + ViaVersion-${project.version} + clean install + + + . + false + ../ + + LICENSE + + + + . + true + src/main/resources/ + + * + + + + + + + + + org.apache.maven.plugins + maven-shade-plugin + 2.4.3 + + false + false + + + org.spacehq.opennbt + us.myles.viaversion.libs.opennbt + + + com.google.gson + us.myles.viaversion.libs.gson + + + org.javassist + us.myles.viaversion.libs.javassist + + + + + + package + + shade + + + + + + + + + + us.myles + viaversion-common + ${project.parent.version} + + + us.myles + viaversion-bukkit + ${project.parent.version} + + + us.myles + viaversion-bungee + ${project.parent.version} + + + us.myles + viaversion-sponge + ${project.parent.version} + + + + \ No newline at end of file diff --git a/pom.xml b/pom.xml index 16bf759f1..60a19b8c5 100644 --- a/pom.xml +++ b/pom.xml @@ -5,15 +5,25 @@ 4.0.0 us.myles - viaversion - 1.0.0-ALPHA-16w39c - jar + viaversion-parent + 1.0.0-ALPHA-modules + pom + + viaversion-parent - ViaVersion Allow newer clients to join older server versions. 2016 https://www.spigotmc.org/resources/viaversion.19254/ + + common + bukkit + bungee + sponge + jar + sponge-legacy + + 3.3.3 @@ -23,107 +33,10 @@ UTF-8 ${projectEncoding} ${projectEncoding} - 1.7 - - - - 1.8.8-R0.1-SNAPSHOT + 1.7 + 1.7 - - ${project.name}-${project.version} - src/main/java - clean install - - - - - . - false - . - - LICENSE - - - - . - true - src/main/resources/ - - * - - - - - - - - - org.apache.maven.plugins - maven-compiler-plugin - 3.5.1 - - ${jdkVersion} - ${jdkVersion} - - - - - - - - org.apache.maven.plugins - maven-shade-plugin - 2.4.3 - - false - false - - - org.spacehq.opennbt - us.myles.viaversion.libs.opennbt - - - com.google.gson - us.myles.viaversion.libs.gson - - - org.javassist - us.myles.viaversion.libs.javassist - - - - - - package - - shade - - - - - - - @@ -145,29 +58,13 @@ - + - org.bukkit - bukkit - ${bukkitVersion} + org.projectlombok + lombok + 1.16.6 provided - true - - - junit - junit - - - gson - com.google.code.gson - - - persistence-api - javax.persistence - - - org.javassist @@ -204,20 +101,20 @@ true - - - org.projectlombok - lombok - 1.16.6 - provided - - - + net.md-5 - bungeecord-api - 1.9-SNAPSHOT + bungeecord-chat + 1.10-SNAPSHOT + + + + + com.google.guava + guava + 17.0 provided + diff --git a/sponge-legacy/pom.xml b/sponge-legacy/pom.xml new file mode 100644 index 000000000..e0063d252 --- /dev/null +++ b/sponge-legacy/pom.xml @@ -0,0 +1,73 @@ + + + + viaversion-parent + us.myles + 1.0.0-ALPHA-modules + + 4.0.0 + + viaversion-sponge-legacy + jar + + + 1.8 + 1.8 + + + + + sponge + http://repo.spongepowered.org/maven + + + + + + + . + true + src/main/resources/ + + * + + + + + + org.codehaus.mojo + templating-maven-plugin + 1.0.0 + + + filter-src + + filter-sources + + + + + + + + + + + us.myles + viaversion-common + ${project.parent.version} + provided + + + + + org.spongepowered + spongeapi + 4.0.0-SNAPSHOT + provided + + + + \ No newline at end of file diff --git a/sponge-legacy/src/main/java/us/myles/ViaVersion/sponge/listeners/protocol1_9to1_8/ItemGrabber.java b/sponge-legacy/src/main/java/us/myles/ViaVersion/sponge/listeners/protocol1_9to1_8/ItemGrabber.java new file mode 100644 index 000000000..8f1069caa --- /dev/null +++ b/sponge-legacy/src/main/java/us/myles/ViaVersion/sponge/listeners/protocol1_9to1_8/ItemGrabber.java @@ -0,0 +1,8 @@ +package us.myles.ViaVersion.sponge.listeners.protocol1_9to1_8; + +import org.spongepowered.api.entity.living.player.Player; +import org.spongepowered.api.item.inventory.ItemStack; + +public interface ItemGrabber { + public ItemStack getItem(Player player); +} diff --git a/sponge-legacy/src/main/java/us/myles/ViaVersion/sponge/listeners/protocol1_9to1_8/sponge4/Sponge4ArmorListener.java b/sponge-legacy/src/main/java/us/myles/ViaVersion/sponge/listeners/protocol1_9to1_8/sponge4/Sponge4ArmorListener.java new file mode 100644 index 000000000..5b542bdb4 --- /dev/null +++ b/sponge-legacy/src/main/java/us/myles/ViaVersion/sponge/listeners/protocol1_9to1_8/sponge4/Sponge4ArmorListener.java @@ -0,0 +1,141 @@ +package us.myles.ViaVersion.sponge.listeners.protocol1_9to1_8.sponge4; + +import org.spongepowered.api.Sponge; +import org.spongepowered.api.entity.living.player.Player; +import org.spongepowered.api.event.Listener; +import org.spongepowered.api.event.action.InteractEvent; +import org.spongepowered.api.event.entity.DisplaceEntityEvent; +import org.spongepowered.api.event.entity.living.humanoid.player.RespawnPlayerEvent; +import org.spongepowered.api.event.filter.cause.Root; +import org.spongepowered.api.event.item.inventory.ClickInventoryEvent; +import org.spongepowered.api.event.network.ClientConnectionEvent; +import org.spongepowered.api.item.inventory.ItemStack; +import org.spongepowered.api.item.inventory.transaction.SlotTransaction; +import us.myles.ViaVersion.api.PacketWrapper; +import us.myles.ViaVersion.api.Via; +import us.myles.ViaVersion.api.ViaListener; +import us.myles.ViaVersion.api.type.Type; +import us.myles.ViaVersion.protocols.protocol1_9to1_8.ArmorType; +import us.myles.ViaVersion.protocols.protocol1_9to1_8.Protocol1_9TO1_8; + +import java.lang.reflect.Field; +import java.util.Optional; +import java.util.UUID; + +public class Sponge4ArmorListener extends ViaListener{ + private static Field entityIdField; + + private static final UUID ARMOR_ATTRIBUTE = UUID.fromString("2AD3F246-FEE1-4E67-B886-69FD380BB150"); + + public Sponge4ArmorListener() { + super(Protocol1_9TO1_8.class); + } + + // + public void sendArmorUpdate(Player player) { + // Ensure that the player is on our pipe + if (!isOnPipe(player.getUniqueId())) return; + + + int armor = 0; + armor += calculate(player.getHelmet()); + armor += calculate(player.getChestplate()); + armor += calculate(player.getLeggings()); + armor += calculate(player.getBoots()); + + PacketWrapper wrapper = new PacketWrapper(0x4B, null, getUserConnection(player.getUniqueId())); + try { + wrapper.write(Type.VAR_INT, getEntityId(player)); // Player ID + wrapper.write(Type.INT, 1); // only 1 property + wrapper.write(Type.STRING, "generic.armor"); + wrapper.write(Type.DOUBLE, 0D); //default 0 armor + wrapper.write(Type.VAR_INT, 1); // 1 modifier + wrapper.write(Type.UUID, ARMOR_ATTRIBUTE); // armor modifier uuid + wrapper.write(Type.DOUBLE, (double) armor); // the modifier value + wrapper.write(Type.BYTE, (byte) 0);// the modifier operation, 0 is add number + + wrapper.send(Protocol1_9TO1_8.class); + } catch (Exception e) { + e.printStackTrace(); + } + } + + private int calculate(Optional itemStack) { + if (itemStack.isPresent()) + return ArmorType.findByType(itemStack.get().getItem().getType().getId()).getArmorPoints(); + + return 0; + } + + @Listener + public void onInventoryClick(ClickInventoryEvent e, @Root Player player) { + for (SlotTransaction transaction : e.getTransactions()) { + if (ArmorType.isArmor(transaction.getFinal().getType().getId()) || + ArmorType.isArmor(e.getCursorTransaction().getFinal().getType().getId())) { + sendDelayedArmorUpdate(player); + break; + } + } + } + + @Listener + public void onInteract(InteractEvent event, @Root Player player) { + if (player.getItemInHand().isPresent()) { + if (ArmorType.isArmor(player.getItemInHand().get().getItem().getId())) + sendDelayedArmorUpdate(player); + } + } + + @Listener + public void onJoin(ClientConnectionEvent.Join e) { + sendArmorUpdate(e.getTargetEntity()); + } + + @Listener + public void onRespawn(RespawnPlayerEvent e) { + sendDelayedArmorUpdate(e.getTargetEntity()); + } + + @Listener + public void onWorldChange(DisplaceEntityEvent.Teleport e) { + if (!(e.getTargetEntity() instanceof Player)) return; + if (!e.getFromTransform().getExtent().getUniqueId().equals(e.getToTransform().getExtent().getUniqueId())) { + sendArmorUpdate((Player) e.getTargetEntity()); + } + } + + public void sendDelayedArmorUpdate(final Player player) { + if (!isOnPipe(player.getUniqueId())) return; // Don't start a task if the player is not on the pipe + Via.getPlatform().runSync(new Runnable() { + @Override + public void run() { + sendArmorUpdate(player); + } + }); + } + + @Override + public void register() { + if (isRegistered()) return; + + Sponge.getEventManager().registerListeners(Via.getPlatform(), this); + setRegistered(true); + } + + protected int getEntityId(Player p) { + try { + if (entityIdField == null) { + entityIdField = p.getClass().getSuperclass().getSuperclass().getSuperclass().getDeclaredField("field_145783_c"); + entityIdField.setAccessible(true); + } + + return entityIdField.getInt(p); + } catch (Exception e) { + Via.getPlatform().getLogger().severe("Could not get the entity id, please report this on our Github"); + e.printStackTrace(); + } + + Via.getPlatform().getLogger().severe("Could not get the entity id, please report this on our Github"); + return -1; + } +} diff --git a/sponge-legacy/src/main/java/us/myles/ViaVersion/sponge/listeners/protocol1_9to1_8/sponge4/Sponge4ItemGrabber.java b/sponge-legacy/src/main/java/us/myles/ViaVersion/sponge/listeners/protocol1_9to1_8/sponge4/Sponge4ItemGrabber.java new file mode 100644 index 000000000..17da6eb35 --- /dev/null +++ b/sponge-legacy/src/main/java/us/myles/ViaVersion/sponge/listeners/protocol1_9to1_8/sponge4/Sponge4ItemGrabber.java @@ -0,0 +1,12 @@ +package us.myles.ViaVersion.sponge.listeners.protocol1_9to1_8.sponge4; + +import org.spongepowered.api.entity.living.player.Player; +import org.spongepowered.api.item.inventory.ItemStack; +import us.myles.ViaVersion.sponge.listeners.protocol1_9to1_8.ItemGrabber; + +public class Sponge4ItemGrabber implements ItemGrabber { + @Override + public ItemStack getItem(Player player) { + return player.getItemInHand().orElse(null); + } +} diff --git a/sponge/pom.xml b/sponge/pom.xml new file mode 100644 index 000000000..f4a3ec61d --- /dev/null +++ b/sponge/pom.xml @@ -0,0 +1,80 @@ + + + + viaversion-parent + us.myles + 1.0.0-ALPHA-modules + + 4.0.0 + + viaversion-sponge + + + 1.8 + 1.8 + + + + + sponge + http://repo.spongepowered.org/maven + + + + + + + . + true + src/main/resources/ + + * + + + + + + org.codehaus.mojo + templating-maven-plugin + 1.0.0 + + + filter-src + + filter-sources + + + + + + + + + + + us.myles + viaversion-common + ${project.parent.version} + provided + + + + + org.spongepowered + spongeapi + 5.0.0-SNAPSHOT + provided + + + + + us.myles + viaversion-sponge-legacy + ${project.parent.version} + compile + + + + \ No newline at end of file diff --git a/sponge/src/main/java-templates/us/myles/ViaVersion/sponge/VersionInfo.java b/sponge/src/main/java-templates/us/myles/ViaVersion/sponge/VersionInfo.java new file mode 100644 index 000000000..960f6a88d --- /dev/null +++ b/sponge/src/main/java-templates/us/myles/ViaVersion/sponge/VersionInfo.java @@ -0,0 +1,5 @@ +package us.myles.ViaVersion.sponge; + +public class VersionInfo { + public static final String VERSION = "${project.version}"; +} diff --git a/sponge/src/main/java/us/myles/ViaVersion/SpongePlugin.java b/sponge/src/main/java/us/myles/ViaVersion/SpongePlugin.java new file mode 100644 index 000000000..78df27c07 --- /dev/null +++ b/sponge/src/main/java/us/myles/ViaVersion/SpongePlugin.java @@ -0,0 +1,196 @@ +package us.myles.ViaVersion; + +import com.google.gson.JsonObject; +import com.google.inject.Inject; +import org.spongepowered.api.Game; +import org.spongepowered.api.config.DefaultConfig; +import org.spongepowered.api.entity.living.player.Player; +import org.spongepowered.api.event.Listener; +import org.spongepowered.api.event.game.state.GameAboutToStartServerEvent; +import org.spongepowered.api.plugin.Plugin; +import org.spongepowered.api.plugin.PluginContainer; +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.command.ViaCommandSender; +import us.myles.ViaVersion.api.configuration.ConfigurationProvider; +import us.myles.ViaVersion.api.platform.TaskId; +import us.myles.ViaVersion.api.platform.ViaPlatform; +import us.myles.ViaVersion.dump.PluginInfo; +import us.myles.ViaVersion.sponge.VersionInfo; +import us.myles.ViaVersion.sponge.commands.SpongeCommandHandler; +import us.myles.ViaVersion.sponge.commands.SpongeCommandSender; +import us.myles.ViaVersion.sponge.platform.*; +import us.myles.ViaVersion.sponge.util.LoggerWrapper; +import us.myles.ViaVersion.util.GsonUtil; + +import java.io.File; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import java.util.UUID; +import java.util.concurrent.TimeUnit; +import java.util.logging.Logger; + +@Plugin(id = "viaversion", + name = "ViaVersion", + version = VersionInfo.VERSION, + authors = {"_MylesC", "Matsv"}, + description = "Allow newer Minecraft versions to connect to an older server version." +) +public class SpongePlugin implements ViaPlatform { + @Inject + private Game game; + + @Inject + private PluginContainer container; + + @Inject + @DefaultConfig(sharedRoot = false) + private File defaultConfig; + + private SpongeViaAPI api = new SpongeViaAPI(); + private SpongeExecutorService asyncExecutor; + private SpongeExecutorService syncExecutor; + private SpongeConfigAPI conf; + private Logger logger; + + @Listener + public void onServerStart(GameAboutToStartServerEvent event) { + // Setup Logger + logger = new LoggerWrapper(container.getLogger()); + // Setup Plugin + conf = new SpongeConfigAPI(defaultConfig.getParentFile()); + syncExecutor = game.getScheduler().createSyncExecutor(this); + asyncExecutor = game.getScheduler().createAsyncExecutor(this); + SpongeCommandHandler commandHandler = new SpongeCommandHandler(); + game.getCommandManager().register(this, commandHandler, Arrays.asList("viaversion", "viaver", "vvsponge")); + getLogger().info("ViaVersion " + getPluginVersion() + " is now loaded, injecting!"); + // Init platform + Via.init(ViaManager.builder() + .platform(this) + .commandHandler(commandHandler) + .injector(new SpongeViaInjector()) + .loader(new SpongeViaLoader(this)) + .build()); + + // Inject! + Via.getManager().init(); + } + + @Override + public Logger getLogger() { + return logger; + } + + @Override + public String getPlatformName() { + return "Sponge"; + } + + @Override + public String getPluginVersion() { + return container.getVersion().orElse("Unknown Version"); + } + + @Override + public TaskId runAsync(Runnable runnable) { + asyncExecutor.execute(runnable); + return new SpongeTaskId(null); + } + + @Override + public TaskId runSync(Runnable runnable) { + syncExecutor.execute(runnable); + return new SpongeTaskId(null); + } + + @Override + public TaskId runRepeatingSync(Runnable runnable, Long ticks) { + Long time = ticks * 50L; + return new SpongeTaskId(syncExecutor.scheduleAtFixedRate(runnable, time, time, TimeUnit.MILLISECONDS).getTask()); + } + + @Override + public void cancelTask(TaskId taskId) { + if (taskId == null) return; + if (taskId.getObject() == null) return; + if (taskId instanceof SpongeTaskId) { + ((SpongeTaskId) taskId).getObject().cancel(); + } + } + + @Override + public ViaCommandSender[] getOnlinePlayers() { + ViaCommandSender[] array = new ViaCommandSender[game.getServer().getOnlinePlayers().size()]; + int i = 0; + for (Player player : game.getServer().getOnlinePlayers()) { + array[i++] = new SpongeCommandSender(player); + } + return array; + } + + @Override + public void sendMessage(UUID uuid, String message) { + for (Player player : game.getServer().getOnlinePlayers()) { + if (player.getUniqueId().equals(uuid)) + player.sendMessage(TextSerializers.LEGACY_FORMATTING_CODE.deserialize(message)); + } + } + + @Override + public boolean kickPlayer(UUID uuid, String message) { + for (Player player : game.getServer().getOnlinePlayers()) { + if (player.getUniqueId().equals(uuid)) { + player.kick(TextSerializers.LEGACY_FORMATTING_CODE.deserialize(message)); + return true; + } + } + return false; + } + + @Override + public boolean isPluginEnabled() { + return true; + } + + @Override + public ViaAPI getApi() { + return api; + } + + @Override + public SpongeConfigAPI getConf() { + return conf; + } + + @Override + public ConfigurationProvider getConfigurationProvider() { + return conf; + } + + @Override + public void onReload() { + getLogger().severe("ViaVersion is already loaded, this should work fine. If you get any console errors, try rebooting."); + } + + @Override + public JsonObject getDump() { + JsonObject platformSpecific = new JsonObject(); + + List plugins = new ArrayList<>(); + for (PluginContainer p : game.getPluginManager().getPlugins()) { + plugins.add(new PluginInfo( + true, + p.getName(), + p.getVersion().orElse("Unknown Version"), + p.getInstance().isPresent() ? p.getInstance().get().getClass().getCanonicalName() : "Unknown", + p.getAuthors() + )); + } + platformSpecific.add("plugins", GsonUtil.getGson().toJsonTree(plugins)); + + return platformSpecific; + } +} diff --git a/sponge/src/main/java/us/myles/ViaVersion/sponge/commands/SpongeCommandHandler.java b/sponge/src/main/java/us/myles/ViaVersion/sponge/commands/SpongeCommandHandler.java new file mode 100644 index 000000000..109c56601 --- /dev/null +++ b/sponge/src/main/java/us/myles/ViaVersion/sponge/commands/SpongeCommandHandler.java @@ -0,0 +1,53 @@ +package us.myles.ViaVersion.sponge.commands; + +import org.spongepowered.api.command.CommandCallable; +import org.spongepowered.api.command.CommandException; +import org.spongepowered.api.command.CommandResult; +import org.spongepowered.api.command.CommandSource; +import org.spongepowered.api.text.Text; +import org.spongepowered.api.world.Location; +import org.spongepowered.api.world.World; +import us.myles.ViaVersion.commands.ViaCommandHandler; + +import javax.annotation.Nullable; +import java.util.List; +import java.util.Optional; + +public class SpongeCommandHandler extends ViaCommandHandler implements CommandCallable { + + @Override + public CommandResult process(CommandSource source, String arguments) throws CommandException { + String[] args = arguments.length() > 0 ? arguments.split(" ") : new String[0]; + onCommand(new SpongeCommandSender(source), args); + return CommandResult.success(); + } + + public List getSuggestions(CommandSource commandSource, String s, @Nullable Location location) throws CommandException { + return getSuggestions(commandSource, s); + } + + public List getSuggestions(CommandSource source, String arguments) throws CommandException { + String[] args = arguments.length() > 0 ? arguments.split(" ") : new String[0]; + return onTabComplete(new SpongeCommandSender(source), args); + } + + @Override + public boolean testPermission(CommandSource source) { + return source.hasPermission("viaversion.admin"); + } + + @Override + public Optional getShortDescription(CommandSource source) { + return Optional.of(Text.of("Shows ViaVersion Version and more.")); + } + + @Override + public Optional getHelp(CommandSource source) { + return Optional.empty(); + } + + @Override + public Text getUsage(CommandSource source) { + return Text.of("Usage /viaversion"); + } +} diff --git a/sponge/src/main/java/us/myles/ViaVersion/sponge/commands/SpongeCommandSender.java b/sponge/src/main/java/us/myles/ViaVersion/sponge/commands/SpongeCommandSender.java new file mode 100644 index 000000000..b095c90bf --- /dev/null +++ b/sponge/src/main/java/us/myles/ViaVersion/sponge/commands/SpongeCommandSender.java @@ -0,0 +1,38 @@ +package us.myles.ViaVersion.sponge.commands; + +import lombok.AllArgsConstructor; +import org.spongepowered.api.command.CommandSource; +import org.spongepowered.api.entity.living.player.Player; +import org.spongepowered.api.text.serializer.TextSerializers; +import us.myles.ViaVersion.api.command.ViaCommandSender; + +import java.util.UUID; + +@AllArgsConstructor +public class SpongeCommandSender implements ViaCommandSender { + private CommandSource source; + + @Override + public boolean hasPermission(String permission) { + return source.hasPermission(permission); + } + + @Override + public void sendMessage(String msg) { + source.sendMessage(TextSerializers.LEGACY_FORMATTING_CODE.deserialize(msg)); + } + + @Override + public UUID getUUID() { + if (source instanceof Player) { + return ((Player) source).getUniqueId(); + } else { + return UUID.fromString(getName()); + } + } + + @Override + public String getName() { + return source.getName(); + } +} 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 new file mode 100644 index 000000000..88248d769 --- /dev/null +++ b/sponge/src/main/java/us/myles/ViaVersion/sponge/handlers/SpongeChannelInitializer.java @@ -0,0 +1,48 @@ +package us.myles.ViaVersion.sponge.handlers; + +import io.netty.channel.Channel; +import io.netty.channel.ChannelInitializer; +import io.netty.channel.socket.SocketChannel; +import io.netty.handler.codec.ByteToMessageDecoder; +import io.netty.handler.codec.MessageToByteEncoder; +import us.myles.ViaVersion.api.data.UserConnection; +import us.myles.ViaVersion.api.protocol.ProtocolPipeline; + +import java.lang.reflect.Method; + +public class SpongeChannelInitializer extends ChannelInitializer { + + private final ChannelInitializer original; + private Method method; + + public SpongeChannelInitializer(ChannelInitializer oldInit) { + this.original = oldInit; + try { + this.method = ChannelInitializer.class.getDeclaredMethod("initChannel", Channel.class); + this.method.setAccessible(true); + } catch (NoSuchMethodException e) { + e.printStackTrace(); + } + } + + public ChannelInitializer getOriginal() { + return original; + } + + @Override + protected void initChannel(SocketChannel socketChannel) throws Exception { + UserConnection info = new UserConnection(socketChannel); + // init protocol + new ProtocolPipeline(info); + // Add originals + this.method.invoke(this.original, socketChannel); + // Add our transformers + MessageToByteEncoder encoder = new SpongeEncodeHandler(info, (MessageToByteEncoder) socketChannel.pipeline().get("encoder")); + ByteToMessageDecoder decoder = new SpongeDecodeHandler(info, (ByteToMessageDecoder) socketChannel.pipeline().get("decoder")); + SpongePacketHandler chunkHandler = new SpongePacketHandler(info); + + socketChannel.pipeline().replace("encoder", "encoder", encoder); + socketChannel.pipeline().replace("decoder", "decoder", decoder); + socketChannel.pipeline().addAfter("packet_handler", "viaversion_packet_handler", chunkHandler); + } +} diff --git a/sponge/src/main/java/us/myles/ViaVersion/sponge/handlers/SpongeDecodeHandler.java b/sponge/src/main/java/us/myles/ViaVersion/sponge/handlers/SpongeDecodeHandler.java new file mode 100644 index 000000000..8ee2180db --- /dev/null +++ b/sponge/src/main/java/us/myles/ViaVersion/sponge/handlers/SpongeDecodeHandler.java @@ -0,0 +1,89 @@ +package us.myles.ViaVersion.sponge.handlers; + +import io.netty.buffer.ByteBuf; +import io.netty.channel.ChannelHandlerContext; +import io.netty.handler.codec.ByteToMessageDecoder; +import us.myles.ViaVersion.api.PacketWrapper; +import us.myles.ViaVersion.api.data.UserConnection; +import us.myles.ViaVersion.api.type.Type; +import us.myles.ViaVersion.exception.CancelException; +import us.myles.ViaVersion.packets.Direction; +import us.myles.ViaVersion.protocols.base.ProtocolInfo; +import us.myles.ViaVersion.util.PipelineUtil; + +import java.lang.reflect.InvocationTargetException; +import java.util.List; + +public class SpongeDecodeHandler extends ByteToMessageDecoder { + + private final ByteToMessageDecoder minecraftDecoder; + private final UserConnection info; + + public SpongeDecodeHandler(UserConnection info, ByteToMessageDecoder minecraftDecoder) { + this.info = info; + this.minecraftDecoder = minecraftDecoder; + } + + @Override + protected void decode(ChannelHandlerContext ctx, ByteBuf bytebuf, List list) throws Exception { + // use transformers + if (bytebuf.readableBytes() > 0) { + // Ignore if pending disconnect + if (info.isPendingDisconnect()) { + return; + } + // Increment received + boolean second = info.incrementReceived(); + // Check PPS + if (second) { + if (info.handlePPS()) + return; + } + + if (info.isActive()) { + // Handle ID + int id = Type.VAR_INT.read(bytebuf); + // Transform + ByteBuf newPacket = ctx.alloc().buffer(); + try { + if (id == PacketWrapper.PASSTHROUGH_ID) { + newPacket.writeBytes(bytebuf); + } else { + PacketWrapper wrapper = new PacketWrapper(id, bytebuf, info); + ProtocolInfo protInfo = info.get(ProtocolInfo.class); + protInfo.getPipeline().transform(Direction.INCOMING, protInfo.getState(), wrapper); + wrapper.writeToBuffer(newPacket); + } + + bytebuf.clear(); + bytebuf = newPacket; + } catch (Exception e) { + // Clear Buffer + bytebuf.clear(); + // Release Packet, be free! + newPacket.release(); + throw e; + } + } + + // call minecraft decoder + try { + list.addAll(PipelineUtil.callDecode(this.minecraftDecoder, ctx, bytebuf)); + } catch (InvocationTargetException e) { + if (e.getCause() instanceof Exception) { + throw (Exception) e.getCause(); + } + } finally { + if (info.isActive()) { + bytebuf.release(); + } + } + } + } + + @Override + public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception { + if (PipelineUtil.containsCause(cause, CancelException.class)) return; + super.exceptionCaught(ctx, cause); + } +} diff --git a/sponge/src/main/java/us/myles/ViaVersion/sponge/handlers/SpongeEncodeHandler.java b/sponge/src/main/java/us/myles/ViaVersion/sponge/handlers/SpongeEncodeHandler.java new file mode 100644 index 000000000..8f12b42a4 --- /dev/null +++ b/sponge/src/main/java/us/myles/ViaVersion/sponge/handlers/SpongeEncodeHandler.java @@ -0,0 +1,70 @@ +package us.myles.ViaVersion.sponge.handlers; + +import io.netty.buffer.ByteBuf; +import io.netty.channel.ChannelHandlerContext; +import io.netty.handler.codec.MessageToByteEncoder; +import us.myles.ViaVersion.api.PacketWrapper; +import us.myles.ViaVersion.api.data.UserConnection; +import us.myles.ViaVersion.api.type.Type; +import us.myles.ViaVersion.exception.CancelException; +import us.myles.ViaVersion.packets.Direction; +import us.myles.ViaVersion.protocols.base.ProtocolInfo; +import us.myles.ViaVersion.util.PipelineUtil; + +import java.lang.reflect.InvocationTargetException; + +public class SpongeEncodeHandler extends MessageToByteEncoder { + private final UserConnection info; + private final MessageToByteEncoder minecraftEncoder; + + public SpongeEncodeHandler(UserConnection info, MessageToByteEncoder minecraftEncoder) { + this.info = info; + this.minecraftEncoder = minecraftEncoder; + } + + + @Override + protected void encode(final ChannelHandlerContext ctx, Object o, final ByteBuf bytebuf) throws Exception { + // handle the packet type + if (!(o instanceof ByteBuf)) { + // call minecraft encoder + try { + PipelineUtil.callEncode(this.minecraftEncoder, ctx, o, bytebuf); + } catch (InvocationTargetException e) { + if (e.getCause() instanceof Exception) { + throw (Exception) e.getCause(); + } + } + } + if (bytebuf.readableBytes() == 0) { + throw new CancelException(); + } + // Increment sent + info.incrementSent(); + if (info.isActive()) { + // Handle ID + int id = Type.VAR_INT.read(bytebuf); + // Transform + ByteBuf oldPacket = bytebuf.copy(); + bytebuf.clear(); + + try { + PacketWrapper wrapper = new PacketWrapper(id, oldPacket, info); + ProtocolInfo protInfo = info.get(ProtocolInfo.class); + protInfo.getPipeline().transform(Direction.OUTGOING, protInfo.getState(), wrapper); + wrapper.writeToBuffer(bytebuf); + } catch (Exception e) { + bytebuf.clear(); + throw e; + } finally { + oldPacket.release(); + } + } + } + + @Override + public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception { + if (PipelineUtil.containsCause(cause, CancelException.class)) return; + super.exceptionCaught(ctx, cause); + } +} diff --git a/sponge/src/main/java/us/myles/ViaVersion/sponge/handlers/SpongePacketHandler.java b/sponge/src/main/java/us/myles/ViaVersion/sponge/handlers/SpongePacketHandler.java new file mode 100644 index 000000000..905685c7e --- /dev/null +++ b/sponge/src/main/java/us/myles/ViaVersion/sponge/handlers/SpongePacketHandler.java @@ -0,0 +1,35 @@ +package us.myles.ViaVersion.sponge.handlers; + +import io.netty.buffer.ByteBuf; +import io.netty.channel.ChannelHandlerContext; +import io.netty.handler.codec.MessageToMessageEncoder; +import us.myles.ViaVersion.api.data.UserConnection; +import us.myles.ViaVersion.protocols.base.ProtocolInfo; + +import java.util.List; + +public class SpongePacketHandler extends MessageToMessageEncoder { + private final UserConnection info; + + public SpongePacketHandler(UserConnection info) { + this.info = info; + } + + @Override + protected void encode(ChannelHandlerContext ctx, Object o, List list) throws Exception { + // Split chunks bulk packet up in to single chunks packets before it reached the encoder. + // This will prevent issues with several plugins and other protocol handlers due to the chunks being sent twice. + // It also sends the chunks in the right order possible resolving some issues with added chunks/block/entity data. + if (!(o instanceof ByteBuf)) { + info.setLastPacket(o); + /* This transformer is more for fixing issues which we find hard at packet level :) */ + if (info.isActive()) { + if (info.get(ProtocolInfo.class).getPipeline().filter(o, list)) { + return; + } + } + } + + list.add(o); + } +} diff --git a/sponge/src/main/java/us/myles/ViaVersion/sponge/listeners/ClientLeaveListener.java b/sponge/src/main/java/us/myles/ViaVersion/sponge/listeners/ClientLeaveListener.java new file mode 100644 index 000000000..20ef79688 --- /dev/null +++ b/sponge/src/main/java/us/myles/ViaVersion/sponge/listeners/ClientLeaveListener.java @@ -0,0 +1,12 @@ +package us.myles.ViaVersion.sponge.listeners; + +import org.spongepowered.api.event.Listener; +import org.spongepowered.api.event.network.ClientConnectionEvent; +import us.myles.ViaVersion.api.Via; + +public class ClientLeaveListener { + @Listener + public void onDisconnect(ClientConnectionEvent.Disconnect disconnect) { + Via.getManager().removePortedClient(disconnect.getTargetEntity().getUniqueId()); + } +} diff --git a/sponge/src/main/java/us/myles/ViaVersion/sponge/listeners/UpdateListener.java b/sponge/src/main/java/us/myles/ViaVersion/sponge/listeners/UpdateListener.java new file mode 100644 index 000000000..010570a63 --- /dev/null +++ b/sponge/src/main/java/us/myles/ViaVersion/sponge/listeners/UpdateListener.java @@ -0,0 +1,16 @@ +package us.myles.ViaVersion.sponge.listeners; + +import org.spongepowered.api.event.Listener; +import org.spongepowered.api.event.network.ClientConnectionEvent; +import us.myles.ViaVersion.api.Via; +import us.myles.ViaVersion.update.UpdateUtil; + +public class UpdateListener { + @Listener + public void onJoin(ClientConnectionEvent.Join join) { + if (join.getTargetEntity().hasPermission("viaversion.update") + && Via.getConfig().isCheckForUpdates()) { + UpdateUtil.sendUpdateMessage(join.getTargetEntity().getUniqueId()); + } + } +} diff --git a/sponge/src/main/java/us/myles/ViaVersion/sponge/listeners/ViaSpongeListener.java b/sponge/src/main/java/us/myles/ViaVersion/sponge/listeners/ViaSpongeListener.java new file mode 100644 index 000000000..b000b7ee0 --- /dev/null +++ b/sponge/src/main/java/us/myles/ViaVersion/sponge/listeners/ViaSpongeListener.java @@ -0,0 +1,49 @@ +package us.myles.ViaVersion.sponge.listeners; + +import lombok.Getter; +import org.spongepowered.api.Sponge; +import org.spongepowered.api.entity.living.player.Player; +import us.myles.ViaVersion.SpongePlugin; +import us.myles.ViaVersion.api.Via; +import us.myles.ViaVersion.api.ViaListener; +import us.myles.ViaVersion.api.protocol.Protocol; + +import java.lang.reflect.Field; + +public class ViaSpongeListener extends ViaListener { + private static Field entityIdField; + + @Getter + private final SpongePlugin plugin; + + public ViaSpongeListener(SpongePlugin plugin, Class requiredPipeline) { + super(requiredPipeline); + this.plugin = plugin; + } + + @Override + public void register() { + if (isRegistered()) return; + + Sponge.getEventManager().registerListeners(plugin, this); + setRegistered(true); + } + + // Hey sponge, please create a getEntityId method :'( + protected int getEntityId(Player p) { + try { + if (entityIdField == null) { + entityIdField = p.getClass().getSuperclass().getSuperclass().getSuperclass().getDeclaredField("field_145783_c"); + entityIdField.setAccessible(true); + } + + return entityIdField.getInt(p); + } catch (Exception e) { + Via.getPlatform().getLogger().severe("Could not get the entity id, please report this on our Github"); + e.printStackTrace(); + } + + Via.getPlatform().getLogger().severe("Could not get the entity id, please report this on our Github"); + return -1; + } +} diff --git a/sponge/src/main/java/us/myles/ViaVersion/sponge/listeners/protocol1_9to1_8/BlockListener.java b/sponge/src/main/java/us/myles/ViaVersion/sponge/listeners/protocol1_9to1_8/BlockListener.java new file mode 100644 index 000000000..482554866 --- /dev/null +++ b/sponge/src/main/java/us/myles/ViaVersion/sponge/listeners/protocol1_9to1_8/BlockListener.java @@ -0,0 +1,29 @@ +package us.myles.ViaVersion.sponge.listeners.protocol1_9to1_8; + +import org.spongepowered.api.entity.living.player.Player; +import org.spongepowered.api.event.Listener; +import org.spongepowered.api.event.block.ChangeBlockEvent; +import org.spongepowered.api.event.filter.cause.Root; +import org.spongepowered.api.world.Location; +import us.myles.ViaVersion.SpongePlugin; +import us.myles.ViaVersion.api.minecraft.Position; +import us.myles.ViaVersion.protocols.protocol1_9to1_8.Protocol1_9TO1_8; +import us.myles.ViaVersion.protocols.protocol1_9to1_8.storage.EntityTracker; +import us.myles.ViaVersion.sponge.listeners.ViaSpongeListener; + +public class BlockListener extends ViaSpongeListener { + + public BlockListener(SpongePlugin plugin) { + super(plugin, Protocol1_9TO1_8.class); + } + + @Listener + public void placeBlock(ChangeBlockEvent.Place e, @Root Player player) { + if (isOnPipe(player.getUniqueId())) { + Location loc = e.getTransactions().get(0).getFinal().getLocation().get(); + getUserConnection(player.getUniqueId()) + .get(EntityTracker.class) + .addBlockInteraction(new Position((long) loc.getX(), (long) loc.getY(), (long) loc.getZ())); + } + } +} diff --git a/sponge/src/main/java/us/myles/ViaVersion/sponge/listeners/protocol1_9to1_8/CommandBlockListener.java b/sponge/src/main/java/us/myles/ViaVersion/sponge/listeners/protocol1_9to1_8/CommandBlockListener.java new file mode 100644 index 000000000..0027f17a2 --- /dev/null +++ b/sponge/src/main/java/us/myles/ViaVersion/sponge/listeners/protocol1_9to1_8/CommandBlockListener.java @@ -0,0 +1,156 @@ +package us.myles.ViaVersion.sponge.listeners.protocol1_9to1_8; + +import io.netty.buffer.ByteBuf; +import io.netty.buffer.ByteBufOutputStream; +import io.netty.buffer.Unpooled; +import org.spacehq.opennbt.tag.builtin.ByteTag; +import org.spacehq.opennbt.tag.builtin.CompoundTag; +import org.spongepowered.api.Sponge; +import org.spongepowered.api.block.tileentity.CommandBlock; +import org.spongepowered.api.block.tileentity.TileEntity; +import org.spongepowered.api.entity.living.player.Player; +import org.spongepowered.api.event.Listener; +import org.spongepowered.api.event.block.InteractBlockEvent; +import org.spongepowered.api.event.entity.living.humanoid.player.RespawnPlayerEvent; +import org.spongepowered.api.event.filter.cause.Root; +import org.spongepowered.api.event.network.ClientConnectionEvent; +import org.spongepowered.api.world.Location; +import org.spongepowered.api.world.World; +import us.myles.ViaVersion.SpongePlugin; +import us.myles.ViaVersion.api.PacketWrapper; +import us.myles.ViaVersion.api.data.UserConnection; +import us.myles.ViaVersion.api.minecraft.Position; +import us.myles.ViaVersion.api.type.Type; +import us.myles.ViaVersion.protocols.protocol1_9to1_8.Protocol1_9TO1_8; +import us.myles.ViaVersion.sponge.listeners.ViaSpongeListener; +import us.myles.ViaVersion.util.ReflectionUtil; + +import java.io.DataOutput; +import java.io.DataOutputStream; +import java.lang.reflect.Method; +import java.util.Optional; + +// TODO Change to bytebuf to not use reflection bullsh*t +public class CommandBlockListener extends ViaSpongeListener { + public CommandBlockListener(SpongePlugin plugin) { + super(plugin, Protocol1_9TO1_8.class); + } + + @Listener + public void onJoin(ClientConnectionEvent.Join e) { + sendOp(e.getTargetEntity()); + } + + @Listener + public void onRespawn(RespawnPlayerEvent e) { + if (!isOnPipe(e.getTargetEntity().getUniqueId())) return; + + Sponge.getScheduler().createTaskBuilder().delayTicks(1).execute(new Runnable() { + @Override + public void run() { + sendOp(e.getTargetEntity()); + } + }).submit(getPlugin()); + } + + @Listener + public void onInteract(InteractBlockEvent e, @Root Player player) { + Optional> location = e.getTargetBlock().getLocation(); + if (!location.isPresent()) return; + Optional optTile = location.get().getTileEntity(); + if (!optTile.isPresent()) return; + TileEntity block = optTile.get(); + if (block instanceof CommandBlock) { + CommandBlock cmd = (CommandBlock) block; + try { + sendCommandBlockPacket(cmd, player); + } catch (Exception ex) { + ex.printStackTrace(); + } + } + } + +// TODO Change world +// @EventHandler(priority = EventPriority.MONITOR) +// public void onWorldChange(PlayerChangedWorldEvent e) { +// sendOp(e.getPlayer()); +// } + +// @EventHandler(ignoreCancelled = true) +// public void onInteract(PlayerInteractEvent e) { +// if (e.getAction() == Action.RIGHT_CLICK_BLOCK && isOnPipe(e.getPlayer()) && e.getPlayer().isOp()) { +// try { +// sendCommandBlockPacket(e.getClickedBlock(), e.getPlayer()); +// } catch (Exception ex) { +// ex.printStackTrace(); +// } +// } +// } + + private void sendOp(Player p) { + // TODO Is there an isOp check? + if (p.hasPermission("viaversion.commandblocks") && isOnPipe(p.getUniqueId())) { + try { + PacketWrapper wrapper = new PacketWrapper(0x1B, null, getUserConnection(p.getUniqueId())); // Entity status + + wrapper.write(Type.INT, getEntityId(p)); // Entity ID + wrapper.write(Type.BYTE, (byte) 26); //Hardcoded op permission level + + wrapper.send(Protocol1_9TO1_8.class); + } catch (Exception e) { + e.printStackTrace(); + } + } + } + + private void sendCommandBlockPacket(CommandBlock b, Player player) throws Exception { + Method m = b.getClass().getDeclaredMethod("func_145844_m"); + m.setAccessible(true); + + Object updatePacket = m.invoke(b); + + PacketWrapper wrapper = generatePacket(updatePacket, getUserConnection(player.getUniqueId())); + wrapper.send(Protocol1_9TO1_8.class); + } + + // + private PacketWrapper generatePacket(Object updatePacket, UserConnection usr) throws Exception { + PacketWrapper wrapper = new PacketWrapper(0x09, null, usr); // Update block entity + + long[] pos = getPosition(ReflectionUtil.get(updatePacket, "field_179824_a", Class.forName("net.minecraft.util.BlockPos"))); + + wrapper.write(Type.POSITION, new Position(pos[0], pos[1], pos[2])); //Block position + wrapper.write(Type.BYTE, (byte) 2); // Action id always 2 + + CompoundTag nbt = getNBT(ReflectionUtil.get(updatePacket, "field_148860_e", Class.forName("net.minecraft.nbt.NBTTagCompound"))); + if (nbt == null) { + wrapper.write(Type.BYTE, (byte) 0); //If nbt is null. Use 0 as nbt + return wrapper; + } + nbt.put(new ByteTag("powered", (byte) 0)); + nbt.put(new ByteTag("auto", (byte) 0)); + nbt.put(new ByteTag("conditionMet", (byte) 0)); + + wrapper.write(Type.NBT, nbt); // NBT TAG + return wrapper; + } + + private long[] getPosition(Object obj) throws ClassNotFoundException, NoSuchFieldException, IllegalAccessException { + return new long[]{ + (long) ReflectionUtil.getSuper(obj, "field_177962_a", int.class), //X + (long) ReflectionUtil.getSuper(obj, "field_177960_b", int.class), //Y + (long) ReflectionUtil.getSuper(obj, "field_177961_c", int.class) //Z + }; + } + + private CompoundTag getNBT(Object obj) throws Exception { + ByteBuf buf = Unpooled.buffer(); + Method m = Class.forName("net.minecraft.nbt.CompressedStreamTools").getMethod("func_74800_a", Class.forName("net.minecraft.nbt.NBTTagCompound"), DataOutput.class); + m.invoke(null, obj, new DataOutputStream(new ByteBufOutputStream(buf))); + try { + return Type.NBT.read(buf); + } finally { + buf.release(); + } + } +} diff --git a/sponge/src/main/java/us/myles/ViaVersion/sponge/listeners/protocol1_9to1_8/DeathListener.java b/sponge/src/main/java/us/myles/ViaVersion/sponge/listeners/protocol1_9to1_8/DeathListener.java new file mode 100644 index 000000000..eece82ce0 --- /dev/null +++ b/sponge/src/main/java/us/myles/ViaVersion/sponge/listeners/protocol1_9to1_8/DeathListener.java @@ -0,0 +1,65 @@ +package us.myles.ViaVersion.sponge.listeners.protocol1_9to1_8; + +import org.spongepowered.api.entity.living.player.Player; +import org.spongepowered.api.event.Listener; +import org.spongepowered.api.event.Order; +import org.spongepowered.api.event.entity.DestructEntityEvent; +import org.spongepowered.api.world.World; +import us.myles.ViaVersion.SpongePlugin; +import us.myles.ViaVersion.api.PacketWrapper; +import us.myles.ViaVersion.api.Via; +import us.myles.ViaVersion.api.type.Type; +import us.myles.ViaVersion.protocols.protocol1_9to1_8.Protocol1_9TO1_8; +import us.myles.ViaVersion.sponge.listeners.ViaSpongeListener; + +import java.util.Optional; + +public class DeathListener extends ViaSpongeListener { + public DeathListener(SpongePlugin plugin) { + super(plugin, Protocol1_9TO1_8.class); + } + + @Listener(order = Order.LAST) + public void onDeath(DestructEntityEvent.Death e) { + if (!(e.getTargetEntity() instanceof Player)) + return; + + Player p = (Player) e.getTargetEntity(); + if (isOnPipe(p.getUniqueId()) && Via.getConfig().isShowNewDeathMessages() && checkGamerule(p.getWorld())) { + sendPacket(p, e.getMessage().toPlain()); + } + } + + public boolean checkGamerule(World w) { + Optional gamerule = w.getGameRule("showDeathMessages"); + + if (gamerule.isPresent()) { + try { + return Boolean.parseBoolean(gamerule.get()); + } catch (Exception e) { + return false; + } + } + return false; + } + + private void sendPacket(final Player p, final String msg) { + Via.getPlatform().runSync(new Runnable() { + @Override + public void run() { + PacketWrapper wrapper = new PacketWrapper(0x2C, null, getUserConnection(p.getUniqueId())); + try { + int entityId = getEntityId(p); + wrapper.write(Type.VAR_INT, 2); // Event - Entity dead + wrapper.write(Type.VAR_INT, entityId); // Player ID + wrapper.write(Type.INT, entityId); // Entity ID + Protocol1_9TO1_8.FIX_JSON.write(wrapper, msg); // Message + + wrapper.send(Protocol1_9TO1_8.class); + } catch (Exception e) { + e.printStackTrace(); + } + } + }); + } +} diff --git a/sponge/src/main/java/us/myles/ViaVersion/sponge/listeners/protocol1_9to1_8/HandItemCache.java b/sponge/src/main/java/us/myles/ViaVersion/sponge/listeners/protocol1_9to1_8/HandItemCache.java new file mode 100644 index 000000000..e2d61fcaa --- /dev/null +++ b/sponge/src/main/java/us/myles/ViaVersion/sponge/listeners/protocol1_9to1_8/HandItemCache.java @@ -0,0 +1,90 @@ +package us.myles.ViaVersion.sponge.listeners.protocol1_9to1_8; + +import org.spongepowered.api.Sponge; +import org.spongepowered.api.entity.living.player.Player; +import org.spongepowered.api.item.inventory.ItemStack; +import us.myles.ViaVersion.api.minecraft.item.Item; +import us.myles.ViaVersion.sponge.listeners.protocol1_9to1_8.sponge4.Sponge4ItemGrabber; +import us.myles.ViaVersion.sponge.listeners.protocol1_9to1_8.sponge5.Sponge5ItemGrabber; + +import java.lang.reflect.Field; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; +import java.util.ArrayList; +import java.util.List; +import java.util.UUID; +import java.util.concurrent.ConcurrentHashMap; + +public class HandItemCache implements Runnable { + public static boolean CACHE = false; + private static ConcurrentHashMap handCache = new ConcurrentHashMap<>(); + private static Field GET_DAMAGE; + private static Method GET_ID; + private static ItemGrabber grabber; + + static { + try { + Class.forName("org.spongepowered.api.event.entity.DisplaceEntityEvent"); + grabber = new Sponge4ItemGrabber(); + } catch (ClassNotFoundException e) { + grabber = new Sponge5ItemGrabber(); + } + } + + public static Item getHandItem(UUID player) { + if (!handCache.containsKey(player)) + return null; + return handCache.get(player); + } + + @Override + public void run() { + List players = new ArrayList<>(handCache.keySet()); + + for (Player p : Sponge.getServer().getOnlinePlayers()) { + handCache.put(p.getUniqueId(), convert(grabber.getItem(p))); + players.remove(p.getUniqueId()); + } + // Remove offline players + for (UUID uuid : players) { + handCache.remove(uuid); + } + } + + public static Item convert(ItemStack itemInHand) { + if (itemInHand == null) return new Item((short) 0, (byte) 0, (short) 0, null); + if (GET_DAMAGE == null) { + try { + GET_DAMAGE = itemInHand.getClass().getDeclaredField("field_77991_e"); + GET_DAMAGE.setAccessible(true); + } catch (NoSuchFieldException e) { + e.printStackTrace(); + } + } + if (GET_ID == null) { + try { + GET_ID = Class.forName("net.minecraft.item.Item").getDeclaredMethod("func_150891_b", Class.forName("net.minecraft.item.Item")); + } catch (NoSuchMethodException e) { + e.printStackTrace(); + } catch (ClassNotFoundException e) { + e.printStackTrace(); + } + } + int id = 0; + try { + id = (int) GET_ID.invoke(null, itemInHand.getItem()); + } catch (IllegalAccessException e) { + e.printStackTrace(); + } catch (InvocationTargetException e) { + e.printStackTrace(); + } + int damage = 0; + try { + damage = (int) GET_DAMAGE.get(itemInHand); + } catch (IllegalAccessException e) { + e.printStackTrace(); + } + return new Item((short) id, (byte) itemInHand.getQuantity(), (short) damage, null); + } +} + diff --git a/sponge/src/main/java/us/myles/ViaVersion/sponge/listeners/protocol1_9to1_8/sponge5/Sponge5ArmorListener.java b/sponge/src/main/java/us/myles/ViaVersion/sponge/listeners/protocol1_9to1_8/sponge5/Sponge5ArmorListener.java new file mode 100644 index 000000000..6052e86b5 --- /dev/null +++ b/sponge/src/main/java/us/myles/ViaVersion/sponge/listeners/protocol1_9to1_8/sponge5/Sponge5ArmorListener.java @@ -0,0 +1,114 @@ +package us.myles.ViaVersion.sponge.listeners.protocol1_9to1_8.sponge5; + +import org.spongepowered.api.data.type.HandTypes; +import org.spongepowered.api.entity.living.player.Player; +import org.spongepowered.api.event.Listener; +import org.spongepowered.api.event.action.InteractEvent; +import org.spongepowered.api.event.entity.MoveEntityEvent; +import org.spongepowered.api.event.entity.living.humanoid.player.RespawnPlayerEvent; +import org.spongepowered.api.event.filter.cause.Root; +import org.spongepowered.api.event.item.inventory.ClickInventoryEvent; +import org.spongepowered.api.event.network.ClientConnectionEvent; +import org.spongepowered.api.item.inventory.ItemStack; +import org.spongepowered.api.item.inventory.transaction.SlotTransaction; +import us.myles.ViaVersion.SpongePlugin; +import us.myles.ViaVersion.api.PacketWrapper; +import us.myles.ViaVersion.api.Via; +import us.myles.ViaVersion.api.type.Type; +import us.myles.ViaVersion.protocols.protocol1_9to1_8.ArmorType; +import us.myles.ViaVersion.protocols.protocol1_9to1_8.Protocol1_9TO1_8; +import us.myles.ViaVersion.sponge.listeners.ViaSpongeListener; + +import java.util.Optional; +import java.util.UUID; + +public class Sponge5ArmorListener extends ViaSpongeListener { + private static final UUID ARMOR_ATTRIBUTE = UUID.fromString("2AD3F246-FEE1-4E67-B886-69FD380BB150"); + + public Sponge5ArmorListener(SpongePlugin plugin) { + super(plugin, Protocol1_9TO1_8.class); + } + + // + public void sendArmorUpdate(Player player) { + // Ensure that the player is on our pipe + if (!isOnPipe(player.getUniqueId())) return; + + + int armor = 0; + armor += calculate(player.getHelmet()); + armor += calculate(player.getChestplate()); + armor += calculate(player.getLeggings()); + armor += calculate(player.getBoots()); + + PacketWrapper wrapper = new PacketWrapper(0x4B, null, getUserConnection(player.getUniqueId())); + try { + wrapper.write(Type.VAR_INT, getEntityId(player)); // Player ID + wrapper.write(Type.INT, 1); // only 1 property + wrapper.write(Type.STRING, "generic.armor"); + wrapper.write(Type.DOUBLE, 0D); //default 0 armor + wrapper.write(Type.VAR_INT, 1); // 1 modifier + wrapper.write(Type.UUID, ARMOR_ATTRIBUTE); // armor modifier uuid + wrapper.write(Type.DOUBLE, (double) armor); // the modifier value + wrapper.write(Type.BYTE, (byte) 0);// the modifier operation, 0 is add number + + wrapper.send(Protocol1_9TO1_8.class); + } catch (Exception e) { + e.printStackTrace(); + } + } + + private int calculate(Optional itemStack) { + if (itemStack.isPresent()) + return ArmorType.findByType(itemStack.get().getItem().getType().getId()).getArmorPoints(); + + return 0; + } + + @Listener + public void onInventoryClick(ClickInventoryEvent e, @Root Player player) { + for (SlotTransaction transaction : e.getTransactions()) { + if (ArmorType.isArmor(transaction.getFinal().getType().getId()) || + ArmorType.isArmor(e.getCursorTransaction().getFinal().getType().getId())) { + sendDelayedArmorUpdate(player); + break; + } + } + } + + @Listener + public void onInteract(InteractEvent event, @Root Player player) { + if (player.getItemInHand(HandTypes.MAIN_HAND).isPresent()) { + if (ArmorType.isArmor(player.getItemInHand(HandTypes.MAIN_HAND).get().getItem().getId())) + sendDelayedArmorUpdate(player); + } + } + + @Listener + public void onJoin(ClientConnectionEvent.Join e) { + sendArmorUpdate(e.getTargetEntity()); + } + + @Listener + public void onRespawn(RespawnPlayerEvent e) { + sendDelayedArmorUpdate(e.getTargetEntity()); + } + + @Listener + public void onWorldChange(MoveEntityEvent.Teleport e) { + if (!(e.getTargetEntity() instanceof Player)) return; + if (!e.getFromTransform().getExtent().getUniqueId().equals(e.getToTransform().getExtent().getUniqueId())) { + sendArmorUpdate((Player) e.getTargetEntity()); + } + } + + public void sendDelayedArmorUpdate(final Player player) { + if (!isOnPipe(player.getUniqueId())) return; // Don't start a task if the player is not on the pipe + Via.getPlatform().runSync(new Runnable() { + @Override + public void run() { + sendArmorUpdate(player); + } + }); + } +} diff --git a/sponge/src/main/java/us/myles/ViaVersion/sponge/listeners/protocol1_9to1_8/sponge5/Sponge5ItemGrabber.java b/sponge/src/main/java/us/myles/ViaVersion/sponge/listeners/protocol1_9to1_8/sponge5/Sponge5ItemGrabber.java new file mode 100644 index 000000000..f9128ec86 --- /dev/null +++ b/sponge/src/main/java/us/myles/ViaVersion/sponge/listeners/protocol1_9to1_8/sponge5/Sponge5ItemGrabber.java @@ -0,0 +1,13 @@ +package us.myles.ViaVersion.sponge.listeners.protocol1_9to1_8.sponge5; + +import org.spongepowered.api.data.type.HandTypes; +import org.spongepowered.api.entity.living.player.Player; +import org.spongepowered.api.item.inventory.ItemStack; +import us.myles.ViaVersion.sponge.listeners.protocol1_9to1_8.ItemGrabber; + +public class Sponge5ItemGrabber implements ItemGrabber { + @Override + public ItemStack getItem(Player player) { + return player.getItemInHand(HandTypes.MAIN_HAND).orElse(null); + } +} diff --git a/sponge/src/main/java/us/myles/ViaVersion/sponge/platform/SpongeBossBar.java b/sponge/src/main/java/us/myles/ViaVersion/sponge/platform/SpongeBossBar.java new file mode 100644 index 000000000..df03b6d31 --- /dev/null +++ b/sponge/src/main/java/us/myles/ViaVersion/sponge/platform/SpongeBossBar.java @@ -0,0 +1,35 @@ +package us.myles.ViaVersion.sponge.platform; + +import lombok.Getter; +import org.spongepowered.api.entity.living.player.Player; +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.boss.CommonBoss; + +@Getter +public class SpongeBossBar extends CommonBoss { + + public SpongeBossBar(String title, float health, BossColor color, BossStyle style) { + super(title, health, color, style); + } + + @Override + public BossBar addPlayer(Player player) { + addPlayer(player.getUniqueId()); + return this; + } + + @Override + public BossBar addPlayers(Player... players) { + for (Player p : players) + addPlayer(p); + return this; + } + + @Override + public BossBar removePlayer(Player player) { + removePlayer(player.getUniqueId()); + return this; + } +} 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 new file mode 100644 index 000000000..b7e4df980 --- /dev/null +++ b/sponge/src/main/java/us/myles/ViaVersion/sponge/platform/SpongeConfigAPI.java @@ -0,0 +1,176 @@ +package us.myles.ViaVersion.sponge.platform; + +import us.myles.ViaVersion.api.ViaVersionConfig; +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", "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; + } + + public boolean isCheckForUpdates() { + return getBoolean("checkforupdates", true); + } + + @Override + public boolean isPreventCollision() { + return getBoolean("prevent-collision", true); + } + + @Override + public boolean isNewEffectIndicator() { + return getBoolean("use-new-effect-indicator", true); + } + + @Override + public boolean isShowNewDeathMessages() { + return getBoolean("use-new-deathmessages", true); + } + + @Override + public boolean isSuppressMetadataErrors() { + return getBoolean("suppress-metadata-errors", false); + } + + @Override + public boolean isShieldBlocking() { + return getBoolean("shield-blocking", true); + } + + @Override + public boolean isHologramPatch() { + return getBoolean("hologram-patch", false); + } + + @Override + public boolean isBossbarPatch() { + return getBoolean("bossbar-patch", true); + } + + @Override + public boolean isBossbarAntiflicker() { + return getBoolean("bossbar-anti-flicker", false); + } + + @Override + public boolean isUnknownEntitiesSuppressed() { + return false; + } + + @Override + public double getHologramYOffset() { + return getDouble("hologram-y", -0.96D); + } + + @Override + public boolean isBlockBreakPatch() { + return false; + } + + @Override + public int getMaxPPS() { + return getInt("max-pps", 800); + } + + @Override + public String getMaxPPSKickMessage() { + return getString("max-pps-kick-msg", "Sending packets too fast? lag?"); + } + + @Override + public int getTrackingPeriod() { + return getInt("tracking-period", 6); + } + + @Override + public int getWarningPPS() { + return getInt("tracking-warning-pps", 120); + } + + @Override + public int getMaxWarnings() { + return getInt("tracking-max-warnings", 3); + } + + @Override + public String getMaxWarningsKickMessage() { + return getString("tracking-max-kick-msg", "You are sending too many packets, :("); + } + + @Override + public boolean isAntiXRay() { + return false; + } + + @Override + public boolean isSendSupportedVersions() { + return getBoolean("send-supported-versions", false); + } + + @Override + public boolean isStimulatePlayerTick() { + return getBoolean("simulate-pt", true); + } + + @Override + public boolean isItemCache() { + return getBoolean("item-cache", true); + } + + @Override + public boolean isNMSPlayerTicking() { + return getBoolean("nms-player-ticking", true); + } + + @Override + public boolean isReplacePistons() { + return getBoolean("replace-pistons", false); + } + + @Override + public int getPistonReplacementId() { + return getInt("replacement-piston-id", 0); + } + + public boolean isAutoTeam() { + // Collision has to be enabled first + return isPreventCollision() && getBoolean("auto-team", true); + } + + @Override + public boolean isForceJsonTransform() { + return getBoolean("force-json-transform", false); + } + + @Override + public List getBlockedProtocols() { + return getIntegerList("block-protocols"); + } + + @Override + public String getBlockedDisconnectMsg() { + return getString("block-disconnect-msg", "You are using an unsupported Minecraft version!"); + } + + @Override + public String getReloadDisconnectMsg() { + return getString("reload-disconnect-msg", "Server reload, please rejoin!"); + } +} diff --git a/sponge/src/main/java/us/myles/ViaVersion/sponge/platform/SpongeTaskId.java b/sponge/src/main/java/us/myles/ViaVersion/sponge/platform/SpongeTaskId.java new file mode 100644 index 000000000..879fa041c --- /dev/null +++ b/sponge/src/main/java/us/myles/ViaVersion/sponge/platform/SpongeTaskId.java @@ -0,0 +1,12 @@ +package us.myles.ViaVersion.sponge.platform; + +import lombok.AllArgsConstructor; +import lombok.Getter; +import org.spongepowered.api.scheduler.Task; +import us.myles.ViaVersion.api.platform.TaskId; + +@Getter +@AllArgsConstructor +public class SpongeTaskId implements TaskId { + private Task object; +} diff --git a/sponge/src/main/java/us/myles/ViaVersion/sponge/platform/SpongeViaAPI.java b/sponge/src/main/java/us/myles/ViaVersion/sponge/platform/SpongeViaAPI.java new file mode 100644 index 000000000..c23452b80 --- /dev/null +++ b/sponge/src/main/java/us/myles/ViaVersion/sponge/platform/SpongeViaAPI.java @@ -0,0 +1,79 @@ +package us.myles.ViaVersion.sponge.platform; + +import io.netty.buffer.ByteBuf; +import lombok.NonNull; +import org.spongepowered.api.entity.living.player.Player; +import us.myles.ViaVersion.api.Via; +import us.myles.ViaVersion.api.ViaAPI; +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.data.UserConnection; +import us.myles.ViaVersion.api.protocol.ProtocolRegistry; +import us.myles.ViaVersion.protocols.base.ProtocolInfo; + +import java.util.Map; +import java.util.SortedSet; +import java.util.TreeSet; +import java.util.UUID; + +public class SpongeViaAPI implements ViaAPI { + + @Override + public int getPlayerVersion(@NonNull Player player) { + if (!isPorted(player.getUniqueId())) + return ProtocolRegistry.SERVER_PROTOCOL; + return getPortedPlayers().get(player.getUniqueId()).get(ProtocolInfo.class).getProtocolVersion(); + } + + @Override + public int getPlayerVersion(@NonNull UUID uuid) { + if (!isPorted(uuid)) + return ProtocolRegistry.SERVER_PROTOCOL; + return getPortedPlayers().get(uuid).get(ProtocolInfo.class).getProtocolVersion(); + } + + @Override + public boolean isPorted(UUID playerUUID) { + return getPortedPlayers().containsKey(playerUUID); + } + + @Override + public String getVersion() { + return Via.getPlatform().getPluginVersion(); + } + + @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 SpongeBossBar(title, 1F, color, style); + } + + @Override + public BossBar createBossBar(String title, float health, BossColor color, BossStyle style) { + return new SpongeBossBar(title, health, color, style); + } + + @Override + public SortedSet getSupportedVersions() { + SortedSet outputSet = new TreeSet<>(ProtocolRegistry.getSupportedVersions()); + outputSet.removeAll(Via.getPlatform().getConf().getBlockedProtocols()); + + return outputSet; + } + + public Map getPortedPlayers() { + return Via.getManager().getPortedPlayers(); + } +} 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 new file mode 100644 index 000000000..3e7a5545a --- /dev/null +++ b/sponge/src/main/java/us/myles/ViaVersion/sponge/platform/SpongeViaInjector.java @@ -0,0 +1,161 @@ +package us.myles.ViaVersion.sponge.platform; + +import io.netty.channel.ChannelFuture; +import io.netty.channel.ChannelHandler; +import io.netty.channel.ChannelInitializer; +import io.netty.channel.socket.SocketChannel; +import org.spongepowered.api.MinecraftVersion; +import org.spongepowered.api.Sponge; +import us.myles.ViaVersion.api.Pair; +import us.myles.ViaVersion.api.Via; +import us.myles.ViaVersion.api.platform.ViaInjector; +import us.myles.ViaVersion.sponge.handlers.SpongeChannelInitializer; +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 SpongeViaInjector implements ViaInjector { + private List injectedFutures = new ArrayList<>(); + private List> injectedLists = new ArrayList<>(); + + @Override + public void inject() throws Exception { + try { + Object connection = getServerConnection(); + if (connection == null) { + throw new Exception("We failed to find the core component 'ServerConnection', please file an issue on our GitHub."); + } + 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) { + try { + injectChannelFuture((ChannelFuture) o); + } catch (Exception e) { + e.printStackTrace(); + } + } + } + } + }; + 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) { + Via.getPlatform().getLogger().severe("Unable to inject ViaVersion, please post these details on our GitHub and ensure you're using a compatible server version."); + throw e; + } + } + + private void injectChannelFuture(ChannelFuture future) throws Exception { + try { + ChannelHandler bootstrapAcceptor = future.channel().pipeline().first(); + try { + ChannelInitializer oldInit = ReflectionUtil.get(bootstrapAcceptor, "childHandler", ChannelInitializer.class); + ChannelInitializer newInit = new SpongeChannelInitializer(oldInit); + + ReflectionUtil.set(bootstrapAcceptor, "childHandler", newInit); + injectedFutures.add(future); + } catch (NoSuchFieldException e) { + throw new Exception("Unable to find core component 'childHandler', please check your plugins. issue: " + bootstrapAcceptor.getClass().getName()); + + } + } catch (Exception e) { + Via.getPlatform().getLogger().severe("We failed to inject ViaVersion, have you got late-bind enabled with something else?"); + throw e; + } + } + + @Override + public void uninject() { + // TODO: Uninject from players currently online + for (ChannelFuture future : injectedFutures) { + ChannelHandler bootstrapAcceptor = future.channel().pipeline().first(); + try { + ChannelInitializer oldInit = ReflectionUtil.get(bootstrapAcceptor, "childHandler", ChannelInitializer.class); + if (oldInit instanceof SpongeChannelInitializer) { + ReflectionUtil.set(bootstrapAcceptor, "childHandler", ((SpongeChannelInitializer) 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(); + } + + public static Object getServer() throws Exception { + return Sponge.getServer(); + } + + @Override + public int getServerProtocolVersion() throws Exception { + MinecraftVersion mcv = Sponge.getPlatform().getMinecraftVersion(); + try { + return (int) mcv.getClass().getDeclaredMethod("getProtocol").invoke(mcv); + } catch (Exception e) { + throw new Exception("Failed to get server protocol", e); + } + } + + @Override + public String getEncoderName() { + return "encoder"; + } + + @Override + public String getDecoderName() { + return "decoder"; + } + + public static Object getServerConnection() throws Exception { + Class serverClazz = Class.forName("net.minecraft.server.MinecraftServer"); + Object server = getServer(); + Object connection = null; + for (Method m : serverClazz.getDeclaredMethods()) { + if (m.getReturnType() != null) { + if (m.getReturnType().getSimpleName().equals("NetworkSystem")) { + if (m.getParameterTypes().length == 0) { + connection = m.invoke(server); + } + } + } + } + return connection; + } + +} 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 new file mode 100644 index 000000000..ebe1c398f --- /dev/null +++ b/sponge/src/main/java/us/myles/ViaVersion/sponge/platform/SpongeViaLoader.java @@ -0,0 +1,65 @@ +package us.myles.ViaVersion.sponge.platform; + +import lombok.AllArgsConstructor; +import org.spongepowered.api.Sponge; +import us.myles.ViaVersion.SpongePlugin; +import us.myles.ViaVersion.api.Via; +import us.myles.ViaVersion.api.data.UserConnection; +import us.myles.ViaVersion.api.minecraft.item.Item; +import us.myles.ViaVersion.api.platform.ViaPlatformLoader; +import us.myles.ViaVersion.protocols.base.ProtocolInfo; +import us.myles.ViaVersion.protocols.protocol1_9to1_8.providers.BulkChunkTranslatorProvider; +import us.myles.ViaVersion.protocols.protocol1_9to1_8.providers.HandItemProvider; +import us.myles.ViaVersion.protocols.protocol1_9to1_8.providers.MovementTransmitterProvider; +import us.myles.ViaVersion.sponge.listeners.ClientLeaveListener; +import us.myles.ViaVersion.sponge.listeners.UpdateListener; +import us.myles.ViaVersion.sponge.listeners.protocol1_9to1_8.BlockListener; +import us.myles.ViaVersion.sponge.listeners.protocol1_9to1_8.CommandBlockListener; +import us.myles.ViaVersion.sponge.listeners.protocol1_9to1_8.DeathListener; +import us.myles.ViaVersion.sponge.listeners.protocol1_9to1_8.HandItemCache; +import us.myles.ViaVersion.sponge.listeners.protocol1_9to1_8.sponge4.Sponge4ArmorListener; +import us.myles.ViaVersion.sponge.listeners.protocol1_9to1_8.sponge5.Sponge5ArmorListener; +import us.myles.ViaVersion.sponge.providers.SpongeViaBulkChunkTranslator; +import us.myles.ViaVersion.sponge.providers.SpongeViaMovementTransmitter; + +@AllArgsConstructor +public class SpongeViaLoader implements ViaPlatformLoader { + private SpongePlugin plugin; + + @Override + public void load() { + // Update Listener + Sponge.getEventManager().registerListeners(plugin, new UpdateListener()); + /* Base Protocol */ + Sponge.getEventManager().registerListeners(plugin, new ClientLeaveListener()); + /* 1.9 client to 1.8 server */ + try { + Class.forName("org.spongepowered.api.event.entity.DisplaceEntityEvent"); + new Sponge4ArmorListener().register(); + } catch (ClassNotFoundException e) { + new Sponge5ArmorListener(plugin).register(); + } + new CommandBlockListener(plugin).register(); + new DeathListener(plugin).register(); + new BlockListener(plugin).register(); + + if (plugin.getConf().isItemCache()) { + Via.getPlatform().runRepeatingSync(new HandItemCache(), 2L); // Updates player's items :) + HandItemCache.CACHE = true; + } + + /* Providers */ + Via.getManager().getProviders().use(BulkChunkTranslatorProvider.class, new SpongeViaBulkChunkTranslator()); + Via.getManager().getProviders().use(MovementTransmitterProvider.class, new SpongeViaMovementTransmitter()); + Via.getManager().getProviders().use(HandItemProvider.class, new HandItemProvider() { + @Override + public Item getHandItem(final UserConnection info) { + if (HandItemCache.CACHE) { + return HandItemCache.getHandItem(info.get(ProtocolInfo.class).getUuid()); + } else { + return super.getHandItem(info); // TODO: On API Docs write about this + } + } + }); + } +} diff --git a/sponge/src/main/java/us/myles/ViaVersion/sponge/providers/SpongeViaBulkChunkTranslator.java b/sponge/src/main/java/us/myles/ViaVersion/sponge/providers/SpongeViaBulkChunkTranslator.java new file mode 100644 index 000000000..04bc61172 --- /dev/null +++ b/sponge/src/main/java/us/myles/ViaVersion/sponge/providers/SpongeViaBulkChunkTranslator.java @@ -0,0 +1,63 @@ +package us.myles.ViaVersion.sponge.providers; + +import com.google.common.collect.Lists; +import us.myles.ViaVersion.api.Via; +import us.myles.ViaVersion.protocols.protocol1_9to1_8.providers.BulkChunkTranslatorProvider; +import us.myles.ViaVersion.protocols.protocol1_9to1_8.storage.ClientChunks; +import us.myles.ViaVersion.util.ReflectionUtil; + +import java.util.List; +import java.util.logging.Level; + +public class SpongeViaBulkChunkTranslator extends BulkChunkTranslatorProvider { + // Reflection + private static ReflectionUtil.ClassReflection mapChunkBulkRef; + private static ReflectionUtil.ClassReflection mapChunkRef; + + static { + + try { + mapChunkBulkRef = new ReflectionUtil.ClassReflection(Class.forName("net.minecraft.network.play.server.S26PacketMapChunkBulk")); + mapChunkRef = new ReflectionUtil.ClassReflection(Class.forName("net.minecraft.network.play.server.S21PacketChunkData")); + } catch (ClassNotFoundException e) { + // Ignore as server is probably 1.9+ + } catch (Exception e) { + Via.getPlatform().getLogger().log(Level.WARNING, "Failed to initialise chunks reflection", e); + } + } + + @Override + public List transformMapChunkBulk(Object packet, ClientChunks clientChunks) { + List list = Lists.newArrayList(); + try { + int[] xcoords = mapChunkBulkRef.getFieldValue("field_149266_a", packet, int[].class); + int[] zcoords = mapChunkBulkRef.getFieldValue("field_149264_b", packet, int[].class); + Object[] chunkMaps = mapChunkBulkRef.getFieldValue("field_179755_c", packet, Object[].class); + for (int i = 0; i < chunkMaps.length; i++) { + int x = xcoords[i]; + int z = zcoords[i]; + Object chunkMap = chunkMaps[i]; + Object chunkPacket = mapChunkRef.newInstance(); + mapChunkRef.setFieldValue("field_149284_a", chunkPacket, x); + mapChunkRef.setFieldValue("field_149282_b", chunkPacket, z); + mapChunkRef.setFieldValue("field_179758_c", chunkPacket, chunkMap); + mapChunkRef.setFieldValue("field_149279_g", chunkPacket, true); // Chunk bulk chunks are always ground-up + clientChunks.getBulkChunks().add(ClientChunks.toLong(x, z)); // Store for later + list.add(chunkPacket); + } + } catch (Exception e) { + Via.getPlatform().getLogger().log(Level.WARNING, "Failed to transform chunks bulk", e); + } + return list; + } + + @Override + public boolean isFiltered(Class packetClass) { + return packetClass.getName().endsWith("S26PacketMapChunkBulk"); + } + + @Override + public boolean isPacketLevel() { + return false; + } +} diff --git a/sponge/src/main/java/us/myles/ViaVersion/sponge/providers/SpongeViaMovementTransmitter.java b/sponge/src/main/java/us/myles/ViaVersion/sponge/providers/SpongeViaMovementTransmitter.java new file mode 100644 index 000000000..346b5f08b --- /dev/null +++ b/sponge/src/main/java/us/myles/ViaVersion/sponge/providers/SpongeViaMovementTransmitter.java @@ -0,0 +1,45 @@ +package us.myles.ViaVersion.sponge.providers; + +import us.myles.ViaVersion.protocols.protocol1_9to1_8.providers.MovementTransmitterProvider; + +import java.lang.reflect.Field; + +public class SpongeViaMovementTransmitter extends MovementTransmitterProvider { + // Used for packet mode + private Object idlePacket; + private Object idlePacket2; + + public SpongeViaMovementTransmitter() { + Class idlePacketClass; + try { + idlePacketClass = Class.forName("net.minecraft.network.play.client.C03PacketPlayer"); + } catch (ClassNotFoundException e) { + return; // We'll hope this is 1.9.4+ + } + try { + idlePacket = idlePacketClass.newInstance(); + idlePacket2 = idlePacketClass.newInstance(); + + Field flying = idlePacketClass.getDeclaredField("field_149474_g"); + flying.setAccessible(true); + + flying.set(idlePacket2, true); + } catch (NoSuchFieldException | InstantiationException | IllegalArgumentException | IllegalAccessException e) { + throw new RuntimeException("Couldn't make player idle packet, help!", e); + } + } + + @Override + public Object getFlyingPacket() { + if (idlePacket == null) + throw new NullPointerException("Could not locate flying packet"); + return idlePacket2; + } + + @Override + public Object getGroundPacket() { + if (idlePacket == null) + throw new NullPointerException("Could not locate flying packet"); + return idlePacket; + } +} diff --git a/sponge/src/main/java/us/myles/ViaVersion/sponge/util/LoggerWrapper.java b/sponge/src/main/java/us/myles/ViaVersion/sponge/util/LoggerWrapper.java new file mode 100644 index 000000000..8c69bf2d4 --- /dev/null +++ b/sponge/src/main/java/us/myles/ViaVersion/sponge/util/LoggerWrapper.java @@ -0,0 +1,125 @@ +package us.myles.ViaVersion.sponge.util; + +import org.slf4j.Logger; + +import java.util.logging.Level; +import java.util.logging.LogRecord; + +public class LoggerWrapper extends java.util.logging.Logger { + private final Logger base; + + public LoggerWrapper(Logger logger) { + super("logger", null); + this.base = logger; + } + + @Override + public void log(LogRecord record) { + log(record.getLevel(), record.getMessage()); + } + + @Override + public void log(Level level, String msg) { + if (level == Level.FINEST) { + base.trace(msg); + return; + } + if (level == Level.FINE) { + base.debug(msg); + return; + } + if (level == Level.WARNING) { + base.warn(msg); + return; + } + if (level == Level.SEVERE) { + base.error(msg); + return; + } + if (level == Level.INFO) { + base.info(msg); + return; + } + base.trace(msg); + return; + } + + @Override + public void log(Level level, String msg, Object param1) { + if (level == Level.FINEST) { + base.trace(msg, param1); + return; + } + if (level == Level.FINE) { + base.debug(msg, param1); + return; + } + if (level == Level.WARNING) { + base.warn(msg, param1); + return; + } + if (level == Level.SEVERE) { + base.error(msg, param1); + return; + } + if (level == Level.INFO) { + base.info(msg, param1); + return; + } + base.trace(msg, param1); + return; + } + + @Override + public void log(Level level, String msg, Object[] params) { + if (level == Level.FINEST) { + base.trace(msg, params); + return; + } + if (level == Level.FINE) { + base.debug(msg, params); + return; + } + if (level == Level.WARNING) { + base.warn(msg, params); + return; + } + if (level == Level.SEVERE) { + base.error(msg, params); + return; + } + if (level == Level.INFO) { + base.info(msg, params); + return; + } + base.trace(msg, params); + return; + } + + @Override + public void log(Level level, String msg, Throwable params) { + if (level == Level.FINEST) { + base.trace(msg, params); + return; + } + if (level == Level.FINE) { + base.debug(msg, params); + return; + } + if (level == Level.WARNING) { + base.warn(msg, params); + return; + } + if (level == Level.SEVERE) { + base.error(msg, params); + return; + } + if (level == Level.INFO) { + base.info(msg, params); + return; + } + base.trace(msg, params); + return; + } + +} diff --git a/src/main/java/us/myles/ViaVersion/Bungee.java b/src/main/java/us/myles/ViaVersion/Bungee.java deleted file mode 100644 index e5f3f4758..000000000 --- a/src/main/java/us/myles/ViaVersion/Bungee.java +++ /dev/null @@ -1,18 +0,0 @@ -package us.myles.ViaVersion; - -import net.md_5.bungee.api.plugin.Plugin; - -import static net.md_5.bungee.api.ChatColor.RED; - -public class Bungee extends Plugin { - - @Override - public void onEnable() { - getLogger().severe(RED + "==============================================="); - getLogger().severe(RED + "ViaVersion is NOT a Bungeecord plugin."); - getLogger().severe(RED + "Install this plugin on all your spigot/bukkit"); - getLogger().severe(RED + "servers and use the latest Bungeecord version"); - getLogger().severe(RED + "to make ViaVersion work with BungeeCord."); - getLogger().severe(RED + "==============================================="); - } -} diff --git a/src/main/java/us/myles/ViaVersion/ViaConfig.java b/src/main/java/us/myles/ViaVersion/ViaConfig.java deleted file mode 100644 index 35f2aab4e..000000000 --- a/src/main/java/us/myles/ViaVersion/ViaConfig.java +++ /dev/null @@ -1,188 +0,0 @@ -package us.myles.ViaVersion; - -import us.myles.ViaVersion.api.ViaVersionConfig; -import us.myles.ViaVersion.util.Configuration; - -import java.io.File; -import java.util.List; - -public class ViaConfig implements ViaVersionConfig { - private final ViaVersionPlugin plugin; - - public ViaConfig(ViaVersionPlugin plugin) { - this.plugin = plugin; - generateConfig(); - } - - public void generateConfig() { - File file = new File(plugin.getDataFolder(), "config.yml"); - if (file.exists()) { - // Update conf options - Configuration oldConfig = new Configuration(file); - oldConfig.reload(false); // Load current options from conf - file.delete(); // Delete old conf - plugin.saveDefaultConfig(); // Generate new conf - Configuration newConfig = new Configuration(file); - newConfig.reload(true); // Load default options - for (String key : oldConfig.getKeys(false)) { - // Set option in new conf if exists - if (newConfig.contains(key)) { - newConfig.set(key, oldConfig.get(key)); - } - } - newConfig.save(); - } else { - plugin.saveDefaultConfig(); - } - } - - @Override - public boolean isCheckForUpdates() { - return plugin.getConfig().getBoolean("checkforupdates", true); - } - - @Override - public boolean isPreventCollision() { - return plugin.getConfig().getBoolean("prevent-collision", true); - } - - @Override - public boolean isNewEffectIndicator() { - return plugin.getConfig().getBoolean("use-new-effect-indicator", true); - } - - @Override - public boolean isShowNewDeathMessages() { - return plugin.getConfig().getBoolean("use-new-deathmessages", false); - } - - @Override - public boolean isSuppressMetadataErrors() { - return plugin.getConfig().getBoolean("suppress-metadata-errors", false); - } - - @Override - public boolean isShieldBlocking() { - return plugin.getConfig().getBoolean("shield-blocking", true); - } - - @Override - public boolean isHologramPatch() { - return plugin.getConfig().getBoolean("hologram-patch", false); - } - - @Override - public boolean isBossbarPatch() { - return plugin.getConfig().getBoolean("bossbar-patch", true); - } - - @Override - public boolean isBossbarAntiflicker() { - return plugin.getConfig().getBoolean("bossbar-anti-flicker", false); - } - - @Override - public boolean isUnknownEntitiesSuppressed() { - return false; - } - - @Override - public double getHologramYOffset() { - return plugin.getConfig().getDouble("hologram-y", -0.96D); - } - - @Override - public boolean isBlockBreakPatch() { - return false; - } - - @Override - public int getMaxPPS() { - return plugin.getConfig().getInt("max-pps", 140); - } - - @Override - public String getMaxPPSKickMessage() { - return plugin.getConfig().getString("max-pps-kick-msg", "Sending packets too fast? lag?"); - } - - @Override - public int getTrackingPeriod() { - return plugin.getConfig().getInt("tracking-period", 6); - } - - @Override - public int getWarningPPS() { - return plugin.getConfig().getInt("tracking-warning-pps", 120); - } - - @Override - public int getMaxWarnings() { - return plugin.getConfig().getInt("tracking-max-warnings", 3); - } - - @Override - public String getMaxWarningsKickMessage() { - return plugin.getConfig().getString("tracking-max-kick-msg", "You are sending too many packets, :("); - } - - @Override - public boolean isAntiXRay() { - return plugin.getConfig().getBoolean("anti-xray-patch", true); - } - - @Override - public boolean isSendSupportedVersions() { - return plugin.getConfig().getBoolean("send-supported-versions", false); - } - - @Override - public boolean isStimulatePlayerTick() { - return plugin.getConfig().getBoolean("simulate-pt", true); - } - - @Override - public boolean isItemCache() { - return plugin.getConfig().getBoolean("item-cache", true); - } - - @Override - public boolean isNMSPlayerTicking() { - return plugin.getConfig().getBoolean("nms-player-ticking", true); - } - - @Override - public boolean isReplacePistons() { - return plugin.getConfig().getBoolean("replace-pistons", false); - } - - @Override - public int getPistonReplacementId() { - return plugin.getConfig().getInt("replacement-piston-id", 0); - } - - public boolean isAutoTeam() { - // Collision has to be enabled first - return isPreventCollision() && plugin.getConfig().getBoolean("auto-team", true); - } - - @Override - public boolean isForceJsonTransform() { - return plugin.getConfig().getBoolean("force-json-transform", false); - } - - @Override - public List getBlockedProtocols() { - return plugin.getConfig().getIntegerList("block-protocols"); - } - - @Override - public String getBlockedDisconnectMsg() { - return plugin.getConfig().getString("block-disconnect-msg", "You are using an unsupported Minecraft version!"); - } - - @Override - public String getReloadDisconnectMsg() { - return plugin.getConfig().getString("reload-disconnect-msg", "Server reload, please rejoin!"); - } -} diff --git a/src/main/java/us/myles/ViaVersion/ViaVersionPlugin.java b/src/main/java/us/myles/ViaVersion/ViaVersionPlugin.java deleted file mode 100644 index 8471af2b2..000000000 --- a/src/main/java/us/myles/ViaVersion/ViaVersionPlugin.java +++ /dev/null @@ -1,530 +0,0 @@ -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.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.protocol.ProtocolRegistry; -import us.myles.ViaVersion.api.protocol.ProtocolVersion; -import us.myles.ViaVersion.boss.ViaBossBar; -import us.myles.ViaVersion.classgenerator.ClassGenerator; -import us.myles.ViaVersion.commands.ViaCommandHandler; -import us.myles.ViaVersion.handlers.ViaVersionInitializer; -import us.myles.ViaVersion.protocols.base.ProtocolInfo; -import us.myles.ViaVersion.update.UpdateListener; -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.concurrent.Callable; -import java.util.concurrent.ConcurrentHashMap; -import java.util.concurrent.Future; -import java.util.concurrent.TimeUnit; - -public class ViaVersionPlugin extends JavaPlugin implements ViaVersionAPI { - - private final Map portedPlayers = new ConcurrentHashMap<>(); - private List injectedFutures = new ArrayList<>(); - private List> injectedLists = new ArrayList<>(); - private ViaCommandHandler 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; - - public ViaVersionPlugin() { - // 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(); - } catch (Exception e) { - e.printStackTrace(); - } - } - } - - @Override - public void onLoad() { - // Config magic - conf = new ViaConfig(this); - 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"); - } catch (ClassNotFoundException e) { - spigot = false; - } - - // Check if it's a spigot build with a protocol mod - try { - compatSpigotBuild = ReflectionUtil.nms("PacketEncoder").getDeclaredField("version") != null; - } catch (Exception e) { - compatSpigotBuild = false; - } - - // Generate classes needed (only works if it's compat or ps) - ClassGenerator.generate(); - lateBind = !isBinded(); - - getLogger().info("ViaVersion " + getDescription().getVersion() + (compatSpigotBuild ? "compat" : "") + " is now loaded" + (lateBind ? ", waiting for boot. (late-bind)" : ", injecting!")); - if (!lateBind) - injectPacketHandler(); - } - - @Override - public void onEnable() { - if (lateBind) - injectPacketHandler(); - if (conf.isCheckForUpdates()) - UpdateUtil.sendUpdateMessage(this); - // 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(); - } - }); - - - Bukkit.getPluginManager().registerEvents(new UpdateListener(this), this); - - getCommand("viaversion").setExecutor(commandHandler = new ViaCommandHandler()); - getCommand("viaversion").setTabCompleter(commandHandler); - - // Register Protocol Listeners - ProtocolRegistry.registerListeners(); - - // Warn them if they have anti-xray on and they aren't using spigot - if (conf.isAntiXRay() && !spigot) { - getLogger().info("You have anti-xray on in your config, since you're not using spigot it won't fix xray!"); - } - } - - @Override - public void onDisable() { - getLogger().info("ViaVersion is disabling, if this is a reload and you experience issues consider rebooting."); - uninject(); - } - - 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() { - @Override - public Boolean call() throws Exception { - runnable.run(); - return true; - } - }); - if (wait) { - f.get(10, TimeUnit.SECONDS); - } - } catch (Exception e) { - System.out.println("Failed to run task: " + e.getClass().getName()); - if (ViaVersion.getInstance().isDebug()) - e.printStackTrace(); - } - } - - public boolean isProtocolSupport() { - return protocolSupport; - } - - public Map getPortedPlayers() { - return portedPlayers; - } - - public boolean handlePPS(UserConnection info) { - // Max PPS Checker - if (conf.getMaxPPS() > 0) { - if (info.getPacketsPerSecond() >= conf.getMaxPPS()) { - info.disconnect(conf.getMaxPPSKickMessage().replace("%pps", ((Long) info.getPacketsPerSecond()).intValue() + "")); - return true; // don't send current packet - } - } - - // Tracking PPS Checker - if (conf.getMaxWarnings() > 0 && conf.getTrackingPeriod() > 0) { - if (info.getSecondsObserved() > conf.getTrackingPeriod()) { - // Reset - info.setWarnings(0); - info.setSecondsObserved(1); - } else { - info.setSecondsObserved(info.getSecondsObserved() + 1); - if (info.getPacketsPerSecond() >= conf.getWarningPPS()) { - info.setWarnings(info.getWarnings() + 1); - } - - if (info.getWarnings() >= conf.getMaxWarnings()) { - info.disconnect(conf.getMaxWarningsKickMessage().replace("%pps", ((Long) info.getPacketsPerSecond()).intValue() + "")); - return true; // don't send current packet - } - } - } - return false; - } -} diff --git a/src/main/java/us/myles/ViaVersion/api/ViaListener.java b/src/main/java/us/myles/ViaVersion/api/ViaListener.java deleted file mode 100644 index 48453d862..000000000 --- a/src/main/java/us/myles/ViaVersion/api/ViaListener.java +++ /dev/null @@ -1,75 +0,0 @@ -package us.myles.ViaVersion.api; - -import lombok.AccessLevel; -import lombok.Getter; -import lombok.NonNull; -import lombok.RequiredArgsConstructor; -import org.bukkit.entity.Player; -import org.bukkit.event.Listener; -import us.myles.ViaVersion.ViaVersionPlugin; -import us.myles.ViaVersion.api.data.UserConnection; -import us.myles.ViaVersion.api.protocol.Protocol; -import us.myles.ViaVersion.protocols.base.ProtocolInfo; - -import java.util.UUID; - -@Getter(AccessLevel.PROTECTED) -@RequiredArgsConstructor -public abstract class ViaListener implements Listener { - private final ViaVersionPlugin plugin; - private final Class requiredPipeline; - private boolean registered = false; - - /** - * Get the UserConnection from a player - * - * @param player Player object - * @return The UserConnection - */ - protected UserConnection getUserConnection(@NonNull Player player) { - return getUserConnection(player.getUniqueId()); - } - - /** - * Get the UserConnection from an UUID - * - * @param uuid UUID object - * @return The UserConnection - */ - protected UserConnection getUserConnection(@NonNull UUID uuid) { - if (!plugin.isPorted(uuid)) return null; - return plugin.getConnection(uuid); - } - - /** - * Checks if the player is on the selected pipe - * - * @param player Player Object - * @return True if on pipe - */ - protected boolean isOnPipe(Player player) { - return isOnPipe(player.getUniqueId()); - } - - /** - * Checks if the UUID is on the selected pipe - * - * @param uuid UUID Object - * @return True if on pipe - */ - protected boolean isOnPipe(UUID uuid) { - UserConnection userConnection = getUserConnection(uuid); - return userConnection != null && - userConnection.get(ProtocolInfo.class).getPipeline().contains(requiredPipeline); - } - - /** - * Register as Bukkit event - */ - public void register() { - if (registered) return; - - plugin.getServer().getPluginManager().registerEvents(this, plugin); - registered = true; - } -} diff --git a/src/main/java/us/myles/ViaVersion/api/minecraft/item/Item.java b/src/main/java/us/myles/ViaVersion/api/minecraft/item/Item.java deleted file mode 100644 index 35209c2e6..000000000 --- a/src/main/java/us/myles/ViaVersion/api/minecraft/item/Item.java +++ /dev/null @@ -1,28 +0,0 @@ -package us.myles.ViaVersion.api.minecraft.item; - -import lombok.*; -import org.bukkit.inventory.ItemStack; -import org.spacehq.opennbt.tag.builtin.CompoundTag; - -@Getter -@Setter -@NoArgsConstructor -@AllArgsConstructor -@ToString -public class Item { - private short id; - private byte amount; - private short data; - private CompoundTag tag; - - /** - * Create an item from a bukkit stack (doesn't save NBT) - * - * @param stack The stack to convert from - * @return The output stack - */ - public static Item getItem(ItemStack stack) { - if (stack == null) return null; - return new Item((short) stack.getTypeId(), (byte) stack.getAmount(), stack.getDurability(), null); - } -} diff --git a/src/main/java/us/myles/ViaVersion/api/minecraft/metadata/Metadata.java b/src/main/java/us/myles/ViaVersion/api/minecraft/metadata/Metadata.java deleted file mode 100644 index 58215b791..000000000 --- a/src/main/java/us/myles/ViaVersion/api/minecraft/metadata/Metadata.java +++ /dev/null @@ -1,26 +0,0 @@ -package us.myles.ViaVersion.api.minecraft.metadata; - -import lombok.AllArgsConstructor; -import lombok.Getter; -import lombok.Setter; -import us.myles.ViaVersion.api.type.Type; - -@AllArgsConstructor -@Getter -@Setter -public class Metadata { - private int id; - private int typeID; - private Type type; - private Object value; - - @Override - public String toString() { - return "Metadata{" + - "id=" + id + - ", typeID=" + typeID + - ", type=" + type + - ", value=" + value + - '}'; - } -} diff --git a/src/main/java/us/myles/ViaVersion/classgenerator/BasicHandlerConstructor.java b/src/main/java/us/myles/ViaVersion/classgenerator/BasicHandlerConstructor.java deleted file mode 100644 index d94d4feaf..000000000 --- a/src/main/java/us/myles/ViaVersion/classgenerator/BasicHandlerConstructor.java +++ /dev/null @@ -1,19 +0,0 @@ -package us.myles.ViaVersion.classgenerator; - -import io.netty.handler.codec.ByteToMessageDecoder; -import io.netty.handler.codec.MessageToByteEncoder; -import us.myles.ViaVersion.api.data.UserConnection; -import us.myles.ViaVersion.handlers.ViaDecodeHandler; -import us.myles.ViaVersion.handlers.ViaEncodeHandler; - -public class BasicHandlerConstructor implements HandlerConstructor { - @Override - public ViaEncodeHandler newEncodeHandler(UserConnection info, MessageToByteEncoder minecraftEncoder) { - return new ViaEncodeHandler(info, minecraftEncoder); - } - - @Override - public ViaDecodeHandler newDecodeHandler(UserConnection info, ByteToMessageDecoder minecraftDecoder) { - return new ViaDecodeHandler(info, minecraftDecoder); - } -} diff --git a/src/main/java/us/myles/ViaVersion/commands/defaultsubs/DebugSubCmd.java b/src/main/java/us/myles/ViaVersion/commands/defaultsubs/DebugSubCmd.java deleted file mode 100644 index 931ac7282..000000000 --- a/src/main/java/us/myles/ViaVersion/commands/defaultsubs/DebugSubCmd.java +++ /dev/null @@ -1,27 +0,0 @@ -package us.myles.ViaVersion.commands.defaultsubs; - -import org.bukkit.command.CommandSender; -import us.myles.ViaVersion.ViaVersionPlugin; -import us.myles.ViaVersion.api.ViaVersion; -import us.myles.ViaVersion.api.command.ViaSubCommand; - -public class DebugSubCmd extends ViaSubCommand { - @Override - public String name() { - return "debug"; - } - - @Override - public String description() { - return "Toggle debug mode"; - } - - @Override - public boolean execute(CommandSender sender, String[] args) { - ViaVersionPlugin plugin = (ViaVersionPlugin) ViaVersion.getInstance(); - - plugin.setDebug(!plugin.isDebug()); - sendMessage(sender, "&6Debug mode is now %s", (plugin.isDebug() ? "&aenabled" : "&cdisabled")); - return true; - } -} diff --git a/src/main/java/us/myles/ViaVersion/commands/defaultsubs/HelpSubCmd.java b/src/main/java/us/myles/ViaVersion/commands/defaultsubs/HelpSubCmd.java deleted file mode 100644 index 40f936107..000000000 --- a/src/main/java/us/myles/ViaVersion/commands/defaultsubs/HelpSubCmd.java +++ /dev/null @@ -1,27 +0,0 @@ -package us.myles.ViaVersion.commands.defaultsubs; - -import org.bukkit.command.CommandSender; -import us.myles.ViaVersion.ViaVersionPlugin; -import us.myles.ViaVersion.api.ViaVersion; -import us.myles.ViaVersion.api.command.ViaSubCommand; -import us.myles.ViaVersion.commands.ViaCommandHandler; - -public class HelpSubCmd extends ViaSubCommand { - @Override - public String name() { - return "help"; - } - - @Override - public String description() { - return "You are looking at it right now!"; - } - - @Override - public boolean execute(CommandSender sender, String[] args) { - ViaVersionPlugin plugin = (ViaVersionPlugin) ViaVersion.getInstance(); - - ((ViaCommandHandler) plugin.getCommandHandler()).showHelp(sender); - return true; - } -} diff --git a/src/main/java/us/myles/ViaVersion/protocols/protocol1_9_3to1_9_1_2/chunks/FakeTileEntity.java b/src/main/java/us/myles/ViaVersion/protocols/protocol1_9_3to1_9_1_2/chunks/FakeTileEntity.java deleted file mode 100644 index adeab98fd..000000000 --- a/src/main/java/us/myles/ViaVersion/protocols/protocol1_9_3to1_9_1_2/chunks/FakeTileEntity.java +++ /dev/null @@ -1,74 +0,0 @@ -package us.myles.ViaVersion.protocols.protocol1_9_3to1_9_1_2.chunks; - -import org.bukkit.Material; -import org.spacehq.opennbt.tag.builtin.CompoundTag; -import org.spacehq.opennbt.tag.builtin.IntTag; -import org.spacehq.opennbt.tag.builtin.StringTag; - -import java.util.Arrays; -import java.util.List; -import java.util.Map; -import java.util.concurrent.ConcurrentHashMap; - -/** - * Mojang changed the way how tile entities inside chunk packets work in 1.10.1 - * It requires now to have all tile entity data included in the chunk packet, otherwise it'll crash. - */ -public class FakeTileEntity { - private static Map tileEntities = new ConcurrentHashMap<>(); - - static { - register(Material.FURNACE, "Furnace"); - register(Arrays.asList(Material.CHEST, Material.TRAPPED_CHEST), "Chest"); - register(Material.ENDER_CHEST, "EnderChest"); - register(Material.JUKEBOX, "RecordPlayer"); - register(Material.DISPENSER, "Trap"); - register(Material.DROPPER, "Dropper"); - register(Arrays.asList(Material.SIGN_POST, Material.WALL_SIGN), "Sign"); - register(Material.MOB_SPAWNER, "MobSpawner"); - register(Material.NOTE_BLOCK, "Music"); - register(Arrays.asList(Material.PISTON_BASE, Material.PISTON_EXTENSION, Material.PISTON_STICKY_BASE, Material.PISTON_MOVING_PIECE), "Piston"); - register(Arrays.asList(Material.BREWING_STAND, Material.CAULDRON), "Cauldron"); - register(Material.ENCHANTMENT_TABLE, "EnchantTable"); - register(Arrays.asList(Material.ENDER_PORTAL, Material.ENDER_PORTAL_FRAME), "Airportal"); - register(Material.BEACON, "Beacon"); - register(Arrays.asList(Material.SKULL, Material.SKULL_ITEM), "Skull"); - register(Arrays.asList(Material.DAYLIGHT_DETECTOR, Material.DAYLIGHT_DETECTOR_INVERTED), "DLDetector"); - register(Material.HOPPER, "Hopper"); - register(Arrays.asList(Material.REDSTONE_COMPARATOR, Material.REDSTONE_COMPARATOR_OFF, Material.REDSTONE_COMPARATOR_ON), "Comparator"); - register(Material.FLOWER_POT, "FlowerPot"); - register(Arrays.asList(Material.STANDING_BANNER, Material.WALL_BANNER, Material.BANNER), "Banner"); - register(209, "EndGateway"); - register(Material.COMMAND.getId(), "Control"); - } - - private static void register(Integer material, String name) { - CompoundTag comp = new CompoundTag(""); - comp.put(new StringTag(name)); - tileEntities.put(material, comp); - } - - private static void register(Material material, String name) { - register(material.getId(), name); - } - - private static void register(List materials, String name) { - for (Material m : materials) - register(m.getId(), name); - } - - public static boolean hasBlock(int block) { - return tileEntities.containsKey(block); - } - - public static CompoundTag getFromBlock(int x, int y, int z, int block) { - if (tileEntities.containsKey(block)) { - CompoundTag tag = tileEntities.get(block).clone(); - tag.put(new IntTag("x", x)); - tag.put(new IntTag("y", y)); - tag.put(new IntTag("z", z)); - return tag; - } - return null; - } -} diff --git a/src/main/java/us/myles/ViaVersion/protocols/protocol1_9_3to1_9_1_2/storage/ClientWorld.java b/src/main/java/us/myles/ViaVersion/protocols/protocol1_9_3to1_9_1_2/storage/ClientWorld.java deleted file mode 100644 index 8c67f60eb..000000000 --- a/src/main/java/us/myles/ViaVersion/protocols/protocol1_9_3to1_9_1_2/storage/ClientWorld.java +++ /dev/null @@ -1,33 +0,0 @@ -package us.myles.ViaVersion.protocols.protocol1_9_3to1_9_1_2.storage; - -import lombok.Getter; -import org.bukkit.World; -import us.myles.ViaVersion.api.data.StoredObject; -import us.myles.ViaVersion.api.data.UserConnection; - -@Getter -public class ClientWorld extends StoredObject { - private World.Environment environment; - - public ClientWorld(UserConnection user) { - super(user); - } - - public void setEnvironment(int environmentId) { - this.environment = getEnvFromId(environmentId); - } - - private World.Environment getEnvFromId(int id) { - switch(id) { - case -1: - return World.Environment.NETHER; - case 0: - return World.Environment.NORMAL; - case 1: - return World.Environment.THE_END; - default: - return World.Environment.NETHER; - //throw new IllegalArgumentException("Invalid environment id:" + id); - } - } -} diff --git a/src/main/java/us/myles/ViaVersion/protocols/protocol1_9to1_8/ArmorType.java b/src/main/java/us/myles/ViaVersion/protocols/protocol1_9to1_8/ArmorType.java deleted file mode 100644 index f05f5bd0b..000000000 --- a/src/main/java/us/myles/ViaVersion/protocols/protocol1_9to1_8/ArmorType.java +++ /dev/null @@ -1,90 +0,0 @@ -package us.myles.ViaVersion.protocols.protocol1_9to1_8; - -import lombok.Getter; -import lombok.RequiredArgsConstructor; -import org.bukkit.Material; -import org.bukkit.inventory.ItemStack; - -import java.util.HashMap; - -@RequiredArgsConstructor -@Getter -public enum ArmorType { - - LEATHER_HELMET(1, 298, Material.LEATHER_HELMET), - LEATHER_CHESTPLATE(3, 299, Material.LEATHER_CHESTPLATE), - LEATHER_LEGGINGS(2, 300, Material.LEATHER_LEGGINGS), - LEATHER_BOOTS(1, 301, Material.LEATHER_BOOTS), - CHAINMAIL_HELMET(2, 302, Material.CHAINMAIL_HELMET), - CHAINMAIL_CHESTPLATE(5, 303, Material.CHAINMAIL_CHESTPLATE), - CHAINMAIL_LEGGINGS(4, 304, Material.CHAINMAIL_LEGGINGS), - CHAINMAIL_BOOTS(1, 305, Material.CHAINMAIL_BOOTS), - IRON_HELMET(2, 306, Material.IRON_HELMET), - IRON_CHESTPLATE(6, 307, Material.IRON_CHESTPLATE), - IRON_LEGGINGS(5, 308, Material.IRON_LEGGINGS), - IRON_BOOTS(2, 309, Material.IRON_BOOTS), - DIAMOND_HELMET(3, 310, Material.DIAMOND_HELMET), - DIAMOND_CHESTPLATE(8, 311, Material.DIAMOND_CHESTPLATE), - DIAMOND_LEGGINGS(6, 312, Material.DIAMOND_LEGGINGS), - DIAMOND_BOOTS(3, 313, Material.DIAMOND_BOOTS), - GOLD_HELMET(2, 314, Material.GOLD_HELMET), - GOLD_CHESTPLATE(5, 315, Material.GOLD_CHESTPLATE), - GOLD_LEGGINGS(3, 316, Material.GOLD_LEGGINGS), - GOLD_BOOTS(1, 317, Material.GOLD_BOOTS), - NONE(0, 0, Material.AIR); - - private static HashMap armor; - - static { - armor = new HashMap(); - for (ArmorType a : ArmorType.values()) { - armor.put(a.getType(), a); - } - } - - private final int armorPoints; - private final int id; - private final Material type; - - public static ArmorType findByType(Material type) { - ArmorType t = armor.get(type); - return t == null ? ArmorType.NONE : t; - } - - public static int calculateArmorPoints(ItemStack[] armor) { - int total = 0; - for (ItemStack anArmor : armor) { - if (anArmor != null) - total += findByType(anArmor.getType()).getArmorPoints(); - } - return total; - } - - public static ArmorType findById(int id) { - for (ArmorType a : ArmorType.values()) - if (a.getId() == id) - return a; - return ArmorType.NONE; - } - - public static boolean isArmor(Material material) { - for (ArmorType a : ArmorType.values()) - if (a.getType() == material) - return true; - return false; - } - - public static int calculateArmorPoints(int[] armor) { - int total = 0; - for (int anArmor : armor) { - if (anArmor != -1) - total += findById(anArmor).getArmorPoints(); - } - return total; - } - - public Material getType() { - return this.type; - } - -} \ No newline at end of file diff --git a/src/main/java/us/myles/ViaVersion/protocols/protocol1_9to1_8/ViaIdleThread.java b/src/main/java/us/myles/ViaVersion/protocols/protocol1_9to1_8/ViaIdleThread.java deleted file mode 100644 index c2498a4ed..000000000 --- a/src/main/java/us/myles/ViaVersion/protocols/protocol1_9to1_8/ViaIdleThread.java +++ /dev/null @@ -1,113 +0,0 @@ -package us.myles.ViaVersion.protocols.protocol1_9to1_8; - -import io.netty.channel.ChannelHandlerContext; -import org.bukkit.Bukkit; -import org.bukkit.entity.Player; -import org.bukkit.scheduler.BukkitRunnable; -import us.myles.ViaVersion.api.ViaVersion; -import us.myles.ViaVersion.api.data.UserConnection; -import us.myles.ViaVersion.protocols.base.ProtocolInfo; -import us.myles.ViaVersion.protocols.protocol1_9to1_8.storage.MovementTracker; -import us.myles.ViaVersion.util.PipelineUtil; -import us.myles.ViaVersion.util.ReflectionUtil; - -import java.lang.reflect.Field; -import java.lang.reflect.InvocationTargetException; -import java.lang.reflect.Method; -import java.util.Map; -import java.util.UUID; - -public class ViaIdleThread extends BukkitRunnable { - private static boolean USE_NMS = true; - private final Map portedPlayers; - // Used for packet mode - private Object idlePacket; - private Object idlePacket2; - // Use for nms - private Method getHandle; - private Field connection; - private Method handleFlying; - - public ViaIdleThread(Map portedPlayers) { - USE_NMS = ViaVersion.getConfig().isNMSPlayerTicking(); - - this.portedPlayers = portedPlayers; - Class idlePacketClass; - try { - idlePacketClass = ReflectionUtil.nms("PacketPlayInFlying"); - } catch (ClassNotFoundException e) { - throw new RuntimeException("Couldn't find idle packet, help!", e); - } - try { - idlePacket = idlePacketClass.newInstance(); - idlePacket2 = idlePacketClass.newInstance(); - - Field flying = idlePacketClass.getDeclaredField("f"); - flying.setAccessible(true); - - flying.set(idlePacket2, true); - } catch (NoSuchFieldException | InstantiationException | IllegalArgumentException | IllegalAccessException e) { - throw new RuntimeException("Couldn't make player idle packet, help!", e); - } - if (USE_NMS) { - try { - getHandle = ReflectionUtil.obc("entity.CraftPlayer").getDeclaredMethod("getHandle"); - } catch (NoSuchMethodException | ClassNotFoundException e) { - throw new RuntimeException("Couldn't find CraftPlayer", e); - } - - try { - connection = ReflectionUtil.nms("EntityPlayer").getDeclaredField("playerConnection"); - } catch (NoSuchFieldException | ClassNotFoundException e) { - throw new RuntimeException("Couldn't find Player Connection", e); - } - - try { - handleFlying = ReflectionUtil.nms("PlayerConnection").getDeclaredMethod("a", idlePacketClass); - } catch (NoSuchMethodException | ClassNotFoundException e) { - throw new RuntimeException("Couldn't find CraftPlayer", e); - } - } - } - - @Override - public void run() { - for (UserConnection info : portedPlayers.values()) { - if (info.get(ProtocolInfo.class).getPipeline().contains(Protocol1_9TO1_8.class)) { - long nextIdleUpdate = info.get(MovementTracker.class).getNextIdlePacket(); - if (nextIdleUpdate <= System.currentTimeMillis()) { - if (info.getChannel().isOpen()) { - if (USE_NMS) { - Player player = Bukkit.getPlayer(info.get(ProtocolInfo.class).getUuid()); - if (player != null) { - try { - // Tick player - Object entityPlayer = getHandle.invoke(player); - Object pc = connection.get(entityPlayer); - if (pc != null) { - handleFlying.invoke(pc, (info.get(MovementTracker.class).isGround() ? idlePacket2 : idlePacket)); - // Tick world - info.get(MovementTracker.class).incrementIdlePacket(); - } - } catch (IllegalAccessException | InvocationTargetException e) { - e.printStackTrace(); - } - } - } else { - // Old method using packets. - ChannelHandlerContext context = PipelineUtil.getContextBefore("decoder", info.getChannel().pipeline()); - if (context != null) { - if (info.get(MovementTracker.class).isGround()) { - context.fireChannelRead(idlePacket2); - } else { - context.fireChannelRead(idlePacket); - } - info.get(MovementTracker.class).incrementIdlePacket(); - } - } - } - } - } - } - } -} diff --git a/src/main/java/us/myles/ViaVersion/protocols/protocol1_9to1_8/metadata/MetaIndex.java b/src/main/java/us/myles/ViaVersion/protocols/protocol1_9to1_8/metadata/MetaIndex.java deleted file mode 100644 index c43dffd12..000000000 --- a/src/main/java/us/myles/ViaVersion/protocols/protocol1_9to1_8/metadata/MetaIndex.java +++ /dev/null @@ -1,192 +0,0 @@ -package us.myles.ViaVersion.protocols.protocol1_9to1_8.metadata; - -import lombok.Getter; -import org.bukkit.entity.*; - -@Getter -public enum MetaIndex { - - // entity - ENTITY_STATUS(org.bukkit.entity.Entity.class, 0, Type.Byte, NewType.Byte), - ENTITY_AIR(org.bukkit.entity.Entity.class, 1, Type.Short, NewType.VarInt), - ENTITY_SILENT(org.bukkit.entity.Entity.class, 4, Type.Byte, NewType.Boolean), - // living entity - LIVINGENTITY_NAMETAG(LivingEntity.class, 2, Type.String, NewType.String), - LIVINGENTITY_ALWAYS_SHOW_NAMETAG(LivingEntity.class, 3, Type.Byte, NewType.Boolean), - LIVINGENTITY_HEALTH(LivingEntity.class, 6, Type.Float, NewType.Float), - LIVINGENTITY_POTION_EFFECT_COLOR(LivingEntity.class, 7, Type.Int, NewType.VarInt), - LIVINGENTITY_IS_POTION_AMBIENT(LivingEntity.class, 8, Type.Byte, NewType.Boolean), - LIVINGENTITY_NUMBER_OF_ARROWS_IN(LivingEntity.class, 9, Type.Byte, NewType.VarInt), - LIVINGENTITY_NO_AI(LivingEntity.class, 15, Type.Byte, 10, NewType.Byte), // in 1.9 this is combined with Left handed, oh. - // ageable - AGEABLE_AGE(Ageable.class, 12, Type.Byte, 11, NewType.Boolean), - // armour stand - STAND_INFO(ArmorStand.class, 10, Type.Byte, NewType.Byte), - STAND_HEAD_POS(ArmorStand.class, 11, Type.Rotation, NewType.Vector3F), - STAND_BODY_POS(ArmorStand.class, 12, Type.Rotation, NewType.Vector3F), - STAND_LA_POS(ArmorStand.class, 13, Type.Rotation, NewType.Vector3F), - STAND_RA_POS(ArmorStand.class, 14, Type.Rotation, NewType.Vector3F), - STAND_LL_POS(ArmorStand.class, 15, Type.Rotation, NewType.Vector3F), - STAND_RL_POS(ArmorStand.class, 16, Type.Rotation, NewType.Vector3F), - // human, discountined? - PLAYER_SKIN_FLAGS(HumanEntity.class, 10, Type.Byte, 12, NewType.Byte), // unsigned on 1.8 - PLAYER_HUMAN_BYTE(HumanEntity.class, 16, Type.Byte, NewType.Discontinued), // unused on 1.8 - PLAYER_ADDITIONAL_HEARTS(HumanEntity.class, 17, Type.Float, 10, NewType.Float), - PLAYER_SCORE(HumanEntity.class, 18, Type.Int, 11, NewType.VarInt), - PLAYER_HAND(HumanEntity.class, -1, Type.NonExistent, 5, NewType.Byte), // new in 1.9 - SOMETHING_ANTICHEAT_PLUGINS_FOR_SOME_REASON_USE(HumanEntity.class, 11, Type.Byte, NewType.Discontinued), //For what we know, This doesn't exists. If you think it exists and knows what it does. Please tell us. - // horse - HORSE_INFO(Horse.class, 16, Type.Int, 12, NewType.Byte), - HORSE_TYPE(Horse.class, 19, Type.Byte, 13, NewType.VarInt), - HORSE_SUBTYPE(Horse.class, 20, Type.Int, 14, NewType.VarInt), - HORSE_OWNER(Horse.class, 21, Type.String, 15, NewType.OptUUID), - HORSE_ARMOR(Horse.class, 22, Type.Int, 16, NewType.VarInt), - // bat - BAT_ISHANGING(Bat.class, 16, Type.Byte, 11, NewType.Byte), - // tameable - TAMING_INFO(Tameable.class, 16, Type.Byte, 12, NewType.Byte), - TAMING_OWNER(Tameable.class, 17, Type.String, 13, NewType.OptUUID), - // ocelot - OCELOT_TYPE(Ocelot.class, 18, Type.Byte, 14, NewType.VarInt), - // wolf - WOLF_HEALTH(Wolf.class, 18, Type.Float, 14, NewType.Float), - WOLF_BEGGING(Wolf.class, 19, Type.Byte, 15, NewType.Boolean), - WOLF_COLLAR(Wolf.class, 20, Type.Byte, 16, NewType.VarInt), - // pig - PIG_SADDLE(Pig.class, 16, Type.Byte, 12, NewType.Boolean), - // rabbit - RABBIT_TYPE(Rabbit.class, 18, Type.Byte, 12, NewType.VarInt), - // sheep - SHEEP_COLOR(Sheep.class, 16, Type.Byte, 12, NewType.Byte), - // villager - VILLAGER_PROFESSION(Villager.class, 16, Type.Int, 12, NewType.VarInt), - // enderman - ENDERMAN_BLOCK(Enderman.class, 16, Type.Short, 11, NewType.BlockID), // special case - ENDERMAN_BLOCKDATA(Enderman.class, 17, Type.Byte, 11, NewType.BlockID), // special case - ENDERMAN_ISSCREAMING(Enderman.class, 18, Type.Byte, 12, NewType.Boolean), - // zombie - ZOMBIE_ISCHILD(Zombie.class, 12, Type.Byte, 11, NewType.Boolean), - ZOMBIE_ISVILLAGER(Zombie.class, 13, Type.Byte, 12, NewType.VarInt), - ZOMBIE_ISCONVERTING(Zombie.class, 14, Type.Byte, 13, NewType.Boolean), - // ZOMBIE_RISINGHANDS added in 1.9 - // blaze - BLAZE_ONFIRE(Blaze.class, 16, Type.Byte, 11, NewType.Byte), - // spider - SPIDER_CIMBING(Spider.class, 16, Type.Byte, 11, NewType.Byte), - // creeper - CREEPER_FUSE(Creeper.class, 16, Type.Byte, 11, NewType.VarInt), // -1 idle, 1 is fuse - CREEPER_ISPOWERED(Creeper.class, 17, Type.Byte, 12, NewType.Boolean), - CREEPER_ISIGNITED(Creeper.class, 18, Type.Byte, 13, NewType.Boolean), - // ghast - GHAST_ISATTACKING(Ghast.class, 16, Type.Byte, 11, NewType.Boolean), - // slime - SLIME_SIZE(Slime.class, 16, Type.Byte, 11, NewType.VarInt), - // skeleton - SKELETON_TYPE(Skeleton.class, 13, Type.Byte, 11, NewType.VarInt), - // witch - WITCH_AGGRO(Witch.class, 21, Type.Byte, 11, NewType.Boolean), - // iron golem - IRON_PLAYERMADE(IronGolem.class, 16, Type.Byte, 11, NewType.Byte), - // wither - WITHER_TARGET1(Wither.class, 17, Type.Int, 11, NewType.VarInt), - WITHER_TARGET2(Wither.class, 18, Type.Int, 12, NewType.VarInt), - WITHER_TARGET3(Wither.class, 19, Type.Int, 13, NewType.VarInt), - WITHER_INVULN_TIME(Wither.class, 20, Type.Int, 14, NewType.VarInt), - WITHER_PROPERTIES(Wither.class, 10, Type.Byte, NewType.Byte), - WITHER_UNKNOWN(Wither.class, 11, Type.Byte, NewType.Discontinued), - // wither skull - WITHERSKULL_INVULN(WitherSkull.class, 10, Type.Byte, 5, NewType.Boolean), - // guardian - GUARDIAN_INFO(Guardian.class, 16, Type.Int, 11, NewType.Byte), - GUARDIAN_TARGET(Guardian.class, 17, Type.Int, 12, NewType.VarInt), - // boat - BOAT_SINCEHIT(Boat.class, 17, Type.Int, 5, NewType.VarInt), - BOAT_FORWARDDIR(Boat.class, 18, Type.Int, 6, NewType.VarInt), - BOAT_DMGTAKEN(Boat.class, 19, Type.Float, 7, NewType.Float), - // BOAT_TYPE in 1.9 - // minecart - MINECART_SHAKINGPOWER(Minecart.class, 17, Type.Int, 5, NewType.VarInt), - MINECART_SHAKINGDIRECTION(Minecart.class, 18, Type.Int, 6, NewType.VarInt), - MINECART_DAMAGETAKEN(Minecart.class, 19, Type.Float, 7, NewType.Float), // also shaking modifier :P - MINECART_BLOCK(Minecart.class, 20, Type.Int, 8, NewType.VarInt), - MINECART_BLOCK_Y(Minecart.class, 21, Type.Int, 9, NewType.VarInt), - MINECART_SHOWBLOCK(Minecart.class, 22, Type.Byte, 10, NewType.Boolean), - // Command minecart (they are still broken) - MINECART_COMMANDBLOCK_COMMAND(Minecart.class, 23, Type.String, 11, NewType.String), - MINECART_COMMANDBLOCK_OUTPUT(Minecart.class, 24, Type.String, 12, NewType.Chat), - // furnace cart - FURNACECART_ISPOWERED(Minecart.class, 16, Type.Byte, 11, NewType.Boolean), - // item drop - ITEM_ITEM(Item.class, 10, Type.Slot, 5, NewType.Slot), - // arrow - ARROW_ISCRIT(Arrow.class, 16, Type.Byte, 5, NewType.Byte), - // firework - FIREWORK_INFO(Firework.class, 8, Type.Slot, 5, NewType.Slot), - // item frame - ITEMFRAME_ITEM(ItemFrame.class, 8, Type.Slot, 5, NewType.Slot), - ITEMFRAME_ROTATION(ItemFrame.class, 9, Type.Byte, 6, NewType.VarInt), - // ender crystal - ENDERCRYSTAL_HEALTH(EnderCrystal.class, 8, Type.Int, NewType.Discontinued), - // Ender dragon boss bar issues - ENDERDRAGON_UNKNOWN(EnderDragon.class, 5, Type.Byte, NewType.Discontinued), - ENDERDRAGON_NAME(EnderDragon.class, 10, Type.String, NewType.Discontinued), - // Normal Ender dragon - ENDERDRAGON_FLAG(EnderDragon.class, 15, Type.Byte, NewType.Discontinued), - ENDERDRAGON_PHASE(EnderDragon.class, 11, Type.Byte, NewType.VarInt); - - private Class clazz; - private int newIndex; - private NewType newType; - private Type oldType; - private int index; - - MetaIndex(Class type, int index, Type oldType, NewType newType) { - this.clazz = type; - this.index = index; - this.newIndex = index; - this.oldType = oldType; - this.newType = newType; - } - - MetaIndex(Class type, int index, Type oldType, int newIndex, NewType newType) { - this.clazz = type; - this.index = index; - this.oldType = oldType; - this.newIndex = newIndex; - this.newType = newType; - } - - public static MetaIndex getIndex(EntityType type, int index) { - Class entityClass = type == null ? LivingEntity.class : type.getEntityClass(); - if (entityClass == null) { - System.out.println("Could not get entity class for " + type); - return null; - } - for (MetaIndex mi : MetaIndex.values()) { - if (mi.getIndex() == index) { - // To fix issue with armour stands colliding with new values - if (mi.getApplicableClass().equals(LivingEntity.class)) continue; - - if ((mi.getApplicableClass().isAssignableFrom(entityClass) || - mi.getApplicableClass().equals(entityClass))) { - return mi; - } - } - } - // fall back to living entity - for (MetaIndex mi : MetaIndex.values()) { - if (mi.getIndex() == index) { - if (mi.getApplicableClass().isAssignableFrom(LivingEntity.class) || - mi.getApplicableClass().equals(LivingEntity.class)) { - return mi; - } - } - } - return null; - } - - public Class getApplicableClass() { - return this.clazz; - } -} - diff --git a/src/main/java/us/myles/ViaVersion/protocols/protocol1_9to1_8/metadata/Type.java b/src/main/java/us/myles/ViaVersion/protocols/protocol1_9to1_8/metadata/Type.java deleted file mode 100644 index 18bb90b4b..000000000 --- a/src/main/java/us/myles/ViaVersion/protocols/protocol1_9to1_8/metadata/Type.java +++ /dev/null @@ -1,23 +0,0 @@ -package us.myles.ViaVersion.protocols.protocol1_9to1_8.metadata; - -import lombok.Getter; -import lombok.RequiredArgsConstructor; - -@RequiredArgsConstructor -@Getter -public enum Type { - Byte(0), - Short(1), - Int(2), - Float(3), - String(4), - Slot(5), - Position(6), - Rotation(7), - NonExistent(-1); - private final int typeID; - - public static Type byId(int id) { - return values()[id]; - } -} diff --git a/src/main/java/us/myles/ViaVersion/protocols/protocolsnapshotto1_10/storage/EntityTracker.java b/src/main/java/us/myles/ViaVersion/protocols/protocolsnapshotto1_10/storage/EntityTracker.java deleted file mode 100644 index b871b7736..000000000 --- a/src/main/java/us/myles/ViaVersion/protocols/protocolsnapshotto1_10/storage/EntityTracker.java +++ /dev/null @@ -1,21 +0,0 @@ -package us.myles.ViaVersion.protocols.protocolsnapshotto1_10.storage; - -import lombok.Getter; -import us.myles.ViaVersion.api.data.StoredObject; -import us.myles.ViaVersion.api.data.UserConnection; - -import java.util.Map; -import java.util.concurrent.ConcurrentHashMap; - -@Getter -public class EntityTracker extends StoredObject { - private final Map clientEntityTypes = new ConcurrentHashMap<>(); - - public EntityTracker(UserConnection user) { - super(user); - } - - public void removeEntity(Integer entityID) { - clientEntityTypes.remove(entityID); - } -} diff --git a/src/main/java/us/myles/ViaVersion/util/EntityUtil.java b/src/main/java/us/myles/ViaVersion/util/EntityUtil.java deleted file mode 100644 index 696f8a576..000000000 --- a/src/main/java/us/myles/ViaVersion/util/EntityUtil.java +++ /dev/null @@ -1,92 +0,0 @@ -package us.myles.ViaVersion.util; - -import org.bukkit.entity.EntityType; - -public class EntityUtil { - - public static EntityType getTypeFromID(int typeID, boolean isObject) { - if (isObject) { - return getObjectFromID(typeID); - } else { - return EntityType.fromId(typeID); - } - } - - // based on http://wiki.vg/index.php?title=Entities - public static EntityType getObjectFromID(int objectID) { - EntityType type; - switch (objectID) { - case 2: - type = EntityType.DROPPED_ITEM; - break; - case 77: - type = EntityType.LEASH_HITCH; - break; - case 60: - type = EntityType.ARROW; - break; - case 61: - type = EntityType.SNOWBALL; - break; - case 63: - type = EntityType.FIREBALL; - break; - case 64: - type = EntityType.SMALL_FIREBALL; - break; - case 65: - type = EntityType.ENDER_PEARL; - break; - case 72: - type = EntityType.ENDER_SIGNAL; - break; - case 75: - type = EntityType.THROWN_EXP_BOTTLE; - break; - case 71: - type = EntityType.ITEM_FRAME; - break; - case 66: - type = EntityType.WITHER_SKULL; - break; - case 50: - type = EntityType.PRIMED_TNT; - break; - case 70: - type = EntityType.FALLING_BLOCK; - break; - case 76: - type = EntityType.FIREWORK; - break; - case 78: - type = EntityType.ARMOR_STAND; - break; - case 1: - type = EntityType.BOAT; - break; - case 10: - type = EntityType.MINECART; - break; - case 51: - type = EntityType.ENDER_CRYSTAL; - break; - case 73: - type = EntityType.SPLASH_POTION; - break; - case 62: - type = EntityType.EGG; - break; - case 90: - type = EntityType.FISHING_HOOK; - break; - default: - type = EntityType.fromId(objectID); - if (type == null) { - System.out.println("Unable to find entity type for " + objectID); - type = EntityType.UNKNOWN; - } - break; - } - return type; - } -} diff --git a/src/main/resources/bungee.yml b/src/main/resources/bungee.yml deleted file mode 100644 index 216d2e7cf..000000000 --- a/src/main/resources/bungee.yml +++ /dev/null @@ -1,4 +0,0 @@ -name: ViaVersion -main: us.myles.ViaVersion.Bungee -author: _MylesC -version: ${project.version} \ No newline at end of file