summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/BlockType.h1
-rw-r--r--src/Entities/Entity.cpp3
-rw-r--r--src/Items/ItemSpawnEgg.h7
-rw-r--r--src/Mobs/CMakeLists.txt6
-rw-r--r--src/Mobs/IncludeAllMonsters.h1
-rw-r--r--src/Mobs/Monster.cpp20
-rw-r--r--src/Mobs/MonsterTypes.h36
-rw-r--r--src/Mobs/Villager.cpp32
-rw-r--r--src/Mobs/Villager.h4
-rw-r--r--src/Mobs/Zombie.cpp6
-rw-r--r--src/Mobs/Zombie.h10
-rw-r--r--src/Mobs/ZombieVillager.cpp87
-rw-r--r--src/Mobs/ZombieVillager.h33
-rw-r--r--src/Protocol/Protocol_1_10.cpp21
-rw-r--r--src/Protocol/Protocol_1_11.cpp26
-rw-r--r--src/Protocol/Protocol_1_12.cpp20
-rw-r--r--src/Protocol/Protocol_1_8.cpp16
-rw-r--r--src/Protocol/Protocol_1_9.cpp21
-rw-r--r--src/WorldStorage/NBTChunkSerializer.cpp19
-rwxr-xr-xsrc/WorldStorage/WSSAnvil.cpp51
-rwxr-xr-xsrc/WorldStorage/WSSAnvil.h1
21 files changed, 358 insertions, 63 deletions
diff --git a/src/BlockType.h b/src/BlockType.h
index 8a70226db..9f8c8fb55 100644
--- a/src/BlockType.h
+++ b/src/BlockType.h
@@ -1079,6 +1079,7 @@ enum ENUM_ITEM_META : short
E_META_SPAWN_EGG_PRIMED_TNT = 20,
E_META_SPAWN_EGG_FALLING_BLOCK = 21,
E_META_SPAWN_EGG_FIREWORK = 22,
+ E_META_SPAWN_EGG_ZOMBIE_VILLAGER = 27,
E_META_SPAWN_EGG_BOAT = 41,
E_META_SPAWN_EGG_MINECART = 42,
E_META_SPAWN_EGG_MINECART_CHEST = 43,
diff --git a/src/Entities/Entity.cpp b/src/Entities/Entity.cpp
index 453bd03d2..e7682e6da 100644
--- a/src/Entities/Entity.cpp
+++ b/src/Entities/Entity.cpp
@@ -456,9 +456,10 @@ bool cEntity::DoTakeDamage(TakeDamageInfo & a_TDI)
switch (Monster->GetMobType())
{
case mtSkeleton:
- case mtZombie:
case mtWither:
+ case mtZombie:
case mtZombiePigman:
+ case mtZombieVillager:
{
a_TDI.FinalDamage += 2.5f * SmiteLevel;
break;
diff --git a/src/Items/ItemSpawnEgg.h b/src/Items/ItemSpawnEgg.h
index 6d4219236..d57b93b2c 100644
--- a/src/Items/ItemSpawnEgg.h
+++ b/src/Items/ItemSpawnEgg.h
@@ -87,11 +87,8 @@ public:
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_ZOMBIE_VILLAGER: return mtZombieVillager;
+ default: return mtInvalidType;
}
- return mtInvalidType;
}
} ;
-
-
-
-
diff --git a/src/Mobs/CMakeLists.txt b/src/Mobs/CMakeLists.txt
index 15456595c..579ba8938 100644
--- a/src/Mobs/CMakeLists.txt
+++ b/src/Mobs/CMakeLists.txt
@@ -36,7 +36,8 @@ SET (SRCS
WitherSkeleton.cpp
Wolf.cpp
Zombie.cpp
- ZombiePigman.cpp)
+ ZombiePigman.cpp
+ ZombieVillager.cpp)
SET (HDRS
AggressiveMonster.h
@@ -78,7 +79,8 @@ SET (HDRS
WitherSkeleton.h
Wolf.h
Zombie.h
- ZombiePigman.h)
+ ZombiePigman.h
+ ZombieVillager.h)
if(NOT MSVC)
add_library(Mobs ${SRCS} ${HDRS})
diff --git a/src/Mobs/IncludeAllMonsters.h b/src/Mobs/IncludeAllMonsters.h
index 17a9dfacd..afb79c97c 100644
--- a/src/Mobs/IncludeAllMonsters.h
+++ b/src/Mobs/IncludeAllMonsters.h
@@ -30,3 +30,4 @@
#include "Wolf.h"
#include "Zombie.h"
#include "ZombiePigman.h"
+#include "ZombieVillager.h"
diff --git a/src/Mobs/Monster.cpp b/src/Mobs/Monster.cpp
index 5e3026a57..d20afa589 100644
--- a/src/Mobs/Monster.cpp
+++ b/src/Mobs/Monster.cpp
@@ -69,6 +69,7 @@ static const struct
{mtWolf, "wolf", "Wolf", "wolf"},
{mtZombie, "zombie", "Zombie", "zombie"},
{mtZombiePigman, "zombiepigman", "PigZombie", "zombie_pigman"},
+ {mtZombieVillager, "zombievillager", "ZombieVillager", "zombie_villager"},
} ;
@@ -662,6 +663,7 @@ void cMonster::KilledBy(TakeDamageInfo & a_TDI)
case mtWitherSkeleton:
case mtZombie:
case mtZombiePigman:
+ case mtZombieVillager:
case mtSlime:
case mtMagmaCube:
{
@@ -1078,6 +1080,7 @@ cMonster::eFamily cMonster::FamilyFromType(eMonsterType a_Type)
case mtWolf: return mfPassive;
case mtZombie: return mfHostile;
case mtZombiePigman: return mfHostile;
+ case mtZombieVillager: return mfHostile;
default:
{
@@ -1176,17 +1179,7 @@ std::unique_ptr<cMonster> cMonster::NewMonsterFromType(eMonsterType a_MobType)
{
return cpp14::make_unique<cSlime>(1 << Random.RandInt(2)); // Size 1, 2 or 4
}
- case mtVillager:
- {
- int VillagerType = Random.RandInt(6);
- if (VillagerType == 6)
- {
- // Give farmers a better chance of spawning
- VillagerType = 0;
- }
-
- return cpp14::make_unique<cVillager>(static_cast<cVillager::eVillagerType>(VillagerType));
- }
+ case mtVillager: return cpp14::make_unique<cVillager>(cVillager::GetRandomProfession());
case mtHorse:
{
// Horses take a type (species), a colour, and a style (dots, stripes, etc.)
@@ -1203,7 +1196,10 @@ std::unique_ptr<cMonster> cMonster::NewMonsterFromType(eMonsterType a_MobType)
return cpp14::make_unique<cHorse>(HorseType, HorseColor, HorseStyle, HorseTameTimes);
}
-
+ case mtZombieVillager:
+ {
+ return cpp14::make_unique<cZombieVillager>(cVillager::GetRandomProfession());
+ }
case mtBat: return cpp14::make_unique<cBat>();
case mtBlaze: return cpp14::make_unique<cBlaze>();
case mtCaveSpider: return cpp14::make_unique<cCaveSpider>();
diff --git a/src/Mobs/MonsterTypes.h b/src/Mobs/MonsterTypes.h
index 7a864fda4..6d3c57852 100644
--- a/src/Mobs/MonsterTypes.h
+++ b/src/Mobs/MonsterTypes.h
@@ -11,6 +11,7 @@ enum eMonsterType
{
mtInvalidType = -1,
+<<<<<<< HEAD
mtBat,
mtBlaze,
mtCaveSpider,
@@ -43,6 +44,41 @@ enum eMonsterType
mtWolf,
mtZombie,
mtZombiePigman,
+=======
+ mtBat = E_META_SPAWN_EGG_BAT,
+ mtBlaze = E_META_SPAWN_EGG_BLAZE,
+ mtCaveSpider = E_META_SPAWN_EGG_CAVE_SPIDER,
+ mtChicken = E_META_SPAWN_EGG_CHICKEN,
+ mtCow = E_META_SPAWN_EGG_COW,
+ mtCreeper = E_META_SPAWN_EGG_CREEPER,
+ mtEnderDragon = E_META_SPAWN_EGG_ENDER_DRAGON,
+ mtEnderman = E_META_SPAWN_EGG_ENDERMAN,
+ mtGhast = E_META_SPAWN_EGG_GHAST,
+ mtGiant = E_META_SPAWN_EGG_GIANT,
+ mtGuardian = E_META_SPAWN_EGG_GUARDIAN,
+ mtHorse = E_META_SPAWN_EGG_HORSE,
+ mtIronGolem = E_META_SPAWN_EGG_IRON_GOLEM,
+ mtMagmaCube = E_META_SPAWN_EGG_MAGMA_CUBE,
+ mtMooshroom = E_META_SPAWN_EGG_MOOSHROOM,
+ mtOcelot = E_META_SPAWN_EGG_OCELOT,
+ mtPig = E_META_SPAWN_EGG_PIG,
+ mtRabbit = E_META_SPAWN_EGG_RABBIT,
+ mtSheep = E_META_SPAWN_EGG_SHEEP,
+ mtSilverfish = E_META_SPAWN_EGG_SILVERFISH,
+ mtSkeleton = E_META_SPAWN_EGG_SKELETON,
+ mtSlime = E_META_SPAWN_EGG_SLIME,
+ mtSnowGolem = E_META_SPAWN_EGG_SNOW_GOLEM,
+ mtSpider = E_META_SPAWN_EGG_SPIDER,
+ mtSquid = E_META_SPAWN_EGG_SQUID,
+ mtVillager = E_META_SPAWN_EGG_VILLAGER,
+ mtWitch = E_META_SPAWN_EGG_WITCH,
+ mtWither = E_META_SPAWN_EGG_WITHER,
+ mtWolf = E_META_SPAWN_EGG_WOLF,
+ mtZombie = E_META_SPAWN_EGG_ZOMBIE,
+ mtZombiePigman = E_META_SPAWN_EGG_ZOMBIE_PIGMAN,
+ mtZombieVillager = E_META_SPAWN_EGG_ZOMBIE_VILLAGER,
+ mtMax = 120, // This is just a hotfix for https://forum.cuberite.org/thread-1616.html. Tolua is too bad to find the highest value, so this is needed.
+>>>>>>> Add Zombie Villagers
} ;
// tolua_end
diff --git a/src/Mobs/Villager.cpp b/src/Mobs/Villager.cpp
index 9558ba536..eca8ed2b6 100644
--- a/src/Mobs/Villager.cpp
+++ b/src/Mobs/Villager.cpp
@@ -107,6 +107,26 @@ void cVillager::Tick(std::chrono::milliseconds a_Dt, cChunk & a_Chunk)
+
+void cVillager::KilledBy(TakeDamageInfo & a_TDI)
+{
+ super::KilledBy(a_TDI);
+
+ // TODO: 0% chance on Easy, 50% chance on Normal and 100% chance on Hard
+ if (GetRandomProvider().RandBool(0.5) && (a_TDI.Attacker != nullptr) && (a_TDI.Attacker->IsMob()))
+ {
+ eMonsterType MonsterType = (static_cast<cMonster *>(a_TDI.Attacker)->GetMobType());
+ if ((MonsterType == mtZombie) || (MonsterType == mtZombieVillager))
+ {
+ m_World->SpawnMob(GetPosX(), GetPosY(), GetPosZ(), mtZombieVillager, false);
+ }
+ }
+}
+
+
+
+
+
////////////////////////////////////////////////////////////////////////////////
// Farmer functions:
@@ -203,7 +223,17 @@ bool cVillager::IsBlockFarmable(BLOCKTYPE a_BlockType)
{
return true;
}
+ default: return false;
}
- return false;
}
+
+
+
+
+cVillager::eVillagerType cVillager::GetRandomProfession()
+{
+ int Profession = GetRandomProvider().RandInt(cVillager::eVillagerType::vtMax - 1);
+
+ return static_cast<cVillager::eVillagerType>(Profession);
+}
diff --git a/src/Mobs/Villager.h b/src/Mobs/Villager.h
index b9a0b7675..2d6644193 100644
--- a/src/Mobs/Villager.h
+++ b/src/Mobs/Villager.h
@@ -29,9 +29,13 @@ public:
CLASS_PROTODEF(cVillager)
+ /** Returns a random Profession. */
+ static eVillagerType GetRandomProfession();
+
// cEntity overrides
virtual bool DoTakeDamage(TakeDamageInfo & a_TDI) override;
virtual void Tick (std::chrono::milliseconds a_Dt, cChunk & a_Chunk) override;
+ virtual void KilledBy (TakeDamageInfo & a_TDI) override;
// cVillager functions
/** return true if the given blocktype are: crops, potatoes or carrots. */
diff --git a/src/Mobs/Zombie.cpp b/src/Mobs/Zombie.cpp
index 451255ed2..02c1efa86 100644
--- a/src/Mobs/Zombie.cpp
+++ b/src/Mobs/Zombie.cpp
@@ -9,10 +9,8 @@
-cZombie::cZombie(bool a_IsVillagerZombie) :
- super("Zombie", mtZombie, "entity.zombie.hurt", "entity.zombie.death", "entity.zombie.ambient", 0.6, 1.8),
- m_IsVillagerZombie(a_IsVillagerZombie),
- m_IsConverting(false)
+cZombie::cZombie() :
+ super("Zombie", mtZombie, "entity.zombie.hurt", "entity.zombie.death", "entity.zombie.ambient", 0.6, 1.8)
{
}
diff --git a/src/Mobs/Zombie.h b/src/Mobs/Zombie.h
index 47a9f1904..20f59a627 100644
--- a/src/Mobs/Zombie.h
+++ b/src/Mobs/Zombie.h
@@ -12,21 +12,13 @@ class cZombie :
typedef cAggressiveMonster super;
public:
- cZombie(bool a_IsVillagerZombie);
+ cZombie();
CLASS_PROTODEF(cZombie)
virtual void GetDrops(cItems & a_Drops, cEntity * a_Killer = nullptr) override;
virtual bool IsUndead(void) override { return true; }
- bool IsVillagerZombie(void) const { return m_IsVillagerZombie; }
- bool IsConverting (void) const { return m_IsConverting; }
-
-private:
-
- bool m_IsVillagerZombie;
- bool m_IsConverting;
-
} ;
diff --git a/src/Mobs/ZombieVillager.cpp b/src/Mobs/ZombieVillager.cpp
new file mode 100644
index 000000000..9d17e6038
--- /dev/null
+++ b/src/Mobs/ZombieVillager.cpp
@@ -0,0 +1,87 @@
+
+#include "Globals.h" // NOTE: MSVC stupidness requires this to be the same across all modules
+
+#include "ZombieVillager.h"
+#include "../World.h"
+#include "../LineBlockTracer.h"
+#include "../Entities/Player.h"
+
+
+
+
+
+cZombieVillager::cZombieVillager(cVillager::eVillagerType a_Profession) :
+ super("ZombieVillager", mtZombieVillager, "entity.zombie_villager.hurt", "entity.zombie_villager.death", "entity.ambient", 0.6, 1.8),
+ m_ConversionTime(-1),
+ m_Profession(a_Profession)
+{
+ SetBurnsInDaylight(true);
+}
+
+
+
+
+
+void cZombieVillager::GetDrops(cItems & a_Drops, cEntity * a_Killer)
+{
+ unsigned int LootingLevel = 0;
+ if (a_Killer != nullptr)
+ {
+ LootingLevel = a_Killer->GetEquippedWeapon().m_Enchantments.GetLevel(cEnchantments::enchLooting);
+ }
+ AddRandomDropItem(a_Drops, 0, 2 + LootingLevel, E_ITEM_ROTTEN_FLESH);
+ cItems RareDrops;
+ RareDrops.Add(cItem(E_ITEM_IRON));
+ RareDrops.Add(cItem(E_ITEM_CARROT));
+ RareDrops.Add(cItem(E_ITEM_POTATO));
+ AddRandomRareDropItem(a_Drops, RareDrops, LootingLevel);
+ AddRandomArmorDropItem(a_Drops, LootingLevel);
+ AddRandomWeaponDropItem(a_Drops, LootingLevel);
+}
+
+
+
+
+
+void cZombieVillager::Tick(std::chrono::milliseconds a_Dt, cChunk & a_Chunk)
+{
+ super::Tick(a_Dt, a_Chunk);
+ if (!IsTicking())
+ {
+ // The base class tick destroyed us
+ return;
+ }
+
+ LOGD("Conversion time: %d", m_ConversionTime);
+
+ if (m_ConversionTime == 0)
+ {
+ m_World->BroadcastSoundEffect("entity.zombie_villager.cure", GetPosition(), 1.0f, 1.0f);
+ Destroy();
+ m_World->SpawnMob(GetPosX(), GetPosY(), GetPosZ(), mtVillager, false);
+ }
+ else if (m_ConversionTime > 0)
+ {
+ m_ConversionTime--;
+ }
+}
+
+
+
+
+
+void cZombieVillager::OnRightClicked(cPlayer & a_Player)
+{
+ super::OnRightClicked(a_Player);
+
+ const cItem & EquippedItem = a_Player.GetEquippedItem();
+ if ((EquippedItem.m_ItemType == E_ITEM_GOLDEN_APPLE) && GetEntityEffect(cEntityEffect::effWeakness) != nullptr)
+ {
+ if (!a_Player.IsGameModeCreative())
+ {
+ a_Player.GetInventory().RemoveOneEquippedItem();
+ }
+
+ m_ConversionTime = 6000;
+ }
+}
diff --git a/src/Mobs/ZombieVillager.h b/src/Mobs/ZombieVillager.h
new file mode 100644
index 000000000..c4c4ae3d1
--- /dev/null
+++ b/src/Mobs/ZombieVillager.h
@@ -0,0 +1,33 @@
+#pragma once
+
+#include "AggressiveMonster.h"
+#include "Villager.h"
+
+
+
+
+
+class cZombieVillager :
+ public cAggressiveMonster
+{
+ typedef cAggressiveMonster super;
+
+public:
+ cZombieVillager(cVillager::eVillagerType a_Profession);
+
+ CLASS_PROTODEF(cZombieVillager)
+
+ virtual void GetDrops (cItems & a_Drops, cEntity * a_Killer = nullptr) override;
+ virtual void Tick (std::chrono::milliseconds a_Dt, cChunk & a_Chunk) override;
+ virtual void OnRightClicked (cPlayer & a_Player) override;
+ virtual bool IsUndead (void) override { return true; }
+
+ int ConversionTime (void) const { return m_ConversionTime; }
+ cVillager::eVillagerType GetProfession (void) const { return m_Profession; }
+
+private:
+
+ int m_ConversionTime;
+ cVillager::eVillagerType m_Profession;
+
+} ;
diff --git a/src/Protocol/Protocol_1_10.cpp b/src/Protocol/Protocol_1_10.cpp
index 8a23ec09d..83df39a6c 100644
--- a/src/Protocol/Protocol_1_10.cpp
+++ b/src/Protocol/Protocol_1_10.cpp
@@ -1008,11 +1008,11 @@ void cProtocol_1_10_0::WriteMobMetadata(cPacketizer & a_Pkt, const cMonster & a_
a_Pkt.WriteBEUInt8(ZOMBIE_TYPE);
a_Pkt.WriteBEUInt8(METADATA_TYPE_VARINT);
- a_Pkt.WriteVarInt32(Zombie.IsVillagerZombie() ? 1 : 0); // TODO: This actually encodes the zombie villager profession, but that isn't implemented yet.
+ a_Pkt.WriteVarInt32(0);
a_Pkt.WriteBEUInt8(ZOMBIE_CONVERTING);
a_Pkt.WriteBEUInt8(METADATA_TYPE_BOOL);
- a_Pkt.WriteBool(Zombie.IsConverting());
+ a_Pkt.WriteBool(false);
break;
} // case mtZombie
@@ -1025,6 +1025,23 @@ void cProtocol_1_10_0::WriteMobMetadata(cPacketizer & a_Pkt, const cMonster & a_
break;
} // case mtZombiePigman
+ case mtZombieVillager:
+ {
+ auto & ZombieVillager = reinterpret_cast<const cZombieVillager &>(a_Mob);
+ a_Pkt.WriteBEUInt8(ZOMBIE_IS_BABY);
+ a_Pkt.WriteBEUInt8(METADATA_TYPE_BOOL);
+ a_Pkt.WriteBool(ZombieVillager.IsBaby());
+
+ a_Pkt.WriteBEUInt8(ZOMBIE_TYPE);
+ a_Pkt.WriteBEUInt8(METADATA_TYPE_VARINT);
+ a_Pkt.WriteVarInt32(ZombieVillager.GetProfession());
+
+ a_Pkt.WriteBEUInt8(ZOMBIE_CONVERTING);
+ a_Pkt.WriteBEUInt8(METADATA_TYPE_BOOL);
+ a_Pkt.WriteBool(ZombieVillager.ConversionTime() != -1);
+ break;
+ } // case mtZombieVillager
+
default: break;
} // switch (a_Mob.GetType())
}
diff --git a/src/Protocol/Protocol_1_11.cpp b/src/Protocol/Protocol_1_11.cpp
index 8a846b540..7e46fa332 100644
--- a/src/Protocol/Protocol_1_11.cpp
+++ b/src/Protocol/Protocol_1_11.cpp
@@ -1182,15 +1182,6 @@ void cProtocol_1_11_0::WriteMobMetadata(cPacketizer & a_Pkt, const cMonster & a_
a_Pkt.WriteBEUInt8(ZOMBIE_IS_BABY);
a_Pkt.WriteBEUInt8(METADATA_TYPE_BOOL);
a_Pkt.WriteBool(Zombie.IsBaby());
-
- // These don't exist
- // a_Pkt.WriteBEUInt8(ZOMBIE_TYPE);
- // a_Pkt.WriteBEUInt8(METADATA_TYPE_VARINT);
- // a_Pkt.WriteVarInt32(Zombie.IsVillagerZombie() ? 1 : 0);
-
- // a_Pkt.WriteBEUInt8(ZOMBIE_CONVERTING);
- // a_Pkt.WriteBEUInt8(METADATA_TYPE_BOOL);
- // a_Pkt.WriteBool(Zombie.IsConverting());
break;
} // case mtZombie
@@ -1203,6 +1194,23 @@ void cProtocol_1_11_0::WriteMobMetadata(cPacketizer & a_Pkt, const cMonster & a_
break;
} // case mtZombiePigman
+ case mtZombieVillager:
+ {
+ auto & ZombieVillager = reinterpret_cast<const cZombieVillager &>(a_Mob);
+ a_Pkt.WriteBEUInt8(ZOMBIE_IS_BABY);
+ a_Pkt.WriteBEUInt8(METADATA_TYPE_BOOL);
+ a_Pkt.WriteBool(ZombieVillager.IsBaby());
+
+ a_Pkt.WriteBEUInt8(ZOMBIE_VILLAGER_CONVERTING);
+ a_Pkt.WriteBEUInt8(METADATA_TYPE_VARINT);
+ a_Pkt.WriteVarInt32(static_cast<UInt32>(ZombieVillager.ConversionTime()));
+
+ a_Pkt.WriteBEUInt8(ZOMBIE_VILLAGER_PROFESSION);
+ a_Pkt.WriteBEUInt8(METADATA_TYPE_VARINT);
+ a_Pkt.WriteVarInt32(static_cast<UInt32>(ZombieVillager.GetProfession()));
+ break;
+ } // case mtZombieVillager
+
default: break;
} // switch (a_Mob.GetType())
}
diff --git a/src/Protocol/Protocol_1_12.cpp b/src/Protocol/Protocol_1_12.cpp
index 01bbf8104..8cf8df6ca 100644
--- a/src/Protocol/Protocol_1_12.cpp
+++ b/src/Protocol/Protocol_1_12.cpp
@@ -908,9 +908,6 @@ void cProtocol_1_12::WriteMobMetadata(cPacketizer & a_Pkt, const cMonster & a_Mo
// a_Pkt.WriteBEUInt8(METADATA_TYPE_VARINT);
// a_Pkt.WriteVarInt32(Zombie.IsVillagerZombie() ? 1 : 0);
- // a_Pkt.WriteBEUInt8(ZOMBIE_CONVERTING);
- // a_Pkt.WriteBEUInt8(METADATA_TYPE_BOOL);
- // a_Pkt.WriteBool(Zombie.IsConverting());
break;
} // case mtZombie
@@ -923,6 +920,23 @@ void cProtocol_1_12::WriteMobMetadata(cPacketizer & a_Pkt, const cMonster & a_Mo
break;
} // case mtZombiePigman
+ case mtZombieVillager:
+ {
+ auto & ZombieVillager = reinterpret_cast<const cZombieVillager &>(a_Mob);
+ a_Pkt.WriteBEUInt8(ZOMBIE_IS_BABY);
+ a_Pkt.WriteBEUInt8(METADATA_TYPE_BOOL);
+ a_Pkt.WriteBool(ZombieVillager.IsBaby());
+
+ a_Pkt.WriteBEUInt8(ZOMBIE_VILLAGER_CONVERTING);
+ a_Pkt.WriteBEUInt8(METADATA_TYPE_VARINT);
+ a_Pkt.WriteVarInt32(static_cast<UInt32>(ZombieVillager.ConversionTime()));
+
+ a_Pkt.WriteBEUInt8(ZOMBIE_VILLAGER_PROFESSION);
+ a_Pkt.WriteBEUInt8(METADATA_TYPE_VARINT);
+ a_Pkt.WriteVarInt32(static_cast<UInt32>(ZombieVillager.GetProfession()));
+ break;
+ } // case mtZombieVillager
+
case mtBlaze:
case mtEnderDragon:
case mtGuardian:
diff --git a/src/Protocol/Protocol_1_8.cpp b/src/Protocol/Protocol_1_8.cpp
index 1b3c261f5..a516ec891 100644
--- a/src/Protocol/Protocol_1_8.cpp
+++ b/src/Protocol/Protocol_1_8.cpp
@@ -3825,9 +3825,9 @@ void cProtocol_1_8_0::WriteMobMetadata(cPacketizer & a_Pkt, const cMonster & a_M
a_Pkt.WriteBEUInt8(0x0c);
a_Pkt.WriteBEInt8(Zombie.IsBaby() ? 1 : -1);
a_Pkt.WriteBEUInt8(0x0d);
- a_Pkt.WriteBEUInt8(Zombie.IsVillagerZombie() ? 1 : 0);
+ a_Pkt.WriteBEUInt8(0);
a_Pkt.WriteBEUInt8(0x0e);
- a_Pkt.WriteBEUInt8(Zombie.IsConverting() ? 1 : 0);
+ a_Pkt.WriteBEUInt8(0);
break;
} // case mtZombie
@@ -3839,6 +3839,18 @@ void cProtocol_1_8_0::WriteMobMetadata(cPacketizer & a_Pkt, const cMonster & a_M
break;
} // case mtZombiePigman
+ case mtZombieVillager:
+ {
+ auto & ZombieVillager = reinterpret_cast<const cZombieVillager &>(a_Mob);
+ a_Pkt.WriteBEUInt8(0x0c);
+ a_Pkt.WriteBEInt8(ZombieVillager.IsBaby() ? 1 : -1);
+ a_Pkt.WriteBEUInt8(0x0d);
+ a_Pkt.WriteBEUInt8(1);
+ a_Pkt.WriteBEUInt8(0x0e);
+ a_Pkt.WriteBEUInt8((ZombieVillager.ConversionTime() == -1) ? 0 : 1);
+ break;
+ } // case mtZombieVillager
+
default: break;
} // switch (a_Mob.GetType())
}
diff --git a/src/Protocol/Protocol_1_9.cpp b/src/Protocol/Protocol_1_9.cpp
index 9f786b02d..e33b65b69 100644
--- a/src/Protocol/Protocol_1_9.cpp
+++ b/src/Protocol/Protocol_1_9.cpp
@@ -4329,11 +4329,11 @@ void cProtocol_1_9_0::WriteMobMetadata(cPacketizer & a_Pkt, const cMonster & a_M
a_Pkt.WriteBEUInt8(12); // Index 12: Is a villager
a_Pkt.WriteBEUInt8(METADATA_TYPE_VARINT);
- a_Pkt.WriteVarInt32(Zombie.IsVillagerZombie() ? 1 : 0); // TODO: This actually encodes the zombie villager profession, but that isn't implemented yet.
+ a_Pkt.WriteVarInt32(0);
a_Pkt.WriteBEUInt8(13); // Index 13: Is converting
a_Pkt.WriteBEUInt8(METADATA_TYPE_BOOL);
- a_Pkt.WriteBool(Zombie.IsConverting());
+ a_Pkt.WriteBool(false);
break;
} // case mtZombie
@@ -4346,6 +4346,23 @@ void cProtocol_1_9_0::WriteMobMetadata(cPacketizer & a_Pkt, const cMonster & a_M
break;
} // case mtZombiePigman
+ case mtZombieVillager:
+ {
+ auto & ZombieVillager = reinterpret_cast<const cZombieVillager &>(a_Mob);
+ a_Pkt.WriteBEUInt8(11); // Index 11: Is baby
+ a_Pkt.WriteBEUInt8(METADATA_TYPE_BOOL);
+ a_Pkt.WriteBool(ZombieVillager.IsBaby());
+
+ a_Pkt.WriteBEUInt8(12); // Index 12: Is a villager
+ a_Pkt.WriteBEUInt8(METADATA_TYPE_VARINT);
+ a_Pkt.WriteVarInt32(ZombieVillager.GetProfession());
+
+ a_Pkt.WriteBEUInt8(13); // Index 13: Is converting
+ a_Pkt.WriteBEUInt8(METADATA_TYPE_BOOL);
+ a_Pkt.WriteBool(ZombieVillager.ConversionTime() != -1);
+ break;
+ } // case mtZombieVillager
+
default: break;
} // switch (a_Mob.GetType())
}
diff --git a/src/WorldStorage/NBTChunkSerializer.cpp b/src/WorldStorage/NBTChunkSerializer.cpp
index 3e8994786..138921264 100644
--- a/src/WorldStorage/NBTChunkSerializer.cpp
+++ b/src/WorldStorage/NBTChunkSerializer.cpp
@@ -738,10 +738,17 @@ public:
case mtVillager: EntityClass = "Villager"; break;
case mtWitch: EntityClass = "Witch"; break;
case mtWither: EntityClass = "WitherBoss"; break;
+<<<<<<< HEAD
case mtWitherSkeleton: EntityClass = "WitherSkeleton"; break;
case mtWolf: EntityClass = "Wolf"; break;
case mtZombie: EntityClass = "Zombie"; break;
case mtZombiePigman: EntityClass = "PigZombie"; break;
+=======
+ case mtWolf: EntityClass = "Wolf"; break;
+ case mtZombie: EntityClass = "Zombie"; break;
+ case mtZombiePigman: EntityClass = "PigZombie"; break;
+ case mtZombieVillager: EntityClass = "ZombieVillager"; break;
+>>>>>>> Add Zombie Villagers
default:
{
ASSERT(!"Unhandled monster type");
@@ -901,10 +908,7 @@ public:
}
case mtZombie:
{
- const cZombie *Zombie = static_cast<const cZombie *>(a_Monster);
- mWriter.AddByte("IsVillager", Zombie->IsVillagerZombie() ? 1 : 0);
- mWriter.AddByte("IsConverting", Zombie->IsConverting() ? 1 : 0);
- mWriter.AddInt ("Age", Zombie->GetAge());
+ mWriter.AddInt("Age", static_cast<const cZombie *>(a_Monster)->GetAge());
break;
}
case mtZombiePigman:
@@ -912,6 +916,13 @@ public:
mWriter.AddInt("Age", static_cast<const cZombiePigman *>(a_Monster)->GetAge());
break;
}
+ case mtZombieVillager:
+ {
+ const cZombieVillager *ZombieVillager = reinterpret_cast<const cZombieVillager *>(a_Monster);
+ mWriter.AddInt("Profession", ZombieVillager->GetProfession());
+ mWriter.AddInt("ConversionTime", ZombieVillager->ConversionTime());
+ mWriter.AddInt("Age", ZombieVillager->GetAge());
+ }
case mtBlaze:
case mtCaveSpider:
case mtChicken:
diff --git a/src/WorldStorage/WSSAnvil.cpp b/src/WorldStorage/WSSAnvil.cpp
index 31934e181..9915e9eb7 100755
--- a/src/WorldStorage/WSSAnvil.cpp
+++ b/src/WorldStorage/WSSAnvil.cpp
@@ -1568,6 +1568,8 @@ void cWSSAnvil::LoadEntityFromNBT(cEntityList & a_Entities, const cParsedNBT & a
{ "minecraft:zombie", &cWSSAnvil::LoadZombieFromNBT },
{ "PigZombie", &cWSSAnvil::LoadPigZombieFromNBT },
{ "minecraft:zombie_pigman", &cWSSAnvil::LoadPigZombieFromNBT },
+ { "ZombieVillager", &cWSSAnvil::LoadZombieVillagerFromNBT },
+ { "minecraft:zombie_villager", &cWSSAnvil::LoadZombieVillagerFromNBT },
};
auto it = EntityTypeToFunction.find(AString(a_IDTag, a_IDTagLength));
@@ -2968,15 +2970,40 @@ void cWSSAnvil::LoadWolfFromNBT(cEntityList & a_Entities, const cParsedNBT & a_N
void cWSSAnvil::LoadZombieFromNBT(cEntityList & a_Entities, const cParsedNBT & a_NBT, int a_TagIdx)
{
- int IsVillagerIdx = a_NBT.FindChildByName(a_TagIdx, "IsVillager");
- if (IsVillagerIdx < 0)
+ std::unique_ptr<cZombie> Monster = cpp14::make_unique<cZombie>();
+ if (!LoadEntityBaseFromNBT(*Monster.get(), a_NBT, a_TagIdx))
{
return;
}
- bool IsVillagerZombie = ((a_NBT.GetByte(IsVillagerIdx) == 1) ? true : false);
+ if (!LoadMonsterBaseFromNBT(*Monster.get(), a_NBT, a_TagIdx))
+ {
+ return;
+ }
+
+ int AgeableIdx = a_NBT.FindChildByName(a_TagIdx, "Age");
+ if (AgeableIdx > 0)
+ {
+ int Age;
+ switch (a_NBT.GetType(AgeableIdx))
+ {
+ case TAG_Byte: Age = static_cast<int>(a_NBT.GetByte(AgeableIdx)); break;
+ case TAG_Int: Age = a_NBT.GetInt(AgeableIdx); break;
+ default: Age = 0; break;
+ }
+ Monster->SetAge(Age);
+ }
+
+ a_Entities.emplace_back(std::move(Monster));
+}
+
+
+
- std::unique_ptr<cZombie> Monster = cpp14::make_unique<cZombie>(IsVillagerZombie);
+
+void cWSSAnvil::LoadPigZombieFromNBT(cEntityList & a_Entities, const cParsedNBT & a_NBT, int a_TagIdx)
+{
+ std::unique_ptr<cZombiePigman> Monster = cpp14::make_unique<cZombiePigman>();
if (!LoadEntityBaseFromNBT(*Monster.get(), a_NBT, a_TagIdx))
{
return;
@@ -3007,9 +3034,17 @@ void cWSSAnvil::LoadZombieFromNBT(cEntityList & a_Entities, const cParsedNBT & a
-void cWSSAnvil::LoadPigZombieFromNBT(cEntityList & a_Entities, const cParsedNBT & a_NBT, int a_TagIdx)
+void cWSSAnvil::LoadZombieVillagerFromNBT(cEntityList & a_Entities, const cParsedNBT & a_NBT, int a_TagIdx)
{
- std::unique_ptr<cZombiePigman> Monster = cpp14::make_unique<cZombiePigman>();
+ int ProfessionIdx = a_NBT.FindChildByName(a_TagIdx, "Profession");
+ if (ProfessionIdx < 0)
+ {
+ return;
+ }
+
+ cVillager::eVillagerType Profession = static_cast<cVillager::eVillagerType>(a_NBT.GetInt(ProfessionIdx));
+
+ std::unique_ptr<cZombieVillager> Monster = cpp14::make_unique<cZombieVillager>(Profession);
if (!LoadEntityBaseFromNBT(*Monster.get(), a_NBT, a_TagIdx))
{
return;
@@ -3020,6 +3055,8 @@ void cWSSAnvil::LoadPigZombieFromNBT(cEntityList & a_Entities, const cParsedNBT
return;
}
+ // TODO: Conversion time
+
int AgeableIdx = a_NBT.FindChildByName(a_TagIdx, "Age");
if (AgeableIdx > 0)
{
@@ -3028,7 +3065,7 @@ void cWSSAnvil::LoadPigZombieFromNBT(cEntityList & a_Entities, const cParsedNBT
{
case TAG_Byte: Age = static_cast<int>(a_NBT.GetByte(AgeableIdx)); break;
case TAG_Int: Age = a_NBT.GetInt (AgeableIdx); break;
- default: Age = 0; break;
+ default: Age = 0; break;
}
Monster->SetAge(Age);
}
diff --git a/src/WorldStorage/WSSAnvil.h b/src/WorldStorage/WSSAnvil.h
index e6b3e5ee9..caee4ade2 100755
--- a/src/WorldStorage/WSSAnvil.h
+++ b/src/WorldStorage/WSSAnvil.h
@@ -232,6 +232,7 @@ protected:
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);
+ void LoadZombieVillagerFromNBT (cEntityList & a_Entities, const cParsedNBT & a_NBT, int a_TagIdx);
/** Loads the owner name and UUID from the entity at the specified NBT tag.
Returns a pair of {name, uuid}. If the entity is not owned, name is an empty string and uuid is nil. */