diff options
Diffstat (limited to 'src/BlockEntities')
-rw-r--r-- | src/BlockEntities/BlockEntity.cpp | 10 | ||||
-rw-r--r-- | src/BlockEntities/ChestEntity.cpp | 7 | ||||
-rw-r--r-- | src/BlockEntities/ChestEntity.h | 18 | ||||
-rw-r--r-- | src/BlockEntities/EnderChestEntity.cpp | 93 | ||||
-rw-r--r-- | src/BlockEntities/EnderChestEntity.h | 44 | ||||
-rw-r--r-- | src/BlockEntities/HopperEntity.cpp | 33 |
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) { |