Skip to content

Qol adjustments #66

Merged
merged 2 commits into from
Apr 19, 2026
Merged
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
Original file line number Diff line number Diff line change
Expand Up @@ -7,27 +7,33 @@
/**
* Manages Firebase listeners and flow between host and joiner.
* Encapsulates all Firebase communication logic.
*
* Auto-start behaviour: the host no longer manually clicks "Start Game".
* As soon as a joiner is detected, the host signals game start and both
* players are navigated to SetupScreen automatically.
*/
public class LobbyFlowController {

public interface FlowListener {
void onJoinerArrived(); // Host: someone joined the lobby
void onGameStarted(); // Joiner: host started the game
void onJoinerArrived(); // Host: joiner detected — auto-start is triggered here
void onGameStarted(); // Joiner: host signalled start
void onError(String message);
}

private final LobbyState lobbyState;
private final FlowListener listener;
private String activeGameId;

public LobbyFlowController(LobbyState lobbyState, FlowListener listener) {
this.lobbyState = lobbyState;
this.listener = listener;
}

/**
* Host: Listens for a joiner to enter the lobby.
* When status becomes "joined", calls onJoinerArrived().
* The host is expected to immediately call signalGameStart() inside
* that callback, then navigate — no manual button press required.
*/
public void listenForJoiner(String gameId) {
this.activeGameId = gameId;
Expand All @@ -38,17 +44,17 @@ public void listenForJoiner(String gameId) {
}
}));
}

/**
* Host: Signals the game to start.
* Writes status = "started" to Firebase.
* Host: Writes status = "started" to Firebase so the joiner is notified.
* Called automatically from LobbyScreen once the joiner arrives.
*/
public void signalGameStart(String gameId) {
lobbyState.startGame(gameId);
}

/**
* Joiner: Listens for host to start the game.
* Joiner: Listens for the host's "started" signal.
* When status becomes "started", calls onGameStarted().
*/
public void listenForGameStart(String gameId) {
Expand All @@ -60,7 +66,7 @@ public void listenForGameStart(String gameId) {
}
}));
}

public String getActiveGameId() {
return activeGameId;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,55 +12,56 @@

/**
* Builds and manages the host-specific UI for lobby creation.
* Contains board size slider, budget slider, create button, and start button.
* Contains board size slider, budget slider, and create button.
*
* The "Start Game" button has been removed. The game now starts
* automatically as soon as an opponent joins the lobby.
*/
public class LobbyHostUI {

public interface HostUIListener {
void onCreateLobby(int boardSize, int budget);
void onStartGame();
void onBack();
}

private final Skin skin;
private final HostUIListener listener;

private int boardSize = LobbyScreenConfig.BOARD_DEFAULT;
private int budget = LobbyScreenConfig.BUDGET_DEFAULT;

private Label boardSizeValueLabel;
private Label budgetValueLabel;
private Label statusLabel;
private TextButton createBtn;
private TextButton startBtn;
private Table sliderSection;

public LobbyHostUI(Skin skin, HostUIListener listener) {
this.skin = skin;
this.listener = listener;
}

public Table build() {
Table container = new Table();
container.top();

// Board size controls
Label boardSizeLabel = new Label("Board Size", skin);
boardSizeValueLabel = new Label(boardSize + " x " + boardSize, skin);

Slider boardSlider = createBoardSlider();

// Budget controls
Label budgetLabel = new Label("Starting Budget", skin);
budgetValueLabel = new Label(String.valueOf(budget), skin);

Slider budgetSlider = createBudgetSlider();

// Status label
statusLabel = new Label("", skin, "small");
statusLabel.setAlignment(Align.center);
// Buttons

// Create button
createBtn = new TextButton("Create Lobby", skin, "accent");
createBtn.addListener(new ChangeListener() {
@Override
Expand All @@ -70,19 +71,7 @@ public void changed(ChangeEvent event, Actor actor) {
}
}
});

startBtn = new TextButton("Start Game", skin, "accent");
startBtn.setVisible(false);
startBtn.setDisabled(true);
startBtn.addListener(new ChangeListener() {
@Override
public void changed(ChangeEvent event, Actor actor) {
if (!startBtn.isDisabled()) {
listener.onStartGame();
}
}
});


// Sliders grouped so they can be hidden after lobby is created
sliderSection = new Table();
sliderSection.add(buildRow(boardSizeLabel, boardSizeValueLabel))
Expand All @@ -97,20 +86,17 @@ public void changed(ChangeEvent event, Actor actor) {
.width(LobbyScreenConfig.SLIDER_WIDTH)
.height(LobbyScreenConfig.SLIDER_HEIGHT)
.padBottom(32).row();

container.add(sliderSection).expandX().fillX().row();
container.add(createBtn)
.width(LobbyScreenConfig.BUTTON_WIDTH)
.height(LobbyScreenConfig.BUTTON_HEIGHT)
.padBottom(8).row();
container.add(startBtn)
.width(LobbyScreenConfig.BUTTON_WIDTH)
.height(LobbyScreenConfig.BUTTON_HEIGHT)
.padBottom(16).row();
container.add(statusLabel).expandX().row();

return container;
}

private Slider createBoardSlider() {
Slider slider = new Slider(
LobbyScreenConfig.BOARD_MIN,
Expand All @@ -128,7 +114,7 @@ public void changed(ChangeEvent event, Actor actor) {
});
return slider;
}

private Slider createBudgetSlider() {
Slider slider = new Slider(
LobbyScreenConfig.BUDGET_MIN,
Expand All @@ -146,52 +132,45 @@ public void changed(ChangeEvent event, Actor actor) {
});
return slider;
}

private Slider.SliderStyle buildSliderStyle() {
Slider.SliderStyle style = new Slider.SliderStyle();
style.background = skin.getDrawable("primary-pixel");
style.knob = skin.getDrawable("accent-pixel");
return style;
}

private Table buildRow(Label left, Label right) {
Table row = new Table();
row.add(left).expandX().left();
row.add(right).expandX().right();
return row;
}
// Public methods for updating UI state

// ── Public methods for updating UI state ──────────────────────────────────

public void showCreatingState() {
createBtn.setDisabled(true);
setStatus("Creating lobby...");
}

public void showLobbyCreated(String gameId) {
sliderSection.setVisible(false);
createBtn.setVisible(false);
startBtn.setVisible(true);
startBtn.setDisabled(true);
setStatus("Lobby created!\nGame ID: " + gameId
+ "\n\nWaiting for opponent to join...");
+ "\n\nWaiting for opponent to join...\nGame will start automatically.");
}

public void showJoinerArrived() {
setStatus("Opponent joined! Press Start Game when you are ready.");
startBtn.setDisabled(false);
}

public void showStartingState() {
startBtn.setDisabled(true);
setStatus("Starting...");

/** Called when a joiner is detected; game starts immediately after this. */
public void showOpponentJoined() {
setStatus("Opponent joined! Starting game...");
}

public void showCreationFailed() {
setStatus("Failed to create lobby. Try again.");
createBtn.setDisabled(false);
}

public void setStatus(String message) {
if (statusLabel != null) {
statusLabel.setText(message);
Expand Down
Loading