bool CreatureDatabase::loadFromXML(const FileName& filename, bool standard, wxString& error, wxArrayString& warnings) { pugi::xml_document doc; pugi::xml_parse_result result = doc.load_file(filename.GetFullPath().mb_str()); if (!result) { error = wxT("Couldn't open file \"") + filename.GetFullName() + wxT("\", invalid format?"); return false; } pugi::xml_node node = doc.child("creatures"); if (!node) { error = wxT("Invalid file signature, this file is not a valid creatures file."); return false; } for (pugi::xml_node creatureNode = node.first_child(); creatureNode; creatureNode = creatureNode.next_sibling()) { if (as_lower_str(creatureNode.name()) != "creature") { continue; } CreatureType* creatureType = CreatureType::loadFromXML(creatureNode, warnings); if (creatureType) { creatureType->standard = standard; if ((*this)[creatureType->name]) { warnings.push_back(wxT("Duplicate creature type name \"") + wxstr(creatureType->name) + wxT("\"! Discarding...")); delete creatureType; } else { creature_map[as_lower_str(creatureType->name)] = creatureType; } } } return true; }
bool Materials::loadMaterials(const FileName& identifier, wxString& error, wxArrayString& warnings) { pugi::xml_document doc; pugi::xml_parse_result result = doc.load_file(identifier.GetFullPath().mb_str()); if(!result) { warnings.push_back("Could not open " + identifier.GetFullName() + " (file not found or syntax error)"); return false; } pugi::xml_node node = doc.child("materials"); if(!node) { warnings.push_back(identifier.GetFullName() + ": Invalid rootheader."); return false; } unserializeMaterials(identifier, node, error, warnings); return true; }
bool Materials::unserializeMaterials(const FileName& filename, pugi::xml_node node, wxString& error, wxArrayString& warnings) { wxString warning; pugi::xml_attribute attribute; for(pugi::xml_node childNode = node.first_child(); childNode; childNode = childNode.next_sibling()) { const std::string& childName = as_lower_str(childNode.name()); if(childName == "include") { if(!(attribute = childNode.attribute("file"))) { continue; } FileName includeName; includeName.SetPath(filename.GetPath()); includeName.SetFullName(wxString(attribute.as_string(), wxConvUTF8)); wxString subError; if(!loadMaterials(includeName, subError, warnings)) { warnings.push_back("Error while loading file \"" + includeName.GetFullName() + "\": " + subError); } } else if(childName == "metaitem") { g_items.loadMetaItem(childNode); } else if(childName == "border") { g_brushes.unserializeBorder(childNode, warnings); if(warning.size()) { warnings.push_back("materials.xml: " + warning); } } else if(childName == "brush") { g_brushes.unserializeBrush(childNode, warnings); if(warning.size()) { warnings.push_back("materials.xml: " + warning); } } else if(childName == "tileset") { unserializeTileset(childNode, warnings); } } return true; }
bool ItemDatabase::loadFromOtb(const FileName& datafile, wxString& error, wxArrayString& warnings) { std::string filename = nstr((datafile.GetPath(wxPATH_GET_VOLUME | wxPATH_GET_SEPARATOR) + datafile.GetFullName())); DiskNodeFileReadHandle f(filename, StringVector(1, "OTBI")); if(!f.isOk()) { error = wxT("Couldn't open file \"") + wxstr(filename) + wxT("\":") + wxstr(f.getErrorMessage()); return false; } BinaryNode* root = f.getRootNode(); #define safe_get(node, func, ...) do {\ if(!node->get##func(__VA_ARGS__)) {\ error = wxstr(f.getErrorMessage()); \ return false; \ } \ } while(false) // Read root flags root->skip(1); // Type info //uint32_t flags = root->skip(4); // Unused? uint8_t attr; safe_get(root, U8, attr); if(attr == ROOT_ATTR_VERSION) { uint16_t datalen; if(!root->getU16(datalen) || datalen != 4 + 4 + 4 + 1*128) { error = wxT("items.otb: Size of version header is invalid, updated .otb version?"); return false; } safe_get(root, U32, MajorVersion); // items otb format file version safe_get(root, U32, MinorVersion); // client version safe_get(root, U32, BuildNumber); // revision std::string csd; csd.resize(128); if(!root->getRAW((uint8_t*)csd.data(), 128)) { // CSDVersion ?? error = wxstr(f.getErrorMessage()); return false; } } else { error = wxT("Expected ROOT_ATTR_VERSION as first node of items.otb!"); } if(settings.getInteger(Config::CHECK_SIGNATURES)) { if(gui.GetCurrentVersion().getOTBVersion().format_version != MajorVersion) { error = wxT("Unsupported items.otb version (version ") + i2ws(MajorVersion) + wxT(")"); return false; } } BinaryNode* itemNode = root->getChild(); switch(MajorVersion) { case 1: return loadFromOtbVer1(itemNode, error, warnings); case 2: return loadFromOtbVer2(itemNode, error, warnings); case 3: return loadFromOtbVer3(itemNode, error, warnings); } return true; }
bool CreatureDatabase::importXMLFromOT(const FileName& filename, wxString& error, wxArrayString& warnings) { pugi::xml_document doc; pugi::xml_parse_result result = doc.load_file(filename.GetFullPath().mb_str()); if (!result) { error = wxT("Couldn't open file \"") + filename.GetFullName() + wxT("\", invalid format?"); return false; } pugi::xml_node node; if ((node = doc.child("monsters"))) { for (pugi::xml_node monsterNode = node.first_child(); monsterNode; monsterNode = monsterNode.next_sibling()) { if (as_lower_str(monsterNode.name()) != "monster") { continue; } pugi::xml_attribute attribute; if (!(attribute = monsterNode.attribute("file"))) { continue; } FileName monsterFile(filename); monsterFile.SetFullName(wxString(attribute.as_string(), wxConvUTF8)); pugi::xml_document monsterDoc; pugi::xml_parse_result monsterResult = monsterDoc.load_file(monsterFile.GetFullPath().mb_str()); if (!monsterResult) { continue; } CreatureType* creatureType = CreatureType::loadFromOTXML(monsterFile, monsterDoc, warnings); if (creatureType) { CreatureType* current = (*this)[creatureType->name]; if (current) { *current = *creatureType; delete creatureType; } else { creature_map[as_lower_str(creatureType->name)] = creatureType; Tileset* tileSet = nullptr; if (creatureType->isNpc) { tileSet = materials.tilesets["NPCs"]; } else { tileSet = materials.tilesets["Others"]; } ASSERT(tileSet != nullptr); Brush* brush = newd CreatureBrush(creatureType); brushes.addBrush(brush); TilesetCategory* tileSetCategory = tileSet->getCategory(TILESET_CREATURE); tileSetCategory->brushlist.push_back(brush); } } } } else if ((node = doc.child("monster")) || (node = doc.child("npc"))) { CreatureType* creatureType = CreatureType::loadFromOTXML(filename, doc, warnings); if (creatureType) { CreatureType* current = (*this)[creatureType->name]; if (current) { *current = *creatureType; delete creatureType; } else { creature_map[as_lower_str(creatureType->name)] = creatureType; Tileset* tileSet = nullptr; if (creatureType->isNpc) { tileSet = materials.tilesets["NPCs"]; } else { tileSet = materials.tilesets["Others"]; } ASSERT(tileSet != nullptr); Brush* brush = newd CreatureBrush(creatureType); brushes.addBrush(brush); TilesetCategory* tileSetCategory = tileSet->getCategory(TILESET_CREATURE); tileSetCategory->brushlist.push_back(brush); } } } else { error = wxT("This is not valid OT npc/monster data file."); return false; } return true; }