1
0

Fixes problems with windows:

- Changed cPlayer:OpenWindow to accept a ref, tolua adds a nil check
- Close open lua window in destructor, to avoid dangling pointers
This commit is contained in:
Lukas Pioch 2017-05-29 21:33:30 +02:00
parent 2b699dc749
commit 7922e6addb
15 changed files with 39 additions and 18 deletions

View File

@ -4,8 +4,10 @@
#include "Globals.h" #include "Globals.h"
#include "LuaWindow.h" #include "LuaWindow.h"
#include "../Entities/Player.h"
#include "../UI/SlotArea.h" #include "../UI/SlotArea.h"
#include "PluginLua.h" #include "PluginLua.h"
#include "Root.h"
#include "lua/src/lauxlib.h" // Needed for LUA_REFNIL #include "lua/src/lauxlib.h" // Needed for LUA_REFNIL
@ -51,6 +53,24 @@ cLuaWindow::~cLuaWindow()
{ {
m_Contents.RemoveListener(*this); m_Contents.RemoveListener(*this);
// Close open lua window from players, to avoid dangling pointers
class cPlayerCallback : public cPlayerListCallback
{
virtual bool Item(cPlayer * a_Player)
{
if (a_Player->GetWindow() == m_LuaWindow)
{
a_Player->CloseWindow(false);
}
return false;
}
cLuaWindow * m_LuaWindow;
public:
cPlayerCallback(cLuaWindow & a_LuaWindow) { m_LuaWindow = &a_LuaWindow; }
} PlayerCallback(*this);
cRoot::Get()->ForEachPlayer(PlayerCallback);
// Must delete slot areas now, because they are referencing this->m_Contents and would try to access it in cWindow's // Must delete slot areas now, because they are referencing this->m_Contents and would try to access it in cWindow's
// destructor, when the member is already gone. // destructor, when the member is already gone.
for (cSlotAreas::iterator itr = m_SlotAreas.begin(), end = m_SlotAreas.end(); itr != end; ++itr) for (cSlotAreas::iterator itr = m_SlotAreas.begin(), end = m_SlotAreas.end(); itr != end; ++itr)

View File

@ -15,7 +15,8 @@
#include "../ItemGrid.h" #include "../ItemGrid.h"
class cPlayer;
typedef cItemCallback<cPlayer> cPlayerListCallback;
/** A window that has been created by a Lua plugin and is handled entirely by that plugin /** A window that has been created by a Lua plugin and is handled entirely by that plugin

View File

@ -297,7 +297,7 @@ bool cBeaconEntity::UsedBy(cPlayer * a_Player)
// if (a_Player->GetWindow() != Window) // if (a_Player->GetWindow() != Window)
// -> Because mojang doesn't send a 'close window' packet when you click the cancel button in the beacon inventory ... // -> Because mojang doesn't send a 'close window' packet when you click the cancel button in the beacon inventory ...
{ {
a_Player->OpenWindow(Window); a_Player->OpenWindow(*Window);
} }
} }
return true; return true;

View File

@ -65,7 +65,7 @@ bool cBrewingstandEntity::UsedBy(cPlayer * a_Player)
{ {
if (a_Player->GetWindow() != Window) if (a_Player->GetWindow() != Window)
{ {
a_Player->OpenWindow(Window); a_Player->OpenWindow(*Window);
} }
} }

View File

@ -101,7 +101,7 @@ bool cChestEntity::UsedBy(cPlayer * a_Player)
{ {
if (a_Player->GetWindow() != Window) if (a_Player->GetWindow() != Window)
{ {
a_Player->OpenWindow(Window); a_Player->OpenWindow(*Window);
} }
} }

View File

@ -153,7 +153,7 @@ bool cDropSpenserEntity::UsedBy(cPlayer * a_Player)
{ {
if (a_Player->GetWindow() != Window) if (a_Player->GetWindow() != Window)
{ {
a_Player->OpenWindow(Window); a_Player->OpenWindow(*Window);
} }
} }
return true; return true;

View File

@ -66,7 +66,7 @@ bool cEnderChestEntity::UsedBy(cPlayer * a_Player)
{ {
if (a_Player->GetWindow() != Window) if (a_Player->GetWindow() != Window)
{ {
a_Player->OpenWindow(Window); a_Player->OpenWindow(*Window);
} }
} }
return true; return true;

View File

@ -69,7 +69,7 @@ bool cFurnaceEntity::UsedBy(cPlayer * a_Player)
{ {
if (a_Player->GetWindow() != Window) if (a_Player->GetWindow() != Window)
{ {
a_Player->OpenWindow(Window); a_Player->OpenWindow(*Window);
} }
} }

View File

@ -95,7 +95,7 @@ bool cHopperEntity::UsedBy(cPlayer * a_Player)
{ {
if (a_Player->GetWindow() != Window) if (a_Player->GetWindow() != Window)
{ {
a_Player->OpenWindow(Window); a_Player->OpenWindow(*Window);
} }
} }

View File

@ -27,7 +27,7 @@ public:
virtual bool OnUse(cChunkInterface & a_ChunkInterface, cWorldInterface & a_WorldInterface, cPlayer * a_Player, int a_BlockX, int a_BlockY, int a_BlockZ, eBlockFace a_BlockFace, int a_CursorX, int a_CursorY, int a_CursorZ) override virtual bool OnUse(cChunkInterface & a_ChunkInterface, cWorldInterface & a_WorldInterface, cPlayer * a_Player, int a_BlockX, int a_BlockY, int a_BlockZ, eBlockFace a_BlockFace, int a_CursorX, int a_CursorY, int a_CursorZ) override
{ {
cWindow * Window = new cAnvilWindow(a_BlockX, a_BlockY, a_BlockZ); cWindow * Window = new cAnvilWindow(a_BlockX, a_BlockY, a_BlockZ);
a_Player->OpenWindow(Window); a_Player->OpenWindow(*Window);
return true; return true;
} }

View File

@ -21,7 +21,7 @@ public:
virtual bool OnUse(cChunkInterface & a_ChunkInterface, cWorldInterface & a_WorldInterface, cPlayer * a_Player, int a_BlockX, int a_BlockY, int a_BlockZ, eBlockFace a_BlockFace, int a_CursorX, int a_CursorY, int a_CursorZ) override virtual bool OnUse(cChunkInterface & a_ChunkInterface, cWorldInterface & a_WorldInterface, cPlayer * a_Player, int a_BlockX, int a_BlockY, int a_BlockZ, eBlockFace a_BlockFace, int a_CursorX, int a_CursorY, int a_CursorZ) override
{ {
cWindow * Window = new cEnchantingWindow(a_BlockX, a_BlockY, a_BlockZ); cWindow * Window = new cEnchantingWindow(a_BlockX, a_BlockY, a_BlockZ);
a_Player->OpenWindow(Window); a_Player->OpenWindow(*Window);
return true; return true;
} }

View File

@ -21,7 +21,7 @@ public:
virtual bool OnUse(cChunkInterface & a_ChunkInterface, cWorldInterface & a_WorldInterface, cPlayer * a_Player, int a_BlockX, int a_BlockY, int a_BlockZ, eBlockFace a_BlockFace, int a_CursorX, int a_CursorY, int a_CursorZ) override virtual bool OnUse(cChunkInterface & a_ChunkInterface, cWorldInterface & a_WorldInterface, cPlayer * a_Player, int a_BlockX, int a_BlockY, int a_BlockZ, eBlockFace a_BlockFace, int a_CursorX, int a_CursorY, int a_CursorZ) override
{ {
cWindow * Window = new cCraftingWindow(a_BlockX, a_BlockY, a_BlockZ); cWindow * Window = new cCraftingWindow(a_BlockX, a_BlockY, a_BlockZ);
a_Player->OpenWindow(Window); a_Player->OpenWindow(*Window);
return true; return true;
} }

View File

@ -1222,7 +1222,7 @@ void cMinecartWithChest::OnRightClicked(cPlayer & a_Player)
{ {
if (a_Player.GetWindow() != Window) if (a_Player.GetWindow() != Window)
{ {
a_Player.OpenWindow(Window); a_Player.OpenWindow(*Window);
} }
} }
} }

View File

@ -1310,15 +1310,15 @@ cTeam * cPlayer::UpdateTeam(void)
void cPlayer::OpenWindow(cWindow * a_Window) void cPlayer::OpenWindow(cWindow & a_Window)
{ {
if (a_Window != m_CurrentWindow) if (&a_Window != m_CurrentWindow)
{ {
CloseWindow(false); CloseWindow(false);
} }
a_Window->OpenedByPlayer(*this); a_Window.OpenedByPlayer(*this);
m_CurrentWindow = a_Window; m_CurrentWindow = &a_Window;
a_Window->SendWholeWindow(*GetClientHandle()); a_Window.SendWholeWindow(*GetClientHandle());
} }

View File

@ -229,7 +229,7 @@ public:
// tolua_begin // tolua_begin
/** Opens the specified window; closes the current one first using CloseWindow() */ /** Opens the specified window; closes the current one first using CloseWindow() */
void OpenWindow(cWindow * a_Window); void OpenWindow(cWindow & a_Window);
/** Closes the current window, resets current window to m_InventoryWindow. A plugin may refuse the closing if a_CanRefuse is true */ /** Closes the current window, resets current window to m_InventoryWindow. A plugin may refuse the closing if a_CanRefuse is true */
void CloseWindow(bool a_CanRefuse = true); void CloseWindow(bool a_CanRefuse = true);