1
0
Fork 0

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:
madmaxoft@gmail.com 2013-05-30 20:40:43 +00:00
parent b58f0cabad
commit 2eb1240e14
9 changed files with 160 additions and 9 deletions

View File

@ -580,8 +580,17 @@ function HandleTestWndCmd(a_Split, a_Player)
return true;
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");
Window:SetSlot(a_Player, 0, cItem(E_ITEM_DIAMOND, 64));
Window:SetOnClosing(OnClosing);
a_Player:OpenWindow(Window);

View File

@ -7,6 +7,7 @@
#include "LuaWindow.h"
#include "UI/SlotArea.h"
#include "Plugin_NewLua.h"
#include "Player.h"
#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),
m_Contents(a_SlotsX, a_SlotsY),
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));
@ -53,7 +56,8 @@ cLuaWindow::~cLuaWindow()
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);
m_Plugin = a_Plugin;
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)
{
super::Destroy();

View File

@ -58,6 +58,12 @@ public:
/// Returns true if SetLuaRef() has been called
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:
/// Contents of the non-inventory part
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
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:
virtual bool ClosedByPlayer(cPlayer & a_Player) override;
virtual void Destroy(void) override;
} ; // tolua_export

View File

@ -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)
{
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_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_function(tolua_S, "AddWebTab", tolua_cPlugin_NewLua_AddWebTab);
tolua_function(tolua_S, "AddTab", tolua_cPlugin_NewLua_AddTab);

View File

@ -435,7 +435,10 @@ Vector3d cPlayer::GetEyePosition()
void cPlayer::OpenWindow(cWindow * a_Window)
{
CloseWindow();
if (a_Window != m_CurrentWindow)
{
CloseWindow();
}
a_Window->OpenedByPlayer(*this);
m_CurrentWindow = a_Window;
a_Window->SendWholeWindow(*GetClientHandle());
@ -453,8 +456,17 @@ void cPlayer::CloseWindow(void)
return;
}
m_CurrentWindow->ClosedByPlayer(*this);
m_CurrentWindow = m_InventoryWindow;
if (m_CurrentWindow->ClosedByPlayer(*this))
{
// Close accepted, go back to inventory window (the default):
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;
}
m_CurrentWindow->ClosedByPlayer(*this);
m_CurrentWindow = m_InventoryWindow;
CloseWindow();
}

View File

@ -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
bool cPlugin_NewLua::PushFunction(const char * a_FunctionName, bool a_bLogError /* = true */)
{

View File

@ -11,8 +11,12 @@
// fwd: Lua
typedef struct lua_State lua_State;
// fwd: UI/Window.h
class cWindow;
@ -101,6 +105,9 @@ public:
/// Removes a previously referenced object (luaL_unref())
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:
cCriticalSection m_CriticalSection;
lua_State * m_LuaState;

View File

@ -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
if (a_Player.IsDraggingItem())
@ -285,6 +285,8 @@ void cWindow::ClosedByPlayer(cPlayer & a_Player)
{
delete this;
}
return true;
}

View File

@ -106,7 +106,9 @@ public:
);
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 BroadcastWholeWindow(void);