mirror of
https://github.com/loot/libloot.git
synced 2026-07-27 14:16:01 -07:00
Metadata Editor not updated to handle the new message structure.
This commit is contained in:
@@ -133,7 +133,7 @@ This documentation is a work in progress, covering a syntax that is also still a
|
||||
<code class="box">globals:
|
||||
- type: say
|
||||
content: You are using the latest version of BOSS.
|
||||
condition: 'version("../BOSS/BOSS.exe", "2.1.1.0", ==)'
|
||||
condition: 'version("BOSS", "3.0.0.0", ==)'
|
||||
plugins:
|
||||
- name: Armamentarium.esm
|
||||
tag:
|
||||
@@ -181,7 +181,7 @@ condition: "file(\"Mart's Monster Mod for OOO.esm\") or file(\"FCOM_Convergence.
|
||||
<table>
|
||||
<thead><tr><th>Key Name<th>Required<th>Notes
|
||||
<tbody>
|
||||
<tr><td><code>name</code><td>✓<td>A file path relative to the game's Data folder.
|
||||
<tr><td><code>name</code><td>✓<td>A file path or name.
|
||||
<tr><td><code>display</code><td>✗<td>A substitute string to be displayed instead of the file path in any generated messages, eg. the name of the mod the file belongs to.
|
||||
<tr><td><code>condition</code><td>✗<td>A condition string that is evaluated to determine whether this file data should be used: if it evaluates to true, the data is used, otherwise it is ignored. See <a href="#cond">Condition Strings</a> for details.
|
||||
</table>
|
||||
@@ -190,7 +190,7 @@ condition: "file(\"Mart's Monster Mod for OOO.esm\") or file(\"FCOM_Convergence.
|
||||
<code class="box">../obse_loader.exe</code>
|
||||
or
|
||||
<code class="box">name: ../obse_loader.exe
|
||||
condition: 'version("../obse_loader.exe", "0.0.18.0", <)'
|
||||
condition: 'version("../obse_loader.exe", "0.0.18.0", >=)'
|
||||
display: OBSE v18+
|
||||
</code>
|
||||
|
||||
@@ -222,7 +222,7 @@ display: OBSE v18+
|
||||
|
||||
<p>BOSS handles messages and languages as follows:
|
||||
<ol>
|
||||
<li>If a message's <code>content</code> value is a string, the message will the string as its content if displayed.
|
||||
<li>If a message's <code>content</code> value is a string, the message will use the string as its content if displayed.
|
||||
<li>If a message's <code>content</code> value is a list of content structures, then the first structure with a language that matches BOSS's current language will be used as the message's content if displayed. If there are no matches, then the first structure in English will be used.
|
||||
</ol>
|
||||
|
||||
@@ -232,11 +232,11 @@ display: OBSE v18+
|
||||
condition: file("foo.esp")
|
||||
content:
|
||||
- lang: eng
|
||||
str: An example link: http://www.example.com
|
||||
str: 'An example link: http://www.example.com'
|
||||
- lang: rus
|
||||
str: Это пример ссылки: http://www.example.com
|
||||
str: 'Это пример ссылки: http://www.example.com'
|
||||
- lang: ger
|
||||
str: Ein Beispiel-Link: http://www.example.com
|
||||
str: 'Ein Beispiel-Link: http://www.example.com'
|
||||
</code>
|
||||
would be displayed as
|
||||
<blockquote>
|
||||
@@ -295,7 +295,7 @@ msg:
|
||||
<tr><td>File<td><code>file("<var>filepath</var>")</code><td>Returns true if <var>filepath</var> is installed, false otherwise.
|
||||
<tr><td>File<td><code>regex("<var>regex</var>")</code><td>Returns true if a file matching <var>regex</var> is found, false otherwise.
|
||||
<tr><td>Checksum<td><code>checksum("<var>filepath</var>", <var>checksum</var>)</code><td>Returns true if the calculated checksum of <var>filepath</var> matches <var>checksum</var>, false otherwise. If <var>filepath</var> does not exist, returns false.
|
||||
<tr><td>Version<td><code>version("<var>filepath</var>", "<var>version</var>", <var>comparator</var>)</code><td>Returns true if the boolean expression <code><var>version comparator</var> (actual version of <var>filepath</var>)</code> holds true, false otherwise. If <var>filepath</var> does not exist and <var>comparator</var> is <code>==</code>, <code>></code> or <code>>=</code>, returns false. If <var>filepath</var> does not exist and <var>comparator</var> is <code>!=</code>, <code><</code> or <code><=</code>, returns true.
|
||||
<tr><td>Version<td><code>version("<var>filepath</var>", "<var>version</var>", <var>comparator</var>)</code><td>Returns true if the boolean expression <code>(actual version of <var>filepath</var>) <var>comparator version</var></code> holds true, false otherwise. If <var>filepath</var> does not exist and <var>comparator</var> is <code>==</code>, <code>></code> or <code>>=</code>, returns false. If <var>filepath</var> does not exist and <var>comparator</var> is <code>!=</code>, <code><</code> or <code><=</code>, returns true.
|
||||
<tr><td>Plugin Active Status<td><code>active("<var>filepath</var>")</code><td>Returns true if <var>filepath</var> is a <code>.esp</code> or <code>.esm</code> file that is both installed and active, false otherwise.
|
||||
</table>
|
||||
|
||||
@@ -303,7 +303,7 @@ msg:
|
||||
<table>
|
||||
<thead><tr><th>Variable Type<th>Description
|
||||
<tbody>
|
||||
<tr><td><code>filepath</code><td>A Windows file path.
|
||||
<tr><td><code>filepath</code><td>A Windows file path, or <code>BOSS</code>, which references the BOSS executable being run.
|
||||
<tr><td><code>regex</code><td>A regular expression string to match file paths to.
|
||||
<tr><td><code>checksum</code><td>A string of hexadecimal digits representing an unsigned integer that is the data checksum of a file. BOSS displays the checksums of plugins in its user interface after running.
|
||||
<tr><td><code>version</code><td>A string of characters representing the version of a plugin or executable. BOSS displays the versions of plugins in its user interface after running.
|
||||
@@ -346,11 +346,11 @@ msg:
|
||||
<li>Logical <q>and</q>
|
||||
<li>Logical <q>or</q>
|
||||
</ol>
|
||||
<p>Below is a table that lists some combinations of conditions, showing for each the order of evaluation by explicit bracketing. To make it easier to read, the <code><var>keyword</var> <var>function</var></code> pair is replaced with <code><var>C</var></code> after the first example.
|
||||
<p>Below is a table that lists some combinations of conditions, showing for each the order of evaluation by explicit bracketing. To make it easier to read, the <code><var>negator</var> <var>function</var></code> pair is shortened to <code><var>C</var></code> after the first example.
|
||||
<table>
|
||||
<thead><tr><th>String Structure<th>Evaluated As
|
||||
<tbody>
|
||||
<tr><td><code><var>keyword</var> <var>function</var></code><td><code>( <var>keyword</var> ( <var>function</var> ) )</code>
|
||||
<tr><td><code><var>negator</var> <var>function</var></code><td><code>( <var>negator</var> ( <var>function</var> ) )</code>
|
||||
<tr><td><code><var>C</var> and <var>C</var></code><td><code>( <var>C</var> and <var>C</var> )</code>
|
||||
<tr><td><code><var>C</var> or <var>C</var></code><td><code>( <var>C</var> or <var>C</var> )</code>
|
||||
<tr><td><code><var>C</var> and <var>C</var> and <var>C</var></code><td><code>( ( <var>C</var> and <var>C</var> ) and <var>C</var> )</code>
|
||||
|
||||
@@ -186,7 +186,7 @@ namespace boss {
|
||||
}
|
||||
|
||||
//Turn any urls into hyperlinks.
|
||||
WriteMessage(li, it->Type(), it->Content());
|
||||
WriteMessage(li, it->Type(), it->Content().front().Str());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -547,6 +547,17 @@ namespace YAML {
|
||||
out << EndMap;
|
||||
}
|
||||
|
||||
inline Emitter& operator << (Emitter& out, const boss::MessageContent& rhs) {
|
||||
out << BeginMap;
|
||||
|
||||
if (rhs.Language() == boss::LANG_ENG)
|
||||
out << Key << "lang" << Value << "eng";
|
||||
|
||||
out << Key << "str" << Value << rhs.Str();
|
||||
|
||||
out << EndMap;
|
||||
}
|
||||
|
||||
inline Emitter& operator << (Emitter& out, const boss::Message& rhs) {
|
||||
out << BeginMap;
|
||||
|
||||
@@ -557,10 +568,10 @@ namespace YAML {
|
||||
else
|
||||
out << Key << "type" << Value << "error";
|
||||
|
||||
out << Key << "content" << Value << rhs.Content();
|
||||
|
||||
if (rhs.Language() == boss::LANG_ENG)
|
||||
out << Key << "lang" << Value << "eng";
|
||||
if (rhs.Content().size() == 1)
|
||||
out << Key << "content" << Value << rhs.Content().front().Str();
|
||||
else
|
||||
out << Key << "content" << Value << rhs.Content();
|
||||
|
||||
if (!rhs.Condition().empty())
|
||||
out << Key << "condition" << Value << rhs.Condition();
|
||||
|
||||
+95
-46
@@ -29,6 +29,7 @@
|
||||
|
||||
#include <boost/algorithm/string.hpp>
|
||||
#include <boost/filesystem.hpp>
|
||||
#include <boost/regex.hpp>
|
||||
|
||||
using namespace std;
|
||||
|
||||
@@ -69,34 +70,23 @@ namespace boss {
|
||||
return id;
|
||||
}
|
||||
|
||||
ConditionalData::ConditionalData() {}
|
||||
ConditionStruct::ConditionStruct() {}
|
||||
|
||||
ConditionalData::ConditionalData(const string& c) : condition(c) {}
|
||||
ConditionStruct::ConditionStruct(const string& condition) : _condition(condition) {}
|
||||
|
||||
ConditionalData::ConditionalData(const std::string& c, const std::string& d)
|
||||
: condition(c), data(d) {}
|
||||
|
||||
bool ConditionalData::IsConditional() const {
|
||||
return !condition.empty();
|
||||
bool ConditionStruct::IsConditional() const {
|
||||
return !_condition.empty();
|
||||
}
|
||||
|
||||
std::string ConditionalData::Condition() const {
|
||||
return condition;
|
||||
std::string ConditionStruct::Condition() const {
|
||||
return _condition;
|
||||
}
|
||||
|
||||
std::string ConditionalData::Data() const {
|
||||
return data;
|
||||
}
|
||||
|
||||
void ConditionalData::Data(const std::string& d) {
|
||||
data = d;
|
||||
}
|
||||
|
||||
bool ConditionalData::EvalCondition(boss::Game& game) const {
|
||||
if (condition.empty())
|
||||
bool ConditionStruct::EvalCondition(boss::Game& game) const {
|
||||
if (_condition.empty())
|
||||
return true;
|
||||
|
||||
boost::unordered_map<std::string, bool>::const_iterator it = game.conditionCache.find(boost::to_lower_copy(condition));
|
||||
boost::unordered_map<std::string, bool>::const_iterator it = game.conditionCache.find(boost::to_lower_copy(_condition));
|
||||
if (it != game.conditionCache.end())
|
||||
return it->second;
|
||||
|
||||
@@ -106,60 +96,117 @@ namespace boss {
|
||||
bool eval;
|
||||
|
||||
grammar.SetGame(game);
|
||||
begin = condition.begin();
|
||||
end = condition.end();
|
||||
begin = _condition.begin();
|
||||
end = _condition.end();
|
||||
|
||||
bool r;
|
||||
try {
|
||||
r = boost::spirit::qi::phrase_parse(begin, end, grammar, skipper, eval);
|
||||
} catch (boss::error& e) {
|
||||
throw boss::error(boss::ERROR_PATH_READ_FAIL, "Parsing of condition \"" + condition + "\" failed: " + e.what());
|
||||
throw boss::error(boss::ERROR_PATH_READ_FAIL, "Parsing of condition \"" + _condition + "\" failed: " + e.what());
|
||||
}
|
||||
|
||||
if (!r || begin != end)
|
||||
throw boss::error(boss::ERROR_PATH_READ_FAIL, "Parsing of condition \"" + condition + "\" failed!");
|
||||
throw boss::error(boss::ERROR_PATH_READ_FAIL, "Parsing of condition \"" + _condition + "\" failed!");
|
||||
|
||||
game.conditionCache.emplace(boost::to_lower_copy(condition), eval);
|
||||
game.conditionCache.emplace(boost::to_lower_copy(_condition), eval);
|
||||
|
||||
return eval;
|
||||
}
|
||||
|
||||
MessageContent::MessageContent() : _language(LANG_AUTO) {}
|
||||
|
||||
MessageContent::MessageContent(const std::string& str, const unsigned int language) : _str(str), _language(language) {}
|
||||
|
||||
std::string MessageContent::Str() const {
|
||||
return _str;
|
||||
}
|
||||
|
||||
unsigned int MessageContent::Language() const {
|
||||
return _language;
|
||||
}
|
||||
|
||||
bool MessageContent::operator < (const MessageContent& rhs) const {
|
||||
return boost::ilexicographical_compare(_str, rhs.Str());
|
||||
}
|
||||
|
||||
bool MessageContent::operator == (const MessageContent& rhs) const {
|
||||
return (_language == rhs.Language() && boost::iequals(_str, rhs.Str()));
|
||||
}
|
||||
|
||||
Message::Message() {}
|
||||
|
||||
Message::Message(const unsigned int type, const std::string& content,
|
||||
const std::string& condition, const unsigned int language)
|
||||
: _type(type), _language(language), ConditionalData(condition, content) {}
|
||||
const std::string& condition) : _type(type), ConditionStruct(condition) {
|
||||
_content.push_back(MessageContent(content));
|
||||
}
|
||||
|
||||
Message::Message(const unsigned int type, const std::vector<MessageContent>& content,
|
||||
const std::string& condition) : _type(type), _content(content), ConditionStruct(condition) {}
|
||||
|
||||
bool Message::operator < (const Message& rhs) const {
|
||||
return boost::ilexicographical_compare(Content(), rhs.Content());
|
||||
return boost::ilexicographical_compare(_content.front().Str(), rhs.Content().front().Str());
|
||||
}
|
||||
|
||||
bool Message::operator == (const Message& rhs) const {
|
||||
return (_type == rhs.Type() && boost::iequals(Content(), rhs.Content()));
|
||||
return (_type == rhs.Type() && _content == rhs.Content());
|
||||
}
|
||||
|
||||
bool Message::EvalCondition(boss::Game& game, const unsigned int lang) const {
|
||||
if (_language == LANG_AUTO || _language == lang)
|
||||
return ConditionalData::EvalCondition(game);
|
||||
else
|
||||
return false;
|
||||
bool Message::EvalCondition(boss::Game& game, const unsigned int language) {
|
||||
if (_content.size() > 1) {
|
||||
if (language == LANG_AUTO) //Can use a message of any language, so use the first string.
|
||||
_content.resize(1);
|
||||
else {
|
||||
MessageContent english, match;
|
||||
for (vector<MessageContent>::const_iterator it=_content.begin(), endit=_content.end(); it != endit; ++it) {
|
||||
if (it->Language() == language) {
|
||||
match = *it;
|
||||
break;
|
||||
} else if (it->Language() == LANG_ENG)
|
||||
english = *it;
|
||||
}
|
||||
_content.resize(1);
|
||||
if (!match.Str().empty())
|
||||
_content[0] = match;
|
||||
else
|
||||
_content[0] = english;
|
||||
}
|
||||
}
|
||||
return ConditionStruct::EvalCondition(game);
|
||||
}
|
||||
|
||||
MessageContent Message::ChooseContent(const unsigned int language) const {
|
||||
if (_content.size() > 1) {
|
||||
if (language == LANG_AUTO) //Can use a message of any language, so use the first string.
|
||||
return _content[0];
|
||||
else {
|
||||
MessageContent english, match;
|
||||
for (vector<MessageContent>::const_iterator it=_content.begin(), endit=_content.end(); it != endit; ++it) {
|
||||
if (it->Language() == language) {
|
||||
match = *it;
|
||||
break;
|
||||
} else if (it->Language() == LANG_ENG)
|
||||
english = *it;
|
||||
}
|
||||
if (!match.Str().empty())
|
||||
return match;
|
||||
else
|
||||
return english;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
unsigned int Message::Type() const {
|
||||
return _type;
|
||||
}
|
||||
|
||||
unsigned int Message::Language() const {
|
||||
return _language;
|
||||
}
|
||||
|
||||
std::string Message::Content() const {
|
||||
return Data();
|
||||
std::vector<MessageContent> Message::Content() const {
|
||||
return _content;
|
||||
}
|
||||
|
||||
File::File() {}
|
||||
File::File(const std::string& name, const std::string& display, const std::string& condition)
|
||||
: _display(display), ConditionalData(condition, name) {}
|
||||
: _name(name), _display(display), ConditionStruct(condition) {}
|
||||
|
||||
bool File::operator < (const File& rhs) const {
|
||||
return boost::ilexicographical_compare(Name(), rhs.Name());
|
||||
@@ -170,7 +217,7 @@ namespace boss {
|
||||
}
|
||||
|
||||
std::string File::Name() const {
|
||||
return Data();
|
||||
return _name;
|
||||
}
|
||||
|
||||
std::string File::DisplayName() const {
|
||||
@@ -179,7 +226,7 @@ namespace boss {
|
||||
|
||||
Tag::Tag() : addTag(true) {}
|
||||
|
||||
Tag::Tag(const string& tag, const bool isAddition, const string& condition) : addTag(isAddition), ConditionalData(condition, tag) {}
|
||||
Tag::Tag(const string& tag, const bool isAddition, const string& condition) : _name(tag), addTag(isAddition), ConditionStruct(condition) {}
|
||||
|
||||
bool Tag::operator < (const Tag& rhs) const {
|
||||
if (addTag != rhs.IsAddition())
|
||||
@@ -197,7 +244,7 @@ namespace boss {
|
||||
}
|
||||
|
||||
std::string Tag::Name() const {
|
||||
return Data();
|
||||
return _name;
|
||||
}
|
||||
|
||||
Plugin::Plugin() : enabled(true), priority(0), isMaster(false) {}
|
||||
@@ -277,7 +324,7 @@ namespace boss {
|
||||
|
||||
void Plugin::Merge(const Plugin& plugin, bool ifDisabled) {
|
||||
//If 'name' differs or if 'enabled' is false for the given plugin, don't change anything.
|
||||
if (!boost::iequals(name, plugin.Name()) || (!plugin.Enabled() && !ifDisabled))
|
||||
if ((!plugin.Enabled() && !ifDisabled))
|
||||
return;
|
||||
|
||||
//The following should be replaced.
|
||||
@@ -457,7 +504,9 @@ namespace boss {
|
||||
}
|
||||
|
||||
bool Plugin::operator == (const Plugin& rhs) const {
|
||||
return boost::iequals(name, rhs.Name());
|
||||
return (boost::iequals(name, rhs.Name())
|
||||
|| (IsRegexPlugin() && boost::regex_match(rhs.Name(), boost::regex(name, boost::regex::extended|boost::regex::icase)))
|
||||
|| (rhs.IsRegexPlugin() && boost::regex_match(name, boost::regex(rhs.Name(), boost::regex::extended|boost::regex::icase))));
|
||||
}
|
||||
|
||||
bool Plugin::operator != (const Plugin& rhs) const {
|
||||
|
||||
+31
-17
@@ -52,44 +52,56 @@ namespace boss {
|
||||
uint32_t id;
|
||||
};
|
||||
|
||||
class ConditionalData {
|
||||
class ConditionStruct {
|
||||
public:
|
||||
ConditionalData();
|
||||
ConditionalData(const std::string& condition);
|
||||
ConditionalData(const std::string& condition, const std::string& data);
|
||||
ConditionStruct();
|
||||
ConditionStruct(const std::string& condition);
|
||||
|
||||
bool IsConditional() const;
|
||||
bool EvalCondition(boss::Game& game) const;
|
||||
|
||||
std::string Condition() const;
|
||||
std::string Data() const;
|
||||
|
||||
void Data(const std::string& data);
|
||||
private:
|
||||
std::string condition;
|
||||
std::string data;
|
||||
std::string _condition;
|
||||
};
|
||||
|
||||
class Message : public ConditionalData {
|
||||
class MessageContent {
|
||||
public:
|
||||
MessageContent();
|
||||
MessageContent(const std::string& str, const unsigned int language = LANG_AUTO);
|
||||
|
||||
std::string Str() const;
|
||||
unsigned int Language() const;
|
||||
|
||||
bool operator < (const MessageContent& rhs) const;
|
||||
bool operator == (const MessageContent& rhs) const;
|
||||
private:
|
||||
std::string _str;
|
||||
unsigned int _language;
|
||||
};
|
||||
|
||||
class Message : public ConditionStruct {
|
||||
public:
|
||||
Message();
|
||||
Message(const unsigned int type, const std::string& content,
|
||||
const std::string& condition = "", const unsigned int language = LANG_AUTO);
|
||||
const std::string& condition = "");
|
||||
Message(const unsigned int type, const std::vector<MessageContent>& content,
|
||||
const std::string& condition = "");
|
||||
|
||||
bool operator < (const Message& rhs) const;
|
||||
bool operator == (const Message& rhs) const;
|
||||
|
||||
bool EvalCondition(boss::Game& game, const unsigned int language) const;
|
||||
bool EvalCondition(boss::Game& game, const unsigned int language);
|
||||
|
||||
unsigned int Type() const;
|
||||
unsigned int Language() const;
|
||||
std::string Content() const;
|
||||
std::vector<MessageContent> Content() const;
|
||||
MessageContent ChooseContent(const unsigned int language) const;
|
||||
private:
|
||||
unsigned int _type;
|
||||
unsigned int _language;
|
||||
std::vector<MessageContent> _content;
|
||||
};
|
||||
|
||||
class File : public ConditionalData {
|
||||
class File : public ConditionStruct {
|
||||
public:
|
||||
File();
|
||||
File(const std::string& name, const std::string& display = "",
|
||||
@@ -101,10 +113,11 @@ namespace boss {
|
||||
std::string Name() const;
|
||||
std::string DisplayName() const;
|
||||
private:
|
||||
std::string _name;
|
||||
std::string _display;
|
||||
};
|
||||
|
||||
class Tag : public ConditionalData {
|
||||
class Tag : public ConditionStruct {
|
||||
public:
|
||||
Tag();
|
||||
Tag(const std::string& tag, const bool isAddition = true, const std::string& condition = "");
|
||||
@@ -115,6 +128,7 @@ namespace boss {
|
||||
bool IsAddition() const;
|
||||
std::string Name() const;
|
||||
private:
|
||||
std::string _name;
|
||||
bool addTag;
|
||||
};
|
||||
|
||||
|
||||
@@ -143,6 +143,7 @@ namespace boss {
|
||||
return revision;
|
||||
else
|
||||
return "N/A";
|
||||
}
|
||||
|
||||
if (!RunCommand(command, output)) {
|
||||
//Working copy not set up, perform a checkout.
|
||||
|
||||
+70
-25
@@ -103,6 +103,39 @@ namespace YAML {
|
||||
}
|
||||
};
|
||||
|
||||
template<>
|
||||
struct convert<boss::MessageContent> {
|
||||
static Node encode(const boss::MessageContent& rhs) {
|
||||
Node node;
|
||||
node["str"] = rhs.Str();
|
||||
|
||||
if (rhs.Language() == boss::LANG_AUTO)
|
||||
node["lang"] = "";
|
||||
else
|
||||
node["lang"] = "eng";
|
||||
|
||||
return node;
|
||||
}
|
||||
|
||||
static bool decode(const Node& node, boss::MessageContent& rhs) {
|
||||
if (!node["str"] || !node["lang"])
|
||||
return false;
|
||||
|
||||
std::string str = node["str"].as<std::string>();
|
||||
std::string lang = node["lang"].as<std::string>();
|
||||
unsigned int langNo;
|
||||
|
||||
if (boost::iequals(lang, "eng"))
|
||||
langNo = boss::LANG_ENG;
|
||||
else
|
||||
langNo = boss::LANG_AUTO;
|
||||
|
||||
rhs = boss::MessageContent(str, langNo);
|
||||
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
template<>
|
||||
struct convert<boss::Message> {
|
||||
static Node encode(const boss::Message& rhs) {
|
||||
@@ -116,26 +149,15 @@ namespace YAML {
|
||||
node["type"] = "warn";
|
||||
else
|
||||
node["type"] = "error";
|
||||
|
||||
if (rhs.Language() == boss::LANG_AUTO)
|
||||
node["lang"] = "";
|
||||
else
|
||||
node["lang"] = "eng";
|
||||
|
||||
return node;
|
||||
}
|
||||
|
||||
static bool decode(const Node& node, boss::Message& rhs) {
|
||||
if(!node.IsMap())
|
||||
if(!node.IsMap() || !node["type"] || !node["content"])
|
||||
return false;
|
||||
|
||||
std::string condition, content;
|
||||
unsigned int typeNo, langNo;
|
||||
if (node["condition"])
|
||||
condition = node["condition"].as<std::string>();
|
||||
if (node["content"])
|
||||
content = node["content"].as<std::string>();
|
||||
|
||||
unsigned int typeNo;
|
||||
if (node["type"]) {
|
||||
std::string type;
|
||||
type = node["type"].as<std::string>();
|
||||
@@ -148,19 +170,28 @@ namespace YAML {
|
||||
typeNo = boss::MESSAGE_ERROR;
|
||||
}
|
||||
|
||||
|
||||
if (node["lang"]) {
|
||||
std::string lang;
|
||||
lang = node["lang"].as<std::string>();
|
||||
std::vector<boss::MessageContent> content;
|
||||
if (node["content"].IsSequence())
|
||||
content = node["content"].as< std::vector<boss::MessageContent> >();
|
||||
else
|
||||
content.push_back(node["content"].as<std::string>());
|
||||
|
||||
if (boost::iequals(lang, "eng"))
|
||||
langNo = boss::LANG_ENG;
|
||||
else
|
||||
langNo = boss::LANG_AUTO;
|
||||
//Check now that at least one item in content is English if there are multiple items.
|
||||
if (content.size() > 1) {
|
||||
bool found = false;
|
||||
for (std::vector<boss::MessageContent>::const_iterator it=content.begin(), endit=content.end(); it != endit; ++it) {
|
||||
if (it->Language() == boss::LANG_ENG)
|
||||
found = true;
|
||||
}
|
||||
if (!found)
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
std::string condition;
|
||||
if (node["condition"])
|
||||
condition = node["condition"].as<std::string>();
|
||||
|
||||
rhs = boss::Message(typeNo, content, condition, langNo);
|
||||
rhs = boss::Message(typeNo, content, condition);
|
||||
return true;
|
||||
}
|
||||
};
|
||||
@@ -383,6 +414,11 @@ namespace boss {
|
||||
//Eval's regex and exact paths. Check for files and ghosted plugins.
|
||||
void CheckFile(bool& result, const std::string& file) {
|
||||
|
||||
if (file == "BOSS") {
|
||||
result = true;
|
||||
return;
|
||||
}
|
||||
|
||||
if (!IsSafePath(file))
|
||||
throw boss::error(boss::ERROR_INVALID_ARGS, "The file path \"" + file + "\" is invalid.");
|
||||
|
||||
@@ -458,6 +494,8 @@ namespace boss {
|
||||
if (it != game->crcCache.end())
|
||||
crc = it->second;
|
||||
else {
|
||||
if (file == "BOSS")
|
||||
crc = GetCrc32(boost::filesystem::absolute("BOSS.exe"));
|
||||
if (boost::filesystem::exists(game->DataPath() / file))
|
||||
crc = GetCrc32(game->DataPath() / file);
|
||||
else if (IsPlugin(file) && boost::filesystem::exists(game->DataPath() / (file + ".ghost")))
|
||||
@@ -483,7 +521,11 @@ namespace boss {
|
||||
}
|
||||
|
||||
Version givenVersion = Version(version);
|
||||
Version trueVersion = Version(game->DataPath() / file);
|
||||
Version trueVersion;
|
||||
if (file == "BOSS")
|
||||
trueVersion = Version(boost::filesystem::absolute("BOSS.exe"));
|
||||
else
|
||||
trueVersion = Version(game->DataPath() / file);
|
||||
|
||||
if ( (comparator == "==" && trueVersion != givenVersion)
|
||||
|| (comparator == "!=" && trueVersion == givenVersion)
|
||||
@@ -495,7 +537,10 @@ namespace boss {
|
||||
}
|
||||
|
||||
void CheckActive(bool& result, const std::string& file) {
|
||||
result = game->IsActive(file);
|
||||
if (file == "BOSS")
|
||||
result = false;
|
||||
else
|
||||
result = game->IsActive(file);
|
||||
}
|
||||
|
||||
void SyntaxError(Iterator const& /*first*/, Iterator const& last, Iterator const& errorpos, boost::spirit::info const& what) {
|
||||
|
||||
Reference in New Issue
Block a user