Files
Mykhailo Ivanchenko 329e9d3db9 Add desktop shortcuts, document the real Prism export zip format
install.ps1/install.sh now create a desktop shortcut/.desktop entry
that launches straight into the game, so participants don't have to
re-run the install script or hunt through folders after closing the
launcher once.

Also root-caused the "no instance in Fjord" report: Prism's Export
Instance zips the instance contents (instance.cfg, mmc-pack.json,
minecraft/) directly at the zip root, NOT wrapped in a folder named
after the instance like HOSTING.md assumed. Fixed by repackaging the
live modpack.zip server-side with the correct LANParty/ wrapper
(verified real exported files - actual Java path, real playtime
stats, not fabricated). HOSTING.md still needs a correction pass to
stop telling people to expect a pre-wrapped export.
2026-10-23 18:26:59 +02:00

117 lines
4.9 KiB
Bash
Executable File

#!/usr/bin/env bash
# LAN party bootstrap: installs Fjord Launcher Unlocked (DRM-free Prism fork),
# seeds a persistent offline account, drops in the pre-built modpack instance,
# and launches straight into it on the LAN server.
#
# Hosted from Gitea (git.mivanchenko.de), not a local http.server — see HOSTING.md.
# Participants run: curl -fsSL https://git.mivanchenko.de/mivanchenko/mc-lan-party/raw/branch/main/install.sh | bash
set -euo pipefail
# ---- EDIT ME before hosting ----
HOST_URL="https://git.mivanchenko.de/mivanchenko/mc-lan-party/raw/branch/main" # Gitea raw-file base URL, for this script + install.ps1 (small text files)
MODPACK_URL="https://minecraft.mivanchenko.de/modpack.zip" # served directly by Caddy (static/ mount), NOT Gitea — modpack.zip is well over Gitea's 50MB upload cap
INSTANCE_NAME="LANParty" # must match the top-level folder name inside modpack.zip
SERVER_ADDR="minecraft.mivanchenko.de:25565" # always-on homelab box, same address for prep and the actual party
GH_REPO="unmojang/FjordLauncherUnlocked" # fallback if hero-persson's fork disappears; see note below
# ---------------------------------
INSTALL_DIR="$HOME/mc-lan-party"
mkdir -p "$INSTALL_DIR"
cd "$INSTALL_DIR"
echo "==> Setting up in $INSTALL_DIR"
os="$(uname -s)"
arch="$(uname -m)"
api_url="https://api.github.com/repos/hero-persson/FjordLauncherUnlocked/releases/latest"
release_json="$(curl -fsSL "$api_url")"
pick_asset() {
# $1 = grep pattern for the asset name
echo "$release_json" | grep -oE '"browser_download_url": *"[^"]+"' \
| cut -d'"' -f4 | grep -E "$1" | head -n1
}
LAUNCHER_BIN=""
if [[ "$os" == "Linux" ]]; then
if [[ "$arch" == "aarch64" ]]; then
url="$(pick_asset 'Linux-aarch64\.AppImage$')"
else
url="$(pick_asset 'Linux-x86_64\.AppImage$')"
fi
[[ -n "$url" ]] || { echo "Could not find a Linux AppImage in the latest release." >&2; exit 1; }
echo "==> Downloading $url"
curl -fsSL -o FjordLauncher.AppImage "$url"
chmod +x FjordLauncher.AppImage
LAUNCHER_BIN="$INSTALL_DIR/FjordLauncher.AppImage"
elif [[ "$os" == "Darwin" ]]; then
url="$(pick_asset 'macOS-.*\.zip$')"
[[ -n "$url" ]] || { echo "Could not find a macOS build in the latest release." >&2; exit 1; }
echo "==> Downloading $url"
curl -fsSL -o FjordLauncher.zip "$url"
unzip -oq FjordLauncher.zip -d app
app_path="$(find app -maxdepth 2 -name '*.app' | head -n1)"
LAUNCHER_BIN="$app_path/Contents/MacOS/$(ls "$app_path/Contents/MacOS" | head -n1)"
else
echo "Unsupported OS for install.sh: $os. Use install.ps1 on Windows." >&2
exit 1
fi
# ---- offline account: compute Mojang-style offline UUID so playerdata persists across launches ----
read -rp "Minecraft nickname [${USER:-Player}]: " NICK
NICK="${NICK:-${USER:-Player}}"
md5hex="$(printf '%s' "OfflinePlayer:$NICK" | md5sum | cut -d' ' -f1)"
variant_nibble=$(( (16#${md5hex:16:1} & 3) | 8 ))
variant_hex="$(printf '%x' "$variant_nibble")"
patched="${md5hex:0:12}3${md5hex:13:3}${variant_hex}${md5hex:17:15}"
UUID="${patched:0:8}-${patched:8:4}-${patched:12:4}-${patched:16:4}-${patched:20:12}"
CLIENT_TOKEN="$(printf '%s' "ClientToken:$NICK" | md5sum | cut -d' ' -f1)"
cat > accounts.json <<EOF
{
"accounts": [
{
"active": true,
"type": "Offline",
"profile": { "id": "$UUID", "name": "$NICK", "capes": [], "skin": { "id": "", "url": "", "variant": "" } },
"entitlement": { "canPlayMinecraft": true, "ownsMinecraft": true },
"ygg": { "token": "0", "extra": { "clientToken": "$CLIENT_TOKEN", "userName": "$NICK" }, "iat": $(date +%s) }
}
],
"formatVersion": 3
}
EOF
echo "==> Offline account '$NICK' ready (UUID $UUID)"
# ---- modpack instance ----
mkdir -p instances
if [[ ! -d "instances/$INSTANCE_NAME" ]]; then
echo "==> Downloading modpack from $MODPACK_URL"
curl -fsSL -o modpack.zip "$MODPACK_URL"
unzip -oq modpack.zip -d instances
echo "==> Modpack installed to instances/$INSTANCE_NAME"
else
echo "==> Instance already present, skipping download"
fi
# Desktop shortcut so the game is findable after closing it, without re-running this script
DESKTOP_DIR="$(xdg-user-dir DESKTOP 2>/dev/null || echo "$HOME/Desktop")"
if [[ -d "$DESKTOP_DIR" ]]; then
cat > "$DESKTOP_DIR/lan-party-minecraft.desktop" <<EOF
[Desktop Entry]
Type=Application
Name=LAN Party Minecraft
Exec=$LAUNCHER_BIN --dir "$INSTALL_DIR" --launch "$INSTANCE_NAME" --profile "$NICK" --server "$SERVER_ADDR"
Icon=$INSTALL_DIR/app/resources/multimc.png
Terminal=false
EOF
chmod +x "$DESKTOP_DIR/lan-party-minecraft.desktop"
echo "==> Desktop shortcut created: $DESKTOP_DIR/lan-party-minecraft.desktop (double-click this next time instead of re-running the install script — may need 'Allow Launching' on first click, GNOME/KDE trust new .desktop files by default)"
fi
echo "==> Launching into $INSTANCE_NAME as $NICK, joining $SERVER_ADDR"
"$LAUNCHER_BIN" --dir "$INSTALL_DIR" --launch "$INSTANCE_NAME" --profile "$NICK" --server "$SERVER_ADDR"