Merge pull request #2942: Add Minecraft 1.21.11 (Protocol 774) Support

Add Minecraft 1.21.11 (Protocol 774) Support
This commit is contained in:
BruceChen 2026-03-22 01:38:31 +08:00 committed by GitHub
commit bc60e99a63
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
21 changed files with 2145 additions and 13 deletions

File diff suppressed because it is too large Load diff

View file

@ -208,6 +208,7 @@ namespace MinecraftClient.Inventory
Cake,
Calcite,
CalibratedSculkSensor,
CamelHuskSpawnEgg,
CamelSpawnEgg,
Campfire,
Candle,
@ -318,9 +319,11 @@ namespace MinecraftClient.Inventory
CopperLantern,
CopperLeggings,
CopperNugget,
CopperNautilusArmor,
CopperOre,
CopperPickaxe,
CopperShovel,
CopperSpear,
CopperSword,
CopperTorch,
CopperTrapdoor,
@ -449,8 +452,10 @@ namespace MinecraftClient.Inventory
DiamondHoe,
DiamondHorseArmor,
DiamondLeggings,
DiamondNautilusArmor,
DiamondOre,
DiamondPickaxe,
DiamondSpear,
DiamondShovel,
DiamondSword,
Diorite,
@ -578,8 +583,10 @@ namespace MinecraftClient.Inventory
GoldenHoe,
GoldenHorseArmor,
GoldenLeggings,
GoldenNautilusArmor,
GoldenPickaxe,
GoldenShovel,
GoldenSpear,
GoldenSword,
Granite,
GraniteSlab,
@ -666,9 +673,11 @@ namespace MinecraftClient.Inventory
IronHorseArmor,
IronIngot,
IronLeggings,
IronNautilusArmor,
IronNugget,
IronOre,
IronPickaxe,
IronSpear,
IronShovel,
IronSword,
IronTrapdoor,
@ -862,6 +871,7 @@ namespace MinecraftClient.Inventory
Mycelium,
NameTag,
NautilusShell,
NautilusSpawnEgg,
NetherBrick,
NetherBrickFence,
NetherBrickSlab,
@ -880,11 +890,14 @@ namespace MinecraftClient.Inventory
NetheriteChestplate,
NetheriteHelmet,
NetheriteHoe,
NetheriteHorseArmor,
NetheriteIngot,
NetheriteLeggings,
NetheriteNautilusArmor,
NetheritePickaxe,
NetheriteScrap,
NetheriteShovel,
NetheriteSpear,
NetheriteSword,
NetheriteUpgradeSmithingTemplate,
Netherrack,
@ -972,6 +985,7 @@ namespace MinecraftClient.Inventory
PaleOakWood,
PandaSpawnEgg,
Paper,
ParchedSpawnEgg,
ParrotSpawnEgg,
PearlescentFroglight,
Peony,
@ -1261,6 +1275,7 @@ namespace MinecraftClient.Inventory
StonePressurePlate,
StoneShovel,
StoneSlab,
StoneSpear,
StoneStairs,
StoneSword,
Stonecutter,
@ -1480,6 +1495,7 @@ namespace MinecraftClient.Inventory
WoodenAxe,
WoodenHoe,
WoodenPickaxe,
WoodenSpear,
WoodenShovel,
WoodenSword,
WritableBook,
@ -1503,6 +1519,7 @@ namespace MinecraftClient.Inventory
ZombieHead,
ZombieHorseSpawnEgg,
ZombieSpawnEgg,
ZombieNautilusSpawnEgg,
ZombieVillagerSpawnEgg,
ZombifiedPiglinSpawnEgg,
}

View file

@ -116,5 +116,13 @@ public enum EntityMetaDataType
/// <summary>
/// Either&lt;GameProfile, Partial&gt; + PlayerSkin.Patch (1.21.9+)
/// </summary>
ResolvableProfile
ResolvableProfile,
/// <summary>
/// VarInt (1.21.11+, holder registry ID)
/// </summary>
ZombieNautilusVariant,
/// <summary>
/// VarInt (1.21.11+, 0=LEFT, 1=RIGHT)
/// </summary>
HumanoidArm
}

View file

@ -26,6 +26,7 @@ public abstract class EntityMetadataPalette
<= Protocol18Handler.MC_1_21_4_Version => new EntityMetadataPalette1206(), // 1.20.6 - 1.21.4
<= Protocol18Handler.MC_1_21_7_Version => new EntityMetadataPalette1215(), // 1.21.5 - 1.21.8
<= Protocol18Handler.MC_1_21_9_Version => new EntityMetadataPalette1219(), // 1.21.9 - 1.21.10
<= Protocol18Handler.MC_1_21_11_Version => new EntityMetadataPalette12111(), // 1.21.11
_ => throw new NotImplementedException()
};
}

View file

@ -0,0 +1,54 @@
using System.Collections.Generic;
namespace MinecraftClient.Mapping.EntityMetadataPalettes;
public class EntityMetadataPalette12111 : EntityMetadataPalette
{
private readonly Dictionary<int, EntityMetaDataType> entityMetadataMappings = new()
{
{ 0, EntityMetaDataType.Byte },
{ 1, EntityMetaDataType.VarInt },
{ 2, EntityMetaDataType.VarLong },
{ 3, EntityMetaDataType.Float },
{ 4, EntityMetaDataType.String },
{ 5, EntityMetaDataType.Chat },
{ 6, EntityMetaDataType.OptionalChat },
{ 7, EntityMetaDataType.Slot },
{ 8, EntityMetaDataType.Boolean },
{ 9, EntityMetaDataType.Rotation },
{ 10, EntityMetaDataType.Position },
{ 11, EntityMetaDataType.OptionalPosition },
{ 12, EntityMetaDataType.Direction },
{ 13, EntityMetaDataType.OptionalLivingEntityReference },
{ 14, EntityMetaDataType.BlockId },
{ 15, EntityMetaDataType.OptionalBlockId },
{ 16, EntityMetaDataType.Particle },
{ 17, EntityMetaDataType.Particles },
{ 18, EntityMetaDataType.VillagerData },
{ 19, EntityMetaDataType.OptionalVarInt },
{ 20, EntityMetaDataType.Pose },
{ 21, EntityMetaDataType.CatVariant },
{ 22, EntityMetaDataType.CowVariant },
{ 23, EntityMetaDataType.WolfVariant },
{ 24, EntityMetaDataType.WolfSoundVariant },
{ 25, EntityMetaDataType.FrogVariant },
{ 26, EntityMetaDataType.PigVariant },
{ 27, EntityMetaDataType.ChickenVariant },
{ 28, EntityMetaDataType.ZombieNautilusVariant },
{ 29, EntityMetaDataType.OptionalGlobalPosition },
{ 30, EntityMetaDataType.PaintingVariant },
{ 31, EntityMetaDataType.SnifferState },
{ 32, EntityMetaDataType.ArmadilloState },
{ 33, EntityMetaDataType.CopperGolemState },
{ 34, EntityMetaDataType.WeatheringCopperState },
{ 35, EntityMetaDataType.Vector3 },
{ 36, EntityMetaDataType.Quaternion },
{ 37, EntityMetaDataType.ResolvableProfile },
{ 38, EntityMetaDataType.HumanoidArm },
};
public override Dictionary<int, EntityMetaDataType> GetEntityMetadataMappingsList()
{
return entityMetadataMappings;
}
}

View file

@ -0,0 +1,175 @@
using System.Collections.Generic;
namespace MinecraftClient.Mapping.EntityPalettes
{
public class EntityPalette12111 : EntityPalette
{
private static readonly Dictionary<int, EntityType> mappings = new();
static EntityPalette12111()
{
mappings[0] = EntityType.AcaciaBoat;
mappings[1] = EntityType.AcaciaChestBoat;
mappings[2] = EntityType.Allay;
mappings[3] = EntityType.AreaEffectCloud;
mappings[4] = EntityType.Armadillo;
mappings[5] = EntityType.ArmorStand;
mappings[6] = EntityType.Arrow;
mappings[7] = EntityType.Axolotl;
mappings[8] = EntityType.BambooChestRaft;
mappings[9] = EntityType.BambooRaft;
mappings[10] = EntityType.Bat;
mappings[11] = EntityType.Bee;
mappings[12] = EntityType.BirchBoat;
mappings[13] = EntityType.BirchChestBoat;
mappings[14] = EntityType.Blaze;
mappings[15] = EntityType.BlockDisplay;
mappings[16] = EntityType.Bogged;
mappings[17] = EntityType.Breeze;
mappings[18] = EntityType.BreezeWindCharge;
mappings[19] = EntityType.Camel;
mappings[20] = EntityType.CamelHusk;
mappings[21] = EntityType.Cat;
mappings[22] = EntityType.CaveSpider;
mappings[23] = EntityType.CherryBoat;
mappings[24] = EntityType.CherryChestBoat;
mappings[25] = EntityType.ChestMinecart;
mappings[26] = EntityType.Chicken;
mappings[27] = EntityType.Cod;
mappings[28] = EntityType.CopperGolem;
mappings[29] = EntityType.CommandBlockMinecart;
mappings[30] = EntityType.Cow;
mappings[31] = EntityType.Creaking;
mappings[32] = EntityType.Creeper;
mappings[33] = EntityType.DarkOakBoat;
mappings[34] = EntityType.DarkOakChestBoat;
mappings[35] = EntityType.Dolphin;
mappings[36] = EntityType.Donkey;
mappings[37] = EntityType.DragonFireball;
mappings[38] = EntityType.Drowned;
mappings[39] = EntityType.Egg;
mappings[40] = EntityType.ElderGuardian;
mappings[41] = EntityType.Enderman;
mappings[42] = EntityType.Endermite;
mappings[43] = EntityType.EnderDragon;
mappings[44] = EntityType.EnderPearl;
mappings[45] = EntityType.EndCrystal;
mappings[46] = EntityType.Evoker;
mappings[47] = EntityType.EvokerFangs;
mappings[48] = EntityType.ExperienceBottle;
mappings[49] = EntityType.ExperienceOrb;
mappings[50] = EntityType.EyeOfEnder;
mappings[51] = EntityType.FallingBlock;
mappings[52] = EntityType.Fireball;
mappings[53] = EntityType.FireworkRocket;
mappings[54] = EntityType.Fox;
mappings[55] = EntityType.Frog;
mappings[56] = EntityType.FurnaceMinecart;
mappings[57] = EntityType.Ghast;
mappings[58] = EntityType.HappyGhast;
mappings[59] = EntityType.Giant;
mappings[60] = EntityType.GlowItemFrame;
mappings[61] = EntityType.GlowSquid;
mappings[62] = EntityType.Goat;
mappings[63] = EntityType.Guardian;
mappings[64] = EntityType.Hoglin;
mappings[65] = EntityType.HopperMinecart;
mappings[66] = EntityType.Horse;
mappings[67] = EntityType.Husk;
mappings[68] = EntityType.Illusioner;
mappings[69] = EntityType.Interaction;
mappings[70] = EntityType.IronGolem;
mappings[71] = EntityType.Item;
mappings[72] = EntityType.ItemDisplay;
mappings[73] = EntityType.ItemFrame;
mappings[74] = EntityType.JungleBoat;
mappings[75] = EntityType.JungleChestBoat;
mappings[76] = EntityType.LeashKnot;
mappings[77] = EntityType.LightningBolt;
mappings[78] = EntityType.Llama;
mappings[79] = EntityType.LlamaSpit;
mappings[80] = EntityType.MagmaCube;
mappings[81] = EntityType.MangroveBoat;
mappings[82] = EntityType.MangroveChestBoat;
mappings[83] = EntityType.Mannequin;
mappings[84] = EntityType.Marker;
mappings[85] = EntityType.Minecart;
mappings[86] = EntityType.Mooshroom;
mappings[87] = EntityType.Mule;
mappings[88] = EntityType.Nautilus;
mappings[89] = EntityType.OakBoat;
mappings[90] = EntityType.OakChestBoat;
mappings[91] = EntityType.Ocelot;
mappings[92] = EntityType.OminousItemSpawner;
mappings[93] = EntityType.Painting;
mappings[94] = EntityType.PaleOakBoat;
mappings[95] = EntityType.PaleOakChestBoat;
mappings[96] = EntityType.Panda;
mappings[97] = EntityType.Parched;
mappings[98] = EntityType.Parrot;
mappings[99] = EntityType.Phantom;
mappings[100] = EntityType.Pig;
mappings[101] = EntityType.Piglin;
mappings[102] = EntityType.PiglinBrute;
mappings[103] = EntityType.Pillager;
mappings[104] = EntityType.PolarBear;
mappings[105] = EntityType.SplashPotion;
mappings[106] = EntityType.LingeringPotion;
mappings[107] = EntityType.Pufferfish;
mappings[108] = EntityType.Rabbit;
mappings[109] = EntityType.Ravager;
mappings[110] = EntityType.Salmon;
mappings[111] = EntityType.Sheep;
mappings[112] = EntityType.Shulker;
mappings[113] = EntityType.ShulkerBullet;
mappings[114] = EntityType.Silverfish;
mappings[115] = EntityType.Skeleton;
mappings[116] = EntityType.SkeletonHorse;
mappings[117] = EntityType.Slime;
mappings[118] = EntityType.SmallFireball;
mappings[119] = EntityType.Sniffer;
mappings[120] = EntityType.Snowball;
mappings[121] = EntityType.SnowGolem;
mappings[122] = EntityType.SpawnerMinecart;
mappings[123] = EntityType.SpectralArrow;
mappings[124] = EntityType.Spider;
mappings[125] = EntityType.SpruceBoat;
mappings[126] = EntityType.SpruceChestBoat;
mappings[127] = EntityType.Squid;
mappings[128] = EntityType.Stray;
mappings[129] = EntityType.Strider;
mappings[130] = EntityType.Tadpole;
mappings[131] = EntityType.TextDisplay;
mappings[132] = EntityType.Tnt;
mappings[133] = EntityType.TntMinecart;
mappings[134] = EntityType.TraderLlama;
mappings[135] = EntityType.Trident;
mappings[136] = EntityType.TropicalFish;
mappings[137] = EntityType.Turtle;
mappings[138] = EntityType.Vex;
mappings[139] = EntityType.Villager;
mappings[140] = EntityType.Vindicator;
mappings[141] = EntityType.WanderingTrader;
mappings[142] = EntityType.Warden;
mappings[143] = EntityType.WindCharge;
mappings[144] = EntityType.Witch;
mappings[145] = EntityType.Wither;
mappings[146] = EntityType.WitherSkeleton;
mappings[147] = EntityType.WitherSkull;
mappings[148] = EntityType.Wolf;
mappings[149] = EntityType.Zoglin;
mappings[150] = EntityType.Zombie;
mappings[151] = EntityType.ZombieHorse;
mappings[152] = EntityType.ZombieNautilus;
mappings[153] = EntityType.ZombieVillager;
mappings[154] = EntityType.ZombifiedPiglin;
mappings[155] = EntityType.Player;
mappings[156] = EntityType.FishingBobber;
}
protected override Dictionary<int, EntityType> GetDict()
{
return mappings;
}
}
}

View file

@ -35,6 +35,7 @@ namespace MinecraftClient.Mapping
Breeze,
BreezeWindCharge,
Camel,
CamelHusk,
Cat,
CaveSpider,
CherryBoat,
@ -105,6 +106,7 @@ namespace MinecraftClient.Mapping
Minecart,
Mooshroom,
Mule,
Nautilus,
OakBoat,
OakChestBoat,
Ocelot,
@ -113,6 +115,7 @@ namespace MinecraftClient.Mapping
PaleOakBoat,
PaleOakChestBoat,
Panda,
Parched,
Parrot,
Phantom,
Pig,
@ -169,6 +172,7 @@ namespace MinecraftClient.Mapping
Zoglin,
Zombie,
ZombieHorse,
ZombieNautilus,
ZombieVillager,
ZombifiedPiglin,
}

View file

@ -46,7 +46,7 @@ namespace MinecraftClient
public const string Version = MCHighestVersion;
public const string MCLowestVersion = "1.4.6";
public const string MCHighestVersion = "1.21.10";
public const string MCHighestVersion = "1.21.11";
public static readonly string? BuildInfo = null;
private static Tuple<Thread, CancellationTokenSource>? offlinePrompt = null;

View file

@ -932,6 +932,10 @@ namespace MinecraftClient.Protocol.Handlers
case EntityMetaDataType.WeatheringCopperState: // Weathering Copper state (1.21.9+)
value = ReadNextVarInt(cache);
break;
case EntityMetaDataType.ZombieNautilusVariant: // ZombieNautilus Variant (1.21.11+)
case EntityMetaDataType.HumanoidArm: // Humanoid Arm (1.21.11+)
value = ReadNextVarInt(cache);
break;
case EntityMetaDataType.ResolvableProfile: // ResolvableProfile (1.21.9+)
ReadNextResolvableProfile(cache);
break;

View file

@ -48,9 +48,9 @@ namespace MinecraftClient.Protocol.Handlers
{
PacketTypePalette p = protocol switch
{
> Protocol18Handler.MC_1_21_9_Version => throw new NotImplementedException(Translations
> Protocol18Handler.MC_1_21_11_Version => throw new NotImplementedException(Translations
.exception_palette_packet),
<= Protocol18Handler.MC_1_21_9_Version and > Protocol18Handler.MC_1_21_7_Version => new PacketPalette1219(),
<= Protocol18Handler.MC_1_21_11_Version and > Protocol18Handler.MC_1_21_7_Version => new PacketPalette1219(),
<= Protocol18Handler.MC_1_21_7_Version and > Protocol18Handler.MC_1_21_5_Version => new PacketPalette1216(),
<= Protocol18Handler.MC_1_21_5_Version and > Protocol18Handler.MC_1_21_4_Version => new PacketPalette1215(),
<= Protocol18Handler.MC_1_21_4_Version and > Protocol18Handler.MC_1_21_2_Version => new PacketPalette1214(),

View file

@ -79,6 +79,7 @@ namespace MinecraftClient.Protocol.Handlers
internal const int MC_1_21_6_Version = 771;
internal const int MC_1_21_7_Version = 772;
internal const int MC_1_21_9_Version = 773;
internal const int MC_1_21_11_Version = 774;
private int compression_treshold = -1;
private int autocomplete_transaction_id = 0;
@ -130,21 +131,21 @@ namespace MinecraftClient.Protocol.Handlers
lastSeenMessagesCollector = protocolVersion >= MC_1_19_3_Version ? new(20) : new(5);
chunkBatchStartTime = GetNanos();
if (handler.GetTerrainEnabled() && protocolVersion > MC_1_21_9_Version)
if (handler.GetTerrainEnabled() && protocolVersion > MC_1_21_11_Version)
{
log.Error($"§c{Translations.extra_terrainandmovement_disabled}");
handler.SetTerrainEnabled(false);
}
if (handler.GetInventoryEnabled() &&
protocolVersion is < MC_1_8_Version or > MC_1_21_9_Version)
protocolVersion is < MC_1_8_Version or > MC_1_21_11_Version)
{
log.Error($"§c{Translations.extra_inventory_disabled}");
handler.SetInventoryEnabled(false);
}
if (handler.GetEntityHandlingEnabled() &&
protocolVersion is < MC_1_8_Version or > MC_1_21_9_Version)
protocolVersion is < MC_1_8_Version or > MC_1_21_11_Version)
{
log.Error($"§c{Translations.extra_entity_disabled}");
handler.SetEntityHandlingEnabled(false);
@ -153,7 +154,7 @@ namespace MinecraftClient.Protocol.Handlers
Block.Palette = protocolVersion switch
{
// Block palette
> MC_1_21_9_Version when handler.GetTerrainEnabled() =>
> MC_1_21_11_Version when handler.GetTerrainEnabled() =>
throw new NotImplementedException(Translations.exception_palette_block),
>= MC_1_21_9_Version => new Palette1219(),
>= MC_1_21_6_Version => new Palette1216(), // 1.21.7/1.21.8 blocks unchanged, reuse 1216
@ -177,8 +178,9 @@ namespace MinecraftClient.Protocol.Handlers
entityPalette = protocolVersion switch
{
// Entity palette
> MC_1_21_9_Version when handler.GetEntityHandlingEnabled() =>
> MC_1_21_11_Version when handler.GetEntityHandlingEnabled() =>
throw new NotImplementedException(Translations.exception_palette_entity),
>= MC_1_21_11_Version => new EntityPalette12111(),
>= MC_1_21_9_Version => new EntityPalette1219(),
>= MC_1_21_6_Version => new EntityPalette1216(), // 1.21.7/1.21.8 entities unchanged, reuse 1216
>= MC_1_21_5_Version => new EntityPalette1215(),
@ -205,8 +207,9 @@ namespace MinecraftClient.Protocol.Handlers
itemPalette = protocolVersion switch
{
// Item palette
> MC_1_21_9_Version when handler.GetInventoryEnabled() =>
> MC_1_21_11_Version when handler.GetInventoryEnabled() =>
throw new NotImplementedException(Translations.exception_palette_item),
>= MC_1_21_11_Version => new ItemPalette12111(),
>= MC_1_21_9_Version => new ItemPalette1219(),
>= MC_1_21_7_Version => new ItemPalette1217(),
>= MC_1_21_6_Version => new ItemPalette1216(),
@ -2665,7 +2668,7 @@ namespace MinecraftClient.Protocol.Handlers
// Also make a palette for field? Will be a lot of work
var healthField = protocolVersion switch
{
> MC_1_21_9_Version => throw new NotImplementedException(Translations
> MC_1_21_11_Version => throw new NotImplementedException(Translations
.exception_palette_healthfield),
// 1.17 and above
>= MC_1_17_Version => 9,

View file

@ -0,0 +1,38 @@
using System.Collections.Generic;
using MinecraftClient.Inventory.ItemPalettes;
using MinecraftClient.Protocol.Handlers.StructuredComponents.Core;
namespace MinecraftClient.Protocol.Handlers.StructuredComponents.Components._1_21_11;
public class AttackRangeComponent(DataTypes dataTypes, ItemPalette itemPalette, SubComponentRegistry subComponentRegistry)
: StructuredComponent(dataTypes, itemPalette, subComponentRegistry)
{
public float MinRange { get; set; }
public float MaxRange { get; set; }
public float MinCreativeRange { get; set; }
public float MaxCreativeRange { get; set; }
public float HitboxMargin { get; set; }
public float MobFactor { get; set; }
public override void Parse(Queue<byte> data)
{
MinRange = dataTypes.ReadNextFloat(data);
MaxRange = dataTypes.ReadNextFloat(data);
MinCreativeRange = dataTypes.ReadNextFloat(data);
MaxCreativeRange = dataTypes.ReadNextFloat(data);
HitboxMargin = dataTypes.ReadNextFloat(data);
MobFactor = dataTypes.ReadNextFloat(data);
}
public override Queue<byte> Serialize()
{
var bytes = new List<byte>();
bytes.AddRange(DataTypes.GetFloat(MinRange));
bytes.AddRange(DataTypes.GetFloat(MaxRange));
bytes.AddRange(DataTypes.GetFloat(MinCreativeRange));
bytes.AddRange(DataTypes.GetFloat(MaxCreativeRange));
bytes.AddRange(DataTypes.GetFloat(HitboxMargin));
bytes.AddRange(DataTypes.GetFloat(MobFactor));
return new Queue<byte>(bytes);
}
}

View file

@ -0,0 +1,47 @@
using System.Collections.Generic;
using MinecraftClient.Inventory.ItemPalettes;
using MinecraftClient.Protocol.Handlers.StructuredComponents.Core;
namespace MinecraftClient.Protocol.Handlers.StructuredComponents.Components._1_21_11;
public class KineticWeaponComponent(DataTypes dataTypes, ItemPalette itemPalette, SubComponentRegistry subComponentRegistry)
: StructuredComponent(dataTypes, itemPalette, subComponentRegistry)
{
public override void Parse(Queue<byte> data)
{
dataTypes.ReadNextVarInt(data); // contactCooldownTicks
dataTypes.ReadNextVarInt(data); // delayTicks
ReadOptionalCondition(data); // dismountConditions
ReadOptionalCondition(data); // knockbackConditions
ReadOptionalCondition(data); // damageConditions
dataTypes.ReadNextFloat(data); // forwardMovement
dataTypes.ReadNextFloat(data); // damageMultiplier
ReadOptionalSoundEventHolder(data); // sound
ReadOptionalSoundEventHolder(data); // hitSound
}
private void ReadOptionalCondition(Queue<byte> data)
{
if (!dataTypes.ReadNextBool(data)) return;
dataTypes.ReadNextVarInt(data); // maxDurationTicks
dataTypes.ReadNextFloat(data); // minSpeed
dataTypes.ReadNextFloat(data); // minRelativeSpeed
}
private void ReadOptionalSoundEventHolder(Queue<byte> data)
{
if (!dataTypes.ReadNextBool(data)) return;
var holderId = dataTypes.ReadNextVarInt(data);
if (holderId == 0)
{
dataTypes.ReadNextString(data);
if (dataTypes.ReadNextBool(data))
dataTypes.ReadNextFloat(data);
}
}
public override Queue<byte> Serialize()
{
return new Queue<byte>();
}
}

View file

@ -0,0 +1,37 @@
using System.Collections.Generic;
using MinecraftClient.Inventory.ItemPalettes;
using MinecraftClient.Protocol.Handlers.StructuredComponents.Core;
namespace MinecraftClient.Protocol.Handlers.StructuredComponents.Components._1_21_11;
public class PiercingWeaponComponent(DataTypes dataTypes, ItemPalette itemPalette, SubComponentRegistry subComponentRegistry)
: StructuredComponent(dataTypes, itemPalette, subComponentRegistry)
{
public bool DealsKnockback { get; set; }
public bool Dismounts { get; set; }
public override void Parse(Queue<byte> data)
{
DealsKnockback = dataTypes.ReadNextBool(data);
Dismounts = dataTypes.ReadNextBool(data);
ReadOptionalSoundEventHolder(data);
ReadOptionalSoundEventHolder(data);
}
private void ReadOptionalSoundEventHolder(Queue<byte> data)
{
if (!dataTypes.ReadNextBool(data)) return;
var holderId = dataTypes.ReadNextVarInt(data);
if (holderId == 0)
{
dataTypes.ReadNextString(data);
if (dataTypes.ReadNextBool(data))
dataTypes.ReadNextFloat(data);
}
}
public override Queue<byte> Serialize()
{
return new Queue<byte>();
}
}

View file

@ -0,0 +1,38 @@
using System.Collections.Generic;
using MinecraftClient.Inventory.ItemPalettes;
using MinecraftClient.Protocol.Handlers.StructuredComponents.Core;
namespace MinecraftClient.Protocol.Handlers.StructuredComponents.Components._1_21_11;
/// <summary>
/// EitherHolder backed by holderRegistry (VarInt = raw registry ID, 0 is valid).
/// Used for DamageType and ZombieNautilusVariant where the holder codec is holderRegistry(),
/// unlike the holder() codec used in SoundEvent (where 0 means inline).
/// </summary>
public class RegistryEitherHolderComponent(DataTypes dataTypes, ItemPalette itemPalette, SubComponentRegistry subComponentRegistry)
: StructuredComponent(dataTypes, itemPalette, subComponentRegistry)
{
public bool IsHolder { get; set; }
public int HolderId { get; set; }
public string? ResourceKey { get; set; }
public override void Parse(Queue<byte> data)
{
IsHolder = dataTypes.ReadNextBool(data);
if (IsHolder)
HolderId = dataTypes.ReadNextVarInt(data);
else
ResourceKey = dataTypes.ReadNextString(data);
}
public override Queue<byte> Serialize()
{
var bytes = new List<byte>();
bytes.AddRange(DataTypes.GetBool(IsHolder));
if (IsHolder)
bytes.AddRange(DataTypes.GetVarInt(HolderId));
else
bytes.AddRange(DataTypes.GetString(ResourceKey ?? ""));
return new Queue<byte>(bytes);
}
}

View file

@ -0,0 +1,26 @@
using System.Collections.Generic;
using MinecraftClient.Inventory.ItemPalettes;
using MinecraftClient.Protocol.Handlers.StructuredComponents.Core;
namespace MinecraftClient.Protocol.Handlers.StructuredComponents.Components._1_21_11;
public class SwingAnimationComponent(DataTypes dataTypes, ItemPalette itemPalette, SubComponentRegistry subComponentRegistry)
: StructuredComponent(dataTypes, itemPalette, subComponentRegistry)
{
public int AnimationType { get; set; }
public int Duration { get; set; }
public override void Parse(Queue<byte> data)
{
AnimationType = dataTypes.ReadNextVarInt(data);
Duration = dataTypes.ReadNextVarInt(data);
}
public override Queue<byte> Serialize()
{
var bytes = new List<byte>();
bytes.AddRange(DataTypes.GetVarInt(AnimationType));
bytes.AddRange(DataTypes.GetVarInt(Duration));
return new Queue<byte>(bytes);
}
}

View file

@ -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_11;
public class UseEffectsComponent(DataTypes dataTypes, ItemPalette itemPalette, SubComponentRegistry subComponentRegistry)
: StructuredComponent(dataTypes, itemPalette, subComponentRegistry)
{
public bool CanSprint { get; set; }
public bool InteractVibrations { get; set; }
public float SpeedMultiplier { get; set; }
public override void Parse(Queue<byte> data)
{
CanSprint = dataTypes.ReadNextBool(data);
InteractVibrations = dataTypes.ReadNextBool(data);
SpeedMultiplier = dataTypes.ReadNextFloat(data);
}
public override Queue<byte> Serialize()
{
var bytes = new List<byte>();
bytes.AddRange(DataTypes.GetBool(CanSprint));
bytes.AddRange(DataTypes.GetBool(InteractVibrations));
bytes.AddRange(DataTypes.GetFloat(SpeedMultiplier));
return new Queue<byte>(bytes);
}
}

View file

@ -0,0 +1,123 @@
using MinecraftClient.Inventory.ItemPalettes;
using MinecraftClient.Protocol.Handlers.StructuredComponents.Components;
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.Components._1_21_5;
using MinecraftClient.Protocol.Handlers.StructuredComponents.Components._1_21_11;
using MinecraftClient.Protocol.Handlers.StructuredComponents.Core;
namespace MinecraftClient.Protocol.Handlers.StructuredComponents.Registries;
public class StructuredComponentsRegistry12111 : StructuredComponentRegistry
{
public StructuredComponentsRegistry12111(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<EmptyComponent>(4, "minecraft:unbreakable");
RegisterComponent<UseEffectsComponent>(5, "minecraft:use_effects");
RegisterComponent<CustomNameComponent>(6, "minecraft:custom_name");
RegisterComponent<PotionDurationScaleComponent>(7, "minecraft:minimum_attack_charge");
RegisterComponent<RegistryEitherHolderComponent>(8, "minecraft:damage_type");
RegisterComponent<ItemNameComponent>(9, "minecraft:item_name");
RegisterComponent<ItemModelComponent>(10, "minecraft:item_model");
RegisterComponent<LoreNameComponent1206>(11, "minecraft:lore");
RegisterComponent<RarityComponent>(12, "minecraft:rarity");
RegisterComponent<EnchantmentsComponent>(13, "minecraft:enchantments");
RegisterComponent<CanPlaceOnComponent>(14, "minecraft:can_place_on");
RegisterComponent<CanBreakComponent>(15, "minecraft:can_break");
RegisterComponent<AttributeModifiersComponent>(16, "minecraft:attribute_modifiers");
RegisterComponent<CustomModelDataComponent>(17, "minecraft:custom_model_data");
RegisterComponent<TooltipDisplayComponent>(18, "minecraft:tooltip_display");
RegisterComponent<RepairCostComponent>(19, "minecraft:repair_cost");
RegisterComponent<CreativeSlotLockComponent>(20, "minecraft:creative_slot_lock");
RegisterComponent<EnchantmentGlintOverrideComponent>(21, "minecraft:enchantment_glint_override");
RegisterComponent<IntangibleProjectileComponent>(22, "minecraft:intangible_projectile");
RegisterComponent<FoodComponent1212>(23, "minecraft:food");
RegisterComponent<ConsumableComponent>(24, "minecraft:consumable");
RegisterComponent<UseRemainderComponent>(25, "minecraft:use_remainder");
RegisterComponent<UseCooldownComponent>(26, "minecraft:use_cooldown");
RegisterComponent<DamageResistantComponent>(27, "minecraft:damage_resistant");
RegisterComponent<ToolComponent>(28, "minecraft:tool");
RegisterComponent<WeaponComponent>(29, "minecraft:weapon");
RegisterComponent<AttackRangeComponent>(30, "minecraft:attack_range");
RegisterComponent<EnchantableComponent>(31, "minecraft:enchantable");
RegisterComponent<EquippableComponent>(32, "minecraft:equippable");
RegisterComponent<RepairableComponent>(33, "minecraft:repairable");
RegisterComponent<GliderComponent>(34, "minecraft:glider");
RegisterComponent<TooltipStyleComponent>(35, "minecraft:tooltip_style");
RegisterComponent<DeathProtectionComponent>(36, "minecraft:death_protection");
RegisterComponent<BlocksAttacksComponent>(37, "minecraft:blocks_attacks");
RegisterComponent<PiercingWeaponComponent>(38, "minecraft:piercing_weapon");
RegisterComponent<KineticWeaponComponent>(39, "minecraft:kinetic_weapon");
RegisterComponent<SwingAnimationComponent>(40, "minecraft:swing_animation");
RegisterComponent<StoredEnchantmentsComponent>(41, "minecraft:stored_enchantments");
RegisterComponent<DyeColorComponent>(42, "minecraft:dyed_color");
RegisterComponent<MapColorComponent>(43, "minecraft:map_color");
RegisterComponent<MapIdComponent>(44, "minecraft:map_id");
RegisterComponent<MapDecorationsComponent>(45, "minecraft:map_decorations");
RegisterComponent<MapPostProcessingComponent>(46, "minecraft:map_post_processing");
RegisterComponent<ChargedProjectilesComponent>(47, "minecraft:charged_projectiles");
RegisterComponent<BundleContentsComponent>(48, "minecraft:bundle_contents");
RegisterComponent<PotionContentsComponent>(49, "minecraft:potion_contents");
RegisterComponent<PotionDurationScaleComponent>(50, "minecraft:potion_duration_scale");
RegisterComponent<SuspiciousStewEffectsComponent>(51, "minecraft:suspicious_stew_effects");
RegisterComponent<WritableBlookContentComponent>(52, "minecraft:writable_book_content");
RegisterComponent<WrittenBlookContentComponent>(53, "minecraft:written_book_content");
RegisterComponent<TrimComponent>(54, "minecraft:trim");
RegisterComponent<DebugStickStateComponent>(55, "minecraft:debug_stick_state");
RegisterComponent<EntityDataComponent>(56, "minecraft:entity_data");
RegisterComponent<BucketEntityDataComponent>(57, "minecraft:bucket_entity_data");
RegisterComponent<BlockEntityDataComponent>(58, "minecraft:block_entity_data");
RegisterComponent<InstrumentComponent1215>(59, "minecraft:instrument");
RegisterComponent<ProvidesTrimMaterialComponent>(60, "minecraft:provides_trim_material");
RegisterComponent<OmniousBottleAmplifierComponent>(61, "minecraft:ominous_bottle_amplifier");
RegisterComponent<JukeBoxPlayableComponent>(62, "minecraft:jukebox_playable");
RegisterComponent<ProvidesBannerPatternsComponent>(63, "minecraft:provides_banner_patterns");
RegisterComponent<RecipesComponent>(64, "minecraft:recipes");
RegisterComponent<LodestoneTrackerComponent>(65, "minecraft:lodestone_tracker");
RegisterComponent<FireworkExplosionComponent>(66, "minecraft:firework_explosion");
RegisterComponent<FireworksComponent>(67, "minecraft:fireworks");
RegisterComponent<ProfileComponent>(68, "minecraft:profile");
RegisterComponent<NoteBlockSoundComponent>(69, "minecraft:note_block_sound");
RegisterComponent<BannerPatternsComponent>(70, "minecraft:banner_patterns");
RegisterComponent<BaseColorComponent>(71, "minecraft:base_color");
RegisterComponent<PotDecorationsComponent>(72, "minecraft:pot_decorations");
RegisterComponent<ContainerComponent>(73, "minecraft:container");
RegisterComponent<BlockStateComponent>(74, "minecraft:block_state");
RegisterComponent<BeesComponent>(75, "minecraft:bees");
RegisterComponent<LockComponent>(76, "minecraft:lock");
RegisterComponent<ContainerLootComponent>(77, "minecraft:container_loot");
RegisterComponent<SoundEventHolderComponent>(78, "minecraft:break_sound");
RegisterComponent<VarIntComponent>(79, "minecraft:villager/variant");
RegisterComponent<VarIntComponent>(80, "minecraft:wolf/variant");
RegisterComponent<VarIntComponent>(81, "minecraft:wolf/sound_variant");
RegisterComponent<VarIntComponent>(82, "minecraft:wolf/collar");
RegisterComponent<VarIntComponent>(83, "minecraft:fox/variant");
RegisterComponent<VarIntComponent>(84, "minecraft:salmon/size");
RegisterComponent<VarIntComponent>(85, "minecraft:parrot/variant");
RegisterComponent<VarIntComponent>(86, "minecraft:tropical_fish/pattern");
RegisterComponent<VarIntComponent>(87, "minecraft:tropical_fish/base_color");
RegisterComponent<VarIntComponent>(88, "minecraft:tropical_fish/pattern_color");
RegisterComponent<VarIntComponent>(89, "minecraft:mooshroom/variant");
RegisterComponent<VarIntComponent>(90, "minecraft:rabbit/variant");
RegisterComponent<VarIntComponent>(91, "minecraft:pig/variant");
RegisterComponent<VarIntComponent>(92, "minecraft:cow/variant");
RegisterComponent<EitherHolderComponent>(93, "minecraft:chicken/variant");
RegisterComponent<RegistryEitherHolderComponent>(94, "minecraft:zombie_nautilus/variant");
RegisterComponent<VarIntComponent>(95, "minecraft:frog/variant");
RegisterComponent<VarIntComponent>(96, "minecraft:horse/variant");
RegisterComponent<PaintingVariantHolderComponent>(97, "minecraft:painting/variant");
RegisterComponent<VarIntComponent>(98, "minecraft:llama/variant");
RegisterComponent<VarIntComponent>(99, "minecraft:axolotl/variant");
RegisterComponent<VarIntComponent>(100, "minecraft:cat/variant");
RegisterComponent<VarIntComponent>(101, "minecraft:cat/collar");
RegisterComponent<VarIntComponent>(102, "minecraft:sheep/color");
RegisterComponent<VarIntComponent>(103, "minecraft:shulker/color");
}
}

View file

@ -21,7 +21,6 @@ public class StructuredComponentsHandler
{
Protocol18Handler.MC_1_20_6_Version => typeof(SubComponentRegistry1206),
Protocol18Handler.MC_1_21_Version => typeof(SubComponentRegistry121),
>= Protocol18Handler.MC_1_21_5_Version => typeof(SubComponentRegistry1212),
>= Protocol18Handler.MC_1_21_2_Version => typeof(SubComponentRegistry1212),
_ => throw new NotSupportedException($"Protocol version {protocolVersion} is not supported for subcomponent registries!")
};
@ -34,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_11_Version => typeof(StructuredComponentsRegistry12111),
>= Protocol18Handler.MC_1_21_5_Version => typeof(StructuredComponentsRegistry1215),
>= Protocol18Handler.MC_1_21_2_Version => typeof(StructuredComponentsRegistry1212),
_ => throw new NotSupportedException($"Protocol version {protocolVersion} is not supported for structured component registries!")

View file

@ -154,7 +154,7 @@ namespace MinecraftClient.Protocol
{
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, 767, 768,
769, 770, 771, 772, 773
769, 770, 771, 772, 773, 774
};
if (Array.IndexOf(suppoertedVersionsProtocol18, protocolVersion) > -1)
@ -368,6 +368,8 @@ namespace MinecraftClient.Protocol
case "1.21.9":
case "1.21.10":
return 773;
case "1.21.11":
return 774;
default:
return 0;
}
@ -455,6 +457,7 @@ namespace MinecraftClient.Protocol
771 => "1.21.6",
772 => "1.21.7",
773 => "1.21.9",
774 => "1.21.11",
_ => "0.0"
};
}

View file

@ -62,6 +62,8 @@ FIELD_TO_ENUM = {
"VECTOR3": "Vector3",
"QUATERNION": "Quaternion",
"RESOLVABLE_PROFILE": "ResolvableProfile",
"ZOMBIE_NAUTILUS_VARIANT": "ZombieNautilusVariant",
"HUMANOID_ARM": "HumanoidArm",
}