Im working on an Windows Classic Desktop application that reads a Minecraft Tekkit settings file line by line and compairs the lines up against an array with settings keys. If the string from the line contains the key the key should be removed from the string and the resulting variable should be used to update an an object's appropriate variable.
Here is the string array with the keys to look for
static string[] tekkitSettingsKeys = {
"generator-settings=",
"op-permission-level=",
"allow-nether=",
"level-name=",
"enable-query=",
"allow-flight=",
"server-port=",
"level-type=",
"enable-rcon=",
"force-gamemode=",
"level-seed=",
"server-ip=",
"max-build-height=",
"spawn-npcs=",
"white-list=",
"spawn-animals=",
"texture-pack=",
"hardcore=",
"snooper-enabled=",
"online-mode=",
"pvp=",
"difficulty=",
"gamemode=",
"player-idle-timeout=",
"max-players=",
"spawn-monsters=",
"generate-structures=",
"view-distance=",
"motd="
};
Here are the variables and the getters and setters for the TekkitServerSettings class
/*
The settings used to customize world generation. See Superflat and Customized for possible settings and examples.
*/
private string _generatorSettings = String.Empty;
/*
Sets permission level for ops.
1 - Ops can bypass spawn protection.
2 - Ops can use /clear, /difficulty, /effect, /gamemode, /gamerule, /give, and /tp, and can edit command blocks.
3 - Ops can use /ban, /deop, /kick, and /op.
4 - Ops can use /stop. DEFAULT
*/
private int _opPermissionLevel = 4;
/*
Allows players to travel to the Nether.
false - Nether portals will not work.
true - The server will allow portals to send players to the Nether.
*/
private bool _allowNether = true;
/*
The "level-name" value will be used as the world name and its folder name. You may also copy your saved game folder here, and change the name to the same as that folder's to load it instead.
Characters such as ' (apostrophe) may need to be escaped by adding a backslash before them.
*/
private string _levelName = "world";
/*
Enables GameSpy4 protocol server listener. Used to get information about server.
*/
private bool _enableQuery = false;
/*
Allows users to use flight on your server while in Survival mode, if they have a mod that provides flight installed.
With allow-flight enabled griefers will possibly be more common, because it will make their work easier. In Creative mode this has no effect.
false - Flight is not allowed (players in air for at least 5 seconds will be kicked).
true - Flight is allowed, and used if the player has a fly mod installed.
*/
private bool _allowFlight = true;
/*
Changes the port the server is hosting (listening) on. This port must be forwarded if the server is hosted in a network using NAT (If you have a home router/firewall).
*/
private int _serverPort = 25565;
/*
Determines the type of map that is generated.
DEFAULT - Standard world with hills, valleys, water, etc.
FLAT - A flat world with no features, meant for building.
LARGEBIOMES - Same as default but all biomes are larger.
AMPLIFIED - Same as default but world-generation height limit is increased.
CUSTOMIZED - Same as default unless generator-settings is set to a preset.
*/
private string _levelType = "DEFAULT";
/*
Enables remote access to the server console.
*/
private bool _enableRcon = false;
/*
Force players to join in the default game mode.
false - Players will join in the gamemode they left in.
true - Players will always join in the default gamemode.
*/
private bool _forceGameMode = false;
/*
Add a seed for your world, as in Singleplayer.
Some examples are: minecraft, 404, 1a2b3c.
*/
private string _levelSeed = String.Empty;
/*
Set this if you want the server to bind to a particular IP. It is strongly recommended that you leave server-ip blank!
Set to blank, or the IP you want your server to run (listen) on.
*/
private string _serverIp = String.Empty;
/*
The maximum height in which building is allowed. Terrain may still naturally generate above a low height limit.
*/
private int _maxBuildHeight = 256;
/*
Determines if villagers will be spawned.
true - Enabled. Villagers will spawn.
false - Disabled. No villagers.
*/
private bool _spawnNpcs = true;
/*
Enables a whitelist on the server.
With a whitelist enabled, users not on the whitelist will be unable to connect. Intended for private servers, such as those for real-life friends or strangers carefully selected via an application process, for example.
false - No white list is used.
true - The file whitelist.json is used to generate the white list.
Note: Ops are automatically white listed, and there is no need to add them to the whitelist.
*/
private bool _whiteList = false;
/*
Determines if animals will be able to spawn.
true - Animals spawn as normal.
false - Animals will immediately vanish.
Tip: if you have major lag, turn this off/set to false.
*/
private bool _spawnAnimals = true;
/*
Server-side texture packs. Provide a link to the zip file */
private string _texturePack = String.Empty;
/*
If set to true, players will be permanently banned if they die.
*/
private bool _hardcore = false;
/*
Sets whether the server sends snoop data regularly to http://snoop.minecraft.net.
false - disable snooping.
true - enable snooping.
*/
private bool _snooperEnabled = true;
/*
Server checks connecting players against minecraft's account database. Only set this to false if your server is not connected to the Internet. Hackers with fake accounts can connect if this is set to false! If minecraft.net is down or inaccessible, no players will be able to connect if this is set to true. Setting this variable to off purposely is called "cracking" a server, and servers that are presently with online mode off are called "cracked" servers, allowing players with unlicensed copies of Minecraft to join.
true - Enabled. The server will assume it has an Internet connection and check every connecting player.
false - Disabled. The server will not attempt to check connecting players.
*/
private bool _onlineMode = true;
/*
Enable PvP on the server. Players shooting themselves with arrows will only receive damage if PvP is enabled.
true - Players will be able to kill each other.
false - Players cannot kill other players (also known as Player versus Environment (PvE)).
Note: Indirect damage sources spawned by players (such as lava, fire, TNT and to some extent water, sand and gravel) will still deal damage to other players.
*/
private bool _pvp = true;
/*
Defines the difficulty (such as damage dealt by mobs and the way hunger and poison affects players) of the server.
0 - Peaceful
1 - Easy
2 - Normal
3 - Hard
*/
private int _difficulty = 1;
/*
Defines the mode of gameplay.
0 - Survival
1 - Creative
2 - Adventure
3 - Spectator
*/
private int _gamemode = 0;
/*
If non-zero, players are kicked from the server if they are idle for more than that many minutes.
Note: Idle time is reset when the server receives one of the following packets:
102 (0x66) WindowClick
108 (0x6c) ButtonClick
130 (0x82) UpdateSign
14 (0xe) BlockDig
15 (0xf) Place
16 (0x10) BlockItemSwitch
18 (0x12) ArmAnimation
19 (0x13) EntityAction
205 (0xcd) ClientCommand
3 (0x3) Chat
7 (0x7) UseEntity
*/
private int _playerIdleTimeout = 0;
/*
The max numbers of players that can play on the server at the same time. Note that if more players are on the server it will use more resources. Note also, admin connections are not counted against the max players.
*/
private int _maxPlayers = 20;
/*
Determines if monsters will be spawned.
true - Enabled. Monsters will appear at night and in the dark.
false - Disabled. No monsters.
This does nothing if difficulty = 0 (peaceful) Unless your difficulty is not set to 0, when a monster can still spawn from a Monster Spawner. Tip: if you have major lag, turn this off/set to false.
*/
private bool _spawnMonsters = true;
/*
Defines whether structures (such as villages) will be generated.
false - Structures will not be generated in new chunks.
true - Structures will be generated in new chunks.
Note: Dungeons will still generate if this is set to false.
*/
private bool _generateStructures = true;
/*
Sets the amount of world data the server sends the client, measured in chunks in each direction of the player (radius, not diameter). It determines the server-side viewing distance. (see Render distance)
10 is the default/recommended. If you have major lag, reduce this value.
*/
private int _viewDistance = 10;
/*
MOTD is short for Message of the day, though you do not need to change it every day. The MOTD is displayed when people join the server.
*/
private string _motd = "A Tekkit Server";
public string GeneratorSettings
{
get { return _generatorSettings; }
set { _generatorSettings = value; }
}
public int OpPermissionLevel
{
get { return _opPermissionLevel; }
set { _opPermissionLevel = value; }
}
public string AllowNether
{
get { return _allowNether ? "true" : "false"; }
set { _allowNether = value == "true" ? true : false; }
}
public string LevelName
{
get { return _levelName; }
set { _levelName = value; }
}
public string EnableQuery
{
get { return _enableQuery ? "true" : "false"; }
set { _enableQuery = value == "true" ? true : false; }
}
public string AllowFlight
{
get { return _allowFlight ? "true" : "false"; }
set { _allowFlight = value == "true" ? true : false; }
}
public int ServerPort
{
get { return _serverPort; }
set { _serverPort = value; }
}
public string LevelType
{
get { return _levelType; }
set { _levelType = value; }
}
public string EnableRcon
{
get { return _enableRcon ? "true" : "false"; }
set { _enableRcon = value == "true" ? true : false; }
}
public string ForceGameMode
{
get { return _forceGameMode ? "true" : "false"; }
set { _forceGameMode = value == "true" ? true : false; }
}
public string LevelSeed
{
get { return _levelSeed; }
set { _levelSeed = value; }
}
public string ServerIp
{
get { return _serverIp; }
set { _serverIp = value; }
}
public int MaxBuildHeight
{
get { return _maxBuildHeight; }
set { _maxBuildHeight = value; }
}
public string SpawnNpcs
{
get { return _spawnNpcs ? "true" : "false"; }
set { _spawnNpcs = value == "true" ? true : false; }
}
public string WhiteList
{
get { return _whiteList ? "true" : "false"; }
set { _whiteList = value == "true" ? true : false; }
}
public string SpawnAnimals
{
get { return _spawnAnimals ? "true" : "false"; }
set { _spawnAnimals = value == "true" ? true : false; }
}
public string TexturePack
{
get { return _texturePack; }
set { _texturePack = value; }
}
public string HardCode
{
get { return _hardcore ? "true" : "false"; }
set { _hardcore = value == "true" ? true : false; }
}
public string SnooperEnabled
{
get { return _snooperEnabled ? "true" : "false"; }
set { _snooperEnabled = value == "true" ? true : false; }
}
public string OnlineMode
{
get { return _onlineMode ? "true" : "false"; }
set { _onlineMode = value == "true" ? true : false; }
}
public string PVP
{
get { return _pvp ? "true" : "false"; }
set { _pvp = value == "true" ? true : false; }
}
public int Difficulty
{
get { return _difficulty; }
set { _difficulty = value; }
}
public int GameMode
{
get { return _gamemode; }
set { _gamemode = value; }
}
public int PlayerIdleTimeout
{
get { return _playerIdleTimeout; }
set { _playerIdleTimeout = value; }
}
public int MaxPlayers
{
get { return _maxPlayers; }
set { _maxPlayers = value; }
}
public string SpawnMonsters
{
get { return _spawnMonsters ? "true" : "false"; }
set { _spawnMonsters = value == "true" ? true : false; }
}
public string GenerateStructures
{
get { return _generateStructures ? "true" : "false"; }
set { _generateStructures = value == "true" ? true : false; }
}
public int ViewDistance
{
get { return _viewDistance; }
set { _viewDistance = value; }
}
public string Motd
{
get { return _motd; }
set { _motd = value; }
}
Below is the method that eventually should read the file, check it line by line if it contains one of the strings from the tekkitSettingsKeys, update the TekkitServerSettings object's appropriate setter and return the TekkitServerSettings object
public static TekkitServerSettings Load(string settingsFilePath)
{
TekkitServerSettings serverSettingsToLoad = new TekkitServerSettings();
string[] linesFromSettingsFile = File.ReadAllLines(settingsFilePath);
foreach (string tekkitSettingsKey in tekkitSettingsKeys)
{
foreach (string lineFromSettingsFile in linesFromSettingsFile)
{
if (lineFromSettingsFile.Contains(tekkitSettingsKey))
{
// Remove the key from the line
var settingValue = lineFromSettingsFile.Replace(tekkitSettingsKey,"");
// update serverSettingsToLoad's value with the appropriate value in an elegant manner.
??
}
}
}
// Check that everything is good
// return the object
}
I have to somehow know the setter i have to update, and i believe there is a somewhat more elegant way to accomplish this rather than make a bunch of if/else statements or a huge switch?
Example
When it runs the second foreach it reads that the string level-type=DEFAULT
contains level-type=
. It removes level-type=
and ends up with settingValue = "DEFAULT"
.
I now have the value and i know that the key is level-type=
. Somehow i want to accomplish serverSettingsToLoad.LevelType = "DEFAULT"
and so forth.
Any suggestions on how to accomplish what i want in the best way? Maybe the way i have set this up to start with isnt the best way?
Thanks!
A simple dictionary will do:
class TekkitServerSettings
{
private readonly static Dictionary<string, Action<TekkitServerSettings, string>>
_settingSetters =
new Dictionary<string, Action<TekkitServerSettings, string>>()
{
{ "generator-settings=", (s, v) => s.GeneratorSettings = v },
{ "op-permission-level=", (s, v) => s.OpPermissionLevel = int.Parse(v) }
};
public string GeneratorSettings { get; set; }
public int OpPermissionLevel { get; set; }
}
This allows you to load the settings simply by finding the appropriate setter action. Of course, you'll probably want some helper methods (something to handle errors the way you want, for example).
The usage is as simple as
if (_settingSetters.ContainsKey(tekkitSettingsKey))
{
_settingSetters[tekkitSettingsKey](serverSettingsToLoad, settingValue);
}
There's plenty of tweaks you'll want to do, of course. For example, you might make the dictionary case-insensitive, or you might want to add some error handling that will tell the user what's broken in his config file (for example, "'5' is an invalid value for op-permissions-level" or "'4x' is an invalid value for op-permissions-level").
Note that I assume you're reading the config file line-by-line, setting any known settings as you go. There's little point in going through the file again and again just to find one of the unordered lines. Just go line-by-line, and search for the setting in the dictionary - it's much faster, and much cleaner.