diff --git a/MinecraftClient/Inventory/EnchantmentMapping.cs b/MinecraftClient/Inventory/EnchantmentMapping.cs index badadb99..1768482e 100644 --- a/MinecraftClient/Inventory/EnchantmentMapping.cs +++ b/MinecraftClient/Inventory/EnchantmentMapping.cs @@ -10,7 +10,7 @@ namespace MinecraftClient.Inventory { #pragma warning disable format // @formatter:off // 1.14 - 1.15.2 - private static Dictionary enchantmentMappings114 = new Dictionary() + private static Dictionary enchantmentMappings114 = new() { //id type { 0, Enchantment.Protection }, @@ -50,7 +50,7 @@ namespace MinecraftClient.Inventory }; // 1.16 - 1.18 - private static Dictionary enchantmentMappings116 = new Dictionary() + private static Dictionary enchantmentMappings116 = new() { //id type { 0, Enchantment.Protection }, @@ -93,8 +93,8 @@ namespace MinecraftClient.Inventory { 37, Enchantment.VanishingCurse } }; - // 1.19+ - private static Dictionary enchantmentMappings = new Dictionary() + // 1.19 - 1.20.4 + private static Dictionary enchantmentMappings119 = new() { //id type { 0, Enchantment.Protection }, @@ -137,6 +137,54 @@ namespace MinecraftClient.Inventory { 37, Enchantment.Mending }, { 38, Enchantment.VanishingCurse } }; + + // 1.20.6+ + private static Dictionary enchantmentMappings = new() + { + //id type + { 0, Enchantment.Protection }, + { 1, Enchantment.FireProtection }, + { 2, Enchantment.FeatherFalling }, + { 3, Enchantment.BlastProtection }, + { 4, Enchantment.ProjectileProtection }, + { 5, Enchantment.Respiration }, + { 6, Enchantment.AquaAffinity }, + { 7, Enchantment.Thorns }, + { 8, Enchantment.DepthStrieder }, + { 9, Enchantment.FrostWalker }, + { 10, Enchantment.BindingCurse }, + { 11, Enchantment.SoulSpeed }, + { 12, Enchantment.SwiftSneak }, + { 13, Enchantment.Sharpness }, + { 14, Enchantment.Smite }, + { 15, Enchantment.BaneOfArthropods }, + { 16, Enchantment.Knockback }, + { 17, Enchantment.FireAspect }, + { 18, Enchantment.Looting }, + { 19, Enchantment.Sweeping }, + { 20, Enchantment.Efficency }, + { 21, Enchantment.SilkTouch }, + { 22, Enchantment.Unbreaking }, + { 23, Enchantment.Fortune }, + { 24, Enchantment.Power }, + { 25, Enchantment.Punch }, + { 26, Enchantment.Flame }, + { 27, Enchantment.Infinity }, + { 28, Enchantment.LuckOfTheSea }, + { 29, Enchantment.Lure }, + { 30, Enchantment.Loyality }, + { 31, Enchantment.Impaling }, + { 32, Enchantment.Riptide }, + { 33, Enchantment.Channeling }, + { 34, Enchantment.Multishot }, + { 35, Enchantment.QuickCharge }, + { 36, Enchantment.Piercing }, + { 37, Enchantment.Density }, + { 38, Enchantment.Breach }, + { 39, Enchantment.WindBurst }, + { 40, Enchantment.Mending }, + { 41, Enchantment.VanishingCurse } + }; #pragma warning restore format // @formatter:on public static Enchantment GetEnchantmentById(int protocolVersion, short id) @@ -144,34 +192,32 @@ namespace MinecraftClient.Inventory if (protocolVersion < Protocol18Handler.MC_1_14_Version) throw new Exception("Enchantments mappings are not implemented bellow 1.14"); - Dictionary map = enchantmentMappings; + var map = protocolVersion switch + { + >= Protocol18Handler.MC_1_14_Version and < Protocol18Handler.MC_1_16_Version => enchantmentMappings114, + >= Protocol18Handler.MC_1_16_Version and < Protocol18Handler.MC_1_19_Version => enchantmentMappings116, + >= Protocol18Handler.MC_1_19_Version and < Protocol18Handler.MC_1_20_6_Version => enchantmentMappings119, + _ => enchantmentMappings + }; - if (protocolVersion >= Protocol18Handler.MC_1_14_Version && protocolVersion < Protocol18Handler.MC_1_16_Version) - map = enchantmentMappings114; - else if (protocolVersion >= Protocol18Handler.MC_1_16_Version && protocolVersion < Protocol18Handler.MC_1_19_Version) - map = enchantmentMappings116; + if (!map.TryGetValue(id, out var value)) + throw new Exception($"Got an Unknown Enchantment ID {id}, please update the Mappings!"); - if (!map.ContainsKey(id)) - throw new Exception("Got an Unknown Enchantment ID '" + id + "', please update the Mappings!"); - - return map[id]; + return value; } public static string GetEnchantmentName(Enchantment enchantment) { - string? trans = ChatParser.TranslateString("enchantment.minecraft." + enchantment.ToString().ToUnderscoreCase()); - if (string.IsNullOrEmpty(trans)) - return "Unknown Enchantment with ID: " + ((short)enchantment) + " (Probably not named in the code yet)"; - else - return trans; + var translation = ChatParser.TranslateString("enchantment.minecraft." + enchantment.ToString().ToUnderscoreCase()); + return string.IsNullOrEmpty(translation) ? $"Unknown Enchantment with ID: {(short)enchantment} (Probably not named in the code yet)" : translation; } public static string ConvertLevelToRomanNumbers(int num) { - string result = string.Empty; - Dictionary romanNumbers = new Dictionary + var result = string.Empty; + var romanNumbers = new Dictionary { - {"M", 1000 }, + {"M", 1000}, {"CM", 900}, {"D", 500}, {"CD", 400}, diff --git a/MinecraftClient/Inventory/Enchantments.cs b/MinecraftClient/Inventory/Enchantments.cs index 34279de0..f1087d51 100644 --- a/MinecraftClient/Inventory/Enchantments.cs +++ b/MinecraftClient/Inventory/Enchantments.cs @@ -3,44 +3,47 @@ // Not implemented for 1.14 public enum Enchantment : short { - Protection = 0, - FireProtection, - FeatherFalling, - BlastProtection, - ProjectileProtection, - Respiration, - AquaAffinity, - Thorns, - DepthStrieder, - FrostWalker, - BindingCurse, - SoulSpeed, - SwiftSneak, - Sharpness, - Smite, + AquaAffinity = 0, BaneOfArthropods, - Knockback, - FireAspect, - Looting, - Sweeping, - Efficency, - SilkTouch, - Unbreaking, - Fortune, - Power, - Punch, - Flame, - Infinity, - LuckOfTheSea, - Lure, - Loyality, - Impaling, - Riptide, + BindingCurse, + BlastProtection, + Breach, Channeling, - Multishot, - QuickCharge, - Piercing, + DepthStrieder, + Density, + Efficency, + FeatherFalling, + FireAspect, + FireProtection, + Flame, + Fortune, + FrostWalker, + Impaling, + Infinity, + Knockback, + Looting, + LuckOfTheSea, + Loyality, + Lure, Mending, - VanishingCurse + Multishot, + Piercing, + Power, + ProjectileProtection, + Protection, + Punch, + QuickCharge, + Respiration, + Riptide, + Sharpness, + SilkTouch, + Smite, + SoulSpeed, + Sweeping, + SwiftSneak, + Thorns, + Unbreaking, + VanishingCurse, + WindBurst } } diff --git a/MinecraftClient/Mapping/EntityMetadataPalette.cs b/MinecraftClient/Mapping/EntityMetadataPalette.cs index 15963231..5b220474 100644 --- a/MinecraftClient/Mapping/EntityMetadataPalette.cs +++ b/MinecraftClient/Mapping/EntityMetadataPalette.cs @@ -22,7 +22,7 @@ public abstract class EntityMetadataPalette <= Protocol18Handler.MC_1_12_2_Version => new EntityMetadataPalette1122(), // 1.9 - 1.12.2 <= Protocol18Handler.MC_1_19_2_Version => new EntityMetadataPalette1191(), // 1.13 - 1.19.2 <= Protocol18Handler.MC_1_19_3_Version => new EntityMetadataPalette1193(), // 1.19.3 - <= Protocol18Handler.MC_1_20_4_Version => new EntityMetadataPalette1194(), // 1.19.4 - 1.20.4 + + <= Protocol18Handler.MC_1_20_6_Version => new EntityMetadataPalette1194(), // 1.19.4 - 1.20.6 + _ => throw new NotImplementedException() }; } diff --git a/MinecraftClient/McClient.cs b/MinecraftClient/McClient.cs index f7dd7fcd..8149a06c 100644 --- a/MinecraftClient/McClient.cs +++ b/MinecraftClient/McClient.cs @@ -118,6 +118,9 @@ namespace MinecraftClient // ChatBot OnNetworkPacket event private bool networkPacketCaptureEnabled = false; + + // Cookies + private Dictionary Cookies { get; set; } = new(); public int GetServerPort() { return port; } public string GetServerHost() { return host; } @@ -143,6 +146,8 @@ namespace MinecraftClient public ILogger GetLogger() { return Log; } public int GetPlayerEntityID() { return playerEntityID; } public List GetLoadedChatBots() { return new List(bots); } + public void GetCookie(string key, out byte[]? data) => Cookies.TryGetValue(key, out data); + public void SetCookie(string key, byte[] data) => Cookies[key] = data; readonly TcpClient client; readonly IMinecraftCom handler; diff --git a/MinecraftClient/Program.cs b/MinecraftClient/Program.cs index 80137cff..c70d7c31 100644 --- a/MinecraftClient/Program.cs +++ b/MinecraftClient/Program.cs @@ -46,7 +46,7 @@ namespace MinecraftClient public const string Version = MCHighestVersion; public const string MCLowestVersion = "1.4.6"; - public const string MCHighestVersion = "1.20.4"; + public const string MCHighestVersion = "1.20.6"; public static readonly string? BuildInfo = null; private static Tuple? offlinePrompt = null; diff --git a/MinecraftClient/Protocol/Handlers/ConfigurationPacketTypesIn.cs b/MinecraftClient/Protocol/Handlers/ConfigurationPacketTypesIn.cs index c9ca6e59..f6add9cf 100644 --- a/MinecraftClient/Protocol/Handlers/ConfigurationPacketTypesIn.cs +++ b/MinecraftClient/Protocol/Handlers/ConfigurationPacketTypesIn.cs @@ -2,16 +2,21 @@ namespace MinecraftClient.Protocol.Handlers; public enum ConfigurationPacketTypesIn { - PluginMessage, + CookieRequest, Disconnect, + FeatureFlags, FinishConfiguration, KeepAlive, + KnownDataPacks, Ping, + PluginMessage, RegistryData, - ResourcePack, RemoveResourcePack, - FeatureFlags, + ResetChat, + ResourcePack, + StoreCookie, + Transfer, UpdateTags, Unknown -} \ No newline at end of file +} diff --git a/MinecraftClient/Protocol/Handlers/ConfigurationPacketTypesOut.cs b/MinecraftClient/Protocol/Handlers/ConfigurationPacketTypesOut.cs index f951a38d..32a99ec2 100644 --- a/MinecraftClient/Protocol/Handlers/ConfigurationPacketTypesOut.cs +++ b/MinecraftClient/Protocol/Handlers/ConfigurationPacketTypesOut.cs @@ -8,6 +8,8 @@ public enum ConfigurationPacketTypesOut KeepAlive, Pong, ResourcePackResponse, + CookieResponse, + KnownDataPacks, Unknown } \ No newline at end of file diff --git a/MinecraftClient/Protocol/Handlers/PacketPalettes/PacketPalette1206.cs b/MinecraftClient/Protocol/Handlers/PacketPalettes/PacketPalette1206.cs new file mode 100644 index 00000000..2a5abce5 --- /dev/null +++ b/MinecraftClient/Protocol/Handlers/PacketPalettes/PacketPalette1206.cs @@ -0,0 +1,230 @@ +using System.Collections.Generic; + +namespace MinecraftClient.Protocol.Handlers.PacketPalettes; + +public class PacketPalette1206 : PacketTypePalette + { + private readonly Dictionary typeIn = new() + { + { 0x00, PacketTypesIn.Bundle }, // Added in 1.19.4 + { 0x01, PacketTypesIn.SpawnEntity }, // Changed in 1.19 (Wiki name: Spawn Entity) + { 0x02, PacketTypesIn.SpawnExperienceOrb }, // (Wiki name: Spawn Exeprience Orb) + { 0x03, PacketTypesIn.EntityAnimation }, // (Wiki name: Entity Animation (clientbound)) + { 0x04, PacketTypesIn.Statistics }, // (Wiki name: Award Statistics) + { 0x05, PacketTypesIn.BlockChangedAck }, // Added 1.19 (Wiki name: Acknowledge Block Change) + { 0x06, PacketTypesIn.BlockBreakAnimation }, // (Wiki name: Set Block Destroy Stage) + { 0x07, PacketTypesIn.BlockEntityData }, // + { 0x08, PacketTypesIn.BlockAction }, // + { 0x09, PacketTypesIn.BlockChange }, // (Wiki name: Block Update) + { 0x0A, PacketTypesIn.BossBar }, // + { 0x0B, PacketTypesIn.ServerDifficulty }, // (Wiki name: Change Difficulty) + { 0x0C, PacketTypesIn.ChunkBatchFinished }, // Added in 1.20.2 + { 0x0D, PacketTypesIn.ChunkBatchStarted }, // Added in 1.20.2 + { 0x0E, PacketTypesIn.ChunksBiomes }, // Added in 1.19.4 + { 0x0F, PacketTypesIn.ClearTiles }, // + { 0x10, PacketTypesIn.TabComplete }, // (Wiki name: Command Suggestions Response) + { 0x11, PacketTypesIn.DeclareCommands }, // (Wiki name: Commands) + { 0x12, PacketTypesIn.CloseWindow }, // (Wiki name: Close Container (clientbound)) + { 0x13, PacketTypesIn.WindowItems }, // (Wiki name: Set Container Content) + { 0x14, PacketTypesIn.WindowProperty }, // (Wiki name: Set Container Property) + { 0x15, PacketTypesIn.SetSlot }, // (Wiki name: Set Container Slot) + { 0x16, PacketTypesIn.CookieRequest }, // Added in 1.20.6 + { 0x17, PacketTypesIn.SetCooldown }, // + { 0x18, PacketTypesIn.ChatSuggestions }, // Added in 1.19.1 + { 0x19, PacketTypesIn.PluginMessage }, // (Wiki name: Plugin Message (clientbound)) + { 0x1A, PacketTypesIn.DamageEvent }, // Added in 1.19.4 + { 0x1B, PacketTypesIn.DebugSample }, // Added in 1.20.6 + { 0x1C, PacketTypesIn.HideMessage }, // Added in 1.19.1 + { 0x1D, PacketTypesIn.Disconnect }, // + { 0x1E, PacketTypesIn.ProfilelessChatMessage }, // Added in 1.19.3 (Wiki name: Disguised Chat Message) + { 0x1F, PacketTypesIn.EntityStatus }, // (Wiki name: Entity Event) + { 0x20, PacketTypesIn.Explosion }, // Changed in 1.19 (Location fields are now Double instead of Float) (Wiki name: Explosion) + { 0x21, PacketTypesIn.UnloadChunk }, // (Wiki name: Forget Chunk) + { 0x22, PacketTypesIn.ChangeGameState }, // (Wiki name: Game Event) + { 0x23, PacketTypesIn.OpenHorseWindow }, // (Wiki name: Horse Screen Open) + { 0x24, PacketTypesIn.HurtAnimation }, // Added in 1.19.4 + { 0x25, PacketTypesIn.InitializeWorldBorder }, // + { 0x26, PacketTypesIn.KeepAlive }, // + { 0x27, PacketTypesIn.ChunkData }, // + { 0x28, PacketTypesIn.Effect }, // (Wiki name: World Event) + { 0x29, PacketTypesIn.Particle }, // Changed in 1.19 (Wiki name: Level Particle) (No need to be implemented) + { 0x2A, PacketTypesIn.UpdateLight }, // (Wiki name: Light Update) + { 0x2B, PacketTypesIn.JoinGame }, // Changed in 1.20.2 (Wiki name: Login (play)) + { 0x2C, PacketTypesIn.MapData }, // (Wiki name: Map Item Data) + { 0x2D, PacketTypesIn.TradeList }, // (Wiki name: Merchant Offers) + { 0x2E, PacketTypesIn.EntityPosition }, // (Wiki name: Move Entity Position) + { 0x2F, PacketTypesIn.EntityPositionAndRotation }, // (Wiki name: Move Entity Position and Rotation) + { 0x30, PacketTypesIn.EntityRotation }, // (Wiki name: Move Entity Rotation) + { 0x31, PacketTypesIn.VehicleMove }, // (Wiki name: Move Vehicle) + { 0x32, PacketTypesIn.OpenBook }, // + { 0x33, PacketTypesIn.OpenWindow }, // (Wiki name: Open Screen) + { 0x34, PacketTypesIn.OpenSignEditor }, // + { 0x35, PacketTypesIn.Ping }, // (Wiki name: Ping (play)) + { 0x36, PacketTypesIn.PingResponse }, // Added in 1.20.2 + { 0x37, PacketTypesIn.CraftRecipeResponse }, // (Wiki name: Place Ghost Recipe) + { 0x38, PacketTypesIn.PlayerAbilities }, // + { 0x39, PacketTypesIn.ChatMessage }, // Changed in 1.19 (Completely changed) (Wiki name: Player Chat Message) + { 0x3A, PacketTypesIn.EndCombatEvent }, // (Wiki name: End Combat) + { 0x3B, PacketTypesIn.EnterCombatEvent }, // (Wiki name: Enter Combat) + { 0x3C, PacketTypesIn.DeathCombatEvent }, // (Wiki name: Combat Death) + { 0x3D, PacketTypesIn.PlayerRemove }, // Added in 1.19.3 (Not used) + { 0x3E, PacketTypesIn.PlayerInfo }, // Changed in 1.19 (Heavy changes) + { 0x3F, PacketTypesIn.FacePlayer }, // (Wiki name: Player Look At) + { 0x40, PacketTypesIn.PlayerPositionAndLook }, // (Wiki name: Synchronize Player Position) + { 0x41, PacketTypesIn.UnlockRecipes }, // (Wiki name: Update Recipe Book) + { 0x42, PacketTypesIn.DestroyEntities }, // (Wiki name: Remove Entites) + { 0x43, PacketTypesIn.RemoveEntityEffect }, // + { 0x44, PacketTypesIn.ResetScore }, // Added in 1.20.3 + { 0x45, PacketTypesIn.RemoveResourcePack }, // Added in 1.20.3 + { 0x46, PacketTypesIn.ResourcePackSend }, // (Wiki name: Add Resource pack (play)) + { 0x47, PacketTypesIn.Respawn }, // Changed in 1.20.2 + { 0x48, PacketTypesIn.EntityHeadLook }, // (Wiki name: Set Head Rotation) + { 0x49, PacketTypesIn.MultiBlockChange }, // (Wiki name: Update Section Blocks) + { 0x4A, PacketTypesIn.SelectAdvancementTab }, // + { 0x4B, PacketTypesIn.ServerData }, // Added in 1.19 + { 0x4C, PacketTypesIn.ActionBar }, // (Wiki name: Set Action Bar Text) + { 0x4D, PacketTypesIn.WorldBorderCenter }, // (Wiki name: Set Border Center) + { 0x4E, PacketTypesIn.WorldBorderLerpSize }, // + { 0x4F, PacketTypesIn.WorldBorderSize }, // (Wiki name: Set World Border Size) + { 0x50, PacketTypesIn.WorldBorderWarningDelay }, // (Wiki name: Set World Border Warning Delay) + { 0x51, PacketTypesIn.WorldBorderWarningReach }, // (Wiki name: Set Border Warning Distance) + { 0x52, PacketTypesIn.Camera }, // (Wiki name: Set Camera) + { 0x53, PacketTypesIn.HeldItemChange }, // (Wiki name: Set Held Item) + { 0x54, PacketTypesIn.UpdateViewPosition }, // (Wiki name: Set Center Chunk) + { 0x55, PacketTypesIn.UpdateViewDistance }, // (Wiki name: Set Render Distance) + { 0x56, PacketTypesIn.SpawnPosition }, // (Wiki name: Set Default Spawn Position) + { 0x57, PacketTypesIn.DisplayScoreboard }, // (Wiki name: Set Display Objective) + { 0x58, PacketTypesIn.EntityMetadata }, // (Wiki name: Set Entity Metadata) + { 0x59, PacketTypesIn.AttachEntity }, // (Wiki name: Link Entities) + { 0x5A, PacketTypesIn.EntityVelocity }, // (Wiki name: Set Entity Velocity) + { 0x5B, PacketTypesIn.EntityEquipment }, // (Wiki name: Set Equipment) + { 0x5C, PacketTypesIn.SetExperience }, // Changed in 1.20.2 + { 0x5D, PacketTypesIn.UpdateHealth }, // (Wiki name: Set Health) + { 0x5E, PacketTypesIn.ScoreboardObjective }, // (Wiki name: Update Objectives) - Changed in 1.20.3 + { 0x5F, PacketTypesIn.SetPassengers }, // + { 0x60, PacketTypesIn.Teams }, // (Wiki name: Update Teams) + { 0x61, PacketTypesIn.UpdateScore }, // (Wiki name: Update Score) + { 0x62, PacketTypesIn.UpdateSimulationDistance }, // (Wiki name: Set Simulation Distance) + { 0x63, PacketTypesIn.SetTitleSubTitle }, // (Wiki name: Set Subtitle Test) + { 0x64, PacketTypesIn.TimeUpdate }, // (Wiki name: Set Time) + { 0x65, PacketTypesIn.SetTitleText }, // (Wiki name: Set Title) + { 0x66, PacketTypesIn.SetTitleTime }, // (Wiki name: Set Title Animation Times) + { 0x67, PacketTypesIn.EntitySoundEffect }, // (Wiki name: Sound Entity) + { 0x68, PacketTypesIn.SoundEffect }, // Changed in 1.19 (Added "Seed" field) (Wiki name: Sound Effect) (No need to be implemented) + { 0x69, PacketTypesIn.StartConfiguration }, // Added in 1.20.2 + { 0x6A, PacketTypesIn.StopSound }, // + { 0x6B, PacketTypesIn.StoreCookie }, // Added in 1.20.6 + { 0x6C, PacketTypesIn.SystemChat }, // Added in 1.19 (Wiki name: System Chat Message) + { 0x6D, PacketTypesIn.PlayerListHeaderAndFooter }, // (Wiki name: Set Tab List Header And Footer) + { 0x6E, PacketTypesIn.NBTQueryResponse }, // (Wiki name: Tag Query Response) + { 0x6F, PacketTypesIn.CollectItem }, // (Wiki name: Pickup Item) + { 0x70, PacketTypesIn.EntityTeleport }, // (Wiki name: Teleport Entity) + { 0x71, PacketTypesIn.SetTickingState }, // Added in 1.20.3 + { 0x72, PacketTypesIn.StepTick }, // Added in 1.20.3 + { 0x73, PacketTypesIn.Transfer }, // Added in 1.20.6 + { 0x74, PacketTypesIn.Advancements }, // (Wiki name: Update Advancements) (Unused) + { 0x75, PacketTypesIn.EntityProperties }, // (Wiki name: Update Attributes) + { 0x76, PacketTypesIn.EntityEffect }, // Changed in 1.19 (Added "Has Factor Data" and "Factor Codec" fields) (Wiki name: Entity Effect) + { 0x77, PacketTypesIn.DeclareRecipes }, // (Wiki name: Update Recipes) (Unused) + { 0x78, PacketTypesIn.Tags }, // (Wiki name: Update Tags) + { 0x79, PacketTypesIn.ProjectilePower }, // Added in 1.20.6 + }; + + private readonly Dictionary typeOut = new() + { + { 0x00, PacketTypesOut.TeleportConfirm }, // (Wiki name: Confirm Teleportation) + { 0x01, PacketTypesOut.QueryBlockNBT }, // (Wiki name: Query Block Entity Tag) + { 0x02, PacketTypesOut.SetDifficulty }, // (Wiki name: Change Difficulty) + { 0x03, PacketTypesOut.MessageAcknowledgment }, // Added in 1.19.1 + { 0x04, PacketTypesOut.ChatCommand }, // Added in 1.19 + { 0x05, PacketTypesOut.SignedChatCommand }, // Added in 1.20.6 + { 0x06, PacketTypesOut.ChatMessage }, // Changed in 1.19 (Completely changed) (Wiki name: Chat) + { 0x07, PacketTypesOut.PlayerSession }, // Added in 1.19.3 + { 0x08, PacketTypesOut.ChunkBatchReceived }, // Added in 1.20.2 + { 0x09, PacketTypesOut.ClientStatus }, // (Wiki name: Client Command) + { 0x0A, PacketTypesOut.ClientSettings }, // (Wiki name: Client Information) + { 0x0B, PacketTypesOut.TabComplete }, // (Wiki name: Command Suggestions Request) + { 0x0C, PacketTypesOut.AcknowledgeConfiguration }, // Added in 1.20.2 + { 0x0D, PacketTypesOut.ClickWindowButton }, // (Wiki name: Click Container Button) + { 0x0E, PacketTypesOut.ClickWindow }, // (Wiki name: Click Container) + { 0x0F, PacketTypesOut.CloseWindow }, // (Wiki name: Close Container (serverbound)) + { 0x10, PacketTypesOut.ChangeContainerSlotState }, // Added in 1.20.3 + { 0x11, PacketTypesOut.CookieResponse }, // Added in 1.20.6 + { 0x12, PacketTypesOut.PluginMessage }, // (Wiki name: Serverbound Plugin Message) + { 0x13, PacketTypesOut.DebugSampleSubscription }, // Added in 1.20.6 + { 0x14, PacketTypesOut.EditBook }, // + { 0x15, PacketTypesOut.EntityNBTRequest }, // (Wiki name: Query Entity Tag) + { 0x16, PacketTypesOut.InteractEntity }, // (Wiki name: Interact) + { 0x17, PacketTypesOut.GenerateStructure }, // (Wiki name: Jigsaw Generate) + { 0x18, PacketTypesOut.KeepAlive }, // (Wiki name: Serverbound Keep Alive (play)) + { 0x19, PacketTypesOut.LockDifficulty }, // + { 0x1A, PacketTypesOut.PlayerPosition }, // (Wiki name: Move Player Position) + { 0x1B, PacketTypesOut.PlayerPositionAndRotation }, // (Wiki name: Set Player Position and Rotation) + { 0x1C, PacketTypesOut.PlayerRotation }, // (Wiki name: Set Player Rotation) + { 0x1D, PacketTypesOut.PlayerMovement }, // (Wiki name: Set Player On Ground) + { 0x1E, PacketTypesOut.VehicleMove }, // (Wiki name: Move Vehicle (serverbound)) + { 0x1F, PacketTypesOut.SteerBoat }, // (Wiki name: Paddle Boat) + { 0x20, PacketTypesOut.PickItem }, // + { 0x21, PacketTypesOut.PingRequest }, // Added in 1.20.2 + { 0x22, PacketTypesOut.CraftRecipeRequest }, // (Wiki name: Place recipe) + { 0x23, PacketTypesOut.PlayerAbilities }, // + { 0x24, PacketTypesOut.PlayerDigging }, // Changed in 1.19 (Added a "Sequence" field) (Wiki name: Player Action) + { 0x25, PacketTypesOut.EntityAction }, // (Wiki name: Player Command) + { 0x26, PacketTypesOut.SteerVehicle }, // (Wiki name: Player Input) + { 0x27, PacketTypesOut.Pong }, // (Wiki name: Pong (play)) + { 0x28, PacketTypesOut.SetDisplayedRecipe }, // (Wiki name: Recipe Book Change Settings) + { 0x29, PacketTypesOut.SetRecipeBookState }, // (Wiki name: Recipe Book Seen Recipe) + { 0x2A, PacketTypesOut.NameItem }, // (Wiki name: Rename Item) + { 0x2B, PacketTypesOut.ResourcePackStatus }, // (Wiki name: Resource Pack (serverbound)) + { 0x2C, PacketTypesOut.AdvancementTab }, // (Wiki name: Seen Advancements) + { 0x2D, PacketTypesOut.SelectTrade }, // + { 0x2E, PacketTypesOut.SetBeaconEffect }, // Changed in 1.19 (No need to be implemented yet) + { 0x2F, PacketTypesOut.HeldItemChange }, // (Wiki name: Set Carried Item (serverbound)) + { 0x30, PacketTypesOut.UpdateCommandBlock }, // (Wiki name: Program Command Block) + { 0x31, PacketTypesOut.UpdateCommandBlockMinecart }, // (Wiki name: Program Command Block Minecart) + { 0x32, PacketTypesOut.CreativeInventoryAction }, // (Wiki name: Set Creative Mode Slot) + { 0x33, PacketTypesOut.UpdateJigsawBlock }, // (Wiki name: Program Jigsaw Block) + { 0x34, PacketTypesOut.UpdateStructureBlock }, // (Wiki name: Program Structure Block) + { 0x35, PacketTypesOut.UpdateSign }, // (Wiki name: Update Sign) + { 0x36, PacketTypesOut.Animation }, // (Wiki name: Swing Arm) + { 0x37, PacketTypesOut.Spectate }, // (Wiki name: Teleport To Entity) + { 0x38, PacketTypesOut.PlayerBlockPlacement }, // Changed in 1.19 (Added a "Sequence" field) (Wiki name: Use Item On) + { 0x39, PacketTypesOut.UseItem }, // Changed in 1.19 (Added a "Sequence" field) (Wiki name: Use Item) + }; + + private readonly Dictionary configurationTypesIn = new() + { + { 0x00, ConfigurationPacketTypesIn.CookieRequest }, + { 0x01, ConfigurationPacketTypesIn.PluginMessage }, + { 0x02, ConfigurationPacketTypesIn.Disconnect }, + { 0x03, ConfigurationPacketTypesIn.FinishConfiguration }, + { 0x04, ConfigurationPacketTypesIn.KeepAlive }, + { 0x05, ConfigurationPacketTypesIn.Ping }, + { 0x06, ConfigurationPacketTypesIn.ResetChat }, + { 0x07, ConfigurationPacketTypesIn.RegistryData }, + { 0x08, ConfigurationPacketTypesIn.RemoveResourcePack }, + { 0x09, ConfigurationPacketTypesIn.ResourcePack }, + { 0x0A, ConfigurationPacketTypesIn.StoreCookie }, + { 0x0B, ConfigurationPacketTypesIn.Transfer }, + { 0x0C, ConfigurationPacketTypesIn.FeatureFlags }, + { 0x0D, ConfigurationPacketTypesIn.UpdateTags }, + { 0x0E, ConfigurationPacketTypesIn.KnownDataPacks } + }; + + private readonly Dictionary configurationTypesOut = new() + { + { 0x00, ConfigurationPacketTypesOut.ClientInformation }, + { 0x01, ConfigurationPacketTypesOut.CookieResponse }, + { 0x02, ConfigurationPacketTypesOut.PluginMessage }, + { 0x03, ConfigurationPacketTypesOut.FinishConfiguration }, + { 0x04, ConfigurationPacketTypesOut.KeepAlive }, + { 0x05, ConfigurationPacketTypesOut.Pong }, + { 0x06, ConfigurationPacketTypesOut.ResourcePackResponse }, + { 0x07, ConfigurationPacketTypesOut.KnownDataPacks } + }; + + protected override Dictionary GetListIn() => typeIn; + protected override Dictionary GetListOut() => typeOut; + protected override Dictionary GetConfigurationListIn() => configurationTypesIn!; + protected override Dictionary GetConfigurationListOut() => configurationTypesOut!; + } \ No newline at end of file diff --git a/MinecraftClient/Protocol/Handlers/PacketType18Handler.cs b/MinecraftClient/Protocol/Handlers/PacketType18Handler.cs index e012f853..5deac47b 100644 --- a/MinecraftClient/Protocol/Handlers/PacketType18Handler.cs +++ b/MinecraftClient/Protocol/Handlers/PacketType18Handler.cs @@ -48,7 +48,7 @@ namespace MinecraftClient.Protocol.Handlers { PacketTypePalette p = protocol switch { - > Protocol18Handler.MC_1_20_4_Version => throw new NotImplementedException(Translations + > Protocol18Handler.MC_1_20_6_Version => throw new NotImplementedException(Translations .exception_palette_packet), <= Protocol18Handler.MC_1_8_Version => new PacketPalette17(), <= Protocol18Handler.MC_1_11_2_Version => new PacketPalette110(), @@ -67,7 +67,8 @@ namespace MinecraftClient.Protocol.Handlers <= Protocol18Handler.MC_1_19_4_Version => new PacketPalette1194(), <= Protocol18Handler.MC_1_20_Version => new PacketPalette1194(), <= Protocol18Handler.MC_1_20_2_Version => new PacketPalette1202(), - _ => new PacketPalette1204() + <= Protocol18Handler.MC_1_20_4_Version => new PacketPalette1204(), + _ => new PacketPalette1206() }; p.SetForgeEnabled(forgeEnabled); diff --git a/MinecraftClient/Protocol/Handlers/PacketTypesIn.cs b/MinecraftClient/Protocol/Handlers/PacketTypesIn.cs index b4b8debc..9eab7b39 100644 --- a/MinecraftClient/Protocol/Handlers/PacketTypesIn.cs +++ b/MinecraftClient/Protocol/Handlers/PacketTypesIn.cs @@ -29,9 +29,11 @@ CloseWindow, // CollectItem, // CombatEvent, // + CookieRequest, // Added in 1.20.6 CraftRecipeResponse, // DamageEvent, // Added in 1.19.4 DeathCombatEvent, // + DebugSample, // Added in 1.20.6 DeclareCommands, // DeclareRecipes, // DestroyEntities, // @@ -83,6 +85,7 @@ PlayerPositionAndLook, // PluginMessage, // ProfilelessChatMessage, // Added in 1.19.3 + ProjectilePower, // Added in 1.20.6 RemoveEntityEffect, // RemoveResourcePack, // Added in 1.20.3 ResetScore, // Added in 1.20.3 @@ -115,6 +118,7 @@ StartConfiguration, // Added in 1.20.2 Statistics, // StopSound, // + StoreCookie, // Added in 1.20.6 SystemChat, // Added in 1.19 TabComplete, // Tags, // @@ -122,6 +126,7 @@ TimeUpdate, // Title, // TradeList, // + Transfer, // Added in 1.20.6 Unknown, // For old version packet that have been removed and not used by mcc UnloadChunk, // UnlockRecipes, // diff --git a/MinecraftClient/Protocol/Handlers/PacketTypesOut.cs b/MinecraftClient/Protocol/Handlers/PacketTypesOut.cs index 61221968..1149a71f 100644 --- a/MinecraftClient/Protocol/Handlers/PacketTypesOut.cs +++ b/MinecraftClient/Protocol/Handlers/PacketTypesOut.cs @@ -20,6 +20,8 @@ CloseWindow, // CraftRecipeRequest, // CreativeInventoryAction, // + CookieResponse, // Added in 1.20.6 + DebugSampleSubscription, // Added in 1.20.6 EditBook, // EnchantItem, // For 1.13.2 or below EntityAction, // @@ -28,6 +30,7 @@ HeldItemChange, // InteractEntity, // KeepAlive, // + KnownDataPacks, // Added in 1.20.6 LockDifficulty, // MessageAcknowledgment, // Added in 1.19.1 (1.19.2) NameItem, // @@ -52,6 +55,7 @@ SetDifficulty, // SetDisplayedRecipe, // Added in 1.16.2 SetRecipeBookState, // Added in 1.16.2 + SignedChatCommand, // Added in 1.20.6 Spectate, // SteerBoat, // SteerVehicle, // diff --git a/MinecraftClient/Protocol/Handlers/Protocol16.cs b/MinecraftClient/Protocol/Handlers/Protocol16.cs index e4faf0bf..969d5e11 100644 --- a/MinecraftClient/Protocol/Handlers/Protocol16.cs +++ b/MinecraftClient/Protocol/Handlers/Protocol16.cs @@ -236,6 +236,16 @@ namespace MinecraftClient.Protocol.Handlers return netRead != null ? netRead.Item1.ManagedThreadId : -1; } + public bool SendCookieResponse(string name, byte[]? data) + { + throw new NotImplementedException(); + } + + public bool SendKnownDataPacks(List<(string, string, string)> knownDataPacks) + { + throw new NotImplementedException(); + } + public void Dispose() { try diff --git a/MinecraftClient/Protocol/Handlers/Protocol18.cs b/MinecraftClient/Protocol/Handlers/Protocol18.cs index 43962bb3..43a45030 100644 --- a/MinecraftClient/Protocol/Handlers/Protocol18.cs +++ b/MinecraftClient/Protocol/Handlers/Protocol18.cs @@ -70,6 +70,7 @@ namespace MinecraftClient.Protocol.Handlers internal const int MC_1_20_Version = 763; internal const int MC_1_20_2_Version = 764; internal const int MC_1_20_4_Version = 765; + internal const int MC_1_20_6_Version = 766; private int compression_treshold = 0; private int autocomplete_transaction_id = 0; @@ -391,8 +392,16 @@ namespace MinecraftClient.Protocol.Handlers List responseData = new(); var understood = pForge.HandleLoginPluginRequest(channel, packetData, ref responseData); SendLoginPluginResponse(messageId, understood, responseData.ToArray()); - return understood; + break; + // Cookie Request + case 0x05: + var cookieName = dataTypes.ReadNextString(packetData); + var cookieData = null as byte[]; + McClient.Instance?.GetCookie(cookieName, out cookieData); + SendCookieResponse(cookieName, cookieData); + break; + // Ignore other packets at this stage default: return true; @@ -404,6 +413,13 @@ namespace MinecraftClient.Protocol.Handlers case CurrentState.Configuration: switch (packetPalette.GetIncomingConfigurationTypeById(packetId)) { + case ConfigurationPacketTypesIn.CookieRequest: + var cookieName = dataTypes.ReadNextString(packetData); + var cookieData = null as byte[]; + McClient.Instance?.GetCookie(cookieName, out cookieData); + SendCookieResponse(cookieName, cookieData); + break; + case ConfigurationPacketTypesIn.Disconnect: handler.OnConnectionLost(ChatBot.DisconnectReason.InGameKick, dataTypes.ReadNextChat(packetData)); @@ -423,11 +439,48 @@ namespace MinecraftClient.Protocol.Handlers break; case ConfigurationPacketTypesIn.RegistryData: - var registryCodec = dataTypes.ReadNextNbt(packetData); - ChatParser.ReadChatType(registryCodec); + if (protocolVersion < MC_1_20_6_Version) + { + var registryCodec = dataTypes.ReadNextNbt(packetData); + ChatParser.ReadChatType(registryCodec); - if (handler.GetTerrainEnabled()) - World.StoreDimensionList(registryCodec); + if (handler.GetTerrainEnabled()) + World.StoreDimensionList(registryCodec); + } + else + { + var registryId = dataTypes.ReadNextString(packetData); + var entryCount = dataTypes.ReadNextVarInt(packetData); + + // Ignore other registries to save on time, we need only these 2 + if(registryId is not ("minecraft:dimension_type" or "minecraft:chat_type")) + break; + + var avaliableChats = new Dictionary(); + var dimensionType = new Dictionary(); + + for (var i = 0; i < entryCount; i++) + { + var entryId = dataTypes.ReadNextString(packetData); + var hasData = dataTypes.ReadNextBool(packetData); + + if (hasData) + { + dataTypes.ReadNextNbt(packetData); // Never seem to be sent because hasData is always false + } + + if (registryId == "minecraft:chat_type") + avaliableChats.Add(i, entryId); + else dimensionType.Add(i, entryId); + } + + if (registryId == "minecraft:chat_type") + ChatParser.ReadChatType(avaliableChats); + else + { + // TODO: 1.20.6 Somehow store this data from dimensionType in the World class + } + } break; @@ -439,6 +492,35 @@ namespace MinecraftClient.Protocol.Handlers case ConfigurationPacketTypesIn.ResourcePack: HandleResourcePackPacket(packetData); break; + + case ConfigurationPacketTypesIn.StoreCookie: + var name = dataTypes.ReadNextString(packetData); + var data = dataTypes.ReadNextByteArray(packetData); + McClient.Instance?.SetCookie(name, data); + break; + + case ConfigurationPacketTypesIn.Transfer: + var host = dataTypes.ReadNextString(packetData); + var port = dataTypes.ReadNextVarInt(packetData); + + // TODO: 1.20.6 Implement Host Chaging in the McClient class + // McClient.Instance?.Transfer(host, port); + break; + + case ConfigurationPacketTypesIn.KnownDataPacks: + var knownPacksCount = dataTypes.ReadNextVarInt(packetData); + List<(string, string, string)> knownDataPacks = new(); + + for (var i = 0; i < knownPacksCount; i++) + { + var nameSpace = dataTypes.ReadNextString(packetData); + var id = dataTypes.ReadNextString(packetData); + var version = dataTypes.ReadNextString(packetData); + knownDataPacks.Add((nameSpace, id, version)); + } + + SendKnownDataPacks(knownDataPacks); + break; // Ignore other packets at this stage default: @@ -574,7 +656,7 @@ namespace MinecraftClient.Protocol.Handlers { var registryCodec = dataTypes.ReadNextNbt( - packetData); // Registry Codec (Dimension Codec) - 1.16 and above + packetData); // Registry Codec (Dimension Codec) - 1.16 - 1.20.1 if (protocolVersion >= MC_1_19_Version) ChatParser.ReadChatType(registryCodec); if (handler.GetTerrainEnabled()) @@ -591,6 +673,7 @@ namespace MinecraftClient.Protocol.Handlers // varInt: [1.9.1 to 1.15.2] // byte: below 1.9.1 string? dimensionTypeName = null; + int? dimensionTypeInt2 = null; Dictionary? dimensionType = null; switch (protocolVersion) { @@ -598,6 +681,9 @@ namespace MinecraftClient.Protocol.Handlers { switch (protocolVersion) { + case >= MC_1_20_6_Version: + dimensionTypeInt2 = dataTypes.ReadNextVarInt(packetData); + break; case >= MC_1_19_Version: dimensionTypeName = dataTypes.ReadNextString(packetData); // Dimension Type: Identifier @@ -642,9 +728,12 @@ namespace MinecraftClient.Protocol.Handlers World.StoreOneDimension(dimensionName, dimensionType!); World.SetDimension(dimensionName); break; - default: + case < MC_1_20_6_Version: World.SetDimension(dimensionTypeName!); break; + case >= MC_1_20_6_Version: + // TODO: 1.20.6 Set the dimension (use dimensionTypeInt) + break; } } @@ -713,6 +802,9 @@ namespace MinecraftClient.Protocol.Handlers } dataTypes.ReadNextVarInt(packetData); // Portal Cooldown + + if (protocolVersion >= MC_1_20_6_Version) + dataTypes.ReadNextBool(packetData); // Enforoces Secure Chat } break; case PacketTypesIn.SpawnPainting: // Just skip, no need for this @@ -1105,7 +1197,7 @@ namespace MinecraftClient.Protocol.Handlers }; } - // TODO: Write a function to use this data ? But seems not too useful + // Maybe write a function to use this data ? But seems not too useful } break; @@ -1148,10 +1240,15 @@ namespace MinecraftClient.Protocol.Handlers case PacketTypesIn.Respawn: string? dimensionTypeNameRespawn = null; Dictionary? dimensionTypeRespawn = null; + int? dimensionTypeInt = null; + if (protocolVersion >= MC_1_16_Version) { switch (protocolVersion) { + case >= MC_1_20_6_Version: + dimensionTypeInt = dataTypes.ReadNextVarInt(packetData); + break; case >= MC_1_19_Version: dimensionTypeNameRespawn = dataTypes.ReadNextString(packetData); // Dimension Type: Identifier @@ -1189,9 +1286,12 @@ namespace MinecraftClient.Protocol.Handlers World.StoreOneDimension(dimensionName, dimensionTypeRespawn!); World.SetDimension(dimensionName); break; - case >= MC_1_19_Version: + case < MC_1_20_6_Version: World.SetDimension(dimensionTypeNameRespawn!); break; + case >= MC_1_20_6_Version: + // TODO: 1.20.6 Set the dimension (use dimensionTypeInt) + break; } } @@ -2262,7 +2362,7 @@ namespace MinecraftClient.Protocol.Handlers var hasFactorData = false; Dictionary? factorCodec = null; - if (protocolVersion >= MC_1_19_Version) + if (protocolVersion >= MC_1_19_Version && protocolVersion < MC_1_20_6_Version) { hasFactorData = dataTypes.ReadNextBool(packetData); if (hasFactorData) @@ -2642,6 +2742,27 @@ namespace MinecraftClient.Protocol.Handlers dataTypes.ReadNextBool(packetData); break; + case PacketTypesIn.CookieRequest: + var cookieName = dataTypes.ReadNextString(packetData); + var cookieData = null as byte[]; + McClient.Instance?.GetCookie(cookieName, out cookieData); + SendCookieResponse(cookieName, cookieData); + break; + + case PacketTypesIn.StoreCookie: + var cookieName2 = dataTypes.ReadNextString(packetData); + var cookieData2 = dataTypes.ReadNextByteArray(packetData); + McClient.Instance?.SetCookie(cookieName2, cookieData2); + break; + + case PacketTypesIn.Transfer: + var host = dataTypes.ReadNextString(packetData); + var port = dataTypes.ReadNextVarInt(packetData); + + // TODO: 1.20.6 Implement Host Chaging in the McClient class + // McClient.Instance?.Transfer(host, port); + break; + default: return false; //Ignored packet } @@ -2845,9 +2966,15 @@ namespace MinecraftClient.Protocol.Handlers var serverId = dataTypes.ReadNextString(packetData); var serverPublicKey = dataTypes.ReadNextByteArray(packetData); var token = dataTypes.ReadNextByteArray(packetData); + + var shouldAuthetnicate = false; + + if (protocolVersion >= MC_1_20_6_Version) + shouldAuthetnicate = dataTypes.ReadNextBool(packetData); + return StartEncryption(handler.GetUserUuidStr(), handler.GetSessionID(), Config.Main.General.AccountType, token, serverId, - serverPublicKey, playerKeyPair, session); + serverPublicKey, playerKeyPair, session, shouldAuthetnicate); } // Login successful @@ -2882,7 +3009,7 @@ namespace MinecraftClient.Protocol.Handlers /// /// True if encryption was successful private bool StartEncryption(string uuid, string sessionID, LoginType type, byte[] token, string serverIDhash, - byte[] serverPublicKey, PlayerKeyPair? playerKeyPair, SessionToken session) + byte[] serverPublicKey, PlayerKeyPair? playerKeyPair, SessionToken session, bool shouldAuthetnicate) { var RSAService = CryptoHandler.DecodeRSAPublicKey(serverPublicKey)!; var secretKey = CryptoHandler.ClientAESPrivateKey ?? CryptoHandler.GenerateAESPrivateKey(); @@ -2902,6 +3029,10 @@ namespace MinecraftClient.Protocol.Handlers if (session.SessionPreCheckTask.Result) // PreCheck Success needCheckSession = false; } + + // 1.20.6++ + if (shouldAuthetnicate) + needCheckSession = true; if (needCheckSession) { @@ -2971,6 +3102,7 @@ namespace MinecraftClient.Protocol.Handlers handler.OnConnectionLost(ChatBot.DisconnectReason.LoginRejected, ChatParser.ParseText(dataTypes.ReadNextString(packetData))); return false; + //Login successful case 0x02: { @@ -2993,6 +3125,10 @@ namespace MinecraftClient.Protocol.Handlers } } + // Strict Error Handling (Ignored) + if (protocolVersion >= MC_1_20_6_Version) + dataTypes.ReadNextBool(packetData); + currentState = protocolVersion < MC_1_20_2_Version ? CurrentState.Play : CurrentState.Configuration; @@ -4538,7 +4674,90 @@ namespace MinecraftClient.Protocol.Handlers return false; } } + + public bool SendCookieResponse(string name, byte[]? data) + { + try + { + var packet = new List(); + var hasPayload = data is not null; + packet.AddRange(dataTypes.GetString(name)); // Identifier + packet.AddRange(dataTypes.GetBool(hasPayload)); // Has payload + + if (hasPayload) + packet.AddRange(dataTypes.GetArray(data!)); // Payload Data Array Size + Data Array + switch(currentState) + { + case CurrentState.Login: + SendPacket(0x04, packet); + break; + + case CurrentState.Configuration: + SendPacket(ConfigurationPacketTypesOut.CookieResponse, packet); + break; + + case CurrentState.Play: + SendPacket(PacketTypesOut.CookieResponse, packet); + break; + } + + return true; + } + catch (SocketException) + { + return false; + } + catch (System.IO.IOException) + { + return false; + } + catch (ObjectDisposedException) + { + return false; + } + } + + public bool SendKnownDataPacks(List<(string, string, string)> knownDataPacks) + { + try + { + var packet = new List(); + packet.AddRange(DataTypes.GetVarInt(knownDataPacks.Count)); // Known Packs Count + foreach (var dataPack in knownDataPacks) + { + packet.AddRange(dataTypes.GetString(dataPack.Item1)); + packet.AddRange(dataTypes.GetString(dataPack.Item2)); + packet.AddRange(dataTypes.GetString(dataPack.Item3)); + } + + switch(currentState) + { + case CurrentState.Configuration: + SendPacket(ConfigurationPacketTypesOut.KnownDataPacks, packet); + break; + + case CurrentState.Play: + SendPacket(PacketTypesOut.KnownDataPacks, packet); + break; + } + + return true; + } + catch (SocketException) + { + return false; + } + catch (System.IO.IOException) + { + return false; + } + catch (ObjectDisposedException) + { + return false; + } + } + private byte[] GenerateSalt() { var salt = new byte[8]; @@ -4559,6 +4778,7 @@ namespace MinecraftClient.Protocol.Handlers { Login = 0, Configuration, - Play + Play, + Transfer } } \ No newline at end of file diff --git a/MinecraftClient/Protocol/IMinecraftCom.cs b/MinecraftClient/Protocol/IMinecraftCom.cs index eb5d03ed..12cdee09 100644 --- a/MinecraftClient/Protocol/IMinecraftCom.cs +++ b/MinecraftClient/Protocol/IMinecraftCom.cs @@ -273,5 +273,18 @@ namespace MinecraftClient.Protocol /// /// Net read thread ID int GetNetMainThreadId(); + + /// + /// Send the server a requested cookie + /// + /// The cookie identifier/name + /// The cookie data byte array + bool SendCookieResponse(string name, byte[]? data); + + /// + /// Send the server known data packs + /// + /// The clist of tuples containing info about the kown data packs (namespace, id, version) + bool SendKnownDataPacks(List<(string, string, string)> knownDataPacks); } } diff --git a/MinecraftClient/Protocol/IMinecraftComHandler.cs b/MinecraftClient/Protocol/IMinecraftComHandler.cs index 138913ec..d6033e9b 100644 --- a/MinecraftClient/Protocol/IMinecraftComHandler.cs +++ b/MinecraftClient/Protocol/IMinecraftComHandler.cs @@ -44,7 +44,9 @@ namespace MinecraftClient.Protocol int GetProtocolVersion(); Container? GetInventory(int inventoryID); ILogger GetLogger(); - + void GetCookie(string key, out byte[]? data); + void SetCookie(string key, byte[] data); + /// /// Invoke a task on the main thread, wait for completion and retrieve return value. /// diff --git a/MinecraftClient/Protocol/Message/ChatParser.cs b/MinecraftClient/Protocol/Message/ChatParser.cs index 5bfd2b66..b540e3b6 100644 --- a/MinecraftClient/Protocol/Message/ChatParser.cs +++ b/MinecraftClient/Protocol/Message/ChatParser.cs @@ -31,9 +31,32 @@ namespace MinecraftClient.Protocol.Message public static Dictionary? ChatId2Type; + // Used to store Chat Types in 1.20.6+ + public static void ReadChatType(Dictionary data) + { + var chatTypeDictionary = ChatId2Type ?? new Dictionary(); + + foreach (var (chatId, chatName) in data) + { + chatTypeDictionary[chatId] = chatName switch + { + "minecraft:chat" => MessageType.CHAT, + "minecraft:emote_command" => MessageType.EMOTE_COMMAND, + "minecraft:msg_command_incoming" => MessageType.MSG_COMMAND_INCOMING, + "minecraft:msg_command_outgoing" => MessageType.MSG_COMMAND_OUTGOING, + "minecraft:say_command" => MessageType.SAY_COMMAND, + "minecraft:team_msg_command_incoming" => MessageType.TEAM_MSG_COMMAND_INCOMING, + "minecraft:team_msg_command_outgoing" => MessageType.TEAM_MSG_COMMAND_OUTGOING, + _ => MessageType.CHAT, + }; + } + + ChatId2Type = chatTypeDictionary; + } + public static void ReadChatType(Dictionary registryCodec) { - Dictionary chatTypeDictionary = ChatId2Type ?? new(); + var chatTypeDictionary = ChatId2Type ?? new Dictionary(); var chatTypeListNbt = (object[])(((Dictionary)registryCodec["minecraft:chat_type"])["value"]); foreach (var (chatName, chatId) in from Dictionary chatTypeNbt in chatTypeListNbt diff --git a/MinecraftClient/Protocol/ProtocolHandler.cs b/MinecraftClient/Protocol/ProtocolHandler.cs index cbf1b1cd..a2ea85b5 100644 --- a/MinecraftClient/Protocol/ProtocolHandler.cs +++ b/MinecraftClient/Protocol/ProtocolHandler.cs @@ -153,7 +153,7 @@ namespace MinecraftClient.Protocol int[] suppoertedVersionsProtocol18 = { 4, 5, 47, 107, 108, 109, 110, 210, 315, 316, 335, 338, 340, 393, 401, 404, 477, 480, 485, 490, 498, 573, - 575, 578, 735, 736, 751, 753, 754, 755, 756, 757, 758, 759, 760, 761, 762, 763, 764, 765 + 575, 578, 735, 736, 751, 753, 754, 755, 756, 757, 758, 759, 760, 761, 762, 763, 764, 765, 766 }; if (Array.IndexOf(suppoertedVersionsProtocol18, protocolVersion) > -1) @@ -345,6 +345,9 @@ namespace MinecraftClient.Protocol case "1.20.3": case "1.20.4": return 765; + case "1.20.5": + case "1.20.6": + return 766; default: return 0; } @@ -424,6 +427,7 @@ namespace MinecraftClient.Protocol 763 => "1.20", 764 => "1.20.2", 765 => "1.20.4", + 766 => "1.20.6", _ => "0.0" }; }