Balatro-Multiplayer / Balatro-Multiplayer/BalatroMultiplayer

[Beta v3 PvP] Opponent disconnect or leave mid-run instantly shows the win screen

Open
#483 0 comments 0 reactions 0 assignees View on GitHub
Dominant language
Lua
Stars
335
Forks
106
Avg merge
2d 2h
Merged PRs (30d)
1

Description

**Status: root cause confirmed**
**Affects:** MultiplayerPvP Closed Beta v3 (mqtt branch)

## Symptom
Tester report: "once opponent leaves you get the you win screen." Any opponent departure mid-run — including a transient network drop — immediately resolves the match as a win for the remaining player. The pause-and-wait-for-reconnection behavior from #478 never triggers.

## Root cause
`pvp_api/lobby_bridge.lua:119-133` — the `PLAYER_LEFT` handler calls `gm:on_player_forfeit(player_id)` unconditionally when `G.STAGE == G.STAGES.RUN`, which broadcasts `pvp_player_won` → win screen. There is no grace period and no leave-vs-drop distinction.

Two contributing factors:
- The bridge never subscribes to the API's `PLAYER_DISCONNECTED` / `PLAYER_RECONNECTED` events (`BalatroMultiplayerAPI/api/lobby/events.lua:23-35`), so the existing pause/countdown machinery (`action_enemyDisconnected` / `action_enemyReconnected`, `networking/action_handlers.lua:108-170`) is unreachable dead code in the MQTT flow.
- An ungraceful MQTT drop also surfaces as `PLAYER_LEFT` (retained `players//info` topic cleared via LWT, `api/lobby/events.lua:112-128`), with no reason field — so a network blip is indistinguishable from a deliberate leave and is treated as a forfeit.

Note: the explicit in-run Forfeit button (`ui/pvp_run_options.lua:47` → `pvp_forfeit` action) is a separate, intentional path and behaves correctly.

Contributor guide

Open the contributing guide

Research direction

Start by tracing pvp_api/lobby_bridge.lua:119-133 alongside BalatroMultiplayerAPI/api/lobby/events.lua:23-35 and 112-128, then inspect networking/action_handlers.lua:108-170. Reproduce a deliberate leave and a transient disconnect in the MQTT flow, using ui/pvp_run_options.lua:47 as the separate forfeit reference. Done means disconnects use the pause/reconnection behavior while deliberate departures remain distinct from the explicit forfeit path.

Written by the indexing model from the issue text.

Assessment

Tech stack
lua
Domain
networking
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Quiet
Clarity
Clearly specified
Newbie friendliness
68/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.