int CSyncedLuaHandle::RemoveSyncedActionFallback(lua_State* L) { //TODO move to LuaHandle string cmdRaw = luaL_checkstring(L, 1); cmdRaw = "/" + cmdRaw; string cmd = cmdRaw; const string::size_type pos = cmdRaw.find_first_of(" \t"); if (pos != string::npos) { cmd.resize(pos); } if (cmd.empty()) { lua_pushboolean(L, false); return 1; } auto lhs = GetSyncedHandle(L); map<string, string>::iterator it = lhs->textCommands.find(cmd); if (it != lhs->textCommands.end()) { lhs->textCommands.erase(it); wordCompletion->RemoveWord(cmdRaw); lua_pushboolean(L, true); } else { lua_pushboolean(L, false); } return 1; }
int CLuaHandleSynced::RemoveSyncedActionFallback(lua_State* L) { const int args = lua_gettop(L); if ((args != 1) || !lua_isstring(L, 1)) { luaL_error(L, "Incorrect arguments to RemoveActionFallback()"); } string cmdRaw = lua_tostring(L, 1); cmdRaw = "/" + cmdRaw; string cmd = cmdRaw; const string::size_type pos = cmdRaw.find_first_of(" \t"); if (pos != string::npos) { cmd.resize(pos); } if (cmd.empty()) { lua_pushboolean(L, false); return 1; } CLuaHandleSynced* lhs = GetSyncedHandle(L); map<string, string>::iterator it = lhs->textCommands.find(cmd); if (it != lhs->textCommands.end()) { lhs->textCommands.erase(it); wordCompletion->RemoveWord(cmdRaw); lua_pushboolean(L, true); } else { lua_pushboolean(L, false); } return 1; }
int CLuaHandleSynced::AddSyncedActionFallback(lua_State* L) { const int args = lua_gettop(L); if ((args != 2) || !lua_isstring(L, 1) || !lua_isstring(L, 2)) { luaL_error(L, "Incorrect arguments to AddActionFallback()"); } string cmdRaw = lua_tostring(L, 1); cmdRaw = "/" + cmdRaw; string cmd = cmdRaw; const string::size_type pos = cmdRaw.find_first_of(" \t"); if (pos != string::npos) { cmd.resize(pos); } if (cmd.empty()) { lua_pushboolean(L, false); return 1; } CLuaHandleSynced* lhs = GetSyncedHandle(L); lhs->textCommands[cmd] = lua_tostring(L, 2); wordCompletion->AddWord(cmdRaw, true, false, false); lua_pushboolean(L, true); return 1; }
int CSyncedLuaHandle::AddSyncedActionFallback(lua_State* L) { string cmdRaw = luaL_checkstring(L, 1); cmdRaw = "/" + cmdRaw; string cmd = cmdRaw; const string::size_type pos = cmdRaw.find_first_of(" \t"); if (pos != string::npos) { cmd.resize(pos); } if (cmd.empty()) { lua_pushboolean(L, false); return 1; } auto lhs = GetSyncedHandle(L); lhs->textCommands[cmd] = luaL_checkstring(L, 2); wordCompletion->AddWord(cmdRaw, true, false, false); lua_pushboolean(L, true); return 1; }
int CSyncedLuaHandle::SyncedNext(lua_State* L) { auto* slh = GetSyncedHandle(L); assert(slh->origNextRef > 0); const std::set<int> whiteList = { LUA_TSTRING, LUA_TNUMBER, LUA_TBOOLEAN, LUA_TNIL, LUA_TTHREAD //FIXME LUA_TTHREAD is normally _not_ synced safe but LUS handler needs it atm (and uses it in a safe way) }; const int oldTop = lua_gettop(L); lua_rawgeti(L, LUA_REGISTRYINDEX, slh->origNextRef); lua_pushvalue(L, 1); if (oldTop >= 2) { lua_pushvalue(L, 2); } else { lua_pushnil(L); } lua_call(L, 2, LUA_MULTRET); const int retCount = lua_gettop(L) - oldTop; assert(retCount == 1 || retCount == 2); if (retCount >= 2) { const int keyType = lua_type(L, -2); if (whiteList.find(keyType) == whiteList.end()) { if (LuaUtils::PushDebugTraceback(L) > 0) { lua_pushfstring(L, "Iterating a table with keys of type \"%s\" in synced context!", lua_typename(L, keyType)); lua_call(L, 1, 1); const auto* errMsg = lua_tostring(L, -1); LOG_L(L_WARNING, "%s", errMsg); } lua_pop(L, 1); // either nil or the errMsg } } return retCount; }
int CLuaHandleSynced::CallAsTeam(lua_State* L) { CLuaHandleSynced* lhs = GetSyncedHandle(L); if (lhs->teamsLocked) { luaL_error(L, "CallAsTeam() called when teams are locked"); } const int args = lua_gettop(L); if ((args < 2) || !lua_isfunction(L, 2)) { luaL_error(L, "Incorrect arguments to CallAsTeam()"); } // save the current access const bool prevFullCtrl = GetHandleFullCtrl(L); const bool prevFullRead = GetHandleFullRead(L); const int prevCtrlTeam = GetHandleCtrlTeam(L); const int prevReadTeam = GetHandleReadTeam(L); const int prevReadAllyTeam = GetHandleReadAllyTeam(L); const int prevSelectTeam = GetHandleSelectTeam(L); // parse the new access if (lua_isnumber(L, 1)) { const int teamID = lua_toint(L, 1); if ((teamID < MinSpecialTeam) || (teamID >= teamHandler->ActiveTeams())) { luaL_error(L, "Bad teamID in SetCtrlTeam"); } // ctrl SetHandleCtrlTeam(L, teamID); SetHandleFullCtrl(L, GetHandleCtrlTeam(L) == CEventClient::AllAccessTeam); // read SetHandleReadTeam(L, teamID); SetHandleReadAllyTeam(L, (teamID < 0) ? teamID : teamHandler->AllyTeam(teamID)); SetHandleFullRead(L, GetHandleReadAllyTeam(L) == CEventClient::AllAccessTeam); // select SetHandleSelectTeam(L, teamID); } else if (lua_istable(L, 1)) { const int table = 1; for (lua_pushnil(L); lua_next(L, table) != 0; lua_pop(L, 1)) { if (!lua_israwstring(L, -2) || !lua_isnumber(L, -1)) { continue; } const string key = lua_tostring(L, -2); const int teamID = lua_toint(L, -1); if ((teamID < MinSpecialTeam) || (teamID >= teamHandler->ActiveTeams())) { luaL_error(L, "Bad teamID in SetCtrlTeam"); } if (key == "ctrl") { SetHandleCtrlTeam(L, teamID); SetHandleFullCtrl(L, GetHandleCtrlTeam(L) == CEventClient::AllAccessTeam); } else if (key == "read") { SetHandleReadTeam(L, teamID); SetHandleReadAllyTeam(L, (teamID < 0) ? teamID : teamHandler->AllyTeam(teamID)); SetHandleFullRead(L, GetHandleReadAllyTeam(L) == CEventClient::AllAccessTeam); } else if (key == "select") { SetHandleSelectTeam(L, teamID); } } } else { luaL_error(L, "Incorrect arguments to CallAsTeam()"); } // call the function const int funcArgs = lua_gettop(L) - 2; // protected call so that the permissions are always reverted const int error = lua_pcall(L, funcArgs, LUA_MULTRET, 0); // revert the permissions SetHandleFullCtrl(L, prevFullCtrl); SetHandleFullRead(L, prevFullRead); SetHandleCtrlTeam(L, prevCtrlTeam); SetHandleReadTeam(L, prevReadTeam); SetHandleReadAllyTeam(L, prevReadAllyTeam); SetHandleSelectTeam(L, prevSelectTeam); if (error != 0) { LOG_L(L_ERROR, "error = %i, %s, %s", error, "CallAsTeam", lua_tostring(L, -1)); lua_error(L); } return lua_gettop(L) - 1; // the teamID/table is still on the stack }