From 0df089b3cbb1b5e6953ab34eb0ea5f57c9b4e072 Mon Sep 17 00:00:00 2001 From: Gerrygames Date: Wed, 24 Oct 2018 19:05:14 +0200 Subject: [PATCH] 1.14 development --- .../api/entities/Entity1_14Types.java | 295 ++++++++++++++++++ .../api/protocol/ProtocolRegistry.java | 3 + .../api/protocol/ProtocolVersion.java | 2 + .../MetadataRewriter.java | 44 +++ .../Protocol1_14To1_13_2.java | 89 ++++++ .../data/EntityTypeRewriter.java | 67 ++++ .../packets/EntityPackets.java | 157 ++++++++++ .../packets/InventoryPackets.java | 245 +++++++++++++++ .../packets/WorldPackets.java | 189 +++++++++++ .../storage/EntityTracker.java | 33 ++ 10 files changed, 1124 insertions(+) create mode 100644 common/src/main/java/us/myles/ViaVersion/api/entities/Entity1_14Types.java create mode 100644 common/src/main/java/us/myles/ViaVersion/protocols/protocol1_14to1_13_2/MetadataRewriter.java create mode 100644 common/src/main/java/us/myles/ViaVersion/protocols/protocol1_14to1_13_2/Protocol1_14To1_13_2.java create mode 100644 common/src/main/java/us/myles/ViaVersion/protocols/protocol1_14to1_13_2/data/EntityTypeRewriter.java create mode 100644 common/src/main/java/us/myles/ViaVersion/protocols/protocol1_14to1_13_2/packets/EntityPackets.java create mode 100644 common/src/main/java/us/myles/ViaVersion/protocols/protocol1_14to1_13_2/packets/InventoryPackets.java create mode 100644 common/src/main/java/us/myles/ViaVersion/protocols/protocol1_14to1_13_2/packets/WorldPackets.java create mode 100644 common/src/main/java/us/myles/ViaVersion/protocols/protocol1_14to1_13_2/storage/EntityTracker.java diff --git a/common/src/main/java/us/myles/ViaVersion/api/entities/Entity1_14Types.java b/common/src/main/java/us/myles/ViaVersion/api/entities/Entity1_14Types.java new file mode 100644 index 000000000..46384c855 --- /dev/null +++ b/common/src/main/java/us/myles/ViaVersion/api/entities/Entity1_14Types.java @@ -0,0 +1,295 @@ +package us.myles.ViaVersion.api.entities; + +import com.google.common.base.Optional; +import lombok.AllArgsConstructor; +import lombok.Getter; +import us.myles.ViaVersion.api.Via; + + +public class Entity1_14Types { + 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 { + // Auto generated + + ENTITY(-1), + + AREA_EFFECT_CLOUD(0, ENTITY), + ENDER_CRYSTAL(16, ENTITY), + EVOCATION_FANGS(20, ENTITY), + XP_ORB(22, ENTITY), + EYE_OF_ENDER_SIGNAL(23, ENTITY), + FALLING_BLOCK(24, ENTITY), + FIREWORKS_ROCKET(25, ENTITY), + ITEM(32, ENTITY), + LLAMA_SPIT(37, ENTITY), + TNT(56, ENTITY), + SHULKER_BULLET(61, ENTITY), + FISHING_BOBBER(96, ENTITY), + + LIVINGENTITY(-1, ENTITY), + ARMOR_STAND(1, LIVINGENTITY), + PLAYER(95, LIVINGENTITY), + + ABSTRACT_INSENTIENT(-1, LIVINGENTITY), + ENDER_DRAGON(17, ABSTRACT_INSENTIENT), + + ABSTRACT_CREATURE(-1, ABSTRACT_INSENTIENT), + + ABSTRACT_AGEABLE(-1, ABSTRACT_CREATURE), + VILLAGER(80, ABSTRACT_AGEABLE), + + // Animals + ABSTRACT_ANIMAL(-1, ABSTRACT_AGEABLE), + CHICKEN(7, ABSTRACT_ANIMAL), + COW(9, ABSTRACT_ANIMAL), + MOOSHROOM(47, COW), + PIG(52, ABSTRACT_ANIMAL), + POLAR_BEAR(55, ABSTRACT_ANIMAL), + RABBIT(57, ABSTRACT_ANIMAL), + SHEEP(59, ABSTRACT_ANIMAL), + TURTLE(74, ABSTRACT_ANIMAL), + + ABSTRACT_TAMEABLE_ANIMAL(-1, ABSTRACT_ANIMAL), + OCELOT(48, ABSTRACT_TAMEABLE_ANIMAL), + WOLF(88, ABSTRACT_TAMEABLE_ANIMAL), + + ABSTRACT_PARROT(-1, ABSTRACT_TAMEABLE_ANIMAL), + PARROT(51, ABSTRACT_PARROT), + + // Horses + ABSTRACT_HORSE(-1, ABSTRACT_ANIMAL), + CHESTED_HORSE(-1, ABSTRACT_HORSE), + DONKEY(11, CHESTED_HORSE), + MULE(46, CHESTED_HORSE), + LLAMA(36, CHESTED_HORSE), + HORSE(29, ABSTRACT_HORSE), + SKELETON_HORSE(64, ABSTRACT_HORSE), + ZOMBIE_HORSE(90, ABSTRACT_HORSE), + + // Golem + ABSTRACT_GOLEM(-1, ABSTRACT_CREATURE), + SNOWMAN(66, ABSTRACT_GOLEM), + VILLAGER_GOLEM(81, ABSTRACT_GOLEM), + SHULKER(60, ABSTRACT_GOLEM), + + // Fish + ABSTRACT_FISHES(-1, ABSTRACT_CREATURE), + COD_MOB(8, ABSTRACT_FISHES), + PUFFER_FISH(53, ABSTRACT_FISHES), + SALMON_MOB(58, ABSTRACT_FISHES), + TROPICAL_FISH(73, ABSTRACT_FISHES), + + // Monsters + ABSTRACT_MONSTER(-1, ABSTRACT_CREATURE), + BLAZE(4, ABSTRACT_MONSTER), + CREEPER(10, ABSTRACT_MONSTER), + ENDERMITE(19, ABSTRACT_MONSTER), + ENDERMAN(18, ABSTRACT_MONSTER), + GIANT(27, ABSTRACT_MONSTER), + SILVERFISH(62, ABSTRACT_MONSTER), + VEX(79, ABSTRACT_MONSTER), + WITCH(84, ABSTRACT_MONSTER), + WITHER(85, ABSTRACT_MONSTER), + + // Illagers + ABSTRACT_ILLAGER_BASE(-1, ABSTRACT_MONSTER), + ABSTRACT_EVO_ILLU_ILLAGER(-1, ABSTRACT_ILLAGER_BASE), + EVOCATION_ILLAGER(21, ABSTRACT_EVO_ILLU_ILLAGER), + ILLUSION_ILLAGER(31, ABSTRACT_EVO_ILLU_ILLAGER), + VINDICATION_ILLAGER(81, ABSTRACT_ILLAGER_BASE), + + // Skeletons + ABSTRACT_SKELETON(-1, ABSTRACT_MONSTER), + SKELETON(63, ABSTRACT_SKELETON), + STRAY(72, ABSTRACT_SKELETON), + WITHER_SKELETON(86, ABSTRACT_SKELETON), + + // Guardians + GUARDIAN(28, ABSTRACT_MONSTER), + ELDER_GUARDIAN(15, GUARDIAN), + + // Spiders + SPIDER(70, ABSTRACT_MONSTER), + CAVE_SPIDER(6, SPIDER), + + // Zombies - META CHECKED + ZOMBIE(89, ABSTRACT_MONSTER), + DROWNED(14, ZOMBIE), + HUSK(30, ZOMBIE), + ZOMBIE_PIGMAN(54, ZOMBIE), + ZOMBIE_VILLAGER(91, ZOMBIE), + + // Flying entities + ABSTRACT_FLYING(-1, ABSTRACT_INSENTIENT), + GHAST(26, ABSTRACT_FLYING), + PHANTOM(92, ABSTRACT_FLYING), + + ABSTRACT_AMBIENT(-1, ABSTRACT_INSENTIENT), + BAT(3, ABSTRACT_AMBIENT), + + ABSTRACT_WATERMOB(-1, ABSTRACT_INSENTIENT), + SQUID(71, ABSTRACT_WATERMOB), + + // Slimes + SLIME(65, ABSTRACT_INSENTIENT), + MAGMA_CUBE(38, SLIME), + + // Hangable objects + ABSTRACT_HANGING(-1, ENTITY), + LEASH_KNOT(35, ABSTRACT_HANGING), + ITEM_FRAME(33, ABSTRACT_HANGING), + PAINTING(49, ABSTRACT_HANGING), + + ABSTRACT_LIGHTNING(-1, ENTITY), + LIGHTNING_BOLT(94, ABSTRACT_LIGHTNING), + + // Arrows + ABSTRACT_ARROW(-1, ENTITY), + ARROW(2, ABSTRACT_ARROW), + SPECTRAL_ARROW(69, ABSTRACT_ARROW), + TRIDENT(97, ABSTRACT_ARROW), + + // Fireballs + ABSTRACT_FIREBALL(-1, ENTITY), + DRAGON_FIREBALL(13, ABSTRACT_FIREBALL), + FIREBALL(34, ABSTRACT_FIREBALL), + SMALL_FIREBALL(66, ABSTRACT_FIREBALL), + WITHER_SKULL(87, ABSTRACT_FIREBALL), + + // Projectiles + PROJECTILE_ABSTRACT(-1, ENTITY), + SNOWBALL(68, PROJECTILE_ABSTRACT), + ENDER_PEARL(76, PROJECTILE_ABSTRACT), + EGG(75, PROJECTILE_ABSTRACT), + POTION(78, PROJECTILE_ABSTRACT), + XP_BOTTLE(77, PROJECTILE_ABSTRACT), + + // Vehicles + MINECART_ABSTRACT(-1, ENTITY), + CHESTED_MINECART_ABSTRACT(-1, MINECART_ABSTRACT), + CHEST_MINECART(40, CHESTED_MINECART_ABSTRACT), + HOPPER_MINECART(43, CHESTED_MINECART_ABSTRACT), + MINECART(39, MINECART_ABSTRACT), + FURNACE_MINECART(42, MINECART_ABSTRACT), + COMMANDBLOCK_MINECART(41, MINECART_ABSTRACT), + TNT_MINECART(45, MINECART_ABSTRACT), + SPAWNER_MINECART(44, MINECART_ABSTRACT), + BOAT(5, 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 == type) + return true; + + parent = parent.getParent(); + } while (parent != null); + + return false; + } + } + + @AllArgsConstructor + @Getter + public enum ObjectTypes { + BOAT(1, EntityType.BOAT), + ITEM(2, EntityType.ITEM), + AREA_EFFECT_CLOUD(3, EntityType.AREA_EFFECT_CLOUD), + MINECART(10, EntityType.MINECART_ABSTRACT), + TNT_PRIMED(50, EntityType.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.LLAMA_SPIT), + FALLING_BLOCK(70, EntityType.FALLING_BLOCK), + ITEM_FRAME(71, EntityType.ITEM_FRAME), + ENDER_SIGNAL(72, EntityType.EYE_OF_ENDER_SIGNAL), + POTION(73, EntityType.POTION), + THROWN_EXP_BOTTLE(75, EntityType.XP_BOTTLE), + FIREWORK(76, EntityType.FIREWORKS_ROCKET), + LEASH(77, EntityType.LEASH_KNOT), + ARMOR_STAND(78, EntityType.ARMOR_STAND), + EVOCATION_FANGS(79, EntityType.EVOCATION_FANGS), + FISHIHNG_HOOK(90, EntityType.FISHING_BOBBER), + SPECTRAL_ARROW(91, EntityType.SPECTRAL_ARROW), + DRAGON_FIREBALL(93, EntityType.DRAGON_FIREBALL), + ; + + private final int id; + private final EntityType type; + + public static Optional findById(int id) { + if (id == -1) + return Optional.absent(); + + for (ObjectTypes ent : ObjectTypes.values()) + if (ent.getId() == id) + return Optional.of(ent); + + return Optional.absent(); + } + + public static Optional getPCEntity(int id) { + Optional output = findById(id); + + if (!output.isPresent()) + return Optional.absent(); + return Optional.of(output.get().getType()); + } + } +} diff --git a/common/src/main/java/us/myles/ViaVersion/api/protocol/ProtocolRegistry.java b/common/src/main/java/us/myles/ViaVersion/api/protocol/ProtocolRegistry.java index 76de968b7..4037abf26 100644 --- a/common/src/main/java/us/myles/ViaVersion/api/protocol/ProtocolRegistry.java +++ b/common/src/main/java/us/myles/ViaVersion/api/protocol/ProtocolRegistry.java @@ -15,6 +15,7 @@ import us.myles.ViaVersion.protocols.protocol1_12_2to1_12_1.Protocol1_12_2TO1_12 import us.myles.ViaVersion.protocols.protocol1_12to1_11_1.Protocol1_12To1_11_1; import us.myles.ViaVersion.protocols.protocol1_13_2to1_13_1.Protocol1_13_2To1_13_1; import us.myles.ViaVersion.protocols.protocol1_13to1_12_2.Protocol1_13To1_12_2; +import us.myles.ViaVersion.protocols.protocol1_14to1_13_2.Protocol1_14To1_13_2; import us.myles.ViaVersion.protocols.protocol1_9_1_2to1_9_3_4.Protocol1_9_1_2TO1_9_3_4; import us.myles.ViaVersion.protocols.protocol1_9_1to1_9.Protocol1_9_1TO1_9; import us.myles.ViaVersion.protocols.protocol1_9_3to1_9_1_2.Protocol1_9_3TO1_9_1_2; @@ -59,6 +60,8 @@ public class ProtocolRegistry { registerProtocol(new Protocol1_13To1_12_2(), Collections.singletonList(ProtocolVersion.v1_13.getId()), ProtocolVersion.v1_12_2.getId()); registerProtocol(new Protocol1_13_1To1_13(), Arrays.asList(ProtocolVersion.v1_13_1.getId()), ProtocolVersion.v1_13.getId()); registerProtocol(new Protocol1_13_2To1_13_1(), Arrays.asList(ProtocolVersion.v1_13_2.getId()), ProtocolVersion.v1_13_1.getId()); + + registerProtocol(new Protocol1_14To1_13_2(), Arrays.asList(ProtocolVersion.v1_14.getId()), ProtocolVersion.v1_13_2.getId()); } /** diff --git a/common/src/main/java/us/myles/ViaVersion/api/protocol/ProtocolVersion.java b/common/src/main/java/us/myles/ViaVersion/api/protocol/ProtocolVersion.java index be8d588d4..a91084aa8 100644 --- a/common/src/main/java/us/myles/ViaVersion/api/protocol/ProtocolVersion.java +++ b/common/src/main/java/us/myles/ViaVersion/api/protocol/ProtocolVersion.java @@ -35,6 +35,7 @@ public class ProtocolVersion { public static final ProtocolVersion v1_13; public static final ProtocolVersion v1_13_1; public static final ProtocolVersion v1_13_2; + public static final ProtocolVersion v1_14; public static final ProtocolVersion unknown; private final int id; @@ -66,6 +67,7 @@ public class ProtocolVersion { register(v1_13 = new ProtocolVersion(393, "1.13")); register(v1_13_1 = new ProtocolVersion(401, "1.13.1")); register(v1_13_2 = new ProtocolVersion(404, "1.13.2")); + register(v1_14 = new ProtocolVersion(441, "1.14")); register(unknown = new ProtocolVersion(-1, "UNKNOWN")); } diff --git a/common/src/main/java/us/myles/ViaVersion/protocols/protocol1_14to1_13_2/MetadataRewriter.java b/common/src/main/java/us/myles/ViaVersion/protocols/protocol1_14to1_13_2/MetadataRewriter.java new file mode 100644 index 000000000..18a865c35 --- /dev/null +++ b/common/src/main/java/us/myles/ViaVersion/protocols/protocol1_14to1_13_2/MetadataRewriter.java @@ -0,0 +1,44 @@ +package us.myles.ViaVersion.protocols.protocol1_14to1_13_2; + +import us.myles.ViaVersion.api.Via; +import us.myles.ViaVersion.api.data.UserConnection; +import us.myles.ViaVersion.api.entities.Entity1_14Types; +import us.myles.ViaVersion.api.minecraft.item.Item; +import us.myles.ViaVersion.api.minecraft.metadata.Metadata; +import us.myles.ViaVersion.api.minecraft.metadata.types.MetaType1_13_2; +import us.myles.ViaVersion.protocols.protocol1_14to1_13_2.packets.InventoryPackets; + +import java.util.ArrayList; +import java.util.List; + +public class MetadataRewriter { + + public static void handleMetadata(int entityId, Entity1_14Types.EntityType type, List metadatas, UserConnection connection) { + for (Metadata metadata : new ArrayList<>(metadatas)) { + try { + // 1.13 changed item to flat item (no data) + if (metadata.getMetaType() == MetaType1_13_2.Slot) { + InventoryPackets.toClient((Item) metadata.getValue()); + } else if (metadata.getMetaType() == MetaType1_13_2.BlockID) { + // Convert to new block id + int data = (int) metadata.getValue(); + metadata.setValue(Protocol1_14To1_13_2.getNewBlockStateId(data)); + } + if (type == null) continue; + if (type.isOrHasParent(Entity1_14Types.EntityType.MINECART_ABSTRACT) && metadata.getId() == 9) { + // New block format + int data = (int) metadata.getValue(); + metadata.setValue(Protocol1_14To1_13_2.getNewBlockStateId(data)); + } + } 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_14to1_13_2/Protocol1_14To1_13_2.java b/common/src/main/java/us/myles/ViaVersion/protocols/protocol1_14to1_13_2/Protocol1_14To1_13_2.java new file mode 100644 index 000000000..dc32e66a0 --- /dev/null +++ b/common/src/main/java/us/myles/ViaVersion/protocols/protocol1_14to1_13_2/Protocol1_14To1_13_2.java @@ -0,0 +1,89 @@ +package us.myles.ViaVersion.protocols.protocol1_14to1_13_2; + +import us.myles.ViaVersion.api.PacketWrapper; +import us.myles.ViaVersion.api.data.UserConnection; +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.packets.State; +import us.myles.ViaVersion.protocols.protocol1_14to1_13_2.packets.EntityPackets; +import us.myles.ViaVersion.protocols.protocol1_14to1_13_2.packets.InventoryPackets; +import us.myles.ViaVersion.protocols.protocol1_14to1_13_2.packets.WorldPackets; +import us.myles.ViaVersion.protocols.protocol1_14to1_13_2.storage.EntityTracker; +import us.myles.ViaVersion.protocols.protocol1_9_3to1_9_1_2.storage.ClientWorld; + +public class Protocol1_14To1_13_2 extends Protocol { + @Override + protected void registerPackets() { + InventoryPackets.register(this); + EntityPackets.register(this); + WorldPackets.register(this); + + registerOutgoing(State.PLAY, 0x4E, 0x4F); + registerOutgoing(State.PLAY, 0x4F, 0x50); + registerOutgoing(State.PLAY, 0x50, 0x51); + registerOutgoing(State.PLAY, 0x51, 0x52); + registerOutgoing(State.PLAY, 0x52, 0x53); + registerOutgoing(State.PLAY, 0x53, 0x54); + + registerOutgoing(State.PLAY, 0x55, 0x56, new PacketRemapper() { + @Override + public void registerMap() { + handler(new PacketHandler() { + @Override + public void handle(PacketWrapper wrapper) throws Exception { + int blockTagsSize = wrapper.passthrough(Type.VAR_INT); // block tags + for (int i = 0; i < blockTagsSize; i++) { + wrapper.passthrough(Type.STRING); + Integer[] blockIds = wrapper.passthrough(Type.VAR_INT_ARRAY); + for (int j = 0; j < blockIds.length; j++) { + blockIds[j] = getNewBlockId(blockIds[j]); + } + } + int itemTagsSize = wrapper.passthrough(Type.VAR_INT); // item tags + for (int i = 0; i < itemTagsSize; i++) { + wrapper.passthrough(Type.STRING); + Integer[] itemIds = wrapper.passthrough(Type.VAR_INT_ARRAY); + for (int j = 0; j < itemIds.length; j++) { + itemIds[j] = InventoryPackets.getNewItemId(itemIds[j]); + } + } + int fluidTagsSize = wrapper.passthrough(Type.VAR_INT); // fluid tags + for (int i = 0; i < fluidTagsSize; i++) { + wrapper.passthrough(Type.STRING); + wrapper.passthrough(Type.VAR_INT_ARRAY); + } + wrapper.write(Type.VAR_INT, 0); // new unknown tags + } + }); + } + }); + } + + public static int getNewBlockStateId(int id) { + if (id < 1121) return id; + else if (id < 3108) return id + 3; + else if (id < 3278) return id + 163; + else if (id < 3978) return id + 203; + else if (id < 3984) return id + 207; + else if (id < 3988) return id + 197; + else if (id < 5284) return id + 203; + else if (id < 7300) return id + 206; + else if (id < 8591) return id + 212; + else if (id < 8595) return id + 226; + else return id + 2192; + } + + public static int getNewBlockId(int id) { + return id; //TODO + } + + @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_14to1_13_2/data/EntityTypeRewriter.java b/common/src/main/java/us/myles/ViaVersion/protocols/protocol1_14to1_13_2/data/EntityTypeRewriter.java new file mode 100644 index 000000000..3c33a2372 --- /dev/null +++ b/common/src/main/java/us/myles/ViaVersion/protocols/protocol1_14to1_13_2/data/EntityTypeRewriter.java @@ -0,0 +1,67 @@ +package us.myles.ViaVersion.protocols.protocol1_14to1_13_2.data; + +import com.google.common.base.Optional; + +import java.util.HashMap; +import java.util.Map; + +public class EntityTypeRewriter { + private static Map entityTypes = new HashMap<>(); + private static Map objectTypes = new HashMap<>(); + + static { + regEnt(74, 75); // egg + regEnt(75, 76); // ender_pearl + regEnt(76, 77); // experience_bottle + regEnt(93, 96); // fishing_bobber + regEnt(80, 81); // iron_golem + regEnt(91, 94); // lightning_bolt + regEnt(50, 51); // parrot + regEnt(90, 92); // phantom + regEnt(51, 52); // pig + regEnt(92, 95); // player + regEnt(54, 55); // polar_bear + regEnt(77, 78); // potion + regEnt(52, 53); // pufferfish + regEnt(56, 57); // rabbit + regEnt(57, 58); // salmon + regEnt(58, 59); // sheep + regEnt(59, 60); // shulker + regEnt(60, 61); // shulker_bullet + regEnt(61, 62); // silverfish + regEnt(62, 63); // skeleton + regEnt(63, 64); // skeleton_horse + regEnt(64, 65); // slime + regEnt(65, 66); // small_fireball + regEnt(66, 67); // snowgolem + regEnt(67, 68); // snowball + regEnt(68, 69); // spectral_arrow + regEnt(69, 70); // spider + regEnt(70, 71); // squid + regEnt(71, 72); // stray + regEnt(55, 56); // tnt + regEnt(94, 97); // trident + regEnt(72, 73); // tropical_fish + regEnt(73, 74); // turtle + regEnt(78, 79); // vex + regEnt(79, 80); // villager + regEnt(81, 82); // vindicator + regEnt(82, 84); // witch + regEnt(83, 85); // wither + regEnt(84, 86); // wither_skeleton + regEnt(85, 87); // wither_skull + regEnt(86, 88); // wolf + regEnt(87, 89); // zombie + regEnt(88, 90); // zombie_horse + regEnt(53, 54); // zombie_pigman + regEnt(89, 91); // zombie_villager + } + + private static void regEnt(int type1_13, int type1_14) { + entityTypes.put(type1_13, type1_14); + } + + public static Optional getNewId(int type1_13) { + return Optional.fromNullable(entityTypes.get(type1_13)); + } +} diff --git a/common/src/main/java/us/myles/ViaVersion/protocols/protocol1_14to1_13_2/packets/EntityPackets.java b/common/src/main/java/us/myles/ViaVersion/protocols/protocol1_14to1_13_2/packets/EntityPackets.java new file mode 100644 index 000000000..60218147e --- /dev/null +++ b/common/src/main/java/us/myles/ViaVersion/protocols/protocol1_14to1_13_2/packets/EntityPackets.java @@ -0,0 +1,157 @@ +package us.myles.ViaVersion.protocols.protocol1_14to1_13_2.packets; + +import com.google.common.base.Optional; +import us.myles.ViaVersion.api.PacketWrapper; +import us.myles.ViaVersion.api.entities.Entity1_14Types; +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_13_2; +import us.myles.ViaVersion.packets.State; +import us.myles.ViaVersion.protocols.protocol1_14to1_13_2.MetadataRewriter; +import us.myles.ViaVersion.protocols.protocol1_14to1_13_2.Protocol1_14To1_13_2; +import us.myles.ViaVersion.protocols.protocol1_14to1_13_2.data.EntityTypeRewriter; +import us.myles.ViaVersion.protocols.protocol1_14to1_13_2.storage.EntityTracker; + +public class EntityPackets { + + public static void register(Protocol protocol) { + + // Spawn entity + protocol.registerOutgoing(State.PLAY, 0x0, 0x0, new PacketRemapper() { + @Override + public void registerMap() { + map(Type.VAR_INT); // 0 - Entity id + map(Type.UUID); // 1 - UUID + map(Type.BYTE); // 2 - Type + map(Type.DOUBLE); // 3 - X + map(Type.DOUBLE); // 4 - Y + map(Type.DOUBLE); // 5 - Z + map(Type.BYTE); // 6 - Pitch + map(Type.BYTE); // 7 - Yaw + map(Type.INT); // 8 - Data + + // 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_14Types.EntityType entType = Entity1_14Types.getTypeFromId(type, true); + + if (entType != null) { + if (entType.is(Entity1_14Types.EntityType.FALLING_BLOCK)) { + int data = wrapper.get(Type.INT, 0); + wrapper.set(Type.INT, 0, Protocol1_14To1_13_2.getNewBlockStateId(data)); + } + } + // Register Type ID + wrapper.user().get(EntityTracker.class).addEntity(entityId, entType); + } + }); + } + }); + + // Spawn mob packet + protocol.registerOutgoing(State.PLAY, 0x3, 0x3, new PacketRemapper() { + @Override + public void registerMap() { + map(Type.VAR_INT); // 0 - Entity ID + map(Type.UUID); // 1 - Entity UUID + map(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_13_2.METADATA_LIST); // 12 - Metadata + + handler(new PacketHandler() { + @Override + public void handle(PacketWrapper wrapper) throws Exception { + int entityId = wrapper.get(Type.VAR_INT, 0); + int type = wrapper.get(Type.VAR_INT, 1); + + type = EntityTypeRewriter.getNewId(type).or(type); + + Entity1_14Types.EntityType entType = Entity1_14Types.getTypeFromId(type, false); + + wrapper.set(Type.VAR_INT, 1, type); + + // Register Type ID + wrapper.user().get(EntityTracker.class).addEntity(entityId, entType); + + MetadataRewriter.handleMetadata(entityId, entType, wrapper.get(Types1_13_2.METADATA_LIST, 0), wrapper.user()); + } + }); + } + }); + + // Spawn player packet + protocol.registerOutgoing(State.PLAY, 0x05, 0x05, new PacketRemapper() { + @Override + public void registerMap() { + map(Type.VAR_INT); // 0 - Entity ID + map(Type.UUID); // 1 - Player UUID + map(Type.DOUBLE); // 2 - X + map(Type.DOUBLE); // 3 - Y + map(Type.DOUBLE); // 4 - Z + map(Type.BYTE); // 5 - Yaw + map(Type.BYTE); // 6 - Pitch + map(Types1_13_2.METADATA_LIST); // 7 - Metadata + + handler(new PacketHandler() { + @Override + public void handle(PacketWrapper wrapper) throws Exception { + int entityId = wrapper.get(Type.VAR_INT, 0); + + Entity1_14Types.EntityType entType = Entity1_14Types.EntityType.PLAYER; + // Register Type ID + wrapper.user().get(EntityTracker.class).addEntity(entityId, entType); + MetadataRewriter.handleMetadata(entityId, entType, wrapper.get(Types1_13_2.METADATA_LIST, 0), wrapper.user()); + } + }); + } + }); + + // Destroy entities + protocol.registerOutgoing(State.PLAY, 0x35, 0x35, 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); + } + }); + } + }); + + // Metadata packet + protocol.registerOutgoing(State.PLAY, 0x3F, 0x3F, new PacketRemapper() { + @Override + public void registerMap() { + map(Type.VAR_INT); // 0 - Entity ID + map(Types1_13_2.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); + MetadataRewriter.handleMetadata(entityId, type.orNull(), wrapper.get(Types1_13_2.METADATA_LIST, 0), wrapper.user()); + } + }); + } + }); + + } +} diff --git a/common/src/main/java/us/myles/ViaVersion/protocols/protocol1_14to1_13_2/packets/InventoryPackets.java b/common/src/main/java/us/myles/ViaVersion/protocols/protocol1_14to1_13_2/packets/InventoryPackets.java new file mode 100644 index 000000000..49146bc31 --- /dev/null +++ b/common/src/main/java/us/myles/ViaVersion/protocols/protocol1_14to1_13_2/packets/InventoryPackets.java @@ -0,0 +1,245 @@ +package us.myles.ViaVersion.protocols.protocol1_14to1_13_2.packets; + +import us.myles.ViaVersion.api.PacketWrapper; +import us.myles.ViaVersion.api.minecraft.item.Item; +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.packets.State; + +public class InventoryPackets { + + public static void register(Protocol protocol) { + + /* + Outgoing packets + */ + + // Set slot packet + protocol.registerOutgoing(State.PLAY, 0x17, 0x17, new PacketRemapper() { + @Override + public void registerMap() { + map(Type.BYTE); // 0 - Window ID + map(Type.SHORT); // 1 - Slot ID + map(Type.FLAT_VAR_INT_ITEM); // 2 - Slot Value + + handler(new PacketHandler() { + @Override + public void handle(PacketWrapper wrapper) throws Exception { + Item stack = wrapper.get(Type.FLAT_VAR_INT_ITEM, 0); + toClient(stack); + } + }); + } + }); + + // Window items packet + protocol.registerOutgoing(State.PLAY, 0x15, 0x15, new PacketRemapper() { + @Override + public void registerMap() { + map(Type.UNSIGNED_BYTE); // 0 - Window ID + map(Type.FLAT_VAR_INT_ITEM_ARRAY); // 1 - Window Values + + handler(new PacketHandler() { + @Override + public void handle(PacketWrapper wrapper) throws Exception { + Item[] stacks = wrapper.get(Type.FLAT_VAR_INT_ITEM_ARRAY, 0); + for (Item stack : stacks) + toClient(stack); + } + }); + } + }); + + // Plugin message + protocol.registerOutgoing(State.PLAY, 0x19, 0x19, new PacketRemapper() { + @Override + public void registerMap() { + map(Type.STRING); // Channel + handler(new PacketHandler() { + @Override + public void handle(PacketWrapper wrapper) throws Exception { + String channel = wrapper.get(Type.STRING, 0); + if (channel.equals("minecraft:trader_list") || channel.equals("trader_list")) { + wrapper.passthrough(Type.INT); // Passthrough Window ID + + int size = wrapper.passthrough(Type.UNSIGNED_BYTE); + for (int i = 0; i < size; i++) { + // Input Item + toClient(wrapper.passthrough(Type.FLAT_VAR_INT_ITEM)); + // Output Item + InventoryPackets.toClient(wrapper.passthrough(Type.FLAT_VAR_INT_ITEM)); + + boolean secondItem = wrapper.passthrough(Type.BOOLEAN); // Has second item + if (secondItem) { + // Second Item + InventoryPackets.toClient(wrapper.passthrough(Type.FLAT_VAR_INT_ITEM)); + } + + wrapper.passthrough(Type.BOOLEAN); // Trade disabled + wrapper.passthrough(Type.INT); // Number of tools uses + wrapper.passthrough(Type.INT); // Maximum number of trade uses + } + } + } + }); + } + }); + + // Entity Equipment Packet + protocol.registerOutgoing(State.PLAY, 0x42, 0x42, new PacketRemapper() { + @Override + public void registerMap() { + map(Type.VAR_INT); // 0 - Entity ID + map(Type.VAR_INT); // 1 - Slot ID + map(Type.FLAT_VAR_INT_ITEM); // 2 - Item + + handler(new PacketHandler() { + @Override + public void handle(PacketWrapper wrapper) throws Exception { + Item stack = wrapper.get(Type.FLAT_VAR_INT_ITEM, 0); + toClient(stack); + } + }); + } + }); + + // Declare Recipes + protocol.registerOutgoing(State.PLAY, 0x54, 0x55, new PacketRemapper() { + @Override + public void registerMap() { + handler(new PacketHandler() { + @Override + public void handle(PacketWrapper wrapper) throws Exception { + int size = wrapper.passthrough(Type.VAR_INT); + int deleted = 0; + for (int i = 0; i < size; i++) { + String id = wrapper.read(Type.STRING); // Recipe Identifier + String type = wrapper.read(Type.STRING); + if (type.equals("crafting_special_banneraddpattern")) { + deleted++; + continue; + } + wrapper.write(Type.STRING, id); + wrapper.write(Type.STRING, type); + + if (type.equals("crafting_shapeless")) { + wrapper.passthrough(Type.STRING); // Group + int ingredientsNo = wrapper.passthrough(Type.VAR_INT); + for (int j = 0; j < ingredientsNo; j++) { + Item[] items = wrapper.passthrough(Type.FLAT_VAR_INT_ITEM_ARRAY_VAR_INT); // Ingredients + } + wrapper.passthrough(Type.FLAT_VAR_INT_ITEM); // Result + } else if (type.equals("crafting_shaped")) { + int ingredientsNo = wrapper.passthrough(Type.VAR_INT) * wrapper.passthrough(Type.VAR_INT); + wrapper.passthrough(Type.STRING); // Group + for (int j = 0; j < ingredientsNo; j++) { + wrapper.passthrough(Type.FLAT_VAR_INT_ITEM_ARRAY_VAR_INT); // Ingredients + } + wrapper.passthrough(Type.FLAT_VAR_INT_ITEM); // Result + } else if (type.equals("smelting")) { + wrapper.passthrough(Type.STRING); // Group + wrapper.passthrough(Type.FLAT_VAR_INT_ITEM_ARRAY_VAR_INT); // Ingredients + wrapper.passthrough(Type.FLAT_VAR_INT_ITEM); + wrapper.passthrough(Type.FLOAT); // EXP + wrapper.passthrough(Type.VAR_INT); // Cooking time + } + } + wrapper.set(Type.VAR_INT, 0, size - deleted); + } + }); + } + }); + + + /* + Incoming packets + */ + + // Click window packet + protocol.registerIncoming(State.PLAY, 0x08, 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.FLAT_VAR_INT_ITEM); // 5 - Clicked Item + + handler(new PacketHandler() { + @Override + public void handle(PacketWrapper wrapper) throws Exception { + Item item = wrapper.get(Type.FLAT_VAR_INT_ITEM, 0); + toServer(item); + } + }); + } + }); + + // Creative Inventory Action + protocol.registerIncoming(State.PLAY, 0x24, 0x24, new PacketRemapper() { + @Override + public void registerMap() { + map(Type.SHORT); // 0 - Slot + map(Type.FLAT_VAR_INT_ITEM); // 1 - Clicked Item + + handler(new PacketHandler() { + @Override + public void handle(PacketWrapper wrapper) throws Exception { + Item item = wrapper.get(Type.FLAT_VAR_INT_ITEM, 0); + toServer(item); + } + }); + } + }); + } + + + public static void toClient(Item item) { + if (item == null) return; + item.setId((short) getNewItemId(item.getId())); + } + + public static int getNewItemId(int id) { + if (id < 108) return id; + else if (id < 119) return id + 3; + else if (id < 460) return id + 4; + else if (id < 542) return id + 43; + else if (id < 561) return id + 48; + else if (id < 593) return id + 49; + else if (id < 657) return id + 53; + else if (id < 662) return id + 54; + else if (id < 665) return id + 55; + else return id + 56; + } + + public static void toServer(Item item) { + if (item == null) return; + item.setId((short) getOldItemId(item.getId())); + } + + public static int getOldItemId(int id) { + if (id < 108) return id; + else if (id < 111) return 1; + else if (id < 122) return id - 3; + else if (id < 123) return 1; + else if (id < 464) return id - 4; + else if (id < 503) return 1; + else if (id < 585) return id - 43; + else if (id < 590) return 1; + else if (id < 609) return id - 48; + else if (id < 610) return 1; + else if (id < 642) return id - 49; + else if (id < 646) return 1; + else if (id < 710) return id - 53; + else if (id < 711) return 1; + else if (id < 716) return id - 54; + else if (id < 717) return 1; + else if (id < 720) return id - 55; + else if (id < 721) return 1; + else if (id < 846) return id - 56; + else return 1; + } +} diff --git a/common/src/main/java/us/myles/ViaVersion/protocols/protocol1_14to1_13_2/packets/WorldPackets.java b/common/src/main/java/us/myles/ViaVersion/protocols/protocol1_14to1_13_2/packets/WorldPackets.java new file mode 100644 index 000000000..60b7eadd9 --- /dev/null +++ b/common/src/main/java/us/myles/ViaVersion/protocols/protocol1_14to1_13_2/packets/WorldPackets.java @@ -0,0 +1,189 @@ +package us.myles.ViaVersion.protocols.protocol1_14to1_13_2.packets; + +import us.myles.ViaVersion.api.PacketWrapper; +import us.myles.ViaVersion.api.minecraft.BlockChangeRecord; +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.packets.State; +import us.myles.ViaVersion.protocols.protocol1_13to1_12_2.types.Chunk1_13Type; +import us.myles.ViaVersion.protocols.protocol1_14to1_13_2.Protocol1_14To1_13_2; +import us.myles.ViaVersion.protocols.protocol1_9_3to1_9_1_2.storage.ClientWorld; + +import java.util.Arrays; + +public class WorldPackets { + + public static void register(Protocol protocol) { + //Chunk + protocol.registerOutgoing(State.PLAY, 0x22, 0x22, new PacketRemapper() { + @Override + public void registerMap() { + handler(new PacketHandler() { + @Override + public void handle(PacketWrapper wrapper) throws Exception { + ClientWorld clientWorld = wrapper.user().get(ClientWorld.class); + Chunk chunk = wrapper.passthrough(new Chunk1_13Type(clientWorld)); + + for (ChunkSection section : chunk.getSections()) { + if (section != null) { + for (int i = 0; i < section.getPalette().size(); i++) { + section.getPalette().set(i, Protocol1_14To1_13_2.getNewBlockStateId(section.getPalette().get(i))); + } + } + } + + if (chunk.isBiomeData()) { + Arrays.fill(chunk.getBiomeData(), (byte) 1); + } + } + }); + } + }); + + // Block Action + protocol.registerOutgoing(State.PLAY, 0x0A, 0x0A, new PacketRemapper() { + @Override + public void registerMap() { + map(Type.POSITION); // Location + map(Type.UNSIGNED_BYTE); // Action id + map(Type.UNSIGNED_BYTE); // Action param + map(Type.VAR_INT); // Block id - /!\ NOT BLOCK STATE + handler(new PacketHandler() { + @Override + public void handle(PacketWrapper wrapper) throws Exception { + //wrapper.set(Type.VAR_INT, 0, Protocol1_14To1_13_2.getNewBlockId(wrapper.get(Type.VAR_INT, 0))); //TODO block ids + } + }); + } + }); + + // Block Change + protocol.registerOutgoing(State.PLAY, 0xB, 0xB, new PacketRemapper() { + @Override + public void registerMap() { + map(Type.POSITION); + map(Type.VAR_INT); + handler(new PacketHandler() { + @Override + public void handle(PacketWrapper wrapper) throws Exception { + int id = wrapper.get(Type.VAR_INT, 0); + + wrapper.set(Type.VAR_INT, 0, Protocol1_14To1_13_2.getNewBlockStateId(id)); + } + }); + } + }); + + // Multi Block Change + protocol.registerOutgoing(State.PLAY, 0xF, 0xF, new PacketRemapper() { + @Override + public void registerMap() { + map(Type.INT); // 0 - Chunk X + map(Type.INT); // 1 - Chunk Z + map(Type.BLOCK_CHANGE_RECORD_ARRAY); // 2 - Records + handler(new PacketHandler() { + @Override + public void handle(PacketWrapper wrapper) throws Exception { + // Convert ids + for (BlockChangeRecord record : wrapper.get(Type.BLOCK_CHANGE_RECORD_ARRAY, 0)) { + int id = record.getBlockId(); + record.setBlockId(Protocol1_14To1_13_2.getNewBlockStateId(id)); + } + } + }); + } + }); + + // Effect packet + protocol.registerOutgoing(State.PLAY, 0x23, 0x23, new PacketRemapper() { + @Override + public void registerMap() { + map(Type.INT); // Effect Id + map(Type.POSITION); // Location + map(Type.INT); // Data + handler(new PacketHandler() { + @Override + public void handle(PacketWrapper wrapper) throws Exception { + int id = wrapper.get(Type.INT, 0); + int data = wrapper.get(Type.INT, 1); + if (id == 1010) { // Play record + wrapper.set(Type.INT, 1, data = InventoryPackets.getNewItemId(data)); + } else if (id == 2001) { // Block break + block break sound + wrapper.set(Type.INT, 1, data = Protocol1_14To1_13_2.getNewBlockStateId(data)); + } + } + }); + } + }); + + //join game + protocol.registerOutgoing(State.PLAY, 0x25, 0x25, new PacketRemapper() { + @Override + public void registerMap() { + map(Type.INT); // 0 - Entity ID + map(Type.UNSIGNED_BYTE); // 1 - Gamemode + map(Type.INT); // 2 - Dimension + + handler(new PacketHandler() { + @Override + public void handle(PacketWrapper wrapper) throws Exception { + // Store the player + ClientWorld clientChunks = wrapper.user().get(ClientWorld.class); + int dimensionId = wrapper.get(Type.INT, 1); + clientChunks.setEnvironment(dimensionId); + } + }); + } + }); + + //respawn + protocol.registerOutgoing(State.PLAY, 0x38, 0x38, new PacketRemapper() { + @Override + public void registerMap() { + map(Type.INT); // 0 - Dimension ID + handler(new PacketHandler() { + @Override + public void handle(PacketWrapper wrapper) throws Exception { + ClientWorld clientWorld = wrapper.user().get(ClientWorld.class); + int dimensionId = wrapper.get(Type.INT, 0); + clientWorld.setEnvironment(dimensionId); + } + }); + } + }); + + //spawn particle + protocol.registerOutgoing(State.PLAY, 0x24, 0x24, new PacketRemapper() { + @Override + public void registerMap() { + map(Type.INT); // 0 - Particle ID + map(Type.BOOLEAN); // 1 - Long Distance + map(Type.FLOAT); // 2 - X + map(Type.FLOAT); // 3 - Y + map(Type.FLOAT); // 4 - Z + map(Type.FLOAT); // 5 - Offset X + map(Type.FLOAT); // 6 - Offset Y + map(Type.FLOAT); // 7 - Offset Z + map(Type.FLOAT); // 8 - Particle Data + map(Type.INT); // 9 - Particle Count + handler(new PacketHandler() { + @Override + public void handle(PacketWrapper wrapper) throws Exception { + int id = wrapper.get(Type.INT, 0); + if (id == 3 || id == 20) { + int data = wrapper.passthrough(Type.VAR_INT); + wrapper.set(Type.VAR_INT, 0, Protocol1_14To1_13_2.getNewBlockStateId(data)); + } else if (id == 27) { + InventoryPackets.toClient(wrapper.passthrough(Type.FLAT_VAR_INT_ITEM)); + } + } + }); + } + }); + } + +} diff --git a/common/src/main/java/us/myles/ViaVersion/protocols/protocol1_14to1_13_2/storage/EntityTracker.java b/common/src/main/java/us/myles/ViaVersion/protocols/protocol1_14to1_13_2/storage/EntityTracker.java new file mode 100644 index 000000000..9d7f7fb88 --- /dev/null +++ b/common/src/main/java/us/myles/ViaVersion/protocols/protocol1_14to1_13_2/storage/EntityTracker.java @@ -0,0 +1,33 @@ +package us.myles.ViaVersion.protocols.protocol1_14to1_13_2.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_14Types; + +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_14Types.EntityType type) { + clientEntityTypes.put(entityId, type); + } + + public boolean has(int entityId) { + return clientEntityTypes.containsKey(entityId); + } + + public Optional get(int id) { + return Optional.fromNullable(clientEntityTypes.get(id)); + } +}