mirror of
https://github.com/MCCTeam/Minecraft-Console-Client
synced 2026-08-15 13:04:36 +00:00
Dynamically parse minecraft:attribute registry from server RegistryData
In 1.20.6+, EntityProperties packets reference attributes by VarInt registry IDs instead of string names. Previously, a hardcoded dictionary of 22 attribute entries (matching the vanilla 1.20.6 registry) was used to map these IDs back to names. This works for vanilla servers but would fail silently for modded servers that add custom attributes — any unknown ID would be reported as "unknown". This commit replaces the hardcoded attribute dictionary with dynamic registry parsing, following the same pattern already used for dimension_type and chat_type registries: - World.cs: Add static `attributeIdMap` field, `SetAttributeIdMap()` and `GetAttributeNameById()` methods for storing/querying attribute names by their VarInt registry IDs. - Protocol18.cs (RegistryData handler): When the server sends a `minecraft:attribute` registry during the Configuration phase, parse all entries and store the ID→name mapping. The `minecraft:` prefix is stripped from entry names to match the format used in EntityProperties packets (e.g. "minecraft:generic.armor" → "generic.armor"). - Protocol18.cs (EntityProperties handler): Remove the hardcoded 22-entry `attributeDictionary` and use `World.GetAttributeNameById()` instead. Unknown IDs still fall back to "unknown" for safety. Also closes issue #4 (Disconnect packet extra boolean) — verified that both Play and Configuration phase Disconnect handlers already use `ReadNextChat()` (NBT format since 1.20.4+), matching the 1.20.6 protocol spec. No code changes needed; updated tracking document to mark as closed. Made-with: Cursor
This commit is contained in:
parent
967f67190c
commit
99ac3d028a
2 changed files with 40 additions and 30 deletions
|
|
@ -28,6 +28,11 @@ namespace MinecraftClient.Mapping
|
|||
/// </summary>
|
||||
private static Dictionary<int, string> dimensionIdMap = new();
|
||||
|
||||
/// <summary>
|
||||
/// VarInt ID → attribute name mapping, populated from RegistryData (minecraft:attribute) in 1.20.6+
|
||||
/// </summary>
|
||||
private static Dictionary<int, string> attributeIdMap = new();
|
||||
|
||||
/// <summary>
|
||||
/// Chunk data parsing progress
|
||||
/// </summary>
|
||||
|
|
@ -232,6 +237,19 @@ namespace MinecraftClient.Mapping
|
|||
return dimensionList.Count > 0;
|
||||
}
|
||||
|
||||
public static void SetAttributeIdMap(Dictionary<int, string> idMap)
|
||||
{
|
||||
attributeIdMap = idMap;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get attribute name by its registry VarInt ID. Returns null if the ID is unknown.
|
||||
/// </summary>
|
||||
public static string? GetAttributeNameById(int id)
|
||||
{
|
||||
return attributeIdMap.TryGetValue(id, out var name) ? name : null;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Store one dimension - Directly used in 1.16.2 to 1.18.2
|
||||
/// </summary>
|
||||
|
|
|
|||
|
|
@ -463,9 +463,11 @@ namespace MinecraftClient.Protocol.Handlers
|
|||
|
||||
var isChat = registryId == "minecraft:chat_type";
|
||||
var isDimension = registryId == "minecraft:dimension_type";
|
||||
var isAttribute = registryId == "minecraft:attribute";
|
||||
|
||||
var availableChats = isChat ? new Dictionary<int, string>() : null;
|
||||
var dimensionIdMap = isDimension ? new Dictionary<int, string>() : null;
|
||||
var attributeIdMap = isAttribute ? new Dictionary<int, string>() : null;
|
||||
|
||||
for (var i = 0; i < entryCount; i++)
|
||||
{
|
||||
|
|
@ -484,6 +486,14 @@ namespace MinecraftClient.Protocol.Handlers
|
|||
if (nbtData != null && handler.GetTerrainEnabled())
|
||||
World.StoreOneDimension(entryId, nbtData);
|
||||
}
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
if (isChat)
|
||||
|
|
@ -494,6 +504,8 @@ namespace MinecraftClient.Protocol.Handlers
|
|||
if (!handler.GetTerrainEnabled() || !World.HasAnyDimension())
|
||||
World.LoadDefaultDimensions1206Plus();
|
||||
}
|
||||
else if (isAttribute)
|
||||
World.SetAttributeIdMap(attributeIdMap!);
|
||||
}
|
||||
|
||||
break;
|
||||
|
|
@ -2502,39 +2514,19 @@ namespace MinecraftClient.Protocol.Handlers
|
|||
? dataTypes.ReadNextVarInt(packetData)
|
||||
: dataTypes.ReadNextInt(packetData);
|
||||
|
||||
var attributeDictionary = new Dictionary<int, string>
|
||||
{
|
||||
{ 0, "generic.armor" },
|
||||
{ 1, "generic.armor_toughness" },
|
||||
{ 2, "generic.attack_damage" },
|
||||
{ 3, "generic.attack_knockback" },
|
||||
{ 4, "generic.attack_speed" },
|
||||
{ 5, "player.block_break_speed" },
|
||||
{ 6, "player.block_interaction_range" },
|
||||
{ 7, "player.entity_interaction_range" },
|
||||
{ 8, "generic.fall_damage_multiplier" },
|
||||
{ 9, "generic.flying_speed" },
|
||||
{ 10, "generic.follow_range" },
|
||||
{ 11, "generic.gravity" },
|
||||
{ 12, "generic.jump_strength" },
|
||||
{ 13, "generic.knockback_resistance" },
|
||||
{ 14, "generic.luck" },
|
||||
{ 15, "generic.max_absorption" },
|
||||
{ 16, "generic.max_health" },
|
||||
{ 17, "generic.movement_speed" },
|
||||
{ 18, "generic.safe_fall_distance" },
|
||||
{ 19, "generic.scale" },
|
||||
{ 20, "zombie.spawn_reinforcements" },
|
||||
{ 21, "generic.step_height" }
|
||||
};
|
||||
|
||||
Dictionary<string, double> keys = new();
|
||||
for (var i = 0; i < numberOfProperties; i++)
|
||||
{
|
||||
var propertyKey = protocolVersion < MC_1_20_6_Version
|
||||
? dataTypes.ReadNextString(packetData)
|
||||
: (attributeDictionary.TryGetValue(dataTypes.ReadNextVarInt(packetData), out var attrName)
|
||||
? attrName : "unknown");
|
||||
string propertyKey;
|
||||
if (protocolVersion < MC_1_20_6_Version)
|
||||
{
|
||||
propertyKey = dataTypes.ReadNextString(packetData);
|
||||
}
|
||||
else
|
||||
{
|
||||
var attrId = dataTypes.ReadNextVarInt(packetData);
|
||||
propertyKey = World.GetAttributeNameById(attrId) ?? "unknown";
|
||||
}
|
||||
var propertyValue2 = dataTypes.ReadNextDouble(packetData);
|
||||
|
||||
List<double> op0 = new();
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue