Added the OnClosing callback to cLuaWindow API
git-svn-id: http://mc-server.googlecode.com/svn/trunk@1534 0a769ca7-a7f5-676a-18bf-c427514a06d6
This commit is contained in:
parent
b58f0cabad
commit
2eb1240e14
@ -580,8 +580,17 @@ function HandleTestWndCmd(a_Split, a_Player)
|
|||||||
return true;
|
return true;
|
||||||
end
|
end
|
||||||
|
|
||||||
|
-- Test out the OnClosing callback's ability to refuse to close the window
|
||||||
|
local attempt = 1;
|
||||||
|
local OnClosing = function(Window, Player)
|
||||||
|
Player:SendMessage("Window closing attempt #" .. attempt);
|
||||||
|
attempt = attempt + 1;
|
||||||
|
return (attempt <= 3); -- refuse twice, then allow
|
||||||
|
end
|
||||||
|
|
||||||
local Window = cLuaWindow(WindowType, WindowSizeX, WindowSizeY, "TestWnd");
|
local Window = cLuaWindow(WindowType, WindowSizeX, WindowSizeY, "TestWnd");
|
||||||
Window:SetSlot(a_Player, 0, cItem(E_ITEM_DIAMOND, 64));
|
Window:SetSlot(a_Player, 0, cItem(E_ITEM_DIAMOND, 64));
|
||||||
|
Window:SetOnClosing(OnClosing);
|
||||||
|
|
||||||
a_Player:OpenWindow(Window);
|
a_Player:OpenWindow(Window);
|
||||||
|
|
||||||
|
@ -7,6 +7,7 @@
|
|||||||
#include "LuaWindow.h"
|
#include "LuaWindow.h"
|
||||||
#include "UI/SlotArea.h"
|
#include "UI/SlotArea.h"
|
||||||
#include "Plugin_NewLua.h"
|
#include "Plugin_NewLua.h"
|
||||||
|
#include "Player.h"
|
||||||
#include "lauxlib.h" // Needed for LUA_REFNIL
|
#include "lauxlib.h" // Needed for LUA_REFNIL
|
||||||
|
|
||||||
|
|
||||||
@ -20,7 +21,9 @@ cLuaWindow::cLuaWindow(cWindow::WindowType a_WindowType, int a_SlotsX, int a_Slo
|
|||||||
super(a_WindowType, a_Title),
|
super(a_WindowType, a_Title),
|
||||||
m_Contents(a_SlotsX, a_SlotsY),
|
m_Contents(a_SlotsX, a_SlotsY),
|
||||||
m_Plugin(NULL),
|
m_Plugin(NULL),
|
||||||
m_LuaRef(LUA_REFNIL)
|
m_LuaRef(LUA_REFNIL),
|
||||||
|
m_OnClosingFnRef(LUA_REFNIL),
|
||||||
|
m_OnSlotChangedFnRef(LUA_REFNIL)
|
||||||
{
|
{
|
||||||
m_SlotAreas.push_back(new cSlotAreaItemGrid(m_Contents, *this));
|
m_SlotAreas.push_back(new cSlotAreaItemGrid(m_Contents, *this));
|
||||||
|
|
||||||
@ -53,7 +56,8 @@ cLuaWindow::~cLuaWindow()
|
|||||||
|
|
||||||
void cLuaWindow::SetLuaRef(cPlugin_NewLua * a_Plugin, int a_LuaRef)
|
void cLuaWindow::SetLuaRef(cPlugin_NewLua * a_Plugin, int a_LuaRef)
|
||||||
{
|
{
|
||||||
ASSERT(m_Plugin == NULL);
|
// Either m_Plugin is not set or equal to the passed plugin; only one plugin can use one cLuaWindow object
|
||||||
|
ASSERT((m_Plugin == NULL) || (m_Plugin == a_Plugin));
|
||||||
ASSERT(m_LuaRef == LUA_REFNIL);
|
ASSERT(m_LuaRef == LUA_REFNIL);
|
||||||
m_Plugin = a_Plugin;
|
m_Plugin = a_Plugin;
|
||||||
m_LuaRef = a_LuaRef;
|
m_LuaRef = a_LuaRef;
|
||||||
@ -72,6 +76,46 @@ bool cLuaWindow::IsLuaReferenced(void) const
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
void cLuaWindow::SetOnClosing(cPlugin_NewLua * a_Plugin, int a_FnRef)
|
||||||
|
{
|
||||||
|
// Either m_Plugin is not set or equal to the passed plugin; only one plugin can use one cLuaWindow object
|
||||||
|
ASSERT((m_Plugin == NULL) || (m_Plugin == a_Plugin));
|
||||||
|
|
||||||
|
// If there already was a function, unreference it first
|
||||||
|
if (m_OnClosingFnRef != LUA_REFNIL)
|
||||||
|
{
|
||||||
|
m_Plugin->Unreference(m_OnClosingFnRef);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Store the new reference
|
||||||
|
m_Plugin = a_Plugin;
|
||||||
|
m_OnClosingFnRef = a_FnRef;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
bool cLuaWindow::ClosedByPlayer(cPlayer & a_Player)
|
||||||
|
{
|
||||||
|
// First notify the plugin through the registered callback:
|
||||||
|
if (m_OnClosingFnRef != LUA_REFNIL)
|
||||||
|
{
|
||||||
|
ASSERT(m_Plugin != NULL);
|
||||||
|
if (m_Plugin->CallbackWindowClosing(m_OnClosingFnRef, *this, a_Player))
|
||||||
|
{
|
||||||
|
// The callback disagrees
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return super::ClosedByPlayer(a_Player);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
void cLuaWindow::Destroy(void)
|
void cLuaWindow::Destroy(void)
|
||||||
{
|
{
|
||||||
super::Destroy();
|
super::Destroy();
|
||||||
|
@ -58,6 +58,12 @@ public:
|
|||||||
/// Returns true if SetLuaRef() has been called
|
/// Returns true if SetLuaRef() has been called
|
||||||
bool IsLuaReferenced(void) const;
|
bool IsLuaReferenced(void) const;
|
||||||
|
|
||||||
|
/// Sets the callback function (Lua reference) to call when the window is about to close
|
||||||
|
void SetOnClosing(cPlugin_NewLua * a_Plugin, int a_FnRef);
|
||||||
|
|
||||||
|
/// Sets the callback function (Lua reference) to call when a slot is changed
|
||||||
|
void SetOnSlotChanged(cPlugin_NewLua * a_Plugin, int a_FnRef);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
/// Contents of the non-inventory part
|
/// Contents of the non-inventory part
|
||||||
cItemGrid m_Contents;
|
cItemGrid m_Contents;
|
||||||
@ -68,7 +74,14 @@ protected:
|
|||||||
/// The Lua object reference, used for keeping the object alive as long as any player has the window open
|
/// The Lua object reference, used for keeping the object alive as long as any player has the window open
|
||||||
int m_LuaRef;
|
int m_LuaRef;
|
||||||
|
|
||||||
|
/// The Lua reference for the callback to call when the window is closing for any player
|
||||||
|
int m_OnClosingFnRef;
|
||||||
|
|
||||||
|
/// The Lua reference for the callback to call when a slot has changed
|
||||||
|
int m_OnSlotChangedFnRef;
|
||||||
|
|
||||||
// cWindow overrides:
|
// cWindow overrides:
|
||||||
|
virtual bool ClosedByPlayer(cPlayer & a_Player) override;
|
||||||
virtual void Destroy(void) override;
|
virtual void Destroy(void) override;
|
||||||
} ; // tolua_export
|
} ; // tolua_export
|
||||||
|
|
||||||
|
@ -938,6 +938,41 @@ static int tolua_cPlayer_OpenWindow(lua_State * tolua_S)
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
static int tolua_cLuaWindow_SetOnClosing(lua_State * tolua_S)
|
||||||
|
{
|
||||||
|
// Function signature: cPlayer:SetOnClosing(CallbackFunction)
|
||||||
|
|
||||||
|
// Retrieve the plugin instance from the Lua state
|
||||||
|
cPlugin_NewLua * Plugin = GetLuaPlugin(tolua_S);
|
||||||
|
if (Plugin == NULL)
|
||||||
|
{
|
||||||
|
// Warning message has already been printed by GetLuaPlugin(), bail out silently
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get the parameters:
|
||||||
|
cLuaWindow * self = (cLuaWindow *)tolua_tousertype(tolua_S, 1, NULL);
|
||||||
|
if (self == NULL)
|
||||||
|
{
|
||||||
|
LOGWARNING("%s: invalid self (%p)", __FUNCTION__, self);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
int FnRef = luaL_ref(tolua_S, LUA_REGISTRYINDEX); // Store function reference
|
||||||
|
if (FnRef == LUA_REFNIL)
|
||||||
|
{
|
||||||
|
LOGERROR("%s: Cannot create a function reference. Callback not set.", __FUNCTION__);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set the callback
|
||||||
|
self->SetOnClosing(Plugin, FnRef);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
static int tolua_cPlugin_NewLua_AddWebTab(lua_State * tolua_S)
|
static int tolua_cPlugin_NewLua_AddWebTab(lua_State * tolua_S)
|
||||||
{
|
{
|
||||||
cPlugin_NewLua * self = (cPlugin_NewLua*)tolua_tousertype(tolua_S,1,0);
|
cPlugin_NewLua * self = (cPlugin_NewLua*)tolua_tousertype(tolua_S,1,0);
|
||||||
@ -1265,6 +1300,10 @@ void ManualBindings::Bind( lua_State* tolua_S )
|
|||||||
tolua_function(tolua_S, "OpenWindow", tolua_cPlayer_OpenWindow);
|
tolua_function(tolua_S, "OpenWindow", tolua_cPlayer_OpenWindow);
|
||||||
tolua_endmodule(tolua_S);
|
tolua_endmodule(tolua_S);
|
||||||
|
|
||||||
|
tolua_beginmodule(tolua_S, "cLuaWindow");
|
||||||
|
tolua_function(tolua_S, "SetOnClosing", tolua_cLuaWindow_SetOnClosing);
|
||||||
|
tolua_endmodule(tolua_S);
|
||||||
|
|
||||||
tolua_beginmodule(tolua_S, "cPlugin_NewLua");
|
tolua_beginmodule(tolua_S, "cPlugin_NewLua");
|
||||||
tolua_function(tolua_S, "AddWebTab", tolua_cPlugin_NewLua_AddWebTab);
|
tolua_function(tolua_S, "AddWebTab", tolua_cPlugin_NewLua_AddWebTab);
|
||||||
tolua_function(tolua_S, "AddTab", tolua_cPlugin_NewLua_AddTab);
|
tolua_function(tolua_S, "AddTab", tolua_cPlugin_NewLua_AddTab);
|
||||||
|
@ -435,7 +435,10 @@ Vector3d cPlayer::GetEyePosition()
|
|||||||
|
|
||||||
void cPlayer::OpenWindow(cWindow * a_Window)
|
void cPlayer::OpenWindow(cWindow * a_Window)
|
||||||
{
|
{
|
||||||
|
if (a_Window != m_CurrentWindow)
|
||||||
|
{
|
||||||
CloseWindow();
|
CloseWindow();
|
||||||
|
}
|
||||||
a_Window->OpenedByPlayer(*this);
|
a_Window->OpenedByPlayer(*this);
|
||||||
m_CurrentWindow = a_Window;
|
m_CurrentWindow = a_Window;
|
||||||
a_Window->SendWholeWindow(*GetClientHandle());
|
a_Window->SendWholeWindow(*GetClientHandle());
|
||||||
@ -453,8 +456,17 @@ void cPlayer::CloseWindow(void)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
m_CurrentWindow->ClosedByPlayer(*this);
|
if (m_CurrentWindow->ClosedByPlayer(*this))
|
||||||
|
{
|
||||||
|
// Close accepted, go back to inventory window (the default):
|
||||||
m_CurrentWindow = m_InventoryWindow;
|
m_CurrentWindow = m_InventoryWindow;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Re-open the window
|
||||||
|
m_CurrentWindow->OpenedByPlayer(*this);
|
||||||
|
m_CurrentWindow->SendWholeWindow(*GetClientHandle());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -467,8 +479,7 @@ void cPlayer::CloseWindowIfID(char a_WindowID)
|
|||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
m_CurrentWindow->ClosedByPlayer(*this);
|
CloseWindow();
|
||||||
m_CurrentWindow = m_InventoryWindow;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -1665,6 +1665,30 @@ void cPlugin_NewLua::Unreference(int a_LuaRef)
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
bool cPlugin_NewLua::CallbackWindowClosing(int a_FnRef, cWindow & a_Window, cPlayer & a_Player)
|
||||||
|
{
|
||||||
|
cCSLock Lock(m_CriticalSection);
|
||||||
|
lua_rawgeti(m_LuaState, LUA_REGISTRYINDEX, a_FnRef); // Push the function to be called
|
||||||
|
tolua_pushusertype(m_LuaState, &a_Window, "cWindow");
|
||||||
|
tolua_pushusertype(m_LuaState, &a_Player, "cPlayer");
|
||||||
|
|
||||||
|
// Call function:
|
||||||
|
int s = lua_pcall(m_LuaState, 2, 1, 0);
|
||||||
|
if (report_errors(m_LuaState, s))
|
||||||
|
{
|
||||||
|
LOGERROR("LUA error in %s. Stack size: %i", __FUNCTION__, lua_gettop(m_LuaState));
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool bRetVal = (tolua_toboolean(m_LuaState, -1, false) > 0);
|
||||||
|
lua_pop(m_LuaState, 1);
|
||||||
|
return bRetVal;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// Helper functions
|
// Helper functions
|
||||||
bool cPlugin_NewLua::PushFunction(const char * a_FunctionName, bool a_bLogError /* = true */)
|
bool cPlugin_NewLua::PushFunction(const char * a_FunctionName, bool a_bLogError /* = true */)
|
||||||
{
|
{
|
||||||
|
@ -11,8 +11,12 @@
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// fwd: Lua
|
||||||
typedef struct lua_State lua_State;
|
typedef struct lua_State lua_State;
|
||||||
|
|
||||||
|
// fwd: UI/Window.h
|
||||||
|
class cWindow;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@ -101,6 +105,9 @@ public:
|
|||||||
/// Removes a previously referenced object (luaL_unref())
|
/// Removes a previously referenced object (luaL_unref())
|
||||||
void Unreference(int a_LuaRef);
|
void Unreference(int a_LuaRef);
|
||||||
|
|
||||||
|
/// Calls the plugin-specified "cLuaWindow closing" callback. Returns true only if the callback returned true
|
||||||
|
bool CallbackWindowClosing(int a_FnRef, cWindow & a_Window, cPlayer & a_Player);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
cCriticalSection m_CriticalSection;
|
cCriticalSection m_CriticalSection;
|
||||||
lua_State * m_LuaState;
|
lua_State * m_LuaState;
|
||||||
|
@ -251,7 +251,7 @@ void cWindow::OpenedByPlayer(cPlayer & a_Player)
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
void cWindow::ClosedByPlayer(cPlayer & a_Player)
|
bool cWindow::ClosedByPlayer(cPlayer & a_Player)
|
||||||
{
|
{
|
||||||
// Checks whether the player is still holding an item
|
// Checks whether the player is still holding an item
|
||||||
if (a_Player.IsDraggingItem())
|
if (a_Player.IsDraggingItem())
|
||||||
@ -285,6 +285,8 @@ void cWindow::ClosedByPlayer(cPlayer & a_Player)
|
|||||||
{
|
{
|
||||||
delete this;
|
delete this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -106,7 +106,9 @@ public:
|
|||||||
);
|
);
|
||||||
|
|
||||||
void OpenedByPlayer(cPlayer & a_Player);
|
void OpenedByPlayer(cPlayer & a_Player);
|
||||||
void ClosedByPlayer(cPlayer & a_Player);
|
|
||||||
|
/// Called when a player closes this window; notifies all slot areas. Returns true if close accepted
|
||||||
|
virtual bool ClosedByPlayer(cPlayer & a_Player);
|
||||||
|
|
||||||
void SendWholeWindow(cClientHandle & a_Client);
|
void SendWholeWindow(cClientHandle & a_Client);
|
||||||
void BroadcastWholeWindow(void);
|
void BroadcastWholeWindow(void);
|
||||||
|
Loading…
Reference in New Issue
Block a user