diff --git a/source/Bindings.cpp b/source/Bindings.cpp index 49eba37e5..77eea9269 100644 --- a/source/Bindings.cpp +++ b/source/Bindings.cpp @@ -1,6 +1,6 @@ /* ** Lua binding: AllToLua -** Generated automatically by tolua++-1.0.92 on 10/20/12 13:37:50. +** Generated automatically by tolua++-1.0.92 on 10/20/12 23:51:02. */ #ifndef __cplusplus @@ -296,9 +296,9 @@ static int tolua_AllToLua_cStairs_RotationToMetaData00(lua_State* tolua_S) #endif { float a_Rotation = ((float) tolua_tonumber(tolua_S,2,0)); - int a_Direction = ((int) tolua_tonumber(tolua_S,3,0)); + char a_BlockFace = ((char) tolua_tonumber(tolua_S,3,0)); { - char tolua_ret = (char) cStairs::RotationToMetaData(a_Rotation,a_Direction); + unsigned char tolua_ret = (unsigned char) cStairs::RotationToMetaData(a_Rotation,a_BlockFace); tolua_pushnumber(tolua_S,(lua_Number)tolua_ret); } } @@ -14237,38 +14237,6 @@ static int tolua_AllToLua_cChestEntity_UsedBy00(lua_State* tolua_S) } #endif //#ifndef TOLUA_DISABLE -/* method: GetChestHeight of class cChestEntity */ -#ifndef TOLUA_DISABLE_tolua_AllToLua_cChestEntity_GetChestHeight00 -static int tolua_AllToLua_cChestEntity_GetChestHeight00(lua_State* tolua_S) -{ -#ifndef TOLUA_RELEASE - tolua_Error tolua_err; - if ( - !tolua_isusertype(tolua_S,1,"cChestEntity",0,&tolua_err) || - !tolua_isnoobj(tolua_S,2,&tolua_err) - ) - goto tolua_lerror; - else -#endif - { - cChestEntity* self = (cChestEntity*) tolua_tousertype(tolua_S,1,0); -#ifndef TOLUA_RELEASE - if (!self) tolua_error(tolua_S,"invalid 'self' in function 'GetChestHeight'", NULL); -#endif - { - int tolua_ret = (int) self->GetChestHeight(); - tolua_pushnumber(tolua_S,(lua_Number)tolua_ret); - } - } - return 1; -#ifndef TOLUA_RELEASE - tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'GetChestHeight'.",&tolua_err); - return 0; -#endif -} -#endif //#ifndef TOLUA_DISABLE - /* get function: __cBlockEntityWindowOwner__ of class cChestEntity */ #ifndef TOLUA_DISABLE_tolua_get_cChestEntity___cBlockEntityWindowOwner__ static int tolua_get_cChestEntity___cBlockEntityWindowOwner__(lua_State* tolua_S) @@ -22995,7 +22963,6 @@ TOLUA_API int tolua_AllToLua_open (lua_State* tolua_S) tolua_function(tolua_S,"GetSlot",tolua_AllToLua_cChestEntity_GetSlot00); tolua_function(tolua_S,"SetSlot",tolua_AllToLua_cChestEntity_SetSlot00); tolua_function(tolua_S,"UsedBy",tolua_AllToLua_cChestEntity_UsedBy00); - tolua_function(tolua_S,"GetChestHeight",tolua_AllToLua_cChestEntity_GetChestHeight00); tolua_variable(tolua_S,"__cBlockEntityWindowOwner__",tolua_get_cChestEntity___cBlockEntityWindowOwner__,NULL); tolua_endmodule(tolua_S); tolua_cclass(tolua_S,"Lua__cChestEntity","Lua__cChestEntity","cChestEntity",NULL); diff --git a/source/Bindings.h b/source/Bindings.h index 158b66767..b69b590a7 100644 --- a/source/Bindings.h +++ b/source/Bindings.h @@ -1,6 +1,6 @@ /* ** Lua binding: AllToLua -** Generated automatically by tolua++-1.0.92 on 10/20/12 13:37:51. +** Generated automatically by tolua++-1.0.92 on 10/20/12 23:51:03. */ /* Exported function */ diff --git a/source/ChestEntity.cpp b/source/ChestEntity.cpp index 262217da8..2f038897c 100644 --- a/source/ChestEntity.cpp +++ b/source/ChestEntity.cpp @@ -22,10 +22,8 @@ class cRoot; -cChestEntity::cChestEntity(int a_X, int a_Y, int a_Z, cWorld * a_World) - : cBlockEntity( E_BLOCK_CHEST, a_X, a_Y, a_Z, a_World) - , m_TopChest( false ) - , m_JoinedChest( NULL ) +cChestEntity::cChestEntity(int a_BlockX, int a_BlockY, int a_BlockZ, cWorld * a_World) : + cBlockEntity(E_BLOCK_CHEST, a_BlockX, a_BlockY, a_BlockZ, a_World) { m_Content = new cItem[ c_ChestHeight * c_ChestWidth ]; SetBlockEntity(this); // cBlockEntityWindowOwner @@ -37,51 +35,45 @@ cChestEntity::cChestEntity(int a_X, int a_Y, int a_Z, cWorld * a_World) cChestEntity::~cChestEntity() { - if( GetWindow() ) + cWindow * Window = GetWindow(); + if (Window != NULL) { - GetWindow()->OwnerDestroyed(); + Window->OwnerDestroyed(); } - if( m_Content ) - { - delete [] m_Content; - } + delete [] m_Content; } -void cChestEntity::Destroy() +void cChestEntity::Destroy(void) { // Drop items cItems Pickups; - for( int i = 0; i < c_ChestHeight * c_ChestWidth; ++i ) + for (int i = 0; i < c_ChestHeight * c_ChestWidth; ++i) { - if( !m_Content[i].IsEmpty() ) + if (!m_Content[i].IsEmpty()) { Pickups.push_back(m_Content[i]); m_Content[i].Empty(); } } m_World->SpawnItemPickups(Pickups, m_PosX, m_PosY, m_PosZ); - if (m_JoinedChest) - { - m_JoinedChest->RemoveJoinedChest(this); - } } -const cItem * cChestEntity::GetSlot( int a_Slot ) const +const cItem * cChestEntity::GetSlot(int a_Slot) const { - if( a_Slot > -1 && a_Slot < c_ChestHeight*c_ChestWidth ) + if ((a_Slot > -1) && (a_Slot < c_ChestHeight * c_ChestWidth)) { - return &m_Content[ a_Slot ]; + return &m_Content[a_Slot]; } - return 0; + return NULL; } @@ -112,7 +104,7 @@ void cChestEntity::SetSlot(int a_Slot, const cItem & a_Item) -bool cChestEntity::LoadFromJson( const Json::Value& a_Value ) +bool cChestEntity::LoadFromJson(const Json::Value & a_Value) { m_PosX = a_Value.get("x", 0).asInt(); m_PosY = a_Value.get("y", 0).asInt(); @@ -120,7 +112,7 @@ bool cChestEntity::LoadFromJson( const Json::Value& a_Value ) Json::Value AllSlots = a_Value.get("Slots", 0); int SlotIdx = 0; - for( Json::Value::iterator itr = AllSlots.begin(); itr != AllSlots.end(); ++itr ) + for (Json::Value::iterator itr = AllSlots.begin(); itr != AllSlots.end(); ++itr) { cItem Item; Item.FromJson( *itr ); @@ -134,7 +126,7 @@ bool cChestEntity::LoadFromJson( const Json::Value& a_Value ) -void cChestEntity::SaveToJson( Json::Value& a_Value ) +void cChestEntity::SaveToJson(Json::Value & a_Value) { a_Value["x"] = m_PosX; a_Value["y"] = m_PosY; @@ -142,12 +134,15 @@ void cChestEntity::SaveToJson( Json::Value& a_Value ) unsigned int NumSlots = c_ChestHeight*c_ChestWidth; Json::Value AllSlots; - for(unsigned int i = 0; i < NumSlots; i++) + for (unsigned int i = 0; i < NumSlots; i++) { Json::Value Slot; - const cItem * Item = GetSlot( i ); - if( Item ) Item->GetJson( Slot ); - AllSlots.append( Slot ); + const cItem * Item = GetSlot(i); + if (Item != NULL) + { + Item->GetJson(Slot); + } + AllSlots.append(Slot); } a_Value["Slots"] = AllSlots; } @@ -172,7 +167,7 @@ void cChestEntity::UsedBy(cPlayer * a_Player) { if (GetWindow() == NULL) { - OpenWindow(new cChestWindow(m_PosX, m_PosY, m_PosZ, this)); + OpenNewWindow(); } if (GetWindow()) { @@ -196,28 +191,51 @@ void cChestEntity::UsedBy(cPlayer * a_Player) -cItem * cChestEntity::GetContents(bool a_OnlyThis) +void cChestEntity::OpenNewWindow(void) { - if (m_JoinedChest && !a_OnlyThis) + // Callback for opening together with neighbor chest: + class cOpenDouble : + public cChestCallback { - // TODO: "Combined" memory leaks here - cItem * Combined = new cItem[GetChestHeight() * c_ChestWidth]; - cItem * first = (m_TopChest) ? GetContents(true) : m_JoinedChest->GetContents(true); - cItem * second = (!m_TopChest) ? GetContents(true) : m_JoinedChest->GetContents(true); - for (int i = 0; i < GetChestHeight() * c_ChestWidth; i++) + cChestEntity * m_ThisChest; + public: + cOpenDouble(cChestEntity * a_ThisChest) : + m_ThisChest(a_ThisChest) { - int index = i % (c_ChestHeight * c_ChestWidth); - if (i < c_ChestHeight * c_ChestWidth) - Combined[index] = first[index]; - else - Combined[index] = second[index]; } - return Combined; - } - else + + 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) + ) { - return m_Content; + // 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)); } diff --git a/source/ChestEntity.h b/source/ChestEntity.h index 2269e6614..82d1e7b50 100644 --- a/source/ChestEntity.h +++ b/source/ChestEntity.h @@ -27,37 +27,31 @@ class cChestEntity : // tolua_export public cBlockEntityWindowOwner // tolua_export { // tolua_export public: - cChestEntity(int a_X, int a_Y, int a_Z, cWorld * a_World); + cChestEntity(int a_BlockX, int a_BlockY, int a_BlockZ, cWorld * a_World); virtual ~cChestEntity(); virtual void Destroy(); - void HandleData( cNBTData* a_NBTData ); - - const cItem * GetSlot( int a_Slot ) const; //tolua_export - void SetSlot(int a_Slot, const cItem & a_Item ); //tolua_export + const cItem * GetSlot(int a_Slot) const; // tolua_export + void SetSlot(int a_Slot, const cItem & a_Item ); // tolua_export 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); // tolua_export + + /// Opens a new chest window for this chests. Scans for neighbors to open a double chest window, if appropriate. + void OpenNewWindow(void); - virtual void UsedBy( cPlayer * a_Player ); //tolua_export - - cChestEntity * GetJoinedChest() { return m_JoinedChest; } // NOTE: Is this a safe function? Should it be exported to Lua? - void SetJoinedChest(cChestEntity *a_Chest) { m_JoinedChest = a_Chest; } - void RemoveJoinedChest(cChestEntity *a_Chest) { if (m_JoinedChest && m_JoinedChest == a_Chest) { m_JoinedChest = NULL; m_TopChest = false; } } - - int GetChestHeight() { return ((m_JoinedChest) ? c_ChestHeight * 2 : c_ChestHeight); } //tolua_export - cItem * GetContents(bool a_OnlyThis = false); + cItem * GetContents(void) { return m_Content; } static const int c_ChestWidth = 9; static const int c_ChestHeight = 3; private: - cItem * m_Content; - bool m_TopChest; - cChestEntity * m_JoinedChest; + cItem * m_Content; }; //tolua_export diff --git a/source/Protocol/Protocol132.cpp b/source/Protocol/Protocol132.cpp index 0a2e7d0c9..2e5803273 100644 --- a/source/Protocol/Protocol132.cpp +++ b/source/Protocol/Protocol132.cpp @@ -52,19 +52,19 @@ const int MAX_ENC_LEN = 512; // Maximum size of the encrypted message; should b enum { - PACKET_KEEP_ALIVE = 0x00, - PACKET_LOGIN = 0x01, - PACKET_ENTITY_EQUIPMENT = 0x05, - PACKET_COMPASS = 0x06, - PACKET_PLAYER_SPAWN = 0x14, - PACKET_COLLECT_PICKUP = 0x16, - PACKET_SPAWN_MOB = 0x18, - PACKET_DESTROY_ENTITIES = 0x1d, - PACKET_CHUNK_DATA = 0x33, - PACKET_BLOCK_CHANGE = 0x35, - PACKET_BLOCK_ACTION = 0x36, - PACKET_BLOCK_BREAK_ANIM = 0x37, - PACKET_SOUND_EFFECT = 0x3e + PACKET_KEEP_ALIVE = 0x00, + PACKET_LOGIN = 0x01, + PACKET_ENTITY_EQUIPMENT = 0x05, + PACKET_COMPASS = 0x06, + PACKET_PLAYER_SPAWN = 0x14, + PACKET_COLLECT_PICKUP = 0x16, + PACKET_SPAWN_MOB = 0x18, + PACKET_DESTROY_ENTITIES = 0x1d, + PACKET_CHUNK_DATA = 0x33, + PACKET_BLOCK_CHANGE = 0x35, + PACKET_BLOCK_ACTION = 0x36, + PACKET_BLOCK_BREAK_ANIM = 0x37, + PACKET_SOUND_EFFECT = 0x3e } ; diff --git a/source/UI/Window.cpp b/source/UI/Window.cpp index 0c955ba57..dc5587390 100644 --- a/source/UI/Window.cpp +++ b/source/UI/Window.cpp @@ -155,8 +155,6 @@ void cWindow::OpenedByPlayer(cPlayer & a_Player) } // for itr - m_SlotAreas[] } - // TODO: Notify all areas that a new player has opened the window - a_Player.GetClientHandle()->SendWindowOpen(m_WindowID, m_WindowType, m_WindowTitle, GetNumSlots() - c_NumInventorySlots); } @@ -405,20 +403,43 @@ cCraftingWindow::cCraftingWindow(int a_BlockX, int a_BlockY, int a_BlockZ) : /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // cChestWindow: -cChestWindow::cChestWindow(int a_BlockX, int a_BlockY, int a_BlockZ, cChestEntity * a_Chest) : - cWindow(cWindow::Chest, "MCS-Chest"), +cChestWindow::cChestWindow(cChestEntity * a_Chest) : + cWindow(cWindow::Chest, "MCS-SingleChest"), m_World(a_Chest->GetWorld()), - m_BlockX(a_BlockX), - m_BlockY(a_BlockY), - m_BlockZ(a_BlockZ) + m_BlockX(a_Chest->GetPosX()), + m_BlockY(a_Chest->GetPosY()), + m_BlockZ(a_Chest->GetPosZ()) { m_SlotAreas.push_back(new cSlotAreaChest(a_Chest, *this)); - - // TODO: Double chests - m_SlotAreas.push_back(new cSlotAreaInventory(*this)); m_SlotAreas.push_back(new cSlotAreaHotBar(*this)); + // Play the opening sound: + m_World->BroadcastSoundEffect("random.chestopen", m_BlockX * 8, m_BlockY * 8, m_BlockZ * 8, 1, 1); + + // Send out the chest-open packet: + m_World->BroadcastBlockAction(m_BlockX, m_BlockY, m_BlockZ, 1, 1, E_BLOCK_CHEST); +} + + + + + +cChestWindow::cChestWindow(cChestEntity * a_PrimaryChest, cChestEntity * a_SecondaryChest) : + cWindow(cWindow::Chest, "MCS-DoubleChest"), + m_World(a_PrimaryChest->GetWorld()), + m_BlockX(a_PrimaryChest->GetPosX()), + m_BlockY(a_PrimaryChest->GetPosY()), + m_BlockZ(a_PrimaryChest->GetPosZ()) +{ + m_SlotAreas.push_back(new cSlotAreaChest(a_PrimaryChest, *this)); + m_SlotAreas.push_back(new cSlotAreaChest(a_SecondaryChest, *this)); + m_SlotAreas.push_back(new cSlotAreaInventory(*this)); + m_SlotAreas.push_back(new cSlotAreaHotBar(*this)); + + // Play the opening sound: + m_World->BroadcastSoundEffect("random.chestopen", m_BlockX * 8, m_BlockY * 8, m_BlockZ * 8, 1, 1); + // Send out the chest-open packet: m_World->BroadcastBlockAction(m_BlockX, m_BlockY, m_BlockZ, 1, 1, E_BLOCK_CHEST); } @@ -431,6 +452,8 @@ cChestWindow::~cChestWindow() { // Send out the chest-close packet: m_World->BroadcastBlockAction(m_BlockX, m_BlockY, m_BlockZ, 1, 0, E_BLOCK_CHEST); + + m_World->BroadcastSoundEffect("random.chestclosed", m_BlockX * 8, m_BlockY * 8, m_BlockZ * 8, 1, 1); } diff --git a/source/UI/Window.h b/source/UI/Window.h index 8caab3bd1..a570ed480 100644 --- a/source/UI/Window.h +++ b/source/UI/Window.h @@ -152,7 +152,8 @@ class cChestWindow : public cWindow { public: - cChestWindow(int a_BlockX, int a_BlockY, int a_BlockZ, cChestEntity * a_Chest); + cChestWindow(cChestEntity * a_Chest); + cChestWindow(cChestEntity * a_PrimaryChest, cChestEntity * a_SecondaryChest); ~cChestWindow(); protected: