{ lib, stdenv, buildDotnetModule, dotnetCorePackages, wrapGAppsHook3, copyDesktopItems, gdk-pixbuf, webkitgtk_4_1, gtk3, glib, libnotify, fontconfig, gst_all_1, zenity, makeDesktopItem, callPackage, }: let sources = callPackage ../../../../_sources/generated.nix { }; src = sources.VRCNext.src; # Version from the nvfetcher tag (v2026.40.6); AppInfo.cs may lag the tag. version = lib.removePrefix "v" sources.VRCNext.version; in buildDotnetModule rec { pname = "vrcnext"; inherit version src; projectFile = "VRCNext.csproj"; nugetDeps = ./deps.json; # This csproj picks its TFM via `$(RuntimeIdentifier.StartsWith('linux'))`. # `dotnet restore --runtime` does NOT set RuntimeIdentifier during project # evaluation (only build/publish do), so pass it as a property or restore # targets net9.0-windows and fails with NETSDK1100. dotnetRestoreFlags = [ "-p:RuntimeIdentifier=${dotnetCorePackages.systemToDotnetRid stdenv.hostPlatform.system}" ]; dotnet-sdk = dotnetCorePackages.sdk_9_0; executables = [ "VRCNext" ]; nativeBuildInputs = [ wrapGAppsHook3 copyDesktopItems ]; # gdk-pixbuf so wrapGAppsHook3 emits GDK_PIXBUF_MODULE_FILE (GTK file # dialogs via libnfd.so need icon loaders). buildInputs = [ gdk-pixbuf ]; # buildDotnetModule already wraps with makeWrapper (dotnetFixupPhase); # fold the gapps args in there instead of double-wrapping. dontWrapGApps = true; # Prebuilt native libs (Photino.Native.so, libnfd.so, libSkiaSharp.so) # have no RUNPATH; these get suffixed onto LD_LIBRARY_PATH. runtimeDeps = [ webkitgtk_4_1 gtk3 glib gdk-pixbuf libnotify fontconfig gst_all_1.gstreamer gst_all_1.gst-plugins-base gst_all_1.gst-plugins-good gst_all_1.gst-libav ]; makeWrapperArgs = [ # WebKitGTK's web process dies on Wayland with "Error 71 (Protocol # error) dispatching to Wayland display" when the DMA-BUF renderer # handshake fails (well-known NixOS issue); disable it. "--set" "WEBKIT_DISABLE_DMABUF_RENDERER" "1" # WebKitGTK discovers gstreamer plugins via the plugin path, not LD_LIBRARY_PATH. "--prefix" "GST_PLUGIN_SYSTEM_PATH" ":" (lib.makeSearchPath "lib/gstreamer-1.0" [ gst_all_1.gst-plugins-base gst_all_1.gst-plugins-good gst_all_1.gst-libav ]) # The app shells out to zenity (dialogs) and notify-send (libnotify). "--prefix" "PATH" ":" (lib.makeBinPath [ zenity libnotify ]) ]; preFixup = '' makeWrapperArgs+=("''${gappsWrapperArgs[@]}") ''; postInstall = '' install -Dm644 "$src/frontend/logo.png" "$out/share/icons/hicolor/512x512/apps/vrcnext.png" ''; desktopItems = [ (makeDesktopItem { name = "vrcnext"; exec = "VRCNext %u"; icon = "vrcnext"; comment = "VRChat companion app"; desktopName = "VRCNext"; categories = [ "Game" "Utility" "Network" ]; mimeTypes = [ "x-scheme-handler/vrcn" ]; startupWMClass = "VRCNext"; }) ]; meta = { description = "VRChat launcher and management system"; homepage = "https://github.com/shinyflvre/VRCNext"; license = { fullName = "VRCNext Non-Commercial Open Source License (VNCOL) 1.0"; shortName = "vncol"; url = "https://github.com/shinyflvre/VRCNext/blob/master/LICENSE"; free = false; }; mainProgram = "VRCNext"; platforms = [ "x86_64-linux" ]; }; }