Skip to content

Commit

Permalink
Merge pull request #67 from TDT4240-14/development
Browse files Browse the repository at this point in the history
Development
  • Loading branch information
benjamls authored Apr 19, 2026
2 parents 50eb3a9 + 2185d7c commit ea01bb1
Show file tree
Hide file tree
Showing 5 changed files with 157 additions and 153 deletions.
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

0 comments on commit ea01bb1

Please sign in to comment.