SocketIOGameRoom.java
package com.github.quizclash.plugin.network;
import com.github.quizclash.application.TerminationException;
import com.github.quizclash.application.room.GameRoom;
import com.github.quizclash.application.room.GameRoomListener;
import com.github.quizclash.domain.CategoryRepository;
import com.github.quizclash.domain.InvalidQuestionFormatException;
import com.github.quizclash.domain.User;
import io.socket.client.IO;
import io.socket.client.Socket;
import org.json.JSONArray;
import org.json.JSONObject;
import java.net.URI;
import java.util.ArrayList;
import java.util.List;
public class SocketIOGameRoom extends GameRoom {
private final Object lock = new Object();
private final Socket socket;
private final List<GameRoomListener> gameRoomListeners = new ArrayList<>();
private String roomName;
private List<User> players = new ArrayList<>();
private OnlineCategoryRepository onlineCategoryRepository;
public SocketIOGameRoom(User user, URI gameServerURL, String code) {
super(user, code);
this.socket = IO.socket(gameServerURL);
socket.on("joined room", args -> {
JSONObject response = (JSONObject) args[0];
roomName = response.getString("room_name");
JSONArray categories_json = response.getJSONArray("categories");
try {
onlineCategoryRepository = new OnlineCategoryRepository(categories_json);
} catch (InvalidQuestionFormatException e) {
throw new TerminationException("QuizClash was interrupted");
}
dispatchRoomJoin();
});
socket.on("show players", args -> {
JSONObject response = (JSONObject) args[0];
JSONArray playersArray = response.getJSONArray("players");
players = playersArray.toList().stream().map(name -> new User((String) name)).toList();
dispatchPlayerUpdate();
});
socket.on("game start", args -> dispatchGameStart());
socket.on("game turn action", args -> dispatchGameTurnAction());
socket.on("game turn listen", args -> dispatchGameTurnListen());
socket.on("game turn listen category submission",
args -> dispatchGameTurnListenCategorySubmission((Integer) args[0]));
socket.on("game turn listen question option submission",
args -> dispatchGameTurnListenQuestionOptionSubmission((Integer) args[0]));
socket.on("game finished", args -> releaseGameLock());
socket.on("room terminated", args -> releaseGameLock());
socket.connect();
JSONObject roomToJoin = new JSONObject();
roomToJoin.put("user_name", this.getNameOfPlayingUser());
roomToJoin.put("room_code", code);
socket.emit("join", roomToJoin);
}
private void releaseGameLock() {
synchronized (lock) {
lock.notifyAll();
}
socket.off();
socket.close();
}
@Override
public void waitForGameToFinish() throws TerminationException {
synchronized (lock) {
try {
lock.wait();
} catch (InterruptedException e) {
throw new TerminationException("QuizClash was interrupted");
}
}
}
@Override
public void addListener(GameRoomListener gameRoomListener) {
gameRoomListeners.add(gameRoomListener);
}
@Override
public void dispatchRoomJoin() {
gameRoomListeners.forEach(GameRoomListener::onJoinedRoom);
}
@Override
public void dispatchPlayerUpdate() {
gameRoomListeners.forEach(GameRoomListener::onUpdatePlayers);
}
@Override
public void dispatchGameStart() {
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
throw new TerminationException("QuizClash was interrupted");
}
gameRoomListeners.forEach(GameRoomListener::onGameStart);
}
@Override
public String getRoomName() {
return roomName;
}
@Override
public List<User> getPlayers() {
return players;
}
@Override
public CategoryRepository getRoomCategoryRepository() {
return onlineCategoryRepository;
}
@Override
public void sendSelectedCategoryId(int categoryId) {
socket.emit("game turn action category submission", categoryId);
}
@Override
public void sendSelectedQuestionOptionIndex(int questionOptionIndex) {
socket.emit("game turn action question option submission", questionOptionIndex);
}
@Override
public void dispatchGameTurnAction() {
gameRoomListeners.forEach(GameRoomListener::onGameTurnAction);
}
@Override
public void dispatchGameTurnListen() {
gameRoomListeners.forEach(GameRoomListener::onGameTurnListen);
}
@Override
public void dispatchGameTurnListenCategorySubmission(int selectedCategoryId) {
gameRoomListeners.forEach(
gameRoomListener -> gameRoomListener.onGameTurnListenCategorySubmission(
selectedCategoryId));
}
@Override
public void dispatchGameTurnListenQuestionOptionSubmission(int selectedQuestionOptionIndex) {
gameRoomListeners.forEach(
gameRoomListener -> gameRoomListener.onGameTurnListenQuestionOptionSubmission(
selectedQuestionOptionIndex));
}
}