diff options
author | yuuko <yuuko@partyvan.io> | 2024-08-29 21:51:04 -0700 |
---|---|---|
committer | yuuko <yuuko@partyvan.io> | 2024-08-29 21:51:04 -0700 |
commit | 56449e59d7aabd1c06fb67a51a1e129b55cb9270 (patch) | |
tree | 19f3faf805e9b6461a5940d1a050d13e5271ef55 |
break out of system config
35 files changed, 954 insertions, 0 deletions
@@ -0,0 +1,12 @@ +Copyright (C) 2024 by yuuko <yuuko@partyvan.io> + +Permission to use, copy, modify, and/or distribute this software for any +purpose with or without fee is hereby granted. + +THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH +REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND +FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, +INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM +LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR +OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR +PERFORMANCE OF THIS SOFTWARE. diff --git a/README.md b/README.md new file mode 100644 index 0000000..5d0f767 --- /dev/null +++ b/README.md @@ -0,0 +1,38 @@ +### /!\ ALART /!\ ALPHA PROOF OF CONCEPT /!\ ALART /!\ + +Currently the SM/MMS side of things builds exclusively against SDK 2013 +Multiplayer. Accordingly, there are some underlying 32-bit assumptions. + +srcds-nix +========= + +This is a Nix package set and library for Source Engine dedicated servers. +It currently features: + +* fetchers for Steam content: `fetchDepotCache`, `fetchDepotFile`, `mkDepot` + * Courtesy of a patched DepotDownloader, derivations are fixed-output on the + contents of deterministic manifests, then on the SHA1 hashes within. + * This is quite distinct from the usual `steamcmd` approach, but yields a + far more reproducible server environment. Additionally, the network traffic + between `lib.fakeHash` and TOFU is measured in kilobytes, not potential + gigabytes as with [steam-fetcher]. +* AMBuild +* MetaMod: Source +* SourceMod + * a standard extensible package set for plugins and extensions, including: + * `mkDerivation` analogue: `buildSMPlugin` + * setup hook for `spcomp` include paths + * coming soon: development shells to replicate your server setup + +Usage +----- + +* `default.nix` lets you `callPackage` this repository the old-fashioned way + to get the top-level package set. +* `overlay.nix` adds it as `srcdsPackages` to the target. `srcdsPackages` is + considered its canonical place in nixpkgs. +* `flake.nix` exposes: + * `packages.${system}.default` is the top-level package set. + * `overlays.default` points to `overlay.nix`. + +[steam-fetcher]: https://github.com/nix-community/steam-fetcher diff --git a/default.nix b/default.nix new file mode 100644 index 0000000..6254ecb --- /dev/null +++ b/default.nix @@ -0,0 +1,7 @@ +let + purity = if builtins ? currentSystem then + import <nixpkgs> {} + else + throw "OOPS: srcds-nix/default.nix called without pkgs in a pure context"; +in +{ pkgs ? purity, ... }: pkgs.callPackage ./srcds-pkgs {} diff --git a/flake.lock b/flake.lock new file mode 100644 index 0000000..c261cf8 --- /dev/null +++ b/flake.lock @@ -0,0 +1,27 @@ +{ + "nodes": { + "nixpkgs": { + "locked": { + "lastModified": 1724727824, + "narHash": "sha256-0XH9MJk54imJm+RHOLTUJ7e+ponLW00tw5ke4MTVa1Y=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "36bae45077667aff5720e5b3f1a5458f51cf0776", + "type": "github" + }, + "original": { + "owner": "NixOS", + "ref": "nixos-24.05", + "repo": "nixpkgs", + "type": "github" + } + }, + "root": { + "inputs": { + "nixpkgs": "nixpkgs" + } + } + }, + "root": "root", + "version": 7 +} diff --git a/flake.nix b/flake.nix new file mode 100644 index 0000000..5c2bc84 --- /dev/null +++ b/flake.nix @@ -0,0 +1,10 @@ +{ + inputs.nixpkgs.url = "github:NixOS/nixpkgs/nixos-24.05"; + + outputs = { self, nixpkgs, ... }@inputs: { + overlays.default = import ./overlay.nix; + packages = builtins.mapAttrs + (_arch: pkgs: { default = import ./default.nix pkgs; }) + nixpkgs.legacyPackages; + }; +} diff --git a/overlay.nix b/overlay.nix new file mode 100644 index 0000000..8a51cc3 --- /dev/null +++ b/overlay.nix @@ -0,0 +1,3 @@ +self: _super: { + srcdsPackages = import ./default.nix self; +} diff --git a/srcds-pkgs/ambuild.nix b/srcds-pkgs/ambuild.nix new file mode 100644 index 0000000..5621f49 --- /dev/null +++ b/srcds-pkgs/ambuild.nix @@ -0,0 +1,23 @@ +{ lib, buildPythonPackage, fetchFromGitHub }: +let + owner = "alliedmodders"; +in buildPythonPackage rec { + pname = "ambuild"; + version = "2024-07-07"; + + src = fetchFromGitHub { + inherit owner; + repo = pname; + rev = "551dd3f630f90377cbe536fbaf12e0b6bca91253"; + sha256 = "1xfjxs3ajrrz66pdspwrnr5faifk1r3i5nha8vmz510z07h5g6g3"; + }; + + # doCheck = false; + + meta = with lib; { + description = "Lightweight build system designed for performance and accuracy"; + homepage = "https://github.com/${owner}/${pname}"; + platforms = platforms.unix; + license = licenses.bsd3; + }; +} diff --git a/srcds-pkgs/bad/libfinite.nix b/srcds-pkgs/bad/libfinite.nix new file mode 100644 index 0000000..300bd18 --- /dev/null +++ b/srcds-pkgs/bad/libfinite.nix @@ -0,0 +1,20 @@ +# https://sourceware.org/git/?p=glibc.git;a=commit;h=7bdb921d +{ runCommandWith, multiStdenv, writeText }: +runCommandWith { + stdenv = multiStdenv; + name = "libfinite.a"; +} '' + cc -o finite.o -m32 -c ${writeText "finite.c" '' + #include <math.h> + /* metamod */ + double __pow_finite(double x, double y) { return pow(x, y); } + /* sourcemod */ + float __acosf_finite(float x) { return acosf(x); }; + double __acos_finite(double x) { return acos(x); }; + double __asin_finite(double x) { return asin(x); }; + float __atan2f_finite(double y, double x) { return atan2f(y, x); } + double __atan2_finite(double y, double x) { return atan2(y, x); } + double __log_finite(double x) { return log(x); } + ''} + ar rcs $out finite.o +'' diff --git a/srcds-pkgs/bad/mysql_5_5.nix b/srcds-pkgs/bad/mysql_5_5.nix new file mode 100644 index 0000000..bd7534c --- /dev/null +++ b/srcds-pkgs/bad/mysql_5_5.nix @@ -0,0 +1,14 @@ +# TODO: find out if sourcemod is lying about needing to build against 5.5 +{ lib, stdenv, fetchurl, ncurses, cmake }: +stdenv.mkDerivation rec { + pname = "mysql"; + version = "5.5.62"; + + src = fetchurl { + url = "https://downloads.mysql.com/archives/get/p/23/file/mysql-${version}.tar.gz"; + hash = "sha256-seeFO8HwSqv2dx4K2UfzWsjSN/SzXQcG0QlclSb/mdc="; + }; + + nativeBuildInputs = [ cmake ]; + buildInputs = [ ncurses ]; +} diff --git a/srcds-pkgs/build-sm-plugin.nix b/srcds-pkgs/build-sm-plugin.nix new file mode 100644 index 0000000..d55338d --- /dev/null +++ b/srcds-pkgs/build-sm-plugin.nix @@ -0,0 +1,71 @@ +/* there is a lot of hideous directory-shuffling bureaucracy here. it + * encompasses all that has been found necessary out in the wild. sourcemod + * plugins following a sane standard project structure is a fairly recent + * development. + */ +{ lib, stdenvNoCC, sourcemod }: +{ scriptingPath ? "scripting" +, includePath ? "scripting/include" +, pluginsPath ? "plugins" +, translationsPath ? "translations" +, gamedataPath ? "gamedata" +, removePrebuilt ? true +, nativeBuildInputs ? [] +, ... +}@args: +let + inherit (lib) hasSuffix; +in +assert !hasSuffix "/" scriptingPath; +assert !hasSuffix "/" includePath; +assert !hasSuffix "/" pluginsPath; +assert !hasSuffix "/" translationsPath; +assert !hasSuffix "/" gamedataPath; +stdenvNoCC.mkDerivation ({ + inherit + scriptingPath includePath pluginsPath translationsPath gamedataPath + removePrebuilt; + configurePhase = '' + runHook preConfigure + source <(for d in scripting include plugins translations gamedata; do + echo "''${d}Path=$PWD/"\$"''${d}Path" + done) + cd /build + for p in scripting plugins translations gamedata; do + path="$(eval echo \$"''${p}Path")" + [ -d "$path" ] && cp -rT "$path" ./"$p" + done + case "$includePath" in + "$scriptingPath/include") :;; + "$scriptingPath"/*) echo TODO; exit 1;; + *) cp -r "$includePath" ./scripting/include;; + esac + [ -n "''${removePrebuilt:-}" ] && rm -f plugins/*.smx; + mkdir -p scripting/include plugins/disabled translations gamedata + runHook postConfigure + ''; + + buildPhase = '' + runHook preBuild + cd /build/scripting + [ -d ./include ] && SPCOMPFLAGS="$SPCOMPFLAGS -i ./include" + for plug in *.sp; do + spcomp -o "../plugins/disabled/''${plug%.sp}.smx" "$plug" + done + runHook postBuild + ''; + + installPhase = '' + runHook preInstall + cd /build + find . -type d -empty -delete + odir=$out/share/addons/sourcemod + mkdir -p $odir + for d in scripting plugins translation gamedata; do + [ -d $d ] && cp -r $d $odir/$d + done + runHook postInstall + ''; +} // args // { + nativeBuildInputs = nativeBuildInputs ++ [ sourcemod ]; +}) diff --git a/srcds-pkgs/default.nix b/srcds-pkgs/default.nix new file mode 100644 index 0000000..1b8294c --- /dev/null +++ b/srcds-pkgs/default.nix @@ -0,0 +1,55 @@ +let f = self: with self; { + inherit (self) callPackage; + + libfinite = callPackage ./bad/libfinite.nix {}; + mysql_5_5 = pkgs.pkgsi686Linux.callPackage ./bad/mysql_5_5.nix {}; + + ambuild = callPackage ./ambuild.nix { + inherit (pkgs.python3Packages) buildPythonPackage; + }; + + hl2sdk-2013 = callPackage ./hl2sdk-2013.nix {}; + + metamod-source = callPackage ./metamod-source.nix { + hl2sdk = hl2sdk-2013; + }; + sourcemod = callPackage ./sourcemod { + hl2sdk = hl2sdk-2013; + }; + + buildSMPlugin = callPackage ./build-sm-plugin.nix {}; + # TODO: see if it even makes sense to abstract this hard + # buildSMExtension = callPackage ./build-sm-extension.nix {}; + + depotdownloader-json = callPackage ./depotdownloader-json {}; + + fetchDepotCache = callPackage ./fetchdepotcache.nix { + depotdownloader = depotdownloader-json; + }; + fetchDepotFile = callPackage ./fetchdepotfile.nix { + depotdownloader = depotdownloader-json; + }; + mkDepot = callPackage ./mkdepot.nix {}; + + SM-Memory = callPackage ./extensions/SM-Memory.nix {}; + SM-neocurl-ext = callPackage ./extensions/SM-neocurl-ext.nix {}; + + Chat-Logger-Redux = callPackage ./plugins/Chat-Logger-Redux.nix {}; + Open-Fortress-Tools = callPackage ./plugins/Open-Fortress-Tools.nix {}; + SteamTools = callPackage ./plugins/SteamTools.nix {}; + SteamWorks = callPackage ./plugins/SteamWorks.nix {}; + Updater = callPackage ./plugins/Updater.nix {}; + ftz_cheats = callPackage ./plugins/ftz_cheats.nix {}; + morecolors = callPackage ./plugins/morecolors.nix {}; + nativevotes-updated = callPackage ./plugins/nativevotes-updated.nix {}; + openfrags = callPackage ./plugins/openfrags.nix {}; + smlib = callPackage ./plugins/smlib.nix {}; + socket = callPackage ./plugins/socket.nix {}; + yuuko_votes = callPackage ./plugins/yuuko_votes.nix {}; +}; in +{ lib +, newScope +, recurseIntoAttrs +, pkgs +}: +recurseIntoAttrs (lib.makeScope newScope (self: f self // { inherit pkgs; })) diff --git a/srcds-pkgs/depotdownloader-json/0001-emit-json-in-.DepotDownload.patch b/srcds-pkgs/depotdownloader-json/0001-emit-json-in-.DepotDownload.patch new file mode 100644 index 0000000..6a58ac6 --- /dev/null +++ b/srcds-pkgs/depotdownloader-json/0001-emit-json-in-.DepotDownload.patch @@ -0,0 +1,51 @@ +From 5ca2011ef9c6463c6e5953101792b663b6546373 Mon Sep 17 00:00:00 2001 +From: yuuko <yuuko@kurofuku.me> +Date: Fri, 31 Mar 2023 16:03:32 -0700 +Subject: [PATCH] emit json in .DepotDownload + +--- + DepotDownloader/ContentDownloader.cs | 1 + + DepotDownloader/ProtoManifest.cs | 8 ++++++++ + 2 files changed, 9 insertions(+) + +diff --git a/DepotDownloader/ContentDownloader.cs b/DepotDownloader/ContentDownloader.cs +index 7cee83f7..3bf79aa5 100644 +--- a/DepotDownloader/ContentDownloader.cs ++++ b/DepotDownloader/ContentDownloader.cs +@@ -929,6 +929,7 @@ namespace DepotDownloader + + newProtoManifest = new ProtoManifest(depotManifest, depot.manifestId); + newProtoManifest.SaveToFile(newManifestFileName, out checksum); ++ newProtoManifest.SaveToJSON(newManifestFileName.Replace(".bin", ".json")); + File.WriteAllBytes(newManifestFileName + ".sha", checksum); + + Console.WriteLine(" Done!"); +diff --git a/DepotDownloader/ProtoManifest.cs b/DepotDownloader/ProtoManifest.cs +index 70389a05..c5e12cfc 100644 +--- a/DepotDownloader/ProtoManifest.cs ++++ b/DepotDownloader/ProtoManifest.cs +@@ -2,6 +2,8 @@ + using System.Collections.Generic; + using System.IO; + using System.IO.Compression; ++using System.Text; ++using System.Text.Json; + using ProtoBuf; + using SteamKit2; + +@@ -142,6 +144,12 @@ namespace DepotDownloader + } + } + ++ public void SaveToJSON(string filename) ++ { ++ var jsonBytes = new UTF8Encoding(true).GetBytes(JsonSerializer.Serialize(this)); ++ File.Open(filename, FileMode.Create).Write(jsonBytes, 0, jsonBytes.Length); ++ } ++ + public void SaveToFile(string filename, out byte[] checksum) + { + using (var ms = new MemoryStream()) +-- +2.38.4 + diff --git a/srcds-pkgs/depotdownloader-json/0002-ProtoManifest-sort-files-in-constructor.patch b/srcds-pkgs/depotdownloader-json/0002-ProtoManifest-sort-files-in-constructor.patch new file mode 100644 index 0000000..ac4fe97 --- /dev/null +++ b/srcds-pkgs/depotdownloader-json/0002-ProtoManifest-sort-files-in-constructor.patch @@ -0,0 +1,24 @@ +From 7c067e609efabd54039905dc35edf91afb6c5dad Mon Sep 17 00:00:00 2001 +From: yuuko <yuuko@kurofuku.me> +Date: Wed, 1 Nov 2023 06:46:57 -0700 +Subject: [PATCH] ProtoManifest: sort files in constructor + +--- + DepotDownloader/ProtoManifest.cs | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/DepotDownloader/ProtoManifest.cs b/DepotDownloader/ProtoManifest.cs +index c5e12cfc..5f66595c 100644 +--- a/DepotDownloader/ProtoManifest.cs ++++ b/DepotDownloader/ProtoManifest.cs +@@ -21,6 +21,7 @@ namespace DepotDownloader + public ProtoManifest(DepotManifest sourceManifest, ulong id) : this() + { + sourceManifest.Files.ForEach(f => Files.Add(new FileData(f))); ++ Files.Sort((f1,f2) => f1.FileName.CompareTo(f2.FileName)); + ID = id; + CreationTime = sourceManifest.CreationTime; + } +-- +2.42.0 + diff --git a/srcds-pkgs/depotdownloader-json/default.nix b/srcds-pkgs/depotdownloader-json/default.nix new file mode 100644 index 0000000..c09422d --- /dev/null +++ b/srcds-pkgs/depotdownloader-json/default.nix @@ -0,0 +1,10 @@ +{ depotdownloader }: +depotdownloader.overrideAttrs({ patches ? [], version, ... }: { + patches = assert builtins.elem version [ "2.4.7" "2.5.0" ]; patches ++ [ + # with this, nix has access to the hashes in the manifest + ./0001-emit-json-in-.DepotDownload.patch + # the manifest can arrive out of order across requests to the same build! + # luckily that singular reproducibility snag is patched in 1 line. + ./0002-ProtoManifest-sort-files-in-constructor.patch + ]; +}) diff --git a/srcds-pkgs/extensions/SM-Memory.nix b/srcds-pkgs/extensions/SM-Memory.nix new file mode 100644 index 0000000..5d1761a --- /dev/null +++ b/srcds-pkgs/extensions/SM-Memory.nix @@ -0,0 +1,51 @@ +{ lib, multiStdenv, fetchFromGitHub +, metamod-source, sourcemod, ambuild +, ed +}: +multiStdenv.mkDerivation rec { + pname = "SM-Memory"; + version = "1.5.1"; + + src = fetchFromGitHub { + owner = "Scags"; + repo = pname; + rev = "V${version}"; + sha256 = "031nbx18hhqgnryzy00rv5bc8v1k7fbkb3677ndm7nkif13p12aa"; + }; + + nativeBuildInputs = [ ambuild sourcemod ed ]; + + patchPhase = '' + pushd pawn/sourcemod/scripting + substituteInPlace memtest_{func,vec}.sp --replace smmem_ smmem/ + ed memtest.sp <<EOF + /#include/a + #include <smmem/dynlib.inc> + . + w + EOF + popd + ''; + + configurePhase = '' + cd build + python ../configure.py \ + --sm-path ${sourcemod.src} \ + --mms-path ${metamod-source.src} + ''; + + buildPhase = '' + ambuild + pushd package/addons/sourcemod/scripting + mkdir -p ../plugins/disabled + for i in *.sp; do + spcomp -i include $i -o ../plugins/disabled/''${i%.sp}.smx + done + popd + ''; + + installPhase = '' + mkdir $out + mv package $out/share + ''; +} diff --git a/srcds-pkgs/extensions/SM-neocurl-ext.nix b/srcds-pkgs/extensions/SM-neocurl-ext.nix new file mode 100644 index 0000000..8ac2e02 --- /dev/null +++ b/srcds-pkgs/extensions/SM-neocurl-ext.nix @@ -0,0 +1,43 @@ +# pkgsi686Linux.pkgsStatic.callPackage +{ lib, multiStdenv, fetchgit, ed +, metamod-source, sourcemod, ambuild, pkg-config, pkg-config-unwrapped +, pkgsi686Linux +}: +multiStdenv.mkDerivation rec { + pname = "SM-neocurl-ext"; + version = "2.0.1"; + + src = fetchgit { + url = "https://git.partyvan.io/${pname}"; + rev = "0f0f543d79966fc938b3205e5273820e4c2edc56"; + hash = "sha256-zRZddNWc6rl4E/StpTuwtMoL0GVuPRAbcihJ0ViKddo="; + }; + + patchPhase = '' + ed AMBuilder <<EOF + g/pkg_config/s/static/dynamic/ + w + EOF + ''; + + nativeBuildInputs = [ ed ambuild sourcemod pkg-config pkg-config-unwrapped ]; + buildInputs = with pkgsi686Linux; [ openssl curl curl.dev ]; + + configurePhase = '' + mkdir build + cd build + python ../configure.py \ + --sm-path ${sourcemod.src} \ + --mms-path ${metamod-source.src} + ''; + + buildPhase = '' + ambuild + ''; + + installPhase = '' + mkdir -p $out + cp -r package $out/share + ''; +} +
\ No newline at end of file diff --git a/srcds-pkgs/fetchdepotcache.nix b/srcds-pkgs/fetchdepotcache.nix new file mode 100644 index 0000000..6546126 --- /dev/null +++ b/srcds-pkgs/fetchdepotcache.nix @@ -0,0 +1,27 @@ +{ lib, runCommand +, depotdownloader, cacert +}: +{ app, depot, manifest, hash }: +let + app' = builtins.toString app; + depot' = builtins.toString depot; +in +runCommand "depotcache-${manifest}" { + nativeBuildInputs = [ depotdownloader cacert ]; + outputHashMode = "recursive"; + outputHashAlgo = null; + outputHash = hash; + passthru = { inherit app depot manifest; }; +} '' + mkdir -p $out + export HOME=$out + cd $out + DepotDownloader \ + -app ${app'} \ + -depot ${depot'} \ + -manifest ${manifest} \ + -filelist /dev/null \ + -dir . + + rm -rf .local +'' diff --git a/srcds-pkgs/fetchdepotfile.nix b/srcds-pkgs/fetchdepotfile.nix new file mode 100644 index 0000000..6af2507 --- /dev/null +++ b/srcds-pkgs/fetchdepotfile.nix @@ -0,0 +1,46 @@ +# as nice as it would be to just put the file in its expected directory +# structure and symlinkJoin them together at the end, creating that structure +# sacrifices the use of steam's hashes -- nix hashing isn't hierarchical +# or anything, just "archive everything and hash it like another flat file". +{ lib, runCommand +, depotdownloader, cacert +}: +{ FileName, FileHash, Flags, cache, ... }: +with lib; +assert !hasPrefix "/" FileName; +let + dirname = dirOf FileName; + basename = baseNameOf FileName; + src = runCommand basename { + inherit (cache.passthru) app depot manifest; + inherit basename dirname FileName; + cache = "${cache}"; + + passthru = { inherit dirname basename; }; + nativeBuildInputs = [ depotdownloader cacert ]; + outputHashMode = "flat"; + outputHashAlgo = "sha1"; + outputHash = FileHash; + } '' + export HOME=$PWD + cp -r $cache/.DepotDownloader ./ + chmod -R 777 .DepotDownloader + DepotDownloader \ + -app $app -depot $depot -manifest $manifest \ + -filelist <(echo "$FileName") -dir . + + mv $FileName $out + chmod -x $out + ''; +# nix refuses to flat hash executables lol +in if bitAnd Flags 32 != 0 then + runCommand src.name { + inherit src; + inherit (src) passthru; + } '' + cp $src $out + chmod +x $out + '' +else src + + diff --git a/srcds-pkgs/hl2sdk-2013.nix b/srcds-pkgs/hl2sdk-2013.nix new file mode 100644 index 0000000..1d386fc --- /dev/null +++ b/srcds-pkgs/hl2sdk-2013.nix @@ -0,0 +1,9 @@ +{ lib, fetchFromGitHub }: +fetchFromGitHub { + owner = "alliedmodders"; + repo = "hl2sdk"; + rev = "4c27c1305c5e042ae1f62f6dc6ba7e96fd06e05d"; + sha256 = "02ffi72whmbjfjalp23l5s5gqwk2rbqxfkba1rncd22mird93pqh"; + + name = "hl2sdk-sdk2013"; +}
\ No newline at end of file diff --git a/srcds-pkgs/metamod-source.nix b/srcds-pkgs/metamod-source.nix new file mode 100644 index 0000000..2f9c92e --- /dev/null +++ b/srcds-pkgs/metamod-source.nix @@ -0,0 +1,66 @@ +{ lib, multiStdenv +, fetchFromGitHub, ed +, hl2sdk, ambuild, libfinite +}: let + owner = "alliedmodders"; + buildno = "1155"; +in multiStdenv.mkDerivation rec { + pname = "metamod-source"; + version = "1.11_${buildno}"; + + src = fetchFromGitHub rec { + inherit owner; + repo = pname; + rev = "2009298c32735b6de1712ff88e2309c"; + fetchSubmodules = true; + hash = "sha256-cPrllC3IljtV9SWn2NZbV8yHvehqLNGkZQ0RK07yCz4="; + }; + + nativeBuildInputs = [ ambuild ed ]; + + hardeningDisable = [ "all" ]; + + CXXFLAGS="-Wno-error=class-memaccess -Wno-error=format-truncation"; + + postPatch = '' + mkdir .git + echo "ref: refs/heads/main" > .git/HEAD + ed support/buildbot/generate_headers.py <<EOF + /^def get_git_version/;/return/a + def get_git_version(): + return '${buildno}', '${builtins.substring 0 7 src.rev}', '${src.rev}' + . + w + EOF + ed AMBuildScript <<EOF + /tier1]/s|]|, '${libfinite}' ]| + w + EOF + ''; + + configurePhase = '' + ln -s ${hl2sdk} ${hl2sdk.name} + + mkdir -p build + pushd build + python ../configure.py --sdks present + ''; + + buildPhase = '' + ambuild + popd + ''; + + installPhase = '' + mkdir $out + mv build/package $out/share + cp -r $src $out/include + ''; + + meta = with lib; { + description = "C++ plugin environment and detour library for the Source Engine"; + homepage = "https://github.com/${owner}/${pname}"; + platforms = platforms.unix; + license = licenses.zlib; + }; +} diff --git a/srcds-pkgs/mkdepot.nix b/srcds-pkgs/mkdepot.nix new file mode 100644 index 0000000..8c1acaa --- /dev/null +++ b/srcds-pkgs/mkdepot.nix @@ -0,0 +1,19 @@ +{ lib, runCommand, fetchDepotFile }: +name: caches: ps: +with lib; +let + emitStep = { FileName, Flags, Chunks, ... }@file: + if bitAnd Flags 64 != 0 || Chunks == [] then '' + mkdir -p $out/'${FileName}' + '' else let drv = fetchDepotFile file; in '' + mkdir -p $out/'${drv.passthru.dirname}' + ln -s '${drv}' $out/'${FileName}' + ''; + emitManifest = cache: with cache.passthru; let + json = "${cache}/.DepotDownloader/${toString depot}_${manifest}.json"; + mkStep = file: emitStep (file // { inherit cache; }); + in concatMapStrings mkStep (importJSON json).Files; +in runCommand name {} '' + ${concatMapStringsSep "\n" emitManifest caches} + ${ps} +'' diff --git a/srcds-pkgs/plugins/Chat-Logger-Redux.nix b/srcds-pkgs/plugins/Chat-Logger-Redux.nix new file mode 100644 index 0000000..7acbc79 --- /dev/null +++ b/srcds-pkgs/plugins/Chat-Logger-Redux.nix @@ -0,0 +1,19 @@ +{ lib, buildSMPlugin, fetchFromGitHub }: +buildSMPlugin rec { + pname = "Chat-Logger-Redux"; + version = "2021-09-06"; + + src = fetchFromGitHub { + owner = "Drixevel-Archive"; + repo = pname; + rev = "5a297b1f3680d2c862ba914476902105c89a9213"; + hash = "sha256-9jVRIRKX3axPYGV0vAWpikQuEQgzIdhcAMMIO2dPWU8="; + }; + + preBuild = '' + # the entire set of sourcemod headers are vendored in here for some reason + rm /build/scripting/include/*.inc + # i don't even know what to say about this one + rm /build/scripting/{compile.{dat,bat},spcomp.exe} + ''; +} diff --git a/srcds-pkgs/plugins/Open-Fortress-Tools.nix b/srcds-pkgs/plugins/Open-Fortress-Tools.nix new file mode 100644 index 0000000..86269ab --- /dev/null +++ b/srcds-pkgs/plugins/Open-Fortress-Tools.nix @@ -0,0 +1,15 @@ +{ lib, buildSMPlugin, fetchFromGitHub }: +buildSMPlugin rec { + pname = "Open-Fortress-Tools"; + version = "2024-08-22"; + + src = fetchFromGitHub { + owner = "openfortress"; + repo = "SM-${pname}"; + rev = "05cb78a9411843e16ddab5f651edec5f481200b1"; + hash = "sha256-Y2uCVB2fivzQq7bC7g8KK/qiido7qopv9tcLhEr/h6w="; + }; + + removePrebuilt = false; + dontBuild = true; +} diff --git a/srcds-pkgs/plugins/SteamTools.nix b/srcds-pkgs/plugins/SteamTools.nix new file mode 100644 index 0000000..2755fa5 --- /dev/null +++ b/srcds-pkgs/plugins/SteamTools.nix @@ -0,0 +1,21 @@ +{ lib, buildSMPlugin, fetchFromGitHub, runCommand }: +let + pname = "SteamTools"; + src' = fetchFromGitHub { + # transitional syntax fork that's been sitting in PRs for 4 years ww + owner = "JoinedSenses"; + repo = pname; + rev = "0ce8122e5d2a453c5b4b23fb2871bc24b35e27fe"; + hash = "sha256-Vq60/GxwlyfYgQKjnMR8CaeyfMApJIvvZWD94o4LwYc="; + }; +in +buildSMPlugin /* rec */ { + inherit pname; + version = "2020-05-01"; + + src = runCommand "source" {} '' + odir=$out/scripting/include + mkdir -p $odir + cp ${src'}/plugin/steamtools.inc $odir/ + ''; +} diff --git a/srcds-pkgs/plugins/SteamWorks.nix b/srcds-pkgs/plugins/SteamWorks.nix new file mode 100644 index 0000000..169f6d0 --- /dev/null +++ b/srcds-pkgs/plugins/SteamWorks.nix @@ -0,0 +1,19 @@ +{ buildSMPlugin, fetchFromGitHub, runCommand }: +let + src' = fetchFromGitHub { + owner = "KyleSanderson"; + repo = "SteamWorks"; + rev = "f0c1b62dff615511b27824aaa2815c7dc58d2716"; + hash = "sha256-ugjaM04Jm1MKGmdtTAYVRD+ONOevc0PHAWqxBFSeu4o="; + }; +in +buildSMPlugin rec { + pname = "SteamWorks"; + version = "2023-04-02"; + + src = runCommand "source" {} '' + odir=$out/scripting/ + mkdir -p $odir + cp -r ${src'}/Pawn/includes $odir/include + ''; +} diff --git a/srcds-pkgs/plugins/Updater.nix b/srcds-pkgs/plugins/Updater.nix new file mode 100644 index 0000000..3c252fd --- /dev/null +++ b/srcds-pkgs/plugins/Updater.nix @@ -0,0 +1,28 @@ +{ fetchzip, buildSMPlugin, ed +, SM-neocurl-ext, SteamTools, SteamWorks, socket +}: +buildSMPlugin rec { + pname = "Updater"; + version = "1.2.1"; + + src = fetchzip { + url = "https://forums.alliedmods.net/attachment.php?attachmentid=183438"; + extension = "zip"; + stripRoot = false; + hash = "sha256-M+kUvHzwiJXOGIdbUql5nbFdCPdzYdRM1BCq6Y8Fuls="; + }; + + nativeBuildInputs = [ ed ]; + buildInputs = [ SM-neocurl-ext SteamTools SteamWorks socket ]; + + postPatch = '' + ed scripting/updater.sp <<EOF + /"sm_updater"/s/2/1/ + w + EOF + ed scripting/updater/plugins.sp <<EOF + /64] /s//64], / + w + EOF + ''; +} diff --git a/srcds-pkgs/plugins/ftz_cheats.nix b/srcds-pkgs/plugins/ftz_cheats.nix new file mode 100644 index 0000000..3e8d32c --- /dev/null +++ b/srcds-pkgs/plugins/ftz_cheats.nix @@ -0,0 +1,14 @@ +{ lib, fetchzip, buildSMPlugin, smlib }: +buildSMPlugin rec { + pname = "ftz_cheats"; + version = "1.1"; + + src = fetchzip { + url = "https://forums.alliedmods.net/attachment.php?attachmentid=109393"; + extension = "zip"; + stripRoot = false; + hash = "sha256-05RRJuIldc6gvYkYcpQokFwKYvR+wMCgy7KylUi1vTY="; + }; + + buildInputs = [ smlib ]; +} diff --git a/srcds-pkgs/plugins/morecolors.nix b/srcds-pkgs/plugins/morecolors.nix new file mode 100644 index 0000000..325b353 --- /dev/null +++ b/srcds-pkgs/plugins/morecolors.nix @@ -0,0 +1,20 @@ +{ lib, fetchFromGitHub, stdenvNoCC }: +stdenvNoCC.mkDerivation rec { + pname = "morecolors"; + version = "2022-07-07"; + + src = fetchFromGitHub { + owner = "DoctorMcKay"; + repo = "sourcemod-plugins"; + rev = "6c7ffca2b580b3b313ee2027ac4dd12b7fad226a"; + hash = "sha256-zmwyIMSwr2BV3feuiAZhUj2SAh5C+vp/HnGufYMpu60="; + }; + + phases = [ "unpackPhase" "installPhase" ]; + + installPhase = '' + odir=$out/share/addons/sourcemod/scripting/include + mkdir -p $odir + cp scripting/include/morecolors.inc $odir/ + ''; +} diff --git a/srcds-pkgs/plugins/nativevotes-updated.nix b/srcds-pkgs/plugins/nativevotes-updated.nix new file mode 100644 index 0000000..4044294 --- /dev/null +++ b/srcds-pkgs/plugins/nativevotes-updated.nix @@ -0,0 +1,16 @@ +{ buildSMPlugin, fetchFromGitHub }: +buildSMPlugin rec { + pname = "nativevotes-updated"; + version = "2023-10-17"; + + src = fetchFromGitHub { + owner = "sapphonie"; + repo = "sourcemod-${pname}"; + rev = "47d00d636fd7bee3419fb310e4c3d8674278248d"; + sha256 = "0yvlsclhdjsy0amrff3a6y2k2bfalcyrjp57s5jnxv30gqc3d1rg"; + }; + + preConfigure = '' + cd addons/sourcemod + ''; +} diff --git a/srcds-pkgs/plugins/openfrags.nix b/srcds-pkgs/plugins/openfrags.nix new file mode 100644 index 0000000..07bb629 --- /dev/null +++ b/srcds-pkgs/plugins/openfrags.nix @@ -0,0 +1,16 @@ +{ buildSMPlugin, fetchFromGitHub +, Updater, morecolors, Open-Fortress-Tools +}: +buildSMPlugin rec { + pname = "openfrags"; + version = "2.2"; + + src = fetchFromGitHub { + owner = "TheRatest"; + repo = pname; + rev = "3cece524f0b91364300c8c8618d41430af86be95"; + hash = "sha256-qK3zcQm8+FA/xA0gFMlo2K6d+u+mpupMLyToOG3eMeg="; + }; + + buildInputs = [ morecolors Updater Open-Fortress-Tools ]; +} diff --git a/srcds-pkgs/plugins/smlib.nix b/srcds-pkgs/plugins/smlib.nix new file mode 100644 index 0000000..5f283c9 --- /dev/null +++ b/srcds-pkgs/plugins/smlib.nix @@ -0,0 +1,22 @@ +{ fetchFromGitHub, buildSMPlugin }: +buildSMPlugin rec { + pname = "smlib"; + version = "2022-01-11"; + + src = fetchFromGitHub { + owner = "bcserv"; + repo = pname; + # transitional_syntax branch + rev = "2c14acb85314e25007f5a61789833b243e7d0cab"; + hash = "sha256-yonYBCaEZGjbxhKvQ2NNVBpiUqyMxuchEgL+bsWomuo="; + }; + + postPatch = '' + sed -i \ + '/#include <sdktools_entinput>/a #include <sdktools_variant_t>' \ + scripting/include/smlib/entities.inc + ''; + + # technically unnecessary as buildPhase simply won't find anything to build + dontBuild = true; +} diff --git a/srcds-pkgs/plugins/socket.nix b/srcds-pkgs/plugins/socket.nix new file mode 100644 index 0000000..5a7cdc2 --- /dev/null +++ b/srcds-pkgs/plugins/socket.nix @@ -0,0 +1,27 @@ +{ buildSMPlugin, fetchFromGitHub, runCommand }: +let + src' = fetchFromGitHub { + owner = "nefarius"; + repo = "sm-ext-socket"; + rev = "ed6bf7a12bd3f801610592301e12062b367fa27b"; + hash = "sha256-M13Nt58tlXXBO1fB2Y3vQLyD4Wlzrwd6mHWSf5JTUwY="; + }; + /* + socket.src = fetchzip { + url = "http://forums.alliedmods.net/attachment.php?attachmentid=83286"; + extension = "zip"; + stripRoot = false; + hash = "sha256-EDCEyzSynz8Uotgx6xVmEiGgXf1FBtOzW1YNfsOad+U="; + }; + */ +in +buildSMPlugin rec { + pname = "socket"; + version = "2018-11-14"; + + src = runCommand "source" {} '' + odir=$out/scripting/include + mkdir -p $odir + cp ${src'}/socket.inc $odir/ + ''; +} diff --git a/srcds-pkgs/plugins/yuuko_votes.nix b/srcds-pkgs/plugins/yuuko_votes.nix new file mode 100644 index 0000000..fb11fad --- /dev/null +++ b/srcds-pkgs/plugins/yuuko_votes.nix @@ -0,0 +1,13 @@ +{ lib, buildSMPlugin, fetchgit, SM-Memory }: +buildSMPlugin rec { + pname = "yuuko_votes"; + version = "2024-08-12"; + + src = fetchgit { + url = "https://git.partyvan.io/yuuko_votes"; + rev = "acafa384e1dfec7d877bc4fcac0dc78e8f9429db"; + hash = "sha256-PNCl9oM2j0CSiJp6jt0Cn9gGwGsbwmZ55xt/m05Tmzc="; + }; + + buildInputs = [ SM-Memory ]; +} diff --git a/srcds-pkgs/sourcemod/default.nix b/srcds-pkgs/sourcemod/default.nix new file mode 100644 index 0000000..90c31f9 --- /dev/null +++ b/srcds-pkgs/sourcemod/default.nix @@ -0,0 +1,82 @@ +{ lib, multiStdenv, pkgsi686Linux +, writeShellScript +, fetchFromGitHub, ed +, hl2sdk, ambuild, metamod-source, libfinite +, mysql_5_5 +}: let + inherit (pkgsi686Linux) zlib; + owner = "alliedmodders"; + buildno = "6968"; +in multiStdenv.mkDerivation rec { + pname = "sourcemod"; + version = "1.11_${buildno}"; + + src = fetchFromGitHub rec { + inherit owner; + repo = pname; + rev = "13510eab809a98b6a62354fc9848641"; + fetchSubmodules = true; + hash = "sha256-leV0Q7g5bnJljzQxv3z6t5p/1d9TxILPvIuSYuq8LmE="; + }; + + nativeBuildInputs = [ ambuild ed ]; + buildInputs = [ zlib mysql_5_5 ]; + + hardeningDisable = [ "all" ]; + + CXXFLAGS="-Wno-error=sign-compare -Wno-error=ignored-attributes"; + + postPatch = '' + mkdir .git + echo "ref: refs/heads/main" > .git/HEAD + ed tools/buildbot/generate_headers.py <<EOF + /^def get_git_version/;/return/a + def get_git_version(): + return '${buildno}', '${builtins.substring 0 7 src.rev}', '${src.rev}' + . + w + EOF + for i in sdktools dhooks sdkhooks; do + sed -i '/invalid-offsetof/s,no-,no-error=,' extensions/$i/AMBuilder + done + ed AMBuildScript <<EOF + /'mathlib.a'/s|$|, '${libfinite}',| + w + EOF + ''; + + configurePhase = '' + ln -s ${hl2sdk} ${hl2sdk.name} + ln -s ${metamod-source}/include metamod-source + mkdir -p build + cd build + python ../configure.py --sdks present --mysql-path ${mysql_5_5} + ''; + + buildPhase = '' + ambuild + ''; + + installPhase = '' + mkdir $out + mv package $out/share + cd $out/share/addons/sourcemod/plugins + mv *.smx disabled/ + mkdir -p $out/bin + cd $out/bin + cp ${writeShellScript "spcomp" '' + echo OUT/share/addons/sourcemod/scripting/spcomp $SPCOMPFLAGS "$@" + OUT/share/addons/sourcemod/scripting/spcomp $SPCOMPFLAGS "$@" + ''} ./spcomp + substituteInPlace ./spcomp --replace OUT "$out" + ''; + + setupHook = ./setup-hook.sh; + + meta = with lib; { + description = "Source Engine scripting and administration"; + homepage = "https://github.com/${owner}/${pname}"; + platforms = platforms.unix; + license = licenses.gpl3; + }; +} diff --git a/srcds-pkgs/sourcemod/setup-hook.sh b/srcds-pkgs/sourcemod/setup-hook.sh new file mode 100644 index 0000000..17d8617 --- /dev/null +++ b/srcds-pkgs/sourcemod/setup-hook.sh @@ -0,0 +1,16 @@ +SPCOMPFLAGS=${SPCOMPFLAGS:-} +dontUseSourcepawnFindHeaders=${dontUseSourcepawnFindHeaders:-} +sourcepawnFindHeaders(){ + [ -n "${dontUseSourcepawnFindHeaders:-}" ] && return + for plug in $buildInputs; do + local ipath="$plug/share/addons/sourcemod/scripting/include" + if [ -d "$ipath" ]; then + echo "found sourcepawn headers: \"$ipath\"" + SPCOMPFLAGS="$SPCOMPFLAGS -i $ipath" + fi + done + dontUseSourcepawnFindHeaders=1 + export SPCOMPFLAGS dontUseSourcepawnFindHeaders +} + +addEnvHooks "$targetOffset" sourcepawnFindHeaders |