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."; }