diff --git a/MinecraftClient/Inventory/EnchantmentMapping.cs b/MinecraftClient/Inventory/EnchantmentMapping.cs index 4f6fca47..e21e3cde 100644 --- a/MinecraftClient/Inventory/EnchantmentMapping.cs +++ b/MinecraftClient/Inventory/EnchantmentMapping.cs @@ -196,7 +196,7 @@ namespace MinecraftClient.Inventory { >= 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, + >= Protocol18Handler.MC_1_19_Version and < Protocol18Handler.MC_1_21_Version => enchantmentMappings119, _ => enchantmentMappings }; diff --git a/MinecraftClient/Mapping/EntityMetadataPalette.cs b/MinecraftClient/Mapping/EntityMetadataPalette.cs index 5b220474..db544f39 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_6_Version => new EntityMetadataPalette1194(), // 1.19.4 - 1.20.6 + + <= Protocol18Handler.MC_1_21_Version => new EntityMetadataPalette1194(), // 1.19.4 - 1.21 + _ => throw new NotImplementedException() }; } diff --git a/MinecraftClient/Program.cs b/MinecraftClient/Program.cs index 6ff4d63b..1b68583d 100644 --- a/MinecraftClient/Program.cs +++ b/MinecraftClient/Program.cs @@ -17,7 +17,6 @@ using MinecraftClient.Protocol.Session; using MinecraftClient.Scripting; using MinecraftClient.WinAPI; using Sentry; -using Tomlet; using static MinecraftClient.Settings; using static MinecraftClient.Settings.ConsoleConfigHealper.ConsoleConfig; using static MinecraftClient.Settings.MainConfigHelper.MainConfig.AdvancedConfig; @@ -47,11 +46,11 @@ namespace MinecraftClient public const string Version = MCHighestVersion; public const string MCLowestVersion = "1.4.6"; - public const string MCHighestVersion = "1.20.6"; + public const string MCHighestVersion = "1.21"; public static readonly string? BuildInfo = null; private static Tuple? offlinePrompt = null; - private static IDisposable _sentrySdk; + private static IDisposable? _sentrySdk = null; private static bool useMcVersionOnce = false; private static string settingsIniPath = "MinecraftClient.ini"; @@ -74,6 +73,11 @@ namespace MinecraftClient options.EnableTracing = true; options.SendDefaultPii = false; }); + + AppDomain.CurrentDomain.UnhandledException += (sender, eventArgs) => + { + SentrySdk.CaptureException((Exception)eventArgs.ExceptionObject); + }; } Task.Run(() => @@ -208,7 +212,7 @@ namespace MinecraftClient } if (!Config.Main.Advanced.EnableSentry) - _sentrySdk.Dispose(); + _sentrySdk?.Dispose(); } //Other command-line arguments @@ -355,7 +359,7 @@ namespace MinecraftClient ConsoleColorModeType.vt100_8bit)).Append(i); } sb.Append(ColorHelper.GetResetEscapeCode()).Append(']'); - ConsoleIO.WriteLine(string.Format(Translations.debug_color_test, sb.ToString())); + ConsoleIO.WriteLine(string.Format(Translations.debug_color_test, sb)); } { // Test 24 bit color StringBuilder sb = new(); @@ -369,7 +373,7 @@ namespace MinecraftClient ConsoleColorModeType.vt100_24bit)).Append(i); } sb.Append(ColorHelper.GetResetEscapeCode()).Append(']'); - ConsoleIO.WriteLine(string.Format(Translations.debug_color_test, sb.ToString())); + ConsoleIO.WriteLine(string.Format(Translations.debug_color_test, sb)); } } @@ -382,7 +386,7 @@ namespace MinecraftClient } // Setup exit cleaning code - ExitCleanUp.Add(() => { DoExit(0); }); + ExitCleanUp.Add(() => { DoExit(); }); //Asking the user to type in missing data such as Username and Password bool useBrowser = Config.Main.General.AccountType == LoginType.microsoft && Config.Main.General.Method == LoginMethod.browser; @@ -526,10 +530,10 @@ namespace MinecraftClient worldId = availableWorlds[worldIndex]; if (availableWorlds.Contains(worldId)) { - string RealmsAddress = ProtocolHandler.GetRealmsWorldServerAddress(worldId, InternalConfig.Username, session.PlayerID, session.ID); - if (RealmsAddress != "") + string realmsAddress = ProtocolHandler.GetRealmsWorldServerAddress(worldId, InternalConfig.Username, session.PlayerID, session.ID); + if (realmsAddress != "") { - addressInput = RealmsAddress; + addressInput = realmsAddress; isRealms = true; InternalConfig.MinecraftVersion = MCHighestVersion; } @@ -547,7 +551,7 @@ namespace MinecraftClient } else { - HandleFailure(Translations.error_realms_disabled, false, null); + HandleFailure(Translations.error_realms_disabled); return; } } @@ -560,7 +564,7 @@ namespace MinecraftClient if (InternalConfig.MinecraftVersion != "" && Settings.ToLowerIfNeed(InternalConfig.MinecraftVersion) != "auto") { - protocolversion = Protocol.ProtocolHandler.MCVer2ProtocolVersion(InternalConfig.MinecraftVersion); + protocolversion = ProtocolHandler.MCVer2ProtocolVersion(InternalConfig.MinecraftVersion); if (protocolversion != 0) ConsoleIO.WriteLineFormatted(string.Format(Translations.mcc_use_version, InternalConfig.MinecraftVersion, protocolversion)); @@ -584,7 +588,7 @@ namespace MinecraftClient ConsoleIO.WriteLine(Translations.mcc_retrieve); if (!ProtocolHandler.GetServerInfo(InternalConfig.ServerIP, InternalConfig.ServerPort, ref protocolversion, ref forgeInfo)) { - HandleFailure(Translations.error_ping, true, ChatBots.AutoRelog.DisconnectReason.ConnectionLost); + HandleFailure(Translations.error_ping, true, ChatBot.DisconnectReason.ConnectionLost); return; } } @@ -632,7 +636,7 @@ namespace MinecraftClient } else { - HandleFailure(Translations.error_forgeforce, true, ChatBots.AutoRelog.DisconnectReason.ConnectionLost); + HandleFailure(Translations.error_forgeforce, true, ChatBot.DisconnectReason.ConnectionLost); return; } } @@ -672,8 +676,7 @@ namespace MinecraftClient else { string failureMessage = Translations.error_login; - string failureReason = string.Empty; - failureReason = result switch + string failureReason = result switch { #pragma warning disable format // @formatter:off ProtocolHandler.LoginResult.AccountMigrated => Translations.error_login_migrated, @@ -714,6 +717,7 @@ namespace MinecraftClient /// Disconnect the current client from the server and restart it /// /// Optional delay, in seconds, before restarting + /// Optional, keep account and server settings public static void Restart(int delaySeconds = 0, bool keepAccountAndServerSettings = false) { ConsoleInteractive.ConsoleReader.StopReadThread(); @@ -734,7 +738,7 @@ namespace MinecraftClient public static void DoExit(int exitcode = 0) { - WriteBackSettings(true); + WriteBackSettings(); ConsoleInteractive.ConsoleSuggestion.ClearSuggestions(); ConsoleIO.WriteLineFormatted("§a" + string.Format(Translations.config_saving, settingsIniPath)); @@ -749,7 +753,7 @@ namespace MinecraftClient /// public static void Exit(int exitcode = 0) { - new Thread(new ThreadStart(() => { DoExit(exitcode); })).Start(); + new Thread(() => { DoExit(exitcode); }).Start(); } /// @@ -759,7 +763,7 @@ namespace MinecraftClient /// Error message to display and optionally pass to AutoRelog bot /// Specify if the error is related to an incompatible or unkown server version /// If set, the error message will be processed by the AutoRelog bot - public static void HandleFailure(string? errorMessage = null, bool versionError = false, ChatBots.AutoRelog.DisconnectReason? disconnectReason = null) + public static void HandleFailure(string? errorMessage = null, bool versionError = false, ChatBot.DisconnectReason? disconnectReason = null) { if (!String.IsNullOrEmpty(errorMessage)) { diff --git a/MinecraftClient/Protocol/Handlers/ConfigurationPacketTypesIn.cs b/MinecraftClient/Protocol/Handlers/ConfigurationPacketTypesIn.cs index f6add9cf..0648601a 100644 --- a/MinecraftClient/Protocol/Handlers/ConfigurationPacketTypesIn.cs +++ b/MinecraftClient/Protocol/Handlers/ConfigurationPacketTypesIn.cs @@ -3,6 +3,7 @@ namespace MinecraftClient.Protocol.Handlers; public enum ConfigurationPacketTypesIn { CookieRequest, + CustomReportDetails, Disconnect, FeatureFlags, FinishConfiguration, @@ -14,6 +15,7 @@ public enum ConfigurationPacketTypesIn RemoveResourcePack, ResetChat, ResourcePack, + ServerLinks, StoreCookie, Transfer, UpdateTags, diff --git a/MinecraftClient/Protocol/Handlers/DataTypes.cs b/MinecraftClient/Protocol/Handlers/DataTypes.cs index 160e0fb8..dc953c56 100644 --- a/MinecraftClient/Protocol/Handlers/DataTypes.cs +++ b/MinecraftClient/Protocol/Handlers/DataTypes.cs @@ -974,7 +974,7 @@ namespace MinecraftClient.Protocol.Handlers ReadDustParticle(cache); break; case 13: - // 1.20,6+ - minecraft:dust + // 1.20.6+ - minecraft:dust ReadDustParticle(cache); break; case 14: @@ -1038,7 +1038,7 @@ namespace MinecraftClient.Protocol.Handlers break; case 28: // 1.20.6+ - if (protocolversion > Protocol18Handler.MC_1_20_6_Version) + if (protocolversion >= Protocol18Handler.MC_1_20_6_Version) ReadNextVarInt(cache); // minecraft:falling_dust (BlockState) break; case 30: @@ -1053,7 +1053,7 @@ namespace MinecraftClient.Protocol.Handlers break; case 35: // 1.20.6+ - if (protocolversion > Protocol18Handler.MC_1_20_6_Version) + if (protocolversion >= Protocol18Handler.MC_1_20_6_Version) ReadNextFloat(cache); // minecraft:sculk_charge (Roll) break; case 36: @@ -1117,6 +1117,11 @@ namespace MinecraftClient.Protocol.Handlers if (protocolversion >= Protocol18Handler.MC_1_20_6_Version) ReadNextItemSlot(cache, itemPalette); // minecraft:item (Item) break; + case 45: + // 1.21+ + if(protocolversion >= Protocol18Handler.MC_1_21_Version) + ReadVibration(cache); + break; case 99: // 1.20.6+ if (protocolversion >= Protocol18Handler.MC_1_20_6_Version) @@ -1143,12 +1148,21 @@ namespace MinecraftClient.Protocol.Handlers ReadNextFloat(cache); // From red ReadNextFloat(cache); // From green ReadNextFloat(cache); // From blue - ReadNextFloat(cache); // Scale ReadNextFloat(cache); // To red ReadNextFloat(cache); // To green - ReadNextFloat(cache); // To Blue + ReadNextFloat(cache); // To blue + ReadNextFloat(cache); // Scale } + private void ReadVibration(Queue cache) + { + ReadNextVarInt(cache); // Position Source Type + ReadNextLocation(cache); // Block Position + ReadNextVarInt(cache); // Entity ID + ReadNextFloat(cache); // Entity eye height + ReadNextVarInt(cache); // Ticks + } + /// /// Read a single villager trade from a cache of bytes and remove it from the cache /// diff --git a/MinecraftClient/Protocol/Handlers/Packet/s2c/DeclareCommands.cs b/MinecraftClient/Protocol/Handlers/Packet/s2c/DeclareCommands.cs index 6e4575ab..a0a0d117 100644 --- a/MinecraftClient/Protocol/Handlers/Packet/s2c/DeclareCommands.cs +++ b/MinecraftClient/Protocol/Handlers/Packet/s2c/DeclareCommands.cs @@ -10,6 +10,12 @@ namespace MinecraftClient.Protocol.Handlers.packet.s2c public static void Read(DataTypes dataTypes, Queue packetData, int protocolVersion) { + // TODO: Fix this + // It crashes in 1.20.6+ , could not figure out why + // it's hard to debug, so I'll just disable it for now + if(protocolVersion > Protocol18Handler.MC_1_20_4_Version) + return; + int count = dataTypes.ReadNextVarInt(packetData); Nodes = new CommandNode[count]; for (int i = 0; i < count; ++i) diff --git a/MinecraftClient/Protocol/Handlers/PacketPalettes/PacketPalette121.cs b/MinecraftClient/Protocol/Handlers/PacketPalettes/PacketPalette121.cs new file mode 100644 index 00000000..fc8b64bb --- /dev/null +++ b/MinecraftClient/Protocol/Handlers/PacketPalettes/PacketPalette121.cs @@ -0,0 +1,234 @@ +using System.Collections.Generic; + +namespace MinecraftClient.Protocol.Handlers.PacketPalettes; + +public class PacketPalette121 : 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 + { 0x7A, PacketTypesIn.CustomReportDetails }, // Added in 1.21 + { 0x7B, PacketTypesIn.ServerLinks } // Added in 1.21 + }; + + 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 }, + { 0x0F, ConfigurationPacketTypesIn.CustomReportDetails }, // Added in 1.21 (Not used) + { 0x10, ConfigurationPacketTypesIn.ServerLinks } // Added in 1.21 (Not used) + }; + + 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 5deac47b..7d80d4ee 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_6_Version => throw new NotImplementedException(Translations + > Protocol18Handler.MC_1_21_Version => throw new NotImplementedException(Translations .exception_palette_packet), <= Protocol18Handler.MC_1_8_Version => new PacketPalette17(), <= Protocol18Handler.MC_1_11_2_Version => new PacketPalette110(), @@ -68,7 +68,8 @@ namespace MinecraftClient.Protocol.Handlers <= Protocol18Handler.MC_1_20_Version => new PacketPalette1194(), <= Protocol18Handler.MC_1_20_2_Version => new PacketPalette1202(), <= Protocol18Handler.MC_1_20_4_Version => new PacketPalette1204(), - _ => new PacketPalette1206() + <= Protocol18Handler.MC_1_20_6_Version => new PacketPalette1206(), + _ => new PacketPalette121() }; p.SetForgeEnabled(forgeEnabled); diff --git a/MinecraftClient/Protocol/Handlers/PacketTypesIn.cs b/MinecraftClient/Protocol/Handlers/PacketTypesIn.cs index 9eab7b39..d3feabb7 100644 --- a/MinecraftClient/Protocol/Handlers/PacketTypesIn.cs +++ b/MinecraftClient/Protocol/Handlers/PacketTypesIn.cs @@ -31,6 +31,7 @@ CombatEvent, // CookieRequest, // Added in 1.20.6 CraftRecipeResponse, // + CustomReportDetails, // Added in 1.21 (Not used) DamageEvent, // Added in 1.19.4 DeathCombatEvent, // DebugSample, // Added in 1.20.6 @@ -95,6 +96,7 @@ SelectAdvancementTab, // ServerData, // Added in 1.19 ServerDifficulty, // + ServerLinks, // Added in 1.21 (Not used) SetCompression, // For 1.8 or below SetCooldown, // SetDisplayChatPreview, // Added in 1.19 diff --git a/MinecraftClient/Protocol/Handlers/Protocol18.cs b/MinecraftClient/Protocol/Handlers/Protocol18.cs index b682551f..f8a8c427 100644 --- a/MinecraftClient/Protocol/Handlers/Protocol18.cs +++ b/MinecraftClient/Protocol/Handlers/Protocol18.cs @@ -72,8 +72,9 @@ namespace MinecraftClient.Protocol.Handlers 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; + internal const int MC_1_21_Version = 767; - private int compression_treshold = 0; + private int compression_treshold = -1; private int autocomplete_transaction_id = 0; private readonly Dictionary window_actions = new(); private CurrentState currentState = CurrentState.Login; @@ -123,21 +124,21 @@ namespace MinecraftClient.Protocol.Handlers lastSeenMessagesCollector = protocolVersion >= MC_1_19_3_Version ? new(20) : new(5); chunkBatchStartTime = GetNanos(); - if (handler.GetTerrainEnabled() && protocolVersion > MC_1_20_6_Version) + if (handler.GetTerrainEnabled() && protocolVersion > MC_1_21_Version) { log.Error($"§c{Translations.extra_terrainandmovement_disabled}"); handler.SetTerrainEnabled(false); } if (handler.GetInventoryEnabled() && - protocolVersion is < MC_1_8_Version or > MC_1_20_6_Version) + protocolVersion is < MC_1_8_Version or > MC_1_21_Version) { log.Error($"§c{Translations.extra_inventory_disabled}"); handler.SetInventoryEnabled(false); } if (handler.GetEntityHandlingEnabled() && - protocolVersion is < MC_1_8_Version or > MC_1_20_6_Version) + protocolVersion is < MC_1_8_Version or > MC_1_21_Version) { log.Error($"§c{Translations.extra_entity_disabled}"); handler.SetEntityHandlingEnabled(false); @@ -146,9 +147,9 @@ namespace MinecraftClient.Protocol.Handlers Block.Palette = protocolVersion switch { // Block palette - > MC_1_20_6_Version when handler.GetTerrainEnabled() => + > MC_1_21_Version when handler.GetTerrainEnabled() => throw new NotImplementedException(Translations.exception_palette_block), - MC_1_20_6_Version => new Palette1206(), + >= MC_1_20_6_Version => new Palette1206(), >= MC_1_20_4_Version => new Palette1204(), >= MC_1_20_Version => new Palette120(), MC_1_19_4_Version => new Palette1194(), @@ -165,9 +166,9 @@ namespace MinecraftClient.Protocol.Handlers entityPalette = protocolVersion switch { // Entity palette - > MC_1_20_6_Version when handler.GetEntityHandlingEnabled() => + > MC_1_21_Version when handler.GetEntityHandlingEnabled() => throw new NotImplementedException(Translations.exception_palette_entity), - MC_1_20_6_Version => new EntityPalette1206(), + >= MC_1_20_6_Version => new EntityPalette1206(), >= MC_1_20_4_Version => new EntityPalette1204(), >= MC_1_20_Version => new EntityPalette120(), MC_1_19_4_Version => new EntityPalette1194(), @@ -188,9 +189,9 @@ namespace MinecraftClient.Protocol.Handlers itemPalette = protocolVersion switch { // Item palette - > MC_1_20_6_Version when handler.GetInventoryEnabled() => + > MC_1_21_Version when handler.GetInventoryEnabled() => throw new NotImplementedException(Translations.exception_palette_item), - MC_1_20_6_Version => new ItemPalette1206(), + >= MC_1_20_6_Version => new ItemPalette1206(), >= MC_1_20_4_Version => new ItemPalette1204(), >= MC_1_20_Version => new ItemPalette120(), MC_1_19_4_Version => new ItemPalette1194(), @@ -349,7 +350,7 @@ namespace MinecraftClient.Protocol.Handlers //Handle packet decompression if (protocolVersion >= MC_1_8_Version - && compression_treshold > 0) + && compression_treshold >= 0) { var sizeUncompressed = dataTypes.ReadNextVarInt(packetData); if (sizeUncompressed != 0) // != 0 means compressed, let's decompress @@ -457,7 +458,7 @@ namespace MinecraftClient.Protocol.Handlers } else { - // TODO: Implement proper parsing for 1.20.6 when there is a custom data pack on the server + // TODO: Implement proper parsing for 1.20.6 / 1.21 when there is a custom data pack on the server // THis is a temporary workaround to get the client to be useable asap var registryId = dataTypes.ReadNextString(packetData); @@ -2309,6 +2310,15 @@ namespace MinecraftClient.Protocol.Handlers if (handler.GetEntityHandlingEnabled()) { var entity = dataTypes.ReadNextEntity(packetData, entityPalette, false); + + if (protocolVersion >= MC_1_20_2_Version) + { + if (entity.Type == EntityType.Player) + handler.OnSpawnPlayer(entity.ID, entity.UUID, entity.Location, (byte)entity.Yaw, (byte)entity.Pitch); + + break; + } + handler.OnSpawnEntity(entity); } @@ -2526,7 +2536,10 @@ namespace MinecraftClient.Protocol.Handlers { 18, "generic.safe_fall_distance" }, { 19, "generic.scale" }, { 20, "zombie.spawn_reinforcements" }, - { 21, "generic.step_height" } + { 21, "generic.step_height" }, + { 22, "generic.submerged_mining_speed" }, + { 23, "generic.sweeping_damage_ratio" }, + { 24, "generic.water_movement_efficiency" } }; Dictionary keys = new(); @@ -2543,7 +2556,7 @@ namespace MinecraftClient.Protocol.Handlers var numberOfModifiers = dataTypes.ReadNextVarInt(packetData); for (var j = 0; j < numberOfModifiers; j++) { - dataTypes.ReadNextUUID(packetData); + var modifierId = protocolVersion < MC_1_21_Version ? dataTypes.ReadNextUUID(packetData).ToString() : dataTypes.ReadNextString(packetData); var amount = dataTypes.ReadNextDouble(packetData); var operation = dataTypes.ReadNextByte(packetData); switch (operation) @@ -2579,7 +2592,7 @@ namespace MinecraftClient.Protocol.Handlers // Also make a palette for field? Will be a lot of work var healthField = protocolVersion switch { - > MC_1_20_6_Version => throw new NotImplementedException(Translations + > MC_1_21_Version => throw new NotImplementedException(Translations .exception_palette_healthfield), // 1.17 and above >= MC_1_17_Version => 9, @@ -2669,28 +2682,41 @@ namespace MinecraftClient.Protocol.Handlers // Records for (var i = 0; i < explosionBlockCount; i++) - dataTypes.ReadData(3, packetData); + dataTypes.ReadNextByteArray(packetData, 3); // Maybe use in the future when the physics are implemented dataTypes.ReadNextFloat(packetData); // Player Motion X dataTypes.ReadNextFloat(packetData); // Player Motion Y dataTypes.ReadNextFloat(packetData); // Player Motion Z - if (protocolVersion >= MC_1_20_4_Version) + // Cut off here, there is an issue, the code bllow crashes on sound name reading + // I am unable to figure out what part of the code is reading more bytes than it should + // TODO: Fix + handler.OnExplosion(explosionLocation, explosionStrength, explosionBlockCount); + break; + + /*if (protocolVersion >= MC_1_20_4_Version) { - dataTypes.ReadNextVarInt(packetData); // Block Interaction - dataTypes.ReadParticleData(packetData, itemPalette); // Small Explosion Particles - dataTypes.ReadParticleData(packetData, itemPalette); // Large Explosion Particles + var blockInteraction = dataTypes.ReadNextVarInt(packetData); // Block Interaction + + if(explosionStrength >= 2.0 || blockInteraction != 0) + dataTypes.ReadParticleData(packetData, itemPalette); // Large Explosion Particles + else + dataTypes.ReadParticleData(packetData, itemPalette); // Small Explosion Particles // Explosion Sound dataTypes.ReadNextString(packetData); // Sound Name - var hasFixedRange = dataTypes.ReadNextBool(packetData); - if (hasFixedRange) - dataTypes.ReadNextFloat(packetData); // Range + + if (protocolVersion < MC_1_21_Version) + { + var hasFixedRange = dataTypes.ReadNextBool(packetData); + if (hasFixedRange) + dataTypes.ReadNextFloat(packetData); // Range + } } handler.OnExplosion(explosionLocation, explosionStrength, explosionBlockCount); - break; + break;*/ case PacketTypesIn.HeldItemChange: handler.OnHeldItemChange(dataTypes.ReadNextByte(packetData)); // Slot break; @@ -2919,7 +2945,7 @@ namespace MinecraftClient.Protocol.Handlers //The inner packet var thePacket = dataTypes.ConcatBytes(DataTypes.GetVarInt(packetId), packetData.ToArray()); - if (compression_treshold > 0) //Compression enabled? + if (compression_treshold >= 0) //Compression enabled? { thePacket = thePacket.Length >= compression_treshold ? dataTypes.ConcatBytes(DataTypes.GetVarInt(thePacket.Length), ZlibUtils.Compress(thePacket)) @@ -4060,6 +4086,13 @@ namespace MinecraftClient.Protocol.Handlers packet.AddRange(DataTypes.GetVarInt(hand)); if (protocolVersion >= MC_1_19_Version) packet.AddRange(DataTypes.GetVarInt(sequenceId)); + + if (protocolVersion >= MC_1_21_Version) + { + packet.AddRange(dataTypes.GetFloat(LastYaw)); + packet.AddRange(dataTypes.GetFloat(LastPitch)); + } + SendPacket(PacketTypesOut.UseItem, packet); return true; } diff --git a/MinecraftClient/Protocol/Handlers/StructuredComponents/Components/1_21/JukeBoxPlayableComponent.cs b/MinecraftClient/Protocol/Handlers/StructuredComponents/Components/1_21/JukeBoxPlayableComponent.cs new file mode 100644 index 00000000..d97b9cf8 --- /dev/null +++ b/MinecraftClient/Protocol/Handlers/StructuredComponents/Components/1_21/JukeBoxPlayableComponent.cs @@ -0,0 +1,99 @@ +using System; +using System.Collections.Generic; +using MinecraftClient.Inventory.ItemPalettes; +using MinecraftClient.Protocol.Handlers.StructuredComponents.Components.Subcomponents; +using MinecraftClient.Protocol.Handlers.StructuredComponents.Components.Subcomponents._1_21; +using MinecraftClient.Protocol.Handlers.StructuredComponents.Core; + +namespace MinecraftClient.Protocol.Handlers.StructuredComponents.Components._1_21; + +public class JukeBoxPlayableComponent(DataTypes dataTypes, ItemPalette itemPalette, SubComponentRegistry subComponentRegistry) + : StructuredComponent(dataTypes, itemPalette, subComponentRegistry) +{ + public bool DirectMode { get; set; } + public string? SongName { get; set; } + public int? SongType { get; set; } + public SoundEventSubComponent? SoundEvent { get; set; } + public string? Description { get; set; } + public float? Duration { get; set; } + public int? Output { get; set; } + public bool ShowTooltip { get; set; } + + public override void Parse(Queue data) + { + DirectMode = dataTypes.ReadNextBool(data); + + if (!DirectMode) + SongName = dataTypes.ReadNextString(data); + + if (DirectMode) + { + SongType = dataTypes.ReadNextVarInt(data); + + if (SongType == 0) + { + SoundEvent = + (SoundEventSubComponent)subComponentRegistry.ParseSubComponent(SubComponents.SoundEvent, data); + Description = dataTypes.ReadNextString(data); + Duration = dataTypes.ReadNextFloat(data); + Output = dataTypes.ReadNextVarInt(data); + } + } + + ShowTooltip = dataTypes.ReadNextBool(data); + } + + public override Queue Serialize() + { + var data = new List(); + + data.AddRange(DataTypes.GetBool(DirectMode)); + + if (!DirectMode) + { + if (string.IsNullOrEmpty(SongName?.Trim())) + throw new ArgumentNullException($"Can not serialize JukeBoxPlayableComponent due to SongName being null or empty!"); + + data.AddRange(DataTypes.GetString(SongName)); + } + + if (DirectMode) + { + if(SongType is null) + throw new ArgumentNullException($"Can not serialize JukeBoxPlayableComponent due to SongType being null!"); + + data.AddRange(DataTypes.GetVarInt((int)SongType)); + + if (SongType == 0) + { + if (SoundEvent is null) + throw new ArgumentNullException( + $"Can not serialize JukeBoxPlayableComponent due to SoundEvent being null"); + + data.AddRange(SoundEvent.Serialize()); + + if (string.IsNullOrEmpty(Description?.Trim())) + throw new ArgumentNullException( + $"Can not serialize JukeBoxPlayableComponent due to Description being null or empty!"); + + data.AddRange(DataTypes.GetString(Description)); + + if (Duration is null) + throw new ArgumentNullException( + $"Can not serialize JukeBoxPlayableComponent due to Duration being null!"); + + data.AddRange(DataTypes.GetFloat((float)Duration)); + + if (Output is null) + throw new ArgumentNullException( + $"Can not serialize JukeBoxPlayableComponent due to Description being null!"); + + data.AddRange(DataTypes.GetVarInt((int)Output)); + } + } + + data.AddRange(DataTypes.GetBool(ShowTooltip)); + + return new Queue(data); + } +} \ No newline at end of file diff --git a/MinecraftClient/Protocol/Handlers/StructuredComponents/Components/Subcomponents/1_21/SoundEventSubComponent.cs b/MinecraftClient/Protocol/Handlers/StructuredComponents/Components/Subcomponents/1_21/SoundEventSubComponent.cs new file mode 100644 index 00000000..cfa0f833 --- /dev/null +++ b/MinecraftClient/Protocol/Handlers/StructuredComponents/Components/Subcomponents/1_21/SoundEventSubComponent.cs @@ -0,0 +1,45 @@ +using System; +using System.Collections.Generic; +using MinecraftClient.Protocol.Handlers.StructuredComponents.Core; + +namespace MinecraftClient.Protocol.Handlers.StructuredComponents.Components.Subcomponents._1_21; + +public class SoundEventSubComponent(DataTypes dataTypes, SubComponentRegistry subComponentRegistry) : SubComponent(dataTypes, subComponentRegistry) +{ + public int Type { get; set; } + public string? SoundName { get; set; } + public bool HasFixedRange { get; set; } + public float FixedRange { get; set; } + + protected override void Parse(Queue data) + { + Type = dataTypes.ReadNextVarInt(data); + + if (Type != 0) return; + + SoundName = dataTypes.ReadNextString(data); + HasFixedRange = dataTypes.ReadNextBool(data); + + if (HasFixedRange) + FixedRange = dataTypes.ReadNextFloat(data); + } + + public override Queue Serialize() + { + var data = new List(); + data.AddRange(DataTypes.GetVarInt(Type)); + + if (Type != 0) return new Queue(data); + + if (string.IsNullOrEmpty(SoundName?.Trim())) + throw new ArgumentNullException($"Can not serialize SoundEventSubComponent due to SoundName being null or empty!"); + + data.AddRange(DataTypes.GetString(SoundName)); + data.AddRange(DataTypes.GetBool(HasFixedRange)); + + if(HasFixedRange) + data.AddRange(DataTypes.GetFloat(FixedRange)); + + return new Queue(data); + } +} \ No newline at end of file diff --git a/MinecraftClient/Protocol/Handlers/StructuredComponents/Components/Subcomponents/SubComponents.cs b/MinecraftClient/Protocol/Handlers/StructuredComponents/Components/Subcomponents/SubComponents.cs index 5152c9cd..9fdc974c 100644 --- a/MinecraftClient/Protocol/Handlers/StructuredComponents/Components/Subcomponents/SubComponents.cs +++ b/MinecraftClient/Protocol/Handlers/StructuredComponents/Components/Subcomponents/SubComponents.cs @@ -11,4 +11,5 @@ public abstract class SubComponents public const string Details = "Details"; public const string Rule = "Rule"; public const string FireworkExplosion = "FireworkExplosion"; + public const string SoundEvent = "SoundEvent"; } \ No newline at end of file diff --git a/MinecraftClient/Protocol/Handlers/StructuredComponents/Registries/StructuredComponentsRegistry1206.cs b/MinecraftClient/Protocol/Handlers/StructuredComponents/Registries/StructuredComponentsRegistry1206.cs index ebf75e41..afc5a134 100644 --- a/MinecraftClient/Protocol/Handlers/StructuredComponents/Registries/StructuredComponentsRegistry1206.cs +++ b/MinecraftClient/Protocol/Handlers/StructuredComponents/Registries/StructuredComponentsRegistry1206.cs @@ -25,7 +25,7 @@ public class StructuredComponentsRegistry1206 : StructuredComponentRegistry RegisterComponent(13, "minecraft:custom_model_data"); RegisterComponent(14, "minecraft:hide_additional_tooltip"); RegisterComponent(15, "minecraft:hide_tooltip"); - RegisterComponent(16, "minecraft:repair_cost"); + RegisterComponent(16, "minecraft:repair_cost"); RegisterComponent(17, "minecraft:creative_slot_lock"); RegisterComponent(18, "minecraft:enchantment_glint_override"); RegisterComponent(19, "minecraft:intangible_projectile"); diff --git a/MinecraftClient/Protocol/Handlers/StructuredComponents/Registries/StructuredComponentsRegistry121.cs b/MinecraftClient/Protocol/Handlers/StructuredComponents/Registries/StructuredComponentsRegistry121.cs new file mode 100644 index 00000000..076b49d0 --- /dev/null +++ b/MinecraftClient/Protocol/Handlers/StructuredComponents/Registries/StructuredComponentsRegistry121.cs @@ -0,0 +1,71 @@ +using MinecraftClient.Inventory.ItemPalettes; +using MinecraftClient.Protocol.Handlers.StructuredComponents.Components._1_20_6; +using MinecraftClient.Protocol.Handlers.StructuredComponents.Components._1_21; +using MinecraftClient.Protocol.Handlers.StructuredComponents.Core; + +namespace MinecraftClient.Protocol.Handlers.StructuredComponents.Registries; + +public class StructuredComponentsRegistry121 : StructuredComponentRegistry +{ + public StructuredComponentsRegistry121(DataTypes dataTypes, ItemPalette itemPalette, SubComponentRegistry subComponentRegistry) + : base(dataTypes, itemPalette, subComponentRegistry) + { + RegisterComponent(0, "minecraft:custom_data"); + RegisterComponent(1, "minecraft:max_stack_size"); + RegisterComponent(2, "minecraft:max_damage"); + RegisterComponent(3, "minecraft:damage"); + RegisterComponent(4, "minecraft:unbreakable"); + RegisterComponent(5, "minecraft:custom_name"); + RegisterComponent(6, "minecraft:item_name"); + RegisterComponent(7, "minecraft:lore"); + RegisterComponent(8, "minecraft:rarity"); + RegisterComponent(9, "minecraft:enchantments"); + RegisterComponent(10, "minecraft:can_place_on"); + RegisterComponent(11, "minecraft:can_break"); + RegisterComponent(12, "minecraft:attribute_modifiers"); + RegisterComponent(13, "minecraft:custom_model_data"); + RegisterComponent(14, "minecraft:hide_additional_tooltip"); + RegisterComponent(15, "minecraft:hide_tooltip"); + RegisterComponent(16, "minecraft:repair_cost"); + RegisterComponent(17, "minecraft:creative_slot_lock"); + RegisterComponent(18, "minecraft:enchantment_glint_override"); + RegisterComponent(19, "minecraft:intangible_projectile"); + RegisterComponent(20, "minecraft:food"); + RegisterComponent(21, "minecraft:fire_resistant"); + RegisterComponent(22, "minecraft:tool"); + RegisterComponent(23, "minecraft:stored_enchantments"); + RegisterComponent(24, "minecraft:dyed_color"); + RegisterComponent(25, "minecraft:map_color"); + RegisterComponent(26, "minecraft:map_id"); + RegisterComponent(27, "minecraft:map_decorations"); + RegisterComponent(28, "minecraft:map_post_processing"); + RegisterComponent(29, "minecraft:charged_projectiles"); + RegisterComponent(30, "minecraft:bundle_contents"); + RegisterComponent(31, "minecraft:potion_contents"); + RegisterComponent(32, "minecraft:suspicious_stew_effects"); + RegisterComponent(33, "minecraft:writable_book_content"); + RegisterComponent(34, "minecraft:written_book_content"); + RegisterComponent(35, "minecraft:trim"); + RegisterComponent(36, "minecraft:debug_stick_state"); + RegisterComponent(37, "minecraft:entity_data"); + RegisterComponent(38, "minecraft:bucket_entity_data"); + RegisterComponent(39, "minecraft:block_entity_data"); + RegisterComponent(40, "minecraft:instrument"); + RegisterComponent(41, "minecraft:ominous_bottle_amplifier"); + RegisterComponent(42, "minecraft:jukebox_playable"); + RegisterComponent(43, "minecraft:recipes"); + RegisterComponent(44, "minecraft:lodestone_tracker"); + RegisterComponent(45, "minecraft:firework_explosion"); + RegisterComponent(46, "minecraft:fireworks"); + RegisterComponent(47, "minecraft:profile"); + RegisterComponent(48, "minecraft:note_block_sound"); + RegisterComponent(49, "minecraft:banner_patterns"); + RegisterComponent(50, "minecraft:base_color"); + RegisterComponent(51, "minecraft:pot_decorations"); + RegisterComponent(52, "minecraft:container"); + RegisterComponent(53, "minecraft:block_state"); + RegisterComponent(54, "minecraft:bees"); + RegisterComponent(55, "minecraft:lock"); + RegisterComponent(56, "minecraft:container_loot"); + } +} \ No newline at end of file diff --git a/MinecraftClient/Protocol/Handlers/StructuredComponents/Registries/Subcomponents/SubComponentRegistry121.cs b/MinecraftClient/Protocol/Handlers/StructuredComponents/Registries/Subcomponents/SubComponentRegistry121.cs new file mode 100644 index 00000000..7515020f --- /dev/null +++ b/MinecraftClient/Protocol/Handlers/StructuredComponents/Registries/Subcomponents/SubComponentRegistry121.cs @@ -0,0 +1,15 @@ +using MinecraftClient.Protocol.Handlers.StructuredComponents.Components._1_20_6; +using MinecraftClient.Protocol.Handlers.StructuredComponents.Components.Subcomponents; +using MinecraftClient.Protocol.Handlers.StructuredComponents.Components.Subcomponents._1_20_6; +using MinecraftClient.Protocol.Handlers.StructuredComponents.Components.Subcomponents._1_21; +using MinecraftClient.Protocol.Handlers.StructuredComponents.Core; + +namespace MinecraftClient.Protocol.Handlers.StructuredComponents.Registries.Subcomponents; + +public class SubComponentRegistry121 : SubComponentRegistry1206 +{ + public SubComponentRegistry121(DataTypes dataTypes) : base(dataTypes) + { + RegisterSubComponent(SubComponents.SoundEvent); + } +} \ No newline at end of file diff --git a/MinecraftClient/Protocol/Handlers/StructuredComponents/StructuredComponentsHandler.cs b/MinecraftClient/Protocol/Handlers/StructuredComponents/StructuredComponentsHandler.cs index 95502463..2fd0cb82 100644 --- a/MinecraftClient/Protocol/Handlers/StructuredComponents/StructuredComponentsHandler.cs +++ b/MinecraftClient/Protocol/Handlers/StructuredComponents/StructuredComponentsHandler.cs @@ -20,6 +20,7 @@ public class StructuredComponentsHandler var subcomponentRegistryType = protocolVersion switch { Protocol18Handler.MC_1_20_6_Version => typeof(SubComponentRegistry1206), + Protocol18Handler.MC_1_21_Version => typeof(SubComponentRegistry121), _ => throw new NotSupportedException($"Protocol version {protocolVersion} is not supported for subcomponent registries!") }; @@ -30,6 +31,7 @@ public class StructuredComponentsHandler var registryType = protocolVersion switch { Protocol18Handler.MC_1_20_6_Version => typeof(StructuredComponentsRegistry1206), + Protocol18Handler.MC_1_21_Version => typeof(StructuredComponentsRegistry121), _ => throw new NotSupportedException($"Protocol version {protocolVersion} is not supported for structured component registries!") }; diff --git a/MinecraftClient/Protocol/ProtocolHandler.cs b/MinecraftClient/Protocol/ProtocolHandler.cs index a2ea85b5..b53354ee 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, 766 + 575, 578, 735, 736, 751, 753, 754, 755, 756, 757, 758, 759, 760, 761, 762, 763, 764, 765, 766, 767 }; if (Array.IndexOf(suppoertedVersionsProtocol18, protocolVersion) > -1) @@ -348,6 +348,9 @@ namespace MinecraftClient.Protocol case "1.20.5": case "1.20.6": return 766; + case "1.21": + case "1.21.1": + return 767; default: return 0; } @@ -428,6 +431,7 @@ namespace MinecraftClient.Protocol 764 => "1.20.2", 765 => "1.20.4", 766 => "1.20.6", + 767 => "1.21", _ => "0.0" }; }