mirror of
https://github.com/rommapp/romm.git
synced 2026-10-12 02:21:58 +00:00
* feat(player): play RPG Maker 2000/2003 games in the browser with EasyRPG Embed the EasyRPG web player for extracted game folders on the rpg-maker platform. The backend generates the player's index.json from the scanned files and merges in the free EasyRPG RTP under every name the official and fan RTPs give its assets, so games that lean on the RTP find them. In-game saves sync with the user's RomM saves through the player's IndexedDB storage. Co-Authored-By: Claude Opus 5.5 (1M context) <[email protected]> * refactor(easyrpg): read the free RTP from a fixed path instead of an env var The full image always keeps the RTP at /var/www/html/assets/easyrpg/rtp, so the path is a constant beside the web path nginx serves it under. The dev container links its copy there at startup. Co-Authored-By: Claude Opus 5.5 (1M context) <[email protected]> * fix(easyrpg): code-review fixes for the save sync and asset endpoint - Wait for an in-flight push before the quit push, so the newest save uploads - Keep Play disabled until the fresh rom (and its saves) is fetched - Stop onPlay and the rom fetch from acting after the view unmounts - Leave through usePlayerExit like the other players - Handle a rejected IDB commit when the run itself fails - Track uploads by the browser's file name - Load only visibility and files per asset request, not the full rom - Serve DEV_MODE files as octet-stream, matching nginx - Make the traversal test actually reach the endpoint Co-Authored-By: Claude Opus 5.5 (1M context) <[email protected]> * refactor(easyrpg): simplify pass over the player and asset endpoint - Load only file paths per asset request, and look up RTP folders in O(1) - Reuse RomFile.file_name_for_download and usePlayerFullscreen - Share one dev/prod serve helper for game and RTP files - Derive the save sync's game key from the rom - Have the RTP table tool reuse normalize_name - Make save-module internals private and tidy the prepare/read loops Co-Authored-By: Claude Opus 5.5 (1M context) <[email protected]> * feat(easyrpg): flag RPG Maker game folders on the rom schemas Gallery lists carry no files, so the frontend guessed that every multi-file rom on the rpg-maker platform was playable, including RPG Maker XP/VX/MV folders. Rom now has a deferred `is_easyrpg_game` subquery (an RPG_RT.ldb at the folder root), loaded with the other gallery file stats and derived from loaded files on the with_files path, and the frontend reads it. Co-Authored-By: Claude Opus 5.5 (1M context) <[email protected]> * refactor(easyrpg): drop server save sync, keep saves per user in the browser Server sync moves to a follow-up that puts the web players on device sync. Saves now stay in the player's IndexedDB, as js-dos does, with the same note on the start page. The player is launched as `<rom id>-<user id>` so each RomM account sharing a browser profile keeps its own saves; nginx and Vite drop the user id when routing to the backend. Co-Authored-By: Claude Opus 5.5 (1M context) <[email protected]> * fix(easyrpg): address Greptile review - Start timing the play session once the player page loads - Use object-form props in the view test's button mock - Keep the RTP table tool's docstring to one sentence Co-Authored-By: Claude Opus 5.5 (1M context) <[email protected]> * refactor(easyrpg): keep the RTP table in a fixtures folder Matches handler/metadata/fixtures, where the other bundled data files live. Co-Authored-By: Claude Opus 5.5 (1M context) <[email protected]> --------- Co-authored-by: Claude Opus 5.5 (1M context) <[email protected]>
143 lines
5.0 KiB
Plaintext
143 lines
5.0 KiB
Plaintext
# This template is used to generate the default.conf file for the nginx server,
|
|
# by using `envsubst` to replace the environment variables in the template with
|
|
# their actual values.
|
|
|
|
# Gunicorn upstream. Defined here (not in nginx.conf) so the port stays in sync
|
|
# with the ${DEV_PORT} gunicorn binds to.
|
|
upstream wsgi_server {
|
|
server 127.0.0.1:${DEV_PORT};
|
|
}
|
|
|
|
# Helper to get scheme regardless if we are behind a proxy or not
|
|
map $http_x_forwarded_proto $forwardscheme {
|
|
default $scheme;
|
|
https https;
|
|
}
|
|
|
|
# COEP and COOP headers for cross-origin isolation, which are set only for the
|
|
# EmulatorJS and js-dos player paths, to enable SharedArrayBuffer support, which
|
|
# is needed for multi-threaded cores. Not $uri: try_files rewrites it to
|
|
# /index.html before add_header runs, so the query string is matched explicitly.
|
|
# frontend/scripts/playerIsolationHeaders.ts restates these entries for the dev server.
|
|
map $request_uri $coep_header {
|
|
default "";
|
|
~^/rom/.*/(ejs|jsdos)(\?|$) "require-corp";
|
|
~^/console/rom/[0-9]+/play "require-corp";
|
|
}
|
|
map $request_uri $coop_header {
|
|
default "";
|
|
~^/rom/.*/(ejs|jsdos)(\?|$) "same-origin";
|
|
~^/console/rom/[0-9]+/play "same-origin";
|
|
}
|
|
|
|
# The EasyRPG web player fetches each file of a game from games/<rom id>-<user id>/
|
|
# beside itself. Built from the raw $request_uri, so names keep the client's encoding.
|
|
map $request_uri $easyrpg_backend_uri {
|
|
default "";
|
|
~^/assets/easyrpg/games/(?<rom_id>[0-9]+)-[0-9]+/(?<easyrpg_path>[^?]*) /api/roms/$rom_id/easyrpg/$easyrpg_path;
|
|
}
|
|
|
|
# Library resources under /assets/romm/resources/ are a mix. Covers (?ts=) and
|
|
# manuals (?v=) are versioned by a known cache-busting query, so they can be
|
|
# frozen; screenshots and RA badges reuse stable filenames (0.jpg, ...) and are
|
|
# overwritten on re-scrape, so they must revalidate. Freeze only when a
|
|
# recognized version param (ts or v) is present, not on any arbitrary query
|
|
# (e.g. ?download=1 must not pin a screenshot for a year).
|
|
map $args $resources_cache_control {
|
|
default "public, max-age=3600, must-revalidate";
|
|
"~(^|&)(ts|v)=" "public, max-age=31536000, immutable";
|
|
}
|
|
|
|
server {
|
|
root /var/www/html;
|
|
listen ${ROMM_PORT};
|
|
${IPV6_LISTEN}
|
|
server_name localhost;
|
|
|
|
${NGINX_ACCESS_LOG}
|
|
|
|
proxy_set_header Host $http_host;
|
|
proxy_set_header X-Real-IP $remote_addr;
|
|
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
|
proxy_set_header X-Forwarded-Proto $forwardscheme;
|
|
|
|
# Serve the .gz siblings the frontend build writes. Scoped to the build output:
|
|
# the internal /library/ and /cache/ locations must never match a ROM's own
|
|
# .gz sibling, and library resources have no precompressed form.
|
|
location / {
|
|
gzip_static on;
|
|
try_files $uri $uri/ /index.html;
|
|
proxy_redirect off;
|
|
add_header Cache-Control "no-cache";
|
|
add_header Access-Control-Allow-Origin *;
|
|
add_header Access-Control-Allow-Methods *;
|
|
add_header Access-Control-Allow-Headers *;
|
|
add_header Cross-Origin-Embedder-Policy $coep_header;
|
|
add_header Cross-Origin-Opener-Policy $coop_header;
|
|
}
|
|
|
|
# Freeze content-hashed frontend bundles (fingerprinted files under /assets)
|
|
location ~* "^/assets/[^/]+-[A-Za-z0-9_-]{8,}\.(js|mjs|css|map|woff2?|ttf|otf|eot|svg|png|jpe?g|gif|webp|avif|ico|json|wasm)$" {
|
|
add_header Cache-Control "public, max-age=31536000, immutable";
|
|
gzip_static on;
|
|
try_files $uri $uri/ =404;
|
|
}
|
|
|
|
# Freeze library resources carrying cache-busting query
|
|
location /assets/romm/resources/ {
|
|
add_header Cache-Control $resources_cache_control;
|
|
try_files $uri $uri/ =404;
|
|
}
|
|
|
|
location ^~ /assets/easyrpg/games/ {
|
|
if ($easyrpg_backend_uri = "") {
|
|
return 404;
|
|
}
|
|
proxy_pass http://wsgi_server$easyrpg_backend_uri;
|
|
}
|
|
|
|
# Everything else under /assets keeps a stable URL across image upgrades
|
|
location /assets {
|
|
add_header Cache-Control "public, max-age=3600, must-revalidate";
|
|
gzip_static on;
|
|
try_files $uri $uri/ =404;
|
|
}
|
|
|
|
# OpenAPI for swagger and redoc
|
|
location /openapi.json {
|
|
proxy_pass http://wsgi_server;
|
|
}
|
|
|
|
# Backend api calls
|
|
location /api {
|
|
proxy_pass http://wsgi_server;
|
|
proxy_request_buffering off;
|
|
proxy_buffering off;
|
|
proxy_read_timeout 300s;
|
|
}
|
|
location ~ ^/(ws|netplay) {
|
|
proxy_pass http://wsgi_server;
|
|
proxy_http_version 1.1;
|
|
proxy_set_header Upgrade $http_upgrade;
|
|
proxy_set_header Connection "upgrade";
|
|
}
|
|
|
|
# Internally redirect download requests
|
|
location /library/ {
|
|
internal;
|
|
alias "${ROMM_BASE_PATH}/library/";
|
|
}
|
|
|
|
# Internally redirect cached zip file requests (Range-resumable downloads)
|
|
location /cache/ {
|
|
internal;
|
|
alias "${ROMM_BASE_PATH}/cache/";
|
|
}
|
|
|
|
# Internal decoding endpoint, used to decode base64 encoded data
|
|
location /decode {
|
|
internal;
|
|
js_content decode.decodeBase64;
|
|
}
|
|
}
|