mirror of
https://github.com/loot/libloot.git
synced 2026-07-27 14:16:01 -07:00
Improved metadata change handling.
* The clear metadata functions now rederive the derived metadata, and send the new derivations to the JS side. * The JS side now observes changes to the derived metadata and updates the UI where necessary to reflect changes. * Dirty message generation has been refactored into Plugin::CheckInstallValidity, which now returns true if the plugin is dirty. The editor panel is still not yet updated though.
This commit is contained in:
@@ -55,11 +55,18 @@ var pluginMenuProto = Object.create(HTMLElement.prototype, {
|
||||
]
|
||||
});
|
||||
|
||||
loot.query(request).then(function(result){
|
||||
/* Need to also empty the UI-side user metadata. */
|
||||
loot.query(request).then(JSON.parse).then(function(result){
|
||||
/* Need to empty the UI-side user metadata. */
|
||||
for (var i = 0; i < loot.game.plugins.length; ++i) {
|
||||
if (loot.game.plugins[i].id == pluginID) {
|
||||
loot.game.plugins[i].userlist = undefined;
|
||||
|
||||
loot.game.plugins[i].modPriority = result.modPriority;
|
||||
loot.game.plugins[i].isGlobalPriority = result.isGlobalPriority;
|
||||
loot.game.plugins[i].messages = result.messages;
|
||||
loot.game.plugins[i].tags = result.tags;
|
||||
loot.game.plugins[i].isDirty = result.isDirty;
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -58,7 +58,9 @@ function Plugin(obj) {
|
||||
return data;
|
||||
}
|
||||
|
||||
Plugin.prototype.getTagsStrings = function () {
|
||||
|
||||
|
||||
Plugin.prototype.updateCardTags = function() {
|
||||
var tagsAdded = [];
|
||||
var tagsRemoved = [];
|
||||
|
||||
@@ -83,11 +85,16 @@ function Plugin(obj) {
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
tagsAdded: tagsAdded.join(', '),
|
||||
tagsRemoved: tagsRemoved.join(', ')
|
||||
};
|
||||
|
||||
if (tagsAdded.length != 0) {
|
||||
this.card.getElementsByClassName('tag add')[0].textContent = tagsAdded.join(', ');
|
||||
} else {
|
||||
this.card.getElementsByClassName('tag add')[0].classList.toggle('hidden');
|
||||
}
|
||||
if (tagsRemoved.length != 0) {
|
||||
this.card.getElementsByClassName('tag remove')[0].textContent = tagsRemoved.join(', ');
|
||||
} else {
|
||||
this.card.getElementsByClassName('tag remove')[0].classList.toggle('hidden');
|
||||
}
|
||||
}
|
||||
|
||||
Plugin.prototype.getPriorityString = function() {
|
||||
@@ -100,6 +107,27 @@ function Plugin(obj) {
|
||||
return priorityText;
|
||||
}
|
||||
|
||||
Plugin.prototype.updateCardMessages = function() {
|
||||
var messageUL = this.card.getElementsByTagName('ul')[0];
|
||||
/* First clear any existing messages. */
|
||||
while(messageUL.firstElementChild) {
|
||||
messageUL.removeChild(messageUL.firstElementChild);
|
||||
}
|
||||
/* Now add the new messages. */
|
||||
if (this.messages && this.messages.length != 0) {
|
||||
this.messages.forEach(function(message) {
|
||||
var messageLi = document.createElement('li');
|
||||
messageLi.className = message.type;
|
||||
// Use the Marked library for Markdown formatting support.
|
||||
messageLi.innerHTML = marked(message.content[0].str);
|
||||
messageUL.appendChild(messageLi);
|
||||
|
||||
});
|
||||
} else {
|
||||
this.card.getElementsByTagName('ul')[0].classList.toggle('hidden');
|
||||
}
|
||||
}
|
||||
|
||||
Plugin.prototype.createCard = function() {
|
||||
var card = new PluginCard();
|
||||
this.card = card;
|
||||
@@ -119,31 +147,10 @@ function Plugin(obj) {
|
||||
}
|
||||
|
||||
/* Fill in Bash Tag suggestions. */
|
||||
var tags = this.getTagsStrings();
|
||||
if (tags.tagsAdded) {
|
||||
card.getElementsByClassName('tag add')[0].textContent = tags.tagsAdded;
|
||||
} else {
|
||||
card.getElementsByClassName('tag add')[0].classList.toggle('hidden');
|
||||
}
|
||||
if (tags.tagsRemoved) {
|
||||
card.getElementsByClassName('tag remove')[0].textContent = tags.tagsRemoved;
|
||||
} else {
|
||||
card.getElementsByClassName('tag remove')[0].classList.toggle('hidden');
|
||||
}
|
||||
this.updateCardTags();
|
||||
|
||||
/* Fill in messages. */
|
||||
if (this.messages && this.messages.length != 0) {
|
||||
this.messages.forEach(function(message) {
|
||||
var messageLi = document.createElement('li');
|
||||
messageLi.className = message.type;
|
||||
// Use the Marked library for Markdown formatting support.
|
||||
messageLi.innerHTML = marked(message.content[0].str);
|
||||
card.getElementsByTagName('ul')[0].appendChild(messageLi);
|
||||
|
||||
});
|
||||
} else {
|
||||
card.getElementsByTagName('ul')[0].classList.toggle('hidden');
|
||||
}
|
||||
this.updateCardMessages();
|
||||
|
||||
/* The content elements steal the name, CRC and version, so they
|
||||
don't get distributed into the editor part of the shadow DOM.
|
||||
@@ -328,6 +335,57 @@ function Plugin(obj) {
|
||||
if (change.name == 'userlist') {
|
||||
change.object.li.setAttribute('data-edits', change.object[change.name] != undefined);
|
||||
change.object.card.setAttribute('data-edits', change.object[change.name] != undefined);
|
||||
} else if (change.name == 'modPriority') {
|
||||
change.object.li.querySelector('.priority').textContent = change.object.getPriorityString();
|
||||
change.object.card.shadowRoot.getElementById('priorityValue').value = change.object[change.name];
|
||||
} else if (change.name == 'isGlobalPriority') {
|
||||
change.object.li.querySelector('.priority').textContent = change.object.getPriorityString();
|
||||
} else if (change.name == 'messages') {
|
||||
change.object.updateCardMessages();
|
||||
/* For messages, the card's messages need updating,
|
||||
as do the message counts. */
|
||||
var oldTotal = 0;
|
||||
var newTotal = 0;
|
||||
var oldWarns = 0;
|
||||
var newWarns = 0;
|
||||
var oldErrs = 0;
|
||||
var newErrs = 0;
|
||||
|
||||
if (change.oldValue) {
|
||||
oldTotal = change.oldValue.length;
|
||||
|
||||
change.oldValue.forEach(function(message){
|
||||
if (message.type == 'warn') {
|
||||
++oldWarns;
|
||||
} else if (message.type == 'error') {
|
||||
++oldErrs;
|
||||
}
|
||||
});
|
||||
}
|
||||
if (change.object[change.name]) {
|
||||
newTotal = change.object[change.name].length;
|
||||
|
||||
change.object[change.name].forEach(function(message){
|
||||
if (message.type == 'warn') {
|
||||
++newWarns;
|
||||
} else if (message.type == 'error') {
|
||||
++newErrs;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
document.getElementById('filterTotalMessageNo').textContent = parseInt(document.getElementById('filterTotalMessageNo').textContent, 10) + newTotal - oldTotal;
|
||||
document.getElementById('totalMessageNo').textContent = parseInt(document.getElementById('totalMessageNo').textContent, 10) + newTotal - oldTotal;
|
||||
document.getElementById('totalWarningNo').textContent = parseInt(document.getElementById('totalWarningNo').textContent, 10) + newWarns - oldWarns;
|
||||
document.getElementById('totalErrorNo').textContent = parseInt(document.getElementById('totalErrorNo').textContent, 10) + newErrs - oldErrs;
|
||||
} else if (change.name == 'tags') {
|
||||
change.object.updateCardTags();
|
||||
} else if (change.name == 'isDirty') {
|
||||
if (change.object[change.name]) {
|
||||
document.getElementById('dirtyPluginNo').textContent = ++parseInt(document.getElementById('dirtyPluginNo').textContent, 10);
|
||||
} else {
|
||||
document.getElementById('dirtyPluginNo').textContent = --parseInt(document.getElementById('dirtyPluginNo').textContent, 10);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@@ -308,10 +308,22 @@ function redatePlugins(evt) {
|
||||
function clearAllMetadata(evt) {
|
||||
showMessageDialog('Clear All Metadata', 'Are you sure you want to clear all existing user-added metadata from all plugins?', function(result){
|
||||
if (result) {
|
||||
loot.query('clearAllMetadata').then(function(result){
|
||||
/* Need to also empty the UI-side user metadata. */
|
||||
loot.game.plugins.forEach(function(plugin){
|
||||
plugin.userlist = undefined;
|
||||
loot.query('clearAllMetadata').then(JSON.parse).then(function(result){
|
||||
/* Need to empty the UI-side user metadata. */
|
||||
result.forEach(function(plugin){
|
||||
for (var i = 0; i < loot.game.plugins.length; ++i) {
|
||||
if (loot.game.plugins[i].name == plugin.name) {
|
||||
loot.game.plugins[i].userlist = undefined;
|
||||
|
||||
loot.game.plugins[i].modPriority = plugin.modPriority;
|
||||
loot.game.plugins[i].isGlobalPriority = plugin.isGlobalPriority;
|
||||
loot.game.plugins[i].messages = plugin.messages;
|
||||
loot.game.plugins[i].tags = plugin.tags;
|
||||
loot.game.plugins[i].isDirty = plugin.isDirty;
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
});
|
||||
}).catch(processCefError);
|
||||
}
|
||||
@@ -707,9 +719,9 @@ function updateInterfaceWithGameInfo(response) {
|
||||
generalMessagesList.appendChild(li);
|
||||
|
||||
if (li.className == 'warn') {
|
||||
warnMessageNo++;
|
||||
++warnMessageNo;
|
||||
} else if (li.className == 'error') {
|
||||
errorMessageNo++;
|
||||
++errorMessageNo;
|
||||
}
|
||||
}
|
||||
totalMessageNo = loot.game.globalMessages.length;
|
||||
@@ -729,11 +741,11 @@ function updateInterfaceWithGameInfo(response) {
|
||||
plugin.messages.forEach(function(message) {
|
||||
|
||||
if (message.type == 'warn') {
|
||||
warnMessageNo++;
|
||||
++warnMessageNo;
|
||||
} else if (message.type == 'error') {
|
||||
errorMessageNo++;
|
||||
++errorMessageNo;
|
||||
}
|
||||
totalMessageNo++;
|
||||
++totalMessageNo;
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
@@ -725,7 +725,7 @@ namespace loot {
|
||||
return false;
|
||||
}
|
||||
|
||||
void Plugin::CheckInstallValidity(const Game& game) {
|
||||
bool Plugin::CheckInstallValidity(const Game& game) {
|
||||
unsigned int messageType;
|
||||
if (game.IsActive(name))
|
||||
messageType = loot::Message::error;
|
||||
@@ -755,6 +755,37 @@ namespace loot {
|
||||
messages.push_back(loot::Message(messageType, (boost::format(boost::locale::translate("This plugin is incompatible with \"%1%\", but both are present.")) % inc.Name()).str()));
|
||||
}
|
||||
}
|
||||
|
||||
// Also evaluate dirty info.
|
||||
bool isDirty = false;
|
||||
for (const auto &element : _dirtyInfo) {
|
||||
boost::format f;
|
||||
if (element.ITMs() > 0 && element.UDRs() > 0 && element.DeletedNavmeshes() > 0)
|
||||
f = boost::format(boost::locale::translate("Contains %1% ITM records, %2% UDR records and %3% deleted navmeshes. Clean with %4%.")) % element.ITMs() % element.UDRs() % element.DeletedNavmeshes() % element.CleaningUtility();
|
||||
else if (element.ITMs() == 0 && element.UDRs() == 0 && element.DeletedNavmeshes() == 0)
|
||||
f = boost::format(boost::locale::translate("Clean with %1%.")) % element.CleaningUtility();
|
||||
|
||||
|
||||
else if (element.ITMs() == 0 && element.UDRs() > 0 && element.DeletedNavmeshes() > 0)
|
||||
f = boost::format(boost::locale::translate("Contains %1% UDR records and %2% deleted navmeshes. Clean with %3%.")) % element.UDRs() % element.DeletedNavmeshes() % element.CleaningUtility();
|
||||
else if (element.ITMs() == 0 && element.UDRs() == 0 && element.DeletedNavmeshes() > 0)
|
||||
f = boost::format(boost::locale::translate("Contains %1% deleted navmeshes. Clean with %2%.")) % element.DeletedNavmeshes() % element.CleaningUtility();
|
||||
else if (element.ITMs() == 0 && element.UDRs() > 0 && element.DeletedNavmeshes() == 0)
|
||||
f = boost::format(boost::locale::translate("Contains %1% UDR records. Clean with %2%.")) % element.UDRs() % element.CleaningUtility();
|
||||
|
||||
else if (element.ITMs() > 0 && element.UDRs() == 0 && element.DeletedNavmeshes() > 0)
|
||||
f = boost::format(boost::locale::translate("Contains %1% ITM records and %2% deleted navmeshes. Clean with %3%.")) % element.ITMs() % element.DeletedNavmeshes() % element.CleaningUtility();
|
||||
else if (element.ITMs() > 0 && element.UDRs() == 0 && element.DeletedNavmeshes() == 0)
|
||||
f = boost::format(boost::locale::translate("Contains %1% ITM records. Clean with %2%.")) % element.ITMs() % element.CleaningUtility();
|
||||
|
||||
else if (element.ITMs() > 0 && element.UDRs() > 0 && element.DeletedNavmeshes() == 0)
|
||||
f = boost::format(boost::locale::translate("Contains %1% ITM records and %2% UDR records. Clean with %3%.")) % element.ITMs() % element.UDRs() % element.CleaningUtility();
|
||||
|
||||
messages.push_back(loot::Message(loot::Message::warn, f.str()));
|
||||
isDirty = true;
|
||||
}
|
||||
|
||||
return isDirty;
|
||||
}
|
||||
|
||||
bool Plugin::LoadsBSA(const Game& game) const {
|
||||
|
||||
@@ -220,7 +220,7 @@ namespace loot {
|
||||
bool MustLoadAfter(const Plugin& plugin) const; //Checks masters, reqs and loadAfter.
|
||||
|
||||
//Validity checks.
|
||||
void CheckInstallValidity(const Game& game); //Checks that reqs and masters are all present, and that no incs are present. Returns a map of filenames and whether they are missing (if bool is true, then filename is a req or master, otherwise it's an inc).
|
||||
bool CheckInstallValidity(const Game& game); //Checks that reqs and masters are all present, and that no incs are present. Returns true if the plugin is dirty.
|
||||
private:
|
||||
std::string name;
|
||||
bool enabled; //Default to true.
|
||||
|
||||
+94
-43
@@ -131,8 +131,57 @@ namespace loot {
|
||||
return true;
|
||||
}
|
||||
else if (request == "clearAllMetadata") {
|
||||
// First regenerate the derived metadata (priority, messages, tags and dirty state)
|
||||
// for any plugins with userlist entries, ignoring the user metadata.
|
||||
|
||||
//Set language.
|
||||
unsigned int language;
|
||||
if (g_app_state.GetSettings()["language"])
|
||||
language = Language(g_app_state.GetSettings()["language"].as<string>()).Code();
|
||||
else
|
||||
language = Language::any;
|
||||
|
||||
YAML::Node pluginsNode;
|
||||
for (const auto &plugin : g_app_state.CurrentGame().userlist.plugins) {
|
||||
YAML::Node temp;
|
||||
|
||||
auto pluginIt = g_app_state.CurrentGame().plugins.find(plugin.Name());
|
||||
if (pluginIt != g_app_state.CurrentGame().plugins.end()) {
|
||||
Plugin tempPlugin(pluginIt->second);
|
||||
|
||||
tempPlugin.MergeMetadata(g_app_state.CurrentGame().masterlist.FindPlugin(pluginIt->first));
|
||||
|
||||
//Evaluate any conditions
|
||||
BOOST_LOG_TRIVIAL(trace) << "Evaluate conditions for merged plugin data.";
|
||||
try {
|
||||
tempPlugin.EvalAllConditions(g_app_state.CurrentGame(), language);
|
||||
}
|
||||
catch (std::exception& e) {
|
||||
BOOST_LOG_TRIVIAL(error) << "\"" << tempPlugin.Name() << "\" contains a condition that could not be evaluated. Details: " << e.what();
|
||||
g_app_state.CurrentGame().masterlist.messages.push_back(Message(Message::error, (format(loc::translate("\"%1%\" contains a condition that could not be evaluated. Details: %2%")) % tempPlugin.Name() % e.what()).str()));
|
||||
}
|
||||
|
||||
//Also check install validity.
|
||||
BOOST_LOG_TRIVIAL(trace) << "Checking that the current install is valid according to this plugin's data.";
|
||||
bool isDirty = tempPlugin.CheckInstallValidity(g_app_state.CurrentGame());
|
||||
|
||||
// Now add to pluginNode.
|
||||
temp["name"] = tempPlugin.Name();
|
||||
temp["modPriority"] = modulo(tempPlugin.Priority(), max_priority);
|
||||
temp["isGlobalPriority"] = (abs(tempPlugin.Priority()) >= max_priority);
|
||||
temp["messages"] = tempPlugin.Messages();
|
||||
temp["tags"] = tempPlugin.Tags();
|
||||
temp["isDirty"] = isDirty;
|
||||
}
|
||||
|
||||
pluginsNode.push_back(temp);
|
||||
}
|
||||
// Now clear the user metadata.
|
||||
g_app_state.CurrentGame().userlist.clear();
|
||||
callback->Success("");
|
||||
if (pluginsNode.size() > 0)
|
||||
callback->Success(JSON::stringify(pluginsNode));
|
||||
else
|
||||
callback->Success("[]");
|
||||
return true;
|
||||
}
|
||||
else {
|
||||
@@ -270,13 +319,50 @@ namespace loot {
|
||||
const string pluginName = req["args"][0].as<string>();
|
||||
BOOST_LOG_TRIVIAL(debug) << "Clearing user metadata for plugin " << pluginName;
|
||||
|
||||
auto pluginIt = find(g_app_state.CurrentGame().userlist.plugins.begin(), g_app_state.CurrentGame().userlist.plugins.end(), Plugin(pluginName));
|
||||
auto ulistPluginIt = find(g_app_state.CurrentGame().userlist.plugins.begin(), g_app_state.CurrentGame().userlist.plugins.end(), Plugin(pluginName));
|
||||
|
||||
if (pluginIt != g_app_state.CurrentGame().userlist.plugins.end()) {
|
||||
g_app_state.CurrentGame().userlist.plugins.erase(pluginIt);
|
||||
if (ulistPluginIt != g_app_state.CurrentGame().userlist.plugins.end()) {
|
||||
g_app_state.CurrentGame().userlist.plugins.erase(ulistPluginIt);
|
||||
}
|
||||
|
||||
callback->Success("");
|
||||
//Set language.
|
||||
unsigned int language;
|
||||
if (g_app_state.GetSettings()["language"])
|
||||
language = Language(g_app_state.GetSettings()["language"].as<string>()).Code();
|
||||
else
|
||||
language = Language::any;
|
||||
|
||||
// Now rederive the displayed metadata from the masterlist.
|
||||
YAML::Node pluginNode;
|
||||
auto pluginIt = g_app_state.CurrentGame().plugins.find(pluginName);
|
||||
if (pluginIt != g_app_state.CurrentGame().plugins.end()) {
|
||||
Plugin tempPlugin(pluginIt->second);
|
||||
|
||||
tempPlugin.MergeMetadata(g_app_state.CurrentGame().masterlist.FindPlugin(pluginIt->first));
|
||||
|
||||
//Evaluate any conditions
|
||||
BOOST_LOG_TRIVIAL(trace) << "Evaluate conditions for merged plugin data.";
|
||||
try {
|
||||
tempPlugin.EvalAllConditions(g_app_state.CurrentGame(), language);
|
||||
}
|
||||
catch (std::exception& e) {
|
||||
BOOST_LOG_TRIVIAL(error) << "\"" << tempPlugin.Name() << "\" contains a condition that could not be evaluated. Details: " << e.what();
|
||||
g_app_state.CurrentGame().masterlist.messages.push_back(Message(Message::error, (format(loc::translate("\"%1%\" contains a condition that could not be evaluated. Details: %2%")) % tempPlugin.Name() % e.what()).str()));
|
||||
}
|
||||
|
||||
//Also check install validity.
|
||||
BOOST_LOG_TRIVIAL(trace) << "Checking that the current install is valid according to this plugin's data.";
|
||||
bool isDirty = tempPlugin.CheckInstallValidity(g_app_state.CurrentGame());
|
||||
|
||||
// Now add to pluginNode.
|
||||
pluginNode["modPriority"] = modulo(tempPlugin.Priority(), max_priority);
|
||||
pluginNode["isGlobalPriority"] = (abs(tempPlugin.Priority()) >= max_priority);
|
||||
pluginNode["messages"] = tempPlugin.Messages();
|
||||
pluginNode["tags"] = tempPlugin.Tags();
|
||||
pluginNode["isDirty"] = isDirty;
|
||||
}
|
||||
|
||||
callback->Success(JSON::stringify(pluginNode));
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -464,49 +550,14 @@ namespace loot {
|
||||
|
||||
//Also check install validity.
|
||||
BOOST_LOG_TRIVIAL(trace) << "Checking that the current install is valid according to this plugin's data.";
|
||||
mlistPlugin.CheckInstallValidity(g_app_state.CurrentGame());
|
||||
|
||||
// Also evaluate dirty info.
|
||||
std::list<Message> messages = mlistPlugin.Messages();
|
||||
std::set<PluginDirtyInfo> dirtyInfo = mlistPlugin.DirtyInfo();
|
||||
size_t numDirtyInfo(0);
|
||||
for (const auto &element : dirtyInfo) {
|
||||
boost::format f;
|
||||
if (element.ITMs() > 0 && element.UDRs() > 0 && element.DeletedNavmeshes() > 0)
|
||||
f = boost::format(boost::locale::translate("Contains %1% ITM records, %2% UDR records and %3% deleted navmeshes. Clean with %4%.")) % element.ITMs() % element.UDRs() % element.DeletedNavmeshes() % element.CleaningUtility();
|
||||
else if (element.ITMs() == 0 && element.UDRs() == 0 && element.DeletedNavmeshes() == 0)
|
||||
f = boost::format(boost::locale::translate("Clean with %1%.")) % element.CleaningUtility();
|
||||
|
||||
|
||||
else if (element.ITMs() == 0 && element.UDRs() > 0 && element.DeletedNavmeshes() > 0)
|
||||
f = boost::format(boost::locale::translate("Contains %1% UDR records and %2% deleted navmeshes. Clean with %3%.")) % element.UDRs() % element.DeletedNavmeshes() % element.CleaningUtility();
|
||||
else if (element.ITMs() == 0 && element.UDRs() == 0 && element.DeletedNavmeshes() > 0)
|
||||
f = boost::format(boost::locale::translate("Contains %1% deleted navmeshes. Clean with %2%.")) % element.DeletedNavmeshes() % element.CleaningUtility();
|
||||
else if (element.ITMs() == 0 && element.UDRs() > 0 && element.DeletedNavmeshes() == 0)
|
||||
f = boost::format(boost::locale::translate("Contains %1% UDR records. Clean with %2%.")) % element.UDRs() % element.CleaningUtility();
|
||||
|
||||
else if (element.ITMs() > 0 && element.UDRs() == 0 && element.DeletedNavmeshes() > 0)
|
||||
f = boost::format(boost::locale::translate("Contains %1% ITM records and %2% deleted navmeshes. Clean with %3%.")) % element.ITMs() % element.DeletedNavmeshes() % element.CleaningUtility();
|
||||
else if (element.ITMs() > 0 && element.UDRs() == 0 && element.DeletedNavmeshes() == 0)
|
||||
f = boost::format(boost::locale::translate("Contains %1% ITM records. Clean with %2%.")) % element.ITMs() % element.CleaningUtility();
|
||||
|
||||
else if (element.ITMs() > 0 && element.UDRs() > 0 && element.DeletedNavmeshes() == 0)
|
||||
f = boost::format(boost::locale::translate("Contains %1% ITM records and %2% UDR records. Clean with %3%.")) % element.ITMs() % element.UDRs() % element.CleaningUtility();
|
||||
|
||||
messages.push_back(loot::Message(loot::Message::warn, f.str()));
|
||||
++numDirtyInfo;
|
||||
}
|
||||
bool isDirty = mlistPlugin.CheckInstallValidity(g_app_state.CurrentGame());
|
||||
|
||||
// Now add to pluginNode.
|
||||
pluginNode["modPriority"] = modulo(mlistPlugin.Priority(), max_priority);
|
||||
pluginNode["isGlobalPriority"] = (abs(mlistPlugin.Priority()) >= max_priority);
|
||||
pluginNode["messages"] = messages;
|
||||
pluginNode["messages"] = mlistPlugin.Messages();
|
||||
pluginNode["tags"] = mlistPlugin.Tags();
|
||||
pluginNode["isDirty"] = (numDirtyInfo > 0);
|
||||
|
||||
BOOST_LOG_TRIVIAL(trace) << "messages length: " << messages.size();
|
||||
BOOST_LOG_TRIVIAL(trace) << "tags length: " << mlistPlugin.Tags().size();
|
||||
|
||||
pluginNode["isDirty"] = isDirty;
|
||||
|
||||
gameNode["plugins"].push_back(pluginNode);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user