1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115
|
/* This file is part of the Spring engine (GPL v2 or later), see LICENSE.html */
#include "System/mmgr.h"
#include "LuaUnsyncedCall.h"
#include "LuaInclude.h"
#include "LuaHandle.h"
#include "LuaGaia.h"
#include "LuaRules.h"
#include "LuaHashString.h"
#include "LuaUI.h"
#include "LuaUtils.h"
#include <set>
#include <list>
#include <cctype>
/******************************************************************************/
/******************************************************************************/
static int HandleXCall(lua_State* L)
{
const int addrIndex = lua_upvalueindex(1);
const int nameIndex = lua_upvalueindex(2);
if (!lua_isuserdata(L, addrIndex) || !lua_israwstring(L, nameIndex)) {
luaL_error(L, "Bad function name type");
}
CLuaHandle** addr = (CLuaHandle**) lua_touserdata(L, addrIndex);
if (*addr == NULL) {
return 0; // handle is not currently active
}
CLuaHandle* lh = *addr;
const char* funcName = lua_tostring(L, nameIndex);
return lh->UnsyncedXCall(L, funcName);
}
static int IndexHook(lua_State* L)
{
CLuaHandle** addr = (CLuaHandle**) lua_touserdata(L, lua_upvalueindex(1));
if (!lua_israwstring(L, 2)) {
return 0; // missing string name for function
}
lua_pushlightuserdata(L, addr);
lua_pushstring(L, lua_tostring(L, 2));
lua_pushcclosure(L, HandleXCall, 2);
return 1;
}
static int CallHook(lua_State* L)
{
CLuaHandle** addr = (CLuaHandle**) lua_touserdata(L, lua_upvalueindex(1));
const int args = lua_gettop(L); // arg 1 is the table
if (args <= 1) {
// is the handle currently active?
lua_pushboolean(L, (*addr != NULL));
return 1;
}
else if ((args >= 2) && lua_israwstring(L, 2)) {
// see if the specified function exists
const string funcName = lua_tostring(L, 2);
CLuaHandle* lh = *addr;
if (lh == NULL) {
return 0; // not running
}
lua_pushboolean(L, lh->HasUnsyncedXCall(L, funcName));
return 1;
}
return 0;
}
static int PushCallHandler(lua_State* L, CLuaHandle** addr, const string& name)
{
lua_pushsstring(L, name);
CLuaHandle*** ptr = (CLuaHandle***) lua_newuserdata(L, sizeof(CLuaHandle**));
*ptr = addr;
lua_newtable(L); {
lua_pushliteral(L, "__index");
lua_pushlightuserdata(L, addr);
lua_pushcclosure(L, IndexHook, 1);
lua_rawset(L, -3);
lua_pushliteral(L, "__call");
lua_pushlightuserdata(L, addr);
lua_pushcclosure(L, CallHook, 1);
lua_rawset(L, -3);
lua_pushliteral(L, "__metatable");
lua_pushliteral(L, "can't touch this");
lua_rawset(L, -3);
}
lua_setmetatable(L, -2); // set the userdata's metatable
lua_rawset(L, -3);
return 0;
}
bool LuaUnsyncedCall::PushEntries(lua_State* L)
{
PushCallHandler(L, (CLuaHandle**) &luaGaia, "LuaGaia");
PushCallHandler(L, (CLuaHandle**) &luaRules, "LuaRules");
PushCallHandler(L, (CLuaHandle**) &luaUI, "LuaUI");
return true;
}
/******************************************************************************/
/******************************************************************************/
|