void CArtHandler::loadObject(std::string scope, std::string name, const JsonNode & data, size_t index) { auto object = loadFromJson(data, normalizeIdentifier(scope, "core", name)); object->id = ArtifactID(index); object->iconIndex = object->id; assert(artifacts[index] == nullptr); // ensure that this id was not loaded before artifacts[index] = object; VLC->modh->identifiers.requestIdentifier(scope, "object", "artifact", [=](si32 index) { JsonNode conf; conf.setMeta(scope); VLC->objtypeh->loadSubObject(object->identifier, conf, Obj::ARTIFACT, object->id.num); if (!object->advMapDef.empty()) { JsonNode templ; templ.setMeta(scope); templ["animation"].String() = object->advMapDef; // add new template. // Necessary for objects added via mods that don't have any templates in H3 VLC->objtypeh->getHandlerFor(Obj::ARTIFACT, object->id)->addTemplate(templ); } // object does not have any templates - this is not usable object (e.g. pseudo-art like lock) if (VLC->objtypeh->getHandlerFor(Obj::ARTIFACT, object->id)->getTemplates().empty()) VLC->objtypeh->removeSubObject(Obj::ARTIFACT, object->id); }); registerObject(scope, "artifact", name, object->id); }
static JsonNode loadPatches(std::string path) { JsonNode node = JsonUtils::assembleFromFiles(path); for (auto & entry : node.Struct()) JsonUtils::validate(entry.second, "vcmi:mapHeader", "patch for " + entry.first); return node; }
static ui32 loadJsonOrMax(const JsonNode & input) { if (input.isNull()) return std::numeric_limits<ui32>::max(); else return input.Float(); }
JsonNode JsonReader::ParseArray() { JsonNode object = JsonNode(JsonNode::Type::Array); bool end = false; /* Verify we're parsing an array */ if (*m_data == '[') m_data++; while (!end) { /* Use the index value as the key name */ object[object.ChildCount()] = this->ParseValue(); while (*m_data != ',' && *m_data != ']' && !EndOfFile()) m_data++; switch (*m_data) { case ',': m_data++; break; case ']': end = true; m_data++; break; default: PrintError("Syntax Error : ',' , ']' were expected. "); end = true; break; }; } return object; }
void CContentHandler::ContentTypeHandler::preloadModData(std::string modName, std::vector<std::string> fileList) { JsonNode data = JsonUtils::assembleFromFiles(fileList); data.setMeta(modName); ModInfo & modInfo = modData[modName]; for(auto entry : data.Struct()) { size_t colon = entry.first.find(':'); if (colon == std::string::npos) { // normal object, local to this mod modInfo.modData[entry.first].swap(entry.second); } else { std::string remoteName = entry.first.substr(0, colon); std::string objectName = entry.first.substr(colon + 1); // patching this mod? Send warning and continue - this situation can be handled normally if (remoteName == modName) logGlobal->warnStream() << "Redundant namespace definition for " << objectName; JsonNode & remoteConf = modData[remoteName].patches[objectName]; JsonUtils::merge(remoteConf, entry.second); } } }
bool JsonParser::extractArray(JsonNode &node) { pos++; node.setType(JsonNode::DATA_VECTOR); if (!extractWhitespace()) return false; //Empty array found if (input[pos] == ']') { pos++; return true; } while (true) { //NOTE: currently 50% of time is this vector resizing. //May be useful to use list during parsing and then swap() all items to vector node.Vector().resize(node.Vector().size()+1); if (!extractElement(node.Vector().back(), ']')) return false; if (input[pos] == ']') { pos++; return true; } } }
void CSettingsView::loadSettings() { int resX = settings["video"]["screenRes"]["width"].Float(); int resY = settings["video"]["screenRes"]["height"].Float(); int resIndex = ui->comboBoxResolution->findText(QString("%1x%2").arg(resX).arg(resY)); ui->comboBoxResolution->setCurrentIndex(resIndex); ui->comboBoxFullScreen->setCurrentIndex(settings["video"]["fullscreen"].Bool()); int neutralAIIndex = ui->comboBoxNeutralAI->findText(QString::fromUtf8(settings["server"]["neutralAI"].String().c_str())); int playerAIIndex = ui->comboBoxPlayerAI->findText(QString::fromUtf8(settings["server"]["playerAI"].String().c_str())); ui->comboBoxNeutralAI->setCurrentIndex(neutralAIIndex); ui->comboBoxPlayerAI->setCurrentIndex(playerAIIndex); ui->spinBoxNetworkPort->setValue(settings["server"]["port"].Float()); ui->comboBoxEnableMods->setCurrentIndex(settings["launcher"]["enableInstalledMods"].Bool()); // all calls to plainText will trigger textChanged() signal overwriting config. Create backup before editing widget JsonNode urls = settings["launcher"]["repositoryURL"]; ui->plainTextEditRepos->clear(); for (auto entry : urls.Vector()) ui->plainTextEditRepos->appendPlainText(QString::fromUtf8(entry.String().c_str())); ui->lineEditUserDataDir->setText(QString::fromUtf8(VCMIDirs::get().userDataPath().c_str())); QStringList dataDirs; for (auto string : VCMIDirs::get().dataPaths()) dataDirs += QString::fromUtf8(string.c_str()); ui->lineEditGameDir->setText(dataDirs.join(':')); }
bool JsonParser::extractString(JsonNode &node) { std::string str; if (!extractString(str)) return false; node.setType(JsonNode::DATA_STRING); node.String() = str; return true; }
std::unique_ptr<IMapPatcher> CMapService::getMapPatcher(std::string scenarioName) { static JsonNode node; if (node.isNull()) node = loadPatches("config/mapOverrides.json"); boost::to_lower(scenarioName); logGlobal->debugStream() << "Request to patch map " << scenarioName; return std::unique_ptr<IMapPatcher>(new CMapPatcher(node[scenarioName])); }
boost::optional<si32> CIdentifierStorage::getIdentifier(std::string type, const JsonNode & name, bool silent) { auto pair = splitString(name.String(), ':'); // remoteScope:name auto idList = getPossibleIdentifiers(ObjectCallback(name.meta, pair.first, type, pair.second, std::function<void(si32)>(), silent)); if (idList.size() == 1) return idList.front().id; if (!silent) logGlobal->errorStream() << "Failed to resolve identifier " << name.String() << " of type " << type << " from mod " << name.meta; return boost::optional<si32>(); }
si32 selectNextID(const JsonNode & fixedID, const Map & map, si32 defaultID) { if (!fixedID.isNull() && fixedID.Float() < defaultID) return fixedID.Float(); // H3M object with fixed ID if (map.empty()) return defaultID; // no objects loaded, keep gap for H3M objects if (map.rbegin()->first >= defaultID) return map.rbegin()->first + 1; // some modded objects loaded, return next available return defaultID; // some H3M objects loaded, first modded found }
void CModHandler::handleData(Handler handler, const JsonNode & source, std::string listName, std::string schemaName) { JsonNode config = JsonUtils::assembleFromFiles(source[listName].convertTo<std::vector<std::string> >()); for(auto & entry : config.Struct()) { if (!entry.second.isNull()) // may happens if mod removed object by setting json entry to null { JsonUtils::validate(entry.second, schemaName, entry.first); handler->load(entry.first, entry.second); } } }
void JsonWriter::writeNode(const JsonNode &node) { switch(node.getType()) { break; case JsonNode::DATA_NULL: out << "null"; break; case JsonNode::DATA_BOOL: if (node.Bool()) out << "true"; else out << "false"; break; case JsonNode::DATA_FLOAT: out << node.Float(); break; case JsonNode::DATA_STRING: writeString(node.String()); break; case JsonNode::DATA_VECTOR: out << "[" << "\n"; writeContainer(node.Vector().begin(), node.Vector().end()); out << prefix << "]"; break; case JsonNode::DATA_STRUCT: out << "{" << "\n"; writeContainer(node.Struct().begin(), node.Struct().end()); out << prefix << "}"; } }
void SettingsStorage::invalidateNode(const std::vector<std::string> &changedPath) { for(SettingsListener * listener : listeners) listener->nodeInvalidated(changedPath); JsonNode savedConf = config; JsonNode schema(ResourceID("config/schemas/settings.json")); savedConf.Struct().erase("session"); JsonUtils::minimize(savedConf, "vcmi:settings"); std::ofstream file(*CResourceHandler::get()->getResourceName(ResourceID("config/settings.json")), std::ofstream::trunc); file << savedConf; }
std::string check(const JsonNode & schema, const JsonNode & data, ValidationData & validator) { const TValidatorMap & knownFields = getKnownFieldsFor(data.getType()); std::string errors; for(auto & entry : schema.Struct()) { auto checker = knownFields.find(entry.first); if (checker != knownFields.end()) errors += checker->second(validator, schema, entry.second, data); //else // errors += validator.makeErrorMessage("Unknown entry in schema " + entry.first); } return errors; }
CMappedFileLoader::CMappedFileLoader(const std::string & mountPoint, const JsonNode &config) { for(auto entry : config.Struct()) { fileList[ResourceID(mountPoint + entry.first)] = ResourceID(mountPoint + entry.second.String()); } }
void CIdentifierStorage::requestIdentifier(const JsonNode & name, const std::function<void(si32)> & callback) { auto pair = splitString(name.String(), ':'); // remoteScope:<type.name> auto pair2 = splitString(pair.second, '.'); // type.name requestIdentifier(ObjectCallback(name.meta, pair.first, pair2.first, pair2.second, callback)); }
void CBonusTypeHandler::load(const JsonNode& config) { for(auto & node : config.Struct()) { auto it = bonusNameMap.find(node.first); if(it == bonusNameMap.end()) { //TODO: new bonus // CBonusType bt; // loadItem(node.second, bt); // // auto new_id = bonusTypes.size(); // // bonusTypes.push_back(bt); logBonus->warnStream() << "Adding new bonuses not implemented (" << node.first << ")"; } else { CBonusType& bt = bonusTypes[it->second]; loadItem(node.second, bt); logBonus->traceStream() << "Loaded bonus type " << node.first; } } }
void CTownHandler::loadBuildings(CTown &town, const JsonNode & source) { BOOST_FOREACH(const JsonNode &node, source.Vector()) { loadBuilding(town, node); } }
void CTownHandler::loadStructures(CTown &town, const JsonNode & source) { BOOST_FOREACH(const JsonNode &node, source.Vector()) { loadStructure(town, node); } }
static void readIcon(JsonNode source, std::string & small, std::string & large) { if (source.getType() == JsonNode::DATA_STRUCT) // don't crash on old format { small = source["small"].String(); large = source["large"].String(); } }
bool JsonParser::extractNull(JsonNode &node) { if (!extractLiteral("null")) return false; node.clear(); return true; }
bool JsonParser::extractFalse(JsonNode &node) { if (!extractLiteral("false")) return false; node.Bool() = false; return true; }
void CObjectClassesHandler::loadSubObject(std::string name, JsonNode config, si32 ID, boost::optional<si32> subID) { config.setType(JsonNode::DATA_STRUCT); // ensure that input is not NULL assert(objects.count(ID)); if (subID) { assert(objects.at(ID)->objects.count(subID.get()) == 0); assert(config["index"].isNull()); config["index"].Float() = subID.get(); } std::string oldMeta = config.meta; // FIXME: move into inheritNode? JsonUtils::inherit(config, objects.at(ID)->base); config.setMeta(oldMeta); loadObjectEntry(config, objects[ID]); }
void CHeroClassHandler::loadObject(std::string scope, std::string name, const JsonNode & data) { auto object = loadFromJson(data, normalizeIdentifier(scope, "core", name)); object->id = heroClasses.size(); heroClasses.push_back(object); VLC->modh->identifiers.requestIdentifier(scope, "object", "hero", [=](si32 index) { JsonNode classConf = data["mapObject"]; classConf["heroClass"].String() = name; classConf.setMeta(scope); VLC->objtypeh->loadSubObject(name, classConf, index, object->id); }); VLC->modh->identifiers.registerObject(scope, "heroClass", name, object->id); }
bool JsonParser::extractFloat(JsonNode &node) { assert(input[pos] == '-' || (input[pos] >= '0' && input[pos] <= '9')); bool negative=false; double result=0; if (input[pos] == '-') { pos++; negative = true; } if (input[pos] < '0' || input[pos] > '9') return error("Number expected!"); //Extract integer part while (input[pos] >= '0' && input[pos] <= '9') { result = result*10+(input[pos]-'0'); pos++; } if (input[pos] == '.') { //extract fractional part pos++; double fractMult = 0.1; if (input[pos] < '0' || input[pos] > '9') return error("Decimal part expected!"); while (input[pos] >= '0' && input[pos] <= '9') { result = result + fractMult*(input[pos]-'0'); fractMult /= 10; pos++; } } //TODO: exponential part if (negative) result = -result; node.setType(JsonNode::DATA_FLOAT); node.Float() = result; return true; }
void CSettingsView::on_plainTextEditRepos_textChanged() { Settings node = settings.write["launcher"]["repositoryURL"]; QStringList list = ui->plainTextEditRepos->toPlainText().split('\n'); node->Vector().clear(); for (QString line : list) { if (line.trimmed().size() > 0) { JsonNode entry; entry.String() = line.trimmed().toUtf8().data(); node->Vector().push_back(entry); } } }
bool JsonParse::AddValue(JsonValue *obj) { bool ret = false; JsonNode *current; JsonType type; current = m_ctx.Current(); if (current) { type = static_cast<JsonValue *>(current)->GetType(); } if (current && type != JsonType_Object && type != JsonType_Tuple) { current->AddChild(obj); ret = true; } return ret; }
void CHeroClassHandler::loadObject(std::string scope, std::string name, const JsonNode & data, size_t index) { auto object = loadFromJson(data, normalizeIdentifier(scope, "core", name)); object->id = index; assert(heroClasses[index] == nullptr); // ensure that this id was not loaded before heroClasses[index] = object; VLC->modh->identifiers.requestIdentifier(scope, "object", "hero", [=](si32 index) { JsonNode classConf = data["mapObject"]; classConf["heroClass"].String() = name; classConf.setMeta(scope); VLC->objtypeh->loadSubObject(name, classConf, index, object->id); }); VLC->modh->identifiers.registerObject(scope, "heroClass", name, object->id); }
void CTownHandler::loadStructures(CTown &town, const JsonNode & source) { if (source.getType() == JsonNode::DATA_VECTOR) { for(auto &node : source.Vector()) { if (!node.isNull()) loadStructure(town, node); } } else { for(auto &node : source.Struct()) { if (!node.second.isNull()) loadStructure(town, node.second); } } }