summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Server/Plugins/APIDump/APIDesc.lua13
-rw-r--r--Server/monsters.ini8
-rw-r--r--src/BlockType.h1
-rw-r--r--src/Items/ItemSpawnEgg.h53
-rw-r--r--src/MobSpawner.cpp19
-rw-r--r--src/Mobs/CMakeLists.txt2
-rw-r--r--src/Mobs/IncludeAllMonsters.h1
-rw-r--r--src/Mobs/Monster.cpp186
-rw-r--r--src/Mobs/MonsterTypes.h1
-rw-r--r--src/Mobs/Skeleton.cpp17
-rw-r--r--src/Mobs/Skeleton.h8
-rw-r--r--src/Mobs/WitherSkeleton.cpp62
-rw-r--r--src/Mobs/WitherSkeleton.h28
-rw-r--r--src/Protocol/Protocol_1_10.cpp17
-rw-r--r--src/Protocol/Protocol_1_11.cpp12
-rw-r--r--src/Protocol/Protocol_1_12.cpp13
-rw-r--r--src/Protocol/Protocol_1_13.cpp1
-rw-r--r--src/Protocol/Protocol_1_8.cpp16
-rw-r--r--src/Protocol/Protocol_1_9.cpp18
-rw-r--r--src/World.cpp2
-rw-r--r--src/WorldStorage/NBTChunkSerializer.cpp70
-rwxr-xr-xsrc/WorldStorage/WSSAnvil.cpp37
-rwxr-xr-xsrc/WorldStorage/WSSAnvil.h1
23 files changed, 355 insertions, 231 deletions
diff --git a/Server/Plugins/APIDump/APIDesc.lua b/Server/Plugins/APIDump/APIDesc.lua
index 69e7cd75b..d71a0ccbe 100644
--- a/Server/Plugins/APIDump/APIDesc.lua
+++ b/Server/Plugins/APIDump/APIDesc.lua
@@ -9290,6 +9290,10 @@ a_Player:OpenWindow(Window);
{
Notes = "",
},
+ mtWitherSkeleton =
+ {
+ Notes = "",
+ },
mtWolf =
{
Notes = "",
@@ -16686,6 +16690,10 @@ end
{
Notes = "A flag in the metadata of heads that indicates that the head is a zombie head.",
},
+ E_META_SPAWN_EGG_WITHER_SKELETON =
+ {
+ Notes = ""
+ },
E_META_SPONGE_DRY =
{
Notes = "A flag in the metadata of sponges that indicates that the sponge is dry.",
@@ -16790,6 +16798,10 @@ end
{
Notes = "Something concerning (i.e. reload) is about to happen",
},
+ mtWitherSkeleton =
+ {
+ Notes = ""
+ },
hMain =
{
Notes = "The main hand",
@@ -17049,6 +17061,7 @@ end
"mtVillager",
"mtWitch",
"mtWither",
+ "mtWitherSkeleton",
"mtWolf",
"mtZombie",
"mtZombiePigman",
diff --git a/Server/monsters.ini b/Server/monsters.ini
index bf1fc95a4..31e5b1479 100644
--- a/Server/monsters.ini
+++ b/Server/monsters.ini
@@ -190,6 +190,14 @@ AttackRate=1.0
MaxHealth=26
SightDistance=25.0
+[WitherSkeleton]
+AttackDamage=5.0
+AttackRange=1.0
+AttackRate=1.0
+IsFireproof=1
+MaxHealth=20
+SightDistance=25.0
+
[Wolf]
AttackDamage=8.0
AttackRange=1.0
diff --git a/src/BlockType.h b/src/BlockType.h
index bd4b0c625..8a70226db 100644
--- a/src/BlockType.h
+++ b/src/BlockType.h
@@ -1063,6 +1063,7 @@ enum ENUM_ITEM_META : short
// See also cMonster::eType, since monster type and spawn egg meta are the same
E_META_SPAWN_EGG_PICKUP = 1,
E_META_SPAWN_EGG_EXPERIENCE_ORB = 2,
+ E_META_SPAWN_EGG_WITHER_SKELETON = 5,
E_META_SPAWN_EGG_LEASH_KNOT = 8,
E_META_SPAWN_EGG_PAINTING = 9,
E_META_SPAWN_EGG_ARROW = 10,
diff --git a/src/Items/ItemSpawnEgg.h b/src/Items/ItemSpawnEgg.h
index 52317a6cb..6d4219236 100644
--- a/src/Items/ItemSpawnEgg.h
+++ b/src/Items/ItemSpawnEgg.h
@@ -60,32 +60,33 @@ public:
{
switch (a_ItemDamage)
{
- case E_META_SPAWN_EGG_BAT: return mtBat;
- case E_META_SPAWN_EGG_BLAZE: return mtBlaze;
- case E_META_SPAWN_EGG_CAVE_SPIDER: return mtCaveSpider;
- case E_META_SPAWN_EGG_CHICKEN: return mtChicken;
- case E_META_SPAWN_EGG_COW: return mtCow;
- case E_META_SPAWN_EGG_CREEPER: return mtCreeper;
- case E_META_SPAWN_EGG_ENDERMAN: return mtEnderman;
- case E_META_SPAWN_EGG_GHAST: return mtGhast;
- case E_META_SPAWN_EGG_GUARDIAN: return mtGuardian;
- case E_META_SPAWN_EGG_HORSE: return mtHorse;
- case E_META_SPAWN_EGG_MAGMA_CUBE: return mtMagmaCube;
- case E_META_SPAWN_EGG_MOOSHROOM: return mtMooshroom;
- case E_META_SPAWN_EGG_OCELOT: return mtOcelot;
- case E_META_SPAWN_EGG_PIG: return mtPig;
- case E_META_SPAWN_EGG_RABBIT: return mtRabbit;
- case E_META_SPAWN_EGG_SHEEP: return mtSheep;
- case E_META_SPAWN_EGG_SILVERFISH: return mtSilverfish;
- case E_META_SPAWN_EGG_SKELETON: return mtSkeleton;
- case E_META_SPAWN_EGG_SLIME: return mtSlime;
- case E_META_SPAWN_EGG_SPIDER: return mtSpider;
- case E_META_SPAWN_EGG_SQUID: return mtSquid;
- case E_META_SPAWN_EGG_VILLAGER: return mtVillager;
- case E_META_SPAWN_EGG_WITCH: return mtWitch;
- case E_META_SPAWN_EGG_WOLF: return mtWolf;
- case E_META_SPAWN_EGG_ZOMBIE: return mtZombie;
- case E_META_SPAWN_EGG_ZOMBIE_PIGMAN: return mtZombiePigman;
+ case E_META_SPAWN_EGG_BAT: return mtBat;
+ case E_META_SPAWN_EGG_BLAZE: return mtBlaze;
+ case E_META_SPAWN_EGG_CAVE_SPIDER: return mtCaveSpider;
+ case E_META_SPAWN_EGG_CHICKEN: return mtChicken;
+ case E_META_SPAWN_EGG_COW: return mtCow;
+ case E_META_SPAWN_EGG_CREEPER: return mtCreeper;
+ case E_META_SPAWN_EGG_ENDERMAN: return mtEnderman;
+ case E_META_SPAWN_EGG_GHAST: return mtGhast;
+ case E_META_SPAWN_EGG_GUARDIAN: return mtGuardian;
+ case E_META_SPAWN_EGG_HORSE: return mtHorse;
+ case E_META_SPAWN_EGG_MAGMA_CUBE: return mtMagmaCube;
+ case E_META_SPAWN_EGG_MOOSHROOM: return mtMooshroom;
+ case E_META_SPAWN_EGG_OCELOT: return mtOcelot;
+ case E_META_SPAWN_EGG_PIG: return mtPig;
+ case E_META_SPAWN_EGG_RABBIT: return mtRabbit;
+ case E_META_SPAWN_EGG_SHEEP: return mtSheep;
+ case E_META_SPAWN_EGG_SILVERFISH: return mtSilverfish;
+ case E_META_SPAWN_EGG_SKELETON: return mtSkeleton;
+ case E_META_SPAWN_EGG_SLIME: return mtSlime;
+ case E_META_SPAWN_EGG_SPIDER: return mtSpider;
+ case E_META_SPAWN_EGG_SQUID: return mtSquid;
+ case E_META_SPAWN_EGG_VILLAGER: return mtVillager;
+ case E_META_SPAWN_EGG_WITCH: return mtWitch;
+ case E_META_SPAWN_EGG_WITHER_SKELETON: return mtWitherSkeleton;
+ case E_META_SPAWN_EGG_WOLF: return mtWolf;
+ case E_META_SPAWN_EGG_ZOMBIE: return mtZombie;
+ case E_META_SPAWN_EGG_ZOMBIE_PIGMAN: return mtZombiePigman;
}
return mtInvalidType;
}
diff --git a/src/MobSpawner.cpp b/src/MobSpawner.cpp
index 73531f2fc..4d18b7358 100644
--- a/src/MobSpawner.cpp
+++ b/src/MobSpawner.cpp
@@ -287,6 +287,18 @@ bool cMobSpawner::CanSpawnHere(cChunk * a_Chunk, Vector3i a_RelPos, eMonsterType
);
}
+ case mtWitherSkeleton:
+ {
+ return (
+ (targetBlock == E_BLOCK_AIR) &&
+ (blockAbove == E_BLOCK_AIR) &&
+ (!cBlockInfo::IsTransparent(blockBelow)) &&
+ (skyLight <= 7) &&
+ (blockLight <= 7) &&
+ (random.RandBool(0.6))
+ );
+ }
+
case mtWolf:
{
return (
@@ -443,6 +455,7 @@ std::set<eMonsterType> cMobSpawner::GetAllowedMobTypes(EMCSBiome a_Biome)
ListOfSpawnables.insert(mtBlaze);
ListOfSpawnables.insert(mtGhast);
ListOfSpawnables.insert(mtMagmaCube);
+ ListOfSpawnables.insert(mtWitherSkeleton);
ListOfSpawnables.insert(mtZombiePigman);
return ListOfSpawnables;
@@ -461,7 +474,11 @@ cMonster * cMobSpawner::TryToSpawnHere(cChunk * a_Chunk, Vector3i a_RelPos, EMCS
{
return nullptr;
}
- if (m_MobType == mtWolf)
+ if (m_MobType == mtWitherSkeleton)
+ {
+ a_MaxPackSize = 5;
+ }
+ else if (m_MobType == mtWolf)
{
a_MaxPackSize = 8;
}
diff --git a/src/Mobs/CMakeLists.txt b/src/Mobs/CMakeLists.txt
index d9969cfdc..15456595c 100644
--- a/src/Mobs/CMakeLists.txt
+++ b/src/Mobs/CMakeLists.txt
@@ -33,6 +33,7 @@ SET (SRCS
Villager.cpp
Witch.cpp
Wither.cpp
+ WitherSkeleton.cpp
Wolf.cpp
Zombie.cpp
ZombiePigman.cpp)
@@ -74,6 +75,7 @@ SET (HDRS
Villager.h
Witch.h
Wither.h
+ WitherSkeleton.h
Wolf.h
Zombie.h
ZombiePigman.h)
diff --git a/src/Mobs/IncludeAllMonsters.h b/src/Mobs/IncludeAllMonsters.h
index 53c709c2b..17a9dfacd 100644
--- a/src/Mobs/IncludeAllMonsters.h
+++ b/src/Mobs/IncludeAllMonsters.h
@@ -26,6 +26,7 @@
#include "Villager.h"
#include "Witch.h"
#include "Wither.h"
+#include "WitherSkeleton.h"
#include "Wolf.h"
#include "Zombie.h"
#include "ZombiePigman.h"
diff --git a/src/Mobs/Monster.cpp b/src/Mobs/Monster.cpp
index 5a01663e5..b56390b6f 100644
--- a/src/Mobs/Monster.cpp
+++ b/src/Mobs/Monster.cpp
@@ -37,37 +37,38 @@ static const struct
const char * m_VanillaNameNBT;
} g_MobTypeNames[] =
{
- {mtBat, "bat", "Bat", "bat"},
- {mtBlaze, "blaze", "Blaze", "blaze"},
- {mtCaveSpider, "cavespider", "CaveSpider", "cave_spider"},
- {mtChicken, "chicken", "Chicken", "chicken"},
- {mtCow, "cow", "Cow", "cow"},
- {mtCreeper, "creeper", "Creeper", "creeper"},
- {mtEnderman, "enderman", "Enderman", "enderman"},
- {mtEnderDragon, "enderdragon", "EnderDragon", "ender_dragon"},
- {mtGhast, "ghast", "Ghast", "ghast"},
- {mtGiant, "giant", "Giant", "giant"},
- {mtGuardian, "guardian", "Guardian", "guardian"},
- {mtHorse, "horse", "EntityHorse", "horse"},
- {mtIronGolem, "irongolem", "VillagerGolem", "iron_golem"},
- {mtMagmaCube, "magmacube", "LavaSlime", "magma_cube"},
- {mtMooshroom, "mooshroom", "MushroomCow", "mooshroom"},
- {mtOcelot, "ocelot", "Ozelot", "ocelot"},
- {mtPig, "pig", "Pig", "pig"},
- {mtRabbit, "rabbit", "Rabbit", "rabbit"},
- {mtSheep, "sheep", "Sheep", "sheep"},
- {mtSilverfish, "silverfish", "Silverfish", "silverfish"},
- {mtSkeleton, "skeleton", "Skeleton", "skeleton"},
- {mtSlime, "slime", "Slime", "slime"},
- {mtSnowGolem, "snowgolem", "SnowMan", "snow_golem"},
- {mtSpider, "spider", "Spider", "spider"},
- {mtSquid, "squid", "Squid", "squid"},
- {mtVillager, "villager", "Villager", "villager"},
- {mtWitch, "witch", "Witch", "witch"},
- {mtWither, "wither", "WitherBoss", "wither"},
- {mtWolf, "wolf", "Wolf", "wolf"},
- {mtZombie, "zombie", "Zombie", "zombie"},
- {mtZombiePigman, "zombiepigman", "PigZombie", "zombie_pigman"},
+ {mtBat, "bat", "Bat", "bat"},
+ {mtBlaze, "blaze", "Blaze", "blaze"},
+ {mtCaveSpider, "cavespider", "CaveSpider", "cave_spider"},
+ {mtChicken, "chicken", "Chicken", "chicken"},
+ {mtCow, "cow", "Cow", "cow"},
+ {mtCreeper, "creeper", "Creeper", "creeper"},
+ {mtEnderman, "enderman", "Enderman", "enderman"},
+ {mtEnderDragon, "enderdragon", "EnderDragon", "ender_dragon"},
+ {mtGhast, "ghast", "Ghast", "ghast"},
+ {mtGiant, "giant", "Giant", "giant"},
+ {mtGuardian, "guardian", "Guardian", "guardian"},
+ {mtHorse, "horse", "EntityHorse", "horse"},
+ {mtIronGolem, "irongolem", "VillagerGolem", "iron_golem"},
+ {mtMagmaCube, "magmacube", "LavaSlime", "magma_cube"},
+ {mtMooshroom, "mooshroom", "MushroomCow", "mooshroom"},
+ {mtOcelot, "ocelot", "Ozelot", "ocelot"},
+ {mtPig, "pig", "Pig", "pig"},
+ {mtRabbit, "rabbit", "Rabbit", "rabbit"},
+ {mtSheep, "sheep", "Sheep", "sheep"},
+ {mtSilverfish, "silverfish", "Silverfish", "silverfish"},
+ {mtSkeleton, "skeleton", "Skeleton", "skeleton"},
+ {mtSlime, "slime", "Slime", "slime"},
+ {mtSnowGolem, "snowgolem", "SnowMan", "snow_golem"},
+ {mtSpider, "spider", "Spider", "spider"},
+ {mtSquid, "squid", "Squid", "squid"},
+ {mtVillager, "villager", "Villager", "villager"},
+ {mtWitch, "witch", "Witch", "witch"},
+ {mtWither, "wither", "WitherBoss", "wither"},
+ {mtWitherSkeleton, "witherskeleton", "WitherSkeleton", "wither_skeleton"},
+ {mtWolf, "wolf", "Wolf", "wolf"},
+ {mtZombie, "zombie", "Zombie", "zombie"},
+ {mtZombiePigman, "zombiepigman", "PigZombie", "zombie_pigman"},
} ;
@@ -658,6 +659,7 @@ void cMonster::KilledBy(TakeDamageInfo & a_TDI)
case mtSkeleton:
case mtSpider:
case mtWitch:
+ case mtWitherSkeleton:
case mtZombie:
case mtZombiePigman:
case mtSlime:
@@ -1044,37 +1046,38 @@ cMonster::eFamily cMonster::FamilyFromType(eMonsterType a_Type)
switch (a_Type)
{
- case mtBat: return mfAmbient;
- case mtBlaze: return mfHostile;
- case mtCaveSpider: return mfHostile;
- case mtChicken: return mfPassive;
- case mtCow: return mfPassive;
- case mtCreeper: return mfHostile;
- case mtEnderDragon: return mfNoSpawn;
- case mtEnderman: return mfHostile;
- case mtGhast: return mfHostile;
- case mtGiant: return mfNoSpawn;
- case mtGuardian: return mfWater; // Just because they have special spawning conditions. If Watertemples have been added, this needs to be edited!
- case mtHorse: return mfPassive;
- case mtIronGolem: return mfPassive;
- case mtMagmaCube: return mfHostile;
- case mtMooshroom: return mfHostile;
- case mtOcelot: return mfPassive;
- case mtPig: return mfPassive;
- case mtRabbit: return mfPassive;
- case mtSheep: return mfPassive;
- case mtSilverfish: return mfHostile;
- case mtSkeleton: return mfHostile;
- case mtSlime: return mfHostile;
- case mtSnowGolem: return mfNoSpawn;
- case mtSpider: return mfHostile;
- case mtSquid: return mfWater;
- case mtVillager: return mfPassive;
- case mtWitch: return mfHostile;
- case mtWither: return mfNoSpawn;
- case mtWolf: return mfHostile;
- case mtZombie: return mfHostile;
- case mtZombiePigman: return mfHostile;
+ case mtBat: return mfAmbient;
+ case mtBlaze: return mfHostile;
+ case mtCaveSpider: return mfHostile;
+ case mtChicken: return mfPassive;
+ case mtCow: return mfPassive;
+ case mtCreeper: return mfHostile;
+ case mtEnderDragon: return mfNoSpawn;
+ case mtEnderman: return mfHostile;
+ case mtGhast: return mfHostile;
+ case mtGiant: return mfNoSpawn;
+ case mtGuardian: return mfWater; // Just because they have special spawning conditions. If Watertemples have been added, this needs to be edited!
+ case mtHorse: return mfPassive;
+ case mtIronGolem: return mfPassive;
+ case mtMagmaCube: return mfHostile;
+ case mtMooshroom: return mfHostile;
+ case mtOcelot: return mfPassive;
+ case mtPig: return mfPassive;
+ case mtRabbit: return mfPassive;
+ case mtSheep: return mfPassive;
+ case mtSilverfish: return mfHostile;
+ case mtSkeleton: return mfHostile;
+ case mtSlime: return mfHostile;
+ case mtSnowGolem: return mfNoSpawn;
+ case mtSpider: return mfHostile;
+ case mtSquid: return mfWater;
+ case mtVillager: return mfPassive;
+ case mtWitch: return mfHostile;
+ case mtWither: return mfNoSpawn;
+ case mtWitherSkeleton: return mfHostile;
+ case mtWolf: return mfHostile;
+ case mtZombie: return mfHostile;
+ case mtZombiePigman: return mfHostile;
default:
{
@@ -1173,11 +1176,6 @@ std::unique_ptr<cMonster> cMonster::NewMonsterFromType(eMonsterType a_MobType)
{
return cpp14::make_unique<cSlime>(1 << Random.RandInt(2)); // Size 1, 2 or 4
}
- case mtSkeleton:
- {
- // TODO: Actual detection of spawning in Nether
- return cpp14::make_unique<cSkeleton>(false);
- }
case mtVillager:
{
int VillagerType = Random.RandInt(6);
@@ -1206,32 +1204,34 @@ std::unique_ptr<cMonster> cMonster::NewMonsterFromType(eMonsterType a_MobType)
return cpp14::make_unique<cHorse>(HorseType, HorseColor, HorseStyle, HorseTameTimes);
}
- case mtBat: return cpp14::make_unique<cBat>();
- case mtBlaze: return cpp14::make_unique<cBlaze>();
- case mtCaveSpider: return cpp14::make_unique<cCaveSpider>();
- case mtChicken: return cpp14::make_unique<cChicken>();
- case mtCow: return cpp14::make_unique<cCow>();
- case mtCreeper: return cpp14::make_unique < cCreeper>();
- case mtEnderDragon: return cpp14::make_unique<cEnderDragon>();
- case mtEnderman: return cpp14::make_unique<cEnderman>();
- case mtGhast: return cpp14::make_unique<cGhast>();
- case mtGiant: return cpp14::make_unique<cGiant>();
- case mtGuardian: return cpp14::make_unique<cGuardian>();
- case mtIronGolem: return cpp14::make_unique<cIronGolem>();
- case mtMooshroom: return cpp14::make_unique<cMooshroom>();
- case mtOcelot: return cpp14::make_unique<cOcelot>();
- case mtPig: return cpp14::make_unique<cPig>();
- case mtRabbit: return cpp14::make_unique<cRabbit>();
- case mtSheep: return cpp14::make_unique<cSheep>();
- case mtSilverfish: return cpp14::make_unique<cSilverfish>();
- case mtSnowGolem: return cpp14::make_unique<cSnowGolem>();
- case mtSpider: return cpp14::make_unique<cSpider>();
- case mtSquid: return cpp14::make_unique<cSquid>();
- case mtWitch: return cpp14::make_unique<cWitch>();
- case mtWither: return cpp14::make_unique<cWither>();
- case mtWolf: return cpp14::make_unique<cWolf>();
- case mtZombie: return cpp14::make_unique<cZombie>(false); // TODO: Infected zombie parameter
- case mtZombiePigman: return cpp14::make_unique<cZombiePigman>();
+ case mtBat: return cpp14::make_unique<cBat>();
+ case mtBlaze: return cpp14::make_unique<cBlaze>();
+ case mtCaveSpider: return cpp14::make_unique<cCaveSpider>();
+ case mtChicken: return cpp14::make_unique<cChicken>();
+ case mtCow: return cpp14::make_unique<cCow>();
+ case mtCreeper: return cpp14::make_unique<cCreeper>();
+ case mtEnderDragon: return cpp14::make_unique<cEnderDragon>();
+ case mtEnderman: return cpp14::make_unique<cEnderman>();
+ case mtGhast: return cpp14::make_unique<cGhast>();
+ case mtGiant: return cpp14::make_unique<cGiant>();
+ case mtGuardian: return cpp14::make_unique<cGuardian>();
+ case mtIronGolem: return cpp14::make_unique<cIronGolem>();
+ case mtMooshroom: return cpp14::make_unique<cMooshroom>();
+ case mtOcelot: return cpp14::make_unique<cOcelot>();
+ case mtPig: return cpp14::make_unique<cPig>();
+ case mtRabbit: return cpp14::make_unique<cRabbit>();
+ case mtSheep: return cpp14::make_unique<cSheep>();
+ case mtSilverfish: return cpp14::make_unique<cSilverfish>();
+ case mtSkeleton: return cpp14::make_unique<cSkeleton>();
+ case mtSnowGolem: return cpp14::make_unique<cSnowGolem>();
+ case mtSpider: return cpp14::make_unique<cSpider>();
+ case mtSquid: return cpp14::make_unique<cSquid>();
+ case mtWitch: return cpp14::make_unique<cWitch>();
+ case mtWither: return cpp14::make_unique<cWither>();
+ case mtWitherSkeleton: return cpp14::make_unique<cWitherSkeleton>();
+ case mtWolf: return cpp14::make_unique<cWolf>();
+ case mtZombie: return cpp14::make_unique<cZombie>(false); // TODO: Infected zombie parameter
+ case mtZombiePigman: return cpp14::make_unique<cZombiePigman>();
default:
{
ASSERT(!"Unhandled mob type whilst trying to spawn mob!");
diff --git a/src/Mobs/MonsterTypes.h b/src/Mobs/MonsterTypes.h
index 6aaa61dc6..7a864fda4 100644
--- a/src/Mobs/MonsterTypes.h
+++ b/src/Mobs/MonsterTypes.h
@@ -39,6 +39,7 @@ enum eMonsterType
mtVillager,
mtWitch,
mtWither,
+ mtWitherSkeleton,
mtWolf,
mtZombie,
mtZombiePigman,
diff --git a/src/Mobs/Skeleton.cpp b/src/Mobs/Skeleton.cpp
index e8a345d7f..e58bb9384 100644
--- a/src/Mobs/Skeleton.cpp
+++ b/src/Mobs/Skeleton.cpp
@@ -9,9 +9,8 @@
-cSkeleton::cSkeleton(bool IsWither) :
- super("Skeleton", mtSkeleton, "entity.skeleton.hurt", "entity.skeleton.death", "entity.skeleton.ambient", 0.6, 1.8),
- m_bIsWither(IsWither)
+cSkeleton::cSkeleton(void) :
+ super("Skeleton", mtSkeleton, "entity.skeleton.hurt", "entity.skeleton.death", "entity.skeleton.ambient", 0.6, 1.8)
{
}
@@ -26,18 +25,8 @@ void cSkeleton::GetDrops(cItems & a_Drops, cEntity * a_Killer)
{
LootingLevel = a_Killer->GetEquippedWeapon().m_Enchantments.GetLevel(cEnchantments::enchLooting);
}
- if (IsWither())
- {
- AddRandomUncommonDropItem(a_Drops, 33.0f, E_ITEM_COAL);
- cItems RareDrops;
- RareDrops.Add(cItem(E_ITEM_HEAD, 1, 1));
- AddRandomRareDropItem(a_Drops, RareDrops, LootingLevel);
- }
- else
- {
- AddRandomDropItem(a_Drops, 0, 2 + LootingLevel, E_ITEM_ARROW);
+ AddRandomDropItem(a_Drops, 0, 2 + LootingLevel, E_ITEM_ARROW);
- }
AddRandomDropItem(a_Drops, 0, 2 + LootingLevel, E_ITEM_BONE);
AddRandomArmorDropItem(a_Drops, LootingLevel);
AddRandomWeaponDropItem(a_Drops, LootingLevel);
diff --git a/src/Mobs/Skeleton.h b/src/Mobs/Skeleton.h
index 0316fb9b5..cb7dec5ad 100644
--- a/src/Mobs/Skeleton.h
+++ b/src/Mobs/Skeleton.h
@@ -13,7 +13,7 @@ class cSkeleton :
typedef cAggressiveMonster super;
public:
- cSkeleton(bool IsWither);
+ cSkeleton(void);
CLASS_PROTODEF(cSkeleton)
@@ -23,12 +23,6 @@ public:
virtual bool IsUndead(void) override { return true; }
- bool IsWither(void) const { return m_bIsWither; }
-
-private:
-
- bool m_bIsWither;
-
} ;
diff --git a/src/Mobs/WitherSkeleton.cpp b/src/Mobs/WitherSkeleton.cpp
new file mode 100644
index 000000000..7dd8d5017
--- /dev/null
+++ b/src/Mobs/WitherSkeleton.cpp
@@ -0,0 +1,62 @@
+
+#include "Globals.h" // NOTE: MSVC stupidness requires this to be the same across all modules
+
+#include "WitherSkeleton.h"
+#include "../World.h"
+#include "../ClientHandle.h"
+
+
+
+
+cWitherSkeleton::cWitherSkeleton(void) :
+ super("WitherSkeleton", mtWitherSkeleton, "entity.wither_skeleton.hurt", "entity.wither_skeleton.death", "entity.wither_skeleton.ambient", 0.7, 2.4)
+{
+}
+
+
+
+
+
+bool cWitherSkeleton::Attack(std::chrono::milliseconds a_Dt)
+{
+ if (GetTarget() == nullptr)
+ {
+ return false;
+ }
+
+ GetTarget()->AddEntityEffect(cEntityEffect::effWither, 200, 0);
+ return super::Attack(a_Dt);
+}
+
+
+
+
+
+void cWitherSkeleton::GetDrops(cItems & a_Drops, cEntity * a_Killer)
+{
+ unsigned int LootingLevel = 0;
+ if (a_Killer != nullptr)
+ {
+ LootingLevel = a_Killer->GetEquippedWeapon().m_Enchantments.GetLevel(cEnchantments::enchLooting);
+ }
+ AddRandomUncommonDropItem(a_Drops, 33.0f, E_ITEM_COAL);
+ AddRandomUncommonDropItem(a_Drops, 8.5f, E_ITEM_STONE_SWORD, GetRandomProvider().RandInt<short>(50));
+
+ cItems RareDrops;
+ RareDrops.Add(cItem(E_ITEM_HEAD, 1, 1));
+ AddRandomRareDropItem(a_Drops, RareDrops, LootingLevel);
+
+ AddRandomDropItem(a_Drops, 0, 2 + LootingLevel, E_ITEM_BONE);
+ AddRandomArmorDropItem(a_Drops, LootingLevel);
+ AddRandomWeaponDropItem(a_Drops, LootingLevel);
+}
+
+
+
+
+
+void cWitherSkeleton::SpawnOn(cClientHandle & a_ClientHandle)
+{
+ super::SpawnOn(a_ClientHandle);
+ a_ClientHandle.SendEntityEquipment(*this, 0, cItem(E_ITEM_STONE_SWORD));
+}
diff --git a/src/Mobs/WitherSkeleton.h b/src/Mobs/WitherSkeleton.h
new file mode 100644
index 000000000..c77d06822
--- /dev/null
+++ b/src/Mobs/WitherSkeleton.h
@@ -0,0 +1,28 @@
+
+#pragma once
+
+#include "AggressiveMonster.h"
+
+
+
+
+
+class cWitherSkeleton :
+ public cAggressiveMonster
+{
+ typedef cAggressiveMonster super;
+
+public:
+ cWitherSkeleton(void);
+
+ CLASS_PROTODEF(cWitherSkeleton)
+
+ virtual bool Attack(std::chrono::milliseconds a_Dt) override;
+ virtual void GetDrops(cItems & a_Drops, cEntity * a_Killer = nullptr) override;
+ virtual void SpawnOn(cClientHandle & a_ClientHandle) override;
+
+} ;
+
+
+
+
diff --git a/src/Protocol/Protocol_1_10.cpp b/src/Protocol/Protocol_1_10.cpp
index 38abdb53b..47d27c461 100644
--- a/src/Protocol/Protocol_1_10.cpp
+++ b/src/Protocol/Protocol_1_10.cpp
@@ -889,15 +889,6 @@ void cProtocol_1_10_0::WriteMobMetadata(cPacketizer & a_Pkt, const cMonster & a_
break;
} // case mtSheep
- case mtSkeleton:
- {
- auto & Skeleton = static_cast<const cSkeleton &>(a_Mob);
- a_Pkt.WriteBEUInt8(SKELETON_TYPE);
- a_Pkt.WriteBEUInt8(METADATA_TYPE_VARINT);
- a_Pkt.WriteVarInt32(Skeleton.IsWither() ? 1 : 0);
- break;
- } // case mtSkeleton
-
case mtSlime:
{
auto & Slime = static_cast<const cSlime &>(a_Mob);
@@ -940,6 +931,14 @@ void cProtocol_1_10_0::WriteMobMetadata(cPacketizer & a_Pkt, const cMonster & a_
break;
} // case mtWither
+ case mtWitherSkeleton:
+ {
+ a_Pkt.WriteBEUInt8(SKELETON_TYPE);
+ a_Pkt.WriteBEUInt8(METADATA_TYPE_VARINT);
+ a_Pkt.WriteVarInt32(1); // Is wither skeleton
+ break;
+ } // case mtWitherSkeleton
+
case mtWolf:
{
auto & Wolf = static_cast<const cWolf &>(a_Mob);
diff --git a/src/Protocol/Protocol_1_11.cpp b/src/Protocol/Protocol_1_11.cpp
index 1346d64cf..8a846b540 100644
--- a/src/Protocol/Protocol_1_11.cpp
+++ b/src/Protocol/Protocol_1_11.cpp
@@ -573,6 +573,7 @@ UInt32 cProtocol_1_11_0::GetProtocolMobType(eMonsterType a_MobType)
case mtVillager: return 120;
case mtWitch: return 66;
case mtWither: return 64;
+ case mtWitherSkeleton: return 5;
case mtWolf: return 95;
case mtZombie: return 54;
case mtZombiePigman: return 57;
@@ -1094,17 +1095,6 @@ void cProtocol_1_11_0::WriteMobMetadata(cPacketizer & a_Pkt, const cMonster & a_
break;
} // case mtSheep
- case mtSkeleton:
- {
- // XXX Skeletons are separate entities; all skeletons are currently treated as regular ones
-
- // auto & Skeleton = static_cast<const cSkeleton &>(a_Mob);
- // a_Pkt.WriteBEUInt8(SKELETON_TYPE);
- // a_Pkt.WriteBEUInt8(METADATA_TYPE_VARINT);
- // a_Pkt.WriteVarInt32(Skeleton.IsWither() ? 1 : 0);
- break;
- } // case mtSkeleton
-
case mtSlime:
{
auto & Slime = static_cast<const cSlime &>(a_Mob);
diff --git a/src/Protocol/Protocol_1_12.cpp b/src/Protocol/Protocol_1_12.cpp
index b67a244d6..ee2d7064c 100644
--- a/src/Protocol/Protocol_1_12.cpp
+++ b/src/Protocol/Protocol_1_12.cpp
@@ -815,17 +815,6 @@ void cProtocol_1_12::WriteMobMetadata(cPacketizer & a_Pkt, const cMonster & a_Mo
break;
} // case mtSheep
- case mtSkeleton:
- {
- // XXX Skeletons are separate entities; all skeletons are currently treated as regular ones
-
- // auto & Skeleton = static_cast<const cSkeleton &>(a_Mob);
- // a_Pkt.WriteBEUInt8(SKELETON_TYPE);
- // a_Pkt.WriteBEUInt8(METADATA_TYPE_VARINT);
- // a_Pkt.WriteVarInt32(Skeleton.IsWither() ? 1 : 0);
- break;
- } // case mtSkeleton
-
case mtSlime:
{
auto & Slime = static_cast<const cSlime &>(a_Mob);
@@ -954,7 +943,9 @@ void cProtocol_1_12::WriteMobMetadata(cPacketizer & a_Pkt, const cMonster & a_Mo
case mtGiant:
case mtSilverfish:
+ case mtSkeleton:
case mtSquid:
+ case mtWitherSkeleton:
{
// Mobs with no extra fields
break;
diff --git a/src/Protocol/Protocol_1_13.cpp b/src/Protocol/Protocol_1_13.cpp
index 5aa23e763..70375795f 100644
--- a/src/Protocol/Protocol_1_13.cpp
+++ b/src/Protocol/Protocol_1_13.cpp
@@ -430,6 +430,7 @@ UInt32 cProtocol_1_13::GetProtocolMobType(eMonsterType a_MobType)
case mtVillager: return 79;
case mtWitch: return 82;
case mtWither: return 83;
+ case mtWitherSkeleton: return 84;
case mtWolf: return 86;
case mtZombie: return 87;
case mtZombiePigman: return 53;
diff --git a/src/Protocol/Protocol_1_8.cpp b/src/Protocol/Protocol_1_8.cpp
index 9509fe51e..668ca7542 100644
--- a/src/Protocol/Protocol_1_8.cpp
+++ b/src/Protocol/Protocol_1_8.cpp
@@ -1862,6 +1862,7 @@ UInt32 cProtocol_1_8_0::GetProtocolMobType(eMonsterType a_MobType)
case mtVillager: return 120;
case mtWitch: return 66;
case mtWither: return 64;
+ case mtWitherSkeleton: return 51;
case mtWolf: return 95;
case mtZombie: return 54;
case mtZombiePigman: return 57;
@@ -3714,14 +3715,6 @@ void cProtocol_1_8_0::WriteMobMetadata(cPacketizer & a_Pkt, const cMonster & a_M
break;
} // case mtRabbit
- case mtSkeleton:
- {
- auto & Skeleton = static_cast<const cSkeleton &>(a_Mob);
- a_Pkt.WriteBEUInt8(0x0d);
- a_Pkt.WriteBEUInt8(Skeleton.IsWither() ? 1 : 0);
- break;
- } // case mtSkeleton
-
case mtSlime:
{
auto & Slime = static_cast<const cSlime &>(a_Mob);
@@ -3758,6 +3751,13 @@ void cProtocol_1_8_0::WriteMobMetadata(cPacketizer & a_Pkt, const cMonster & a_M
break;
} // case mtWither
+ case mtWitherSkeleton:
+ {
+ a_Pkt.WriteBEUInt8(0x0d);
+ a_Pkt.WriteBEUInt8(1); // Is wither skeleton
+ break;
+ } // case mtWitherSkeleton
+
case mtWolf:
{
auto & Wolf = static_cast<const cWolf &>(a_Mob);
diff --git a/src/Protocol/Protocol_1_9.cpp b/src/Protocol/Protocol_1_9.cpp
index dbcbce18c..b6fa567fd 100644
--- a/src/Protocol/Protocol_1_9.cpp
+++ b/src/Protocol/Protocol_1_9.cpp
@@ -1918,6 +1918,7 @@ UInt32 cProtocol_1_9_0::GetProtocolMobType(eMonsterType a_MobType)
case mtVillager: return 120;
case mtWitch: return 66;
case mtWither: return 64;
+ case mtWitherSkeleton: return 51;
case mtWolf: return 95;
case mtZombie: return 54;
case mtZombiePigman: return 57;
@@ -4201,15 +4202,6 @@ void cProtocol_1_9_0::WriteMobMetadata(cPacketizer & a_Pkt, const cMonster & a_M
break;
} // case mtSheep
- case mtSkeleton:
- {
- auto & Skeleton = static_cast<const cSkeleton &>(a_Mob);
- a_Pkt.WriteBEUInt8(11); // Index 11: Type
- a_Pkt.WriteBEUInt8(METADATA_TYPE_VARINT);
- a_Pkt.WriteVarInt32(Skeleton.IsWither() ? 1 : 0);
- break;
- } // case mtSkeleton
-
case mtSlime:
{
auto & Slime = static_cast<const cSlime &>(a_Mob);
@@ -4252,6 +4244,14 @@ void cProtocol_1_9_0::WriteMobMetadata(cPacketizer & a_Pkt, const cMonster & a_M
break;
} // case mtWither
+ case mtWitherSkeleton:
+ {
+ a_Pkt.WriteBEUInt8(11); // Index 11: Type
+ a_Pkt.WriteBEUInt8(METADATA_TYPE_VARINT);
+ a_Pkt.WriteVarInt32(1); // Is wither skeleton
+ break;
+ } // case mtWitherSkeleton
+
case mtWolf:
{
auto & Wolf = static_cast<const cWolf &>(a_Mob);
diff --git a/src/World.cpp b/src/World.cpp
index 464d84be5..10cfc2047 100644
--- a/src/World.cpp
+++ b/src/World.cpp
@@ -895,7 +895,7 @@ void cWorld::InitializeAndLoadMobSpawningValues(cIniFile & a_IniFile)
switch (m_Dimension)
{
case dimOverworld: DefaultMonsters = "bat, cavespider, chicken, cow, creeper, guardian, horse, mooshroom, ocelot, pig, rabbit, sheep, silverfish, skeleton, slime, spider, squid, wolf, zombie"; break; // TODO Re-add Enderman when bugs are fixed
- case dimNether: DefaultMonsters = "blaze, ghast, magmacube, skeleton, zombiepigman"; break;
+ case dimNether: DefaultMonsters = "blaze, ghast, magmacube, witherskeleton, zombiepigman"; break;
case dimEnd: DefaultMonsters = ""; break; // TODO Re-add Enderman when bugs are fixed
case dimNotSet: ASSERT(!"Dimension not set"); break;
}
diff --git a/src/WorldStorage/NBTChunkSerializer.cpp b/src/WorldStorage/NBTChunkSerializer.cpp
index 014ee2c27..3e8994786 100644
--- a/src/WorldStorage/NBTChunkSerializer.cpp
+++ b/src/WorldStorage/NBTChunkSerializer.cpp
@@ -710,37 +710,38 @@ public:
const char * EntityClass = nullptr;
switch (a_Monster->GetMobType())
{
- case mtBat: EntityClass = "Bat"; break;
- case mtBlaze: EntityClass = "Blaze"; break;
- case mtCaveSpider: EntityClass = "CaveSpider"; break;
- case mtChicken: EntityClass = "Chicken"; break;
- case mtCow: EntityClass = "Cow"; break;
- case mtCreeper: EntityClass = "Creeper"; break;
- case mtEnderDragon: EntityClass = "EnderDragon"; break;
- case mtEnderman: EntityClass = "Enderman"; break;
- case mtGhast: EntityClass = "Ghast"; break;
- case mtGiant: EntityClass = "Giant"; break;
- case mtGuardian: EntityClass = "Guardian"; break;
- case mtHorse: EntityClass = "Horse"; break;
- case mtIronGolem: EntityClass = "VillagerGolem"; break;
- case mtMagmaCube: EntityClass = "LavaSlime"; break;
- case mtMooshroom: EntityClass = "MushroomCow"; break;
- case mtOcelot: EntityClass = "Ozelot"; break;
- case mtPig: EntityClass = "Pig"; break;
- case mtRabbit: EntityClass = "Rabbit"; break;
- case mtSheep: EntityClass = "Sheep"; break;
- case mtSilverfish: EntityClass = "Silverfish"; break;
- case mtSkeleton: EntityClass = "Skeleton"; break;
- case mtSlime: EntityClass = "Slime"; break;
- case mtSnowGolem: EntityClass = "SnowMan"; break;
- case mtSpider: EntityClass = "Spider"; break;
- case mtSquid: EntityClass = "Squid"; break;
- case mtVillager: EntityClass = "Villager"; break;
- case mtWitch: EntityClass = "Witch"; break;
- case mtWither: EntityClass = "WitherBoss"; break;
- case mtWolf: EntityClass = "Wolf"; break;
- case mtZombie: EntityClass = "Zombie"; break;
- case mtZombiePigman: EntityClass = "PigZombie"; break;
+ case mtBat: EntityClass = "Bat"; break;
+ case mtBlaze: EntityClass = "Blaze"; break;
+ case mtCaveSpider: EntityClass = "CaveSpider"; break;
+ case mtChicken: EntityClass = "Chicken"; break;
+ case mtCow: EntityClass = "Cow"; break;
+ case mtCreeper: EntityClass = "Creeper"; break;
+ case mtEnderDragon: EntityClass = "EnderDragon"; break;
+ case mtEnderman: EntityClass = "Enderman"; break;
+ case mtGhast: EntityClass = "Ghast"; break;
+ case mtGiant: EntityClass = "Giant"; break;
+ case mtGuardian: EntityClass = "Guardian"; break;
+ case mtHorse: EntityClass = "Horse"; break;
+ case mtIronGolem: EntityClass = "VillagerGolem"; break;
+ case mtMagmaCube: EntityClass = "LavaSlime"; break;
+ case mtMooshroom: EntityClass = "MushroomCow"; break;
+ case mtOcelot: EntityClass = "Ozelot"; break;
+ case mtPig: EntityClass = "Pig"; break;
+ case mtRabbit: EntityClass = "Rabbit"; break;
+ case mtSheep: EntityClass = "Sheep"; break;
+ case mtSilverfish: EntityClass = "Silverfish"; break;
+ case mtSkeleton: EntityClass = "Skeleton"; break;
+ case mtSlime: EntityClass = "Slime"; break;
+ case mtSnowGolem: EntityClass = "SnowMan"; break;
+ case mtSpider: EntityClass = "Spider"; break;
+ case mtSquid: EntityClass = "Squid"; break;
+ case mtVillager: EntityClass = "Villager"; break;
+ case mtWitch: EntityClass = "Witch"; break;
+ case mtWither: EntityClass = "WitherBoss"; break;
+ case mtWitherSkeleton: EntityClass = "WitherSkeleton"; break;
+ case mtWolf: EntityClass = "Wolf"; break;
+ case mtZombie: EntityClass = "Zombie"; break;
+ case mtZombiePigman: EntityClass = "PigZombie"; break;
default:
{
ASSERT(!"Unhandled monster type");
@@ -869,11 +870,6 @@ public:
mWriter.AddInt("Size", static_cast<const cSlime *>(a_Monster)->GetSize());
break;
}
- case mtSkeleton:
- {
- mWriter.AddByte("SkeletonType", (static_cast<const cSkeleton *>(a_Monster)->IsWither() ? 1 : 0));
- break;
- }
case mtVillager:
{
const cVillager *Villager = static_cast<const cVillager *>(a_Monster);
@@ -927,10 +923,12 @@ public:
case mtIronGolem:
case mtMooshroom:
case mtSilverfish:
+ case mtSkeleton:
case mtSnowGolem:
case mtSpider:
case mtSquid:
case mtWitch:
+ case mtWitherSkeleton:
{
// Other mobs have no special tags.
break;
diff --git a/src/WorldStorage/WSSAnvil.cpp b/src/WorldStorage/WSSAnvil.cpp
index 65facd817..31934e181 100755
--- a/src/WorldStorage/WSSAnvil.cpp
+++ b/src/WorldStorage/WSSAnvil.cpp
@@ -1560,6 +1560,8 @@ void cWSSAnvil::LoadEntityFromNBT(cEntityList & a_Entities, const cParsedNBT & a
{ "minecraft:witch", &cWSSAnvil::LoadWitchFromNBT },
{ "WitherBoss", &cWSSAnvil::LoadWitherFromNBT },
{ "minecraft:wither", &cWSSAnvil::LoadWitherFromNBT },
+ { "WitherSkeleton", &cWSSAnvil::LoadWitherSkeletonFromNBT },
+ { "minecraft:wither_skeleton", &cWSSAnvil::LoadWitherSkeletonFromNBT },
{ "Wolf", &cWSSAnvil::LoadWolfFromNBT },
{ "minecraft:wolf", &cWSSAnvil::LoadWolfFromNBT },
{ "Zombie", &cWSSAnvil::LoadZombieFromNBT },
@@ -2660,15 +2662,20 @@ void cWSSAnvil::LoadSilverfishFromNBT(cEntityList & a_Entities, const cParsedNBT
void cWSSAnvil::LoadSkeletonFromNBT(cEntityList & a_Entities, const cParsedNBT & a_NBT, int a_TagIdx)
{
+ // Wither skeleton is a separate mob in Minecraft 1.11+, but we need this to
+ // load them from older worlds where wither skeletons were only a skeleton with a flag
int TypeIdx = a_NBT.FindChildByName(a_TagIdx, "SkeletonType");
- if (TypeIdx < 0)
+
+ std::unique_ptr<cMonster> Monster;
+ if ((TypeIdx > 0) && (a_NBT.GetByte(TypeIdx) == 1))
{
- return;
+ Monster = cpp14::make_unique<cWitherSkeleton>();
+ }
+ else
+ {
+ Monster = cpp14::make_unique<cSkeleton>();
}
- bool Type = ((a_NBT.GetByte(TypeIdx) == 1) ? true : false);
-
- std::unique_ptr<cSkeleton> Monster = cpp14::make_unique<cSkeleton>(Type);
if (!LoadEntityBaseFromNBT(*Monster.get(), a_NBT, a_TagIdx))
{
return;
@@ -2863,6 +2870,26 @@ void cWSSAnvil::LoadWitherFromNBT(cEntityList & a_Entities, const cParsedNBT & a
+void cWSSAnvil::LoadWitherSkeletonFromNBT(cEntityList & a_Entities, const cParsedNBT & a_NBT, int a_TagIdx)
+{
+ auto Monster = cpp14::make_unique<cWitherSkeleton>();
+ if (!LoadEntityBaseFromNBT(*Monster.get(), a_NBT, a_TagIdx))
+ {
+ return;
+ }
+
+ if (!LoadMonsterBaseFromNBT(*Monster.get(), a_NBT, a_TagIdx))
+ {
+ return;
+ }
+
+ a_Entities.emplace_back(std::move(Monster));
+}
+
+
+
+
+
void cWSSAnvil::LoadWolfFromNBT(cEntityList & a_Entities, const cParsedNBT & a_NBT, int a_TagIdx)
{
std::unique_ptr<cWolf> Monster = cpp14::make_unique<cWolf>();
diff --git a/src/WorldStorage/WSSAnvil.h b/src/WorldStorage/WSSAnvil.h
index 949ff61ff..e6b3e5ee9 100755
--- a/src/WorldStorage/WSSAnvil.h
+++ b/src/WorldStorage/WSSAnvil.h
@@ -228,6 +228,7 @@ protected:
void LoadVillagerFromNBT (cEntityList & a_Entities, const cParsedNBT & a_NBT, int a_TagIdx);
void LoadWitchFromNBT (cEntityList & a_Entities, const cParsedNBT & a_NBT, int a_TagIdx);
void LoadWitherFromNBT (cEntityList & a_Entities, const cParsedNBT & a_NBT, int a_TagIdx);
+ void LoadWitherSkeletonFromNBT (cEntityList & a_Entities, const cParsedNBT & a_NBT, int a_TagIdx);
void LoadWolfFromNBT (cEntityList & a_Entities, const cParsedNBT & a_NBT, int a_TagIdx);
void LoadZombieFromNBT (cEntityList & a_Entities, const cParsedNBT & a_NBT, int a_TagIdx);
void LoadPigZombieFromNBT (cEntityList & a_Entities, const cParsedNBT & a_NBT, int a_TagIdx);