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,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);
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue