about summary refs log tree commit diff
path: root/nixos
diff options
context:
space:
mode:
authorKevin Cox <kevincox@kevincox.ca>2023-06-29 07:36:04 -0400
committerGitHub <noreply@github.com>2023-06-29 07:36:04 -0400
commit65365bbb8387ffdd4ad228a93125fb91ea2bc758 (patch)
tree53284afa0d99cad2950d4e5d25ce0ee25465a640 /nixos
parent5619360467972b38b361a6d784a6c2025ca46ef3 (diff)
parent6cb0b6a4d63bab23bb5cd460561bf60b701db48b (diff)
Merge pull request #240417 from kevincox/minetest-conf
nixos.minetest-server: Add option for generating config file and ability to add extra command line flags
Diffstat (limited to 'nixos')
-rw-r--r--nixos/modules/services/games/minetest-server.nix71
1 files changed, 63 insertions, 8 deletions
diff --git a/nixos/modules/services/games/minetest-server.nix b/nixos/modules/services/games/minetest-server.nix
index 578364ec542bb..8dc3601534973 100644
--- a/nixos/modules/services/games/minetest-server.nix
+++ b/nixos/modules/services/games/minetest-server.nix
@@ -3,15 +3,52 @@
 with lib;
 
 let
+  CONTAINS_NEWLINE_RE = ".*\n.*";
+  # The following values are reserved as complete option values:
+  # { - start of a group.
+  # """ - start of a multi-line string.
+  RESERVED_VALUE_RE = "[[:space:]]*(\"\"\"|\\{)[[:space:]]*";
+  NEEDS_MULTILINE_RE = "${CONTAINS_NEWLINE_RE}|${RESERVED_VALUE_RE}";
+
+  # There is no way to encode """ on its own line in a Minetest config.
+  UNESCAPABLE_RE = ".*\n\"\"\"\n.*";
+
+  toConfMultiline = name: value:
+    assert lib.assertMsg
+      ((builtins.match UNESCAPABLE_RE value) == null)
+      ''""" can't be on its own line in a minetest config.'';
+    "${name} = \"\"\"\n${value}\n\"\"\"\n";
+
+  toConf = values:
+    lib.concatStrings
+      (lib.mapAttrsToList
+        (name: value: {
+          bool = "${name} = ${toString value}\n";
+          int = "${name} = ${toString value}\n";
+          null = "";
+          set = "${name} = {\n${toConf value}}\n";
+          string =
+            if (builtins.match NEEDS_MULTILINE_RE value) != null
+            then toConfMultiline name value
+            else "${name} = ${value}\n";
+        }.${builtins.typeOf value})
+        values);
+
   cfg   = config.services.minetest-server;
-  flag  = val: name: optionalString (val != null) "--${name} ${toString val} ";
+  flag  = val: name: lib.optionals (val != null) ["--${name}" "${toString val}"];
+
   flags = [
-    (flag cfg.gameId "gameid")
-    (flag cfg.world "world")
-    (flag cfg.configPath "config")
-    (flag cfg.logPath "logfile")
-    (flag cfg.port "port")
-  ];
+    "--server"
+  ]
+    ++ (
+      if cfg.configPath != null
+      then ["--config" cfg.configPath]
+      else ["--config" (builtins.toFile "minetest.conf" (toConf cfg.config))])
+    ++ (flag cfg.gameId "gameid")
+    ++ (flag cfg.world "world")
+    ++ (flag cfg.logPath "logfile")
+    ++ (flag cfg.port "port")
+    ++ cfg.extraArgs;
 in
 {
   options = {
@@ -55,6 +92,16 @@ in
         '';
       };
 
+      config = mkOption {
+        type = types.attrsOf types.anything;
+        default = {};
+        description = lib.mdDoc ''
+          Settings to add to the minetest config file.
+
+          This option is ignored if `configPath` is set.
+        '';
+      };
+
       logPath = mkOption {
         type        = types.nullOr types.path;
         default     = null;
@@ -75,6 +122,14 @@ in
           If set to null, the default 30000 will be used.
         '';
       };
+
+      extraArgs = mkOption {
+        type = types.listOf types.str;
+        default = [];
+        description = lib.mdDoc ''
+          Additional command line flags to pass to the minetest executable.
+        '';
+      };
     };
   };
 
@@ -100,7 +155,7 @@ in
       script = ''
         cd /var/lib/minetest
 
-        exec ${pkgs.minetest}/bin/minetest --server ${concatStrings flags}
+        exec ${pkgs.minetest}/bin/minetest ${lib.escapeShellArgs flags}
       '';
     };
   };