summaryrefslogtreecommitdiffstats
path: root/src/BlockEntities
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--src/BlockEntities/BlockEntity.cpp10
-rw-r--r--src/BlockEntities/ChestEntity.cpp7
-rw-r--r--src/BlockEntities/ChestEntity.h18
-rw-r--r--src/BlockEntities/EnderChestEntity.cpp93
-rw-r--r--src/BlockEntities/EnderChestEntity.h44
-rw-r--r--src/BlockEntities/HopperEntity.cpp33
6 files changed, 92 insertions, 113 deletions
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/ChestEntity.cpp b/src/BlockEntities/ChestEntity.cpp
index cb9cc89bf..ca164464c 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);
}
diff --git a/src/BlockEntities/ChestEntity.h b/src/BlockEntities/ChestEntity.h
index ce16f84d7..310618504 100644
--- a/src/BlockEntities/ChestEntity.h
+++ b/src/BlockEntities/ChestEntity.h
@@ -34,8 +34,8 @@ public:
// 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 +48,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/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..04af67683 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;
-
-public:
- enum {
- ContentsHeight = 3,
- ContentsWidth = 9,
- } ;
+ typedef cBlockEntity super;
+public:
// tolua_end
- /// Constructor used for normal operation
- cEnderChestEntity(int a_BlockX, int a_BlockY, int a_BlockZ, cWorld * a_World);
-
+ 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/HopperEntity.cpp b/src/BlockEntities/HopperEntity.cpp
index 5856f20d1..aaf82d150 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
@@ -322,6 +323,7 @@ bool cHopperEntity::MoveItemsOut(cChunk & a_Chunk, Int64 a_CurrentTick)
bool res = false;
switch (DestChunk->GetBlock(OutRelX, OutY, OutRelZ))
{
+ case E_BLOCK_TRAPPED_CHEST:
case E_BLOCK_CHEST:
{
// Chests have special handling because of double-chests
@@ -378,7 +380,7 @@ bool cHopperEntity::MoveItemsFromChest(cChunk & a_Chunk)
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;
@@ -395,13 +397,18 @@ 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;
}
+
+ BLOCKTYPE Block = Neighbor->GetBlock(x, m_PosY + 1, z);
+ if (Block != Chest->GetBlockType())
+ {
+ // Not the same kind of chest
+ continue;
+ }
+
Chest = (cChestEntity *)Neighbor->GetBlockEntity(m_PosX + Coords[i].x, m_PosY + 1, m_PosZ + Coords[i].z);
if (Chest == NULL)
{
@@ -550,10 +557,11 @@ bool cHopperEntity::MoveItemsToChest(cChunk & a_Chunk, int a_BlockX, int a_Block
}
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;
@@ -572,13 +580,18 @@ bool cHopperEntity::MoveItemsToChest(cChunk & a_Chunk, int a_BlockX, int a_Block
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, a_BlockY, 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)
{