summaryrefslogtreecommitdiffstats
path: root/source/BlockEntities/ChestEntity.cpp
diff options
context:
space:
mode:
authormadmaxoft@gmail.com <madmaxoft@gmail.com@0a769ca7-a7f5-676a-18bf-c427514a06d6>2013-05-28 21:12:47 +0200
committermadmaxoft@gmail.com <madmaxoft@gmail.com@0a769ca7-a7f5-676a-18bf-c427514a06d6>2013-05-28 21:12:47 +0200
commit9be27992e211631cb4e72619c78c5c23397b2a9c (patch)
treed981f1123709c10db9cf3432ccbb793285226f2e /source/BlockEntities/ChestEntity.cpp
parentBlock entities now receive the cChunk param in their Tick() function (diff)
downloadcuberite-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.cpp179
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));
+}
+
+
+
+