bang bang

This commit is contained in:
bryanthaboi
2026-08-04 16:37:21 -04:00
parent 12b4c93279
commit d18824cfae
9 changed files with 715 additions and 392 deletions
@@ -259,7 +259,19 @@ bool httpDownload(const char *url, const char *destPath, const char *userAgent,
return false; return false;
JNIEnv *env = (JNIEnv*) SDL_AndroidGetJNIEnv(); JNIEnv *env = (JNIEnv*) SDL_AndroidGetJNIEnv();
jclass activity = env->FindClass("org/love2d/android/GameActivity"); // NOT FindClass: this is the one bridge called off the main thread
// (love.thread workers in src/net/fetch_worker.lua and
// src/update/check_worker.lua). A worker is a raw pthread whose JNI
// class loader is the system one, which cannot see app classes, so
// FindClass("org/love2d/android/GameActivity") left a pending
// ClassNotFoundException and the next JNI call aborted the process --
// opening FIND MODS killed the app on the first stats fetch. Resolving
// through the live activity instance works from any attached thread.
jobject activityObj = (jobject) SDL_AndroidGetActivity();
if (activityObj == nullptr)
return false;
jclass activity = env->GetObjectClass(activityObj);
env->DeleteLocalRef(activityObj);
// Old APK / new liblove skew: report "no transport" the same way a // Old APK / new liblove skew: report "no transport" the same way a
// missing curl does, instead of aborting on a missing method (#597). // missing curl does, instead of aborting on a missing method (#597).
+4 -4
View File
@@ -65,10 +65,10 @@ mkdir -p "$CACHE" "$WORK" "$DIST/mac" "$DIST/win" "$DIST/linux"
say "packing game.love" say "packing game.love"
LOVE_FILE="$WORK/game.love" LOVE_FILE="$WORK/game.love"
rm -f "$LOVE_FILE" rm -f "$LOVE_FILE"
# libs/ carries the vendored FlexLove toolkit the launcher UI is built on # The launcher UI kit lives at src/ui/kit (inside src/, packed wholesale);
# (src/import/LauncherView.lua); a build without it dies on the first frame. # the vendored libs/flexlove tree it replaced is gone.
(cd "$ROOT" && zip -q -9 -r "$LOVE_FILE" \ (cd "$ROOT" && zip -q -9 -r "$LOVE_FILE" \
main.lua conf.lua src libs data assets tools/save-editor \ main.lua conf.lua src data assets tools/save-editor \
tools/rom_manifest.json tools/rom_manifest_blue.json \ tools/rom_manifest.json tools/rom_manifest_blue.json \
tools/rom_manifest_yellow.json \ tools/rom_manifest_yellow.json \
-x '*.DS_Store' 'data/generated/*' 'assets/generated/*') -x '*.DS_Store' 'data/generated/*' 'assets/generated/*')
@@ -88,7 +88,7 @@ fi
# way once). # way once).
for required in tools/save-editor/App.lua tools/save-editor/Kit.lua \ for required in tools/save-editor/App.lua tools/save-editor/Kit.lua \
tools/save-editor/panels/Party.lua \ tools/save-editor/panels/Party.lua \
libs/flexlove/FlexLove.lua \ src/ui/kit/Kit.lua \
tools/rom_manifest.json tools/rom_manifest_blue.json \ tools/rom_manifest.json tools/rom_manifest_blue.json \
tools/rom_manifest_yellow.json; do tools/rom_manifest_yellow.json; do
grep -qxF "$required" "$LOVE_LISTING" \ grep -qxF "$required" "$LOVE_LISTING" \
+11 -11
View File
@@ -202,12 +202,10 @@ pack_game_love() {
# APK, so the mod manager's Delete can't remove it and it reappears every # APK, so the mod manager's Delete can't remove it and it reappears every
# launch. Pokewalker ships as an importable .zip instead, which gives it # launch. Pokewalker ships as an importable .zip instead, which gives it
# a real install/upgrade/delete lifecycle. # a real install/upgrade/delete lifecycle.
# libs/ carries the vendored FlexLove toolkit the launcher UI is built on # The launcher UI kit lives at src/ui/kit (inside src/, packed wholesale);
# (src/import/LauncherView.lua requires it at the top level, and RomImporter # the vendored libs/flexlove tree it replaced is gone.
# calls into that view from both update and draw), so an archive without it
# dies on the first frame with nothing left to fall back to.
(cd "$ROOT" && zip -q -9 -r "$LOVE_FILE" \ (cd "$ROOT" && zip -q -9 -r "$LOVE_FILE" \
main.lua conf.lua src libs data assets tools/save-editor \ main.lua conf.lua src data assets tools/save-editor \
tools/rom_manifest.json tools/rom_manifest_blue.json \ tools/rom_manifest.json tools/rom_manifest_blue.json \
tools/rom_manifest_yellow.json \ tools/rom_manifest_yellow.json \
-x '*.DS_Store' -x '*/.git/*' -x '*/.DS_Store' \ -x '*.DS_Store' -x '*/.git/*' -x '*/.DS_Store' \
@@ -229,12 +227,14 @@ pack_game_love() {
|| fail "game.love is missing the save editor (Edit on a save row would crash)" || fail "game.love is missing the save editor (Edit on a save row would crash)"
grep -qx "$YELLOW_MANIFEST_RELATIVE" <<< "$archive_entries" \ grep -qx "$YELLOW_MANIFEST_RELATIVE" <<< "$archive_entries" \
|| fail "game.love is missing the Yellow ROM import manifest" || fail "game.love is missing the Yellow ROM import manifest"
# This gate exists because libs/ was added to scripts/build.sh's payload and # This gate exists because the launcher's UI toolkit once lived outside
# to no other packager, so Android and iOS built an APK/IPA whose launcher # src/ (libs/flexlove) and was added to scripts/build.sh's payload and to
# threw on require("libs.flexlove.FlexLove") before drawing anything. Source # no other packager, so Android and iOS built an APK/IPA whose launcher
# runs read libs/ off the working tree, so only a build can catch it. # threw before drawing anything. The kit now lives inside src/, but the
grep -qx 'libs/flexlove/FlexLove.lua' <<< "$archive_entries" \ # gate stays: source runs read the working tree, so only a build can catch
|| fail "game.love is missing the FlexLove UI toolkit (launcher dies on frame 1)" # a packaging miss.
grep -qx 'src/ui/kit/Kit.lua' <<< "$archive_entries" \
|| fail "game.love is missing the launcher UI kit (launcher dies on frame 1)"
say "game.love: $(du -h "$LOVE_FILE" | cut -f1) -> $LOVE_FILE" say "game.love: $(du -h "$LOVE_FILE" | cut -f1) -> $LOVE_FILE"
# This script packs its own game.love (it does not reuse build.sh's), so it # This script packs its own game.love (it does not reuse build.sh's), so it
+8 -9
View File
@@ -315,13 +315,11 @@ pack_game_love() {
# it reappears every launch. Mods install as .zips at runtime instead # it reappears every launch. Mods install as .zips at runtime instead
# (launcher -> MODS -> Import mod .zip), the same lifecycle as every # (launcher -> MODS -> Import mod .zip), the same lifecycle as every
# other platform. # other platform.
# libs/ carries the vendored FlexLove toolkit the launcher UI is built on # The launcher UI kit lives at src/ui/kit (inside src/, packed wholesale);
# (src/import/LauncherView.lua requires it at the top level, and RomImporter # the vendored libs/flexlove tree it replaced is gone.
# calls into that view from both update and draw), so an archive without it
# dies on the first frame with nothing left to fall back to.
# shellcheck disable=SC2086 # MANIFESTS is a deliberate word list # shellcheck disable=SC2086 # MANIFESTS is a deliberate word list
(cd "$ROOT" && zip -q -9 -r "$LOVE_FILE" \ (cd "$ROOT" && zip -q -9 -r "$LOVE_FILE" \
main.lua conf.lua src libs data assets tools/save-editor \ main.lua conf.lua src data assets tools/save-editor \
$MANIFESTS \ $MANIFESTS \
-x '*.DS_Store' -x '*/.git/*' -x '*/.DS_Store' \ -x '*.DS_Store' -x '*/.git/*' -x '*/.DS_Store' \
-x 'data/generated/*' -x 'assets/generated/*') -x 'data/generated/*' -x 'assets/generated/*')
@@ -337,14 +335,15 @@ pack_game_love() {
# in 0.1.45 through 0.1.47: decodeManifest (src/import/RomImporter.lua) errors # in 0.1.45 through 0.1.47: decodeManifest (src/import/RomImporter.lua) errors
# outright when a version's manifest is absent, so Import ROM on Yellow died # outright when a version's manifest is absent, so Import ROM on Yellow died
# in the built app while dev, which reads the source tree, stayed green. # in the built app while dev, which reads the source tree, stayed green.
# libs/flexlove/FlexLove.lua is on the list for the same reason: it was added # src/ui/kit/Kit.lua is on the list for the same reason: the launcher's UI
# to build.sh's payload and to no other packager, so the mobile builds shipped # toolkit once lived outside src/ (libs/flexlove) and shipped missing from
# a launcher that threw before drawing its first frame. # the mobile packagers, so the launcher threw before drawing its first
# frame. The kit is inside src/ now; the gate stays to catch a repeat.
archive_entries="$(unzip -Z1 "$LOVE_FILE")" archive_entries="$(unzip -Z1 "$LOVE_FILE")"
# shellcheck disable=SC2086 # MANIFESTS is a deliberate word list # shellcheck disable=SC2086 # MANIFESTS is a deliberate word list
for required in src/update/Boot.lua tools/save-editor/App.lua \ for required in src/update/Boot.lua tools/save-editor/App.lua \
tools/save-editor/Kit.lua tools/save-editor/panels/Party.lua \ tools/save-editor/Kit.lua tools/save-editor/panels/Party.lua \
libs/flexlove/FlexLove.lua \ src/ui/kit/Kit.lua \
$MANIFESTS; do $MANIFESTS; do
printf '%s\n' "$archive_entries" | grep -qx "$required" \ printf '%s\n' "$archive_entries" | grep -qx "$required" \
|| fail "game.love is missing $required" || fail "game.love is missing $required"
+4 -4
View File
@@ -44,10 +44,10 @@ mkdir -p "$(dirname "$OUTPUT")" "$(dirname "$LISTING")"
say "packing game.love" say "packing game.love"
rm -f "$OUTPUT" rm -f "$OUTPUT"
# libs/ carries the vendored FlexLove toolkit the launcher UI is built on # The launcher UI kit lives at src/ui/kit (inside src/, packed wholesale);
# (src/import/LauncherView.lua); a build without it dies on the first frame. # the vendored libs/flexlove tree it replaced is gone.
(cd "$ROOT" && zip -q -9 -r "$OUTPUT" \ (cd "$ROOT" && zip -q -9 -r "$OUTPUT" \
main.lua conf.lua src libs data assets tools/save-editor \ main.lua conf.lua src data assets tools/save-editor \
tools/rom_manifest.json tools/rom_manifest_blue.json \ tools/rom_manifest.json tools/rom_manifest_blue.json \
tools/rom_manifest_yellow.json \ tools/rom_manifest_yellow.json \
-x '*.DS_Store' 'data/generated/*' 'assets/generated/*') -x '*.DS_Store' 'data/generated/*' 'assets/generated/*')
@@ -88,7 +88,7 @@ for required in tools/save-editor/App.lua tools/save-editor/Kit.lua \
tools/save-editor/panels/Party.lua \ tools/save-editor/panels/Party.lua \
tools/rom_manifest.json tools/rom_manifest_blue.json \ tools/rom_manifest.json tools/rom_manifest_blue.json \
tools/rom_manifest_yellow.json \ tools/rom_manifest_yellow.json \
libs/flexlove/FlexLove.lua \ src/ui/kit/Kit.lua \
src/import/LauncherView.lua; do src/import/LauncherView.lua; do
grep -qxF "$required" "$LISTING" \ grep -qxF "$required" "$LISTING" \
|| fail "game.love is missing $required" || fail "game.love is missing $required"
File diff suppressed because it is too large Load Diff
+4
View File
@@ -3468,6 +3468,10 @@ function RomImporter:_pumpFindStats()
end end
self._findStatsCache = self._findStatsCache or {} self._findStatsCache = self._findStatsCache or {}
self._findStatsCache[id] = cached self._findStatsCache[id] = cached
-- The FIND list's sort cache is keyed on this revision; without the
-- bump a Popularity/date sort stays frozen in the order of the first
-- frame (no stats yet = name order) even after every fetch lands.
self._findStatsRev = (self._findStatsRev or 0) + 1
end end
end end
if next(pending) == nil then self._findStatsPending = nil end if next(pending) == nil then self._findStatsPending = nil end
+13 -8
View File
@@ -257,16 +257,21 @@ end
-- across all releases - Released 2024-05-31 - Updated 2026-07-01". -- across all releases - Released 2024-05-31 - Updated 2026-07-01".
-- Each part is optional; nil everywhere means nil, so a row with no data -- Each part is optional; nil everywhere means nil, so a row with no data
-- shows no line rather than a wrong "0". -- shows no line rather than a wrong "0".
function ModUpdate.downloadsLine(total)
if total == nil then return nil end
return Strings("%s downloads across all releases",
ModUpdate.formatCount(total))
end
function ModUpdate.datesLine(first, latest)
if not (first or latest) then return nil end
return Strings("Released %s - Updated %s", first or "?", latest or "?")
end
function ModUpdate.statsLine(total, first, latest) function ModUpdate.statsLine(total, first, latest)
local parts = {} local parts = {}
if total ~= nil then parts[#parts + 1] = ModUpdate.downloadsLine(total)
parts[#parts + 1] = Strings("%s downloads across all releases", parts[#parts + 1] = ModUpdate.datesLine(first, latest)
ModUpdate.formatCount(total))
end
if first or latest then
parts[#parts + 1] = Strings("Released %s - Updated %s",
first or "?", latest or "?")
end
if #parts == 0 then return nil end if #parts == 0 then return nil end
return table.concat(parts, " - ") return table.concat(parts, " - ")
end end
+8 -1
View File
@@ -368,7 +368,10 @@ Kit._navQueue = nil
Kit._activateId = nil Kit._activateId = nil
-- Register a focusable. Returns true when it currently holds the ring. -- Register a focusable. Returns true when it currently holds the ring.
-- Shielded widgets do not register: while a modal owns the frame the ring
-- must not wander through (or Enter-activate) the controls underneath it.
function Kit.focusable(id, x, y, w, h) function Kit.focusable(id, x, y, w, h)
if Kit.blockClicks then return false end
local n = (Kit._navN or 0) + 1 local n = (Kit._navN or 0) + 1
Kit._navN = n Kit._navN = n
local slot = Kit._nav[n] local slot = Kit._nav[n]
@@ -492,6 +495,9 @@ function Kit.hit(x, y, w, h)
end end
function Kit.hover(x, y, w, h) function Kit.hover(x, y, w, h)
-- Shielded widgets (drawn while a modal owns the frame) must not glow
-- either: a hover highlight under the scrim reads as "still clickable".
if Kit.blockClicks then return false end
return Kit.hit(x, y, w, h) return Kit.hit(x, y, w, h)
end end
@@ -640,7 +646,8 @@ function Kit.button(x, y, w, h, label, opts)
end end
if not enabled then return false end if not enabled then return false end
return Kit.press(x, y, w, h) return Kit.press(x, y, w, h)
or (opts.id ~= nil and Kit._activateId == opts.id) or (not Kit.blockClicks and opts.id ~= nil
and Kit._activateId == opts.id)
end end
-- A small square control: +/- steppers, arrow cyclers, the row X. -- A small square control: +/- steppers, arrow cyclers, the row X.