1
0
Fork 0

BlockEntities: Support cloning self.

This commit is contained in:
Mattes D 2017-06-15 15:32:33 +02:00 committed by Lukas Pioch
parent 49e015b8de
commit 0dd1cd750b
41 changed files with 640 additions and 309 deletions

View File

@ -11,13 +11,14 @@
cBeaconEntity::cBeaconEntity(int a_BlockX, int a_BlockY, int a_BlockZ, cWorld * a_World):
super(E_BLOCK_BEACON, a_BlockX, a_BlockY, a_BlockZ, 1, 1, a_World),
cBeaconEntity::cBeaconEntity(BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta, int a_BlockX, int a_BlockY, int a_BlockZ, cWorld * a_World):
Super(a_BlockType, a_BlockMeta, a_BlockX, a_BlockY, a_BlockZ, 1, 1, a_World),
m_IsActive(false),
m_BeaconLevel(0),
m_PrimaryEffect(cEntityEffect::effNoEffect),
m_SecondaryEffect(cEntityEffect::effNoEffect)
{
ASSERT(a_BlockType == E_BLOCK_BEACON);
UpdateBeacon();
}
@ -268,6 +269,30 @@ void cBeaconEntity::GiveEffects(void)
void cBeaconEntity::CopyFrom(const cBlockEntity & a_Src)
{
Super::CopyFrom(a_Src);
auto & src = reinterpret_cast<const cBeaconEntity &>(a_Src);
m_BeaconLevel = src.m_BeaconLevel;
m_Contents.CopyFrom(src.m_Contents);
m_IsActive = src.m_IsActive;
m_PrimaryEffect = src.m_PrimaryEffect;
m_SecondaryEffect = src.m_SecondaryEffect;
}
void cBeaconEntity::SendTo(cClientHandle & a_Client)
{
a_Client.SendUpdateBlockEntity(*this);
}
bool cBeaconEntity::Tick(std::chrono::milliseconds a_Dt, cChunk & a_Chunk)
{
// Update the beacon every 4 seconds
@ -306,12 +331,3 @@ bool cBeaconEntity::UsedBy(cPlayer * a_Player)
void cBeaconEntity::SendTo(cClientHandle & a_Client)
{
a_Client.SendUpdateBlockEntity(*this);
}

View File

@ -19,16 +19,17 @@
class cBeaconEntity :
public cBlockEntityWithItems
{
typedef cBlockEntityWithItems super;
typedef cBlockEntityWithItems Super;
public:
// tolua_end
BLOCKENTITY_PROTODEF(cBeaconEntity)
cBeaconEntity(int a_BlockX, int a_BlockY, int a_BlockZ, cWorld * a_World);
cBeaconEntity(BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta, int a_BlockX, int a_BlockY, int a_BlockZ, cWorld * a_World);
// cBlockEntity overrides:
virtual void CopyFrom(const cBlockEntity & a_Src) override;
virtual void SendTo(cClientHandle & a_Client) override;
virtual bool Tick(std::chrono::milliseconds a_Dt, cChunk & a_Chunk) override;
virtual bool UsedBy(cPlayer * a_Player) override;

View File

@ -29,24 +29,24 @@ cBlockEntity * cBlockEntity::CreateByBlockType(BLOCKTYPE a_BlockType, NIBBLETYPE
{
switch (a_BlockType)
{
case E_BLOCK_BEACON: return new cBeaconEntity (a_BlockX, a_BlockY, a_BlockZ, a_World);
case E_BLOCK_CHEST: return new cChestEntity (a_BlockX, a_BlockY, a_BlockZ, a_World, a_BlockType);
case E_BLOCK_COMMAND_BLOCK: return new cCommandBlockEntity(a_BlockX, a_BlockY, a_BlockZ, a_World);
case E_BLOCK_DISPENSER: return new cDispenserEntity (a_BlockX, a_BlockY, a_BlockZ, a_World);
case E_BLOCK_DROPPER: return new cDropperEntity (a_BlockX, a_BlockY, a_BlockZ, a_World);
case E_BLOCK_ENDER_CHEST: return new cEnderChestEntity (a_BlockX, a_BlockY, a_BlockZ, a_World);
case E_BLOCK_FLOWER_POT: return new cFlowerPotEntity (a_BlockX, a_BlockY, a_BlockZ, a_World);
case E_BLOCK_FURNACE: return new cFurnaceEntity (a_BlockX, a_BlockY, a_BlockZ, a_BlockType, a_BlockMeta, a_World);
case E_BLOCK_BREWING_STAND: return new cBrewingstandEntity(a_BlockX, a_BlockY, a_BlockZ, a_BlockType, a_BlockMeta, a_World);
case E_BLOCK_HEAD: return new cMobHeadEntity (a_BlockX, a_BlockY, a_BlockZ, a_World);
case E_BLOCK_HOPPER: return new cHopperEntity (a_BlockX, a_BlockY, a_BlockZ, a_World);
case E_BLOCK_MOB_SPAWNER: return new cMobSpawnerEntity (a_BlockX, a_BlockY, a_BlockZ, a_World);
case E_BLOCK_JUKEBOX: return new cJukeboxEntity (a_BlockX, a_BlockY, a_BlockZ, a_World);
case E_BLOCK_LIT_FURNACE: return new cFurnaceEntity (a_BlockX, a_BlockY, a_BlockZ, a_BlockType, a_BlockMeta, a_World);
case E_BLOCK_SIGN_POST: return new cSignEntity (a_BlockType, a_BlockX, a_BlockY, a_BlockZ, a_World);
case E_BLOCK_TRAPPED_CHEST: return new cChestEntity (a_BlockX, a_BlockY, a_BlockZ, a_World, a_BlockType);
case E_BLOCK_WALLSIGN: return new cSignEntity (a_BlockType, a_BlockX, a_BlockY, a_BlockZ, a_World);
case E_BLOCK_NOTE_BLOCK: return new cNoteEntity (a_BlockX, a_BlockY, a_BlockZ, a_World);
case E_BLOCK_BEACON: return new cBeaconEntity (a_BlockType, a_BlockMeta, a_BlockX, a_BlockY, a_BlockZ, a_World);
case E_BLOCK_CHEST: return new cChestEntity (a_BlockType, a_BlockMeta, a_BlockX, a_BlockY, a_BlockZ, a_World);
case E_BLOCK_COMMAND_BLOCK: return new cCommandBlockEntity(a_BlockType, a_BlockMeta, a_BlockX, a_BlockY, a_BlockZ, a_World);
case E_BLOCK_DISPENSER: return new cDispenserEntity (a_BlockType, a_BlockMeta, a_BlockX, a_BlockY, a_BlockZ, a_World);
case E_BLOCK_DROPPER: return new cDropperEntity (a_BlockType, a_BlockMeta, a_BlockX, a_BlockY, a_BlockZ, a_World);
case E_BLOCK_ENDER_CHEST: return new cEnderChestEntity (a_BlockType, a_BlockMeta, a_BlockX, a_BlockY, a_BlockZ, a_World);
case E_BLOCK_FLOWER_POT: return new cFlowerPotEntity (a_BlockType, a_BlockMeta, a_BlockX, a_BlockY, a_BlockZ, a_World);
case E_BLOCK_FURNACE: return new cFurnaceEntity (a_BlockType, a_BlockMeta, a_BlockX, a_BlockY, a_BlockZ, a_World);
case E_BLOCK_BREWING_STAND: return new cBrewingstandEntity(a_BlockType, a_BlockMeta, a_BlockX, a_BlockY, a_BlockZ, a_World);
case E_BLOCK_HEAD: return new cMobHeadEntity (a_BlockType, a_BlockMeta, a_BlockX, a_BlockY, a_BlockZ, a_World);
case E_BLOCK_HOPPER: return new cHopperEntity (a_BlockType, a_BlockMeta, a_BlockX, a_BlockY, a_BlockZ, a_World);
case E_BLOCK_MOB_SPAWNER: return new cMobSpawnerEntity (a_BlockType, a_BlockMeta, a_BlockX, a_BlockY, a_BlockZ, a_World);
case E_BLOCK_JUKEBOX: return new cJukeboxEntity (a_BlockType, a_BlockMeta, a_BlockX, a_BlockY, a_BlockZ, a_World);
case E_BLOCK_LIT_FURNACE: return new cFurnaceEntity (a_BlockType, a_BlockMeta, a_BlockX, a_BlockY, a_BlockZ, a_World);
case E_BLOCK_SIGN_POST: return new cSignEntity (a_BlockType, a_BlockMeta, a_BlockX, a_BlockY, a_BlockZ, a_World);
case E_BLOCK_TRAPPED_CHEST: return new cChestEntity (a_BlockType, a_BlockMeta, a_BlockX, a_BlockY, a_BlockZ, a_World);
case E_BLOCK_WALLSIGN: return new cSignEntity (a_BlockType, a_BlockMeta, a_BlockX, a_BlockY, a_BlockZ, a_World);
case E_BLOCK_NOTE_BLOCK: return new cNoteEntity (a_BlockType, a_BlockMeta, a_BlockX, a_BlockY, a_BlockZ, a_World);
}
LOGD("%s: Requesting creation of an unknown block entity - block type %d (%s)",
__FUNCTION__, a_BlockType, ItemTypeToString(a_BlockType).c_str()
@ -58,3 +58,25 @@ cBlockEntity * cBlockEntity::CreateByBlockType(BLOCKTYPE a_BlockType, NIBBLETYPE
cBlockEntity * cBlockEntity::Clone(int a_BlockX, int a_BlockY, int a_BlockZ)
{
auto res = std::unique_ptr<cBlockEntity>(CreateByBlockType(m_BlockType, m_BlockMeta, a_BlockX, a_BlockY, a_BlockZ, nullptr));
res->CopyFrom(*this);
return res.release();
}
void cBlockEntity::CopyFrom(const cBlockEntity & a_Src)
{
// Nothing to copy, but check that we're copying the right entity:
ASSERT(m_BlockType == a_Src.m_BlockType);
ASSERT(m_BlockMeta == a_Src.m_BlockMeta);
}

View File

@ -9,7 +9,7 @@
#define BLOCKENTITY_PROTODEF(classname) \
virtual bool IsA(const char * a_ClassName) const override \
{ \
return ((a_ClassName != nullptr) && ((strcmp(a_ClassName, #classname) == 0) || super::IsA(a_ClassName))); \
return ((a_ClassName != nullptr) && ((strcmp(a_ClassName, #classname) == 0) || Super::IsA(a_ClassName))); \
} \
virtual const char * GetClass(void) const override \
{ \
@ -21,7 +21,7 @@
} \
virtual const char * GetParentClass(void) const override \
{ \
return super::GetClass(); \
return Super::GetClass(); \
}
@ -40,13 +40,14 @@ class cWorld;
class cBlockEntity
{
protected:
cBlockEntity(BLOCKTYPE a_BlockType, int a_BlockX, int a_BlockY, int a_BlockZ, cWorld * a_World) :
cBlockEntity(BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta, int a_BlockX, int a_BlockY, int a_BlockZ, cWorld * a_World) :
m_PosX(a_BlockX),
m_PosY(a_BlockY),
m_PosZ(a_BlockZ),
m_RelX(a_BlockX - cChunkDef::Width * FAST_FLOOR_DIV(a_BlockX, cChunkDef::Width)),
m_RelZ(a_BlockZ - cChunkDef::Width * FAST_FLOOR_DIV(a_BlockZ, cChunkDef::Width)),
m_BlockType(a_BlockType),
m_BlockMeta(a_BlockMeta),
m_World(a_World)
{
}
@ -68,6 +69,15 @@ public:
Returns nullptr for unknown block types. */
static cBlockEntity * CreateByBlockType(BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta, int a_BlockX, int a_BlockY, int a_BlockZ, cWorld * a_World = nullptr);
/** Makes an exact copy of this block entity, except for its m_World (set to nullptr), and at a new position.
Uses CopyFrom() to copy the properties. */
cBlockEntity * Clone(int a_BlockX, int a_BlockY, int a_BlockZ);
/** Copies all properties of a_Src into this entity, except for its m_World and location.
Each non-abstract descendant should override to copy its specific properties, and call
Super::CopyFrom(a_Src) to copy the common ones. */
virtual void CopyFrom(const cBlockEntity & a_Src);
static const char * GetClassStatic(void) // Needed for ManualBindings's ForEach templates
{
return "cBlockEntity";
@ -124,8 +134,14 @@ protected:
/** Position relative to the chunk, used to speed up ticking */
int m_RelX, m_RelZ;
/** The blocktype representing this particular instance in the world.
Mainly used for multi-block-type entities, such as furnaces / lit furnaces. */
BLOCKTYPE m_BlockType;
/** The block meta representing this particular instance in the world
Mainly used for directional entities, such as dispensers. */
NIBBLETYPE m_BlockMeta;
cWorld * m_World;
} ; // tolua_export

View File

@ -0,0 +1,72 @@
// BlockEntityWithItems.cpp
// Implements the cBlockEntityWithItems class representing a common ancestor for all block entities that have an ItemGrid
#include "Globals.h"
#include "BlockEntityWithItems.h"
cBlockEntityWithItems::cBlockEntityWithItems(
BLOCKTYPE a_BlockType,
NIBBLETYPE a_BlockMeta,
int a_BlockX, int a_BlockY, int a_BlockZ,
int a_ItemGridWidth, int a_ItemGridHeight,
cWorld * a_World
):
Super(a_BlockType, a_BlockMeta, a_BlockX, a_BlockY, a_BlockZ, a_World),
cBlockEntityWindowOwner(this),
m_Contents(a_ItemGridWidth, a_ItemGridHeight)
{
m_Contents.AddListener(*this);
}
void cBlockEntityWithItems::Destroy(void)
{
// Drop the contents as pickups:
ASSERT(m_World != nullptr);
cItems Pickups;
m_Contents.CopyToItems(Pickups);
m_Contents.Clear();
m_World->SpawnItemPickups(Pickups, m_PosX + 0.5, m_PosY + 0.5, m_PosZ + 0.5); // Spawn in centre of block
}
void cBlockEntityWithItems::CopyFrom(const cBlockEntity & a_Src)
{
Super::CopyFrom(a_Src);
auto & src = reinterpret_cast<const cBlockEntityWithItems &>(a_Src);
m_Contents.CopyFrom(src.m_Contents);
}
void cBlockEntityWithItems::OnSlotChanged(cItemGrid * a_Grid, int a_SlotNum)
{
UNUSED(a_SlotNum);
ASSERT(a_Grid == &m_Contents);
if (m_World != nullptr)
{
if (GetWindow() != nullptr)
{
GetWindow()->BroadcastWholeWindow();
}
m_World->MarkChunkDirty(GetChunkX(), GetChunkZ());
}
}

View File

@ -26,35 +26,25 @@ class cBlockEntityWithItems :
// tolua_begin
public cBlockEntityWindowOwner
{
typedef cBlockEntity super;
typedef cBlockEntity Super;
public:
// tolua_end
BLOCKENTITY_PROTODEF(cBlockEntityWithItems)
cBlockEntityWithItems(
BLOCKTYPE a_BlockType, // Type of the block that the entity represents
NIBBLETYPE a_BlockMeta, // Meta of the block that the entity represents
int a_BlockX, int a_BlockY, int a_BlockZ, // Position of the block entity
int a_ItemGridWidth, int a_ItemGridHeight, // Dimensions of the ItemGrid
cWorld * a_World // Optional world to assign to the entity
) :
super(a_BlockType, a_BlockX, a_BlockY, a_BlockZ, a_World),
cBlockEntityWindowOwner(this),
m_Contents(a_ItemGridWidth, a_ItemGridHeight)
{
m_Contents.AddListener(*this);
}
);
virtual void Destroy(void) override
{
// Drop the contents as pickups:
ASSERT(m_World != nullptr);
cItems Pickups;
m_Contents.CopyToItems(Pickups);
m_Contents.Clear();
m_World->SpawnItemPickups(Pickups, m_PosX + 0.5, m_PosY + 0.5, m_PosZ + 0.5); // Spawn in centre of block
}
// cBlockEntity overrides:
virtual void Destroy(void) override;
virtual void CopyFrom(const cBlockEntity & a_Src) override;
// tolua_begin
@ -76,20 +66,7 @@ protected:
cItemGrid m_Contents;
// cItemGrid::cListener overrides:
virtual void OnSlotChanged(cItemGrid * a_Grid, int a_SlotNum) override
{
UNUSED(a_SlotNum);
ASSERT(a_Grid == &m_Contents);
if (m_World != nullptr)
{
if (GetWindow() != nullptr)
{
GetWindow()->BroadcastWholeWindow();
}
m_World->MarkChunkDirty(GetChunkX(), GetChunkZ());
}
}
virtual void OnSlotChanged(cItemGrid * a_Grid, int a_SlotNum) override;
} ; // tolua_export

View File

@ -19,19 +19,14 @@
cBrewingstandEntity::cBrewingstandEntity(int a_BlockX, int a_BlockY, int a_BlockZ, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta, cWorld * a_World) :
super(a_BlockType, a_BlockX, a_BlockY, a_BlockZ, ContentsWidth, ContentsHeight, a_World),
m_BlockMeta(a_BlockMeta),
cBrewingstandEntity::cBrewingstandEntity(BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta, int a_BlockX, int a_BlockY, int a_BlockZ, cWorld * a_World):
Super(a_BlockType, a_BlockMeta, a_BlockX, a_BlockY, a_BlockZ, ContentsWidth, ContentsHeight, a_World),
m_IsDestroyed(false),
m_IsBrewing(false),
m_TimeBrewed(0),
m_RemainingFuel(0)
{
m_Contents.AddListener(*this);
for (int i = 0; i < 3; i++)
{
m_Results[i] = cItem{};
}
}
@ -52,33 +47,41 @@ cBrewingstandEntity::~cBrewingstandEntity()
bool cBrewingstandEntity::UsedBy(cPlayer * a_Player)
void cBrewingstandEntity::Destroy()
{
cWindow * Window = GetWindow();
if (Window == nullptr)
{
OpenWindow(new cBrewingstandWindow(m_PosX, m_PosY, m_PosZ, this));
Window = GetWindow();
}
m_IsDestroyed = true;
Super::Destroy();
}
if (Window != nullptr)
{
if (a_Player->GetWindow() != Window)
{
a_Player->OpenWindow(*Window);
}
}
if (m_IsBrewing)
void cBrewingstandEntity::CopyFrom(const cBlockEntity & a_Src)
{
Super::CopyFrom(a_Src);
auto & src = reinterpret_cast<const cBrewingstandEntity &>(a_Src);
m_IsBrewing = src.m_IsBrewing;
for (size_t i = 0; i < ARRAYCOUNT(m_CurrentBrewingRecipes); ++i)
{
BroadcastProgress(0, m_NeedBrewingTime - m_TimeBrewed);
m_CurrentBrewingRecipes[i] = src.m_CurrentBrewingRecipes[i];
}
else
for (size_t i = 0; i < ARRAYCOUNT(m_Results); ++i)
{
BroadcastProgress(0, 0);
m_Results[i] = src.m_Results[i];
}
BroadcastProgress(1, m_RemainingFuel);
return true;
m_TimeBrewed = src.m_TimeBrewed;
m_RemainingFuel = src.m_RemainingFuel;
}
void cBrewingstandEntity::SendTo(cClientHandle & a_Client)
{
// Nothing needs to be sent
UNUSED(a_Client);
}
@ -159,10 +162,33 @@ bool cBrewingstandEntity::Tick(std::chrono::milliseconds a_Dt, cChunk & a_Chunk)
void cBrewingstandEntity::SendTo(cClientHandle & a_Client)
bool cBrewingstandEntity::UsedBy(cPlayer * a_Player)
{
// Nothing needs to be sent
UNUSED(a_Client);
cWindow * Window = GetWindow();
if (Window == nullptr)
{
OpenWindow(new cBrewingstandWindow(m_PosX, m_PosY, m_PosZ, this));
Window = GetWindow();
}
if (Window != nullptr)
{
if (a_Player->GetWindow() != Window)
{
a_Player->OpenWindow(*Window);
}
}
if (m_IsBrewing)
{
BroadcastProgress(0, m_NeedBrewingTime - m_TimeBrewed);
}
else
{
BroadcastProgress(0, 0);
}
BroadcastProgress(1, m_RemainingFuel);
return true;
}
@ -185,7 +211,7 @@ void cBrewingstandEntity::BroadcastProgress(short a_ProgressbarID, short a_Value
void cBrewingstandEntity::OnSlotChanged(cItemGrid * a_ItemGrid, int a_SlotNum)
{
super::OnSlotChanged(a_ItemGrid, a_SlotNum);
Super::OnSlotChanged(a_ItemGrid, a_SlotNum);
if (m_IsDestroyed)
{

View File

@ -18,7 +18,7 @@ class cClientHandle;
class cBrewingstandEntity :
public cBlockEntityWithItems
{
typedef cBlockEntityWithItems super;
typedef cBlockEntityWithItems Super;
public:
enum
@ -38,19 +38,16 @@ public:
BLOCKENTITY_PROTODEF(cBrewingstandEntity)
/** Constructor used for normal operation */
cBrewingstandEntity(int a_BlockX, int a_BlockY, int a_BlockZ, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta, cWorld * a_World);
cBrewingstandEntity(BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta, int a_BlockX, int a_BlockY, int a_BlockZ, cWorld * a_World);
virtual ~cBrewingstandEntity() override;
// cBlockEntity overrides:
virtual void Destroy() override;
virtual void CopyFrom(const cBlockEntity & a_Src) override;
virtual void SendTo(cClientHandle & a_Client) override;
virtual bool Tick(std::chrono::milliseconds a_Dt, cChunk & a_Chunk) override;
virtual bool UsedBy(cPlayer * a_Player) override;
virtual void Destroy() override
{
m_IsDestroyed = true;
super::Destroy();
}
// tolua_begin
@ -109,10 +106,9 @@ public:
/** Gets the recipes. Will be called if the brewing stand gets loaded from the world. */
void LoadRecipes(void);
protected:
/** Block meta of the block currently represented by this entity */
NIBBLETYPE m_BlockMeta;
protected:
/** Set to true when the brewing stand entity has been destroyed to prevent the block being set again */
bool m_IsDestroyed;
@ -127,7 +123,7 @@ protected:
const cBrewingRecipes::cRecipe * m_CurrentBrewingRecipes[3] = {};
/** Result items for the bottle inputs */
cItem m_Results[3] = {};
cItem m_Results[3];
/** Amount of ticks that the current item has been brewed */
short m_TimeBrewed;

View File

@ -5,6 +5,7 @@ include_directories ("${PROJECT_SOURCE_DIR}/../")
SET (SRCS
BeaconEntity.cpp
BlockEntity.cpp
BlockEntityWithItems.cpp
BrewingstandEntity.cpp
ChestEntity.cpp
CommandBlockEntity.cpp

View File

@ -11,8 +11,8 @@
cChestEntity::cChestEntity(int a_BlockX, int a_BlockY, int a_BlockZ, cWorld * a_World, BLOCKTYPE a_Type) :
super(a_Type, a_BlockX, a_BlockY, a_BlockZ, ContentsWidth, ContentsHeight, a_World),
cChestEntity::cChestEntity(BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta, int a_BlockX, int a_BlockY, int a_BlockZ, cWorld * a_World):
Super(a_BlockType, a_BlockMeta, a_BlockX, a_BlockY, a_BlockZ, ContentsWidth, ContentsHeight, a_World),
m_NumActivePlayers(0),
m_Neighbour(nullptr)
{
@ -46,6 +46,21 @@ cChestEntity::~cChestEntity()
void cChestEntity::CopyFrom(const cBlockEntity & a_Src)
{
Super::CopyFrom(a_Src);
auto & src = reinterpret_cast<const cChestEntity &>(a_Src);
m_Contents.CopyFrom(src.m_Contents);
// Reset the neighbor and player count, there's no sense in copying these:
m_Neighbour = nullptr;
m_NumActivePlayers = 0;
}
void cChestEntity::SendTo(cClientHandle & a_Client)
{
// Send a dummy "number of players with chest open" packet to make the chest visible:

View File

@ -17,7 +17,7 @@ class cClientHandle;
class cChestEntity :
public cBlockEntityWithItems
{
typedef cBlockEntityWithItems super;
typedef cBlockEntityWithItems Super;
public:
enum
@ -31,11 +31,12 @@ public:
BLOCKENTITY_PROTODEF(cChestEntity)
/** Constructor used for normal operation */
cChestEntity(int a_BlockX, int a_BlockY, int a_BlockZ, cWorld * a_World, BLOCKTYPE a_Type);
cChestEntity(BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta, int a_BlockX, int a_BlockY, int a_BlockZ, cWorld * a_World);
virtual ~cChestEntity() override;
// cBlockEntity overrides:
virtual void CopyFrom(const cBlockEntity & a_Src) override;
virtual void SendTo(cClientHandle & a_Client) override;
virtual bool UsedBy(cPlayer * a_Player) override;

View File

@ -17,11 +17,13 @@
cCommandBlockEntity::cCommandBlockEntity(int a_X, int a_Y, int a_Z, cWorld * a_World) :
super(E_BLOCK_COMMAND_BLOCK, a_X, a_Y, a_Z, a_World),
cCommandBlockEntity::cCommandBlockEntity(BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta, int a_BlockX, int a_BlockY, int a_BlockZ, cWorld * a_World):
Super(a_BlockType, a_BlockMeta, a_BlockX, a_BlockY, a_BlockZ, a_World),
m_ShouldExecute(false),
m_Result(0)
{}
{
ASSERT(a_BlockType == E_BLOCK_COMMAND_BLOCK);
}
@ -112,6 +114,20 @@ void cCommandBlockEntity::Activate(void)
void cCommandBlockEntity::CopyFrom(const cBlockEntity & a_Src)
{
Super::CopyFrom(a_Src);
auto & src = reinterpret_cast<const cCommandBlockEntity &>(a_Src);
m_Command = src.m_Command;
m_LastOutput = src.m_LastOutput;
m_Result = src.m_Result;
m_ShouldExecute = src.m_ShouldExecute;
}
bool cCommandBlockEntity::Tick(std::chrono::milliseconds a_Dt, cChunk & a_Chunk)
{
UNUSED(a_Dt);

View File

@ -20,7 +20,7 @@
class cCommandBlockEntity :
public cBlockEntity
{
typedef cBlockEntity super;
typedef cBlockEntity Super;
public:
@ -29,8 +29,10 @@ public:
BLOCKENTITY_PROTODEF(cCommandBlockEntity)
/** Creates a new empty command block entity */
cCommandBlockEntity(int a_X, int a_Y, int a_Z, cWorld * a_World);
cCommandBlockEntity(BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta, int a_BlockX, int a_BlockY, int a_BlockZ, cWorld * a_World);
// cBlockEntity overrides:
virtual void CopyFrom(const cBlockEntity & a_Src) override;
virtual bool Tick(std::chrono::milliseconds a_Dt, cChunk & a_Chunk) override;
virtual void SendTo(cClientHandle & a_Client) override;
virtual bool UsedBy(cPlayer * a_Player) override;

View File

@ -13,9 +13,10 @@
cDispenserEntity::cDispenserEntity(int a_BlockX, int a_BlockY, int a_BlockZ, cWorld * a_World) :
super(E_BLOCK_DISPENSER, a_BlockX, a_BlockY, a_BlockZ, a_World)
cDispenserEntity::cDispenserEntity(BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta, int a_BlockX, int a_BlockY, int a_BlockZ, cWorld * a_World):
Super(a_BlockType, a_BlockMeta, a_BlockX, a_BlockY, a_BlockZ, a_World)
{
ASSERT(a_BlockType == E_BLOCK_DISPENSER);
}
@ -309,9 +310,9 @@ Vector3d cDispenserEntity::GetShootVector(NIBBLETYPE a_Meta)
bool cDispenserEntity::ScoopUpLiquid(int a_SlotNum, short a_BucketItemType)
bool cDispenserEntity::ScoopUpLiquid(int a_SlotNum, short a_ResultingBucketItemType)
{
cItem LiquidBucket(a_BucketItemType, 1);
cItem LiquidBucket(a_ResultingBucketItemType, 1);
if (m_Contents.GetSlot(a_SlotNum).m_ItemCount == 1)
{
// Special case: replacing one empty bucket with one full bucket

View File

@ -11,7 +11,7 @@
class cDispenserEntity :
public cDropSpenserEntity
{
typedef cDropSpenserEntity super;
typedef cDropSpenserEntity Super;
public:
@ -20,7 +20,7 @@ public:
BLOCKENTITY_PROTODEF(cDispenserEntity)
/** Constructor used for normal operation */
cDispenserEntity(int a_BlockX, int a_BlockY, int a_BlockZ, cWorld * a_World);
cDispenserEntity(BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta, int a_BlockX, int a_BlockY, int a_BlockZ, cWorld * a_World);
// tolua_begin
@ -38,7 +38,7 @@ private:
virtual void DropSpenseFromSlot(cChunk & a_Chunk, int a_SlotNum) override;
/** If such a bucket can fit, adds it to m_Contents and returns true */
bool ScoopUpLiquid(int a_SlotNum, short a_BucketItemType);
bool ScoopUpLiquid(int a_SlotNum, short a_ResultingBucketItemType);
/** If the a_BlockInFront can be washed away by liquid and the empty bucket can fit,
does the m_Contents processing and returns true. Returns false otherwise. */

View File

@ -15,8 +15,8 @@
cDropSpenserEntity::cDropSpenserEntity(BLOCKTYPE a_BlockType, int a_BlockX, int a_BlockY, int a_BlockZ, cWorld * a_World) :
super(a_BlockType, a_BlockX, a_BlockY, a_BlockZ, ContentsWidth, ContentsHeight, a_World),
cDropSpenserEntity::cDropSpenserEntity(BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta, int a_BlockX, int a_BlockY, int a_BlockZ, cWorld * a_World):
Super(a_BlockType, a_BlockMeta, a_BlockX, a_BlockY, a_BlockZ, ContentsWidth, ContentsHeight, a_World),
m_ShouldDropSpense(false)
{
}
@ -113,6 +113,18 @@ void cDropSpenserEntity::Activate(void)
void cDropSpenserEntity::CopyFrom(const cBlockEntity & a_Src)
{
Super::CopyFrom(a_Src);
auto & src = reinterpret_cast<const cDropSpenserEntity &>(a_Src);
m_Contents.CopyFrom(src.m_Contents);
m_ShouldDropSpense = src.m_ShouldDropSpense;
}
bool cDropSpenserEntity::Tick(std::chrono::milliseconds a_Dt, cChunk & a_Chunk)
{
UNUSED(a_Dt);

View File

@ -26,7 +26,7 @@ class cClientHandle;
class cDropSpenserEntity :
public cBlockEntityWithItems
{
typedef cBlockEntityWithItems super;
typedef cBlockEntityWithItems Super;
public:
enum
@ -39,10 +39,11 @@ public:
BLOCKENTITY_PROTODEF(cDropSpenserEntity)
cDropSpenserEntity(BLOCKTYPE a_BlockType, int a_BlockX, int a_BlockY, int a_BlockZ, cWorld * a_World);
cDropSpenserEntity(BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta, int a_BlockX, int a_BlockY, int a_BlockZ, cWorld * a_World);
virtual ~cDropSpenserEntity() override;
// cBlockEntity overrides:
virtual void CopyFrom(const cBlockEntity & a_Src);
virtual bool Tick(std::chrono::milliseconds a_Dt, cChunk & a_Chunk) override;
virtual void SendTo(cClientHandle & a_Client) override;
virtual bool UsedBy(cPlayer * a_Player) override;

View File

@ -10,9 +10,10 @@
cDropperEntity::cDropperEntity(int a_BlockX, int a_BlockY, int a_BlockZ, cWorld * a_World) :
super(E_BLOCK_DROPPER, a_BlockX, a_BlockY, a_BlockZ, a_World)
cDropperEntity::cDropperEntity(BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta, int a_BlockX, int a_BlockY, int a_BlockZ, cWorld * a_World):
Super(a_BlockType, a_BlockMeta, a_BlockX, a_BlockY, a_BlockZ, a_World)
{
ASSERT(a_BlockType == E_BLOCK_DROPPER);
}

View File

@ -19,7 +19,7 @@
class cDropperEntity :
public cDropSpenserEntity
{
typedef cDropSpenserEntity super;
typedef cDropSpenserEntity Super;
public:
@ -28,7 +28,7 @@ public:
BLOCKENTITY_PROTODEF(cDropperEntity)
/** Constructor used for normal operation */
cDropperEntity(int a_BlockX, int a_BlockY, int a_BlockZ, cWorld * a_World);
cDropperEntity(BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta, int a_BlockX, int a_BlockY, int a_BlockZ, cWorld * a_World);
protected:
// cDropSpenserEntity overrides:

View File

@ -12,10 +12,11 @@
cEnderChestEntity::cEnderChestEntity(int a_BlockX, int a_BlockY, int a_BlockZ, cWorld * a_World) :
super(E_BLOCK_ENDER_CHEST, a_BlockX, a_BlockY, a_BlockZ, a_World),
cEnderChestEntity::cEnderChestEntity(BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta, int a_BlockX, int a_BlockY, int a_BlockZ, cWorld * a_World):
Super(a_BlockType, a_BlockMeta, a_BlockX, a_BlockY, a_BlockZ, a_World),
cBlockEntityWindowOwner(this)
{
ASSERT(a_BlockType == E_BLOCK_ENDER_CHEST);
}

View File

@ -13,14 +13,14 @@ class cEnderChestEntity :
public cBlockEntity,
public cBlockEntityWindowOwner
{
typedef cBlockEntity super;
typedef cBlockEntity Super;
public:
// tolua_end
BLOCKENTITY_PROTODEF(cEnderChestEntity)
cEnderChestEntity(int a_BlockX, int a_BlockY, int a_BlockZ, cWorld * a_World);
cEnderChestEntity(BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta, int a_BlockX, int a_BlockY, int a_BlockZ, cWorld * a_World);
virtual ~cEnderChestEntity() override;
// cBlockEntity overrides:

View File

@ -13,16 +13,45 @@
cFlowerPotEntity::cFlowerPotEntity(int a_BlockX, int a_BlockY, int a_BlockZ, cWorld * a_World) :
super(E_BLOCK_FLOWER_POT, a_BlockX, a_BlockY, a_BlockZ, a_World)
cFlowerPotEntity::cFlowerPotEntity(BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta, int a_BlockX, int a_BlockY, int a_BlockZ, cWorld * a_World):
Super(a_BlockType, a_BlockMeta, a_BlockX, a_BlockY, a_BlockZ, a_World)
{
ASSERT(a_BlockType == E_BLOCK_FLOWER_POT);
}
void cFlowerPotEntity::Destroy(void)
{
// Drop the contents as pickups:
if (!m_Item.IsEmpty())
{
ASSERT(m_World != nullptr);
cItems Pickups;
Pickups.Add(m_Item);
m_World->SpawnItemPickups(Pickups, m_PosX + 0.5, m_PosY + 0.5, m_PosZ + 0.5);
m_Item.Empty();
}
}
void cFlowerPotEntity::CopyFrom(const cBlockEntity & a_Src)
{
Super::CopyFrom(a_Src);
auto & src = reinterpret_cast<const cFlowerPotEntity &>(a_Src);
m_Item = src.m_Item;
}
// It don't do anything when 'used'
bool cFlowerPotEntity::UsedBy(cPlayer * a_Player)
{
if (IsItemInPot())
@ -56,24 +85,6 @@ void cFlowerPotEntity::SendTo(cClientHandle & a_Client)
void cFlowerPotEntity::Destroy(void)
{
// Drop the contents as pickups:
if (!m_Item.IsEmpty())
{
ASSERT(m_World != nullptr);
cItems Pickups;
Pickups.Add(m_Item);
m_World->SpawnItemPickups(Pickups, m_PosX + 0.5, m_PosY + 0.5, m_PosZ + 0.5);
m_Item.Empty();
}
}
bool cFlowerPotEntity::IsFlower(short m_ItemType, short m_ItemData)
{
switch (m_ItemType)

View File

@ -20,7 +20,7 @@
class cFlowerPotEntity :
public cBlockEntity
{
typedef cBlockEntity super;
typedef cBlockEntity Super;
public:
@ -29,9 +29,8 @@ public:
BLOCKENTITY_PROTODEF(cFlowerPotEntity)
/** Creates a new flowerpot entity at the specified block coords. a_World may be nullptr */
cFlowerPotEntity(int a_BlocX, int a_BlockY, int a_BlockZ, cWorld * a_World);
cFlowerPotEntity(BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta, int a_BlockX, int a_BlockY, int a_BlockZ, cWorld * a_World);
virtual void Destroy(void) override;
// tolua_begin
@ -46,7 +45,9 @@ public:
// tolua_end
/** Called when the player is using the entity; returns true if it was a successful use, return false if it should be treated as a normal block */
// cBlockEntity overrides:
virtual void Destroy(void) override;
virtual void CopyFrom(const cBlockEntity & a_Src) override;
virtual bool UsedBy(cPlayer * a_Player) override;
virtual void SendTo(cClientHandle & a_Client) override;

View File

@ -23,9 +23,8 @@ enum
cFurnaceEntity::cFurnaceEntity(int a_BlockX, int a_BlockY, int a_BlockZ, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta, cWorld * a_World) :
super(a_BlockType, a_BlockX, a_BlockY, a_BlockZ, ContentsWidth, ContentsHeight, a_World),
m_BlockMeta(a_BlockMeta),
cFurnaceEntity::cFurnaceEntity(BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta, int a_BlockX, int a_BlockY, int a_BlockZ, cWorld * a_World):
Super(a_BlockType, a_BlockMeta, a_BlockX, a_BlockY, a_BlockZ, ContentsWidth, ContentsHeight, a_World),
m_CurrentRecipe(nullptr),
m_IsDestroyed(false),
m_IsCooking(a_BlockType == E_BLOCK_LIT_FURNACE),
@ -56,36 +55,40 @@ cFurnaceEntity::~cFurnaceEntity()
bool cFurnaceEntity::UsedBy(cPlayer * a_Player)
void cFurnaceEntity::Destroy()
{
cWindow * Window = GetWindow();
if (Window == nullptr)
{
OpenWindow(new cFurnaceWindow(m_PosX, m_PosY, m_PosZ, this));
Window = GetWindow();
}
if (Window != nullptr)
{
if (a_Player->GetWindow() != Window)
{
a_Player->OpenWindow(*Window);
}
}
UpdateProgressBars(true);
return true;
m_IsDestroyed = true;
Super::Destroy();
}
bool cFurnaceEntity::ContinueCooking(void)
void cFurnaceEntity::CopyFrom(const cBlockEntity & a_Src)
{
UpdateInput();
UpdateFuel();
return m_IsCooking;
Super::CopyFrom(a_Src);
auto & src = reinterpret_cast<const cFurnaceEntity &>(a_Src);
m_Contents.CopyFrom(src.m_Contents);
m_CurrentRecipe = src.m_CurrentRecipe;
m_FuelBurnTime = src.m_FuelBurnTime;
m_IsCooking = src.m_IsCooking;
m_IsDestroyed = src.m_IsDestroyed;
m_IsLoading = src.m_IsLoading;
m_LastInput = src.m_LastInput;
m_NeedCookTime = src.m_NeedCookTime;
m_TimeBurned = src.m_TimeBurned;
m_TimeCooked = src.m_TimeCooked;
}
void cFurnaceEntity::SendTo(cClientHandle & a_Client)
{
// Nothing needs to be sent
UNUSED(a_Client);
}
@ -134,10 +137,36 @@ bool cFurnaceEntity::Tick(std::chrono::milliseconds a_Dt, cChunk & a_Chunk)
void cFurnaceEntity::SendTo(cClientHandle & a_Client)
bool cFurnaceEntity::UsedBy(cPlayer * a_Player)
{
// Nothing needs to be sent
UNUSED(a_Client);
cWindow * Window = GetWindow();
if (Window == nullptr)
{
OpenWindow(new cFurnaceWindow(m_PosX, m_PosY, m_PosZ, this));
Window = GetWindow();
}
if (Window != nullptr)
{
if (a_Player->GetWindow() != Window)
{
a_Player->OpenWindow(*Window);
}
}
UpdateProgressBars(true);
return true;
}
bool cFurnaceEntity::ContinueCooking(void)
{
UpdateInput();
UpdateFuel();
return m_IsCooking;
}
@ -208,7 +237,7 @@ void cFurnaceEntity::BurnNewFuel(void)
void cFurnaceEntity::OnSlotChanged(cItemGrid * a_ItemGrid, int a_SlotNum)
{
super::OnSlotChanged(a_ItemGrid, a_SlotNum);
Super::OnSlotChanged(a_ItemGrid, a_SlotNum);
if (m_IsDestroyed)
{

View File

@ -18,7 +18,7 @@ class cClientHandle;
class cFurnaceEntity :
public cBlockEntityWithItems
{
typedef cBlockEntityWithItems super;
typedef cBlockEntityWithItems Super;
public:
enum
@ -36,19 +36,16 @@ public:
BLOCKENTITY_PROTODEF(cFurnaceEntity)
/** Constructor used for normal operation */
cFurnaceEntity(int a_BlockX, int a_BlockY, int a_BlockZ, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta, cWorld * a_World);
cFurnaceEntity(BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta, int a_BlockX, int a_BlockY, int a_BlockZ, cWorld * a_World);
virtual ~cFurnaceEntity() override;
// cBlockEntity overrides:
virtual void Destroy() override;
virtual void CopyFrom(const cBlockEntity & a_Src) override;
virtual void SendTo(cClientHandle & a_Client) override;
virtual bool Tick(std::chrono::milliseconds a_Dt, cChunk & a_Chunk) override;
virtual bool UsedBy(cPlayer * a_Player) override;
virtual void Destroy() override
{
m_IsDestroyed = true;
super::Destroy();
}
/** Restarts cooking
Used after the furnace is loaded from storage to set up the internal variables so that cooking continues, if it was active
@ -106,10 +103,8 @@ public:
m_IsLoading = a_IsLoading;
}
protected:
/** Block meta of the block currently represented by this entity */
NIBBLETYPE m_BlockMeta;
protected:
/** The recipe for the current input slot */
const cFurnaceRecipe::cRecipe * m_CurrentRecipe;

View File

@ -17,11 +17,12 @@
cHopperEntity::cHopperEntity(int a_BlockX, int a_BlockY, int a_BlockZ, cWorld * a_World) :
super(E_BLOCK_HOPPER, a_BlockX, a_BlockY, a_BlockZ, ContentsWidth, ContentsHeight, a_World),
cHopperEntity::cHopperEntity(BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta, int a_BlockX, int a_BlockY, int a_BlockZ, cWorld * a_World):
Super(a_BlockType, a_BlockMeta, a_BlockX, a_BlockY, a_BlockZ, ContentsWidth, ContentsHeight, a_World),
m_LastMoveItemsInTick(0),
m_LastMoveItemsOutTick(0)
{
ASSERT(a_BlockType == E_BLOCK_HOPPER);
}
@ -52,16 +53,28 @@ bool cHopperEntity::GetOutputBlockPos(NIBBLETYPE a_BlockMeta, int & a_OutputX, i
void cHopperEntity::CopyFrom(const cBlockEntity & a_Src)
{
Super::CopyFrom(a_Src);
auto & src = reinterpret_cast<const cHopperEntity &>(a_Src);
m_LastMoveItemsInTick = src.m_LastMoveItemsInTick;
m_LastMoveItemsOutTick = src.m_LastMoveItemsOutTick;
}
bool cHopperEntity::Tick(std::chrono::milliseconds a_Dt, cChunk & a_Chunk)
{
UNUSED(a_Dt);
Int64 CurrentTick = a_Chunk.GetWorld()->GetWorldAge();
bool res = false;
res = MoveItemsIn (a_Chunk, CurrentTick) || res;
res = MovePickupsIn(a_Chunk, CurrentTick) || res;
res = MoveItemsOut (a_Chunk, CurrentTick) || res;
return res;
bool isDirty = false;
isDirty = MoveItemsIn (a_Chunk, CurrentTick) || isDirty;
isDirty = MovePickupsIn(a_Chunk, CurrentTick) || isDirty;
isDirty = MoveItemsOut (a_Chunk, CurrentTick) || isDirty;
return isDirty;
}

View File

@ -19,7 +19,7 @@
class cHopperEntity :
public cBlockEntityWithItems
{
typedef cBlockEntityWithItems super;
typedef cBlockEntityWithItems Super;
public:
enum
@ -34,7 +34,7 @@ public:
BLOCKENTITY_PROTODEF(cHopperEntity)
/** Constructor used for normal operation */
cHopperEntity(int a_BlockX, int a_BlockY, int a_BlockZ, cWorld * a_World);
cHopperEntity(BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta, int a_BlockX, int a_BlockY, int a_BlockZ, cWorld * a_World);
/** Returns the block coords of the block receiving the output items, based on the meta
Returns false if unattached.
@ -47,6 +47,7 @@ protected:
Int64 m_LastMoveItemsOutTick;
// cBlockEntity overrides:
virtual void CopyFrom(const cBlockEntity & a_Src) override;
virtual bool Tick(std::chrono::milliseconds a_Dt, cChunk & a_Chunk) override;
virtual void SendTo(cClientHandle & a_Client) override;
virtual bool UsedBy(cPlayer * a_Player) override;

View File

@ -10,10 +10,11 @@
cJukeboxEntity::cJukeboxEntity(int a_BlockX, int a_BlockY, int a_BlockZ, cWorld * a_World) :
super(E_BLOCK_JUKEBOX, a_BlockX, a_BlockY, a_BlockZ, a_World),
cJukeboxEntity::cJukeboxEntity(BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta, int a_BlockX, int a_BlockY, int a_BlockZ, cWorld * a_World):
Super(a_BlockType, a_BlockMeta, a_BlockX, a_BlockY, a_BlockZ, a_World),
m_Record(0)
{
ASSERT(a_BlockType == E_BLOCK_JUKEBOX);
}
@ -28,6 +29,17 @@ cJukeboxEntity::~cJukeboxEntity()
void cJukeboxEntity::CopyFrom(const cBlockEntity & a_Src)
{
Super::CopyFrom(a_Src);
auto & src = reinterpret_cast<const cJukeboxEntity &>(a_Src);
m_Record = src.m_Record;
}
bool cJukeboxEntity::UsedBy(cPlayer * a_Player)
{
if (IsPlayingRecord())

View File

@ -12,14 +12,15 @@
class cJukeboxEntity :
public cBlockEntity
{
typedef cBlockEntity super;
typedef cBlockEntity Super;
public:
// tolua_end
BLOCKENTITY_PROTODEF(cJukeboxEntity)
cJukeboxEntity(int a_BlockX, int a_BlockY, int a_BlockZ, cWorld * a_World);
cJukeboxEntity(BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta, int a_BlockX, int a_BlockY, int a_BlockZ, cWorld * a_World);
virtual ~cJukeboxEntity() override;
// tolua_begin
@ -44,6 +45,8 @@ public:
// tolua_end
// cBlockEntity overrides:
virtual void CopyFrom(const cBlockEntity & a_Src) override;
virtual bool UsedBy(cPlayer * a_Player) override;
virtual void SendTo(cClientHandle &) override {}

View File

@ -13,17 +13,33 @@
cMobHeadEntity::cMobHeadEntity(int a_BlockX, int a_BlockY, int a_BlockZ, cWorld * a_World) :
super(E_BLOCK_HEAD, a_BlockX, a_BlockY, a_BlockZ, a_World),
cMobHeadEntity::cMobHeadEntity(BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta, int a_BlockX, int a_BlockY, int a_BlockZ, cWorld * a_World):
Super(a_BlockType, a_BlockMeta, a_BlockX, a_BlockY, a_BlockZ, a_World),
m_Type(SKULL_TYPE_SKELETON),
m_Rotation(SKULL_ROTATION_NORTH)
{
ASSERT(a_BlockType == E_BLOCK_HEAD);
}
void cMobHeadEntity::CopyFrom(const cBlockEntity & a_Src)
{
Super::CopyFrom(a_Src);
auto & src = reinterpret_cast<const cMobHeadEntity &>(a_Src);
m_OwnerName = src.m_OwnerName;
m_OwnerTexture = src.m_OwnerTexture;
m_OwnerTextureSignature = src.m_OwnerTextureSignature;
m_OwnerUUID = src.m_OwnerUUID;
m_Rotation = src.m_Rotation;
m_Type = src.m_Type;
}
bool cMobHeadEntity::UsedBy(cPlayer * a_Player)
{
UNUSED(a_Player);

View File

@ -20,7 +20,7 @@
class cMobHeadEntity :
public cBlockEntity
{
typedef cBlockEntity super;
typedef cBlockEntity Super;
public:
@ -29,7 +29,7 @@ public:
BLOCKENTITY_PROTODEF(cMobHeadEntity)
/** Creates a new mob head entity at the specified block coords. a_World may be nullptr */
cMobHeadEntity(int a_BlockX, int a_BlockY, int a_BlockZ, cWorld * a_World);
cMobHeadEntity(BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta, int a_BlockX, int a_BlockY, int a_BlockZ, cWorld * a_World);
// tolua_begin
@ -65,6 +65,8 @@ public:
// tolua_end
// cBlockEntity overrides:
virtual void CopyFrom(const cBlockEntity & a_Src) override;
virtual bool UsedBy(cPlayer * a_Player) override;
virtual void SendTo(cClientHandle & a_Client) override;

View File

@ -13,12 +13,26 @@
cMobSpawnerEntity::cMobSpawnerEntity(int a_BlockX, int a_BlockY, int a_BlockZ, cWorld * a_World)
: super(E_BLOCK_MOB_SPAWNER, a_BlockX, a_BlockY, a_BlockZ, a_World)
, m_Entity(mtPig)
, m_SpawnDelay(100)
, m_IsActive(false)
cMobSpawnerEntity::cMobSpawnerEntity(BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta, int a_BlockX, int a_BlockY, int a_BlockZ, cWorld * a_World):
Super(a_BlockType, a_BlockMeta, a_BlockX, a_BlockY, a_BlockZ, a_World),
m_Entity(mtPig),
m_SpawnDelay(100),
m_IsActive(false)
{
ASSERT(a_BlockType == E_BLOCK_MOB_SPAWNER);
}
void cMobSpawnerEntity::CopyFrom(const cBlockEntity & a_Src)
{
Super::CopyFrom(a_Src);
auto & src = reinterpret_cast<const cMobSpawnerEntity &>(a_Src);
m_Entity = src.m_Entity;
m_IsActive = src.m_IsActive;
m_SpawnDelay = src.m_SpawnDelay;
}

View File

@ -20,13 +20,15 @@
class cMobSpawnerEntity :
public cBlockEntity
{
typedef cBlockEntity super;
typedef cBlockEntity Super;
public:
// tolua_end
cMobSpawnerEntity(int a_BlockX, int a_BlockY, int a_BlockZ, cWorld * a_World);
cMobSpawnerEntity(BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta, int a_BlockX, int a_BlockY, int a_BlockZ, cWorld * a_World);
// cBlockEntity overrides:
virtual void CopyFrom(const cBlockEntity & a_Src) override;
virtual void SendTo(cClientHandle & a_Client) override;
virtual bool UsedBy(cPlayer * a_Player) override;
virtual bool Tick(std::chrono::milliseconds a_Dt, cChunk & a_Chunk) override;

View File

@ -9,10 +9,22 @@
cNoteEntity::cNoteEntity(int a_BlockX, int a_BlockY, int a_BlockZ, cWorld * a_World) :
super(E_BLOCK_NOTE_BLOCK, a_BlockX, a_BlockY, a_BlockZ, a_World),
cNoteEntity::cNoteEntity(BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta, int a_BlockX, int a_BlockY, int a_BlockZ, cWorld * a_World):
Super(a_BlockType, a_BlockMeta, a_BlockX, a_BlockY, a_BlockZ, a_World),
m_Pitch(0)
{
ASSERT(a_BlockType == E_BLOCK_NOTE_BLOCK);
}
void cNoteEntity::CopyFrom(const cBlockEntity & a_Src)
{
Super::CopyFrom(a_Src);
auto & src = reinterpret_cast<const cNoteEntity &>(a_Src);
m_Pitch = src.m_Pitch;
}

View File

@ -25,7 +25,7 @@ enum ENUM_NOTE_INSTRUMENTS
class cNoteEntity :
public cBlockEntity
{
typedef cBlockEntity super;
typedef cBlockEntity Super;
public:
// tolua_end
@ -33,7 +33,7 @@ public:
BLOCKENTITY_PROTODEF(cNoteEntity)
/** Creates a new note entity. a_World may be nullptr */
cNoteEntity(int a_X, int a_Y, int a_Z, cWorld * a_World);
cNoteEntity(BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta, int a_BlockX, int a_BlockY, int a_BlockZ, cWorld * a_World);
virtual ~cNoteEntity() override {}
// tolua_begin
@ -45,6 +45,8 @@ public:
// tolua_end
// cBlockEntity overrides:
virtual void CopyFrom(const cBlockEntity & a_Src) override;
virtual bool UsedBy(cPlayer * a_Player) override;
virtual void SendTo(cClientHandle &) override {}

View File

@ -12,10 +12,25 @@
cSignEntity::cSignEntity(BLOCKTYPE a_BlockType, int a_X, int a_Y, int a_Z, cWorld * a_World) :
super(a_BlockType, a_X, a_Y, a_Z, a_World)
cSignEntity::cSignEntity(BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta, int a_BlockX, int a_BlockY, int a_BlockZ, cWorld * a_World):
Super(a_BlockType, a_BlockMeta, a_BlockX, a_BlockY, a_BlockZ, a_World)
{
ASSERT((a_Y >= 0) && (a_Y < cChunkDef::Height));
ASSERT((a_BlockType == E_BLOCK_WALLSIGN) || (a_BlockType == E_BLOCK_SIGN_POST));
ASSERT(cChunkDef::IsValidHeight(a_BlockY));
}
void cSignEntity::CopyFrom(const cBlockEntity & a_Src)
{
Super::CopyFrom(a_Src);
auto & src = reinterpret_cast<const cSignEntity &>(a_Src);
for (size_t i = 0; i < ARRAYCOUNT(m_Line); ++i)
{
m_Line[i] = src.m_Line[i];
}
}

View File

@ -19,7 +19,7 @@
class cSignEntity :
public cBlockEntity
{
typedef cBlockEntity super;
typedef cBlockEntity Super;
public:
@ -28,7 +28,7 @@ public:
BLOCKENTITY_PROTODEF(cSignEntity)
/** Creates a new empty sign entity at the specified block coords and block type (wall or standing). a_World may be nullptr */
cSignEntity(BLOCKTYPE a_BlockType, int a_X, int a_Y, int a_Z, cWorld * a_World);
cSignEntity(BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta, int a_BlockX, int a_BlockY, int a_BlockZ, cWorld * a_World);
// tolua_begin
@ -43,6 +43,8 @@ public:
// tolua_end
// cBlockEntity overrides:
virtual void CopyFrom(const cBlockEntity & a_Src) override;
virtual bool UsedBy(cPlayer * a_Player) override;
virtual void SendTo(cClientHandle & a_Client) override;

View File

@ -73,6 +73,22 @@ void cItemGrid::GetSlotCoords(int a_SlotNum, int & a_X, int & a_Y) const
void cItemGrid::CopyFrom(const cItemGrid & a_Src)
{
ASSERT(m_Width == a_Src.m_Width);
ASSERT(m_Height == a_Src.m_Height);
for (int i = m_NumSlots - 1; i >= 0; --i)
{
m_Slots[i] = a_Src.m_Slots[i];
}
// The listeners are not copied
}
const cItem & cItemGrid::GetSlot(int a_X, int a_Y) const
{
return GetSlot(GetSlotNum(a_X, a_Y));

View File

@ -48,6 +48,11 @@ public:
/** Converts slot number into XY coords; sets coords to -1 on invalid slot number. Exported in ManualBindings.cpp */
void GetSlotCoords(int a_SlotNum, int & a_X, int & a_Y) const;
/** Copies all items from a_Src to this grid.
Both grids must be the same size (asserts).
Doesn't copy the listeners. */
void CopyFrom(const cItemGrid & a_Src);
// tolua_begin
// Retrieve slots by coords or slot number; Logs warning and returns the first slot on invalid coords / slotnum

View File

@ -692,23 +692,23 @@ cBlockEntity * cWSSAnvil::LoadBlockEntityFromNBT(const cParsedNBT & a_NBT, int a
switch (a_BlockType)
{
// Specific entity loaders:
case E_BLOCK_BEACON: return LoadBeaconFromNBT (a_NBT, a_Tag, a_BlockX, a_BlockY, a_BlockZ);
case E_BLOCK_BREWING_STAND: return LoadBrewingstandFromNBT(a_NBT, a_Tag, a_BlockX, a_BlockY, a_BlockZ, E_BLOCK_BREWING_STAND, a_BlockMeta);
case E_BLOCK_CHEST: return LoadChestFromNBT (a_NBT, a_Tag, a_BlockX, a_BlockY, a_BlockZ, E_BLOCK_CHEST);
case E_BLOCK_COMMAND_BLOCK: return LoadCommandBlockFromNBT(a_NBT, a_Tag, a_BlockX, a_BlockY, a_BlockZ);
case E_BLOCK_DISPENSER: return LoadDispenserFromNBT (a_NBT, a_Tag, a_BlockX, a_BlockY, a_BlockZ);
case E_BLOCK_DROPPER: return LoadDropperFromNBT (a_NBT, a_Tag, a_BlockX, a_BlockY, a_BlockZ);
case E_BLOCK_FLOWER_POT: return LoadFlowerPotFromNBT (a_NBT, a_Tag, a_BlockX, a_BlockY, a_BlockZ);
case E_BLOCK_FURNACE: return LoadFurnaceFromNBT (a_NBT, a_Tag, a_BlockX, a_BlockY, a_BlockZ, E_BLOCK_FURNACE, a_BlockMeta);
case E_BLOCK_HEAD: return LoadMobHeadFromNBT (a_NBT, a_Tag, a_BlockX, a_BlockY, a_BlockZ);
case E_BLOCK_HOPPER: return LoadHopperFromNBT (a_NBT, a_Tag, a_BlockX, a_BlockY, a_BlockZ);
case E_BLOCK_JUKEBOX: return LoadJukeboxFromNBT (a_NBT, a_Tag, a_BlockX, a_BlockY, a_BlockZ);
case E_BLOCK_LIT_FURNACE: return LoadFurnaceFromNBT (a_NBT, a_Tag, a_BlockX, a_BlockY, a_BlockZ, E_BLOCK_LIT_FURNACE, a_BlockMeta);
case E_BLOCK_MOB_SPAWNER: return LoadMobSpawnerFromNBT (a_NBT, a_Tag, a_BlockX, a_BlockY, a_BlockZ);
case E_BLOCK_NOTE_BLOCK: return LoadNoteBlockFromNBT (a_NBT, a_Tag, a_BlockX, a_BlockY, a_BlockZ);
case E_BLOCK_SIGN_POST: return LoadSignFromNBT (a_NBT, a_Tag, a_BlockX, a_BlockY, a_BlockZ, E_BLOCK_SIGN_POST);
case E_BLOCK_TRAPPED_CHEST: return LoadChestFromNBT (a_NBT, a_Tag, a_BlockX, a_BlockY, a_BlockZ, E_BLOCK_TRAPPED_CHEST);
case E_BLOCK_WALLSIGN: return LoadSignFromNBT (a_NBT, a_Tag, a_BlockX, a_BlockY, a_BlockZ, E_BLOCK_WALLSIGN);
case E_BLOCK_BEACON: return LoadBeaconFromNBT (a_NBT, a_Tag, a_BlockType, a_BlockMeta, a_BlockX, a_BlockY, a_BlockZ);
case E_BLOCK_BREWING_STAND: return LoadBrewingstandFromNBT(a_NBT, a_Tag, a_BlockType, a_BlockMeta, a_BlockX, a_BlockY, a_BlockZ);
case E_BLOCK_CHEST: return LoadChestFromNBT (a_NBT, a_Tag, a_BlockType, a_BlockMeta, a_BlockX, a_BlockY, a_BlockZ);
case E_BLOCK_COMMAND_BLOCK: return LoadCommandBlockFromNBT(a_NBT, a_Tag, a_BlockType, a_BlockMeta, a_BlockX, a_BlockY, a_BlockZ);
case E_BLOCK_DISPENSER: return LoadDispenserFromNBT (a_NBT, a_Tag, a_BlockType, a_BlockMeta, a_BlockX, a_BlockY, a_BlockZ);
case E_BLOCK_DROPPER: return LoadDropperFromNBT (a_NBT, a_Tag, a_BlockType, a_BlockMeta, a_BlockX, a_BlockY, a_BlockZ);
case E_BLOCK_FLOWER_POT: return LoadFlowerPotFromNBT (a_NBT, a_Tag, a_BlockType, a_BlockMeta, a_BlockX, a_BlockY, a_BlockZ);
case E_BLOCK_FURNACE: return LoadFurnaceFromNBT (a_NBT, a_Tag, a_BlockType, a_BlockMeta, a_BlockX, a_BlockY, a_BlockZ);
case E_BLOCK_HEAD: return LoadMobHeadFromNBT (a_NBT, a_Tag, a_BlockType, a_BlockMeta, a_BlockX, a_BlockY, a_BlockZ);
case E_BLOCK_HOPPER: return LoadHopperFromNBT (a_NBT, a_Tag, a_BlockType, a_BlockMeta, a_BlockX, a_BlockY, a_BlockZ);
case E_BLOCK_JUKEBOX: return LoadJukeboxFromNBT (a_NBT, a_Tag, a_BlockType, a_BlockMeta, a_BlockX, a_BlockY, a_BlockZ);
case E_BLOCK_LIT_FURNACE: return LoadFurnaceFromNBT (a_NBT, a_Tag, a_BlockType, a_BlockMeta, a_BlockX, a_BlockY, a_BlockZ);
case E_BLOCK_MOB_SPAWNER: return LoadMobSpawnerFromNBT (a_NBT, a_Tag, a_BlockType, a_BlockMeta, a_BlockX, a_BlockY, a_BlockZ);
case E_BLOCK_NOTE_BLOCK: return LoadNoteBlockFromNBT (a_NBT, a_Tag, a_BlockType, a_BlockMeta, a_BlockX, a_BlockY, a_BlockZ);
case E_BLOCK_SIGN_POST: return LoadSignFromNBT (a_NBT, a_Tag, a_BlockType, a_BlockMeta, a_BlockX, a_BlockY, a_BlockZ);
case E_BLOCK_TRAPPED_CHEST: return LoadChestFromNBT (a_NBT, a_Tag, a_BlockType, a_BlockMeta, a_BlockX, a_BlockY, a_BlockZ);
case E_BLOCK_WALLSIGN: return LoadSignFromNBT (a_NBT, a_Tag, a_BlockType, a_BlockMeta, a_BlockX, a_BlockY, a_BlockZ);
// Blocktypes that have block entities but don't load their contents from disk:
case E_BLOCK_ENDER_CHEST: return nullptr;
@ -858,7 +858,7 @@ void cWSSAnvil::LoadItemGridFromNBT(cItemGrid & a_ItemGrid, const cParsedNBT & a
bool cWSSAnvil::CheckBlockEntityType(const cParsedNBT & a_NBT, int a_TagIdx, const char * a_ExpectedType)
bool cWSSAnvil::CheckBlockEntityType(const cParsedNBT & a_NBT, int a_TagIdx, const char * a_ExpectedType, int a_BlockX, int a_BlockY, int a_BlockZ)
{
// Check if the given tag is a compound:
if (a_NBT.GetType(a_TagIdx) != TAG_Compound)
@ -878,9 +878,10 @@ bool cWSSAnvil::CheckBlockEntityType(const cParsedNBT & a_NBT, int a_TagIdx, con
{
return true;
}
LOGWARNING("Block entity type mismatch: exp \"%s\", got \"%s\".",
LOGWARNING("Block entity type mismatch: exp \"%s\", got \"%s\". The block entity at {%d, %d, %d} will lose all its properties.",
a_ExpectedType,
AString(a_NBT.GetData(TagID), static_cast<size_t>(a_NBT.GetDataLength(TagID))).c_str()
AString(a_NBT.GetData(TagID), static_cast<size_t>(a_NBT.GetDataLength(TagID))).c_str(),
a_BlockX, a_BlockY, a_BlockZ
);
return false;
}
@ -889,15 +890,15 @@ bool cWSSAnvil::CheckBlockEntityType(const cParsedNBT & a_NBT, int a_TagIdx, con
cBlockEntity * cWSSAnvil::LoadBeaconFromNBT(const cParsedNBT & a_NBT, int a_TagIdx, int a_BlockX, int a_BlockY, int a_BlockZ)
cBlockEntity * cWSSAnvil::LoadBeaconFromNBT(const cParsedNBT & a_NBT, int a_TagIdx, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta, int a_BlockX, int a_BlockY, int a_BlockZ)
{
// Check if the data has a proper type:
if (!CheckBlockEntityType(a_NBT, a_TagIdx, "Beacon"))
if (!CheckBlockEntityType(a_NBT, a_TagIdx, "Beacon", a_BlockX, a_BlockY, a_BlockZ))
{
return nullptr;
}
std::unique_ptr<cBeaconEntity> Beacon = cpp14::make_unique<cBeaconEntity>(a_BlockX, a_BlockY, a_BlockZ, m_World);
auto Beacon = cpp14::make_unique<cBeaconEntity>(a_BlockType, a_BlockMeta, a_BlockX, a_BlockY, a_BlockZ, m_World);
int CurrentLine = a_NBT.FindChildByName(a_TagIdx, "Levels");
if (CurrentLine >= 0)
@ -931,10 +932,10 @@ cBlockEntity * cWSSAnvil::LoadBeaconFromNBT(const cParsedNBT & a_NBT, int a_TagI
cBlockEntity * cWSSAnvil::LoadBrewingstandFromNBT(const cParsedNBT & a_NBT, int a_TagIdx, int a_BlockX, int a_BlockY, int a_BlockZ, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta)
cBlockEntity * cWSSAnvil::LoadBrewingstandFromNBT(const cParsedNBT & a_NBT, int a_TagIdx, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta, int a_BlockX, int a_BlockY, int a_BlockZ)
{
// Check if the data has a proper type:
if (!CheckBlockEntityType(a_NBT, a_TagIdx, "Brewingstand"))
if (!CheckBlockEntityType(a_NBT, a_TagIdx, "Brewingstand", a_BlockX, a_BlockY, a_BlockZ))
{
return nullptr;
}
@ -945,7 +946,7 @@ cBlockEntity * cWSSAnvil::LoadBrewingstandFromNBT(const cParsedNBT & a_NBT, int
return nullptr; // Make it an empty brewingstand - the chunk loader will provide an empty cBrewingstandEntity for this
}
std::unique_ptr<cBrewingstandEntity> Brewingstand(new cBrewingstandEntity(a_BlockX, a_BlockY, a_BlockZ, a_BlockType, a_BlockMeta, m_World));
auto Brewingstand = cpp14::make_unique<cBrewingstandEntity>(a_BlockType, a_BlockMeta, a_BlockX, a_BlockY, a_BlockZ, m_World);
// Fuel has to be loaded at first, because of slot events:
int Fuel = a_NBT.FindChildByName(a_TagIdx, "Fuel");
@ -988,7 +989,7 @@ cBlockEntity * cWSSAnvil::LoadBrewingstandFromNBT(const cParsedNBT & a_NBT, int
cBlockEntity * cWSSAnvil::LoadChestFromNBT(const cParsedNBT & a_NBT, int a_TagIdx, int a_BlockX, int a_BlockY, int a_BlockZ, BLOCKTYPE a_ChestBlockType)
cBlockEntity * cWSSAnvil::LoadChestFromNBT(const cParsedNBT & a_NBT, int a_TagIdx, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta, int a_BlockX, int a_BlockY, int a_BlockZ)
{
// Check if the data has a proper type:
// Note that older Cuberite code used "TrappedChest" for trapped chests; new code mimics vanilla and uses "Chest" throughout, but we allow migration here:
@ -1015,7 +1016,7 @@ cBlockEntity * cWSSAnvil::LoadChestFromNBT(const cParsedNBT & a_NBT, int a_TagId
{
return nullptr; // Make it an empty chest - the chunk loader will provide an empty cChestEntity for this
}
std::unique_ptr<cChestEntity> Chest = cpp14::make_unique<cChestEntity>(a_BlockX, a_BlockY, a_BlockZ, m_World, a_ChestBlockType);
auto Chest = cpp14::make_unique<cChestEntity>(a_BlockType, a_BlockMeta, a_BlockX, a_BlockY, a_BlockZ, m_World);
LoadItemGridFromNBT(Chest->GetContents(), a_NBT, Items);
return Chest.release();
}
@ -1024,15 +1025,15 @@ cBlockEntity * cWSSAnvil::LoadChestFromNBT(const cParsedNBT & a_NBT, int a_TagId
cBlockEntity * cWSSAnvil::LoadCommandBlockFromNBT(const cParsedNBT & a_NBT, int a_TagIdx, int a_BlockX, int a_BlockY, int a_BlockZ)
cBlockEntity * cWSSAnvil::LoadCommandBlockFromNBT(const cParsedNBT & a_NBT, int a_TagIdx, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta, int a_BlockX, int a_BlockY, int a_BlockZ)
{
// Check if the data has a proper type:
if (!CheckBlockEntityType(a_NBT, a_TagIdx, "Control"))
if (!CheckBlockEntityType(a_NBT, a_TagIdx, "Control", a_BlockX, a_BlockY, a_BlockZ))
{
return nullptr;
}
std::unique_ptr<cCommandBlockEntity> CmdBlock = cpp14::make_unique<cCommandBlockEntity>(a_BlockX, a_BlockY, a_BlockZ, m_World);
auto CmdBlock = cpp14::make_unique<cCommandBlockEntity>(a_BlockType, a_BlockMeta, a_BlockX, a_BlockY, a_BlockZ, m_World);
int currentLine = a_NBT.FindChildByName(a_TagIdx, "Command");
if (currentLine >= 0)
@ -1061,10 +1062,10 @@ cBlockEntity * cWSSAnvil::LoadCommandBlockFromNBT(const cParsedNBT & a_NBT, int
cBlockEntity * cWSSAnvil::LoadDispenserFromNBT(const cParsedNBT & a_NBT, int a_TagIdx, int a_BlockX, int a_BlockY, int a_BlockZ)
cBlockEntity * cWSSAnvil::LoadDispenserFromNBT(const cParsedNBT & a_NBT, int a_TagIdx, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta, int a_BlockX, int a_BlockY, int a_BlockZ)
{
// Check if the data has a proper type:
if (!CheckBlockEntityType(a_NBT, a_TagIdx, "Trap"))
if (!CheckBlockEntityType(a_NBT, a_TagIdx, "Trap", a_BlockX, a_BlockY, a_BlockZ))
{
return nullptr;
}
@ -1074,7 +1075,7 @@ cBlockEntity * cWSSAnvil::LoadDispenserFromNBT(const cParsedNBT & a_NBT, int a_T
{
return nullptr; // Make it an empty dispenser - the chunk loader will provide an empty cDispenserEntity for this
}
std::unique_ptr<cDispenserEntity> Dispenser = cpp14::make_unique<cDispenserEntity>(a_BlockX, a_BlockY, a_BlockZ, m_World);
auto Dispenser = cpp14::make_unique<cDispenserEntity>(a_BlockType, a_BlockMeta, a_BlockX, a_BlockY, a_BlockZ, m_World);
LoadItemGridFromNBT(Dispenser->GetContents(), a_NBT, Items);
return Dispenser.release();
}
@ -1083,10 +1084,10 @@ cBlockEntity * cWSSAnvil::LoadDispenserFromNBT(const cParsedNBT & a_NBT, int a_T
cBlockEntity * cWSSAnvil::LoadDropperFromNBT(const cParsedNBT & a_NBT, int a_TagIdx, int a_BlockX, int a_BlockY, int a_BlockZ)
cBlockEntity * cWSSAnvil::LoadDropperFromNBT(const cParsedNBT & a_NBT, int a_TagIdx, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta, int a_BlockX, int a_BlockY, int a_BlockZ)
{
// Check if the data has a proper type:
if (!CheckBlockEntityType(a_NBT, a_TagIdx, "Dropper"))
if (!CheckBlockEntityType(a_NBT, a_TagIdx, "Dropper", a_BlockX, a_BlockY, a_BlockZ))
{
return nullptr;
}
@ -1096,7 +1097,7 @@ cBlockEntity * cWSSAnvil::LoadDropperFromNBT(const cParsedNBT & a_NBT, int a_Tag
{
return nullptr; // Make it an empty dropper - the chunk loader will provide an empty cDropperEntity for this
}
std::unique_ptr<cDropperEntity> Dropper = cpp14::make_unique<cDropperEntity>(a_BlockX, a_BlockY, a_BlockZ, m_World);
auto Dropper = cpp14::make_unique<cDropperEntity>(a_BlockType, a_BlockMeta, a_BlockX, a_BlockY, a_BlockZ, m_World);
LoadItemGridFromNBT(Dropper->GetContents(), a_NBT, Items);
return Dropper.release();
}
@ -1105,15 +1106,15 @@ cBlockEntity * cWSSAnvil::LoadDropperFromNBT(const cParsedNBT & a_NBT, int a_Tag
cBlockEntity * cWSSAnvil::LoadFlowerPotFromNBT(const cParsedNBT & a_NBT, int a_TagIdx, int a_BlockX, int a_BlockY, int a_BlockZ)
cBlockEntity * cWSSAnvil::LoadFlowerPotFromNBT(const cParsedNBT & a_NBT, int a_TagIdx, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta, int a_BlockX, int a_BlockY, int a_BlockZ)
{
// Check if the data has a proper type:
if (!CheckBlockEntityType(a_NBT, a_TagIdx, "FlowerPot"))
if (!CheckBlockEntityType(a_NBT, a_TagIdx, "FlowerPot", a_BlockX, a_BlockY, a_BlockZ))
{
return nullptr;
}
std::unique_ptr<cFlowerPotEntity> FlowerPot = cpp14::make_unique<cFlowerPotEntity>(a_BlockX, a_BlockY, a_BlockZ, m_World);
auto FlowerPot = cpp14::make_unique<cFlowerPotEntity>(a_BlockType, a_BlockMeta, a_BlockX, a_BlockY, a_BlockZ, m_World);
cItem Item;
int currentLine = a_NBT.FindChildByName(a_TagIdx, "Item");
@ -1143,10 +1144,10 @@ cBlockEntity * cWSSAnvil::LoadFlowerPotFromNBT(const cParsedNBT & a_NBT, int a_T
cBlockEntity * cWSSAnvil::LoadFurnaceFromNBT(const cParsedNBT & a_NBT, int a_TagIdx, int a_BlockX, int a_BlockY, int a_BlockZ, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta)
cBlockEntity * cWSSAnvil::LoadFurnaceFromNBT(const cParsedNBT & a_NBT, int a_TagIdx, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta, int a_BlockX, int a_BlockY, int a_BlockZ)
{
// Check if the data has a proper type:
if (!CheckBlockEntityType(a_NBT, a_TagIdx, "Furnace"))
if (!CheckBlockEntityType(a_NBT, a_TagIdx, "Furnace", a_BlockX, a_BlockY, a_BlockZ))
{
return nullptr;
}
@ -1157,7 +1158,7 @@ cBlockEntity * cWSSAnvil::LoadFurnaceFromNBT(const cParsedNBT & a_NBT, int a_Tag
return nullptr; // Make it an empty furnace - the chunk loader will provide an empty cFurnaceEntity for this
}
std::unique_ptr<cFurnaceEntity> Furnace = cpp14::make_unique<cFurnaceEntity>(a_BlockX, a_BlockY, a_BlockZ, a_BlockType, a_BlockMeta, m_World);
auto Furnace = cpp14::make_unique<cFurnaceEntity>(a_BlockType, a_BlockMeta, a_BlockX, a_BlockY, a_BlockZ, m_World);
Furnace->SetLoading(true);
// Load slots:
@ -1202,15 +1203,15 @@ cBlockEntity * cWSSAnvil::LoadFurnaceFromNBT(const cParsedNBT & a_NBT, int a_Tag
cBlockEntity * cWSSAnvil::LoadMobSpawnerFromNBT(const cParsedNBT & a_NBT, int a_TagIdx, int a_BlockX, int a_BlockY, int a_BlockZ)
cBlockEntity * cWSSAnvil::LoadMobSpawnerFromNBT(const cParsedNBT & a_NBT, int a_TagIdx, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta, int a_BlockX, int a_BlockY, int a_BlockZ)
{
// Check if the data has a proper type:
if (!CheckBlockEntityType(a_NBT, a_TagIdx, "MobSpawner"))
if (!CheckBlockEntityType(a_NBT, a_TagIdx, "MobSpawner", a_BlockX, a_BlockY, a_BlockZ))
{
return nullptr;
}
std::unique_ptr<cMobSpawnerEntity> MobSpawner = cpp14::make_unique<cMobSpawnerEntity>(a_BlockX, a_BlockY, a_BlockZ, m_World);
auto MobSpawner = cpp14::make_unique<cMobSpawnerEntity>(a_BlockType, a_BlockMeta, a_BlockX, a_BlockY, a_BlockZ, m_World);
// Load entity (Cuberite worlds):
int Type = a_NBT.FindChildByName(a_TagIdx, "Entity");
@ -1250,10 +1251,10 @@ cBlockEntity * cWSSAnvil::LoadMobSpawnerFromNBT(const cParsedNBT & a_NBT, int a_
cBlockEntity * cWSSAnvil::LoadHopperFromNBT(const cParsedNBT & a_NBT, int a_TagIdx, int a_BlockX, int a_BlockY, int a_BlockZ)
cBlockEntity * cWSSAnvil::LoadHopperFromNBT(const cParsedNBT & a_NBT, int a_TagIdx, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta, int a_BlockX, int a_BlockY, int a_BlockZ)
{
// Check if the data has a proper type:
if (!CheckBlockEntityType(a_NBT, a_TagIdx, "Hopper"))
if (!CheckBlockEntityType(a_NBT, a_TagIdx, "Hopper", a_BlockX, a_BlockY, a_BlockZ))
{
return nullptr;
}
@ -1263,7 +1264,7 @@ cBlockEntity * cWSSAnvil::LoadHopperFromNBT(const cParsedNBT & a_NBT, int a_TagI
{
return nullptr; // Make it an empty hopper - the chunk loader will provide an empty cHopperEntity for this
}
std::unique_ptr<cHopperEntity> Hopper = cpp14::make_unique<cHopperEntity>(a_BlockX, a_BlockY, a_BlockZ, m_World);
auto Hopper = cpp14::make_unique<cHopperEntity>(a_BlockType, a_BlockMeta, a_BlockX, a_BlockY, a_BlockZ, m_World);
LoadItemGridFromNBT(Hopper->GetContents(), a_NBT, Items);
return Hopper.release();
}
@ -1272,15 +1273,15 @@ cBlockEntity * cWSSAnvil::LoadHopperFromNBT(const cParsedNBT & a_NBT, int a_TagI
cBlockEntity * cWSSAnvil::LoadJukeboxFromNBT(const cParsedNBT & a_NBT, int a_TagIdx, int a_BlockX, int a_BlockY, int a_BlockZ)
cBlockEntity * cWSSAnvil::LoadJukeboxFromNBT(const cParsedNBT & a_NBT, int a_TagIdx, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta, int a_BlockX, int a_BlockY, int a_BlockZ)
{
// Check if the data has a proper type:
if (!CheckBlockEntityType(a_NBT, a_TagIdx, "RecordPlayer"))
if (!CheckBlockEntityType(a_NBT, a_TagIdx, "RecordPlayer", a_BlockX, a_BlockY, a_BlockZ))
{
return nullptr;
}
std::unique_ptr<cJukeboxEntity> Jukebox = cpp14::make_unique<cJukeboxEntity>(a_BlockX, a_BlockY, a_BlockZ, m_World);
auto Jukebox = cpp14::make_unique<cJukeboxEntity>(a_BlockType, a_BlockMeta, a_BlockX, a_BlockY, a_BlockZ, m_World);
int Record = a_NBT.FindChildByName(a_TagIdx, "Record");
if (Record >= 0)
{
@ -1293,15 +1294,15 @@ cBlockEntity * cWSSAnvil::LoadJukeboxFromNBT(const cParsedNBT & a_NBT, int a_Tag
cBlockEntity * cWSSAnvil::LoadMobHeadFromNBT(const cParsedNBT & a_NBT, int a_TagIdx, int a_BlockX, int a_BlockY, int a_BlockZ)
cBlockEntity * cWSSAnvil::LoadMobHeadFromNBT(const cParsedNBT & a_NBT, int a_TagIdx, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta, int a_BlockX, int a_BlockY, int a_BlockZ)
{
// Check if the data has a proper type:
if (!CheckBlockEntityType(a_NBT, a_TagIdx, "Skull"))
if (!CheckBlockEntityType(a_NBT, a_TagIdx, "Skull", a_BlockX, a_BlockY, a_BlockZ))
{
return nullptr;
}
std::unique_ptr<cMobHeadEntity> MobHead = cpp14::make_unique<cMobHeadEntity>(a_BlockX, a_BlockY, a_BlockZ, m_World);
auto MobHead = cpp14::make_unique<cMobHeadEntity>(a_BlockType, a_BlockMeta, a_BlockX, a_BlockY, a_BlockZ, m_World);
int currentLine = a_NBT.FindChildByName(a_TagIdx, "SkullType");
if (currentLine >= 0)
@ -1365,15 +1366,15 @@ cBlockEntity * cWSSAnvil::LoadMobHeadFromNBT(const cParsedNBT & a_NBT, int a_Tag
cBlockEntity * cWSSAnvil::LoadNoteBlockFromNBT(const cParsedNBT & a_NBT, int a_TagIdx, int a_BlockX, int a_BlockY, int a_BlockZ)
cBlockEntity * cWSSAnvil::LoadNoteBlockFromNBT(const cParsedNBT & a_NBT, int a_TagIdx, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta, int a_BlockX, int a_BlockY, int a_BlockZ)
{
// Check if the data has a proper type:
if (!CheckBlockEntityType(a_NBT, a_TagIdx, "Music"))
if (!CheckBlockEntityType(a_NBT, a_TagIdx, "Music", a_BlockX, a_BlockY, a_BlockZ))
{
return nullptr;
}
std::unique_ptr<cNoteEntity> NoteBlock = cpp14::make_unique<cNoteEntity>(a_BlockX, a_BlockY, a_BlockZ, m_World);
auto NoteBlock = cpp14::make_unique<cNoteEntity>(a_BlockType, a_BlockMeta, a_BlockX, a_BlockY, a_BlockZ, m_World);
int note = a_NBT.FindChildByName(a_TagIdx, "note");
if (note >= 0)
{
@ -1386,15 +1387,15 @@ cBlockEntity * cWSSAnvil::LoadNoteBlockFromNBT(const cParsedNBT & a_NBT, int a_T
cBlockEntity * cWSSAnvil::LoadSignFromNBT(const cParsedNBT & a_NBT, int a_TagIdx, int a_BlockX, int a_BlockY, int a_BlockZ, BLOCKTYPE a_BlockType)
cBlockEntity * cWSSAnvil::LoadSignFromNBT(const cParsedNBT & a_NBT, int a_TagIdx, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta, int a_BlockX, int a_BlockY, int a_BlockZ)
{
// Check if the data has a proper type:
if (!CheckBlockEntityType(a_NBT, a_TagIdx, "Sign"))
if (!CheckBlockEntityType(a_NBT, a_TagIdx, "Sign", a_BlockX, a_BlockY, a_BlockZ))
{
return nullptr;
}
std::unique_ptr<cSignEntity> Sign = cpp14::make_unique<cSignEntity>(a_BlockType, a_BlockX, a_BlockY, a_BlockZ, m_World);
auto Sign = cpp14::make_unique<cSignEntity>(a_BlockType, a_BlockMeta, a_BlockX, a_BlockY, a_BlockZ, m_World);
int currentLine = a_NBT.FindChildByName(a_TagIdx, "Text1");
if (currentLine >= 0)

View File

@ -145,23 +145,25 @@ protected:
Slots outside the ItemGrid range are ignored */
void LoadItemGridFromNBT(cItemGrid & a_ItemGrid, const cParsedNBT & a_NBT, int a_ItemsTagIdx, int s_SlotOffset = 0);
/** Returns true iff the "id" child tag inside the specified tag equals the specified expected type. */
bool CheckBlockEntityType(const cParsedNBT & a_NBT, int a_TagIdx, const char * a_ExpectedType);
/** Returns true iff the "id" child tag inside the specified tag equals the specified expected type.
Logs a warning to the console on mismatch.
The coordinates are used only for the log message. */
bool CheckBlockEntityType(const cParsedNBT & a_NBT, int a_TagIdx, const char * a_ExpectedType, int a_BlockX, int a_BlockY, int a_BlockZ);
cBlockEntity * LoadBeaconFromNBT (const cParsedNBT & a_NBT, int a_TagIdx, int a_BlockX, int a_BlockY, int a_BlockZ);
cBlockEntity * LoadBrewingstandFromNBT(const cParsedNBT & a_NBT, int a_TagIdx, int a_BlockX, int a_BlockY, int a_BlockZ, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta);
cBlockEntity * LoadChestFromNBT (const cParsedNBT & a_NBT, int a_TagIdx, int a_BlockX, int a_BlockY, int a_BlockZ, BLOCKTYPE a_ChestBlockType);
cBlockEntity * LoadCommandBlockFromNBT(const cParsedNBT & a_NBT, int a_TagIdx, int a_BlockX, int a_BlockY, int a_BlockZ);
cBlockEntity * LoadDispenserFromNBT (const cParsedNBT & a_NBT, int a_TagIdx, int a_BlockX, int a_BlockY, int a_BlockZ);
cBlockEntity * LoadDropperFromNBT (const cParsedNBT & a_NBT, int a_TagIdx, int a_BlockX, int a_BlockY, int a_BlockZ);
cBlockEntity * LoadFlowerPotFromNBT (const cParsedNBT & a_NBT, int a_TagIdx, int a_BlockX, int a_BlockY, int a_BlockZ);
cBlockEntity * LoadFurnaceFromNBT (const cParsedNBT & a_NBT, int a_TagIdx, int a_BlockX, int a_BlockY, int a_BlockZ, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta);
cBlockEntity * LoadMobSpawnerFromNBT (const cParsedNBT & a_NBT, int a_TagIdx, int a_BlockX, int a_BlockY, int a_BlockZ);
cBlockEntity * LoadHopperFromNBT (const cParsedNBT & a_NBT, int a_TagIdx, int a_BlockX, int a_BlockY, int a_BlockZ);
cBlockEntity * LoadJukeboxFromNBT (const cParsedNBT & a_NBT, int a_TagIdx, int a_BlockX, int a_BlockY, int a_BlockZ);
cBlockEntity * LoadMobHeadFromNBT (const cParsedNBT & a_NBT, int a_TagIdx, int a_BlockX, int a_BlockY, int a_BlockZ);
cBlockEntity * LoadNoteBlockFromNBT (const cParsedNBT & a_NBT, int a_TagIdx, int a_BlockX, int a_BlockY, int a_BlockZ);
cBlockEntity * LoadSignFromNBT (const cParsedNBT & a_NBT, int a_TagIdx, int a_BlockX, int a_BlockY, int a_BlockZ, BLOCKTYPE a_SignBlockType);
cBlockEntity * LoadBeaconFromNBT (const cParsedNBT & a_NBT, int a_TagIdx, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta, int a_BlockX, int a_BlockY, int a_BlockZ);
cBlockEntity * LoadBrewingstandFromNBT(const cParsedNBT & a_NBT, int a_TagIdx, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta, int a_BlockX, int a_BlockY, int a_BlockZ);
cBlockEntity * LoadChestFromNBT (const cParsedNBT & a_NBT, int a_TagIdx, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta, int a_BlockX, int a_BlockY, int a_BlockZ);
cBlockEntity * LoadCommandBlockFromNBT(const cParsedNBT & a_NBT, int a_TagIdx, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta, int a_BlockX, int a_BlockY, int a_BlockZ);
cBlockEntity * LoadDispenserFromNBT (const cParsedNBT & a_NBT, int a_TagIdx, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta, int a_BlockX, int a_BlockY, int a_BlockZ);
cBlockEntity * LoadDropperFromNBT (const cParsedNBT & a_NBT, int a_TagIdx, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta, int a_BlockX, int a_BlockY, int a_BlockZ);
cBlockEntity * LoadFlowerPotFromNBT (const cParsedNBT & a_NBT, int a_TagIdx, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta, int a_BlockX, int a_BlockY, int a_BlockZ);
cBlockEntity * LoadFurnaceFromNBT (const cParsedNBT & a_NBT, int a_TagIdx, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta, int a_BlockX, int a_BlockY, int a_BlockZ);
cBlockEntity * LoadMobSpawnerFromNBT (const cParsedNBT & a_NBT, int a_TagIdx, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta, int a_BlockX, int a_BlockY, int a_BlockZ);
cBlockEntity * LoadHopperFromNBT (const cParsedNBT & a_NBT, int a_TagIdx, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta, int a_BlockX, int a_BlockY, int a_BlockZ);
cBlockEntity * LoadJukeboxFromNBT (const cParsedNBT & a_NBT, int a_TagIdx, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta, int a_BlockX, int a_BlockY, int a_BlockZ);
cBlockEntity * LoadMobHeadFromNBT (const cParsedNBT & a_NBT, int a_TagIdx, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta, int a_BlockX, int a_BlockY, int a_BlockZ);
cBlockEntity * LoadNoteBlockFromNBT (const cParsedNBT & a_NBT, int a_TagIdx, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta, int a_BlockX, int a_BlockY, int a_BlockZ);
cBlockEntity * LoadSignFromNBT (const cParsedNBT & a_NBT, int a_TagIdx, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta, int a_BlockX, int a_BlockY, int a_BlockZ);
void LoadEntityFromNBT(cEntityList & a_Entities, const cParsedNBT & a_NBT, int a_EntityTagIdx, const char * a_IDTag, size_t a_IDTagLength);