82 lines
3.8 KiB
GDScript
82 lines
3.8 KiB
GDScript
class_name ServerSettings
|
|
extends RefCounted
|
|
|
|
const DEFAULTS := {"server_name": "BLOCKLINE Dedicated", "bind": "0.0.0.0", "port": 27840,
|
|
"mode": "TDM", "map": "quarry", "max_players": 8, "bots": 8, "difficulty": 1, "score_limit": 50,
|
|
"time_limit": 600, "round_delay": 10, "discovery": true}
|
|
const RANGES := {"port": [1024, 65535], "max_players": [2, 8], "bots": [0, 8],
|
|
"difficulty": [0, 3], "score_limit": [1, 200], "time_limit": [60, 1800], "round_delay": [3, 120]}
|
|
const OPTIONS := {"name": "server_name", "bind": "bind", "port": "port", "mode": "mode", "map": "map",
|
|
"max-players": "max_players", "bots": "bots", "difficulty": "difficulty",
|
|
"score-limit": "score_limit", "time-limit": "time_limit", "round-delay": "round_delay", "discovery": "discovery"}
|
|
|
|
static func validate(settings: Dictionary) -> String:
|
|
for key in settings:
|
|
if not DEFAULTS.has(key):
|
|
return "Unbekannte Einstellung: " + str(key)
|
|
for key in RANGES:
|
|
var value: Variant = settings.get(key)
|
|
if not (value is int or value is float) or not is_finite(float(value)) or float(value) != floor(float(value)):
|
|
return "%s muss eine ganze Zahl sein." % key
|
|
if value < RANGES[key][0] or value > RANGES[key][1]:
|
|
return "%s muss zwischen %s und %s liegen." % [key, RANGES[key][0], RANGES[key][1]]
|
|
if settings.bots > settings.max_players:
|
|
return "bots darf max_players nicht uebersteigen."
|
|
if settings.port == LanDiscovery.DISCOVERY_PORT:
|
|
return "UDP 27841 ist fuer die LAN-Suche reserviert."
|
|
if not settings.get("server_name") is String or settings.server_name.strip_edges().is_empty() or settings.server_name.length() > 40:
|
|
return "server_name muss 1 bis 40 Zeichen enthalten."
|
|
if not settings.get("bind") is String or not settings.bind.is_valid_ip_address() or settings.bind.contains(":"):
|
|
return "bind muss eine lokale IPv4-Adresse sein (z.B. 0.0.0.0)."
|
|
if settings.get("mode") not in ["TDM", "FFA", "DOM", "KC"]:
|
|
return "mode muss TDM, FFA, DOM oder KC sein."
|
|
if settings.get("map", "quarry") not in MapCatalog.IDS:
|
|
return "map muss quarry oder dust2 sein."
|
|
if not settings.get("discovery") is bool:
|
|
return "discovery muss true oder false sein."
|
|
return ""
|
|
|
|
static func read(args: PackedStringArray) -> Dictionary:
|
|
var path := "res://server.json"
|
|
for arg in args:
|
|
if arg.begins_with("--config="):
|
|
path = arg.trim_prefix("--config=")
|
|
if not FileAccess.file_exists(path):
|
|
return {"error": "Konfiguration fehlt: " + path}
|
|
var parser := JSON.new()
|
|
if parser.parse(FileAccess.get_file_as_string(path)) != OK or not parser.data is Dictionary:
|
|
return {"error": "Ungueltiges JSON in " + path + ": " + parser.get_error_message()}
|
|
var settings := DEFAULTS.duplicate()
|
|
settings.merge(parser.data, true)
|
|
var result := {"settings": settings, "error": "", "run_for": 0, "stop_file": ""}
|
|
for arg in args:
|
|
if arg == "--dedicated" or arg.begins_with("--config="):
|
|
continue
|
|
var split := arg.find("=")
|
|
if not arg.begins_with("--") or split < 3:
|
|
return {"error": "Option muss --name=wert verwenden: " + arg}
|
|
var option := arg.substr(2, split - 2)
|
|
var value := arg.substr(split + 1)
|
|
if option == "stop-file":
|
|
result.stop_file = value
|
|
elif option == "run-for":
|
|
if not value.is_valid_int() or int(value) < 1 or int(value) > 86400:
|
|
return {"error": "run-for muss 1 bis 86400 Sekunden sein."}
|
|
result.run_for = int(value)
|
|
elif OPTIONS.has(option):
|
|
var key: String = OPTIONS[option]
|
|
if RANGES.has(key):
|
|
if not value.is_valid_int():
|
|
return {"error": option + " muss eine ganze Zahl sein."}
|
|
settings[key] = int(value)
|
|
elif key == "discovery":
|
|
if value not in ["true", "false"]:
|
|
return {"error": "discovery muss true oder false sein."}
|
|
settings[key] = value == "true"
|
|
else:
|
|
settings[key] = value
|
|
else:
|
|
return {"error": "Unbekannte Option: " + option}
|
|
result.error = validate(settings)
|
|
return result
|