Finalize properties parsing system and load/save
This commit is contained in:
parent
4488d8bcf2
commit
ac693ed4e5
|
@ -6,7 +6,8 @@ using namespace Feather;
|
||||||
int main()
|
int main()
|
||||||
{
|
{
|
||||||
ServerProperties properties("server.properties");
|
ServerProperties properties("server.properties");
|
||||||
printf("Starting server on port %d\n", properties.Get<int>("server-port"));
|
properties.Save();
|
||||||
|
printf("Starting server on port %d\n", properties.serverPort.GetValue());
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,47 @@
|
||||||
|
#include "Properties.h"
|
||||||
|
#include "../util/StringUtil.h"
|
||||||
|
|
||||||
|
static const string STRING_TRUE("true");
|
||||||
|
static const string STRING_FALSE("false");
|
||||||
|
|
||||||
|
namespace Feather
|
||||||
|
{
|
||||||
|
template <>
|
||||||
|
string Properties::Get<string>(string_view key)
|
||||||
|
{
|
||||||
|
return properties.at(string(key));
|
||||||
|
}
|
||||||
|
|
||||||
|
template <>
|
||||||
|
bool Properties::Get<bool>(string_view key)
|
||||||
|
{
|
||||||
|
string value = Get<string>(key);
|
||||||
|
if (StringUtil::iequal(value, STRING_TRUE))
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// TODO: complain about non-bool
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
template <>
|
||||||
|
int Properties::Get<int>(string_view key)
|
||||||
|
{
|
||||||
|
return std::stoi(Get<string>(key));
|
||||||
|
}
|
||||||
|
|
||||||
|
template <>
|
||||||
|
long Properties::Get<long>(string_view key)
|
||||||
|
{
|
||||||
|
return std::stol(Get<string>(key));
|
||||||
|
}
|
||||||
|
|
||||||
|
template <>
|
||||||
|
long long Properties::Get<long long>(string_view key)
|
||||||
|
{
|
||||||
|
return std::stoll(Get<string>(key));
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,21 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <iostream>
|
||||||
|
#include <string>
|
||||||
|
#include <string_view>
|
||||||
|
#include <unordered_map>
|
||||||
|
|
||||||
|
using std::string;
|
||||||
|
using std::string_view;
|
||||||
|
using std::unordered_map;
|
||||||
|
|
||||||
|
namespace Feather
|
||||||
|
{
|
||||||
|
class Properties
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
template <typename T> T Get(string_view key);
|
||||||
|
protected:
|
||||||
|
unordered_map<string, string> properties;
|
||||||
|
};
|
||||||
|
}
|
|
@ -0,0 +1,68 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "Properties.h"
|
||||||
|
#include "ServerProperties.h"
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
#include <string_view>
|
||||||
|
#include <unordered_map>
|
||||||
|
#include <functional>
|
||||||
|
|
||||||
|
using std::string;
|
||||||
|
using std::string_view;
|
||||||
|
using std::unordered_map;
|
||||||
|
|
||||||
|
namespace Feather
|
||||||
|
{
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
class Property
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
Property(string_view key) : key(key) {}
|
||||||
|
Property(string_view key, T defaultValue) : key(key), value(defaultValue) {}
|
||||||
|
Property(string_view key, std::function<T(T)> op, T defaultValue) : key(key), op(op), value(defaultValue) {}
|
||||||
|
|
||||||
|
void Init(Properties *properties)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
SetValue(properties->Get<T>(key));
|
||||||
|
}
|
||||||
|
catch (std::out_of_range err)
|
||||||
|
{
|
||||||
|
// process default value from constructor
|
||||||
|
SetValue(value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void SetValue(T value)
|
||||||
|
{
|
||||||
|
if (op) {
|
||||||
|
this->value = op(value);
|
||||||
|
} else {
|
||||||
|
this->value = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
virtual T GetValue() { return value; }
|
||||||
|
|
||||||
|
inline string ToString() { return std::to_string(value); }
|
||||||
|
|
||||||
|
string_view key;
|
||||||
|
private:
|
||||||
|
T value = T();
|
||||||
|
std::function<T(T)> op;
|
||||||
|
};
|
||||||
|
|
||||||
|
template <>
|
||||||
|
inline string Property<string>::ToString()
|
||||||
|
{
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <>
|
||||||
|
inline string Property<bool>::ToString()
|
||||||
|
{
|
||||||
|
return value ? "true" : "false";
|
||||||
|
}
|
||||||
|
}
|
|
@ -3,15 +3,15 @@
|
||||||
#include <fstream>
|
#include <fstream>
|
||||||
#include <string_view>
|
#include <string_view>
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
|
#include <ctime>
|
||||||
|
#include <cstring>
|
||||||
|
#include <iomanip>
|
||||||
|
|
||||||
#include "../util/StringUtil.h"
|
#include "../util/StringUtil.h"
|
||||||
|
|
||||||
static const string STRING_TRUE("true");
|
|
||||||
static const string STRING_FALSE("false");
|
|
||||||
|
|
||||||
namespace Feather
|
namespace Feather
|
||||||
{
|
{
|
||||||
ServerProperties::ServerProperties(const char* path)
|
void ServerProperties::Load()
|
||||||
{
|
{
|
||||||
std::ifstream file;
|
std::ifstream file;
|
||||||
file.open(path);
|
file.open(path);
|
||||||
|
@ -47,45 +47,93 @@ namespace Feather
|
||||||
}
|
}
|
||||||
file.close();
|
file.close();
|
||||||
}
|
}
|
||||||
|
else
|
||||||
//for ( auto const& pair : properties )
|
{
|
||||||
// std::cout << "[" << pair.first << "] = [" << pair.second << "]\n";
|
printf("Could not find %s\n");
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
template <>
|
|
||||||
string ServerProperties::Get<string>(string_view key)
|
|
||||||
{
|
|
||||||
return properties[string(key)];
|
|
||||||
}
|
|
||||||
|
|
||||||
template <>
|
|
||||||
bool ServerProperties::Get<bool>(string_view key)
|
|
||||||
{
|
|
||||||
string value = Get<string>(key);
|
|
||||||
if (StringUtil::iequal(value, STRING_TRUE)) {
|
|
||||||
return true;
|
|
||||||
} else {
|
|
||||||
// TODO: complain about non-bool
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
template <>
|
void ServerProperties::Save()
|
||||||
int ServerProperties::Get<int>(string_view key)
|
|
||||||
{
|
{
|
||||||
return std::stoi(Get<string>(key));
|
std::ofstream file;
|
||||||
}
|
file.open(path);
|
||||||
|
|
||||||
template <>
|
file << "#Minecraft server properties" << std::endl;
|
||||||
long ServerProperties::Get<long>(string_view key)
|
|
||||||
{
|
|
||||||
return std::stol(Get<string>(key));
|
|
||||||
}
|
|
||||||
|
|
||||||
template <>
|
auto time = std::time(nullptr);
|
||||||
long long ServerProperties::Get<long long>(string_view key)
|
auto localTime = *std::localtime(&time);
|
||||||
{
|
|
||||||
return std::stoll(Get<string>(key));
|
// The following code abbreviates a time zone like "Pacifc Daylight Time"
|
||||||
|
// to a short form like "PDT". If the time zone is already abbreviated
|
||||||
|
// then it won't change the abbreviation
|
||||||
|
|
||||||
|
char timeZone[256];
|
||||||
|
strftime(timeZone, 256, "%Z", &localTime);
|
||||||
|
|
||||||
|
char timeZoneAbbr[5];
|
||||||
|
int counter = 0;
|
||||||
|
for (int i = 0; i < strlen(timeZone); i++)
|
||||||
|
{
|
||||||
|
char c = timeZone[i];
|
||||||
|
if (std::isupper(c)) {
|
||||||
|
timeZoneAbbr[counter++] = c;
|
||||||
|
// stop before last char to insert 0
|
||||||
|
if (counter >= 4) {
|
||||||
|
timeZoneAbbr[counter] = 0;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Ex: Thu Jul 23 01:43:47 PDT 2020
|
||||||
|
file << "#" << std::put_time(&localTime, "%a %b %d %H:%M:%S ") << timeZoneAbbr << std::put_time(&localTime, " %Y") << std::endl;
|
||||||
|
|
||||||
|
file << onlineMode.key << "=" << onlineMode.ToString() << std::endl;
|
||||||
|
file << preventProxyConnections.key << "=" << preventProxyConnections.ToString() << std::endl;
|
||||||
|
file << serverIp.key << "=" << serverIp.ToString() << std::endl;
|
||||||
|
file << spawnAnimals.key << "=" << spawnAnimals.ToString() << std::endl;
|
||||||
|
file << spawnNpcs.key << "=" << spawnNpcs.ToString() << std::endl;
|
||||||
|
file << pvp.key << "=" << pvp.ToString() << std::endl;
|
||||||
|
file << allowFlight.key << "=" << allowFlight.ToString() << std::endl;
|
||||||
|
file << resourcePack.key << "=" << resourcePack.ToString() << std::endl;
|
||||||
|
file << motd.key << "=" << motd.ToString() << std::endl;
|
||||||
|
file << forceGameMode.key << "=" << forceGameMode.ToString() << std::endl;
|
||||||
|
file << enforceWhitelist.key << "=" << enforceWhitelist.ToString() << std::endl;
|
||||||
|
file << levelName.key << "=" << levelName.ToString() << std::endl;
|
||||||
|
file << serverPort.key << "=" << serverPort.ToString() << std::endl;
|
||||||
|
file << maxBuildHeight.key << "=" << maxBuildHeight.ToString() << std::endl;
|
||||||
|
//file << announcePlayerAchievements.key << "=" << announcePlayerAchievements.ToString() << std::endl;
|
||||||
|
file << enableQuery.key << "=" << enableQuery.ToString() << std::endl;
|
||||||
|
file << queryPort.key << "=" << queryPort.ToString() << std::endl;
|
||||||
|
file << enableRcon.key << "=" << enableRcon.ToString() << std::endl;
|
||||||
|
file << rconPort.key << "=" << rconPort.ToString() << std::endl;
|
||||||
|
file << rconPassword.key << "=" << rconPassword.ToString() << std::endl;
|
||||||
|
//file << resourcePackHash.key << "=" << resourcePackHash.ToString() << std::endl;
|
||||||
|
file << resourcePackSha1.key << "=" << resourcePackSha1.ToString() << std::endl;
|
||||||
|
file << hardcore.key << "=" << hardcore.ToString() << std::endl;
|
||||||
|
file << allowNether.key << "=" << allowNether.ToString() << std::endl;
|
||||||
|
file << spawnMonsters.key << "=" << spawnMonsters.ToString() << std::endl;
|
||||||
|
file << snooperEnabled.key << "=" << snooperEnabled.ToString() << std::endl;
|
||||||
|
file << useNativeTransport.key << "=" << useNativeTransport.ToString() << std::endl;
|
||||||
|
file << enableCommandBlock.key << "=" << enableCommandBlock.ToString() << std::endl;
|
||||||
|
file << spawnProtection.key << "=" << spawnProtection.ToString() << std::endl;
|
||||||
|
file << opPermissionLevel.key << "=" << opPermissionLevel.ToString() << std::endl;
|
||||||
|
file << functionPermissionLevel.key << "=" << functionPermissionLevel.ToString() << std::endl;
|
||||||
|
file << maxTickTime.key << "=" << maxTickTime.ToString() << std::endl;
|
||||||
|
file << viewDistance.key << "=" << viewDistance.ToString() << std::endl;
|
||||||
|
file << maxPlayers.key << "=" << maxPlayers.ToString() << std::endl;
|
||||||
|
file << networkCompressionThreshold.key << "=" << networkCompressionThreshold.ToString() << std::endl;
|
||||||
|
file << broadcastRconToOps.key << "=" << broadcastRconToOps.ToString() << std::endl;
|
||||||
|
file << broadcastConsoleToOps.key << "=" << broadcastConsoleToOps.ToString() << std::endl;
|
||||||
|
file << maxWorldSize.key << "=" << maxWorldSize.ToString() << std::endl;
|
||||||
|
file << syncChunkWrites.key << "=" << syncChunkWrites.ToString() << std::endl;
|
||||||
|
file << enableJmxMonitoring.key << "=" << enableJmxMonitoring.ToString() << std::endl;
|
||||||
|
file << enableStatus.key << "=" << enableStatus.ToString() << std::endl;
|
||||||
|
file << entityBroadcastRangePercentage.key << "=" << entityBroadcastRangePercentage.ToString() << std::endl;
|
||||||
|
file << playerIdleTimeout.key << "=" << playerIdleTimeout.ToString() << std::endl;
|
||||||
|
file << whiteList.key << "=" << whiteList.ToString() << std::endl;
|
||||||
|
|
||||||
|
file << std::endl;
|
||||||
|
file.close();
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -1,21 +1,127 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include "Properties.h"
|
||||||
|
#include "Property.h"
|
||||||
|
|
||||||
|
#include <iostream>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
#include <string_view>
|
||||||
#include <unordered_map>
|
#include <unordered_map>
|
||||||
|
#include <algorithm>
|
||||||
|
|
||||||
using std::string;
|
using std::string;
|
||||||
using std::string_view;
|
using std::string_view;
|
||||||
|
using std::unordered_map;
|
||||||
|
|
||||||
namespace Feather
|
namespace Feather
|
||||||
{
|
{
|
||||||
class ServerProperties
|
class ServerProperties : public Properties
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
ServerProperties(const char* path);
|
|
||||||
|
|
||||||
template <typename T>
|
Property<bool> onlineMode = Property<bool>("online-mode", true);
|
||||||
T Get(string_view key);
|
Property<bool> preventProxyConnections = Property<bool>("prevent-proxy-connections", false);
|
||||||
|
Property<string> serverIp = Property<string>("server-ip", "");
|
||||||
|
Property<bool> spawnAnimals = Property<bool>("spawn-animals", true);
|
||||||
|
Property<bool> spawnNpcs = Property<bool>("spawn-npcs", true);
|
||||||
|
Property<bool> pvp = Property<bool>("pvp", true);
|
||||||
|
Property<bool> allowFlight = Property<bool>("allow-flight", false);
|
||||||
|
Property<string> resourcePack = Property<string>("resource-pack", "");
|
||||||
|
Property<string> motd = Property<string>("motd", "A Minecraft Server");
|
||||||
|
Property<bool> forceGameMode = Property<bool>("force-gamemode", false);
|
||||||
|
Property<bool> enforceWhitelist = Property<bool>("enforce-whitelist", false);
|
||||||
|
//Property<Difficulty> difficulty = Property<Difficulty>("difficulty", DedicatedServerProperties.dispatchNumberOrString(Difficulty::byId, Difficulty::byName), Difficulty::getKey, Difficulty.EASY);
|
||||||
|
//Property<GameType> gamemode = Property<GameType>("gamemode", DedicatedServerProperties.dispatchNumberOrString(GameType::byId, GameType::byName), GameType::getName, GameType.SURVIVAL);
|
||||||
|
Property<string> levelName = Property<string>("level-name", "world");
|
||||||
|
Property<int> serverPort = Property<int>("server-port", 25565);
|
||||||
|
Property<int> maxBuildHeight = Property<int>("max-build-height", [](int n) { return std::clamp((n + 8) / 16 * 16, 64, 256); }, 256); // round to nearest 16, clamp to range [64, 256]
|
||||||
|
// (REMOVED) Property<bool> announcePlayerAchievements = Property<bool>("announce-player-achievements");
|
||||||
|
Property<bool> enableQuery = Property<bool>("enable-query", false);
|
||||||
|
Property<int> queryPort = Property<int>("query.port", 25565);
|
||||||
|
Property<bool> enableRcon = Property<bool>("enable-rcon", false);
|
||||||
|
Property<int> rconPort = Property<int>("rcon.port", 25575);
|
||||||
|
Property<string> rconPassword = Property<string>("rcon.password", "");
|
||||||
|
// (REMOVED) Property<string> resourcePackHash = Property<string>("resource-pack-hash");
|
||||||
|
Property<string> resourcePackSha1 = Property<string>("resource-pack-sha1", "");
|
||||||
|
Property<bool> hardcore = Property<bool>("hardcore", false);
|
||||||
|
Property<bool> allowNether = Property<bool>("allow-nether", true);
|
||||||
|
Property<bool> spawnMonsters = Property<bool>("spawn-monsters", true);
|
||||||
|
|
||||||
|
Property<bool> snooperEnabled = Property<bool>("snooper-enabled", true);
|
||||||
|
Property<bool> useNativeTransport = Property<bool>("use-native-transport", true);
|
||||||
|
Property<bool> enableCommandBlock = Property<bool>("enable-command-block", false);
|
||||||
|
Property<int> spawnProtection = Property<int>("spawn-protection", 16);
|
||||||
|
Property<int> opPermissionLevel = Property<int>("op-permission-level", 4);
|
||||||
|
Property<int> functionPermissionLevel = Property<int>("function-permission-level", 2);
|
||||||
|
Property<long> maxTickTime = Property<long>("max-tick-time");//, TimeUnit.MINUTES.toMillis(1L));
|
||||||
|
Property<int> viewDistance = Property<int>("view-distance", 10);
|
||||||
|
Property<int> maxPlayers = Property<int>("max-players", 20);
|
||||||
|
Property<int> networkCompressionThreshold = Property<int>("network-compression-threshold", 256);
|
||||||
|
Property<bool> broadcastRconToOps = Property<bool>("broadcast-rcon-to-ops", true);
|
||||||
|
Property<bool> broadcastConsoleToOps = Property<bool>("broadcast-console-to-ops", true);
|
||||||
|
Property<int> maxWorldSize = Property<int>("max-world-size", [](int n) { return std::clamp(n, 1, 29999984); }, 29999984);
|
||||||
|
Property<bool> syncChunkWrites = Property<bool>("sync-chunk-writes", true);
|
||||||
|
Property<bool> enableJmxMonitoring = Property<bool>("enable-jmx-monitoring", false);
|
||||||
|
Property<bool> enableStatus = Property<bool>("enable-status", true);
|
||||||
|
Property<int> entityBroadcastRangePercentage = Property<int>("entity-broadcast-range-percentage", [](int n) { return std::clamp(n, 10, 1000); }, 100);
|
||||||
|
/*mutable*/ Property<int> playerIdleTimeout = Property<int>("player-idle-timeout", 0);
|
||||||
|
/*mutable*/ Property<bool> whiteList = Property<bool>("white-list", false);
|
||||||
|
//Property<WorldGenSettings> worldGenSettings = WorldGenSettings.create(properties);
|
||||||
|
|
||||||
|
ServerProperties(const char* path) : path(path)
|
||||||
|
{
|
||||||
|
Load();
|
||||||
|
|
||||||
|
onlineMode.Init(this);
|
||||||
|
preventProxyConnections.Init(this);
|
||||||
|
serverIp.Init(this);
|
||||||
|
spawnAnimals.Init(this);
|
||||||
|
spawnNpcs.Init(this);
|
||||||
|
pvp.Init(this);
|
||||||
|
allowFlight.Init(this);
|
||||||
|
resourcePack.Init(this);
|
||||||
|
motd.Init(this);
|
||||||
|
forceGameMode.Init(this);
|
||||||
|
enforceWhitelist.Init(this);
|
||||||
|
levelName.Init(this);
|
||||||
|
serverPort.Init(this);
|
||||||
|
maxBuildHeight.Init(this);
|
||||||
|
//announcePlayerAchievements.Init(this);
|
||||||
|
enableQuery.Init(this);
|
||||||
|
queryPort.Init(this);
|
||||||
|
enableRcon.Init(this);
|
||||||
|
rconPort.Init(this);
|
||||||
|
rconPassword.Init(this);
|
||||||
|
//resourcePackHash.Init(this);
|
||||||
|
resourcePackSha1.Init(this);
|
||||||
|
hardcore.Init(this);
|
||||||
|
allowNether.Init(this);
|
||||||
|
spawnMonsters.Init(this);
|
||||||
|
snooperEnabled.Init(this);
|
||||||
|
useNativeTransport.Init(this);
|
||||||
|
enableCommandBlock.Init(this);
|
||||||
|
spawnProtection.Init(this);
|
||||||
|
opPermissionLevel.Init(this);
|
||||||
|
functionPermissionLevel.Init(this);
|
||||||
|
maxTickTime.Init(this);
|
||||||
|
viewDistance.Init(this);
|
||||||
|
maxPlayers.Init(this);
|
||||||
|
networkCompressionThreshold.Init(this);
|
||||||
|
broadcastRconToOps.Init(this);
|
||||||
|
broadcastConsoleToOps.Init(this);
|
||||||
|
maxWorldSize.Init(this);
|
||||||
|
syncChunkWrites.Init(this);
|
||||||
|
enableJmxMonitoring.Init(this);
|
||||||
|
enableStatus.Init(this);
|
||||||
|
entityBroadcastRangePercentage.Init(this);
|
||||||
|
playerIdleTimeout.Init(this);
|
||||||
|
whiteList.Init(this);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void Load();
|
||||||
|
void Save();
|
||||||
private:
|
private:
|
||||||
std::unordered_map<string, string> properties;
|
const char* path;
|
||||||
};
|
};
|
||||||
}
|
}
|
Loading…
Reference in New Issue