inputs: { config, lib, pkgs, ... }: with lib; let cfg = config.gaming; sunshineSrc = pkgs.fetchFromGitHub { owner = "loki-47-6F-64"; repo = "sunshine"; rev = "e4c9c292e57d39136df2d46d1e9b66eba53f3bd3"; sha256 = "sha256-YrQHHpw7GOcdlnyJI28VShYFrTRq7kpILnkyCYf77NE="; fetchSubmodules = true; }; sunshineAssets = pkgs.runCommandNoCC "sunshine-assets" { } '' cp -r ${sunshineSrc}/assets $out ''; sunshine = pkgs.stdenv.mkDerivation { name = "sunshine"; src = sunshineSrc; cmakeFlags = [ "-DSUNSHINE_ASSETS_DIR=assets" "-DSUNSHINE_DEFAULT_DIR=${sunshineAssets}" ]; postPatch = '' substituteInPlace CMakeLists.txt \ --replace '/usr/include/libevdev-1.0' '${pkgs.libevdev}/include/libevdev-1.0' ''; installPhase = '' mkdir -p $out/bin cp sunshine $out/bin mkdir -p $out/etc cp -r ../assets $out/etc ''; postFixup = '' wrapProgram $out/bin/sunshine --prefix LD_LIBRARY_PATH ":" "/run/opengl-driver/lib" ''; nativeBuildInputs = with pkgs; [ cmake pkgconfig makeWrapper ]; hardeningDisable = [ "format" ]; buildInputs = with pkgs; [ icu openssl (boost.override { enableShared = false; enableStatic = true; }) wayland valgrind libffi ffmpeg libevdev libcap libdrm libpulseaudio libopus cudaPackages_11_4.cudatoolkit xorg.libXrandr xorg.libXfixes xorg.libXtst xorg.libxcb ]; }; in { options.gaming = { enable = mkEnableOption "Enable gaming stuff"; newWine = mkOption { type = types.bool; default = false; description = "If you want to include wine-staging as new-wine"; }; sunshineService = mkOption { type = types.bool; description = "Enable sunshine game streaming service"; }; steamService = mkOption { type = types.bool; description = "Enable running steam as a service"; }; scService = mkOption { type = types.bool; description = "Enable running sc-controller as a service. This integrates with steamService to make sure your steam controller will continuously be mapped."; }; }; config = mkIf cfg.enable { gaming.sunshineService = mkOptionDefault false; gaming.steamService = mkOptionDefault cfg.sunshineService; gaming.scService = mkOptionDefault cfg.steamService; home.sessionVariables = { STAGING_RT_PRIORITY_SERVER = 90; }; home.packages = let newwine = (pkgs.wineFull.override { wineBuild = "wineWow"; wineRelease = "staging"; }); newwinetricks = pkgs.winetricks.overrideAttrs (old: rec { pathAdd = "${newwine}/bin:" + old.pathAdd; postInstall = '' sed -i \ -e '2i PATH="${pathAdd}"' \ "$out/bin/winetricks" ''; }); oldwine = pkgs.wineWowPackages.full; oldwinetricks = pkgs.winetricks.overrideAttrs (old: rec { pathAdd = "${oldwine}/bin:" + old.pathAdd; postInstall = '' sed -i \ -e '2i PATH="${pathAdd}"' \ "$out/bin/winetricks" ''; }); in with pkgs; [ oldwine oldwinetricks sc-controller dolphinEmuMaster tuxpaint extremetuxracer ] ++ lib.optionals cfg.newWine [ ( pkgs.runCommand "new-wine-stuff" { } '' mkdir -p $out/bin ln -s ${newwine}/bin/wine $out/bin/new-wine ln -s ${newwine}/bin/winecfg $out/bin/new-winecfg ln -s ${newwinetricks}/bin/winetricks $out/bin/new-winetricks '' ) ] ++ lib.optional cfg.steamService (pkgs.writeShellScriptBin "steam" "${pkgs.systemd}/bin/systemctl --user start steam"); systemd.user.services.sunshine = mkIf cfg.sunshineService { Unit = { Description = "Host for Moonlight Streaming Client"; Requires = [ "dbus.service" ]; After = [ "graphical-session-pre.target" "network.target" ]; PartOf = [ "graphical-session.target" ]; }; Install = { WantedBy = [ "graphical-session.target" ]; }; Service = { WorkingDirectory = "${config.xdg.configHome}/sunshine"; Restart = "on-failure"; RestartSec = 3; ExecStart = "${sunshine}/bin/sunshine"; ExecStartPre = let script = pkgs.writeShellScript "sunshine-pre-start" '' ${pkgs.coreutils}/bin/mkdir -p $HOME/.config/sunshine/assets ${pkgs.coreutils}/bin/rm -rf $HOME/.config/sunshine/assets/shaders ${pkgs.coreutils}/bin/rm -rf $HOME/.config/sunshine/assets/web ${pkgs.coreutils}/bin/rm -rf $HOME/.config/sunshine/assets/box.png ${pkgs.coreutils}/bin/cp --no-preserve=all -r ${sunshineAssets}/shaders $HOME/.config/sunshine/assets ${pkgs.coreutils}/bin/cp --no-preserve=all -r ${sunshineAssets}/web $HOME/.config/sunshine/assets ${pkgs.coreutils}/bin/cp --no-preserve=all ${sunshineAssets}/box.png $HOME/.config/sunshine/assets ''; in "${script}"; }; }; systemd.user.services.scc = mkIf cfg.scService { Unit = { Description = "User-mode driver and GTK3 based GUI for Steam Controller"; After = [ "graphical-session-pre.target" ]; PartOf = [ "graphical-session.target" ]; }; Service = { Type = "simple"; ExecStart = "${pkgs.sc-controller}/bin/scc-daemon debug"; Restart = "always"; RestartSec = 5; }; Install = { WantedBy = [ "graphical-session.target" ]; }; }; systemd.user.services.steam = mkIf cfg.steamService { Unit = { Description = "Start Steam gaming platform"; After = [ "graphical-session-pre.target" ]; PartOf = [ "graphical-session.target" ]; }; Service = { Type = "simple"; ExecStart = let steamStart = pkgs.writeShellScript "steam-start" '' ${pkgs.systemd}/bin/systemctl --user stop scc # no sleep is needed here because steam is slow as fuck lol /run/current-system/sw/bin/steam -fulldesktopres ''; in lib.mkIf cfg.scService "${steamStart}"; ExecStop = let steamStop = pkgs.writeShellScript "steam-stop" '' ${pkgs.coreutils}/bin/sleep 5 # give time for controller to reset ${pkgs.systemd}/bin/systemctl --user start scc ''; in lib.mkIf cfg.scService "${steamStop}"; }; Install = { WantedBy = [ "graphical-session.target" ]; }; }; }; }