diff options
Diffstat (limited to 'src/BlockEntities')
24 files changed, 244 insertions, 176 deletions
diff --git a/src/BlockEntities/BeaconEntity.cpp b/src/BlockEntities/BeaconEntity.cpp index 0914353eb..4b9662797 100644 --- a/src/BlockEntities/BeaconEntity.cpp +++ b/src/BlockEntities/BeaconEntity.cpp @@ -32,7 +32,7 @@ int cBeaconEntity::GetPyramidLevel(void) } Area.Read( - m_World, + m_World, GetPosX() - 4, GetPosX() + 4, MinY, MaxY, GetPosZ() - 4, GetPosZ() + 4, @@ -66,7 +66,7 @@ int cBeaconEntity::GetPyramidLevel(void) bool cBeaconEntity::IsMineralBlock(BLOCKTYPE a_BlockType) { - switch(a_BlockType) + switch (a_BlockType) { case E_BLOCK_DIAMOND_BLOCK: case E_BLOCK_GOLD_BLOCK: diff --git a/src/BlockEntities/BeaconEntity.h b/src/BlockEntities/BeaconEntity.h index b1df68bc4..ee1eda391 100644 --- a/src/BlockEntities/BeaconEntity.h +++ b/src/BlockEntities/BeaconEntity.h @@ -33,7 +33,7 @@ public: static bool IsMineralBlock(BLOCKTYPE a_BlockType); // cBlockEntity overrides: - virtual void SaveToJson(Json::Value& a_Value ) override; + virtual void SaveToJson(Json::Value& a_Value) override; virtual void SendTo(cClientHandle & a_Client) override; virtual void UsedBy(cPlayer * a_Player) override; virtual bool Tick(float a_Dt, cChunk & /* a_Chunk */) override; diff --git a/src/BlockEntities/BlockEntity.cpp b/src/BlockEntities/BlockEntity.cpp index 430f04551..05ad03a3d 100644 --- a/src/BlockEntities/BlockEntity.cpp +++ b/src/BlockEntities/BlockEntity.cpp @@ -28,24 +28,26 @@ 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); + 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_HEAD: return new cMobHeadEntity (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_FURNACE: return new cFurnaceEntity (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_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_JUKEBOX: return new cJukeboxEntity (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() ); + ASSERT(!"Requesting creation of an unknown block entity"); return NULL; } diff --git a/src/BlockEntities/BlockEntity.h b/src/BlockEntities/BlockEntity.h index 7c6688f8d..5710f8543 100644 --- a/src/BlockEntities/BlockEntity.h +++ b/src/BlockEntities/BlockEntity.h @@ -38,9 +38,9 @@ protected: public: // tolua_end - virtual ~cBlockEntity() {}; // force a virtual destructor in all descendants + virtual ~cBlockEntity() {} // force a virtual destructor in all descendants - virtual void Destroy(void) {}; + virtual void Destroy(void) {} void SetWorld(cWorld * a_World) { @@ -79,7 +79,7 @@ public: virtual void SaveToJson (Json::Value & a_Value) = 0; /// Called when a player uses this entity; should open the UI window - virtual void UsedBy( cPlayer * a_Player ) = 0; + virtual void UsedBy( cPlayer * a_Player) = 0; /** Sends the packet defining the block entity to the client specified. To send to all eligible clients, use cWorld::BroadcastBlockEntity() diff --git a/src/BlockEntities/BlockEntityWithItems.h b/src/BlockEntities/BlockEntityWithItems.h index 918781a00..5f1639d45 100644 --- a/src/BlockEntities/BlockEntityWithItems.h +++ b/src/BlockEntities/BlockEntityWithItems.h @@ -50,7 +50,7 @@ public: 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 + m_World->SpawnItemPickups(Pickups, m_PosX + 0.5, m_PosY + 0.5, m_PosZ + 0.5); // Spawn in centre of block } // tolua_begin diff --git a/src/BlockEntities/CMakeLists.txt b/src/BlockEntities/CMakeLists.txt index 3e3d17f86..d87594b0d 100644 --- a/src/BlockEntities/CMakeLists.txt +++ b/src/BlockEntities/CMakeLists.txt @@ -4,9 +4,41 @@ project (MCServer) include_directories ("${PROJECT_SOURCE_DIR}/../") -file(GLOB SOURCE - "*.cpp" - "*.h" -) +SET (SRCS + BeaconEntity.cpp + BlockEntity.cpp + ChestEntity.cpp + CommandBlockEntity.cpp + DispenserEntity.cpp + DropSpenserEntity.cpp + DropperEntity.cpp + EnderChestEntity.cpp + FlowerPotEntity.cpp + FurnaceEntity.cpp + HopperEntity.cpp + JukeboxEntity.cpp + MobHeadEntity.cpp + NoteEntity.cpp + SignEntity.cpp) -add_library(BlockEntities ${SOURCE}) +SET (HDRS + BeaconEntity.h + BlockEntity.h + BlockEntityWithItems.h + ChestEntity.h + CommandBlockEntity.h + DispenserEntity.h + DropSpenserEntity.h + DropperEntity.h + EnderChestEntity.h + FlowerPotEntity.h + FurnaceEntity.h + HopperEntity.h + JukeboxEntity.h + MobHeadEntity.h + NoteEntity.h + SignEntity.h) + +if(NOT MSVC) + add_library(BlockEntities ${SRCS} ${HDRS}) +endif() diff --git a/src/BlockEntities/ChestEntity.cpp b/src/BlockEntities/ChestEntity.cpp index dfbe6ae87..21e1f6ba2 100644 --- a/src/BlockEntities/ChestEntity.cpp +++ b/src/BlockEntities/ChestEntity.cpp @@ -11,8 +11,9 @@ -cChestEntity::cChestEntity(int a_BlockX, int a_BlockY, int a_BlockZ, cWorld * a_World) : - super(E_BLOCK_CHEST, a_BlockX, a_BlockY, a_BlockZ, ContentsWidth, ContentsHeight, a_World) +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), + m_NumActivePlayers(0) { cBlockEntityWindowOwner::SetBlockEntity(this); } @@ -113,7 +114,7 @@ void cChestEntity::UsedBy(cPlayer * a_Player) // The few false positives aren't much to worry about int ChunkX, ChunkZ; cChunkDef::BlockToChunk(m_PosX, m_PosZ, ChunkX, ChunkZ); - m_World->MarkChunkDirty(ChunkX, ChunkZ); + m_World->MarkChunkDirty(ChunkX, ChunkZ, true); } @@ -122,6 +123,13 @@ void cChestEntity::UsedBy(cPlayer * a_Player) void cChestEntity::OpenNewWindow(void) { + // TODO: cats are an obstruction + if ((GetPosY() + 1 < cChunkDef::Height) && cBlockInfo::IsSolid(GetWorld()->GetBlock(GetPosX(), GetPosY() + 1, GetPosZ()))) + { + // Obstruction, don't open + return; + } + // Callback for opening together with neighbor chest: class cOpenDouble : public cChestCallback @@ -135,6 +143,12 @@ void cChestEntity::OpenNewWindow(void) virtual bool Item(cChestEntity * a_Chest) override { + if ((a_Chest->GetPosY() + 1 < cChunkDef::Height) && cBlockInfo::IsSolid(a_Chest->GetWorld()->GetBlock(a_Chest->GetPosX(), a_Chest->GetPosY() + 1, a_Chest->GetPosZ()))) + { + // Obstruction, don't open + return false; + } + // The primary chest should eb the one with lesser X or Z coord: cChestEntity * Primary = a_Chest; cChestEntity * Secondary = m_ThisChest; @@ -155,15 +169,15 @@ void cChestEntity::OpenNewWindow(void) if ( m_World->DoWithChestAt(m_PosX - 1, m_PosY, m_PosZ, OpenDbl) || m_World->DoWithChestAt(m_PosX + 1, m_PosY, m_PosZ, OpenDbl) || - m_World->DoWithChestAt(m_PosX , m_PosY, m_PosZ - 1, OpenDbl) || - m_World->DoWithChestAt(m_PosX , m_PosY, m_PosZ + 1, OpenDbl) + m_World->DoWithChestAt(m_PosX, m_PosY, m_PosZ - 1, OpenDbl) || + m_World->DoWithChestAt(m_PosX, m_PosY, m_PosZ + 1, OpenDbl) ) { // The double-chest window has been opened in the callback return; } - // There is no chest neighbor, open a single-chest window: + // There is no chest neighbor, open a single-chest window: OpenWindow(new cChestWindow(this)); } diff --git a/src/BlockEntities/ChestEntity.h b/src/BlockEntities/ChestEntity.h index ce16f84d7..cd06b3e2c 100644 --- a/src/BlockEntities/ChestEntity.h +++ b/src/BlockEntities/ChestEntity.h @@ -27,15 +27,16 @@ class cChestEntity : typedef cBlockEntityWithItems super; public: - enum { + enum + { ContentsHeight = 3, ContentsWidth = 9, } ; // tolua_end - /// Constructor used for normal operation - cChestEntity(int a_BlockX, int a_BlockY, int a_BlockZ, cWorld * a_World); + /** Constructor used for normal operation */ + cChestEntity(int a_BlockX, int a_BlockY, int a_BlockZ, cWorld * a_World, BLOCKTYPE a_Type); virtual ~cChestEntity(); @@ -48,8 +49,20 @@ public: virtual void SendTo(cClientHandle & a_Client) override; virtual void UsedBy(cPlayer * a_Player) override; - /// Opens a new chest window for this chest. Scans for neighbors to open a double chest window, if appropriate. + /** Opens a new chest window for this chest. + Scans for neighbors to open a double chest window, if appropriate. */ void OpenNewWindow(void); + + /** Gets the number of players who currently have this chest open */ + int GetNumberOfPlayers(void) const { return m_NumActivePlayers; } + + /** Sets the number of players who currently have this chest open */ + void SetNumberOfPlayers(int a_NumActivePlayers) { m_NumActivePlayers = a_NumActivePlayers; } + +private: + + /** Number of players who currently have this chest open */ + int m_NumActivePlayers; } ; // tolua_export diff --git a/src/BlockEntities/CommandBlockEntity.cpp b/src/BlockEntities/CommandBlockEntity.cpp index 146ad915b..45f8a3e4d 100644 --- a/src/BlockEntities/CommandBlockEntity.cpp +++ b/src/BlockEntities/CommandBlockEntity.cpp @@ -11,7 +11,7 @@ #include "../CommandOutput.h" #include "../Root.h" -#include "../Server.h" // ExecuteConsoleCommand() +#include "../Server.h" // ExecuteConsoleCommand() #include "../Chunk.h" diff --git a/src/BlockEntities/CommandBlockEntity.h b/src/BlockEntities/CommandBlockEntity.h index 12157670f..d02bf7d7b 100644 --- a/src/BlockEntities/CommandBlockEntity.h +++ b/src/BlockEntities/CommandBlockEntity.h @@ -26,7 +26,7 @@ namespace Json // tolua_begin -class cCommandBlockEntity : +class cCommandBlockEntity : public cBlockEntity { typedef cBlockEntity super; @@ -38,8 +38,8 @@ public: /// Creates a new empty command block entity cCommandBlockEntity(int a_X, int a_Y, int a_Z, cWorld * a_World); - bool LoadFromJson( const Json::Value& a_Value ); - virtual void SaveToJson(Json::Value& a_Value ) override; + bool LoadFromJson( const Json::Value& a_Value); + virtual void SaveToJson(Json::Value& a_Value) override; virtual bool Tick(float a_Dt, cChunk & a_Chunk) override; virtual void SendTo(cClientHandle & a_Client) override; diff --git a/src/BlockEntities/DropSpenserEntity.cpp b/src/BlockEntities/DropSpenserEntity.cpp index 0012742fb..dc38e3e9b 100644 --- a/src/BlockEntities/DropSpenserEntity.cpp +++ b/src/BlockEntities/DropSpenserEntity.cpp @@ -42,7 +42,7 @@ cDropSpenserEntity::~cDropSpenserEntity() void cDropSpenserEntity::AddDropSpenserDir(int & a_BlockX, int & a_BlockY, int & a_BlockZ, NIBBLETYPE a_Direction) { - switch (a_Direction) + switch (a_Direction & 0x07) // Vanilla uses the 8th bit to determine power state - we don't { case E_META_DROPSPENSER_FACING_YM: a_BlockY--; return; case E_META_DROPSPENSER_FACING_YP: a_BlockY++; return; @@ -90,7 +90,7 @@ void cDropSpenserEntity::DropSpense(cChunk & a_Chunk) int SmokeDir = 0; switch (Meta) { - case E_META_DROPSPENSER_FACING_YP: SmokeDir = 4; break; // YP & YM don't have associated smoke dirs, just do 4 (centre of block) + case E_META_DROPSPENSER_FACING_YP: SmokeDir = 4; break; // YP & YM don't have associated smoke dirs, just do 4 (centre of block) case E_META_DROPSPENSER_FACING_YM: SmokeDir = 4; break; case E_META_DROPSPENSER_FACING_XM: SmokeDir = 3; break; case E_META_DROPSPENSER_FACING_XP: SmokeDir = 5; break; @@ -99,7 +99,7 @@ void cDropSpenserEntity::DropSpense(cChunk & a_Chunk) } m_World->BroadcastSoundParticleEffect(2000, m_PosX, m_PosY, m_PosZ, SmokeDir); m_World->BroadcastSoundEffect("random.click", m_PosX * 8, m_PosY * 8, m_PosZ * 8, 1.0f, 1.0f); -} +} @@ -235,7 +235,7 @@ void cDropSpenserEntity::DropFromSlot(cChunk & a_Chunk, int a_SlotNum) cItems Pickups; Pickups.push_back(m_Contents.RemoveOneItem(a_SlotNum)); - const int PickupSpeed = m_World->GetTickRandomNumber(4) + 2; // At least 2, at most 6 + const int PickupSpeed = m_World->GetTickRandomNumber(4) + 2; // At least 2, at most 6 int PickupSpeedX = 0, PickupSpeedY = 0, PickupSpeedZ = 0; switch (Meta) { @@ -249,7 +249,7 @@ void cDropSpenserEntity::DropFromSlot(cChunk & a_Chunk, int a_SlotNum) double MicroX, MicroY, MicroZ; MicroX = DispX + 0.5; - MicroY = DispY + 0.4; // Slightly less than half, to accomodate actual texture hole on DropSpenser + MicroY = DispY + 0.4; // Slightly less than half, to accomodate actual texture hole on DropSpenser MicroZ = DispZ + 0.5; diff --git a/src/BlockEntities/DropSpenserEntity.h b/src/BlockEntities/DropSpenserEntity.h index 47d3bd492..9f58d0b07 100644 --- a/src/BlockEntities/DropSpenserEntity.h +++ b/src/BlockEntities/DropSpenserEntity.h @@ -35,7 +35,8 @@ class cDropSpenserEntity : typedef cBlockEntityWithItems super; public: - enum { + enum + { ContentsHeight = 3, ContentsWidth = 3, } ; diff --git a/src/BlockEntities/EnderChestEntity.cpp b/src/BlockEntities/EnderChestEntity.cpp index e53930798..17816d63e 100644 --- a/src/BlockEntities/EnderChestEntity.cpp +++ b/src/BlockEntities/EnderChestEntity.cpp @@ -12,9 +12,8 @@ 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, ContentsWidth, ContentsHeight, a_World) + super(E_BLOCK_ENDER_CHEST, a_BlockX, a_BlockY, a_BlockZ, a_World) { - cBlockEntityWindowOwner::SetBlockEntity(this); } @@ -34,95 +33,63 @@ cEnderChestEntity::~cEnderChestEntity() -bool cEnderChestEntity::LoadFromJson(const Json::Value & a_Value) +void cEnderChestEntity::UsedBy(cPlayer * a_Player) { - m_PosX = a_Value.get("x", 0).asInt(); - m_PosY = a_Value.get("y", 0).asInt(); - m_PosZ = a_Value.get("z", 0).asInt(); - - Json::Value AllSlots = a_Value.get("Slots", 0); - int SlotIdx = 0; - for (Json::Value::iterator itr = AllSlots.begin(); itr != AllSlots.end(); ++itr) + // If the window is not created, open it anew: + cWindow * Window = GetWindow(); + if (Window == NULL) { - cItem Item; - Item.FromJson(*itr); - SetSlot(SlotIdx, Item); - SlotIdx++; + OpenNewWindow(); + Window = GetWindow(); } - return true; -} - - - - - -void cEnderChestEntity::SaveToJson(Json::Value & a_Value) -{ - a_Value["x"] = m_PosX; - a_Value["y"] = m_PosY; - a_Value["z"] = m_PosZ; - - Json::Value AllSlots; - for (int i = m_Contents.GetNumSlots() - 1; i >= 0; i--) + + // Open the window for the player: + if (Window != NULL) { - Json::Value Slot; - m_Contents.GetSlot(i).GetJson(Slot); - AllSlots.append(Slot); + if (a_Player->GetWindow() != Window) + { + a_Player->OpenWindow(Window); + } } - a_Value["Slots"] = AllSlots; } -void cEnderChestEntity::SendTo(cClientHandle & a_Client) +void cEnderChestEntity::OpenNewWindow() { - // The chest entity doesn't need anything sent to the client when it's created / gets in the viewdistance - // All the actual handling is in the cWindow UI code that gets called when the chest is rclked - - UNUSED(a_Client); + OpenWindow(new cEnderChestWindow(this)); } -void cEnderChestEntity::UsedBy(cPlayer * a_Player) +void cEnderChestEntity::LoadFromJson(const Json::Value & a_Value, cItemGrid & a_Grid) { - // If the window is not created, open it anew: - cWindow * Window = GetWindow(); - if (Window == NULL) - { - OpenNewWindow(); - Window = GetWindow(); - } - - // Open the window for the player: - if (Window != NULL) + int SlotIdx = 0; + for (Json::Value::iterator itr = a_Value.begin(); itr != a_Value.end(); ++itr) { - if (a_Player->GetWindow() != Window) - { - a_Player->OpenWindow(Window); - } + cItem Item; + Item.FromJson(*itr); + a_Grid.SetSlot(SlotIdx, Item); + SlotIdx++; } - - // This is rather a hack - // Instead of marking the chunk as dirty upon chest contents change, we mark it dirty now - // We cannot properly detect contents change, but such a change doesn't happen without a player opening the chest first. - // The few false positives aren't much to worry about - int ChunkX, ChunkZ; - cChunkDef::BlockToChunk(m_PosX, m_PosZ, ChunkX, ChunkZ); - m_World->MarkChunkDirty(ChunkX, ChunkZ); } -void cEnderChestEntity::OpenNewWindow(void) +void cEnderChestEntity::SaveToJson(Json::Value & a_Value, const cItemGrid & a_Grid) { - OpenWindow(new cEnderChestWindow(this)); + for (int i = 0; i < a_Grid.GetNumSlots(); i++) + { + Json::Value Slot; + a_Grid.GetSlot(i).GetJson(Slot); + a_Value.append(Slot); + } } diff --git a/src/BlockEntities/EnderChestEntity.h b/src/BlockEntities/EnderChestEntity.h index 45beee45f..ed178f6fc 100644 --- a/src/BlockEntities/EnderChestEntity.h +++ b/src/BlockEntities/EnderChestEntity.h @@ -1,20 +1,9 @@ #pragma once -#include "BlockEntityWithItems.h" - - - - - -namespace Json -{ - class Value; -}; - -class cClientHandle; -class cServer; -class cNBTData; +#include "BlockEntity.h" +#include "UI/WindowOwner.h" +#include "json/json.h" @@ -22,33 +11,28 @@ class cNBTData; // tolua_begin class cEnderChestEntity : - public cBlockEntityWithItems + public cBlockEntity, + public cBlockEntityWindowOwner { - typedef cBlockEntityWithItems super; + typedef cBlockEntity super; public: - enum { - ContentsHeight = 3, - ContentsWidth = 9, - } ; - // tolua_end - /// Constructor used for normal operation cEnderChestEntity(int a_BlockX, int a_BlockY, int a_BlockZ, cWorld * a_World); - virtual ~cEnderChestEntity(); static const char * GetClassStatic(void) { return "cEnderChestEntity"; } - - bool LoadFromJson(const Json::Value & a_Value); // cBlockEntity overrides: - virtual void SaveToJson(Json::Value & a_Value) override; - virtual void SendTo(cClientHandle & a_Client) override; virtual void UsedBy(cPlayer * a_Player) override; + virtual void SaveToJson(Json::Value & a_Value) override { UNUSED(a_Value); } + virtual void SendTo(cClientHandle & a_Client) override { UNUSED(a_Client); } + + static void LoadFromJson(const Json::Value & a_Value, cItemGrid & a_Grid); + static void SaveToJson(Json::Value & a_Value, const cItemGrid & a_Grid); - /// Opens a new chest window for this chest. Scans for neighbors to open a double chest window, if appropriate. + /** Opens a new enderchest window for this enderchest */ void OpenNewWindow(void); } ; // tolua_export diff --git a/src/BlockEntities/FlowerPotEntity.h b/src/BlockEntities/FlowerPotEntity.h index da3fe9b7e..89901cf2d 100644 --- a/src/BlockEntities/FlowerPotEntity.h +++ b/src/BlockEntities/FlowerPotEntity.h @@ -27,7 +27,7 @@ namespace Json // tolua_begin -class cFlowerPotEntity : +class cFlowerPotEntity : public cBlockEntity { typedef cBlockEntity super; @@ -39,8 +39,8 @@ public: /** Creates a new flowerpot entity at the specified block coords. a_World may be NULL */ cFlowerPotEntity(int a_BlocX, int a_BlockY, int a_BlockZ, cWorld * a_World); - bool LoadFromJson( const Json::Value& a_Value ); - virtual void SaveToJson(Json::Value& a_Value ) override; + bool LoadFromJson( const Json::Value& a_Value); + virtual void SaveToJson(Json::Value& a_Value) override; virtual void Destroy(void) override; @@ -53,7 +53,7 @@ public: cItem GetItem(void) const { return m_Item; } /** Set the item in the flower pot */ - void SetItem(const cItem a_Item) { m_Item = a_Item; } + void SetItem(const cItem & a_Item) { m_Item = a_Item; } // tolua_end diff --git a/src/BlockEntities/FurnaceEntity.cpp b/src/BlockEntities/FurnaceEntity.cpp index 1b1741713..72fd7f2b3 100644 --- a/src/BlockEntities/FurnaceEntity.cpp +++ b/src/BlockEntities/FurnaceEntity.cpp @@ -160,7 +160,7 @@ bool cFurnaceEntity::LoadFromJson(const Json::Value & a_Value) -void cFurnaceEntity::SaveToJson( Json::Value& a_Value ) +void cFurnaceEntity::SaveToJson( Json::Value& a_Value) { a_Value["x"] = m_PosX; a_Value["y"] = m_PosY; diff --git a/src/BlockEntities/HopperEntity.cpp b/src/BlockEntities/HopperEntity.cpp index 7f001c739..48d3b8dcc 100644 --- a/src/BlockEntities/HopperEntity.cpp +++ b/src/BlockEntities/HopperEntity.cpp @@ -157,6 +157,7 @@ bool cHopperEntity::MoveItemsIn(cChunk & a_Chunk, Int64 a_CurrentTick) bool res = false; switch (a_Chunk.GetBlock(m_RelX, m_PosY + 1, m_RelZ)) { + case E_BLOCK_TRAPPED_CHEST: case E_BLOCK_CHEST: { // Chests have special handling because of double-chests @@ -218,7 +219,7 @@ bool cHopperEntity::MovePickupsIn(cChunk & a_Chunk, Int64 a_CurrentTick) } Vector3f EntityPos = a_Entity->GetPosition(); - Vector3f BlockPos(m_Pos.x + 0.5f, (float)m_Pos.y + 1, m_Pos.z + 0.5f); // One block above hopper, and search from center outwards + Vector3f BlockPos(m_Pos.x + 0.5f, (float)m_Pos.y + 1, m_Pos.z + 0.5f); // One block above hopper, and search from center outwards double Distance = (EntityPos - BlockPos).Length(); if (Distance < 0.5) @@ -242,7 +243,7 @@ bool cHopperEntity::MovePickupsIn(cChunk & a_Chunk, Int64 a_CurrentTick) { m_bFoundPickupsAbove = true; m_Contents.SetSlot(i, Item); - a_Pickup->Destroy(); // Kill pickup + a_Pickup->Destroy(); // Kill pickup return true; } @@ -252,11 +253,11 @@ bool cHopperEntity::MovePickupsIn(cChunk & a_Chunk, Int64 a_CurrentTick) int PreviousCount = m_Contents.GetSlot(i).m_ItemCount; - Item.m_ItemCount -= m_Contents.ChangeSlotCount(i, Item.m_ItemCount) - PreviousCount; // Set count to however many items were added + Item.m_ItemCount -= m_Contents.ChangeSlotCount(i, Item.m_ItemCount) - PreviousCount; // Set count to however many items were added if (Item.IsEmpty()) { - a_Pickup->Destroy(); // Kill pickup if all items were added + a_Pickup->Destroy(); // Kill pickup if all items were added } return true; } @@ -294,23 +295,24 @@ bool cHopperEntity::MoveItemsOut(cChunk & a_Chunk, Int64 a_CurrentTick) return false; } - int bx, by, bz; + // Get the coords of the block where to output items: + int OutX, OutY, OutZ; NIBBLETYPE Meta = a_Chunk.GetMeta(m_RelX, m_PosY, m_RelZ); - if (!GetOutputBlockPos(Meta, bx, by, bz)) + if (!GetOutputBlockPos(Meta, OutX, OutY, OutZ)) { // Not attached to another container return false; } - if (by < 0) + if (OutY < 0) { // Cannot output below the zero-th block level return false; } // Convert coords to relative: - int rx = bx - a_Chunk.GetPosX() * cChunkDef::Width; - int rz = bz - a_Chunk.GetPosZ() * cChunkDef::Width; - cChunk * DestChunk = a_Chunk.GetRelNeighborChunkAdjustCoords(rx, rz); + int OutRelX = OutX - a_Chunk.GetPosX() * cChunkDef::Width; + int OutRelZ = OutZ - a_Chunk.GetPosZ() * cChunkDef::Width; + cChunk * DestChunk = a_Chunk.GetRelNeighborChunkAdjustCoords(OutRelX, OutRelZ); if (DestChunk == NULL) { // The destination chunk has been unloaded, don't tick @@ -319,26 +321,33 @@ bool cHopperEntity::MoveItemsOut(cChunk & a_Chunk, Int64 a_CurrentTick) // Call proper moving function, based on the blocktype present at the coords: bool res = false; - switch (DestChunk->GetBlock(rx, by, rz)) + switch (DestChunk->GetBlock(OutRelX, OutY, OutRelZ)) { + case E_BLOCK_TRAPPED_CHEST: case E_BLOCK_CHEST: { // Chests have special handling because of double-chests - res = MoveItemsToChest(*DestChunk, bx, by, bz); + res = MoveItemsToChest(*DestChunk, OutX, OutY, OutZ); break; } case E_BLOCK_LIT_FURNACE: case E_BLOCK_FURNACE: { // Furnaces have special handling because of the direction-to-slot relation - res = MoveItemsToFurnace(*DestChunk, bx, by, bz, Meta); + res = MoveItemsToFurnace(*DestChunk, OutX, OutY, OutZ, Meta); break; } case E_BLOCK_DISPENSER: case E_BLOCK_DROPPER: case E_BLOCK_HOPPER: { - res = MoveItemsToGrid(*(cBlockEntityWithItems *)DestChunk->GetBlockEntity(bx, by, bz)); + cBlockEntityWithItems * BlockEntity = (cBlockEntityWithItems *)DestChunk->GetBlockEntity(OutX, OutY, OutZ); + if (BlockEntity == NULL) + { + LOGWARNING("%s: A block entity was not found where expected at {%d, %d, %d}", __FUNCTION__, OutX, OutY, OutZ); + return false; + } + res = MoveItemsToGrid(*BlockEntity); break; } } @@ -359,13 +368,19 @@ bool cHopperEntity::MoveItemsOut(cChunk & a_Chunk, Int64 a_CurrentTick) /// Moves items from a chest (dblchest) above the hopper into this hopper. Returns true if contents have changed. bool cHopperEntity::MoveItemsFromChest(cChunk & a_Chunk) { - if (MoveItemsFromGrid(*(cChestEntity *)a_Chunk.GetBlockEntity(m_PosX, m_PosY + 1, m_PosZ))) + cChestEntity * MainChest = (cChestEntity *)a_Chunk.GetBlockEntity(m_PosX, m_PosY + 1, m_PosZ); + if (MainChest == NULL) + { + LOGWARNING("%s: A chest entity was not found where expected, at {%d, %d, %d}", __FUNCTION__, m_PosX, m_PosY + 1, m_PosZ); + return false; + } + if (MoveItemsFromGrid(*MainChest)) { // Moved the item from the chest directly above the hopper return true; } - // Check if the chest is a double-chest, if so, try to move from there: + // Check if the chest is a double-chest (chest directly above was empty), if so, try to move from there: static const struct { int x, z; @@ -382,16 +397,29 @@ bool cHopperEntity::MoveItemsFromChest(cChunk & a_Chunk) int x = m_RelX + Coords[i].x; int z = m_RelZ + Coords[i].z; cChunk * Neighbor = a_Chunk.GetRelNeighborChunkAdjustCoords(x, z); - if ( - (Neighbor == NULL) || - (Neighbor->GetBlock(x, m_PosY + 1, z) != E_BLOCK_CHEST) - ) + if (Neighbor == NULL) { continue; } - if (MoveItemsFromGrid(*(cChestEntity *)Neighbor->GetBlockEntity(x, m_PosY, z))) + + BLOCKTYPE Block = Neighbor->GetBlock(x, m_PosY + 1, z); + if (Block != MainChest->GetBlockType()) { - return true; + // Not the same kind of chest + continue; + } + + cChestEntity * SideChest = (cChestEntity *)Neighbor->GetBlockEntity(m_PosX + Coords[i].x, m_PosY + 1, m_PosZ + Coords[i].z); + if (SideChest == NULL) + { + LOGWARNING("%s: A chest entity was not found where expected, at {%d, %d, %d}", __FUNCTION__, m_PosX + Coords[i].x, m_PosY + 1, m_PosZ + Coords[i].z); + } + else + { + if (MoveItemsFromGrid(*SideChest)) + { + return true; + } } return false; } @@ -408,7 +436,11 @@ bool cHopperEntity::MoveItemsFromChest(cChunk & a_Chunk) bool cHopperEntity::MoveItemsFromFurnace(cChunk & a_Chunk) { cFurnaceEntity * Furnace = (cFurnaceEntity *)a_Chunk.GetBlockEntity(m_PosX, m_PosY + 1, m_PosZ); - ASSERT(Furnace != NULL); + if (Furnace == NULL) + { + LOGWARNING("%s: A furnace entity was not found where expected, at {%d, %d, %d}", __FUNCTION__, m_PosX, m_PosY + 1, m_PosZ); + return false; + } // Try move from the output slot: if (MoveItemsFromSlot(*Furnace, cFurnaceEntity::fsOutput, true)) @@ -517,12 +549,19 @@ bool cHopperEntity::MoveItemsFromSlot(cBlockEntityWithItems & a_Entity, int a_Sl bool cHopperEntity::MoveItemsToChest(cChunk & a_Chunk, int a_BlockX, int a_BlockY, int a_BlockZ) { // Try the chest directly connected to the hopper: - if (MoveItemsToGrid(*(cChestEntity *)a_Chunk.GetBlockEntity(a_BlockX, a_BlockY, a_BlockZ))) + cChestEntity * Chest = (cChestEntity *)a_Chunk.GetBlockEntity(a_BlockX, a_BlockY, a_BlockZ); + if (Chest == NULL) + { + LOGWARNING("%s: A chest entity was not found where expected, at {%d, %d, %d}", __FUNCTION__, a_BlockX, a_BlockY, a_BlockZ); + return false; + } + if (MoveItemsToGrid(*Chest)) { + // Chest block directly connected was not full return true; } - // Check if the chest is a double-chest, if so, try to move into the other half: + // Check if the chest is a double-chest (chest block directly connected was full), if so, try to move into the other half: static const struct { int x, z; @@ -534,19 +573,32 @@ bool cHopperEntity::MoveItemsToChest(cChunk & a_Chunk, int a_BlockX, int a_Block {0, 1}, {0, -1}, } ; + int RelX = a_BlockX - a_Chunk.GetPosX() * cChunkDef::Width; + int RelZ = a_BlockZ - a_Chunk.GetPosZ() * cChunkDef::Width; for (size_t i = 0; i < ARRAYCOUNT(Coords); i++) { - int x = m_RelX + Coords[i].x; - int z = m_RelZ + Coords[i].z; + int x = RelX + Coords[i].x; + int z = RelZ + Coords[i].z; cChunk * Neighbor = a_Chunk.GetRelNeighborChunkAdjustCoords(x, z); - if ( - (Neighbor == NULL) || - (Neighbor->GetBlock(x, m_PosY + 1, z) != E_BLOCK_CHEST) - ) + if (Neighbor == NULL) + { + continue; + } + + BLOCKTYPE Block = Neighbor->GetBlock(x, a_BlockY, z); + if (Block != Chest->GetBlockType()) + { + // Not the same kind of chest + continue; + } + + Chest = (cChestEntity *)Neighbor->GetBlockEntity(a_BlockX + Coords[i].x, a_BlockY, a_BlockZ + Coords[i].z); + if (Chest == NULL) { + LOGWARNING("%s: A chest entity was not found where expected, at {%d, %d, %d} (%d, %d)", __FUNCTION__, a_BlockX + Coords[i].x, a_BlockY, a_BlockZ + Coords[i].z, x, z); continue; } - if (MoveItemsToGrid(*(cChestEntity *)Neighbor->GetBlockEntity(a_BlockX, a_BlockY, a_BlockZ))) + if (MoveItemsToGrid(*Chest)) { return true; } diff --git a/src/BlockEntities/HopperEntity.h b/src/BlockEntities/HopperEntity.h index 6ef98f43a..8e856fcda 100644 --- a/src/BlockEntities/HopperEntity.h +++ b/src/BlockEntities/HopperEntity.h @@ -22,7 +22,8 @@ class cHopperEntity : typedef cBlockEntityWithItems super; public: - enum { + enum + { ContentsHeight = 1, ContentsWidth = 5, TICKS_PER_TRANSFER = 8, ///< How many ticks at minimum between two item transfers to or from the hopper diff --git a/src/BlockEntities/JukeboxEntity.h b/src/BlockEntities/JukeboxEntity.h index 3d1d604f7..d677d340f 100644 --- a/src/BlockEntities/JukeboxEntity.h +++ b/src/BlockEntities/JukeboxEntity.h @@ -19,7 +19,7 @@ namespace Json // tolua_begin -class cJukeboxEntity : +class cJukeboxEntity : public cBlockEntity { typedef cBlockEntity super; @@ -58,7 +58,7 @@ public: static const char * GetClassStatic(void) { return "cJukeboxEntity"; } virtual void UsedBy(cPlayer * a_Player) override; - virtual void SendTo(cClientHandle &) override { }; + virtual void SendTo(cClientHandle &) override {} private: int m_Record; diff --git a/src/BlockEntities/MobHeadEntity.cpp b/src/BlockEntities/MobHeadEntity.cpp index dc9c18d58..ce895eb6f 100644 --- a/src/BlockEntities/MobHeadEntity.cpp +++ b/src/BlockEntities/MobHeadEntity.cpp @@ -70,6 +70,8 @@ void cMobHeadEntity::SetOwner(const AString & a_Owner) void cMobHeadEntity::SendTo(cClientHandle & a_Client) { + cWorld * World = a_Client.GetPlayer()->GetWorld(); + a_Client.SendBlockChange(m_PosX, m_PosY, m_PosZ, m_BlockType, World->GetBlockMeta(m_PosX, m_PosY, m_PosZ)); a_Client.SendUpdateBlockEntity(*this); } diff --git a/src/BlockEntities/MobHeadEntity.h b/src/BlockEntities/MobHeadEntity.h index 367eb15e7..f91a3cc9e 100644 --- a/src/BlockEntities/MobHeadEntity.h +++ b/src/BlockEntities/MobHeadEntity.h @@ -25,7 +25,7 @@ namespace Json // tolua_begin -class cMobHeadEntity : +class cMobHeadEntity : public cBlockEntity { typedef cBlockEntity super; @@ -37,8 +37,8 @@ public: /** Creates a new mob head entity at the specified block coords. a_World may be NULL */ cMobHeadEntity(int a_BlockX, int a_BlockY, int a_BlockZ, cWorld * a_World); - bool LoadFromJson( const Json::Value& a_Value ); - virtual void SaveToJson(Json::Value& a_Value ) override; + bool LoadFromJson( const Json::Value& a_Value); + virtual void SaveToJson(Json::Value& a_Value) override; // tolua_begin diff --git a/src/BlockEntities/NoteEntity.cpp b/src/BlockEntities/NoteEntity.cpp index 58b05a324..95145c117 100644 --- a/src/BlockEntities/NoteEntity.cpp +++ b/src/BlockEntities/NoteEntity.cpp @@ -91,7 +91,7 @@ void cNoteEntity::MakeSound(void) // TODO: instead of calculating the power function over and over, make a precalculated table - there's only 24 pitches after all float calcPitch = pow(2.0f, ((float)m_Pitch - 12.0f) / 12.0f); - m_World->BroadcastSoundEffect(sampleName, m_PosX * 8, m_PosY * 8, m_PosZ * 8, 3.0f, calcPitch); + m_World->BroadcastSoundEffect(sampleName, (double)m_PosX, (double)m_PosY, (double)m_PosZ, 3.0f, calcPitch); } diff --git a/src/BlockEntities/NoteEntity.h b/src/BlockEntities/NoteEntity.h index b698899c0..e8497da3e 100644 --- a/src/BlockEntities/NoteEntity.h +++ b/src/BlockEntities/NoteEntity.h @@ -28,7 +28,7 @@ enum ENUM_NOTE_INSTRUMENTS // tolua_begin -class cNoteEntity : +class cNoteEntity : public cBlockEntity { typedef cBlockEntity super; @@ -52,7 +52,7 @@ public: // tolua_end virtual void UsedBy(cPlayer * a_Player) override; - virtual void SendTo(cClientHandle &) override { }; + virtual void SendTo(cClientHandle &) override {} static const char * GetClassStatic(void) { return "cNoteEntity"; } diff --git a/src/BlockEntities/SignEntity.h b/src/BlockEntities/SignEntity.h index 80c7bbfdf..33af100a4 100644 --- a/src/BlockEntities/SignEntity.h +++ b/src/BlockEntities/SignEntity.h @@ -25,7 +25,7 @@ namespace Json // tolua_begin -class cSignEntity : +class cSignEntity : public cBlockEntity { typedef cBlockEntity super; @@ -37,8 +37,8 @@ public: /// Creates a new empty sign entity at the specified block coords and block type (wall or standing). a_World may be NULL cSignEntity(BLOCKTYPE a_BlockType, int a_X, int a_Y, int a_Z, cWorld * a_World); - bool LoadFromJson( const Json::Value& a_Value ); - virtual void SaveToJson(Json::Value& a_Value ) override; + bool LoadFromJson( const Json::Value& a_Value); + virtual void SaveToJson(Json::Value& a_Value) override; // tolua_begin |