bool CLuaHandleSynced::SetupUnsyncedFunction(const char* funcName) { // copy the function from UNSYNCED into // the registry, and setfenv() it to UNSYNCED lua_settop(L, 0); unsyncedStr.GetRegistry(L); if (!lua_istable(L, -1)) { lua_settop(L, 0); //FIXME logOutput.Print("ERROR: missing UNSYNCED table for %s", name.c_str()); return false; } const int unsynced = lua_gettop(L); lua_pushstring(L, funcName); lua_pushstring(L, funcName); lua_gettable(L, unsynced); if (lua_isnil(L, -1)) { lua_rawset(L, LUA_REGISTRYINDEX); lua_settop(L, 0); return true; } else if (!lua_isfunction(L, -1)) { lua_settop(L, 0); logOutput.Print("%s in %s is not a function", funcName, GetName().c_str()); return false; } lua_pushvalue(L, unsynced); lua_setfenv(L, -2); lua_rawset(L, LUA_REGISTRYINDEX); lua_settop(L, 0); return true; }
bool CLuaHandleSynced::LoadUnsyncedCode(const string& code, const string& debug) { lua_settop(L, 0); int error; error = luaL_loadbuffer(L, code.c_str(), code.size(), debug.c_str()); if (error != 0) { logOutput.Print("error = %i, %s, %s\n", error, debug.c_str(), lua_tostring(L, -1)); lua_settop(L, 0); return false; } unsyncedStr.GetRegistry(L); if (!lua_istable(L, -1)) { lua_settop(L, 0); return false; } lua_setfenv(L, -2); CLuaHandle* orig = activeHandle; SetActiveHandle(); error = lua_pcall(L, 0, 0, 0); SetActiveHandle(orig); if (error != 0) { logOutput.Print("error = %i, %s, %s\n", error, debug.c_str(), lua_tostring(L, -1)); lua_settop(L, 0); return false; } return true; }
bool CLuaHandleSynced::LoadUnsyncedCode(lua_State *L, const string& code, const string& debug) { lua_settop(L, 0); int error; error = luaL_loadbuffer(L, code.c_str(), code.size(), debug.c_str()); if (error != 0) { LOG_L(L_ERROR, "error = %i, %s, %s", error, debug.c_str(), lua_tostring(L, -1)); lua_settop(L, 0); return false; } unsyncedStr.GetRegistry(L); if (!lua_istable(L, -1)) { lua_settop(L, 0); return false; } lua_setfenv(L, -2); SetRunning(L, true); error = lua_pcall(L, 0, 0, 0); SetRunning(L, false); if (error != 0) { LOG_L(L_ERROR, "error = %i, %s, %s", error, debug.c_str(), lua_tostring(L, -1)); lua_settop(L, 0); return false; } return true; }
int CLuaHandleSynced::UnsyncedXCall(lua_State* srcState, const string& funcName) { const bool prevSynced = synced; synced = false; unsyncedStr.GetRegistry(L); // push the UNSYNCED table const int retval = XCall(srcState, funcName); synced = prevSynced; return retval; }
bool CLuaHandleSynced::HasUnsyncedXCall(const string& funcName) { unsyncedStr.GetRegistry(L); // push the UNSYNCED table if (!lua_istable(L, -1)) { lua_pop(L, 1); return false; } lua_pushstring(L, funcName.c_str()); // push the function name lua_rawget(L, -2); // get the function const bool haveFunc = lua_isfunction(L, -1); lua_pop(L, 2); return haveFunc; }
bool CLuaHandleSynced::CopyGlobalToUnsynced(const char* name) { lua_settop(L, 0); unsyncedStr.GetRegistry(L); const int unsynced = lua_gettop(L); lua_pushstring(L, name); lua_getglobal(L, name); lua_rawset(L, unsynced); lua_settop(L, 0); return true; }
int CLuaHandleSynced::UnsyncedXCall(lua_State* srcState, const string& funcName) { SELECT_UNSYNCED_LUA_STATE(); GML_DRCMUTEX_LOCK(lua); // UnsyncedXCall const bool prevSynced = GetHandleSynced(L); SetHandleSynced(L, false); unsyncedStr.GetRegistry(L); // push the UNSYNCED table const int retval = XCall(L, srcState, funcName); SetHandleSynced(L, prevSynced); return retval; }
bool CLuaHandleSynced::HasUnsyncedXCall(lua_State* srcState, const string& funcName) { SELECT_UNSYNCED_LUA_STATE(); GML_DRCMUTEX_LOCK(lua); // HasUnsyncedXCall unsyncedStr.GetRegistry(L); // push the UNSYNCED table if (!lua_istable(L, -1)) { lua_pop(L, 1); return false; } lua_pushsstring(L, funcName); // push the function name lua_rawget(L, -2); // get the function const bool haveFunc = lua_isfunction(L, -1); lua_pop(L, 2); return haveFunc; }
bool CLuaHandleSynced::SetupUnsynced(const string& code, const string& filename) { if ((L == NULL) || code.empty()) { return false; } // make the UNSYNCED table unsyncedStr.Push(L); lua_newtable(L); lua_rawset(L, LUA_REGISTRYINDEX); unsyncedStr.GetRegistry(L); AddBasicCalls(); // into UNSYNCED // remove Script.Kill() lua_pushstring(L, "Script"); lua_rawget(L, -2); lua_pushstring(L, "Kill"); lua_pushnil(L); lua_rawset(L, -3); LuaPushNamedCFunc(L, "UpdateCallIn", CallOutUnsyncedUpdateCallIn); lua_pop(L, 1); lua_pushstring(L, "_G"); unsyncedStr.GetRegistry(L); lua_rawset(L, -3); LuaPushNamedCFunc(L, "loadstring", LoadStringData); LuaPushNamedCFunc(L, "CallAsTeam", CallAsTeam); // load our libraries if (!LuaSyncedTable::PushEntries(L) || !AddEntriesToTable(L, "VFS", LuaVFS::PushUnsynced) || !AddEntriesToTable(L, "UnitDefs", LuaUnitDefs::PushEntries) || !AddEntriesToTable(L, "WeaponDefs", LuaWeaponDefs::PushEntries) || !AddEntriesToTable(L, "FeatureDefs", LuaFeatureDefs::PushEntries) || !AddEntriesToTable(L, "Script", LuaUnsyncedCall::PushEntries) || !AddEntriesToTable(L, "Script", LuaScream::PushEntries) || !AddEntriesToTable(L, "Spring", LuaSyncedRead::PushEntries) || !AddEntriesToTable(L, "Spring", LuaUnsyncedCtrl::PushEntries) || !AddEntriesToTable(L, "Spring", LuaUnsyncedRead::PushEntries) || !AddEntriesToTable(L, "gl", LuaOpenGL::PushEntries) || !AddEntriesToTable(L, "GL", LuaConstGL::PushEntries) || !AddEntriesToTable(L, "Game", LuaConstGame::PushEntries) || !AddEntriesToTable(L, "CMD", LuaConstCMD::PushEntries) || !AddEntriesToTable(L, "CMDTYPE", LuaConstCMDTYPE::PushEntries)) { KillLua(); return false; } lua_pushstring(L, "math"); lua_newtable(L); lua_getglobal(L, "math"); LightCopyTable(-2, -1); lua_pop(L, 1); lua_rawset(L, -3); lua_pushstring(L, "table"); lua_newtable(L); lua_getglobal(L, "table"); LightCopyTable(-2, -1); lua_pop(L, 1); lua_rawset(L, -3); lua_pushstring(L, "string"); lua_newtable(L); lua_getglobal(L, "string"); LightCopyTable(-2, -1); lua_pop(L, 1); lua_rawset(L, -3); if (!CopyRealRandomFuncs()) { KillLua(); return false; } lua_settop(L, 0); // note the absence of loadstring() -- global access const char* labels[] = { "assert", "error", "print", "next", "pairs", "ipairs", "tonumber", "tostring", "type", "collectgarbage", "gcinfo", "unpack", "getmetatable", "setmetatable", "rawequal", "rawget", "rawset", "getfenv", "setfenv", "pcall", "xpcall", "_VERSION", NULL }; for (const char** l = labels; *l != NULL; l++) { CopyGlobalToUnsynced(*l); } // add code from the sub-class unsyncedStr.GetRegistry(L); if (!AddUnsyncedCode()) { KillLua(); return false; } lua_settop(L, 0); if (!LoadUnsyncedCode(code, filename)) { KillLua(); return false; } if (!SetupUnsyncedFunction("RecvFromSynced") || !SetupUnsyncedFunction("Update") || !SetupUnsyncedFunction("DrawGenesis") || !SetupUnsyncedFunction("DrawWorld") || !SetupUnsyncedFunction("DrawWorldPreUnit") || !SetupUnsyncedFunction("DrawWorldShadow") || !SetupUnsyncedFunction("DrawWorldReflection") || !SetupUnsyncedFunction("DrawWorldRefraction") || !SetupUnsyncedFunction("DrawScreenEffects") || !SetupUnsyncedFunction("DrawScreen") || !SetupUnsyncedFunction("DrawInMiniMap")) { return false; } return true; }