2016-03-04 23:02:44 +00:00
|
|
|
#include "hecl/CVarManager.hpp"
|
|
|
|
#include "hecl/CVar.hpp"
|
2018-01-11 09:35:27 +00:00
|
|
|
#include "hecl/Console.hpp"
|
2016-03-04 23:02:44 +00:00
|
|
|
#include <athena/FileWriter.hpp>
|
|
|
|
#include <athena/Utility.hpp>
|
|
|
|
#include <hecl/Runtime.hpp>
|
2015-12-02 21:11:10 +00:00
|
|
|
#include <memory>
|
|
|
|
|
2016-03-04 23:02:44 +00:00
|
|
|
namespace hecl
|
2015-12-02 21:11:10 +00:00
|
|
|
{
|
|
|
|
|
|
|
|
CVar* com_developer = nullptr;
|
|
|
|
CVar* com_configfile = nullptr;
|
|
|
|
CVar* com_enableCheats = nullptr;
|
|
|
|
|
2015-12-04 01:43:29 +00:00
|
|
|
CVarManager* CVarManager::m_instance = nullptr;
|
|
|
|
|
2018-01-14 07:37:00 +00:00
|
|
|
static logvisor::Module CVarLog("CVarManager");
|
2016-03-04 23:02:44 +00:00
|
|
|
CVarManager::CVarManager(hecl::Runtime::FileStoreManager& store, bool useBinary)
|
2015-12-02 21:11:10 +00:00
|
|
|
: m_store(store),
|
|
|
|
m_useBinary(useBinary)
|
|
|
|
{
|
2015-12-04 01:43:29 +00:00
|
|
|
m_instance = this;
|
2015-12-02 21:11:10 +00:00
|
|
|
com_configfile = newCVar("config", "File to store configuration", std::string("config"), CVar::EFlags::System);
|
2018-01-14 07:37:00 +00:00
|
|
|
com_developer = newCVar("developer", "Enables developer mode", false, (CVar::EFlags::System | CVar::EFlags::ReadOnly | CVar::EFlags::InternalArchivable));
|
2015-12-02 21:11:10 +00:00
|
|
|
com_enableCheats = newCVar("iamaweiner", "Enable cheats", false, (CVar::EFlags::System | CVar::EFlags::ReadOnly | CVar::EFlags::Hidden));
|
|
|
|
}
|
|
|
|
|
|
|
|
CVarManager::~CVarManager()
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
void CVarManager::update()
|
|
|
|
{
|
|
|
|
for (const std::pair<std::string, CVar*>& pair : m_cvars)
|
|
|
|
if (pair.second->isModified())
|
|
|
|
{
|
|
|
|
pair.second->dispatch();
|
|
|
|
pair.second->clearModified();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
bool CVarManager::registerCVar(CVar* cvar)
|
|
|
|
{
|
2017-11-13 06:13:53 +00:00
|
|
|
std::string tmp(cvar->name());
|
2016-03-04 23:02:44 +00:00
|
|
|
athena::utility::tolower(tmp);
|
2015-12-02 21:11:10 +00:00
|
|
|
if (m_cvars.find(tmp) != m_cvars.end())
|
|
|
|
return false;
|
|
|
|
|
|
|
|
m_cvars[tmp] = cvar;
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2017-11-13 06:13:53 +00:00
|
|
|
CVar* CVarManager::findCVar(std::string_view name)
|
2015-12-02 21:11:10 +00:00
|
|
|
{
|
2017-11-13 06:13:53 +00:00
|
|
|
std::string lower(name);
|
|
|
|
athena::utility::tolower(lower);
|
|
|
|
auto search = m_cvars.find(lower);
|
|
|
|
if (search == m_cvars.end())
|
2015-12-02 21:11:10 +00:00
|
|
|
return nullptr;
|
|
|
|
|
2017-11-13 06:13:53 +00:00
|
|
|
return search->second;
|
2015-12-02 21:11:10 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
std::vector<CVar*> CVarManager::archivedCVars() const
|
|
|
|
{
|
|
|
|
std::vector<CVar*> ret;
|
|
|
|
for (const std::pair<std::string, CVar*>& pair : m_cvars)
|
|
|
|
if (pair.second->isArchive())
|
|
|
|
ret.push_back(pair.second);
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
std::vector<CVar*> CVarManager::cvars() const
|
|
|
|
{
|
|
|
|
std::vector<CVar*> ret;
|
|
|
|
for (const std::pair<std::string, CVar*>& pair : m_cvars)
|
|
|
|
ret.push_back(pair.second);
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
void CVarManager::deserialize(CVar* cvar)
|
|
|
|
{
|
2018-01-14 07:37:00 +00:00
|
|
|
if (!cvar || (!cvar->isArchive() && !cvar->isInternalArchivable()))
|
2015-12-02 21:11:10 +00:00
|
|
|
return;
|
|
|
|
|
|
|
|
CVarContainer container;
|
|
|
|
#if _WIN32
|
2017-11-14 03:34:05 +00:00
|
|
|
hecl::SystemString filename = hecl::SystemString(m_store.getStoreRoot()) + _S('/') + com_configfile->toWideLiteral();
|
2015-12-02 21:11:10 +00:00
|
|
|
#else
|
2017-11-13 06:13:53 +00:00
|
|
|
hecl::SystemString filename = hecl::SystemString(m_store.getStoreRoot()) + _S('/') + com_configfile->toLiteral();
|
2015-12-02 21:11:10 +00:00
|
|
|
#endif
|
2016-03-04 23:02:44 +00:00
|
|
|
hecl::Sstat st;
|
2015-12-02 21:11:10 +00:00
|
|
|
|
|
|
|
if (m_useBinary)
|
|
|
|
{
|
|
|
|
filename += _S(".bin");
|
2016-03-04 23:02:44 +00:00
|
|
|
if (hecl::Stat(filename.c_str(), &st) || !S_ISREG(st.st_mode))
|
2015-12-02 21:11:10 +00:00
|
|
|
return;
|
2016-03-04 23:02:44 +00:00
|
|
|
athena::io::FileReader reader(filename);
|
2015-12-02 21:11:10 +00:00
|
|
|
if (reader.isOpen())
|
|
|
|
container.read(reader);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
filename += _S(".yaml");
|
2016-03-04 23:02:44 +00:00
|
|
|
if (hecl::Stat(filename.c_str(), &st) || !S_ISREG(st.st_mode))
|
2015-12-02 21:11:10 +00:00
|
|
|
return;
|
2016-08-22 03:46:45 +00:00
|
|
|
athena::io::FileReader reader(filename);
|
|
|
|
if (reader.isOpen())
|
|
|
|
container.fromYAMLStream(reader);
|
2015-12-02 21:11:10 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if (container.cvars.size() > 0)
|
|
|
|
{
|
|
|
|
auto serialized = std::find_if(container.cvars.begin(), container.cvars.end(), [&cvar](const DNACVAR::CVar& c) -> bool
|
|
|
|
{ return c.m_name == cvar->name(); });
|
|
|
|
|
|
|
|
if (serialized != container.cvars.end())
|
|
|
|
{
|
|
|
|
DNACVAR::CVar& tmp = *serialized;
|
|
|
|
|
2015-12-03 04:08:14 +00:00
|
|
|
if (cvar->m_value != tmp.m_value)
|
2018-01-14 07:37:00 +00:00
|
|
|
{
|
|
|
|
cvar->unlock();
|
|
|
|
cvar->fromLiteralToType(tmp.m_value, true);
|
|
|
|
cvar->m_wasDeserialized = true;
|
|
|
|
cvar->lock();
|
|
|
|
}
|
2015-12-02 21:11:10 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void CVarManager::serialize()
|
|
|
|
{
|
|
|
|
CVarContainer container;
|
|
|
|
for (const std::pair<std::string, CVar*>& pair : m_cvars)
|
2018-01-14 07:37:00 +00:00
|
|
|
if (pair.second->isArchive() || (pair.second->isInternalArchivable() && pair.second->wasDeserialized() && !pair.second->hasDefaultValue()))
|
2015-12-02 21:11:10 +00:00
|
|
|
{
|
|
|
|
CVar tmp = *pair.second;
|
|
|
|
container.cvars.push_back(tmp);
|
|
|
|
}
|
|
|
|
|
2018-01-14 07:37:00 +00:00
|
|
|
container.cvarCount = atUint32(container.cvars.size());
|
2015-12-02 21:11:10 +00:00
|
|
|
|
|
|
|
#if _WIN32
|
2017-11-13 06:13:53 +00:00
|
|
|
hecl::SystemString filename = hecl::SystemString(m_store.getStoreRoot()) + _S('/') + com_configfile->toWideLiteral();
|
2015-12-02 21:11:10 +00:00
|
|
|
#else
|
2017-11-13 06:13:53 +00:00
|
|
|
hecl::SystemString filename = hecl::SystemString(m_store.getStoreRoot()) + _S('/') + com_configfile->toLiteral();
|
2015-12-02 21:11:10 +00:00
|
|
|
#endif
|
|
|
|
|
|
|
|
if (m_useBinary)
|
|
|
|
{
|
|
|
|
filename += _S(".bin");
|
2016-03-04 23:02:44 +00:00
|
|
|
athena::io::FileWriter writer(filename);
|
2015-12-02 21:11:10 +00:00
|
|
|
if (writer.isOpen())
|
|
|
|
container.write(writer);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
filename += _S(".yaml");
|
2016-08-22 03:46:45 +00:00
|
|
|
athena::io::FileWriter writer(filename);
|
|
|
|
if (writer.isOpen())
|
|
|
|
container.toYAMLStream(writer);
|
2015-12-02 21:11:10 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-12-04 01:43:29 +00:00
|
|
|
CVarManager* CVarManager::instance()
|
|
|
|
{
|
|
|
|
return m_instance;
|
|
|
|
}
|
|
|
|
|
2018-01-14 07:37:00 +00:00
|
|
|
void CVarManager::list(Console* con, const std::vector<std::string>& /*args*/)
|
2018-01-11 09:35:27 +00:00
|
|
|
{
|
2018-01-14 02:39:32 +00:00
|
|
|
for (const auto& cvar : m_cvars)
|
|
|
|
{
|
|
|
|
if (!cvar.second->isHidden())
|
|
|
|
con->report(Console::Level::Info, "%s: %s", cvar.first.c_str(), cvar.second->help().c_str());
|
|
|
|
}
|
2018-01-11 09:35:27 +00:00
|
|
|
}
|
|
|
|
|
2018-01-11 16:26:33 +00:00
|
|
|
void CVarManager::setCVar(Console* con, const std::vector<std::string> &args)
|
2018-01-11 09:35:27 +00:00
|
|
|
{
|
2018-01-14 02:39:32 +00:00
|
|
|
if (args.size() < 2)
|
|
|
|
{
|
|
|
|
con->report(Console::Level::Info, "Usage setCvar <cvar> <value>");
|
|
|
|
return;
|
|
|
|
}
|
2018-01-11 09:35:27 +00:00
|
|
|
|
2018-01-14 02:39:32 +00:00
|
|
|
std::string cvName = args[0];
|
|
|
|
athena::utility::tolower(cvName);
|
|
|
|
if (m_cvars.find(cvName) == m_cvars.end())
|
|
|
|
{
|
|
|
|
con->report(Console::Level::Error, "CVar '%s' does not exist", args[0].c_str());
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
CVar* cv = m_cvars[cvName];
|
|
|
|
std::string value = args[1];
|
|
|
|
auto it = args.begin() + 2;
|
|
|
|
for (; it != args.end(); ++it)
|
|
|
|
value += " " + *it;
|
|
|
|
|
|
|
|
if (!cv->fromLiteralToType(value))
|
|
|
|
con->report(Console::Level::Warning, "Unable to cvar '%s' to value '%s'", args[0].c_str(), value.c_str());
|
2018-01-11 09:35:27 +00:00
|
|
|
}
|
|
|
|
|
2018-01-11 16:26:33 +00:00
|
|
|
void CVarManager::getCVar(Console* con, const std::vector<std::string> &args)
|
2018-01-11 09:35:27 +00:00
|
|
|
{
|
2018-01-14 02:39:32 +00:00
|
|
|
if (args.empty())
|
|
|
|
{
|
|
|
|
con->report(Console::Level::Info, "Usage getCVar <cvar>");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
std::string cvName = args[0];
|
|
|
|
athena::utility::tolower(cvName);
|
|
|
|
if (m_cvars.find(cvName) == m_cvars.end())
|
|
|
|
{
|
|
|
|
con->report(Console::Level::Error, "CVar '%s' does not exist", args[0].c_str());
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
const CVar* cv = m_cvars[cvName];
|
|
|
|
con->report(Console::Level::Info, "'%s' = '%s'", cv->name().data(), cv->value().c_str());
|
2018-01-11 09:35:27 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
bool CVarManager::restartRequired() const
|
|
|
|
{
|
|
|
|
for (const auto& cv : m_cvars)
|
|
|
|
{
|
|
|
|
if (cv.second->isModified() && cv.second->modificationRequiresRestart())
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2015-12-02 21:11:10 +00:00
|
|
|
bool CVarManager::suppressDeveloper()
|
|
|
|
{
|
|
|
|
bool oldDeveloper = com_developer->toBoolean();
|
|
|
|
CVarUnlocker unlock(com_developer);
|
|
|
|
com_developer->fromBoolean(false);
|
|
|
|
|
|
|
|
return oldDeveloper;
|
|
|
|
}
|
|
|
|
|
|
|
|
void CVarManager::restoreDeveloper(bool oldDeveloper)
|
|
|
|
{
|
|
|
|
CVarUnlocker unlock(com_developer);
|
|
|
|
com_developer->fromBoolean(oldDeveloper);
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|