Skip to content

Commit

Permalink
Implemented 1.8 Entity Handling
Browse files Browse the repository at this point in the history
Implemented 1.8 Entity Handling
  • Loading branch information
milutinke authored Mar 29, 2023
2 parents cd39c1e + 2a82c35 commit e8b3e6b
Show file tree
Hide file tree
Showing 8 changed files with 474 additions and 90 deletions.
3 changes: 3 additions & 0 deletions MinecraftClient/Mapping/EntityMetaDataType.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,9 @@ namespace MinecraftClient.Mapping;
public enum EntityMetaDataType
{
Byte,
Short, // 1.8 only
Int, // 1.8 only
Vector3Int, // 1.8 only (not used by the game)
VarInt,
VarLong,
Float,
Expand Down
4 changes: 2 additions & 2 deletions MinecraftClient/Mapping/EntityMetadataPalette.cs
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,8 @@ public EntityMetaDataType GetDataType(int typeId)

public static EntityMetadataPalette GetPalette(int protocolVersion)
{
if (protocolVersion < Protocol18Handler.MC_1_9_Version)
throw new NotImplementedException();
if (protocolVersion <= Protocol18Handler.MC_1_8_Version)
return new EntityMetadataPalette18(); // 1.8
else if (protocolVersion <= Protocol18Handler.MC_1_12_2_Version)
return new EntityMetadataPalette1122(); // 1.9 - 1.12.2
else if (protocolVersion <= Protocol18Handler.MC_1_19_2_Version)
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
using System.Collections.Generic;

namespace MinecraftClient.Mapping.EntityMetadataPalettes;

public class EntityMetadataPalette18 : EntityMetadataPalette
{
// 1.8 : https://wiki.vg/index.php?title=Entity_metadata&oldid=6220
private readonly Dictionary<int, EntityMetaDataType> entityMetadataMappings = new()
{
{ 0, EntityMetaDataType.Byte },
{ 1, EntityMetaDataType.Short },
{ 2, EntityMetaDataType.Int },
{ 3, EntityMetaDataType.Float },
{ 4, EntityMetaDataType.String },
{ 5, EntityMetaDataType.Slot },
{ 6, EntityMetaDataType.Vector3Int },
{ 7, EntityMetaDataType.Rotation }
};

public override Dictionary<int, EntityMetaDataType> GetEntityMetadataMappingsList()
{
return entityMetadataMappings;
}
}

This file was deleted.

114 changes: 114 additions & 0 deletions MinecraftClient/Mapping/EntityPalettes/EntityPalette18.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,114 @@
using System;
using System.Collections.Generic;

namespace MinecraftClient.Mapping.EntityPalettes
{
/// <summary>
/// Defines mappings of entitiy IDs for 1.8
/// Manually typed out by Milutinke :(
/// Data source: https://pokechu22.github.io/Burger/1.8.json and https://wiki.vg/index.php?title=Entity_metadata&oldid=7415
/// </summary>
public class EntityPalette18 : EntityPalette
{
private static Dictionary<int, EntityType> mappingsObjects = new Dictionary<int, EntityType>()
{
// https://wiki.vg/Entity_metadata#Objects
{ 1, EntityType.Boat },
{ 2, EntityType.Item },
{ 3, EntityType.AreaEffectCloud },
{ 10, EntityType.Minecart },
{ 50, EntityType.Tnt },
{ 51, EntityType.EndCrystal },
{ 60, EntityType.Arrow },
{ 61, EntityType.Snowball },
{ 62, EntityType.Egg },
{ 63, EntityType.Fireball },
{ 64, EntityType.SmallFireball },
{ 65, EntityType.EnderPearl },
{ 66, EntityType.WitherSkull },
{ 70, EntityType.FallingBlock },
{ 71, EntityType.ItemFrame },
{ 72, EntityType.EyeOfEnder },
{ 73, EntityType.Egg },
{ 75, EntityType.ExperienceBottle },
{ 76, EntityType.FireworkRocket },
{ 77, EntityType.LeashKnot },
{ 78, EntityType.ArmorStand },
{ 90, EntityType.FishingBobber },
{ 91, EntityType.SpectralArrow },
{ 93, EntityType.DragonFireball },
};

private static Dictionary<int, EntityType> mappingsMobs = new Dictionary<int, EntityType>() {
{ 1, EntityType.Item },
{ 2, EntityType.ExperienceOrb },
{ 8, EntityType.LeashKnot },
{ 9, EntityType.Painting },
{ 10, EntityType.Arrow },
{ 11, EntityType.Snowball },
{ 12, EntityType.Fireball },
{ 13, EntityType.SmallFireball },
{ 14, EntityType.EnderPearl },
{ 15, EntityType.EyeOfEnder },
{ 16, EntityType.Potion },
{ 17, EntityType.ExperienceBottle },
{ 18, EntityType.ItemFrame },
{ 19, EntityType.WitherSkull },
{ 20, EntityType.Tnt },
{ 21, EntityType.FallingBlock },
{ 22, EntityType.FireworkRocket },
{ 30, EntityType.ArmorStand },
{ 40, EntityType.CommandBlockMinecart },
{ 41, EntityType.Boat },
{ 42, EntityType.Minecart },
{ 43, EntityType.ChestMinecart },
{ 44, EntityType.FurnaceMinecart },
{ 45, EntityType.TntMinecart },
{ 46, EntityType.HopperMinecart },
{ 47, EntityType.SpawnerMinecart },
{ 50, EntityType.Creeper },
{ 51, EntityType.Skeleton },
{ 52, EntityType.Spider },
{ 53, EntityType.Giant },
{ 54, EntityType.Zombie },
{ 55, EntityType.Slime },
{ 56, EntityType.Ghast },
{ 57, EntityType.ZombifiedPiglin },
{ 58, EntityType.Enderman },
{ 59, EntityType.CaveSpider },
{ 60, EntityType.Silverfish },
{ 61, EntityType.Blaze },
{ 62, EntityType.MagmaCube },
{ 63, EntityType.EnderDragon },
{ 64, EntityType.Wither },
{ 65, EntityType.Bat },
{ 66, EntityType.Witch },
{ 67, EntityType.Endermite },
{ 68, EntityType.Guardian },
{ 90, EntityType.Pig },
{ 91, EntityType.Sheep },
{ 92, EntityType.Cow },
{ 93, EntityType.Chicken },
{ 94, EntityType.Squid },
{ 95, EntityType.Wolf },
{ 96, EntityType.Mooshroom },
{ 97, EntityType.SnowGolem },
{ 98, EntityType.Cat },
{ 99, EntityType.IronGolem },
{ 100, EntityType.Horse },
{ 101, EntityType.Rabbit },
{ 120, EntityType.Villager },
{ 200, EntityType.EndCrystal }
};

protected override Dictionary<int, EntityType> GetDict()
{
return mappingsMobs;
}

protected override Dictionary<int, EntityType> GetDictNonLiving()
{
return mappingsObjects;
}
}
}
120 changes: 90 additions & 30 deletions MinecraftClient/Protocol/Handlers/DataTypes.cs
Original file line number Diff line number Diff line change
Expand Up @@ -463,47 +463,74 @@ public Dictionary<string, object> ReadNextNbt(Queue<byte> cache)
public Entity ReadNextEntity(Queue<byte> cache, EntityPalette entityPalette, bool living)
{
int entityID = ReadNextVarInt(cache);
if (protocolversion > Protocol18Handler.MC_1_8_Version)
ReadNextUUID(cache);
Guid entityUUID = Guid.Empty;

// UUID field added in 1.9 +
if (protocolversion >= Protocol18Handler.MC_1_9_Version)
entityUUID = ReadNextUUID(cache);

// Entity type data type change from byte to varint in 1.13.2
EntityType entityType;
// Entity type data type change from byte to varint after 1.14
if (protocolversion > Protocol18Handler.MC_1_13_Version)
entityType = entityPalette.FromId(ReadNextVarInt(cache), living);

if (living)
{
// For living entities the Type field was changed to VarInt from Byte in 1.11 +
if (protocolversion >= Protocol18Handler.MC_1_11_Version)
entityType = entityPalette.FromId(ReadNextVarInt(cache), living);
else entityType = entityPalette.FromId(ReadNextByte(cache), living);
}
else
{
// For non-living entities the Type field was changed to VarInt from Byte in 1.13.2 +
if (protocolversion >= Protocol18Handler.MC_1_13_2_Version)
entityType = entityPalette.FromId(ReadNextVarInt(cache), living);
else entityType = entityPalette.FromId(ReadNextByte(cache), living);
}

Double entityX, entityY, entityZ;

if (protocolversion < Protocol18Handler.MC_1_9_Version)
{
entityX = ReadNextInt(cache) / 32.0D; // X
entityY = ReadNextInt(cache) / 32.0D; // Y
entityZ = ReadNextInt(cache) / 32.0D; // Z
}
else
entityType = entityPalette.FromId(ReadNextByte(cache), living);
{
entityX = ReadNextDouble(cache); // X
entityY = ReadNextDouble(cache); // Y
entityZ = ReadNextDouble(cache); // Z
}

double entityX = ReadNextDouble(cache);
double entityY = ReadNextDouble(cache);
double entityZ = ReadNextDouble(cache);
byte entityPitch = ReadNextByte(cache);
byte entityYaw = ReadNextByte(cache);

int metadata = -1;
byte entityPitch, entityYaw;

if (living)
{
if (protocolversion == Protocol18Handler.MC_1_18_2_Version)
entityYaw = ReadNextByte(cache);
else
entityPitch = ReadNextByte(cache);
entityYaw = ReadNextByte(cache); // Yaw
entityPitch = ReadNextByte(cache); // Pitch
entityPitch = ReadNextByte(cache); // Head Pitch
}
else
{
entityPitch = ReadNextByte(cache); // Pitch
entityYaw = ReadNextByte(cache); // Yaw

if (protocolversion >= Protocol18Handler.MC_1_19_Version)
{
entityYaw = ReadNextByte(cache);
metadata = ReadNextVarInt(cache);
}
else
metadata = ReadNextInt(cache);
entityYaw = ReadNextByte(cache); // Head Yaw

// Data
if (protocolversion >= Protocol18Handler.MC_1_19_Version)
ReadNextVarInt(cache);
else ReadNextInt(cache);
}

short velocityX = ReadNextShort(cache);
short velocityY = ReadNextShort(cache);
short velocityZ = ReadNextShort(cache);

return new Entity(entityID, entityType, new Location(entityX, entityY, entityZ), entityYaw, entityPitch,
metadata);
return new Entity(entityID, entityType, new Location(entityX, entityY, entityZ), entityYaw, entityPitch, metadata);
}

/// <summary>
Expand Down Expand Up @@ -599,18 +626,30 @@ private object ReadNbtField(Queue<byte> cache, int fieldType)
}
}

//TODO: Refactor this to use new Entity Metadata Palettes
/// <summary>
/// Read a Entity MetaData and remove it from the cache
/// </summary>
/// <param name="cache"></param>
/// <param name="itemPalette"></param>
/// <param name="metadataPalette"></param>
/// <returns></returns>
/// <exception cref="NotImplementedException"></exception>
/// <exception cref="System.IO.InvalidDataException"></exception>
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();
byte key = ReadNextByte(cache);
byte terminteValue = protocolversion <= Protocol18Handler.MC_1_8_Version
? (byte)0x7f // 1.8 (https://wiki.vg/index.php?title=Entity_metadata&oldid=6220#Entity_Metadata_Format)
: (byte)0xff; // 1.9+

while (key != 0xff)
while (key != terminteValue)
{
int typeId = ReadNextVarInt(cache);
int typeId = protocolversion <= Protocol18Handler.MC_1_8_Version
? key >> 5 // 1.8
: ReadNextVarInt(cache); // 1.9+


EntityMetaDataType type;
try
{
Expand All @@ -620,12 +659,29 @@ private object ReadNbtField(Queue<byte> cache, int fieldType)
{
throw new System.IO.InvalidDataException("Unknown Metadata Type ID " + typeId + ". Is this up to date for new MC Version?");
}

if (protocolversion <= Protocol18Handler.MC_1_8_Version)
key = (byte)(key & 0x1f);

// Value's data type is depended on Type
object? value = null;

switch (type)
{
case EntityMetaDataType.Short: // 1.8 only
value = ReadNextShort(cache);
break;
case EntityMetaDataType.Int: // 1.8 only
value = ReadNextInt(cache);
break;
case EntityMetaDataType.Vector3Int: // 1.8 only
value = new List<int>()
{
ReadNextInt(cache),
ReadNextInt(cache),
ReadNextInt(cache),
};
break;
case EntityMetaDataType.Byte: // byte
value = ReadNextByte(cache);
break;
Expand Down Expand Up @@ -760,7 +816,11 @@ private object ReadNbtField(Queue<byte> cache, int fieldType)
return data;
}

// Currently not handled. Reading data only
/// <summary>
/// Currently not handled. Reading data only
/// </summary>
/// <param name="cache"></param>
/// <param name="itemPalette"></param>
protected void ReadParticleData(Queue<byte> cache, ItemPalette itemPalette)
{
if (protocolversion < Protocol18Handler.MC_1_13_Version)
Expand Down
Loading

0 comments on commit e8b3e6b

Please sign in to comment.