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 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143
|
/* This file is part of the Spring engine (GPL v2 or later), see LICENSE.html */
#include "LuaInterCall.h"
#include "LuaInclude.h"
#include "LuaHandle.h"
#include "LuaGaia.h"
#include "LuaRules.h"
#include "LuaUI.h"
enum {
LUA_UI,
LUA_RULES,
LUA_GAIA
};
static CLuaHandle* GetLuaHandle(lua_State* L, int index)
{
int* addr = (int*) lua_touserdata(L, index);
if (addr == NULL) {
luaL_error(L, "Bad XCall target");
return NULL;
}
const bool isSrcSynced = CLuaHandle::GetHandleSynced(L);
switch (*addr) {
case LUA_UI:
if (!luaUI) return NULL; // handle is not currently active
return luaUI;
case LUA_RULES:
if (!luaRules) return NULL; // handle is not currently active
return (isSrcSynced) ? static_cast<CLuaHandle*>(&luaRules->syncedLuaHandle) : static_cast<CLuaHandle*>(&luaRules->unsyncedLuaHandle);
case LUA_GAIA:
if (!luaGaia) return NULL; // handle is not currently active
return (isSrcSynced) ? static_cast<CLuaHandle*>(&luaGaia->syncedLuaHandle) : static_cast<CLuaHandle*>(&luaGaia->unsyncedLuaHandle);
default:
luaL_error(L, "Bad XCall target");
return NULL;
};
}
/******************************************************************************/
/******************************************************************************/
static int HandleXCall(lua_State* L)
{
const int addrIndex = lua_upvalueindex(1);
const int nameIndex = lua_upvalueindex(2);
CLuaHandle* lh = GetLuaHandle(L, addrIndex);
const std::string funcName = luaL_checksstring(L, nameIndex);
if (lh == NULL) return 0;
return lh->XCall(L, funcName);
}
static int IndexHook(lua_State* L)
{
if (!lua_israwstring(L, -1)) {
return luaL_error(L, "Script.XYZ: only strings allowed got ", lua_typename(L, -1));
}
lua_pushvalue(L, lua_upvalueindex(1));
lua_pushvalue(L, -2);
lua_pushcclosure(L, HandleXCall, 2);
return 1;
}
static int CallHook(lua_State* L)
{
const int addrIndex = lua_upvalueindex(1);
CLuaHandle* lh = GetLuaHandle(L, addrIndex);
if (lh == NULL) return 0;
const int args = lua_gettop(L); // arg 1 is the table
if (args <= 1) {
// is the handle currently active?
lua_pushboolean(L, (lh != NULL));
return 1;
}
else if (args >= 2) {
// see if the specified function exists
const string funcName = luaL_checksstring(L, 2);
lua_pushboolean(L, lh->HasXCall(funcName));
return 1;
}
return 0;
}
static int PushCallHandler(lua_State* L, int luaInstance, const string& name)
{
lua_pushsstring(L, name);
int* ptr = (int*) lua_newuserdata(L, sizeof(int));
*ptr = luaInstance;
{ // create metatable of the userdata
lua_newtable(L); {
lua_pushliteral(L, "__index");
lua_pushvalue(L, -3); //userdata
lua_pushcclosure(L, IndexHook, 1);
lua_rawset(L, -3);
lua_pushliteral(L, "__call");
lua_pushvalue(L, -3); //userdata
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 LuaInterCall::PushEntriesSynced(lua_State* L)
{
PushCallHandler(L, LUA_GAIA, "LuaGaia");
PushCallHandler(L, LUA_RULES, "LuaRules");
return true;
}
bool LuaInterCall::PushEntriesUnsynced(lua_State* L)
{
PushCallHandler(L, LUA_GAIA, "LuaGaia");
PushCallHandler(L, LUA_RULES, "LuaRules");
PushCallHandler(L, LUA_UI, "LuaUI");
return true;
}
/******************************************************************************/
/******************************************************************************/
|