mirror of
https://github.com/tiennm99/caro.git
synced 2026-09-05 12:16:43 +00:00
feat(server): rewrite event handlers for Gomoku game flow
- Create ServerEventListener_CODE_GAME_MOVE with move validation, win detection, and inline AI response for PVE - Rewrite GAME_STARTING for 2-player Gomoku (black/white assignment) - Rewrite ROOM_JOIN to auto-start at 2 players - Rewrite ROOM_CREATE_PVE for single AI opponent - Simplify RoomClearTask (remove robot substitution logic) - Fix ClientRole.PLAYER references in handlers - Replace Chinese comments with English
This commit is contained in:
+9
-16
@@ -4,7 +4,6 @@ import org.nico.ratel.landlords.channel.ChannelUtils;
|
||||
import org.nico.ratel.landlords.entity.ClientSide;
|
||||
import org.nico.ratel.landlords.entity.Room;
|
||||
import org.nico.ratel.landlords.enums.ClientEventCode;
|
||||
import org.nico.ratel.landlords.enums.ClientRole;
|
||||
import org.nico.ratel.landlords.helper.MapHelper;
|
||||
import org.nico.ratel.landlords.server.ServerContains;
|
||||
|
||||
@@ -14,37 +13,31 @@ public class ServerEventListener_CODE_CLIENT_EXIT implements ServerEventListener
|
||||
|
||||
@Override
|
||||
public void call(ClientSide clientSide, String data) {
|
||||
synchronized (locked){
|
||||
synchronized (locked) {
|
||||
Room room = ServerContains.getRoom(clientSide.getRoomId());
|
||||
if (room == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
String result = MapHelper.newInstance()
|
||||
.put("roomId", room.getId())
|
||||
.put("exitClientId", clientSide.getId())
|
||||
.put("exitClientNickname", clientSide.getNickname())
|
||||
.json();
|
||||
|
||||
for (ClientSide client : room.getClientSideList()) {
|
||||
if (client.getRole() == ClientRole.PLAYER) {
|
||||
if (client.getChannel() != null) {
|
||||
ChannelUtils.pushToClient(client.getChannel(), ClientEventCode.CODE_CLIENT_EXIT, result);
|
||||
client.init();
|
||||
}
|
||||
}
|
||||
|
||||
notifyWatcherClientExit(room, clientSide);
|
||||
// Notify spectators
|
||||
for (ClientSide watcher : room.getWatcherList()) {
|
||||
ChannelUtils.pushToClient(watcher.getChannel(), ClientEventCode.CODE_CLIENT_EXIT, clientSide.getNickname());
|
||||
}
|
||||
|
||||
ServerContains.removeRoom(room.getId());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 通知所有观战者玩家退出游戏
|
||||
*
|
||||
* @param room 房间
|
||||
* @param player 退出游戏玩家
|
||||
*/
|
||||
private void notifyWatcherClientExit(Room room, ClientSide player) {
|
||||
for (ClientSide watcher : room.getWatcherList()) {
|
||||
ChannelUtils.pushToClient(watcher.getChannel(), ClientEventCode.CODE_CLIENT_EXIT, player.getNickname());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+4
-6
@@ -4,7 +4,6 @@ import org.nico.ratel.landlords.channel.ChannelUtils;
|
||||
import org.nico.ratel.landlords.entity.ClientSide;
|
||||
import org.nico.ratel.landlords.entity.Room;
|
||||
import org.nico.ratel.landlords.enums.ClientEventCode;
|
||||
import org.nico.ratel.landlords.enums.ClientRole;
|
||||
import org.nico.ratel.landlords.helper.MapHelper;
|
||||
import org.nico.ratel.landlords.server.ServerContains;
|
||||
|
||||
@@ -12,7 +11,6 @@ public class ServerEventListener_CODE_CLIENT_OFFLINE implements ServerEventListe
|
||||
|
||||
@Override
|
||||
public void call(ClientSide clientSide, String data) {
|
||||
|
||||
Room room = ServerContains.getRoom(clientSide.getRoomId());
|
||||
|
||||
if (room == null) {
|
||||
@@ -21,6 +19,7 @@ public class ServerEventListener_CODE_CLIENT_OFFLINE implements ServerEventListe
|
||||
}
|
||||
|
||||
if (room.getWatcherList().contains(clientSide)) {
|
||||
room.getWatcherList().remove(clientSide);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -29,15 +28,14 @@ public class ServerEventListener_CODE_CLIENT_OFFLINE implements ServerEventListe
|
||||
.put("exitClientId", clientSide.getId())
|
||||
.put("exitClientNickname", clientSide.getNickname())
|
||||
.json();
|
||||
|
||||
for (ClientSide client : room.getClientSideList()) {
|
||||
if (client.getRole() != ClientRole.PLAYER) {
|
||||
continue;
|
||||
}
|
||||
if (client.getId() != clientSide.getId()) {
|
||||
if (client.getChannel() != null && client.getId() != clientSide.getId()) {
|
||||
ChannelUtils.pushToClient(client.getChannel(), ClientEventCode.CODE_CLIENT_EXIT, result);
|
||||
client.init();
|
||||
}
|
||||
}
|
||||
|
||||
ServerContains.removeRoom(room.getId());
|
||||
}
|
||||
}
|
||||
|
||||
+143
@@ -0,0 +1,143 @@
|
||||
package org.nico.ratel.landlords.server.event;
|
||||
|
||||
import org.nico.ratel.landlords.channel.ChannelUtils;
|
||||
import org.nico.ratel.landlords.entity.ClientSide;
|
||||
import org.nico.ratel.landlords.entity.Board;
|
||||
import org.nico.ratel.landlords.entity.GameMove;
|
||||
import org.nico.ratel.landlords.entity.Room;
|
||||
import org.nico.ratel.landlords.enums.ClientEventCode;
|
||||
import org.nico.ratel.landlords.enums.GameResult;
|
||||
import org.nico.ratel.landlords.enums.PieceType;
|
||||
import org.nico.ratel.landlords.enums.RoomType;
|
||||
import org.nico.ratel.landlords.helper.GomokuHelper;
|
||||
import org.nico.ratel.landlords.helper.MapHelper;
|
||||
import org.nico.ratel.landlords.robot.GomokuAI;
|
||||
import org.nico.ratel.landlords.server.ServerContains;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
public class ServerEventListener_CODE_GAME_MOVE implements ServerEventListener {
|
||||
|
||||
@Override
|
||||
public void call(ClientSide clientSide, String data) {
|
||||
Room room = ServerContains.getRoom(clientSide.getRoomId());
|
||||
if (room == null) {
|
||||
ChannelUtils.pushToClient(clientSide.getChannel(), ClientEventCode.CODE_ROOM_PLAY_FAIL_BY_INEXIST, null);
|
||||
return;
|
||||
}
|
||||
|
||||
Map<String, Object> map = MapHelper.parser(data);
|
||||
int row = (int) map.get("row");
|
||||
int col = (int) map.get("col");
|
||||
|
||||
// Check turn
|
||||
if (!room.isPlayerTurn(clientSide.getId())) {
|
||||
ChannelUtils.pushToClient(clientSide.getChannel(), ClientEventCode.CODE_GAME_MOVE_NOT_YOUR_TURN, null);
|
||||
return;
|
||||
}
|
||||
|
||||
Board board = room.getGameBoard();
|
||||
|
||||
// Check bounds
|
||||
if (row < 0 || row >= Board.BOARD_SIZE || col < 0 || col >= Board.BOARD_SIZE) {
|
||||
ChannelUtils.pushToClient(clientSide.getChannel(), ClientEventCode.CODE_GAME_MOVE_OUT_OF_BOUNDS, null);
|
||||
return;
|
||||
}
|
||||
|
||||
// Check occupied
|
||||
if (board.getPiece(row, col) != PieceType.EMPTY) {
|
||||
ChannelUtils.pushToClient(clientSide.getChannel(), ClientEventCode.CODE_GAME_MOVE_OCCUPIED, null);
|
||||
return;
|
||||
}
|
||||
|
||||
// Make the move
|
||||
GameResult result = GomokuHelper.makeMove(room, row, col, clientSide.getId());
|
||||
|
||||
// Broadcast move to all players and spectators
|
||||
String moveResult = MapHelper.newInstance()
|
||||
.put("row", row)
|
||||
.put("col", col)
|
||||
.put("piece", room.getPlayerPiece(clientSide.getId()).name())
|
||||
.put("playerNickname", clientSide.getNickname())
|
||||
.put("playerId", clientSide.getId())
|
||||
.json();
|
||||
broadcastToRoom(room, ClientEventCode.CODE_GAME_MOVE_SUCCESS, moveResult);
|
||||
|
||||
// Check game over
|
||||
if (result != GameResult.IN_PROGRESS) {
|
||||
handleGameOver(room, result);
|
||||
return;
|
||||
}
|
||||
|
||||
// PVE: trigger AI move if next turn is AI
|
||||
if (room.getType() == RoomType.PVE) {
|
||||
handleAIMove(room);
|
||||
}
|
||||
}
|
||||
|
||||
private void handleAIMove(Room room) {
|
||||
// Find AI player (the one with null channel)
|
||||
ClientSide aiPlayer = null;
|
||||
for (ClientSide client : room.getClientSideList()) {
|
||||
if (client.getChannel() == null) {
|
||||
aiPlayer = client;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (aiPlayer == null || !room.isPlayerTurn(aiPlayer.getId())) {
|
||||
return;
|
||||
}
|
||||
|
||||
PieceType aiPiece = room.getPlayerPiece(aiPlayer.getId());
|
||||
GomokuAI ai = new GomokuAI(aiPiece);
|
||||
GameMove aiMove = ai.getNextMove(room.getGameBoard(), room.getDifficultyCoefficient());
|
||||
if (aiMove == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
GameResult result = GomokuHelper.makeMove(room, aiMove.getRow(), aiMove.getCol(), aiPlayer.getId());
|
||||
|
||||
String moveResult = MapHelper.newInstance()
|
||||
.put("row", aiMove.getRow())
|
||||
.put("col", aiMove.getCol())
|
||||
.put("piece", aiPiece.name())
|
||||
.put("playerNickname", aiPlayer.getNickname())
|
||||
.put("playerId", aiPlayer.getId())
|
||||
.json();
|
||||
broadcastToRoom(room, ClientEventCode.CODE_GAME_MOVE_SUCCESS, moveResult);
|
||||
|
||||
if (result != GameResult.IN_PROGRESS) {
|
||||
handleGameOver(room, result);
|
||||
}
|
||||
}
|
||||
|
||||
private void handleGameOver(Room room, GameResult result) {
|
||||
String winnerNickname = "";
|
||||
if (result == GameResult.BLACK_WIN) {
|
||||
ClientSide winner = room.getClientSideMap().get(room.getBlackPlayerId());
|
||||
winnerNickname = winner != null ? winner.getNickname() : "Black";
|
||||
} else if (result == GameResult.WHITE_WIN) {
|
||||
ClientSide winner = room.getClientSideMap().get(room.getWhitePlayerId());
|
||||
winnerNickname = winner != null ? winner.getNickname() : "White";
|
||||
}
|
||||
|
||||
String gameOverData = MapHelper.newInstance()
|
||||
.put("result", result.name())
|
||||
.put("winnerNickname", winnerNickname)
|
||||
.put("board", GomokuHelper.formatBoardForDisplay(room.getGameBoard()))
|
||||
.json();
|
||||
broadcastToRoom(room, ClientEventCode.CODE_GAME_OVER, gameOverData);
|
||||
}
|
||||
|
||||
private void broadcastToRoom(Room room, ClientEventCode code, String data) {
|
||||
for (ClientSide client : room.getClientSideList()) {
|
||||
if (client.getChannel() != null) {
|
||||
ChannelUtils.pushToClient(client.getChannel(), code, data);
|
||||
}
|
||||
}
|
||||
for (ClientSide watcher : room.getWatcherList()) {
|
||||
ChannelUtils.pushToClient(watcher.getChannel(), code, data);
|
||||
}
|
||||
}
|
||||
}
|
||||
+18
-22
@@ -3,49 +3,45 @@ package org.nico.ratel.landlords.server.event;
|
||||
import org.nico.ratel.landlords.channel.ChannelUtils;
|
||||
import org.nico.ratel.landlords.entity.ClientSide;
|
||||
import org.nico.ratel.landlords.entity.Room;
|
||||
import org.nico.ratel.landlords.enums.*;
|
||||
import org.nico.ratel.landlords.enums.ClientEventCode;
|
||||
import org.nico.ratel.landlords.enums.ClientStatus;
|
||||
import org.nico.ratel.landlords.enums.RoomStatus;
|
||||
import org.nico.ratel.landlords.enums.ServerEventCode;
|
||||
import org.nico.ratel.landlords.helper.MapHelper;
|
||||
import org.nico.ratel.landlords.print.SimplePrinter;
|
||||
import org.nico.ratel.landlords.server.ServerContains;
|
||||
|
||||
import java.util.concurrent.ConcurrentSkipListMap;
|
||||
|
||||
public class ServerEventListener_CODE_GAME_READY implements ServerEventListener {
|
||||
|
||||
@Override
|
||||
public void call(ClientSide clientSide, String data) {
|
||||
Room room = ServerContains.getRoom(clientSide.getRoomId());
|
||||
if (room == null) {
|
||||
if (room == null || room.getStatus() == RoomStatus.STARTING) {
|
||||
return;
|
||||
}
|
||||
SimplePrinter.serverLog("房间状态:" + room.getStatus());
|
||||
SimplePrinter.serverLog("玩家状态:" + clientSide.getStatus());
|
||||
if (room.getStatus() == RoomStatus.STARTING) {
|
||||
return;
|
||||
}
|
||||
if (clientSide.getStatus() == ClientStatus.PLAYING || clientSide.getStatus() == ClientStatus.TO_CHOOSE || clientSide.getStatus() == ClientStatus.CALL_LANDLORD) {
|
||||
if (clientSide.getStatus() == ClientStatus.PLAYING) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Toggle ready state
|
||||
clientSide.setStatus(clientSide.getStatus() == ClientStatus.READY ? ClientStatus.NO_READY : ClientStatus.READY);
|
||||
|
||||
String result = MapHelper.newInstance()
|
||||
.put("clientNickName", clientSide.getNickname())
|
||||
.put("status", clientSide.getStatus())
|
||||
.put("clientId", clientSide.getId())
|
||||
.json();
|
||||
boolean allReady = true;
|
||||
ConcurrentSkipListMap<Integer, ClientSide> roomClientMap = (ConcurrentSkipListMap<Integer, ClientSide>) room.getClientSideMap();
|
||||
if (roomClientMap.size() < 3) {
|
||||
allReady = false;
|
||||
} else {
|
||||
for (ClientSide client : room.getClientSideList()) {
|
||||
if (client.getRole() == ClientRole.PLAYER && client.getStatus() != ClientStatus.READY) {
|
||||
allReady = false;
|
||||
break;
|
||||
}
|
||||
|
||||
// Check if all human players are ready (need 2 players)
|
||||
boolean allReady = room.getClientSideMap().size() >= 2;
|
||||
for (ClientSide client : room.getClientSideList()) {
|
||||
if (client.getChannel() != null && client.getStatus() != ClientStatus.READY) {
|
||||
allReady = false;
|
||||
}
|
||||
}
|
||||
|
||||
// Notify all human players
|
||||
for (ClientSide client : room.getClientSideList()) {
|
||||
if (client.getRole() == ClientRole.PLAYER) {
|
||||
if (client.getChannel() != null) {
|
||||
ChannelUtils.pushToClient(client.getChannel(), ClientEventCode.CODE_GAME_READY, result);
|
||||
}
|
||||
}
|
||||
|
||||
+39
-72
@@ -1,101 +1,68 @@
|
||||
package org.nico.ratel.landlords.server.event;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
|
||||
import org.nico.ratel.landlords.channel.ChannelUtils;
|
||||
import org.nico.ratel.landlords.entity.ClientSide;
|
||||
import org.nico.ratel.landlords.entity.Poker;
|
||||
import org.nico.ratel.landlords.entity.Room;
|
||||
import org.nico.ratel.landlords.enums.*;
|
||||
import org.nico.ratel.landlords.enums.ClientEventCode;
|
||||
import org.nico.ratel.landlords.enums.ClientRole;
|
||||
import org.nico.ratel.landlords.enums.ClientStatus;
|
||||
import org.nico.ratel.landlords.enums.PieceType;
|
||||
import org.nico.ratel.landlords.enums.RoomStatus;
|
||||
import org.nico.ratel.landlords.helper.MapHelper;
|
||||
import org.nico.ratel.landlords.helper.PokerHelper;
|
||||
import org.nico.ratel.landlords.server.ServerContains;
|
||||
import org.nico.ratel.landlords.server.robot.RobotEventListener;
|
||||
import org.nico.ratel.landlords.utils.JsonUtils;
|
||||
import org.nico.ratel.landlords.utils.LastCardsUtils;
|
||||
|
||||
public class ServerEventListener_CODE_GAME_STARTING implements ServerEventListener {
|
||||
|
||||
@Override
|
||||
public void call(ClientSide clientSide, String data) {
|
||||
|
||||
Room room = ServerContains.getRoom(clientSide.getRoomId());
|
||||
if (room == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
LinkedList<ClientSide> roomClientList = room.getClientSideList();
|
||||
|
||||
// Send the points of poker
|
||||
List<List<Poker>> pokersList = PokerHelper.distributePoker();
|
||||
int cursor = 0;
|
||||
for (ClientSide client : roomClientList) {
|
||||
client.setPokers(pokersList.get(cursor++));
|
||||
if (roomClientList.size() < 2) {
|
||||
return;
|
||||
}
|
||||
room.setLandlordPokers(pokersList.get(3));
|
||||
|
||||
// Push information about the robber
|
||||
int startGrabIndex = (int) (Math.random() * 3);
|
||||
ClientSide startGrabClient = roomClientList.get(startGrabIndex);
|
||||
room.setCurrentSellClient(startGrabClient.getId());
|
||||
// Assign players: first = BLACK, second = WHITE
|
||||
ClientSide blackPlayer = roomClientList.get(0);
|
||||
ClientSide whitePlayer = roomClientList.get(1);
|
||||
|
||||
// Push start game messages
|
||||
blackPlayer.setRole(ClientRole.BLACK_PLAYER);
|
||||
whitePlayer.setRole(ClientRole.WHITE_PLAYER);
|
||||
blackPlayer.setStatus(ClientStatus.PLAYING);
|
||||
whitePlayer.setStatus(ClientStatus.PLAYING);
|
||||
|
||||
room.setBlackPlayerId(blackPlayer.getId());
|
||||
room.setWhitePlayerId(whitePlayer.getId());
|
||||
room.setCurrentTurn(PieceType.BLACK);
|
||||
room.setStatus(RoomStatus.STARTING);
|
||||
room.setCreateTime(System.currentTimeMillis());
|
||||
room.setLastFlushTime(System.currentTimeMillis());
|
||||
room.resetGame();
|
||||
|
||||
// Record the first speaker
|
||||
room.setFirstSellClient(startGrabClient.getId());
|
||||
List<List<Poker>> otherPokers = new ArrayList<>();
|
||||
for (ClientSide client : roomClientList) {
|
||||
client.setType(ClientType.PEASANT);
|
||||
client.setStatus(ClientStatus.PLAYING);
|
||||
for(ClientSide otherClient : roomClientList){
|
||||
if(otherClient.getId() != client.getId()){
|
||||
otherPokers.add(otherClient.getPokers());
|
||||
}
|
||||
}
|
||||
otherPokers.add(room.getLandlordPokers());
|
||||
String lastCards = LastCardsUtils.getLastCards(otherPokers);
|
||||
otherPokers = new ArrayList<>();
|
||||
String result = MapHelper.newInstance()
|
||||
.put("roomId", room.getId())
|
||||
.put("roomOwner", room.getRoomOwner())
|
||||
.put("roomClientCount", room.getClientSideList().size())
|
||||
.put("nextClientNickname", startGrabClient.getNickname())
|
||||
.put("nextClientId", startGrabClient.getId())
|
||||
.put("pokers", client.getPokers())
|
||||
.put("lastPokers",lastCards)
|
||||
.put("highestScore", 0)
|
||||
.json();
|
||||
|
||||
if (client.getRole() == ClientRole.PLAYER) {
|
||||
ChannelUtils.pushToClient(client.getChannel(), ClientEventCode.CODE_GAME_STARTING, result);
|
||||
} else {
|
||||
if (startGrabClient.getId() == client.getId()) {
|
||||
RobotEventListener.get(ClientEventCode.CODE_GAME_LANDLORD_ELECT).call(client, result);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
notifyWatcherGameStart(room);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 通知房间内的观战人员游戏开始
|
||||
*
|
||||
* @param room 房间
|
||||
*/
|
||||
private void notifyWatcherGameStart(Room room) {
|
||||
String result = MapHelper.newInstance()
|
||||
.put("player1", room.getClientSideList().getFirst().getNickname())
|
||||
.put("player2", room.getClientSideList().getFirst().getNext().getNickname())
|
||||
.put("player3", room.getClientSideList().getLast().getNickname())
|
||||
.put("roomId", room.getId())
|
||||
.put("blackPlayerId", blackPlayer.getId())
|
||||
.put("blackPlayerNickname", blackPlayer.getNickname())
|
||||
.put("whitePlayerId", whitePlayer.getId())
|
||||
.put("whitePlayerNickname", whitePlayer.getNickname())
|
||||
.put("boardSize", 15)
|
||||
.json();
|
||||
for (ClientSide clientSide : room.getWatcherList()) {
|
||||
ChannelUtils.pushToClient(clientSide.getChannel(), ClientEventCode.CODE_GAME_STARTING, result);
|
||||
|
||||
// Notify human players
|
||||
for (ClientSide client : roomClientList) {
|
||||
if (client.getChannel() != null) {
|
||||
ChannelUtils.pushToClient(client.getChannel(), ClientEventCode.CODE_GAME_STARTING, result);
|
||||
}
|
||||
}
|
||||
|
||||
// Notify spectators
|
||||
for (ClientSide watcher : room.getWatcherList()) {
|
||||
ChannelUtils.pushToClient(watcher.getChannel(), ClientEventCode.CODE_GAME_STARTING, result);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+1
-1
@@ -24,7 +24,7 @@ public class ServerEventListener_CODE_GAME_WATCH implements ServerEventListener
|
||||
|
||||
ChannelUtils.pushToClient(clientSide.getChannel(), ClientEventCode.CODE_ROOM_JOIN_FAIL_BY_INEXIST, result);
|
||||
} else {
|
||||
// 将用户加入到房间中的观战者列表中
|
||||
// Add user to the room's spectator list
|
||||
clientSide.setRoomId(room.getId());
|
||||
room.getWatcherList().add(clientSide);
|
||||
|
||||
|
||||
+1
-1
@@ -12,7 +12,7 @@ public class ServerEventListener_CODE_GAME_WATCH_EXIT implements ServerEventList
|
||||
Room room = ServerContains.getRoom(clientSide.getRoomId());
|
||||
|
||||
if (room != null) {
|
||||
// 房间如果存在,则将观战者从房间观战列表中移除
|
||||
// Remove spectator from room's watcher list if room exists
|
||||
clientSide.setRoomId(room.getId());
|
||||
boolean successful = room.getWatcherList().remove(clientSide);
|
||||
if (successful) {
|
||||
|
||||
+4
-4
@@ -5,6 +5,7 @@ import org.nico.ratel.landlords.channel.ChannelUtils;
|
||||
import org.nico.ratel.landlords.entity.ClientSide;
|
||||
import org.nico.ratel.landlords.entity.Room;
|
||||
import org.nico.ratel.landlords.enums.ClientEventCode;
|
||||
import org.nico.ratel.landlords.enums.ClientRole;
|
||||
import org.nico.ratel.landlords.enums.ClientStatus;
|
||||
import org.nico.ratel.landlords.enums.RoomStatus;
|
||||
import org.nico.ratel.landlords.enums.RoomType;
|
||||
@@ -14,22 +15,21 @@ public class ServerEventListener_CODE_ROOM_CREATE implements ServerEventListener
|
||||
|
||||
@Override
|
||||
public void call(ClientSide clientSide, String data) {
|
||||
|
||||
Room room = new Room(ServerContains.getServerId());
|
||||
room.setStatus(RoomStatus.WAIT);
|
||||
room.setType(RoomType.PVP);
|
||||
room.setRoomOwner(clientSide.getNickname());
|
||||
room.getClientSideMap().put(clientSide.getId(), clientSide);
|
||||
room.getClientSideList().add(clientSide);
|
||||
room.setCurrentSellClient(clientSide.getId());
|
||||
room.setCreateTime(System.currentTimeMillis());
|
||||
room.setLastFlushTime(System.currentTimeMillis());
|
||||
|
||||
clientSide.setRoomId(room.getId());
|
||||
ServerContains.addRoom(room);
|
||||
|
||||
clientSide.setRole(ClientRole.BLACK_PLAYER);
|
||||
clientSide.setStatus(ClientStatus.NO_READY);
|
||||
|
||||
ServerContains.addRoom(room);
|
||||
|
||||
ChannelUtils.pushToClient(clientSide.getChannel(), ClientEventCode.CODE_ROOM_CREATE_SUCCESS, Noson.reversal(room));
|
||||
}
|
||||
}
|
||||
|
||||
+34
-29
@@ -3,54 +3,59 @@ package org.nico.ratel.landlords.server.event;
|
||||
import org.nico.ratel.landlords.channel.ChannelUtils;
|
||||
import org.nico.ratel.landlords.entity.ClientSide;
|
||||
import org.nico.ratel.landlords.entity.Room;
|
||||
import org.nico.ratel.landlords.enums.*;
|
||||
import org.nico.ratel.landlords.robot.RobotDecisionMakers;
|
||||
import org.nico.ratel.landlords.enums.ClientEventCode;
|
||||
import org.nico.ratel.landlords.enums.ClientRole;
|
||||
import org.nico.ratel.landlords.enums.ClientStatus;
|
||||
import org.nico.ratel.landlords.enums.RoomStatus;
|
||||
import org.nico.ratel.landlords.enums.RoomType;
|
||||
import org.nico.ratel.landlords.enums.ServerEventCode;
|
||||
import org.nico.ratel.landlords.server.ServerContains;
|
||||
|
||||
public class ServerEventListener_CODE_ROOM_CREATE_PVE implements ServerEventListener {
|
||||
|
||||
@Override
|
||||
public void call(ClientSide clientSide, String data) {
|
||||
|
||||
int difficultyCoefficient = Integer.parseInt(data);
|
||||
if (!RobotDecisionMakers.contains(difficultyCoefficient)) {
|
||||
int difficulty = Integer.parseInt(data);
|
||||
if (difficulty < 1 || difficulty > 3) {
|
||||
ChannelUtils.pushToClient(clientSide.getChannel(), ClientEventCode.CODE_PVE_DIFFICULTY_NOT_SUPPORT, null);
|
||||
return;
|
||||
}
|
||||
|
||||
Room room = new Room(ServerContains.getServerId());
|
||||
room.setType(RoomType.PVE);
|
||||
room.setStatus(RoomStatus.BLANK);
|
||||
room.setStatus(RoomStatus.WAIT);
|
||||
room.setRoomOwner(clientSide.getNickname());
|
||||
room.setDifficultyCoefficient(difficulty);
|
||||
room.setCreateTime(System.currentTimeMillis());
|
||||
room.setLastFlushTime(System.currentTimeMillis());
|
||||
|
||||
// Add human player
|
||||
room.getClientSideMap().put(clientSide.getId(), clientSide);
|
||||
room.getClientSideList().add(clientSide);
|
||||
room.setCurrentSellClient(clientSide.getId());
|
||||
room.setCreateTime(System.currentTimeMillis());
|
||||
room.setDifficultyCoefficient(difficultyCoefficient);
|
||||
|
||||
clientSide.setRoomId(room.getId());
|
||||
clientSide.setRole(ClientRole.BLACK_PLAYER);
|
||||
|
||||
// Add AI robot (1 robot for 2-player Gomoku)
|
||||
ClientSide robot = new ClientSide(-ServerContains.getClientId(), ClientStatus.PLAYING, null);
|
||||
robot.setNickname("AI_" + getDifficultyName(difficulty));
|
||||
robot.setRole(ClientRole.WHITE_PLAYER);
|
||||
robot.setRoomId(room.getId());
|
||||
room.getClientSideMap().put(robot.getId(), robot);
|
||||
room.getClientSideList().add(robot);
|
||||
ServerContains.CLIENT_SIDE_MAP.put(robot.getId(), robot);
|
||||
|
||||
ServerContains.addRoom(room);
|
||||
|
||||
ClientSide preClient = clientSide;
|
||||
//Add robots
|
||||
for (int index = 1; index < 3; index++) {
|
||||
ClientSide robot = new ClientSide(-ServerContains.getClientId(), ClientStatus.PLAYING, null);
|
||||
robot.setNickname("robot_" + index);
|
||||
robot.setRole(ClientRole.ROBOT);
|
||||
preClient.setNext(robot);
|
||||
robot.setPre(preClient);
|
||||
robot.setRoomId(room.getId());
|
||||
room.getClientSideMap().put(robot.getId(), robot);
|
||||
room.getClientSideList().add(robot);
|
||||
|
||||
preClient = robot;
|
||||
ServerContains.CLIENT_SIDE_MAP.put(robot.getId(), robot);
|
||||
}
|
||||
preClient.setNext(clientSide);
|
||||
clientSide.setPre(preClient);
|
||||
|
||||
// Auto-start game
|
||||
ServerEventListener.get(ServerEventCode.CODE_GAME_STARTING).call(clientSide, String.valueOf(room.getId()));
|
||||
}
|
||||
|
||||
|
||||
private String getDifficultyName(int difficulty) {
|
||||
switch (difficulty) {
|
||||
case 1: return "Easy";
|
||||
case 2: return "Medium";
|
||||
case 3: return "Hard";
|
||||
default: return "Easy";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+15
-30
@@ -1,7 +1,6 @@
|
||||
package org.nico.ratel.landlords.server.event;
|
||||
|
||||
import java.util.LinkedList;
|
||||
import java.util.concurrent.ConcurrentSkipListMap;
|
||||
|
||||
import org.nico.ratel.landlords.channel.ChannelUtils;
|
||||
import org.nico.ratel.landlords.entity.ClientSide;
|
||||
@@ -17,7 +16,6 @@ public class ServerEventListener_CODE_ROOM_JOIN implements ServerEventListener {
|
||||
|
||||
@Override
|
||||
public void call(ClientSide clientSide, String data) {
|
||||
|
||||
Room room = ServerContains.getRoom(Integer.parseInt(data));
|
||||
|
||||
if (room == null) {
|
||||
@@ -27,7 +25,9 @@ public class ServerEventListener_CODE_ROOM_JOIN implements ServerEventListener {
|
||||
ChannelUtils.pushToClient(clientSide.getChannel(), ClientEventCode.CODE_ROOM_JOIN_FAIL_BY_INEXIST, result);
|
||||
return;
|
||||
}
|
||||
if (room.getClientSideList().size() == 3) {
|
||||
|
||||
// Gomoku is 2-player
|
||||
if (room.getClientSideList().size() >= 2) {
|
||||
String result = MapHelper.newInstance()
|
||||
.put("roomId", room.getId())
|
||||
.put("roomOwner", room.getRoomOwner())
|
||||
@@ -35,51 +35,36 @@ public class ServerEventListener_CODE_ROOM_JOIN implements ServerEventListener {
|
||||
ChannelUtils.pushToClient(clientSide.getChannel(), ClientEventCode.CODE_ROOM_JOIN_FAIL_BY_FULL, result);
|
||||
return;
|
||||
}
|
||||
// join default ready
|
||||
|
||||
clientSide.setStatus(ClientStatus.READY);
|
||||
clientSide.setRoomId(room.getId());
|
||||
|
||||
ConcurrentSkipListMap<Integer, ClientSide> roomClientMap = (ConcurrentSkipListMap<Integer, ClientSide>) room.getClientSideMap();
|
||||
LinkedList<ClientSide> roomClientList = room.getClientSideList();
|
||||
|
||||
if (roomClientList.size() > 0) {
|
||||
ClientSide pre = roomClientList.getLast();
|
||||
pre.setNext(clientSide);
|
||||
clientSide.setPre(pre);
|
||||
}
|
||||
|
||||
roomClientList.add(clientSide);
|
||||
roomClientMap.put(clientSide.getId(), clientSide);
|
||||
room.getClientSideMap().put(clientSide.getId(), clientSide);
|
||||
room.setStatus(RoomStatus.WAIT);
|
||||
|
||||
String result = MapHelper.newInstance()
|
||||
.put("clientId", clientSide.getId())
|
||||
.put("clientNickname", clientSide.getNickname())
|
||||
.put("roomId", room.getId())
|
||||
.put("roomOwner", room.getRoomOwner())
|
||||
.put("roomClientCount", room.getClientSideList().size())
|
||||
.put("roomClientCount", roomClientList.size())
|
||||
.json();
|
||||
for (ClientSide client : roomClientMap.values()) {
|
||||
ChannelUtils.pushToClient(client.getChannel(), ClientEventCode.CODE_ROOM_JOIN_SUCCESS, result);
|
||||
|
||||
for (ClientSide client : room.getClientSideMap().values()) {
|
||||
if (client.getChannel() != null) {
|
||||
ChannelUtils.pushToClient(client.getChannel(), ClientEventCode.CODE_ROOM_JOIN_SUCCESS, result);
|
||||
}
|
||||
}
|
||||
|
||||
if (roomClientMap.size() == 3) {
|
||||
clientSide.setNext(roomClientList.getFirst());
|
||||
roomClientList.getFirst().setPre(clientSide);
|
||||
|
||||
// Auto-start when 2 players joined
|
||||
if (roomClientList.size() == 2) {
|
||||
ServerEventListener.get(ServerEventCode.CODE_GAME_STARTING).call(clientSide, String.valueOf(room.getId()));
|
||||
return;
|
||||
}
|
||||
|
||||
notifyWatcherJoinRoom(room, clientSide);
|
||||
}
|
||||
|
||||
/**
|
||||
* 通知观战者玩家加入房间
|
||||
*
|
||||
* @param room 房间
|
||||
* @param clientSide 玩家
|
||||
*/
|
||||
private void notifyWatcherJoinRoom(Room room, ClientSide clientSide) {
|
||||
// Notify spectators
|
||||
for (ClientSide watcher : room.getWatcherList()) {
|
||||
ChannelUtils.pushToClient(watcher.getChannel(), ClientEventCode.CODE_ROOM_JOIN_SUCCESS, clientSide.getNickname());
|
||||
}
|
||||
|
||||
+1
-1
@@ -34,7 +34,7 @@ public class ProtobufTransferHandler extends ChannelInboundHandlerAdapter {
|
||||
//init client info
|
||||
ClientSide clientSide = new ClientSide(getId(ctx.channel()), ClientStatus.TO_CHOOSE, ch);
|
||||
clientSide.setNickname(String.valueOf(clientSide.getId()));
|
||||
clientSide.setRole(ClientRole.PLAYER);
|
||||
clientSide.setRole(ClientRole.BLACK_PLAYER);
|
||||
|
||||
ServerContains.CLIENT_SIDE_MAP.put(clientSide.getId(), clientSide);
|
||||
SimplePrinter.serverLog("Has client connect to the server: " + clientSide.getId());
|
||||
|
||||
+1
-1
@@ -62,7 +62,7 @@ public class WebsocketTransferHandler extends SimpleChannelInboundHandler<TextWe
|
||||
// init client info
|
||||
ClientSide clientSide = new ClientSide(getId(ctx.channel()), ClientStatus.TO_CHOOSE, ch);
|
||||
clientSide.setNickname(String.valueOf(clientSide.getId()));
|
||||
clientSide.setRole(ClientRole.PLAYER);
|
||||
clientSide.setRole(ClientRole.BLACK_PLAYER);
|
||||
|
||||
ServerContains.CLIENT_SIDE_MAP.put(clientSide.getId(), clientSide);
|
||||
SimplePrinter.serverLog("Has client connect to the server:" + clientSide.getId());
|
||||
|
||||
+18
-98
@@ -3,34 +3,23 @@ package org.nico.ratel.landlords.server.timer;
|
||||
import java.util.Map;
|
||||
import java.util.TimerTask;
|
||||
|
||||
import org.nico.ratel.landlords.channel.ChannelUtils;
|
||||
import org.nico.ratel.landlords.entity.ClientSide;
|
||||
import org.nico.ratel.landlords.entity.Room;
|
||||
import org.nico.ratel.landlords.enums.ClientEventCode;
|
||||
import org.nico.ratel.landlords.enums.ClientRole;
|
||||
import org.nico.ratel.landlords.enums.ClientStatus;
|
||||
import org.nico.ratel.landlords.enums.RoomStatus;
|
||||
import org.nico.ratel.landlords.enums.RoomType;
|
||||
import org.nico.ratel.landlords.enums.ServerEventCode;
|
||||
import org.nico.ratel.landlords.print.SimplePrinter;
|
||||
import org.nico.ratel.landlords.server.ServerContains;
|
||||
import org.nico.ratel.landlords.server.event.ServerEventListener;
|
||||
import org.nico.ratel.landlords.server.robot.RobotEventListener;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author nico
|
||||
* Periodically cleans up idle or expired rooms.
|
||||
*/
|
||||
|
||||
public class RoomClearTask extends TimerTask {
|
||||
|
||||
//The room wait time of after create is 100s
|
||||
// Room wait time after creation: 100s
|
||||
private static final long waitingStatusInterval = 1000 * 100;
|
||||
|
||||
//The room starting destroy time is 100s
|
||||
private static final long startingStatusInterval = 1000 * 300;
|
||||
|
||||
//The room live time is 600s
|
||||
// Room live time: 20 minutes
|
||||
private static final long liveTime = 1000 * 60 * 20;
|
||||
|
||||
@Override
|
||||
@@ -40,7 +29,6 @@ public class RoomClearTask extends TimerTask {
|
||||
} catch (Exception e) {
|
||||
SimplePrinter.serverLog(e.getMessage());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public void doing() {
|
||||
@@ -51,95 +39,27 @@ public class RoomClearTask extends TimerTask {
|
||||
|
||||
long now = System.currentTimeMillis();
|
||||
for (Room room : rooms.values()) {
|
||||
long alreadyLiveTime = System.currentTimeMillis() - room.getCreateTime();
|
||||
SimplePrinter.serverLog("room " + room.getId() + " already live " + alreadyLiveTime + "ms");
|
||||
if (alreadyLiveTime > liveTime) {
|
||||
SimplePrinter.serverLog("room " + room.getId() + " live time overflow " + liveTime + ", closed!");
|
||||
ServerEventListener.get(ServerEventCode.CODE_CLIENT_EXIT).call(room.getClientSideList().get(0), null);
|
||||
continue;
|
||||
}
|
||||
long alreadyLiveTime = now - room.getCreateTime();
|
||||
if (alreadyLiveTime > liveTime) {
|
||||
SimplePrinter.serverLog("room " + room.getId() + " live time overflow, closed!");
|
||||
closeRoom(room);
|
||||
continue;
|
||||
}
|
||||
|
||||
long diff = now - room.getLastFlushTime();
|
||||
if (room.getStatus() != RoomStatus.STARTING && diff > waitingStatusInterval) {
|
||||
SimplePrinter.serverLog("room " + room.getId() + " starting waiting time overflow " + waitingStatusInterval + ", closed!");
|
||||
ServerEventListener.get(ServerEventCode.CODE_CLIENT_EXIT).call(room.getClientSideList().get(0), null);
|
||||
continue;
|
||||
}
|
||||
if (room.getType() != RoomType.PVP) {
|
||||
continue;
|
||||
if (room.getStatus() != RoomStatus.STARTING && diff > waitingStatusInterval) {
|
||||
SimplePrinter.serverLog("room " + room.getId() + " waiting time overflow, closed!");
|
||||
closeRoom(room);
|
||||
}
|
||||
|
||||
if (diff <= startingStatusInterval) {
|
||||
continue;
|
||||
}
|
||||
|
||||
boolean allRobots = true;
|
||||
for (ClientSide client : room.getClientSideList()) {
|
||||
if (client.getId() != room.getCurrentSellClient() && client.getRole() == ClientRole.PLAYER) {
|
||||
allRobots = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
ClientSide currentPlayer = room.getClientSideMap().get(room.getCurrentSellClient());
|
||||
|
||||
if (allRobots) {
|
||||
SimplePrinter.serverLog("room " + room.getId() + " all is robots, closed!");
|
||||
ServerEventListener.get(ServerEventCode.CODE_CLIENT_EXIT).call(currentPlayer, null);
|
||||
continue;
|
||||
}
|
||||
// Kick this client
|
||||
ChannelUtils.pushToClient(currentPlayer.getChannel(), ClientEventCode.CODE_CLIENT_KICK, null);
|
||||
|
||||
notifyWatcherClientKick(room, currentPlayer);
|
||||
|
||||
// Remove current player
|
||||
room.getClientSideMap().remove(currentPlayer.getId());
|
||||
room.getClientSideList().remove(currentPlayer);
|
||||
|
||||
ClientSide robot = new ClientSide(-ServerContains.getClientId(), ClientStatus.PLAYING, null);
|
||||
robot.setNickname(currentPlayer.getNickname());
|
||||
robot.setRole(ClientRole.ROBOT);
|
||||
robot.setRoomId(room.getId());
|
||||
robot.setNext(currentPlayer.getNext());
|
||||
robot.setPre(currentPlayer.getPre());
|
||||
robot.getNext().setPre(robot);
|
||||
robot.getPre().setNext(robot);
|
||||
robot.setPokers(currentPlayer.getPokers());
|
||||
robot.setType(currentPlayer.getType());
|
||||
|
||||
room.getClientSideMap().put(robot.getId(), robot);
|
||||
room.getClientSideList().add(robot);
|
||||
room.setCurrentSellClient(robot.getId());
|
||||
|
||||
// If last sell client is current client, replace it to robot id
|
||||
if (room.getLastSellClient() == currentPlayer.getId()) {
|
||||
room.setLastSellClient(robot.getId());
|
||||
}
|
||||
|
||||
// Set robot difficulty -> simple
|
||||
room.setDifficultyCoefficient(1);
|
||||
|
||||
ServerContains.CLIENT_SIDE_MAP.put(robot.getId(), robot);
|
||||
|
||||
// Initialize client
|
||||
currentPlayer.init();
|
||||
|
||||
SimplePrinter.serverLog("room " + room.getId() + " player " + currentPlayer.getNickname() + " " + startingStatusInterval + "ms not operating, automatic custody!");
|
||||
|
||||
RobotEventListener.get(room.getLandlordId() == -1 ? ClientEventCode.CODE_GAME_LANDLORD_ELECT : ClientEventCode.CODE_GAME_POKER_PLAY).call(robot, null);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Notify spectators that a player has been kicked from the room
|
||||
*
|
||||
* @param room room
|
||||
* @param player player who was kicked
|
||||
*/
|
||||
private void notifyWatcherClientKick(Room room, ClientSide player) {
|
||||
for (ClientSide watcher : room.getWatcherList()) {
|
||||
ChannelUtils.pushToClient(watcher.getChannel(), ClientEventCode.CODE_CLIENT_KICK, player.getNickname());
|
||||
private void closeRoom(Room room) {
|
||||
if (!room.getClientSideList().isEmpty()) {
|
||||
ClientSide first = room.getClientSideList().get(0);
|
||||
ServerEventListener.get(ServerEventCode.CODE_CLIENT_EXIT).call(first, null);
|
||||
} else {
|
||||
ServerContains.removeRoom(room.getId());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user