diff --git a/core/src/main/java/nl/matsv/viabackwards/api/ViaBackwardsPlatform.java b/core/src/main/java/nl/matsv/viabackwards/api/ViaBackwardsPlatform.java index 4ce67b3e..4228b5a1 100644 --- a/core/src/main/java/nl/matsv/viabackwards/api/ViaBackwardsPlatform.java +++ b/core/src/main/java/nl/matsv/viabackwards/api/ViaBackwardsPlatform.java @@ -18,6 +18,7 @@ import nl.matsv.viabackwards.protocol.protocol1_12_1to1_12_2.Protocol1_12_1To1_1 import nl.matsv.viabackwards.protocol.protocol1_12_2to1_13.Protocol1_12_2To1_13; import nl.matsv.viabackwards.protocol.protocol1_12to1_12_1.Protocol1_12To1_12_1; import nl.matsv.viabackwards.protocol.protocol1_13_1to1_13_2.Protocol1_13_1To1_13_2; +import nl.matsv.viabackwards.protocol.protocol1_13_2to1_14.Protocol1_13_2To1_14; import nl.matsv.viabackwards.protocol.protocol1_13to1_13_1.Protocol1_13To1_13_1; import nl.matsv.viabackwards.protocol.protocol1_9_4to1_10.Protocol1_9_4To1_10; import us.myles.ViaVersion.api.protocol.ProtocolRegistry; @@ -44,6 +45,7 @@ public interface ViaBackwardsPlatform { ProtocolRegistry.registerProtocol(new Protocol1_12_2To1_13(), Collections.singletonList(ProtocolVersion.v1_12_2.getId()), ProtocolVersion.v1_13.getId()); ProtocolRegistry.registerProtocol(new Protocol1_13To1_13_1(), Collections.singletonList(ProtocolVersion.v1_13.getId()), ProtocolVersion.v1_13_1.getId()); ProtocolRegistry.registerProtocol(new Protocol1_13_1To1_13_2(), Collections.singletonList(ProtocolVersion.v1_13_1.getId()), ProtocolVersion.v1_13_2.getId()); + ProtocolRegistry.registerProtocol(new Protocol1_13_2To1_14(), Collections.singletonList(ProtocolVersion.v1_13_2.getId()), ProtocolVersion.v1_14.getId()); } } diff --git a/core/src/main/java/nl/matsv/viabackwards/api/entities/types/EntityType1_14.java b/core/src/main/java/nl/matsv/viabackwards/api/entities/types/EntityType1_14.java new file mode 100644 index 00000000..df97e3a1 --- /dev/null +++ b/core/src/main/java/nl/matsv/viabackwards/api/entities/types/EntityType1_14.java @@ -0,0 +1,257 @@ +package nl.matsv.viabackwards.api.entities.types; + +import lombok.AllArgsConstructor; +import lombok.Getter; +import us.myles.ViaVersion.api.Via; + +import java.util.ArrayList; +import java.util.List; +import java.util.Optional; + +public class EntityType1_14 { + public static EntityType1_14.EntityType getTypeFromId(int typeID) { + Optional type = EntityType.findById(typeID); + + if (!type.isPresent()) { + Via.getPlatform().getLogger().severe("Could not find type id " + typeID); + return EntityType.ENTITY; // Fall back to the basic ENTITY + } + + return type.get(); + } + + @AllArgsConstructor + @Getter + public enum EntityType implements AbstractEntityType { + // Auto generated + + ENTITY(-1), + + AREA_EFFECT_CLOUD(0, ENTITY), + ENDER_CRYSTAL(17, ENTITY), + EVOCATION_FANGS(21, ENTITY), + XP_ORB(23, ENTITY), + EYE_OF_ENDER_SIGNAL(24, ENTITY), + FALLING_BLOCK(25, ENTITY), + FIREWORKS_ROCKET(26, ENTITY), + ITEM(34, ENTITY), + LLAMA_SPIT(39, ENTITY), + TNT(58, ENTITY), + SHULKER_BULLET(63, ENTITY), + FISHING_BOBBER(101, ENTITY), + + LIVINGENTITY(-1, ENTITY), + ARMOR_STAND(1, LIVINGENTITY), + PLAYER(100, LIVINGENTITY), + + ABSTRACT_INSENTIENT(-1, LIVINGENTITY), + ENDER_DRAGON(18, ABSTRACT_INSENTIENT), + + ABSTRACT_CREATURE(-1, ABSTRACT_INSENTIENT), + + ABSTRACT_AGEABLE(-1, ABSTRACT_CREATURE), + VILLAGER(84, ABSTRACT_AGEABLE), + WANDERING_TRADER(88, ABSTRACT_AGEABLE), + + // Animals + ABSTRACT_ANIMAL(-1, ABSTRACT_AGEABLE), + DOLPHIN(13, ABSTRACT_INSENTIENT), + CHICKEN(8, ABSTRACT_ANIMAL), + COW(10, ABSTRACT_ANIMAL), + MOOSHROOM(49, COW), + PIG(54, ABSTRACT_ANIMAL), + POLAR_BEAR(57, ABSTRACT_ANIMAL), + RABBIT(59, ABSTRACT_ANIMAL), + SHEEP(61, ABSTRACT_ANIMAL), + TURTLE(77, ABSTRACT_ANIMAL), + FOX(27, ABSTRACT_ANIMAL), + + ABSTRACT_TAMEABLE_ANIMAL(-1, ABSTRACT_ANIMAL), + CAT(6, ABSTRACT_TAMEABLE_ANIMAL), + OCELOT(50, ABSTRACT_TAMEABLE_ANIMAL), + WOLF(93, ABSTRACT_TAMEABLE_ANIMAL), + + ABSTRACT_PARROT(-1, ABSTRACT_TAMEABLE_ANIMAL), + PARROT(53, ABSTRACT_PARROT), + + // Horses + ABSTRACT_HORSE(-1, ABSTRACT_ANIMAL), + CHESTED_HORSE(-1, ABSTRACT_HORSE), + DONKEY(12, CHESTED_HORSE), + MULE(48, CHESTED_HORSE), + LLAMA(38, CHESTED_HORSE), + TRADER_LLAMA(75, CHESTED_HORSE), + HORSE(31, ABSTRACT_HORSE), + SKELETON_HORSE(66, ABSTRACT_HORSE), + ZOMBIE_HORSE(95, ABSTRACT_HORSE), + + // Golem + ABSTRACT_GOLEM(-1, ABSTRACT_CREATURE), + SNOWMAN(69, ABSTRACT_GOLEM), + VILLAGER_GOLEM(85, ABSTRACT_GOLEM), + SHULKER(62, ABSTRACT_GOLEM), + + // Fish + ABSTRACT_FISHES(-1, ABSTRACT_CREATURE), + COD(9, ABSTRACT_FISHES), + PUFFER_FISH(55, ABSTRACT_FISHES), + SALMON_MOB(60, ABSTRACT_FISHES), + TROPICAL_FISH(76, ABSTRACT_FISHES), + + // Monsters + ABSTRACT_MONSTER(-1, ABSTRACT_CREATURE), + BLAZE(4, ABSTRACT_MONSTER), + CREEPER(11, ABSTRACT_MONSTER), + ENDERMITE(20, ABSTRACT_MONSTER), + ENDERMAN(19, ABSTRACT_MONSTER), + GIANT(29, ABSTRACT_MONSTER), + SILVERFISH(64, ABSTRACT_MONSTER), + VEX(83, ABSTRACT_MONSTER), + WITCH(89, ABSTRACT_MONSTER), + WITHER(90, ABSTRACT_MONSTER), + RAVAGER(98, ABSTRACT_MONSTER), + + // Illagers + ABSTRACT_ILLAGER_BASE(-1, ABSTRACT_MONSTER), + ABSTRACT_EVO_ILLU_ILLAGER(-1, ABSTRACT_ILLAGER_BASE), + EVOCATION_ILLAGER(22, ABSTRACT_EVO_ILLU_ILLAGER), + ILLUSION_ILLAGER(33, ABSTRACT_EVO_ILLU_ILLAGER), + VINDICATION_ILLAGER(86, ABSTRACT_ILLAGER_BASE), + PILLAGER(87, ABSTRACT_ILLAGER_BASE), + + // Skeletons + ABSTRACT_SKELETON(-1, ABSTRACT_MONSTER), + SKELETON(65, ABSTRACT_SKELETON), + STRAY(74, ABSTRACT_SKELETON), + WITHER_SKELETON(91, ABSTRACT_SKELETON), + + // Guardians + GUARDIAN(30, ABSTRACT_MONSTER), + ELDER_GUARDIAN(16, GUARDIAN), + + // Spiders + SPIDER(72, ABSTRACT_MONSTER), + CAVE_SPIDER(7, SPIDER), + + // Zombies - META CHECKED + ZOMBIE(94, ABSTRACT_MONSTER), + DROWNED(15, ZOMBIE), + HUSK(32, ZOMBIE), + ZOMBIE_PIGMAN(56, ZOMBIE), + ZOMBIE_VILLAGER(96, ZOMBIE), + + // Flying entities + ABSTRACT_FLYING(-1, ABSTRACT_INSENTIENT), + GHAST(28, ABSTRACT_FLYING), + PHANTOM(97, ABSTRACT_FLYING), + + ABSTRACT_AMBIENT(-1, ABSTRACT_INSENTIENT), + BAT(3, ABSTRACT_AMBIENT), + + ABSTRACT_WATERMOB(-1, ABSTRACT_INSENTIENT), + SQUID(73, ABSTRACT_WATERMOB), + + // Slimes + SLIME(67, ABSTRACT_INSENTIENT), + MAGMA_CUBE(40, SLIME), + + // Hangable objects + ABSTRACT_HANGING(-1, ENTITY), + LEASH_KNOT(37, ABSTRACT_HANGING), + ITEM_FRAME(35, ABSTRACT_HANGING), + PAINTING(51, ABSTRACT_HANGING), + + ABSTRACT_LIGHTNING(-1, ENTITY), + LIGHTNING_BOLT(99, ABSTRACT_LIGHTNING), + + // Arrows + ABSTRACT_ARROW(-1, ENTITY), + ARROW(2, ABSTRACT_ARROW), + SPECTRAL_ARROW(71, ABSTRACT_ARROW), + TRIDENT(82, ABSTRACT_ARROW), + + // Fireballs + ABSTRACT_FIREBALL(-1, ENTITY), + DRAGON_FIREBALL(14, ABSTRACT_FIREBALL), + FIREBALL(36, ABSTRACT_FIREBALL), + SMALL_FIREBALL(68, ABSTRACT_FIREBALL), + WITHER_SKULL(92, ABSTRACT_FIREBALL), + + // Projectiles + PROJECTILE_ABSTRACT(-1, ENTITY), + SNOWBALL(70, PROJECTILE_ABSTRACT), + ENDER_PEARL(79, PROJECTILE_ABSTRACT), + EGG(78, PROJECTILE_ABSTRACT), + POTION(81, PROJECTILE_ABSTRACT), + XP_BOTTLE(80, PROJECTILE_ABSTRACT), + + // Vehicles + MINECART_ABSTRACT(-1, ENTITY), + CHESTED_MINECART_ABSTRACT(-1, MINECART_ABSTRACT), + CHEST_MINECART(42, CHESTED_MINECART_ABSTRACT), + HOPPER_MINECART(45, CHESTED_MINECART_ABSTRACT), + MINECART(41, MINECART_ABSTRACT), + FURNACE_MINECART(44, MINECART_ABSTRACT), + COMMANDBLOCK_MINECART(43, MINECART_ABSTRACT), + TNT_MINECART(47, MINECART_ABSTRACT), + SPAWNER_MINECART(46, MINECART_ABSTRACT), + BOAT(5, ENTITY), + ; + + private final int id; + private final EntityType parent; + + EntityType(int id) { + this.id = id; + this.parent = null; + } + + public static java.util.Optional findById(int id) { + if (id == -1) // Check if this is called + return java.util.Optional.empty(); + + for (EntityType ent : EntityType.values()) + if (ent.getId() == id) + return java.util.Optional.of(ent); + + return java.util.Optional.empty(); + } + + public boolean is(AbstractEntityType... types) { + for (AbstractEntityType type : types) + if (is(type)) + return true; + return false; + } + + public boolean is(AbstractEntityType type) { + return this == type; + } + + public boolean isOrHasParent(AbstractEntityType type) { + EntityType parent = this; + + do { + if (parent == type) + return true; + + parent = parent.getParent(); + } while (parent != null); + + return false; + } + + @Override + public List getParents() { + List types = new ArrayList<>(); + EntityType parent = this; + + do { + types.add(parent); + parent = parent.getParent(); + } while (parent != null); + + return types; + } + } +} \ No newline at end of file diff --git a/core/src/main/java/nl/matsv/viabackwards/protocol/protocol1_13_2to1_14/Protocol1_13_2To1_14.java b/core/src/main/java/nl/matsv/viabackwards/protocol/protocol1_13_2to1_14/Protocol1_13_2To1_14.java new file mode 100644 index 00000000..b2ad930d --- /dev/null +++ b/core/src/main/java/nl/matsv/viabackwards/protocol/protocol1_13_2to1_14/Protocol1_13_2To1_14.java @@ -0,0 +1,183 @@ +package nl.matsv.viabackwards.protocol.protocol1_13_2to1_14; + +import nl.matsv.viabackwards.ViaBackwards; +import nl.matsv.viabackwards.api.BackwardsProtocol; +import nl.matsv.viabackwards.api.entities.storage.EntityTracker; +import nl.matsv.viabackwards.protocol.protocol1_13_2to1_14.data.BackwardsMappings; +import nl.matsv.viabackwards.protocol.protocol1_13_2to1_14.data.SoundMapping; +import nl.matsv.viabackwards.protocol.protocol1_13_2to1_14.packets.BlockItemPackets1_14; +import nl.matsv.viabackwards.protocol.protocol1_13_2to1_14.packets.EntityPackets1_14; +import nl.matsv.viabackwards.protocol.protocol1_13_2to1_14.packets.PlayerPackets1_14; +import nl.matsv.viabackwards.protocol.protocol1_13_2to1_14.packets.SoundPackets1_14; +import us.myles.ViaVersion.api.PacketWrapper; +import us.myles.ViaVersion.api.data.UserConnection; +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_9_3to1_9_1_2.storage.ClientWorld; + +public class Protocol1_13_2To1_14 extends BackwardsProtocol { + public static BlockItemPackets1_14 blockItem; + public static EntityPackets1_14 entity; + + static { + BackwardsMappings.init(); + SoundMapping.init(); + } + + @Override + protected void registerPackets() { + blockItem = new BlockItemPackets1_14(); + blockItem.register(this); + entity = new EntityPackets1_14(); + entity.register(this); + new PlayerPackets1_14().register(this); + new SoundPackets1_14().register(this); + + out(State.PLAY, 0x2E, 0x2D); // c + out(State.PLAY, 0x2F, 0x2E); // c + out(State.PLAY, 0x30, 0x2F); // c + out(State.PLAY, 0x31, 0x30); // c + out(State.PLAY, 0x32, 0x31); // c + out(State.PLAY, 0x33, 0x32); // c + // Entity sound + out(State.PLAY, 0x4E, -1, new PacketRemapper() { + @Override + public void registerMap() { // c + handler(new PacketHandler() { + @Override + public void handle(PacketWrapper packetWrapper) throws Exception { + packetWrapper.cancel(); // todo + } + }); + } + }); + + registerOutgoing(State.PLAY, 0x4F, 0x4E); // c + registerOutgoing(State.PLAY, 0x50, 0x4F); // c + registerOutgoing(State.PLAY, 0x51, 0x50); // c + + registerOutgoing(State.PLAY, 0x52, 0x51, new PacketRemapper() { // c + @Override + public void registerMap() { + handler(new PacketHandler() { + @Override + public void handle(PacketWrapper wrapper) throws Exception { + wrapper.passthrough(Type.BOOLEAN); // Reset/clear + int size = wrapper.passthrough(Type.VAR_INT); // Mapping size + + for (int i = 0; i < size; i++) { + wrapper.passthrough(Type.STRING); // Identifier + + // Parent + if (wrapper.passthrough(Type.BOOLEAN)) + wrapper.passthrough(Type.STRING); + + // Display data + if (wrapper.passthrough(Type.BOOLEAN)) { + wrapper.passthrough(Type.STRING); // Title + wrapper.passthrough(Type.STRING); // Description + blockItem.handleItemToClient(wrapper.passthrough(Type.FLAT_VAR_INT_ITEM)); // Icon + wrapper.passthrough(Type.VAR_INT); // Frame type + int flags = wrapper.passthrough(Type.INT); // Flags + if ((flags & 1) != 0) + wrapper.passthrough(Type.STRING); // Background texture + wrapper.passthrough(Type.FLOAT); // X + wrapper.passthrough(Type.FLOAT); // Y + } + + wrapper.passthrough(Type.STRING_ARRAY); // Criteria + + int arrayLength = wrapper.passthrough(Type.VAR_INT); + for (int array = 0; array < arrayLength; array++) { + wrapper.passthrough(Type.STRING_ARRAY); // String array + } + } + } + }); + } + }); + + registerOutgoing(State.PLAY, 0x53, 0x52); // c + registerOutgoing(State.PLAY, 0x54, 0x53); // c + + // tags + registerOutgoing(State.PLAY, 0x56, 0x55, new PacketRemapper() { + @Override + public void registerMap() { // c + handler(new PacketHandler() { + @Override + public void handle(PacketWrapper wrapper) throws Exception { + int blockTagsSize = wrapper.read(Type.VAR_INT); + wrapper.write(Type.VAR_INT, blockTagsSize); // 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] = getNewBlockStateId(blockIds[j]); + } + } + int itemTagsSize = wrapper.read(Type.VAR_INT); + wrapper.write(Type.VAR_INT, itemTagsSize); // 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] = /*BlockItemPackets1_14.getNewItemId TODO BLOCK IDS*/(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); + } + // Eat entity tags + int entityTagsSize = wrapper.read(Type.VAR_INT); + for (int i = 0; i < entityTagsSize; i++) { + wrapper.read(Type.STRING); + wrapper.read(Type.VAR_INT_ARRAY); + } + } + }); + } + }); + + + // Light update + out(State.PLAY, 0x57, -1, new PacketRemapper() { + @Override + public void registerMap() { + handler(new PacketHandler() { + @Override + public void handle(PacketWrapper packetWrapper) throws Exception { + packetWrapper.cancel(); // todo + } + }); + } + }); + } + + public static int getNewBlockStateId(int id) { + int newId = BackwardsMappings.blockMappings.getNewBlock(id); + if (newId == -1) { + ViaBackwards.getPlatform().getLogger().warning("Missing 1.14 block for 1.13.2 block " + id); + return 0; + } + return newId; + } + + @Override + public void init(UserConnection user) { + // Register ClientWorld + if (!user.has(ClientWorld.class)) + user.put(new ClientWorld(user)); + + // Register EntityTracker if it doesn't exist yet. + if (!user.has(EntityTracker.class)) + user.put(new EntityTracker(user)); + + // Init protocol in EntityTracker + user.get(EntityTracker.class).initProtocol(this); + } +} diff --git a/core/src/main/java/nl/matsv/viabackwards/protocol/protocol1_13_2to1_14/data/BackwardsMappings.java b/core/src/main/java/nl/matsv/viabackwards/protocol/protocol1_13_2to1_14/data/BackwardsMappings.java new file mode 100644 index 00000000..aba75614 --- /dev/null +++ b/core/src/main/java/nl/matsv/viabackwards/protocol/protocol1_13_2to1_14/data/BackwardsMappings.java @@ -0,0 +1,99 @@ +package nl.matsv.viabackwards.protocol.protocol1_13_2to1_14.data; + +import nl.matsv.viabackwards.ViaBackwards; +import us.myles.ViaVersion.api.Via; +import us.myles.ViaVersion.protocols.protocol1_14to1_13_2.data.MappingData; +import us.myles.ViaVersion.util.GsonUtil; +import us.myles.viaversion.libs.gson.JsonElement; +import us.myles.viaversion.libs.gson.JsonObject; +import us.myles.viaversion.libs.gson.JsonPrimitive; + +import java.io.IOException; +import java.io.InputStreamReader; +import java.util.Arrays; +import java.util.Map; + +public class BackwardsMappings { + public static BlockMappings blockMappings; + + public static void init() { + JsonObject mapping1_13_2 = MappingData.loadData("mapping-1.13.2.json"); + JsonObject mapping1_14 = MappingData.loadData("mapping-1.14.json"); + JsonObject mapping1_13_2to1_14 = loadData("mapping-1.13.2to1.14.json"); + + ViaBackwards.getPlatform().getLogger().info("Loading block mapping..."); + blockMappings = new BlockMappingsShortArray(mapping1_14.getAsJsonObject("blockstates"), mapping1_13_2.getAsJsonObject("blockstates"), mapping1_13_2to1_14.getAsJsonObject("blockstates")); + } + + + private static void mapIdentifiers(short[] output, JsonObject newIdentifiers, JsonObject oldIdentifiers, JsonObject mapping) { + for (Map.Entry entry : newIdentifiers.entrySet()) { + String key = entry.getValue().getAsString(); + Map.Entry value = findValue(oldIdentifiers, key); + if (value == null) { + JsonPrimitive replacement = mapping.getAsJsonPrimitive(key); + if (replacement == null && key.contains("[")) { + replacement = mapping.getAsJsonPrimitive(key.substring(0, key.indexOf('['))); + } + if (replacement != null) { + if (replacement.getAsString().startsWith("id:")) { + String id = replacement.getAsString().replace("id:", ""); + value = findValue(oldIdentifiers, oldIdentifiers.getAsJsonPrimitive(id).getAsString()); + } else { + value = findValue(oldIdentifiers, replacement.getAsString()); + } + } + if (value == null) { + if (!Via.getConfig().isSuppress1_13ConversionErrors() || Via.getManager().isDebug()) { + if (replacement != null) { + ViaBackwards.getPlatform().getLogger().warning("No key for " + entry.getValue() + "/" + replacement.getAsString() + " :( "); + } else { + ViaBackwards.getPlatform().getLogger().warning("No key for " + entry.getValue() + " :( "); + } + } + continue; + } + } + output[Integer.parseInt(entry.getKey())] = Short.parseShort(value.getKey()); + } + } + + + private static Map.Entry findValue(JsonObject object, String needle) { + for (Map.Entry entry : object.entrySet()) { + String value = entry.getValue().getAsString(); + if (value.equals(needle)) { + return entry; + } + } + return null; + } + + public static JsonObject loadData(String name) { + try (InputStreamReader reader = new InputStreamReader(BackwardsMappings.class.getClassLoader().getResourceAsStream("assets/viabackwards/data/" + name))) { + return GsonUtil.getGson().fromJson(reader, JsonObject.class); + } catch (IOException ex) { + ex.printStackTrace(); + } + + return null; + } + + public interface BlockMappings { + int getNewBlock(int old); + } + + private static class BlockMappingsShortArray implements BlockMappings { + private short[] oldToNew = new short[11258 + 1]; + + private BlockMappingsShortArray(JsonObject newIdentifiers, JsonObject oldIdentifiers, JsonObject mapping) { + Arrays.fill(oldToNew, (short) -1); + mapIdentifiers(oldToNew, newIdentifiers, oldIdentifiers, mapping); + } + + @Override + public int getNewBlock(int old) { + return old >= 0 && old < oldToNew.length ? oldToNew[old] : -1; + } + } +} diff --git a/core/src/main/java/nl/matsv/viabackwards/protocol/protocol1_13_2to1_14/data/EntityTypeMapping.java b/core/src/main/java/nl/matsv/viabackwards/protocol/protocol1_13_2to1_14/data/EntityTypeMapping.java new file mode 100644 index 00000000..fed85d0d --- /dev/null +++ b/core/src/main/java/nl/matsv/viabackwards/protocol/protocol1_13_2to1_14/data/EntityTypeMapping.java @@ -0,0 +1,28 @@ +package nl.matsv.viabackwards.protocol.protocol1_13_2to1_14.data; + + +import us.myles.ViaVersion.protocols.protocol1_14to1_13_2.data.EntityTypeRewriter; + +import java.lang.reflect.Field; +import java.util.HashMap; +import java.util.Map; +import java.util.Optional; + +public class EntityTypeMapping { + private static Map entityTypes = new HashMap<>(); + + static { + try { + Field field = EntityTypeRewriter.class.getDeclaredField("entityTypes"); + field.setAccessible(true); + Map entityTypes = (Map) field.get(null); + entityTypes.forEach((type1_12, type1_13) -> EntityTypeMapping.entityTypes.put(type1_13, type1_12)); + } catch (NoSuchFieldException | IllegalAccessException ex) { + ex.printStackTrace(); + } + } + + public static Optional getOldId(int type1_13) { + return Optional.ofNullable(entityTypes.get(type1_13)); + } +} diff --git a/core/src/main/java/nl/matsv/viabackwards/protocol/protocol1_13_2to1_14/data/SoundMapping.java b/core/src/main/java/nl/matsv/viabackwards/protocol/protocol1_13_2to1_14/data/SoundMapping.java new file mode 100644 index 00000000..fd92084a --- /dev/null +++ b/core/src/main/java/nl/matsv/viabackwards/protocol/protocol1_13_2to1_14/data/SoundMapping.java @@ -0,0 +1,44 @@ +package nl.matsv.viabackwards.protocol.protocol1_13_2to1_14.data; + +import us.myles.viaversion.libs.gson.JsonArray; +import us.myles.viaversion.libs.gson.JsonElement; +import us.myles.viaversion.libs.gson.JsonObject; + +import java.util.Arrays; + +import static us.myles.ViaVersion.protocols.protocol1_13to1_12_2.data.MappingData.loadData; + +public class SoundMapping { + private static short[] sounds = new short[772]; + + public static void init() { + JsonObject mapping1_13_2 = loadData("mapping-1.13.2.json"); + JsonObject mapping1_14 = loadData("mapping-1.14.json"); + + Arrays.fill(sounds, (short) -1); + mapIdentifiers(sounds, mapping1_14.getAsJsonArray("sounds"), mapping1_13_2.getAsJsonArray("sounds")); + } + + private static void mapIdentifiers(short[] output, JsonArray oldIdentifiers, JsonArray newIdentifiers) { + for (int i = 0; i < oldIdentifiers.size(); i++) { + JsonElement v = oldIdentifiers.get(i); + Integer index = findIndex(newIdentifiers, v.getAsString()); + if (index == null) continue; //There will be missing sounds, since we are goind backwards + output[i] = index.shortValue(); + } + } + + private static Integer findIndex(JsonArray array, String value) { + for (int i = 0; i < array.size(); i++) { + JsonElement v = array.get(i); + if (v.getAsString().equals(value)) { + return i; + } + } + return null; + } + + public static int getOldSound(int newSound) { + return newSound >= sounds.length ? -1 : sounds[newSound]; + } +} diff --git a/core/src/main/java/nl/matsv/viabackwards/protocol/protocol1_13_2to1_14/packets/BlockItemPackets1_14.java b/core/src/main/java/nl/matsv/viabackwards/protocol/protocol1_13_2to1_14/packets/BlockItemPackets1_14.java new file mode 100644 index 00000000..7afa91c7 --- /dev/null +++ b/core/src/main/java/nl/matsv/viabackwards/protocol/protocol1_13_2to1_14/packets/BlockItemPackets1_14.java @@ -0,0 +1,592 @@ +package nl.matsv.viabackwards.protocol.protocol1_13_2to1_14.packets; + +import com.google.common.collect.ImmutableSet; +import nl.matsv.viabackwards.ViaBackwards; +import nl.matsv.viabackwards.api.rewriters.BlockItemRewriter; +import nl.matsv.viabackwards.protocol.protocol1_13_2to1_14.Protocol1_13_2To1_14; +import nl.matsv.viabackwards.protocol.protocol1_13_2to1_14.data.BackwardsMappings; +import nl.matsv.viabackwards.protocol.protocol1_13to1_13_1.packets.InventoryPackets1_13_1; +import us.myles.ViaVersion.api.PacketWrapper; +import us.myles.ViaVersion.api.minecraft.BlockChangeRecord; +import us.myles.ViaVersion.api.minecraft.Environment; +import us.myles.ViaVersion.api.minecraft.chunks.Chunk; +import us.myles.ViaVersion.api.minecraft.chunks.ChunkSection; +import us.myles.ViaVersion.api.minecraft.item.Item; +import us.myles.ViaVersion.api.remapper.PacketHandler; +import us.myles.ViaVersion.api.remapper.PacketRemapper; +import us.myles.ViaVersion.api.remapper.ValueCreator; +import us.myles.ViaVersion.api.type.Type; +import us.myles.ViaVersion.packets.State; +import us.myles.ViaVersion.protocols.protocol1_13to1_12_2.ChatRewriter; +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_14to1_13_2.data.MappingData; +import us.myles.ViaVersion.protocols.protocol1_14to1_13_2.types.Chunk1_14Type; +import us.myles.ViaVersion.protocols.protocol1_9_3to1_9_1_2.storage.ClientWorld; +import us.myles.viaversion.libs.opennbt.conversion.ConverterRegistry; +import us.myles.viaversion.libs.opennbt.tag.builtin.CompoundTag; +import us.myles.viaversion.libs.opennbt.tag.builtin.ListTag; +import us.myles.viaversion.libs.opennbt.tag.builtin.StringTag; +import us.myles.viaversion.libs.opennbt.tag.builtin.Tag; + +import java.util.Set; + +public class BlockItemPackets1_14 extends BlockItemRewriter { + private static String NBT_TAG_NAME = "ViaBackwards|" + Protocol1_13_2To1_14.class.getSimpleName(); + + @Override + protected void registerPackets(Protocol1_13_2To1_14 protocol) { + // Open window + protocol.registerOutgoing(State.PLAY, 0x58, 0x14, new PacketRemapper() { + @Override + public void registerMap() { // c + handler(new PacketHandler() { + @Override + public void handle(PacketWrapper wrapper) throws Exception { + int id = wrapper.read(Type.VAR_INT); + wrapper.write(Type.UNSIGNED_BYTE, (short) id); + int type = wrapper.read(Type.VAR_INT); + String stringType = null; + int slotSize = 0; + switch (type) { + case 0: + stringType = "minecraft:container"; + slotSize = 27; + break; + case 1: + stringType = "minecraft:container"; + slotSize = 54; + break; + case 7: + stringType = "minecraft:crafting_table"; + break; + case 9: + stringType = "minecraft:furnace"; + break; + case 2: + stringType = "minecraft:dropper"; + break; + case 8: + stringType = "minecraft:enchanting_table"; + break; + case 6: + stringType = "minecraft:brewing_stand"; + break; + case 14: + stringType = "minecraft:villager"; + break; + case 4: + stringType = "minecraft:beacon"; + break; + case 3: + stringType = "minecraft:anvil"; + break; + case 11: + stringType = "minecraft:hopper"; + break; + case 15: + stringType = "minecraft:shulker_box"; + break; + } + + if (stringType == null) { + ViaBackwards.getPlatform().getLogger().warning("Can't open inventory for 1.13 player! Type: " + type); + wrapper.cancel(); + return; + } + + wrapper.write(Type.STRING, stringType); + wrapper.passthrough(Type.STRING); + wrapper.write(Type.UNSIGNED_BYTE, (short) slotSize); + } + }); + } + }); + + // Horse window + protocol.registerOutgoing(State.PLAY, 0x14, 0x14, new PacketRemapper() { + @Override + public void registerMap() { // c + handler(new PacketHandler() { + @Override + public void handle(PacketWrapper wrapper) throws Exception { + wrapper.passthrough(Type.UNSIGNED_BYTE); // Window id + wrapper.write(Type.STRING, "EntityHorse"); // Type + wrapper.write(Type.STRING, "{\"translate\":\"minecraft.horse\"}"); // Title + wrapper.write(Type.UNSIGNED_BYTE, wrapper.read(Type.VAR_INT).shortValue()); // Number of slots + wrapper.passthrough(Type.INT); // Entity id + } + }); + } + }); + + // 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) handleItemToClient(stack); + } + }); + } + }); + + // 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 { + handleItemToClient(wrapper.get(Type.FLAT_VAR_INT_ITEM, 0)); + } + }); + } + }); + + // Trade list + protocol.out(State.PLAY, 0x59, 0x19, new PacketRemapper() { + @Override + public void registerMap() { + handler(new PacketHandler() { + @Override + public void handle(PacketWrapper wrapper) throws Exception { + wrapper.write(Type.STRING, "minecraft:trader_list"); + wrapper.read(Type.STRING); // Remove channel + + int windowId = wrapper.read(Type.INT); + wrapper.write(Type.VAR_INT, windowId); + + int size = wrapper.passthrough(Type.UNSIGNED_BYTE); + for (int i = 0; i < size; i++) { + // Input Item + handleItemToClient(wrapper.passthrough(Type.FLAT_VAR_INT_ITEM)); + // Output Item + handleItemToClient(wrapper.passthrough(Type.FLAT_VAR_INT_ITEM)); + + boolean secondItem = wrapper.passthrough(Type.BOOLEAN); // Has second item + if (secondItem) { + // Second Item + handleItemToClient(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 + } + } + }); + } + }); + + // Book open + protocol.registerOutgoing(State.PLAY, 0x2C, 0x19, new PacketRemapper() { + @Override + public void registerMap() { + handler(new PacketHandler() { + @Override + public void handle(PacketWrapper wrapper) throws Exception { + wrapper.write(Type.STRING, "minecraft:book_open"); + wrapper.passthrough(Type.VAR_INT); + } + }); + } + }); + + // 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 { + handleItemToClient(wrapper.get(Type.FLAT_VAR_INT_ITEM, 0)); + } + }); + } + }); + + Set removedTypes = ImmutableSet.of("crafting_special_suspiciousstew", "blasting", "smoking", "campfire_cooking"); + + // Declare Recipes + protocol.registerOutgoing(State.PLAY, 0x55, 0x54, new PacketRemapper() { // c + @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 type = wrapper.read(Type.STRING); + String id = wrapper.read(Type.STRING); // Recipe Identifier + type = type.replace("minecraft:", ""); + if (removedTypes.contains(type)) { + if (!type.equals("crafting_special_suspiciousstew")) { + wrapper.read(Type.STRING); // Group + Item[] items = wrapper.read(Type.FLAT_VAR_INT_ITEM_ARRAY_VAR_INT); // Ingredients + wrapper.read(Type.FLAT_VAR_INT_ITEM); + wrapper.read(Type.FLOAT); // EXP + wrapper.read(Type.VAR_INT); // Cooking time + } + 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 + for (Item item : items) handleItemToClient(item); + } + handleItemToClient(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++) { + Item[] items = wrapper.passthrough(Type.FLAT_VAR_INT_ITEM_ARRAY_VAR_INT); // Ingredients + for (Item item : items) handleItemToClient(item); + } + handleItemToClient(wrapper.passthrough(Type.FLAT_VAR_INT_ITEM)); // Result + } else if (type.equals("smelting")) { + wrapper.passthrough(Type.STRING); // Group + Item[] items = wrapper.passthrough(Type.FLAT_VAR_INT_ITEM_ARRAY_VAR_INT); // Ingredients + for (Item item : items) handleItemToClient(item); + handleItemToClient(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 { + handleItemToServer(wrapper.get(Type.FLAT_VAR_INT_ITEM, 0)); + } + }); + } + }); + + // 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 { + handleItemToServer(wrapper.get(Type.FLAT_VAR_INT_ITEM, 0)); + } + }); + } + }); + + // Block break animation + protocol.registerOutgoing(State.PLAY, 0x08, 0x08, new PacketRemapper() { + @Override + public void registerMap() { + map(Type.VAR_INT); + map(Type.POSITION1_14, Type.POSITION); + map(Type.BYTE); + } + }); + + // Update block entity + protocol.registerOutgoing(State.PLAY, 0x09, 0x09, new PacketRemapper() { + @Override + public void registerMap() { + map(Type.POSITION1_14, Type.POSITION); + } + }); + + // Block Action + protocol.registerOutgoing(State.PLAY, 0x0A, 0x0A, new PacketRemapper() { + @Override + public void registerMap() { + map(Type.POSITION, Type.POSITION1_14); // 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_13_2To1_14.getNewBlockStateId(wrapper.get(Type.VAR_INT, 0))); + } + }); + } + }); + + // Block Change + protocol.registerOutgoing(State.PLAY, 0xB, 0xB, new PacketRemapper() { + @Override + public void registerMap() { + map(Type.POSITION, Type.POSITION1_14); + 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_13_2To1_14.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_13_2To1_14.getNewBlockStateId(id)); + } + } + }); + } + }); + + //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.read(new Chunk1_14Type(clientWorld)); + wrapper.write(new Chunk1_13Type(clientWorld), chunk); + + for (ChunkSection section : chunk.getSections()) { + if (section == null) continue; + section.setBlockLight(new byte[2048]); + if (clientWorld.getEnvironment() == Environment.NORMAL) { + section.setSkyLight(new byte[2048]); + } + for (int i = 0; i < section.getPaletteSize(); i++) { + int old = section.getPaletteEntry(i); + int newId = Protocol1_13_2To1_14.getNewBlockStateId(old); + section.setPaletteEntry(i, newId); + } + } + } + }); + } + }); + + // Effect packet + protocol.registerOutgoing(State.PLAY, 0x23, 0x23, new PacketRemapper() { + @Override + public void registerMap() { + map(Type.INT); // Effect Id + map(Type.POSITION, Type.POSITION1_14); // 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 = BlockItemPackets1_14.getNewItemId(data)); + } else if (id == 2001) { // Block break + block break sound + wrapper.set(Type.INT, 1, data = Protocol1_14To1_13_2.getNewBlockStateId(data)); + } + } + }); + } + }); + + //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) { + handleItemToClient(wrapper.passthrough(Type.FLAT_VAR_INT_ITEM)); + } + } + }); + } + }); + + + //Map Data + protocol.registerOutgoing(State.PLAY, 0x26, 0x26, new PacketRemapper() { + @Override + public void registerMap() { + map(Type.VAR_INT); + map(Type.BYTE); + map(Type.BOOLEAN); + map(Type.BOOLEAN, Type.NOTHING); // Locked + } + }); + + //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 position + protocol.registerOutgoing(State.PLAY, 0x49, 0x49, new PacketRemapper() { + @Override + public void registerMap() { + map(Type.POSITION, Type.POSITION1_14); + } + }); + } + + @Override + protected void registerRewrites() { + + } + + @Override + public Item handleItemToClient(Item i) { + Item item = super.handleItemToClient(i); + item.setIdentifier(getOldItemId(item.getIdentifier())); + + CompoundTag tag; + if ((tag = item.getTag()) != null) { + // Display Name now uses JSON + if (tag.get("display") instanceof CompoundTag) { + CompoundTag display = tag.get("display"); + if (((CompoundTag) tag.get("display")).get("Lore") instanceof ListTag) { + ListTag lore = display.get("Lore"); + ListTag via = display.get(NBT_TAG_NAME + "|Lore"); + if (via != null) { + display.put(ConverterRegistry.convertToTag("Lore", ConverterRegistry.convertToValue(via))); + } else { + for (Tag loreEntry : lore) { + if (loreEntry instanceof StringTag) { + ((StringTag) loreEntry).setValue( + ChatRewriter.jsonTextToLegacy( + ((StringTag) loreEntry).getValue() + ) + ); + } + } + } + display.remove(NBT_TAG_NAME + "|Lore"); + } + } + } + return item; + } + + @Override + public Item handleItemToServer(Item i) { + Item item = super.handleItemToServer(i); + item.setIdentifier(getNewItemId(item.getIdentifier())); + + CompoundTag tag; + if ((tag = item.getTag()) != null) { + // Display Lore now uses JSON + if (tag.get("display") instanceof CompoundTag) { + CompoundTag display = tag.get("display"); + if (display.get("Lore") instanceof ListTag) { + ListTag lore = display.get("Lore"); + display.put(ConverterRegistry.convertToTag(NBT_TAG_NAME + "|Lore", ConverterRegistry.convertToValue(lore))); + for (Tag loreEntry : lore) { + if (loreEntry instanceof StringTag) { + ((StringTag) loreEntry).setValue( + ChatRewriter.legacyTextToJson( + ((StringTag) loreEntry).getValue() + ) + ); + } + } + } + } + } + return item; + } + + public static int getNewItemId(int id) { + Integer newId = MappingData.oldToNewItems.get(id); + if (newId == null) { + ViaBackwards.getPlatform().getLogger().warning("Missing 1.14 item for 1.13.2 item " + id); + return 1; + } + return newId; + } + + + public static int getOldItemId(int id) { + Integer oldId = MappingData.oldToNewItems.inverse().get(id); + return oldId != null ? oldId : 1; + } +} diff --git a/core/src/main/java/nl/matsv/viabackwards/protocol/protocol1_13_2to1_14/packets/EntityPackets1_14.java b/core/src/main/java/nl/matsv/viabackwards/protocol/protocol1_13_2to1_14/packets/EntityPackets1_14.java new file mode 100644 index 00000000..84c96bc4 --- /dev/null +++ b/core/src/main/java/nl/matsv/viabackwards/protocol/protocol1_13_2to1_14/packets/EntityPackets1_14.java @@ -0,0 +1,208 @@ +package nl.matsv.viabackwards.protocol.protocol1_13_2to1_14.packets; + +import nl.matsv.viabackwards.api.entities.storage.MetaStorage; +import nl.matsv.viabackwards.api.entities.types.EntityType1_13; +import nl.matsv.viabackwards.api.entities.types.EntityType1_14; +import nl.matsv.viabackwards.api.rewriters.EntityRewriter; +import nl.matsv.viabackwards.protocol.protocol1_13_2to1_14.Protocol1_13_2To1_14; +import nl.matsv.viabackwards.protocol.protocol1_13_2to1_14.data.EntityTypeMapping; +import us.myles.ViaVersion.api.PacketWrapper; +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.api.type.types.version.Types1_14; +import us.myles.ViaVersion.packets.State; +import us.myles.ViaVersion.protocols.protocol1_9_3to1_9_1_2.storage.ClientWorld; + +public class EntityPackets1_14 extends EntityRewriter { + @Override + protected void registerPackets(Protocol1_13_2To1_14 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.VAR_INT, 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); + int typeId = wrapper.get(Type.VAR_INT, 1); + + EntityType1_14.EntityType type1_14 = EntityType1_14.getTypeFromId(typeId); + typeId = EntityTypeMapping.getOldId(type1_14.getId()).orElse(type1_14.getId()); + EntityType1_13.EntityType type1_13 = EntityType1_13.getTypeFromId(typeId, true); // todo object id + wrapper.cancel(); + + if (type1_13 != null) { + if (type1_13.is(EntityType1_13.EntityType.FALLING_BLOCK)) { + int data = wrapper.get(Type.INT, 0); + wrapper.set(Type.INT, 0, Protocol1_13_2To1_14.blockItem.handleBlockID(data)); + } + } + + wrapper.set(Type.VAR_INT, 1, typeId); + // Register Type ID + getEntityTracker(wrapper.user()).trackEntityType(entityId, type1_13); + } + }); + } + }); + + // 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_14.METADATA_LIST, 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 = EntityTypeMapping.getOldId(type).orElse(type); + + EntityType1_13.EntityType entType = EntityType1_13.getTypeFromId(type, false); + + wrapper.set(Type.VAR_INT, 1, type); + + // Register Type ID + addTrackedEntity(wrapper.user(), entityId, entType); + + wrapper.set(Types1_13_2.METADATA_LIST, 0, + handleMeta( + wrapper.user(), + entityId, + new MetaStorage(wrapper.get(Types1_13_2.METADATA_LIST, 0)) + ).getMetaDataList() + ); + } + }); + } + }); + + // Spawn painting + protocol.registerOutgoing(State.PLAY, 0x04, 0x04, new PacketRemapper() { + @Override + public void registerMap() { + map(Type.VAR_INT); + map(Type.UUID); + map(Type.VAR_INT); + map(Type.POSITION1_14, Type.POSITION); + map(Type.BYTE); + } + }); + + // 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_14.METADATA_LIST, 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); + + EntityType1_13.EntityType entType = EntityType1_13.EntityType.PLAYER; + // Register Type ID + addTrackedEntity(wrapper.user(), entityId, entType); + wrapper.set(Types1_13_2.METADATA_LIST, 0, + handleMeta( + wrapper.user(), + entityId, + new MetaStorage(wrapper.get(Types1_13_2.METADATA_LIST, 0)) + ).getMetaDataList() + ); + } + }); + } + }); + + + // Metadata packet + protocol.registerOutgoing(State.PLAY, 0x3F, 0x3F, new PacketRemapper() { + @Override + public void registerMap() { + map(Type.VAR_INT); // 0 - Entity ID + map(Types1_14.METADATA_LIST, 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); + + wrapper.set(Types1_13_2.METADATA_LIST, 0, + handleMeta( + wrapper.user(), + entityId, + new MetaStorage(wrapper.get(Types1_13_2.METADATA_LIST, 0)) + ).getMetaDataList() + ); + } + }); + } + }); + + //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); + + int entityId = wrapper.get(Type.INT, 0); + + // Register Type ID + addTrackedEntity(wrapper.user(), entityId, EntityType1_13.EntityType.PLAYER); + } + }); + } + }); + + + } + + @Override + protected void registerRewrites() { + + } +} diff --git a/core/src/main/java/nl/matsv/viabackwards/protocol/protocol1_13_2to1_14/packets/PlayerPackets1_14.java b/core/src/main/java/nl/matsv/viabackwards/protocol/protocol1_13_2to1_14/packets/PlayerPackets1_14.java new file mode 100644 index 00000000..f41cb8eb --- /dev/null +++ b/core/src/main/java/nl/matsv/viabackwards/protocol/protocol1_13_2to1_14/packets/PlayerPackets1_14.java @@ -0,0 +1,139 @@ +package nl.matsv.viabackwards.protocol.protocol1_13_2to1_14.packets; + +import nl.matsv.viabackwards.api.rewriters.Rewriter; +import nl.matsv.viabackwards.protocol.protocol1_13_2to1_14.Protocol1_13_2To1_14; +import us.myles.ViaVersion.api.PacketWrapper; +import us.myles.ViaVersion.api.minecraft.Position; +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 PlayerPackets1_14 extends Rewriter { + @Override + protected void registerPackets(Protocol1_13_2To1_14 protocol) { + + // Open Sign Editor + protocol.registerOutgoing(State.PLAY, 0x2D, 0x2C, new PacketRemapper() { // c + @Override + public void registerMap() { + map(Type.POSITION1_14, Type.POSITION); + } + }); + + // Query Block NBT + protocol.registerIncoming(State.PLAY, 0x01, 0x01, new PacketRemapper() { + @Override + public void registerMap() { + map(Type.VAR_INT); + map(Type.POSITION, Type.POSITION1_14); + } + }); + + // Edit Book + protocol.registerIncoming(State.PLAY, 0x0B, 0x0B, new PacketRemapper() { + @Override + public void registerMap() { + handler(new PacketHandler() { + @Override + public void handle(PacketWrapper wrapper) throws Exception { + Protocol1_13_2To1_14.blockItem.handleItemToServer(wrapper.passthrough(Type.FLAT_VAR_INT_ITEM)); + } + }); + } + }); + + // Player Digging + protocol.registerIncoming(State.PLAY, 0x18, 0x18, new PacketRemapper() { + @Override + public void registerMap() { + map(Type.VAR_INT); + map(Type.POSITION, Type.POSITION1_14); + map(Type.BYTE); + } + }); + + // Recipe Book Data + protocol.registerIncoming(State.PLAY, 0x1B, 0x1B, new PacketRemapper() { + @Override + public void registerMap() { + map(Type.VAR_INT); + handler(new PacketHandler() { + @Override + public void handle(PacketWrapper wrapper) throws Exception { + int type = wrapper.get(Type.VAR_INT, 0); + if (type == 0) { + wrapper.passthrough(Type.STRING); + } else if (type == 1) { + wrapper.passthrough(Type.BOOLEAN); // Crafting Recipe Book Open + wrapper.passthrough(Type.BOOLEAN); // Crafting Recipe Filter Active + wrapper.passthrough(Type.BOOLEAN); // Smelting Recipe Book Open + wrapper.passthrough(Type.BOOLEAN); // Smelting Recipe Filter Active + + // Unknown new booleans + wrapper.read(Type.BOOLEAN); + wrapper.read(Type.BOOLEAN); + wrapper.read(Type.BOOLEAN); + wrapper.read(Type.BOOLEAN); + } + } + }); + } + }); + + // Update Command Block + protocol.registerIncoming(State.PLAY, 0x22, 0x22, new PacketRemapper() { + @Override + public void registerMap() { + map(Type.POSITION, Type.POSITION1_14); + } + }); + + // Update Structure Block + protocol.registerIncoming(State.PLAY, 0x25, 0x25, new PacketRemapper() { + @Override + public void registerMap() { + map(Type.POSITION, Type.POSITION1_14); + } + }); + + // Update Sign + protocol.registerIncoming(State.PLAY, 0x26, 0x26, new PacketRemapper() { + @Override + public void registerMap() { + map(Type.POSITION, Type.POSITION1_14); + } + }); + + // Player Block Placement + protocol.registerIncoming(State.PLAY, 0x29, 0x29, new PacketRemapper() { + @Override + public void registerMap() { + handler(new PacketHandler() { + @Override + public void handle(PacketWrapper wrapper) throws Exception { + Position position = wrapper.read(Type.POSITION); + int face = wrapper.read(Type.VAR_INT); + int hand = wrapper.read(Type.VAR_INT); + float x = wrapper.read(Type.FLOAT); + float y = wrapper.read(Type.FLOAT); + float z = wrapper.read(Type.FLOAT); + + wrapper.write(Type.VAR_INT, hand); + wrapper.write(Type.POSITION1_14, position); + wrapper.write(Type.VAR_INT, face); + wrapper.write(Type.FLOAT, x); + wrapper.write(Type.FLOAT, y); + wrapper.write(Type.FLOAT, z); + wrapper.write(Type.BOOLEAN, false); // Inside block + } + }); + } + }); + } + + @Override + protected void registerRewrites() { + + } +} diff --git a/core/src/main/java/nl/matsv/viabackwards/protocol/protocol1_13_2to1_14/packets/SoundPackets1_14.java b/core/src/main/java/nl/matsv/viabackwards/protocol/protocol1_13_2to1_14/packets/SoundPackets1_14.java new file mode 100644 index 00000000..5e803edb --- /dev/null +++ b/core/src/main/java/nl/matsv/viabackwards/protocol/protocol1_13_2to1_14/packets/SoundPackets1_14.java @@ -0,0 +1,34 @@ +package nl.matsv.viabackwards.protocol.protocol1_13_2to1_14.packets; + +import nl.matsv.viabackwards.api.rewriters.Rewriter; +import nl.matsv.viabackwards.protocol.protocol1_13_2to1_14.Protocol1_13_2To1_14; +import nl.matsv.viabackwards.protocol.protocol1_13_2to1_14.data.SoundMapping; +import us.myles.ViaVersion.api.PacketWrapper; +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 SoundPackets1_14 extends Rewriter { + @Override + protected void registerPackets(Protocol1_13_2To1_14 protocol) { + // Sound Effect + protocol.registerOutgoing(State.PLAY, 0x4D, 0x4D, new PacketRemapper() { + @Override + public void registerMap() { + map(Type.VAR_INT); // Sound Id + handler(new PacketHandler() { + @Override + public void handle(PacketWrapper wrapper) throws Exception { + wrapper.set(Type.VAR_INT, 0, SoundMapping.getOldSound(wrapper.get(Type.VAR_INT, 0))); + } + }); + } + }); + } + + @Override + protected void registerRewrites() { + + } +} diff --git a/core/src/main/resources/assets/viabackwards/data/mapping-1.13.2to1.14.json b/core/src/main/resources/assets/viabackwards/data/mapping-1.13.2to1.14.json new file mode 100644 index 00000000..26bb3825 --- /dev/null +++ b/core/src/main/resources/assets/viabackwards/data/mapping-1.13.2to1.14.json @@ -0,0 +1,4 @@ +{ + "blockstates": { + } +} \ No newline at end of file diff --git a/pom.xml b/pom.xml index 6fd7c8b8..fa166e63 100644 --- a/pom.xml +++ b/pom.xml @@ -66,7 +66,7 @@ us.myles viaversion - 2.0.0-SNAPSHOT + 2.0.0-19w09a provided