mirror of
https://github.com/MCCTeam/Minecraft-Console-Client
synced 2026-08-15 13:04:36 +00:00
fix: resolve entity tracking, container interaction, and enchantment mapping issues for 1.21
- SpawnEntity packet handler now registers non-player entities via OnSpawnEntity for protocol >= 1.20.2 (previously only players were tracked, causing 'entity near' to find nothing) - PlaceBlock gains lookAtBlock option that sends a position/rotation update before the block placement packet, fixing containers not opening via useblock - Enchantment registry IDs are now dynamically parsed from server RegistryData (minecraft:enchantment), fixing incorrect enchantment name display in 1.21 - AttributeModifiersComponent uses base SubComponent type to avoid InvalidCastException when parsing 1.21-specific attribute subcomponents Made-with: Cursor
This commit is contained in:
parent
7609832976
commit
896263acc8
5 changed files with 98 additions and 10 deletions
|
|
@ -1,4 +1,4 @@
|
|||
using Brigadier.NET;
|
||||
using Brigadier.NET;
|
||||
using Brigadier.NET.Builder;
|
||||
using MinecraftClient.CommandHandler;
|
||||
using MinecraftClient.Mapping;
|
||||
|
|
@ -48,7 +48,7 @@ namespace MinecraftClient.Commands
|
|||
Location current = handler.GetCurrentLocation();
|
||||
block = block.ToAbsolute(current).ToFloor();
|
||||
Location blockCenter = block.ToCenter();
|
||||
bool res = handler.PlaceBlock(block, Direction.Down);
|
||||
bool res = handler.PlaceBlock(block, Direction.Down, lookAtBlock: true);
|
||||
return r.SetAndReturn(string.Format(Translations.cmd_useblock_use, blockCenter.X, blockCenter.Y, blockCenter.Z, res ? "succeeded" : "failed"), res);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -207,9 +207,74 @@ namespace MinecraftClient.Inventory
|
|||
}
|
||||
|
||||
private static Dictionary<Enchantments, short>? reverseEnchantmentMappings;
|
||||
private static Dictionary<int, Enchantments>? dynamicEnchantmentIdMap;
|
||||
|
||||
private static readonly Dictionary<string, Enchantments> nameToEnchantment = new()
|
||||
{
|
||||
{ "protection", Enchantments.Protection },
|
||||
{ "fire_protection", Enchantments.FireProtection },
|
||||
{ "feather_falling", Enchantments.FeatherFalling },
|
||||
{ "blast_protection", Enchantments.BlastProtection },
|
||||
{ "projectile_protection", Enchantments.ProjectileProtection },
|
||||
{ "respiration", Enchantments.Respiration },
|
||||
{ "aqua_affinity", Enchantments.AquaAffinity },
|
||||
{ "thorns", Enchantments.Thorns },
|
||||
{ "depth_strider", Enchantments.DepthStrider },
|
||||
{ "frost_walker", Enchantments.FrostWalker },
|
||||
{ "binding_curse", Enchantments.BindingCurse },
|
||||
{ "soul_speed", Enchantments.SoulSpeed },
|
||||
{ "swift_sneak", Enchantments.SwiftSneak },
|
||||
{ "sharpness", Enchantments.Sharpness },
|
||||
{ "smite", Enchantments.Smite },
|
||||
{ "bane_of_arthropods", Enchantments.BaneOfArthropods },
|
||||
{ "knockback", Enchantments.Knockback },
|
||||
{ "fire_aspect", Enchantments.FireAspect },
|
||||
{ "looting", Enchantments.Looting },
|
||||
{ "sweeping_edge", Enchantments.Sweeping },
|
||||
{ "efficiency", Enchantments.Efficiency },
|
||||
{ "silk_touch", Enchantments.SilkTouch },
|
||||
{ "unbreaking", Enchantments.Unbreaking },
|
||||
{ "fortune", Enchantments.Fortune },
|
||||
{ "power", Enchantments.Power },
|
||||
{ "punch", Enchantments.Punch },
|
||||
{ "flame", Enchantments.Flame },
|
||||
{ "infinity", Enchantments.Infinity },
|
||||
{ "luck_of_the_sea", Enchantments.LuckOfTheSea },
|
||||
{ "lure", Enchantments.Lure },
|
||||
{ "loyalty", Enchantments.Loyalty },
|
||||
{ "impaling", Enchantments.Impaling },
|
||||
{ "riptide", Enchantments.Riptide },
|
||||
{ "channeling", Enchantments.Channeling },
|
||||
{ "multishot", Enchantments.Multishot },
|
||||
{ "quick_charge", Enchantments.QuickCharge },
|
||||
{ "piercing", Enchantments.Piercing },
|
||||
{ "density", Enchantments.Density },
|
||||
{ "breach", Enchantments.Breach },
|
||||
{ "wind_burst", Enchantments.WindBurst },
|
||||
{ "mending", Enchantments.Mending },
|
||||
{ "vanishing_curse", Enchantments.VanishingCurse },
|
||||
};
|
||||
|
||||
/// <summary>
|
||||
/// Set the dynamic enchantment ID map from server RegistryData.
|
||||
/// Called during configuration phase when receiving minecraft:enchantment registry.
|
||||
/// </summary>
|
||||
public static void SetDynamicEnchantmentIdMap(Dictionary<int, string> idMap)
|
||||
{
|
||||
dynamicEnchantmentIdMap = new Dictionary<int, Enchantments>();
|
||||
foreach (var kvp in idMap)
|
||||
{
|
||||
var name = kvp.Value.StartsWith("minecraft:") ? kvp.Value.Substring("minecraft:".Length) : kvp.Value;
|
||||
if (nameToEnchantment.TryGetValue(name, out var enchantment))
|
||||
dynamicEnchantmentIdMap[kvp.Key] = enchantment;
|
||||
}
|
||||
reverseEnchantmentMappings = null;
|
||||
}
|
||||
|
||||
public static Enchantments GetEnchantmentByRegistryId1206(int id)
|
||||
{
|
||||
if (dynamicEnchantmentIdMap != null && dynamicEnchantmentIdMap.TryGetValue(id, out var dynValue))
|
||||
return dynValue;
|
||||
if (enchantmentMappings.TryGetValue((short)id, out var value))
|
||||
return value;
|
||||
return (Enchantments)(-1);
|
||||
|
|
@ -220,8 +285,16 @@ namespace MinecraftClient.Inventory
|
|||
if (reverseEnchantmentMappings == null)
|
||||
{
|
||||
reverseEnchantmentMappings = new Dictionary<Enchantments, short>();
|
||||
foreach (var kvp in enchantmentMappings)
|
||||
reverseEnchantmentMappings[kvp.Value] = kvp.Key;
|
||||
if (dynamicEnchantmentIdMap != null)
|
||||
{
|
||||
foreach (var kvp in dynamicEnchantmentIdMap)
|
||||
reverseEnchantmentMappings[kvp.Value] = (short)kvp.Key;
|
||||
}
|
||||
else
|
||||
{
|
||||
foreach (var kvp in enchantmentMappings)
|
||||
reverseEnchantmentMappings[kvp.Value] = kvp.Key;
|
||||
}
|
||||
}
|
||||
return reverseEnchantmentMappings.TryGetValue(enchantment, out var id) ? id : -1;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2392,10 +2392,19 @@ namespace MinecraftClient
|
|||
/// </summary>
|
||||
/// <param name="location">Location to place block to</param>
|
||||
/// <param name="blockFace">Block face (e.g. Direction.Down when clicking on the block below to place this block)</param>
|
||||
/// <param name="lookAtBlock">Also look at the block before interacting</param>
|
||||
/// <returns>TRUE if successfully placed</returns>
|
||||
public bool PlaceBlock(Location location, Direction blockFace, Hand hand = Hand.MainHand)
|
||||
public bool PlaceBlock(Location location, Direction blockFace, Hand hand = Hand.MainHand, bool lookAtBlock = false)
|
||||
{
|
||||
return InvokeOnMainThread(() => handler.SendPlayerBlockPlacement((int)hand, location, blockFace, sequenceId++));
|
||||
return InvokeOnMainThread(() =>
|
||||
{
|
||||
if (lookAtBlock)
|
||||
{
|
||||
UpdateLocation(GetCurrentLocation(), location.ToCenter());
|
||||
handler.SendLocationUpdate(GetCurrentLocation(), Movement.IsOnGround(world, GetCurrentLocation()), _yaw, _pitch);
|
||||
}
|
||||
return handler.SendPlayerBlockPlacement((int)hand, location, blockFace, sequenceId++);
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -465,10 +465,12 @@ namespace MinecraftClient.Protocol.Handlers
|
|||
var isChat = registryId == "minecraft:chat_type";
|
||||
var isDimension = registryId == "minecraft:dimension_type";
|
||||
var isAttribute = registryId == "minecraft:attribute";
|
||||
var isEnchantment = registryId == "minecraft:enchantment";
|
||||
|
||||
var availableChats = isChat ? new Dictionary<int, string>() : null;
|
||||
var dimensionIdMap = isDimension ? new Dictionary<int, string>() : null;
|
||||
var attributeIdMap = isAttribute ? new Dictionary<int, string>() : null;
|
||||
var enchantmentIdMap = isEnchantment ? new Dictionary<int, string>() : null;
|
||||
|
||||
for (var i = 0; i < entryCount; i++)
|
||||
{
|
||||
|
|
@ -489,12 +491,13 @@ namespace MinecraftClient.Protocol.Handlers
|
|||
}
|
||||
else if (isAttribute)
|
||||
{
|
||||
// Strip "minecraft:" prefix to match the format used in EntityProperties packets
|
||||
var attrName = entryId.StartsWith("minecraft:")
|
||||
? entryId.Substring("minecraft:".Length)
|
||||
: entryId;
|
||||
attributeIdMap!.Add(i, attrName);
|
||||
}
|
||||
else if (isEnchantment)
|
||||
enchantmentIdMap!.Add(i, entryId);
|
||||
}
|
||||
|
||||
if (isChat)
|
||||
|
|
@ -507,6 +510,8 @@ namespace MinecraftClient.Protocol.Handlers
|
|||
}
|
||||
else if (isAttribute)
|
||||
World.SetAttributeIdMap(attributeIdMap!);
|
||||
else if (isEnchantment)
|
||||
EnchantmentMapping.SetDynamicEnchantmentIdMap(enchantmentIdMap!);
|
||||
}
|
||||
|
||||
break;
|
||||
|
|
@ -2339,6 +2344,8 @@ namespace MinecraftClient.Protocol.Handlers
|
|||
{
|
||||
if (entity.Type == EntityType.Player)
|
||||
handler.OnSpawnPlayer(entity.ID, entity.UUID, entity.Location, (byte)entity.Yaw, (byte)entity.Pitch);
|
||||
else
|
||||
handler.OnSpawnEntity(entity);
|
||||
|
||||
break;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,7 +2,6 @@ using System;
|
|||
using System.Collections.Generic;
|
||||
using MinecraftClient.Inventory.ItemPalettes;
|
||||
using MinecraftClient.Protocol.Handlers.StructuredComponents.Components.Subcomponents;
|
||||
using MinecraftClient.Protocol.Handlers.StructuredComponents.Components.Subcomponents._1_20_6;
|
||||
using MinecraftClient.Protocol.Handlers.StructuredComponents.Core;
|
||||
|
||||
namespace MinecraftClient.Protocol.Handlers.StructuredComponents.Components._1_20_6;
|
||||
|
|
@ -11,7 +10,7 @@ public class AttributeModifiersComponent(DataTypes dataTypes, ItemPalette itemPa
|
|||
: StructuredComponent(dataTypes, itemPalette, subComponentRegistry)
|
||||
{
|
||||
public int NumberOfAttributes { get; set; }
|
||||
public List<AttributeSubComponent> Attributes { get; set; } = new();
|
||||
public List<SubComponent> Attributes { get; set; } = new();
|
||||
public bool ShowInTooltip { get; set; }
|
||||
|
||||
public override void Parse(Queue<byte> data)
|
||||
|
|
@ -19,7 +18,7 @@ public class AttributeModifiersComponent(DataTypes dataTypes, ItemPalette itemPa
|
|||
NumberOfAttributes = dataTypes.ReadNextVarInt(data);
|
||||
|
||||
for (var i = 0; i < NumberOfAttributes; i++)
|
||||
Attributes.Add((AttributeSubComponent)subComponentRegistry.ParseSubComponent(SubComponents.Attribute, data));
|
||||
Attributes.Add(subComponentRegistry.ParseSubComponent(SubComponents.Attribute, data));
|
||||
|
||||
ShowInTooltip = dataTypes.ReadNextBool(data);
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue