Merge pull request #2 from OpenMW/master

Add recent OpenMW commits by AnyOldName3
This commit is contained in:
David Cernat 2016-07-20 02:58:57 +03:00 committed by GitHub
commit 360eec30a0
5 changed files with 271 additions and 35 deletions

View file

@ -22,6 +22,7 @@ Programmers
Alexander Nadeau (wareya) Alexander Nadeau (wareya)
Alexander Olofsson (Ace) Alexander Olofsson (Ace)
Allofich Allofich
AnyOldName3
Austin Salgat (Salgat) Austin Salgat (Salgat)
Artem Kotsynyak (greye) Artem Kotsynyak (greye)
artemutin artemutin

View file

@ -79,19 +79,19 @@ bool parseOptions (int argc, char** argv, OMW::Engine& engine, Files::Configurat
("data", bpo::value<Files::PathContainer>()->default_value(Files::PathContainer(), "data") ("data", bpo::value<Files::PathContainer>()->default_value(Files::PathContainer(), "data")
->multitoken()->composing(), "set data directories (later directories have higher priority)") ->multitoken()->composing(), "set data directories (later directories have higher priority)")
("data-local", bpo::value<std::string>()->default_value(""), ("data-local", bpo::value<Files::EscapeHashString>()->default_value(""),
"set local data directory (highest priority)") "set local data directory (highest priority)")
("fallback-archive", bpo::value<StringsVector>()->default_value(StringsVector(), "fallback-archive") ("fallback-archive", bpo::value<Files::EscapeStringVector>()->default_value(Files::EscapeStringVector(), "fallback-archive")
->multitoken(), "set fallback BSA archives (later archives have higher priority)") ->multitoken(), "set fallback BSA archives (later archives have higher priority)")
("resources", bpo::value<std::string>()->default_value("resources"), ("resources", bpo::value<Files::EscapeHashString>()->default_value("resources"),
"set resources directory") "set resources directory")
("start", bpo::value<std::string>()->default_value(""), ("start", bpo::value<Files::EscapeHashString>()->default_value(""),
"set initial cell") "set initial cell")
("content", bpo::value<StringsVector>()->default_value(StringsVector(), "") ("content", bpo::value<Files::EscapeStringVector>()->default_value(Files::EscapeStringVector(), "")
->multitoken(), "content file(s): esm/esp, or omwgame/omwaddon") ->multitoken(), "content file(s): esm/esp, or omwgame/omwaddon")
("no-sound", bpo::value<bool>()->implicit_value(true) ("no-sound", bpo::value<bool>()->implicit_value(true)
@ -109,7 +109,7 @@ bool parseOptions (int argc, char** argv, OMW::Engine& engine, Files::Configurat
("script-console", bpo::value<bool>()->implicit_value(true) ("script-console", bpo::value<bool>()->implicit_value(true)
->default_value(false), "enable console-only script functionality") ->default_value(false), "enable console-only script functionality")
("script-run", bpo::value<std::string>()->default_value(""), ("script-run", bpo::value<Files::EscapeHashString>()->default_value(""),
"select a file containing a list of console commands that is executed on startup") "select a file containing a list of console commands that is executed on startup")
("script-warn", bpo::value<int>()->implicit_value (1) ("script-warn", bpo::value<int>()->implicit_value (1)
@ -119,13 +119,13 @@ bool parseOptions (int argc, char** argv, OMW::Engine& engine, Files::Configurat
"\t1 - show warning but consider script as correctly compiled anyway\n" "\t1 - show warning but consider script as correctly compiled anyway\n"
"\t2 - treat warnings as errors") "\t2 - treat warnings as errors")
("script-blacklist", bpo::value<StringsVector>()->default_value(StringsVector(), "") ("script-blacklist", bpo::value<Files::EscapeStringVector>()->default_value(Files::EscapeStringVector(), "")
->multitoken(), "ignore the specified script (if the use of the blacklist is enabled)") ->multitoken(), "ignore the specified script (if the use of the blacklist is enabled)")
("script-blacklist-use", bpo::value<bool>()->implicit_value(true) ("script-blacklist-use", bpo::value<bool>()->implicit_value(true)
->default_value(true), "enable script blacklisting") ->default_value(true), "enable script blacklisting")
("load-savegame", bpo::value<std::string>()->default_value(""), ("load-savegame", bpo::value<Files::EscapeHashString>()->default_value(""),
"load a save game file on game startup (specify an absolute filename or a filename relative to the current working directory)") "load a save game file on game startup (specify an absolute filename or a filename relative to the current working directory)")
("skip-menu", bpo::value<bool>()->implicit_value(true) ("skip-menu", bpo::value<bool>()->implicit_value(true)
@ -137,7 +137,7 @@ bool parseOptions (int argc, char** argv, OMW::Engine& engine, Files::Configurat
("fs-strict", bpo::value<bool>()->implicit_value(true) ("fs-strict", bpo::value<bool>()->implicit_value(true)
->default_value(false), "strict file system handling (no case folding)") ->default_value(false), "strict file system handling (no case folding)")
( "encoding", bpo::value<std::string>()-> ("encoding", bpo::value<Files::EscapeHashString>()->
default_value("win1252"), default_value("win1252"),
"Character encoding used in OpenMW game messages:\n" "Character encoding used in OpenMW game messages:\n"
"\n\twin1250 - Central and Eastern European such as Polish, Czech, Slovak, Hungarian, Slovene, Bosnian, Croatian, Serbian (Latin script), Romanian and Albanian languages\n" "\n\twin1250 - Central and Eastern European such as Polish, Czech, Slovak, Hungarian, Slovene, Bosnian, Croatian, Serbian (Latin script), Romanian and Albanian languages\n"
@ -173,20 +173,20 @@ bool parseOptions (int argc, char** argv, OMW::Engine& engine, Files::Configurat
{ {
cfgMgr.readConfiguration(variables, desc, true); cfgMgr.readConfiguration(variables, desc, true);
Version::Version v = Version::getOpenmwVersion(variables["resources"].as<std::string>()); Version::Version v = Version::getOpenmwVersion(variables["resources"].as<Files::EscapeHashString>().toStdString());
std::cout << v.describe() << std::endl; std::cout << v.describe() << std::endl;
return false; return false;
} }
cfgMgr.readConfiguration(variables, desc); cfgMgr.readConfiguration(variables, desc);
Version::Version v = Version::getOpenmwVersion(variables["resources"].as<std::string>()); Version::Version v = Version::getOpenmwVersion(variables["resources"].as<Files::EscapeHashString>().toStdString());
std::cout << v.describe() << std::endl; std::cout << v.describe() << std::endl;
engine.setGrabMouse(!variables.count("no-grab")); engine.setGrabMouse(!variables.count("no-grab"));
// Font encoding settings // Font encoding settings
std::string encoding(variables["encoding"].as<std::string>()); std::string encoding(variables["encoding"].as<Files::EscapeHashString>().toStdString());
std::cout << ToUTF8::encodingUsingMessage(encoding) << std::endl; std::cout << ToUTF8::encodingUsingMessage(encoding) << std::endl;
engine.setEncoding(ToUTF8::calculateEncoding(encoding)); engine.setEncoding(ToUTF8::calculateEncoding(encoding));
@ -195,7 +195,7 @@ bool parseOptions (int argc, char** argv, OMW::Engine& engine, Files::Configurat
Files::PathContainer dataDirs(variables["data"].as<Files::PathContainer>()); Files::PathContainer dataDirs(variables["data"].as<Files::PathContainer>());
std::string local(variables["data-local"].as<std::string>()); std::string local(variables["data-local"].as<Files::EscapeHashString>().toStdString());
if (!local.empty()) if (!local.empty())
{ {
dataDirs.push_back(Files::PathContainer::value_type(local)); dataDirs.push_back(Files::PathContainer::value_type(local));
@ -206,15 +206,15 @@ bool parseOptions (int argc, char** argv, OMW::Engine& engine, Files::Configurat
engine.setDataDirs(dataDirs); engine.setDataDirs(dataDirs);
// fallback archives // fallback archives
StringsVector archives = variables["fallback-archive"].as<StringsVector>(); StringsVector archives = variables["fallback-archive"].as<Files::EscapeStringVector>().toStdStringVector();
for (StringsVector::const_iterator it = archives.begin(); it != archives.end(); ++it) for (StringsVector::const_iterator it = archives.begin(); it != archives.end(); ++it)
{ {
engine.addArchive(*it); engine.addArchive(*it);
} }
engine.setResourceDir(variables["resources"].as<std::string>()); engine.setResourceDir(variables["resources"].as<Files::EscapeHashString>().toStdString());
StringsVector content = variables["content"].as<StringsVector>(); StringsVector content = variables["content"].as<Files::EscapeStringVector>().toStdStringVector();
if (content.empty()) if (content.empty())
{ {
std::cout << "No content file given (esm/esp, nor omwgame/omwaddon). Aborting..." << std::endl; std::cout << "No content file given (esm/esp, nor omwgame/omwaddon). Aborting..." << std::endl;
@ -229,7 +229,7 @@ bool parseOptions (int argc, char** argv, OMW::Engine& engine, Files::Configurat
} }
// startup-settings // startup-settings
engine.setCell(variables["start"].as<std::string>()); engine.setCell(variables["start"].as<Files::EscapeHashString>().toStdString());
engine.setSkipMenu (variables["skip-menu"].as<bool>(), variables["new-game"].as<bool>()); engine.setSkipMenu (variables["skip-menu"].as<bool>(), variables["new-game"].as<bool>());
if (!variables["skip-menu"].as<bool>() && variables["new-game"].as<bool>()) if (!variables["skip-menu"].as<bool>() && variables["new-game"].as<bool>())
std::cerr << "new-game used without skip-menu -> ignoring it" << std::endl; std::cerr << "new-game used without skip-menu -> ignoring it" << std::endl;
@ -239,11 +239,11 @@ bool parseOptions (int argc, char** argv, OMW::Engine& engine, Files::Configurat
engine.setCompileAllDialogue(variables["script-all-dialogue"].as<bool>()); engine.setCompileAllDialogue(variables["script-all-dialogue"].as<bool>());
engine.setScriptsVerbosity(variables["script-verbose"].as<bool>()); engine.setScriptsVerbosity(variables["script-verbose"].as<bool>());
engine.setScriptConsoleMode (variables["script-console"].as<bool>()); engine.setScriptConsoleMode (variables["script-console"].as<bool>());
engine.setStartupScript (variables["script-run"].as<std::string>()); engine.setStartupScript (variables["script-run"].as<Files::EscapeHashString>().toStdString());
engine.setWarningsMode (variables["script-warn"].as<int>()); engine.setWarningsMode (variables["script-warn"].as<int>());
engine.setScriptBlacklist (variables["script-blacklist"].as<StringsVector>()); engine.setScriptBlacklist (variables["script-blacklist"].as<Files::EscapeStringVector>().toStdStringVector());
engine.setScriptBlacklistUse (variables["script-blacklist-use"].as<bool>()); engine.setScriptBlacklistUse (variables["script-blacklist-use"].as<bool>());
engine.setSaveGameFile (variables["load-savegame"].as<std::string>()); engine.setSaveGameFile (variables["load-savegame"].as<Files::EscapeHashString>().toStdString());
// other settings // other settings
engine.setSoundUsage(!variables["no-sound"].as<bool>()); engine.setSoundUsage(!variables["no-sound"].as<bool>());

View file

@ -3,6 +3,8 @@
#include <boost/program_options.hpp> #include <boost/program_options.hpp>
#include <components/files/configurationmanager.hpp>
// Parses and validates a fallback map from boost program_options. // Parses and validates a fallback map from boost program_options.
// Note: for boost to pick up the validate function, you need to pull in the namespace e.g. // Note: for boost to pick up the validate function, you need to pull in the namespace e.g.
// by using namespace Fallback; // by using namespace Fallback;
@ -11,38 +13,59 @@ namespace Fallback
{ {
struct FallbackMap { struct FallbackMap {
std::map<std::string,std::string> mMap; std::map<std::string, std::string> mMap;
}; };
void validate(boost::any &v, std::vector<std::string> const &tokens, FallbackMap*, int) void validate(boost::any &v, std::vector<std::string> const &tokens, FallbackMap*, int)
{ {
if(v.empty()) if (v.empty())
{ {
v = boost::any(FallbackMap()); v = boost::any(FallbackMap());
} }
FallbackMap *map = boost::any_cast<FallbackMap>(&v); FallbackMap *map = boost::any_cast<FallbackMap>(&v);
for(std::vector<std::string>::const_iterator it=tokens.begin(); it != tokens.end(); ++it) for (std::vector<std::string>::const_iterator it = tokens.begin(); it != tokens.end(); ++it)
{ {
int sep = it->find(","); std::string temp = Files::EscapeHashString::processString(*it);
if(sep < 1 || sep == (int)it->length()-1) int sep = temp.find(",");
#if (BOOST_VERSION < 104200) if (sep < 1 || sep == (int)temp.length() - 1)
#if (BOOST_VERSION < 104200)
throw boost::program_options::validation_error("invalid value"); throw boost::program_options::validation_error("invalid value");
#else #else
throw boost::program_options::validation_error(boost::program_options::validation_error::invalid_option_value); throw boost::program_options::validation_error(boost::program_options::validation_error::invalid_option_value);
#endif #endif
std::string key(it->substr(0,sep)); std::string key(temp.substr(0, sep));
std::string value(it->substr(sep+1)); std::string value(temp.substr(sep + 1));
if(map->mMap.find(key) == map->mMap.end()) if (map->mMap.find(key) == map->mMap.end())
{ {
map->mMap.insert(std::make_pair (key,value)); map->mMap.insert(std::make_pair(key, value));
} }
} }
} }
}
namespace Files {
void validate(boost::any &v, const std::vector<std::string> &tokens, Files::EscapeHashString * eHS, int a)
{
boost::program_options::validators::check_first_occurrence(v);
if (v.empty())
v = boost::any(EscapeHashString(boost::program_options::validators::get_single_string(tokens)));
}
void validate(boost::any &v, const std::vector<std::string> &tokens, EscapeStringVector *, int)
{
if (v.empty())
v = boost::any(EscapeStringVector());
EscapeStringVector * eSV = boost::any_cast<EscapeStringVector>(&v);
for (std::vector<std::string>::const_iterator it = tokens.begin(); it != tokens.end(); ++it)
eSV->mVector.push_back(EscapeHashString(*it));
}
} }
#endif #endif

View file

@ -3,9 +3,11 @@
#include <string> #include <string>
#include <iostream> #include <iostream>
#include <algorithm> #include <algorithm>
#include <ctype.h>
#include <boost/bind.hpp> #include <boost/bind.hpp>
#include <boost/algorithm/string/erase.hpp> #include <boost/algorithm/string/erase.hpp>
#include <boost/algorithm/string/replace.hpp>
#include <boost/filesystem/fstream.hpp> #include <boost/filesystem/fstream.hpp>
/** /**
@ -139,8 +141,11 @@ bool ConfigurationManager::loadConfig(const boost::filesystem::path& path,
if (!mSilent) if (!mSilent)
std::cout << "Loading config file: " << cfgFile.string() << "... "; std::cout << "Loading config file: " << cfgFile.string() << "... ";
boost::filesystem::ifstream configFileStream(cfgFile); boost::filesystem::ifstream configFileStreamUnfiltered(cfgFile);
if (configFileStream.is_open()) boost::iostreams::filtering_istream configFileStream;
configFileStream.push(escape_hash_filter());
configFileStream.push(configFileStreamUnfiltered);
if (configFileStreamUnfiltered.is_open())
{ {
boost::program_options::store(boost::program_options::parse_config_file( boost::program_options::store(boost::program_options::parse_config_file(
configFileStream, description, true), variables); configFileStream, description, true), variables);
@ -159,6 +164,152 @@ bool ConfigurationManager::loadConfig(const boost::filesystem::path& path,
return false; return false;
} }
const int escape_hash_filter::sEscape = '@';
const int escape_hash_filter::sEscapeIdentifier = 'a';
const int escape_hash_filter::sHashIdentifier = 'h';
escape_hash_filter::escape_hash_filter() : mNext(), mSeenNonWhitespace(false), mFinishLine(false)
{
}
escape_hash_filter::~escape_hash_filter()
{
}
template <typename Source>
int escape_hash_filter::get(Source & src)
{
if (mNext.empty())
{
int character = boost::iostreams::get(src);
bool record = true;
if (character == boost::iostreams::WOULD_BLOCK)
{
mNext.push(character);
record = false;
}
else if (character == EOF)
{
mSeenNonWhitespace = false;
mFinishLine = false;
mNext.push(character);
}
else if (character == '\n')
{
mSeenNonWhitespace = false;
mFinishLine = false;
mNext.push(character);
}
else if (mFinishLine)
{
mNext.push(character);
}
else if (character == '#')
{
if (mSeenNonWhitespace)
{
mNext.push(sEscape);
mNext.push(sHashIdentifier);
}
else
{
//it's fine being interpreted by Boost as a comment, and so is anything afterwards
mNext.push(character);
mFinishLine = true;
}
}
else if (mPrevious == sEscape)
{
mNext.push(sEscape);
mNext.push(sEscapeIdentifier);
}
else
{
mNext.push(character);
}
if (!mSeenNonWhitespace && !isspace(character))
mSeenNonWhitespace = true;
if (record)
mPrevious = character;
}
int retval = mNext.front();
mNext.pop();
return retval;
}
std::string EscapeHashString::processString(const std::string & str)
{
std::string temp = boost::replace_all_copy<std::string>(str, std::string() + (char)escape_hash_filter::sEscape + (char)escape_hash_filter::sHashIdentifier, "#");
boost::replace_all(temp, std::string() + (char)escape_hash_filter::sEscape + (char)escape_hash_filter::sEscapeIdentifier, std::string((char) escape_hash_filter::sEscape, 1));
return temp;
}
EscapeHashString::EscapeHashString() : mData()
{
}
EscapeHashString::EscapeHashString(const std::string & str) : mData(EscapeHashString::processString(str))
{
}
EscapeHashString::EscapeHashString(const std::string & str, size_t pos, size_t len) : mData(EscapeHashString::processString(str), pos, len)
{
}
EscapeHashString::EscapeHashString(const char * s) : mData(EscapeHashString::processString(std::string(s)))
{
}
EscapeHashString::EscapeHashString(const char * s, size_t n) : mData(EscapeHashString::processString(std::string(s)), 0, n)
{
}
EscapeHashString::EscapeHashString(size_t n, char c) : mData(n, c)
{
}
template <class InputIterator>
EscapeHashString::EscapeHashString(InputIterator first, InputIterator last) : mData(EscapeHashString::processString(std::string(first, last)))
{
}
std::string EscapeHashString::toStdString() const
{
return std::string(mData);
}
std::istream & operator>> (std::istream & is, EscapeHashString & eHS)
{
std::string temp;
is >> temp;
eHS = EscapeHashString(temp);
return is;
}
std::ostream & operator<< (std::ostream & os, const EscapeHashString & eHS)
{
os << eHS.mData;
return os;
}
EscapeStringVector::EscapeStringVector() : mVector()
{
}
EscapeStringVector::~EscapeStringVector()
{
}
std::vector<std::string> EscapeStringVector::toStdStringVector() const
{
std::vector<std::string> temp = std::vector<std::string>();
for (std::vector<EscapeHashString>::const_iterator it = mVector.begin(); it != mVector.end(); ++it)
{
temp.push_back(it->toStdString());
}
return temp;
}
const boost::filesystem::path& ConfigurationManager::getGlobalPath() const const boost::filesystem::path& ConfigurationManager::getGlobalPath() const
{ {
return mFixedPath.getGlobalConfigPath(); return mFixedPath.getGlobalConfigPath();

View file

@ -2,8 +2,10 @@
#define COMPONENTS_FILES_CONFIGURATIONMANAGER_HPP #define COMPONENTS_FILES_CONFIGURATIONMANAGER_HPP
#include <map> #include <map>
#include <queue>
#include <boost/program_options.hpp> #include <boost/program_options.hpp>
#include <boost/iostreams/filtering_stream.hpp>
#include <components/files/fixedpath.hpp> #include <components/files/fixedpath.hpp>
#include <components/files/collections.hpp> #include <components/files/collections.hpp>
@ -63,6 +65,65 @@ struct ConfigurationManager
bool mSilent; bool mSilent;
}; };
/**
* \struct escape_hash_filter
*/
struct escape_hash_filter : public boost::iostreams::input_filter
{
static const int sEscape;
static const int sHashIdentifier;
static const int sEscapeIdentifier;
escape_hash_filter();
virtual ~escape_hash_filter();
template <typename Source> int get(Source & src);
private:
std::queue<int> mNext;
int mPrevious;
bool mSeenNonWhitespace;
bool mFinishLine;
};
/**
* \class EscapeHashString
*/
class EscapeHashString
{
private:
std::string mData;
public:
static std::string processString(const std::string & str);
EscapeHashString();
EscapeHashString(const std::string & str);
EscapeHashString(const std::string & str, size_t pos, size_t len = std::string::npos);
EscapeHashString(const char * s);
EscapeHashString(const char * s, size_t n);
EscapeHashString(size_t n, char c);
template <class InputIterator>
EscapeHashString(InputIterator first, InputIterator last);
std::string toStdString() const;
friend std::ostream & operator<< (std::ostream & os, const EscapeHashString & eHS);
};
std::istream & operator>> (std::istream & is, EscapeHashString & eHS);
struct EscapeStringVector
{
std::vector<Files::EscapeHashString> mVector;
EscapeStringVector();
virtual ~EscapeStringVector();
std::vector<std::string> toStdStringVector() const;
};
} /* namespace Cfg */ } /* namespace Cfg */
#endif /* COMPONENTS_FILES_CONFIGURATIONMANAGER_HPP */ #endif /* COMPONENTS_FILES_CONFIGURATIONMANAGER_HPP */