{
  stdenv,
  lib,
  fetchFromGitHub,
  cmake,
  ninja,
  jdk17,
  ghc_filesystem,
  zlib,
  file,
  xorg,
  libpulseaudio,
  openal,
  qt6,
  glfw,
  pciutils,
  udev,
  glxinfo,
  qt6Packages,
  libGL,
  flite,
  addDriverRunpath,
  vulkan-loader,
  msaClientID ? null,
  extra-cmake-modules,
  makeWrapper,
  gamemode,
  mangohud,
  glfw-wayland-minecraft,
  writeShellScript,
}:

let
  polymc =
    let
      binpath = lib.makeBinPath [
        xorg.xrandr
        glxinfo
        pciutils
      ];

      libpath = lib.makeLibraryPath [
        xorg.libX11
        xorg.libXext
        xorg.libXcursor
        xorg.libXrandr
        xorg.libXxf86vm
        libpulseaudio
        libGL
        vulkan-loader
        glfw
        openal
        udev
        flite
        stdenv.cc.cc.lib
      ];

      gameLibraryPath = libpath + ":${addDriverRunpath.driverLink}/lib";

    in
    stdenv.mkDerivation (
      let
        version = "6.1";
      in
      {
        pname = "polymc" + (lib.optionalString ((lib.versions.major qt6.qtbase.version) == "5") "-qt5");
        inherit version;

        src = fetchFromGitHub {
          owner = "PolyMC";
          repo = "PolyMC";
          rev = version;
          sha256 = "sha256-AOy13zAWQ0CtsX9z1M+fxH7Sh/QSFy7EdQ/fD9yUYc8=";
          fetchSubmodules = true;
        };
        dontWrapQtApps = true;
        nativeBuildInputs = [
          cmake
          extra-cmake-modules
          ninja
          jdk17
          qt6.wrapQtAppsHook
          file
          ghc_filesystem
        ];
        buildInputs = [
          qt6.qtbase
          qt6.qtsvg
          qt6.qtcharts
          qt6.qtwayland
          qt6Packages.quazip
          zlib
        ];

        cmakeFlags = [
          "-GNinja"
          "-DLauncher_QT_VERSION_MAJOR=${lib.versions.major qt6.qtbase.version}"
        ]
        ++ lib.optionals (msaClientID != null) [ "-DLauncher_MSA_CLIENT_ID=${msaClientID}" ];

        postPatch = ''
          # hardcode jdk paths
          substituteInPlace launcher/java/JavaUtils.cpp \
            --replace 'scanJavaDir("/usr/lib/jvm")' 'javas.append("${jdk17}/lib/openjdk/bin/java")'
        '';

        postFixup = ''
          # xorg.xrandr needed for LWJGL [2.9.2, 3) https://github.com/LWJGL/lwjgl/issues/128
          wrapQtApp $out/bin/polymc \
            --suffix LD_LIBRARY_PATH : "${gameLibraryPath}" \
            --suffix PATH : "${binpath}" \
            --set-default ALSOFT_DRIVERS "pulse"
        '';
        passthru = {

          wrap =
            {
              extraJDKs ? [ ],
              extraPaths ? [ ],
              extraLibs ? [ ],
              withWaylandGLFW ? false,
              withMangohud ? true,
              withGamemode ? true,
            }:
            stdenv.mkDerivation (
              let
                libsPath =
                  (lib.makeLibraryPath (extraLibs ++ lib.optional withGamemode gamemode.lib))
                  + lib.optionalString withMangohud "${mangohud + "/lib/mangohud"}";
                binsPath = lib.makeBinPath (extraPaths ++ lib.optional withMangohud mangohud);
                waylandPreExec = writeShellScript "waylandGLFW" ''
                  if [ -n "$WAYLAND_DISPLAY" ]; then
                    export LD_LIBRARY_PATH=${lib.getLib glfw-wayland-minecraft}/lib:"$LD_LIBRARY_PATH"
                  fi
                '';
              in
              {
                pname = "${polymc.pname}-wrapped";
                inherit (polymc) version;
                inherit libsPath binsPath waylandPreExec;

                src = polymc;
                nativeBuildInputs = [ makeWrapper ];
                phases = [
                  "installPhase"
                  "fixupPhase"
                ];
                installPhase = ''
                  mkdir -p $out/bin
                  ln -s $src/bin/polymc $out/bin/polymc
                  ln -s $src/share $out/share
                '';

                postFixup =
                  let
                    javaPaths = lib.makeSearchPath "bin/java" extraJDKs;
                  in
                  ''
                    wrapProgram $out/bin/polymc \
                      --suffix LD_LIBRARY_PATH : "${libsPath}" \
                      --suffix POLYMC_JAVA_PATHS : "${javaPaths}" \
                      --suffix PATH : "${binsPath}" ${lib.optionalString withWaylandGLFW "--run ${waylandPreExec}"}

                  '';

                preferLocalBuild = true;
                inherit (polymc) meta;

              }
            );
        };
        meta = {
          homepage = "https://polymc.org/";
          downloadPage = "https://polymc.org/download/";
          changelog = "https://github.com/PolyMC/PolyMC/releases";
          description = "A free, open source launcher for Minecraft";
          longDescription = ''
            Allows you to have multiple, separate instances of Minecraft (each with
            their own mods, texture packs, saves, etc) and helps you manage them and
            their associated options with a simple interface.
          '';
          platforms = [ "x86_64-linux" ];
          license = lib.licenses.gpl3Only;
        };
      }
    );
in
polymc
