summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/BlockEntities/DispenserEntity.cpp2
-rw-r--r--src/Blocks/BlockPortal.h2
-rw-r--r--src/Blocks/WorldInterface.h2
-rw-r--r--src/CMakeLists.txt1
-rw-r--r--src/Color.cpp76
-rw-r--r--src/Color.h58
-rw-r--r--src/CraftingRecipes.cpp192
-rw-r--r--src/CraftingRecipes.h3
-rw-r--r--src/Entities/ThrownEggEntity.cpp10
-rw-r--r--src/Generating/Trees.h1
-rw-r--r--src/Item.cpp19
-rw-r--r--src/Item.h11
-rw-r--r--src/Items/ItemMobHead.h2
-rw-r--r--src/Items/ItemPumpkin.h4
-rw-r--r--src/Items/ItemSpawnEgg.h2
-rw-r--r--src/Mobs/Monster.h2
-rw-r--r--src/Mobs/Mooshroom.cpp2
-rw-r--r--src/Mobs/Pig.cpp2
-rw-r--r--src/Mobs/Rabbit.cpp15
-rw-r--r--src/Mobs/Rabbit.h25
-rw-r--r--src/Mobs/Spider.cpp42
-rw-r--r--src/Mobs/Spider.h2
-rw-r--r--src/Mobs/Villager.cpp2
-rw-r--r--src/Protocol/Protocol17x.cpp36
-rw-r--r--src/Protocol/Protocol18x.cpp48
-rw-r--r--src/Simulator/FloodyFluidSimulator.cpp9
-rw-r--r--src/World.cpp7
-rw-r--r--src/World.h3
-rw-r--r--src/WorldStorage/NBTChunkSerializer.cpp91
-rwxr-xr-xsrc/WorldStorage/WSSAnvil.cpp13
30 files changed, 593 insertions, 91 deletions
diff --git a/src/BlockEntities/DispenserEntity.cpp b/src/BlockEntities/DispenserEntity.cpp
index a847f1b65..297d5273e 100644
--- a/src/BlockEntities/DispenserEntity.cpp
+++ b/src/BlockEntities/DispenserEntity.cpp
@@ -105,7 +105,7 @@ void cDispenserEntity::DropSpenseFromSlot(cChunk & a_Chunk, int a_SlotNum)
{
double MobX = 0.5 + (DispX + DispChunk->GetPosX() * cChunkDef::Width);
double MobZ = 0.5 + (DispZ + DispChunk->GetPosZ() * cChunkDef::Width);
- if (m_World->SpawnMob(MobX, DispY, MobZ, static_cast<eMonsterType>(m_Contents.GetSlot(a_SlotNum).m_ItemDamage)) != cEntity::INVALID_ID)
+ if (m_World->SpawnMob(MobX, DispY, MobZ, static_cast<eMonsterType>(m_Contents.GetSlot(a_SlotNum).m_ItemDamage), false) != cEntity::INVALID_ID)
{
m_Contents.ChangeSlotCount(a_SlotNum, -1);
}
diff --git a/src/Blocks/BlockPortal.h b/src/Blocks/BlockPortal.h
index c18acbdb5..4af50984e 100644
--- a/src/Blocks/BlockPortal.h
+++ b/src/Blocks/BlockPortal.h
@@ -49,7 +49,7 @@ public:
int PosX = a_Chunk.GetPosX() * cChunkDef::Width + a_RelX;
int PosZ = a_Chunk.GetPosZ() * cChunkDef::Width + a_RelZ;
- a_WorldInterface.SpawnMob(PosX, a_RelY, PosZ, mtZombiePigman);
+ a_WorldInterface.SpawnMob(PosX, a_RelY, PosZ, mtZombiePigman, false);
}
virtual bool CanBeAt(cChunkInterface & a_ChunkInterface, int a_RelX, int a_RelY, int a_RelZ, const cChunk & a_Chunk) override
diff --git a/src/Blocks/WorldInterface.h b/src/Blocks/WorldInterface.h
index 826df7034..ede0837a4 100644
--- a/src/Blocks/WorldInterface.h
+++ b/src/Blocks/WorldInterface.h
@@ -35,7 +35,7 @@ public:
/** Spawns a mob of the specified type.
Returns the mob's UniqueID if recognized and spawned, or cEntity::INVALID_ID on failure. */
- virtual UInt32 SpawnMob(double a_PosX, double a_PosY, double a_PosZ, eMonsterType a_MonsterType) = 0;
+ virtual UInt32 SpawnMob(double a_PosX, double a_PosY, double a_PosZ, eMonsterType a_MonsterType, bool a_Baby) = 0;
/** Spawns an experience orb at the given location with the given reward.
Returns the UniqueID of the spawned experience orb, or cEntity::INVALID_ID on failure. */
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index 6c8fe7d0c..d941b7d4c 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -28,6 +28,7 @@ SET (SRCS
ChunkSender.cpp
ChunkStay.cpp
ClientHandle.cpp
+ Color.cpp
CommandOutput.cpp
CompositeChat.cpp
CraftingRecipes.cpp
diff --git a/src/Color.cpp b/src/Color.cpp
new file mode 100644
index 000000000..f2180e2d9
--- /dev/null
+++ b/src/Color.cpp
@@ -0,0 +1,76 @@
+#include "Globals.h" // NOTE: MSVC stupidness requires this to be the same across all modules
+
+#include "Color.h"
+
+
+
+
+
+#define COLOR_RED_BITS 0x00FF0000
+#define COLOR_GREEN_BITS 0x0000FF00
+#define COLOR_BLUE_BITS 0x000000FF
+#define COLOR_RED_OFFSET 16
+#define COLOR_GREEN_OFFSET 8
+
+
+
+
+
+void cColor::SetColor(unsigned char a_Red, unsigned char a_Green, unsigned char a_Blue)
+{
+ m_Color = (static_cast<unsigned int>(a_Red) << COLOR_RED_OFFSET) + (static_cast<unsigned int>(a_Green) << COLOR_GREEN_OFFSET) + (static_cast<unsigned int>(a_Blue));
+}
+
+
+
+
+
+void cColor::SetRed(unsigned char a_Red)
+{
+ m_Color = (static_cast<unsigned int>(a_Red) << COLOR_RED_OFFSET) + ((COLOR_GREEN_BITS | COLOR_BLUE_BITS) & m_Color);
+}
+
+
+
+
+
+void cColor::SetGreen(unsigned char a_Green)
+{
+ m_Color = (static_cast<unsigned int>(a_Green) << COLOR_GREEN_OFFSET) + ((COLOR_RED_BITS | COLOR_BLUE_BITS) & m_Color);
+}
+
+
+
+
+
+void cColor::SetBlue(unsigned char a_Blue)
+{
+ m_Color = static_cast<unsigned int>(a_Blue) + ((COLOR_RED_BITS | COLOR_GREEN_BITS) & m_Color);
+}
+
+
+
+
+
+unsigned char cColor::GetRed() const
+{
+ return (m_Color & COLOR_RED_BITS) >> COLOR_RED_OFFSET;
+}
+
+
+
+
+
+unsigned char cColor::GetGreen() const
+{
+ return (m_Color & COLOR_GREEN_BITS) >> COLOR_GREEN_OFFSET;
+}
+
+
+
+
+
+unsigned char cColor::GetBlue() const
+{
+ return m_Color & COLOR_BLUE_BITS;
+}
diff --git a/src/Color.h b/src/Color.h
new file mode 100644
index 000000000..a90e8372b
--- /dev/null
+++ b/src/Color.h
@@ -0,0 +1,58 @@
+
+// Color.h
+
+// Declares a class to handle item color related code
+
+
+
+
+
+#pragma once
+
+ // tolua_begin
+
+class cColor
+{
+public:
+
+ enum
+ {
+ COLOR_MIN = 0,
+ COLOR_MAX = 255,
+ COLOR_LIMIT = 256,
+ COLOR_NONE = 0xFFFFFFFF,
+ };
+ cColor() { m_Color = COLOR_NONE;}
+ cColor(unsigned char a_Red, unsigned char a_Green, unsigned char a_Blue) { SetColor(a_Red, a_Green, a_Blue); }
+
+ /// Returns whether the color is a valid color
+ bool IsValid() const { return m_Color != COLOR_NONE; }
+
+ /// Changes the color
+ void SetColor(unsigned char a_Red, unsigned char a_Green, unsigned char a_Blue);
+
+ /// Alters the red value of the color
+ void SetRed(unsigned char a_Red);
+
+ /// Alters the green value of the color
+ void SetGreen(unsigned char a_Red);
+
+ /// Alters the blue value of the color
+ void SetBlue(unsigned char a_Red);
+
+ /// Returns the red value of the color
+ unsigned char GetRed() const;
+
+ /// Returns the green value of the color
+ unsigned char GetGreen() const;
+
+ /// Returns the blue value of the color
+ unsigned char GetBlue() const;
+
+ /// Resets the color
+ void Clear() { m_Color = COLOR_NONE; }
+ // tolua_end
+
+ unsigned int m_Color;
+
+};
diff --git a/src/CraftingRecipes.cpp b/src/CraftingRecipes.cpp
index 0bb77d341..d3a28292a 100644
--- a/src/CraftingRecipes.cpp
+++ b/src/CraftingRecipes.cpp
@@ -787,6 +787,9 @@ cCraftingRecipes::cRecipe * cCraftingRecipes::MatchRecipe(const cItem * a_Crafti
// We use Recipe instead of a_Recipe because we want the wildcard ingredients' slot numbers as well, which was just added previously
HandleFireworks(a_CraftingGrid, Recipe.get(), a_GridStride, a_OffsetX, a_OffsetY);
+ // Handle Dyed Leather
+ HandleDyedLeather(a_CraftingGrid, Recipe.get(), a_GridStride, a_GridWidth, a_GridHeight);
+
return Recipe.release();
}
@@ -874,3 +877,192 @@ void cCraftingRecipes::HandleFireworks(const cItem * a_CraftingGrid, cCraftingRe
+
+void cCraftingRecipes::HandleDyedLeather(const cItem * a_CraftingGrid, cCraftingRecipes::cRecipe * a_Recipe, int a_GridStride, int a_GridWidth, int a_GridHeight)
+{
+ short result_type = a_Recipe->m_Result.m_ItemType;
+ if ((result_type == E_ITEM_LEATHER_CAP) || (result_type == E_ITEM_LEATHER_TUNIC) || (result_type == E_ITEM_LEATHER_PANTS) || (result_type == E_ITEM_LEATHER_BOOTS))
+ {
+ bool found = false;
+ cItem temp;
+
+ float red = 0;
+ float green = 0;
+ float blue = 0;
+ float dye_count = 0;
+
+ for (int x = 0; x < a_GridWidth; ++x)
+ {
+ for (int y = 0; y < a_GridHeight; ++y)
+ {
+ int GridIdx = x + a_GridStride * y;
+ if ((a_CraftingGrid[GridIdx].m_ItemType == result_type) && (found == false))
+ {
+ found = true;
+ temp = a_CraftingGrid[GridIdx].CopyOne();
+ // The original color of the item affects the result
+ if (temp.m_ItemColor.IsValid())
+ {
+ red += temp.m_ItemColor.GetRed();
+ green += temp.m_ItemColor.GetGreen();
+ blue += temp.m_ItemColor.GetBlue();
+ ++dye_count;
+ }
+ }
+ else if (a_CraftingGrid[GridIdx].m_ItemType == E_ITEM_DYE)
+ {
+ switch (a_CraftingGrid[GridIdx].m_ItemDamage)
+ {
+ case E_META_DYE_BLACK:
+ {
+ red += 23;
+ green += 23;
+ blue += 23;
+ break;
+ }
+ case E_META_DYE_RED:
+ {
+ red += 142;
+ green += 47;
+ blue += 47;
+ break;
+ }
+ case E_META_DYE_GREEN:
+ {
+ red += 95;
+ green += 118;
+ blue += 47;
+ break;
+ }
+ case E_META_DYE_BROWN:
+ {
+ red += 95;
+ green += 71;
+ blue += 47;
+ break;
+ }
+ case E_META_DYE_BLUE:
+ {
+ red += 47;
+ green += 71;
+ blue += 165;
+ break;
+ }
+ case E_META_DYE_PURPLE:
+ {
+ red += 118;
+ green += 59;
+ blue += 165;
+ break;
+ }
+ case E_META_DYE_CYAN:
+ {
+ red += 71;
+ green += 118;
+ blue += 142;
+ break;
+ }
+ case E_META_DYE_LIGHTGRAY:
+ {
+ red += 142;
+ green += 142;
+ blue += 142;
+ break;
+ }
+ case E_META_DYE_GRAY:
+ {
+ red += 71;
+ green += 71;
+ blue += 71;
+ break;
+ }
+ case E_META_DYE_PINK:
+ {
+ red += 225;
+ green += 118;
+ blue += 153;
+ break;
+ }
+ case E_META_DYE_LIGHTGREEN:
+ {
+ red += 118;
+ green += 190;
+ blue += 23;
+ break;
+ }
+ case E_META_DYE_YELLOW:
+ {
+ red += 213;
+ green += 213;
+ blue += 47;
+ break;
+ }
+ case E_META_DYE_LIGHTBLUE:
+ {
+ red += 95;
+ green += 142;
+ blue += 201;
+ break;
+ }
+ case E_META_DYE_MAGENTA:
+ {
+ red += 165;
+ green += 71;
+ blue += 201;
+ break;
+ }
+ case E_META_DYE_ORANGE:
+ {
+ red += 201;
+ green += 118;
+ blue += 47;
+ break;
+ }
+ case E_META_DYE_WHITE:
+ {
+ red += 237;
+ green += 237;
+ blue += 237;
+ break;
+ }
+ }
+ ++dye_count;
+ }
+ else if (a_CraftingGrid[GridIdx].m_ItemType != E_ITEM_EMPTY)
+ {
+ return;
+ }
+ }
+ }
+
+ if (!found)
+ {
+ return;
+ }
+
+ // Calculate the rgb values
+ double maximum = static_cast<double>(std::max({red, green, blue}));
+
+ double average_red = red / dye_count;
+ double average_green = green / dye_count;
+ double average_blue = blue / dye_count;
+ double average_max = maximum / dye_count;
+
+ double max_average = std::max({average_red, average_green, average_blue});
+
+ double gain_factor = average_max / max_average;
+
+
+ unsigned char result_red = static_cast<unsigned char>(average_red * gain_factor);
+ unsigned char result_green = static_cast<unsigned char>(average_green * gain_factor);
+ unsigned char result_blue = static_cast<unsigned char>(average_blue * gain_factor);
+
+ // Set the results values
+ a_Recipe->m_Result = temp;
+ a_Recipe->m_Result.m_ItemColor.SetColor(result_red, result_green, result_blue);
+ }
+}
+
+
+
+
diff --git a/src/CraftingRecipes.h b/src/CraftingRecipes.h
index 44444d42e..778dd495a 100644
--- a/src/CraftingRecipes.h
+++ b/src/CraftingRecipes.h
@@ -168,6 +168,9 @@ protected:
/** Searches for anything firework related, and does the data setting if appropriate */
void HandleFireworks(const cItem * a_CraftingGrid, cCraftingRecipes::cRecipe * a_Recipe, int a_GridStride, int a_OffsetX, int a_OffsetY);
+
+ /// Searches for anything dye related for leather, calculates the appropriate color value, and sets the resulting value.
+ void HandleDyedLeather(const cItem * a_CraftingGrid, cCraftingRecipes::cRecipe * a_Recipe, int a_GridStride, int a_GridWidth, int a_GridHeight);
} ;
diff --git a/src/Entities/ThrownEggEntity.cpp b/src/Entities/ThrownEggEntity.cpp
index e9ef29239..91bca1da7 100644
--- a/src/Entities/ThrownEggEntity.cpp
+++ b/src/Entities/ThrownEggEntity.cpp
@@ -69,13 +69,13 @@ void cThrownEggEntity::TrySpawnChicken(const Vector3d & a_HitPos)
{
if (m_World->GetTickRandomNumber(7) == 1)
{
- m_World->SpawnMob(a_HitPos.x, a_HitPos.y, a_HitPos.z, mtChicken);
+ m_World->SpawnMob(a_HitPos.x, a_HitPos.y, a_HitPos.z, mtChicken, false);
}
else if (m_World->GetTickRandomNumber(32) == 1)
{
- m_World->SpawnMob(a_HitPos.x, a_HitPos.y, a_HitPos.z, mtChicken);
- m_World->SpawnMob(a_HitPos.x, a_HitPos.y, a_HitPos.z, mtChicken);
- m_World->SpawnMob(a_HitPos.x, a_HitPos.y, a_HitPos.z, mtChicken);
- m_World->SpawnMob(a_HitPos.x, a_HitPos.y, a_HitPos.z, mtChicken);
+ m_World->SpawnMob(a_HitPos.x, a_HitPos.y, a_HitPos.z, mtChicken, false);
+ m_World->SpawnMob(a_HitPos.x, a_HitPos.y, a_HitPos.z, mtChicken, false);
+ m_World->SpawnMob(a_HitPos.x, a_HitPos.y, a_HitPos.z, mtChicken, false);
+ m_World->SpawnMob(a_HitPos.x, a_HitPos.y, a_HitPos.z, mtChicken, false);
}
}
diff --git a/src/Generating/Trees.h b/src/Generating/Trees.h
index 092d71182..b0363e050 100644
--- a/src/Generating/Trees.h
+++ b/src/Generating/Trees.h
@@ -106,6 +106,7 @@ void GetLargeJungleTreeImage(int a_BlockX, int a_BlockY, int a_BlockZ, cNoise &
/// Generates an image of a small jungle tree (1x1 trunk)
void GetSmallJungleTreeImage(int a_BlockX, int a_BlockY, int a_BlockZ, cNoise & a_Noise, int a_Seq, sSetBlockVector & a_LogBlocks, sSetBlockVector & a_OtherBlocks);
+/// Moves the x and z coordinants to the north-west corner of a 2x2 of saplings. Returns true if a 2x2 was found, otherwise it returns false
bool GetLargeTreeAdjustment(cWorld & a_World, int & a_X, int & a_Y, int & a_Z, NIBBLETYPE a_Meta);
diff --git a/src/Item.cpp b/src/Item.cpp
index 36c444328..7bd344ae8 100644
--- a/src/Item.cpp
+++ b/src/Item.cpp
@@ -142,6 +142,13 @@ void cItem::GetJson(Json::Value & a_OutValue) const
a_OutValue["Lore"] = m_Lore;
}
+ if (m_ItemColor.IsValid())
+ {
+ a_OutValue["Color_Red"] = m_ItemColor.GetRed();
+ a_OutValue["Color_Green"] = m_ItemColor.GetGreen();
+ a_OutValue["Color_Blue"] = m_ItemColor.GetBlue();
+ }
+
if ((m_ItemType == E_ITEM_FIREWORK_ROCKET) || (m_ItemType == E_ITEM_FIREWORK_STAR))
{
a_OutValue["Flicker"] = m_FireworkItem.m_HasFlicker;
@@ -172,6 +179,18 @@ void cItem::FromJson(const Json::Value & a_Value)
m_CustomName = a_Value.get("Name", "").asString();
m_Lore = a_Value.get("Lore", "").asString();
+ int red = a_Value.get("Color_Red", -1).asInt();
+ int green = a_Value.get("Color_Green", -1).asInt();
+ int blue = a_Value.get("Color_Blue", -1).asInt();
+ if ((red > -1) && (red < static_cast<int>(cColor::COLOR_LIMIT)) && (green > -1) && (green < static_cast<int>(cColor::COLOR_LIMIT)) && (blue > -1) && (blue < static_cast<int>(cColor::COLOR_LIMIT)))
+ {
+ m_ItemColor.SetColor(static_cast<unsigned char>(red), static_cast<unsigned char>(green), static_cast<unsigned char>(blue));
+ }
+ else if ((red != -1) || (blue != -1) || (green != -1))
+ {
+ LOGWARNING("Item with invalid red, green, and blue values read in from json file.");
+ }
+
if ((m_ItemType == E_ITEM_FIREWORK_ROCKET) || (m_ItemType == E_ITEM_FIREWORK_STAR))
{
m_FireworkItem.m_HasFlicker = a_Value.get("Flicker", false).asBool();
diff --git a/src/Item.h b/src/Item.h
index 056b5eb8a..8f47c4177 100644
--- a/src/Item.h
+++ b/src/Item.h
@@ -12,6 +12,7 @@
#include "Defines.h"
#include "Enchantments.h"
#include "WorldStorage/FireworksSerializer.h"
+#include "Color.h"
@@ -19,6 +20,7 @@
// fwd:
class cItemHandler;
+class cColor;
namespace Json
{
@@ -41,7 +43,8 @@ public:
m_CustomName(""),
m_Lore(""),
m_RepairCost(0),
- m_FireworkItem()
+ m_FireworkItem(),
+ m_ItemColor()
{
}
@@ -62,7 +65,8 @@ public:
m_CustomName (a_CustomName),
m_Lore (a_Lore),
m_RepairCost (0),
- m_FireworkItem()
+ m_FireworkItem(),
+ m_ItemColor()
{
if (!IsValidItem(m_ItemType))
{
@@ -105,6 +109,7 @@ public:
m_Lore = "";
m_RepairCost = 0;
m_FireworkItem.EmptyData();
+ m_ItemColor.Clear();
}
@@ -114,6 +119,7 @@ public:
m_ItemCount = 0;
m_ItemDamage = 0;
m_RepairCost = 0;
+ m_ItemColor.Clear();
}
@@ -206,6 +212,7 @@ public:
int m_RepairCost;
cFireworkItem m_FireworkItem;
+ cColor m_ItemColor;
};
// tolua_end
diff --git a/src/Items/ItemMobHead.h b/src/Items/ItemMobHead.h
index 9a4044bc0..e0f72be9b 100644
--- a/src/Items/ItemMobHead.h
+++ b/src/Items/ItemMobHead.h
@@ -278,7 +278,7 @@ public:
// Spawn the wither:
int BlockX = a_PlacedHeadX + a_OffsetX;
int BlockZ = a_PlacedHeadZ + a_OffsetZ;
- a_World.SpawnMob(static_cast<double>(BlockX) + 0.5, a_PlacedHeadY - 2, static_cast<double>(BlockZ) + 0.5, mtWither);
+ a_World.SpawnMob(static_cast<double>(BlockX) + 0.5, a_PlacedHeadY - 2, static_cast<double>(BlockZ) + 0.5, mtWither, false);
AwardSpawnWitherAchievement(a_World, BlockX, a_PlacedHeadY - 2, BlockZ);
return true;
}
diff --git a/src/Items/ItemPumpkin.h b/src/Items/ItemPumpkin.h
index fa00179d3..7a53d522f 100644
--- a/src/Items/ItemPumpkin.h
+++ b/src/Items/ItemPumpkin.h
@@ -96,7 +96,7 @@ public:
}
// Spawn the golem:
- a_World.SpawnMob(static_cast<double>(a_BlockX) + 0.5, a_BlockY - 2, static_cast<double>(a_BlockZ) + 0.5, mtSnowGolem);
+ a_World.SpawnMob(static_cast<double>(a_BlockX) + 0.5, a_BlockY - 2, static_cast<double>(a_BlockZ) + 0.5, mtSnowGolem, false);
return true;
}
@@ -142,7 +142,7 @@ public:
}
// Spawn the golem:
- a_World.SpawnMob(static_cast<double>(a_BlockX) + 0.5, a_BlockY - 2, static_cast<double>(a_BlockZ) + 0.5, mtIronGolem);
+ a_World.SpawnMob(static_cast<double>(a_BlockX) + 0.5, a_BlockY - 2, static_cast<double>(a_BlockZ) + 0.5, mtIronGolem, false);
return true;
} // for i - ArmOffsets[]
diff --git a/src/Items/ItemSpawnEgg.h b/src/Items/ItemSpawnEgg.h
index b67fe074d..85dd2d245 100644
--- a/src/Items/ItemSpawnEgg.h
+++ b/src/Items/ItemSpawnEgg.h
@@ -40,7 +40,7 @@ public:
eMonsterType MonsterType = ItemDamageToMonsterType(a_Item.m_ItemDamage);
if (
(MonsterType != mtInvalidType) && // Valid monster type
- (a_World->SpawnMob(a_BlockX + 0.5, a_BlockY, a_BlockZ + 0.5, MonsterType) != cEntity::INVALID_ID)) // Spawning succeeded
+ (a_World->SpawnMob(a_BlockX + 0.5, a_BlockY, a_BlockZ + 0.5, MonsterType, false) != cEntity::INVALID_ID)) // Spawning succeeded
{
if (!a_Player->IsGameModeCreative())
{
diff --git a/src/Mobs/Monster.h b/src/Mobs/Monster.h
index 2832a1570..d5de3b19e 100644
--- a/src/Mobs/Monster.h
+++ b/src/Mobs/Monster.h
@@ -115,9 +115,11 @@ public:
virtual bool IsTame (void) const { return false; }
virtual bool IsSitting (void) const { return false; }
+ // tolua_begin
bool IsBaby (void) const { return m_Age < 0; }
char GetAge (void) const { return m_Age; }
void SetAge(char a_Age) { m_Age = a_Age; }
+ // tolua_end
// tolua_begin
diff --git a/src/Mobs/Mooshroom.cpp b/src/Mobs/Mooshroom.cpp
index 3b2fbad57..08cabe143 100644
--- a/src/Mobs/Mooshroom.cpp
+++ b/src/Mobs/Mooshroom.cpp
@@ -67,7 +67,7 @@ void cMooshroom::OnRightClicked(cPlayer & a_Player)
cItems Drops;
Drops.push_back(cItem(E_BLOCK_RED_MUSHROOM, 5, 0));
m_World->SpawnItemPickups(Drops, GetPosX(), GetPosY(), GetPosZ(), 10);
- m_World->SpawnMob(GetPosX(), GetPosY(), GetPosZ(), mtCow);
+ m_World->SpawnMob(GetPosX(), GetPosY(), GetPosZ(), mtCow, false);
Destroy();
} break;
}
diff --git a/src/Mobs/Pig.cpp b/src/Mobs/Pig.cpp
index efa779ac2..21c8e923a 100644
--- a/src/Mobs/Pig.cpp
+++ b/src/Mobs/Pig.cpp
@@ -108,7 +108,7 @@ bool cPig::DoTakeDamage(TakeDamageInfo & a_TDI)
if (a_TDI.DamageType == dtLightning)
{
Destroy();
- m_World->SpawnMob(GetPosX(), GetPosY(), GetPosZ(), mtZombiePigman);
+ m_World->SpawnMob(GetPosX(), GetPosY(), GetPosZ(), mtZombiePigman, false);
return true;
}
return true;
diff --git a/src/Mobs/Rabbit.cpp b/src/Mobs/Rabbit.cpp
index c7f3d58f0..9d10212bf 100644
--- a/src/Mobs/Rabbit.cpp
+++ b/src/Mobs/Rabbit.cpp
@@ -10,7 +10,20 @@
cRabbit::cRabbit(void) :
- super("Rabbit", mtRabbit, "mob.rabbit.idle", "mob.rabbit.death", 0.82, 0.68)
+ cRabbit(static_cast<eRabbitType>(cFastRandom().NextInt(
+ static_cast<UInt8>(eRabbitType::SaltAndPepper) + 1 // Max possible Rabbit-Type
+ )), 0)
+{
+}
+
+
+
+
+
+cRabbit::cRabbit(eRabbitType Type, int MoreCarrotTicks) :
+ super("Rabbit", mtRabbit, "mob.rabbit.idle", "mob.rabbit.death", 0.82, 0.68),
+ m_Type(Type),
+ m_MoreCarrotTicks(MoreCarrotTicks)
{
}
diff --git a/src/Mobs/Rabbit.h b/src/Mobs/Rabbit.h
index e86c85579..56181e3d0 100644
--- a/src/Mobs/Rabbit.h
+++ b/src/Mobs/Rabbit.h
@@ -7,6 +7,21 @@
+enum class eRabbitType : UInt8
+{
+ Brown = 0,
+ White = 1,
+ Black = 2,
+ BlackAndWhite = 3,
+ Gold = 4,
+ SaltAndPepper = 5,
+ TheKillerBunny = 99
+};
+
+
+
+
+
class cRabbit :
public cPassiveMonster
{
@@ -14,11 +29,19 @@ class cRabbit :
public:
cRabbit();
+ cRabbit(eRabbitType Type, int MoreCarrotTicks = 0);
CLASS_PROTODEF(cRabbit)
virtual void GetDrops(cItems & a_Drops, cEntity * a_Killer = nullptr) override;
-
virtual const cItem GetFollowedItem(void) const override { return cItem(E_ITEM_CARROT); }
+ eRabbitType GetRabbitType() const { return m_Type; }
+ UInt8 GetRabbitTypeAsNumber() const { return static_cast<UInt8>(GetRabbitType()); }
+ int GetMoreCarrotTicks() const { return m_MoreCarrotTicks; }
+
+private:
+
+ eRabbitType m_Type;
+ int m_MoreCarrotTicks; // Ticks until the Rabbit eat planted Carrots
} ;
diff --git a/src/Mobs/Spider.cpp b/src/Mobs/Spider.cpp
index 184a1d912..a9da28750 100644
--- a/src/Mobs/Spider.cpp
+++ b/src/Mobs/Spider.cpp
@@ -3,7 +3,8 @@
#include "Spider.h"
-
+#include "../World.h"
+#include "../Entities/Player.h"
@@ -33,3 +34,42 @@ void cSpider::GetDrops(cItems & a_Drops, cEntity * a_Killer)
+
+void cSpider::EventSeePlayer(cEntity * a_Entity)
+{
+ if (!GetWorld()->IsChunkLighted(GetChunkX(), GetChunkZ()))
+ {
+ GetWorld()->QueueLightChunk(GetChunkX(), GetChunkZ());
+ return;
+ }
+
+ if (!static_cast<cPlayer *>(a_Entity)->IsGameModeCreative() && (GetWorld()->GetBlockBlockLight(this->GetPosition()) <= 9))
+ {
+ super::EventSeePlayer(a_Entity);
+ }
+}
+
+
+
+
+
+bool cSpider::DoTakeDamage(TakeDamageInfo & a_TDI)
+{
+ if (!super::DoTakeDamage(a_TDI))
+ {
+ return false;
+ }
+
+ // If the source of the damage is not from an pawn entity, switch to idle
+ if ((a_TDI.Attacker == nullptr) || !a_TDI.Attacker->IsPawn())
+ {
+ m_EMState = IDLE;
+ }
+ else
+ {
+ // If the source of the damage is from a pawn entity, chase that entity
+ m_EMState = CHASING;
+ }
+
+ return true;
+}
diff --git a/src/Mobs/Spider.h b/src/Mobs/Spider.h
index 24134c00f..4f9df7887 100644
--- a/src/Mobs/Spider.h
+++ b/src/Mobs/Spider.h
@@ -18,6 +18,8 @@ public:
CLASS_PROTODEF(cSpider)
virtual void GetDrops(cItems & a_Drops, cEntity * a_Killer = nullptr) override;
+ virtual void EventSeePlayer(cEntity *) override;
+ virtual bool DoTakeDamage(TakeDamageInfo & a_TDI) override;
} ;
diff --git a/src/Mobs/Villager.cpp b/src/Mobs/Villager.cpp
index e4953d546..9239575d0 100644
--- a/src/Mobs/Villager.cpp
+++ b/src/Mobs/Villager.cpp
@@ -41,7 +41,7 @@ bool cVillager::DoTakeDamage(TakeDamageInfo & a_TDI)
if (a_TDI.DamageType == dtLightning)
{
Destroy();
- m_World->SpawnMob(GetPosX(), GetPosY(), GetPosZ(), mtWitch);
+ m_World->SpawnMob(GetPosX(), GetPosY(), GetPosZ(), mtWitch, false);
return true;
}
return true;
diff --git a/src/Protocol/Protocol17x.cpp b/src/Protocol/Protocol17x.cpp
index dc602ec6c..098c62a90 100644
--- a/src/Protocol/Protocol17x.cpp
+++ b/src/Protocol/Protocol17x.cpp
@@ -2637,6 +2637,10 @@ void cProtocol172::ParseItemMetadata(cItem & a_Item, const AString & a_Metadata)
a_Item.m_Lore = Lore;
}
+ else if ((NBT.GetType(displaytag) == TAG_Int) && (NBT.GetName(displaytag) == "color"))
+ {
+ a_Item.m_ItemColor.m_Color = static_cast<unsigned int>(NBT.GetInt(displaytag));
+ }
}
}
else if ((TagName == "Fireworks") || (TagName == "Explosion"))
@@ -2723,7 +2727,7 @@ void cProtocol172::WriteItem(cPacketizer & a_Pkt, const cItem & a_Item)
a_Pkt.WriteBEInt8(a_Item.m_ItemCount);
a_Pkt.WriteBEInt16(a_Item.m_ItemDamage);
- if (a_Item.m_Enchantments.IsEmpty() && a_Item.IsBothNameAndLoreEmpty() && (a_Item.m_ItemType != E_ITEM_FIREWORK_ROCKET) && (a_Item.m_ItemType != E_ITEM_FIREWORK_STAR))
+ if (a_Item.m_Enchantments.IsEmpty() && a_Item.IsBothNameAndLoreEmpty() && (a_Item.m_ItemType != E_ITEM_FIREWORK_ROCKET) && (a_Item.m_ItemType != E_ITEM_FIREWORK_STAR) && !a_Item.m_ItemColor.IsValid())
{
a_Pkt.WriteBEInt16(-1);
return;
@@ -2740,9 +2744,15 @@ void cProtocol172::WriteItem(cPacketizer & a_Pkt, const cItem & a_Item)
const char * TagName = (a_Item.m_ItemType == E_ITEM_BOOK) ? "StoredEnchantments" : "ench";
EnchantmentSerializer::WriteToNBTCompound(a_Item.m_Enchantments, Writer, TagName);
}
- if (!a_Item.IsBothNameAndLoreEmpty())
+ if (!a_Item.IsBothNameAndLoreEmpty() || a_Item.m_ItemColor.IsValid())
{
Writer.BeginCompound("display");
+
+ if (a_Item.m_ItemColor.IsValid())
+ {
+ Writer.AddInt("color", static_cast<int>(a_Item.m_ItemColor.m_Color));
+ }
+
if (!a_Item.IsCustomNameEmpty())
{
Writer.AddString("Name", a_Item.m_CustomName.c_str());
@@ -3006,6 +3016,19 @@ void cProtocol172::WriteEntityMetadata(cPacketizer & a_Pkt, const cEntity & a_En
void cProtocol172::WriteMobMetadata(cPacketizer & a_Pkt, const cMonster & a_Mob)
{
+ // Living Enitiy Metadata
+ if (a_Mob.HasCustomName())
+ {
+ a_Pkt.WriteBEUInt8(0x8a);
+ a_Pkt.WriteString(a_Mob.GetCustomName());
+
+ a_Pkt.WriteBEUInt8(0x0b);
+ a_Pkt.WriteBool(a_Mob.IsCustomNameAlwaysVisible());
+ }
+
+ a_Pkt.WriteBEUInt8(0x66);
+ a_Pkt.WriteBEFloat(a_Mob.GetHealth());
+
switch (a_Mob.GetMobType())
{
case mtBat:
@@ -3199,15 +3222,6 @@ void cProtocol172::WriteMobMetadata(cPacketizer & a_Pkt, const cMonster & a_Mob)
break;
}
} // switch (a_Mob.GetType())
-
- // Custom name:
- if (a_Mob.HasCustomName())
- {
- a_Pkt.WriteBEUInt8(0x8a);
- a_Pkt.WriteString(a_Mob.GetCustomName());
- a_Pkt.WriteBEUInt8(0x0b);
- a_Pkt.WriteBEUInt8(a_Mob.IsCustomNameAlwaysVisible() ? 1 : 0);
- }
}
diff --git a/src/Protocol/Protocol18x.cpp b/src/Protocol/Protocol18x.cpp
index db510825e..e8acf8bd4 100644
--- a/src/Protocol/Protocol18x.cpp
+++ b/src/Protocol/Protocol18x.cpp
@@ -2869,6 +2869,10 @@ void cProtocol180::ParseItemMetadata(cItem & a_Item, const AString & a_Metadata)
a_Item.m_Lore = Lore;
}
+ else if ((NBT.GetType(displaytag) == TAG_Int) && (NBT.GetName(displaytag) == "color"))
+ {
+ a_Item.m_ItemColor.m_Color = static_cast<unsigned int>(NBT.GetInt(displaytag));
+ }
}
}
else if ((TagName == "Fireworks") || (TagName == "Explosion"))
@@ -3018,12 +3022,13 @@ void cProtocol180::WriteItem(cPacketizer & a_Pkt, const cItem & a_Item)
a_Pkt.WriteBEInt8(a_Item.m_ItemCount);
a_Pkt.WriteBEInt16(a_Item.m_ItemDamage);
- if (a_Item.m_Enchantments.IsEmpty() && a_Item.IsBothNameAndLoreEmpty() && (a_Item.m_ItemType != E_ITEM_FIREWORK_ROCKET) && (a_Item.m_ItemType != E_ITEM_FIREWORK_STAR))
+ if (a_Item.m_Enchantments.IsEmpty() && a_Item.IsBothNameAndLoreEmpty() && (a_Item.m_ItemType != E_ITEM_FIREWORK_ROCKET) && (a_Item.m_ItemType != E_ITEM_FIREWORK_STAR) && !a_Item.m_ItemColor.IsValid())
{
a_Pkt.WriteBEInt8(0);
return;
}
+
// Send the enchantments and custom names:
cFastNBTWriter Writer;
if (a_Item.m_RepairCost != 0)
@@ -3035,9 +3040,14 @@ void cProtocol180::WriteItem(cPacketizer & a_Pkt, const cItem & a_Item)
const char * TagName = (a_Item.m_ItemType == E_ITEM_BOOK) ? "StoredEnchantments" : "ench";
EnchantmentSerializer::WriteToNBTCompound(a_Item.m_Enchantments, Writer, TagName);
}
- if (!a_Item.IsBothNameAndLoreEmpty())
+ if (!a_Item.IsBothNameAndLoreEmpty() || a_Item.m_ItemColor.IsValid())
{
Writer.BeginCompound("display");
+ if (a_Item.m_ItemColor.IsValid())
+ {
+ Writer.AddInt("color", static_cast<int>(a_Item.m_ItemColor.m_Color));
+ }
+
if (!a_Item.IsCustomNameEmpty())
{
Writer.AddString("Name", a_Item.m_CustomName.c_str());
@@ -3197,7 +3207,7 @@ void cProtocol180::WriteEntityMetadata(cPacketizer & a_Pkt, const cEntity & a_En
}
a_Pkt.WriteBEUInt8(0); // Byte(0) + index 0
a_Pkt.WriteBEUInt8(Flags);
-
+
switch (a_Entity.GetEntityType())
{
case cEntity::etPlayer: break; // TODO?
@@ -3303,6 +3313,19 @@ void cProtocol180::WriteEntityMetadata(cPacketizer & a_Pkt, const cEntity & a_En
void cProtocol180::WriteMobMetadata(cPacketizer & a_Pkt, const cMonster & a_Mob)
{
+ // Living Enitiy Metadata
+ if (a_Mob.HasCustomName())
+ {
+ a_Pkt.WriteBEUInt8(0x82);
+ a_Pkt.WriteString(a_Mob.GetCustomName());
+
+ a_Pkt.WriteBEUInt8(0x03);
+ a_Pkt.WriteBool(a_Mob.IsCustomNameAlwaysVisible());
+ }
+
+ a_Pkt.WriteBEUInt8(0x66);
+ a_Pkt.WriteBEFloat(a_Mob.GetHealth());
+
switch (a_Mob.GetMobType())
{
case mtBat:
@@ -3414,14 +3437,6 @@ void cProtocol180::WriteMobMetadata(cPacketizer & a_Pkt, const cMonster & a_Mob)
break;
} // case mtPig
- case mtRabbit:
- {
- auto & Rabbit = reinterpret_cast<const cRabbit &>(a_Mob);
- a_Pkt.WriteBEUInt8(0x0c);
- a_Pkt.WriteBEInt8(Rabbit.GetAge());
- break;
- } // case mtRabbit
-
case mtSheep:
{
auto & Sheep = reinterpret_cast<const cSheep &>(a_Mob);
@@ -3439,6 +3454,17 @@ void cProtocol180::WriteMobMetadata(cPacketizer & a_Pkt, const cMonster & a_Mob)
break;
} // case mtSheep
+ case mtRabbit:
+ {
+ auto & Rabbit = reinterpret_cast<const cRabbit &>(a_Mob);
+ a_Pkt.WriteBEUInt8(0x12);
+ a_Pkt.WriteBEUInt8(Rabbit.GetRabbitTypeAsNumber());
+
+ a_Pkt.WriteBEUInt8(0x0c);
+ a_Pkt.WriteBEInt8(Rabbit.GetAge());
+ break;
+ } // case mtRabbit
+
case mtSkeleton:
{
auto & Skeleton = reinterpret_cast<const cSkeleton &>(a_Mob);
diff --git a/src/Simulator/FloodyFluidSimulator.cpp b/src/Simulator/FloodyFluidSimulator.cpp
index 69c46f090..1e56f9528 100644
--- a/src/Simulator/FloodyFluidSimulator.cpp
+++ b/src/Simulator/FloodyFluidSimulator.cpp
@@ -111,9 +111,12 @@ void cFloodyFluidSimulator::SimulateBlock(cChunk * a_Chunk, int a_RelX, int a_Re
// If source creation is on, check for it here:
if (
- (m_NumNeighborsForSource > 0) && // Source creation is on
- (MyMeta == m_Falloff) && // Only exactly one block away from a source (fast bail-out)
- !IsPassableForFluid(Below) && // Only exactly 1 block deep
+ (m_NumNeighborsForSource > 0) && // Source creation is on
+ (MyMeta == m_Falloff) && // Only exactly one block away from a source (fast bail-out)
+ (
+ !IsPassableForFluid(Below) || // Only exactly 1 block deep
+ (Below == m_StationaryFluidBlock) // Or a source block underneath
+ ) &&
CheckNeighborsForSource(a_Chunk, a_RelX, a_RelY, a_RelZ) // Did we create a source?
)
{
diff --git a/src/World.cpp b/src/World.cpp
index dec335253..b152d119a 100644
--- a/src/World.cpp
+++ b/src/World.cpp
@@ -3326,7 +3326,7 @@ bool cWorld::IsBlockDirectlyWatered(int a_BlockX, int a_BlockY, int a_BlockZ)
-UInt32 cWorld::SpawnMob(double a_PosX, double a_PosY, double a_PosZ, eMonsterType a_MonsterType)
+UInt32 cWorld::SpawnMob(double a_PosX, double a_PosY, double a_PosZ, eMonsterType a_MonsterType, bool a_Baby)
{
cMonster * Monster = nullptr;
@@ -3337,6 +3337,11 @@ UInt32 cWorld::SpawnMob(double a_PosX, double a_PosY, double a_PosZ, eMonsterTyp
}
Monster->SetPosition(a_PosX, a_PosY, a_PosZ);
+ if (a_Baby)
+ {
+ Monster->SetAge(-1);
+ }
+
return SpawnMobFinalize(Monster);
}
diff --git a/src/World.h b/src/World.h
index aeab7bfa5..ab2b197c5 100644
--- a/src/World.h
+++ b/src/World.h
@@ -484,6 +484,7 @@ public:
BLOCKTYPE GetBlock (const Vector3i & a_Pos) { return GetBlock( a_Pos.x, a_Pos.y, a_Pos.z); }
NIBBLETYPE GetBlockMeta(const Vector3i & a_Pos) { return GetBlockMeta( a_Pos.x, a_Pos.y, a_Pos.z); }
void SetBlockMeta(const Vector3i & a_Pos, NIBBLETYPE a_MetaData) { SetBlockMeta( a_Pos.x, a_Pos.y, a_Pos.z, a_MetaData); }
+ NIBBLETYPE GetBlockBlockLight(const Vector3i & a_Pos) { return GetBlockBlockLight( a_Pos.x, a_Pos.y, a_Pos.z); }
// tolua_end
/** Writes the block area into the specified coords.
@@ -842,7 +843,7 @@ public:
bool IsBlockDirectlyWatered(int a_BlockX, int a_BlockY, int a_BlockZ); // tolua_export
/** Spawns a mob of the specified type. Returns the mob's UniqueID if recognized and spawned, cEntity::INVALID_ID otherwise */
- virtual UInt32 SpawnMob(double a_PosX, double a_PosY, double a_PosZ, eMonsterType a_MonsterType) override; // tolua_export
+ virtual UInt32 SpawnMob(double a_PosX, double a_PosY, double a_PosZ, eMonsterType a_MonsterType, bool a_Baby = false) override; // tolua_export
UInt32 SpawnMobFinalize(cMonster * a_Monster);
diff --git a/src/WorldStorage/NBTChunkSerializer.cpp b/src/WorldStorage/NBTChunkSerializer.cpp
index 234c60d62..cfbbcd0b4 100644
--- a/src/WorldStorage/NBTChunkSerializer.cpp
+++ b/src/WorldStorage/NBTChunkSerializer.cpp
@@ -528,113 +528,118 @@ void cNBTChunkSerializer::AddMonsterEntity(cMonster * a_Monster)
{
case mtBat:
{
- m_Writer.AddByte("BatFlags", ((const cBat *)a_Monster)->IsHanging());
+ m_Writer.AddByte("BatFlags", reinterpret_cast<const cBat *>(a_Monster)->IsHanging());
break;
}
case mtCreeper:
{
- m_Writer.AddByte("powered", ((const cCreeper *)a_Monster)->IsCharged());
- m_Writer.AddByte("ignited", ((const cCreeper *)a_Monster)->IsBlowing());
+ const cCreeper *Creeper = reinterpret_cast<const cCreeper *>(a_Monster);
+ m_Writer.AddByte("powered", Creeper->IsCharged());
+ m_Writer.AddByte("ignited", Creeper->IsBlowing());
break;
}
case mtEnderman:
{
- m_Writer.AddShort("carried", (Int16)((const cEnderman *)a_Monster)->GetCarriedBlock());
- m_Writer.AddShort("carriedData", (Int16)((const cEnderman *)a_Monster)->GetCarriedMeta());
+ const cEnderman *Enderman = reinterpret_cast<const cEnderman *>(a_Monster);
+ m_Writer.AddShort("carried", (Int16) Enderman->GetCarriedBlock());
+ m_Writer.AddShort("carriedData", (Int16) Enderman->GetCarriedMeta());
break;
}
case mtHorse:
{
- const cHorse & Horse = *((const cHorse *)a_Monster);
- m_Writer.AddByte("ChestedHorse", Horse.IsChested());
- m_Writer.AddByte("EatingHaystack", Horse.IsEating());
- m_Writer.AddByte("Tame", Horse.IsTame());
- m_Writer.AddInt ("Type", Horse.GetHorseType());
- m_Writer.AddInt ("Color", Horse.GetHorseColor());
- m_Writer.AddInt ("Style", Horse.GetHorseStyle());
- m_Writer.AddInt ("ArmorType", Horse.GetHorseArmour());
- m_Writer.AddByte("Saddle", Horse.IsSaddled());
- m_Writer.AddByte("Age", Horse.GetAge());
+ const cHorse *Horse = reinterpret_cast<const cHorse *>(a_Monster);
+ m_Writer.AddByte("ChestedHorse", Horse->IsChested());
+ m_Writer.AddByte("EatingHaystack", Horse->IsEating());
+ m_Writer.AddByte("Tame", Horse->IsTame());
+ m_Writer.AddInt ("Type", Horse->GetHorseType());
+ m_Writer.AddInt ("Color", Horse->GetHorseColor());
+ m_Writer.AddInt ("Style", Horse->GetHorseStyle());
+ m_Writer.AddInt ("ArmorType", Horse->GetHorseArmour());
+ m_Writer.AddByte("Saddle", Horse->IsSaddled());
+ m_Writer.AddByte("Age", Horse->GetAge());
break;
}
case mtMagmaCube:
{
- m_Writer.AddInt("Size", ((const cMagmaCube *)a_Monster)->GetSize());
+ m_Writer.AddInt("Size", reinterpret_cast<const cMagmaCube *>(a_Monster)->GetSize());
break;
}
case mtSheep:
{
- m_Writer.AddByte("Sheared", ((const cSheep *)a_Monster)->IsSheared());
- m_Writer.AddByte("Color", ((const cSheep *)a_Monster)->GetFurColor());
- m_Writer.AddByte("Age", ((const cSheep *)a_Monster)->GetAge());
+ const cSheep *Sheep = reinterpret_cast<const cSheep *>(a_Monster);
+ m_Writer.AddByte("Sheared", Sheep->IsSheared());
+ m_Writer.AddByte("Color", Sheep->GetFurColor());
+ m_Writer.AddByte("Age", Sheep->GetAge());
break;
}
case mtSlime:
{
- m_Writer.AddInt("Size", ((const cSlime *)a_Monster)->GetSize());
+ m_Writer.AddInt("Size", reinterpret_cast<const cSlime *>(a_Monster)->GetSize());
break;
}
case mtSkeleton:
{
- m_Writer.AddByte("SkeletonType", (((const cSkeleton *)a_Monster)->IsWither() ? 1 : 0));
+ m_Writer.AddByte("SkeletonType", (reinterpret_cast<const cSkeleton *>(a_Monster)->IsWither() ? 1 : 0));
break;
}
case mtVillager:
{
- m_Writer.AddInt("Profession", ((const cVillager *)a_Monster)->GetVilType());
- m_Writer.AddByte("Age", ((const cVillager *)a_Monster)->GetAge());
+ const cVillager *Villager = reinterpret_cast<const cVillager *>(a_Monster);
+ m_Writer.AddInt("Profession", Villager->GetVilType());
+ m_Writer.AddByte("Age", Villager->GetAge());
break;
}
case mtWither:
{
- m_Writer.AddInt("Invul", ((const cWither *)a_Monster)->GetWitherInvulnerableTicks());
+ m_Writer.AddInt("Invul", reinterpret_cast<const cWither *>(a_Monster)->GetWitherInvulnerableTicks());
break;
}
case mtWolf:
{
- const cWolf & Wolf = *((cWolf *)a_Monster);
- if (!Wolf.GetOwnerName().empty())
+ const cWolf *Wolf = reinterpret_cast<const cWolf *>(a_Monster);
+ if (!Wolf->GetOwnerName().empty())
{
- m_Writer.AddString("Owner", Wolf.GetOwnerName());
+ m_Writer.AddString("Owner", Wolf->GetOwnerName());
}
- if (!Wolf.GetOwnerUUID().empty())
+ if (!Wolf->GetOwnerUUID().empty())
{
- m_Writer.AddString("OwnerUUID", Wolf.GetOwnerUUID());
+ m_Writer.AddString("OwnerUUID", Wolf->GetOwnerUUID());
}
- m_Writer.AddByte("Sitting", Wolf.IsSitting() ? 1 : 0);
- m_Writer.AddByte("Angry", Wolf.IsAngry() ? 1 : 0);
- m_Writer.AddByte("CollarColor", (unsigned char)Wolf.GetCollarColor());
- m_Writer.AddByte("Age", Wolf.GetAge());
+ m_Writer.AddByte("Sitting", Wolf->IsSitting() ? 1 : 0);
+ m_Writer.AddByte("Angry", Wolf->IsAngry() ? 1 : 0);
+ m_Writer.AddByte("CollarColor", (unsigned char) Wolf->GetCollarColor());
+ m_Writer.AddByte("Age", Wolf->GetAge());
break;
}
case mtZombie:
{
- m_Writer.AddByte("IsVillager", (((const cZombie *)a_Monster)->IsVillagerZombie() ? 1 : 0));
- m_Writer.AddByte("IsConverting", (((const cZombie *)a_Monster)->IsConverting() ? 1 : 0));
- m_Writer.AddByte("Age", (((const cZombie *)a_Monster)->GetAge()));
+ const cZombie *Zombie = reinterpret_cast<const cZombie *>(a_Monster);
+ m_Writer.AddByte("IsVillager", Zombie->IsVillagerZombie() ? 1 : 0);
+ m_Writer.AddByte("IsConverting", Zombie->IsConverting() ? 1 : 0);
+ m_Writer.AddByte("Age", Zombie->GetAge());
break;
}
case mtZombiePigman:
{
- m_Writer.AddByte("Age", (((const cZombiePigman *)a_Monster)->GetAge()));
+ m_Writer.AddByte("Age", reinterpret_cast<const cZombiePigman *>(a_Monster)->GetAge());
break;
}
case mtOcelot:
{
- const cOcelot & Ocelot = *((cOcelot *)a_Monster);
- m_Writer.AddByte("Age", Ocelot.GetAge());
+ m_Writer.AddByte("Age", reinterpret_cast<const cOcelot *>(a_Monster)->GetAge());
break;
}
case mtPig:
{
- const cPig & Pig = *((cPig *)a_Monster);
- m_Writer.AddByte("Age", Pig.GetAge());
+ m_Writer.AddByte("Age", reinterpret_cast<const cPig *>(a_Monster)->GetAge());
break;
}
case mtRabbit:
{
- const cRabbit & Rabbit = *((cRabbit *)a_Monster);
- m_Writer.AddByte("Age", Rabbit.GetAge());
+ const cRabbit *Rabbit = reinterpret_cast<const cRabbit *>(a_Monster);
+ m_Writer.AddInt("RabbitType", Rabbit->GetRabbitTypeAsNumber());
+ m_Writer.AddInt("MoreCarrotTicks", Rabbit->GetMoreCarrotTicks());
+ m_Writer.AddByte("Age", Rabbit->GetAge());
break;
}
case mtInvalidType:
diff --git a/src/WorldStorage/WSSAnvil.cpp b/src/WorldStorage/WSSAnvil.cpp
index 62918f44e..54071b9df 100755
--- a/src/WorldStorage/WSSAnvil.cpp
+++ b/src/WorldStorage/WSSAnvil.cpp
@@ -2396,7 +2396,18 @@ void cWSSAnvil::LoadPigFromNBT(cEntityList & a_Entities, const cParsedNBT & a_NB
void cWSSAnvil::LoadRabbitFromNBT(cEntityList & a_Entities, const cParsedNBT & a_NBT, int a_TagIdx)
{
- std::unique_ptr<cRabbit> Monster = cpp14::make_unique<cRabbit>();
+ int TypeIdx = a_NBT.FindChildByName(a_TagIdx, "RabbitType");
+ int MoreCarrotTicksIdx = a_NBT.FindChildByName(a_TagIdx, "MoreCarrotTicks");
+
+ if ((TypeIdx < 0) || (MoreCarrotTicksIdx < 0))
+ {
+ return;
+ }
+
+ int Type = a_NBT.GetInt(TypeIdx);
+ int MoreCarrotTicks = a_NBT.GetInt(MoreCarrotTicksIdx);
+
+ std::unique_ptr<cRabbit> Monster = cpp14::make_unique<cRabbit>(static_cast<eRabbitType>(Type), MoreCarrotTicks);
if (!LoadEntityBaseFromNBT(*Monster.get(), a_NBT, a_TagIdx))
{
return;