diff --git a/common/src/main/java/us/myles/ViaVersion/api/entities/Entity1_12Types.java b/common/src/main/java/us/myles/ViaVersion/api/entities/Entity1_12Types.java new file mode 100644 index 000000000..8a2933ff4 --- /dev/null +++ b/common/src/main/java/us/myles/ViaVersion/api/entities/Entity1_12Types.java @@ -0,0 +1,253 @@ +/* + * Copyright (c) 2016 Matsv + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +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.12 Entity / Object taken from https://github.com/Matsv/ViaBackwards/blob/master/core/src/main/java/nl/matsv/viabackwards/api/entities/types/EntityType1_12.java +public class Entity1_12Types { + 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), + 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), + ENTITY_ILLAGER_ABSTRACT(-1, ENTITY_INSENTIENT), + EVOCATION_ILLAGER(34, ENTITY_ILLAGER_ABSTRACT), + VEX(35, ENTITY_INSENTIENT), + VINDICATION_ILLAGER(36, ENTITY_ILLAGER_ABSTRACT), + ILLUSION_ILLAGER(37, EVOCATION_ILLAGER), + + // 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), + PARROT(105, 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.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(79, 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/protocols/protocol1_11to1_10/packets/InventoryPackets.java b/common/src/main/java/us/myles/ViaVersion/protocols/protocol1_11to1_10/packets/InventoryPackets.java index 2622fdbb5..69c5e52e0 100644 --- a/common/src/main/java/us/myles/ViaVersion/protocols/protocol1_11to1_10/packets/InventoryPackets.java +++ b/common/src/main/java/us/myles/ViaVersion/protocols/protocol1_11to1_10/packets/InventoryPackets.java @@ -52,7 +52,7 @@ public class InventoryPackets { }); // Entity Equipment Packet - protocol.registerOutgoing(State.PLAY, 0x3C, 0x3C, new PacketRemapper() { + protocol.registerOutgoing(State.PLAY, 0x3C, 0x3E, new PacketRemapper() { @Override public void registerMap() { map(Type.VAR_INT); // 0 - Entity ID @@ -105,7 +105,7 @@ public class InventoryPackets { */ // Click window packet - protocol.registerIncoming(State.PLAY, 0x07, 0x07, new PacketRemapper() { + protocol.registerIncoming(State.PLAY, 0x07, 0x08, new PacketRemapper() { @Override public void registerMap() { map(Type.UNSIGNED_BYTE); // 0 - Window ID @@ -127,7 +127,7 @@ public class InventoryPackets { ); // Creative Inventory Action - protocol.registerIncoming(State.PLAY, 0x18, 0x18, new PacketRemapper() { + protocol.registerIncoming(State.PLAY, 0x18, 0x1b, new PacketRemapper() { @Override public void registerMap() { map(Type.SHORT); // 0 - Slot diff --git a/common/src/main/java/us/myles/ViaVersion/protocols/protocol1_12to1_11_1/BedRewriter.java b/common/src/main/java/us/myles/ViaVersion/protocols/protocol1_12to1_11_1/BedRewriter.java new file mode 100644 index 000000000..506ad9742 --- /dev/null +++ b/common/src/main/java/us/myles/ViaVersion/protocols/protocol1_12to1_11_1/BedRewriter.java @@ -0,0 +1,20 @@ +package us.myles.ViaVersion.protocols.protocol1_12to1_11_1; + +import us.myles.ViaVersion.api.minecraft.item.Item; + +public class BedRewriter { + + public static void toClientItem(Item item) { + if (item == null) return; + if (item.getId() == 355 && item.getData() == 0) { + item.setData((short) 14); + } + } + + public static void toServerItem(Item item) { + if (item == null) return; + if (item.getId() == 355 && item.getData() == 14) { + item.setData((short) 0); + } + } +} diff --git a/common/src/main/java/us/myles/ViaVersion/protocols/protocol1_12to1_11_1/MetadataRewriter.java b/common/src/main/java/us/myles/ViaVersion/protocols/protocol1_12to1_11_1/MetadataRewriter.java new file mode 100644 index 000000000..25da30137 --- /dev/null +++ b/common/src/main/java/us/myles/ViaVersion/protocols/protocol1_12to1_11_1/MetadataRewriter.java @@ -0,0 +1,31 @@ +package us.myles.ViaVersion.protocols.protocol1_12to1_11_1; + +import us.myles.ViaVersion.api.Via; +import us.myles.ViaVersion.api.data.UserConnection; +import us.myles.ViaVersion.api.entities.Entity1_12Types; +import us.myles.ViaVersion.api.minecraft.item.Item; +import us.myles.ViaVersion.api.minecraft.metadata.Metadata; + +import java.util.ArrayList; +import java.util.List; + +public class MetadataRewriter { + public static void handleMetadata(int entityId, Entity1_12Types.EntityType type, List metadatas, UserConnection connection) { + for (Metadata metadata : new ArrayList<>(metadatas)) { + try { + if (metadata.getValue() instanceof Item) { + // Apply rewrite + BedRewriter.toClientItem((Item) metadata.getValue()); + } + } catch (Exception e) { + metadatas.remove(metadata); + if (!Via.getConfig().isSuppressMetadataErrors() || Via.getManager().isDebug()) { + Via.getPlatform().getLogger().warning("An error occurred with entity metadata handler"); + Via.getPlatform().getLogger().warning("Metadata: " + metadata); + e.printStackTrace(); + } + } + } + + } +} diff --git a/common/src/main/java/us/myles/ViaVersion/protocols/protocol1_12to1_11_1/Protocol1_12To1_11_1.java b/common/src/main/java/us/myles/ViaVersion/protocols/protocol1_12to1_11_1/Protocol1_12To1_11_1.java index 60d910b39..28439e776 100644 --- a/common/src/main/java/us/myles/ViaVersion/protocols/protocol1_12to1_11_1/Protocol1_12To1_11_1.java +++ b/common/src/main/java/us/myles/ViaVersion/protocols/protocol1_12to1_11_1/Protocol1_12To1_11_1.java @@ -3,15 +3,20 @@ package us.myles.ViaVersion.protocols.protocol1_12to1_11_1; import com.github.steveice10.opennbt.tag.builtin.CompoundTag; import com.github.steveice10.opennbt.tag.builtin.IntTag; import com.github.steveice10.opennbt.tag.builtin.StringTag; +import com.google.common.base.Optional; import us.myles.ViaVersion.api.PacketWrapper; import us.myles.ViaVersion.api.data.UserConnection; +import us.myles.ViaVersion.api.entities.Entity1_12Types; import us.myles.ViaVersion.api.minecraft.chunks.Chunk; import us.myles.ViaVersion.api.minecraft.chunks.ChunkSection; import us.myles.ViaVersion.api.protocol.Protocol; import us.myles.ViaVersion.api.remapper.PacketHandler; import us.myles.ViaVersion.api.remapper.PacketRemapper; import us.myles.ViaVersion.api.type.Type; +import us.myles.ViaVersion.api.type.types.version.Types1_12; import us.myles.ViaVersion.packets.State; +import us.myles.ViaVersion.protocols.protocol1_12to1_11_1.packets.InventoryPackets; +import us.myles.ViaVersion.protocols.protocol1_12to1_11_1.storage.EntityTracker; import us.myles.ViaVersion.protocols.protocol1_9_1_2to1_9_3_4.types.Chunk1_9_3_4Type; import us.myles.ViaVersion.protocols.protocol1_9_3to1_9_1_2.storage.ClientWorld; @@ -19,7 +24,66 @@ public class Protocol1_12To1_11_1 extends Protocol { @Override protected void registerPackets() { + InventoryPackets.register(this); // Outgoing + // 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_12Types.EntityType entType = Entity1_12Types.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 + public void registerMap() { + map(Type.VAR_INT); // 0 - Entity ID + map(Type.UUID); // 1 - Entity UUID + map(Type.UNSIGNED_BYTE, Type.VAR_INT); // 2 - Entity Type + map(Type.DOUBLE); // 3 - X + map(Type.DOUBLE); // 4 - Y + map(Type.DOUBLE); // 5 - Z + map(Type.BYTE); // 6 - Yaw + map(Type.BYTE); // 7 - Pitch + map(Type.BYTE); // 8 - Head Pitch + map(Type.SHORT); // 9 - Velocity X + map(Type.SHORT); // 10 - Velocity Y + map(Type.SHORT); // 11 - Velocity Z + map(Types1_12.METADATA_LIST); // 12 - Metadata + + 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); + + Entity1_12Types.EntityType entType = Entity1_12Types.getTypeFromId(type, false); + // Register Type ID + wrapper.user().get(EntityTracker.class).addEntity(entityId, entType); + MetadataRewriter.handleMetadata(entityId, entType, wrapper.get(Types1_12.METADATA_LIST, 0), wrapper.user()); + } + }); + } + }); // Chunk Data registerOutgoing(State.PLAY, 0x20, 0x20, new PacketRemapper() { @@ -90,7 +154,21 @@ public class Protocol1_12To1_11_1 extends Protocol { registerOutgoing(State.PLAY, 0x26, 0x27); registerOutgoing(State.PLAY, 0x27, 0x28); // New packet at 0x30 - registerOutgoing(State.PLAY, 0x30, 0x31); + // Destroy entities + registerOutgoing(State.PLAY, 0x30, 0x31, new PacketRemapper() { + @Override + public void registerMap() { + map(Type.VAR_INT_ARRAY); // 0 - Entity IDS + + handler(new PacketHandler() { + @Override + public void handle(PacketWrapper wrapper) throws Exception { + for (int entity : wrapper.get(Type.VAR_INT_ARRAY, 0)) + wrapper.user().get(EntityTracker.class).removeEntity(entity); + } + }); + } + }); registerOutgoing(State.PLAY, 0x31, 0x32); registerOutgoing(State.PLAY, 0x32, 0x33); // Respawn Packet @@ -117,10 +195,29 @@ public class Protocol1_12To1_11_1 extends Protocol { registerOutgoing(State.PLAY, 0x36, 0x38); registerOutgoing(State.PLAY, 0x37, 0x39); registerOutgoing(State.PLAY, 0x38, 0x3a); - registerOutgoing(State.PLAY, 0x39, 0x3b); + // Metadata packet + registerOutgoing(State.PLAY, 0x39, 0x3b, new PacketRemapper() { + @Override + public void registerMap() { + map(Type.VAR_INT); // 0 - Entity ID + map(Types1_12.METADATA_LIST); // 1 - Metadata list + handler(new PacketHandler() { + @Override + public void handle(PacketWrapper wrapper) throws Exception { + int entityId = wrapper.get(Type.VAR_INT, 0); + + Optional type = wrapper.user().get(EntityTracker.class).get(entityId); + if (!type.isPresent()) + return; + + MetadataRewriter.handleMetadata(entityId, type.get(), wrapper.get(Types1_12.METADATA_LIST, 0), wrapper.user()); + } + }); + } + }); registerOutgoing(State.PLAY, 0x3a, 0x3c); registerOutgoing(State.PLAY, 0x3b, 0x3d); - registerOutgoing(State.PLAY, 0x3c, 0x3e); + // registerOutgoing(State.PLAY, 0x3c, 0x3e); - Handled in InventoryPackets registerOutgoing(State.PLAY, 0x3d, 0x3f); registerOutgoing(State.PLAY, 0x3e, 0x40); registerOutgoing(State.PLAY, 0x3f, 0x41); @@ -131,7 +228,7 @@ public class Protocol1_12To1_11_1 extends Protocol { registerOutgoing(State.PLAY, 0x44, 0x46); registerOutgoing(State.PLAY, 0x45, 0x47); - // Sound effect, should work fine, might need checking for parrots? + // Sound effect registerOutgoing(State.PLAY, 0x46, 0x48, new PacketRemapper() { @Override public void registerMap() { @@ -184,7 +281,7 @@ public class Protocol1_12To1_11_1 extends Protocol { registerIncoming(State.PLAY, 0x04, 0x05); registerIncoming(State.PLAY, 0x05, 0x06); registerIncoming(State.PLAY, 0x06, 0x07); - registerIncoming(State.PLAY, 0x07, 0x08); + // registerIncoming(State.PLAY, 0x07, 0x08); - Handled in InventoryPackets registerIncoming(State.PLAY, 0x08, 0x09); registerIncoming(State.PLAY, 0x09, 0x0a); registerIncoming(State.PLAY, 0x0a, 0x0b); @@ -229,7 +326,7 @@ public class Protocol1_12To1_11_1 extends Protocol { } }); registerIncoming(State.PLAY, 0x17, 0x1a); - registerIncoming(State.PLAY, 0x18, 0x1b); + // registerIncoming(State.PLAY, 0x18, 0x1b); - Handled in InventoryPackets registerIncoming(State.PLAY, 0x19, 0x1c); registerIncoming(State.PLAY, 0x1a, 0x1d); registerIncoming(State.PLAY, 0x1b, 0x1e); @@ -262,6 +359,7 @@ public class Protocol1_12To1_11_1 extends Protocol { @Override public void init(UserConnection userConnection) { + userConnection.put(new EntityTracker(userConnection)); if (!userConnection.has(ClientWorld.class)) userConnection.put(new ClientWorld(userConnection)); } diff --git a/common/src/main/java/us/myles/ViaVersion/protocols/protocol1_12to1_11_1/packets/InventoryPackets.java b/common/src/main/java/us/myles/ViaVersion/protocols/protocol1_12to1_11_1/packets/InventoryPackets.java new file mode 100644 index 000000000..573ddad78 --- /dev/null +++ b/common/src/main/java/us/myles/ViaVersion/protocols/protocol1_12to1_11_1/packets/InventoryPackets.java @@ -0,0 +1,147 @@ +package us.myles.ViaVersion.protocols.protocol1_12to1_11_1.packets; + +import us.myles.ViaVersion.api.PacketWrapper; +import us.myles.ViaVersion.api.minecraft.item.Item; +import us.myles.ViaVersion.api.remapper.PacketHandler; +import us.myles.ViaVersion.api.remapper.PacketRemapper; +import us.myles.ViaVersion.api.type.Type; +import us.myles.ViaVersion.packets.State; +import us.myles.ViaVersion.protocols.protocol1_12to1_11_1.BedRewriter; +import us.myles.ViaVersion.protocols.protocol1_12to1_11_1.Protocol1_12To1_11_1; + +public class InventoryPackets { + public static void register(Protocol1_12To1_11_1 protocol) { + /* + Incoming packets + */ + + // Set slot packet + protocol.registerOutgoing(State.PLAY, 0x16, 0x16, new PacketRemapper() { + @Override + public void registerMap() { + map(Type.BYTE); // 0 - Window ID + map(Type.SHORT); // 1 - Slot ID + map(Type.ITEM); // 2 - Slot Value + + handler(new PacketHandler() { + @Override + public void handle(PacketWrapper wrapper) throws Exception { + Item stack = wrapper.get(Type.ITEM, 0); + BedRewriter.toClientItem(stack); + } + }); + } + }); + + // Window items packet + protocol.registerOutgoing(State.PLAY, 0x14, 0x14, new PacketRemapper() { + @Override + public void registerMap() { + map(Type.UNSIGNED_BYTE); // 0 - Window ID + map(Type.ITEM_ARRAY); // 1 - Window Values + + handler(new PacketHandler() { + @Override + public void handle(PacketWrapper wrapper) throws Exception { + Item[] stacks = wrapper.get(Type.ITEM_ARRAY, 0); + for (Item stack : stacks) + BedRewriter.toClientItem(stack); + } + }); + } + }); + + // Entity Equipment Packet + protocol.registerOutgoing(State.PLAY, 0x3C, 0x3E, new PacketRemapper() { + @Override + public void registerMap() { + map(Type.VAR_INT); // 0 - Entity ID + map(Type.VAR_INT); // 1 - Slot ID + map(Type.ITEM); // 2 - Item + + handler(new PacketHandler() { + @Override + public void handle(PacketWrapper wrapper) throws Exception { + Item stack = wrapper.get(Type.ITEM, 0); + BedRewriter.toClientItem(stack); + } + }); + } + }); + + // Plugin message Packet -> Trading + protocol.registerOutgoing(State.PLAY, 0x18, 0x18, new PacketRemapper() { + @Override + public void registerMap() { + map(Type.STRING); // 0 - Channel + + handler(new PacketHandler() { + @Override + public void handle(PacketWrapper wrapper) throws Exception { + if (wrapper.get(Type.STRING, 0).equalsIgnoreCase("MC|TrList")) { + wrapper.passthrough(Type.INT); // Passthrough Window ID + + int size = wrapper.passthrough(Type.UNSIGNED_BYTE); + for (int i = 0; i < size; i++) { + BedRewriter.toClientItem(wrapper.passthrough(Type.ITEM)); // Input Item + BedRewriter.toClientItem(wrapper.passthrough(Type.ITEM)); // Output Item + + boolean secondItem = wrapper.passthrough(Type.BOOLEAN); // Has second item + if (secondItem) + BedRewriter.toClientItem(wrapper.passthrough(Type.ITEM)); // Second Item + + wrapper.passthrough(Type.BOOLEAN); // Trade disabled + wrapper.passthrough(Type.INT); // Number of tools uses + wrapper.passthrough(Type.INT); // Maximum number of trade uses + } + } + } + }); + } + }); + + /* + Incoming packets + */ + + // Click window packet + protocol.registerIncoming(State.PLAY, 0x07, 0x08, new PacketRemapper() { + @Override + public void registerMap() { + map(Type.UNSIGNED_BYTE); // 0 - Window ID + map(Type.SHORT); // 1 - Slot + map(Type.BYTE); // 2 - Button + map(Type.SHORT); // 3 - Action number + map(Type.VAR_INT); // 4 - Mode + map(Type.ITEM); // 5 - Clicked Item + + handler(new PacketHandler() { + @Override + public void handle(PacketWrapper wrapper) throws Exception { + Item item = wrapper.get(Type.ITEM, 0); + BedRewriter.toServerItem(item); + } + }); + } + } + ); + + // Creative Inventory Action + protocol.registerIncoming(State.PLAY, 0x18, 0x1b, new PacketRemapper() { + @Override + public void registerMap() { + map(Type.SHORT); // 0 - Slot + map(Type.ITEM); // 1 - Clicked Item + + handler(new PacketHandler() { + @Override + public void handle(PacketWrapper wrapper) throws Exception { + Item item = wrapper.get(Type.ITEM, 0); + BedRewriter.toServerItem(item); + } + }); + } + } + ); + } +} diff --git a/common/src/main/java/us/myles/ViaVersion/protocols/protocol1_12to1_11_1/storage/EntityTracker.java b/common/src/main/java/us/myles/ViaVersion/protocols/protocol1_12to1_11_1/storage/EntityTracker.java new file mode 100644 index 000000000..1464d0468 --- /dev/null +++ b/common/src/main/java/us/myles/ViaVersion/protocols/protocol1_12to1_11_1/storage/EntityTracker.java @@ -0,0 +1,36 @@ +package us.myles.ViaVersion.protocols.protocol1_12to1_11_1.storage; + +import com.google.common.base.Optional; +import us.myles.ViaVersion.api.data.StoredObject; +import us.myles.ViaVersion.api.data.UserConnection; +import us.myles.ViaVersion.api.entities.Entity1_12Types; + +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; + +public class EntityTracker extends StoredObject { + private final Map clientEntityTypes = new ConcurrentHashMap<>(); + + public EntityTracker(UserConnection user) { + super(user); + } + + public void removeEntity(int entityId) { + clientEntityTypes.remove(entityId); + } + + public void addEntity(int entityId, Entity1_12Types.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)); + } + +}