package websocket; import com.google.gson.JsonArray; import com.google.gson.JsonElement; import com.google.gson.JsonObject; import com.google.gson.JsonParser; import game.Room; import model.UserProfile; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; import org.eclipse.jetty.websocket.api.RemoteEndpoint; import org.eclipse.jetty.websocket.api.Session; import org.eclipse.jetty.websocket.api.WebSocketAdapter; import websocket.message.Message; import java.util.ArrayList; import java.util.List; /** * nickolay, 21.02.15. */ public class GameWebSocketHandler extends WebSocketAdapter { public static final Logger LOG = LogManager.getLogger(GameWebSocketHandler.class); public static final int CLOSE_REASON_NO_AUTH = 1; public enum MessageType { CODE_ROOM_PLAYERS_RESPONSE, CODE_PLAYER_CONNECTED_RESPONSE, CODE_PLAYER_DISCONNECTED_RESPONSE, CODE_READY_REQUEST, CODE_READY_RESPONSE, CODE_INIT_STATE_RESPONSE, CODE_KEY_REQUEST, CODE_KEY_RESPONSE, CODE_SNAKE_UPDATES_RESPONSE, CODE_NEW_BONUS_RESPONSE, CODE_BONUS_EAT_RESPONSE, CODE_ROUND_END_RESPONSE, CODE_GAME_OVER_RESPONSE, CODE_ROOM_START_RESPONSE, CODE_SNAKE_ARC_RESPONSE, CODE_SNAKE_PATCH_REQUEST,//15 CODE_SNAKE_PATCH_RESPONSE, CODE_START_ROUND_RESPONSE, CODE_RATING_UPDATE_RESPONSE, CODE_CREATE_ROOM_REQUEST, CODE_CONNECT_TO_ROOM_REQUEST, CODE_GET_ROOMS_REQUEST, CODE_ROOMS_RESPONSE, CODE_CONNECTED_TO_ROOM_RESPONSE } private WebSocketMessageListener messageListener; private UserProfile userProfile; private Room room; private Session session; public GameWebSocketHandler(UserProfile userProfile, WebSocketMessageListener messageListener) { this.userProfile = userProfile; this.messageListener = messageListener; } @Override public void onWebSocketError(Throwable cause) { System.out.println("[GameWebSocketHandler] WebSocket error: " + cause.toString() + " for user " + userProfile); messageListener.onDisconnect(this); } @Override public void onWebSocketClose(int statusCode, String reason) { System.out.println("[GameWebSocketHandler] WebSocket closed: " + statusCode + " for user " + userProfile); messageListener.onDisconnect(this); } @Override public void onWebSocketText(String message) { try { JsonObject jresponse = (JsonObject) new JsonParser().parse(message); MessageType responseType = MessageType.values()[jresponse.get("code").getAsInt()]; switch (responseType) { case CODE_ROOM_PLAYERS_RESPONSE: break; case CODE_PLAYER_CONNECTED_RESPONSE: break; case CODE_PLAYER_DISCONNECTED_RESPONSE: break; case CODE_READY_REQUEST: boolean isReady = jresponse.get("ready").getAsBoolean(); messageListener.onUserReady(this, isReady); break; case CODE_READY_RESPONSE: break; case CODE_INIT_STATE_RESPONSE: break; case CODE_KEY_REQUEST: boolean isLeft = jresponse.get("isLeft").getAsBoolean(); boolean isUp = jresponse.get("isUp").getAsBoolean(); messageListener.onControl(this, isLeft, isUp); break; case CODE_KEY_RESPONSE: break; case CODE_SNAKE_UPDATES_RESPONSE: break; case CODE_ROOM_START_RESPONSE: break; case CODE_SNAKE_ARC_RESPONSE: break; case CODE_SNAKE_PATCH_REQUEST: JsonArray array = jresponse.get("ids").getAsJsonArray(); List<Integer> lostIds = new ArrayList<>(); for (JsonElement elem : array) { lostIds.add(elem.getAsInt()); } room.sendPatchToUser(userProfile, lostIds); break; case CODE_NEW_BONUS_RESPONSE: break; case CODE_BONUS_EAT_RESPONSE: break; case CODE_ROUND_END_RESPONSE: break; case CODE_GAME_OVER_RESPONSE: break; case CODE_SNAKE_PATCH_RESPONSE: break; case CODE_START_ROUND_RESPONSE: break; case CODE_RATING_UPDATE_RESPONSE: break; case CODE_CREATE_ROOM_REQUEST: break; case CODE_CONNECT_TO_ROOM_REQUEST: messageListener.onConnectToRoom( this, jresponse.get("room").getAsString() ); break; case CODE_GET_ROOMS_REQUEST: messageListener.onGetRooms( this ); break; } } catch (ClassCastException e) { // TODO: error response e.printStackTrace(); } } @Override public void onWebSocketConnect(Session session) { this.session = session; messageListener.onNewConnection(this); } public boolean sendMessage(Message message) { try { RemoteEndpoint remote = session.getRemote(); synchronized (remote) { try { remote.sendString(message.getBody()); return true; } catch (Exception we) { System.out.println("[GameWebSocketHandler] Ошибка при отправке пакета (" + we.getMessage() + "). Дисконнектинг игрока."); return false; } } } catch (Exception e) { System.out.println("[GameWebSocketHandler] Ошибка при получении RemoteEndpoint (" + e.getMessage() + "). Дисконнектинг игрока."); return false; } } public void disconnect(int closeReason, String description) { session.close(closeReason, description); } public UserProfile getUserProfile() { return userProfile; } public Room getRoom() { return room; } public void setRoom(Room room) { this.room = room; } public interface WebSocketMessageListener { void onNewConnection(GameWebSocketHandler handler); void onDisconnect(GameWebSocketHandler handler); void onUserReady(GameWebSocketHandler handler, boolean isReady); void onControl(GameWebSocketHandler handler, boolean isLeft, boolean isUp); void onConnectToRoom(GameWebSocketHandler handler, String room); void onGetRooms(GameWebSocketHandler handler); } }