diff --git a/.env.example b/.env.example index 2d3126ec..c063c21c 100644 --- a/.env.example +++ b/.env.example @@ -1,3 +1,7 @@ # Experimental flags — copy to .env and edit as needed show_sandbox_collection=false alt_stakes=false + +# Server overrides (take precedence over Multiplayer.jkr / config.lua) +# server_url=balatro.virtualized.dev +# server_port=8788 diff --git a/Multiplayer.json b/Multiplayer.json index e7a9ddf0..1d694179 100644 --- a/Multiplayer.json +++ b/Multiplayer.json @@ -12,7 +12,7 @@ "priority": 10000000, "badge_colour": "AC3232", "badge_text_colour": "FFFFFF", - "version": "0.4.0~pre1-DEV", + "version": "0.4.0~pre2-DEV", "dependencies": [ "Steamodded (>=1.0.0~BETA-1221a)", "Lovely (>=0.8)", diff --git a/config.lua b/config.lua index 50922d1d..c8aa6f1f 100644 --- a/config.lua +++ b/config.lua @@ -2,7 +2,7 @@ return { ["username"] = "Guest", ["blind_col"] = 1, ["server_url"] = "balatro.virtualized.dev", - ["server_port"] = 8788, + ["server_port"] = 8799, ["logging"] = false, ["misprint_display"] = true, ["integrations"] = { diff --git a/core.lua b/core.lua index 96f2ed98..ca644cac 100644 --- a/core.lua +++ b/core.lua @@ -68,7 +68,8 @@ MP.EXPERIMENTAL = { mem_debug = true, } --- Override experimental flags from .env file if present +-- Override experimental flags and server config from .env file if present +MP.ENV = {} local env_path = MP.path .. "/.env" local env_info = NFS.getInfo(env_path) if env_info then @@ -78,17 +79,20 @@ if env_info then line = line:match("^%s*(.-)%s*$") -- trim if line ~= "" and not line:match("^#") then local key, val = line:match("^([%w_]+)%s*=%s*(.+)$") - if key and MP.EXPERIMENTAL[key] ~= nil then + if key then if val == "true" then val = true elseif val == "false" then val = false end - MP.EXPERIMENTAL[key] = val + MP.ENV[key] = val + if MP.EXPERIMENTAL[key] ~= nil then + MP.EXPERIMENTAL[key] = val + end end end end - sendDebugMessage("Loaded .env overrides for MP.EXPERIMENTAL", "MULTIPLAYER") + sendDebugMessage("Loaded .env overrides", "MULTIPLAYER") end end @@ -317,5 +321,11 @@ MP.load_mp_dir("objects/challenges") local SOCKET = MP.load_mp_file("networking/socket.lua") MP.NETWORKING_THREAD = love.thread.newThread(SOCKET) -MP.NETWORKING_THREAD:start(SMODS.Mods["Multiplayer"].config.server_url, SMODS.Mods["Multiplayer"].config.server_port) +local server_url = MP.ENV.server_url or SMODS.Mods["Multiplayer"].config.server_url +local server_port = tonumber(MP.ENV.server_port) or SMODS.Mods["Multiplayer"].config.server_port +sendInfoMessage( + string.format("Connecting to %s:%s", tostring(server_url), tostring(server_port)), + "MULTIPLAYER" +) +MP.NETWORKING_THREAD:start(server_url, server_port) MP.ACTIONS.connect() diff --git a/scripts/release.sh b/scripts/release.sh new file mode 100755 index 00000000..362d793e --- /dev/null +++ b/scripts/release.sh @@ -0,0 +1,139 @@ +#!/usr/bin/env bash +# +# release.sh — build the Multiplayer mod, in one of two modes: +# +# --dev Playtest/dev build. Source is the WORKING TREE (uncommitted edits +# included). Your real .env is baked in so +# the build talks to whatever server/port your .env points at and +# keeps the "-DEV" version (which triggers the in-game dev warning). +# +# --release Shippable build. Source is still the WORKING TREE for now +# (see TODO below to switch to a clean git tag/ref), but: +# - .env is NOT shipped (build falls back to config.lua) +# - version is auto-stripped to a clean release string +# (drops ~preN and -DEV, so no dev-warning overlay) +# - config.lua server port is forced to production +# - core.lua debug defaults (mem_debug) are turned off +# +# Output: dist/Multiplayer-v/ (clean unzipped folder) +# dist/Multiplayer-v.zip (zipped, ready to ship) +# +set -euo pipefail + +# --- production server (used by --release to sanitize config.lua) ------------ +PROD_SERVER_URL="balatro.virtualized.dev" +PROD_SERVER_PORT=8788 + +# --- mode (required, no default — defaulting would risk leaking your .env) --- +MODE="${1:-}" +case "$MODE" in + --dev) MODE=dev ;; + --release) MODE=release ;; + *) + echo "usage: $(basename "$0") --dev | --release" >&2 + exit 2 + ;; +esac + +ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)" +cd "$ROOT" + +# Portable in-place edit (BSD/macOS + GNU sed differ; perl is consistent). +inplace() { perl -0pi -e "$1" "$2"; } + +# --- version (from manifest), with release sanitization --------------------- +VERSION="$(grep -m1 '"version"' Multiplayer.json \ + | sed -E 's/.*"version"[[:space:]]*:[[:space:]]*"([^"]+)".*/\1/')" + +if [ "$MODE" = release ]; then + # Strip the pre-release/dev tail: "0.4.0~pre2-DEV" -> "0.4.0". + VERSION="${VERSION%%~*}" # drop everything from the first '~' + VERSION="${VERSION%-[Dd][Ee][Vv]}" # drop a trailing '-DEV' if no '~' was present + if printf '%s' "$VERSION" | grep -qi 'dev'; then + echo "!! refusing to make a release: version still looks like a dev build ('$VERSION')" >&2 + exit 1 + fi +fi + +SAFE_VERSION="$(printf '%s' "$VERSION" | tr -c 'A-Za-z0-9._-' '_')" +NAME="Multiplayer-v${SAFE_VERSION}" + +DIST="${ROOT}/dist" +STAGE="${DIST}/${NAME}" +ZIP="${DIST}/${NAME}.zip" + +echo "==> building ${NAME} (mode: ${MODE}, version: ${VERSION})" + +rm -rf "$STAGE" "$ZIP" +mkdir -p "$STAGE" + +# --- copy working tree, strip noise ----------------------------------------- +# TODO(release): build from a clean git ref instead of the working tree, e.g. +# git archive --format=tar | ( cd "$STAGE" && tar -xf - ) +# then skip the rsync below. For now both modes use the working tree. +# +# -a archive. In --dev we also pass -L to follow symlinks (turns the .env +# symlink into its real contents); --release excludes .env entirely instead. +RSYNC_FLAGS=(-a) +ENV_EXCLUDE=() +if [ "$MODE" = dev ]; then + RSYNC_FLAGS+=(-L) +else + ENV_EXCLUDE+=(--exclude='/.env') +fi + +rsync "${RSYNC_FLAGS[@]}" \ + ${ENV_EXCLUDE[@]+"${ENV_EXCLUDE[@]}"} \ + --exclude='/dist/' \ + --exclude='.git' \ + --exclude='/.github/' \ + --exclude='.gitignore' \ + --exclude='.gitattributes' \ + --exclude='.DS_Store' \ + --exclude='/.context/' \ + --exclude='/.claude/' \ + --exclude='.vscode/' \ + --exclude='.idea/' \ + --exclude='.vs/' \ + --exclude='.luarc.json' \ + --exclude='.lovelyignore' \ + --exclude='/agents.md' \ + --exclude='CLAUDE.md' \ + --exclude='CLAUDE.local.md' \ + --exclude='/CONTRIBUTING.md' \ + --exclude='stylua.toml' \ + --exclude='/tests/' \ + --exclude='/scripts/' \ + ./ "$STAGE/" + +find "$STAGE" -name '.DS_Store' -delete + +# --- release-only: sanitize the staged copy --------------------------------- +if [ "$MODE" = release ]; then + # Clean version into the shipped manifest (no ~preN / -DEV -> no dev warning). + inplace "s/(\"version\"\\s*:\\s*\")[^\"]+\"/\${1}${VERSION}\"/" "$STAGE/Multiplayer.json" + # Point config.lua at the production server (working tree may hold a dev port). + inplace "s/(\\[\"server_url\"\\]\\s*=\\s*\")[^\"]*\"/\${1}${PROD_SERVER_URL}\"/" "$STAGE/config.lua" + inplace "s/(\\[\"server_port\"\\]\\s*=\\s*)\\d+/\${1}${PROD_SERVER_PORT}/" "$STAGE/config.lua" +fi + +# --- sanity: make sure the bits that MUST (and must NOT) ship are present ---- +for required in Multiplayer.json core.lua; do + if [ ! -e "${STAGE}/${required}" ]; then + echo "!! WARNING: expected '${required}' missing from build" >&2 + fi +done + +if [ "$MODE" = dev ]; then + [ -e "${STAGE}/.env" ] || echo "!! WARNING: dev build but '.env' missing" >&2 +else + [ -e "${STAGE}/.env" ] && echo "!! WARNING: release build is shipping a '.env' — it should not" >&2 + [ -e "${STAGE}/.env.example" ] || echo "!! WARNING: release build missing '.env.example'" >&2 +fi + +# --- zip it ----------------------------------------------------------------- +( cd "$DIST" && zip -rqX "${NAME}.zip" "$NAME" ) + +echo "==> folder: ${STAGE}" +echo "==> zip: ${ZIP}" +echo "==> done."