diff options
author | madmaxoft@gmail.com <madmaxoft@gmail.com@0a769ca7-a7f5-676a-18bf-c427514a06d6> | 2013-05-28 21:12:47 +0200 |
---|---|---|
committer | madmaxoft@gmail.com <madmaxoft@gmail.com@0a769ca7-a7f5-676a-18bf-c427514a06d6> | 2013-05-28 21:12:47 +0200 |
commit | 9be27992e211631cb4e72619c78c5c23397b2a9c (patch) | |
tree | d981f1123709c10db9cf3432ccbb793285226f2e /source/BlockEntities/ChestEntity.cpp | |
parent | Block entities now receive the cChunk param in their Tick() function (diff) | |
download | cuberite-9be27992e211631cb4e72619c78c5c23397b2a9c.tar cuberite-9be27992e211631cb4e72619c78c5c23397b2a9c.tar.gz cuberite-9be27992e211631cb4e72619c78c5c23397b2a9c.tar.bz2 cuberite-9be27992e211631cb4e72619c78c5c23397b2a9c.tar.lz cuberite-9be27992e211631cb4e72619c78c5c23397b2a9c.tar.xz cuberite-9be27992e211631cb4e72619c78c5c23397b2a9c.tar.zst cuberite-9be27992e211631cb4e72619c78c5c23397b2a9c.zip |
Diffstat (limited to 'source/BlockEntities/ChestEntity.cpp')
-rw-r--r-- | source/BlockEntities/ChestEntity.cpp | 179 |
1 files changed, 179 insertions, 0 deletions
diff --git a/source/BlockEntities/ChestEntity.cpp b/source/BlockEntities/ChestEntity.cpp new file mode 100644 index 000000000..769fadc22 --- /dev/null +++ b/source/BlockEntities/ChestEntity.cpp @@ -0,0 +1,179 @@ + +#include "Globals.h" // NOTE: MSVC stupidness requires this to be the same across all modules + +#include "ChestEntity.h" +#include "../Item.h" +#include "../Player.h" +#include "../UI/Window.h" +#include "../Noise.h" +#include <json/json.h> + + + + + +cChestEntity::cChestEntity(int a_BlockX, int a_BlockY, int a_BlockZ) : + super(E_BLOCK_CHEST, a_BlockX, a_BlockY, a_BlockZ, ContentsWidth, ContentsHeight, NULL) +{ + cBlockEntityWindowOwner::SetBlockEntity(this); +} + + + + + +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) +{ + cBlockEntityWindowOwner::SetBlockEntity(this); +} + + + + + +cChestEntity::~cChestEntity() +{ + cWindow * Window = GetWindow(); + if (Window != NULL) + { + Window->OwnerDestroyed(); + } +} + + + + + +bool cChestEntity::LoadFromJson(const Json::Value & a_Value) +{ + 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) + { + cItem Item; + Item.FromJson( *itr ); + SetSlot( SlotIdx, Item ); + SlotIdx++; + } + return true; +} + + + + + +void cChestEntity::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--) + { + Json::Value Slot; + m_Contents.GetSlot(i).GetJson(Slot); + AllSlots.append(Slot); + } + a_Value["Slots"] = AllSlots; +} + + + + + +void cChestEntity::SendTo(cClientHandle & a_Client) +{ + // 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); +} + + + + + +void cChestEntity::UsedBy(cPlayer * a_Player) +{ + if (GetWindow() == NULL) + { + OpenNewWindow(); + } + if (GetWindow()) + { + if( a_Player->GetWindow() != GetWindow() ) + { + a_Player->OpenWindow( GetWindow() ); + GetWindow()->SendWholeWindow(*a_Player->GetClientHandle()); + } + } + + // 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_PosY, m_PosZ, ChunkX, ChunkZ); + m_World->MarkChunkDirty(ChunkX, ChunkZ); +} + + + + + +void cChestEntity::OpenNewWindow(void) +{ + // Callback for opening together with neighbor chest: + class cOpenDouble : + public cChestCallback + { + cChestEntity * m_ThisChest; + public: + cOpenDouble(cChestEntity * a_ThisChest) : + m_ThisChest(a_ThisChest) + { + } + + virtual bool Item(cChestEntity * a_Chest) override + { + // The primary chest should eb the one with lesser X or Z coord: + cChestEntity * Primary = a_Chest; + cChestEntity * Secondary = m_ThisChest; + if ( + (Primary->GetPosX() > Secondary->GetPosX()) || + (Primary->GetPosZ() > Secondary->GetPosZ()) + ) + { + std::swap(Primary, Secondary); + } + m_ThisChest->OpenWindow(new cChestWindow(Primary, Secondary)); + return false; + } + } ; + + // Scan neighbors for adjacent chests: + cOpenDouble OpenDbl(this); + 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) + ) + { + // The double-chest window has been opened in the callback + return; + } + + // There is no chest neighbor, open a single-chest window: + OpenWindow(new cChestWindow(this)); +} + + + + |