#pragma once #include #include #include #include #include using CRSMConfigException = std::logic_error; namespace CRSMConfigValueType { enum Type { None, String, Integer, Boolean, List, Map }; } class CRSMConfigValueBase { public: virtual void setValue(const QString&) { } virtual QString value() { return ""; } virtual CRSMConfigValueType::Type type() { return CRSMConfigValueType::Type::None; } }; template class CRSMConfigValue : public CRSMConfigValueBase { public: // CRSMConfigValue(Type&) { } virtual void setValue(const QString&) { throw CRSMConfigException("Cannot assign"); } virtual QString value() { throw CRSMConfigException("Cannot get the value"); } }; using String = QString; using Integer = int; using Boolean = bool; #define List(Type) QList #define Map(KeyType, ValueType) QMap template<> class CRSMConfigValue : public CRSMConfigValueBase { String& config; public: CRSMConfigValue(String& config) : config(config) { } virtual void setValue(const QString& value) { config = value; } virtual QString value() { return config; } virtual CRSMConfigValueType::Type type() { return CRSMConfigValueType::Type::String; } }; template<> class CRSMConfigValue : public CRSMConfigValueBase { Integer& config; public: CRSMConfigValue(Integer& config) : config(config) { } virtual void setValue(const QString& value) { bool ok = true; Integer val = value.toInt(&ok, 0); if(!ok) throw CRSMConfigException("\"" + value.toStdString() + "\" could not be parsed as an Integer"); config = val; } virtual QString value() { return QString::number(config); } virtual CRSMConfigValueType::Type type() { return CRSMConfigValueType::Type::Integer; } }; template<> class CRSMConfigValue : public CRSMConfigValueBase { Boolean& config; public: CRSMConfigValue(Boolean& config) : config(config) { } virtual void setValue(const QString& value) { if(value == "true") { config = true; } else if(value == "false") { config = false; } else { throw CRSMConfigException("\"" + value.toStdString() + "\" could not be parsed as a Boolean"); } } virtual QString value() { return config ? "true" : "false"; } virtual CRSMConfigValueType::Type type() { return CRSMConfigValueType::Type::Boolean; } }; class CRSMConfigValueList : public CRSMConfigValueBase { public: virtual void append(const QString& entry) = 0; virtual QStringList getValues() = 0; }; class CRSMConfigValueMap : public CRSMConfigValueBase { public: virtual void setKeyValue(const QString& key, const QString& value) = 0; virtual QMap getValues() = 0; }; template class CRSMConfigValue> : public CRSMConfigValueList { using ListType = QList; ListType& config; public: CRSMConfigValue(ListType& config) : config(config) {} virtual ListType& list() { return config; } virtual CRSMConfigValueType::Type type() { return CRSMConfigValueType::Type::List; } virtual void append(const QString &entry) { Type val; CRSMConfigValue configValue(val); configValue.setValue(entry); if(!config.contains(val)) { config.append(val); } } virtual QStringList getValues() { QStringList ret; foreach(Type val, config) { CRSMConfigValue value(val); ret.append(value.value()); } return ret; } }; template class CRSMConfigValue> : public CRSMConfigValueMap { using MapType = QMap; MapType& config; public: CRSMConfigValue(MapType& config) : config(config) {} virtual MapType& map() { return config; } virtual CRSMConfigValueType::Type type() { return CRSMConfigValueType::Type::Map; } virtual void setKeyValue(const QString& key, const QString& value) { KeyType keyVal; CRSMConfigValue keyConfigValue(keyVal); keyConfigValue.setValue(key); ValueType valueVal; CRSMConfigValue valueConfigValue(valueVal); valueConfigValue.setValue(value); config[keyVal] = valueVal; } virtual QMap getValues() { QMap ret; foreach(KeyType key, config.keys()) { CRSMConfigValue keyValue(key); CRSMConfigValue valValue(config[key]); ret[keyValue.value()] = valValue.value(); } return ret; } }; template CRSMConfigValue* mkConfigValue(Type& Value) { return new CRSMConfigValue(Value); } class CRSMConfig { public: struct { Integer ManagementPort = 9372; String ListFolder = "ScenarioLists"; } CRSM; struct { struct { String Arguments = "/fullscreen /lobby:300 /nosignup Objects.c4d"; String Config = "config"; String Executable = "clonk-server"; List(String) IgnoreFolders = {"Network", "Records.c4f", "Savegames.c4f"}; Integer EmptyTimer = 60; } Server; struct { struct { Integer Count = 5; Integer Time = 3; } AntiFlood; Map(Integer, String) Moderators; Integer RegainAdminTime = 120; } Chat; } Clonk; struct { Boolean Auto = true; Boolean RandomizeAuto = true; Integer MaxWishesPerScen = 2; Integer MaxWishesPerUser = 2; Integer UserListLength = 5; Map(String, String) Alias; } Hosting; struct { Boolean Use = false; String Server = "irc.euirc.net"; String Nick = "CRSM"; String Password = ""; String RealName = "Dedicated Clonk server powered by CRSM"; String Channel = "#crsm"; Boolean UseIngameChat = false; String IngameChannel = "#crsm-ingame"; String QuitMessage = "Dedicated Clonk server powered by CRSM"; Integer ReconnectDelay = 10; String ScenListMessage = "A list of available scenarios is available ingame or in a lobby."; Map(String, String) Moderators; } IRC; struct { struct { String ReattachId = ""; } ProcessManager; struct { struct { String Directory; String ServerNick; String ServerPCName; } Clonk; } Volatile; struct { Map(String, String) AliasWishes; } Hosting; } Auto; struct { Boolean ServerUses = false; Boolean PromptEnabled = false; Integer RereadLimit = 50; } Readline; explicit CRSMConfig(); void setConfigValue(const QString& name, const QString& value); void addConfigListEntry(const QString& name, const QString& value); void setConfigMapValue(const QString& name, const QString& key, const QString& value); QString read(const QString& fileName); bool write(const QString& fileName); void clear(); protected: void addConfigValue(QString name, CRSMConfigValueBase *value); CRSMConfigValueBase& getConfigValue(const QString &name); private: #define ConfigValue(Value) {#Value, mkConfigValue(Value)} QMap configValues { ConfigValue(CRSM.ManagementPort), ConfigValue(CRSM.ListFolder), ConfigValue(Clonk.Server.Arguments), ConfigValue(Clonk.Server.Config), ConfigValue(Clonk.Server.Executable), ConfigValue(Clonk.Server.EmptyTimer), ConfigValue(Clonk.Server.IgnoreFolders), ConfigValue(Clonk.Chat.AntiFlood.Count), ConfigValue(Clonk.Chat.AntiFlood.Time), ConfigValue(Clonk.Chat.Moderators), ConfigValue(Clonk.Chat.RegainAdminTime), ConfigValue(Hosting.Auto), ConfigValue(Hosting.RandomizeAuto), ConfigValue(Hosting.MaxWishesPerScen), ConfigValue(Hosting.MaxWishesPerUser), ConfigValue(Hosting.UserListLength), ConfigValue(Hosting.Alias), ConfigValue(IRC.Use), ConfigValue(IRC.Server), ConfigValue(IRC.Nick), ConfigValue(IRC.Password), ConfigValue(IRC.RealName), ConfigValue(IRC.Channel), ConfigValue(IRC.UseIngameChat), ConfigValue(IRC.IngameChannel), ConfigValue(IRC.QuitMessage), ConfigValue(IRC.ReconnectDelay), ConfigValue(IRC.ScenListMessage), ConfigValue(IRC.Moderators), ConfigValue(Auto.ProcessManager.ReattachId), ConfigValue(Auto.Hosting.AliasWishes), ConfigValue(Readline.ServerUses), ConfigValue(Readline.PromptEnabled), ConfigValue(Readline.RereadLimit) }; #undef ConfigValue }; #undef String #undef Integer #undef Boolean #undef List #undef Map