#16 + updated CreateGameScreen

functionality of CreateGameScreen WIP
main
Johannes Teubler 3 years ago
parent d5bece96d1
commit e8b2d64119

@ -1,5 +1,6 @@
subprojects {
dependencies {
implementation(project(":wizard-common"))
implementation(JavaWebSocket.id)
}
}

@ -0,0 +1,59 @@
package eu.jonahbauer.wizard.client.libgdx;
import eu.jonahbauer.wizard.client.libgdx.state.ClientState;
import eu.jonahbauer.wizard.client.libgdx.state.Menu;
import eu.jonahbauer.wizard.common.machine.TimeoutContext;
import eu.jonahbauer.wizard.common.messages.client.ClientMessage;
import eu.jonahbauer.wizard.common.messages.server.ServerMessage;
import lombok.Getter;
import lombok.extern.log4j.Log4j2;
@Log4j2
public class Client extends TimeoutContext<ClientState, Client> {
@Getter
private final WizardGame game;
@Getter
private ClientSocket socket;
public Client(WizardGame game) {
super(new Menu());
this.game = game;
}
@Override
protected void handleError(Throwable t) {
// TODO better error handling
t.printStackTrace();
}
public void setSocket(ClientSocket socket) {
this.socket = socket;
if (socket != null) {
this.socket.setAttachment(this);
}
}
public void onOpen() {
execute(s -> s.onOpen(this));
}
public void onClose(int code, String reason, boolean remote) {
execute(s -> s.onClose(this, code, reason, remote));
}
public void onMessage(ServerMessage message) {
log.debug(message.toString());
execute(s -> s.onMessage(this, message));
}
@Override
protected void onTransition(ClientState from, ClientState to) {
System.out.println("Transistion from " + from.getClass().getSimpleName() + " to " + to.getClass().getSimpleName());
}
public void send(ClientMessage message) {
getSocket().send(message.toString());
}
}

@ -0,0 +1,47 @@
package eu.jonahbauer.wizard.client.libgdx;
import com.badlogic.gdx.Gdx;
import eu.jonahbauer.wizard.common.messages.server.ServerMessage;
import org.java_websocket.client.WebSocketClient;
import org.java_websocket.framing.CloseFrame;
import org.java_websocket.handshake.ServerHandshake;
import javax.net.ssl.SSLSocketFactory;
import java.net.URI;
public class ClientSocket extends WebSocketClient {
public ClientSocket(URI serverUri) {
super(serverUri);
if ("wss".equals(getURI().getScheme())) {
setSocketFactory(SSLSocketFactory.getDefault());
}
}
@Override
public void onOpen(ServerHandshake serverHandshake) {
Gdx.app.postRunnable(() -> getClient().onOpen());
}
@Override
public void onMessage(String s) {
ServerMessage message = ServerMessage.parse(s);
Gdx.app.postRunnable(() -> getClient().onMessage(message));
}
@Override
public void onClose(int i, String s, boolean b) {
Gdx.app.postRunnable(() -> getClient().onClose(i, s, b));
}
@Override
public void onError(Exception e) {
e.printStackTrace();
close(CloseFrame.ABNORMAL_CLOSE, e.getMessage());
}
private Client getClient() {
return getAttachment();
}
}

@ -5,10 +5,20 @@ import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.Graphics;
import com.badlogic.gdx.Input;
import com.badlogic.gdx.audio.Music;
import com.badlogic.gdx.audio.Sound;
import com.badlogic.gdx.graphics.Pixmap;
import com.badlogic.gdx.graphics.Texture;
import com.badlogic.gdx.graphics.g2d.BitmapFont;
import com.badlogic.gdx.graphics.g2d.SpriteBatch;
import com.badlogic.gdx.graphics.g2d.TextureAtlas;
import com.badlogic.gdx.graphics.g2d.TextureRegion;
import com.badlogic.gdx.scenes.scene2d.Stage;
import com.badlogic.gdx.scenes.scene2d.ui.Skin;
import com.badlogic.gdx.utils.I18NBundle;
import eu.jonahbauer.wizard.client.libgdx.screens.GameScreen;
import com.badlogic.gdx.utils.viewport.ExtendViewport;
import com.badlogic.gdx.utils.viewport.FitViewport;
import eu.jonahbauer.wizard.client.libgdx.screens.MainMenuScreen;
import lombok.Getter;
import java.util.Locale;
@ -19,10 +29,14 @@ public class WizardGame extends Game {
public SpriteBatch batch;
public I18NBundle messages;
public Data data;
private boolean toggle;
private int oldHeight, oldWidth;
@Getter
private final Client client = new Client(this);
@Override
public void create() {
@ -40,7 +54,7 @@ public class WizardGame extends Game {
Gdx.graphics.setCursor(Gdx.graphics.newCursor(cursor, 0, 0));
cursor.dispose();
this.setScreen(new GameScreen(this));
this.setScreen(new MainMenuScreen(this));
}
@Override
@ -71,5 +85,70 @@ public class WizardGame extends Game {
@Override
public void dispose () {
batch.dispose();
client.shutdownNow();
var socket = client.getSocket();
if (socket != null) {
socket.close();
}
}
public static class Data {
public final ExtendViewport extendViewport;
public final FitViewport fitViewport;
public final Sound buttonClickSound;
public final TextureAtlas uiskinAtlas;
public final TextureAtlas menuAtlas;
public final TextureRegion title;
public final TextureRegion background;
public final TextureRegion[] corners = new TextureRegion[4];
public final TextureRegion[] symbols = new TextureRegion[4];
public final Skin skin;
public final Stage stage;
public Data() {
this.extendViewport = new ExtendViewport(WizardGame.WIDTH, WizardGame.HEIGHT);
this.fitViewport = new FitViewport(WizardGame.WIDTH, WizardGame.HEIGHT);
this.buttonClickSound = Gdx.audio.newSound(Gdx.files.internal("button_click_s.mp3"));
this.uiskinAtlas = new TextureAtlas(Gdx.files.internal(UiskinAtlas.$PATH));
this.menuAtlas = new TextureAtlas(Gdx.files.internal(MenuAtlas.$PATH));
this.title = menuAtlas.findRegion(MenuAtlas.TITLE);
this.background = menuAtlas.findRegion(MenuAtlas.BACKGROUND);
this.corners[0] = menuAtlas.findRegion(MenuAtlas.ECKE_LO);
this.corners[1] = menuAtlas.findRegion(MenuAtlas.ECKE_LU);
this.corners[2] = menuAtlas.findRegion(MenuAtlas.ECKE_RU);
this.corners[3] = menuAtlas.findRegion(MenuAtlas.ECKE_RO);
this.symbols[0] = menuAtlas.findRegion(MenuAtlas.SYMBOL0);
this.symbols[1] = menuAtlas.findRegion(MenuAtlas.SYMBOL1);
this.symbols[2] = menuAtlas.findRegion(MenuAtlas.SYMBOL2);
this.symbols[3] = menuAtlas.findRegion(MenuAtlas.SYMBOL3);
this.skin = new Skin(Gdx.files.internal("uiskin.json"), uiskinAtlas);
this.skin.getAll(BitmapFont.class).forEach(entry ->
entry.value.getRegion().getTexture().setFilter(Texture.TextureFilter.Linear, Texture.TextureFilter.Linear)
);
this.stage = new Stage(fitViewport);
if (WizardGame.DEBUG) {
stage.setDebugAll(true);
}
}
public void reset() {
stage.clear();
}
public void dispose() {
buttonClickSound.dispose();
uiskinAtlas.dispose();
menuAtlas.dispose();
skin.dispose();
stage.dispose();
}
}
}

@ -8,11 +8,10 @@ import com.badlogic.gdx.scenes.scene2d.ui.Container;
import com.badlogic.gdx.scenes.scene2d.utils.Drawable;
import eu.jonahbauer.wizard.client.libgdx.WizardGame;
import eu.jonahbauer.wizard.client.libgdx.screens.GameScreen;
import eu.jonahbauer.wizard.client.libgdx.screens.MenuScreen;
public abstract class Overlay {
protected final MenuScreen.Data data;
protected final WizardGame.Data data;
protected final TextureAtlas atlas;
private Container<?> root;

@ -7,7 +7,13 @@ import com.badlogic.gdx.scenes.scene2d.ui.TextButton;
import com.badlogic.gdx.scenes.scene2d.ui.TextField;
import com.badlogic.gdx.scenes.scene2d.utils.ChangeListener;
import com.badlogic.gdx.utils.Align;
import eu.jonahbauer.wizard.client.libgdx.ClientSocket;
import eu.jonahbauer.wizard.client.libgdx.WizardGame;
import eu.jonahbauer.wizard.client.libgdx.state.AwaitingConnection;
import eu.jonahbauer.wizard.common.messages.server.ServerMessage;
import lombok.SneakyThrows;
import java.net.URI;
public class ConnectScreen extends MenuScreen {
@ -16,47 +22,53 @@ public class ConnectScreen extends MenuScreen {
private TextField uri;
public ConnectScreen(WizardGame game) {
super(game);
}
private final ChangeListener listener = new ChangeListener() {
@SneakyThrows
@Override
public void changed(ChangeEvent event, Actor actor) {
if (actor == buttonBack) {
game.setScreen(new MainMenuScreen(game, data));
game.setScreen(new MainMenuScreen(game));
sfxClick();
} else if (actor == buttonConnect) {
game.setScreen(new LobbyScreen(game, data));
// TODO error handling, uri syntax, etc.
ClientSocket socket = new ClientSocket(new URI(uri.getText()));
game.getClient().setSocket(socket);
game.getClient().transition(new AwaitingConnection());
socket.connect();
sfxClick();
}
}
};
public ConnectScreen(WizardGame game, Data data) {
super(game, data);
}
@Override
public void show() {
super.show();
buttonBack = new TextButton(game.messages.get("menu.connect.back"), data.skin);
buttonBack = new TextButton(game.messages.get("menu.connect.back"), game.data.skin);
buttonBack.setPosition(WizardGame.WIDTH * 0.275f, BUTTON_BAR_Y);
buttonConnect = new TextButton(game.messages.get("menu.connect.connect"), data.skin);
buttonConnect = new TextButton(game.messages.get("menu.connect.connect"), game.data.skin);
buttonConnect.setPosition(WizardGame.WIDTH * 0.725f - buttonConnect.getWidth(), BUTTON_BAR_Y);
var label = new Label(game.messages.get("menu.connect.address.label"), data.skin);
var label = new Label(game.messages.get("menu.connect.address.label"), game.data.skin);
label.setSize(0.4f * WizardGame.WIDTH, 64);
label.setAlignment(Align.center);
label.setPosition(0.5f * (WizardGame.WIDTH - label.getWidth()), 0.55f * (WizardGame.HEIGHT - label.getHeight()));
uri = new TextField("", data.skin);
uri.setMessageText("wss://localhost/wizard");
// TODO sensible default value
uri = new TextField("wss://webdev.jonahbauer.eu/wizard/", game.data.skin);
uri.setMessageText(game.messages.get("menu.connect.uri.hint"));
uri.setSize(0.4f * WizardGame.WIDTH, 64);
uri.setPosition(0.5f * (WizardGame.WIDTH - uri.getWidth()), 0.45f * (WizardGame.HEIGHT - uri.getHeight()));
Gdx.input.setInputProcessor(data.stage);
data.stage.addActor(buttonBack);
data.stage.addActor(buttonConnect);
data.stage.addActor(uri);
data.stage.addActor(label);
Gdx.input.setInputProcessor(game.data.stage);
game.data.stage.addActor(buttonBack);
game.data.stage.addActor(buttonConnect);
game.data.stage.addActor(uri);
game.data.stage.addActor(label);
buttonBack.addListener(listener);
buttonConnect.addListener(listener);

@ -2,79 +2,124 @@ package eu.jonahbauer.wizard.client.libgdx.screens;
import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.scenes.scene2d.Actor;
import com.badlogic.gdx.scenes.scene2d.ui.TextButton;
import com.badlogic.gdx.scenes.scene2d.ui.TextField;
import com.badlogic.gdx.scenes.scene2d.ui.*;
import com.badlogic.gdx.scenes.scene2d.utils.ChangeListener;
import com.badlogic.gdx.utils.Array;
import eu.jonahbauer.wizard.client.libgdx.WizardGame;
import eu.jonahbauer.wizard.client.libgdx.state.Session;
import eu.jonahbauer.wizard.common.messages.client.CreateSessionMessage;
import eu.jonahbauer.wizard.common.messages.data.SessionData;
import eu.jonahbauer.wizard.common.messages.server.SessionJoinedMessage;
import eu.jonahbauer.wizard.common.model.Configuration;
public class CreateGameScreen extends MenuScreen {
TextButton backButton;
TextButton continueButton;
private TextButton buttonBack;
private TextButton buttonContinue;
TextField option1;
TextField option2;
TextField option3;
TextField option4;
TextField option5;
TextField option6;
private TextField sessionName;
private TextField playerName;
private TextField timeOut;
ChangeListener listener = new ChangeListener() {
long selectedTimeOut;
String userName;
SelectBox<String> configurations;
private final ChangeListener listener = new ChangeListener() {
@Override
public void changed(ChangeEvent event, Actor actor) {
if (actor == backButton) {
game.setScreen(new LobbyScreen(game, data));
sfxClick();
} else if (actor == continueButton) {
game.setScreen(new WaitingScreen(game, data));
if (actor == buttonBack) {
game.setScreen(new LobbyScreen(game));
sfxClick();
} else if (actor == buttonContinue) {
if( sessionName.getText() == null ) {
System.out.println("Please select a session name.");
sessionName.clear();
}
if (playerName.getText() == null) {
userName = "Mallory";
System.out.println("Your name will be " + userName + ".");
}
try{
selectedTimeOut = Long.parseLong(timeOut.getText());
} catch (NumberFormatException e) {
System.out.println("Please select a valid timeout.");
timeOut.clear();
}
int selected = configurations.getSelectedIndex();
Configuration config = Configuration.values()[selected];
game.getClient().send(new CreateSessionMessage(sessionName.getText(), playerName.getText(), selectedTimeOut, config));
}
}
};
public CreateGameScreen(WizardGame game, Data data) {
super(game, data);
public CreateGameScreen(WizardGame game) {
super(game);
}
@Override
public void show() {
super.show();
backButton = new TextButton("Zurück", data.skin);
backButton.setPosition(WizardGame.WIDTH * 0.275f, BUTTON_BAR_Y);
continueButton = new TextButton("Erstellen", data.skin);
continueButton.setPosition(WizardGame.WIDTH * 0.725f - continueButton.getWidth(), BUTTON_BAR_Y);
buttonBack = new TextButton(game.messages.get("menu.connect.back"), game.data.skin);
buttonBack.setPosition(WizardGame.WIDTH * 0.275f, BUTTON_BAR_Y);
buttonContinue = new TextButton("Erstellen", game.data.skin);
buttonContinue.setPosition(WizardGame.WIDTH * 0.725f - buttonContinue.getWidth(), BUTTON_BAR_Y);
option1 = new TextField("1", data.skin);
option1.setPosition(WizardGame.WIDTH * 0.3f, WizardGame.HEIGHT * 0.6f);
option1.setSize(250, continueButton.getHeight());
option2 = new TextField("2", data.skin);
option2.setPosition(option1.getX(), option1.getY() - WizardGame.HEIGHT * 0.12f);
option2.setSize(250, continueButton.getHeight());
option3 = new TextField("3", data.skin);
option3.setPosition(option2.getX(), option2.getY() - WizardGame.HEIGHT * 0.12f);
option3.setSize(250, continueButton.getHeight());
sessionName = new TextField("", game.data.skin);
sessionName.setPosition(WizardGame.WIDTH * 0.3f, WizardGame.HEIGHT * 0.5f);
sessionName.setSize(0.4f * WizardGame.WIDTH, 64);
option4 = new TextField("4", data.skin);
option4.setPosition(WizardGame.WIDTH * 0.65f - option4.getWidth(), option1.getY());
option4.setSize(250, continueButton.getHeight());
option5 = new TextField("5", data.skin);
option5.setPosition(option4.getX(), option2.getY());
option5.setSize(250, continueButton.getHeight());
option6 = new TextField("6", data.skin);
option6.setPosition(option4.getX(), option3.getY());
option6.setSize(250, continueButton.getHeight());
playerName = new TextField("", game.data.skin);
playerName.setPosition(WizardGame.WIDTH * 0.3f, WizardGame.HEIGHT * 0.45f);
playerName.setSize(0.4f * WizardGame.WIDTH, 64);
Gdx.input.setInputProcessor(data.stage);
data.stage.addActor(backButton);
data.stage.addActor(continueButton);
data.stage.addActor(option1);
data.stage.addActor(option2);
data.stage.addActor(option3);
data.stage.addActor(option4);
data.stage.addActor(option5);
data.stage.addActor(option6);
timeOut = new TextField("", game.data.skin);
timeOut.setPosition(WizardGame.WIDTH * 0.3f, WizardGame.HEIGHT * 0.4f);
timeOut.setSize(0.4f * WizardGame.WIDTH, 64);
configurations = new SelectBox<>(game.data.skin);
configurations.setSize(400, 64);
configurations.setPosition(WizardGame.WIDTH * 0.3f, WizardGame.HEIGHT * 0.3f);
Array<String> values = new Array<>();
for (Configuration value: Configuration.values() ) {
values.add(value.toString());
}
backButton.addListener(listener);
continueButton.addListener(listener);
configurations.setItems(values);
var contentTable = new Table().center().left();
contentTable.columnDefaults(0).growX().width(0.4f * WizardGame.WIDTH - 20);
contentTable.setSize(0.4f * WizardGame.WIDTH - 20, 400);
contentTable.add(new Label(game.messages.get("menu.lobby.player_name.label"), game.data.skin)).row();
contentTable.add(playerName).row();
contentTable.add(new Label(game.messages.get("menu.lobby.session_name.label"), game.data.skin)).row();
contentTable.add(sessionName).row();
contentTable.add(new Label(game.messages.get("menu.lobby.create_session.timeout.label"), game.data.skin)).row();
contentTable.add(timeOut).row();
contentTable.add(new Label(game.messages.get("menu.lobby.session_configuration.label"), game.data.skin)).row();
contentTable.add(configurations).row();
contentTable.setPosition(WizardGame.WIDTH * 0.3f, WizardGame.HEIGHT * 0.3f);
Gdx.input.setInputProcessor(game.data.stage);
game.data.stage.addActor(buttonContinue);
game.data.stage.addActor(contentTable);
game.data.stage.addActor(buttonBack);
buttonContinue.addListener(listener);
buttonBack.addListener(listener);
}
public void performTransition(SessionJoinedMessage joined) {
int selected = configurations.getSelectedIndex();
Configuration config = Configuration.values()[selected];
System.out.println("Transition from Lobby to Session");
SessionData sessionData = new SessionData(joined.getSession(), sessionName.getText(), joined.getPlayers().size(), config);
game.getClient().transition(new Session(joined, sessionData, playerName.getText()));
}
}

@ -72,11 +72,7 @@ public class GameScreen extends MenuScreen {
private final Map<UUID, Label> nameLabels = new HashMap<>();
public GameScreen(WizardGame game) {
this(game, null);
}
public GameScreen(WizardGame game, Data data) {
super(game, data);
super(game);
this.game = game;
//<editor-fold desc="Sample Data" defaultstate="collapsed">
@ -99,7 +95,7 @@ public class GameScreen extends MenuScreen {
public void show() {
super.show();
atlas = new TextureAtlas(Gdx.files.internal(GameAtlas.$PATH));
overlay = new TextureRegionDrawable(data.uiskinAtlas.findRegion(UiskinAtlas.WHITE)).tint(new Color(0,0,0,0.5f));
overlay = new TextureRegionDrawable(game.data.uiskinAtlas.findRegion(UiskinAtlas.WHITE)).tint(new Color(0,0,0,0.5f));
seat();
prepareLabels();
@ -116,7 +112,7 @@ public class GameScreen extends MenuScreen {
messages.setSize(1200, 0);
messages.setTouchable(Touchable.disabled);
padOfTruth = new PadOfTruth(data.skin, new TextureRegionDrawable(atlas.findRegion(GameAtlas.PAD_OF_TRUTH)));
padOfTruth = new PadOfTruth(game.data.skin, new TextureRegionDrawable(atlas.findRegion(GameAtlas.PAD_OF_TRUTH)));
padOfTruth.setPosition(1910 - 636f, 10);
padOfTruth.setOrigin(636f, 0);
@ -125,16 +121,16 @@ public class GameScreen extends MenuScreen {
setNames();
Gdx.input.setInputProcessor(data.stage);
data.stage.addActor(container);
data.stage.addActor(cardStack);
data.stage.addActor(padOfTruth);
data.stage.addActor(messages);
data.stage.addActor(debugButtons());
Gdx.input.setInputProcessor(game.data.stage);
game.data.stage.addActor(container);
game.data.stage.addActor(cardStack);
game.data.stage.addActor(padOfTruth);
game.data.stage.addActor(messages);
game.data.stage.addActor(debugButtons());
}
private Group debugButtons() {
var trump = new TextButton("Trump", data.skin, "simple");
var trump = new TextButton("Trump", game.data.skin, "simple");
trump.align(Align.left);
trump.addListener(new ChangeListener() {
@Override
@ -146,7 +142,7 @@ public class GameScreen extends MenuScreen {
}
});
var playCard = new TextButton("Play Card", data.skin, "simple");
var playCard = new TextButton("Play Card", game.data.skin, "simple");
playCard.addListener(new ChangeListener() {
@Override
public void changed(ChangeEvent event, Actor actor) {
@ -160,7 +156,7 @@ public class GameScreen extends MenuScreen {
}
});
var deal = new TextButton("Deal", data.skin, "simple");
var deal = new TextButton("Deal", game.data.skin, "simple");
deal.addListener(new ChangeListener() {
@Override
public void changed(ChangeEvent event, Actor actor) {
@ -169,7 +165,7 @@ public class GameScreen extends MenuScreen {
}
});
var round = new TextButton("Round", data.skin, "simple");
var round = new TextButton("Round", game.data.skin, "simple");
round.addListener(new ChangeListener() {
@Override
public void changed(ChangeEvent event, Actor actor) {
@ -178,7 +174,7 @@ public class GameScreen extends MenuScreen {
}
});
var scores = new TextButton("Scores", data.skin, "simple");
var scores = new TextButton("Scores", game.data.skin, "simple");
scores.addListener(new ChangeListener() {
@Override
public void changed(ChangeEvent event, Actor actor) {
@ -187,7 +183,7 @@ public class GameScreen extends MenuScreen {
}
});
var predictions = new TextButton("Predictions", data.skin, "simple");
var predictions = new TextButton("Predictions", game.data.skin, "simple");
predictions.addListener(new ChangeListener() {
@Override
public void changed(ChangeEvent event, Actor actor) {
@ -195,7 +191,7 @@ public class GameScreen extends MenuScreen {
}
});
var playOtherCard = new TextButton("Play Other Card", data.skin, "simple");
var playOtherCard = new TextButton("Play Other Card", game.data.skin, "simple");
playOtherCard.addListener(new ChangeListener() {
@Override
public void changed(ChangeEvent event, Actor actor) {
@ -208,7 +204,7 @@ public class GameScreen extends MenuScreen {
}
});
var makePrediction = new TextButton("Make Prediction", data.skin, "simple");
var makePrediction = new TextButton("Make Prediction", game.data.skin, "simple");
makePrediction.addListener(new ChangeListener() {
@Override
public void changed(ChangeEvent event, Actor actor) {
@ -216,7 +212,7 @@ public class GameScreen extends MenuScreen {
}
});
var changePrediction = new TextButton("Change Prediction", data.skin, "simple");
var changePrediction = new TextButton("Change Prediction", game.data.skin, "simple");
changePrediction.addListener(new ChangeListener() {
@Override
public void changed(ChangeEvent event, Actor actor) {
@ -224,7 +220,7 @@ public class GameScreen extends MenuScreen {
}
});
var chooseTrump = new TextButton("Choose Trump", data.skin, "simple");
var chooseTrump = new TextButton("Choose Trump", game.data.skin, "simple");
chooseTrump.addListener(new ChangeListener() {
@Override
public void changed(ChangeEvent event, Actor actor) {
@ -250,17 +246,17 @@ public class GameScreen extends MenuScreen {
@Override
protected void renderBackground(float delta) {
float scale = Math.max(
data.extendViewport.getWorldWidth() / WizardGame.WIDTH,
data.extendViewport.getWorldHeight() / WizardGame.HEIGHT
game.data.extendViewport.getWorldWidth() / WizardGame.WIDTH,
game.data.extendViewport.getWorldHeight() / WizardGame.HEIGHT
);
game.batch.setColor(1, 1, 1, 0.25f);
game.batch.draw(data.background, 0,0, scale * WizardGame.WIDTH, scale * WizardGame.HEIGHT);
game.batch.draw(game.data.background, 0,0, scale * WizardGame.WIDTH, scale * WizardGame.HEIGHT);
game.batch.draw(
data.title,
(data.extendViewport.getWorldWidth() - data.title.getRegionWidth() * 0.75f) / 2f,
(data.extendViewport.getWorldHeight() - data.title.getRegionHeight() * 0.75f) / 2f,
0.75f * data.title.getRegionWidth(),
0.75f * data.title.getRegionHeight()
game.data.title,
(game.data.extendViewport.getWorldWidth() - game.data.title.getRegionWidth() * 0.75f) / 2f,
(game.data.extendViewport.getWorldHeight() - game.data.title.getRegionHeight() * 0.75f) / 2f,
0.75f * game.data.title.getRegionWidth(),
0.75f * game.data.title.getRegionHeight()
);
}
@ -287,13 +283,13 @@ public class GameScreen extends MenuScreen {
private void prepareLabels() {
for (UUID player : players) {
if (self.equals(player)) continue;
var label = new Label("", data.skin);
var label = new Label("", game.data.skin);
var seat = seats.get(player);
label.setX(seat.getLabelX());
label.setY(seat.getLabelY());
label.setAlignment(seat.getLabelAlign());
this.nameLabels.put(player, label);
data.stage.addActor(label);
game.data.stage.addActor(label);
}
}
@ -327,7 +323,7 @@ public class GameScreen extends MenuScreen {
cardStack.clearChildren();
stack.clear();
new StartRoundOverlay(this, round).show(data.stage);
new StartRoundOverlay(this, round).show(game.data.stage);
}
private void startTrick() {
@ -364,7 +360,7 @@ public class GameScreen extends MenuScreen {
trumpCardActor = new CardActor(Card.HIDDEN, atlas);
}
new TrumpOverlay(this, null, trumpCard, trumpSuit).show(data.stage);
new TrumpOverlay(this, null, trumpCard, trumpSuit).show(game.data.stage);
}
private void addPrediction(UUID player, int prediction) {
@ -427,7 +423,7 @@ public class GameScreen extends MenuScreen {
}
private void addMessage(String text) {
var label = new Label(text, data.skin);
var label = new Label(text, game.data.skin);
label.addAction(sequence(
delay(1.5f),
alpha(0, 0.25f),
@ -461,9 +457,9 @@ public class GameScreen extends MenuScreen {
setActivePlayer(userInput.getPlayer(), userInput.getAction());
if (self.equals(userInput.getPlayer())) {
switch (userInput.getAction()) {
case PICK_TRUMP -> new PickTrumpOverlay(this, false).show(data.stage);
case MAKE_PREDICTION -> new MakePredictionOverlay(this, round).show(data.stage);
case CHANGE_PREDICTION -> new ChangePredictionOverlay(this, round, predictions.get(self)).show(data.stage);
case PICK_TRUMP -> new PickTrumpOverlay(this, false).show(game.data.stage);
case MAKE_PREDICTION -> new MakePredictionOverlay(this, round).show(game.data.stage);
case CHANGE_PREDICTION -> new ChangePredictionOverlay(this, round, predictions.get(self)).show(game.data.stage);
}
// TODO do something
}
@ -479,8 +475,8 @@ public class GameScreen extends MenuScreen {
}
}
public MenuScreen.Data getData() {
return data;
public WizardGame.Data getData() {
return game.data;
}
@Getter

@ -0,0 +1,37 @@
package eu.jonahbauer.wizard.client.libgdx.screens;
import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.scenes.scene2d.ui.Label;
import com.badlogic.gdx.scenes.scene2d.ui.TextButton;
import com.badlogic.gdx.scenes.scene2d.ui.VerticalGroup;
import eu.jonahbauer.wizard.client.libgdx.WizardGame;
public class LoadingScreen extends MenuScreen {
private final String key;
@Deprecated
public LoadingScreen(WizardGame game) {
this(game, "menu.loading.loading");
}
public LoadingScreen(WizardGame game, String key) {
super(game);
this.key = key;
}
@Override
public void show() {
super.show();
var label = new Label(game.messages.get(key), game.data.skin);
var content = new VerticalGroup();
content.setPosition(WizardGame.WIDTH * 0.5f, WizardGame.HEIGHT*0.5f);
content.addActor(label);
game.data.stage.addActor(content);
Gdx.input.setInputProcessor(game.data.stage);
}
}

@ -6,56 +6,73 @@ import com.badlogic.gdx.scenes.scene2d.ui.*;
import com.badlogic.gdx.scenes.scene2d.utils.ChangeListener;
import eu.jonahbauer.wizard.client.libgdx.WizardGame;
import eu.jonahbauer.wizard.client.libgdx.actors.AutoFocusScrollPane;
import eu.jonahbauer.wizard.client.libgdx.state.AwaitingJoinSession;
import eu.jonahbauer.wizard.client.libgdx.state.Creation;
import eu.jonahbauer.wizard.client.libgdx.state.Lobby;
import eu.jonahbauer.wizard.client.libgdx.state.Menu;
import eu.jonahbauer.wizard.common.messages.client.JoinSessionMessage;
import eu.jonahbauer.wizard.common.messages.data.SessionData;
import eu.jonahbauer.wizard.common.model.Configuration;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;
import java.util.stream.IntStream;
import java.util.stream.StreamSupport;
public class LobbyScreen extends MenuScreen {
private TextButton buttonBack;
private TextButton buttonJoin;
private TextButton buttonCreate;
private TextField playerName;
private Label labelSessionName;
private Label labelSessionPlayerCount;
private Label labelSessionConfiguration;
private UUID selectedSession;
private List<SessionData> sessions;
private final Map<UUID, SessionData> sessionData = new HashMap<>();
private final ChangeListener listener = new ChangeListener() {
@Override
public void changed(ChangeEvent event, Actor actor) {
if (actor == buttonBack) {
game.setScreen(new ConnectScreen(game, data));
game.getClient().transition(new Menu());
sfxClick();
} else if (actor == buttonJoin) {
game.setScreen(new WaitingScreen(game, data));
if(playerName.getText().isEmpty()) {
System.out.println("Please choose a player name");
game.getClient().transition(new Menu());
}
if (selectedSession != null) {
var name = playerName.getText();
var session = sessionData.get(selectedSession);
game.getClient().transition(new AwaitingJoinSession(session, name));
game.getClient().send(new JoinSessionMessage(selectedSession, name));
}
sfxClick();
} else if (actor == buttonCreate) {
game.setScreen(new CreateGameScreen(game, data));
game.setScreen(new CreateGameScreen(game));
sfxClick();
}
}
};
public LobbyScreen(WizardGame game, Data data) {
super(game, data);
public LobbyScreen(WizardGame game) {
super(game);
}
@Override
public void show() {
super.show();
buttonBack = new TextButton(game.messages.get("menu.lobby.back"), data.skin);
buttonJoin = new TextButton(game.messages.get("menu.lobby.join"), data.skin);
buttonBack = new TextButton(game.messages.get("menu.lobby.back"), game.data.skin);
buttonJoin = new TextButton(game.messages.get("menu.lobby.join"), game.data.skin);
buttonJoin.setDisabled(true);
buttonCreate = new TextButton(game.messages.get("menu.lobby.create"), data.skin);
sessions = new List<>(data.skin) {
buttonCreate = new TextButton(game.messages.get("menu.lobby.create"), game.data.skin);
sessions = new List<>(game.data.skin) {
@Override
public String toString(SessionData session) {
return session.getName();
@ -64,18 +81,21 @@ public class LobbyScreen extends MenuScreen {
sessions.addListener(new ChangeListener() {
@Override
public void changed(ChangeEvent event, Actor actor) {
updateData(sessions.getSelected());
var selected = sessions.getSelected();
updateData(selected);
}
});
var listContainer = new AutoFocusScrollPane(sessions, data.skin);
var listContainer = new AutoFocusScrollPane(sessions, game.data.skin);
listContainer.layout();
var content = new HorizontalGroup().grow().space(20);
content.setPosition(0.25f * WizardGame.WIDTH, 0.3f * WizardGame.HEIGHT);
content.setSize(0.5f * WizardGame.WIDTH, 400);
content.addActor(new Container<>(listContainer).width(0.2f * WizardGame.WIDTH).height(400));
content.addActor(createInfoTable());
content.layout();
var buttons = new HorizontalGroup();
buttons.setPosition(WizardGame.WIDTH * 0.2f, BUTTON_BAR_Y);
buttons.setSize(WizardGame.WIDTH * 0.60f, 125);
@ -83,67 +103,103 @@ public class LobbyScreen extends MenuScreen {
buttons.addActor(buttonCreate);
buttons.addActor(buttonJoin);
buttons.space(Math.max(0, (float) (buttons.getWidth() - StreamSupport.stream(buttons.getChildren().spliterator(), false).mapToDouble(Actor::getWidth).sum()) / (buttons.getChildren().size - 1)));
Gdx.input.setInputProcessor(data.stage);
data.stage.addActor(content);
data.stage.addActor(buttons);
Gdx.input.setInputProcessor(game.data.stage);
game.data.stage.addActor(content);
game.data.stage.addActor(buttons);
buttonBack.addListener(listener);
buttonJoin.addListener(listener);
buttonCreate.addListener(listener);
addSessions(
IntStream.range(1, 16)
.mapToObj(i -> new SessionData(
UUID.randomUUID(),
"Session " + i,
i % 5,
Configuration.values()[i % Configuration.values().length]
))
.toArray(SessionData[]::new)
);
}
public void addSessions(SessionData...sessions) {
for (SessionData session : sessions) {
this.sessions.getItems().add(session);
public void addSession(SessionData session) {
this.sessionData.put(session.getUuid(), session);
this.sessions.getItems().add(session);
this.sessions.invalidateHierarchy();
}
public void removeSession(UUID session) {
this.sessionData.remove(session);
var items = this.sessions.getItems();
for (int i = 0; i < items.size; i++) {
if (items.get(i).getUuid().equals(session)) {
items.removeIndex(i);
break;
}
}
this.sessions.invalidateHierarchy();
if (session.equals(selectedSession)) {
updateData(null);
}
}
public void modifySession(SessionData session) {
this.sessionData.put(session.getUuid(), session);
var items = this.sessions.getItems();
for (int i = 0; i < items.size; i++) {
if (items.get(i).getUuid().equals(session.getUuid())) {
items.set(i, session);
break;
}
}
this.sessions.invalidateHierarchy();
if (session.getUuid().equals(selectedSession)) {
updateData(session);
}
}
public void setSessions(SessionData... sessions) {
this.sessionData.clear();
Arrays.stream(sessions).forEach(s -> this.sessionData.put(s.getUuid(), s));
var items = this.sessions.getItems();
items.clear();
items.addAll(sessions);
this.sessions.invalidateHierarchy();
}
private void updateData(SessionData data) {
System.out.println(data);
labelSessionName.setText(data.getName());
labelSessionPlayerCount.setText(Integer.toString(data.getPlayerCount()));
labelSessionConfiguration.setText(data.getConfiguration().toString());
if (data != null) {
labelSessionName.setText(data.getName());
labelSessionPlayerCount.setText(Integer.toString(data.getPlayerCount()));
labelSessionConfiguration.setText(data.getConfiguration().toString());
selectedSession = data.getUuid();
} else {
labelSessionName.setText("");
labelSessionPlayerCount.setText("");
labelSessionConfiguration.setText("");
selectedSession = null;
}
buttonJoin.setDisabled(data == null);
}
private Table createInfoTable() {
float infoTableWidth = 0.3f * WizardGame.WIDTH - 20;
playerName = new TextField("", data.skin);
labelSessionName = new Label("", data.skin, "textfield");
labelSessionConfiguration = new Label("", data.skin, "textfield");
labelSessionPlayerCount = new Label("", data.skin, "textfield");
playerName = new TextField("", game.data.skin);
labelSessionName = new Label("", game.data.skin, "textfield");
labelSessionConfiguration = new Label("", game.data.skin, "textfield");
labelSessionPlayerCount = new Label("", game.data.skin, "textfield");
labelSessionName.setEllipsis(true);
labelSessionConfiguration.setEllipsis(true);
labelSessionPlayerCount.setEllipsis(true);
var infoTable = new Table().center().left();
infoTable.columnDefaults(0).growX().width(infoTableWidth);
infoTable.setSize(infoTableWidth, 400);
infoTable.add(new Label(game.messages.get("menu.lobby.player_name.label"), data.skin)).row();
infoTable.add(new Label(game.messages.get("menu.lobby.player_name.label"), game.data.skin)).row();
infoTable.add(playerName).row();
infoTable.add(new Label(game.messages.get("menu.lobby.session_name.label"), data.skin)).row();
infoTable.add(new Label(game.messages.get("menu.lobby.session_name.label"), game.data.skin)).row();
infoTable.add(labelSessionName).row();
infoTable.add(new Label(game.messages.get("menu.lobby.session_configuration.label"), data.skin)).row();
infoTable.add(new Label(game.messages.get("menu.lobby.session_configuration.label"), game.data.skin)).row();
infoTable.add(labelSessionConfiguration).row();
infoTable.add(new Label(game.messages.get("menu.lobby.session_player_count.label"), data.skin)).row();
infoTable.add(new Label(game.messages.get("menu.lobby.session_player_count.label"), game.data.skin)).row();
infoTable.add(labelSessionPlayerCount).row();
return infoTable;
}
}

@ -5,6 +5,7 @@ import com.badlogic.gdx.scenes.scene2d.Actor;
import com.badlogic.gdx.scenes.scene2d.ui.TextButton;
import com.badlogic.gdx.scenes.scene2d.utils.ChangeListener;
import eu.jonahbauer.wizard.client.libgdx.WizardGame;
import eu.jonahbauer.wizard.common.messages.server.ServerMessage;
public class MainMenuScreen extends MenuScreen {
@ -15,7 +16,7 @@ public class MainMenuScreen extends MenuScreen {
@Override
public void changed(ChangeEvent event, Actor actor) {
if (actor == buttonPlay) {
game.setScreen(new ConnectScreen(game, data));
game.setScreen(new ConnectScreen(game));
sfxClick();
} else if (actor == buttonQuit) {
sfxClick();
@ -29,22 +30,18 @@ public class MainMenuScreen extends MenuScreen {
super(game);
}
public MainMenuScreen(WizardGame game, Data data) {
super(game, data);
}
@Override
public void show() {
super.show();
buttonPlay = new TextButton(game.messages.get("menu.main.play"), data.skin);
buttonPlay = new TextButton(game.messages.get("menu.main.play"), game.data.skin);
buttonPlay.setPosition((WizardGame.WIDTH - buttonPlay.getWidth()) / 2f, 192 + 504 - 120f - 125f);
buttonQuit = new TextButton(game.messages.get("menu.main.quit"), data.skin);
buttonQuit = new TextButton(game.messages.get("menu.main.quit"), game.data.skin);
buttonQuit.setPosition((WizardGame.WIDTH - buttonQuit.getWidth()) / 2f, 192 + 120f);
Gdx.input.setInputProcessor(data.stage);
data.stage.addActor(buttonPlay);
data.stage.addActor(buttonQuit);
Gdx.input.setInputProcessor(game.data.stage);
game.data.stage.addActor(buttonPlay);
game.data.stage.addActor(buttonQuit);
buttonPlay.addListener(listener);
buttonQuit.addListener(listener);
@ -55,9 +52,9 @@ public class MainMenuScreen extends MenuScreen {
super.renderForeground(delta);
int width = 160, height = 224;
int left = 384, right = 384, top = 384, bottom = 192;
this.game.batch.draw(data.symbols[0], left, bottom, width, height);
this.game.batch.draw(data.symbols[1], left, WizardGame.HEIGHT - top - height, width, height);
this.game.batch.draw(data.symbols[2], WizardGame.WIDTH - right - width, bottom, width, height);
this.game.batch.draw(data.symbols[3], WizardGame.WIDTH - right - width, WizardGame.HEIGHT - top - height, width, height);
this.game.batch.draw(game.data.symbols[0], left, bottom, width, height);
this.game.batch.draw(game.data.symbols[1], left, WizardGame.HEIGHT - top - height, width, height);
this.game.batch.draw(game.data.symbols[2], WizardGame.WIDTH - right - width, bottom, width, height);
this.game.batch.draw(game.data.symbols[3], WizardGame.WIDTH - right - width, WizardGame.HEIGHT - top - height, width, height);
}
}

@ -2,18 +2,7 @@ package eu.jonahbauer.wizard.client.libgdx.screens;
import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.Screen;
import com.badlogic.gdx.audio.Sound;
import com.badlogic.gdx.graphics.GL20;
import com.badlogic.gdx.graphics.Texture;
import com.badlogic.gdx.graphics.g2d.BitmapFont;
import com.badlogic.gdx.graphics.g2d.TextureAtlas;
import com.badlogic.gdx.graphics.g2d.TextureRegion;
import com.badlogic.gdx.scenes.scene2d.Stage;
import com.badlogic.gdx.scenes.scene2d.ui.Skin;
import com.badlogic.gdx.utils.viewport.ExtendViewport;
import com.badlogic.gdx.utils.viewport.FitViewport;
import eu.jonahbauer.wizard.client.libgdx.MenuAtlas;
import eu.jonahbauer.wizard.client.libgdx.UiskinAtlas;
import eu.jonahbauer.wizard.client.libgdx.WizardGame;
public abstract class MenuScreen implements Screen {
@ -21,85 +10,19 @@ public abstract class MenuScreen implements Screen {
protected WizardGame game;
// shared data between all menu screens
public static class Data {
public final ExtendViewport extendViewport;
public final FitViewport fitViewport;
public final Sound buttonClickSound;
public final TextureAtlas uiskinAtlas;
public final TextureAtlas menuAtlas;
public final TextureRegion title;
public final TextureRegion background;
public final TextureRegion[] corners = new TextureRegion[4];
public final TextureRegion[] symbols = new TextureRegion[4];
public final Skin skin;
public final Stage stage;
public Data() {
this.extendViewport = new ExtendViewport(WizardGame.WIDTH, WizardGame.HEIGHT);
this.fitViewport = new FitViewport(WizardGame.WIDTH, WizardGame.HEIGHT);
this.buttonClickSound = Gdx.audio.newSound(Gdx.files.internal("button_click_s.mp3"));
this.uiskinAtlas = new TextureAtlas(Gdx.files.internal(UiskinAtlas.$PATH));
this.menuAtlas = new TextureAtlas(Gdx.files.internal(MenuAtlas.$PATH));
this.title = menuAtlas.findRegion(MenuAtlas.TITLE);
this.background = menuAtlas.findRegion(MenuAtlas.BACKGROUND);
this.corners[0] = menuAtlas.findRegion(MenuAtlas.ECKE_LO);
this.corners[1] = menuAtlas.findRegion(MenuAtlas.ECKE_LU);
this.corners[2] = menuAtlas.findRegion(MenuAtlas.ECKE_RU);
this.corners[3] = menuAtlas.findRegion(MenuAtlas.ECKE_RO);
this.symbols[0] = menuAtlas.findRegion(MenuAtlas.SYMBOL0);
this.symbols[1] = menuAtlas.findRegion(MenuAtlas.SYMBOL1);
this.symbols[2] = menuAtlas.findRegion(MenuAtlas.SYMBOL2);
this.symbols[3] = menuAtlas.findRegion(MenuAtlas.SYMBOL3);
this.skin = new Skin(Gdx.files.internal("uiskin.json"), uiskinAtlas);
this.skin.getAll(BitmapFont.class).forEach(entry ->
entry.value.getRegion().getTexture().setFilter(Texture.TextureFilter.Linear, Texture.TextureFilter.Linear)
);
this.stage = new Stage(fitViewport);
}
public void reset() {
stage.clear();
}
public void dispose() {
buttonClickSound.dispose();
uiskinAtlas.dispose();
menuAtlas.dispose();
skin.dispose();
stage.dispose();
}
}
protected Data data;
// shared game.data between all menu screens
protected boolean dispose;
public MenuScreen(WizardGame game) {
this.game = game;
}
protected MenuScreen(WizardGame game, Data data) {
this.game = game;
this.data = data;
}
@Override
public void show() {
if (data == null) {
data = new Data();
if (game.data == null) {
game.data = new WizardGame.Data();
} else {
data.reset();
}
if (WizardGame.DEBUG) {
data.stage.setDebugAll(true);
game.data.reset();
}
}
@ -108,42 +31,42 @@ public abstract class MenuScreen implements Screen {
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT | GL20.GL_DEPTH_BUFFER_BIT | (Gdx.graphics.getBufferFormat().coverageSampling?GL20.GL_COVERAGE_BUFFER_BIT_NV:0));
// Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
data.extendViewport.apply(true);
game.batch.setProjectionMatrix(data.extendViewport.getCamera().combined);
game.data.extendViewport.apply(true);
game.batch.setProjectionMatrix(game.data.extendViewport.getCamera().combined);
game.batch.begin();
renderBackground(delta);
game.batch.end();
data.fitViewport.apply();
game.batch.setProjectionMatrix(data.fitViewport.getCamera().combined);
game.data.fitViewport.apply();
game.batch.setProjectionMatrix(game.data.fitViewport.getCamera().combined);
game.batch.begin();
renderForeground(delta);
game.batch.end();
data.stage.act(delta);
data.stage.draw();
game.data.stage.act(delta);
game.data.stage.draw();
}
protected void renderBackground(float delta) {
float scale = Math.max(
data.extendViewport.getWorldWidth() / WizardGame.WIDTH,
data.extendViewport.getWorldHeight() / WizardGame.HEIGHT
game.data.extendViewport.getWorldWidth() / WizardGame.WIDTH,
game.data.extendViewport.getWorldHeight() / WizardGame.HEIGHT
);
game.batch.draw(data.background, 0, 0, scale * WizardGame.WIDTH, scale * WizardGame.HEIGHT);
game.batch.draw(data.corners[0], 0, data.extendViewport.getWorldHeight() - data.corners[0].getRegionHeight());
game.batch.draw(data.corners[1], 0, 0);
game.batch.draw(data.corners[2], data.extendViewport.getWorldWidth() - data.corners[2].getRegionWidth(), 0);
game.batch.draw(data.corners[3], data.extendViewport.getWorldWidth() - data.corners[3].getRegionWidth(), data.extendViewport.getWorldHeight() - data.corners[3].getRegionHeight());
game.batch.draw(game.data.background, 0, 0, scale * WizardGame.WIDTH, scale * WizardGame.HEIGHT);
game.batch.draw(game.data.corners[0], 0, game.data.extendViewport.getWorldHeight() - game.data.corners[0].getRegionHeight());
game.batch.draw(game.data.corners[1], 0, 0);
game.batch.draw(game.data.corners[2], game.data.extendViewport.getWorldWidth() - game.data.corners[2].getRegionWidth(), 0);
game.batch.draw(game.data.corners[3], game.data.extendViewport.getWorldWidth() - game.data.corners[3].getRegionWidth(), game.data.extendViewport.getWorldHeight() - game.data.corners[3].getRegionHeight());
}
protected void renderForeground(float delta) {
game.batch.draw(data.title, 555, WizardGame.HEIGHT - 192 - 96, 810, 192);
game.batch.draw(game.data.title, 555, WizardGame.HEIGHT - 192 - 96, 810, 192);
}
@Override
public final void resize(int width, int height) {
data.extendViewport.update(width, height);
data.fitViewport.update(width, height);
game.data.extendViewport.update(width, height);
game.data.fitViewport.update(width, height);
}
@Override
@ -164,11 +87,11 @@ public abstract class MenuScreen implements Screen {
@Override
public void dispose() {
if (dispose) {
data.dispose();
game.data.dispose();
}
}
protected void sfxClick() {
data.buttonClickSound.play(0.6f);
game.data.buttonClickSound.play(0.6f);
}
}

@ -1,122 +1,173 @@
package eu.jonahbauer.wizard.client.libgdx.screens;
import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.graphics.Color;
import com.badlogic.gdx.scenes.scene2d.Actor;
import com.badlogic.gdx.scenes.scene2d.ui.*;
import com.badlogic.gdx.scenes.scene2d.utils.ChangeListener;
import eu.jonahbauer.wizard.client.libgdx.WizardGame;
import eu.jonahbauer.wizard.client.libgdx.actors.AutoFocusScrollPane;
import eu.jonahbauer.wizard.client.libgdx.state.AwaitingJoinLobby;
import eu.jonahbauer.wizard.client.libgdx.state.Session;
import eu.jonahbauer.wizard.common.messages.client.LeaveSessionMessage;
import eu.jonahbauer.wizard.common.messages.client.ReadyMessage;
import eu.jonahbauer.wizard.common.messages.data.PlayerData;
import eu.jonahbauer.wizard.common.messages.data.SessionData;
import eu.jonahbauer.wizard.common.model.Configuration;
import java.util.UUID;
public class WaitingScreen extends MenuScreen {
private TextButton buttonLeave;
private TextButton buttonReady;
private SessionData session;
private UUID myUUID;
private String myName;
private boolean myReady;
private Label labelSessionName;
private Label labelSessionUUID;
private Label labelSessionConfiguration;
private Label labelPlayerName;
private List<PlayerData> players;
{
// sample data
session = new SessionData(UUID.randomUUID(), "Session X", -1, Configuration.DEFAULT);
myUUID = UUID.randomUUID();
myName = "Max Mustermann";
}
private AutoFocusScrollPane listContainer;
private final ChangeListener listener = new ChangeListener() {
@Override
public void changed(ChangeEvent event, Actor actor) {
if (actor == buttonLeave) {
game.setScreen(new LobbyScreen(game, data));
game.getClient().transition(new AwaitingJoinLobby());
game.getClient().send(new LeaveSessionMessage());
sfxClick();
} else if (actor == buttonReady) {
ready(!myReady);
var state = (Session) game.getClient().getState();
state.setNextReady(!state.isReady());
game.getClient().send(new ReadyMessage(!state.isReady()));
buttonReady.setDisabled(true);
sfxClick();
}
}
};
public WaitingScreen(WizardGame game, Data data) {
super(game, data);
public WaitingScreen(WizardGame game) {
super(game);
}
@Override
public void show() {
super.show();
buttonLeave = new TextButton(game.messages.get("menu.waiting.leave"), data.skin);
buttonLeave = new TextButton(game.messages.get("menu.waiting.leave"), game.data.skin);
buttonLeave.setPosition(WizardGame.WIDTH * 0.275f, BUTTON_BAR_Y);
buttonReady = new TextButton(game.messages.get("menu.waiting.ready"), data.skin);
buttonReady = new TextButton(game.messages.get("menu.waiting.ready"), game.data.skin);
buttonReady.setPosition(WizardGame.WIDTH * 0.725f - buttonReady.getWidth(), BUTTON_BAR_Y);
players = new List<>(data.skin) {
players = new List<>(game.data.skin) {
@Override
public String toString(PlayerData player) {
return player.getName();
}
};
var listContainer = new AutoFocusScrollPane(players, data.skin);
listContainer = new AutoFocusScrollPane(players, game.data.skin);
listContainer.layout();
var content = new HorizontalGroup().grow().space(20);
content.setPosition(0.25f * WizardGame.WIDTH, 0.3f * WizardGame.HEIGHT);
content.setSize(0.5f * WizardGame.WIDTH, 400);
content.addActor(new Container<>(listContainer).width(0.2f * WizardGame.WIDTH).height(400));
content.addActor(createInfoTable());
content.layout();
Gdx.input.setInputProcessor(data.stage);
data.stage.addActor(buttonLeave);
data.stage.addActor(buttonReady);
data.stage.addActor(content);
Gdx.input.setInputProcessor(game.data.stage);
game.data.stage.addActor(buttonLeave);
game.data.stage.addActor(buttonReady);
game.data.stage.addActor(content);
buttonLeave.addListener(listener);
buttonReady.addListener(listener);
// sample data
for (int i = 1; i <= 4; i++) {
players.getItems().add(new PlayerData(UUID.randomUUID(), "Player " + i, false));
}
players.invalidateHierarchy();
}
private void ready(boolean ready) {
this.myReady = ready;
public void setReady(boolean ready) {
buttonReady.setDisabled(false);
buttonReady.setText(game.messages.get(ready ? "menu.waiting.not_ready" : "menu.waiting.ready"));
}
public void addPlayer(PlayerData player) {
this.players.getItems().add(player);
var items = this.players.getItems();
for (int i = 0; i < items.size; i++) {
if (items.get(i).getUuid().equals(player.getUuid())) {
items.set(i, player);
break;
}
}
this.players.invalidateHierarchy();
}
public void removePlayer(UUID player) {
var items = this.players.getItems();
for (int i = 0; i < items.size; i++) {
if (items.get(i).getUuid().equals(player)) {
items.removeIndex(i);
break;
}
}
this.players.invalidateHierarchy();
}
public void modifyPlayer(PlayerData data) {
var items = this.players.getItems();
for (int i = 0; i < items.size; i++) {
if (items.get(i).getUuid().equals(data.getUuid())) {
items.set(i, data);
break;
}
}
this.players.invalidateHierarchy();
}
public void setPlayers(PlayerData... players) {
var items = this.players.getItems();
items.clear();
items.addAll(players);
this.players.invalidateHierarchy();
}
public void setSession(SessionData session) {
this.labelSessionName.setText(session.getName());
this.labelSessionUUID.setText(session.getUuid().toString());
this.labelSessionConfiguration.setText(session.getConfiguration().toString());
}
public void setPlayerName(String name) {
this.labelPlayerName.setText(name);
}
private Table createInfoTable() {
float infoTableWidth = 0.3f * WizardGame.WIDTH - 20;
var labelSessionName = new Label(session.getName(), data.skin, "textfield");
var labelSessionUUID = new Label(session.getUuid().toString(), data.skin, "textfield");
var labelSessionConfiguration = new Label(session.getConfiguration().toString(), data.skin, "textfield");
var labelPlayerName = new Label(myName, data.skin, "textfield");
labelSessionName = new Label("", game.data.skin, "textfield");
labelSessionUUID = new Label("", game.data.skin, "textfield");
labelSessionConfiguration = new Label("", game.data.skin, "textfield");
labelPlayerName = new Label("", game.data.skin, "textfield");
labelSessionName.setEllipsis(true);
labelSessionUUID.setEllipsis(true);
labelSessionConfiguration.setEllipsis(true);
labelPlayerName.setEllipsis(true);
var infoTable = new Table().center().left();
infoTable.columnDefaults(0).growX().width(infoTableWidth);
infoTable.setSize(infoTableWidth, 400);
infoTable.add(new Label(game.messages.get("menu.waiting.session_name.label"), data.skin)).row();
infoTable.add(new Label(game.messages.get("menu.waiting.session_name.label"), game.data.skin)).row();
infoTable.add(labelSessionName).row();
infoTable.add(new Label(game.messages.get("menu.waiting.session_uuid.label"), data.skin)).row();
infoTable.add(new Label(game.messages.get("menu.waiting.session_uuid.label"), game.data.skin)).row();
infoTable.add(labelSessionUUID).row();
infoTable.add(new Label(game.messages.get("menu.waiting.session_configuration.label"), data.skin)).row();
infoTable.add(new Label(game.messages.get("menu.waiting.session_configuration.label"), game.data.skin)).row();
infoTable.add(labelSessionConfiguration).row();
infoTable.add(new Label(game.messages.get("menu.waiting.player_name.label"), data.skin)).row();
infoTable.add(new Label(game.messages.get("menu.waiting.player_name.label"), game.data.skin)).row();
infoTable.add(labelPlayerName).row();
return infoTable;
}
}

@ -0,0 +1,28 @@
package eu.jonahbauer.wizard.client.libgdx.state;
import eu.jonahbauer.wizard.client.libgdx.Client;
import eu.jonahbauer.wizard.common.messages.server.ServerMessage;
import lombok.SneakyThrows;
import java.util.Optional;
public abstract class Awaiting extends BaseState implements ClientState {
@Override
public Optional<ClientState> onMessage(Client client, ServerMessage message) {
return unexpectedMessage(client, message);
}
@Override
@SneakyThrows
public Optional<ClientState> onEnter(Client client) {
client.timeout(this, 10_000);
return Optional.empty();
}
@Override
public Optional<ClientState> onTimeout(Client client) {
System.out.println("Timed out. Returning to menu");
return Optional.of(new Menu());
}
}

@ -0,0 +1,29 @@
package eu.jonahbauer.wizard.client.libgdx.state;
import eu.jonahbauer.wizard.client.libgdx.Client;
import eu.jonahbauer.wizard.client.libgdx.screens.LoadingScreen;
import eu.jonahbauer.wizard.client.libgdx.screens.LobbyScreen;
import java.util.Optional;
public class AwaitingConnection extends Awaiting {
@Override
public Optional<ClientState> onEnter(Client client) {
System.out.println("Awaiting connection...");
client.getGame().setScreen(new LoadingScreen(client.getGame()));
return super.onEnter(client);
}
@Override
public Optional<ClientState> onOpen(Client client) {
System.out.println("Connection established.");
return Optional.of(new AwaitingJoinLobby());
}
@Override
public Optional<ClientState> onClose(Client client, int code, String reason, boolean remote) {
System.out.println("Connection could not be established. (code=%d, reason=%s)" + code + reason);
return Optional.of(new Menu());
}
}

@ -0,0 +1,27 @@
package eu.jonahbauer.wizard.client.libgdx.state;
import eu.jonahbauer.wizard.client.libgdx.Client;
import eu.jonahbauer.wizard.client.libgdx.screens.LoadingScreen;
import eu.jonahbauer.wizard.common.messages.server.ServerMessage;
import eu.jonahbauer.wizard.common.messages.server.SessionListMessage;
import java.util.Optional;
public final class AwaitingJoinLobby extends Awaiting {
@Override
public Optional<ClientState> onEnter(Client client) {
System.out.println("Waiting for session list...");
client.getGame().setScreen(new LoadingScreen(client.getGame()));
return super.onEnter(client);
}
@Override
public Optional<ClientState> onMessage(Client client, ServerMessage message) {
if (message instanceof SessionListMessage list) {
return Optional.of(new Lobby(list));
} else {
return super.onMessage(client, message);
}
}
}

@ -0,0 +1,46 @@
package eu.jonahbauer.wizard.client.libgdx.state;
import eu.jonahbauer.wizard.client.libgdx.Client;
import eu.jonahbauer.wizard.client.libgdx.screens.LoadingScreen;
import eu.jonahbauer.wizard.common.messages.data.SessionData;
import eu.jonahbauer.wizard.common.messages.server.*;
import lombok.Getter;
import lombok.RequiredArgsConstructor;
import java.util.Optional;
@Getter
@RequiredArgsConstructor
public final class AwaitingJoinSession extends Awaiting {
private final SessionData session;
private final String playerName;
@Override
public Optional<ClientState> onEnter(Client client) {
System.out.println("Waiting for acknowledgment...");
client.getGame().setScreen(new LoadingScreen(client.getGame()));
return super.onEnter(client);
}
@Override
public Optional<ClientState> onMessage(Client client, ServerMessage message) {
if (message instanceof SessionJoinedMessage joined) {
return Optional.of(new Session(joined, session, playerName));
} else if (message instanceof NackMessage nack) {
switch (nack.getCode()) {
case NackMessage.GAME_ALREADY_STARTED -> System.out.println("Error: Game has already started.");
case NackMessage.SESSION_FULL -> System.out.println("Error: The session is full.");
case NackMessage.SESSION_NOT_FOUND -> System.out.println("Error: Session not found.");
case NackMessage.NAME_TAKEN -> System.out.println("Error: Name already taken.");
default -> { return super.onMessage(client, message); }
}
return Optional.of(new AwaitingJoinLobby());
} else if (message instanceof SessionModifiedMessage || message instanceof SessionRemovedMessage) {
// drop
return Optional.empty();
} else {
return super.onMessage(client, message);
}
}
}

@ -0,0 +1,35 @@
package eu.jonahbauer.wizard.client.libgdx.state;
import eu.jonahbauer.wizard.client.libgdx.Client;
import eu.jonahbauer.wizard.common.messages.server.ServerMessage;
import java.util.Optional;
public abstract class BaseState implements ClientState {
@Override
public Optional<ClientState> onEnter(Client context) {
return ClientState.super.onEnter(context);
}
@Override
public Optional<ClientState> onOpen(Client client) {
throw new IllegalStateException();
}
@Override
public Optional<ClientState> onClose(Client client, int code, String reason, boolean remote) {
if (remote) {
System.out.println("Lost connection " + code + " " + reason);
} else {
System.out.println("Connection closed " + code + " " + reason);
}
return Optional.of(new Menu());
}
protected static Optional<ClientState> unexpectedMessage(Client client, ServerMessage message) {
// return to menu on unexpected message
System.out.println("Fatal: Unexpected message " + message + ". Returning to menu.");
return Optional.of(new Menu());
}
}

@ -0,0 +1,16 @@
package eu.jonahbauer.wizard.client.libgdx.state;
import eu.jonahbauer.wizard.client.libgdx.Client;
import eu.jonahbauer.wizard.common.machine.TimeoutState;
import eu.jonahbauer.wizard.common.messages.server.ServerMessage;
import java.util.Optional;
public interface ClientState extends TimeoutState<ClientState, Client> {
Optional<ClientState> onOpen(Client client);
Optional<ClientState> onMessage(Client client, ServerMessage message);
Optional<ClientState> onClose(Client client, int code, String reason, boolean remote);
}

@ -0,0 +1,34 @@
package eu.jonahbauer.wizard.client.libgdx.state;
import eu.jonahbauer.wizard.client.libgdx.Client;
import eu.jonahbauer.wizard.client.libgdx.screens.CreateGameScreen;
import eu.jonahbauer.wizard.common.messages.server.ServerMessage;
import eu.jonahbauer.wizard.common.messages.server.SessionCreatedMessage;
import java.util.Optional;
public final class Creation extends BaseState {
private CreateGameScreen createScreen;
public Creation() {
}
@Override
public Optional<ClientState> onEnter(Client client) {
createScreen = new CreateGameScreen(client.getGame());
client.getGame().setScreen(createScreen);
return super.onEnter(client);
}
@Override
public Optional<ClientState> onMessage(Client client, ServerMessage message) {
if (message instanceof SessionCreatedMessage created) {
return Optional.empty();
} else {
return unexpectedMessage(client, message);
}
}
}

@ -0,0 +1,54 @@
package eu.jonahbauer.wizard.client.libgdx.state;
import com.badlogic.gdx.utils.reflect.ClassReflection;
import eu.jonahbauer.wizard.client.libgdx.Client;
import eu.jonahbauer.wizard.client.libgdx.screens.CreateGameScreen;
import eu.jonahbauer.wizard.client.libgdx.screens.LobbyScreen;
import eu.jonahbauer.wizard.common.messages.data.SessionData;
import eu.jonahbauer.wizard.common.messages.server.*;
import java.util.Optional;
public final class Lobby extends BaseState {
private SessionListMessage list;
private LobbyScreen lobbyScreen;
private CreateGameScreen createScreen;
public Lobby(SessionListMessage list) {
this.list = list;
}
@Override
public Optional<ClientState> onEnter(Client client) {
lobbyScreen = new LobbyScreen(client.getGame());
client.getGame().setScreen(lobbyScreen);
lobbyScreen.setSessions(list.getSessions().toArray(new SessionData[0]));
list = null;
return super.onEnter(client);
}
@Override
public Optional<ClientState> onMessage(Client client, ServerMessage message) {
if (message instanceof SessionCreatedMessage created) {
lobbyScreen.addSession(created.getSession());
return Optional.empty();
} else if (message instanceof SessionRemovedMessage removed) {
lobbyScreen.removeSession(removed.getSession());
return Optional.empty();
} else if (message instanceof SessionModifiedMessage modified) {
lobbyScreen.modifySession(modified.getSession());
return Optional.empty();
} else if (message instanceof SessionListMessage list) {
lobbyScreen.setSessions(list.getSessions().toArray(new SessionData[0]));
return Optional.empty();
} else if (message instanceof SessionJoinedMessage joined) {
//TODO find solution
createScreen = new CreateGameScreen(client.getGame());
return Optional.empty();
} else {
return unexpectedMessage(client, message);
}
}
}

@ -0,0 +1,35 @@
package eu.jonahbauer.wizard.client.libgdx.state;
import eu.jonahbauer.wizard.client.libgdx.Client;
import eu.jonahbauer.wizard.client.libgdx.screens.MainMenuScreen;
import eu.jonahbauer.wizard.common.messages.server.ServerMessage;
import lombok.SneakyThrows;
import org.java_websocket.framing.CloseFrame;
import java.util.Optional;
public final class Menu extends BaseState {
@Override
@SneakyThrows
public Optional<ClientState> onEnter(Client client) {
if (client.getSocket() != null && client.getSocket().isOpen()) {
client.getSocket().close(CloseFrame.GOING_AWAY);
}
client.getGame().setScreen(new MainMenuScreen(client.getGame()));
return super.onEnter(client);
}
@Override
public Optional<ClientState> onMessage(Client client, ServerMessage message) {
// it is possible that there are messages still queued after
// returning to the menu as a result of a previous message
return Optional.empty();
}
@Override
public Optional<ClientState> onClose(Client client, int code, String reason, boolean remote) {
super.onClose(client, code, reason, remote);
return Optional.empty();
}
}

@ -0,0 +1,84 @@
package eu.jonahbauer.wizard.client.libgdx.state;
import eu.jonahbauer.wizard.client.libgdx.Client;
import eu.jonahbauer.wizard.client.libgdx.screens.GameScreen;
import eu.jonahbauer.wizard.client.libgdx.screens.WaitingScreen;
import eu.jonahbauer.wizard.common.messages.data.PlayerData;
import eu.jonahbauer.wizard.common.messages.data.SessionData;
import eu.jonahbauer.wizard.common.messages.server.*;
import eu.jonahbauer.wizard.common.model.Configuration;
import lombok.Getter;
import lombok.Setter;
import java.util.Optional;
import java.util.UUID;
@Getter
public final class Session extends BaseState {
private SessionJoinedMessage joined;
private WaitingScreen sessionScreen;
private final UUID self;
private final String secret;
private final SessionData session;
private final String playerName;
private boolean ready;
@Setter
private Boolean nextReady;
public Session(SessionJoinedMessage joined, SessionData session, String playerName) {
if (!joined.getSession().equals(session.getUuid())) throw new RuntimeException();
this.self = joined.getPlayer();
this.secret = joined.getSecret();
this.session = session;
this.joined = joined;
this.playerName = playerName;
}
@Override
public Optional<ClientState> onEnter(Client client) {
sessionScreen = new WaitingScreen(client.getGame());
client.getGame().setScreen(sessionScreen);
sessionScreen.setPlayers(joined.getPlayers().toArray(new PlayerData[0]));
sessionScreen.setReady(false);
sessionScreen.setPlayerName(playerName);
sessionScreen.setSession(session);
joined = null;
return super.onEnter(client);
}
@Override
public Optional<ClientState> onMessage(Client client, ServerMessage message) {
if (message instanceof PlayerJoinedMessage join) {
sessionScreen.addPlayer(join.getPlayer());
return Optional.empty();
} else if (message instanceof PlayerLeftMessage leave) {
sessionScreen.removePlayer(leave.getPlayer());
return Optional.empty();
} else if (message instanceof PlayerModifiedMessage modified) {
sessionScreen.modifyPlayer(modified.getPlayer());
return Optional.empty();
} else if (message instanceof StartingGameMessage) {
client.getGame().setScreen(new GameScreen(client.getGame()));
return Optional.empty();
} else if (nextReady != null && message instanceof NackMessage nack) {
// TODO display error
System.out.println("Error: " + nack.getMessage());
sessionScreen.setReady(!nextReady);
nextReady = null;
return Optional.empty();
} else if (nextReady != null && message instanceof AckMessage) {
sessionScreen.setReady(nextReady);
ready = nextReady;
nextReady = null;
return Optional.empty();
} else {
return unexpectedMessage(client, message);
}
}
}

@ -4,6 +4,7 @@ menu.main.quit=Close
menu.connect.connect=Connect
menu.connect.back=Back
menu.connect.address.label=Enter Server Address
menu.connect.uri.hint=Server Address
menu.lobby.join=Join
menu.lobby.create=Create
@ -13,6 +14,11 @@ menu.lobby.session_name.label=Session Name
menu.lobby.session_player_count.label=Current Player Count
menu.lobby.session_configuration.label=Configuration
menu.lobby.create_session.timeout.label=Timeout
menu.loading.loading=Loading...
menu.loading.back=Return To Main Menu
menu.waiting.ready=Ready
menu.waiting.not_ready=Not Ready
menu.waiting.leave=Leave

@ -4,6 +4,7 @@ menu.main.quit=Verlassen
menu.connect.connect=Verbinden
menu.connect.back=Zurück
menu.connect.address.label=Server-Adresse eingeben
menu.connect.uri.hint=Server Address
menu.lobby.join=Beitreten
menu.lobby.create=Erstellen
@ -13,6 +14,11 @@ menu.lobby.session_name.label=Session Name
menu.lobby.session_player_count.label=Spieleranzahl
menu.lobby.session_configuration.label=Spielvariante
menu.lobby.create_session.timeout.label=Timeout
menu.loading.loading=Laden...
menu.loading.back=Zurück zum Hauptmenü
menu.waiting.ready=Bereit
menu.waiting.not_ready=Nicht Bereit
menu.waiting.leave=Verlassen

Loading…
Cancel
Save