feat: JumpAcademy.tf maps
This commit is contained in:
1
.gitattributes
vendored
1
.gitattributes
vendored
@@ -1 +1,2 @@
|
|||||||
tf2/packages/huds/hud-db/hud-db.json linguist-generated=true
|
tf2/packages/huds/hud-db/hud-db.json linguist-generated=true
|
||||||
|
tf2/packages/maps/jump-academy/jump-academy.json linguist-generated=true
|
||||||
|
|||||||
@@ -134,7 +134,7 @@ Don't hesitate to open issues/PRs not only for "real issues" (bugs, missing feat
|
|||||||
- [ ] Tests.
|
- [ ] Tests.
|
||||||
- [X] Figure out installation for Impermanence users.
|
- [X] Figure out installation for Impermanence users.
|
||||||
- [ ] Package Paysus' animation overhauls.
|
- [ ] Package Paysus' animation overhauls.
|
||||||
- [ ] Generate package set from [[https://cdn.jumpacademy.tf/][jumpacademy.tf]].
|
- [X] Generate package set from [[https://cdn.jumpacademy.tf/][jumpacademy.tf]].
|
||||||
|
|
||||||
* See also
|
* See also
|
||||||
|
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
{ stdenv, lib }:
|
{ stdenv, lib }:
|
||||||
|
|
||||||
{ pname
|
{ pname
|
||||||
, version ? "nover"
|
, version ? ""
|
||||||
, custom ? []
|
, custom ? []
|
||||||
, cfg ? []
|
, cfg ? []
|
||||||
, maps ? []
|
, maps ? []
|
||||||
@@ -19,9 +19,9 @@ let
|
|||||||
${lib.toShellVar "outputList_${output}" var}
|
${lib.toShellVar "outputList_${output}" var}
|
||||||
for i in "''${outputList_${output}[@]}"; do
|
for i in "''${outputList_${output}[@]}"; do
|
||||||
name="$(stripHash "$i")"
|
name="$(stripHash "$i")"
|
||||||
vpkDir="#vpk-''${name}#"
|
wrapperDir="#''${name}#"
|
||||||
if [ -d "$vpkDir" ]; then
|
if [ -d "$wrapperDir" ]; then
|
||||||
mv "$vpkDir/$name" "$out/${output}/$name"
|
mv "$wrapperDir"/* "$out/${output}/"
|
||||||
else
|
else
|
||||||
mv "$name" "$out/${output}/$name"
|
mv "$name" "$out/${output}/$name"
|
||||||
fi
|
fi
|
||||||
@@ -38,21 +38,38 @@ in stdenv.mkDerivation ({
|
|||||||
inherit pname version;
|
inherit pname version;
|
||||||
# Adapted from stdenv's _defaultUnpack().
|
# Adapted from stdenv's _defaultUnpack().
|
||||||
unpackCmd = ''
|
unpackCmd = ''
|
||||||
if [ "''${curSrc##*.}" = "vpk" ]; then
|
echo "hello i am unpackcmdjkj"
|
||||||
destination="#vpk-$(stripHash "$curSrc")#/$(stripHash "$curSrc")"
|
set -e
|
||||||
mkdir "$(dirname "$destination")"
|
case "$curSrc" in
|
||||||
if [ -e "$destination" ]; then
|
*.vpk)
|
||||||
echo "Cannot copy $curSrc to $destination: destination already exists!"
|
name="$(stripHash "$curSrc")"
|
||||||
echo "Did you specify two \"srcs\" with the same \"name\"?"
|
destination="#$name#/$name"
|
||||||
return 1
|
mkdir "$(dirname "$destination")"
|
||||||
fi
|
if [ -e "$destination" ]; then
|
||||||
# We can't preserve hardlinks because they may have been
|
echo "Cannot copy $curSrc to $destination: destination already exists!"
|
||||||
# introduced by store optimization, which might break things
|
echo "Did you specify two \"srcs\" with the same \"name\"?"
|
||||||
# in the build.
|
return 1
|
||||||
cp -r --preserve=mode,timestamps --reflink=auto -- "$curSrc" "$destination"
|
fi
|
||||||
else
|
# We can't preserve hardlinks because they may have been
|
||||||
return 1
|
# introduced by store optimization, which might break things
|
||||||
fi
|
# in the build.
|
||||||
|
cp -r --preserve=mode,timestamps --reflink=auto -- "$curSrc" "$destination"
|
||||||
|
;;
|
||||||
|
*.bsp.bz2)
|
||||||
|
bzfile="$(stripHash "$curSrc")"
|
||||||
|
file="''${bzfile%.bz2}"
|
||||||
|
destination="#$bzfile#/$file"
|
||||||
|
mkdir "$(dirname "$destination")"
|
||||||
|
bunzip2 -c "$curSrc" > "$destination"
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
return 1
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
'';
|
||||||
|
preUnpack = ''
|
||||||
|
echo "$unpackCmd"
|
||||||
|
echo "$unpackCmdHooks"
|
||||||
'';
|
'';
|
||||||
installPhase = ''
|
installPhase = ''
|
||||||
set -xe
|
set -xe
|
||||||
|
|||||||
@@ -40,7 +40,7 @@ in lib.mergeAttrsList [
|
|||||||
{ inherit mkTf2Config fetchFromGameBanana mkCfg mergeTf2Configs; }
|
{ inherit mkTf2Config fetchFromGameBanana mkCfg mergeTf2Configs; }
|
||||||
{ mastercomfig = callPackage ./mastercomfig.nix {}; }
|
{ mastercomfig = callPackage ./mastercomfig.nix {}; }
|
||||||
{ huds = callPackage ./huds {}; }
|
{ huds = callPackage ./huds {}; }
|
||||||
{ maps = callPackage ./maps.nix {}; }
|
{ maps = callPackage ./maps {}; }
|
||||||
(callPackage ./misc.nix {})
|
(callPackage ./misc.nix {})
|
||||||
(callPackage ./scripts.nix {})
|
(callPackage ./scripts.nix {})
|
||||||
]
|
]
|
||||||
|
|||||||
@@ -1,14 +0,0 @@
|
|||||||
{ fetchFromGameBanana, mkTf2Config }:
|
|
||||||
|
|
||||||
{
|
|
||||||
jump_beef = mkTf2Config {
|
|
||||||
pname = "jump_beef";
|
|
||||||
maps = [
|
|
||||||
(fetchFromGameBanana {
|
|
||||||
name = "jump_beef";
|
|
||||||
id = "323807";
|
|
||||||
hash = "sha256-A/MqnQJAt+MOZGnZOy7CgbLuXwKdbU0DjudMkTZoW6c=";
|
|
||||||
})
|
|
||||||
];
|
|
||||||
};
|
|
||||||
}
|
|
||||||
6
tf2/packages/maps/default.nix
Normal file
6
tf2/packages/maps/default.nix
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
{ pkgs, callPackage, fetchFromGitHub, mkTf2Config }@args:
|
||||||
|
|
||||||
|
let
|
||||||
|
jump-academy = callPackage ./jump-academy {};
|
||||||
|
extras = callPackage ./extras.nix {};
|
||||||
|
in jump-academy // extras
|
||||||
14
tf2/packages/maps/extras.nix
Normal file
14
tf2/packages/maps/extras.nix
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
{ fetchFromGameBanana, mkTf2Config }:
|
||||||
|
|
||||||
|
{
|
||||||
|
# jump_beef = mkTf2Config {
|
||||||
|
# pname = "jump_beef";
|
||||||
|
# maps = [
|
||||||
|
# (fetchFromGameBanana {
|
||||||
|
# name = "jump_beef";
|
||||||
|
# id = "323807";
|
||||||
|
# hash = "sha256-A/MqnQJAt+MOZGnZOy7CgbLuXwKdbU0DjudMkTZoW6c=";
|
||||||
|
# })
|
||||||
|
# ];
|
||||||
|
# };
|
||||||
|
}
|
||||||
13
tf2/packages/maps/jump-academy/default.nix
Normal file
13
tf2/packages/maps/jump-academy/default.nix
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
{ mkTf2Config, fetchurl }:
|
||||||
|
|
||||||
|
builtins.mapAttrs
|
||||||
|
(name: e: mkTf2Config {
|
||||||
|
pname = name;
|
||||||
|
env.description = e.description;
|
||||||
|
maps = [
|
||||||
|
(fetchurl {
|
||||||
|
inherit (e.src) url hash;
|
||||||
|
})
|
||||||
|
];
|
||||||
|
})
|
||||||
|
(builtins.fromJSON (builtins.readFile ./jump-academy.json))
|
||||||
113
tf2/packages/maps/jump-academy/fetch_jump_academy.clj
Normal file
113
tf2/packages/maps/jump-academy/fetch_jump_academy.clj
Normal file
@@ -0,0 +1,113 @@
|
|||||||
|
(ns fetch-jump-academy
|
||||||
|
(:require [babashka.fs :as fs]
|
||||||
|
[babashka.process :as p]
|
||||||
|
[babashka.http-client :as http]
|
||||||
|
[cheshire.core :as json]
|
||||||
|
[clojure.tools.logging :as l]
|
||||||
|
[clojure.string :as str]
|
||||||
|
[clojure.java.io :as io]
|
||||||
|
[clojure.edn :as edn]))
|
||||||
|
|
||||||
|
(def ^:dynamic *dry-run?* true)
|
||||||
|
|
||||||
|
(def cache-dir (fs/xdg-cache-home "fetch-jump-academy"))
|
||||||
|
|
||||||
|
(def maps-cache-dir (fs/file cache-dir "maps"))
|
||||||
|
|
||||||
|
(defn list-maps []
|
||||||
|
(let [map-list-file (fs/file cache-dir "map-list.edn")]
|
||||||
|
(fs/create-dirs cache-dir)
|
||||||
|
(if (fs/exists? map-list-file)
|
||||||
|
(with-open [r (io/reader map-list-file)]
|
||||||
|
(edn/read (java.io.PushbackReader. r)))
|
||||||
|
(if *dry-run?*
|
||||||
|
(throw (ex-info (str "Cannot list maps during a dry run "
|
||||||
|
"unless previous result is cached.")
|
||||||
|
{}))
|
||||||
|
(let [resp (http/post
|
||||||
|
"https://cdn.jumpacademy.tf/?generate"
|
||||||
|
{:headers {:content-type "application/x-www-form-urlencoded"}
|
||||||
|
:body (slurp "./request")})]
|
||||||
|
(if (= (:status resp) 200)
|
||||||
|
(as-> (:body resp)
|
||||||
|
$
|
||||||
|
(str/replace $ "wget " "")
|
||||||
|
(str/split $ #"[\n\r]")
|
||||||
|
(pr-str $)
|
||||||
|
(spit map-list-file $))
|
||||||
|
(throw (ex-info "Bad response from jumpacademny.tf" resp))))))))
|
||||||
|
|
||||||
|
(defmacro race [x y]
|
||||||
|
`(let [p# (promise)
|
||||||
|
f1# (future (deliver p# ~x))
|
||||||
|
f2# (future (deliver p# ~y))
|
||||||
|
winner# @p#]
|
||||||
|
(future-cancel f1#)
|
||||||
|
(future-cancel f2#)
|
||||||
|
winner#))
|
||||||
|
|
||||||
|
(defn prefetch [url]
|
||||||
|
(let [command ["nix store prefetch-file --json" url]]
|
||||||
|
(if *dry-run?*
|
||||||
|
(do (apply println "$" command)
|
||||||
|
"«hash»")
|
||||||
|
(when-some [data
|
||||||
|
(race (apply p/shell {:out :string} command)
|
||||||
|
(do (Thread/sleep (* 120 1000))
|
||||||
|
(binding [*out* *err*]
|
||||||
|
(l/warnf "Timed out whilst prefetching %s" url))
|
||||||
|
nil))]
|
||||||
|
(-> data :out (json/decode keyword) :hash)))))
|
||||||
|
|
||||||
|
(defn prefetch*
|
||||||
|
"A caching variant of `prefetch`."
|
||||||
|
[url]
|
||||||
|
(let [[_ file-name] (re-find #"/([^/]*)$" url)
|
||||||
|
cache-entry (fs/file maps-cache-dir (str file-name ".hash"))]
|
||||||
|
(if (fs/exists? cache-entry)
|
||||||
|
(let [cached-result (slurp cache-entry)]
|
||||||
|
cached-result)
|
||||||
|
(let [hash (prefetch url)]
|
||||||
|
(when (and hash
|
||||||
|
;; During dry runs, `prefetch` will return fake hashes that
|
||||||
|
;; we don't want to pollute the cache with.
|
||||||
|
(not *dry-run?*))
|
||||||
|
(fs/create-dirs (fs/parent cache-entry))
|
||||||
|
(spit cache-entry hash))
|
||||||
|
hash))))
|
||||||
|
|
||||||
|
(defn fetch-map
|
||||||
|
"Construct a map with the necessary info to package a map from JumpAcademy.
|
||||||
|
`name` is expected to be the package's name. URL is the map's CDN URL on
|
||||||
|
JumpAcademy. Returns nil on failure."
|
||||||
|
[name url]
|
||||||
|
(binding [*out* *err*]
|
||||||
|
(l/infof "Fetching %s" name))
|
||||||
|
(when-some [hash (prefetch* url)]
|
||||||
|
{:description (format "Map %s for TF2" name)
|
||||||
|
;; For forward-compatibility, when we hopefully add support those
|
||||||
|
;; pesky non-GitHub downloads.
|
||||||
|
:src {:__type "zip"
|
||||||
|
:url url
|
||||||
|
:hash hash}}))
|
||||||
|
|
||||||
|
(defn parse-map-name [url]
|
||||||
|
(let [[_ name] (re-find #"/([^/]*)\.bsp\.bz2$" url)]
|
||||||
|
name))
|
||||||
|
|
||||||
|
(defn fetch-jump-academy []
|
||||||
|
(into {}
|
||||||
|
(for [map-url (list-maps)]
|
||||||
|
(let [map-name (parse-map-name map-url)]
|
||||||
|
(if-some [map-info (fetch-map map-name map-url)]
|
||||||
|
[(keyword map-name)
|
||||||
|
map-info]
|
||||||
|
(binding [*out* *err*]
|
||||||
|
(l/warnf "Skipping map `%s`" map-name)
|
||||||
|
nil))))))
|
||||||
|
|
||||||
|
(defn -main []
|
||||||
|
(binding [*dry-run?* false]
|
||||||
|
(-> (fetch-jump-academy)
|
||||||
|
json/encode
|
||||||
|
print)))
|
||||||
1
tf2/packages/maps/jump-academy/jump-academy.json
generated
Normal file
1
tf2/packages/maps/jump-academy/jump-academy.json
generated
Normal file
File diff suppressed because one or more lines are too long
1
tf2/packages/maps/jump-academy/request
Normal file
1
tf2/packages/maps/jump-academy/request
Normal file
File diff suppressed because one or more lines are too long
Reference in New Issue
Block a user