uintmax_t Plugin::GetFileSize(const std::string & filename, const Game & game) { boost::filesystem::path realPath = game.DataPath() / filename; if (!boost::filesystem::exists(realPath)) realPath += ".ghost"; return boost::filesystem::file_size(realPath); }
bool Plugin::IsValid(const std::string& filename, const Game& game) { BOOST_LOG_TRIVIAL(trace) << "Checking to see if \"" << filename << "\" is a valid plugin."; //If the filename passed ends in '.ghost', that should be trimmed. std::string name; if (boost::iends_with(filename, ".ghost")) name = filename.substr(0, filename.length() - 6); else name = filename; // Check that the file has a valid extension. if (!boost::iends_with(name, ".esm") && !boost::iends_with(name, ".esp")) return false; // Add the ".ghost" file extension if the plugin is ghosted. boost::filesystem::path filepath = game.DataPath() / name; if (!boost::filesystem::exists(filepath) && boost::filesystem::exists(filepath.string() + ".ghost")) filepath += ".ghost"; if (libespm::Plugin::isValid(filepath, game.LibespmId(), true)) return true; BOOST_LOG_TRIVIAL(warning) << "The .es(p|m) file \"" << filename << "\" is not a valid plugin."; return false; }
void Plugin::CheckInstallValidity(const Game& game) { BOOST_LOG_TRIVIAL(trace) << "Checking that the current install is valid according to " << Name() << "'s data."; if (IsActive()) { auto pluginExists = [](const Game& game, const std::string& file) { return boost::filesystem::exists(game.DataPath() / file) || ((boost::iends_with(file, ".esp") || boost::iends_with(file, ".esm")) && boost::filesystem::exists(game.DataPath() / (file + ".ghost"))); }; if (tags_.find(Tag("Filter")) == tags_.end()) { for (const auto &master : getMasters()) { if (!pluginExists(game, master)) { BOOST_LOG_TRIVIAL(error) << "\"" << Name() << "\" requires \"" << master << "\", but it is missing."; messages_.push_back(Message(MessageType::error, (boost::format(boost::locale::translate("This plugin requires \"%1%\" to be installed, but it is missing.")) % master).str())); } else if (!game.IsPluginActive(master)) { BOOST_LOG_TRIVIAL(error) << "\"" << Name() << "\" requires \"" << master << "\", but it is inactive."; messages_.push_back(Message(MessageType::error, (boost::format(boost::locale::translate("This plugin requires \"%1%\" to be active, but it is inactive.")) % master).str())); } } } for (const auto &req : Reqs()) { if (!pluginExists(game, req.Name())) { BOOST_LOG_TRIVIAL(error) << "\"" << Name() << "\" requires \"" << req.Name() << "\", but it is missing."; messages_.push_back(Message(MessageType::error, (boost::format(boost::locale::translate("This plugin requires \"%1%\" to be installed, but it is missing.")) % req.Name()).str())); } } for (const auto &inc : Incs()) { if (pluginExists(game, inc.Name()) && game.IsPluginActive(inc.Name())) { BOOST_LOG_TRIVIAL(error) << "\"" << Name() << "\" is incompatible with \"" << inc.Name() << "\", but both are present."; messages_.push_back(Message(MessageType::error, (boost::format(boost::locale::translate("This plugin is incompatible with \"%1%\", but both are present.")) % inc.Name()).str())); } } } // Also generate dirty messages. for (const auto &element : DirtyInfo()) { messages_.push_back(element.AsMessage()); } }
Plugin::Plugin(const Game& game, const std::string& name, const bool headerOnly) : PluginMetadata(name), libespm::Plugin(game.LibespmId()), isEmpty_(true), isActive_(false), loadsArchive_(false), crc_(0), numOverrideRecords_(0) { try { boost::filesystem::path filepath = game.DataPath() / Name(); // In case the plugin is ghosted. if (!boost::filesystem::exists(filepath) && boost::filesystem::exists(filepath.string() + ".ghost")) filepath += ".ghost"; load(filepath, headerOnly); isEmpty_ = getRecordAndGroupCount() == 0; if (!headerOnly) { BOOST_LOG_TRIVIAL(trace) << Name() << ": Caching CRC value."; crc_ = GetCrc32(filepath); } BOOST_LOG_TRIVIAL(trace) << Name() << ": Counting override FormIDs."; for (const auto& formID : getFormIds()) { if (!boost::iequals(formID.getPluginName(), Name())) ++numOverrideRecords_; } //Also read Bash Tags applied and version string in description. string text = getDescription(); BOOST_LOG_TRIVIAL(trace) << Name() << ": " << "Attempting to extract Bash Tags from the description."; size_t pos1 = text.find("{{BASH:"); if (pos1 != string::npos && pos1 + 7 != text.length()) { pos1 += 7; size_t pos2 = text.find("}}", pos1); if (pos2 != string::npos && pos1 != pos2) { text = text.substr(pos1, pos2 - pos1); std::vector<string> bashTags; boost::split(bashTags, text, [](char c) { return c == ','; }); for (auto &tag : bashTags) { boost::trim(tag); BOOST_LOG_TRIVIAL(trace) << Name() << ": " << "Extracted Bash Tag: " << tag; tags_.insert(Tag(tag)); } } } // Get whether the plugin is active or not. isActive_ = game.LoadOrderHandler::IsPluginActive(Name()); // Get whether the plugin loads an archive (BSA/BA2) or not. const string archiveExtension = game.GetArchiveFileExtension(); if (game.Type() == GameType::tes5) { // Skyrim plugins only load BSAs that exactly match their basename. loadsArchive_ = boost::filesystem::exists(game.DataPath() / (Name().substr(0, Name().length() - 4) + archiveExtension)); } else if (game.Type() != GameType::tes4 || boost::iends_with(Name(), ".esp")) { //Oblivion .esp files and FO3, FNV, FO4 plugins can load archives which begin with the plugin basename. string basename = Name().substr(0, Name().length() - 4); for (boost::filesystem::directory_iterator it(game.DataPath()); it != boost::filesystem::directory_iterator(); ++it) { if (boost::iequals(it->path().extension().string(), archiveExtension) && boost::istarts_with(it->path().filename().string(), basename)) { loadsArchive_ = true; break; } } } } catch (std::exception& e) { BOOST_LOG_TRIVIAL(error) << "Cannot read plugin file \"" << name << "\". Details: " << e.what(); messages_.push_back(Message(MessageType::error, (boost::format(boost::locale::translate("Cannot read \"%1%\". Details: %2%")) % name % e.what()).str())); } BOOST_LOG_TRIVIAL(trace) << Name() << ": " << "Plugin loading complete."; }