diff --git a/src/main/java/us/myles/ViaVersion/ConnectionInfo.java b/src/main/java/us/myles/ViaVersion/ConnectionInfo.java deleted file mode 100644 index b90f4a84d..000000000 --- a/src/main/java/us/myles/ViaVersion/ConnectionInfo.java +++ /dev/null @@ -1,73 +0,0 @@ -package us.myles.ViaVersion; - -import io.netty.buffer.ByteBuf; -import io.netty.channel.ChannelHandler; -import io.netty.channel.socket.SocketChannel; -import lombok.Getter; -import lombok.Setter; -import org.bukkit.Bukkit; -import org.bukkit.entity.Player; -import us.myles.ViaVersion.chunks.ChunkManager; -import us.myles.ViaVersion.packets.State; - -@Getter -@Setter -public class ConnectionInfo { - private static final long IDLE_PACKET_DELAY = 50L; // Update every 50ms (20tps) - private static final long IDLE_PACKET_LIMIT = 20; // Max 20 ticks behind - - private final SocketChannel channel; - private final ChunkManager chunkManager; - private Object lastPacket; - private java.util.UUID UUID; - private State state = State.HANDSHAKE; - private String openWindow; - private int protocol = 0; - private int compression = 0; - private int entityID; - private boolean active = true; - private String username; - private long nextIdlePacket = 0L; - - public ConnectionInfo(SocketChannel socketChannel) { - this.channel = socketChannel; - this.chunkManager = new ChunkManager(this); - } - - public Player getPlayer() { - return UUID == null ? null : Bukkit.getPlayer(UUID); - } - - public void setActive(boolean active) { - this.active = active; - this.nextIdlePacket = System.currentTimeMillis() + IDLE_PACKET_DELAY; // Update every 50 ticks - } - - public void sendRawPacket(final ByteBuf packet, boolean currentThread) { - final ChannelHandler handler = channel.pipeline().get("encoder"); - if (currentThread) { - channel.pipeline().context(handler).writeAndFlush(packet); - } else { - channel.eventLoop().submit(new Runnable() { - @Override - public void run() { - channel.pipeline().context(handler).writeAndFlush(packet); - } - }); - } - } - - public void sendRawPacket(final ByteBuf packet) { - sendRawPacket(packet, false); - } - - public void closeWindow() { - this.openWindow = null; - } - - public void incrementIdlePacket() { - // Notify of next update - // Allow a maximum lag spike of 1 second (20 ticks/updates) - this.nextIdlePacket = Math.max(nextIdlePacket + IDLE_PACKET_DELAY, System.currentTimeMillis() - IDLE_PACKET_DELAY * IDLE_PACKET_LIMIT); - } -} diff --git a/src/main/java/us/myles/ViaVersion/ViaVersionPlugin.java b/src/main/java/us/myles/ViaVersion/ViaVersionPlugin.java index 1fdb5a3ed..e297a3222 100644 --- a/src/main/java/us/myles/ViaVersion/ViaVersionPlugin.java +++ b/src/main/java/us/myles/ViaVersion/ViaVersionPlugin.java @@ -11,7 +11,6 @@ import org.bukkit.entity.Player; import org.bukkit.event.EventHandler; import org.bukkit.event.Listener; import org.bukkit.event.player.PlayerQuitEvent; -import org.bukkit.inventory.ItemStack; import org.bukkit.plugin.java.JavaPlugin; import us.myles.ViaVersion.api.ViaVersion; import us.myles.ViaVersion.api.ViaVersionAPI; @@ -48,25 +47,6 @@ public class ViaVersionPlugin extends JavaPlugin implements ViaVersionAPI { private final Map portedPlayers = new ConcurrentHashMap<>(); private boolean debug = false; - public static ItemStack getHandItem(final ConnectionInfo info) { - try { - return Bukkit.getScheduler().callSyncMethod(Bukkit.getPluginManager().getPlugin("ViaVersion"), new Callable() { - @Override - public ItemStack call() throws Exception { - if (info.getPlayer() != null) { - return info.getPlayer().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; - } - } - @Override public void onEnable() { ViaVersion.setInstance(this); @@ -265,7 +245,7 @@ public class ViaVersionPlugin extends JavaPlugin implements ViaVersionAPI { public int getPlayerVersion(@NonNull Player player) { if (!isPorted(player)) return 47; - return portedPlayers.get(player.getUniqueId()).getProtocol(); + return portedPlayers.get(player.getUniqueId()).get(ProtocolInfo.class).getProtocolVersion(); } @Override diff --git a/src/main/java/us/myles/ViaVersion/boss/ViaBossBar.java b/src/main/java/us/myles/ViaVersion/boss/ViaBossBar.java index a9d80e08d..236a85db9 100644 --- a/src/main/java/us/myles/ViaVersion/boss/ViaBossBar.java +++ b/src/main/java/us/myles/ViaVersion/boss/ViaBossBar.java @@ -12,8 +12,8 @@ import us.myles.ViaVersion.api.boss.BossColor; import us.myles.ViaVersion.api.boss.BossFlag; import us.myles.ViaVersion.api.boss.BossStyle; import us.myles.ViaVersion.packets.PacketType; -import us.myles.ViaVersion.transformers.OutgoingTransformer; import us.myles.ViaVersion.util.PacketUtil; +import us.myles.ViaVersion2.api.protocol1_9to1_8.Protocol1_9TO1_8; import java.util.*; @@ -192,7 +192,7 @@ public class ViaBossBar implements BossBar { } private String fixJson(String text) { - return OutgoingTransformer.fixJson(text); + return Protocol1_9TO1_8.fixJson(text); } @RequiredArgsConstructor diff --git a/src/main/java/us/myles/ViaVersion/chunks/ChunkManager.java b/src/main/java/us/myles/ViaVersion/chunks/ChunkManager.java deleted file mode 100644 index cac027861..000000000 --- a/src/main/java/us/myles/ViaVersion/chunks/ChunkManager.java +++ /dev/null @@ -1,202 +0,0 @@ -package us.myles.ViaVersion.chunks; - -import com.google.common.collect.Lists; -import com.google.common.collect.Sets; -import io.netty.buffer.ByteBuf; -import io.netty.buffer.Unpooled; -import org.bukkit.Bukkit; -import us.myles.ViaVersion.ConnectionInfo; -import us.myles.ViaVersion.util.PacketUtil; -import us.myles.ViaVersion.util.ReflectionUtil; -import us.myles.ViaVersion.util.ReflectionUtil.ClassReflection; - -import java.nio.ByteBuffer; -import java.nio.ByteOrder; -import java.nio.ShortBuffer; -import java.util.BitSet; -import java.util.List; -import java.util.Set; -import java.util.logging.Level; - -public class ChunkManager { - /** - * Amount of sections in a chunk. - */ - private static final int SECTION_COUNT = 16; - /** - * size of each chunk section (16x16x16). - */ - private static final int SECTION_SIZE = 16; - /** - * Length of biome data. - */ - private static final int BIOME_DATA_LENGTH = 256; - - private final ConnectionInfo info; - private final Set loadedChunks = Sets.newConcurrentHashSet(); - private final Set bulkChunks = Sets.newConcurrentHashSet(); - - // Reflection - private static ClassReflection mapChunkBulkRef; - private static ClassReflection mapChunkRef; - - static { - try { - mapChunkBulkRef = new ClassReflection(ReflectionUtil.nms("PacketPlayOutMapChunkBulk")); - mapChunkRef = new ClassReflection(ReflectionUtil.nms("PacketPlayOutMapChunk")); - } catch(Exception e) { - Bukkit.getLogger().log(Level.WARNING, "Failed to initialise chunk reflection", e); - } - } - - public ChunkManager(ConnectionInfo info) { - this.info = info; - } - - /** - * Transform a map chunk bulk in to separate map chunk packets. - * These packets are registered so that they will never be seen as unload packets. - * - * @param packet to transform - * @return List of chunk data packets - */ - - - /** - * Read chunk from 1.8 chunk data. - * - * @param input data - * @return Chunk - */ - public Chunk readChunk(ByteBuf input) { - // Primary data - int chunkX = input.readInt(); - int chunkZ = input.readInt(); - long chunkHash = toLong(chunkX, chunkZ); - boolean groundUp = input.readByte() != 0; - int bitmask = input.readUnsignedShort(); - int dataLength = PacketUtil.readVarInt(input); - - // Data to be read - BitSet usedSections = new BitSet(16); - ChunkSection[] sections = new ChunkSection[16]; - byte[] biomeData = null; - - // Calculate section count from bitmask - for(int i = 0; i < 16; i++) { - if((bitmask & (1 << i)) != 0) { - usedSections.set(i); - } - } - int sectionCount = usedSections.cardinality(); // the amount of sections set - - // If the chunk is from a chunk bulk, it is never an unload packet - // Other wise, if it has no data, it is :) - boolean isBulkPacket = bulkChunks.remove(chunkHash); - if(sectionCount == 0 && groundUp && !isBulkPacket && loadedChunks.contains(chunkHash)) { - // This is a chunk unload packet - loadedChunks.remove(chunkHash); - return new Chunk(chunkX, chunkZ); - } - - int startIndex = input.readerIndex(); - loadedChunks.add(chunkHash); // mark chunk as loaded - - // Read blocks - for(int i = 0; i < SECTION_COUNT; i++) { - if(!usedSections.get(i)) continue; // Section not set - ChunkSection section = new ChunkSection(); - sections[i] = section; - - // Read block data and convert to short buffer - byte[] blockData = new byte[ChunkSection.SIZE * 2]; - input.readBytes(blockData); - ShortBuffer blockBuf = ByteBuffer.wrap(blockData).order(ByteOrder.LITTLE_ENDIAN).asShortBuffer(); - - for(int j = 0; j < ChunkSection.SIZE; j++) { - int mask = blockBuf.get(); - int type = mask >> 4; - int data = mask & 0xF; - section.setBlock(j, type, data); - } - } - - // Read block light - for(int i = 0; i < SECTION_COUNT; i++) { - if(!usedSections.get(i)) continue; // Section not set, has no light - byte[] blockLightArray = new byte[ChunkSection.LIGHT_LENGTH]; - input.readBytes(blockLightArray); - sections[i].setBlockLight(blockLightArray); - } - - // Read sky light - int bytesLeft = dataLength - (input.readerIndex() - startIndex); - if(bytesLeft >= ChunkSection.LIGHT_LENGTH) { - for(int i = 0; i < SECTION_COUNT; i++) { - if(!usedSections.get(i)) continue; // Section not set, has no light - byte[] skyLightArray = new byte[ChunkSection.LIGHT_LENGTH]; - input.readBytes(skyLightArray); - sections[i].setSkyLight(skyLightArray); - bytesLeft -= ChunkSection.LIGHT_LENGTH; - } - } - - // Read biome data - if(bytesLeft >= BIOME_DATA_LENGTH) { - biomeData = new byte[BIOME_DATA_LENGTH]; - input.readBytes(biomeData); - bytesLeft -= BIOME_DATA_LENGTH; - } - - // Check remaining bytes - if(bytesLeft > 0) { - Bukkit.getLogger().log(Level.WARNING, bytesLeft + " Bytes left after reading chunk! (" + groundUp + ")"); - } - - // Return chunk - return new Chunk(chunkX, chunkZ, groundUp, bitmask, sections, biomeData); - } - - /** - * Write chunk over 1.9 protocol. - * - * @param chunk chunk - * @param output output - */ - public void writeChunk(Chunk chunk, ByteBuf output) { - if(chunk.isUnloadPacket()) { - output.clear(); - PacketUtil.writeVarInt(0x1D, output); - } - - // Write primary info - output.writeInt(chunk.getX()); - output.writeInt(chunk.getZ()); - if(chunk.isUnloadPacket()) return; - output.writeByte(chunk.isGroundUp() ? 0x01 : 0x00); - PacketUtil.writeVarInt(chunk.getPrimaryBitmask(), output); - - ByteBuf buf = Unpooled.buffer(); - for(int i = 0; i < SECTION_COUNT; i++) { - ChunkSection section = chunk.getSections()[i]; - if(section == null) continue; // Section not set - section.writeBlocks(buf); - section.writeBlockLight(buf); - if(!section.hasSkyLight()) continue; // No sky light, we're done here. - section.writeSkyLight(buf); - } - buf.readerIndex(0); - PacketUtil.writeVarInt(buf.readableBytes() + (chunk.hasBiomeData() ? 256 : 0), output); - output.writeBytes(buf); - buf.release(); // release buffer - - // Write biome data - if(chunk.hasBiomeData()) { - output.writeBytes(chunk.getBiomeData()); - } - } - - private static long toLong(int msw, int lsw) { - return ((long) msw << 32) + lsw - -2147483648L; - } -} diff --git a/src/main/java/us/myles/ViaVersion/metadata/MetadataRewriter.java b/src/main/java/us/myles/ViaVersion/metadata/MetadataRewriter.java deleted file mode 100644 index 4d456af73..000000000 --- a/src/main/java/us/myles/ViaVersion/metadata/MetadataRewriter.java +++ /dev/null @@ -1,216 +0,0 @@ -package us.myles.ViaVersion.metadata; - -import io.netty.buffer.ByteBuf; -import lombok.Getter; -import lombok.Setter; -import org.bukkit.entity.EntityType; -import org.bukkit.util.EulerAngle; -import org.bukkit.util.Vector; -import us.myles.ViaVersion.ViaVersionPlugin; -import us.myles.ViaVersion.api.ViaVersion; -import us.myles.ViaVersion.slot.ItemSlotRewriter; -import us.myles.ViaVersion.slot.ItemSlotRewriter.ItemStack; -import us.myles.ViaVersion.transformers.OutgoingTransformer; -import us.myles.ViaVersion.util.PacketUtil; - -import java.util.ArrayList; -import java.util.List; -import java.util.UUID; - -public class MetadataRewriter { - - public static void writeMetadata1_9(EntityType type, List list, ByteBuf output) { - short id = -1; - int data = -1; - for (Entry entry : list) { - MetaIndex metaIndex = entry.index; - try { - 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 - output.writeByte(metaIndex.getNewIndex()); - output.writeByte(metaIndex.getNewType().getTypeID()); - } - Object value = entry.value; - switch (metaIndex.getNewType()) { - case Byte: - // convert from int, byte - if (metaIndex.getOldType() == Type.Byte) { - output.writeByte((Byte) value); - } - if (metaIndex.getOldType() == Type.Int) { - output.writeByte(((Integer) value).byteValue()); - } - // After writing the last one - if (metaIndex == MetaIndex.ENTITY_STATUS && type == EntityType.PLAYER) { - output.writeByte(MetaIndex.PLAYER_HAND.getNewIndex()); - output.writeByte(MetaIndex.PLAYER_HAND.getNewType().getTypeID()); - if ((((Byte) value) & 0x10) == 0x10) { // Player eating/aiming/drinking - output.writeByte(1); // Using main hand - } else { - output.writeByte(0); // Not using any hand to stop animation - } - } - break; - case OptUUID: - String owner = (String) value; - UUID toWrite = null; - if (owner.length() != 0) { - try { - toWrite = UUID.fromString(owner); - } catch (Exception ignored) { - } - } - output.writeBoolean(toWrite != null); - if (toWrite != null) - PacketUtil.writeUUID(toWrite, output); - break; - case BlockID: - // if we have both sources :)) - if (metaIndex.getOldType() == Type.Byte) { - data = (Byte) value; - } - if (metaIndex.getOldType() == Type.Short) { - id = (Short) value; - } - if (id != -1 && data != -1) { - int combined = id << 4 | data; - data = -1; - id = -1; - PacketUtil.writeVarInt(combined, output); - } - break; - case VarInt: - // convert from int, short, byte - if (metaIndex.getOldType() == Type.Byte) { - PacketUtil.writeVarInt(((Byte) value).intValue(), output); - } - if (metaIndex.getOldType() == Type.Short) { - PacketUtil.writeVarInt(((Short) value).intValue(), output); - } - if (metaIndex.getOldType() == Type.Int) { - PacketUtil.writeVarInt((Integer) value, output); - } - break; - case Float: - output.writeFloat((Float) value); - break; - case String: - PacketUtil.writeString((String) value, output); - break; - case Boolean: - if (metaIndex == MetaIndex.AGEABLE_AGE) - output.writeBoolean((Byte) value < 0); - else - output.writeBoolean((Byte) value != 0); - break; - case Slot: - ItemStack item = (ItemStack) value; - ItemSlotRewriter.fixIdsFrom1_8To1_9(item); - ItemSlotRewriter.writeItemStack(item, output); - break; - case Position: - Vector vector = (Vector) value; - output.writeInt((int) vector.getX()); - output.writeInt((int) vector.getY()); - output.writeInt((int) vector.getZ()); - break; - case Vector3F: - EulerAngle angle = (EulerAngle) value; - output.writeFloat((float) angle.getX()); - output.writeFloat((float) angle.getY()); - output.writeFloat((float) angle.getZ()); - break; - case Chat: - PacketUtil.writeString(OutgoingTransformer.fixJson((String) value), output); - break; - default: - System.out.println("[Out] Unhandled MetaDataType: " + metaIndex.getNewType()); - break; - } - } - } catch (Exception e) { - if (!((ViaVersionPlugin) ViaVersion.getInstance()).isSuppressMetadataErrors()) { - 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.oldID); - else - System.out.println("An error occurred with entity meta data for UNKNOWN_ENTITY OldID: " + entry.oldID); - if (metaIndex != null) { - System.out.println("Old ID: " + metaIndex.getIndex() + " New ID: " + metaIndex.getNewIndex()); - System.out.println("Old Type: " + metaIndex.getOldType() + " New Type: " + metaIndex.getNewType()); - } - e.printStackTrace(); - } - } - } - output.writeByte(255); - } - - public static List readMetadata1_8(EntityType entityType, ByteBuf buf) { - List entries = new ArrayList<>(); - byte item; - while ((item = buf.readByte()) != 127) { - Type type = Type.byId((item & 0xE0) >> 5); - int id = item & 0x1F; - MetaIndex index = MetaIndex.getIndex(entityType, id); - switch (type) { - case Byte: - entries.add(new Entry(index, buf.readByte(), id)); - break; - case Short: - entries.add(new Entry(index, buf.readShort(), id)); - break; - case Int: - entries.add(new Entry(index, buf.readInt(), id)); - break; - case Float: - entries.add(new Entry(index, buf.readFloat(), id)); - break; - case String: - entries.add(new Entry(index, PacketUtil.readString(buf), id)); - break; - case Slot: { - try { - entries.add(new Entry(index, ItemSlotRewriter.readItemStack(buf), id)); - } catch (Exception e) { - e.printStackTrace(); - } - } - break; - case Position: { - int x = buf.readInt(); - int y = buf.readInt(); - int z = buf.readInt(); - entries.add(new Entry(index, new Vector(x, y, z), id)); - break; - } - case Rotation: { - float x = buf.readFloat(); - float y = buf.readFloat(); - float z = buf.readFloat(); - entries.add(new Entry(index, new EulerAngle(x, y, z), id)); - break; - } - default: - System.out.println("[Out] Unhandled MetaDataType: " + type); - break; - } - } - return entries; - } - - @Getter - @Setter - public static final class Entry { - - private final int oldID; - private MetaIndex index; - private Object value; - - public Entry(MetaIndex index, Object value, int id) { - this.index = index; - this.value = value; - this.oldID = id; - } - } -} diff --git a/src/main/java/us/myles/ViaVersion/slot/ItemSlotRewriter.java b/src/main/java/us/myles/ViaVersion/slot/ItemSlotRewriter.java deleted file mode 100644 index ef04eb164..000000000 --- a/src/main/java/us/myles/ViaVersion/slot/ItemSlotRewriter.java +++ /dev/null @@ -1,322 +0,0 @@ -package us.myles.ViaVersion.slot; - -import io.netty.buffer.ByteBuf; -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; -import org.spacehq.opennbt.tag.builtin.Tag; -import us.myles.ViaVersion.CancelException; -import us.myles.ViaVersion.transformers.OutgoingTransformer; -import us.myles.ViaVersion.util.PacketUtil; - -import java.io.IOException; -import java.util.Collections; -import java.util.HashMap; -import java.util.Map; - -public class ItemSlotRewriter { - - private static final Map ENTTIY_NAME_TO_ID = new HashMap<>(); - private static final Map ENTTIY_ID_TO_NAME = new HashMap<>(); - private static final Map POTION_NAME_TO_ID = new HashMap<>(); - private static final Map POTION_ID_TO_NAME = new HashMap<>(); - - static { - /* Entities */ - registerEntity(1, "Item"); - registerEntity(2, "XPOrb"); - registerEntity(7, "ThrownEgg"); - registerEntity(8, "LeashKnot"); - registerEntity(9, "Painting"); - registerEntity(10, "Arrow"); - registerEntity(11, "Snowball"); - registerEntity(12, "Fireball"); - registerEntity(13, "SmallFireball"); - registerEntity(14, "ThrownEnderpearl"); - registerEntity(15, "EyeOfEnderSignal"); - registerEntity(16, "ThrownPotion"); - registerEntity(17, "ThrownExpBottle"); - registerEntity(18, "ItemFrame"); - registerEntity(19, "WitherSkull"); - registerEntity(20, "PrimedTnt"); - registerEntity(21, "FallingSand"); - registerEntity(22, "FireworksRocketEntity"); - registerEntity(30, "ArmorStand"); - registerEntity(40, "MinecartCommandBlock"); - registerEntity(41, "Boat"); - registerEntity(42, "MinecartRideable"); - registerEntity(43, "MinecartChest"); - registerEntity(44, "MinecartFurnace"); - registerEntity(45, "MinecartTNT"); - registerEntity(46, "MinecartHopper"); - registerEntity(47, "MinecartSpawner"); - registerEntity(48, "Mob"); - registerEntity(49, "Monster"); - registerEntity(50, "Creeper"); - registerEntity(51, "Skeleton"); - registerEntity(52, "Spider"); - registerEntity(53, "Giant"); - registerEntity(54, "Zombie"); - registerEntity(55, "Slime"); - registerEntity(56, "Ghast"); - registerEntity(57, "PigZombie"); - registerEntity(58, "Enderman"); - registerEntity(59, "CaveSpider"); - registerEntity(60, "Silverfish"); - registerEntity(61, "Blaze"); - registerEntity(62, "LavaSlime"); - registerEntity(63, "EnderDragon"); - registerEntity(64, "WitherBoss"); - registerEntity(65, "Bat"); - registerEntity(66, "Witch"); - registerEntity(67, "Endermite"); - registerEntity(68, "Guardian"); - registerEntity(90, "Pig"); - registerEntity(91, "Sheep"); - registerEntity(92, "Cow"); - registerEntity(93, "Chicken"); - registerEntity(94, "Squid"); - registerEntity(95, "Wolf"); - registerEntity(96, "MushroomCow"); - registerEntity(97, "SnowMan"); - registerEntity(98, "Ozelot"); - registerEntity(99, "VillagerGolem"); - registerEntity(100, "EntityHorse"); - registerEntity(101, "Rabbit"); - registerEntity(120, "Villager"); - registerEntity(200, "EnderCrystal"); - - /* Potions */ - registerPotion(0, "water"); - registerPotion(64, "mundane"); - registerPotion(32, "thick"); - registerPotion(16, "awkward"); - - registerPotion(8198, "night_vision"); - registerPotion(8262, "long_night_vision"); - - registerPotion(8206, "invisibility"); - registerPotion(8270, "long_invisibility"); - - registerPotion(8203, "leaping"); - registerPotion(8267, "long_leaping"); - registerPotion(8235, "strong_leaping"); - - registerPotion(8195, "fire_resistance"); - registerPotion(8259, "long_fire_resistance"); - - registerPotion(8194, "swiftness"); - registerPotion(8258, "long_swiftness"); - registerPotion(8226, "strong_swiftness"); - - registerPotion(8202, "slowness"); - registerPotion(8266, "long_slowness"); - - registerPotion(8205, "water_breathing"); - registerPotion(8269, "long_water_breathing"); - - registerPotion(8197, "healing"); - registerPotion(8229, "strong_healing"); - - registerPotion(8204, "harming"); - registerPotion(8236, "strong_harming"); - - registerPotion(8196, "poison"); - registerPotion(8260, "long_poison"); - registerPotion(8228, "strong_poison"); - - registerPotion(8193, "regeneration"); - registerPotion(8257, "long_regeneration"); - registerPotion(8225, "strong_regeneration"); - - registerPotion(8201, "strength"); - registerPotion(8265, "long_strength"); - registerPotion(8233, "strong_strength"); - - registerPotion(8200, "weakness"); - registerPotion(8264, "long_weakness"); - - } - - public static void rewrite1_9To1_8(ByteBuf input, ByteBuf output) throws CancelException { - try { - ItemStack item = readItemStack(input); - fixIdsFrom1_9To1_8(item); - writeItemStack(item, output); - } catch (Exception e) { - System.out.println("Error while rewriting an item slot."); - e.printStackTrace(); - throw new CancelException(); - } - } - - public static void rewrite1_8To1_9(ByteBuf input, ByteBuf output) throws CancelException { - try { - ItemStack item = readItemStack(input); - fixIdsFrom1_8To1_9(item); - writeItemStack(item, output); - } catch (Exception e) { - System.out.println("Error while rewriting an item slot."); - e.printStackTrace(); - throw new CancelException(); - } - } - - public static void fixIdsFrom1_9To1_8(ItemStack item) { - if (item != null) { - if (item.id == Material.MONSTER_EGG.getId() && item.data == 0) { - CompoundTag tag = item.tag; - int data = 0; - if (tag != null && tag.get("EntityTag") instanceof CompoundTag) { - CompoundTag entityTag = tag.get("EntityTag"); - if (entityTag.get("id") instanceof StringTag) { - StringTag id = entityTag.get("id"); - if (ENTTIY_NAME_TO_ID.containsKey(id.getValue())) - data = ENTTIY_NAME_TO_ID.get(id.getValue()); - } - } - item.tag = null; - item.data = (short) data; - } - if (item.id == Material.POTION.getId()) { - CompoundTag tag = item.tag; - int data = 0; - if (tag != null && tag.get("Potion") instanceof StringTag) { - StringTag potion = tag.get("Potion"); - String potionName = potion.getValue().replace("minecraft:", ""); - if (POTION_NAME_TO_ID.containsKey(potionName)) { - data = POTION_NAME_TO_ID.get(potionName); - } - } - item.tag = null; - item.data = (short) data; - } - if (item.id == 438) { - CompoundTag tag = item.tag; - int data = 0; - item.id = (short) Material.POTION.getId(); - if (tag != null && tag.get("Potion") instanceof StringTag) { - StringTag potion = tag.get("Potion"); - String potionName = potion.getValue().replace("minecraft:", ""); - if (POTION_NAME_TO_ID.containsKey(potionName)) { - data = POTION_NAME_TO_ID.get(potionName) + 8192; - } - } - item.tag = null; - item.data = (short) data; - } - } - } - - public static void fixIdsFrom1_8To1_9(ItemStack item) { - if (item != null) { - if (item.id == Material.MONSTER_EGG.getId() && item.data != 0) { - CompoundTag tag = item.tag; - if (tag == null) { - tag = new CompoundTag("tag"); - } - CompoundTag entityTag = new CompoundTag("EntityTag"); - if (ENTTIY_ID_TO_NAME.containsKey((int) item.data)) { - StringTag id = new StringTag("id", ENTTIY_ID_TO_NAME.get((int) item.data)); - entityTag.put(id); - tag.put(entityTag); - } - item.tag = tag; - item.data = 0; - } - if (item.id == Material.POTION.getId()) { - CompoundTag tag = item.tag; - if (tag == null) { - tag = new CompoundTag("tag"); - } - if (item.data >= 16384) { - item.id = 438; // splash id - item.data = (short) (item.data - 8192); - } - if (POTION_ID_TO_NAME.containsKey((int) item.data)) { - String name = POTION_ID_TO_NAME.get((int) item.data); - StringTag potion = new StringTag("Potion", "minecraft:" + name); - tag.put(potion); - } - item.tag = tag; - item.data = 0; - } - if (item.id == Material.WRITTEN_BOOK.getId()) { - CompoundTag tag = item.tag; - if (tag == null) { - tag = new CompoundTag("tag"); - } - ListTag pages = tag.get("pages"); - if (pages == null) { - pages = new ListTag("pages", Collections.singletonList(new StringTag(OutgoingTransformer.fixJson("")))); - tag.put(pages); - item.tag = tag; - return; - } - - for (int i = 0; i < pages.size(); i++) { - if (!(pages.get(i) instanceof StringTag)) - continue; - StringTag page = pages.get(i); - page.setValue(OutgoingTransformer.fixJson(page.getValue())); - } - item.tag = tag; - } - } - } - - public static ItemStack readItemStack(ByteBuf input) throws IOException { - short id = input.readShort(); - if (id < 0) { - - return null; - } else { - ItemStack item = new ItemStack(); - item.id = id; - item.amount = input.readByte(); - item.data = input.readShort(); - item.tag = PacketUtil.readNBT(input); - return item; - } - } - - public static void writeItemStack(ItemStack item, ByteBuf output) throws IOException { - if (item == null) { - output.writeShort(-1); - } else { - output.writeShort(item.id); - output.writeByte(item.amount); - output.writeShort(item.data); - PacketUtil.writeNBT(output, item.tag); - } - } - - private static void registerEntity(Integer id, String name) { - ENTTIY_ID_TO_NAME.put(id, name); - ENTTIY_NAME_TO_ID.put(name, id); - } - - private static void registerPotion(Integer id, String name) { - POTION_ID_TO_NAME.put(id, name); - POTION_NAME_TO_ID.put(name, id); - } - - public static class ItemStack { - - public short id; - public byte amount; - public short data; - public CompoundTag tag; - - public static ItemStack fromBukkit(org.bukkit.inventory.ItemStack stack) { - if(stack == null) return null; - ItemStack item = new ItemStack(); - item.id = (short) stack.getTypeId(); - item.amount = (byte) stack.getAmount(); - item.data = stack.getData().getData(); - // TODO: nbt - return item; - } - } -} diff --git a/src/main/java/us/myles/ViaVersion/transformers/IncomingTransformer.java b/src/main/java/us/myles/ViaVersion/transformers/IncomingTransformer.java deleted file mode 100644 index 3a91b088c..000000000 --- a/src/main/java/us/myles/ViaVersion/transformers/IncomingTransformer.java +++ /dev/null @@ -1,361 +0,0 @@ -package us.myles.ViaVersion.transformers; - -import io.netty.buffer.ByteBuf; -import io.netty.buffer.Unpooled; -import org.bukkit.Material; -import org.bukkit.inventory.ItemStack; -import us.myles.ViaVersion.CancelException; -import us.myles.ViaVersion.ConnectionInfo; -import us.myles.ViaVersion.ViaVersionPlugin; -import us.myles.ViaVersion.api.ViaVersion; -import us.myles.ViaVersion.packets.PacketType; -import us.myles.ViaVersion.packets.State; -import us.myles.ViaVersion.slot.ItemSlotRewriter; -import us.myles.ViaVersion.util.PacketUtil; - -import java.io.IOException; - -public class IncomingTransformer { - private final ViaVersionPlugin plugin = (ViaVersionPlugin) ViaVersion.getInstance(); - private final ConnectionInfo info; - private boolean startedBlocking = false; - - public IncomingTransformer(ConnectionInfo info) { - this.info = info; - } - - public void transform(int packetID, ByteBuf input, ByteBuf output) throws CancelException { - PacketType packet = PacketType.getIncomingPacket(info.getState(), packetID); - if (packet == null) { - System.out.println("incoming packet not found " + packetID + " state: " + info.getState()); - throw new RuntimeException("Incoming Packet not found? " + packetID + " State: " + info.getState() + " Version: " + info.getProtocol()); - } - int original = packetID; - - if (packet.getPacketID() != -1) { - packetID = packet.getPacketID(); - } - if (plugin.isDebug()) { - if (packet != PacketType.PLAY_PLAYER_POSITION_LOOK_REQUEST && packet != PacketType.PLAY_KEEP_ALIVE_REQUEST && packet != PacketType.PLAY_PLAYER_POSITION_REQUEST && packet != PacketType.PLAY_PLAYER_LOOK_REQUEST) { - System.out.println("Direction " + packet.getDirection().name() + " Packet Type: " + packet + " New ID: " + packetID + " Original: " + original + " Size: " + input.readableBytes()); - } - } - if (packet == PacketType.PLAY_TP_CONFIRM || packet == PacketType.PLAY_VEHICLE_MOVE_REQUEST) { //TODO handle client-sided horse riding - throw new CancelException(); - } - // Handle movement increment - // Update idle status (player, position, look, positionandlook) - if(packet == PacketType.PLAY_PLAYER || packet == PacketType.PLAY_PLAYER_POSITION_REQUEST || packet == PacketType.PLAY_PLAYER_LOOK_REQUEST || packet == PacketType.PLAY_PLAYER_POSITION_LOOK_REQUEST) { - info.incrementIdlePacket(); - } - PacketUtil.writeVarInt(packetID, output); - if (packet == PacketType.HANDSHAKE) { - int protVer = PacketUtil.readVarInt(input); - info.setProtocol(protVer); - PacketUtil.writeVarInt(protVer <= 102 ? protVer : 47, output); // pretend to be older - - if (protVer <= 102) { - // not 1.9, remove pipes - info.setActive(false); - } - String serverAddress = PacketUtil.readString(input); - PacketUtil.writeString(serverAddress, output); - - int serverPort = input.readUnsignedShort(); - output.writeShort(serverPort); - - int nextState = PacketUtil.readVarInt(input); - PacketUtil.writeVarInt(nextState, output); - - if (nextState == 1) { - info.setState(State.STATUS); - } - if (nextState == 2) { - info.setState(State.LOGIN); - } - return; - } - if (packet == PacketType.PLAY_UPDATE_SIGN_REQUEST) { - Long location = input.readLong(); - output.writeLong(location); - for (int i = 0; i < 4; i++) { - String line = PacketUtil.readString(input); - line = OutgoingTransformer.fixJson(line); - PacketUtil.writeString(line, output); - } - return; - } - if (packet == PacketType.PLAY_TAB_COMPLETE_REQUEST) { - String text = PacketUtil.readString(input); - PacketUtil.writeString(text, output); - input.readBoolean(); // assume command - output.writeBytes(input); - return; - } - if (packet == PacketType.PLAY_PLAYER_DIGGING) { - int status = input.readByte() & 0xFF; // unsign - if (status == 5 && startedBlocking) { - // stopped blocking - startedBlocking = false; - sendSecondHandItem(null); - } - if (status == 6) { // item swap - throw new CancelException(); - } - output.writeByte(status); - // write remaining bytes - Long position = input.readLong(); - output.writeLong(position); - - int face = input.readUnsignedByte(); - output.writeByte(face); - return; - } - if (packet == PacketType.PLAY_HELD_ITEM_CHANGE_REQUEST) { - if (startedBlocking) { - // stopped blocking - startedBlocking = false; - sendSecondHandItem(null); - } - } - if (packet == PacketType.PLAY_CLICK_WINDOW) { - // if placed in new slot, reject :) - int windowID = input.readUnsignedByte(); - short slot = input.readShort(); - - byte button = input.readByte(); - short action = input.readShort(); - int mode = input.readByte(); - - // if the action is on an elytra armour slot - boolean throwItem = (slot == 45 && windowID == 0); - - if (info.getOpenWindow() != null && windowID > 0) { - if (info.getOpenWindow().equals("minecraft:brewing_stand")) { - if (slot == 4) { - // throw - throwItem = true; - } - if (slot > 4) - slot = (short) (slot - 1); - } - } - if (throwItem) { - ByteBuf buf = info.getChannel().alloc().buffer(); - PacketUtil.writeVarInt(PacketType.PLAY_SET_SLOT.getNewPacketID(), buf); - buf.writeByte(windowID); - buf.writeShort(slot); - buf.writeShort(-1); // empty - info.sendRawPacket(buf); - // Continue the packet simulating throw - mode = 0; - button = 0; - slot = -999; - } - output.writeByte(windowID); - output.writeShort(slot); - output.writeByte(button); - output.writeShort(action); - output.writeByte(mode); - ItemSlotRewriter.rewrite1_9To1_8(input, output); - return; - } - if (packet == PacketType.PLAY_CLOSE_WINDOW_REQUEST) { - info.closeWindow(); - } - if (packet == PacketType.PLAY_CLIENT_SETTINGS) { - String locale = PacketUtil.readString(input); - PacketUtil.writeString(locale, output); - - byte view = input.readByte(); - output.writeByte(view); - - int chatMode = PacketUtil.readVarInt(input); - output.writeByte(chatMode); - - boolean chatColours = input.readBoolean(); - output.writeBoolean(chatColours); - - short skinParts = input.readUnsignedByte(); - output.writeByte(skinParts); - - PacketUtil.readVarInt(input); - return; - } - if (packet == PacketType.PLAY_ANIMATION_REQUEST) { - PacketUtil.readVarInt(input); - return; - } - if (packet == PacketType.PLAY_ENTITY_ACTION) { - int playerId = PacketUtil.readVarInt(input); - int action = PacketUtil.readVarInt(input); - int jump = PacketUtil.readVarInt(input); - if (action == 6 || action == 8) //Ignore stop jumping / start elytra flying - throw new CancelException(); - if (action == 7) //Change open horse inventory to the 1.8 value - action = 6; - PacketUtil.writeVarInt(playerId, output); - PacketUtil.writeVarInt(action, output); - PacketUtil.writeVarInt(jump, output); - return; - } - if (packet == PacketType.PLAY_USE_ENTITY) { - int target = PacketUtil.readVarInt(input); - PacketUtil.writeVarInt(target, output); - - int type = PacketUtil.readVarInt(input); - PacketUtil.writeVarInt(type, output); - if (type == 2) { - float targetX = input.readFloat(); - output.writeFloat(targetX); - float targetY = input.readFloat(); - output.writeFloat(targetY); - float targetZ = input.readFloat(); - output.writeFloat(targetZ); - } - if (type == 0 || type == 2) { - PacketUtil.readVarInt(input); - } - return; - } - if (packet == PacketType.PLAY_PLUGIN_MESSAGE_REQUEST) { - String name = PacketUtil.readString(input); - PacketUtil.writeString(name, output); - byte[] b = new byte[input.readableBytes()]; - input.readBytes(b); - // patch books - switch (name) { - case "MC|BSign": { - ByteBuf in = Unpooled.wrappedBuffer(b); - try { - ItemSlotRewriter.ItemStack stack = ItemSlotRewriter.readItemStack(in); - if (stack != null) - stack.id = (short) Material.WRITTEN_BOOK.getId(); - // write - ItemSlotRewriter.writeItemStack(stack, output); - } catch (IOException e) { - e.printStackTrace(); - } - return; - } - case "MC|AutoCmd": { - ByteBuf in = Unpooled.wrappedBuffer(b); - int x = in.readInt(); - int y = in.readInt(); - int z = in.readInt(); - String command = PacketUtil.readString(in); - boolean flag = in.readBoolean(); - - output.clear(); - PacketUtil.writeVarInt(PacketType.PLAY_PLUGIN_MESSAGE_REQUEST.getPacketID(), output); - PacketUtil.writeString("MC|AdvCdm", output); - output.writeByte(0); - output.writeInt(x); - output.writeInt(y); - output.writeInt(z); - PacketUtil.writeString(command, output); - output.writeBoolean(flag); - return; - } - case "MC|AdvCmd": - output.clear(); - PacketUtil.writeVarInt(PacketType.PLAY_PLUGIN_MESSAGE_REQUEST.getPacketID(), output); - PacketUtil.writeString("MC|AdvCdm", output); - output.writeBytes(b); - break; - } - output.writeBytes(b); - } - if (packet == PacketType.PLAY_PLAYER_BLOCK_PLACEMENT) { - Long position = input.readLong(); - output.writeLong(position); - int face = PacketUtil.readVarInt(input); - output.writeByte(face); - PacketUtil.readVarInt(input); - - ItemStack inHand = plugin.getHandItem(info); - try { - ItemSlotRewriter.ItemStack item = ItemSlotRewriter.ItemStack.fromBukkit(inHand); - ItemSlotRewriter.fixIdsFrom1_9To1_8(item); - ItemSlotRewriter.writeItemStack(item, output); - } catch (Exception e) { - e.printStackTrace(); - } - short curX = input.readUnsignedByte(); - output.writeByte(curX); - short curY = input.readUnsignedByte(); - output.writeByte(curY); - short curZ = input.readUnsignedByte(); - output.writeByte(curZ); - return; - } - if (packet == PacketType.PLAY_USE_ITEM) { - int hand = PacketUtil.readVarInt(input); - output.clear(); - PacketUtil.writeVarInt(PacketType.PLAY_PLAYER_BLOCK_PLACEMENT.getPacketID(), output); - // Simulate using item :) - output.writeLong(-1L); - output.writeByte(255); - // write item in hand - ItemStack inHand = plugin.getHandItem(info); - if (inHand != null && plugin.isShieldBlocking()) { - if (inHand.getType().name().endsWith("SWORD")) { - // blocking? - if (hand == 0) { - if (!startedBlocking) { - startedBlocking = true; - ItemSlotRewriter.ItemStack shield = new ItemSlotRewriter.ItemStack(); - shield.id = 442; - shield.amount = 1; - shield.data = 0; - sendSecondHandItem(shield); - } - throw new CancelException(); - } - } - } - try { - ItemSlotRewriter.ItemStack item = ItemSlotRewriter.ItemStack.fromBukkit(inHand); - ItemSlotRewriter.fixIdsFrom1_9To1_8(item); - ItemSlotRewriter.writeItemStack(item, output); - } catch (Exception e) { - e.printStackTrace(); - } - - output.writeByte(0); //Is zero in 1.8, not -1 - output.writeByte(0); - output.writeByte(0); - return; - } - if (packet == PacketType.PLAY_CREATIVE_INVENTORY_ACTION) { - short slot = input.readShort(); - if (slot == 45) { - ByteBuf buf = info.getChannel().alloc().buffer(); - PacketUtil.writeVarInt(PacketType.PLAY_SET_SLOT.getNewPacketID(), buf); - buf.writeByte(0); - buf.writeShort(slot); - buf.writeShort(-1); // empty - info.sendRawPacket(buf); - // Continue the packet simulating throw - slot = -999; - } - output.writeShort(slot); - ItemSlotRewriter.rewrite1_9To1_8(input, output); - } - output.writeBytes(input); - } - - private void sendSecondHandItem(ItemSlotRewriter.ItemStack o) { - ByteBuf buf = info.getChannel().alloc().buffer(); - PacketUtil.writeVarInt(PacketType.PLAY_ENTITY_EQUIPMENT.getNewPacketID(), buf); - PacketUtil.writeVarInt(info.getEntityID(), buf); - PacketUtil.writeVarInt(1, buf); // slot - // write shield - try { - ItemSlotRewriter.writeItemStack(o, buf); - } catch (IOException e) { - e.printStackTrace(); - } - info.sendRawPacket(buf); - } -} diff --git a/src/main/java/us/myles/ViaVersion/transformers/OutgoingTransformer.java b/src/main/java/us/myles/ViaVersion/transformers/OutgoingTransformer.java deleted file mode 100644 index bf3234e9a..000000000 --- a/src/main/java/us/myles/ViaVersion/transformers/OutgoingTransformer.java +++ /dev/null @@ -1,946 +0,0 @@ -package us.myles.ViaVersion.transformers; - -import com.google.gson.Gson; -import com.google.gson.GsonBuilder; -import com.google.gson.JsonObject; -import io.netty.buffer.ByteBuf; -import org.bukkit.Material; -import org.bukkit.entity.EntityType; -import org.spacehq.opennbt.tag.builtin.CompoundTag; -import org.spacehq.opennbt.tag.builtin.StringTag; -import us.myles.ViaVersion.CancelException; -import us.myles.ViaVersion.ConnectionInfo; -import us.myles.ViaVersion.ViaVersionPlugin; -import us.myles.ViaVersion.api.ViaVersion; -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.chunks.Chunk; -import us.myles.ViaVersion.chunks.ChunkManager; -import us.myles.ViaVersion.metadata.MetaIndex; -import us.myles.ViaVersion.metadata.MetadataRewriter; -import us.myles.ViaVersion.metadata.MetadataRewriter.Entry; -import us.myles.ViaVersion.packets.PacketType; -import us.myles.ViaVersion.packets.State; -import us.myles.ViaVersion.slot.ItemSlotRewriter; -import us.myles.ViaVersion.sounds.SoundEffect; -import us.myles.ViaVersion.util.EntityUtil; -import us.myles.ViaVersion.util.PacketUtil; - -import java.io.IOException; -import java.util.*; - -import static us.myles.ViaVersion.util.PacketUtil.*; - - -public class OutgoingTransformer { - private static Gson gson = new GsonBuilder().create(); - - private final ViaVersionPlugin plugin = (ViaVersionPlugin) ViaVersion.getInstance(); - - private final ConnectionInfo info; - private final Map uuidMap = new HashMap<>(); - private final Map clientEntityTypes = new HashMap<>(); - private final Map vehicleMap = new HashMap<>(); - private final Set validBlocking = new HashSet<>(); - private final Set knownHolograms = new HashSet<>(); - private final Map bossBarMap = new HashMap<>(); - private boolean autoTeam = false; - private boolean teamExists = false; - - public OutgoingTransformer(ConnectionInfo info) { - this.info = info; - } - - public static String fixJson(String line) { - if (line == null || line.equalsIgnoreCase("null")) { - line = "{\"text\":\"\"}"; - } else { - if ((!line.startsWith("\"") || !line.endsWith("\"")) && (!line.startsWith("{") || !line.endsWith("}"))) { - JsonObject jsonObject = new JsonObject(); - jsonObject.addProperty("text", line); - return gson.toJson(jsonObject); - } - if (line.startsWith("\"") && line.endsWith("\"")) { - line = "{\"text\":" + line + "}"; - } - } - try { - gson.fromJson(line, JsonObject.class); - } catch (Exception e) { - System.out.println("Invalid JSON String: \"" + line + "\" Please report this issue to the ViaVersion Github: " + e.getMessage()); - return "{\"text\":\"\"}"; - } - return line; - } - - public void transform(int packetID, ByteBuf input, ByteBuf output) throws CancelException { - PacketType packet = PacketType.getOutgoingPacket(info.getState(), packetID); - int original = packetID; - if (packet == null) { - throw new RuntimeException("Outgoing Packet not found? " + packetID + " State: " + info.getState() + " Version: " + info.getProtocol()); - } - if (packet.getPacketID() != -1) { - packetID = packet.getNewPacketID(); - } - if (ViaVersion.getInstance().isDebug()) { - if (packet != PacketType.PLAY_CHUNK_DATA && packet != PacketType.PLAY_KEEP_ALIVE && packet != PacketType.PLAY_TIME_UPDATE && (!packet.name().toLowerCase().contains("move") && !packet.name().toLowerCase().contains("look"))) { - System.out.println("Direction " + packet.getDirection().name() + " Packet Type: " + packet + " New ID: " + packetID + " Original: " + original + " Size: " + input.readableBytes()); - } - } - - // By default no transform - PacketUtil.writeVarInt(packetID, output); - if (packet == PacketType.PLAY_NAMED_SOUND_EFFECT) { - String name = PacketUtil.readString(input); - - SoundEffect effect = SoundEffect.getByName(name); - int catid = 0; - String newname = name; - if (effect != null) { - if (effect.isBreaksound()) { - throw new CancelException(); - } - catid = effect.getCategory().getId(); - newname = effect.getNewName(); - } - PacketUtil.writeString(newname, output); - PacketUtil.writeVarInt(catid, output); - output.writeBytes(input); - } - if (packet == PacketType.PLAY_EFFECT) { - int effectid = input.readInt(); - if (effectid >= 1000 && effectid < 2000 && effectid != 1005) //Sound effect - throw new CancelException(); - if (effectid == 1005) //Fix jukebox - effectid = 1010; - output.writeInt(effectid); - } - if (packet == PacketType.PLAY_ATTACH_ENTITY) { - int passenger = input.readInt(); - int vehicle = input.readInt(); - boolean lead = input.readBoolean(); - if (!lead) { - output.clear(); - writeVarInt(PacketType.PLAY_SET_PASSENGERS.getNewPacketID(), output); - if (vehicle == -1) { - if (!vehicleMap.containsKey(passenger)) - throw new CancelException(); - vehicle = vehicleMap.remove(passenger); - writeVarInt(vehicle, output); - writeVarIntArray(Collections.emptyList(), output); - } else { - writeVarInt(vehicle, output); - writeVarIntArray(Collections.singletonList(passenger), output); - vehicleMap.put(passenger, vehicle); - } - return; - } - output.writeInt(passenger); - output.writeInt(vehicle); - return; - } - if (packet == PacketType.PLAY_PLUGIN_MESSAGE) { - String name = PacketUtil.readString(input); - PacketUtil.writeString(name, output); - byte[] b = new byte[input.readableBytes()]; - input.readBytes(b); - // patch books - if (name.equals("MC|BOpen")) { - PacketUtil.writeVarInt(0, output); - } - output.writeBytes(b); - } - if (packet == PacketType.PLAY_DISCONNECT) { - String reason = readString(input); - writeString(fixJson(reason), output); - return; - } - if (packet == PacketType.PLAY_TITLE) { - int action = PacketUtil.readVarInt(input); - PacketUtil.writeVarInt(action, output); - if (action == 0 || action == 1) { - String text = PacketUtil.readString(input); - PacketUtil.writeString(fixJson(text), output); - } - output.writeBytes(input); - return; - } - if (packet == PacketType.PLAY_PLAYER_LIST_ITEM) { - int action = readVarInt(input); - writeVarInt(action, output); - int players = readVarInt(input); - writeVarInt(players, output); - - // loop through players - for (int i = 0; i < players; i++) { - UUID uuid = readUUID(input); - writeUUID(uuid, output); - if (action == 0) { // add player - writeString(readString(input), output); // name - - int properties = readVarInt(input); - writeVarInt(properties, output); - - // loop through properties - for (int j = 0; j < properties; j++) { - writeString(readString(input), output); // name - writeString(readString(input), output); // value - boolean isSigned = input.readBoolean(); - output.writeBoolean(isSigned); - if (isSigned) { - writeString(readString(input), output); // signature - } - } - - writeVarInt(readVarInt(input), output); // gamemode - writeVarInt(readVarInt(input), output); // ping - boolean hasDisplayName = input.readBoolean(); - output.writeBoolean(hasDisplayName); - if (hasDisplayName) { - writeString(fixJson(readString(input)), output); // display name - } - } else if ((action == 1) || (action == 2)) { // update gamemode || update latency - writeVarInt(readVarInt(input), output); - } else if (action == 3) { // update display name - boolean hasDisplayName = input.readBoolean(); - output.writeBoolean(hasDisplayName); - if (hasDisplayName) { - writeString(fixJson(readString(input)), output); // display name - } - } else if (action == 4) { // remove player - // no fields - } - } - - return; - } - if (packet == PacketType.PLAY_PLAYER_LIST_HEADER_FOOTER) { - String header = readString(input); - String footer = readString(input); - writeString(fixJson(header), output); - writeString(fixJson(footer), output); - return; - } - if (packet == PacketType.PLAY_ENTITY_TELEPORT) { - int id = PacketUtil.readVarInt(input); - PacketUtil.writeVarInt(id, output); - - int x = input.readInt(); - output.writeDouble(x / 32D); - int y = input.readInt(); - if (plugin.isHologramPatch() & knownHolograms.contains(id)) { - y = (int) ((y) + (plugin.getHologramYOffset() * 32D)); - } - output.writeDouble(y / 32D); - int z = input.readInt(); - output.writeDouble(z / 32D); - - byte yaw = input.readByte(); - output.writeByte(yaw); - byte pitch = input.readByte(); - output.writeByte(pitch); - - boolean onGround = input.readBoolean(); - output.writeBoolean(onGround); - return; - - } - if (packet == PacketType.PLAY_ENTITY_LOOK_MOVE) { - int id = PacketUtil.readVarInt(input); - PacketUtil.writeVarInt(id, output); - int x = input.readByte(); - output.writeShort(x * 128); - int y = input.readByte(); - if (plugin.isHologramPatch() & knownHolograms.contains(id)) { - y = (int) ((y) + plugin.getHologramYOffset()); - } - output.writeShort(y * 128); - int z = input.readByte(); - output.writeShort(z * 128); - - byte yaw = input.readByte(); - output.writeByte(yaw); - byte pitch = input.readByte(); - output.writeByte(pitch); - - boolean onGround = input.readBoolean(); - output.writeBoolean(onGround); - return; - - } - if (packet == PacketType.PLAY_ENTITY_RELATIVE_MOVE) { - int id = PacketUtil.readVarInt(input); - PacketUtil.writeVarInt(id, output); - short x = (short) (input.readByte()); - output.writeShort(x * 128); - short y = (short) (input.readByte()); - if (plugin.isHologramPatch() & knownHolograms.contains(id)) { - y = (short) (y - 1); - } - output.writeShort(y * 128); - short z = (short) (input.readByte()); - output.writeShort(z * 128); - - boolean onGround = input.readBoolean(); - output.writeBoolean(onGround); - - return; - - } - if (packet == PacketType.LOGIN_SETCOMPRESSION) { - int factor = PacketUtil.readVarInt(input); - info.setCompression(factor); - PacketUtil.writeVarInt(factor, output); - return; - } - - if (packet == PacketType.STATUS_RESPONSE) { - String originalStatus = PacketUtil.readString(input); - try { - JsonObject jsonObject = gson.fromJson(originalStatus, JsonObject.class); - JsonObject version = jsonObject.get("version").getAsJsonObject(); - if (version.get("protocol").getAsInt() != 9999) //Fix ServerListPlus custom outdated message - version.addProperty("protocol", info.getProtocol()); - PacketUtil.writeString(gson.toJson(jsonObject), output); - } catch (Exception e) { - e.printStackTrace(); - } - return; - } - if (packet == PacketType.LOGIN_SUCCESS) { - info.setState(State.PLAY); - - String uuid = PacketUtil.readString(input); - PacketUtil.writeString(uuid, output); - UUID uniqueId = UUID.fromString(uuid); - info.setUUID(uniqueId); - // plugin.addPortedClient(info); - String username = PacketUtil.readString(input); - info.setUsername(username); - PacketUtil.writeString(username, output); - return; - } - - if (packet == PacketType.PLAY_PLAYER_POSITION_LOOK) { - output.writeBytes(input); - PacketUtil.writeVarInt(0, output); - return; - } - if (packet == PacketType.PLAY_ENTITY_EQUIPMENT) { - int id = PacketUtil.readVarInt(input); - PacketUtil.writeVarInt(id, output); - short slot = input.readShort(); - - if (slot > 0) { - slot += 1; // add 1 so it's now 2-5 - } - PacketUtil.writeVarInt(slot, output); - if (slot == 0) { - // Read aheat for sword - input.markReaderIndex(); - short itemID = input.readShort(); - if (itemID != -1) { - Material m = Material.getMaterial(itemID); - if (m != null) { - if (m.name().endsWith("SWORD")) { - validBlocking.add(id); - } else { - validBlocking.remove(id); - } - } - } else { - validBlocking.remove(id); - } - input.resetReaderIndex(); - } - ItemSlotRewriter.rewrite1_8To1_9(input, output); - return; - } - if (packet == PacketType.PLAY_ENTITY_METADATA) { - int id = PacketUtil.readVarInt(input); - PacketUtil.writeVarInt(id, output); - - transformMetadata(id, input, output); - return; - } - - if (packet == PacketType.PLAY_SPAWN_GLOBAL_ENTITY) { - int id = PacketUtil.readVarInt(input); - PacketUtil.writeVarInt(id, output); - - // only used for lightning - byte type = input.readByte(); - clientEntityTypes.put(id, EntityType.LIGHTNING); - output.writeByte(type); - - double x = input.readInt(); - output.writeDouble(x / 32D); - double y = input.readInt(); - output.writeDouble(y / 32D); - double z = input.readInt(); - output.writeDouble(z / 32D); - return; - } - if (packet == PacketType.PLAY_DESTROY_ENTITIES) { - int count = PacketUtil.readVarInt(input); - PacketUtil.writeVarInt(count, output); - - int[] toDestroy = PacketUtil.readVarInts(count, input); - for (int entityID : toDestroy) { - clientEntityTypes.remove(entityID); - knownHolograms.remove(entityID); - PacketUtil.writeVarInt(entityID, output); - - // Remvoe boss bar - BossBar bar = bossBarMap.remove(entityID); - if (bar != null) { - bar.hide(); - } - } - return; - } - if (packet == PacketType.PLAY_SPAWN_OBJECT) { - int id = PacketUtil.readVarInt(input); - PacketUtil.writeVarInt(id, output); - PacketUtil.writeUUID(getUUID(id), output); - - byte type = input.readByte(); - clientEntityTypes.put(id, EntityUtil.getTypeFromID(type, true)); - output.writeByte(type); - - double x = input.readInt(); - output.writeDouble(x / 32D); - double y = input.readInt(); - output.writeDouble(y / 32D); - double z = input.readInt(); - output.writeDouble(z / 32D); - byte pitch = input.readByte(); - output.writeByte(pitch); - byte yaw = input.readByte(); - output.writeByte(yaw); - - int data = input.readInt(); - output.writeInt(data); - - short vX = 0, vY = 0, vZ = 0; - if (data > 0) { - vX = input.readShort(); - vY = input.readShort(); - vZ = input.readShort(); - } - output.writeShort(vX); - output.writeShort(vY); - output.writeShort(vZ); - - return; - } - if (packet == PacketType.PLAY_SPAWN_XP_ORB) { - int id = PacketUtil.readVarInt(input); - clientEntityTypes.put(id, EntityType.EXPERIENCE_ORB); - PacketUtil.writeVarInt(id, output); - double x = input.readInt(); - output.writeDouble(x / 32D); - double y = input.readInt(); - output.writeDouble(y / 32D); - double z = input.readInt(); - output.writeDouble(z / 32D); - - short data = input.readShort(); - output.writeShort(data); - - return; - } - if (packet == PacketType.PLAY_SPAWN_PAINTING) { - int id = PacketUtil.readVarInt(input); - clientEntityTypes.put(id, EntityType.PAINTING); - PacketUtil.writeVarInt(id, output); - - PacketUtil.writeUUID(getUUID(id), output); - String title = PacketUtil.readString(input); - PacketUtil.writeString(title, output); - - long[] position = PacketUtil.readBlockPosition(input); - PacketUtil.writeBlockPosition(output, position[0], position[1], position[2]); - - byte direction = input.readByte(); - output.writeByte(direction); - - return; - } - if (packet == PacketType.PLAY_WINDOW_PROPERTY) { - int windowId = input.readUnsignedByte(); - output.writeByte(windowId); - short property = input.readShort(); - short value = input.readShort(); - - if (info.getOpenWindow() != null) { - if (info.getOpenWindow().equalsIgnoreCase("minecraft:enchanting_table")) { - if (property > 3 && property < 7) { - short level = (short) (value >> 8); - short enchantID = (short) (value & 0xFF); - // Property 1 - ByteBuf buf1 = info.getChannel().alloc().buffer(); - PacketUtil.writeVarInt(PacketType.PLAY_WINDOW_PROPERTY.getNewPacketID(), buf1); - buf1.writeByte(windowId); - buf1.writeShort(property); - buf1.writeShort(enchantID); - - info.sendRawPacket(buf1); - - property = (short) (property + 3); - value = level; - } - } - } - output.writeShort(property); - output.writeShort(value); - } - if (packet == PacketType.PLAY_OPEN_WINDOW) { - int windowId = input.readUnsignedByte(); - String type = readString(input); - info.setOpenWindow(type); - String windowTitle = readString(input); - - output.writeByte(windowId); - writeString(type, output); - writeString(fixJson(windowTitle), output); - int slots = input.readUnsignedByte(); - if (type.equals("minecraft:brewing_stand")) { - slots = slots + 1; // new slot - } - output.writeByte(slots); - output.writeBytes(input); - return; - } - if (packet == PacketType.PLAY_CLOSE_WINDOW) { - info.closeWindow(); - } - if (packet == PacketType.PLAY_SET_SLOT) { - int windowId = input.readUnsignedByte(); - output.writeByte(windowId); - - short slot = input.readShort(); - if (info.getOpenWindow() != null) { - if (info.getOpenWindow().equals("minecraft:brewing_stand")) { - if (slot >= 4) - slot = (short) (slot + 1); - } - } - output.writeShort(slot); - ItemSlotRewriter.rewrite1_8To1_9(input, output); - return; - } - if (packet == PacketType.PLAY_WINDOW_ITEMS) { - int windowId = input.readUnsignedByte(); - output.writeByte(windowId); - - short count = input.readShort(); - boolean brewing = false; - if (info.getOpenWindow() != null && windowId > 0) { - if (info.getOpenWindow().equals("minecraft:brewing_stand")) { - brewing = true; - } - } - output.writeShort(brewing ? (count + 1) : count); - - for (int i = 0; i < count; i++) { - - ItemSlotRewriter.rewrite1_8To1_9(input, output); - - // write "fuel" slot - if (brewing && i == 3) { - output.writeShort(-1); // empty slot - } - } - return; - } - if (packet == PacketType.PLAY_SPAWN_MOB) { - int id = PacketUtil.readVarInt(input); - PacketUtil.writeVarInt(id, output); - - PacketUtil.writeUUID(getUUID(id), output); - short type = input.readUnsignedByte(); - clientEntityTypes.put(id, EntityUtil.getTypeFromID(type, false)); - output.writeByte(type); - - double x = input.readInt(); - output.writeDouble(x / 32D); - double y = input.readInt(); - output.writeDouble(y / 32D); - double z = input.readInt(); - output.writeDouble(z / 32D); - byte yaw = input.readByte(); - output.writeByte(yaw); - byte pitch = input.readByte(); - output.writeByte(pitch); - byte headPitch = input.readByte(); - output.writeByte(headPitch); - - short vX = input.readShort(); - output.writeShort(vX); - short vY = input.readShort(); - output.writeShort(vY); - short vZ = input.readShort(); - output.writeShort(vZ); - - transformMetadata(id, input, output); - return; - } - if (packet == PacketType.PLAY_UPDATE_SIGN) { - Long location = input.readLong(); - output.writeLong(location); - for (int i = 0; i < 4; i++) { - String line = PacketUtil.readString(input); - PacketUtil.writeString(fixJson(line), output); - } - } - if (packet == PacketType.PLAY_CHAT_MESSAGE) { - String chat = PacketUtil.readString(input); - PacketUtil.writeString(fixJson(chat), output); - - byte pos = input.readByte(); - output.writeByte(pos); - return; - } - if (packet == PacketType.PLAY_JOIN_GAME) { - int id = input.readInt(); - clientEntityTypes.put(id, EntityType.PLAYER); - info.setEntityID(id); - output.writeInt(id); - - int gamemode = input.readUnsignedByte(); - output.writeByte(gamemode); - int dimension = input.readByte(); - output.writeByte(dimension); - int difficulty = input.readUnsignedByte(); - if (info.getProtocol() >= 108) { - // 1.8.1 Pre 2 - output.writeInt(difficulty); - } else { - output.writeByte(difficulty); - } - int maxPlayers = input.readUnsignedByte(); - output.writeByte(maxPlayers); - String level = PacketUtil.readString(input); - PacketUtil.writeString(level, output); - boolean reducedDebug = input.readBoolean(); - output.writeBoolean(reducedDebug); - return; - } - if (packet == PacketType.PLAY_SERVER_DIFFICULTY) { - if (plugin.isAutoTeam()) { - autoTeam = true; - sendTeamPacket(true); - } - } - if (packet == PacketType.PLAY_SPAWN_PLAYER) { - int id = PacketUtil.readVarInt(input); - PacketUtil.writeVarInt(id, output); - clientEntityTypes.put(id, EntityType.PLAYER); - UUID playerUUID = PacketUtil.readUUID(input); - PacketUtil.writeUUID(playerUUID, output); - - double x = input.readInt(); - output.writeDouble(x / 32D); - double y = input.readInt(); - output.writeDouble(y / 32D); - double z = input.readInt(); - output.writeDouble(z / 32D); - - byte pitch = input.readByte(); - output.writeByte(pitch); - byte yaw = input.readByte(); - output.writeByte(yaw); - - // next field is Current Item, this was removed in 1.9 so we'll ignore it - input.readShort(); - - transformMetadata(id, input, output); - - return; - } - if (packet == PacketType.PLAY_MAP) { - int damage = PacketUtil.readVarInt(input); - PacketUtil.writeVarInt(damage, output); - byte scale = input.readByte(); - output.writeByte(scale); - output.writeBoolean(true); - output.writeBytes(input); - return; - } - if (packet == PacketType.PLAY_ENTITY_EFFECT) { - int id = PacketUtil.readVarInt(input); - PacketUtil.writeVarInt(id, output); - byte effectID = input.readByte(); - output.writeByte(effectID); - byte amplifier = input.readByte(); - output.writeByte(amplifier); - int duration = PacketUtil.readVarInt(input); - PacketUtil.writeVarInt(duration, output); - // we need to write as a byte instead of boolean - boolean hideParticles = input.readBoolean(); - output.writeByte(hideParticles ? plugin.isNewEffectIndicator() ? 2 : 1 : 0); - return; - } - if (packet == PacketType.PLAY_TEAM) { - String teamName = PacketUtil.readString(input); - PacketUtil.writeString(teamName, output); - byte mode = input.readByte(); - output.writeByte(mode); - if (mode == 0 || mode == 2) { - PacketUtil.writeString(PacketUtil.readString(input), output); - PacketUtil.writeString(PacketUtil.readString(input), output); - PacketUtil.writeString(PacketUtil.readString(input), output); - - output.writeByte(input.readByte()); - PacketUtil.writeString(PacketUtil.readString(input), output); - - PacketUtil.writeString(plugin.isPreventCollision() ? "never" : "", output); // collission rule :) - - output.writeByte(input.readByte()); - } - if (mode == 0 || mode == 3 || mode == 4) { - // add players - int count = PacketUtil.readVarInt(input); - PacketUtil.writeVarInt(count, output); - - for (int i = 0; i < count; i++) { - String name = PacketUtil.readString(input); - if (autoTeam && name.equalsIgnoreCase(info.getUsername())) { - if (mode == 4) { - // since removing add to auto team - plugin.run(new Runnable() { - @Override - public void run() { - sendTeamPacket(true); - } - }, false); - } else { - // since adding remove from auto team - sendTeamPacket(false); - } - } - PacketUtil.writeString(name, output); - } - } - output.writeBytes(input); - return; - } - if (packet == PacketType.PLAY_UPDATE_BLOCK_ENTITY) { - long[] pos = PacketUtil.readBlockPosition(input); - PacketUtil.writeBlockPosition(output, pos[0], pos[1], pos[2]); - int action = input.readUnsignedByte(); - output.writeByte(action); - if (action == 1) { // update spawner - try { - int index = input.readerIndex(); - CompoundTag tag = PacketUtil.readNBT(input); - if (tag != null && tag.contains("EntityId")) { - String entity = (String) tag.get("EntityId").getValue(); - CompoundTag spawn = new CompoundTag("SpawnData"); - spawn.put(new StringTag("id", entity)); - tag.put(spawn); - PacketUtil.writeNBT(output, tag); - } else if (tag != null) { // EntityID does not exist - CompoundTag spawn = new CompoundTag("SpawnData"); - spawn.put(new StringTag("id", "AreaEffectCloud")); //Make spawners show up as empty when no EntityId is given. - tag.put(spawn); - PacketUtil.writeNBT(output, spawn); - } else { //There doesn't exist any NBT tag - input.readerIndex(index); - output.writeBytes(input, input.readableBytes()); - } - } catch (IOException e) { - e.printStackTrace(); - } - return; - } - if (action == 2) { //Update commandblock - throw new CancelException(); //Only update if player interact with commandblock (The commandblock window will update every time this packet is sent, this would prevent you from change things that update every tick) - } - output.writeBytes(input, input.readableBytes()); - return; - } - if (packet == PacketType.PLAY_CHUNK_DATA) { - // Read chunk - ChunkManager chunkManager = info.getChunkManager(); - Chunk chunk = chunkManager.readChunk(input); - if (chunk == null) { - throw new CancelException(); - } - - // Write chunk - chunkManager.writeChunk(chunk, output); - return; - } - output.writeBytes(input); - } - - private void sendTeamPacket(boolean b) { - ByteBuf buf = info.getChannel().alloc().buffer(); - PacketUtil.writeVarInt(PacketType.PLAY_TEAM.getNewPacketID(), buf); - PacketUtil.writeString("viaversion", buf); // Use viaversion as name - if (b) { - // add - if (!teamExists) { - buf.writeByte(0); // make team - PacketUtil.writeString("viaversion", buf); - PacketUtil.writeString("", buf); // prefix - PacketUtil.writeString("", buf); // suffix - buf.writeByte(0); // friendly fire - PacketUtil.writeString("", buf); // nametags - PacketUtil.writeString("never", buf); // collision rule :) - buf.writeByte(0); // color - } else - buf.writeByte(3); - PacketUtil.writeVarInt(1, buf); // player count - PacketUtil.writeString(info.getUsername(), buf); // us - } else { - buf.writeByte(1); // remove team - } - teamExists = b; - info.sendRawPacket(buf); - } - - private void transformMetadata(int entityID, ByteBuf input, ByteBuf output) throws CancelException { - EntityType type = clientEntityTypes.get(entityID); - if (type == null) { - System.out.println("Unable to get entity for ID: " + entityID); - output.writeByte(255); - return; - } - List list = MetadataRewriter.readMetadata1_8(type, input); - for (MetadataRewriter.Entry entry : list) { - handleMetadata(entityID, entry, type); - } - // Fix: wither (crash fix) - if (type == EntityType.WITHER) { - // Remove custom value if already exist - Iterator it = list.iterator(); - while (it.hasNext()) { - Entry e = it.next(); - if (e.getOldID() == 10) { - it.remove(); - } - } - - list.add(new Entry(MetaIndex.WITHER_PROPERTIES, (byte) 0, 10)); - } - // Fix: Dragon (crash fix) - if (type == EntityType.ENDER_DRAGON) { - // Remove custom value if already exist - Iterator it = list.iterator(); - while (it.hasNext()) { - Entry e = it.next(); - if (e.getOldID() == 11) { - it.remove(); - } - } - - list.add(new Entry(MetaIndex.ENDERDRAGON_PHASE, (byte) 0, 11)); - } - MetadataRewriter.writeMetadata1_9(type, list, output); - } - - private void handleMetadata(int entityID, MetadataRewriter.Entry entry, EntityType type) { - // This handles old IDs - if (type == EntityType.PLAYER) { - if (entry.getOldID() == 0) { - // Byte - byte data = (byte) entry.getValue(); - if (entityID != info.getEntityID() && plugin.isShieldBlocking()) { - if ((data & 0x10) == 0x10) { - if (validBlocking.contains(entityID)) { - ItemSlotRewriter.ItemStack shield = new ItemSlotRewriter.ItemStack(); - shield.id = 442; - shield.amount = 1; - shield.data = 0; - sendSecondHandItem(entityID, shield); - } - } else { - sendSecondHandItem(entityID, null); - } - } - } - } - if (type == EntityType.ARMOR_STAND && plugin.isHologramPatch()) { - if (entry.getOldID() == 0) { - byte data = (byte) entry.getValue(); - if ((data & 0x20) == 0x20) { - if (!knownHolograms.contains(entityID)) { - knownHolograms.add(entityID); - // Send movement - ByteBuf buf = info.getChannel().alloc().buffer(); - PacketUtil.writeVarInt(PacketType.PLAY_ENTITY_RELATIVE_MOVE.getNewPacketID(), buf); - PacketUtil.writeVarInt(entityID, buf); - buf.writeShort(0); - buf.writeShort((short) (128D * (plugin.getHologramYOffset() * 32D))); - buf.writeShort(0); - buf.writeBoolean(true); - info.sendRawPacket(buf, false); - } - } - } - } - - // Boss bar - if (plugin.isBossbarPatch()) { - if (type == EntityType.ENDER_DRAGON || type == EntityType.WITHER) { - if (entry.getOldID() == 2) { - BossBar bar = bossBarMap.get(entityID); - String title = (String) entry.getValue(); - title = title.isEmpty() ? (type == EntityType.ENDER_DRAGON ? "Ender Dragon" : "Wither") : title; - if (bar == null) { - bar = ViaVersion.getInstance().createBossBar(title, BossColor.PINK, BossStyle.SOLID); - bossBarMap.put(entityID, bar); - bar.addPlayer(info.getPlayer()); - bar.show(); - } else { - bar.setTitle(title); - } - } else if (entry.getOldID() == 6 && !plugin.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 health = Math.max(0.0f, Math.min(((float) entry.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); - bossBarMap.put(entityID, bar); - bar.addPlayer(info.getPlayer()); - bar.show(); - } else { - bar.setHealth(health); - } - } - } - } - } - - - private UUID getUUID(int id) { - if (uuidMap.containsKey(id)) { - return uuidMap.get(id); - } else { - UUID uuid = UUID.randomUUID(); - uuidMap.put(id, uuid); - return uuid; - } - } - - private void sendSecondHandItem(int entityID, ItemSlotRewriter.ItemStack o) { - - ByteBuf buf = info.getChannel().alloc().buffer(); - PacketUtil.writeVarInt(PacketType.PLAY_ENTITY_EQUIPMENT.getNewPacketID(), buf); - PacketUtil.writeVarInt(entityID, buf); - PacketUtil.writeVarInt(1, buf); // slot - // write shield - try { - ItemSlotRewriter.writeItemStack(o, buf); - } catch (IOException e) { - e.printStackTrace(); - } - info.sendRawPacket(buf, true); - } -} \ No newline at end of file diff --git a/src/main/java/us/myles/ViaVersion2/api/protocol1_9to1_8/ItemRewriter.java b/src/main/java/us/myles/ViaVersion2/api/protocol1_9to1_8/ItemRewriter.java index ffc3091d0..5394f3b51 100644 --- a/src/main/java/us/myles/ViaVersion2/api/protocol1_9to1_8/ItemRewriter.java +++ b/src/main/java/us/myles/ViaVersion2/api/protocol1_9to1_8/ItemRewriter.java @@ -5,7 +5,6 @@ import org.spacehq.opennbt.tag.builtin.CompoundTag; import org.spacehq.opennbt.tag.builtin.ListTag; import org.spacehq.opennbt.tag.builtin.StringTag; import org.spacehq.opennbt.tag.builtin.Tag; -import us.myles.ViaVersion.transformers.OutgoingTransformer; import us.myles.ViaVersion2.api.item.Item; import java.util.Collections; @@ -222,7 +221,7 @@ public class ItemRewriter { } ListTag pages = tag.get("pages"); if (pages == null) { - pages = new ListTag("pages", Collections.singletonList(new StringTag(OutgoingTransformer.fixJson("")))); + pages = new ListTag("pages", Collections.singletonList(new StringTag(Protocol1_9TO1_8.fixJson("")))); tag.put(pages); item.setTag(tag); return; @@ -232,7 +231,7 @@ public class ItemRewriter { if (!(pages.get(i) instanceof StringTag)) continue; StringTag page = pages.get(i); - page.setValue(OutgoingTransformer.fixJson(page.getValue())); + page.setValue(Protocol1_9TO1_8.fixJson(page.getValue())); } item.setTag(tag); } diff --git a/src/main/java/us/myles/ViaVersion2/api/protocol1_9to1_8/Protocol1_9TO1_8.java b/src/main/java/us/myles/ViaVersion2/api/protocol1_9to1_8/Protocol1_9TO1_8.java index f67de10fb..ee48bda6b 100644 --- a/src/main/java/us/myles/ViaVersion2/api/protocol1_9to1_8/Protocol1_9TO1_8.java +++ b/src/main/java/us/myles/ViaVersion2/api/protocol1_9to1_8/Protocol1_9TO1_8.java @@ -1,5 +1,8 @@ package us.myles.ViaVersion2.api.protocol1_9to1_8; +import com.google.gson.Gson; +import com.google.gson.GsonBuilder; +import com.google.gson.JsonObject; import org.bukkit.Bukkit; import org.bukkit.inventory.ItemStack; import org.json.simple.JSONObject; @@ -26,31 +29,15 @@ import java.util.concurrent.Callable; import java.util.concurrent.TimeUnit; public class Protocol1_9TO1_8 extends Protocol { + private static Gson gson = new GsonBuilder().create(); + public static Type> METADATA_LIST = new MetadataListType(); public static Type METADATA = new MetadataType(); public static ValueTransformer FIX_JSON = new ValueTransformer(Type.STRING) { @Override public String transform(PacketWrapper wrapper, String line) { - if (line == null || line.equalsIgnoreCase("null")) { - line = "{\"text\":\"\"}"; - } else { - if ((!line.startsWith("\"") || !line.endsWith("\"")) && (!line.startsWith("{") || !line.endsWith("}"))) { - JSONObject obj = new JSONObject(); - obj.put("text", line); - return obj.toJSONString(); - } - if (line.startsWith("\"") && line.endsWith("\"")) { - line = "{\"text\":" + line + "}"; - } - } - try { - new JSONParser().parse(line); - } catch (Exception e) { - System.out.println("Invalid JSON String: \"" + line + "\" Please report this issue to the ViaVersion Github: " + e.getMessage()); - return "{\"text\":\"\"}"; - } - return line; + return fixJson(line); } }; @@ -75,6 +62,27 @@ public class Protocol1_9TO1_8 extends Protocol { userConnection.put(new InventoryTracker(userConnection)); } + public static String fixJson(String line) { + if (line == null || line.equalsIgnoreCase("null")) { + line = "{\"text\":\"\"}"; + } else { + if ((!line.startsWith("\"") || !line.endsWith("\"")) && (!line.startsWith("{") || !line.endsWith("}"))) { + JsonObject jsonObject = new JsonObject(); + jsonObject.addProperty("text", line); + return gson.toJson(jsonObject); + } + if (line.startsWith("\"") && line.endsWith("\"")) { + line = "{\"text\":" + line + "}"; + } + } + try { + gson.fromJson(line, JsonObject.class); + } catch (Exception e) { + System.out.println("Invalid JSON String: \"" + line + "\" Please report this issue to the ViaVersion Github: " + e.getMessage()); + return "{\"text\":\"\"}"; + } + return line; + } public static ItemStack getHandItem(final UserConnection info) { try { diff --git a/src/main/java/us/myles/ViaVersion2/api/protocol1_9to1_8/metadata/MetadataRewriter.java b/src/main/java/us/myles/ViaVersion2/api/protocol1_9to1_8/metadata/MetadataRewriter.java index 20c7e008e..8a3c8ce20 100644 --- a/src/main/java/us/myles/ViaVersion2/api/protocol1_9to1_8/metadata/MetadataRewriter.java +++ b/src/main/java/us/myles/ViaVersion2/api/protocol1_9to1_8/metadata/MetadataRewriter.java @@ -8,10 +8,10 @@ import us.myles.ViaVersion.api.ViaVersion; import us.myles.ViaVersion.metadata.MetaIndex; import us.myles.ViaVersion.metadata.NewType; import us.myles.ViaVersion.metadata.Type; -import us.myles.ViaVersion.transformers.OutgoingTransformer; import us.myles.ViaVersion2.api.item.Item; import us.myles.ViaVersion2.api.metadata.Metadata; import us.myles.ViaVersion2.api.protocol1_9to1_8.ItemRewriter; +import us.myles.ViaVersion2.api.protocol1_9to1_8.Protocol1_9TO1_8; import java.util.ArrayList; import java.util.List; @@ -127,7 +127,7 @@ public class MetadataRewriter { break; case Chat: entry.setType(us.myles.ViaVersion2.api.type.Type.STRING); - value = OutgoingTransformer.fixJson((String) value); + value = Protocol1_9TO1_8.fixJson((String) value); entry.setValue(value); break; default: diff --git a/src/main/java/us/myles/ViaVersion2/api/protocol1_9to1_8/packets/EntityPackets.java b/src/main/java/us/myles/ViaVersion2/api/protocol1_9to1_8/packets/EntityPackets.java index 6e5805993..88d5f9180 100644 --- a/src/main/java/us/myles/ViaVersion2/api/protocol1_9to1_8/packets/EntityPackets.java +++ b/src/main/java/us/myles/ViaVersion2/api/protocol1_9to1_8/packets/EntityPackets.java @@ -56,6 +56,7 @@ public class EntityPackets { } else { passengerPacket.write(Type.VAR_INT, vehicle); passengerPacket.write(Type.VAR_INT_ARRAY, new Integer[]{passenger}); + tracker.getVehicleMap().put(passenger, vehicle); } passengerPacket.send(); // Send the packet } diff --git a/src/main/java/us/myles/ViaVersion2/api/protocol1_9to1_8/packets/InventoryPackets.java b/src/main/java/us/myles/ViaVersion2/api/protocol1_9to1_8/packets/InventoryPackets.java index 093403918..3ce9673f9 100644 --- a/src/main/java/us/myles/ViaVersion2/api/protocol1_9to1_8/packets/InventoryPackets.java +++ b/src/main/java/us/myles/ViaVersion2/api/protocol1_9to1_8/packets/InventoryPackets.java @@ -196,7 +196,7 @@ public class InventoryPackets { }); /* Packets which do not have any field remapping or handlers */ - + protocol.registerOutgoing(State.PLAY, 0x09, 0x37); // Held Item Change Packet protocol.registerOutgoing(State.PLAY, 0x32, 0x11); // Confirm Transaction Packet /* Incoming Packets */ @@ -215,6 +215,27 @@ public class InventoryPackets { ItemRewriter.toServer(stack); } }); + // Elytra throw patch + handler(new PacketHandler() { + @Override + public void handle(PacketWrapper wrapper) throws Exception { + final short slot = wrapper.get(Type.SHORT, 0); + boolean throwItem = (slot == 45); + if (throwItem) { + // Send a packet wiping the slot + wrapper.create(0x16, new ValueCreator() { + @Override + public void write(PacketWrapper wrapper) throws Exception { + wrapper.write(Type.UNSIGNED_BYTE, (short) 0); + wrapper.write(Type.SHORT, slot); + wrapper.write(Type.SHORT, (short) -1); + } + }).send(); + // Finally reset to simulate throwing item + wrapper.set(Type.SHORT, 0, (short) -999); // Set slot to -999 + } + } + }); } }); diff --git a/src/main/java/us/myles/ViaVersion2/api/protocol1_9to1_8/packets/PlayerPackets.java b/src/main/java/us/myles/ViaVersion2/api/protocol1_9to1_8/packets/PlayerPackets.java index 61c336861..a62097f3c 100644 --- a/src/main/java/us/myles/ViaVersion2/api/protocol1_9to1_8/packets/PlayerPackets.java +++ b/src/main/java/us/myles/ViaVersion2/api/protocol1_9to1_8/packets/PlayerPackets.java @@ -252,8 +252,6 @@ public class PlayerPackets { protocol.registerOutgoing(State.PLAY, 0x43, 0x36); // Camera Packet protocol.registerOutgoing(State.PLAY, 0x2B, 0x1E); // Change Game State Packet - protocol.registerOutgoing(State.PLAY, 0x09, 0x37); // Held Item Change Packet - protocol.registerOutgoing(State.PLAY, 0x3D, 0x38); // Display Scoreboard Packet protocol.registerOutgoing(State.PLAY, 0x3B, 0x3F); // Scoreboard Objective Packet protocol.registerOutgoing(State.PLAY, 0x3C, 0x42); // Update Score Packet diff --git a/src/main/java/us/myles/ViaVersion2/api/protocol1_9to1_8/packets/WorldPackets.java b/src/main/java/us/myles/ViaVersion2/api/protocol1_9to1_8/packets/WorldPackets.java index a7c98b726..45d6d7adf 100644 --- a/src/main/java/us/myles/ViaVersion2/api/protocol1_9to1_8/packets/WorldPackets.java +++ b/src/main/java/us/myles/ViaVersion2/api/protocol1_9to1_8/packets/WorldPackets.java @@ -145,15 +145,7 @@ public class WorldPackets { } }); - /* Packets which do not have any field remapping or handlers */ - - protocol.registerOutgoing(State.PLAY, 0x25, 0x08); // Block Break Animation Packet - protocol.registerOutgoing(State.PLAY, 0x24, 0x0A); // Block Action Packet - protocol.registerOutgoing(State.PLAY, 0x23, 0x0B); // Block Change Packet - protocol.registerOutgoing(State.PLAY, 0x22, 0x10); // Multi Block Change Packet - protocol.registerOutgoing(State.PLAY, 0x27, 0x1C); // Explosion Packet - protocol.registerOutgoing(State.PLAY, 0x2A, 0x22); // Particle Packet - + // Server Difficulty Packet protocol.registerOutgoing(State.PLAY, 0x41, 0x0D, new PacketRemapper() { @Override public void registerMap() { @@ -168,7 +160,15 @@ public class WorldPackets { } }); } - }); // Server Difficulty Packet + }); + /* Packets which do not have any field remapping or handlers */ + + protocol.registerOutgoing(State.PLAY, 0x25, 0x08); // Block Break Animation Packet + protocol.registerOutgoing(State.PLAY, 0x24, 0x0A); // Block Action Packet + protocol.registerOutgoing(State.PLAY, 0x23, 0x0B); // Block Change Packet + protocol.registerOutgoing(State.PLAY, 0x22, 0x10); // Multi Block Change Packet + protocol.registerOutgoing(State.PLAY, 0x27, 0x1C); // Explosion Packet + protocol.registerOutgoing(State.PLAY, 0x2A, 0x22); // Particle Packet protocol.registerOutgoing(State.PLAY, 0x03, 0x44); // Update Time Packet protocol.registerOutgoing(State.PLAY, 0x44, 0x35); // World Border Packet