mirror of
https://github.com/gensokyo-zone/infrastructure.git
synced 2026-02-09 12:29:19 -08:00
feat(steam): mkbeatsaber
This commit is contained in:
parent
46c6fbc8c1
commit
fc11fb8152
18 changed files with 891 additions and 44 deletions
111
modules/nixos/steam/account-switch.nix
Normal file
111
modules/nixos/steam/account-switch.nix
Normal file
|
|
@ -0,0 +1,111 @@
|
|||
{
|
||||
config,
|
||||
lib,
|
||||
inputs,
|
||||
pkgs,
|
||||
...
|
||||
}: let
|
||||
inherit (inputs.self.lib.lib) userIs;
|
||||
inherit (lib.options) mkOption mkEnableOption;
|
||||
inherit (lib.modules) mkIf mkMerge mkDefault mkOptionDefault;
|
||||
inherit (lib.attrsets) filterAttrs mapAttrsToList listToAttrs nameValuePair;
|
||||
inherit (lib.lists) singleton;
|
||||
cfg = config.services.steam.accountSwitch;
|
||||
in {
|
||||
options.services.steam.accountSwitch = with lib.types; {
|
||||
enable = mkEnableOption "steam-account-switch";
|
||||
setup = mkEnableOption "steam-account-switch data";
|
||||
group = mkOption {
|
||||
type = str;
|
||||
default = "steamaccount";
|
||||
};
|
||||
sharePath = mkOption {
|
||||
type = str;
|
||||
};
|
||||
rootDir = mkOption {
|
||||
type = path;
|
||||
};
|
||||
binDir = mkOption {
|
||||
type = path;
|
||||
default = cfg.rootDir + "/bin";
|
||||
};
|
||||
gamesDir = mkOption {
|
||||
type = path;
|
||||
default = cfg.rootDir + "/games";
|
||||
};
|
||||
dataDir = mkOption {
|
||||
type = path;
|
||||
default = cfg.rootDir + "/data";
|
||||
};
|
||||
sharedDataDir = mkOption {
|
||||
type = path;
|
||||
default = cfg.dataDir + "/shared";
|
||||
};
|
||||
workingDir = mkOption {
|
||||
type = path;
|
||||
default = cfg.rootDir + "/working";
|
||||
};
|
||||
sharedWorkingDir = mkOption {
|
||||
type = path;
|
||||
default = cfg.workingDir + "/shared";
|
||||
};
|
||||
users = mkOption {
|
||||
type = listOf str;
|
||||
};
|
||||
};
|
||||
|
||||
config = let
|
||||
steamUsers = filterAttrs (_: userIs cfg.group) config.users.users;
|
||||
in {
|
||||
services.steam.accountSwitch = {
|
||||
users = mkOptionDefault (
|
||||
mapAttrsToList (_: user: user.name) steamUsers
|
||||
);
|
||||
};
|
||||
services.tmpfiles = let
|
||||
toplevel = {
|
||||
owner = mkDefault "admin";
|
||||
group = mkDefault cfg.group;
|
||||
mode = mkDefault "3775";
|
||||
};
|
||||
shared = {
|
||||
inherit (toplevel) owner group;
|
||||
mode = "2775";
|
||||
};
|
||||
personal = owner: {
|
||||
inherit owner;
|
||||
inherit (shared) group mode;
|
||||
};
|
||||
setupFiles = singleton {
|
||||
${cfg.rootDir} = toplevel;
|
||||
${cfg.binDir} = toplevel;
|
||||
${cfg.binDir + "/users"} = shared;
|
||||
${cfg.dataDir} = toplevel;
|
||||
${cfg.sharedDataDir} = shared;
|
||||
${cfg.workingDir} = toplevel;
|
||||
${cfg.sharedWorkingDir} = shared;
|
||||
} ++ map (owner: {
|
||||
${cfg.dataDir + "/${owner}"} = personal owner;
|
||||
${cfg.workingDir + "/${owner}"} = personal owner;
|
||||
}) cfg.users;
|
||||
userBinFiles = listToAttrs (map (user: nameValuePair "${cfg.binDir}/users/${user}.bat" {
|
||||
inherit (toplevel) owner group;
|
||||
mode = "0755";
|
||||
type = "copy";
|
||||
src = pkgs.writeTextFile {
|
||||
name = "steam-${user}.bat";
|
||||
executable = true;
|
||||
text = ''
|
||||
setx GENSO_STEAM_USER ${user}
|
||||
'';
|
||||
};
|
||||
}) cfg.users);
|
||||
in {
|
||||
enable = mkIf (cfg.enable || cfg.setup) true;
|
||||
files = mkMerge [
|
||||
(mkIf cfg.setup (mkMerge setupFiles))
|
||||
(mkIf cfg.enable userBinFiles)
|
||||
];
|
||||
};
|
||||
};
|
||||
}
|
||||
269
modules/nixos/steam/beatsaber.nix
Normal file
269
modules/nixos/steam/beatsaber.nix
Normal file
|
|
@ -0,0 +1,269 @@
|
|||
{
|
||||
config,
|
||||
pkgs,
|
||||
lib,
|
||||
inputs,
|
||||
...
|
||||
}: let
|
||||
inherit (inputs.self.lib.lib) mkWinPath userIs;
|
||||
inherit (lib.options) mkOption mkEnableOption;
|
||||
inherit (lib.modules) mkIf mkMerge mkDefault mkOptionDefault;
|
||||
inherit (lib.strings) removePrefix replaceStrings;
|
||||
inherit (lib.attrsets) filterAttrs mapAttrs' mapAttrsToList listToAttrs nameValuePair;
|
||||
inherit (lib.lists) concatMap head singleton;
|
||||
inherit (lib.meta) getExe;
|
||||
inherit (config.services.steam) accountSwitch;
|
||||
cfg = config.services.steam.beatsaber;
|
||||
versionModule = { config, name, ... }: {
|
||||
options = with lib.types; {
|
||||
version = mkOption {
|
||||
type = str;
|
||||
default = name;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
mkSharePath = path: mkWinPath (
|
||||
"%GENSO_SMB_SHARED_MOUNT%"
|
||||
+ "/${accountSwitch.sharePath}"
|
||||
+ "/${removePrefix (accountSwitch.rootDir + "/") path}"
|
||||
);
|
||||
vars = ''
|
||||
if "%GENSO_STEAM_INSTALL%" == "" set "GENSO_STEAM_INSTALL=C:\Program Files (x86)\Steam"
|
||||
if "%GENSO_STEAM_LIBRARY_BS%" == "" set "GENSO_STEAM_LIBRARY_BS=%GENSO_STEAM_INSTALL%"
|
||||
if "%GENSO_STEAM_BS_VERSION%" == "" set "GENSO_STEAM_BS_VERSION=${cfg.defaultVersion}"
|
||||
if "%GENSO_SMB_HOST%" == "" set "GENSO_SMB_HOST=smb.${config.networking.domain}"
|
||||
if "%GENSO_SMB_SHARED_MOUNT%" == "" set "GENSO_SMB_SHARED_MOUNT=\\%GENSO_SMB_HOST%\shared"
|
||||
set "STEAM_BS_LIBRARY=%GENSO_STEAM_LIBRARY_BS%\steamapps\common\Beat Saber"
|
||||
set "STEAM_BS_APPDATA=%USERPROFILE%\AppData\LocalLow\Hyperbolic Magnetism\Beat Saber"
|
||||
set "STEAM_USER_DATA=${mkSharePath accountSwitch.dataDir}\%GENSO_STEAM_USER%"
|
||||
set "STEAM_WORKING_DATA=${mkSharePath accountSwitch.workingDir}\%GENSO_STEAM_USER%"
|
||||
set "STEAM_BINDIR=${mkSharePath accountSwitch.binDir}"
|
||||
if "%GENSO_STEAM_USER%" == "" goto NOUSER
|
||||
'';
|
||||
eof = ''
|
||||
goto:eof
|
||||
|
||||
:NOUSER
|
||||
echo no steam user set
|
||||
'';
|
||||
mount = ''
|
||||
rmdir "%STEAM_BS_APPDATA%"
|
||||
mklink /D "%STEAM_BS_APPDATA%" "%STEAM_USER_DATA%\BeatSaber\AppData"
|
||||
|
||||
rmdir "%STEAM_BS_LIBRARY%"
|
||||
mklink /D "%STEAM_BS_LIBRARY%" "%STEAM_WORKING_DATA%\BeatSaber\%GENSO_STEAM_BS_VERSION%"
|
||||
'';
|
||||
mountbeatsaber = ''
|
||||
${vars}
|
||||
${mount}
|
||||
${eof}
|
||||
'';
|
||||
launchbeatsaber = ''
|
||||
${vars}
|
||||
${mount}
|
||||
cd /d "%STEAM_BS_LIBRARY%"
|
||||
"%STEAM_BS_LIBRARY%\Beat Saber.exe"
|
||||
${eof}
|
||||
'';
|
||||
fpfcbeatsaber = ''
|
||||
${vars}
|
||||
${mount}
|
||||
cd /d "%STEAM_BS_LIBRARY%"
|
||||
"%STEAM_BS_LIBRARY%\Beat Saber.exe" fpfc
|
||||
${eof}
|
||||
'';
|
||||
|
||||
mkbeatsabersh = pkgs.writeShellScriptBin "mkbeatsaber.sh" ''
|
||||
source ${./mkbeatsaber.sh}
|
||||
'';
|
||||
mkbeatsaber = pkgs.writeShellScriptBin "mkbeatsaber" ''
|
||||
set -eu
|
||||
|
||||
ARG_GAME_VERSION=$1
|
||||
shift
|
||||
if [[ $# -gt 0 ]]; then
|
||||
ARG_USER=$1
|
||||
shift
|
||||
else
|
||||
ARG_USER=$(${pkgs.coreutils}/bin/id -un)
|
||||
fi
|
||||
|
||||
cd ${accountSwitch.workingDir}
|
||||
mkdir -m2775 -p "$ARG_USER/BeatSaber/$ARG_GAME_VERSION"
|
||||
chown "$ARG_USER" "$ARG_USER" "$ARG_USER/BeatSaber"
|
||||
cd "$ARG_USER/BeatSaber/$ARG_GAME_VERSION"
|
||||
${getExe mkbeatsabersh} \
|
||||
"${accountSwitch.gamesDir}/BeatSaber" \
|
||||
"$ARG_GAME_VERSION" \
|
||||
"${accountSwitch.sharedDataDir}/BeatSaber" \
|
||||
"${accountSwitch.dataDir}/$ARG_USER/BeatSaber"
|
||||
'';
|
||||
in {
|
||||
options.services.steam.beatsaber = with lib.types; {
|
||||
enable = mkEnableOption "beatsaber scripts";
|
||||
setup = mkEnableOption "beatsaber data" // {
|
||||
default = accountSwitch.setup;
|
||||
};
|
||||
group = mkOption {
|
||||
type = str;
|
||||
default = "beatsaber";
|
||||
};
|
||||
defaultVersion = mkOption {
|
||||
type = str;
|
||||
};
|
||||
versions = mkOption {
|
||||
type = attrsOf (submodule versionModule);
|
||||
default = { };
|
||||
};
|
||||
users = mkOption {
|
||||
type = listOf str;
|
||||
};
|
||||
};
|
||||
|
||||
config = let
|
||||
in {
|
||||
services.steam.beatsaber = let
|
||||
bsUsers = filterAttrs (_: userIs cfg.group) config.users.users;
|
||||
allVersions = mapAttrsToList (_: version: version.version) cfg.versions;
|
||||
in {
|
||||
defaultVersion = mkIf (allVersions != [ ]) (mkOptionDefault (
|
||||
head allVersions
|
||||
));
|
||||
users = mkOptionDefault (
|
||||
mapAttrsToList (_: user: user.name) bsUsers
|
||||
);
|
||||
};
|
||||
environment = mkIf cfg.enable {
|
||||
systemPackages = [
|
||||
mkbeatsaber
|
||||
mkbeatsabersh
|
||||
];
|
||||
};
|
||||
systemd.services = mkIf cfg.setup (listToAttrs (map (user: nameValuePair "steam-setup-beatsaber-${user}" {
|
||||
script = mkMerge (mapAttrsToList (_: version: ''
|
||||
${getExe mkbeatsaber} ${version.version} ${user}
|
||||
'') cfg.versions);
|
||||
path = [
|
||||
pkgs.coreutils
|
||||
];
|
||||
wantedBy = [
|
||||
"multi-user.target"
|
||||
];
|
||||
after = [
|
||||
"tmpfiles.service"
|
||||
];
|
||||
serviceConfig = {
|
||||
RemainAfterExit = mkOptionDefault true;
|
||||
User = mkOptionDefault user;
|
||||
};
|
||||
}) cfg.users));
|
||||
services.tmpfiles = let
|
||||
toplevel = {
|
||||
owner = mkDefault "admin";
|
||||
group = mkDefault cfg.group;
|
||||
mode = mkDefault "3775";
|
||||
};
|
||||
shared = {
|
||||
inherit (toplevel) owner group;
|
||||
mode = mkDefault "2775";
|
||||
};
|
||||
personal = owner: {
|
||||
inherit owner;
|
||||
inherit (shared) group mode;
|
||||
};
|
||||
bin = {
|
||||
inherit (toplevel) owner group;
|
||||
mode = "0755";
|
||||
type = "copy";
|
||||
};
|
||||
sharedFolders = [
|
||||
"CustomAvatars"
|
||||
"CustomLevels"
|
||||
"CustomNotes"
|
||||
"CustomPlatforms"
|
||||
"CustomSabers"
|
||||
"CustomWalls"
|
||||
"AppData"
|
||||
"UserData"
|
||||
];
|
||||
setupFiles = [
|
||||
{
|
||||
"${accountSwitch.sharedDataDir}/BeatSaber" = toplevel;
|
||||
"${accountSwitch.binDir}/beatsaber" = shared;
|
||||
}
|
||||
(listToAttrs (
|
||||
map (folder:
|
||||
nameValuePair "${accountSwitch.sharedDataDir}/BeatSaber/${folder}" shared
|
||||
) sharedFolders
|
||||
))
|
||||
] ++ concatMap (owner:
|
||||
singleton {
|
||||
"${accountSwitch.dataDir}/${owner}/BeatSaber" = personal owner;
|
||||
"${accountSwitch.dataDir}/${owner}/BeatSaber/AppData" = personal owner;
|
||||
"${accountSwitch.dataDir}/${owner}/BeatSaber/UserData" = personal owner;
|
||||
} ++ mapAttrsToList (_: version: {
|
||||
"${accountSwitch.dataDir}/${owner}/BeatSaber/${version.version}" = personal owner;
|
||||
}) cfg.versions
|
||||
) accountSwitch.users
|
||||
++ mapAttrsToList (_: version: {
|
||||
"${accountSwitch.sharedDataDir}/BeatSaber/${version.version}" = shared;
|
||||
}) cfg.versions;
|
||||
versionBinFiles = mapAttrs' (_: version: nameValuePair
|
||||
"${accountSwitch.binDir}/beatsaber/${replaceStrings [ "." ] [ "_" ] version.version}.bat"
|
||||
{
|
||||
inherit (bin) owner group mode type;
|
||||
src = pkgs.writeTextFile {
|
||||
name = "beatsaber-${version.version}.bat";
|
||||
executable = true;
|
||||
text = ''
|
||||
setx GENSO_STEAM_BS_VERSION ${version.version}
|
||||
'';
|
||||
};
|
||||
}
|
||||
) cfg.versions;
|
||||
binFiles = {
|
||||
"${accountSwitch.binDir}/beatsaber/mount.bat" = {
|
||||
inherit (bin) owner group mode type;
|
||||
src = pkgs.writeTextFile {
|
||||
name = "beatsaber-mount.bat";
|
||||
executable = true;
|
||||
text = mountbeatsaber;
|
||||
};
|
||||
};
|
||||
"${accountSwitch.binDir}/beatsaber/launch.bat" = {
|
||||
inherit (bin) owner group mode type;
|
||||
src = pkgs.writeTextFile {
|
||||
name = "beatsaber-launch.bat";
|
||||
executable = true;
|
||||
text = launchbeatsaber;
|
||||
};
|
||||
};
|
||||
"${accountSwitch.binDir}/beatsaber/fpfc.bat" = {
|
||||
inherit (bin) owner group mode type;
|
||||
src = pkgs.writeTextFile {
|
||||
name = "beatsaber-fpfc.bat";
|
||||
executable = true;
|
||||
text = fpfcbeatsaber;
|
||||
};
|
||||
};
|
||||
"${accountSwitch.binDir}/beatsaber/ModAssistant.exe" = {
|
||||
inherit (toplevel) owner group;
|
||||
mode = "0755";
|
||||
type = "copy";
|
||||
src = pkgs.fetchurl {
|
||||
url = "https://github.com/Assistant/ModAssistant/releases/download/v1.1.32/ModAssistant.exe";
|
||||
hash = "sha256-ozu2gYFiz+2BjptqL80DmUopbahbyGKFO1IPd7BhVPM=";
|
||||
executable = true;
|
||||
};
|
||||
};
|
||||
} // versionBinFiles;
|
||||
in {
|
||||
enable = mkIf (cfg.enable || cfg.setup) true;
|
||||
files = mkMerge [
|
||||
(mkIf cfg.setup (mkMerge setupFiles))
|
||||
(mkIf cfg.enable binFiles)
|
||||
];
|
||||
};
|
||||
};
|
||||
}
|
||||
46
modules/nixos/steam/library.nix
Normal file
46
modules/nixos/steam/library.nix
Normal file
|
|
@ -0,0 +1,46 @@
|
|||
{
|
||||
config,
|
||||
lib,
|
||||
...
|
||||
}: let
|
||||
inherit (lib.options) mkOption mkEnableOption;
|
||||
inherit (lib.modules) mkIf mkDefault;
|
||||
inherit (config.services.steam) accountSwitch;
|
||||
cfg = config.services.steam.library;
|
||||
in {
|
||||
options.services.steam.library = with lib.types; {
|
||||
setup = mkEnableOption "steam library data";
|
||||
group = mkOption {
|
||||
type = str;
|
||||
default = accountSwitch.group;
|
||||
};
|
||||
rootDir = mkOption {
|
||||
type = path;
|
||||
};
|
||||
steamappsDir = mkOption {
|
||||
type = path;
|
||||
default = cfg.rootDir + "/steamapps";
|
||||
};
|
||||
};
|
||||
|
||||
config = {
|
||||
services.tmpfiles = let
|
||||
toplevel = {
|
||||
owner = mkDefault "admin";
|
||||
group = mkDefault cfg.group;
|
||||
mode = mkDefault "3775";
|
||||
};
|
||||
shared = {
|
||||
inherit (toplevel) owner group;
|
||||
mode = "2775";
|
||||
};
|
||||
setupFiles = {
|
||||
${cfg.rootDir} = toplevel;
|
||||
${cfg.steamappsDir} = shared;
|
||||
};
|
||||
in {
|
||||
enable = mkIf cfg.setup true;
|
||||
files = mkIf cfg.setup setupFiles;
|
||||
};
|
||||
};
|
||||
}
|
||||
83
modules/nixos/steam/mkbeatsaber.sh
Normal file
83
modules/nixos/steam/mkbeatsaber.sh
Normal file
|
|
@ -0,0 +1,83 @@
|
|||
#!/usr/bin/env bash
|
||||
set -eu
|
||||
|
||||
ARG_GAME_SRC=$1
|
||||
ARG_GAME_VERSION=$2
|
||||
ARG_SHARED_DATA=$3
|
||||
ARG_USER_DATA=$4
|
||||
shift 4
|
||||
|
||||
if ! [[ -e "$ARG_GAME_SRC/$ARG_GAME_VERSION/Beat Saber.exe" ]]; then
|
||||
echo unexpected game src >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
ln -srf "$ARG_GAME_SRC/$ARG_GAME_VERSION/"*.{exe,dll} ./
|
||||
ln -srf "$ARG_GAME_SRC/$ARG_GAME_VERSION/"{MonoBleedingEdge,Plugins} ./
|
||||
rm "Beat Saber.exe"
|
||||
cp "$ARG_GAME_SRC/$ARG_GAME_VERSION/Beat Saber.exe" ./
|
||||
chmod 0775 "Beat Saber.exe"
|
||||
|
||||
BSDATA="Beat Saber_Data"
|
||||
mkdir -pm2775 "$BSDATA"
|
||||
ln -srf "$ARG_GAME_SRC/$ARG_GAME_VERSION/$BSDATA/"* "$BSDATA/" || true
|
||||
ln -srf "$ARG_SHARED_DATA/CustomLevels" "$BSDATA/"
|
||||
rm -f "$BSDATA/Managed"
|
||||
|
||||
mkdir -pm2775 UserData
|
||||
|
||||
ln -srf "$ARG_SHARED_DATA/"{CustomAvatars,CustomNotes,CustomPlatforms,CustomSabers,CustomWalls,Playlists} ./
|
||||
for shareddir in DynamicOpenVR IPA Libs Logs Plugins "$BSDATA/Managed" UserData/SongCore; do
|
||||
shareddirsrc="$ARG_SHARED_DATA/$ARG_GAME_VERSION/$shareddir"
|
||||
if [[ ! -e $shareddirsrc ]]; then
|
||||
mkdir -pm2775 "$shareddirsrc"
|
||||
if [[ $shareddir = */Managed ]]; then
|
||||
cp "$ARG_GAME_SRC/$ARG_GAME_VERSION/$BSDATA/Managed/"* "$shareddirsrc/" || true
|
||||
chmod 0775 "$shareddirsrc/"*.dll || true
|
||||
fi
|
||||
fi
|
||||
ln -srf "$shareddirsrc" "./$(dirname "$shareddir")"
|
||||
done
|
||||
for sharedfile in IPA.exe IPA.exe.config IPA.runtimeconfig.json winhttp.dll; do
|
||||
sharedfilesrc="$ARG_SHARED_DATA/$ARG_GAME_VERSION/$sharedfile"
|
||||
if [[ ! -e "$sharedfilesrc" ]]; then
|
||||
mkdir -pm2775 "$(dirname "$sharedfilesrc")"
|
||||
if [[ $sharedfile = *.json ]]; then
|
||||
echo '{}' > "$sharedfilesrc"
|
||||
else
|
||||
touch "$sharedfilesrc"
|
||||
fi
|
||||
chmod 0775 "$sharedfilesrc" || true
|
||||
fi
|
||||
ln -f "$sharedfilesrc" ./
|
||||
done
|
||||
|
||||
for sharedfile in "Beat Saber IPA.json"; do
|
||||
sharedfilesrc="$ARG_SHARED_DATA/$ARG_GAME_VERSION/UserData/$sharedfile"
|
||||
if [[ ! -e "$sharedfilesrc" ]]; then
|
||||
mkdir -pm2775 "$(dirname "$sharedfilesrc")"
|
||||
if [[ $sharedfile = *.json ]]; then
|
||||
echo '{}' > "$sharedfilesrc"
|
||||
else
|
||||
touch "$sharedfilesrc"
|
||||
fi
|
||||
fi
|
||||
ln -f "$sharedfilesrc" "UserData/$(dirname "$sharedfile")"
|
||||
done
|
||||
ln -f "$ARG_SHARED_DATA/UserData/"*.{json,ini,proto,etag} UserData/
|
||||
ln -srf "$ARG_SHARED_DATA/UserData/"{ScoreSaber,Chroma,Nya,SongRankedBadge,HitScoreVisualizer}/ UserData/
|
||||
|
||||
SFDATA="UserData/Saber Factory"
|
||||
mkdir -pm2775 "$SFDATA"
|
||||
ln -srf "$ARG_SHARED_DATA/$SFDATA/"*/ "$SFDATA/"
|
||||
ln -srf "$ARG_USER_DATA/$SFDATA/"*/ "$SFDATA/"
|
||||
ln -f "$ARG_USER_DATA/$SFDATA/"*.json "$SFDATA/"
|
||||
|
||||
for userdir in Camera2 DrinkWater Enhancements; do
|
||||
userdirsrc="$ARG_USER_DATA/UserData/$userdir"
|
||||
if [[ ! -e $userdirsrc ]]; then
|
||||
mkdir -pm3775 "$userdirsrc"
|
||||
fi
|
||||
ln -srf "$userdirsrc" UserData/
|
||||
done
|
||||
ln -f "$ARG_USER_DATA/UserData/"*.{json,ini,dat} UserData/
|
||||
Loading…
Add table
Add a link
Reference in a new issue