Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions .env.example
Original file line number Diff line number Diff line change
@@ -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
2 changes: 1 addition & 1 deletion Multiplayer.json
Original file line number Diff line number Diff line change
Expand Up @@ -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)",
Expand Down
2 changes: 1 addition & 1 deletion config.lua
Original file line number Diff line number Diff line change
Expand Up @@ -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"] = {
Expand Down
20 changes: 15 additions & 5 deletions core.lua
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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

Expand Down Expand Up @@ -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()
139 changes: 139 additions & 0 deletions scripts/release.sh
Original file line number Diff line number Diff line change
@@ -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<version>/ (clean unzipped folder)
# dist/Multiplayer-v<version>.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 <tag> | ( 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."