feat: 添加房间详情 API
This commit is contained in:
@@ -0,0 +1,53 @@
|
||||
package com.webgame.webgamebackend.common.dto.game;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 房间详情响应
|
||||
*
|
||||
* 包含房间基本信息、玩家信息(含座位号和准备状态)、对局状态。
|
||||
* 用于前端进入房间页时获取初始快照。
|
||||
*/
|
||||
public record RoomDetailResponse(
|
||||
String roomId,
|
||||
String name,
|
||||
String gameId,
|
||||
String gameIcon,
|
||||
String gameName,
|
||||
Integer maxPlayers,
|
||||
String mode,
|
||||
Integer stakes,
|
||||
String status,
|
||||
String creatorId,
|
||||
String creatorName,
|
||||
Boolean allowSpectate,
|
||||
List<RoomPlayerDetail> players,
|
||||
/** 对局中才有棋盘状态 */
|
||||
int[][] boardState,
|
||||
/** 当前轮到哪方落子(黑方/白方的 userId),null 表示对局未开始 */
|
||||
String currentTurn,
|
||||
/** 走棋记录(对局中才有) */
|
||||
List<MoveItem> moves
|
||||
) {
|
||||
|
||||
/**
|
||||
* 带座位号和准备状态的玩家信息
|
||||
*/
|
||||
public record RoomPlayerDetail(
|
||||
String userId,
|
||||
String avatar,
|
||||
String nickname,
|
||||
int seatNumber,
|
||||
boolean ready
|
||||
) {}
|
||||
|
||||
/**
|
||||
* 走棋记录项
|
||||
*/
|
||||
public record MoveItem(
|
||||
int moveIndex,
|
||||
String playerId,
|
||||
int row,
|
||||
int col
|
||||
) {}
|
||||
}
|
||||
@@ -112,6 +112,18 @@ public class GameController {
|
||||
return ApiResponse.ok(ready);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取房间详情
|
||||
*
|
||||
* 无需登录即可查看(观战者也可查看)。
|
||||
*/
|
||||
@SaIgnore
|
||||
@GetMapping("/room/{roomId}")
|
||||
public ApiResponse<RoomDetailResponse> roomDetail(@PathVariable String roomId) {
|
||||
RoomDetailResponse result = gameService.getRoomDetail(roomId);
|
||||
return ApiResponse.ok(result);
|
||||
}
|
||||
|
||||
/**
|
||||
* 开始游戏
|
||||
*
|
||||
|
||||
@@ -74,4 +74,12 @@ public interface GameService {
|
||||
* @param ownerId 房主 account_id
|
||||
*/
|
||||
void startGame(String roomId, String ownerId);
|
||||
|
||||
/**
|
||||
* 获取房间详情(进入房间时获取初始快照)
|
||||
*
|
||||
* @param roomId 房间 ID
|
||||
* @return 房间详情
|
||||
*/
|
||||
RoomDetailResponse getRoomDetail(String roomId);
|
||||
}
|
||||
|
||||
@@ -1,9 +1,12 @@
|
||||
package com.webgame.webgamebackend.service;
|
||||
|
||||
import com.webgame.webgamebackend.entities.GameMoveEntity;
|
||||
import com.webgame.webgamebackend.ws.RoomSessionManager;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 五子棋游戏服务
|
||||
*
|
||||
@@ -14,6 +17,22 @@ import org.springframework.stereotype.Service;
|
||||
@Service
|
||||
public class GomokuGameService {
|
||||
|
||||
/**
|
||||
* 从走棋记录重建棋盘状态
|
||||
*
|
||||
* @param moves 走棋记录(按步序升序)
|
||||
* @param boardSize 棋盘大小(五子棋通常 15 或 19)
|
||||
* @return 二维棋盘数组,0=空 1=黑子 2=白子
|
||||
*/
|
||||
public static int[][] rebuildBoard(List<GameMoveEntity> moves, int boardSize) {
|
||||
int[][] board = new int[boardSize][boardSize];
|
||||
for (int i = 0; i < moves.size(); i++) {
|
||||
GameMoveEntity move = moves.get(i);
|
||||
board[move.getRowNum()][move.getColNum()] = (i % 2 == 0) ? 1 : 2;
|
||||
}
|
||||
return board;
|
||||
}
|
||||
|
||||
public void placeStone(String roomId, String userId, int row, int col, RoomSessionManager sessionManager) {
|
||||
log.warn("[GomokuGameService] placeStone 暂未实现, roomId={}, userId={}, row={}, col={}", roomId, userId, row, col);
|
||||
}
|
||||
|
||||
@@ -9,6 +9,7 @@ import com.webgame.webgamebackend.repository.*;
|
||||
import com.webgame.webgamebackend.common.event.SseEventPublisher;
|
||||
import com.webgame.webgamebackend.common.event.SseEventType;
|
||||
import com.webgame.webgamebackend.service.GameService;
|
||||
import com.webgame.webgamebackend.service.GomokuGameService;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
|
||||
@@ -427,6 +428,65 @@ public class GameServiceImpl implements GameService {
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public RoomDetailResponse getRoomDetail(String roomId) {
|
||||
GameRoomEntity room = gameRoomRepository.findById(roomId)
|
||||
.orElseThrow(() -> new BusinessException(ErrorCode.ROOM_NOT_FOUND));
|
||||
|
||||
GameConfigEntity gameConfig = gameConfigRepository.findByGameId(room.getGameId())
|
||||
.orElseThrow(() -> new BusinessException(ErrorCode.GAME_NOT_FOUND));
|
||||
|
||||
// 组装玩家详情(含座位号和准备状态)
|
||||
List<RoomPlayerEntity> roomPlayers = roomPlayerRepository.findByRoomId(roomId);
|
||||
List<String> userIds = roomPlayers.stream()
|
||||
.map(RoomPlayerEntity::getUserId).toList();
|
||||
Map<String, UserEntity> userMap = userRepository.findByAccountIdIn(userIds).stream()
|
||||
.collect(Collectors.toMap(u -> u.getAccount().getId(), u -> u));
|
||||
|
||||
List<RoomDetailResponse.RoomPlayerDetail> playerDetails = roomPlayers.stream()
|
||||
.map(rp -> {
|
||||
UserEntity user = userMap.get(rp.getUserId());
|
||||
return new RoomDetailResponse.RoomPlayerDetail(
|
||||
rp.getUserId(),
|
||||
user != null ? user.getAvatar() : "",
|
||||
user != null ? user.getNickName() : "未知玩家",
|
||||
rp.getSeatNumber(),
|
||||
rp.getReadyStatus()
|
||||
);
|
||||
}).toList();
|
||||
|
||||
String creatorName = getNickname(room.getCreatorId());
|
||||
|
||||
// 对局中或有对局记录时,查询棋盘状态
|
||||
int[][] boardState = null;
|
||||
String currentTurn = null;
|
||||
List<RoomDetailResponse.MoveItem> moves = List.of();
|
||||
|
||||
if ("playing".equals(room.getStatus()) || "finished".equals(room.getStatus())) {
|
||||
// 查询走棋记录
|
||||
List<GameMoveEntity> moveEntities = gameMoveRepository.findByRoomIdOrderByMoveIndexAsc(roomId);
|
||||
moves = moveEntities.stream()
|
||||
.map(m -> new RoomDetailResponse.MoveItem(
|
||||
m.getMoveIndex(), m.getPlayerId(), m.getRowNum(), m.getColNum()))
|
||||
.toList();
|
||||
|
||||
// 从走棋记录重建棋盘
|
||||
boardState = GomokuGameService.rebuildBoard(moveEntities, room.getMaxPlayers());
|
||||
// currentTurn 由服务端运行时管理,HTTP 快照中暂不返回
|
||||
}
|
||||
|
||||
log.info("[游戏服务] 获取房间详情, roomId={}, status={}, 玩家数={}",
|
||||
roomId, room.getStatus(), playerDetails.size());
|
||||
|
||||
return new RoomDetailResponse(
|
||||
room.getId(), room.getName(), room.getGameId(),
|
||||
gameConfig.getIcon(), gameConfig.getName(),
|
||||
room.getMaxPlayers(), room.getMode(), room.getStakes(),
|
||||
room.getStatus(), room.getCreatorId(), creatorName,
|
||||
room.getAllowSpectate(), playerDetails, boardState, currentTurn, moves
|
||||
);
|
||||
}
|
||||
|
||||
// ==================== 私有辅助方法 ====================
|
||||
|
||||
/**
|
||||
|
||||
Reference in New Issue
Block a user