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
|
/* This file is part of the Spring engine (GPL v2 or later), see LICENSE.html */
#include "LuaSyncedTable.h"
#include "LuaInclude.h"
#include "LuaHandleSynced.h"
#include "LuaHashString.h"
#include "LuaUtils.h"
static int SyncTableIndex(lua_State* L);
static int SyncTableNewIndex(lua_State* L);
static int SyncTableMetatable(lua_State* L);
/******************************************************************************/
/******************************************************************************/
static bool PushSyncedTable(lua_State* L)
{
HSTR_PUSH(L, "SYNCED");
lua_newtable(L); { // the proxy table
lua_newtable(L); { // the metatable
LuaPushNamedCFunc(L, "__index", SyncTableIndex);
LuaPushNamedCFunc(L, "__newindex", SyncTableNewIndex);
LuaPushNamedCFunc(L, "__metatable", SyncTableMetatable);
}
lua_setmetatable(L, -2);
}
lua_rawset(L, -3);
return true;
}
/******************************************************************************/
static int SyncTableIndex(lua_State* dstL)
{
if (lua_isnoneornil(dstL, -1))
return 0;
auto slh = CLuaHandleSynced::GetSyncedHandle(dstL);
if (!slh->IsValid())
return 0;
auto srcL = slh->GetLuaState();
const int srcTop = lua_gettop(srcL);
const int dstTop = lua_gettop(dstL);
// copy the index & get value
lua_pushvalue(srcL, LUA_GLOBALSINDEX);
const int keyCopied = LuaUtils::CopyData(srcL, dstL, 1);
assert(keyCopied > 0);
lua_rawget(srcL, -2);
// copy to destination
const int valueCopied = LuaUtils::CopyData(dstL, srcL, 1);
if (lua_istable(dstL, -1)) {
// disallow writing in SYNCED[...]
lua_newtable(dstL); { // the metatable
LuaPushNamedCFunc(dstL, "__newindex", SyncTableNewIndex);
LuaPushNamedCFunc(dstL, "__metatable", SyncTableMetatable);
}
lua_setmetatable(dstL, -2);
}
assert(valueCopied == 1);
assert(dstTop + 1 == lua_gettop(dstL));
lua_settop(srcL, srcTop);
return valueCopied;
}
static int SyncTableNewIndex(lua_State* L)
{
luaL_error(L, "Attempt to write to SYNCED table");
return 0;
}
static int SyncTableMetatable(lua_State* L)
{
luaL_error(L, "Attempt to access SYNCED metatable");
return 0;
}
/******************************************************************************/
/******************************************************************************/
bool LuaSyncedTable::PushEntries(lua_State* L)
{
PushSyncedTable(L);
// backward compability
lua_pushliteral(L, "snext");
lua_getglobal(L, "next");
lua_rawset(L, -3);
lua_pushliteral(L, "spairs");
lua_getglobal(L, "pairs");
lua_rawset(L, -3);
lua_pushliteral(L, "sipairs");
lua_getglobal(L, "ipairs");
lua_rawset(L, -3);
return true;
}
/******************************************************************************/
/******************************************************************************/
|