Add Selkies streamer prototype for Java games
Runs a Flashpoint game natively in a container and streams it to the browser. fp-launch follows the Linux launcher's sequence: start the game server, mount the game's zip, and run startJava.sh through the proxy.
This commit is contained in:
@@ -0,0 +1,14 @@
|
||||
FROM ghcr.io/linuxserver/baseimage-selkies:debiantrixie
|
||||
|
||||
RUN apt-get update && \
|
||||
DEBIAN_FRONTEND=noninteractive apt-get install -y --no-install-recommends \
|
||||
fontconfig \
|
||||
fonts-dejavu-core \
|
||||
libasound2-plugins \
|
||||
libxi6 \
|
||||
libxrender1 \
|
||||
libxtst6 \
|
||||
sqlite3 && \
|
||||
rm -rf /var/lib/apt/lists/*
|
||||
|
||||
COPY root/ /
|
||||
@@ -0,0 +1,35 @@
|
||||
# Flashpoint streamer (prototype)
|
||||
|
||||
Runs a Flashpoint game natively on the server and streams it to the browser with
|
||||
[Selkies](https://github.com/selkies-project/selkies), for platforms that cannot
|
||||
run in a browser. One container plays one game, set by `GAME_ID`. Only Java
|
||||
applets are supported so far.
|
||||
|
||||
## Requirements
|
||||
|
||||
A Linux Flashpoint install at `FLASHPOINT_HOST_PATH`. The streamer uses the
|
||||
Infinity build's `Server/FlashpointGameServer` and `FPSoftware/Java`, which
|
||||
Ultimate's packed zips do not include on Linux. To add them to an extracted
|
||||
Ultimate without overwriting its data, copy an extracted
|
||||
[Infinity for Linux](https://flashpointarchive.org/downloads) over it:
|
||||
|
||||
```sh
|
||||
rsync -a --ignore-existing /path/to/infinity/ /path/to/flashpoint/
|
||||
```
|
||||
|
||||
## Usage
|
||||
|
||||
```sh
|
||||
FLASHPOINT_HOST_PATH=/path/to/flashpoint docker compose up -d --build
|
||||
```
|
||||
|
||||
Open `https://<host>:3001` and accept the self-signed certificate. To play a
|
||||
different game, set `GAME_ID` and recreate the container. The launch log is at
|
||||
`/config/fp-launch.log` inside the container.
|
||||
|
||||
## How it works
|
||||
|
||||
`fp-launch` follows the Flashpoint launcher's Linux launch sequence: it starts
|
||||
the game server, mounts the game's zip through the server's `mountzip` API, and
|
||||
runs the game's application with its HTTP proxy pointed at the game server.
|
||||
Selkies restarts the game when it exits (`RESTART_APP`).
|
||||
@@ -0,0 +1,16 @@
|
||||
services:
|
||||
flashpoint-streamer:
|
||||
build: .
|
||||
container_name: flashpoint-streamer
|
||||
shm_size: 1gb
|
||||
ports:
|
||||
- "${STREAMER_PORT:-3001}:3001"
|
||||
volumes:
|
||||
- ${FLASHPOINT_HOST_PATH:?FLASHPOINT_HOST_PATH is required}:/flashpoint:ro
|
||||
environment:
|
||||
- PUID=${PUID:-1000}
|
||||
- PGID=${PGID:-1000}
|
||||
- GAME_ID=${GAME_ID:-247a4c93-c252-49c8-8bc9-fb43d5c039df}
|
||||
- RESTART_APP=true
|
||||
- NO_DECOR=true
|
||||
- TITLE=Flashpoint
|
||||
@@ -0,0 +1 @@
|
||||
fp-launch "$GAME_ID" >>"$HOME/fp-launch.log" 2>&1
|
||||
@@ -0,0 +1,2 @@
|
||||
pcm.!default { type pulse }
|
||||
ctl.!default { type pulse }
|
||||
+40
@@ -0,0 +1,40 @@
|
||||
#!/usr/bin/env bash
|
||||
# Launch a Flashpoint game by ID the way the Linux launcher does: start the
|
||||
# game server, mount the game's zip, then run its application through the proxy.
|
||||
set -euo pipefail
|
||||
|
||||
FP_PATH=${FP_PATH:-/flashpoint}
|
||||
ID=${1:?usage: fp-launch <game id>}
|
||||
DB=$FP_PATH/Data/flashpoint.sqlite
|
||||
API=http://127.0.0.1:22501/fpProxy/api
|
||||
|
||||
[[ $ID =~ ^[0-9a-f-]{36}$ ]] || { echo "Invalid game id: $ID" >&2; exit 1; }
|
||||
|
||||
if ! curl -s -o /dev/null "$API/listmountzip"; then
|
||||
"$FP_PATH/Server/FlashpointGameServer" -rootPath "$FP_PATH" \
|
||||
-useInfinityServer=false -handleLegacyRequests=true &
|
||||
until curl -s -o /dev/null "$API/listmountzip"; do sleep 0.2; done
|
||||
fi
|
||||
|
||||
IFS=$'\x1f' read -r app cmd date_added < <(sqlite3 -readonly -separator $'\x1f' "$DB" "
|
||||
select coalesce(nullif(d.applicationPath, ''), g.applicationPath),
|
||||
coalesce(nullif(d.launchCommand, ''), g.launchCommand),
|
||||
coalesce(d.dateAdded, '')
|
||||
from game g left join game_data d on d.id = g.activeDataId
|
||||
where g.id = '$ID'") || true
|
||||
[[ -n ${app:-} ]] || { echo "Game not found: $ID" >&2; exit 1; }
|
||||
|
||||
if [[ -n $date_added ]]; then
|
||||
zip=$FP_PATH/Data/Games/$ID-$(date -u -d "$date_added" +%s%3N).zip
|
||||
curl -sf -X POST -H 'Content-Type: application/json' \
|
||||
-d "{\"filePath\": \"$zip\"}" "$API/mountzip" >/dev/null ||
|
||||
{ echo "Failed to mount $zip" >&2; exit 1; }
|
||||
fi
|
||||
|
||||
echo "Launching $ID: $app $cmd"
|
||||
case ${app,,} in
|
||||
'fpsoftware\startjava.bat' | 'fpsoftware\startjavainbrowser.bat')
|
||||
FP_PATH=$FP_PATH exec "$FP_PATH/FPSoftware/startJava.sh" "$cmd" ;;
|
||||
*)
|
||||
echo "Unsupported application: $app" >&2; exit 1 ;;
|
||||
esac
|
||||
Reference in New Issue
Block a user