diff --git a/MinecraftClient/ChatBots/AutoAttack.cs b/MinecraftClient/ChatBots/AutoAttack.cs
index 6ccd9f58..99ccac3b 100644
--- a/MinecraftClient/ChatBots/AutoAttack.cs
+++ b/MinecraftClient/ChatBots/AutoAttack.cs
@@ -112,7 +112,7 @@ namespace MinecraftClient.ChatBots
/// If the entity should be attacked
public bool handleEntity(Entity entity)
{
- if (!entity.IsHostile())
+ if (!entity.Type.IsHostile())
return false;
bool isBeingAttacked = entitiesToAttack.ContainsKey(entity.ID);
diff --git a/MinecraftClient/ChatBots/AutoFishing.cs b/MinecraftClient/ChatBots/AutoFishing.cs
index 701ad180..e5e91adb 100644
--- a/MinecraftClient/ChatBots/AutoFishing.cs
+++ b/MinecraftClient/ChatBots/AutoFishing.cs
@@ -46,7 +46,7 @@ namespace MinecraftClient.ChatBots
public override void OnEntitySpawn(Entity entity)
{
- if (entity.TypeID == 102)
+ if (entity.Type == EntityType.FishingBobber)
{
if (GetCurrentLocation().Distance(entity.Location) < 2 && !isFishing)
{
@@ -60,7 +60,7 @@ namespace MinecraftClient.ChatBots
public override void OnEntityDespawn(Entity entity)
{
- if(entity.TypeID == 102 && isFishing)
+ if (entity.Type == EntityType.FishingBobber)
{
if(entity.ID == fishingRod.ID)
{
diff --git a/MinecraftClient/Inventory/ItemTypeGenerator.cs b/MinecraftClient/Inventory/ItemTypeGenerator.cs
index fa99d3cb..a056b7f0 100644
--- a/MinecraftClient/Inventory/ItemTypeGenerator.cs
+++ b/MinecraftClient/Inventory/ItemTypeGenerator.cs
@@ -1,7 +1,4 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.IO;
+using MinecraftClient.Protocol;
namespace MinecraftClient.Inventory
{
@@ -14,45 +11,10 @@ namespace MinecraftClient.Inventory
/// Generate ItemType.cs from Minecraft registries.json
///
/// path to registries.json
- /// output path for ItemTypes.cs
/// java -cp minecraft_server.jar net.minecraft.data.Main --reports
- public static void JsonToClass(string registriesJsonFile, string outputEnum)
+ public static void GenerateItemTypes(string registriesJsonFile)
{
- HashSet itemIds = new HashSet();
- Json.JSONData registries = Json.ParseJson(File.ReadAllText(registriesJsonFile));
- Json.JSONData itemRegistry = registries.Properties["minecraft:item"].Properties["entries"];
- List outFile = new List();
-
- outFile.AddRange(new[] {
- "namespace MinecraftClient.Inventory",
- "{",
- " public enum ItemType",
- " {"
- });
-
- foreach (KeyValuePair item in itemRegistry.Properties)
- {
- int itemId = int.Parse(item.Value.Properties["protocol_id"].StringValue);
-
- //minecraft:item_name => ItemName
- string itemName = String.Concat(
- item.Key.Replace("minecraft:", "")
- .Split('_')
- .Select(word => char.ToUpper(word[0]) + word.Substring(1))
- );
-
- if (itemIds.Contains(itemId))
- throw new InvalidDataException("Duplicate item ID " + itemId + "!?");
-
- outFile.Add(" " + itemName + " = " + itemId + ',');
- }
-
- outFile.AddRange(new[] {
- " }",
- "}"
- });
-
- File.WriteAllLines(outputEnum, outFile);
+ DataTypeGenerator.GenerateEnum(registriesJsonFile, "minecraft:item", "ItemType", "MinecraftClient.Inventory");
}
}
}
diff --git a/MinecraftClient/Mapping/Block.cs b/MinecraftClient/Mapping/Block.cs
index 7d835565..0a9eb382 100644
--- a/MinecraftClient/Mapping/Block.cs
+++ b/MinecraftClient/Mapping/Block.cs
@@ -15,7 +15,7 @@ namespace MinecraftClient.Mapping
/// Get or set global block ID to Material mapping
/// The global Palette is a concept introduced with Minecraft 1.13
///
- public static BlockPaletteMapping Palette { get; set; }
+ public static BlockPalette Palette { get; set; }
///
/// Storage for block ID and metadata, as ushort for compatibility, performance and lower memory footprint
diff --git a/MinecraftClient/Mapping/BlockPalettes/BlockPaletteMapping.cs b/MinecraftClient/Mapping/BlockPalettes/BlockPalette.cs
similarity index 96%
rename from MinecraftClient/Mapping/BlockPalettes/BlockPaletteMapping.cs
rename to MinecraftClient/Mapping/BlockPalettes/BlockPalette.cs
index 717f5cb5..9b8611b6 100644
--- a/MinecraftClient/Mapping/BlockPalettes/BlockPaletteMapping.cs
+++ b/MinecraftClient/Mapping/BlockPalettes/BlockPalette.cs
@@ -5,7 +5,7 @@ using System.Text;
namespace MinecraftClient.Mapping.BlockPalettes
{
- public abstract class BlockPaletteMapping
+ public abstract class BlockPalette
{
///
/// Get mapping dictionary. Must be overriden with proper implementation.
diff --git a/MinecraftClient/Mapping/BlockPalettes/Palette112.cs b/MinecraftClient/Mapping/BlockPalettes/Palette112.cs
index e0f7438d..7afc42ad 100644
--- a/MinecraftClient/Mapping/BlockPalettes/Palette112.cs
+++ b/MinecraftClient/Mapping/BlockPalettes/Palette112.cs
@@ -9,7 +9,7 @@ namespace MinecraftClient.Mapping.BlockPalettes
/// Some blocks previously had different IDs depending on state, they have been merged here
/// Comments correspond to changed material names since previous MCC versions
///
- public class Palette112 : BlockPaletteMapping
+ public class Palette112 : BlockPalette
{
private static Dictionary materials = new Dictionary()
{
diff --git a/MinecraftClient/Mapping/BlockPalettes/Palette113.cs b/MinecraftClient/Mapping/BlockPalettes/Palette113.cs
index 18c7db37..ca29cfab 100644
--- a/MinecraftClient/Mapping/BlockPalettes/Palette113.cs
+++ b/MinecraftClient/Mapping/BlockPalettes/Palette113.cs
@@ -7,7 +7,7 @@ namespace MinecraftClient.Mapping.BlockPalettes
/// Defines mappings for Minecraft 1.13.
/// Automatically generated using BlockPaletteGenerator.cs
///
- public class Palette113 : BlockPaletteMapping
+ public class Palette113 : BlockPalette
{
private static Dictionary materials = new Dictionary();
diff --git a/MinecraftClient/Mapping/BlockPalettes/Palette114.cs b/MinecraftClient/Mapping/BlockPalettes/Palette114.cs
index ea0bab3e..2503f1bb 100644
--- a/MinecraftClient/Mapping/BlockPalettes/Palette114.cs
+++ b/MinecraftClient/Mapping/BlockPalettes/Palette114.cs
@@ -7,7 +7,7 @@ namespace MinecraftClient.Mapping.BlockPalettes
/// Defines mappings for Minecraft 1.14.
/// Automatically generated using BlockPaletteGenerator.cs
///
- public class Palette114 : BlockPaletteMapping
+ public class Palette114 : BlockPalette
{
private static Dictionary materials = new Dictionary();
diff --git a/MinecraftClient/Mapping/BlockPalettes/Palette115.cs b/MinecraftClient/Mapping/BlockPalettes/Palette115.cs
index bb823763..b56accc1 100644
--- a/MinecraftClient/Mapping/BlockPalettes/Palette115.cs
+++ b/MinecraftClient/Mapping/BlockPalettes/Palette115.cs
@@ -7,7 +7,7 @@ namespace MinecraftClient.Mapping.BlockPalettes
/// Defines mappings for Minecraft 1.15.
/// Automatically generated using BlockPaletteGenerator.cs
///
- public class Palette115 : BlockPaletteMapping
+ public class Palette115 : BlockPalette
{
private static Dictionary materials = new Dictionary();
diff --git a/MinecraftClient/Mapping/Entity.cs b/MinecraftClient/Mapping/Entity.cs
index 9feae262..011cb912 100644
--- a/MinecraftClient/Mapping/Entity.cs
+++ b/MinecraftClient/Mapping/Entity.cs
@@ -21,60 +21,15 @@ namespace MinecraftClient.Mapping
public Guid UUID;
///
- /// Entity type determined by Minecraft Console Client
+ /// Entity type
///
public EntityType Type;
- ///
- /// Entity type ID (more precise than Type, but may change between Minecraft versions)
- ///
- public int TypeID;
-
///
/// Entity location in the Minecraft world
///
public Location Location;
- ///
- /// Create a new entity based on Entity ID and location
- ///
- /// Entity ID
- /// Entity location
- public Entity(int ID, Location location)
- {
- this.ID = ID;
- this.Location = location;
- }
-
- ///
- /// Create a new entity based on Entity ID, Entity Type and location
- ///
- /// Entity ID
- /// Entity Type ID
- /// Entity location
- public Entity(int ID, int TypeID, Location location)
- {
- this.ID = ID;
- this.TypeID = TypeID;
- this.Location = location;
- }
-
- ///
- /// Create a new entity based on Entity ID, Entity Type, location, and UUID
- ///
- /// Entity ID
- /// Entity Type ID
- /// Entity Type Enum
- /// Entity location
- public Entity(int ID, int TypeID, EntityType type, Location location, Guid uuid)
- {
- this.ID = ID;
- this.TypeID = TypeID;
- this.Type = type;
- this.Location = location;
- this.UUID = uuid;
- }
-
///
/// Create a new entity based on Entity ID, Entity Type and location
///
@@ -100,41 +55,5 @@ namespace MinecraftClient.Mapping
this.Location = location;
this.UUID = uuid;
}
-
- ///
- /// Return TRUE if the Entity is an hostile mob
- ///
- /// New mobs added in newer Minecraft versions might be absent from the list
- /// TRUE if hostile
- public bool IsHostile()
- {
- switch (TypeID)
- {
- case 5: return true; // Blaze;
- case 12: return true; // Creeper
- case 16: return true; // Drowned
- case 23: return true; // Evoker
- case 29: return true; // Ghast
- case 31: return true; // Guardian
- case 33: return true; // Husk
- case 41: return true; // Magma Cube
- case 57: return true; // Zombie Pigman
- case 63: return true; // Shulker
- case 65: return true; // Silverfish
- case 66: return true; // Skeleton
- case 68: return true; // Slime
- case 75: return true; // Stray
- case 84: return true; // Vex
- case 87: return true; // Vindicator
- case 88: return true; // Pillager
- case 90: return true; // Witch
- case 92: return true; // Wither Skeleton
- case 95: return true; // Zombie
- case 97: return true; // Zombie Villager
- case 98: return true; // Phantom
- case 99: return true; // Ravager
- default: return false;
- }
- }
}
}
diff --git a/MinecraftClient/Mapping/EntityPalettes/EntityPalette.cs b/MinecraftClient/Mapping/EntityPalettes/EntityPalette.cs
new file mode 100644
index 00000000..9b29f460
--- /dev/null
+++ b/MinecraftClient/Mapping/EntityPalettes/EntityPalette.cs
@@ -0,0 +1,51 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+
+namespace MinecraftClient.Mapping.EntityPalettes
+{
+ public abstract class EntityPalette
+ {
+ ///
+ /// Get mapping dictionary. Must be overriden with proper implementation.
+ ///
+ /// Palette dictionary
+ protected abstract Dictionary GetDict();
+
+ ///
+ /// Get mapping dictionary for pre-1.13. May be overriden with proper implementation.
+ ///
+ /// Palette dictionary for non-living entities (pre-1.13)
+ protected virtual Dictionary GetDictNonLiving()
+ {
+ return null;
+ }
+
+ ///
+ /// Get entity type from type ID
+ ///
+ /// Entity type ID
+ /// EntityType corresponding to the specified ID
+ public EntityType FromId(int id, bool living)
+ {
+ Dictionary entityTypes = GetDict();
+ Dictionary entityTypesNonLiving = GetDictNonLiving();
+
+ if (entityTypesNonLiving != null && !living)
+ {
+ //Pre-1.13 non-living entities have a different set of IDs (entityTypesNonLiving != null)
+ if (entityTypesNonLiving.ContainsKey(id))
+ return entityTypesNonLiving[id];
+ }
+ else
+ {
+ //Post-1.13 entities have the same set of IDs regardless of living status
+ if (entityTypes.ContainsKey(id))
+ return entityTypes[id];
+ }
+
+ throw new System.IO.InvalidDataException("Unknown Entity ID " + id + ". Is Entity Palette up to date for this Minecraft version?");
+ }
+ }
+}
diff --git a/MinecraftClient/Mapping/EntityPalettes/EntityPalette113.cs b/MinecraftClient/Mapping/EntityPalettes/EntityPalette113.cs
new file mode 100644
index 00000000..22135c59
--- /dev/null
+++ b/MinecraftClient/Mapping/EntityPalettes/EntityPalette113.cs
@@ -0,0 +1,156 @@
+using System;
+using System.Collections.Generic;
+
+namespace MinecraftClient.Mapping.EntityPalettes
+{
+ ///
+ /// Defines mappings for pre-1.14 entitiy IDs
+ /// Pre-1.14 Minecraft has 2 set of ids: One for non-living objects and one for living mobs
+ /// Post-1.14 Minecraft has only one set of ids for all types of entities
+ ///
+ public class EntityPalette113 : EntityPalette
+ {
+ private static Dictionary mappingsObjects = new Dictionary()
+ {
+ // 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 },
+ { 67, EntityType.ShulkerBullet },
+ { 68, EntityType.LlamaSpit },
+ { 70, EntityType.FallingBlock },
+ { 71, EntityType.ItemFrame },
+ { 72, EntityType.EyeOfEnder },
+ { 73, EntityType.Potion },
+ { 75, EntityType.ExperienceBottle },
+ { 76, EntityType.FireworkRocket },
+ { 77, EntityType.LeashKnot },
+ { 78, EntityType.ArmorStand },
+ { 79, EntityType.EvokerFangs },
+ { 90, EntityType.FishingBobber },
+ { 91, EntityType.SpectralArrow },
+ { 93, EntityType.DragonFireball },
+ { 94, EntityType.Trident },
+ };
+
+ private static Dictionary mappingsMobs = new Dictionary()
+ {
+ // https://wiki.vg/Entity_metadata#Mobs
+ { 0, EntityType.AreaEffectCloud },
+ { 1, EntityType.ArmorStand },
+ { 2, EntityType.Arrow },
+ { 3, EntityType.Bat },
+ { 4, EntityType.Blaze },
+ { 5, EntityType.Boat },
+ { 6, EntityType.CaveSpider },
+ { 7, EntityType.Chicken },
+ { 8, EntityType.Cod },
+ { 9, EntityType.Cow },
+ { 10, EntityType.Creeper },
+ { 11, EntityType.Donkey },
+ { 12, EntityType.Dolphin },
+ { 13, EntityType.DragonFireball },
+ { 14, EntityType.Drowned },
+ { 15, EntityType.ElderGuardian },
+ { 16, EntityType.EndCrystal },
+ { 17, EntityType.EnderDragon },
+ { 18, EntityType.Enderman },
+ { 19, EntityType.Endermite },
+ { 20, EntityType.EvokerFangs },
+ { 21, EntityType.Evoker },
+ { 22, EntityType.ExperienceBottle },
+ { 23, EntityType.EyeOfEnder },
+ { 24, EntityType.FallingBlock },
+ { 25, EntityType.FireworkRocket },
+ { 26, EntityType.Ghast },
+ { 27, EntityType.Giant },
+ { 28, EntityType.Guardian },
+ { 29, EntityType.Horse },
+ { 30, EntityType.Husk },
+ { 31, EntityType.Illusioner },
+ { 32, EntityType.Item },
+ { 33, EntityType.ItemFrame },
+ { 34, EntityType.Fireball },
+ { 35, EntityType.LeashKnot },
+ { 36, EntityType.Llama },
+ { 37, EntityType.LlamaSpit },
+ { 38, EntityType.MagmaCube },
+ { 39, EntityType.Minecart },
+ { 40, EntityType.ChestMinecart },
+ { 41, EntityType.CommandBlockMinecart },
+ { 42, EntityType.FurnaceMinecart },
+ { 43, EntityType.HopperMinecart },
+ { 44, EntityType.SpawnerMinecart },
+ { 45, EntityType.TntMinecart },
+ { 46, EntityType.Mule },
+ { 47, EntityType.Mooshroom },
+ { 48, EntityType.Ocelot },
+ { 49, EntityType.Painting },
+ { 50, EntityType.Parrot },
+ { 51, EntityType.Pig },
+ { 52, EntityType.Pufferfish },
+ { 53, EntityType.ZombiePigman },
+ { 54, EntityType.PolarBear },
+ { 55, EntityType.Tnt },
+ { 56, EntityType.Rabbit },
+ { 57, EntityType.Salmon },
+ { 58, EntityType.Sheep },
+ { 59, EntityType.Shulker },
+ { 60, EntityType.ShulkerBullet },
+ { 61, EntityType.Silverfish },
+ { 62, EntityType.Skeleton },
+ { 63, EntityType.SkeletonHorse },
+ { 64, EntityType.Slime },
+ { 65, EntityType.SmallFireball },
+ { 66, EntityType.SnowGolem },
+ { 67, EntityType.Snowball },
+ { 68, EntityType.SpectralArrow },
+ { 69, EntityType.Spider },
+ { 70, EntityType.Squid },
+ { 71, EntityType.Stray },
+ { 72, EntityType.TropicalFish },
+ { 73, EntityType.Turtle },
+ { 74, EntityType.Egg },
+ { 75, EntityType.EnderPearl },
+ { 76, EntityType.ExperienceBottle },
+ { 77, EntityType.Potion },
+ { 78, EntityType.Vex },
+ { 79, EntityType.Villager },
+ { 80, EntityType.IronGolem },
+ { 81, EntityType.Vindicator },
+ { 82, EntityType.Witch },
+ { 83, EntityType.Wither },
+ { 84, EntityType.WitherSkeleton },
+ { 85, EntityType.WitherSkull },
+ { 86, EntityType.Wolf },
+ { 87, EntityType.Zombie },
+ { 88, EntityType.ZombieHorse },
+ { 89, EntityType.ZombieVillager },
+ { 90, EntityType.Phantom },
+ { 91, EntityType.LightningBolt },
+ { 92, EntityType.Player },
+ { 93, EntityType.FishingBobber },
+ { 94, EntityType.Trident },
+ };
+
+ protected override Dictionary GetDict()
+ {
+ return mappingsMobs;
+ }
+
+ protected override Dictionary GetDictNonLiving()
+ {
+ return mappingsObjects;
+ }
+ }
+}
diff --git a/MinecraftClient/Mapping/EntityPalettes/EntityPalette114.cs b/MinecraftClient/Mapping/EntityPalettes/EntityPalette114.cs
new file mode 100644
index 00000000..58ce763a
--- /dev/null
+++ b/MinecraftClient/Mapping/EntityPalettes/EntityPalette114.cs
@@ -0,0 +1,125 @@
+using System;
+using System.Collections.Generic;
+
+namespace MinecraftClient.Mapping.EntityPalettes
+{
+ ///
+ /// Defines mappings for Minecraft 1.14.
+ /// Automatically generated using EntityPaletteGenerator.cs
+ ///
+ public class EntityPalette114 : EntityPalette
+ {
+ private static Dictionary mappings = new Dictionary();
+
+ static EntityPalette114()
+ {
+ mappings[0] = EntityType.AreaEffectCloud;
+ mappings[1] = EntityType.ArmorStand;
+ mappings[2] = EntityType.Arrow;
+ mappings[3] = EntityType.Bat;
+ mappings[4] = EntityType.Blaze;
+ mappings[5] = EntityType.Boat;
+ mappings[6] = EntityType.Cat;
+ mappings[7] = EntityType.CaveSpider;
+ mappings[8] = EntityType.Chicken;
+ mappings[9] = EntityType.Cod;
+ mappings[10] = EntityType.Cow;
+ mappings[11] = EntityType.Creeper;
+ mappings[12] = EntityType.Donkey;
+ mappings[13] = EntityType.Dolphin;
+ mappings[14] = EntityType.DragonFireball;
+ mappings[15] = EntityType.Drowned;
+ mappings[16] = EntityType.ElderGuardian;
+ mappings[17] = EntityType.EndCrystal;
+ mappings[18] = EntityType.EnderDragon;
+ mappings[19] = EntityType.Enderman;
+ mappings[20] = EntityType.Endermite;
+ mappings[21] = EntityType.EvokerFangs;
+ mappings[22] = EntityType.Evoker;
+ mappings[23] = EntityType.ExperienceOrb;
+ mappings[24] = EntityType.EyeOfEnder;
+ mappings[25] = EntityType.FallingBlock;
+ mappings[26] = EntityType.FireworkRocket;
+ mappings[27] = EntityType.Fox;
+ mappings[28] = EntityType.Ghast;
+ mappings[29] = EntityType.Giant;
+ mappings[30] = EntityType.Guardian;
+ mappings[31] = EntityType.Horse;
+ mappings[32] = EntityType.Husk;
+ mappings[33] = EntityType.Illusioner;
+ mappings[34] = EntityType.Item;
+ mappings[35] = EntityType.ItemFrame;
+ mappings[36] = EntityType.Fireball;
+ mappings[37] = EntityType.LeashKnot;
+ mappings[38] = EntityType.Llama;
+ mappings[39] = EntityType.LlamaSpit;
+ mappings[40] = EntityType.MagmaCube;
+ mappings[41] = EntityType.Minecart;
+ mappings[42] = EntityType.ChestMinecart;
+ mappings[43] = EntityType.CommandBlockMinecart;
+ mappings[44] = EntityType.FurnaceMinecart;
+ mappings[45] = EntityType.HopperMinecart;
+ mappings[46] = EntityType.SpawnerMinecart;
+ mappings[47] = EntityType.TntMinecart;
+ mappings[48] = EntityType.Mule;
+ mappings[49] = EntityType.Mooshroom;
+ mappings[50] = EntityType.Ocelot;
+ mappings[51] = EntityType.Painting;
+ mappings[52] = EntityType.Panda;
+ mappings[53] = EntityType.Parrot;
+ mappings[54] = EntityType.Pig;
+ mappings[55] = EntityType.Pufferfish;
+ mappings[56] = EntityType.ZombiePigman;
+ mappings[57] = EntityType.PolarBear;
+ mappings[58] = EntityType.Tnt;
+ mappings[59] = EntityType.Rabbit;
+ mappings[60] = EntityType.Salmon;
+ mappings[61] = EntityType.Sheep;
+ mappings[62] = EntityType.Shulker;
+ mappings[63] = EntityType.ShulkerBullet;
+ mappings[64] = EntityType.Silverfish;
+ mappings[65] = EntityType.Skeleton;
+ mappings[66] = EntityType.SkeletonHorse;
+ mappings[67] = EntityType.Slime;
+ mappings[68] = EntityType.SmallFireball;
+ mappings[69] = EntityType.SnowGolem;
+ mappings[70] = EntityType.Snowball;
+ mappings[71] = EntityType.SpectralArrow;
+ mappings[72] = EntityType.Spider;
+ mappings[73] = EntityType.Squid;
+ mappings[74] = EntityType.Stray;
+ mappings[75] = EntityType.TraderLlama;
+ mappings[76] = EntityType.TropicalFish;
+ mappings[77] = EntityType.Turtle;
+ mappings[78] = EntityType.Egg;
+ mappings[79] = EntityType.EnderPearl;
+ mappings[80] = EntityType.ExperienceBottle;
+ mappings[81] = EntityType.Potion;
+ mappings[82] = EntityType.Trident;
+ mappings[83] = EntityType.Vex;
+ mappings[84] = EntityType.Villager;
+ mappings[85] = EntityType.IronGolem;
+ mappings[86] = EntityType.Vindicator;
+ mappings[87] = EntityType.Pillager;
+ mappings[88] = EntityType.WanderingTrader;
+ mappings[89] = EntityType.Witch;
+ mappings[90] = EntityType.Wither;
+ mappings[91] = EntityType.WitherSkeleton;
+ mappings[92] = EntityType.WitherSkull;
+ mappings[93] = EntityType.Wolf;
+ mappings[94] = EntityType.Zombie;
+ mappings[95] = EntityType.ZombieHorse;
+ mappings[96] = EntityType.ZombieVillager;
+ mappings[97] = EntityType.Phantom;
+ mappings[98] = EntityType.Ravager;
+ mappings[99] = EntityType.LightningBolt;
+ mappings[100] = EntityType.Player;
+ mappings[101] = EntityType.FishingBobber;
+ }
+
+ protected override Dictionary GetDict()
+ {
+ return mappings;
+ }
+ }
+}
diff --git a/MinecraftClient/Mapping/EntityPalettes/EntityPalette115.cs b/MinecraftClient/Mapping/EntityPalettes/EntityPalette115.cs
new file mode 100644
index 00000000..d01955ef
--- /dev/null
+++ b/MinecraftClient/Mapping/EntityPalettes/EntityPalette115.cs
@@ -0,0 +1,126 @@
+using System;
+using System.Collections.Generic;
+
+namespace MinecraftClient.Mapping.EntityPalettes
+{
+ ///
+ /// Defines mappings for Minecraft 1.15.
+ /// Automatically generated using EntityPaletteGenerator.cs
+ ///
+ public class EntityPalette115 : EntityPalette
+ {
+ private static Dictionary mappings = new Dictionary();
+
+ static EntityPalette115()
+ {
+ mappings[0] = EntityType.AreaEffectCloud;
+ mappings[1] = EntityType.ArmorStand;
+ mappings[2] = EntityType.Arrow;
+ mappings[3] = EntityType.Bat;
+ mappings[4] = EntityType.Bee;
+ mappings[5] = EntityType.Blaze;
+ mappings[6] = EntityType.Boat;
+ mappings[7] = EntityType.Cat;
+ mappings[8] = EntityType.CaveSpider;
+ mappings[9] = EntityType.Chicken;
+ mappings[10] = EntityType.Cod;
+ mappings[11] = EntityType.Cow;
+ mappings[12] = EntityType.Creeper;
+ mappings[13] = EntityType.Donkey;
+ mappings[14] = EntityType.Dolphin;
+ mappings[15] = EntityType.DragonFireball;
+ mappings[16] = EntityType.Drowned;
+ mappings[17] = EntityType.ElderGuardian;
+ mappings[18] = EntityType.EndCrystal;
+ mappings[19] = EntityType.EnderDragon;
+ mappings[20] = EntityType.Enderman;
+ mappings[21] = EntityType.Endermite;
+ mappings[22] = EntityType.EvokerFangs;
+ mappings[23] = EntityType.Evoker;
+ mappings[24] = EntityType.ExperienceOrb;
+ mappings[25] = EntityType.EyeOfEnder;
+ mappings[26] = EntityType.FallingBlock;
+ mappings[27] = EntityType.FireworkRocket;
+ mappings[28] = EntityType.Fox;
+ mappings[29] = EntityType.Ghast;
+ mappings[30] = EntityType.Giant;
+ mappings[31] = EntityType.Guardian;
+ mappings[32] = EntityType.Horse;
+ mappings[33] = EntityType.Husk;
+ mappings[34] = EntityType.Illusioner;
+ mappings[35] = EntityType.Item;
+ mappings[36] = EntityType.ItemFrame;
+ mappings[37] = EntityType.Fireball;
+ mappings[38] = EntityType.LeashKnot;
+ mappings[39] = EntityType.Llama;
+ mappings[40] = EntityType.LlamaSpit;
+ mappings[41] = EntityType.MagmaCube;
+ mappings[42] = EntityType.Minecart;
+ mappings[43] = EntityType.ChestMinecart;
+ mappings[44] = EntityType.CommandBlockMinecart;
+ mappings[45] = EntityType.FurnaceMinecart;
+ mappings[46] = EntityType.HopperMinecart;
+ mappings[47] = EntityType.SpawnerMinecart;
+ mappings[48] = EntityType.TntMinecart;
+ mappings[49] = EntityType.Mule;
+ mappings[50] = EntityType.Mooshroom;
+ mappings[51] = EntityType.Ocelot;
+ mappings[52] = EntityType.Painting;
+ mappings[53] = EntityType.Panda;
+ mappings[54] = EntityType.Parrot;
+ mappings[55] = EntityType.Pig;
+ mappings[56] = EntityType.Pufferfish;
+ mappings[57] = EntityType.ZombiePigman;
+ mappings[58] = EntityType.PolarBear;
+ mappings[59] = EntityType.Tnt;
+ mappings[60] = EntityType.Rabbit;
+ mappings[61] = EntityType.Salmon;
+ mappings[62] = EntityType.Sheep;
+ mappings[63] = EntityType.Shulker;
+ mappings[64] = EntityType.ShulkerBullet;
+ mappings[65] = EntityType.Silverfish;
+ mappings[66] = EntityType.Skeleton;
+ mappings[67] = EntityType.SkeletonHorse;
+ mappings[68] = EntityType.Slime;
+ mappings[69] = EntityType.SmallFireball;
+ mappings[70] = EntityType.SnowGolem;
+ mappings[71] = EntityType.Snowball;
+ mappings[72] = EntityType.SpectralArrow;
+ mappings[73] = EntityType.Spider;
+ mappings[74] = EntityType.Squid;
+ mappings[75] = EntityType.Stray;
+ mappings[76] = EntityType.TraderLlama;
+ mappings[77] = EntityType.TropicalFish;
+ mappings[78] = EntityType.Turtle;
+ mappings[79] = EntityType.Egg;
+ mappings[80] = EntityType.EnderPearl;
+ mappings[81] = EntityType.ExperienceBottle;
+ mappings[82] = EntityType.Potion;
+ mappings[83] = EntityType.Trident;
+ mappings[84] = EntityType.Vex;
+ mappings[85] = EntityType.Villager;
+ mappings[86] = EntityType.IronGolem;
+ mappings[87] = EntityType.Vindicator;
+ mappings[88] = EntityType.Pillager;
+ mappings[89] = EntityType.WanderingTrader;
+ mappings[90] = EntityType.Witch;
+ mappings[91] = EntityType.Wither;
+ mappings[92] = EntityType.WitherSkeleton;
+ mappings[93] = EntityType.WitherSkull;
+ mappings[94] = EntityType.Wolf;
+ mappings[95] = EntityType.Zombie;
+ mappings[96] = EntityType.ZombieHorse;
+ mappings[97] = EntityType.ZombieVillager;
+ mappings[98] = EntityType.Phantom;
+ mappings[99] = EntityType.Ravager;
+ mappings[100] = EntityType.LightningBolt;
+ mappings[101] = EntityType.Player;
+ mappings[102] = EntityType.FishingBobber;
+ }
+
+ protected override Dictionary GetDict()
+ {
+ return mappings;
+ }
+ }
+}
diff --git a/MinecraftClient/Mapping/EntityPalettes/EntityPaletteGenerator.cs b/MinecraftClient/Mapping/EntityPalettes/EntityPaletteGenerator.cs
new file mode 100644
index 00000000..141bcf6d
--- /dev/null
+++ b/MinecraftClient/Mapping/EntityPalettes/EntityPaletteGenerator.cs
@@ -0,0 +1,20 @@
+using MinecraftClient.Protocol;
+
+namespace MinecraftClient.Mapping.EntityPalettes
+{
+ ///
+ /// Generator for MCC ItemType enumeration
+ ///
+ public static class EntityPaletteGenerator
+ {
+ ///
+ /// Generate EntityType.cs from Minecraft registries.json
+ ///
+ /// path to registries.json
+ /// java -cp minecraft_server.jar net.minecraft.data.Main --reports
+ public static void GenerateEntityTypes(string registriesJsonFile)
+ {
+ DataTypeGenerator.GenerateEnumWithPalette(registriesJsonFile, "minecraft:entity_type", "EntityType", "MinecraftClient.Mapping", "EntityPalette", "MinecraftClient.Mapping.EntityPalettes");
+ }
+ }
+}
diff --git a/MinecraftClient/Mapping/EntityPalettes/EntityType114.cs b/MinecraftClient/Mapping/EntityPalettes/EntityType114.cs
new file mode 100644
index 00000000..52ff21de
--- /dev/null
+++ b/MinecraftClient/Mapping/EntityPalettes/EntityType114.cs
@@ -0,0 +1,108 @@
+namespace MinecraftClient.Mapping
+{
+ public enum EntityType115
+ {
+ AreaEffectCloud = 0,
+ ArmorStand = 1,
+ Arrow = 2,
+ Bat = 3,
+ Blaze = 4,
+ Boat = 5,
+ Cat = 6,
+ CaveSpider = 7,
+ Chicken = 8,
+ Cod = 9,
+ Cow = 10,
+ Creeper = 11,
+ Donkey = 12,
+ Dolphin = 13,
+ DragonFireball = 14,
+ Drowned = 15,
+ ElderGuardian = 16,
+ EndCrystal = 17,
+ EnderDragon = 18,
+ Enderman = 19,
+ Endermite = 20,
+ EvokerFangs = 21,
+ Evoker = 22,
+ ExperienceOrb = 23,
+ EyeOfEnder = 24,
+ FallingBlock = 25,
+ FireworkRocket = 26,
+ Fox = 27,
+ Ghast = 28,
+ Giant = 29,
+ Guardian = 30,
+ Horse = 31,
+ Husk = 32,
+ Illusioner = 33,
+ Item = 34,
+ ItemFrame = 35,
+ Fireball = 36,
+ LeashKnot = 37,
+ Llama = 38,
+ LlamaSpit = 39,
+ MagmaCube = 40,
+ Minecart = 41,
+ ChestMinecart = 42,
+ CommandBlockMinecart = 43,
+ FurnaceMinecart = 44,
+ HopperMinecart = 45,
+ SpawnerMinecart = 46,
+ TntMinecart = 47,
+ Mule = 48,
+ Mooshroom = 49,
+ Ocelot = 50,
+ Painting = 51,
+ Panda = 52,
+ Parrot = 53,
+ Pig = 54,
+ Pufferfish = 55,
+ ZombiePigman = 56,
+ PolarBear = 57,
+ Tnt = 58,
+ Rabbit = 59,
+ Salmon = 60,
+ Sheep = 61,
+ Shulker = 62,
+ ShulkerBullet = 63,
+ Silverfish = 64,
+ Skeleton = 65,
+ SkeletonHorse = 66,
+ Slime = 67,
+ SmallFireball = 68,
+ SnowGolem = 69,
+ Snowball = 70,
+ SpectralArrow = 71,
+ Spider = 72,
+ Squid = 73,
+ Stray = 74,
+ TraderLlama = 75,
+ TropicalFish = 76,
+ Turtle = 77,
+ Egg = 78,
+ EnderPearl = 79,
+ ExperienceBottle = 80,
+ Potion = 81,
+ Trident = 82,
+ Vex = 83,
+ Villager = 84,
+ IronGolem = 85,
+ Vindicator = 86,
+ Pillager = 87,
+ WanderingTrader = 88,
+ Witch = 89,
+ Wither = 90,
+ WitherSkeleton = 91,
+ WitherSkull = 92,
+ Wolf = 93,
+ Zombie = 94,
+ ZombieHorse = 95,
+ ZombieVillager = 96,
+ Phantom = 97,
+ Ravager = 98,
+ LightningBolt = 99,
+ Player = 100,
+ FishingBobber = 101,
+ }
+}
diff --git a/MinecraftClient/Mapping/EntityPalettes/EntityType115.cs b/MinecraftClient/Mapping/EntityPalettes/EntityType115.cs
new file mode 100644
index 00000000..66361ac0
--- /dev/null
+++ b/MinecraftClient/Mapping/EntityPalettes/EntityType115.cs
@@ -0,0 +1,109 @@
+namespace MinecraftClient.Mapping
+{
+ public enum EntityType114
+ {
+ AreaEffectCloud = 0,
+ ArmorStand = 1,
+ Arrow = 2,
+ Bat = 3,
+ Bee = 4,
+ Blaze = 5,
+ Boat = 6,
+ Cat = 7,
+ CaveSpider = 8,
+ Chicken = 9,
+ Cod = 10,
+ Cow = 11,
+ Creeper = 12,
+ Donkey = 13,
+ Dolphin = 14,
+ DragonFireball = 15,
+ Drowned = 16,
+ ElderGuardian = 17,
+ EndCrystal = 18,
+ EnderDragon = 19,
+ Enderman = 20,
+ Endermite = 21,
+ EvokerFangs = 22,
+ Evoker = 23,
+ ExperienceOrb = 24,
+ EyeOfEnder = 25,
+ FallingBlock = 26,
+ FireworkRocket = 27,
+ Fox = 28,
+ Ghast = 29,
+ Giant = 30,
+ Guardian = 31,
+ Horse = 32,
+ Husk = 33,
+ Illusioner = 34,
+ Item = 35,
+ ItemFrame = 36,
+ Fireball = 37,
+ LeashKnot = 38,
+ Llama = 39,
+ LlamaSpit = 40,
+ MagmaCube = 41,
+ Minecart = 42,
+ ChestMinecart = 43,
+ CommandBlockMinecart = 44,
+ FurnaceMinecart = 45,
+ HopperMinecart = 46,
+ SpawnerMinecart = 47,
+ TntMinecart = 48,
+ Mule = 49,
+ Mooshroom = 50,
+ Ocelot = 51,
+ Painting = 52,
+ Panda = 53,
+ Parrot = 54,
+ Pig = 55,
+ Pufferfish = 56,
+ ZombiePigman = 57,
+ PolarBear = 58,
+ Tnt = 59,
+ Rabbit = 60,
+ Salmon = 61,
+ Sheep = 62,
+ Shulker = 63,
+ ShulkerBullet = 64,
+ Silverfish = 65,
+ Skeleton = 66,
+ SkeletonHorse = 67,
+ Slime = 68,
+ SmallFireball = 69,
+ SnowGolem = 70,
+ Snowball = 71,
+ SpectralArrow = 72,
+ Spider = 73,
+ Squid = 74,
+ Stray = 75,
+ TraderLlama = 76,
+ TropicalFish = 77,
+ Turtle = 78,
+ Egg = 79,
+ EnderPearl = 80,
+ ExperienceBottle = 81,
+ Potion = 82,
+ Trident = 83,
+ Vex = 84,
+ Villager = 85,
+ IronGolem = 86,
+ Vindicator = 87,
+ Pillager = 88,
+ WanderingTrader = 89,
+ Witch = 90,
+ Wither = 91,
+ WitherSkeleton = 92,
+ WitherSkull = 93,
+ Wolf = 94,
+ Zombie = 95,
+ ZombieHorse = 96,
+ ZombieVillager = 97,
+ Phantom = 98,
+ Ravager = 99,
+ LightningBolt = 100,
+ Player = 101,
+ FishingBobber = 102,
+ }
+}
diff --git a/MinecraftClient/Mapping/EntityType.cs b/MinecraftClient/Mapping/EntityType.cs
index 9333f222..63ae6de2 100644
--- a/MinecraftClient/Mapping/EntityType.cs
+++ b/MinecraftClient/Mapping/EntityType.cs
@@ -1,14 +1,121 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-
namespace MinecraftClient.Mapping
{
+ ///
+ /// Represents Minecraft Entity Types
+ ///
+ ///
+ /// Generated from registries.json using EntityPaletteGenerator.cs.
+ /// Typical steps to handle new entity IDs for newer Minecraft versions:
+ /// 1. Generate registries.json using data reporting on Vanilla Minecraft (https://wiki.vg/Data_Generators)
+ /// 2. Generate temporary EntityTypeXXX.cs and EntityPaletteXXX.cs using EntityPaletteGenerator.cs
+ /// 3. Perform a diff with existing versions, add missing entries in EntityType.cs and EntityTypeExtensions.cs
+ /// 4. If existing entity IDs were not randomized by Mojang, simply add missing state entries to the latest existing PaletteXXX.cs
+ /// 5. If existing entity IDs were randomized, add a new palette as PaletteXXX.cs into the codebase (worst case)
+ ///
public enum EntityType
{
- MobAndAnimal,
+ AreaEffectCloud,
+ ArmorStand,
+ Arrow,
+ Bat,
+ Bee,
+ Blaze,
+ Boat,
+ Cat,
+ CaveSpider,
+ Chicken,
+ Cod,
+ Cow,
+ Creeper,
+ Donkey,
+ Dolphin,
+ DragonFireball,
+ Drowned,
+ ElderGuardian,
+ EndCrystal,
+ EnderDragon,
+ Enderman,
+ Endermite,
+ EvokerFangs,
+ Evoker,
+ ExperienceOrb,
+ EyeOfEnder,
+ FallingBlock,
+ FireworkRocket,
+ Fox,
+ Ghast,
+ Giant,
+ Guardian,
+ Horse,
+ Husk,
+ Illusioner,
+ Item,
+ ItemFrame,
+ Fireball,
+ LeashKnot,
+ Llama,
+ LlamaSpit,
+ MagmaCube,
+ Minecart,
+ ChestMinecart,
+ CommandBlockMinecart,
+ FurnaceMinecart,
+ HopperMinecart,
+ SpawnerMinecart,
+ TntMinecart,
+ Mule,
+ Mooshroom,
+ Ocelot,
+ Painting,
+ Panda,
+ Parrot,
+ Pig,
+ Pufferfish,
+ ZombiePigman,
+ PolarBear,
+ Tnt,
+ Rabbit,
+ Salmon,
+ Sheep,
+ Shulker,
+ ShulkerBullet,
+ Silverfish,
+ Skeleton,
+ SkeletonHorse,
+ Slime,
+ SmallFireball,
+ SnowGolem,
+ Snowball,
+ SpectralArrow,
+ Spider,
+ Squid,
+ Stray,
+ TraderLlama,
+ TropicalFish,
+ Turtle,
+ Egg,
+ EnderPearl,
+ ExperienceBottle,
+ Potion,
+ Trident,
+ Vex,
+ Villager,
+ IronGolem,
+ Vindicator,
+ Pillager,
+ WanderingTrader,
+ Witch,
+ Wither,
+ WitherSkeleton,
+ WitherSkull,
+ Wolf,
+ Zombie,
+ ZombieHorse,
+ ZombieVillager,
+ Phantom,
+ Ravager,
+ LightningBolt,
Player,
- NonLivingThings,
+ FishingBobber,
}
}
diff --git a/MinecraftClient/Mapping/EntityTypeExtensions.cs b/MinecraftClient/Mapping/EntityTypeExtensions.cs
new file mode 100644
index 00000000..93dc596a
--- /dev/null
+++ b/MinecraftClient/Mapping/EntityTypeExtensions.cs
@@ -0,0 +1,48 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+
+namespace MinecraftClient.Mapping
+{
+ public static class EntityTypeExtensions
+ {
+ ///
+ /// Return TRUE if the Entity is an hostile mob
+ ///
+ /// New mobs added in newer Minecraft versions might be absent from the list
+ /// TRUE if hostile
+ public static bool IsHostile(this EntityType e)
+ {
+ switch (e)
+ {
+ case EntityType.Blaze:
+ case EntityType.Creeper:
+ case EntityType.Drowned:
+ case EntityType.Evoker:
+ case EntityType.Ghast:
+ case EntityType.Guardian:
+ case EntityType.Husk:
+ case EntityType.MagmaCube:
+ case EntityType.Phantom:
+ case EntityType.Pillager:
+ case EntityType.Ravager:
+ case EntityType.Shulker:
+ case EntityType.Silverfish:
+ case EntityType.Skeleton:
+ case EntityType.Slime:
+ case EntityType.Stray:
+ case EntityType.Vex:
+ case EntityType.Vindicator:
+ case EntityType.Witch:
+ case EntityType.WitherSkeleton:
+ case EntityType.Zombie:
+ case EntityType.ZombiePigman:
+ case EntityType.ZombieVillager:
+ return true;
+ default:
+ return false;
+ }
+ }
+ }
+}
diff --git a/MinecraftClient/McTcpClient.cs b/MinecraftClient/McTcpClient.cs
index c5fb4027..734e78df 100644
--- a/MinecraftClient/McTcpClient.cs
+++ b/MinecraftClient/McTcpClient.cs
@@ -1222,47 +1222,16 @@ namespace MinecraftClient
}
///
- /// Called when a non-living entity spawned (fishing hook, minecart, etc)
+ /// Called when an entity spawned
///
- ///
- ///
- ///
- ///
- public void OnSpawnEntity(int EntityID, int TypeID, Guid UUID, Location location)
+ public void OnSpawnEntity(Entity entity)
{
- if (entities.ContainsKey(EntityID)) return;
- Entity entity = new Entity(EntityID, TypeID, EntityType.NonLivingThings, location, UUID);
- entities.Add(EntityID, entity);
- foreach (ChatBot bot in bots.ToArray())
- {
- try
- {
- bot.OnEntitySpawn(entity);
- }
- catch (Exception e)
- {
- if (!(e is ThreadAbortException))
- {
- ConsoleIO.WriteLogLine("OnEntitySpawn: Got error from " + bot.ToString() + ": " + e.ToString());
- }
- else throw; //ThreadAbortException should not be caught
- }
- }
- }
+ // The entity should not already exist, but if it does, let's consider the previous one is being destroyed
+ if (entities.ContainsKey(entity.ID))
+ OnDestroyEntities(new[] { entity.ID });
+
+ entities.Add(entity.ID, entity);
- ///
- /// Called when an Entity was created/spawned.
- ///
- ///
- ///
- ///
- ///
- /// Cannot determine is a Mob or a Cuty Animal
- public void OnSpawnLivingEntity(int EntityID, int TypeID, Guid UUID, Location location)
- {
- if (entities.ContainsKey(EntityID)) return;
- Entity entity = new Entity(EntityID, TypeID, EntityType.MobAndAnimal, location, UUID);
- entities.Add(EntityID, entity);
foreach (ChatBot bot in bots.ToArray())
{
try
diff --git a/MinecraftClient/MinecraftClient.csproj b/MinecraftClient/MinecraftClient.csproj
index a62ed363..f549f177 100644
--- a/MinecraftClient/MinecraftClient.csproj
+++ b/MinecraftClient/MinecraftClient.csproj
@@ -117,9 +117,15 @@
-
+
+
+
+
+
+
+
@@ -129,6 +135,7 @@
+
diff --git a/MinecraftClient/Program.cs b/MinecraftClient/Program.cs
index 462cbfcb..b5a4f7e7 100644
--- a/MinecraftClient/Program.cs
+++ b/MinecraftClient/Program.cs
@@ -20,6 +20,7 @@ namespace MinecraftClient
/// Typical steps to update MCC for a new Minecraft version
/// - Implement protocol changes (see Protocol18.cs)
/// - Handle new block types and states (see Material.cs)
+ /// - Add support for new entity types (see EntityType.cs)
/// - Add new item types for inventories (see ItemType.cs)
/// - Mark new version as handled (see ProtocolHandler.cs)
/// - Update MCHighestVersion field below (for versionning)
diff --git a/MinecraftClient/Protocol/DataTypeGenerator.cs b/MinecraftClient/Protocol/DataTypeGenerator.cs
new file mode 100644
index 00000000..f0070523
--- /dev/null
+++ b/MinecraftClient/Protocol/DataTypeGenerator.cs
@@ -0,0 +1,144 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.IO;
+
+namespace MinecraftClient.Protocol
+{
+ ///
+ /// Generic generator for MCC Enumerations such as ItemType or EntityType, mapping protocol IDs to actual enumeration fields such as 1 => Stone for inventories.
+ /// Works by processing Minecraft registries.json exported from minecraft_server.jar
+ ///
+ /// java -cp minecraft_server.jar net.minecraft.data.Main --reports
+ public static class DataTypeGenerator
+ {
+ ///
+ /// Read Minecraft registry from Json and build a dictionary
+ ///
+ /// Path to registries.json generated from Minecraft server Jar
+ /// Name of registry we want to process, e.g. minecraft:item
+ ///
+ private static Dictionary LoadRegistry(string registriesJsonFile, string jsonRegistryName)
+ {
+ Json.JSONData rawJson = Json.ParseJson(File.ReadAllText(registriesJsonFile));
+ Json.JSONData rawRegistry = rawJson.Properties[jsonRegistryName].Properties["entries"];
+ Dictionary registry = new Dictionary();
+
+ foreach (KeyValuePair entry in rawRegistry.Properties)
+ {
+ int entryId = int.Parse(entry.Value.Properties["protocol_id"].StringValue);
+
+ //minecraft:item_name => ItemName
+ string entryName = String.Concat(
+ entry.Key.Replace("minecraft:", "")
+ .Split('_')
+ .Select(word => char.ToUpper(word[0]) + word.Substring(1))
+ );
+
+ if (registry.ContainsKey(entryId))
+ throw new InvalidDataException("Duplicate entry ID " + entryId + "!?");
+
+ registry.Add(entryId, entryName);
+ }
+
+ return registry;
+ }
+
+ ///
+ /// Generate MCC Enum from a Minecraft registry without Palette (static enum that does not change between versions)
+ ///
+ /// Path to registries.json generated from Minecraft server Jar
+ /// Name of registry we want to process, e.g. minecraft:item
+ /// Output enum name, e.g. ItemType (output file will be ItemType.cs)
+ /// Output enum namespace, e.g. MinecraftClient.Inventory
+ public static void GenerateEnum(string registriesJsonFile, string jsonRegistryName, string outputEnum, string enumNamespace)
+ {
+ List outputEnumLines = new List();
+
+ outputEnumLines.AddRange(new[] {
+ "namespace " + enumNamespace,
+ "{",
+ " public enum " + outputEnum,
+ " {"
+ });
+
+ Dictionary registry = LoadRegistry(registriesJsonFile, jsonRegistryName);
+ foreach (KeyValuePair entry in registry)
+ outputEnumLines.Add(" " + entry.Value + " = " + entry.Key + ',');
+
+ outputEnumLines.AddRange(new[] {
+ " }",
+ "}"
+ });
+
+ string outputEnumPath = Path.Combine(Path.GetDirectoryName(registriesJsonFile), outputEnum + "XXX.cs");
+ File.WriteAllLines(outputEnumPath, outputEnumLines);
+ }
+
+ ///
+ /// Generate MCC Enum from a Minecraft registry with Palette (dynamic enum that changes between versions)
+ ///
+ /// Path to registries.json generated from Minecraft server Jar
+ /// Name of registry we want to process, e.g. minecraft:item
+ /// Output enum name, e.g. ItemType (output file will be ItemType.cs)
+ /// Enum namespace, e.g. MinecraftClient.Mapping
+ /// Output palette name, e.g. ItemPalette (output file will be ItemPalette.cs and ItemPaletteXXX.cs)
+ /// Palette namespace, e.g. MinecraftClient.EntityPalettes
+ public static void GenerateEnumWithPalette(string registriesJsonFile, string jsonRegistryName, string outputEnum, string enumNamespace, string outputPalette, string paletteNamespace)
+ {
+ List outputEnumLines = new List();
+ List outputPaletteLines = new List();
+
+ outputEnumLines.AddRange(new[] {
+ "namespace " + enumNamespace,
+ "{",
+ " public enum " + outputEnum,
+ " {"
+ });
+
+ outputPaletteLines.AddRange(new[] {
+ "using System;",
+ "using System.Collections.Generic;",
+ "",
+ "namespace " + paletteNamespace,
+ "{",
+ " public class " + outputPalette + "XXX : " + outputPalette,
+ " {",
+ " private static Dictionary mappings = new Dictionary();",
+ "",
+ " static " + outputPalette + "XXX()",
+ " {",
+ });
+
+ Dictionary registry = LoadRegistry(registriesJsonFile, jsonRegistryName);
+
+ foreach (KeyValuePair entry in registry)
+ {
+ outputEnumLines.Add(" " + entry.Value + ',');
+ outputPaletteLines.Add(" mappings[" + entry.Key + "] = " + outputEnum + "." + entry.Value + ";");
+ }
+
+ outputEnumLines.AddRange(new[] {
+ " }",
+ "}"
+ });
+
+ outputPaletteLines.AddRange(new[] {
+ " }",
+ "",
+ " protected override Dictionary GetDict()",
+ " {",
+ " return mappings;",
+ " }",
+ " }",
+ "}"
+ });
+
+ string outputEnumPath = Path.Combine(Path.GetDirectoryName(registriesJsonFile), outputEnum + "XXX.cs");
+ string outputPalettePath = Path.Combine(Path.GetDirectoryName(registriesJsonFile), outputPalette + "XXX.cs");
+
+ File.WriteAllLines(outputEnumPath, outputEnumLines);
+ File.WriteAllLines(outputPalettePath, outputPaletteLines);
+ }
+ }
+}
diff --git a/MinecraftClient/Protocol/Handlers/DataTypes.cs b/MinecraftClient/Protocol/Handlers/DataTypes.cs
index 6cccbdd9..bad87456 100644
--- a/MinecraftClient/Protocol/Handlers/DataTypes.cs
+++ b/MinecraftClient/Protocol/Handlers/DataTypes.cs
@@ -6,6 +6,7 @@ using System.Net.Sockets;
using MinecraftClient.Mapping;
using MinecraftClient.Crypto;
using MinecraftClient.Inventory;
+using MinecraftClient.Mapping.EntityPalettes;
namespace MinecraftClient.Protocol.Handlers
{
@@ -321,9 +322,8 @@ namespace MinecraftClient.Protocol.Handlers
}
///
- /// Read a single item slot from a cache of byte and remove it from the cache
+ /// Read a single item slot from a cache of bytes and remove it from the cache
///
- /// Item
/// The item that was read or NULL for an empty slot
public Item ReadNextItemSlot(Queue cache)
{
@@ -354,6 +354,45 @@ namespace MinecraftClient.Protocol.Handlers
}
}
+ ///
+ /// Read entity information from a cache of bytes and remove it from the cache
+ ///
+ /// Mappings for converting entity type Ids to EntityType
+ /// TRUE for living entities (layout differs)
+ /// Entity information
+ public Entity ReadNextEntity(Queue cache, EntityPalette entityPalette, bool living)
+ {
+ int entityID = ReadNextVarInt(cache);
+ Guid entityUUID = Guid.Empty;
+
+ if (protocolversion > Protocol18Handler.MC18Version)
+ {
+ entityUUID = ReadNextUUID(cache);
+ }
+
+ EntityType entityType = entityPalette.FromId(ReadNextVarInt(cache), living);
+ Double entityX = ReadNextDouble(cache);
+ Double entityY = ReadNextDouble(cache);
+ Double entityZ = ReadNextDouble(cache);
+ byte entityYaw = ReadNextByte(cache);
+ byte entityPitch = ReadNextByte(cache);
+
+ if (living)
+ {
+ byte entityHeadPitch = ReadNextByte(cache);
+ }
+ else
+ {
+ int metadata = ReadNextInt(cache);
+ }
+
+ short velocityX = ReadNextShort(cache);
+ short velocityY = ReadNextShort(cache);
+ short velocityZ = ReadNextShort(cache);
+
+ return new Entity(entityID, entityType, new Location(entityX, entityY, entityZ));
+ }
+
///
/// Read an uncompressed Named Binary Tag blob and remove it from the cache (internal)
///
diff --git a/MinecraftClient/Protocol/Handlers/Protocol18.cs b/MinecraftClient/Protocol/Handlers/Protocol18.cs
index df8639f0..2c1cef89 100644
--- a/MinecraftClient/Protocol/Handlers/Protocol18.cs
+++ b/MinecraftClient/Protocol/Handlers/Protocol18.cs
@@ -9,6 +9,7 @@ using MinecraftClient.Proxy;
using System.Security.Cryptography;
using MinecraftClient.Mapping;
using MinecraftClient.Mapping.BlockPalettes;
+using MinecraftClient.Mapping.EntityPalettes;
using MinecraftClient.Protocol.Handlers.Forge;
using MinecraftClient.Inventory;
@@ -50,6 +51,7 @@ namespace MinecraftClient.Protocol.Handlers
Protocol18Forge pForge;
Protocol18Terrain pTerrain;
IMinecraftComHandler handler;
+ EntityPalette entityPalette;
SocketWrapper socketWrapper;
DataTypes dataTypes;
Thread netRead;
@@ -94,6 +96,16 @@ namespace MinecraftClient.Protocol.Handlers
else Block.Palette = new Palette113();
}
else Block.Palette = new Palette112();
+
+ if (protocolversion >= MC114Version)
+ {
+ if (protocolversion > MC1152Version && handler.GetEntityHandlingEnabled())
+ throw new NotImplementedException("Please update entity types handling for this Minecraft version. See EntityType.cs");
+ if (protocolversion >= MC115Version)
+ entityPalette = new EntityPalette115();
+ else entityPalette = new EntityPalette114();
+ }
+ else entityPalette = new EntityPalette113();
}
///
@@ -195,7 +207,7 @@ namespace MinecraftClient.Protocol.Handlers
}
}
// Regular in-game packets
- switch (Protocol18PacketTypes.GetPacketIncomingType(packetID, protocolversion))
+ else switch (Protocol18PacketTypes.GetPacketIncomingType(packetID, protocolversion))
{
case PacketIncomingType.KeepAlive:
SendPacket(PacketOutgoingType.KeepAlive, packetData);
@@ -569,54 +581,18 @@ namespace MinecraftClient.Protocol.Handlers
case PacketIncomingType.SpawnEntity:
if (handler.GetEntityHandlingEnabled())
{
- int EntityID = dataTypes.ReadNextVarInt(packetData);
- Guid EntityUUID = Guid.Empty;
- if (protocolversion > MC18Version)
- {
- EntityUUID = dataTypes.ReadNextUUID(packetData);
- }
- int EntityType = dataTypes.ReadNextVarInt(packetData);
- Double X = dataTypes.ReadNextDouble(packetData);
- Double Y = dataTypes.ReadNextDouble(packetData);
- Double Z = dataTypes.ReadNextDouble(packetData);
- byte EntityYaw = dataTypes.ReadNextByte(packetData);
- byte EntityPitch = dataTypes.ReadNextByte(packetData);
- int Data = dataTypes.ReadNextInt(packetData);
- short VelocityX = dataTypes.ReadNextShort(packetData);
- short VelocityY = dataTypes.ReadNextShort(packetData);
- short VelocityZ = dataTypes.ReadNextShort(packetData);
-
- Location EntityLocation = new Location(X, Y, Z);
-
- handler.OnSpawnEntity(EntityID, EntityType, EntityUUID, EntityLocation);
+ Entity entity = dataTypes.ReadNextEntity(packetData, entityPalette, false);
+ handler.OnSpawnEntity(entity);
}
break;
case PacketIncomingType.SpawnLivingEntity:
- if (login_phase) break; // same packet ID with login packet
if (handler.GetEntityHandlingEnabled())
{
- int EntityID = dataTypes.ReadNextVarInt(packetData);
- Guid EntityUUID = Guid.Empty;
- if (protocolversion > MC18Version)
- {
- EntityUUID = dataTypes.ReadNextUUID(packetData);
- }
- int EntityType = dataTypes.ReadNextVarInt(packetData);
- Double X = dataTypes.ReadNextDouble(packetData);
- Double Y = dataTypes.ReadNextDouble(packetData);
- Double Z = dataTypes.ReadNextDouble(packetData);
- byte EntityYaw = dataTypes.ReadNextByte(packetData);
- byte EntityPitch = dataTypes.ReadNextByte(packetData);
- byte EntityHeadPitch = dataTypes.ReadNextByte(packetData);
- short VelocityX = dataTypes.ReadNextShort(packetData);
- short VelocityY = dataTypes.ReadNextShort(packetData);
- short VelocityZ = dataTypes.ReadNextShort(packetData);
-
+ Entity entity = dataTypes.ReadNextEntity(packetData, entityPalette, true);
// packet before 1.15 has metadata at the end
-
- Location EntityLocation = new Location(X, Y, Z);
-
- handler.OnSpawnLivingEntity(EntityID, EntityType, EntityUUID, EntityLocation);
+ // this is not handled in dataTypes.ReadNextEntity()
+ // we are simply ignoring leftover data in packet
+ handler.OnSpawnEntity(entity);
}
break;
case PacketIncomingType.SpawnPlayer:
@@ -713,7 +689,6 @@ namespace MinecraftClient.Protocol.Handlers
}
break;
case PacketIncomingType.TimeUpdate:
- if (login_phase) break;
long WorldAge = dataTypes.ReadNextLong(packetData);
long TimeOfday = dataTypes.ReadNextLong(packetData);
handler.OnTimeUpdate(WorldAge, TimeOfday);
diff --git a/MinecraftClient/Protocol/Handlers/Protocol18PacketTypes.cs b/MinecraftClient/Protocol/Handlers/Protocol18PacketTypes.cs
index b85a36bb..eef0045d 100644
--- a/MinecraftClient/Protocol/Handlers/Protocol18PacketTypes.cs
+++ b/MinecraftClient/Protocol/Handlers/Protocol18PacketTypes.cs
@@ -46,8 +46,8 @@ namespace MinecraftClient.Protocol.Handlers
// Set Cooldown does not exists
case 0x03: return PacketIncomingType.TimeUpdate;
// Entity handling
- case 0x0E: return PacketIncomingType.SpawnEntity; // for non-living entity
- case 0x0F: return PacketIncomingType.SpawnLivingEntity; // for living entity
+ case 0x0E: return PacketIncomingType.SpawnEntity;
+ case 0x0F: return PacketIncomingType.SpawnLivingEntity;
case 0x05: return PacketIncomingType.SpawnPlayer;
case 0x13: return PacketIncomingType.DestroyEntities;
case 0x15: return PacketIncomingType.EntityPosition;
@@ -85,8 +85,8 @@ namespace MinecraftClient.Protocol.Handlers
case 0x17: return PacketIncomingType.SetCooldown;
case 0x44: return PacketIncomingType.TimeUpdate;
// Entity handling
- case 0x00: return PacketIncomingType.SpawnEntity; // for non-living entity
- case 0x03: return PacketIncomingType.SpawnLivingEntity; // for living entity
+ case 0x00: return PacketIncomingType.SpawnEntity;
+ case 0x03: return PacketIncomingType.SpawnLivingEntity;
case 0x05: return PacketIncomingType.SpawnPlayer;
case 0x30: return PacketIncomingType.DestroyEntities;
case 0x25: return PacketIncomingType.EntityPosition;
@@ -122,8 +122,8 @@ namespace MinecraftClient.Protocol.Handlers
case 0x17: return PacketIncomingType.SetCooldown;
case 0x46: return PacketIncomingType.TimeUpdate;
// Entity handling
- case 0x00: return PacketIncomingType.SpawnEntity; // for non-living entity
- case 0x03: return PacketIncomingType.SpawnLivingEntity; // for living entity
+ case 0x00: return PacketIncomingType.SpawnEntity;
+ case 0x03: return PacketIncomingType.SpawnLivingEntity;
case 0x05: return PacketIncomingType.SpawnPlayer;
case 0x31: return PacketIncomingType.DestroyEntities;
case 0x26: return PacketIncomingType.EntityPosition;
@@ -159,8 +159,8 @@ namespace MinecraftClient.Protocol.Handlers
case 0x17: return PacketIncomingType.SetCooldown;
case 0x47: return PacketIncomingType.TimeUpdate;
// Entity handling
- case 0x00: return PacketIncomingType.SpawnEntity; // for non-living entity
- case 0x03: return PacketIncomingType.SpawnLivingEntity; // for living entity
+ case 0x00: return PacketIncomingType.SpawnEntity;
+ case 0x03: return PacketIncomingType.SpawnLivingEntity;
case 0x05: return PacketIncomingType.SpawnPlayer;
case 0x32: return PacketIncomingType.DestroyEntities;
case 0x26: return PacketIncomingType.EntityPosition;
@@ -196,8 +196,8 @@ namespace MinecraftClient.Protocol.Handlers
case 0x18: return PacketIncomingType.SetCooldown;
case 0x4A: return PacketIncomingType.TimeUpdate;
// Entity handling
- case 0x00: return PacketIncomingType.SpawnEntity; // for non-living entity
- case 0x03: return PacketIncomingType.SpawnLivingEntity; // for living entity
+ case 0x00: return PacketIncomingType.SpawnEntity;
+ case 0x03: return PacketIncomingType.SpawnLivingEntity;
case 0x05: return PacketIncomingType.SpawnPlayer;
case 0x35: return PacketIncomingType.DestroyEntities;
case 0x28: return PacketIncomingType.EntityPosition;
@@ -232,8 +232,8 @@ namespace MinecraftClient.Protocol.Handlers
case 0x17: return PacketIncomingType.SetCooldown;
case 0x4E: return PacketIncomingType.TimeUpdate;
// Entity handling
- case 0x00: return PacketIncomingType.SpawnEntity; // for non-living entity
- case 0x03: return PacketIncomingType.SpawnLivingEntity; // for living entity
+ case 0x00: return PacketIncomingType.SpawnEntity;
+ case 0x03: return PacketIncomingType.SpawnLivingEntity;
case 0x05: return PacketIncomingType.SpawnPlayer;
case 0x37: return PacketIncomingType.DestroyEntities;
case 0x28: return PacketIncomingType.EntityPosition;
@@ -268,8 +268,8 @@ namespace MinecraftClient.Protocol.Handlers
case 0x18: return PacketIncomingType.SetCooldown;
case 0x4F: return PacketIncomingType.TimeUpdate;
// Entity handling
- case 0x00: return PacketIncomingType.SpawnEntity; // for non-living entity
- case 0x03: return PacketIncomingType.SpawnLivingEntity; // for living entity
+ case 0x00: return PacketIncomingType.SpawnEntity;
+ case 0x03: return PacketIncomingType.SpawnLivingEntity;
case 0x05: return PacketIncomingType.SpawnPlayer;
case 0x38: return PacketIncomingType.DestroyEntities;
case 0x29: return PacketIncomingType.EntityPosition;
diff --git a/MinecraftClient/Protocol/IMinecraftComHandler.cs b/MinecraftClient/Protocol/IMinecraftComHandler.cs
index c870e5cd..778f5d4b 100644
--- a/MinecraftClient/Protocol/IMinecraftComHandler.cs
+++ b/MinecraftClient/Protocol/IMinecraftComHandler.cs
@@ -131,22 +131,10 @@ namespace MinecraftClient.Protocol
void OnPluginChannelMessage(string channel, byte[] data);
///
- /// Called when a non-living entity has spawned
+ /// Called when an entity has spawned
///
- /// Entity ID
- /// Entity Type ID
- /// Entity UUID
- /// Entity location
- void OnSpawnEntity(int EntityID, int EntityType, Guid UUID, Location location);
-
- ///
- /// Called when a living entity has spawned
- ///
- /// Entity ID
- /// Entity Type ID
- /// Entity UUID
- /// Entity location
- void OnSpawnLivingEntity(int EntityID, int EntityType, Guid UUID, Location location);
+ /// Spawned entity
+ void OnSpawnEntity(Entity entity);
///
/// Called when a player has spawned
@@ -156,7 +144,7 @@ namespace MinecraftClient.Protocol
/// Entity location
/// Player head yaw
/// Player head pitch
- void OnSpawnPlayer(int EntityID, Guid UUID, Location location, byte Yaw, byte Pitch);
+ void OnSpawnPlayer(int entityID, Guid uuid, Location location, byte yaw, byte pitch);
///
/// Called when entities have despawned
@@ -172,7 +160,7 @@ namespace MinecraftClient.Protocol
/// Y offset
/// Z offset
/// TRUE if on ground
- void OnEntityPosition(int EntityID, Double Dx, Double Dy, Double Dz,bool onGround);
+ void OnEntityPosition(int entityID, Double dx, Double dy, Double dz,bool onGround);
///
/// Called when an entity moved to fixed coordinates
@@ -182,28 +170,28 @@ namespace MinecraftClient.Protocol
/// Y
/// Z
/// TRUE if on ground
- void OnEntityTeleport(int EntityID, Double X, Double Y, Double Z, bool onGround);
+ void OnEntityTeleport(int entityID, Double x, Double y, Double z, bool onGround);
///
/// Called when additional properties have been received for an entity
///
/// Entity ID
/// Dictionary of properties
- void OnEntityProperties(int EntityID, Dictionary prop);
+ void OnEntityProperties(int entityID, Dictionary prop);
///
/// Called when the world age has been updated
///
/// World age
/// Time of Day
- void OnTimeUpdate(long WorldAge, long TimeOfDay);
+ void OnTimeUpdate(long worldAge, long timeOfDay);
///
/// Called when inventory items have been received
///
/// Inventory ID
/// Item list
- void OnWindowItems(byte inventoryID, Dictionary itemList);
+ void OnWindowItems(byte inventoryID, Dictionary itemList);
///
/// Called when a single slot has been updated inside an inventory