#!/usr/bin/env bash # Compila o Plankter (mio / supercell, Purism Free-Software Game Jam 2024; codigo GPL-3.0-or-later, arte, musica e # efeitos CC0; codeberg.org/supercell/Plankter) para a web (HTML5) com o HaxeFlixel, tudo pinado e conferido pelo # SHA-256 (o projeto nao fixa versoes; usamos o conjunto que era o atual na epoca do jogo): # Haxe 4.3.6 (release oficial macOS) + Neko 2.4.0 (para o haxelib e o Lime), Lime 8.1.2, OpenFL 9.3.3, # HaxeFlixel 5.8.0, flixel-addons 3.2.3 e flixel-ui 2.6.1 (os zips do lib.haxe.org). # O ndll do Lime 8.1.2 so existe para x86_64, entao em Apple Silicon a compilacao roda sob Rosetta # (`arch -x86_64`); a saida e JavaScript e nao depende da arquitetura de quem compila. # # Mudancas, todas feitas aqui (o fonte GPL publicado e o projeto do commit pinado, sem nenhuma mudanca): # - a fonte padrao do HaxeFlixel, "Nokia Cellphone FC Small" (zeh Fernando; o proprio autor diz nao saber se a # fonte original da Nokia tem copyright), vira a Jersey 20 (SIL OFL 1.1, google/fonts no commit pinado): # troca do arquivo de fonte embutido pelo flixel (include.xml) e de FlxAssets.FONT_DEFAULT; o texto do jogo todo # usa essa fonte. A Monsterrat do depurador (so existe com FLX_NO_DEBUG desligado) sai do include.xml; # - uma Content-Security-Policy no index.html (nenhuma conexao fora desta origem); # - a versao do cache de assets, um numero aleatorio que o Lime grava no Plankter.js, vira 1 (build reprodutivel). # # src/FredGames.Bundler/Builds/build-plankter.sh # # Saida: artifacts/build/plankter-7bb2d4a/{web.tar.gz,plankter-7bb2d4a.tar.gz,third-party-licenses.txt, # Jersey20-OFL.txt}, que o bundle.yaml do jogo confere pelo SHA-256. web.tar.gz e o jogo (pasta web/); # plankter-7bb2d4a.tar.gz e o fonte publicado (o repositorio do commit). Os dois saem iguais a cada execucao. set -euo pipefail NAME=plankter COMMIT=7bb2d4a4bdef21c349686a7239e7fdae29a82a08 SHA256=026546b3ce5831c48dcd2ac72d399efd557711f0bc0180d1be6ef79c18818a64 HAXE=4.3.6 HAXE_SHA256=4a705fc1a35e269480e733be53a660ab1d2093f79fe5518dfba8f6301c232bd6 NEKO=2.4.0 NEKO_SHA256=4d1407228843e144639d41edfd51642a06a90a2f9ded0582c3a459b1dd1b4f15 FONTS_COMMIT=9862abc066c9b83bf84c3e8ed1fc2d8d48f9bbf0 LIBS="lime:8,1,2:cc5fa948712e6affcbde151f8a79d2ec0a7df3995e051e050925fd494472cc64 openfl:9,3,3:cf869950b56875fa3c47470ec9a90fec4cf54245c7f5e9e544613602f582dbc8 flixel:5,8,0:23e6d9078c00ce0e9d0302ca0179057b3269f6d3f7dc4378d3d5da790b71cfe1 flixel-addons:3,2,3:599507311b00e6ce5511e9e1a22e9fcbbbca1cc37c79684729587cc29bec9930 flixel-ui:2,6,1:eed3a59e4e527d8b6ec57a8f86e41a667c945495a41cc76f87c16eb601dab709" here="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" root="$(git -C "$here" rev-parse --show-toplevel 2>/dev/null || pwd)" out="$root/artifacts/build/$NAME-${COMMIT:0:7}" cache="$root/artifacts/build/cache" tools="$root/artifacts/tools" libs="$tools/haxelib-plankter" mkdir -p "$cache" fetch() { if [ ! -f "$cache/$2" ]; then curl -fsSL --retry 4 "$1" -o "$cache/$2.partial" && mv "$cache/$2.partial" "$cache/$2" fi echo "$3 $cache/$2" | shasum -a 256 -c - } install_tools() { if [ ! -d "$tools/haxe-$HAXE" ]; then fetch "https://github.com/HaxeFoundation/haxe/releases/download/$HAXE/haxe-$HAXE-osx.tar.gz" "haxe-$HAXE-osx.tar.gz" "$HAXE_SHA256" rm -rf "$tools/haxe-$HAXE.tmp"; mkdir -p "$tools/haxe-$HAXE.tmp" tar -xzf "$cache/haxe-$HAXE-osx.tar.gz" -C "$tools/haxe-$HAXE.tmp" --strip-components 1 mv "$tools/haxe-$HAXE.tmp" "$tools/haxe-$HAXE" fi if [ ! -d "$tools/neko-$NEKO" ]; then fetch "https://github.com/HaxeFoundation/neko/releases/download/v${NEKO//./-}/neko-$NEKO-osx-universal.tar.gz" "neko-$NEKO-osx-universal.tar.gz" "$NEKO_SHA256" rm -rf "$tools/neko-$NEKO.tmp"; mkdir -p "$tools/neko-$NEKO.tmp" tar -xzf "$cache/neko-$NEKO-osx-universal.tar.gz" -C "$tools/neko-$NEKO.tmp" --strip-components 1 mv "$tools/neko-$NEKO.tmp" "$tools/neko-$NEKO" fi # Bibliotecas do haxelib: cada uma em /, com .current = versao com pontos. mkdir -p "$libs" while IFS=: read -r lib ver sha; do [ -d "$libs/$lib/$ver" ] && continue fetch "https://lib.haxe.org/files/3.0/$lib-$ver.zip" "$lib-$ver.zip" "$sha" rm -rf "$libs/$lib/$ver.tmp"; mkdir -p "$libs/$lib/$ver.tmp" unzip -q "$cache/$lib-$ver.zip" -d "$libs/$lib/$ver.tmp" # Alguns zips (o do Lime) trazem uma unica pasta na raiz; o haxelib a tira ao instalar. if [ ! -f "$libs/$lib/$ver.tmp/haxelib.json" ]; then inner=$(ls "$libs/$lib/$ver.tmp"); mv "$libs/$lib/$ver.tmp/$inner" "$libs/$lib/$ver.tmp2" rmdir "$libs/$lib/$ver.tmp"; mv "$libs/$lib/$ver.tmp2" "$libs/$lib/$ver.tmp" fi mv "$libs/$lib/$ver.tmp" "$libs/$lib/$ver" printf '%s' "${ver//,/.}" > "$libs/$lib/.current" done <<< "$LIBS" } if [ "${1:-}" = "--install" ]; then install_tools; exit 0; fi lockf -k "$root/artifacts/haxe-$HAXE.lock" bash "${BASH_SOURCE[0]}" --install fetch "https://codeberg.org/supercell/Plankter/archive/$COMMIT.tar.gz" "$NAME-${COMMIT:0:7}.tar.gz" "$SHA256" fetch "https://raw.githubusercontent.com/google/fonts/$FONTS_COMMIT/ofl/jersey20/Jersey20-Regular.ttf" \ "Jersey20-Regular-${FONTS_COMMIT:0:7}.ttf" 76670d7e8826860e3d2f2846b88bc1652135b8d54b6adfa5a87649b9fa4bd3b4 fetch "https://raw.githubusercontent.com/google/fonts/$FONTS_COMMIT/ofl/jersey20/OFL.txt" \ "Jersey20-OFL-${FONTS_COMMIT:0:7}.txt" 436d5836064cec796c7ddde6fb4faeabdb6f2f17443a24a30d0c38b75d13f922 rm -rf "$out" mkdir -p "$out/tree" "$out/web" "$out/haxelib" "$out/bin" "$out/home" tar -xzf "$cache/$NAME-${COMMIT:0:7}.tar.gz" -C "$out/tree" --strip-components 1 tree="$out/tree" # Fonte publicado: o repositorio do commit, em tar deterministico (ordem, dono e data fixos). TZ=UTC find "$tree" -exec touch -t 202001010000 {} + ( cd "$tree" && find . -type f | sed 's|^\./||' | LC_ALL=C sort > "$out/files.txt" ) ( cd "$tree" && COPYFILE_DISABLE=1 tar --format=ustar --uid 0 --gid 0 --uname root --gname root -n \ -cf - -T "$out/files.txt" ) | gzip -n -9 > "$out/$NAME-${COMMIT:0:7}.tar.gz" # Repositorio de bibliotecas desta compilacao: links para as originais e um flixel proprio, ja com as mudancas. for lib in lime openfl flixel-addons flixel-ui; do ln -s "$libs/$lib" "$out/haxelib/$lib"; done mkdir -p "$out/haxelib/flixel" cp -R "$libs/flixel/5,8,0" "$out/haxelib/flixel/5,8,0" printf '%s' "5.8.0" > "$out/haxelib/flixel/.current" flixel="$out/haxelib/flixel/5,8,0" cp "$cache/Jersey20-Regular-${FONTS_COMMIT:0:7}.ttf" "$flixel/assets/fonts/jersey20.ttf" rm "$flixel/assets/fonts/nokiafc22.ttf" "$flixel/assets/fonts/nokiafc22.ttf.hash" "$flixel/assets/fonts/nokiafc22.woff" \ "$flixel/assets/fonts/nokiafc22.svg" sed -i.bak 's|nokiafc22.ttf|jersey20.ttf|g' "$flixel/include.xml" sed -i.bak 's|FONT_DEFAULT:String = "Nokia Cellphone FC Small"|FONT_DEFAULT:String = "Jersey 20 Regular"|' "$flixel/flixel/system/FlxAssets.hx" grep -q 'FONT_DEFAULT:String = "Jersey 20 Regular"' "$flixel/flixel/system/FlxAssets.hx" sed -i.bak2 '/fonts\/monsterrat.ttf/d' "$flixel/include.xml" ! grep -q 'monsterrat\|nokia' "$flixel/include.xml" rm "$flixel/flixel/system/FlxAssets.hx.bak" "$flixel/include.xml.bak" "$flixel/include.xml.bak2" # O haxelib e o neko sao chamados pelo Lime por um shell (/bin/sh), que perde o DYLD_*: dois wrappers resolvem. for b in haxelib neko; do real="$tools/haxe-$HAXE/$b"; [ "$b" = neko ] && real="$tools/neko-$NEKO/neko" printf '#!/bin/sh\nexport DYLD_FALLBACK_LIBRARY_PATH=%s\nexec %s "$@"\n' "$tools/neko-$NEKO" "$real" > "$out/bin/$b" chmod +x "$out/bin/$b" done export NEKOPATH="$tools/neko-$NEKO" DYLD_FALLBACK_LIBRARY_PATH="$tools/neko-$NEKO" HAXE_STD_PATH="$tools/haxe-$HAXE/std" export PATH="$out/bin:$tools/haxe-$HAXE:$PATH" HAXEPATH="$tools/haxe-$HAXE" HAXELIB_PATH="$out/haxelib" export HOME="$out/home" TZ=UTC LC_ALL=C cd "$tree" arch -x86_64 /bin/bash -c 'haxelib run lime build html5 -release' > "$out/build.log" 2>&1 || { tail -30 "$out/build.log" >&2; exit 1; } bin="$tree/export/html5/bin" test -f "$bin/Plankter.js" grep -q "font-family: 'Jersey 20 Regular'" "$bin/index.html" # CSP: nenhuma conexao fora desta origem. python3 -I - "$bin/index.html" <<'PY' import sys, pathlib p = pathlib.Path(sys.argv[1]); t = p.read_text() csp = ('\n\t') assert t.count('') == 1 t = t.replace('', '\n\t' + csp.rstrip('\t'), 1) p.write_text(t) PY # O Lime grava um numero aleatorio como versao do cache de assets; fixo, a compilacao sai igual a cada vez. python3 -I - "$bin/Plankter.js" <<'PY' import sys, re, pathlib p = pathlib.Path(sys.argv[1]); t = p.read_text() t, n = re.subn(r'(this\.image = new haxe_ds_StringMap\(\);\n\tthis\.version = )\d+;', r'\g<1>1;', t) assert n == 1, n p.write_text(t) PY rmdir "$bin/lib" 2>/dev/null || true cp -R "$bin/." "$out/web/" TZ=UTC find "$out/web" -exec touch -t 202001010000 {} + ( cd "$out" && find web -type f | LC_ALL=C sort > "$out/web-files.txt" ) ( cd "$out" && COPYFILE_DISABLE=1 tar --format=ustar --uid 0 --gid 0 --uname root --gname root -n \ -cf - -T "$out/web-files.txt" ) | gzip -n -9 > "$out/web.tar.gz" # Licencas do que a compilacao embute no jogo (Haxe std, Lime, OpenFL, HaxeFlixel e as bibliotecas JS do Lime). { echo "Plankter - third-party licences of the code compiled into the game (Plankter.js)" echo "================================================================================" echo echo "Built with Haxe $HAXE, Lime 8.1.2, OpenFL 9.3.3, HaxeFlixel 5.8.0, flixel-addons 3.2.3 and flixel-ui 2.6.1" echo "(see src/build-plankter.sh). Every library below is under the MIT licence; texts follow." echo echo "--- Haxe standard library ---" sed -n '/^Copyright (C)2005/,/^DEALINGS IN THE SOFTWARE\./p' "$tools/haxe-$HAXE/LICENSE.txt" for l in lime:8,1,2 openfl:9,3,3 flixel:5,8,0 flixel-addons:3,2,3 flixel-ui:2,6,1; do echo; echo "--- ${l%%:*} ${l##*:} (LICENSE.md) ---" cat "$libs/${l%%:*}/${l##*:}/LICENSE.md" done echo; echo "--- Lime NOTICE.md (the JavaScript libraries below are bundled in the HTML5 output) ---" sed -n '/howler.js 2.1.1/,/stats.js r16/p' "$libs/lime/8,1,2/NOTICE.md" echo "(the output carries howler.js v2.2.4: Copyright (c) 2013-2020 James Simpson and GoldFire Studios, Inc., MIT;" echo " FileSaver.js: Copyright (c) 2016 Eli Grey, MIT; pako 1.0.2: Copyright (C) 2014-2017 Vitaly Puzrin and Andrey Tupitsin," echo " MIT, with zlib parts Copyright (C) 1995-2013 Jean-loup Gailly and Mark Adler, zlib licence. The MIT licence" echo " text is the one above; the notices travel inside Plankter.js.)" } > "$out/third-party-licenses.txt" cp "$cache/Jersey20-OFL-${FONTS_COMMIT:0:7}.txt" "$out/Jersey20-OFL.txt" ls -l "$out/web" "$out"/*.tar.gz