mirror of
https://github.com/MCCTeam/Minecraft-Console-Client
synced 2026-08-15 13:04:36 +00:00
feat: add packet palette, data components, and protocol fixes for MC 1.21.2
Packet Palette (Phase 2.1): - Create PacketPalette1212.cs with complete ID mapping for protocol 768 (131 clientbound + 60 serverbound play packets, plus config packets) - Add new PacketTypesIn enum values: EntityPositionSync, MoveMinecartAlongTrack, PlayerRotation, RecipeBookAdd/Remove/Settings, SetCursorItem, SetHeldSlot, SetPlayerInventory - Add new PacketTypesOut enum values: BundleItemSelected, ClientTickEnd - Update PacketType18Handler routing for 1.21.2 Data Components (Phase 1.4): - Create StructuredComponentsRegistry1212 with 67 components (was 57 in 1.21) reflecting the new 1.21.2 DataComponents ordering - Implement 11 new component parsers: ConsumableComponent, UseRemainderComponent, UseCooldownComponent, DamageResistantComponent, EnchantableComponent, EquippableComponent, RepairableComponent, GliderComponent, TooltipStyleComponent, DeathProtectionComponent, ItemModelComponent - Create FoodComponent1212 (simplified: nutrition/saturation/canAlwaysEat only; eatSeconds/effects/usingConvertsTo moved to consumable/use_remainder) - Create SubComponentRegistry1212 and route in StructuredComponentsHandler Protocol Fixes: - Fix PlayerPositionAndLook packet for 1.21.2 (new format: teleportId first, added deltaMovement Vec3, flags as Int instead of Byte) - Fix login success packet (remove strictErrorHandling read for >= 1.21.2) - Fix ClientSettings/ClientInformation packet (add particleStatus VarInt) - Add SetHeldSlot as alias for HeldItemChange in packet handler Verified: MCC connects to 1.21.2 vanilla server, stays connected, chat works. Made-with: Cursor
This commit is contained in:
parent
df833ae2a8
commit
57a0dedb33
20 changed files with 953 additions and 33 deletions
|
|
@ -0,0 +1,243 @@
|
|||
using System.Collections.Generic;
|
||||
|
||||
namespace MinecraftClient.Protocol.Handlers.PacketPalettes;
|
||||
|
||||
public class PacketPalette1212 : PacketTypePalette
|
||||
{
|
||||
private readonly Dictionary<int, PacketTypesIn> typeIn = new()
|
||||
{
|
||||
{ 0x00, PacketTypesIn.Bundle }, // Bundle delimiter
|
||||
{ 0x01, PacketTypesIn.SpawnEntity }, // Add Entity
|
||||
{ 0x02, PacketTypesIn.SpawnExperienceOrb }, // Add Experience Orb
|
||||
{ 0x03, PacketTypesIn.EntityAnimation }, // Animate
|
||||
{ 0x04, PacketTypesIn.Statistics }, // Award Stats
|
||||
{ 0x05, PacketTypesIn.BlockChangedAck }, // Block Changed Ack
|
||||
{ 0x06, PacketTypesIn.BlockBreakAnimation }, // Block Destruction
|
||||
{ 0x07, PacketTypesIn.BlockEntityData }, // Block Entity Data
|
||||
{ 0x08, PacketTypesIn.BlockAction }, // Block Event
|
||||
{ 0x09, PacketTypesIn.BlockChange }, // Block Update
|
||||
{ 0x0A, PacketTypesIn.BossBar }, // Boss Event
|
||||
{ 0x0B, PacketTypesIn.ServerDifficulty }, // Change Difficulty
|
||||
{ 0x0C, PacketTypesIn.ChunkBatchFinished }, // Chunk Batch Finished
|
||||
{ 0x0D, PacketTypesIn.ChunkBatchStarted }, // Chunk Batch Start
|
||||
{ 0x0E, PacketTypesIn.ChunksBiomes }, // Chunks Biomes
|
||||
{ 0x0F, PacketTypesIn.ClearTiles }, // Clear Titles
|
||||
{ 0x10, PacketTypesIn.TabComplete }, // Command Suggestions
|
||||
{ 0x11, PacketTypesIn.DeclareCommands }, // Commands
|
||||
{ 0x12, PacketTypesIn.CloseWindow }, // Container Close
|
||||
{ 0x13, PacketTypesIn.WindowItems }, // Container Set Content
|
||||
{ 0x14, PacketTypesIn.WindowProperty }, // Container Set Data
|
||||
{ 0x15, PacketTypesIn.SetSlot }, // Container Set Slot
|
||||
{ 0x16, PacketTypesIn.CookieRequest }, // Cookie Request
|
||||
{ 0x17, PacketTypesIn.SetCooldown }, // Cooldown
|
||||
{ 0x18, PacketTypesIn.ChatSuggestions }, // Custom Chat Completions
|
||||
{ 0x19, PacketTypesIn.PluginMessage }, // Custom Payload
|
||||
{ 0x1A, PacketTypesIn.DamageEvent }, // Damage Event
|
||||
{ 0x1B, PacketTypesIn.DebugSample }, // Debug Sample
|
||||
{ 0x1C, PacketTypesIn.HideMessage }, // Delete Chat
|
||||
{ 0x1D, PacketTypesIn.Disconnect }, // Disconnect
|
||||
{ 0x1E, PacketTypesIn.ProfilelessChatMessage }, // Disguised Chat
|
||||
{ 0x1F, PacketTypesIn.EntityStatus }, // Entity Event
|
||||
{ 0x20, PacketTypesIn.EntityPositionSync }, // Entity Position Sync (new in 1.21.2)
|
||||
{ 0x21, PacketTypesIn.Explosion }, // Explode
|
||||
{ 0x22, PacketTypesIn.UnloadChunk }, // Forget Level Chunk
|
||||
{ 0x23, PacketTypesIn.ChangeGameState }, // Game Event
|
||||
{ 0x24, PacketTypesIn.OpenHorseWindow }, // Horse Screen Open
|
||||
{ 0x25, PacketTypesIn.HurtAnimation }, // Hurt Animation
|
||||
{ 0x26, PacketTypesIn.InitializeWorldBorder }, // Initialize Border
|
||||
{ 0x27, PacketTypesIn.KeepAlive }, // Keep Alive
|
||||
{ 0x28, PacketTypesIn.ChunkData }, // Level Chunk With Light
|
||||
{ 0x29, PacketTypesIn.Effect }, // Level Event
|
||||
{ 0x2A, PacketTypesIn.Particle }, // Level Particles
|
||||
{ 0x2B, PacketTypesIn.UpdateLight }, // Light Update
|
||||
{ 0x2C, PacketTypesIn.JoinGame }, // Login
|
||||
{ 0x2D, PacketTypesIn.MapData }, // Map Item Data
|
||||
{ 0x2E, PacketTypesIn.TradeList }, // Merchant Offers
|
||||
{ 0x2F, PacketTypesIn.EntityPosition }, // Move Entity Pos
|
||||
{ 0x30, PacketTypesIn.EntityPositionAndRotation }, // Move Entity Pos Rot
|
||||
{ 0x31, PacketTypesIn.MoveMinecartAlongTrack }, // Move Minecart Along Track (new in 1.21.2)
|
||||
{ 0x32, PacketTypesIn.EntityRotation }, // Move Entity Rot
|
||||
{ 0x33, PacketTypesIn.VehicleMove }, // Move Vehicle
|
||||
{ 0x34, PacketTypesIn.OpenBook }, // Open Book
|
||||
{ 0x35, PacketTypesIn.OpenWindow }, // Open Screen
|
||||
{ 0x36, PacketTypesIn.OpenSignEditor }, // Open Sign Editor
|
||||
{ 0x37, PacketTypesIn.Ping }, // Ping
|
||||
{ 0x38, PacketTypesIn.PingResponse }, // Pong Response
|
||||
{ 0x39, PacketTypesIn.CraftRecipeResponse }, // Place Ghost Recipe
|
||||
{ 0x3A, PacketTypesIn.PlayerAbilities }, // Player Abilities
|
||||
{ 0x3B, PacketTypesIn.ChatMessage }, // Player Chat
|
||||
{ 0x3C, PacketTypesIn.EndCombatEvent }, // Player Combat End
|
||||
{ 0x3D, PacketTypesIn.EnterCombatEvent }, // Player Combat Enter
|
||||
{ 0x3E, PacketTypesIn.DeathCombatEvent }, // Player Combat Kill
|
||||
{ 0x3F, PacketTypesIn.PlayerRemove }, // Player Info Remove
|
||||
{ 0x40, PacketTypesIn.PlayerInfo }, // Player Info Update
|
||||
{ 0x41, PacketTypesIn.FacePlayer }, // Player Look At
|
||||
{ 0x42, PacketTypesIn.PlayerPositionAndLook }, // Player Position
|
||||
{ 0x43, PacketTypesIn.PlayerRotation }, // Player Rotation (new in 1.21.2)
|
||||
{ 0x44, PacketTypesIn.RecipeBookAdd }, // Recipe Book Add (new in 1.21.2, replaces UnlockRecipes)
|
||||
{ 0x45, PacketTypesIn.RecipeBookRemove }, // Recipe Book Remove (new in 1.21.2)
|
||||
{ 0x46, PacketTypesIn.RecipeBookSettings }, // Recipe Book Settings (new in 1.21.2)
|
||||
{ 0x47, PacketTypesIn.DestroyEntities }, // Remove Entities
|
||||
{ 0x48, PacketTypesIn.RemoveEntityEffect }, // Remove Mob Effect
|
||||
{ 0x49, PacketTypesIn.ResetScore }, // Reset Score
|
||||
{ 0x4A, PacketTypesIn.RemoveResourcePack }, // Resource Pack Pop
|
||||
{ 0x4B, PacketTypesIn.ResourcePackSend }, // Resource Pack Push
|
||||
{ 0x4C, PacketTypesIn.Respawn }, // Respawn
|
||||
{ 0x4D, PacketTypesIn.EntityHeadLook }, // Rotate Head
|
||||
{ 0x4E, PacketTypesIn.MultiBlockChange }, // Section Blocks Update
|
||||
{ 0x4F, PacketTypesIn.SelectAdvancementTab }, // Select Advancements Tab
|
||||
{ 0x50, PacketTypesIn.ServerData }, // Server Data
|
||||
{ 0x51, PacketTypesIn.ActionBar }, // Set Action Bar Text
|
||||
{ 0x52, PacketTypesIn.WorldBorderCenter }, // Set Border Center
|
||||
{ 0x53, PacketTypesIn.WorldBorderLerpSize }, // Set Border Lerp Size
|
||||
{ 0x54, PacketTypesIn.WorldBorderSize }, // Set Border Size
|
||||
{ 0x55, PacketTypesIn.WorldBorderWarningDelay }, // Set Border Warning Delay
|
||||
{ 0x56, PacketTypesIn.WorldBorderWarningReach }, // Set Border Warning Distance
|
||||
{ 0x57, PacketTypesIn.Camera }, // Set Camera
|
||||
{ 0x58, PacketTypesIn.UpdateViewPosition }, // Set Chunk Cache Center
|
||||
{ 0x59, PacketTypesIn.UpdateViewDistance }, // Set Chunk Cache Radius
|
||||
{ 0x5A, PacketTypesIn.SetCursorItem }, // Set Cursor Item (new in 1.21.2)
|
||||
{ 0x5B, PacketTypesIn.SpawnPosition }, // Set Default Spawn Position
|
||||
{ 0x5C, PacketTypesIn.DisplayScoreboard }, // Set Display Objective
|
||||
{ 0x5D, PacketTypesIn.EntityMetadata }, // Set Entity Data
|
||||
{ 0x5E, PacketTypesIn.AttachEntity }, // Set Entity Link
|
||||
{ 0x5F, PacketTypesIn.EntityVelocity }, // Set Entity Motion
|
||||
{ 0x60, PacketTypesIn.EntityEquipment }, // Set Equipment
|
||||
{ 0x61, PacketTypesIn.SetExperience }, // Set Experience
|
||||
{ 0x62, PacketTypesIn.UpdateHealth }, // Set Health
|
||||
{ 0x63, PacketTypesIn.SetHeldSlot }, // Set Held Slot (new in 1.21.2, replaces HeldItemChange)
|
||||
{ 0x64, PacketTypesIn.ScoreboardObjective }, // Set Objective
|
||||
{ 0x65, PacketTypesIn.SetPassengers }, // Set Passengers
|
||||
{ 0x66, PacketTypesIn.SetPlayerInventory }, // Set Player Inventory (new in 1.21.2)
|
||||
{ 0x67, PacketTypesIn.Teams }, // Set Player Team
|
||||
{ 0x68, PacketTypesIn.UpdateScore }, // Set Score
|
||||
{ 0x69, PacketTypesIn.UpdateSimulationDistance }, // Set Simulation Distance
|
||||
{ 0x6A, PacketTypesIn.SetTitleSubTitle }, // Set Subtitle Text
|
||||
{ 0x6B, PacketTypesIn.TimeUpdate }, // Set Time
|
||||
{ 0x6C, PacketTypesIn.SetTitleText }, // Set Title Text
|
||||
{ 0x6D, PacketTypesIn.SetTitleTime }, // Set Titles Animation
|
||||
{ 0x6E, PacketTypesIn.EntitySoundEffect }, // Sound Entity
|
||||
{ 0x6F, PacketTypesIn.SoundEffect }, // Sound
|
||||
{ 0x70, PacketTypesIn.StartConfiguration }, // Start Configuration
|
||||
{ 0x71, PacketTypesIn.StopSound }, // Stop Sound
|
||||
{ 0x72, PacketTypesIn.StoreCookie }, // Store Cookie
|
||||
{ 0x73, PacketTypesIn.SystemChat }, // System Chat
|
||||
{ 0x74, PacketTypesIn.PlayerListHeaderAndFooter }, // Tab List
|
||||
{ 0x75, PacketTypesIn.NBTQueryResponse }, // Tag Query
|
||||
{ 0x76, PacketTypesIn.CollectItem }, // Take Item Entity
|
||||
{ 0x77, PacketTypesIn.EntityTeleport }, // Teleport Entity
|
||||
{ 0x78, PacketTypesIn.SetTickingState }, // Ticking State
|
||||
{ 0x79, PacketTypesIn.StepTick }, // Ticking Step
|
||||
{ 0x7A, PacketTypesIn.Transfer }, // Transfer
|
||||
{ 0x7B, PacketTypesIn.Advancements }, // Update Advancements
|
||||
{ 0x7C, PacketTypesIn.EntityProperties }, // Update Attributes
|
||||
{ 0x7D, PacketTypesIn.EntityEffect }, // Update Mob Effect
|
||||
{ 0x7E, PacketTypesIn.DeclareRecipes }, // Update Recipes
|
||||
{ 0x7F, PacketTypesIn.Tags }, // Update Tags
|
||||
{ 0x80, PacketTypesIn.ProjectilePower }, // Projectile Power
|
||||
{ 0x81, PacketTypesIn.CustomReportDetails }, // Custom Report Details
|
||||
{ 0x82, PacketTypesIn.ServerLinks } // Server Links
|
||||
};
|
||||
|
||||
private readonly Dictionary<int, PacketTypesOut> typeOut = new()
|
||||
{
|
||||
{ 0x00, PacketTypesOut.TeleportConfirm }, // Accept Teleportation
|
||||
{ 0x01, PacketTypesOut.QueryBlockNBT }, // Block Entity Tag Query
|
||||
{ 0x02, PacketTypesOut.BundleItemSelected }, // Bundle Item Selected (new in 1.21.2)
|
||||
{ 0x03, PacketTypesOut.SetDifficulty }, // Change Difficulty
|
||||
{ 0x04, PacketTypesOut.MessageAcknowledgment }, // Chat Ack
|
||||
{ 0x05, PacketTypesOut.ChatCommand }, // Chat Command
|
||||
{ 0x06, PacketTypesOut.SignedChatCommand }, // Chat Command Signed
|
||||
{ 0x07, PacketTypesOut.ChatMessage }, // Chat
|
||||
{ 0x08, PacketTypesOut.PlayerSession }, // Chat Session Update
|
||||
{ 0x09, PacketTypesOut.ChunkBatchReceived }, // Chunk Batch Received
|
||||
{ 0x0A, PacketTypesOut.ClientStatus }, // Client Command
|
||||
{ 0x0B, PacketTypesOut.ClientTickEnd }, // Client Tick End (new in 1.21.2)
|
||||
{ 0x0C, PacketTypesOut.ClientSettings }, // Client Information
|
||||
{ 0x0D, PacketTypesOut.TabComplete }, // Command Suggestion
|
||||
{ 0x0E, PacketTypesOut.AcknowledgeConfiguration }, // Configuration Acknowledged
|
||||
{ 0x0F, PacketTypesOut.ClickWindowButton }, // Container Button Click
|
||||
{ 0x10, PacketTypesOut.ClickWindow }, // Container Click
|
||||
{ 0x11, PacketTypesOut.CloseWindow }, // Container Close
|
||||
{ 0x12, PacketTypesOut.ChangeContainerSlotState }, // Container Slot State Changed
|
||||
{ 0x13, PacketTypesOut.CookieResponse }, // Cookie Response
|
||||
{ 0x14, PacketTypesOut.PluginMessage }, // Custom Payload
|
||||
{ 0x15, PacketTypesOut.DebugSampleSubscription }, // Debug Sample Subscription
|
||||
{ 0x16, PacketTypesOut.EditBook }, // Edit Book
|
||||
{ 0x17, PacketTypesOut.EntityNBTRequest }, // Entity Tag Query
|
||||
{ 0x18, PacketTypesOut.InteractEntity }, // Interact
|
||||
{ 0x19, PacketTypesOut.GenerateStructure }, // Jigsaw Generate
|
||||
{ 0x1A, PacketTypesOut.KeepAlive }, // Keep Alive
|
||||
{ 0x1B, PacketTypesOut.LockDifficulty }, // Lock Difficulty
|
||||
{ 0x1C, PacketTypesOut.PlayerPosition }, // Move Player Pos
|
||||
{ 0x1D, PacketTypesOut.PlayerPositionAndRotation }, // Move Player Pos Rot
|
||||
{ 0x1E, PacketTypesOut.PlayerRotation }, // Move Player Rot
|
||||
{ 0x1F, PacketTypesOut.PlayerMovement }, // Move Player Status Only
|
||||
{ 0x20, PacketTypesOut.VehicleMove }, // Move Vehicle
|
||||
{ 0x21, PacketTypesOut.SteerBoat }, // Paddle Boat
|
||||
{ 0x22, PacketTypesOut.PickItem }, // Pick Item
|
||||
{ 0x23, PacketTypesOut.PingRequest }, // Ping Request
|
||||
{ 0x24, PacketTypesOut.CraftRecipeRequest }, // Place Recipe
|
||||
{ 0x25, PacketTypesOut.PlayerAbilities }, // Player Abilities
|
||||
{ 0x26, PacketTypesOut.PlayerDigging }, // Player Action
|
||||
{ 0x27, PacketTypesOut.EntityAction }, // Player Command
|
||||
{ 0x28, PacketTypesOut.SteerVehicle }, // Player Input
|
||||
{ 0x29, PacketTypesOut.Pong }, // Pong
|
||||
{ 0x2A, PacketTypesOut.SetDisplayedRecipe }, // Recipe Book Change Settings
|
||||
{ 0x2B, PacketTypesOut.SetRecipeBookState }, // Recipe Book Seen Recipe
|
||||
{ 0x2C, PacketTypesOut.NameItem }, // Rename Item
|
||||
{ 0x2D, PacketTypesOut.ResourcePackStatus }, // Resource Pack
|
||||
{ 0x2E, PacketTypesOut.AdvancementTab }, // Seen Advancements
|
||||
{ 0x2F, PacketTypesOut.SelectTrade }, // Select Trade
|
||||
{ 0x30, PacketTypesOut.SetBeaconEffect }, // Set Beacon
|
||||
{ 0x31, PacketTypesOut.HeldItemChange }, // Set Carried Item
|
||||
{ 0x32, PacketTypesOut.UpdateCommandBlock }, // Set Command Block
|
||||
{ 0x33, PacketTypesOut.UpdateCommandBlockMinecart }, // Set Command Minecart
|
||||
{ 0x34, PacketTypesOut.CreativeInventoryAction }, // Set Creative Mode Slot
|
||||
{ 0x35, PacketTypesOut.UpdateJigsawBlock }, // Set Jigsaw Block
|
||||
{ 0x36, PacketTypesOut.UpdateStructureBlock }, // Set Structure Block
|
||||
{ 0x37, PacketTypesOut.UpdateSign }, // Sign Update
|
||||
{ 0x38, PacketTypesOut.Animation }, // Swing
|
||||
{ 0x39, PacketTypesOut.Spectate }, // Teleport To Entity
|
||||
{ 0x3A, PacketTypesOut.PlayerBlockPlacement }, // Use Item On
|
||||
{ 0x3B, PacketTypesOut.UseItem }, // Use Item
|
||||
};
|
||||
|
||||
private readonly Dictionary<int, ConfigurationPacketTypesIn> 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 },
|
||||
{ 0x10, ConfigurationPacketTypesIn.ServerLinks }
|
||||
};
|
||||
|
||||
private readonly Dictionary<int, ConfigurationPacketTypesOut> 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<int, PacketTypesIn> GetListIn() => typeIn;
|
||||
protected override Dictionary<int, PacketTypesOut> GetListOut() => typeOut;
|
||||
protected override Dictionary<int, ConfigurationPacketTypesIn> GetConfigurationListIn() => configurationTypesIn!;
|
||||
protected override Dictionary<int, ConfigurationPacketTypesOut> GetConfigurationListOut() => configurationTypesOut!;
|
||||
}
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
using System;
|
||||
using System;
|
||||
using MinecraftClient.Protocol.Handlers.PacketPalettes;
|
||||
|
||||
namespace MinecraftClient.Protocol.Handlers
|
||||
|
|
@ -48,7 +48,7 @@ namespace MinecraftClient.Protocol.Handlers
|
|||
{
|
||||
PacketTypePalette p = protocol switch
|
||||
{
|
||||
> Protocol18Handler.MC_1_21_Version => throw new NotImplementedException(Translations
|
||||
> Protocol18Handler.MC_1_21_2_Version => throw new NotImplementedException(Translations
|
||||
.exception_palette_packet),
|
||||
<= Protocol18Handler.MC_1_8_Version => new PacketPalette17(),
|
||||
<= Protocol18Handler.MC_1_11_2_Version => new PacketPalette110(),
|
||||
|
|
@ -69,7 +69,8 @@ namespace MinecraftClient.Protocol.Handlers
|
|||
<= Protocol18Handler.MC_1_20_2_Version => new PacketPalette1202(),
|
||||
<= Protocol18Handler.MC_1_20_4_Version => new PacketPalette1204(),
|
||||
<= Protocol18Handler.MC_1_20_6_Version => new PacketPalette1206(),
|
||||
_ => new PacketPalette121()
|
||||
<= Protocol18Handler.MC_1_21_Version => new PacketPalette121(),
|
||||
_ => new PacketPalette1212()
|
||||
};
|
||||
|
||||
p.SetForgeEnabled(forgeEnabled);
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
namespace MinecraftClient.Protocol.Handlers
|
||||
namespace MinecraftClient.Protocol.Handlers
|
||||
{
|
||||
/// <summary>
|
||||
/// Incoming packet types
|
||||
|
|
@ -51,6 +51,7 @@
|
|||
EntityMovement, //
|
||||
EntityPosition, //
|
||||
EntityPositionAndRotation, //
|
||||
EntityPositionSync, // Added in 1.21.2
|
||||
EntityProperties, //
|
||||
EntityRotation, //
|
||||
EntitySoundEffect, //
|
||||
|
|
@ -58,6 +59,7 @@
|
|||
EntityTeleport, //
|
||||
EntityVelocity, //
|
||||
Explosion, //
|
||||
MoveMinecartAlongTrack, // Added in 1.21.2
|
||||
FacePlayer, //
|
||||
FeatureFlags, // Added in 1.19.3
|
||||
HeldItemChange, //
|
||||
|
|
@ -84,6 +86,7 @@
|
|||
PlayerListHeaderAndFooter, //
|
||||
PlayerRemove, // Added in 1.19.3 (Not used)
|
||||
PlayerPositionAndLook, //
|
||||
PlayerRotation, // Added in 1.21.2
|
||||
PluginMessage, //
|
||||
ProfilelessChatMessage, // Added in 1.19.3
|
||||
ProjectilePower, // Added in 1.20.6
|
||||
|
|
@ -92,6 +95,9 @@
|
|||
ResetScore, // Added in 1.20.3
|
||||
ResourcePackSend, //
|
||||
Respawn, //
|
||||
RecipeBookAdd, // Added in 1.21.2 (replaces UnlockRecipes)
|
||||
RecipeBookRemove, // Added in 1.21.2
|
||||
RecipeBookSettings, // Added in 1.21.2
|
||||
ScoreboardObjective, //
|
||||
SelectAdvancementTab, //
|
||||
ServerData, // Added in 1.19
|
||||
|
|
@ -99,9 +105,12 @@
|
|||
ServerLinks, // Added in 1.21 (Not used)
|
||||
SetCompression, // For 1.8 or below
|
||||
SetCooldown, //
|
||||
SetCursorItem, // Added in 1.21.2
|
||||
SetDisplayChatPreview, // Added in 1.19
|
||||
SetExperience, //
|
||||
SetHeldSlot, // Added in 1.21.2 (replaces HeldItemChange clientbound)
|
||||
SetPassengers, //
|
||||
SetPlayerInventory, // Added in 1.21.2
|
||||
SetSlot, //
|
||||
SetTickingState, // Added in 1.20.3
|
||||
StepTick, // Added in 1.20.3
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
namespace MinecraftClient.Protocol.Handlers
|
||||
namespace MinecraftClient.Protocol.Handlers
|
||||
{
|
||||
/// <summary>
|
||||
/// Outgoing packet types
|
||||
|
|
@ -8,6 +8,7 @@
|
|||
AcknowledgeConfiguration, // Added in 1.20.2
|
||||
AdvancementTab, //
|
||||
Animation, //
|
||||
BundleItemSelected, // Added in 1.21.2
|
||||
ChangeContainerSlotState, // Added in 1.20.3
|
||||
ChatCommand, // Added in 1.19
|
||||
ChatMessage, //
|
||||
|
|
@ -17,6 +18,7 @@
|
|||
ClickWindowButton, //
|
||||
ClientSettings, //
|
||||
ClientStatus, //
|
||||
ClientTickEnd, // Added in 1.21.2
|
||||
CloseWindow, //
|
||||
CraftRecipeRequest, //
|
||||
CreativeInventoryAction, //
|
||||
|
|
|
|||
|
|
@ -1411,18 +1411,40 @@ namespace MinecraftClient.Protocol.Handlers
|
|||
break;
|
||||
case PacketTypesIn.PlayerPositionAndLook:
|
||||
{
|
||||
// These always need to be read, since we need the field after them for teleport confirm
|
||||
var location = new Location(
|
||||
dataTypes.ReadNextDouble(packetData), // X
|
||||
dataTypes.ReadNextDouble(packetData), // Y
|
||||
dataTypes.ReadNextDouble(packetData) // Z
|
||||
);
|
||||
int teleportId;
|
||||
Location location;
|
||||
float yaw, pitch;
|
||||
int locMask;
|
||||
|
||||
var yaw = dataTypes.ReadNextFloat(packetData);
|
||||
var pitch = dataTypes.ReadNextFloat(packetData);
|
||||
var locMask = dataTypes.ReadNextByte(packetData);
|
||||
if (protocolVersion >= MC_1_21_2_Version)
|
||||
{
|
||||
teleportId = dataTypes.ReadNextVarInt(packetData);
|
||||
location = new Location(
|
||||
dataTypes.ReadNextDouble(packetData), // X
|
||||
dataTypes.ReadNextDouble(packetData), // Y
|
||||
dataTypes.ReadNextDouble(packetData) // Z
|
||||
);
|
||||
dataTypes.ReadNextDouble(packetData); // Delta X
|
||||
dataTypes.ReadNextDouble(packetData); // Delta Y
|
||||
dataTypes.ReadNextDouble(packetData); // Delta Z
|
||||
yaw = dataTypes.ReadNextFloat(packetData);
|
||||
pitch = dataTypes.ReadNextFloat(packetData);
|
||||
locMask = dataTypes.ReadNextInt(packetData); // Int flags (was Byte before 1.21.2)
|
||||
}
|
||||
else
|
||||
{
|
||||
location = new Location(
|
||||
dataTypes.ReadNextDouble(packetData), // X
|
||||
dataTypes.ReadNextDouble(packetData), // Y
|
||||
dataTypes.ReadNextDouble(packetData) // Z
|
||||
);
|
||||
yaw = dataTypes.ReadNextFloat(packetData);
|
||||
pitch = dataTypes.ReadNextFloat(packetData);
|
||||
locMask = dataTypes.ReadNextByte(packetData);
|
||||
teleportId = protocolVersion >= MC_1_9_Version
|
||||
? dataTypes.ReadNextVarInt(packetData) : -1;
|
||||
}
|
||||
|
||||
// entity handling require player pos for distance calculating
|
||||
if (handler.GetTerrainEnabled() || handler.GetEntityHandlingEnabled())
|
||||
{
|
||||
if (protocolVersion >= MC_1_8_Version)
|
||||
|
|
@ -1434,24 +1456,11 @@ namespace MinecraftClient.Protocol.Handlers
|
|||
}
|
||||
}
|
||||
|
||||
if (protocolVersion >= MC_1_9_Version)
|
||||
if (teleportId >= 0)
|
||||
{
|
||||
var teleportId = dataTypes.ReadNextVarInt(packetData);
|
||||
|
||||
if (teleportId < 0)
|
||||
{
|
||||
yaw = LastYaw;
|
||||
pitch = LastPitch;
|
||||
}
|
||||
else
|
||||
{
|
||||
LastYaw = yaw;
|
||||
LastPitch = pitch;
|
||||
}
|
||||
|
||||
LastYaw = yaw;
|
||||
LastPitch = pitch;
|
||||
handler.UpdateLocation(location, yaw, pitch);
|
||||
|
||||
// Teleport confirm packet
|
||||
SendPacket(PacketTypesOut.TeleportConfirm, DataTypes.GetVarInt(teleportId));
|
||||
|
||||
if (Config.Main.Advanced.TemporaryFixBadpacket)
|
||||
|
|
@ -2723,6 +2732,7 @@ namespace MinecraftClient.Protocol.Handlers
|
|||
handler.OnExplosion(explosionLocation, explosionStrength, explosionBlockCount);
|
||||
break;
|
||||
case PacketTypesIn.HeldItemChange:
|
||||
case PacketTypesIn.SetHeldSlot:
|
||||
handler.OnHeldItemChange(dataTypes.ReadNextByte(packetData)); // Slot
|
||||
break;
|
||||
case PacketTypesIn.ScoreboardObjective:
|
||||
|
|
@ -3251,8 +3261,8 @@ namespace MinecraftClient.Protocol.Handlers
|
|||
}
|
||||
}
|
||||
|
||||
// Strict Error Handling (Ignored)
|
||||
if (protocolVersion >= MC_1_20_6_Version)
|
||||
// Strict Error Handling (removed in 1.21.2)
|
||||
if (protocolVersion >= MC_1_20_6_Version && protocolVersion < MC_1_21_2_Version)
|
||||
dataTypes.ReadNextBool(packetData);
|
||||
|
||||
currentState = protocolVersion < MC_1_20_2_Version
|
||||
|
|
@ -3844,6 +3854,9 @@ namespace MinecraftClient.Protocol.Handlers
|
|||
|
||||
if (protocolVersion >= MC_1_18_1_Version)
|
||||
fields.Add(1); // 1.18 and above - Allow server listings
|
||||
|
||||
if (protocolVersion >= MC_1_21_2_Version)
|
||||
fields.AddRange(DataTypes.GetVarInt(0)); // 1.21.2+ Particle status: 0=All, 1=Decreased, 2=Minimal
|
||||
SendPacket(PacketTypesOut.ClientSettings, fields);
|
||||
}
|
||||
catch (SocketException)
|
||||
|
|
|
|||
|
|
@ -0,0 +1,129 @@
|
|||
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_2;
|
||||
|
||||
public class ConsumableComponent(DataTypes dataTypes, ItemPalette itemPalette, SubComponentRegistry subComponentRegistry)
|
||||
: StructuredComponent(dataTypes, itemPalette, subComponentRegistry)
|
||||
{
|
||||
public float ConsumeSeconds { get; set; }
|
||||
public int Animation { get; set; }
|
||||
public SoundEventSubComponent? Sound { get; set; }
|
||||
public bool HasConsumeParticles { get; set; }
|
||||
public List<ConsumeEffectData> Effects { get; set; } = new();
|
||||
|
||||
public override void Parse(Queue<byte> data)
|
||||
{
|
||||
ConsumeSeconds = dataTypes.ReadNextFloat(data);
|
||||
Animation = dataTypes.ReadNextVarInt(data);
|
||||
Sound = (SoundEventSubComponent)subComponentRegistry.ParseSubComponent(SubComponents.SoundEvent, data);
|
||||
HasConsumeParticles = dataTypes.ReadNextBool(data);
|
||||
|
||||
var effectCount = dataTypes.ReadNextVarInt(data);
|
||||
for (var i = 0; i < effectCount; i++)
|
||||
{
|
||||
var effectTypeId = dataTypes.ReadNextVarInt(data);
|
||||
var effectData = ReadConsumeEffectPayload(effectTypeId, data);
|
||||
Effects.Add(new ConsumeEffectData(effectTypeId, effectData));
|
||||
}
|
||||
}
|
||||
|
||||
private byte[] ReadConsumeEffectPayload(int effectTypeId, Queue<byte> data)
|
||||
{
|
||||
var payload = new List<byte>();
|
||||
switch (effectTypeId)
|
||||
{
|
||||
case 0: // apply_effects: List<MobEffectInstance> + probability(float)
|
||||
var effectCount = dataTypes.ReadNextVarInt(data);
|
||||
payload.AddRange(DataTypes.GetVarInt(effectCount));
|
||||
for (var i = 0; i < effectCount; i++)
|
||||
payload.AddRange(ReadMobEffectInstance(data));
|
||||
payload.AddRange(DataTypes.GetFloat(dataTypes.ReadNextFloat(data)));
|
||||
break;
|
||||
case 1: // remove_effects: HolderSet<MobEffect>
|
||||
payload.AddRange(ReadHolderSet(data));
|
||||
break;
|
||||
case 2: // clear_all_effects: empty
|
||||
break;
|
||||
case 3: // teleport_randomly: float diameter
|
||||
payload.AddRange(DataTypes.GetFloat(dataTypes.ReadNextFloat(data)));
|
||||
break;
|
||||
case 4: // play_sound: Holder<SoundEvent>
|
||||
var sound = (SoundEventSubComponent)subComponentRegistry.ParseSubComponent(SubComponents.SoundEvent, data);
|
||||
payload.AddRange(sound.Serialize());
|
||||
break;
|
||||
}
|
||||
return payload.ToArray();
|
||||
}
|
||||
|
||||
private byte[] ReadMobEffectInstance(Queue<byte> data)
|
||||
{
|
||||
var result = new List<byte>();
|
||||
var effectId = dataTypes.ReadNextVarInt(data);
|
||||
result.AddRange(DataTypes.GetVarInt(effectId));
|
||||
result.AddRange(ReadMobEffectDetails(data));
|
||||
return result.ToArray();
|
||||
}
|
||||
|
||||
private byte[] ReadMobEffectDetails(Queue<byte> data)
|
||||
{
|
||||
var result = new List<byte>();
|
||||
var amplifier = dataTypes.ReadNextVarInt(data);
|
||||
result.AddRange(DataTypes.GetVarInt(amplifier));
|
||||
var duration = dataTypes.ReadNextVarInt(data);
|
||||
result.AddRange(DataTypes.GetVarInt(duration));
|
||||
var ambient = dataTypes.ReadNextBool(data);
|
||||
result.AddRange(DataTypes.GetBool(ambient));
|
||||
var showParticles = dataTypes.ReadNextBool(data);
|
||||
result.AddRange(DataTypes.GetBool(showParticles));
|
||||
var showIcon = dataTypes.ReadNextBool(data);
|
||||
result.AddRange(DataTypes.GetBool(showIcon));
|
||||
var hasHiddenEffect = dataTypes.ReadNextBool(data);
|
||||
result.AddRange(DataTypes.GetBool(hasHiddenEffect));
|
||||
if (hasHiddenEffect)
|
||||
result.AddRange(ReadMobEffectDetails(data));
|
||||
return result.ToArray();
|
||||
}
|
||||
|
||||
private byte[] ReadHolderSet(Queue<byte> data)
|
||||
{
|
||||
var result = new List<byte>();
|
||||
var type = dataTypes.ReadNextVarInt(data);
|
||||
result.AddRange(DataTypes.GetVarInt(type));
|
||||
if (type == 0)
|
||||
{
|
||||
var tagName = dataTypes.ReadNextString(data);
|
||||
result.AddRange(DataTypes.GetString(tagName));
|
||||
}
|
||||
else
|
||||
{
|
||||
for (var i = 0; i < type - 1; i++)
|
||||
{
|
||||
var id = dataTypes.ReadNextVarInt(data);
|
||||
result.AddRange(DataTypes.GetVarInt(id));
|
||||
}
|
||||
}
|
||||
return result.ToArray();
|
||||
}
|
||||
|
||||
public override Queue<byte> Serialize()
|
||||
{
|
||||
var data = new List<byte>();
|
||||
data.AddRange(DataTypes.GetFloat(ConsumeSeconds));
|
||||
data.AddRange(DataTypes.GetVarInt(Animation));
|
||||
if (Sound != null) data.AddRange(Sound.Serialize());
|
||||
data.AddRange(DataTypes.GetBool(HasConsumeParticles));
|
||||
data.AddRange(DataTypes.GetVarInt(Effects.Count));
|
||||
foreach (var effect in Effects)
|
||||
{
|
||||
data.AddRange(DataTypes.GetVarInt(effect.EffectTypeId));
|
||||
data.AddRange(effect.Payload);
|
||||
}
|
||||
return new Queue<byte>(data);
|
||||
}
|
||||
|
||||
public record ConsumeEffectData(int EffectTypeId, byte[] Payload);
|
||||
}
|
||||
|
|
@ -0,0 +1,23 @@
|
|||
using System.Collections.Generic;
|
||||
using MinecraftClient.Inventory.ItemPalettes;
|
||||
using MinecraftClient.Protocol.Handlers.StructuredComponents.Core;
|
||||
|
||||
namespace MinecraftClient.Protocol.Handlers.StructuredComponents.Components._1_21_2;
|
||||
|
||||
public class DamageResistantComponent(DataTypes dataTypes, ItemPalette itemPalette, SubComponentRegistry subComponentRegistry)
|
||||
: StructuredComponent(dataTypes, itemPalette, subComponentRegistry)
|
||||
{
|
||||
public string Types { get; set; } = null!;
|
||||
|
||||
public override void Parse(Queue<byte> data)
|
||||
{
|
||||
Types = dataTypes.ReadNextString(data);
|
||||
}
|
||||
|
||||
public override Queue<byte> Serialize()
|
||||
{
|
||||
var data = new List<byte>();
|
||||
data.AddRange(DataTypes.GetString(Types));
|
||||
return new Queue<byte>(data);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,106 @@
|
|||
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_2;
|
||||
|
||||
public class DeathProtectionComponent(DataTypes dataTypes, ItemPalette itemPalette, SubComponentRegistry subComponentRegistry)
|
||||
: StructuredComponent(dataTypes, itemPalette, subComponentRegistry)
|
||||
{
|
||||
public List<ConsumeEffectData> DeathEffects { get; set; } = new();
|
||||
|
||||
public override void Parse(Queue<byte> data)
|
||||
{
|
||||
var effectCount = dataTypes.ReadNextVarInt(data);
|
||||
for (var i = 0; i < effectCount; i++)
|
||||
{
|
||||
var effectTypeId = dataTypes.ReadNextVarInt(data);
|
||||
var effectData = ReadConsumeEffectPayload(effectTypeId, data);
|
||||
DeathEffects.Add(new ConsumeEffectData(effectTypeId, effectData));
|
||||
}
|
||||
}
|
||||
|
||||
private byte[] ReadConsumeEffectPayload(int effectTypeId, Queue<byte> data)
|
||||
{
|
||||
var payload = new List<byte>();
|
||||
switch (effectTypeId)
|
||||
{
|
||||
case 0: // apply_effects
|
||||
var effectCount = dataTypes.ReadNextVarInt(data);
|
||||
payload.AddRange(DataTypes.GetVarInt(effectCount));
|
||||
for (var i = 0; i < effectCount; i++)
|
||||
payload.AddRange(ReadMobEffectInstance(data));
|
||||
payload.AddRange(DataTypes.GetFloat(dataTypes.ReadNextFloat(data)));
|
||||
break;
|
||||
case 1: // remove_effects
|
||||
payload.AddRange(ReadHolderSet(data));
|
||||
break;
|
||||
case 2: // clear_all_effects
|
||||
break;
|
||||
case 3: // teleport_randomly
|
||||
payload.AddRange(DataTypes.GetFloat(dataTypes.ReadNextFloat(data)));
|
||||
break;
|
||||
case 4: // play_sound
|
||||
var sound = (SoundEventSubComponent)subComponentRegistry.ParseSubComponent(SubComponents.SoundEvent, data);
|
||||
payload.AddRange(sound.Serialize());
|
||||
break;
|
||||
}
|
||||
return payload.ToArray();
|
||||
}
|
||||
|
||||
private byte[] ReadMobEffectInstance(Queue<byte> data)
|
||||
{
|
||||
var result = new List<byte>();
|
||||
result.AddRange(DataTypes.GetVarInt(dataTypes.ReadNextVarInt(data)));
|
||||
result.AddRange(ReadMobEffectDetails(data));
|
||||
return result.ToArray();
|
||||
}
|
||||
|
||||
private byte[] ReadMobEffectDetails(Queue<byte> data)
|
||||
{
|
||||
var result = new List<byte>();
|
||||
result.AddRange(DataTypes.GetVarInt(dataTypes.ReadNextVarInt(data)));
|
||||
result.AddRange(DataTypes.GetVarInt(dataTypes.ReadNextVarInt(data)));
|
||||
result.AddRange(DataTypes.GetBool(dataTypes.ReadNextBool(data)));
|
||||
result.AddRange(DataTypes.GetBool(dataTypes.ReadNextBool(data)));
|
||||
result.AddRange(DataTypes.GetBool(dataTypes.ReadNextBool(data)));
|
||||
var hasHidden = dataTypes.ReadNextBool(data);
|
||||
result.AddRange(DataTypes.GetBool(hasHidden));
|
||||
if (hasHidden)
|
||||
result.AddRange(ReadMobEffectDetails(data));
|
||||
return result.ToArray();
|
||||
}
|
||||
|
||||
private byte[] ReadHolderSet(Queue<byte> data)
|
||||
{
|
||||
var result = new List<byte>();
|
||||
var type = dataTypes.ReadNextVarInt(data);
|
||||
result.AddRange(DataTypes.GetVarInt(type));
|
||||
if (type == 0)
|
||||
{
|
||||
result.AddRange(DataTypes.GetString(dataTypes.ReadNextString(data)));
|
||||
}
|
||||
else
|
||||
{
|
||||
for (var i = 0; i < type - 1; i++)
|
||||
result.AddRange(DataTypes.GetVarInt(dataTypes.ReadNextVarInt(data)));
|
||||
}
|
||||
return result.ToArray();
|
||||
}
|
||||
|
||||
public override Queue<byte> Serialize()
|
||||
{
|
||||
var data = new List<byte>();
|
||||
data.AddRange(DataTypes.GetVarInt(DeathEffects.Count));
|
||||
foreach (var effect in DeathEffects)
|
||||
{
|
||||
data.AddRange(DataTypes.GetVarInt(effect.EffectTypeId));
|
||||
data.AddRange(effect.Payload);
|
||||
}
|
||||
return new Queue<byte>(data);
|
||||
}
|
||||
|
||||
public record ConsumeEffectData(int EffectTypeId, byte[] Payload);
|
||||
}
|
||||
|
|
@ -0,0 +1,23 @@
|
|||
using System.Collections.Generic;
|
||||
using MinecraftClient.Inventory.ItemPalettes;
|
||||
using MinecraftClient.Protocol.Handlers.StructuredComponents.Core;
|
||||
|
||||
namespace MinecraftClient.Protocol.Handlers.StructuredComponents.Components._1_21_2;
|
||||
|
||||
public class EnchantableComponent(DataTypes dataTypes, ItemPalette itemPalette, SubComponentRegistry subComponentRegistry)
|
||||
: StructuredComponent(dataTypes, itemPalette, subComponentRegistry)
|
||||
{
|
||||
public int Value { get; set; }
|
||||
|
||||
public override void Parse(Queue<byte> data)
|
||||
{
|
||||
Value = dataTypes.ReadNextVarInt(data);
|
||||
}
|
||||
|
||||
public override Queue<byte> Serialize()
|
||||
{
|
||||
var data = new List<byte>();
|
||||
data.AddRange(DataTypes.GetVarInt(Value));
|
||||
return new Queue<byte>(data);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,94 @@
|
|||
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_2;
|
||||
|
||||
public class EquippableComponent(DataTypes dataTypes, ItemPalette itemPalette, SubComponentRegistry subComponentRegistry)
|
||||
: StructuredComponent(dataTypes, itemPalette, subComponentRegistry)
|
||||
{
|
||||
public int Slot { get; set; }
|
||||
public SoundEventSubComponent? EquipSound { get; set; }
|
||||
public bool HasModel { get; set; }
|
||||
public string? Model { get; set; }
|
||||
public bool HasCameraOverlay { get; set; }
|
||||
public string? CameraOverlay { get; set; }
|
||||
public bool HasAllowedEntities { get; set; }
|
||||
public int AllowedEntitiesType { get; set; }
|
||||
public string? AllowedEntitiesTag { get; set; }
|
||||
public List<int>? AllowedEntitiesIds { get; set; }
|
||||
public bool Dispensable { get; set; }
|
||||
public bool Swappable { get; set; }
|
||||
public bool DamageOnHurt { get; set; }
|
||||
|
||||
public override void Parse(Queue<byte> data)
|
||||
{
|
||||
Slot = dataTypes.ReadNextVarInt(data);
|
||||
EquipSound = (SoundEventSubComponent)subComponentRegistry.ParseSubComponent(SubComponents.SoundEvent, data);
|
||||
|
||||
HasModel = dataTypes.ReadNextBool(data);
|
||||
if (HasModel)
|
||||
Model = dataTypes.ReadNextString(data);
|
||||
|
||||
HasCameraOverlay = dataTypes.ReadNextBool(data);
|
||||
if (HasCameraOverlay)
|
||||
CameraOverlay = dataTypes.ReadNextString(data);
|
||||
|
||||
HasAllowedEntities = dataTypes.ReadNextBool(data);
|
||||
if (HasAllowedEntities)
|
||||
{
|
||||
AllowedEntitiesType = dataTypes.ReadNextVarInt(data);
|
||||
if (AllowedEntitiesType == 0)
|
||||
{
|
||||
AllowedEntitiesTag = dataTypes.ReadNextString(data);
|
||||
}
|
||||
else
|
||||
{
|
||||
AllowedEntitiesIds = new List<int>();
|
||||
for (var i = 0; i < AllowedEntitiesType - 1; i++)
|
||||
AllowedEntitiesIds.Add(dataTypes.ReadNextVarInt(data));
|
||||
}
|
||||
}
|
||||
|
||||
Dispensable = dataTypes.ReadNextBool(data);
|
||||
Swappable = dataTypes.ReadNextBool(data);
|
||||
DamageOnHurt = dataTypes.ReadNextBool(data);
|
||||
}
|
||||
|
||||
public override Queue<byte> Serialize()
|
||||
{
|
||||
var data = new List<byte>();
|
||||
data.AddRange(DataTypes.GetVarInt(Slot));
|
||||
if (EquipSound != null) data.AddRange(EquipSound.Serialize());
|
||||
|
||||
data.AddRange(DataTypes.GetBool(HasModel));
|
||||
if (HasModel && Model != null)
|
||||
data.AddRange(DataTypes.GetString(Model));
|
||||
|
||||
data.AddRange(DataTypes.GetBool(HasCameraOverlay));
|
||||
if (HasCameraOverlay && CameraOverlay != null)
|
||||
data.AddRange(DataTypes.GetString(CameraOverlay));
|
||||
|
||||
data.AddRange(DataTypes.GetBool(HasAllowedEntities));
|
||||
if (HasAllowedEntities)
|
||||
{
|
||||
data.AddRange(DataTypes.GetVarInt(AllowedEntitiesType));
|
||||
if (AllowedEntitiesType == 0 && AllowedEntitiesTag != null)
|
||||
{
|
||||
data.AddRange(DataTypes.GetString(AllowedEntitiesTag));
|
||||
}
|
||||
else if (AllowedEntitiesIds != null)
|
||||
{
|
||||
foreach (var id in AllowedEntitiesIds)
|
||||
data.AddRange(DataTypes.GetVarInt(id));
|
||||
}
|
||||
}
|
||||
|
||||
data.AddRange(DataTypes.GetBool(Dispensable));
|
||||
data.AddRange(DataTypes.GetBool(Swappable));
|
||||
data.AddRange(DataTypes.GetBool(DamageOnHurt));
|
||||
return new Queue<byte>(data);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,29 @@
|
|||
using System.Collections.Generic;
|
||||
using MinecraftClient.Inventory.ItemPalettes;
|
||||
using MinecraftClient.Protocol.Handlers.StructuredComponents.Core;
|
||||
|
||||
namespace MinecraftClient.Protocol.Handlers.StructuredComponents.Components._1_21_2;
|
||||
|
||||
public class FoodComponent1212(DataTypes dataTypes, ItemPalette itemPalette, SubComponentRegistry subComponentRegistry)
|
||||
: StructuredComponent(dataTypes, itemPalette, subComponentRegistry)
|
||||
{
|
||||
public int Nutrition { get; set; }
|
||||
public float Saturation { get; set; }
|
||||
public bool CanAlwaysEat { get; set; }
|
||||
|
||||
public override void Parse(Queue<byte> data)
|
||||
{
|
||||
Nutrition = dataTypes.ReadNextVarInt(data);
|
||||
Saturation = dataTypes.ReadNextFloat(data);
|
||||
CanAlwaysEat = dataTypes.ReadNextBool(data);
|
||||
}
|
||||
|
||||
public override Queue<byte> Serialize()
|
||||
{
|
||||
var data = new List<byte>();
|
||||
data.AddRange(DataTypes.GetVarInt(Nutrition));
|
||||
data.AddRange(DataTypes.GetFloat(Saturation));
|
||||
data.AddRange(DataTypes.GetBool(CanAlwaysEat));
|
||||
return new Queue<byte>(data);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,8 @@
|
|||
using MinecraftClient.Inventory.ItemPalettes;
|
||||
using MinecraftClient.Protocol.Handlers.StructuredComponents.Components;
|
||||
using MinecraftClient.Protocol.Handlers.StructuredComponents.Core;
|
||||
|
||||
namespace MinecraftClient.Protocol.Handlers.StructuredComponents.Components._1_21_2;
|
||||
|
||||
public class GliderComponent(DataTypes dataTypes, ItemPalette itemPalette, SubComponentRegistry subComponentRegistry)
|
||||
: EmptyComponent(dataTypes, itemPalette, subComponentRegistry);
|
||||
|
|
@ -0,0 +1,23 @@
|
|||
using System.Collections.Generic;
|
||||
using MinecraftClient.Inventory.ItemPalettes;
|
||||
using MinecraftClient.Protocol.Handlers.StructuredComponents.Core;
|
||||
|
||||
namespace MinecraftClient.Protocol.Handlers.StructuredComponents.Components._1_21_2;
|
||||
|
||||
public class ItemModelComponent(DataTypes dataTypes, ItemPalette itemPalette, SubComponentRegistry subComponentRegistry)
|
||||
: StructuredComponent(dataTypes, itemPalette, subComponentRegistry)
|
||||
{
|
||||
public string Identifier { get; set; } = null!;
|
||||
|
||||
public override void Parse(Queue<byte> data)
|
||||
{
|
||||
Identifier = dataTypes.ReadNextString(data);
|
||||
}
|
||||
|
||||
public override Queue<byte> Serialize()
|
||||
{
|
||||
var data = new List<byte>();
|
||||
data.AddRange(DataTypes.GetString(Identifier));
|
||||
return new Queue<byte>(data);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,44 @@
|
|||
using System.Collections.Generic;
|
||||
using MinecraftClient.Inventory.ItemPalettes;
|
||||
using MinecraftClient.Protocol.Handlers.StructuredComponents.Core;
|
||||
|
||||
namespace MinecraftClient.Protocol.Handlers.StructuredComponents.Components._1_21_2;
|
||||
|
||||
public class RepairableComponent(DataTypes dataTypes, ItemPalette itemPalette, SubComponentRegistry subComponentRegistry)
|
||||
: StructuredComponent(dataTypes, itemPalette, subComponentRegistry)
|
||||
{
|
||||
public int Type { get; set; }
|
||||
public string? TagName { get; set; }
|
||||
public List<int>? ItemIds { get; set; }
|
||||
|
||||
public override void Parse(Queue<byte> data)
|
||||
{
|
||||
Type = dataTypes.ReadNextVarInt(data);
|
||||
if (Type == 0)
|
||||
{
|
||||
TagName = dataTypes.ReadNextString(data);
|
||||
}
|
||||
else
|
||||
{
|
||||
ItemIds = new List<int>();
|
||||
for (var i = 0; i < Type - 1; i++)
|
||||
ItemIds.Add(dataTypes.ReadNextVarInt(data));
|
||||
}
|
||||
}
|
||||
|
||||
public override Queue<byte> Serialize()
|
||||
{
|
||||
var data = new List<byte>();
|
||||
data.AddRange(DataTypes.GetVarInt(Type));
|
||||
if (Type == 0 && TagName != null)
|
||||
{
|
||||
data.AddRange(DataTypes.GetString(TagName));
|
||||
}
|
||||
else if (ItemIds != null)
|
||||
{
|
||||
foreach (var id in ItemIds)
|
||||
data.AddRange(DataTypes.GetVarInt(id));
|
||||
}
|
||||
return new Queue<byte>(data);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,23 @@
|
|||
using System.Collections.Generic;
|
||||
using MinecraftClient.Inventory.ItemPalettes;
|
||||
using MinecraftClient.Protocol.Handlers.StructuredComponents.Core;
|
||||
|
||||
namespace MinecraftClient.Protocol.Handlers.StructuredComponents.Components._1_21_2;
|
||||
|
||||
public class TooltipStyleComponent(DataTypes dataTypes, ItemPalette itemPalette, SubComponentRegistry subComponentRegistry)
|
||||
: StructuredComponent(dataTypes, itemPalette, subComponentRegistry)
|
||||
{
|
||||
public string Identifier { get; set; } = null!;
|
||||
|
||||
public override void Parse(Queue<byte> data)
|
||||
{
|
||||
Identifier = dataTypes.ReadNextString(data);
|
||||
}
|
||||
|
||||
public override Queue<byte> Serialize()
|
||||
{
|
||||
var data = new List<byte>();
|
||||
data.AddRange(DataTypes.GetString(Identifier));
|
||||
return new Queue<byte>(data);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,31 @@
|
|||
using System.Collections.Generic;
|
||||
using MinecraftClient.Inventory.ItemPalettes;
|
||||
using MinecraftClient.Protocol.Handlers.StructuredComponents.Core;
|
||||
|
||||
namespace MinecraftClient.Protocol.Handlers.StructuredComponents.Components._1_21_2;
|
||||
|
||||
public class UseCooldownComponent(DataTypes dataTypes, ItemPalette itemPalette, SubComponentRegistry subComponentRegistry)
|
||||
: StructuredComponent(dataTypes, itemPalette, subComponentRegistry)
|
||||
{
|
||||
public float Seconds { get; set; }
|
||||
public bool HasCooldownGroup { get; set; }
|
||||
public string? CooldownGroup { get; set; }
|
||||
|
||||
public override void Parse(Queue<byte> data)
|
||||
{
|
||||
Seconds = dataTypes.ReadNextFloat(data);
|
||||
HasCooldownGroup = dataTypes.ReadNextBool(data);
|
||||
if (HasCooldownGroup)
|
||||
CooldownGroup = dataTypes.ReadNextString(data);
|
||||
}
|
||||
|
||||
public override Queue<byte> Serialize()
|
||||
{
|
||||
var data = new List<byte>();
|
||||
data.AddRange(DataTypes.GetFloat(Seconds));
|
||||
data.AddRange(DataTypes.GetBool(HasCooldownGroup));
|
||||
if (HasCooldownGroup && CooldownGroup != null)
|
||||
data.AddRange(DataTypes.GetString(CooldownGroup));
|
||||
return new Queue<byte>(data);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,24 @@
|
|||
using System.Collections.Generic;
|
||||
using MinecraftClient.Inventory;
|
||||
using MinecraftClient.Inventory.ItemPalettes;
|
||||
using MinecraftClient.Protocol.Handlers.StructuredComponents.Core;
|
||||
|
||||
namespace MinecraftClient.Protocol.Handlers.StructuredComponents.Components._1_21_2;
|
||||
|
||||
public class UseRemainderComponent(DataTypes dataTypes, ItemPalette itemPalette, SubComponentRegistry subComponentRegistry)
|
||||
: StructuredComponent(dataTypes, itemPalette, subComponentRegistry)
|
||||
{
|
||||
public Item? ConvertInto { get; set; }
|
||||
|
||||
public override void Parse(Queue<byte> data)
|
||||
{
|
||||
ConvertInto = dataTypes.ReadNextItemSlot(data, ItemPalette);
|
||||
}
|
||||
|
||||
public override Queue<byte> Serialize()
|
||||
{
|
||||
var data = new List<byte>();
|
||||
data.AddRange(dataTypes.GetItemSlot(ConvertInto, ItemPalette));
|
||||
return new Queue<byte>(data);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,82 @@
|
|||
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.Components._1_21_2;
|
||||
using MinecraftClient.Protocol.Handlers.StructuredComponents.Core;
|
||||
|
||||
namespace MinecraftClient.Protocol.Handlers.StructuredComponents.Registries;
|
||||
|
||||
public class StructuredComponentsRegistry1212 : StructuredComponentRegistry
|
||||
{
|
||||
public StructuredComponentsRegistry1212(DataTypes dataTypes, ItemPalette itemPalette, SubComponentRegistry subComponentRegistry)
|
||||
: base(dataTypes, itemPalette, subComponentRegistry)
|
||||
{
|
||||
RegisterComponent<CustomDataComponent>(0, "minecraft:custom_data");
|
||||
RegisterComponent<MaxStackSizeComponent>(1, "minecraft:max_stack_size");
|
||||
RegisterComponent<MaxDamageComponent>(2, "minecraft:max_damage");
|
||||
RegisterComponent<DamageComponent>(3, "minecraft:damage");
|
||||
RegisterComponent<UnbrekableComponent1206>(4, "minecraft:unbreakable");
|
||||
RegisterComponent<CustomNameComponent>(5, "minecraft:custom_name");
|
||||
RegisterComponent<ItemNameComponent>(6, "minecraft:item_name");
|
||||
RegisterComponent<ItemModelComponent>(7, "minecraft:item_model");
|
||||
RegisterComponent<LoreNameComponent1206>(8, "minecraft:lore");
|
||||
RegisterComponent<RarityComponent>(9, "minecraft:rarity");
|
||||
RegisterComponent<EnchantmentsComponent>(10, "minecraft:enchantments");
|
||||
RegisterComponent<CanPlaceOnComponent>(11, "minecraft:can_place_on");
|
||||
RegisterComponent<CanBreakComponent>(12, "minecraft:can_break");
|
||||
RegisterComponent<AttributeModifiersComponent>(13, "minecraft:attribute_modifiers");
|
||||
RegisterComponent<CustomModelDataComponent>(14, "minecraft:custom_model_data");
|
||||
RegisterComponent<HideAdditionalTooltipComponent>(15, "minecraft:hide_additional_tooltip");
|
||||
RegisterComponent<HideTooltipComponent>(16, "minecraft:hide_tooltip");
|
||||
RegisterComponent<RepairCostComponent>(17, "minecraft:repair_cost");
|
||||
RegisterComponent<CreativeSlotLockComponent>(18, "minecraft:creative_slot_lock");
|
||||
RegisterComponent<EnchantmentGlintOverrideComponent>(19, "minecraft:enchantment_glint_override");
|
||||
RegisterComponent<IntangibleProjectileComponent>(20, "minecraft:intangible_projectile");
|
||||
RegisterComponent<FoodComponent1212>(21, "minecraft:food");
|
||||
RegisterComponent<ConsumableComponent>(22, "minecraft:consumable");
|
||||
RegisterComponent<UseRemainderComponent>(23, "minecraft:use_remainder");
|
||||
RegisterComponent<UseCooldownComponent>(24, "minecraft:use_cooldown");
|
||||
RegisterComponent<DamageResistantComponent>(25, "minecraft:damage_resistant");
|
||||
RegisterComponent<ToolComponent>(26, "minecraft:tool");
|
||||
RegisterComponent<EnchantableComponent>(27, "minecraft:enchantable");
|
||||
RegisterComponent<EquippableComponent>(28, "minecraft:equippable");
|
||||
RegisterComponent<RepairableComponent>(29, "minecraft:repairable");
|
||||
RegisterComponent<GliderComponent>(30, "minecraft:glider");
|
||||
RegisterComponent<TooltipStyleComponent>(31, "minecraft:tooltip_style");
|
||||
RegisterComponent<DeathProtectionComponent>(32, "minecraft:death_protection");
|
||||
RegisterComponent<StoredEnchantmentsComponent>(33, "minecraft:stored_enchantments");
|
||||
RegisterComponent<DyeColorComponent>(34, "minecraft:dyed_color");
|
||||
RegisterComponent<MapColorComponent>(35, "minecraft:map_color");
|
||||
RegisterComponent<MapIdComponent>(36, "minecraft:map_id");
|
||||
RegisterComponent<MapDecorationsComponent>(37, "minecraft:map_decorations");
|
||||
RegisterComponent<MapPostProcessingComponent>(38, "minecraft:map_post_processing");
|
||||
RegisterComponent<ChargedProjectilesComponent>(39, "minecraft:charged_projectiles");
|
||||
RegisterComponent<BundleContentsComponent>(40, "minecraft:bundle_contents");
|
||||
RegisterComponent<PotionContentsComponent>(41, "minecraft:potion_contents");
|
||||
RegisterComponent<SuspiciousStewEffectsComponent>(42, "minecraft:suspicious_stew_effects");
|
||||
RegisterComponent<WritableBlookContentComponent>(43, "minecraft:writable_book_content");
|
||||
RegisterComponent<WrittenBlookContentComponent>(44, "minecraft:written_book_content");
|
||||
RegisterComponent<TrimComponent>(45, "minecraft:trim");
|
||||
RegisterComponent<DebugStickStateComponent>(46, "minecraft:debug_stick_state");
|
||||
RegisterComponent<EntityDataComponent>(47, "minecraft:entity_data");
|
||||
RegisterComponent<BucketEntityDataComponent>(48, "minecraft:bucket_entity_data");
|
||||
RegisterComponent<BlockEntityDataComponent>(49, "minecraft:block_entity_data");
|
||||
RegisterComponent<InstrumentComponent>(50, "minecraft:instrument");
|
||||
RegisterComponent<OmniousBottleAmplifierComponent>(51, "minecraft:ominous_bottle_amplifier");
|
||||
RegisterComponent<JukeBoxPlayableComponent>(52, "minecraft:jukebox_playable");
|
||||
RegisterComponent<RecipesComponent>(53, "minecraft:recipes");
|
||||
RegisterComponent<LodestoneTrackerComponent>(54, "minecraft:lodestone_tracker");
|
||||
RegisterComponent<FireworkExplosionComponent>(55, "minecraft:firework_explosion");
|
||||
RegisterComponent<FireworksComponent>(56, "minecraft:fireworks");
|
||||
RegisterComponent<ProfileComponent>(57, "minecraft:profile");
|
||||
RegisterComponent<NoteBlockSoundComponent>(58, "minecraft:note_block_sound");
|
||||
RegisterComponent<BannerPatternsComponent>(59, "minecraft:banner_patterns");
|
||||
RegisterComponent<BaseColorComponent>(60, "minecraft:base_color");
|
||||
RegisterComponent<PotDecorationsComponent>(61, "minecraft:pot_decorations");
|
||||
RegisterComponent<ContainerComponent>(62, "minecraft:container");
|
||||
RegisterComponent<BlockStateComponent>(63, "minecraft:block_state");
|
||||
RegisterComponent<BeesComponent>(64, "minecraft:bees");
|
||||
RegisterComponent<LockComponent>(65, "minecraft:lock");
|
||||
RegisterComponent<ContainerLootComponent>(66, "minecraft:container_loot");
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,11 @@
|
|||
using MinecraftClient.Protocol.Handlers.StructuredComponents.Components.Subcomponents._1_21;
|
||||
using MinecraftClient.Protocol.Handlers.StructuredComponents.Core;
|
||||
|
||||
namespace MinecraftClient.Protocol.Handlers.StructuredComponents.Registries.Subcomponents;
|
||||
|
||||
public class SubComponentRegistry1212 : SubComponentRegistry121
|
||||
{
|
||||
public SubComponentRegistry1212(DataTypes dataTypes) : base(dataTypes)
|
||||
{
|
||||
}
|
||||
}
|
||||
|
|
@ -21,6 +21,7 @@ public class StructuredComponentsHandler
|
|||
{
|
||||
Protocol18Handler.MC_1_20_6_Version => typeof(SubComponentRegistry1206),
|
||||
Protocol18Handler.MC_1_21_Version => typeof(SubComponentRegistry121),
|
||||
>= Protocol18Handler.MC_1_21_2_Version => typeof(SubComponentRegistry1212),
|
||||
_ => throw new NotSupportedException($"Protocol version {protocolVersion} is not supported for subcomponent registries!")
|
||||
};
|
||||
|
||||
|
|
@ -32,6 +33,7 @@ public class StructuredComponentsHandler
|
|||
{
|
||||
Protocol18Handler.MC_1_20_6_Version => typeof(StructuredComponentsRegistry1206),
|
||||
Protocol18Handler.MC_1_21_Version => typeof(StructuredComponentsRegistry121),
|
||||
>= Protocol18Handler.MC_1_21_2_Version => typeof(StructuredComponentsRegistry1212),
|
||||
_ => throw new NotSupportedException($"Protocol version {protocolVersion} is not supported for structured component registries!")
|
||||
};
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue