333 changes: 333 additions & 0 deletions src/settingdef.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,333 @@
/*
Minetest
Copyright (C) 2010-2015 celeron55, Perttu Ahola <celeron55@gmail.com>
This program is free software you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation either version 2.1 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License along
with this program if not, write to the Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/

/* This is no regular include header with guards and such, it is used to
* generate settings related code.
* The defaults aren't final, check defaultsettings.cpp for the adjustment it does.
* If you include this file, you have to define a macro
* MTCONF_SET_EXT(enum name, official name, default value), where
* "official name" is used as string specifier for the name.
* For the sake of better error reporting when a subsequent usage of this file is wrong,
* you should undef that value again after inclusion.
* If you evaluate default or lowercase values, this file relies on util/string.h and
* config.h. If you don't evaluate those, it solely relies on config.h.
* You have to ensure the needed files when you include this file.
*/

#ifndef MTCONF_SET_EXT
#error "MTCONF_SET_EXT needs to be set when including settingdef.h!"
#else
#define MTCONF_SET_SIMPLE(uppercase, default) MTCONF_SET_EXT(uppercase, lowercase( #uppercase ), default)
#endif

// Client and server

MTCONF_SET_SIMPLE(NAME, "")

// Client stuff
MTCONF_SET_SIMPLE(REMOTE_PORT, "30000")
MTCONF_SET_SIMPLE(KEYMAP_FORWARD, "KEY_KEY_W")
MTCONF_SET_SIMPLE(KEYMAP_BACKWARD, "KEY_KEY_S")
MTCONF_SET_SIMPLE(KEYMAP_LEFT, "KEY_KEY_A")
MTCONF_SET_SIMPLE(KEYMAP_RIGHT, "KEY_KEY_D")
MTCONF_SET_SIMPLE(KEYMAP_JUMP, "KEY_SPACE")
MTCONF_SET_SIMPLE(KEYMAP_SNEAK, "KEY_LSHIFT")
MTCONF_SET_SIMPLE(KEYMAP_DROP, "KEY_KEY_Q")
MTCONF_SET_SIMPLE(KEYMAP_INVENTORY, "KEY_KEY_I")
MTCONF_SET_SIMPLE(KEYMAP_SPECIAL1, "KEY_KEY_E")
MTCONF_SET_SIMPLE(KEYMAP_CHAT, "KEY_KEY_T")
MTCONF_SET_SIMPLE(KEYMAP_CMD, "/")
MTCONF_SET_SIMPLE(KEYMAP_CONSOLE, "KEY_F10")
MTCONF_SET_SIMPLE(KEYMAP_RANGESELECT, "KEY_KEY_R")
MTCONF_SET_SIMPLE(KEYMAP_FREEMOVE, "KEY_KEY_K")
MTCONF_SET_SIMPLE(KEYMAP_FASTMOVE, "KEY_KEY_J")
MTCONF_SET_SIMPLE(KEYMAP_NOCLIP, "KEY_KEY_H")
MTCONF_SET_SIMPLE(KEYMAP_CINEMATIC, "KEY_F8")
MTCONF_SET_SIMPLE(KEYMAP_SCREENSHOT, "KEY_F12")
MTCONF_SET_SIMPLE(KEYMAP_TOGGLE_HUD, "KEY_F1")
MTCONF_SET_SIMPLE(KEYMAP_TOGGLE_CHAT, "KEY_F2")
MTCONF_SET_SIMPLE(KEYMAP_TOGGLE_FORCE_FOG_OFF, "KEY_F3")
#if DEBUG
MTCONF_SET_SIMPLE(KEYMAP_TOGGLE_UPDATE_CAMERA, "KEY_F4")
#else
MTCONF_SET_SIMPLE(KEYMAP_TOGGLE_UPDATE_CAMERA, "none")
#endif
MTCONF_SET_SIMPLE(KEYMAP_TOGGLE_DEBUG, "KEY_F5")
MTCONF_SET_SIMPLE(KEYMAP_TOGGLE_PROFILER, "KEY_F6")
MTCONF_SET_SIMPLE(KEYMAP_CAMERA_MODE, "KEY_F7")
MTCONF_SET_SIMPLE(KEYMAP_INCREASE_VIEWING_RANGE_MIN, "+")
MTCONF_SET_SIMPLE(KEYMAP_DECREASE_VIEWING_RANGE_MIN, "-")
MTCONF_SET_SIMPLE(ENABLE_BUILD_WHERE_YOU_STAND, "false")
MTCONF_SET_SIMPLE(3D_MODE, "none")
MTCONF_SET_SIMPLE(3D_PARALAX_STRENGTH, "0.025")
MTCONF_SET_SIMPLE(AUX1_DESCENDS, "false")
MTCONF_SET_SIMPLE(DOUBLETAP_JUMP, "false")
MTCONF_SET_SIMPLE(ALWAYS_FLY_FAST, "true")
MTCONF_SET_SIMPLE(DIRECTIONAL_COLORED_FOG, "true")
MTCONF_SET_SIMPLE(TOOLTIP_SHOW_DELAY, "400")

// Some (temporary) keys for debugging
MTCONF_SET_SIMPLE(KEYMAP_PRINT_DEBUG_STACKS, "KEY_KEY_P")
MTCONF_SET_SIMPLE(KEYMAP_QUICKTUNE_PREV, "KEY_HOME")
MTCONF_SET_SIMPLE(KEYMAP_QUICKTUNE_NEXT, "KEY_END")
MTCONF_SET_SIMPLE(KEYMAP_QUICKTUNE_DEC, "KEY_NEXT")
MTCONF_SET_SIMPLE(KEYMAP_QUICKTUNE_INC, "KEY_PRIOR")

// Show debug info by default?
#ifdef NDEBUG
MTCONF_SET_SIMPLE(SHOW_DEBUG, "false")
#else
MTCONF_SET_SIMPLE(SHOW_DEBUG, "true")
#endif

MTCONF_SET_SIMPLE(WANTED_FPS, "30")
MTCONF_SET_SIMPLE(FPS_MAX, "60")
MTCONF_SET_SIMPLE(PAUSE_FPS_MAX, "20")
// A bit more than the server will send around the player, to make fog blend well
MTCONF_SET_SIMPLE(VIEWING_RANGE_NODES_MAX, "240")
MTCONF_SET_SIMPLE(VIEWING_RANGE_NODES_MIN, "35")
MTCONF_SET_EXT(SCREENW, "screenW", "800")
MTCONF_SET_EXT(SCREENH, "screenH", "600")
MTCONF_SET_SIMPLE(FULLSCREEN, "false")
MTCONF_SET_SIMPLE(FULLSCREEN_BPP, "24")
MTCONF_SET_SIMPLE(FSAA, "0")
MTCONF_SET_SIMPLE(VSYNC, "false")
MTCONF_SET_SIMPLE(ADDRESS, "")
MTCONF_SET_SIMPLE(RANDOM_INPUT, "false")
MTCONF_SET_SIMPLE(CLIENT_UNLOAD_UNUSED_DATA_TIMEOUT, "600")
MTCONF_SET_SIMPLE(ENABLE_FOG, "true")
MTCONF_SET_SIMPLE(FOV, "72")
MTCONF_SET_SIMPLE(VIEW_BOBBING, "true")
MTCONF_SET_SIMPLE(NEW_STYLE_WATER, "false")
MTCONF_SET_SIMPLE(NEW_STYLE_LEAVES, "true")
MTCONF_SET_SIMPLE(CONNECTED_GLASS, "false")
MTCONF_SET_SIMPLE(SMOOTH_LIGHTING, "true")
MTCONF_SET_SIMPLE(DISPLAY_GAMMA, "1.8")
MTCONF_SET_SIMPLE(TEXTURE_PATH, "")
MTCONF_SET_SIMPLE(SHADER_PATH, "")
MTCONF_SET_SIMPLE(VIDEO_DRIVER, "opengl")
MTCONF_SET_SIMPLE(FREE_MOVE, "false")
MTCONF_SET_SIMPLE(NOCLIP, "false")
MTCONF_SET_SIMPLE(CONTINUOUS_FORWARD, "false")
MTCONF_SET_SIMPLE(CINEMATIC, "false")
MTCONF_SET_SIMPLE(CAMERA_SMOOTHING, "0")
MTCONF_SET_SIMPLE(CINEMATIC_CAMERA_SMOOTHING, "0.7")
MTCONF_SET_SIMPLE(FAST_MOVE, "false")
MTCONF_SET_SIMPLE(INVERT_MOUSE, "false")
MTCONF_SET_SIMPLE(ENABLE_CLOUDS, "true")
MTCONF_SET_SIMPLE(SCREENSHOT_PATH, ".")
MTCONF_SET_SIMPLE(VIEW_BOBBING_AMOUNT, "1.0")
MTCONF_SET_SIMPLE(FALL_BOBBING_AMOUNT, "0.0")
MTCONF_SET_SIMPLE(ENABLE_3D_CLOUDS, "true")
MTCONF_SET_SIMPLE(CLOUD_HEIGHT, "120")
MTCONF_SET_SIMPLE(CLOUD_RADIUS, "12")
MTCONF_SET_SIMPLE(MENU_CLOUDS, "true")
MTCONF_SET_SIMPLE(OPAQUE_WATER, "false")
MTCONF_SET_SIMPLE(CONSOLE_COLOR, "")
MTCONF_SET_SIMPLE(CONSOLE_ALPHA, "200")
MTCONF_SET_SIMPLE(SELECTIONBOX_COLOR, "")
MTCONF_SET_SIMPLE(ENABLE_NODE_HIGHLIGHTING, "false")
MTCONF_SET_SIMPLE(CROSSHAIR_COLOR, "")
MTCONF_SET_SIMPLE(CROSSHAIR_ALPHA, "255")
MTCONF_SET_SIMPLE(HUD_SCALING, "1.0")
MTCONF_SET_SIMPLE(GUI_SCALING, "1.0")
MTCONF_SET_SIMPLE(GUI_SCALING_FILTER, "false")
MTCONF_SET_SIMPLE(GUI_SCALING_FILTER_TXR2IMG, "true")
MTCONF_SET_SIMPLE(MOUSE_SENSITIVITY, "0.2")
MTCONF_SET_SIMPLE(ENABLE_SOUND, "true")
MTCONF_SET_SIMPLE(SOUND_VOLUME, "0.8")
MTCONF_SET_SIMPLE(DESYNCHRONIZE_MAPBLOCK_TEXTURE_ANIMATION, "true")
MTCONF_SET_SIMPLE(SELECTIONBOX_WIDTH, "2")
MTCONF_SET_SIMPLE(HUD_HOTBAR_MAX_WIDTH, "1.0")
MTCONF_SET_SIMPLE(ENABLE_LOCAL_MAP_SAVING, "false")

MTCONF_SET_SIMPLE(MIP_MAP, "false")
MTCONF_SET_SIMPLE(ANISOTROPIC_FILTER, "false")
MTCONF_SET_SIMPLE(BILINEAR_FILTER, "false")
MTCONF_SET_SIMPLE(TRILINEAR_FILTER, "false")
MTCONF_SET_SIMPLE(TEXTURE_CLEAN_TRANSPARENT, "false")
MTCONF_SET_SIMPLE(TEXTURE_MIN_SIZE, "64")
MTCONF_SET_SIMPLE(PRELOAD_ITEM_VISUALS, "false")
MTCONF_SET_SIMPLE(ENABLE_BUMPMAPPING, "false")
MTCONF_SET_SIMPLE(ENABLE_PARALLAX_OCCLUSION, "false")
MTCONF_SET_SIMPLE(GENERATE_NORMALMAPS, "false")
MTCONF_SET_SIMPLE(NORMALMAPS_STRENGTH, "0.6")
MTCONF_SET_SIMPLE(NORMALMAPS_SMOOTH, "1")
MTCONF_SET_SIMPLE(PARALLAX_OCCLUSION_SCALE, "0.06")
MTCONF_SET_SIMPLE(PARALLAX_OCCLUSION_BIAS, "0.03")
MTCONF_SET_SIMPLE(ENABLE_WAVING_WATER, "false")
MTCONF_SET_SIMPLE(WATER_WAVE_HEIGHT, "1.0")
MTCONF_SET_SIMPLE(WATER_WAVE_LENGTH, "20.0")
MTCONF_SET_SIMPLE(WATER_WAVE_SPEED, "5.0")
MTCONF_SET_SIMPLE(ENABLE_WAVING_LEAVES, "false")
MTCONF_SET_SIMPLE(ENABLE_WAVING_PLANTS, "false")
MTCONF_SET_SIMPLE(AMBIENT_OCCLUSION_GAMMA, "2.2")
MTCONF_SET_SIMPLE(ENABLE_SHADERS, "true")
MTCONF_SET_SIMPLE(REPEAT_RIGHTCLICK_TIME, "0.25")
MTCONF_SET_SIMPLE(ENABLE_PARTICLES, "true")
MTCONF_SET_SIMPLE(ENABLE_MESH_CACHE, "true")

MTCONF_SET_SIMPLE(CURL_TIMEOUT, "5000")
MTCONF_SET_SIMPLE(CURL_PARALLEL_LIMIT, "8")
MTCONF_SET_SIMPLE(CURL_FILE_DOWNLOAD_TIMEOUT, "300000")
MTCONF_SET_SIMPLE(CURL_VERIFY_CERT, "true")

MTCONF_SET_SIMPLE(ENABLE_REMOTE_MEDIA_SERVER, "true")

MTCONF_SET_SIMPLE(SERVERLIST_URL, "servers.minetest.net")
MTCONF_SET_SIMPLE(SERVERLIST_FILE, "favoriteservers.txt")
MTCONF_SET_SIMPLE(SERVER_ANNOUNCE, "false")
MTCONF_SET_SIMPLE(SERVER_URL, "")
MTCONF_SET_SIMPLE(SERVER_ADDRESS, "")
MTCONF_SET_SIMPLE(SERVER_NAME, "")
MTCONF_SET_SIMPLE(SERVER_DESCRIPTION, "")

#if USE_FREETYPE
MTCONF_SET_SIMPLE(FREETYPE, "true")
MTCONF_SET_SIMPLE(FONT_PATH, porting::getDataPath("fonts" DIR_DELIM "liberationsans.ttf"))
MTCONF_SET_SIMPLE(FONT_SHADOW, "1")
MTCONF_SET_SIMPLE(FONT_SHADOW_ALPHA, "128")
MTCONF_SET_SIMPLE(MONO_FONT_PATH, porting::getDataPath("fonts" DIR_DELIM "liberationmono.ttf"))
MTCONF_SET_SIMPLE(FALLBACK_FONT_PATH, porting::getDataPath("fonts" DIR_DELIM "DroidSansFallbackFull.ttf"))

MTCONF_SET_SIMPLE(FALLBACK_FONT_SHADOW, "1")
MTCONF_SET_SIMPLE(FALLBACK_FONT_SHADOW_ALPHA, "128")

MTCONF_SET_SIMPLE(FONT_SIZE, itos(TTF_DEFAULT_FONT_SIZE))
MTCONF_SET_SIMPLE(MONO_FONT_SIZE, itos(TTF_DEFAULT_FONT_SIZE))
MTCONF_SET_SIMPLE(FALLBACK_FONT_SIZE, itos(TTF_DEFAULT_FONT_SIZE))
#else
MTCONF_SET_SIMPLE(FREETYPE, "false")
MTCONF_SET_SIMPLE(FONT_PATH, porting::getDataPath("fonts" DIR_DELIM "lucida_sans"))
MTCONF_SET_SIMPLE(MONO_FONT_PATH, porting::getDataPath("fonts" DIR_DELIM "mono_dejavu_sans"))

MTCONF_SET_SIMPLE(FONT_SIZE, itos(DEFAULT_FONT_SIZE))
MTCONF_SET_SIMPLE(MONO_FONT_SIZE, itos(DEFAULT_FONT_SIZE))
#endif

// Server stuff
// "map-dir" doesn't exist by default.
MTCONF_SET_SIMPLE(WORKAROUND_WINDOW_SIZE, "5")
MTCONF_SET_SIMPLE(MAX_PACKETS_PER_ITERATION, "1024")
MTCONF_SET_SIMPLE(PORT, "30000")
MTCONF_SET_SIMPLE(BIND_ADDRESS, "")
MTCONF_SET_SIMPLE(DEFAULT_GAME, "minetest")
MTCONF_SET_SIMPLE(MOTD, "")
MTCONF_SET_SIMPLE(MAX_USERS, "15")
MTCONF_SET_SIMPLE(STRICT_PROTOCOL_VERSION_CHECKING, "false")
MTCONF_SET_SIMPLE(CREATIVE_MODE, "false")
MTCONF_SET_SIMPLE(ENABLE_DAMAGE, "true")
MTCONF_SET_SIMPLE(FIXED_MAP_SEED, "")
MTCONF_SET_SIMPLE(GIVE_INITIAL_STUFF, "false")
MTCONF_SET_SIMPLE(DEFAULT_PASSWORD, "")
MTCONF_SET_SIMPLE(DEFAULT_PRIVS, "interact")
MTCONF_SET_SIMPLE(PLAYER_TRANSFER_DISTANCE, "0")
MTCONF_SET_SIMPLE(ENABLE_PVP, "true")
MTCONF_SET_SIMPLE(DISALLOW_EMPTY_PASSWORD, "false")
MTCONF_SET_SIMPLE(DISABLE_ANTICHEAT, "false")
MTCONF_SET_SIMPLE(ENABLE_ROLLBACK_RECORDING, "false")
#ifdef NDEBUG
MTCONF_SET_SIMPLE(DEPRECATED_LUA_API_HANDLING, "legacy")
#else
MTCONF_SET_SIMPLE(DEPRECATED_LUA_API_HANDLING, "log")
#endif

MTCONF_SET_SIMPLE(PROFILER_PRINT_INTERVAL, "0")
MTCONF_SET_SIMPLE(ENABLE_MAPGEN_DEBUG_INFO, "false")
MTCONF_SET_SIMPLE(ACTIVE_OBJECT_SEND_RANGE_BLOCKS, "3")
MTCONF_SET_SIMPLE(ACTIVE_BLOCK_RANGE, "2")
//MTCONF_SET_SIMPLE(MAX_SIMULTANEOUS_BLOCK_SENDS_PER_CLIENT, "1")
// This causes frametime jitter on client side, or does it?
MTCONF_SET_SIMPLE(MAX_SIMULTANEOUS_BLOCK_SENDS_PER_CLIENT, "10")
MTCONF_SET_SIMPLE(MAX_SIMULTANEOUS_BLOCK_SENDS_SERVER_TOTAL, "40")
MTCONF_SET_SIMPLE(MAX_BLOCK_SEND_DISTANCE, "9")
MTCONF_SET_SIMPLE(MAX_BLOCK_GENERATE_DISTANCE, "7")
MTCONF_SET_SIMPLE(MAX_CLEAROBJECTS_EXTRA_LOADED_BLOCKS, "4096")
MTCONF_SET_SIMPLE(TIME_SEND_INTERVAL, "5")
MTCONF_SET_SIMPLE(TIME_SPEED, "72")
MTCONF_SET_SIMPLE(YEAR_DAYS, "30")
MTCONF_SET_SIMPLE(SERVER_UNLOAD_UNUSED_DATA_TIMEOUT, "29")
MTCONF_SET_SIMPLE(MAX_OBJECTS_PER_BLOCK, "49")
MTCONF_SET_SIMPLE(SERVER_MAP_SAVE_INTERVAL, "5.3")
MTCONF_SET_SIMPLE(SQLITE_SYNCHRONOUS, "2")
MTCONF_SET_SIMPLE(FULL_BLOCK_SEND_ENABLE_MIN_TIME_FROM_BUILDING, "2.0")
MTCONF_SET_SIMPLE(DEDICATED_SERVER_STEP, "0.1")
MTCONF_SET_SIMPLE(IGNORE_WORLD_LOAD_ERRORS, "false")
MTCONF_SET_SIMPLE(REMOTE_MEDIA, "")
MTCONF_SET_SIMPLE(DEBUG_LOG_LEVEL, "2")
MTCONF_SET_SIMPLE(EMERGEQUEUE_LIMIT_TOTAL, "256")
MTCONF_SET_SIMPLE(EMERGEQUEUE_LIMIT_DISKONLY, "32")
MTCONF_SET_SIMPLE(EMERGEQUEUE_LIMIT_GENERATE, "32")
MTCONF_SET_SIMPLE(NUM_EMERGE_THREADS, "1")

// physics stuff
MTCONF_SET_SIMPLE(MOVEMENT_ACCELERATION_DEFAULT, "3")
MTCONF_SET_SIMPLE(MOVEMENT_ACCELERATION_AIR, "2")
MTCONF_SET_SIMPLE(MOVEMENT_ACCELERATION_FAST, "10")
MTCONF_SET_SIMPLE(MOVEMENT_SPEED_WALK, "4")
MTCONF_SET_SIMPLE(MOVEMENT_SPEED_CROUCH, "1.35")
MTCONF_SET_SIMPLE(MOVEMENT_SPEED_FAST, "20")
MTCONF_SET_SIMPLE(MOVEMENT_SPEED_CLIMB, "2")
MTCONF_SET_SIMPLE(MOVEMENT_SPEED_JUMP, "6.5")
MTCONF_SET_SIMPLE(MOVEMENT_LIQUID_FLUIDITY, "1")
MTCONF_SET_SIMPLE(MOVEMENT_LIQUID_FLUIDITY_SMOOTH, "0.5")
MTCONF_SET_SIMPLE(MOVEMENT_LIQUID_SINK, "10")
MTCONF_SET_SIMPLE(MOVEMENT_GRAVITY, "9.81")

//liquid stuff
MTCONF_SET_SIMPLE(LIQUID_LOOP_MAX, "100000")
MTCONF_SET_SIMPLE(LIQUID_QUEUE_PURGE_TIME, "0")
MTCONF_SET_SIMPLE(LIQUID_UPDATE, "1.0")

//mapgen stuff
MTCONF_SET_SIMPLE(MG_NAME, "v6")
MTCONF_SET_SIMPLE(WATER_LEVEL, "1")
MTCONF_SET_SIMPLE(CHUNKSIZE, "5")
MTCONF_SET_SIMPLE(MG_FLAGS, "dungeons")
MTCONF_SET_SIMPLE(MGV6_SPFLAGS, "jungles")
MTCONF_SET_SIMPLE(ENABLE_FLOATING_DUNGEONS, "true")

// IPv6
MTCONF_SET_SIMPLE(ENABLE_IPV6, "true")
MTCONF_SET_SIMPLE(IPV6_SERVER, "false")

MTCONF_SET_SIMPLE(MAIN_MENU_PATH, "")
MTCONF_SET_SIMPLE(MAIN_MENU_MOD_MGR, "1")
MTCONF_SET_SIMPLE(MAIN_MENU_GAME_MGR, "0")
MTCONF_SET_SIMPLE(MODSTORE_DOWNLOAD_URL, "https://forum.minetest.net/media/")
MTCONF_SET_SIMPLE(MODSTORE_LISTMODS_URL, "https://forum.minetest.net/mmdb/mods/")
MTCONF_SET_SIMPLE(MODSTORE_DETAILS_URL, "https://forum.minetest.net/mmdb/mod/*/")

MTCONF_SET_SIMPLE(HIGH_PRECISION_FPU, "true")

MTCONF_SET_SIMPLE(LANGUAGE, "")

#ifdef __ANDROID__

MTCONF_SET_SIMPLE(TOUCHTARGET, "true")
MTCONF_SET_EXT(TMPFOLDER, "TMPFolder", "/sdcard/" PROJECT_NAME_C "/tmp/")
MTCONF_SET_SIMPLE(TOUCHSCREEN_THRESHOLD, "20")
MTCONF_SET_SIMPLE(INVENTORY_IMAGE_HACK, "false")

MTCONF_SET_SIMPLE(CURL_VERIFY_CERT, "false")
#else
MTCONF_SET_SIMPLE(SCREEN_DPI, "72")
#endif

#undef MTCONF_SET_SIMPLE
315 changes: 263 additions & 52 deletions src/settings.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -37,17 +37,155 @@ static Settings main_settings;
Settings *g_settings = &main_settings;
std::string g_settings_path;

Settings::~Settings()
static std::map<std::string, MTSetting> mtsettings_names; //TODO change to unordered_map

static MTSetting get_mtsetting_for_name(const std::string &name)
{
if (mtsettings_names.empty()) {
#define MTCONF_SET_EXT(enumname, lcase, default)\
mtsettings_names[lcase] = CNF_##enumname;
#include "settingdef.h"
#undef MTCONF_SET_EXT
}
std::map<std::string, MTSetting>::iterator it;
it = mtsettings_names.find(name);
if (it != mtsettings_names.end()) {
return it->second;
} else {
return CNF_COUNT;
}
}


static std::string get_name_of_mtsetting(MTSetting setting)
{
switch(setting) {
#define MTCONF_SET_EXT(enumname, lcase, default)\
case CNF_##enumname: return lcase;
#include "settingdef.h"
#undef MTCONF_SET_EXT
default:
return "";
}
}


MTSettingsContainer::~MTSettingsContainer()
{
clear();
}


Settings & Settings::operator += (const Settings &other)
const SettingsEntry* MTSettingsContainer::find(const std::string &name) const
{
update(other);
std::map<std::string, SettingsEntry*>::const_iterator it;
it = m_map.find(name);
if (it == m_map.end()) {
return NULL;
} else {
return it->second;
}
}

return *this;

const SettingsEntry* MTSettingsContainer::find(MTSetting setting) const
{
return m_entries[setting];
}


std::map<std::string, SettingsEntry*>::const_iterator MTSettingsContainer::begin() const
{
return m_map.begin();
}


std::map<std::string, SettingsEntry*>::const_iterator MTSettingsContainer::end() const
{
return m_map.end();
}


bool MTSettingsContainer::has(const std::string &name) const
{
return m_map.find(name) != m_map.end();
}


bool MTSettingsContainer::has(MTSetting setting) const
{
// m_entries always contains an entry for a setting, but m_map doesn't always
return m_map.find(get_name_of_mtsetting(setting)) != m_map.end();
}


SettingsEntry& MTSettingsContainer::operator[] (const std::string &name)
{
std::map<std::string, SettingsEntry*>::iterator it;
it = m_map.find(name);
if (it == m_map.end()) {
SettingsEntry *entry = new SettingsEntry;
m_map[name] = entry;
MTSetting s = get_mtsetting_for_name(name);
if (s != CNF_COUNT)
m_entries[s] = entry;
return *entry;
} else {
return *it->second;
}
}


SettingsEntry& MTSettingsContainer::operator[] (MTSetting setting)
{
if (setting < CNF_COUNT) {
SettingsEntry *entry = m_entries[setting];
if (entry != NULL)
return *entry;
}
SettingsEntry *entry = new SettingsEntry;
m_entries[setting] = entry;
m_map[get_name_of_mtsetting(setting)] = entry;
return *entry;
}


void MTSettingsContainer::operator= (const MTSettingsContainer &other)
{
clear();
m_map.insert(other.m_map.begin(), other.m_map.end());
m_entries = other.m_entries;
}


bool MTSettingsContainer::erase(const std::string &name)
{
return m_map.erase(name);
}


bool MTSettingsContainer::erase(MTSetting setting)
{
return m_map.erase(get_name_of_mtsetting(setting));
}


void MTSettingsContainer::clear()
{
std::map<std::string, SettingsEntry*>::iterator it;
for (it = m_map.begin(); it != m_map.end(); ++it) {
delete it->second->group;
delete it->second;
}

m_map.clear();
m_entries.clear();
}


Settings::~Settings()
{
clear();
}


Expand All @@ -60,7 +198,8 @@ Settings & Settings::operator = (const Settings &other)
JMutexAutoLock lock2(other.m_mutex);

clearNoLock();
updateNoLock(other);
m_settings = other.m_settings;
m_defaults = other.m_defaults;

return *this;
}
Expand Down Expand Up @@ -195,10 +334,10 @@ void Settings::writeLines(std::ostream &os, u32 tab_depth) const
{
JMutexAutoLock lock(m_mutex);

for (std::map<std::string, SettingsEntry>::const_iterator
for (std::map<std::string, SettingsEntry*>::const_iterator
it = m_settings.begin();
it != m_settings.end(); ++it)
printEntry(os, it->first, it->second, tab_depth);
printEntry(os, it->first, *it->second, tab_depth);
}


Expand Down Expand Up @@ -230,7 +369,8 @@ void Settings::printEntry(std::ostream &os, const std::string &name,
bool Settings::updateConfigObject(std::istream &is, std::ostream &os,
const std::string &end, u32 tab_depth)
{
std::map<std::string, SettingsEntry>::const_iterator it;
const SettingsEntry *entry;
std::map<std::string, SettingsEntry*>::const_iterator it;
std::set<std::string> present_entries;
std::string line, name, value;
bool was_modified = false;
Expand All @@ -251,10 +391,10 @@ bool Settings::updateConfigObject(std::istream &is, std::ostream &os,
value = getMultiline(is);
/* FALLTHROUGH */
case SPE_KVPAIR:
it = m_settings.find(name);
if (it != m_settings.end() &&
(it->second.is_group || it->second.value != value)) {
printEntry(os, name, it->second, tab_depth);
entry = m_settings.find(name);
if (entry != NULL &&
(entry->is_group || entry->value != value)) {
printEntry(os, name, *entry, tab_depth);
was_modified = true;
} else {
os << line << "\n";
Expand All @@ -264,14 +404,14 @@ bool Settings::updateConfigObject(std::istream &is, std::ostream &os,
present_entries.insert(name);
break;
case SPE_GROUP:
it = m_settings.find(name);
if (it != m_settings.end() && it->second.is_group) {
entry = m_settings.find(name);
if (entry != NULL && entry->is_group) {
os << line << "\n";
sanity_check(it->second.group != NULL);
was_modified |= it->second.group->updateConfigObject(is, os,
sanity_check(entry->group != NULL);
was_modified |= entry->group->updateConfigObject(is, os,
"}", tab_depth + 1);
} else {
printEntry(os, name, it->second, tab_depth);
printEntry(os, name, *entry, tab_depth);
was_modified = true;
}
present_entries.insert(name);
Expand All @@ -287,7 +427,7 @@ bool Settings::updateConfigObject(std::istream &is, std::ostream &os,
if (present_entries.find(it->first) != present_entries.end())
continue;

printEntry(os, it->first, it->second, tab_depth);
printEntry(os, it->first, *it->second, tab_depth);
was_modified = true;
}

Expand Down Expand Up @@ -380,12 +520,12 @@ const SettingsEntry &Settings::getEntry(const std::string &name) const
{
JMutexAutoLock lock(m_mutex);

std::map<std::string, SettingsEntry>::const_iterator n;
if ((n = m_settings.find(name)) == m_settings.end()) {
if ((n = m_defaults.find(name)) == m_defaults.end())
const SettingsEntry *n;
if ((n = m_settings.find(name)) == NULL) {
if ((n = m_defaults.find(name)) == NULL)
throw SettingNotFoundException("Setting [" + name + "] not found.");
}
return n->second;
return *n;
}


Expand All @@ -403,6 +543,7 @@ std::string Settings::get(const std::string &name) const
const SettingsEntry &entry = getEntry(name);
if (entry.is_group)
throw SettingNotFoundException("Setting [" + name + "] is a group.");
// errorstream << "getting " << name << " = " << entry.value << std::endl;
return entry.value;
}

Expand Down Expand Up @@ -559,19 +700,114 @@ bool Settings::getNoiseParamsFromGroup(const std::string &name,
}


const SettingsEntry &Settings::getEntry(MTSetting setting) const
{
JMutexAutoLock lock(m_mutex);

const SettingsEntry *n;
if ((n = m_settings.find(setting)) == NULL) {
if ((n = m_defaults.find(setting)) == NULL)
throw SettingNotFoundException("Setting [id=" + itos(setting) + "] not found.");
}
return *n;
}


Settings *Settings::getGroup(MTSetting setting) const
{
const SettingsEntry &entry = getEntry(setting);
if (!entry.is_group)
throw SettingNotFoundException("Setting [id=" + itos(setting) + "] is not a group.");
return entry.group;
}


std::string Settings::get(MTSetting setting) const
{
const SettingsEntry &entry = getEntry(setting);
if (entry.is_group)
throw SettingNotFoundException("Setting [id=" + itos(setting) + "] is a group.");
return entry.value;
}


bool Settings::getBool(MTSetting setting) const
{
return is_yes(get(setting));
}


u16 Settings::getU16(MTSetting setting) const
{
return stoi(get(setting), 0, 65535);
}


s16 Settings::getS16(MTSetting setting) const
{
return stoi(get(setting), -32768, 32767);
}


s32 Settings::getS32(MTSetting setting) const
{
return stoi(get(setting));
}


float Settings::getFloat(MTSetting setting) const
{
return stof(get(setting));
}


u64 Settings::getU64(MTSetting setting) const
{
u64 value = 0;
std::string s = get(setting);
std::istringstream ss(s);
ss >> value;
return value;
}


v2f Settings::getV2F(MTSetting setting) const
{
v2f value;
Strfnd f(get(setting));
f.next("(");
value.X = stof(f.next(","));
value.Y = stof(f.next(")"));
return value;
}


v3f Settings::getV3F(MTSetting setting) const
{
v3f value;
Strfnd f(get(setting));
f.next("(");
value.X = stof(f.next(","));
value.Y = stof(f.next(","));
value.Z = stof(f.next(")"));
return value;
}



bool Settings::exists(const std::string &name) const
{
JMutexAutoLock lock(m_mutex);

return (m_settings.find(name) != m_settings.end() ||
m_defaults.find(name) != m_defaults.end());
return (m_settings.has(name) ||
m_defaults.has(name));
}


std::vector<std::string> Settings::getNames() const
{
std::vector<std::string> names;
for (std::map<std::string, SettingsEntry>::const_iterator
for (std::map<std::string, SettingsEntry*>::const_iterator
i = m_settings.begin();
i != m_settings.end(); ++i) {
names.push_back(i->first);
Expand Down Expand Up @@ -912,18 +1148,6 @@ void Settings::updateValue(const Settings &other, const std::string &name)
}


void Settings::update(const Settings &other)
{
if (&other == this)
return;

JMutexAutoLock lock(m_mutex);
JMutexAutoLock lock2(other.m_mutex);

updateNoLock(other);
}


SettingsParseEvent Settings::parseConfigObject(const std::string &line,
const std::string &end, std::string &name, std::string &value)
{
Expand Down Expand Up @@ -952,40 +1176,27 @@ SettingsParseEvent Settings::parseConfigObject(const std::string &line,
}


void Settings::updateNoLock(const Settings &other)
{
m_settings.insert(other.m_settings.begin(), other.m_settings.end());
m_defaults.insert(other.m_defaults.begin(), other.m_defaults.end());
}


void Settings::clearNoLock()
{
std::map<std::string, SettingsEntry>::const_iterator it;
for (it = m_settings.begin(); it != m_settings.end(); ++it)
delete it->second.group;
m_settings.clear();

clearDefaultsNoLock();
}

void Settings::clearDefaultsNoLock()
{
std::map<std::string, SettingsEntry>::const_iterator it;
for (it = m_defaults.begin(); it != m_defaults.end(); ++it)
delete it->second.group;
m_defaults.clear();
}


void Settings::registerChangedCallback(std::string name,
void Settings::registerChangedCallback(const std::string &name,
setting_changed_callback cbf, void *userdata)
{
JMutexAutoLock lock(m_callbackMutex);
m_callbacks[name].push_back(std::make_pair(cbf, userdata));
}

void Settings::deregisterChangedCallback(std::string name, setting_changed_callback cbf, void *userdata)
void Settings::deregisterChangedCallback(const std::string &name, setting_changed_callback cbf, void *userdata)
{
JMutexAutoLock lock(m_callbackMutex);
std::map<std::string, std::vector<std::pair<setting_changed_callback, void*> > >::iterator iterToVector = m_callbacks.find(name);
Expand Down
78 changes: 68 additions & 10 deletions src/settings.h
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#include "irrlichttypes_bloated.h"
#include "util/string.h"
#include "jthread/jmutex.h"
#include "config.h"
#include <string>
#include <map>
#include <list>
Expand All @@ -35,6 +36,15 @@ struct NoiseParams;
extern Settings *g_settings;
extern std::string g_settings_path;

enum MTSetting {
#define MTCONF_SET_EXT(enumname, lcase, default) CNF_##enumname,
#define MTCONF_EXEC_FOR_DEFAULT(code)
#include "settingdef.h"
#undef MTCONF_SET_EXT
#undef MTCONF_EXEC_FOR_DEFAULT
CNF_COUNT
};

/** function type to register a changed callback */
typedef void (*setting_changed_callback)(const std::string, void*);

Expand Down Expand Up @@ -89,12 +99,48 @@ struct SettingsEntry {
bool is_group;
};

class MTSettingsContainer {
public:
MTSettingsContainer():
m_entries(CNF_COUNT)
{
}
~MTSettingsContainer();

const SettingsEntry *find(const std::string &name) const;
const SettingsEntry *find(MTSetting setting) const;

std::map<std::string, SettingsEntry*>::const_iterator begin() const;
std::map<std::string, SettingsEntry*>::const_iterator end() const;

bool has(MTSetting setting) const;
bool has(const std::string &name) const;


SettingsEntry &operator[] (MTSetting setting);
SettingsEntry &operator[] (const std::string &name);

void operator= (const MTSettingsContainer &other);

bool erase(const std::string &name);
bool erase(MTSetting setting);

void clear();

private:
void fillWithMTSettings();

std::map<std::string, SettingsEntry*> m_map;
std::vector<SettingsEntry*> m_entries;
};

class Settings {
public:
Settings() {}
// N.B. Groups not allocated with new must be set to NULL in the settings
// tree before object destruction.
~Settings();

Settings & operator += (const Settings &other);
Settings & operator = (const Settings &other);

/***********************
Expand Down Expand Up @@ -149,6 +195,18 @@ class Settings {
bool getNoiseParamsFromValue(const std::string &name, NoiseParams &np) const;
bool getNoiseParamsFromGroup(const std::string &name, NoiseParams &np) const;

const SettingsEntry &getEntry(MTSetting setting) const;
Settings *getGroup(MTSetting setting) const;
std::string get(MTSetting setting) const;
bool getBool(MTSetting setting) const;
u16 getU16(MTSetting setting) const;
s16 getS16(MTSetting setting) const;
s32 getS32(MTSetting setting) const;
u64 getU64(MTSetting setting) const;
float getFloat(MTSetting setting) const;
v2f getV2F(MTSetting setting) const;
v3f getV3F(MTSetting setting) const;

// return all keys used
std::vector<std::string> getNames() const;
bool exists(const std::string &name) const;
Expand Down Expand Up @@ -179,10 +237,6 @@ class Settings {
* Setters *
***********/

// N.B. Groups not allocated with new must be set to NULL in the settings
// tree before object destruction.
bool setEntry(const std::string &name, const void *entry,
bool set_group, bool set_default);
bool set(const std::string &name, const std::string &value);
bool setDefault(const std::string &name, const std::string &value);
bool setGroup(const std::string &name, Settings *group);
Expand All @@ -209,19 +263,23 @@ class Settings {
void clearDefaults();
void updateValue(const Settings &other, const std::string &name);
void update(const Settings &other);
void registerChangedCallback(std::string name, setting_changed_callback cbf, void *userdata = NULL);
void deregisterChangedCallback(std::string name, setting_changed_callback cbf, void *userdata = NULL);
void registerChangedCallback(const std::string &name, setting_changed_callback cbf, void *userdata = NULL);
void deregisterChangedCallback(const std::string &name, setting_changed_callback cbf, void *userdata = NULL);

private:

void updateNoLock(const Settings &other);
// N.B. Groups not allocated with new must be set to NULL in the settings
// tree before object destruction.
bool setEntry(const std::string &name, const void *entry,
bool set_group, bool set_default);

void clearNoLock();
void clearDefaultsNoLock();

void doCallbacks(std::string name);

std::map<std::string, SettingsEntry> m_settings;
std::map<std::string, SettingsEntry> m_defaults;
MTSettingsContainer m_settings;
MTSettingsContainer m_defaults;

std::map<std::string, std::vector<std::pair<setting_changed_callback,void*> > > m_callbacks;

Expand Down