Fix entity metadata handling and dimension handling in 1.19.2

Fix entity metadata handling and dimension handling in 1.19.2
This commit is contained in:
BruceChen 2022-09-16 12:08:13 +08:00 committed by GitHub
commit 59e02c2da9
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
6 changed files with 68 additions and 37 deletions

View file

@ -91,7 +91,7 @@ namespace MinecraftClient.Mapping
/// <summary>
/// Entity metadata
/// </summary>
public Dictionary<int, object> Metadata;
public Dictionary<int, object?> Metadata;
/// <summary>
/// Entity equipment

View file

@ -3135,31 +3135,32 @@ namespace MinecraftClient
/// </summary>
/// <param name="entityID">Entity ID</param>
/// <param name="metadata">The metadata of the entity</param>
public void OnEntityMetadata(int entityID, Dictionary<int, object> metadata)
public void OnEntityMetadata(int entityID, Dictionary<int, object?> metadata)
{
if (entities.ContainsKey(entityID))
{
Entity entity = entities[entityID];
entity.Metadata = metadata;
if (entity.Type.ContainsItem() && metadata.ContainsKey(7) && metadata[7] != null && metadata[7].GetType() == typeof(Item))
if (entity.Type.ContainsItem() && metadata.TryGetValue(7, out object? itemObj) && itemObj != null && itemObj.GetType() == typeof(Item))
{
Item item = (Item)metadata[7];
Item item = (Item)itemObj;
if (item == null)
entity.Item = new Item(ItemType.Air, 0, null);
else entity.Item = item;
}
if (metadata.ContainsKey(6) && metadata[6] != null && metadata[6].GetType() == typeof(Int32))
if (metadata.TryGetValue(6, out object? poseObj) && poseObj != null && poseObj.GetType() == typeof(Int32))
{
entity.Pose = (EntityPose)metadata[6];
entity.Pose = (EntityPose)poseObj;
}
if (metadata.ContainsKey(2) && metadata[2] != null && metadata[2].GetType() == typeof(string))
if (metadata.TryGetValue(2, out object? nameObj) && nameObj != null && nameObj.GetType() == typeof(string))
{
entity.CustomNameJson = metadata[2].ToString();
entity.CustomName = ChatParser.ParseText(metadata[2].ToString());
string name = nameObj.ToString()!;
entity.CustomNameJson = name;
entity.CustomName = ChatParser.ParseText(name);
}
if (metadata.ContainsKey(3) && metadata[3] != null && metadata[3].GetType() == typeof(bool))
if (metadata.TryGetValue(3, out object? nameVisableObj) && nameVisableObj != null && nameVisableObj.GetType() == typeof(bool))
{
entity.IsCustomNameVisible = bool.Parse(metadata[3].ToString());
entity.IsCustomNameVisible = bool.Parse(nameVisableObj.ToString()!);
}
DispatchBotEvent(bot => bot.OnEntityMetadata(entity, metadata));
}

View file

@ -580,9 +580,9 @@ namespace MinecraftClient.Protocol.Handlers
}
}
public Dictionary<int, object> ReadNextMetadata(Queue<byte> cache, ItemPalette itemPalette)
public Dictionary<int, object?> ReadNextMetadata(Queue<byte> cache, ItemPalette itemPalette)
{
Dictionary<int, object> data = new Dictionary<int, object>();
Dictionary<int, object?> data = new();
byte key = ReadNextByte(cache);
while (key != 0xff)
{
@ -600,7 +600,7 @@ namespace MinecraftClient.Protocol.Handlers
}
}
// Value's data type is depended on Type
object value = null;
object? value = null;
// This is backward compatible since new type is appended to the end
// Version upgrade note
@ -625,9 +625,7 @@ namespace MinecraftClient.Protocol.Handlers
break;
case 5: // Optional Chat
if (ReadNextBool(cache))
{
value = ReadNextString(cache);
}
break;
case 6: // Slot
value = ReadNextItemSlot(cache, itemPalette);
@ -636,11 +634,12 @@ namespace MinecraftClient.Protocol.Handlers
value = ReadNextBool(cache);
break;
case 8: // Rotation (3x floats)
List<float> t = new List<float>();
t.Add(ReadNextFloat(cache));
t.Add(ReadNextFloat(cache));
t.Add(ReadNextFloat(cache));
value = t;
value = new List<float>
{
ReadNextFloat(cache),
ReadNextFloat(cache),
ReadNextFloat(cache)
};
break;
case 9: // Position
value = ReadNextLocation(cache);
@ -689,11 +688,12 @@ namespace MinecraftClient.Protocol.Handlers
}
break;
case 16: // Villager Data (3x VarInt)
List<int> d = new List<int>();
d.Add(ReadNextVarInt(cache));
d.Add(ReadNextVarInt(cache));
d.Add(ReadNextVarInt(cache));
value = d;
value = new List<int>
{
ReadNextVarInt(cache),
ReadNextVarInt(cache),
ReadNextVarInt(cache)
};
break;
case 17: // Optional VarInt
if (ReadNextBool(cache))
@ -704,6 +704,21 @@ namespace MinecraftClient.Protocol.Handlers
case 18: // Pose
value = ReadNextVarInt(cache);
break;
case 19: // Cat Variant
value = ReadNextVarInt(cache);
break;
case 20: // Frog Varint
value = ReadNextVarInt(cache);
break;
case 21: // GlobalPos at 1.19.2+; Painting Variant at 1.19-
if (protocolversion <= Protocol18Handler.MC_1_19_Version)
value = ReadNextVarInt(cache);
else
value = null; // Dimension and blockPos, currently not in use
break;
case 22: // Painting Variant
value = ReadNextVarInt(cache);
break;
default:
throw new System.IO.InvalidDataException("Unknown Metadata Type ID " + type + ". Is this up to date for new MC Version?");
}

View file

@ -381,11 +381,12 @@ namespace MinecraftClient.Protocol.Handlers
// String identifier: 1.16 and 1.16.1
// varInt: [1.9.1 to 1.15.2]
// byte: below 1.9.1
string? dimensionTypeName = null;
Dictionary<string, object>? dimensionType = null;
if (protocolVersion >= MC_1_16_Version)
{
if (protocolVersion >= MC_1_19_Version)
dataTypes.ReadNextString(packetData); // Dimension Type: Identifier
dimensionTypeName = dataTypes.ReadNextString(packetData); // Dimension Type: Identifier
else if (protocolVersion >= MC_1_16_2_Version)
dimensionType = dataTypes.ReadNextNbt(packetData); // Dimension Type: NBT Tag Compound
else
@ -405,9 +406,15 @@ namespace MinecraftClient.Protocol.Handlers
string dimensionName = dataTypes.ReadNextString(packetData); // Dimension Name (World Name) - 1.16 and above
if (handler.GetTerrainEnabled())
{
if (protocolVersion >= MC_1_16_2_Version && protocolVersion < MC_1_19_Version)
if (protocolVersion >= MC_1_16_2_Version && protocolVersion <= MC_1_18_2_Version)
{
World.StoreOneDimension(dimensionName, dimensionType!);
World.SetDimension(dimensionName);
World.SetDimension(dimensionName);
}
else if (protocolVersion >= MC_1_19_Version)
{
World.SetDimension(dimensionTypeName!);
}
}
}
@ -601,11 +608,12 @@ namespace MinecraftClient.Protocol.Handlers
}
break;
case PacketTypesIn.Respawn:
string? dimensionTypeNameRespawn = null;
Dictionary<string, object>? dimensionTypeRespawn = null;
if (protocolVersion >= MC_1_16_Version)
{
if (protocolVersion >= MC_1_19_Version)
dataTypes.ReadNextString(packetData); // Dimension Type: Identifier
dimensionTypeNameRespawn = dataTypes.ReadNextString(packetData); // Dimension Type: Identifier
else if (protocolVersion >= MC_1_16_2_Version)
dimensionTypeRespawn = dataTypes.ReadNextNbt(packetData); // Dimension Type: NBT Tag Compound
else
@ -622,9 +630,15 @@ namespace MinecraftClient.Protocol.Handlers
string dimensionName = dataTypes.ReadNextString(packetData); // Dimension Name (World Name) - 1.16 and above
if (handler.GetTerrainEnabled())
{
if (protocolVersion >= MC_1_16_2_Version && protocolVersion < MC_1_19_Version)
if (protocolVersion >= MC_1_16_2_Version && protocolVersion <= MC_1_18_2_Version)
{
World.StoreOneDimension(dimensionName, dimensionTypeRespawn!);
World.SetDimension(dimensionName);
World.SetDimension(dimensionName);
}
else if (protocolVersion >= MC_1_19_Version)
{
World.SetDimension(dimensionTypeNameRespawn!);
}
}
}
@ -1456,7 +1470,7 @@ namespace MinecraftClient.Protocol.Handlers
if (handler.GetEntityHandlingEnabled())
{
int EntityID = dataTypes.ReadNextVarInt(packetData);
Dictionary<int, object> metadata = dataTypes.ReadNextMetadata(packetData, itemPalette);
Dictionary<int, object?> metadata = dataTypes.ReadNextMetadata(packetData, itemPalette);
int healthField; // See https://wiki.vg/Entity_metadata#Living_Entity
if (protocolVersion > MC_1_19_2_Version)
@ -1470,8 +1484,9 @@ namespace MinecraftClient.Protocol.Handlers
else
throw new NotImplementedException(Translations.Get("exception.palette.healthfield"));
if (metadata.ContainsKey(healthField) && metadata[healthField] != null && metadata[healthField].GetType() == typeof(float))
handler.OnEntityHealth(EntityID, (float)metadata[healthField]);
if (metadata.TryGetValue(healthField, out object? healthObj) && healthObj != null && healthObj.GetType() == typeof(float))
handler.OnEntityHealth(EntityID, (float)healthObj);
handler.OnEntityMetadata(EntityID, metadata);
}
break;

View file

@ -318,7 +318,7 @@ namespace MinecraftClient.Protocol
/// </summary>
/// <param name="EntityID">Entity ID</param>
/// <param name="metadata">Entity metadata</param>
void OnEntityMetadata(int EntityID, Dictionary<int, object> metadata);
void OnEntityMetadata(int EntityID, Dictionary<int, object?> metadata);
/// <summary>
/// Called when and explosion occurs on the server

View file

@ -383,7 +383,7 @@ namespace MinecraftClient
/// </summary>
/// <param name="entity">Entity</param>
/// <param name="metadata">The metadata of the entity</param>
public virtual void OnEntityMetadata(Entity entity, Dictionary<int, object> metadata) { }
public virtual void OnEntityMetadata(Entity entity, Dictionary<int, object?> metadata) { }
/// <summary>
/// Called when the status of client player have been changed