diff --git a/MinecraftClient/Mapping/EntityMetaDataType.cs b/MinecraftClient/Mapping/EntityMetaDataType.cs index e435c40d0e..db24f77b20 100644 --- a/MinecraftClient/Mapping/EntityMetaDataType.cs +++ b/MinecraftClient/Mapping/EntityMetaDataType.cs @@ -3,6 +3,9 @@ namespace MinecraftClient.Mapping; public enum EntityMetaDataType { Byte, + Short, // 1.8 only + Int, // 1.8 only + Vector3Int, // 1.8 only (not used by the game) VarInt, VarLong, Float, diff --git a/MinecraftClient/Mapping/EntityMetadataPalette.cs b/MinecraftClient/Mapping/EntityMetadataPalette.cs index bcb0b52a00..9759921f7f 100644 --- a/MinecraftClient/Mapping/EntityMetadataPalette.cs +++ b/MinecraftClient/Mapping/EntityMetadataPalette.cs @@ -16,8 +16,8 @@ public EntityMetaDataType GetDataType(int typeId) public static EntityMetadataPalette GetPalette(int protocolVersion) { - if (protocolVersion < Protocol18Handler.MC_1_9_Version) - throw new NotImplementedException(); + if (protocolVersion <= Protocol18Handler.MC_1_8_Version) + return new EntityMetadataPalette18(); // 1.8 else if (protocolVersion <= Protocol18Handler.MC_1_12_2_Version) return new EntityMetadataPalette1122(); // 1.9 - 1.12.2 else if (protocolVersion <= Protocol18Handler.MC_1_19_2_Version) diff --git a/MinecraftClient/Mapping/EntityMetadataPalettes/EntityMetadataPalette18.cs b/MinecraftClient/Mapping/EntityMetadataPalettes/EntityMetadataPalette18.cs new file mode 100644 index 0000000000..c862092c52 --- /dev/null +++ b/MinecraftClient/Mapping/EntityMetadataPalettes/EntityMetadataPalette18.cs @@ -0,0 +1,24 @@ +using System.Collections.Generic; + +namespace MinecraftClient.Mapping.EntityMetadataPalettes; + +public class EntityMetadataPalette18 : EntityMetadataPalette +{ + // 1.8 : https://wiki.vg/index.php?title=Entity_metadata&oldid=6220 + private readonly Dictionary entityMetadataMappings = new() + { + { 0, EntityMetaDataType.Byte }, + { 1, EntityMetaDataType.Short }, + { 2, EntityMetaDataType.Int }, + { 3, EntityMetaDataType.Float }, + { 4, EntityMetaDataType.String }, + { 5, EntityMetaDataType.Slot }, + { 6, EntityMetaDataType.Vector3Int }, + { 7, EntityMetaDataType.Rotation } + }; + + public override Dictionary GetEntityMetadataMappingsList() + { + return entityMetadataMappings; + } +} \ No newline at end of file diff --git a/MinecraftClient/Mapping/EntityMetadataPalettes/EntityMetadataPalette19.cs b/MinecraftClient/Mapping/EntityMetadataPalettes/EntityMetadataPalette19.cs deleted file mode 100644 index 39cd4963a5..0000000000 --- a/MinecraftClient/Mapping/EntityMetadataPalettes/EntityMetadataPalette19.cs +++ /dev/null @@ -1,31 +0,0 @@ -using System.Collections.Generic; - -namespace MinecraftClient.Mapping.EntityMetadataPalettes; - -// TODO: Use this for 1.8 -public class EntityMetadataPalette19 : EntityMetadataPalette -{ - // 1.8 : https://wiki.vg/index.php?title=Entity_metadata&oldid=6220 (Requires a different algorithm) - // 1.9 : https://wiki.vg/index.php?title=Entity_metadata&oldid=7416 - private readonly Dictionary entityMetadataMappings = new() - { - { 0, EntityMetaDataType.Byte }, - { 1, EntityMetaDataType.VarInt }, - { 2, EntityMetaDataType.Float }, - { 3, EntityMetaDataType.String }, - { 4, EntityMetaDataType.Chat }, - { 5, EntityMetaDataType.Slot }, - { 6, EntityMetaDataType.Boolean }, - { 7, EntityMetaDataType.Vector3 }, - { 8, EntityMetaDataType.Position }, - { 9, EntityMetaDataType.OptionalPosition }, - { 10, EntityMetaDataType.Direction }, - { 11, EntityMetaDataType.OptionalUuid }, - { 12, EntityMetaDataType.OptionalBlockId } - }; - - public override Dictionary GetEntityMetadataMappingsList() - { - return entityMetadataMappings; - } -} \ No newline at end of file diff --git a/MinecraftClient/Mapping/EntityPalettes/EntityPalette18.cs b/MinecraftClient/Mapping/EntityPalettes/EntityPalette18.cs new file mode 100644 index 0000000000..2ff09ace7e --- /dev/null +++ b/MinecraftClient/Mapping/EntityPalettes/EntityPalette18.cs @@ -0,0 +1,114 @@ +using System; +using System.Collections.Generic; + +namespace MinecraftClient.Mapping.EntityPalettes +{ + /// + /// Defines mappings of entitiy IDs for 1.8 + /// Manually typed out by Milutinke :( + /// Data source: https://pokechu22.github.io/Burger/1.8.json and https://wiki.vg/index.php?title=Entity_metadata&oldid=7415 + /// + public class EntityPalette18 : EntityPalette + { + private static Dictionary mappingsObjects = new Dictionary() + { + // https://wiki.vg/Entity_metadata#Objects + { 1, EntityType.Boat }, + { 2, EntityType.Item }, + { 3, EntityType.AreaEffectCloud }, + { 10, EntityType.Minecart }, + { 50, EntityType.Tnt }, + { 51, EntityType.EndCrystal }, + { 60, EntityType.Arrow }, + { 61, EntityType.Snowball }, + { 62, EntityType.Egg }, + { 63, EntityType.Fireball }, + { 64, EntityType.SmallFireball }, + { 65, EntityType.EnderPearl }, + { 66, EntityType.WitherSkull }, + { 70, EntityType.FallingBlock }, + { 71, EntityType.ItemFrame }, + { 72, EntityType.EyeOfEnder }, + { 73, EntityType.Egg }, + { 75, EntityType.ExperienceBottle }, + { 76, EntityType.FireworkRocket }, + { 77, EntityType.LeashKnot }, + { 78, EntityType.ArmorStand }, + { 90, EntityType.FishingBobber }, + { 91, EntityType.SpectralArrow }, + { 93, EntityType.DragonFireball }, + }; + + private static Dictionary mappingsMobs = new Dictionary() { + { 1, EntityType.Item }, + { 2, EntityType.ExperienceOrb }, + { 8, EntityType.LeashKnot }, + { 9, EntityType.Painting }, + { 10, EntityType.Arrow }, + { 11, EntityType.Snowball }, + { 12, EntityType.Fireball }, + { 13, EntityType.SmallFireball }, + { 14, EntityType.EnderPearl }, + { 15, EntityType.EyeOfEnder }, + { 16, EntityType.Potion }, + { 17, EntityType.ExperienceBottle }, + { 18, EntityType.ItemFrame }, + { 19, EntityType.WitherSkull }, + { 20, EntityType.Tnt }, + { 21, EntityType.FallingBlock }, + { 22, EntityType.FireworkRocket }, + { 30, EntityType.ArmorStand }, + { 40, EntityType.CommandBlockMinecart }, + { 41, EntityType.Boat }, + { 42, EntityType.Minecart }, + { 43, EntityType.ChestMinecart }, + { 44, EntityType.FurnaceMinecart }, + { 45, EntityType.TntMinecart }, + { 46, EntityType.HopperMinecart }, + { 47, EntityType.SpawnerMinecart }, + { 50, EntityType.Creeper }, + { 51, EntityType.Skeleton }, + { 52, EntityType.Spider }, + { 53, EntityType.Giant }, + { 54, EntityType.Zombie }, + { 55, EntityType.Slime }, + { 56, EntityType.Ghast }, + { 57, EntityType.ZombifiedPiglin }, + { 58, EntityType.Enderman }, + { 59, EntityType.CaveSpider }, + { 60, EntityType.Silverfish }, + { 61, EntityType.Blaze }, + { 62, EntityType.MagmaCube }, + { 63, EntityType.EnderDragon }, + { 64, EntityType.Wither }, + { 65, EntityType.Bat }, + { 66, EntityType.Witch }, + { 67, EntityType.Endermite }, + { 68, EntityType.Guardian }, + { 90, EntityType.Pig }, + { 91, EntityType.Sheep }, + { 92, EntityType.Cow }, + { 93, EntityType.Chicken }, + { 94, EntityType.Squid }, + { 95, EntityType.Wolf }, + { 96, EntityType.Mooshroom }, + { 97, EntityType.SnowGolem }, + { 98, EntityType.Cat }, + { 99, EntityType.IronGolem }, + { 100, EntityType.Horse }, + { 101, EntityType.Rabbit }, + { 120, EntityType.Villager }, + { 200, EntityType.EndCrystal } + }; + + protected override Dictionary GetDict() + { + return mappingsMobs; + } + + protected override Dictionary GetDictNonLiving() + { + return mappingsObjects; + } + } +} diff --git a/MinecraftClient/Protocol/Handlers/DataTypes.cs b/MinecraftClient/Protocol/Handlers/DataTypes.cs index 1300b1ebb3..5162d4f9bd 100644 --- a/MinecraftClient/Protocol/Handlers/DataTypes.cs +++ b/MinecraftClient/Protocol/Handlers/DataTypes.cs @@ -463,47 +463,74 @@ public Dictionary ReadNextNbt(Queue cache) public Entity ReadNextEntity(Queue cache, EntityPalette entityPalette, bool living) { int entityID = ReadNextVarInt(cache); - if (protocolversion > Protocol18Handler.MC_1_8_Version) - ReadNextUUID(cache); + Guid entityUUID = Guid.Empty; + // UUID field added in 1.9 + + if (protocolversion >= Protocol18Handler.MC_1_9_Version) + entityUUID = ReadNextUUID(cache); + + // Entity type data type change from byte to varint in 1.13.2 EntityType entityType; - // Entity type data type change from byte to varint after 1.14 - if (protocolversion > Protocol18Handler.MC_1_13_Version) - entityType = entityPalette.FromId(ReadNextVarInt(cache), living); + + if (living) + { + // For living entities the Type field was changed to VarInt from Byte in 1.11 + + if (protocolversion >= Protocol18Handler.MC_1_11_Version) + entityType = entityPalette.FromId(ReadNextVarInt(cache), living); + else entityType = entityPalette.FromId(ReadNextByte(cache), living); + } + else + { + // For non-living entities the Type field was changed to VarInt from Byte in 1.13.2 + + if (protocolversion >= Protocol18Handler.MC_1_13_2_Version) + entityType = entityPalette.FromId(ReadNextVarInt(cache), living); + else entityType = entityPalette.FromId(ReadNextByte(cache), living); + } + + Double entityX, entityY, entityZ; + + if (protocolversion < Protocol18Handler.MC_1_9_Version) + { + entityX = ReadNextInt(cache) / 32.0D; // X + entityY = ReadNextInt(cache) / 32.0D; // Y + entityZ = ReadNextInt(cache) / 32.0D; // Z + } else - entityType = entityPalette.FromId(ReadNextByte(cache), living); + { + entityX = ReadNextDouble(cache); // X + entityY = ReadNextDouble(cache); // Y + entityZ = ReadNextDouble(cache); // Z + } - double entityX = ReadNextDouble(cache); - double entityY = ReadNextDouble(cache); - double entityZ = ReadNextDouble(cache); - byte entityPitch = ReadNextByte(cache); - byte entityYaw = ReadNextByte(cache); int metadata = -1; + byte entityPitch, entityYaw; + if (living) { - if (protocolversion == Protocol18Handler.MC_1_18_2_Version) - entityYaw = ReadNextByte(cache); - else - entityPitch = ReadNextByte(cache); + entityYaw = ReadNextByte(cache); // Yaw + entityPitch = ReadNextByte(cache); // Pitch + entityPitch = ReadNextByte(cache); // Head Pitch } else { + entityPitch = ReadNextByte(cache); // Pitch + entityYaw = ReadNextByte(cache); // Yaw + if (protocolversion >= Protocol18Handler.MC_1_19_Version) - { - entityYaw = ReadNextByte(cache); - metadata = ReadNextVarInt(cache); - } - else - metadata = ReadNextInt(cache); + entityYaw = ReadNextByte(cache); // Head Yaw + + // Data + if (protocolversion >= Protocol18Handler.MC_1_19_Version) + ReadNextVarInt(cache); + else ReadNextInt(cache); } short velocityX = ReadNextShort(cache); short velocityY = ReadNextShort(cache); short velocityZ = ReadNextShort(cache); - return new Entity(entityID, entityType, new Location(entityX, entityY, entityZ), entityYaw, entityPitch, - metadata); + return new Entity(entityID, entityType, new Location(entityX, entityY, entityZ), entityYaw, entityPitch, metadata); } /// @@ -599,18 +626,30 @@ private object ReadNbtField(Queue cache, int fieldType) } } - //TODO: Refactor this to use new Entity Metadata Palettes + /// + /// Read a Entity MetaData and remove it from the cache + /// + /// + /// + /// + /// + /// + /// public Dictionary ReadNextMetadata(Queue cache, ItemPalette itemPalette, EntityMetadataPalette metadataPalette) { - if (protocolversion <= Protocol18Handler.MC_1_8_Version) - throw new NotImplementedException(); // Require sepcial implementation - Dictionary data = new(); byte key = ReadNextByte(cache); + byte terminteValue = protocolversion <= Protocol18Handler.MC_1_8_Version + ? (byte)0x7f // 1.8 (https://wiki.vg/index.php?title=Entity_metadata&oldid=6220#Entity_Metadata_Format) + : (byte)0xff; // 1.9+ - while (key != 0xff) + while (key != terminteValue) { - int typeId = ReadNextVarInt(cache); + int typeId = protocolversion <= Protocol18Handler.MC_1_8_Version + ? key >> 5 // 1.8 + : ReadNextVarInt(cache); // 1.9+ + + EntityMetaDataType type; try { @@ -620,12 +659,29 @@ private object ReadNbtField(Queue cache, int fieldType) { throw new System.IO.InvalidDataException("Unknown Metadata Type ID " + typeId + ". Is this up to date for new MC Version?"); } + + if (protocolversion <= Protocol18Handler.MC_1_8_Version) + key = (byte)(key & 0x1f); // Value's data type is depended on Type object? value = null; switch (type) { + case EntityMetaDataType.Short: // 1.8 only + value = ReadNextShort(cache); + break; + case EntityMetaDataType.Int: // 1.8 only + value = ReadNextInt(cache); + break; + case EntityMetaDataType.Vector3Int: // 1.8 only + value = new List() + { + ReadNextInt(cache), + ReadNextInt(cache), + ReadNextInt(cache), + }; + break; case EntityMetaDataType.Byte: // byte value = ReadNextByte(cache); break; @@ -760,7 +816,11 @@ private object ReadNbtField(Queue cache, int fieldType) return data; } - // Currently not handled. Reading data only + /// + /// Currently not handled. Reading data only + /// + /// + /// protected void ReadParticleData(Queue cache, ItemPalette itemPalette) { if (protocolversion < Protocol18Handler.MC_1_13_Version) diff --git a/MinecraftClient/Protocol/Handlers/PacketPalettes/PacketPalette18.cs b/MinecraftClient/Protocol/Handlers/PacketPalettes/PacketPalette18.cs new file mode 100644 index 0000000000..424a74b904 --- /dev/null +++ b/MinecraftClient/Protocol/Handlers/PacketPalettes/PacketPalette18.cs @@ -0,0 +1,130 @@ +using System.Collections.Generic; + +namespace MinecraftClient.Protocol.Handlers.PacketPalettes +{ + public class PacketPalette18 : PacketTypePalette + { + private Dictionary typeIn = new Dictionary() + { + { 0x00, PacketTypesIn.KeepAlive }, + { 0x01, PacketTypesIn.JoinGame }, + { 0x02, PacketTypesIn.ChatMessage }, + { 0x03, PacketTypesIn.TimeUpdate }, + { 0x04, PacketTypesIn.EntityEquipment }, + { 0x05, PacketTypesIn.SpawnPosition }, + { 0x06, PacketTypesIn.UpdateHealth }, + { 0x07, PacketTypesIn.Respawn }, + { 0x08, PacketTypesIn.PlayerPositionAndLook }, + { 0x09, PacketTypesIn.HeldItemChange }, + { 0x0A, PacketTypesIn.UseBed }, + { 0x0B, PacketTypesIn.EntityAnimation }, + { 0x0C, PacketTypesIn.SpawnPlayer }, + { 0x0D, PacketTypesIn.CollectItem }, + { 0x0E, PacketTypesIn.SpawnEntity }, + { 0x0F, PacketTypesIn.SpawnLivingEntity }, + { 0x10, PacketTypesIn.SpawnPainting }, + { 0x11, PacketTypesIn.SpawnExperienceOrb }, + { 0x12, PacketTypesIn.EntityVelocity }, + { 0x13, PacketTypesIn.DestroyEntities }, + { 0x15, PacketTypesIn.EntityMovement }, + { 0x16, PacketTypesIn.EntityRotation }, + { 0x17, PacketTypesIn.EntityPositionAndRotation }, + { 0x18, PacketTypesIn.EntityTeleport }, + { 0x19, PacketTypesIn.EntityHeadLook }, + { 0x1A, PacketTypesIn.EntityStatus }, + { 0x1B, PacketTypesIn.AttachEntity }, + { 0x1C, PacketTypesIn.EntityMetadata }, + { 0x1D, PacketTypesIn.EntityEffect }, + { 0x1E, PacketTypesIn.RemoveEntityEffect }, + { 0x1F, PacketTypesIn.SetExperience }, + { 0x20, PacketTypesIn.EntityProperties }, + { 0x21, PacketTypesIn.ChunkData }, + { 0x22, PacketTypesIn.MultiBlockChange }, + { 0x23, PacketTypesIn.BlockChange }, + { 0x24, PacketTypesIn.BlockAction }, + { 0x25, PacketTypesIn.BlockBreakAnimation }, + // Missing Chunk Bulk Data + { 0x27, PacketTypesIn.Explosion }, + { 0x28, PacketTypesIn.Effect }, + { 0x29, PacketTypesIn.SoundEffect }, + { 0x2A, PacketTypesIn.Particle }, + { 0x2B, PacketTypesIn.ChangeGameState }, + { 0x2C, PacketTypesIn.SpawnWeatherEntity }, + { 0x2D, PacketTypesIn.OpenWindow }, + { 0x2E, PacketTypesIn.CloseWindow }, + { 0x2F, PacketTypesIn.SetSlot }, + { 0x30, PacketTypesIn.WindowItems }, + { 0x31, PacketTypesIn.WindowProperty }, + { 0x32, PacketTypesIn.WindowConfirmation }, + // Missing Update Sign + { 0x34, PacketTypesIn.MapData }, + { 0x35, PacketTypesIn.BlockEntityData }, + { 0x36, PacketTypesIn.OpenSignEditor }, + { 0x37, PacketTypesIn.Statistics }, + // Missing Player List Item + { 0x39, PacketTypesIn.PlayerAbilities }, + { 0x3A, PacketTypesIn.TabComplete }, + { 0x3B, PacketTypesIn.ScoreboardObjective }, + { 0x3C, PacketTypesIn.UpdateScore }, + { 0x3D, PacketTypesIn.DisplayScoreboard }, + { 0x3E, PacketTypesIn.Teams }, + { 0x3D, PacketTypesIn.PluginMessage }, + { 0x40, PacketTypesIn.Disconnect }, + { 0x41, PacketTypesIn.ServerDifficulty }, + { 0x42, PacketTypesIn.CombatEvent }, + { 0x43, PacketTypesIn.Camera }, + { 0x44, PacketTypesIn.WorldBorder }, + { 0x45, PacketTypesIn.Title }, + { 0x47, PacketTypesIn.PlayerListHeaderAndFooter }, + { 0x48, PacketTypesIn.ResourcePackSend }, + { 0x49, PacketTypesIn.UpdateEntityNBT } + }; + + private Dictionary typeOut = new Dictionary() + { + { 0x00, PacketTypesOut.TeleportConfirm }, + { 0x01, PacketTypesOut.Unknown }, + { 0x02, PacketTypesOut.TabComplete }, + { 0x03, PacketTypesOut.ChatMessage }, + { 0x04, PacketTypesOut.ClientStatus }, + { 0x05, PacketTypesOut.ClientSettings }, + { 0x06, PacketTypesOut.WindowConfirmation }, + { 0x07, PacketTypesOut.EnchantItem }, + { 0x08, PacketTypesOut.ClickWindow }, + { 0x09, PacketTypesOut.CloseWindow }, + { 0x0A, PacketTypesOut.PluginMessage }, + { 0x0B, PacketTypesOut.InteractEntity }, + { 0x0C, PacketTypesOut.KeepAlive }, + { 0x0D, PacketTypesOut.PlayerMovement }, + { 0x0E, PacketTypesOut.PlayerPosition }, + { 0x0F, PacketTypesOut.PlayerPositionAndRotation }, + { 0x10, PacketTypesOut.PlayerRotation }, + { 0x11, PacketTypesOut.VehicleMove }, + { 0x12, PacketTypesOut.SteerBoat }, + { 0x13, PacketTypesOut.PlayerAbilities }, + { 0x14, PacketTypesOut.PlayerDigging }, + { 0x15, PacketTypesOut.EntityAction }, + { 0x16, PacketTypesOut.SteerVehicle }, + { 0x17, PacketTypesOut.RecipeBookData }, + { 0x18, PacketTypesOut.ResourcePackStatus }, + { 0x19, PacketTypesOut.AdvancementTab }, + { 0x1A, PacketTypesOut.HeldItemChange }, + { 0x1B, PacketTypesOut.CreativeInventoryAction }, + { 0x1C, PacketTypesOut.UpdateSign }, + { 0x1D, PacketTypesOut.Animation }, + { 0x1E, PacketTypesOut.Spectate }, + { 0x1F, PacketTypesOut.PlayerBlockPlacement }, + { 0x20, PacketTypesOut.UseItem }, + }; + + protected override Dictionary GetListIn() + { + return typeIn; + } + + protected override Dictionary GetListOut() + { + return typeOut; + } + } +} diff --git a/MinecraftClient/Protocol/Handlers/Protocol18.cs b/MinecraftClient/Protocol/Handlers/Protocol18.cs index 53e19404a0..413e7e54e1 100644 --- a/MinecraftClient/Protocol/Handlers/Protocol18.cs +++ b/MinecraftClient/Protocol/Handlers/Protocol18.cs @@ -44,6 +44,7 @@ class Protocol18Handler : IMinecraftCom internal const int MC_1_9_Version = 107; internal const int MC_1_9_1_Version = 108; internal const int MC_1_10_Version = 210; + internal const int MC_1_11_Version = 315; internal const int MC_1_11_2_Version = 316; internal const int MC_1_12_Version = 335; internal const int MC_1_12_2_Version = 340; @@ -119,14 +120,14 @@ public Protocol18Handler(TcpClient Client, int protocolVersion, IMinecraftComHan } if (handler.GetInventoryEnabled() && - (protocolVersion < MC_1_10_Version || protocolVersion > MC_1_19_4_Version)) + (protocolVersion < MC_1_9_Version || protocolVersion > MC_1_19_4_Version)) { log.Error("§c" + Translations.extra_inventory_disabled); handler.SetInventoryEnabled(false); } if (handler.GetEntityHandlingEnabled() && - (protocolVersion < MC_1_10_Version || protocolVersion > MC_1_19_4_Version)) + (protocolVersion < MC_1_8_Version || protocolVersion > MC_1_19_4_Version)) { log.Error("§c" + Translations.extra_entity_disabled); handler.SetEntityHandlingEnabled(false); @@ -177,8 +178,9 @@ public Protocol18Handler(TcpClient Client, int protocolVersion, IMinecraftComHan entityPalette = new EntityPalette114(); else if (protocolVersion >= MC_1_13_Version) entityPalette = new EntityPalette113(); - else + else if (protocolVersion >= MC_1_12_Version) entityPalette = new EntityPalette112(); + else entityPalette = new EntityPalette18(); entityMetadataPalette = EntityMetadataPalette.GetPalette(protocolVersion); @@ -1973,7 +1975,10 @@ internal bool HandlePacket(int packetID, Queue packetData) } else { - int slot2 = dataTypes.ReadNextVarInt(packetData); + int slot2 = protocolVersion < MC_1_9_Version + ? dataTypes.ReadNextShort(packetData) + : dataTypes.ReadNextVarInt(packetData); + Item? item = dataTypes.ReadNextItemSlot(packetData, itemPalette); handler.OnEntityEquipment(entityid, slot2, item); } @@ -1996,13 +2001,26 @@ internal bool HandlePacket(int packetID, Queue packetData) { int EntityID = dataTypes.ReadNextVarInt(packetData); Guid UUID = dataTypes.ReadNextUUID(packetData); - double X = dataTypes.ReadNextDouble(packetData); - double Y = dataTypes.ReadNextDouble(packetData); - double Z = dataTypes.ReadNextDouble(packetData); + + double x, y, z; + + if (protocolVersion < MC_1_9_Version) + { + x = dataTypes.ReadNextInt(packetData) / 32.0D; + y = dataTypes.ReadNextInt(packetData) / 32.0D; + z = dataTypes.ReadNextInt(packetData) / 32.0D; + } + else + { + x = dataTypes.ReadNextDouble(packetData); + y = dataTypes.ReadNextDouble(packetData); + z = dataTypes.ReadNextDouble(packetData); + } + byte Yaw = dataTypes.ReadNextByte(packetData); byte Pitch = dataTypes.ReadNextByte(packetData); - Location EntityLocation = new(X, Y, Z); + Location EntityLocation = new(x, y, z); handler.OnSpawnPlayer(EntityID, UUID, EntityLocation, Yaw, Pitch); } @@ -2059,13 +2077,27 @@ internal bool HandlePacket(int packetID, Queue packetData) if (handler.GetEntityHandlingEnabled()) { int EntityID = dataTypes.ReadNextVarInt(packetData); - Double DeltaX = Convert.ToDouble(dataTypes.ReadNextShort(packetData)); - Double DeltaY = Convert.ToDouble(dataTypes.ReadNextShort(packetData)); - Double DeltaZ = Convert.ToDouble(dataTypes.ReadNextShort(packetData)); + + Double DeltaX, DeltaY, DeltaZ; + + if (protocolVersion < MC_1_9_Version) + { + DeltaX = Convert.ToDouble(dataTypes.ReadNextByte(packetData)); + DeltaY = Convert.ToDouble(dataTypes.ReadNextByte(packetData)); + DeltaZ = Convert.ToDouble(dataTypes.ReadNextByte(packetData)); + } + else + { + DeltaX = Convert.ToDouble(dataTypes.ReadNextShort(packetData)); + DeltaY = Convert.ToDouble(dataTypes.ReadNextShort(packetData)); + DeltaZ = Convert.ToDouble(dataTypes.ReadNextShort(packetData)); + } + bool OnGround = dataTypes.ReadNextBool(packetData); - DeltaX /= (128 * 32); - DeltaY /= (128 * 32); - DeltaZ /= (128 * 32); + DeltaX = DeltaX / (128 * 32); + DeltaY = DeltaY / (128 * 32); + DeltaZ = DeltaZ / (128 * 32); + handler.OnEntityPosition(EntityID, DeltaX, DeltaY, DeltaZ, OnGround); } @@ -2074,15 +2106,30 @@ internal bool HandlePacket(int packetID, Queue packetData) if (handler.GetEntityHandlingEnabled()) { int EntityID = dataTypes.ReadNextVarInt(packetData); - Double DeltaX = Convert.ToDouble(dataTypes.ReadNextShort(packetData)); - Double DeltaY = Convert.ToDouble(dataTypes.ReadNextShort(packetData)); - Double DeltaZ = Convert.ToDouble(dataTypes.ReadNextShort(packetData)); + + Double DeltaX, DeltaY, DeltaZ; + + if (protocolVersion < MC_1_9_Version) + { + DeltaX = dataTypes.ReadNextByte(packetData) / 32.0D; + DeltaY = dataTypes.ReadNextByte(packetData) / 32.0D; + DeltaZ = dataTypes.ReadNextByte(packetData) / 32.0D; + } + else + { + DeltaX = Convert.ToDouble(dataTypes.ReadNextShort(packetData)); + DeltaY = Convert.ToDouble(dataTypes.ReadNextShort(packetData)); + DeltaZ = Convert.ToDouble(dataTypes.ReadNextShort(packetData)); + } + + byte _yaw = dataTypes.ReadNextByte(packetData); byte _pitch = dataTypes.ReadNextByte(packetData); bool OnGround = dataTypes.ReadNextBool(packetData); - DeltaX /= (128 * 32); - DeltaY /= (128 * 32); - DeltaZ /= (128 * 32); + DeltaX = DeltaX / (128 * 32); + DeltaY = DeltaY / (128 * 32); + DeltaZ = DeltaZ / (128 * 32); + handler.OnEntityPosition(EntityID, DeltaX, DeltaY, DeltaZ, OnGround); } @@ -2137,7 +2184,8 @@ internal bool HandlePacket(int packetID, Queue packetData) if (handler.GetEntityHandlingEnabled()) { int EntityID = dataTypes.ReadNextVarInt(packetData); - Dictionary metadata = dataTypes.ReadNextMetadata(packetData, itemPalette, entityMetadataPalette); + Dictionary metadata = + dataTypes.ReadNextMetadata(packetData, itemPalette, entityMetadataPalette); // Also make a palette for field? Will be a lot of work int healthField; // See https://wiki.vg/Entity_metadata#Living_Entity @@ -2149,6 +2197,8 @@ internal bool HandlePacket(int packetID, Queue packetData) healthField = 8; else if (protocolVersion >= MC_1_10_Version) // 1.10 and above healthField = 7; + else if (protocolVersion >= MC_1_8_Version) // 1.8 and above + healthField = 6; else throw new NotImplementedException(Translations.exception_palette_healthfield); @@ -2178,13 +2228,26 @@ internal bool HandlePacket(int packetID, Queue packetData) if (handler.GetEntityHandlingEnabled()) { int EntityID = dataTypes.ReadNextVarInt(packetData); - Double X = dataTypes.ReadNextDouble(packetData); - Double Y = dataTypes.ReadNextDouble(packetData); - Double Z = dataTypes.ReadNextDouble(packetData); + + double x, y, z; + + if (protocolVersion < MC_1_9_Version) + { + x = dataTypes.ReadNextInt(packetData) / 32.0D; + y = dataTypes.ReadNextInt(packetData) / 32.0D; + z = dataTypes.ReadNextInt(packetData) / 32.0D; + } + else + { + x = dataTypes.ReadNextDouble(packetData); + y = dataTypes.ReadNextDouble(packetData); + z = dataTypes.ReadNextDouble(packetData); + } + byte EntityYaw = dataTypes.ReadNextByte(packetData); byte EntityPitch = dataTypes.ReadNextByte(packetData); bool OnGround = dataTypes.ReadNextBool(packetData); - handler.OnEntityTeleport(EntityID, X, Y, Z, OnGround); + handler.OnEntityTeleport(EntityID, x, y, z, OnGround); } break; @@ -3550,10 +3613,31 @@ public bool SendPlayerDigging(int status, Location location, Direction face, int public bool SendPlayerBlockPlacement(int hand, Location location, Direction face, int sequenceId) { if (protocolVersion < MC_1_14_Version) - return false; // NOT IMPLEMENTED for older MC versions + { + Container? playerInventory = handler.GetInventory(0); + + if (playerInventory == null) + return false; + + List packet = new List(); + + packet.AddRange(dataTypes.GetLocation(location)); + packet.Add(dataTypes.GetBlockFace(face)); + + Item item = playerInventory.Items[((McClient)handler).GetCurrentSlot()]; + packet.AddRange(dataTypes.GetItemSlot(item, itemPalette)); + + packet.Add((byte)0); // cursorX + packet.Add((byte)0); // cursorY + packet.Add((byte)0); // cursorZ + + SendPacket(PacketTypesOut.PlayerBlockPlacement, packet); + return true; + } + try { - List packet = new(); + List packet = new List(); packet.AddRange(DataTypes.GetVarInt(hand)); packet.AddRange(dataTypes.GetLocation(location)); packet.AddRange(DataTypes.GetVarInt(dataTypes.GetBlockFace(face)));