Wire up entity metadata palette

This commit is contained in:
ReinforceZwei 2023-03-24 19:46:25 +08:00
parent 1a22002bde
commit f4ad24746c
6 changed files with 225 additions and 337 deletions

View file

@ -25,6 +25,7 @@ public enum EntityMetaDataType
Pose, Pose,
CatVariant, CatVariant,
FrogVariant, FrogVariant,
GlobalPosition,
OptionalGlobalPosition, OptionalGlobalPosition,
PaintingVariant, PaintingVariant,
SnifferState, SnifferState,

View file

@ -1,3 +1,6 @@
using MinecraftClient.Mapping.EntityMetadataPalettes;
using MinecraftClient.Protocol.Handlers;
using System;
using System.Collections.Generic; using System.Collections.Generic;
namespace MinecraftClient.Mapping; namespace MinecraftClient.Mapping;
@ -5,4 +8,29 @@ namespace MinecraftClient.Mapping;
public abstract class EntityMetadataPalette public abstract class EntityMetadataPalette
{ {
public abstract Dictionary<int, EntityMetaDataType> GetEntityMetadataMappingsList(); public abstract Dictionary<int, EntityMetaDataType> GetEntityMetadataMappingsList();
public EntityMetaDataType GetDataType(int typeId)
{
return GetEntityMetadataMappingsList()[typeId];
}
public static EntityMetadataPalette GetPalette(int protocolVersion)
{
if (protocolVersion < Protocol18Handler.MC_1_9_1_Version)
return new EntityMetadataPalette19();
else if (protocolVersion <= Protocol18Handler.MC_1_11_2_Version)
return new EntityMetadataPalette111();
else if (protocolVersion <= Protocol18Handler.MC_1_13_2_Version)
return new EntityMetadataPalette113();
else if (protocolVersion <= Protocol18Handler.MC_1_14_Version)
return new EntityMetadataPalette114();
else if (protocolVersion <= Protocol18Handler.MC_1_19_2_Version)
return new EntityMetadataPalette1191();
else if (protocolVersion <= Protocol18Handler.MC_1_19_3_Version)
return new EntityMetadataPalette1193();
else if (protocolVersion <= Protocol18Handler.MC_1_19_4_Version)
return new EntityMetadataPalette1194();
else
throw new NotImplementedException();
}
} }

View file

@ -27,7 +27,7 @@ public class EntityMetadataPalette1191 : EntityMetadataPalette
{ 18, EntityMetaDataType.Pose }, { 18, EntityMetaDataType.Pose },
{ 19, EntityMetaDataType.CatVariant }, { 19, EntityMetaDataType.CatVariant },
{ 20, EntityMetaDataType.FrogVariant }, { 20, EntityMetaDataType.FrogVariant },
{ 21, EntityMetaDataType.OptionalGlobalPosition }, { 21, EntityMetaDataType.GlobalPosition },
{ 22, EntityMetaDataType.PaintingVariant } { 22, EntityMetaDataType.PaintingVariant }
}; };

View file

@ -28,7 +28,7 @@ public class EntityMetadataPalette1193 : EntityMetadataPalette
{ 19, EntityMetaDataType.Pose }, { 19, EntityMetaDataType.Pose },
{ 20, EntityMetaDataType.CatVariant }, { 20, EntityMetaDataType.CatVariant },
{ 21, EntityMetaDataType.FrogVariant }, { 21, EntityMetaDataType.FrogVariant },
{ 22, EntityMetaDataType.OptionalGlobalPosition }, { 22, EntityMetaDataType.GlobalPosition },
{ 23, EntityMetaDataType.PaintingVariant } { 23, EntityMetaDataType.PaintingVariant }
}; };

View file

@ -590,63 +590,62 @@ namespace MinecraftClient.Protocol.Handlers
} }
//TODO: Refactor this to use new Entity Metadata Palettes //TODO: Refactor this to use new Entity Metadata Palettes
public Dictionary<int, object?> ReadNextMetadata(Queue<byte> cache, ItemPalette itemPalette) public Dictionary<int, object?> ReadNextMetadata(Queue<byte> cache, ItemPalette itemPalette, EntityMetadataPalette metadataPalette)
{ {
if (protocolversion <= Protocol18Handler.MC_1_8_Version)
throw new NotImplementedException(); // Require sepcial implementation
Dictionary<int, object?> data = new(); Dictionary<int, object?> data = new();
byte key = ReadNextByte(cache); byte key = ReadNextByte(cache);
while (key != 0xff) while (key != 0xff)
{ {
int type = ReadNextVarInt(cache); int typeId = ReadNextVarInt(cache);
EntityMetaDataType type;
try
{
type = metadataPalette.GetDataType(typeId);
}
catch (KeyNotFoundException)
{
throw new System.IO.InvalidDataException("Unknown Metadata Type ID " + typeId +
". Is this up to date for new MC Version?");
}
// Value's data type is depended on Type // Value's data type is depended on Type
object? value = null; object? value = null;
// starting from 1.13, Optional Chat is inserted as number 5 in 1.13 and IDs after 5 got shifted.
// Increase type ID by 1 if
// - below 1.13
// - type ID larger than 4
if (protocolversion < Protocol18Handler.MC_1_13_Version)
{
if (type > 4)
++type;
}
// Temporary
if (protocolversion >= Protocol18Handler.MC_1_19_3_Version)
{
switch (type) switch (type)
{ {
case 0: // byte case EntityMetaDataType.Byte: // byte
value = ReadNextByte(cache); value = ReadNextByte(cache);
break; break;
case 1: // VarInt case EntityMetaDataType.VarInt: // VarInt
value = ReadNextVarInt(cache); value = ReadNextVarInt(cache);
break; break;
case 2: // Long case EntityMetaDataType.VarLong: // Long
value = ReadNextLong(cache); value = ReadNextVarLong(cache);
break; break;
; case EntityMetaDataType.Float: // Float
case 3: // Float
value = ReadNextFloat(cache); value = ReadNextFloat(cache);
break; break;
case 4: // String case EntityMetaDataType.String: // String
value = ReadNextString(cache); value = ReadNextString(cache);
break; break;
case 5: // Chat case EntityMetaDataType.Chat: // Chat
value = ReadNextString(cache); value = ReadNextString(cache);
break; break;
case 6: // Optional Chat case EntityMetaDataType.OptionalChat: // Optional Chat
if (ReadNextBool(cache)) if (ReadNextBool(cache))
value = ReadNextString(cache); value = ReadNextString(cache);
break; break;
case 7: // Slot case EntityMetaDataType.Slot: // Slot
value = ReadNextItemSlot(cache, itemPalette); value = ReadNextItemSlot(cache, itemPalette);
break; break;
case 8: // Boolean case EntityMetaDataType.Boolean: // Boolean
value = ReadNextBool(cache); value = ReadNextBool(cache);
break; break;
case 9: // Rotation (3x floats) case EntityMetaDataType.Rotation: // Rotation (3x floats)
value = new List<float> value = new List<float>
{ {
ReadNextFloat(cache), ReadNextFloat(cache),
@ -654,36 +653,34 @@ namespace MinecraftClient.Protocol.Handlers
ReadNextFloat(cache) ReadNextFloat(cache)
}; };
break; break;
case 10: // Position case EntityMetaDataType.Position: // Position
value = ReadNextLocation(cache); value = ReadNextLocation(cache);
break; break;
case 11: // Optional Position case EntityMetaDataType.OptionalPosition: // Optional Position
if (ReadNextBool(cache)) if (ReadNextBool(cache))
{ {
value = ReadNextLocation(cache); value = ReadNextLocation(cache);
} }
break; break;
case 12: // Direction (VarInt) case EntityMetaDataType.Direction: // Direction (VarInt)
value = ReadNextVarInt(cache); value = ReadNextVarInt(cache);
break; break;
case 13: // Optional UUID case EntityMetaDataType.OptionalUuid: // Optional UUID
if (ReadNextBool(cache)) if (ReadNextBool(cache))
{ {
value = ReadNextUUID(cache); value = ReadNextUUID(cache);
} }
break; break;
case 14: // BlockID (VarInt) case EntityMetaDataType.BlockId: // BlockID (VarInt)
value = ReadNextVarInt(cache); value = ReadNextVarInt(cache);
break; break;
case 15: // Optional BlockID (VarInt) case EntityMetaDataType.OptionalBlockId: // Optional BlockID (VarInt)
value = ReadNextVarInt(cache); value = ReadNextVarInt(cache);
break; break;
case 16: // NBT case EntityMetaDataType.Nbt: // NBT
value = ReadNextNbt(cache); value = ReadNextNbt(cache);
break; break;
case 17: // Particle case EntityMetaDataType.Particle: // Particle
// Currently not handled. Reading data only // Currently not handled. Reading data only
int ParticleID = ReadNextVarInt(cache); int ParticleID = ReadNextVarInt(cache);
// TODO: Go through wiki history and write for every version // TODO: Go through wiki history and write for every version
@ -741,7 +738,7 @@ namespace MinecraftClient.Protocol.Handlers
} }
break; break;
case 18: // Villager Data (3x VarInt) case EntityMetaDataType.VillagerData: // Villager Data (3x VarInt)
value = new List<int> value = new List<int>
{ {
ReadNextVarInt(cache), ReadNextVarInt(cache),
@ -749,41 +746,38 @@ namespace MinecraftClient.Protocol.Handlers
ReadNextVarInt(cache) ReadNextVarInt(cache)
}; };
break; break;
case 19: // Optional VarInt case EntityMetaDataType.OptionalVarInt: // Optional VarInt
if (ReadNextBool(cache)) if (ReadNextBool(cache))
{ {
value = ReadNextVarInt(cache); value = ReadNextVarInt(cache);
} }
break; break;
case 20: // Pose case EntityMetaDataType.Pose: // Pose
value = ReadNextVarInt(cache); value = ReadNextVarInt(cache);
break; break;
case 21: // Cat Variant case EntityMetaDataType.CatVariant: // Cat Variant
value = ReadNextVarInt(cache); value = ReadNextVarInt(cache);
break; break;
case 22: // Frog Varint case EntityMetaDataType.FrogVariant: // Frog Varint
value = ReadNextVarInt(cache); value = ReadNextVarInt(cache);
break; break;
case 23: // GlobalPos at 1.19.2+; Painting Variant at 1.19- case EntityMetaDataType.GlobalPosition: // GlobalPos
if (protocolversion <= Protocol18Handler.MC_1_19_Version)
{
value = ReadNextVarInt(cache);
}
else
{
// Dimension and blockPos, currently not in use // Dimension and blockPos, currently not in use
value = new Tuple<string, Location>(ReadNextString(cache), ReadNextLocation(cache)); value = new Tuple<string, Location>(ReadNextString(cache), ReadNextLocation(cache));
break;
case EntityMetaDataType.OptionalGlobalPosition:
if (ReadNextBool(cache))
{
value = new Tuple<string, Location>(ReadNextString(cache), ReadNextLocation(cache));
} }
break; break;
case 24: // Painting Variant case EntityMetaDataType.PaintingVariant: // Painting Variant
value = ReadNextVarInt(cache); value = ReadNextVarInt(cache);
break; break;
case 25: // Sniffer state case EntityMetaDataType.SnifferState: // Sniffer state
value = ReadNextVarInt(cache); value = ReadNextVarInt(cache);
break; break;
case 26: // Vector 3f case EntityMetaDataType.Vector3: // Vector 3f
value = new List<float> value = new List<float>
{ {
ReadNextFloat(cache), ReadNextFloat(cache),
@ -791,7 +785,7 @@ namespace MinecraftClient.Protocol.Handlers
ReadNextFloat(cache) ReadNextFloat(cache)
}; };
break; break;
case 27: // Quaternion case EntityMetaDataType.Quaternion: // Quaternion
value = new List<float> value = new List<float>
{ {
ReadNextFloat(cache), ReadNextFloat(cache),
@ -800,151 +794,12 @@ namespace MinecraftClient.Protocol.Handlers
ReadNextFloat(cache) ReadNextFloat(cache)
}; };
break; break;
default:
throw new System.IO.InvalidDataException("Unknown Metadata Type ID " + type +
". Is this up to date for new MC Version?");
} }
data[key] = value; data[key] = value;
key = ReadNextByte(cache); key = ReadNextByte(cache);
} }
else ConsoleIO.WriteLine($"Entity MetaData finished {data.Count}");
{
// This is backward compatible since new type is appended to the end
// Version upgrade note
// - Check type ID got shifted or not
// - Add new type if any
switch (type)
{
case 0: // byte
value = ReadNextByte(cache);
break;
case 1: // VarInt
value = ReadNextVarInt(cache);
break;
case 2: // Float
value = ReadNextFloat(cache);
break;
case 3: // String
value = ReadNextString(cache);
break;
case 4: // Chat
value = ReadNextString(cache);
break;
case 5: // Optional Chat
if (ReadNextBool(cache))
value = ReadNextString(cache);
break;
case 6: // Slot
value = ReadNextItemSlot(cache, itemPalette);
break;
case 7: // Boolean
value = ReadNextBool(cache);
break;
case 8: // Rotation (3x floats)
value = new List<float>
{
ReadNextFloat(cache),
ReadNextFloat(cache),
ReadNextFloat(cache)
};
break;
case 9: // Position
value = ReadNextLocation(cache);
break;
case 10: // Optional Position
if (ReadNextBool(cache))
{
value = ReadNextLocation(cache);
}
break;
case 11: // Direction (VarInt)
value = ReadNextVarInt(cache);
break;
case 12: // Optional UUID
if (ReadNextBool(cache))
{
value = ReadNextUUID(cache);
}
break;
case 13: // Optional BlockID (VarInt)
value = ReadNextVarInt(cache);
break;
case 14: // NBT
value = ReadNextNbt(cache);
break;
case 15: // Particle
int ParticleID = ReadNextVarInt(cache);
switch (ParticleID)
{
case 3:
ReadNextVarInt(cache);
break;
case 14:
ReadNextFloat(cache);
ReadNextFloat(cache);
ReadNextFloat(cache);
ReadNextFloat(cache);
break;
case 23:
ReadNextVarInt(cache);
break;
case 32:
ReadNextItemSlot(cache, itemPalette);
break;
}
break;
case 16: // Villager Data (3x VarInt)
value = new List<int>
{
ReadNextVarInt(cache),
ReadNextVarInt(cache),
ReadNextVarInt(cache)
};
break;
case 17: // Optional VarInt
if (ReadNextBool(cache))
{
value = ReadNextVarInt(cache);
}
break;
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
{
// Dimension and blockPos, currently not in use
value = new Tuple<string, Location>(ReadNextString(cache), ReadNextLocation(cache));
}
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?");
}
data[key] = value;
key = ReadNextByte(cache);
}
}
return data; return data;
} }

View file

@ -86,6 +86,7 @@ namespace MinecraftClient.Protocol.Handlers
readonly Protocol18Terrain pTerrain; readonly Protocol18Terrain pTerrain;
readonly IMinecraftComHandler handler; readonly IMinecraftComHandler handler;
readonly EntityPalette entityPalette; readonly EntityPalette entityPalette;
readonly EntityMetadataPalette entityMetadataPalette;
readonly ItemPalette itemPalette; readonly ItemPalette itemPalette;
readonly PacketTypePalette packetPalette; readonly PacketTypePalette packetPalette;
readonly SocketWrapper socketWrapper; readonly SocketWrapper socketWrapper;
@ -179,6 +180,8 @@ namespace MinecraftClient.Protocol.Handlers
else else
entityPalette = new EntityPalette112(); entityPalette = new EntityPalette112();
entityMetadataPalette = EntityMetadataPalette.GetPalette(protocolVersion);
// Item palette // Item palette
if (protocolVersion > MC_1_19_4_Version && handler.GetInventoryEnabled()) if (protocolVersion > MC_1_19_4_Version && handler.GetInventoryEnabled())
throw new NotImplementedException(Translations.exception_palette_item); throw new NotImplementedException(Translations.exception_palette_item);
@ -2132,8 +2135,9 @@ namespace MinecraftClient.Protocol.Handlers
if (handler.GetEntityHandlingEnabled()) if (handler.GetEntityHandlingEnabled())
{ {
int EntityID = dataTypes.ReadNextVarInt(packetData); int EntityID = dataTypes.ReadNextVarInt(packetData);
Dictionary<int, object?> metadata = dataTypes.ReadNextMetadata(packetData, itemPalette); Dictionary<int, object?> metadata = dataTypes.ReadNextMetadata(packetData, itemPalette, entityMetadataPalette);
// Also make a palette for field? Will be a lot of work
int healthField; // See https://wiki.vg/Entity_metadata#Living_Entity int healthField; // See https://wiki.vg/Entity_metadata#Living_Entity
if (protocolVersion > MC_1_19_4_Version) if (protocolVersion > MC_1_19_4_Version)
throw new NotImplementedException(Translations.exception_palette_healthfield); throw new NotImplementedException(Translations.exception_palette_healthfield);