static bool WrapTable(lua_State* L) { const int realTable = lua_gettop(L); lua_newtable(L); { // the proxy table lua_newtable(L); { // the metatable HSTR_PUSH(L, "__index"); lua_pushvalue(L, realTable); lua_pushcclosure(L, SyncTableIndex, 1); lua_rawset(L, -3); // closure HSTR_PUSH(L, "__newindex"); lua_pushcfunction(L, SyncTableNewIndex); lua_rawset(L, -3); HSTR_PUSH(L, "__metatable"); lua_pushcfunction(L, SyncTableMetatable); lua_rawset(L, -3); HSTR_PUSH(L, "realTable"); lua_pushvalue(L, realTable); lua_rawset(L, -3); } lua_setmetatable(L, -2); } lua_remove(L, realTable); return true; }
static int WeaponsTable(lua_State* L, const void* data) { const vector<UnitDefWeapon>& weapons = *((const vector<UnitDefWeapon>*)data); lua_newtable(L); for (size_t i = 0; i < weapons.size(); i++) { const UnitDefWeapon& udw = weapons[i]; const WeaponDef* weapon = udw.def; lua_pushnumber(L, i + LUA_WEAPON_BASE_INDEX); lua_newtable(L); { HSTR_PUSH_NUMBER(L, "weaponDef", weapon->id); HSTR_PUSH_NUMBER(L, "slavedTo", udw.slavedTo-1+LUA_WEAPON_BASE_INDEX); HSTR_PUSH_NUMBER(L, "fuelUsage", udw.fuelUsage); HSTR_PUSH_NUMBER(L, "maxAngleDif", udw.maxMainDirAngleDif); HSTR_PUSH_NUMBER(L, "mainDirX", udw.mainDir.x); HSTR_PUSH_NUMBER(L, "mainDirY", udw.mainDir.y); HSTR_PUSH_NUMBER(L, "mainDirZ", udw.mainDir.z); HSTR_PUSH(L, "badTargets"); CategorySetFromBits(L, &udw.badTargetCat); lua_rawset(L, -3); HSTR_PUSH(L, "onlyTargets"); CategorySetFromBits(L, &udw.onlyTargetCat); lua_rawset(L, -3); } lua_rawset(L, -3); } return 1; }
string CLuaHandle::WorldTooltip(const CUnit* unit, const CFeature* feature, const float3* groundPos) { if (!CheckModUICtrl()) { return ""; } LUA_CALL_IN_CHECK(L); lua_checkstack(L, 6); static const LuaHashString cmdStr("WorldTooltip"); if (!PushUnsyncedCallIn(cmdStr)) { return ""; // the call is not defined } int args; if (unit) { HSTR_PUSH(L, "unit"); lua_pushnumber(L, unit->id); args = 2; } else if (feature) { HSTR_PUSH(L, "feature"); lua_pushnumber(L, feature->id); args = 2; } else if (groundPos) { HSTR_PUSH(L, "ground"); lua_pushnumber(L, groundPos->x); lua_pushnumber(L, groundPos->y); lua_pushnumber(L, groundPos->z); args = 4; } else { HSTR_PUSH(L, "selection"); args = 1; } // call the routine if (!RunCallInUnsynced(cmdStr, args, 1)) { return ""; } if (!lua_isstring(L, -1)) { lua_pop(L, 1); return ""; } const string retval = lua_tostring(L, -1); lua_pop(L, 1); return retval; }
bool LuaUnitDefs::PushEntries(lua_State* L) { if (paramMap.empty()) { InitParamMap(); } const map<string, int>& udMap = unitDefHandler->unitDefIDsByName; map<string, int>::const_iterator udIt; for (udIt = udMap.begin(); udIt != udMap.end(); ++udIt) { const UnitDef* ud = unitDefHandler->GetUnitDefByID(udIt->second); if (ud == NULL) { continue; } lua_pushnumber(L, ud->id); lua_newtable(L); { // the proxy table lua_newtable(L); { // the metatable HSTR_PUSH(L, "__index"); lua_pushlightuserdata(L, (void*)ud); lua_pushcclosure(L, UnitDefIndex, 1); lua_rawset(L, -3); // closure HSTR_PUSH(L, "__newindex"); lua_pushlightuserdata(L, (void*)ud); lua_pushcclosure(L, UnitDefNewIndex, 1); lua_rawset(L, -3); HSTR_PUSH(L, "__metatable"); lua_pushlightuserdata(L, (void*)ud); lua_pushcclosure(L, UnitDefMetatable, 1); lua_rawset(L, -3); } lua_setmetatable(L, -2); } HSTR_PUSH(L, "pairs"); lua_pushcfunction(L, Pairs); lua_rawset(L, -3); HSTR_PUSH(L, "next"); lua_pushcfunction(L, Next); lua_rawset(L, -3); lua_rawset(L, -3); // proxy table into UnitDefs } return true; }
bool LuaWeaponDefs::PushEntries(lua_State* L) { if (paramMap.empty()) { InitParamMap(); } const map<string, int>& weaponMap = weaponDefHandler->weaponID; map<string, int>::const_iterator wit; for (wit = weaponMap.begin(); wit != weaponMap.end(); ++wit) { const WeaponDef* wd = &weaponDefHandler->weaponDefs[wit->second]; if (wd == NULL) { continue; } lua_pushnumber(L, wd->id); lua_newtable(L); { // the proxy table lua_newtable(L); { // the metatable HSTR_PUSH(L, "__index"); lua_pushlightuserdata(L, (void*)wd); lua_pushcclosure(L, WeaponDefIndex, 1); lua_rawset(L, -3); // closure HSTR_PUSH(L, "__newindex"); lua_pushlightuserdata(L, (void*)wd); lua_pushcclosure(L, WeaponDefNewIndex, 1); lua_rawset(L, -3); HSTR_PUSH(L, "__metatable"); lua_pushlightuserdata(L, (void*)wd); lua_pushcclosure(L, WeaponDefMetatable, 1); lua_rawset(L, -3); } lua_setmetatable(L, -2); } HSTR_PUSH(L, "pairs"); lua_pushcfunction(L, Pairs); lua_rawset(L, -3); HSTR_PUSH(L, "next"); lua_pushcfunction(L, Next); lua_rawset(L, -3); lua_rawset(L, -3); // proxy table into WeaponDefs } return true; }
bool LuaFeatureDefs::PushEntries(lua_State* L) { if (paramMap.empty()) { InitParamMap(); } const map<string, const FeatureDef*>& featureDefs = featureHandler->GetFeatureDefs(); map<string, const FeatureDef*>::const_iterator fdIt; for (fdIt = featureDefs.begin(); fdIt != featureDefs.end(); ++fdIt) { const FeatureDef* fd = fdIt->second; if (fd == NULL) { continue; } lua_pushnumber(L, fd->id); lua_newtable(L); { // the proxy table lua_newtable(L); { // the metatable HSTR_PUSH(L, "__index"); lua_pushlightuserdata(L, (void*)fd); lua_pushcclosure(L, FeatureDefIndex, 1); lua_rawset(L, -3); // closure HSTR_PUSH(L, "__newindex"); lua_pushlightuserdata(L, (void*)fd); lua_pushcclosure(L, FeatureDefNewIndex, 1); lua_rawset(L, -3); HSTR_PUSH(L, "__metatable"); lua_pushlightuserdata(L, (void*)fd); lua_pushcclosure(L, FeatureDefMetatable, 1); lua_rawset(L, -3); } lua_setmetatable(L, -2); } HSTR_PUSH(L, "pairs"); lua_pushcfunction(L, Pairs); lua_rawset(L, -3); HSTR_PUSH(L, "next"); lua_pushcfunction(L, Next); lua_rawset(L, -3); lua_rawset(L, -3); // proxy table into FeatureDefs } return true; }
void LuaUtils::PushCommandDesc(lua_State* L, const CommandDescription& cd) { const int numParams = cd.params.size(); const int numTblKeys = 12; lua_checkstack(L, 1 + 1 + 1 + 1); lua_createtable(L, 0, numTblKeys); HSTR_PUSH_NUMBER(L, "id", cd.id); HSTR_PUSH_NUMBER(L, "type", cd.type); HSTR_PUSH_STRING(L, "name", cd.name); HSTR_PUSH_STRING(L, "action", cd.action); HSTR_PUSH_STRING(L, "tooltip", cd.tooltip); HSTR_PUSH_STRING(L, "texture", cd.iconname); HSTR_PUSH_STRING(L, "cursor", cd.mouseicon); HSTR_PUSH_BOOL(L, "hidden", cd.hidden); HSTR_PUSH_BOOL(L, "disabled", cd.disabled); HSTR_PUSH_BOOL(L, "showUnique", cd.showUnique); HSTR_PUSH_BOOL(L, "onlyTexture", cd.onlyTexture); HSTR_PUSH(L, "params"); lua_createtable(L, 0, numParams); for (int p = 0; p < numParams; p++) { lua_pushsstring(L, cd.params[p]); lua_rawseti(L, -2, p + 1); } // CmdDesc["params"] = {[1] = "string1", [2] = "string2", ...} lua_settable(L, -3); }
bool CLuaHandle::AddBasicCalls() { HSTR_PUSH(L, "Script"); lua_newtable(L); { HSTR_PUSH_CFUNC(L, "Kill", KillActiveHandle); HSTR_PUSH_CFUNC(L, "GetName", CallOutGetName); HSTR_PUSH_CFUNC(L, "GetSynced", CallOutGetSynced); HSTR_PUSH_CFUNC(L, "GetFullCtrl", CallOutGetFullCtrl); HSTR_PUSH_CFUNC(L, "GetFullRead", CallOutGetFullRead); HSTR_PUSH_CFUNC(L, "GetCtrlTeam", CallOutGetCtrlTeam); HSTR_PUSH_CFUNC(L, "GetReadTeam", CallOutGetReadTeam); HSTR_PUSH_CFUNC(L, "GetReadAllyTeam", CallOutGetReadAllyTeam); HSTR_PUSH_CFUNC(L, "GetSelectTeam", CallOutGetSelectTeam); HSTR_PUSH_CFUNC(L, "GetGlobal", CallOutGetGlobal); HSTR_PUSH_CFUNC(L, "GetRegistry", CallOutGetRegistry); HSTR_PUSH_CFUNC(L, "GetCallInList", CallOutGetCallInList); // special team constants HSTR_PUSH_NUMBER(L, "NO_ACCESS_TEAM", CEventClient::NoAccessTeam); HSTR_PUSH_NUMBER(L, "ALL_ACCESS_TEAM", CEventClient::AllAccessTeam); //FIXME LuaArrays::PushEntries(L); } lua_rawset(L, -3); // extra math utilities lua_getglobal(L, "math"); LuaBitOps::PushEntries(L); lua_pop(L, 1); return true; }
bool CLuaHandle::DefaultCommand(const CUnit* unit, const CFeature* feature, int& cmd) { LUA_CALL_IN_CHECK(L); lua_checkstack(L, 4); static const LuaHashString cmdStr("DefaultCommand"); if (!PushUnsyncedCallIn(cmdStr)) { return false; } int args = 0; if (unit) { HSTR_PUSH(L, "unit"); lua_pushnumber(L, unit->id); args = 2; } else if (feature) { HSTR_PUSH(L, "feature"); lua_pushnumber(L, feature->id); args = 2; } /* FIXME else if (groundPos) { HSTR_PUSH(L, "ground"); lua_pushnumber(L, groundPos->x); lua_pushnumber(L, groundPos->y); lua_pushnumber(L, groundPos->z); args = 4; } else { HSTR_PUSH(L, "selection"); args = 1; } */ // call the routine RunCallInUnsynced(cmdStr, args, 1); if (!lua_isnumber(L, 1)) { lua_pop(L, 1); return false; } cmd = lua_toint(L, -1); lua_pop(L, 1); return true; }
static int DrawTypeString(lua_State* L, const void* data) { const int drawType = *((const int*)data); switch (drawType) { case DRAWTYPE_MODEL: { HSTR_PUSH(L, "model"); break; } case DRAWTYPE_NONE: { HSTR_PUSH(L, "none"); break; } default: { if (drawType >= DRAWTYPE_TREE) { HSTR_PUSH(L, "tree"); } else { HSTR_PUSH(L, "unknown"); } break; } } return 1; }
static inline void PushRealTable(lua_State* L, int index, const char* name) { if (lua_getmetatable(L, 1) == 0) { luaL_error(L, "Error: using %s() with an invalid table", name); } HSTR_PUSH(L, "realTable"); lua_rawget(L, -2); if (!lua_istable(L, -1)) { luaL_error(L, "Error: using %s() with an invalid table", name); } return; }
bool LuaSyncedTable::PushEntries(lua_State* L) { HSTR_PUSH(L, "SYNCED"); lua_pushvalue(L, LUA_GLOBALSINDEX); WrapTable(L); // replace the GLOBAL table with a proxy lua_rawset(L, -3); LuaPushNamedCFunc(L, "snext", Next); LuaPushNamedCFunc(L, "spairs", Pairs); LuaPushNamedCFunc(L, "sipairs", IPairs); return true; }
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 ModelTable(lua_State* L, const void* data) { const UnitDef* ud = static_cast<const UnitDef*>(data); const std::string modelFile = modelParser->FindModelPath(ud->modelName); lua_newtable(L); HSTR_PUSH_STRING(L, "type", StringToLower(FileSystem::GetExtension(modelFile))); HSTR_PUSH_STRING(L, "path", modelFile); HSTR_PUSH_STRING(L, "name", ud->modelName); HSTR_PUSH(L, "textures"); lua_newtable(L); if (ud->model != NULL) { LuaPushNamedString(L, "tex1", ud->model->tex1); LuaPushNamedString(L, "tex2", ud->model->tex2); } lua_rawset(L, -3); return 1; }
bool CLuaHandle::MapDrawCmd(int playerID, int type, const float3* pos0, const float3* pos1, const string* label) { if (!CheckModUICtrl()) { return false; } LUA_CALL_IN_CHECK(L); lua_checkstack(L, 9); static const LuaHashString cmdStr("MapDrawCmd"); if (!PushUnsyncedCallIn(cmdStr)) { return false; // the call is not defined } int args; lua_pushnumber(L, playerID); if (type == CInMapDraw::NET_POINT) { HSTR_PUSH(L, "point"); lua_pushnumber(L, pos0->x); lua_pushnumber(L, pos0->y); lua_pushnumber(L, pos0->z); lua_pushstring(L, label->c_str()); args = 6; } else if (type == CInMapDraw::NET_LINE) { HSTR_PUSH(L, "line"); lua_pushnumber(L, pos0->x); lua_pushnumber(L, pos0->y); lua_pushnumber(L, pos0->z); lua_pushnumber(L, pos1->x); lua_pushnumber(L, pos1->y); lua_pushnumber(L, pos1->z); args = 8; } else if (type == CInMapDraw::NET_ERASE) { HSTR_PUSH(L, "erase"); lua_pushnumber(L, pos0->x); lua_pushnumber(L, pos0->y); lua_pushnumber(L, pos0->z); lua_pushnumber(L, 100.0f); // radius args = 6; } else { logOutput.Print("Unknown MapDrawCmd() type"); lua_pop(L, 2); // pop the function and playerID return false; } // call the routine if (!RunCallInUnsynced(cmdStr, args, 1)) { return false; } // take the event? if (!lua_isboolean(L, -1)) { lua_pop(L, 1); return false; } const bool retval = lua_toboolean(L, -1); lua_pop(L, 1); return retval; }
bool CLuaHandleSynced::SetupSynced(lua_State *L, const string& code, const string& filename) { if (!IsValid() || code.empty()) { return false; } lua_pushvalue(L, LUA_GLOBALSINDEX); HSTR_PUSH(L, "EXPORT"); lua_newtable(L); lua_rawset(L, -3); AddBasicCalls(L); // into Global lua_pushliteral(L, "Script"); lua_rawget(L, -2); LuaPushNamedCFunc(L, "AddActionFallback", AddSyncedActionFallback); LuaPushNamedCFunc(L, "RemoveActionFallback", RemoveSyncedActionFallback); LuaPushNamedCFunc(L, "UpdateCallIn", CallOutSyncedUpdateCallIn); LuaPushNamedCFunc(L, "GetWatchUnit", GetWatchUnitDef); LuaPushNamedCFunc(L, "SetWatchUnit", SetWatchUnitDef); LuaPushNamedCFunc(L, "GetWatchFeature", GetWatchFeatureDef); LuaPushNamedCFunc(L, "SetWatchFeature", SetWatchFeatureDef); LuaPushNamedCFunc(L, "GetWatchWeapon", GetWatchWeaponDef); LuaPushNamedCFunc(L, "SetWatchWeapon", SetWatchWeaponDef); lua_pop(L, 1); // add the custom file loader LuaPushNamedCFunc(L, "SendToUnsynced", SendToUnsynced); LuaPushNamedCFunc(L, "loadstring", LoadStringData); LuaPushNamedCFunc(L, "CallAsTeam", CallAsTeam); LuaPushNamedNumber(L, "COBSCALE", COBSCALE); // load our libraries (LuaSyncedCtrl overrides some LuaUnsyncedCtrl entries) if (!AddEntriesToTable(L, "VFS", LuaVFS::PushSynced) || !AddEntriesToTable(L, "VFS", LuaZipFileReader::PushSynced) || !AddEntriesToTable(L, "VFS", LuaZipFileWriter::PushSynced) || !AddEntriesToTable(L, "UnitDefs", LuaUnitDefs::PushEntries) || !AddEntriesToTable(L, "WeaponDefs", LuaWeaponDefs::PushEntries) || !AddEntriesToTable(L, "FeatureDefs", LuaFeatureDefs::PushEntries) || !AddEntriesToTable(L, "Script", LuaSyncedCall::PushEntries) || !AddEntriesToTable(L, "Spring", LuaUnsyncedCtrl::PushEntries) || !AddEntriesToTable(L, "Spring", LuaSyncedCtrl::PushEntries) || !AddEntriesToTable(L, "Spring", LuaSyncedRead::PushEntries) || !AddEntriesToTable(L, "Game", LuaConstGame::PushEntries) || !AddEntriesToTable(L, "CMD", LuaConstCMD::PushEntries) || !AddEntriesToTable(L, "CMDTYPE", LuaConstCMDTYPE::PushEntries) || !AddEntriesToTable(L, "COB", LuaConstCOB::PushEntries) || !AddEntriesToTable(L, "SFX", LuaConstSFX::PushEntries) || !AddEntriesToTable(L, "LOG", LuaUtils::PushLogEntries) ) { KillLua(); return false; } // add code from the sub-class if (!AddSyncedCode(L)) { KillLua(); return false; } lua_settop(L, 0); if (!LoadCode(L, code, filename)) { KillLua(); return false; } return true; }