1
0
Fork 0
Univerxel/src/client/config.hpp

252 lines
11 KiB
C++

#pragma once
#include "core/utils/toml.hpp"
#include <glm/vec4.hpp>
#include <limits.h>
#include <iomanip>
#include "world/Universe.hpp"
#include "render/Renderer.hpp"
#include "render/Window.hpp"
#include "contouring/Abstract.hpp"
#include "control/Camera.hpp"
namespace config::client {
inline glm::vec4 fromHex(const std::string& str) {
std::array<int, 3> rgb = {UCHAR_MAX};
sscanf(str.c_str() + 1, "%02X%02X%02X", (unsigned int *)&rgb[0], (unsigned int *)&rgb[1], (unsigned int *)&rgb[2]);
return glm::vec4(rgb[0] * 1.f / UCHAR_MAX, rgb[1] * 1.f / UCHAR_MAX, rgb[2] * 1.f / UCHAR_MAX, 1);
}
inline std::string toHexa(const glm::vec4& rgb) {
std::ostringstream sstr;
sstr << '#' << std::hex << std::setw(2) << std::setfill('0') <<
static_cast<int>(rgb.x * UCHAR_MAX) << static_cast<int>(rgb.y * UCHAR_MAX) << static_cast<int>(rgb.z * UCHAR_MAX);
return sstr.str();
}
/// Client side configuration
struct options {
public:
options(toml::node_view<toml::node> config) {
assert(config["enabled"] && "probably a broken config file");
window.targetFPS = config["window"]["target_fps"].value_or(window.targetFPS);
window.sampling = config["window"]["sampling"].value_or(window.sampling);
window.fullscreen = config["window"]["fullscreen"].value_or(window.fullscreen);
renderer.inFlightFrames = config["window"]["parallel_frames"].value_or(renderer.inFlightFrames);
preferVulkan = config["render"]["prefer_vulkan"].value_or(preferVulkan);
renderer.textures = config["render"]["textures"].value_or(renderer.textures);
renderer.textureQuality = config["render"]["texture_quality"].value_or(renderer.textureQuality);
renderer.textureSharpness = config["render"]["texture_angular_quality"].value_or(renderer.textureSharpness);
renderer.voxel.pbr = config["render"]["pbr"].value_or(renderer.voxel.pbr);
renderer.voxel.planar = static_cast<render::Planar>(config["render"]["planar"].value_or(static_cast<int>(renderer.voxel.planar)));
renderer.voxel.stochastic = config["render"]["stochastic"].value_or(renderer.voxel.stochastic);
renderer.voxel.geometry = config["render"]["geometry"].value_or(renderer.voxel.geometry);
renderer.voxel.blend = config["render"]["blend"].value_or(renderer.voxel.blend);
renderer.voxel.fog = config["render"]["fog"].value_or(renderer.voxel.fog);
const std::string fog = config["render"]["fog_color"].value_or(std::string{"#000000"});
renderer.clear_color = fromHex(fog);
renderer.skybox = config["render"]["skybox"].value_or(renderer.skybox);
renderer.voxel.curvature = config["render"]["curvature"].value_or(renderer.voxel.curvature);
renderer.voxel.curv_depth = config["render"]["curvature_depth"].value_or(renderer.voxel.curv_depth);
renderer.voxel.transparency = config["render"]["transparency"].value_or(renderer.voxel.transparency);
culling = config["render"]["culling"].value_or(culling);
contouring = config["contouring"].value_or(std::string(""));
camera.far_dist = config["camera"]["far"].value_or(camera.far_dist);
camera.near_dist = config["camera"]["near"].value_or(camera.near_dist);
camera.fov = config["camera"]["fov"].value_or(camera.fov);
control.sensibility = config["control"]["sensibility"].value_or(control.sensibility);
control.speed = config["control"]["speed"].value_or(control.speed);
control.collide = config["control"]["collide"].value_or(control.collide);
world.loadDistance = config["world"]["load_distance"].value_or(world.loadDistance);
world.keepDistance = config["world"]["keep_distance"].value_or(world.keepDistance);
world.useAverages = config["world"]["use_averages"].value_or(world.useAverages);
world.trustMajorant = config["world"]["trust_majorant"].value_or(world.trustMajorant);
world.editPrediction = config["world"]["edit_prediction"].value_or(world.editPrediction);
world.editHandling = config["world"]["edit_handling"].value_or(world.editHandling);
world.movePrediction = config["world"]["move_prediction"].value_or(world.movePrediction);
world.moveCollision = config["world"]["move_collision"].value_or(world.moveCollision);
#ifndef LIGHT_CLIENT
const auto useLocal = config["connection"]["use_local"].value_or(true);
#else
const auto useLocal = false;
#endif
if(!useLocal) {
world::client::Universe::connection ct;
ct.host = config["connection"]["host"].value_or(ct.host);
ct.port = config["connection"]["port"].value_or(ct.port);
connection = ct;
}
editor.visible = config["editor"]["visible"].value_or(editor.visible);
editor.tool.shape = static_cast<world::action::Shape>(config["editor"]["tool"]["shape"].value_or(static_cast<int>(editor.tool.shape)));
editor.tool.radius = config["editor"]["tool"]["radius"].value_or(editor.tool.radius);
editor.tool.material = config["editor"]["tool"]["material"].value_or(editor.tool.material);
editor.tool.emptyAir = config["editor"]["tool"]["empty_air"].value_or(editor.tool.emptyAir);
console.visible = config["console"]["visible"].value_or(console.visible);
console.scroll = config["console"]["scroll"].value_or(console.scroll);
console.opacity = config["console"]["opacity"].value_or(console.opacity);
debugMenu.bar = config["debug_menu"]["bar"].value_or(debugMenu.bar);
debugMenu.render = config["debug_menu"]["render"].value_or(debugMenu.render);
debugMenu.world = config["debug_menu"]["world"].value_or(debugMenu.world);
debugMenu.contouring = config["debug_menu"]["contouring"].value_or(debugMenu.contouring);
debugMenu.controls = config["debug_menu"]["controls"].value_or(debugMenu.controls);
overlay.visible = config["overlay"]["visible"].value_or(overlay.visible);
overlay.corner = config["overlay"]["corner"].value_or(overlay.corner);
if (config["keys"].is_table()) {
for(auto entry: *config["keys"].as_table()) {
keys.emplace_back(std::stoi(entry.first), entry.second.value_or(-1));
}
}
}
toml::table save() {
auto config = toml::table();
config.insert_or_assign("enabled", true);
config.insert_or_assign("window", toml::table({
{"target_fps", window.targetFPS},
{"sampling", window.sampling},
{"fullscreen", window.fullscreen},
{"parallel_frames", renderer.inFlightFrames}
}));
config.insert_or_assign("render", toml::table({
{"prefer_vulkan", preferVulkan},
{"textures", renderer.textures},
{"texture_quality", renderer.textureQuality},
{"texture_angular_quality", renderer.textureSharpness},
{"pbr", renderer.voxel.pbr},
{"planar", static_cast<int>(renderer.voxel.planar)},
{"stochastic", renderer.voxel.stochastic},
{"geometry", renderer.voxel.geometry},
{"blend", renderer.voxel.blend},
{"fog", renderer.voxel.fog},
{"fog_color", toHexa(renderer.clear_color)},
{"skybox", renderer.skybox},
{"curvature", renderer.voxel.curvature},
{"curvature_depth", renderer.voxel.curv_depth},
{"transparency", renderer.voxel.transparency},
{"culling", culling}
}));
config.insert_or_assign("contouring", contouring);
config.insert_or_assign("camera", toml::table({
{"far", camera.far_dist},
{"near", camera.near_dist},
{"fov", camera.fov}
}));
config.insert_or_assign("control", toml::table({
{"sensibility", control.sensibility},
{"speed", control.speed},
{"collide", control.collide}
}));
config.insert_or_assign("world", toml::table({
{"load_distance", world.loadDistance},
{"keep_distance", world.keepDistance},
{"use_averages", world.useAverages},
{"trust_majorant", world.trustMajorant},
{"edit_prediction", world.editPrediction},
{"edit_handling", world.editHandling},
{"move_prediction", world.movePrediction},
{"move_collision", world.moveCollision}
}));
if(connection.has_value()) {
const auto &ct = connection.value();
config.insert_or_assign("connection", toml::table({
#ifndef LIGHT_CLIENT
{"use_local", false},
#endif
{"host", ct.host},
{"port", ct.port}
}));
} else {
config.insert_or_assign("connection", toml::table({{"use_local", true}}));
}
config.insert_or_assign("editor", toml::table({
{"visible", editor.visible},
{"tool", toml::table({
{"shape", static_cast<int>(editor.tool.shape)},
{"radius", editor.tool.radius},
{"material", editor.tool.material},
{"empty_air", editor.tool.emptyAir}
})}
}));
config.insert_or_assign("console", toml::table({
{"visible", console.visible},
{"scroll", console.scroll},
{"opacity", console.opacity}
}));
config.insert_or_assign("debug_menu", toml::table({
{"bar", debugMenu.bar},
{"render", debugMenu.render},
{"world", debugMenu.world},
{"contouring", debugMenu.contouring},
{"controls", debugMenu.controls}
}));
config.insert_or_assign("overlay", toml::table({
{"visible", overlay.visible},
{"corner", overlay.corner}
}));
toml::table key_table;
for (const auto& key: keys)
key_table.insert_or_assign(std::to_string(key.first), key.second);
config.insert_or_assign("keys", key_table);
return config;
}
world::client::Universe::options world;
struct {
bool bar = false;
bool render = false;
bool world = false;
bool contouring = false;
bool controls = false;
} debugMenu;
windowOptions window;
bool preferVulkan = false;
render::renderOptions renderer;
int culling = 0;
std::string contouring;
Controllable::options control;
Camera::options camera;
struct {
bool visible = false;
struct {
world::action::Shape shape = world::action::Shape::Cube;
int radius = 2;
unsigned short material = 5;
bool emptyAir = true;
} tool;
} editor;
struct {
bool visible = true;
bool scroll = true;
float opacity = .8f;
} console;
struct overlay_t {
bool visible = true;
int corner = 3;
} overlay;
std::optional<world::client::Universe::connection> connection = {};
std::vector<std::pair<int, int>> keys;
};
}