mirror of
https://github.com/edo9300/edopro
synced 2026-08-23 22:26:05 -04:00
294 lines
7.3 KiB
C++
294 lines
7.3 KiB
C++
#include <IrrCompileConfig.h>
|
|
#include <path.h>
|
|
#include "game_config.h"
|
|
#include "bufferio.h"
|
|
#include "porting.h"
|
|
#include "utils.h"
|
|
#include "config.h"
|
|
#include "logging.h"
|
|
#include "file_stream.h"
|
|
#include "fmt.h"
|
|
|
|
namespace ygo {
|
|
|
|
GameConfig::GameConfig() {
|
|
#if EDOPRO_ANDROID
|
|
Load(epro::format("{}/system.conf", porting::internal_storage));
|
|
#endif
|
|
Load(EPRO_TEXT("./config/system.conf"));
|
|
if(configs.empty()) {
|
|
{
|
|
FileStream conf_file{ EPRO_TEXT("./config/configs.json"), FileStream::in };
|
|
if(!conf_file.fail()) {
|
|
try {
|
|
conf_file >> configs;
|
|
}
|
|
catch(const std::exception& e) {
|
|
ErrorLog("Exception occurred while loading configs.json: {}", e.what());
|
|
//throw(e);
|
|
}
|
|
}
|
|
}
|
|
{
|
|
FileStream user_conf_file{ EPRO_TEXT("./config/user_configs.json"), FileStream::in };
|
|
if(!user_conf_file.fail()) {
|
|
try {
|
|
user_conf_file >> user_configs;
|
|
}
|
|
catch(const std::exception& e) {
|
|
ErrorLog("Exception occurred while loading user_configs.json: {}", e.what());
|
|
//throw(e);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
template<typename T, typename tag = T>
|
|
T parseOption(std::string& value) {
|
|
if constexpr(std::is_unsigned_v<T>) {
|
|
return static_cast<T>(std::stoul(value));
|
|
} else {
|
|
return static_cast<T>(std::stoi(value));
|
|
}
|
|
}
|
|
|
|
template<>
|
|
uint64_t parseOption<uint64_t>(std::string& value) {
|
|
return static_cast<uint64_t>(std::stoull(value));
|
|
}
|
|
|
|
template<>
|
|
int64_t parseOption<int64_t>(std::string& value) {
|
|
return static_cast<int64_t>(std::stoll(value));
|
|
}
|
|
|
|
template<>
|
|
bool parseOption<bool>(std::string& value) {
|
|
return !!std::stoi(value);
|
|
}
|
|
|
|
template<>
|
|
float parseOption<float>(std::string& value) {
|
|
return std::stof(value);
|
|
}
|
|
|
|
template<>
|
|
std::string parseOption(std::string& value) {
|
|
return value;
|
|
}
|
|
|
|
template<>
|
|
std::wstring parseOption(std::string& value) {
|
|
return BufferIO::DecodeUTF8(value);
|
|
}
|
|
|
|
template<>
|
|
irr::video::E_DRIVER_TYPE parseOption<irr::video::E_DRIVER_TYPE>(std::string& value) {
|
|
Utils::ToUpperNoAccentsSelf(value);
|
|
#if !EDOPRO_ANDROID
|
|
if(value == "OPENGL")
|
|
return irr::video::EDT_OPENGL;
|
|
#if EDOPRO_WINDOWS
|
|
if(value == "D3D9")
|
|
return irr::video::EDT_DIRECT3D9;
|
|
#if (IRRLICHT_VERSION_MAJOR==1 && IRRLICHT_VERSION_MINOR==9)
|
|
if(value == "D3D9ON12")
|
|
return irr::video::EDT_DIRECT3D9_ON_12;
|
|
#endif
|
|
#endif
|
|
#endif
|
|
#if !EDOPRO_MACOS && (IRRLICHT_VERSION_MAJOR==1 && IRRLICHT_VERSION_MINOR==9)
|
|
if(value == "OGLES1")
|
|
return irr::video::EDT_OGLES1;
|
|
if(value == "OGLES2")
|
|
return irr::video::EDT_OGLES2;
|
|
#endif
|
|
return irr::video::EDT_COUNT;
|
|
}
|
|
|
|
template<>
|
|
ygo::GameConfig::TextFont parseOption<ygo::GameConfig::TextFont>(std::string& value) {
|
|
ygo::GameConfig::TextFont ret;
|
|
auto pos = value.find(' ');
|
|
if(pos == std::string::npos) {
|
|
ret.font = Utils::ToPathString(value);
|
|
return ret;
|
|
}
|
|
ret.font = Utils::ToPathString(value.substr(0, pos));
|
|
ret.size = static_cast<uint8_t>(std::stoi(value.substr(pos)));
|
|
return ret;
|
|
}
|
|
|
|
template<>
|
|
ygo::GameConfig::FallbackFonts parseOption<ygo::GameConfig::FallbackFonts>(std::string& value) {
|
|
ygo::GameConfig::FallbackFonts ret;
|
|
#ifdef YGOPRO_USE_BUNDLED_FONT
|
|
bool listed_bundled = false;
|
|
#endif
|
|
for(auto& font : Utils::TokenizeString<std::string>(value, '"')) {
|
|
if(font.find_first_not_of(' ') == std::string::npos)
|
|
continue;
|
|
const auto parsed_font = parseOption<GameConfig::TextFont>(font);
|
|
if(parsed_font.font == EPRO_TEXT("bundled"))
|
|
#ifdef YGOPRO_USE_BUNDLED_FONT
|
|
listed_bundled = true;
|
|
#else
|
|
continue;
|
|
#endif
|
|
ret.push_back(std::move(parsed_font));
|
|
}
|
|
|
|
#ifdef YGOPRO_USE_BUNDLED_FONT
|
|
if(!listed_bundled)
|
|
ret.emplace_back(ygo::GameConfig::TextFont{ { EPRO_TEXT("bundled") }, 12 });
|
|
#endif
|
|
return ret;
|
|
}
|
|
|
|
template<>
|
|
int parseOption<int, ygo::GameConfig::MaxFPSConfig>(std::string& value) {
|
|
int val = static_cast<int32_t>(std::stol(value));
|
|
if(val < 0 && val != -1)
|
|
val = static_cast<uint32_t>(std::stoul(value));
|
|
return val;
|
|
}
|
|
|
|
template<>
|
|
int parseOption<int, ygo::GameConfig::MusicConfig>(std::string& value) {
|
|
return std::min(std::max(std::stoi(value), 0), 100);
|
|
}
|
|
|
|
template<>
|
|
ygo::SoundManager::BACKEND parseOption<ygo::SoundManager::BACKEND>(std::string& value) {
|
|
Utils::ToUpperNoAccentsSelf(value);
|
|
if(value == "IRRKLANG")
|
|
return SoundManager::IRRKLANG;
|
|
else if(value == "SDL")
|
|
return SoundManager::SDL;
|
|
else if(value == "SDL3")
|
|
return SoundManager::SDL3;
|
|
else if(value == "SFML")
|
|
return SoundManager::SFML;
|
|
else if(value == "MINIAUDIO")
|
|
return SoundManager::MINIAUDIO;
|
|
else if(value == "NONE")
|
|
return SoundManager::NONE;
|
|
else
|
|
return SoundManager::DEFAULT;
|
|
}
|
|
|
|
template<>
|
|
uint8_t parseOption<uint8_t, ygo::GameConfig::BoolMaybeUndefined>(std::string& value) {
|
|
return std::min<uint8_t>(static_cast<uint8_t>(std::stoul(value)), 2);
|
|
}
|
|
|
|
template<typename T>
|
|
std::string serializeOption(const T& value) {
|
|
return epro::to_string(value);
|
|
}
|
|
|
|
template<>
|
|
std::string serializeOption(const uint8_t& value) {
|
|
return epro::to_string((int)value);
|
|
}
|
|
|
|
template<>
|
|
std::string serializeOption(const float& value) {
|
|
return std::to_string(value);
|
|
}
|
|
|
|
template<>
|
|
std::string serializeOption(const bool& value) {
|
|
return epro::to_string((int)value);
|
|
}
|
|
|
|
template<>
|
|
std::string serializeOption<std::wstring>(const std::wstring& value) {
|
|
return BufferIO::EncodeUTF8(value);
|
|
}
|
|
|
|
template<>
|
|
std::string serializeOption(const ygo::GameConfig::TextFont& value) {
|
|
return epro::format("{} {:d}", Utils::ToUTF8IfNeeded(value.font), value.size);
|
|
}
|
|
|
|
template<>
|
|
std::string serializeOption(const ygo::GameConfig::FallbackFonts& value) {
|
|
std::string res;
|
|
for(const auto& font : value) {
|
|
res.append(1, '"').append(serializeOption(font)).append("\" ");
|
|
}
|
|
if(!res.empty())
|
|
res.pop_back();
|
|
return res;
|
|
}
|
|
|
|
template<>
|
|
std::string serializeOption(const irr::video::E_DRIVER_TYPE& driver) {
|
|
switch(driver) {
|
|
#if !EDOPRO_ANDROID
|
|
case irr::video::EDT_OPENGL:
|
|
return "opengl";
|
|
#if EDOPRO_WINDOWS
|
|
case irr::video::EDT_DIRECT3D9:
|
|
return "d3d9";
|
|
#if (IRRLICHT_VERSION_MAJOR==1 && IRRLICHT_VERSION_MINOR==9)
|
|
case irr::video::EDT_DIRECT3D9_ON_12:
|
|
return "d3d9on12";
|
|
#endif
|
|
#endif
|
|
#endif
|
|
#if !EDOPRO_MACOS && (IRRLICHT_VERSION_MAJOR==1 && IRRLICHT_VERSION_MINOR==9)
|
|
case irr::video::EDT_OGLES1:
|
|
return "ogles1";
|
|
case irr::video::EDT_OGLES2:
|
|
return "ogles2";
|
|
#endif
|
|
case irr::video::EDT_COUNT:
|
|
return "default";
|
|
default:
|
|
return "";
|
|
}
|
|
}
|
|
|
|
bool GameConfig::Load(const epro::path_stringview filename) {
|
|
FileStream conf_file{ filename.data(), FileStream::in };
|
|
if(conf_file.fail())
|
|
return false;
|
|
std::string str;
|
|
while (std::getline(conf_file, str)) {
|
|
auto pos = str.find('\r');
|
|
if(str.size() && pos != std::string::npos)
|
|
str.erase(pos);
|
|
if (str.empty() || str.at(0) == '#') {
|
|
continue;
|
|
}
|
|
pos = str.find('=');
|
|
if (pos == std::string::npos)
|
|
continue;
|
|
auto type = str.substr(0, pos - 1);
|
|
str.erase(0, pos + 2);
|
|
try {
|
|
#define OPTION_ALIASED_TAGGED(_type, tag, name, alias, ...) if(type == #alias){name=parseOption<_type,tag>(str); continue;}
|
|
#include "game_config.inl"
|
|
#undef OPTION_ALIASED_TAGGED
|
|
}
|
|
catch (...) {}
|
|
}
|
|
return true;
|
|
}
|
|
|
|
bool GameConfig::Save(const epro::path_stringview filename) {
|
|
FileStream conf_file{ filename.data(), FileStream::out };
|
|
if(conf_file.fail())
|
|
return false;
|
|
conf_file << "# Project Ignis: EDOPro system.conf\n";
|
|
conf_file << "# Overwritten on normal game exit\n";
|
|
#define OPTION_ALIASED_TAGGED(_type, tag, name, alias, ...) conf_file << #alias " = " << serializeOption(name) << "\n";
|
|
#include "game_config.inl"
|
|
#undef OPTION_ALIASED_TAGGED
|
|
return true;
|
|
}
|
|
|
|
}
|