void GUI::UnloadVersion() { UnnamedRenderingLock(); gfx.clear(); current_brush = nullptr; previous_brush = nullptr; house_brush = nullptr; house_exit_brush = nullptr; waypoint_brush = nullptr; optional_brush = nullptr; eraser = nullptr; normal_door_brush = nullptr; locked_door_brush = nullptr; magic_door_brush = nullptr; quest_door_brush = nullptr; hatch_door_brush = nullptr; window_door_brush = nullptr; if(loaded_version != CLIENT_VERSION_NONE) { //g_gui.UnloadVersion(); materials.clear(); brushes.clear(); item_db.clear(); gfx.clear(); FileName cdb = getLoadedVersion()->getLocalDataPath(); cdb.SetFullName(wxT("creatures.xml")); creature_db.saveToXML(cdb); creature_db.clear(); loaded_version = CLIENT_VERSION_NONE; } }
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 Materials::loadExtensions(FileName directoryName, wxString& error, wxArrayString& warnings) { directoryName.Mkdir(0755, wxPATH_MKDIR_FULL); // Create if it doesn't exist wxDir ext_dir(directoryName.GetPath()); if(!ext_dir.IsOpened()) { error = "Could not open extensions directory."; return false; } wxString filename; if(!ext_dir.GetFirst(&filename)) { // No extensions found return true; } StringVector clientVersions; do { FileName fn; fn.SetPath(directoryName.GetPath()); fn.SetFullName(filename); if(fn.GetExt() != "xml") { continue; } pugi::xml_document doc; pugi::xml_parse_result result = doc.load_file(fn.GetFullPath().mb_str()); if(!result) { warnings.push_back("Could not open " + filename + " (file not found or syntax error)"); continue; } pugi::xml_node extensionNode = doc.child("materialsextension"); if(!extensionNode) { warnings.push_back(filename + ": Invalid rootheader."); continue; } pugi::xml_attribute attribute; if(!(attribute = extensionNode.attribute("name"))) { warnings.push_back(filename + ": Couldn't read extension name."); continue; } const std::string& extensionName = attribute.as_string(); if(!(attribute = extensionNode.attribute("author"))) { warnings.push_back(filename + ": Couldn't read extension name."); continue; } const std::string& extensionAuthor = attribute.as_string(); if(!(attribute = extensionNode.attribute("description"))) { warnings.push_back(filename + ": Couldn't read extension name."); continue; } const std::string& extensionDescription = attribute.as_string(); if(extensionName.empty() || extensionAuthor.empty() || extensionDescription.empty()) { warnings.push_back(filename + ": Couldn't read extension attributes (name, author, description)."); continue; } std::string extensionUrl = extensionNode.attribute("url").as_string(); extensionUrl.erase(std::remove(extensionUrl.begin(), extensionUrl.end(), '\'')); std::string extensionAuthorLink = extensionNode.attribute("authorurl").as_string(); extensionAuthorLink.erase(std::remove(extensionAuthorLink.begin(), extensionAuthorLink.end(), '\'')); MaterialsExtension* materialExtension = newd MaterialsExtension(extensionName, extensionAuthor, extensionDescription); materialExtension->url = extensionUrl; materialExtension->author_url = extensionAuthorLink; if((attribute = extensionNode.attribute("client"))) { clientVersions.clear(); const std::string& extensionClientString = attribute.as_string(); size_t lastPosition = 0; size_t position = extensionClientString.find(';'); while(position != std::string::npos) { clientVersions.push_back(extensionClientString.substr(lastPosition, position - lastPosition)); lastPosition = position + 1; position = extensionClientString.find(';', lastPosition); } clientVersions.push_back(extensionClientString.substr(lastPosition)); for(const std::string& version : clientVersions) { materialExtension->addVersion(version); } std::sort(materialExtension->version_list.begin(), materialExtension->version_list.end(), VersionComparisonPredicate); auto duplicate = std::unique(materialExtension->version_list.begin(), materialExtension->version_list.end()); while(duplicate != materialExtension->version_list.end()) { materialExtension->version_list.erase(duplicate); duplicate = std::unique(materialExtension->version_list.begin(), materialExtension->version_list.end()); } } else { warnings.push_back(filename + ": Extension is not available for any version."); } extensions.push_back(materialExtension); if(materialExtension->isForVersion(g_gui.GetCurrentVersionID())) { unserializeMaterials(filename, extensionNode, error, warnings); } } while(ext_dir.GetNext(&filename)); return true; }
bool GUI::LoadDataFiles(wxString& error, wxArrayString& warnings) { FileName data_path = getLoadedVersion()->getDataPath(); FileName client_path = getLoadedVersion()->getClientPath(); FileName extension_path = GetExtensionsDirectory(); FileName exec_directory; try { exec_directory = dynamic_cast<wxStandardPaths&>(wxStandardPaths::Get()).GetExecutablePath(); } catch(std::bad_cast) { error = wxT("Couldn't establish working directory..."); return false; } g_gui.gfx.client_version = getLoadedVersion(); FileName otfi_path = wxString(client_path.GetPath(wxPATH_GET_VOLUME | wxPATH_GET_SEPARATOR) + wxT("Tibia.otfi")); if(!g_gui.gfx.loadOTFI(otfi_path, error, warnings)) { error = wxT("Couldn't load tibia.otfi: ") + error; g_gui.DestroyLoadBar(); UnloadVersion(); return false; } g_gui.CreateLoadBar(wxT("Loading data files")); g_gui.SetLoadDone(0, wxT("Loading Tibia.dat ...")); FileName dat_path = wxString(client_path.GetPath(wxPATH_GET_VOLUME | wxPATH_GET_SEPARATOR) + wxT("Tibia.dat")); if(!g_gui.gfx.loadSpriteMetadata(dat_path, error, warnings)) { error = wxT("Couldn't load tibia.dat: ") + error; g_gui.DestroyLoadBar(); UnloadVersion(); return false; } FileName spr_path = wxString(client_path.GetPath(wxPATH_GET_VOLUME | wxPATH_GET_SEPARATOR) + wxT("Tibia.spr")); g_gui.SetLoadDone(10, wxT("Loading Tibia.spr ...")); if(!g_gui.gfx.loadSpriteData(spr_path.GetFullPath(), error, warnings)) { error = wxT("Couldn't load tibia.spr: ") + error; g_gui.DestroyLoadBar(); UnloadVersion(); return false; } g_gui.SetLoadDone(20, wxT("Loading items.otb ...")); if(!item_db.loadFromOtb(wxString(data_path.GetPath(wxPATH_GET_VOLUME | wxPATH_GET_SEPARATOR) + wxT("items.otb")), error, warnings)) { error = wxT("Couldn't load items.otb: ") + error; g_gui.DestroyLoadBar(); UnloadVersion(); return false; } g_gui.SetLoadDone(30, wxT("Loading items.xml ...")); if(!item_db.loadFromGameXml(wxString(data_path.GetPath(wxPATH_GET_VOLUME | wxPATH_GET_SEPARATOR) + wxT("items.xml")), error, warnings)) { warnings.push_back(wxT("Couldn't load items.xml: ") + error); } g_gui.SetLoadDone(45, wxT("Loading creatures.xml ...")); if(!creature_db.loadFromXML(wxString(data_path.GetPath(wxPATH_GET_VOLUME | wxPATH_GET_SEPARATOR) + wxT("creatures.xml")), true, error, warnings)) { warnings.push_back(wxT("Couldn't load creatures.xml: ") + error); } g_gui.SetLoadDone(45, wxT("Loading user creatures.xml ...")); { FileName cdb = getLoadedVersion()->getLocalDataPath(); cdb.SetFullName(wxT("creatures.xml")); wxString nerr; wxArrayString nwarn; creature_db.loadFromXML(cdb, false, nerr, nwarn); } g_gui.SetLoadDone(50, wxT("Loading materials.xml ...")); if(!materials.loadMaterials(wxString(data_path.GetPath(wxPATH_GET_VOLUME | wxPATH_GET_SEPARATOR) + wxT("materials.xml")), error, warnings)) { warnings.push_back(wxT("Couldn't load materials.xml: ") + error); } g_gui.SetLoadDone(70, wxT("Loading extensions...")); if(!materials.loadExtensions(extension_path, error, warnings)) { //warnings.push_back(wxT("Couldn't load extensions: ") + error); } g_gui.SetLoadDone(70, wxT("Finishing...")); brushes.init(); materials.createOtherTileset(); g_gui.DestroyLoadBar(); return true; }
bool Materials::loadExtensions(FileName directoryName, wxString& error, wxArrayString& warnings) { directoryName.Mkdir(0755, wxPATH_MKDIR_FULL); // Create if it doesn't exist wxDir ext_dir(directoryName.GetPath()); if(ext_dir.IsOpened() == false) { error = wxT("Could not open extensions directory."); return false; } wxString filename; if(!ext_dir.GetFirst(&filename)) { // No extensions found return true; } do { FileName fn; fn.SetPath(directoryName.GetPath()); fn.SetFullName(filename); if(fn.GetExt() != wxT("xml")) continue; xmlDocPtr doc = xmlParseFile(fn.GetFullPath().mb_str()); if(doc) { xmlNodePtr root = xmlDocGetRootElement(doc); if(xmlStrcmp(root->name,(const xmlChar*)"materialsextension") != 0){ xmlFreeDoc(doc); warnings.push_back(filename + wxT(": Invalid rootheader.")); continue; } std::string ext_name, ext_url, ext_author, ext_author_link, ext_desc, ext_client_str; StringVector clientVersions; if( !readXMLValue(root, "name", ext_name) || !readXMLValue(root, "author", ext_author) || !readXMLValue(root, "description", ext_desc)) { warnings.push_back(filename + wxT(": Couldn't read extension attributes (name, author, description).")); continue; } readXMLValue(root, "url", ext_url); ext_url.erase(std::remove(ext_url.begin(), ext_url.end(), '\''), ext_url.end()); readXMLValue(root, "authorurl", ext_author_link); ext_author_link.erase(std::remove(ext_author_link.begin(), ext_author_link.end(), '\''), ext_author_link.end()); MaterialsExtension* me = newd MaterialsExtension(ext_name, ext_author, ext_desc); me->url = ext_url; me->author_url = ext_author_link; if(readXMLValue(root, "client", ext_client_str)) { size_t last_pos = std::numeric_limits<size_t>::max(); size_t pos; do { size_t to_pos = (last_pos == std::numeric_limits<size_t>::max()? 0 : last_pos+1); pos = ext_client_str.find(';', to_pos); if(size_t(pos) != std::string::npos) { clientVersions.push_back(ext_client_str.substr(to_pos, pos-(to_pos))); last_pos = pos; } else { clientVersions.push_back(ext_client_str.substr(to_pos)); break; } } while(true); for(StringVector::iterator iter = clientVersions.begin(); iter != clientVersions.end(); ++iter) { me->addVersion(*iter); } std::sort(me->version_list.begin(), me->version_list.end(), VersionComparisonPredicate); me->version_list.erase(std::unique(me->version_list.begin(), me->version_list.end()), me->version_list.end()); } else { warnings.push_back(filename + wxT(": Extension is not available for any version.")); } extensions.push_back(me); if(me->isForVersion(gui.GetCurrentVersionID())) { unserializeMaterials(filename, root, error, warnings); } } else { warnings.push_back(wxT("Could not open ") + filename + wxT(" (file not found or syntax error)")); continue; } } while(ext_dir.GetNext(&filename)); return true; }