void CMapInfo::ReadTerrainTypes() { const LuaTable terrTypeTable = mapRoot->SubTable("terrainTypes"); for (int tt = 0; tt < 256; tt++) { TerrainType& terrType = terrainTypes[tt]; const LuaTable terrain = terrTypeTable.SubTable(tt); terrType.name = terrain.GetString("name", "Default"); terrType.hardness = terrain.GetFloat("hardness", 1.0f); terrType.receiveTracks = terrain.GetBool("receiveTracks", true); const LuaTable moveTable = terrain.SubTable("moveSpeeds"); terrType.tankSpeed = moveTable.GetFloat("tank", 1.0f); terrType.kbotSpeed = moveTable.GetFloat("kbot", 1.0f); terrType.hoverSpeed = moveTable.GetFloat("hover", 1.0f); terrType.shipSpeed = moveTable.GetFloat("ship", 1.0f); // clamps terrType.hardness = max(0.0f, terrType.hardness); terrType.tankSpeed = max(0.0f, terrType.tankSpeed); terrType.kbotSpeed = max(0.0f, terrType.kbotSpeed); terrType.hoverSpeed = max(0.0f, terrType.hoverSpeed); terrType.shipSpeed = max(0.0f, terrType.shipSpeed); } }
void CArchiveScanner::ReadCacheData(const std::string& filename) { if (!FileSystem::FileExists(filename)) { LOG_L(L_INFO, "Archive cache doesn't exist: %s", filename.c_str()); return; } LuaParser p(filename, SPRING_VFS_RAW, SPRING_VFS_BASE); if (!p.Execute()) { LOG_L(L_ERROR, "Failed to parse archive cache: %s", p.GetErrorLog().c_str()); return; } const LuaTable archiveCache = p.GetRoot(); // Do not load old version caches const int ver = archiveCache.GetInt("internalVer", (INTERNAL_VER + 1)); if (ver != INTERNAL_VER) { return; } const LuaTable archives = archiveCache.SubTable("archives"); for (int i = 1; archives.KeyExists(i); ++i) { const LuaTable curArchive = archives.SubTable(i); const LuaTable archived = curArchive.SubTable("archivedata"); std::string name = curArchive.GetString("name", ""); ArchiveInfo& ai = archiveInfos[StringToLower(name)]; ai.origName = name; ai.path = curArchive.GetString("path", ""); // do not use LuaTable.GetInt() for 32-bit integers, the Spring lua // library uses 32-bit floats to represent numbers, which can only // represent 2^24 consecutive integers ai.modified = strtoul(curArchive.GetString("modified", "0").c_str(), 0, 10); ai.checksum = strtoul(curArchive.GetString("checksum", "0").c_str(), 0, 10); ai.updated = false; ai.archiveData = CArchiveScanner::ArchiveData(archived, true); if (ai.archiveData.GetModType() == modtype::map) { AddDependency(ai.archiveData.GetDependencies(), "Map Helper v1"); } else if (ai.archiveData.GetModType() == modtype::primary) { AddDependency(ai.archiveData.GetDependencies(), "Spring content v1"); } } const LuaTable brokenArchives = archiveCache.SubTable("brokenArchives"); for (int i = 1; brokenArchives.KeyExists(i); ++i) { const LuaTable curArchive = brokenArchives.SubTable(i); std::string name = curArchive.GetString("name", ""); StringToLowerInPlace(name); BrokenArchive& ba = this->brokenArchives[name]; ba.path = curArchive.GetString("path", ""); ba.modified = strtoul(curArchive.GetString("modified", "0").c_str(), 0, 10); ba.updated = false; ba.problem = curArchive.GetString("problem", "unknown"); } isDirty = false; }
void CUnitDefHandler::LoadSounds(const LuaTable& soundsTable, GuiSoundSet& gsound, const string& soundName) { string fileName = soundsTable.GetString(soundName, ""); if (!fileName.empty()) { LoadSound(gsound, fileName, 1.0f); return; } LuaTable sndTable = soundsTable.SubTable(soundName); for (int i = 1; true; i++) { LuaTable sndFileTable = sndTable.SubTable(i); if (sndFileTable.IsValid()) { fileName = sndFileTable.GetString("file", ""); if (!fileName.empty()) { const float volume = sndFileTable.GetFloat("volume", 1.0f); if (volume > 0.0f) { LoadSound(gsound, fileName, volume); } } } else { fileName = sndTable.GetString(i, ""); if (fileName.empty()) { break; } LoadSound(gsound, fileName, 1.0f); } } }
bool CSound::LoadSoundDefs(const std::string& filename) { //! can be called from LuaUnsyncedCtrl too boost::mutex::scoped_lock lck(soundMutex); LuaParser parser(filename, SPRING_VFS_MOD, SPRING_VFS_ZIP); parser.SetLowerKeys(false); parser.SetLowerCppKeys(false); parser.Execute(); if (!parser.IsValid()) { LogObject(LOG_SOUND) << "Could not load " << filename << ": " << parser.GetErrorLog(); return false; } else { const LuaTable soundRoot = parser.GetRoot(); const LuaTable soundItemTable = soundRoot.SubTable("SoundItems"); if (!soundItemTable.IsValid()) { LogObject(LOG_SOUND) << "CSound(): could not parse SoundItems table in " << filename; return false; } else { std::vector<std::string> keys; soundItemTable.GetKeys(keys); for (std::vector<std::string>::const_iterator it = keys.begin(); it != keys.end(); ++it) { const std::string name(*it); soundItemDef bufmap; const LuaTable buf(soundItemTable.SubTable(*it)); buf.GetMap(bufmap); bufmap["name"] = name; soundItemDefMap::const_iterator sit = soundItemDefs.find(name); if (sit != soundItemDefs.end()) LogObject(LOG_SOUND) << "CSound(): two SoundItems have the same name: " << name; soundItemDef::const_iterator inspec = bufmap.find("file"); if (inspec == bufmap.end()) // no file, drop LogObject(LOG_SOUND) << "CSound(): SoundItem has no file tag: " << name; else soundItemDefs[name] = bufmap; if (buf.KeyExists("preload")) { LogObject(LOG_SOUND) << "CSound(): preloading " << name; const size_t newid = sounds.size(); sounds.push_back(new SoundItem(GetWaveBuffer(bufmap["file"], true), bufmap)); soundMap[name] = newid; } } LogObject(LOG_SOUND) << "CSound(): Sucessfully parsed " << keys.size() << " SoundItems from " << filename; } } return true; }
bool CSound::LoadSoundDefs(const std::string& fileName) { //! can be called from LuaUnsyncedCtrl too boost::recursive_mutex::scoped_lock lck(soundMutex); LuaParser parser(fileName, SPRING_VFS_MOD, SPRING_VFS_ZIP); parser.SetLowerKeys(false); parser.SetLowerCppKeys(false); parser.Execute(); if (!parser.IsValid()) { LOG_L(L_WARNING, "Could not load %s: %s", fileName.c_str(), parser.GetErrorLog().c_str()); return false; } else { const LuaTable soundRoot = parser.GetRoot(); const LuaTable soundItemTable = soundRoot.SubTable("SoundItems"); if (!soundItemTable.IsValid()) { LOG_L(L_WARNING, "CSound(): could not parse SoundItems table in %s", fileName.c_str()); return false; } else { std::vector<std::string> keys; soundItemTable.GetKeys(keys); for (std::vector<std::string>::const_iterator it = keys.begin(); it != keys.end(); ++it) { const std::string name(*it); soundItemDef bufmap; const LuaTable buf(soundItemTable.SubTable(*it)); buf.GetMap(bufmap); bufmap["name"] = name; soundItemDefMap::const_iterator sit = soundItemDefs.find(name); if (sit != soundItemDefs.end()) LOG_L(L_WARNING, "Sound %s gets overwritten by %s", name.c_str(), fileName.c_str()); soundItemDef::const_iterator inspec = bufmap.find("file"); if (inspec == bufmap.end()) { // no file, drop LOG_L(L_WARNING, "Sound %s is missing file tag (ignoring)", name.c_str()); } else { soundItemDefs[name] = bufmap; } if (buf.KeyExists("preload")) { MakeItemFromDef(bufmap); } } LOG(" parsed %i sounds from %s", (int)keys.size(), fileName.c_str()); } } return true; }
void CMapInfo::ReadStartPos() { const float defX = 1000.0f; const float defZ = 1000.0f; const float defXStep = 100.0f; const float defZStep = 100.0f; const LuaTable teamsTable = mapRoot->SubTable("teams"); for (int t = 0; t < MAX_TEAMS; ++t) { float3 pos; pos.x = defX + (defXStep * t); pos.z = defZ + (defZStep * t); pos.y = 0.0f; const LuaTable posTable = teamsTable.SubTable(t).SubTable("startPos"); if (posTable.KeyExists("x") && posTable.KeyExists("z")) { pos.x = posTable.GetFloat("x", pos.x); pos.z = posTable.GetFloat("z", pos.z); havePos.push_back(true); } else { havePos.push_back(false); } startPos.push_back(pos); } }
CDamageArrayHandler::CDamageArrayHandler(LuaParser* defsParser) { #define DEFAULT_ARMORDEF_NAME "default" try { const LuaTable rootTable = defsParser->GetRoot().SubTable("ArmorDefs"); if (!rootTable.IsValid()) throw content_error("Error loading ArmorDefs"); // GetKeys() sorts the keys, so can not simply push_back before call rootTable.GetKeys(armorDefKeys); armorDefKeys.insert(armorDefKeys.begin(), DEFAULT_ARMORDEF_NAME); armorDefNameIdxMap[DEFAULT_ARMORDEF_NAME] = 0; LOG("[%s] number of ArmorDefs: " _STPF_, __FUNCTION__, armorDefKeys.size()); // expects the following structure, subtables must be in array-format: // // {"tanks" = {[1] = "supertank", [2] = "megatank"}, "infantry" = {[1] = "dude"}, ...} // // the old (pre-95.0) <key, value> subtable definitions are no longer supported! // for (unsigned int armorDefIdx = 1; armorDefIdx < armorDefKeys.size(); armorDefIdx++) { const std::string armorDefName = StringToLower(armorDefKeys[armorDefIdx]); if (armorDefName == DEFAULT_ARMORDEF_NAME) { // ignore, no need to clear entire table LOG_L(L_WARNING, "[%s] ArmorDefs: tried to define the \"%s\" armor type!", __FUNCTION__, DEFAULT_ARMORDEF_NAME); continue; } armorDefNameIdxMap[armorDefName] = armorDefIdx; const LuaTable armorDefTable = rootTable.SubTable(armorDefKeys[armorDefIdx]); const unsigned int numArmorDefEntries = armorDefTable.GetLength(); for (unsigned int armorDefEntryIdx = 0; armorDefEntryIdx < numArmorDefEntries; armorDefEntryIdx++) { const std::string& unitDefName = StringToLower(armorDefTable.GetString(armorDefEntryIdx + 1, "")); const auto armorDefTableIt = armorDefNameIdxMap.find(unitDefName); if (armorDefTableIt == armorDefNameIdxMap.end()) { armorDefNameIdxMap[unitDefName] = armorDefIdx; continue; } LOG_L(L_WARNING, "[%s] UnitDef \"%s\" in ArmorDef \"%s\" already belongs to ArmorDef category %d!", __FUNCTION__, unitDefName.c_str(), armorDefName.c_str(), armorDefTableIt->second); } } } catch (const content_error&) { armorDefNameIdxMap.clear(); armorDefNameIdxMap[DEFAULT_ARMORDEF_NAME] = 0; armorDefKeys.clear(); armorDefKeys.push_back(DEFAULT_ARMORDEF_NAME); } }
CFeatureHandler::CFeatureHandler() : nextFreeID(0) { PrintLoadMsg("Loading feature definitions"); drawQuadsX = gs->mapx/DRAW_QUAD_SIZE; drawQuadsY = gs->mapy/DRAW_QUAD_SIZE; drawQuads.resize(drawQuadsX * drawQuadsY); treeDrawer = CBaseTreeDrawer::GetTreeDrawer(); const LuaTable rootTable = game->defsParser->GetRoot().SubTable("FeatureDefs"); if (!rootTable.IsValid()) { throw content_error("Error loading FeatureDefs"); } //! featureDefIDs start with 1 featureDefsVector.push_back(NULL); //! get most of the feature defs (missing trees and geovent from the map) vector<string> keys; rootTable.GetKeys(keys); for (int i = 0; i < (int)keys.size(); i++) { const string& name = keys[i]; const LuaTable fdTable = rootTable.SubTable(name); CreateFeatureDef(fdTable, name); } }
CWeaponDefHandler::CWeaponDefHandler() { PrintLoadMsg("Loading weapon definitions"); const LuaTable rootTable = game->defsParser->GetRoot().SubTable("WeaponDefs"); if (!rootTable.IsValid()) { throw content_error("Error loading WeaponDefs"); } vector<string> weaponNames; rootTable.GetKeys(weaponNames); numWeaponDefs = weaponNames.size(); // FIXME: starting at 0, don't need the +1 ? weaponDefs = SAFE_NEW WeaponDef[numWeaponDefs + 1]; for (int wid = 0; wid < (int)weaponNames.size(); wid++) { WeaponDef& wd = weaponDefs[wid]; wd.id = wid; wd.name = weaponNames[wid]; weaponID[wd.name] = wid; const LuaTable wdTable = rootTable.SubTable(wd.name); ParseTAWeapon(wdTable, wd); } }
CWeaponDefHandler::CWeaponDefHandler() { PrintLoadMsg("Loading weapon definitions"); const LuaTable rootTable = game->defsParser->GetRoot().SubTable("WeaponDefs"); if (!rootTable.IsValid()) { throw content_error("Error loading WeaponDefs"); } vector<string> weaponNames; rootTable.GetKeys(weaponNames); numWeaponDefs = weaponNames.size(); weaponDefs = new WeaponDef[numWeaponDefs]; for (int wid = 0; wid < numWeaponDefs; wid++) { WeaponDef& wd = weaponDefs[wid]; wd.id = wid; wd.name = weaponNames[wid]; weaponID[wd.name] = wid; const LuaTable wdTable = rootTable.SubTable(wd.name); ParseWeapon(wdTable, wd); } }
CUnitDefHandler::CUnitDefHandler(void) : noCost(false) { const LuaTable rootTable = game->defsParser->GetRoot().SubTable("UnitDefs"); if (!rootTable.IsValid()) { throw content_error("Error loading UnitDefs"); } vector<string> unitDefNames; rootTable.GetKeys(unitDefNames); unitDefs.reserve(unitDefNames.size() + 1); UnitDef* nullDef = new UnitDef(); unitDefs.push_back(nullDef); for (unsigned int a = 0; a < unitDefNames.size(); ++a) { const string unitName = unitDefNames[a]; LuaTable udTable = rootTable.SubTable(unitName); // parse the unitdef data (but don't load buildpics, etc...) PushNewUnitDef(unitName, udTable); } CleanBuildOptions(); FindStartUnits(); ProcessDecoys(); AssignTechLevels(); }
void CArchiveScanner::ReadCacheData(const string& filename) { LuaParser p(filename, SPRING_VFS_RAW, SPRING_VFS_BASE); if (!p.Execute()) { logOutput.Print("ERROR in " + filename + ": " + p.GetErrorLog()); } const LuaTable archiveCache = p.GetRoot(); const LuaTable archives = archiveCache.SubTable("archives"); // Do not load old version caches const int ver = archiveCache.GetInt("internalVer", (INTERNAL_VER + 1)); if (ver != INTERNAL_VER) { return; } for (int i = 1; archives.KeyExists(i); ++i) { const LuaTable curArchive = archives.SubTable(i); const LuaTable archived = curArchive.SubTable("archivedata"); ArchiveInfo ai; ai.origName = curArchive.GetString("name", ""); ai.path = curArchive.GetString("path", ""); // do not use LuaTable.GetInt() for 32-bit integers, the Spring lua // library uses 32-bit floats to represent numbers, which can only // represent 2^24 consecutive integers ai.modified = strtoul(curArchive.GetString("modified", "0").c_str(), 0, 10); ai.checksum = strtoul(curArchive.GetString("checksum", "0").c_str(), 0, 10); ai.updated = false; ai.archiveData = GetArchiveData(archived); if (ai.archiveData.modType == modtype::map) AddDependency(ai.archiveData.dependencies, "maphelper.sdz"); else if (ai.archiveData.modType == modtype::primary) AddDependency(ai.archiveData.dependencies, "Spring content v1"); string lcname = StringToLower(ai.origName); archiveInfo[lcname] = ai; } isDirty = false; }
CArchiveScanner::ArchiveData CArchiveScanner::GetArchiveData(const LuaTable& archiveTable) { ArchiveData md; if (!archiveTable.IsValid()) { return md; } md.name = archiveTable.GetString("name", ""); md.shortName = archiveTable.GetString("shortName", ""); md.version = archiveTable.GetString("version", ""); md.mutator = archiveTable.GetString("mutator", ""); md.game = archiveTable.GetString("game", ""); md.shortGame = archiveTable.GetString("shortGame", ""); md.description = archiveTable.GetString("description", ""); md.modType = archiveTable.GetInt("modType", 0); md.mapfile = archiveTable.GetString("mapfile", ""); const LuaTable dependencies = archiveTable.SubTable("depend"); for (int dep = 1; dependencies.KeyExists(dep); ++dep) { const std::string depend = dependencies.GetString(dep, ""); md.dependencies.push_back(depend); } const LuaTable replaces = archiveTable.SubTable("replace"); for (int rep = 1; replaces.KeyExists(rep); ++rep) { md.replaces.push_back(replaces.GetString(rep, "")); } // HACK needed until lobbies, lobbyserver and unitsync are sorted out // so they can uniquely identify different versions of the same mod. // (at time of this writing they use name only) // NOTE when changing this, this function is used both by the code that // reads ArchiveCache.lua and the code that reads modinfo.lua from the mod. // so make sure it doesn't keep adding stuff to the name everytime // Spring/unitsync is loaded. if (md.name.find(md.version) == std::string::npos && !md.version.empty()) { md.name += " " + md.version; } return md; }
void CSyncer::LoadUnits(bool checksum) { unitsLeft = 0; LuaParser luaParser("gamedata/defs.lua", SPRING_VFS_MOD_BASE, SPRING_VFS_ZIP); if (!luaParser.Execute()) { logOutput.Print("luaParser.Execute() failed"); return; } LuaTable rootTable = luaParser.GetRoot().SubTable("UnitDefs"); if (!rootTable.IsValid()) { logOutput.Print("root unitdef table invalid"); return; } vector<string> unitDefNames; rootTable.GetKeys(unitDefNames); const int count = (int)unitDefNames.size(); for (int i = 0; i < count; ++i) { const string& udName = unitDefNames[i]; LuaTable udTable = rootTable.SubTable(udName); Unit u; u.fullName = udTable.GetString("name", udName); if (checksum) { const string fileName = udTable.GetString("filename", ""); const string deadName = udTable.GetString("corpse", udName + "_dead"); const string modelName = udTable.GetString("objectname", udName); u.fbi = CalculateCRC(fileName); u.cob = CalculateCRC("scripts/" + udName + ".cob"); u.model = CalculateCRC("objects3d/" + modelName); // s3o ? u.model += CalculateCRC("objects3d/" + modelName + ".3do"); u.model += CalculateCRC("objects3d/" + deadName + ".3do"); } units[udName] = u; } // map the unitIds map<string, Unit>::iterator mit; for (mit = units.begin(); mit != units.end(); ++mit) { unitIds.push_back(mit->first); } unitsLeft = count; return; }
bool SideParser::Load() { dataVec.clear(); errorLog.clear(); LuaParser parser("gamedata/sidedata.lua", SPRING_VFS_MOD_BASE, SPRING_VFS_MOD_BASE); #if !defined UNITSYNC && !defined DEDICATED // this should not be included with unitsync: // 1. avoids linkage with LuaSyncedRead // 2. ModOptions are not valid during unitsync mod parsing parser.GetTable("Spring"); parser.AddFunc("GetModOptions", LuaSyncedRead::GetModOptions); parser.EndTable(); #endif if (!parser.Execute()) { errorLog = parser.GetErrorLog(); return false; } set<string> sideSet; const LuaTable root = parser.GetRoot(); for (int i = 1; /* no-op */; i++) { const LuaTable sideTable = root.SubTable(i); if (!sideTable.IsValid()) { break; } Data data; data.caseName = sideTable.GetString("name", ""); data.sideName = StringToLower(data.caseName); data.startUnit = sideTable.GetString("startUnit", ""); data.startUnit = StringToLower(data.startUnit); if (data.sideName.empty()) { logOutput.Print("Missing side name: %i", i); } else if (data.startUnit.empty()) { logOutput.Print("Missing side start unit: " + data.sideName); } else { if (sideSet.find(data.sideName) != sideSet.end()) { logOutput.Print("Duplicate side name: " + data.sideName); } else { sideSet.insert(data.sideName); dataVec.push_back(data); } } } return true; }
CExplosionGeneratorHandler::CExplosionGeneratorHandler() : luaParser("gamedata/explosions.lua", SPRING_VFS_MOD_BASE, SPRING_VFS_ZIP) { LuaParser aliasParser("gamedata/explosion_alias.lua", SPRING_VFS_MOD_BASE, SPRING_VFS_ZIP); if (!aliasParser.Execute()) { logOutput.Print(aliasParser.GetErrorLog()); } else { const LuaTable root = aliasParser.GetRoot(); projectileClasses.Load(root.SubTable("projectiles")); generatorClasses.Load(root.SubTable("generators")); } if (!luaParser.Execute()) { logOutput.Print(luaParser.GetErrorLog()); } else { luaTable = luaParser.GetRoot(); } }
void CUnitDefHandler::UnitDefLoadSounds(UnitDef* ud, const LuaTable& udTable) { LuaTable soundsTable = udTable.SubTable("sounds"); LoadSounds(soundsTable, ud->sounds.ok, "ok"); // eg. "ok1", "ok2", ... LoadSounds(soundsTable, ud->sounds.select, "select"); // eg. "select1", "select2", ... LoadSounds(soundsTable, ud->sounds.arrived, "arrived"); // eg. "arrived1", "arrived2", ... LoadSounds(soundsTable, ud->sounds.build, "build"); LoadSounds(soundsTable, ud->sounds.activate, "activate"); LoadSounds(soundsTable, ud->sounds.deactivate, "deactivate"); LoadSounds(soundsTable, ud->sounds.cant, "cant"); LoadSounds(soundsTable, ud->sounds.underattack, "underattack"); }
void CProjectileDrawer::ParseAtlasTextures( const bool blockTextures, const LuaTable& textureTable, std::set<std::string>& blockedTextures, CTextureAtlas* textureAtlas) { std::vector<std::string> subTables; std::map<std::string, std::string> texturesMap; std::map<std::string, std::string>::iterator texturesMapIt; textureTable.GetMap(texturesMap); textureTable.GetKeys(subTables); for (texturesMapIt = texturesMap.begin(); texturesMapIt != texturesMap.end(); ++texturesMapIt) { const std::string textureName = StringToLower(texturesMapIt->first); if (blockTextures) { // no textures added to this atlas are allowed // to be overwritten later by other textures of // the same name blockedTextures.insert(textureName); } if (blockTextures || (blockedTextures.find(textureName) == blockedTextures.end())) { textureAtlas->AddTexFromFile(texturesMapIt->first, "bitmaps/" + texturesMapIt->second); } } texturesMap.clear(); for (size_t i = 0; i < subTables.size(); i++) { const LuaTable& textureSubTable = textureTable.SubTable(subTables[i]); if (textureSubTable.IsValid()) { textureSubTable.GetMap(texturesMap); for (texturesMapIt = texturesMap.begin(); texturesMapIt != texturesMap.end(); ++texturesMapIt) { const std::string textureName = StringToLower(texturesMapIt->first); if (blockTextures) { blockedTextures.insert(textureName); } if (blockTextures || (blockedTextures.find(textureName) == blockedTextures.end())) { textureAtlas->AddTexFromFile(texturesMapIt->first, "bitmaps/" + texturesMapIt->second); } } texturesMap.clear(); } } }
bool MapParser::GetStartPos(int team, float3& pos) const { if (!parser->IsValid()) { return false; } const LuaTable teamsTable = parser->GetRoot().SubTable("teams"); const LuaTable posTable = teamsTable.SubTable(team).SubTable("startPos"); if (!posTable.IsValid()) { return false; } pos.x = posTable.GetFloat("x", pos.x); pos.z = posTable.GetFloat("z", pos.z); return true; }
void DefType::ReportUnknownTags(const std::string& instanceName, const LuaTable& luaTable, const std::string pre) { std::vector<std::string> keys; luaTable.GetKeys(keys); for (const std::string& tag: keys) { const DefTagMetaData* meta = GetMetaDataByExternalKey(pre + tag); if (meta != nullptr) continue; if (luaTable.GetType(tag) == LuaTable::TABLE) { ReportUnknownTags(instanceName, luaTable.SubTable(tag), pre + tag + "."); continue; } LOG_L(L_WARNING, "%s: Unknown tag \"%s%s\" in \"%s\"", name.c_str(), pre.c_str(), tag.c_str(), instanceName.c_str()); } }
bool MapParser::GetStartPos(int team, float3& pos) const { errorLog.clear(); if (!parser->IsValid()) { errorLog = "Map-Parser: Failed to get start position for team " + IntToString(team) + ", reason: " + parser->GetErrorLog(); return false; } const LuaTable teamsTable = parser->GetRoot().SubTable("teams"); const LuaTable posTable = teamsTable.SubTable(team).SubTable("startPos"); if (!posTable.IsValid()) { errorLog = "Map-Parser: Failed to get start position for team " + IntToString(team) + ", reason: Not defined in the map's config!"; return false; } pos.x = posTable.GetFloat("x", pos.x); pos.z = posTable.GetFloat("z", pos.z); return true; }
CFeatureHandler::CFeatureHandler() { const LuaTable rootTable = game->defsParser->GetRoot().SubTable("FeatureDefs"); if (!rootTable.IsValid()) { throw content_error("Error loading FeatureDefs"); } // featureDefIDs start with 1 featureDefsVector.push_back(NULL); // get most of the feature defs (missing trees and geovent from the map) vector<string> keys; rootTable.GetKeys(keys); for (int i = 0; i < (int)keys.size(); i++) { const string& nameMixedCase = keys[i]; const string& nameLowerCase = StringToLower(nameMixedCase); const LuaTable& fdTable = rootTable.SubTable(nameMixedCase); AddFeatureDef(nameLowerCase, CreateFeatureDef(fdTable, nameLowerCase)); } }
MoveDefHandler::MoveDefHandler(LuaParser* defsParser) { const LuaTable rootTable = defsParser->GetRoot().SubTable("MoveDefs"); if (!rootTable.IsValid()) throw content_error("Error loading movement definitions"); CRC crc; for (int tt = 0; tt < CMapInfo::NUM_TERRAIN_TYPES; ++tt) { const CMapInfo::TerrainType& terrType = mapInfo->terrainTypes[tt]; crc << terrType.tankSpeed << terrType.kbotSpeed; crc << terrType.hoverSpeed << terrType.shipSpeed; } moveDefs.reserve(rootTable.GetLength()); for (size_t num = 1; /* no test */; num++) { const LuaTable moveDefTable = rootTable.SubTable(num); if (!moveDefTable.IsValid()) { break; } moveDefs.emplace_back(moveDefTable, num); const MoveDef& md = moveDefs.back(); moveDefNames[md.name] = md.pathType; crc << md.GetCheckSum(); } CMoveMath::noHoverWaterMove = (mapInfo->water.damage >= MAX_ALLOWED_WATER_DAMAGE_HMM); CMoveMath::waterDamageCost = (mapInfo->water.damage >= MAX_ALLOWED_WATER_DAMAGE_GMM)? 0.0f: (1.0f / (1.0f + mapInfo->water.damage * 0.1f)); crc << CMoveMath::waterDamageCost; crc << CMoveMath::noHoverWaterMove; checksum = crc.GetDigest(); }
static bool info_parseInfoItem(const LuaTable& root, int index, InfoItem& inf, std::set<string>& infoSet) { const LuaTable& infsTbl = root.SubTable(index); if (!infsTbl.IsValid()) { LOG_L(L_WARNING, "parseInfoItem: subtable %d invalid", index); return false; } // common info properties inf.key = infsTbl.GetString("key", ""); if (inf.key.empty() || (inf.key.find_first_of(InfoItem_badKeyChars) != string::npos)) { LOG_L(L_WARNING, "parseInfoItem: empty key or key contains bad characters"); return false; } std::string lowerKey = StringToLower(inf.key); if (infoSet.find(inf.key) != infoSet.end()) { LOG_L(L_WARNING, "parseInfoItem: key toLowerCase(%s) exists already", inf.key.c_str()); return false; } // TODO add support for info value types other then string inf.valueType = INFO_VALUE_TYPE_STRING; inf.valueTypeString = infsTbl.GetString("value", ""); if (inf.valueTypeString.empty()) { LOG_L(L_WARNING, "parseInfoItem: %s: empty value", inf.key.c_str()); return false; } inf.desc = infsTbl.GetString("desc", ""); infoSet.insert(lowerKey); return true; }
/** Load the messages from gamedata/messages.lua into memory. */ void CMessages::Load() { LuaParser luaParser("gamedata/messages.lua", SPRING_VFS_MOD_BASE, SPRING_VFS_MOD_BASE); if (!luaParser.Execute()) { // Show parse errors in the infolog. logOutput.Print(string("ERROR: messages.lua: ") + luaParser.GetErrorLog()); return; } const LuaTable root = luaParser.GetRoot(); vector<string> labels; root.GetKeys(labels); for (size_t l = 0; l < labels.size(); l++) { const string label = StringToLower(labels[l]); const LuaTable msgTable = root.SubTable(label); if (!msgTable.IsValid()) { continue; } vector<string> msgs; for (int s = 1; true; s++) { const string msg = msgTable.GetString(s, ""); if (msg.empty()) { break; } msgs.push_back(msg); } if (!msgs.empty()) { tr[label] = msgs; } } loaded = true; }
static void option_parseOption(const LuaTable& root, int index, Option& opt, std::set<string>& optionsSet) { const LuaTable& optTbl = root.SubTable(index); if (!optTbl.IsValid()) { throw content_error("parseOption: subtable " + IntToString(index) + " is invalid"); } // common options properties opt.key = optTbl.GetString("key", ""); if (opt.key.empty() || (opt.key.find_first_of(Option_badKeyChars) != string::npos)) { throw content_error("parseOption: (key=\"" + opt.key + "\") empty key or key contains bad characters (\"" + Option_badKeyChars + "\")"); } opt.key = StringToLower(opt.key); opt.scope = optTbl.GetString("scope", "scope"); if (opt.scope.find_first_of(Option_badKeyChars) != string::npos) { throw content_error("parseOption: (key=" + opt.key + ") scope contains bad characters (\"" + Option_badKeyChars + "\"): \"" + opt.scope + "\""); } opt.scope = StringToLower(opt.scope); if (optionsSet.find(opt.key) != optionsSet.end()) { throw content_error("parseOption: key \"" + opt.key + "\" exists already"); } opt.name = optTbl.GetString("name", opt.key); if (opt.name.empty()) { throw content_error("parseOption: (key=" + opt.key + ") empty name"); } opt.desc = optTbl.GetString("desc", opt.name); opt.section = optTbl.GetString("section", ""); opt.style = optTbl.GetString("style", ""); opt.type = optTbl.GetString("type", ""); opt.type = StringToLower(opt.type); // option type specific properties if (opt.type == "bool") { opt.typeCode = opt_bool; opt.boolDef = optTbl.GetBool("def", false); } else if (opt.type == "number") { opt.typeCode = opt_number; opt.numberDef = optTbl.GetFloat("def", 0.0f); opt.numberMin = optTbl.GetFloat("min", -1.0e30f); opt.numberMax = optTbl.GetFloat("max", +1.0e30f); opt.numberStep = optTbl.GetFloat("step", 0.0f); } else if (opt.type == "string") { opt.typeCode = opt_string; opt.stringDef = optTbl.GetString("def", ""); opt.stringMaxLen = optTbl.GetInt("maxlen", 0); } else if (opt.type == "list") { opt.typeCode = opt_list; const LuaTable& listTbl = optTbl.SubTable("items"); if (!listTbl.IsValid()) { throw content_error("parseOption: (key=" + opt.key + ") subtables: items invalid"); } for (int i = 1; listTbl.KeyExists(i); i++) { OptionListItem item; // string format item.key = listTbl.GetString(i, ""); if (!item.key.empty() && (item.key.find_first_of(Option_badKeyChars) == string::npos)) { item.name = item.key; item.desc = item.name; opt.list.push_back(item); continue; } // table format (name & desc) const LuaTable& itemTbl = listTbl.SubTable(i); if (!itemTbl.IsValid()) { throw content_error("parseOption: (key=" + opt.key + ") subtables: subtable " + IntToString(i) + " contains invalid items"); } item.key = itemTbl.GetString("key", ""); if (item.key.empty() || (item.key.find_first_of(Option_badKeyChars) != string::npos)) { throw content_error("parseOption: (key=" + opt.key + ") subtables: (key=\"" + item.key + "\") empty key or key contains bad characters (\"" + Option_badKeyChars + "\")"); } item.key = StringToLower(item.key); item.name = itemTbl.GetString("name", item.key); if (item.name.empty()) { throw content_error("parseOption: (key=" + opt.key + ") subtables: (key=" + item.key + ") empty name"); } item.desc = itemTbl.GetString("desc", item.name); opt.list.push_back(item); } if (opt.list.size() <= 0) { throw content_error("parseOption: (key=" + opt.key + ") subtables: empty list"); } opt.listDef = optTbl.GetString("def", opt.list[0].name); } else if (opt.type == "section") { opt.typeCode = opt_section; } else { throw content_error("parseOption: (key=" + opt.key + ") unknown type \"" + opt.type + "\""); } optionsSet.insert(opt.key); }
void CCustomExplosionGenerator::Load(CExplosionGeneratorHandler* h, const string& tag) { static std::map<string, CEGData> cachedCEGs; std::map<string, CEGData>::iterator it = cachedCEGs.find(tag); if (it == cachedCEGs.end()) { CEGData cegData; const LuaTable& root = h->GetTable(); const LuaTable expTable = root.SubTable(tag); if (!expTable.IsValid()) { throw content_error("Explosion info for " + tag + " not found."); } vector<string> spawns; expTable.GetKeys(spawns); for (vector<string>::iterator si = spawns.begin(); si != spawns.end(); ++si) { ProjectileSpawnInfo psi; const string& spawnName = *si; const LuaTable spawnTable = expTable.SubTable(spawnName); if (!spawnTable.IsValid() || spawnName == "groundflash") { continue; } const string className = spawnTable.GetString("class", spawnName); unsigned int flags = 0; if (spawnTable.GetBool("ground", false)) { flags |= SPW_GROUND; } if (spawnTable.GetBool("water", false)) { flags |= SPW_WATER; } if (spawnTable.GetBool("air", false)) { flags |= SPW_AIR; } if (spawnTable.GetBool("underwater", false)) { flags |= SPW_UNDERWATER; } if (spawnTable.GetBool("unit", false)) { flags |= SPW_UNIT; } if (spawnTable.GetBool("nounit", false)) { flags |= SPW_NO_UNIT; } psi.projectileClass = h->projectileClasses.GetClass(className); psi.flags = flags; psi.count = spawnTable.GetInt("count", 1); string code; map<string, string> props; map<string, string>::const_iterator propIt; spawnTable.SubTable("properties").GetMap(props); for (propIt = props.begin(); propIt != props.end(); ++propIt) { creg::Class::Member* m = psi.projectileClass->FindMember(propIt->first.c_str()); if (m && (m->flags & creg::CM_Config)) { ParseExplosionCode(&psi, m->offset, m->type, propIt->second, code); } } code += (char)OP_END; psi.code.resize(code.size()); copy(code.begin(), code.end(), psi.code.begin()); cegData.projectileSpawn.push_back(psi); } const LuaTable gndTable = expTable.SubTable("groundflash"); const int ttl = gndTable.GetInt("ttl", 0); if (ttl > 0) { cegData.groundFlash.circleAlpha = gndTable.GetFloat("circleAlpha", 0.0f); cegData.groundFlash.flashSize = gndTable.GetFloat("flashSize", 0.0f); cegData.groundFlash.flashAlpha = gndTable.GetFloat("flashAlpha", 0.0f); cegData.groundFlash.circleGrowth = gndTable.GetFloat("circleGrowth", 0.0f); cegData.groundFlash.color = gndTable.GetFloat3("color", float3(1.0f, 1.0f, 0.8f)); unsigned int flags = SPW_GROUND; if (gndTable.GetBool("ground", false)) { flags |= SPW_GROUND; } if (gndTable.GetBool("water", false)) { flags |= SPW_WATER; } if (gndTable.GetBool("air", false)) { flags |= SPW_AIR; } if (gndTable.GetBool("underwater", false)) { flags |= SPW_UNDERWATER; } if (gndTable.GetBool("unit", false)) { flags |= SPW_UNIT; } if (gndTable.GetBool("nounit", false)) { flags |= SPW_NO_UNIT; } cegData.groundFlash.flags = flags; cegData.groundFlash.ttl = ttl; } cegData.useDefaultExplosions = expTable.GetBool("useDefaultExplosions", false); cachedCEGs[tag] = cegData; currentCEG = &cachedCEGs[tag]; } else { currentCEG = &(it->second); } }
unsigned int CCustomExplosionGenerator::Load(CExplosionGeneratorHandler* h, const string& tag) { unsigned int explosionID = -1U; if (tag.empty()) { return explosionID; } const std::map<std::string, unsigned int>::const_iterator it = explosionIDs.find(tag); if (it == explosionIDs.end()) { CEGData cegData; const LuaTable* root = h->GetExplosionTableRoot(); const LuaTable& expTable = (root != NULL)? root->SubTable(tag): LuaTable(); if (!expTable.IsValid()) { // not a fatal error: any calls to ::Explosion will just return early logOutput.Print("[CCEG::Load] WARNING: table for CEG \"" + tag + "\" invalid (parse errors?)"); return explosionID; } vector<string> spawns; expTable.GetKeys(spawns); for (vector<string>::iterator si = spawns.begin(); si != spawns.end(); ++si) { ProjectileSpawnInfo psi; const string& spawnName = *si; const LuaTable spawnTable = expTable.SubTable(spawnName); if (!spawnTable.IsValid() || spawnName == "groundflash") { continue; } const string className = spawnTable.GetString("class", spawnName); psi.projectileClass = h->projectileClasses.GetClass(className); psi.flags = GetFlagsFromTable(spawnTable); psi.count = spawnTable.GetInt("count", 1); if (psi.projectileClass->binder->flags & creg::CF_Synced) { psi.flags |= SPW_SYNCED; } string code; map<string, string> props; map<string, string>::const_iterator propIt; spawnTable.SubTable("properties").GetMap(props); for (propIt = props.begin(); propIt != props.end(); ++propIt) { creg::Class::Member* m = psi.projectileClass->FindMember(propIt->first.c_str()); if (m && (m->flags & creg::CM_Config)) { ParseExplosionCode(&psi, m->offset, m->type, propIt->second, code); } } code += (char)OP_END; psi.code.resize(code.size()); copy(code.begin(), code.end(), psi.code.begin()); cegData.projectileSpawn.push_back(psi); } const LuaTable gndTable = expTable.SubTable("groundflash"); const int ttl = gndTable.GetInt("ttl", 0); if (ttl > 0) { cegData.groundFlash.circleAlpha = gndTable.GetFloat("circleAlpha", 0.0f); cegData.groundFlash.flashSize = gndTable.GetFloat("flashSize", 0.0f); cegData.groundFlash.flashAlpha = gndTable.GetFloat("flashAlpha", 0.0f); cegData.groundFlash.circleGrowth = gndTable.GetFloat("circleGrowth", 0.0f); cegData.groundFlash.color = gndTable.GetFloat3("color", float3(1.0f, 1.0f, 0.8f)); cegData.groundFlash.flags = SPW_GROUND | GetFlagsFromTable(gndTable); cegData.groundFlash.ttl = ttl; } cegData.useDefaultExplosions = expTable.GetBool("useDefaultExplosions", false); explosionID = explosionData.size(); explosionData.push_back(cegData); explosionIDs[tag] = explosionID; } else { explosionID = it->second; } return explosionID; }
void CCustomExplosionGenerator::Load(CExplosionGeneratorHandler* h, const string& tag) { typedef std::map<string, CEGData> CEGMap; typedef std::map<string, CEGData>::iterator CEGMapIt; CEGMapIt it = cachedCEGs.find(tag); if (it == cachedCEGs.end()) { CEGData cegData; const LuaTable& root = h->GetTable(); const LuaTable expTable = root.SubTable(tag); if (!expTable.IsValid()) { throw content_error("Explosion info for " + tag + " not found."); } vector<string> spawns; expTable.GetKeys(spawns); for (vector<string>::iterator si = spawns.begin(); si != spawns.end(); ++si) { ProjectileSpawnInfo psi; const string& spawnName = *si; const LuaTable spawnTable = expTable.SubTable(spawnName); if (!spawnTable.IsValid() || spawnName == "groundflash") { continue; } const string className = spawnTable.GetString("class", spawnName); psi.projectileClass = h->projectileClasses.GetClass(className); psi.flags = GetFlagsFromTable(spawnTable); psi.count = spawnTable.GetInt("count", 1); if (psi.projectileClass->binder->flags & creg::CF_Synced) { psi.flags |= SPW_SYNCED; } string code; map<string, string> props; map<string, string>::const_iterator propIt; spawnTable.SubTable("properties").GetMap(props); for (propIt = props.begin(); propIt != props.end(); ++propIt) { creg::Class::Member* m = psi.projectileClass->FindMember(propIt->first.c_str()); if (m && (m->flags & creg::CM_Config)) { ParseExplosionCode(&psi, m->offset, m->type, propIt->second, code); } } code += (char)OP_END; psi.code.resize(code.size()); copy(code.begin(), code.end(), psi.code.begin()); cegData.projectileSpawn.push_back(psi); } const LuaTable gndTable = expTable.SubTable("groundflash"); const int ttl = gndTable.GetInt("ttl", 0); if (ttl > 0) { cegData.groundFlash.circleAlpha = gndTable.GetFloat("circleAlpha", 0.0f); cegData.groundFlash.flashSize = gndTable.GetFloat("flashSize", 0.0f); cegData.groundFlash.flashAlpha = gndTable.GetFloat("flashAlpha", 0.0f); cegData.groundFlash.circleGrowth = gndTable.GetFloat("circleGrowth", 0.0f); cegData.groundFlash.color = gndTable.GetFloat3("color", float3(1.0f, 1.0f, 0.8f)); cegData.groundFlash.flags = SPW_GROUND | GetFlagsFromTable(gndTable); cegData.groundFlash.ttl = ttl; } cegData.useDefaultExplosions = expTable.GetBool("useDefaultExplosions", false); it = cachedCEGs.insert(std::make_pair(tag, cegData)).first; } currentCEG = it; }
bool CSound::LoadSoundDefsImpl(const std::string& fileName) { //! can be called from LuaUnsyncedCtrl too boost::recursive_mutex::scoped_lock lck(soundMutex); LuaParser parser(fileName, SPRING_VFS_MOD, SPRING_VFS_ZIP); parser.Execute(); if (!parser.IsValid()) { LOG_L(L_WARNING, "Could not load %s: %s", fileName.c_str(), parser.GetErrorLog().c_str()); return false; } else { const LuaTable soundRoot = parser.GetRoot(); const LuaTable soundItemTable = soundRoot.SubTable("SoundItems"); if (!soundItemTable.IsValid()) { LOG_L(L_WARNING, "CSound(): could not parse SoundItems table in %s", fileName.c_str()); return false; } else { std::vector<std::string> keys; soundItemTable.GetKeys(keys); for (std::vector<std::string>::const_iterator it = keys.begin(); it != keys.end(); ++it) { std::string name(*it); soundItemDef bufmap; const LuaTable buf(soundItemTable.SubTable(name)); buf.GetMap(bufmap); bufmap["name"] = name; soundItemDefMap::const_iterator sit = soundItemDefs.find(name); if (name == "default") { defaultItem = bufmap; defaultItem.erase("name"); //must be empty for default item defaultItem.erase("file"); continue; } if (sit != soundItemDefs.end()) LOG_L(L_WARNING, "Sound %s gets overwritten by %s", name.c_str(), fileName.c_str()); if (!buf.KeyExists("file")) { // no file, drop LOG_L(L_WARNING, "Sound %s is missing file tag (ignoring)", name.c_str()); continue; } else { soundItemDefs[name] = bufmap; } if (buf.KeyExists("preload")) { MakeItemFromDef(bufmap); } } LOG(" parsed %i sounds from %s", (int)keys.size(), fileName.c_str()); } } //FIXME why do sounds w/o an own soundItemDef create (!=pointer) a new one from the defaultItem? for (soundItemDefMap::iterator it = soundItemDefs.begin(); it != soundItemDefs.end(); ++it) { soundItemDef& snddef = it->second; if (snddef.find("name") == snddef.end()) { // uses defaultItem! update it! const std::string file = snddef["file"]; snddef = defaultItem; snddef["file"] = file; } } return true; }