Skip to content

Network play: Cannot start MoJhoSto/MomirBasic game — lobby blocks on null deck for auto-generated variants #10642

@emirikol1

Description

@emirikol1

Bug Report

What Happened

In network play, selecting the MoJhoSto or MomirBasic variant and clicking Start without selecting a player deck causes the game to either:

  1. Show "Please specify a deck" error and refuse to start, OR
  2. Crash with a NullPointerException in RegisteredPlayer.<init>() because originalDeck is null

This is incorrect because these variants auto-generate their decks (60 basic lands + avatars) — player deck selection is irrelevant and the deck chooser panel is intentionally hidden when these variants are selected.

Stack Trace (crash path)

java.lang.NullPointerException: Cannot invoke "forge.deck.Deck.getName()" because "this.originalDeck" is null
    at forge.game.player.RegisteredPlayer.restoreDeck(RegisteredPlayer.java:241)
    at forge.game.player.RegisteredPlayer.<init>(RegisteredPlayer.java:45)
    at forge.gamemodes.match.GameLobby.startGame(GameLobby.java:442)

Root Cause

GameLobby.startGame() has a deck null check at line 363 that blocks the game from starting:

if (slot.getDeck() == null) {
    SOptionPane.showMessageDialog("Please specify a deck...");
    return null;
}

This check runs before the auto-generation logic at line 458-467 that would replace the null deck with a generated one. The check does not account for auto-generated variants where a null deck is expected and valid.

Additionally, even if the null check is bypassed, new RegisteredPlayer(deck) at line 442 crashes because RegisteredPlayer's constructor calls deck.getName() on the null deck.

The desktop VLobby.setReady() already had a bypass for MomirBasic/MoJhoSto (checking vntMomirBasic.isSelected() and vntMoJhoSto.isSelected()), but this only guards the ready-up step. The core GameLobby.startGame() and the mobile LobbyScreen.setReady() (local path) were missing the bypass.

Fix

Three changes across two files:

1. forge-gui/src/main/java/forge/gamemodes/match/GameLobby.java

Add auto-gen variant detection before the deck null check loop, skip the check when active, and provide a placeholder deck for RegisteredPlayer:

// Before the loop:
final boolean hasAutoGenVariant = data.appliedVariants.stream().anyMatch(GameType::isAutoGenerated);

// In the loop — skip deck null check:
if (slot.getDeck() == null && !hasAutoGenVariant) { ... }

// Before RegisteredPlayer creation — provide placeholder:
Deck deck = slot.getDeck();
if (deck == null && hasAutoGenVariant) {
    deck = new Deck("auto-generated");
}
RegisteredPlayer rp = new RegisteredPlayer(deck);

2. forge-gui-mobile/src/forge/screens/constructed/LobbyScreen.java

Add the same bypass to the mobile local setReady() path:

boolean autoGenVariant = lobby.getAppliedVariants() != null
        && Iterables.any(lobby.getAppliedVariants(), GameType::isAutoGenerated);
if (decks[index] == null && !autoGenVariant) { ... }

Testing

Fix verified working in local two-instance network play test. Both MoJhoSto and MomirBasic variants can now start without selecting a deck.

Related: #9861 (network multiplayer meta issue), #10131 (related MoJhoSto/MomirBasic NPE, different code path)

Metadata

Metadata

Assignees

Labels

No labels
No labels

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions