···
-
{ lib, config, pkgs, ... } @ args:
-
isEnabled = config.modules.games.enable && config.modules.games.palworld.enable;
-
baseCfg = config.modules.games;
-
cfg = config.modules.games.palworld;
-
name = "palworld-server";
-
scripts = (import ./lib/scripts.nix) args;
-
generateSettings = name: value: let
-
optType = builtins.typeOf optVal;
-
else if optType == "bool"
-
in "${optName}=${encodedVal}")
-
builtins.toFile name ''
-
[/Script/Pal.PalGameWorldSettings]
-
OptionSettings=(${concatStringsSep "," optionSettings})
-
ServerName = "Unnamed Server";
-
AllowConnectPlatform = "Steam";
-
CoopPlayerMaxNum = cfg.maxPlayers;
-
bIsUseBackupSaveData = true;
-
RESTAPIEnabled = false;
-
Paths=../../../Engine/Content
-
Paths=../../../Engine/Plugins/2D/Paper2D/Content
-
Paths=../../../Engine/Plugins/Animation/ControlRigSpline/Content
-
Paths=../../../Engine/Plugins/Animation/ControlRig/Content
-
Paths=../../../Engine/Plugins/Animation/IKRig/Content
-
Paths=../../../Engine/Plugins/Animation/MotionWarping/Content
-
Paths=../../../Engine/Plugins/Bridge/Content
-
Paths=../../../Engine/Plugins/Compositing/Composure/Content
-
Paths=../../../Engine/Plugins/Compositing/OpenColorIO/Content
-
Paths=../../../Engine/Plugins/Developer/AnimationSharing/Content
-
Paths=../../../Engine/Plugins/Developer/Concert/ConcertSync/ConcertSyncClient/Content
-
Paths=../../../Engine/Plugins/Editor/BlueprintHeaderView/Content
-
Paths=../../../Engine/Plugins/Editor/GeometryMode/Content
-
Paths=../../../Engine/Plugins/Editor/ModelingToolsEditorMode/Content
-
Paths=../../../Engine/Plugins/Editor/ObjectMixer/LightMixer/Content
-
Paths=../../../Engine/Plugins/Editor/ObjectMixer/ObjectMixer/Content
-
Paths=../../../Engine/Plugins/Editor/SpeedTreeImporter/Content
-
Paths=../../../Engine/Plugins/Enterprise/DatasmithContent/Content
-
Paths=../../../Engine/Plugins/Enterprise/GLTFExporter/Content
-
Paths=../../../Engine/Plugins/Experimental/ChaosCaching/Content
-
Paths=../../../Engine/Plugins/Experimental/ChaosClothEditor/Content
-
Paths=../../../Engine/Plugins/Experimental/ChaosNiagara/Content
-
Paths=../../../Engine/Plugins/Experimental/ChaosSolverPlugin/Content
-
Paths=../../../Engine/Plugins/Experimental/CommonUI/Content
-
Paths=../../../Engine/Plugins/Experimental/Dataflow/Content
-
Paths=../../../Engine/Plugins/Experimental/FullBodyIK/Content
-
Paths=../../../Engine/Plugins/Experimental/GeometryCollectionPlugin/Content
-
Paths=../../../Engine/Plugins/Experimental/GeometryFlow/Content
-
Paths=../../../Engine/Plugins/Experimental/ImpostorBaker/Content
-
Paths=../../../Engine/Plugins/Experimental/Landmass/Content
-
Paths=../../../Engine/Plugins/Experimental/MeshLODToolset/Content
-
Paths=../../../Engine/Plugins/Experimental/PythonScriptPlugin/Content
-
Paths=../../../Engine/Plugins/Experimental/StaticMeshEditorModeling/Content
-
Paths=../../../Engine/Plugins/Experimental/UVEditor/Content
-
Paths=../../../Engine/Plugins/Experimental/Volumetrics/Content
-
Paths=../../../Engine/Plugins/Experimental/Water/Content
-
Paths=../../../Engine/Plugins/FX/Niagara/Content
-
Paths=../../../Engine/Plugins/JsonBlueprintUtilities/Content
-
Paths=../../../Engine/Plugins/Media/MediaCompositing/Content
-
Paths=../../../Engine/Plugins/Media/MediaPlate/Content
-
Paths=../../../Engine/Plugins/MovieScene/SequencerScripting/Content
-
Paths=../../../Engine/Plugins/PivotTool/Content
-
Paths=../../../Engine/Plugins/PlacementTools/Content
-
Paths=../../../Engine/Plugins/Runtime/AudioSynesthesia/Content
-
Paths=../../../Engine/Plugins/Runtime/AudioWidgets/Content
-
Paths=../../../Engine/Plugins/Runtime/GeometryProcessing/Content
-
Paths=../../../Engine/Plugins/Runtime/Metasound/Content
-
Paths=../../../Engine/Plugins/Runtime/ResonanceAudio/Content
-
Paths=../../../Engine/Plugins/Runtime/SunPosition/Content
-
Paths=../../../Engine/Plugins/Runtime/Synthesis/Content
-
Paths=../../../Engine/Plugins/Runtime/WaveTable/Content
-
Paths=../../../Engine/Plugins/Runtime/WebBrowserWidget/Content
-
Paths=../../../Engine/Plugins/SkyCreatorPlugin/Content
-
Paths=../../../Engine/Plugins/VirtualProduction/CameraCalibrationCore/Content
-
Paths=../../../Engine/Plugins/VirtualProduction/LiveLinkCamera/Content
-
Paths=../../../Engine/Plugins/VirtualProduction/Takes/Content
-
Paths=../../../Engine/Plugins/Web/HttpBlueprint/Content
-
Paths=../../../Pal/Plugins/DLSS/Content
-
Paths=../../../Pal/Plugins/EffectsChecker/Content
-
Paths=../../../Pal/Plugins/HoudiniEngine/Content
-
Paths=../../../Pal/Plugins/PPSkyCreatorPlugin/Content
-
Paths=../../../Pal/Plugins/PocketpairUser/Content
-
Paths=../../../Pal/Plugins/SpreadSheetToCsv/Content
-
Paths=../../../Pal/Plugins/Wwise/Content
-
[/script/onlinesubsystemutils.ipnetdriver]
-
LanServerMaxTickRate=60
-
NetServerMaxTickRate=60
-
[/script/engine.player]
-
ConfiguredInternetSpeed=104857600
-
ConfiguredLanSpeed=104857600
-
[/script/socketsubsystemepic.epicnetdriver]
-
MaxClientRate=104857600
-
MaxInternetClientRate=104857600
-
[/script/engine.engine]
-
SmoothedFrameRateRange=(LowerBound=(Type=Inclusive,Value=30.000000),UpperBound=(Type=Exclusive,Value=60.000000))
-
bUseFixedFrameRate=false
-
NetClientTicksPerSecond=60
-
options.modules.games.palworld = {
-
description = "Whether to enable Palworld Dedicated Server.";
-
default = pkgs.palworld-server;
-
description = "Whether to enable Community Server mode";
-
default = "${baseCfg.datadir}/palworld";
-
type = types.nullOr types.str;
-
maxPlayers = mkOption {
-
config = mkIf isEnabled {
-
modules.router.nftables.capturePorts = [ cfg.port ];
-
networking.firewall.allowedUDPPorts = [ cfg.port ];
-
systemd.tmpfiles.rules = [
-
"d ${cfg.datadir} 0755 ${baseCfg.user} ${baseCfg.group} - -"
-
systemd.services."${name}" = let
-
Pal = "${cfg.package}/Pal";
-
Engine = "${cfg.package}/Engine";
-
settings = baseSettings // cfg.settings;
-
"Pal/Binaries/Linux/steamclient.so" = "${pkgs.steamworks-sdk-redist}/lib/steamclient.so";
-
"Pal/Saved/Config/LinuxServer/PalWorldSettings.ini" = generateSettings "PalWorldSettings.ini" settings;
-
"Pal/Saved/Config/LinuxServer/Engine.ini" = builtins.toFile "Engine.ini" engineSettings;
-
"-port=${toString cfg.port}"
-
"-NoAsyncLoadingThread"
-
"-players=${toString cfg.maxPlayers}"
-
"-NumberOfWorkerThreadsServer=${toString cfg.threads}"
-
++ optionals (cfg.ip != null) [ "-publicip=${cfg.ip}" ]
-
++ optionals cfg.public [ "-publiclobby" ];
-
bin = getExe (pkgs.mkSteamWrapper "${cfg.datadir}/Pal/Binaries/Linux/PalServer-Linux-Shipping");
-
in "${bin} ${concatStringsSep " " args}";
-
wantedBy = mkIf cfg.autostart [ "multi-user.target" ];
-
after = [ "network.target" ];
-
path = with pkgs; [ xdg-user-dirs util-linux ];
-
${scripts.mkDirs name dirs}
-
${scripts.mkFiles name files}
-
Restart = "on-failure";
-
User = "${baseCfg.user}";
-
Group = "${baseCfg.group}";
-
WorkingDirectory = "${cfg.datadir}";
-
CPUQuota = "${toString ((cfg.threads + 1) * 100)}%";
-
ProtectProc = "noaccess";
-
ProtectKernelLogs = true;
-
ProtectKernelModules = true;
-
ProtectKernelTunables = true;
-
RestrictRealtime = true;
-
LockPersonality = true;
-
# Palworld needs namespaces and system calls
-
RestrictNamespaces = false;