I have implemented a websocket endpoint using the API provided with Java EE 7 for a game using HTML5 websockets. I can successfully send messages using a timer task in order to update the ball position, bricks, etc. but I would like to be able to send messages from within my Game class to the correct player, and send a message when the game is lost, when the score is updated, ...
The only way this would be possible for me right now is to send the score, amountOfLives, ... at every single update but I feel like this is not the way to go. Is it possible to send messages to a client from different classes, in this case my Game class?
Game class (See comment what I would like to achieve)
public class Game implements Runnable {
private void loseLife() {
if (lives != 0) {
lives -= 1;
ball.reset(paddle);
} else {
lose();
}
}
private void lose() {
gameRunning = false;
// What I would like to achieve
sendMessage("Game is lost");
}
}
Socket endpoint:
@ServerEndpoint("/singleplayer")
public class SingleplayerSocket {
private static final Set<Session> PLAYERS = Collections.synchronizedSet(new HashSet<Session>());
private Session session;
private Gson gson;
private Game game;
private void sendMessage(String message) {
try {
for (Session player : PLAYERS) {
if (player == session) {
player.getBasicRemote().sendText(message);
}
}
} catch (IOException ex) {
ex.printStackTrace();
}
}
@OnOpen
public void onOpen(Session session) {
this.session = session;
PLAYERS.add(session);
sendMessage("Connection established");
}
@OnMessage
public void onMessage(String message) {
if (session != null && session.isOpen()) {
gson = new Gson();
String messageType = gson.fromJson(message, MessageType.class).getMessage();
switch (messageType) {
case "gameSetup":
String jsonData = getJsonData(message);
GameSetupRequest request = gson.fromJson(jsonData, GameSetupRequest.class);
int canvasWidth = request.getCanvasWidth();
int canvasHeight = request.getCanvasHeight();
String difficultyName = request.getDifficulty();
sendMessage(gameSetup(canvasWidth, canvasHeight, difficultyName));
break;
case "gameStart":
Thread gameLoop = new Thread(game);
gameLoop.start();
Timer timer = new Timer();
timer.schedule(new UpdateTask(), 0, 1000 / 60);
sendMessage("Game started");
break;
}
}
@OnClose
public void onClose(Session session) {
PLAYERS.remove(session);
this.session = null;
}
class UpdateTask extends TimerTask {
@Override
public void run() {
if (game.isGameRunning()) {
sendMessage(gameUpdate());
}
}
}
Solved it by adding the session to my constructor
private Session session;
public Game(Session session, int width, int height) {
this.session = session;
this.WIDTH = width;
this.HEIGHT = height;
}
private void sendMessage(String text) {
try {
session.getBasicRemote().sendText(text);
} catch (IOException e) {
e.printStackTrace();
}
}
and then generating a new game like this:
game = new Game(session, setupRequest.getCanvasWidth(), setupRequest.getCanvasHeight());