Files
BuYuHouDuan/ChessGameSrc/ChessGameService/ChessGameService.cs
T

919 lines
38 KiB
C#
Raw Normal View History

2026-10-12 16:22:04 +08:00
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;
using ChessGameDomain;
using ChessGameService.Param;
using Common.Redis;
using CommonDomain;
using CommonDomain.BaseModel;
using CommonDomain.Enum;
using DotNetCore.CAP;
using Microsoft.Extensions.Logging;
using RedisHelper;
using RedisService;
using UserDomain.Enum;
using UserService;
using UserService.Param;
using UserService.User;
namespace ChessGameService
{
public class ChessGameService : IChessGameService
{
private readonly IRedisService _redisService;
private readonly ILogger<ChessGameService> _logger;
private readonly IDistributedLock _distributedLock;
private readonly IUserService _userService;
private readonly ICapPublisher _capPublisher;
public ChessGameService(IRedisService redisService, ILogger<ChessGameService> logger, IDistributedLock distributedLock, IUserService userService, ICapPublisher capPublisher)
{
_redisService = redisService;
_logger = logger;
_distributedLock = distributedLock;
_userService = userService;
_capPublisher = capPublisher;
}
public async Task<(bool isok, string msg, ChessGameRoom room)> CreateRoomAsync(CreateRoomParam param, string cid)
{
var user = await _userService.GetUser(param.userId);
if (user == null)
return (false, "用户不存在", null);
var gameConfig = _redisService.GetGameConfig();
if (gameConfig == null)
return (false, "游戏配置不存在", null);
return await _distributedLock.TryExecuteAsync(
$"{RedisKey.DistributedLockPrefix}chess:room:{param.roomId}",
() =>
{
var room = _redisService.GetChessRoom(param.roomId);
if (room == null)
{
return Task.FromResult<(bool isok, string msg, ChessGameRoom room)>((false, "房间不存在", null));
}
var allRooms = _redisService.GetAllChessRooms();
if (allRooms != null)
{
foreach (var oldRoom in allRooms)
{
if (oldRoom.RoomId == param.roomId) continue;
var oldUser = oldRoom.users?.FirstOrDefault(u => u.userId == param.userId);
if (oldUser != null)
{
if (oldRoom.createUserId == param.userId)
{
oldRoom.users = new List<RedisChessGameUser>();
oldRoom.state = 3;
oldRoom.password = "";
oldRoom.createUserId = "";
oldRoom.gold = 0;
oldRoom.gameType = 0;
oldRoom.robotCount = 0;
oldRoom.IsGameEnded = false;
oldRoom.EndGameRequests?.Clear();
oldRoom.PendingWinUserId = null;
oldRoom.TimeoutLoserUserId = "";
oldRoom.LastActiveTime = 0;
}
else
{
oldRoom.users.Remove(oldUser);
if (oldRoom.users.Count == 0)
{
oldRoom.state = 3;
oldRoom.password = "";
oldRoom.createUserId = "";
oldRoom.gold = 0;
oldRoom.gameType = 0;
oldRoom.robotCount = 0;
oldRoom.IsGameEnded = false;
}
else
{
oldRoom.gold = 0;
}
}
_redisService.SetChessRoom(oldRoom);
}
}
}
if ((room.state == 3 && room.users.Count == 0) || room.state == 0)
{
bool isCreareRoom = false;
if (gameConfig.ChessConfig.CreateRoomLimit.Any(c=>c==3))
isCreareRoom = true;
if (gameConfig.ChessConfig.CreateRoomLimit.Any(c => c == 1) && user.Assets.VipLevel > 0)
{
var vipLevels = gameConfig.ChessConfig.CreateRoomVipLevels ?? new List<int>();
if (vipLevels.Count == 0 || vipLevels.Contains(user.Assets.VipLevel))
isCreareRoom = true;
}
if (gameConfig.ChessConfig.CreateRoomLimit.Any(c => c == 2) && user.UserType==2)
isCreareRoom = true;
if (!isCreareRoom)
{
var roles = new List<string>();
if (gameConfig.ChessConfig.CreateRoomLimit.Any(c => c == 1)) roles.Add("VIP");
if (gameConfig.ChessConfig.CreateRoomLimit.Any(c => c == 2)) roles.Add("代理");
var msg = roles.Count > 0 ? $"只有{string.Join("/", roles)}才能配置密码" : "没有权限配置密码";
return Task.FromResult<(bool isok, string msg, ChessGameRoom room)>((false, msg, null));
}
room.users = new List<RedisChessGameUser>() { new RedisChessGameUser
{
Cid = cid,
userId = param.userId,
userName = user.BaseInfo.UserName,
userAvatar = user.BaseInfo.AvatarUrl,
Gold = user.Assets.Gold,
type = param.gameType,
IsLeave = false,
IsReady = false
}};
room.gameType = param.gameType;
room.password = param.password;
room.createUserId = param.userId;
room.gold = param.gold;
room.state = 1;
room.robotCount = 0;
room.IsGameEnded = false;
}
else if (room.users.Any(c => c.userId == param.userId))
{
var existing = room.users.First(c => c.userId == param.userId);
existing.Cid = cid;
existing.IsLeave = false;
existing.DisconnectTime = 0;
room.robotCount = Math.Clamp(room.robotCount, 0, Math.Max(0, 2 - room.users.Count));
_redisService.SetChessRoom(room);
return Task.FromResult<(bool isok, string msg, ChessGameRoom room)>((true, "", room));
}
else if (room.state == 3)
return Task.FromResult<(bool isok, string msg, ChessGameRoom room)>((false, "上一局玩家尚未退出", room));
else if (room.users.Count + room.robotCount >= 2 || room.state == 2)
return Task.FromResult<(bool isok, string msg, ChessGameRoom room)>((false, "当前房间已有玩家", room));
else
{
var firstPlayerType = room.gameType;
var secondPlayerType = firstPlayerType == 1 ? 2 : 1;
room.users.Add(new RedisChessGameUser
{
Cid = cid,
userId = param.userId,
userName = user.BaseInfo.UserName,
userAvatar = user.BaseInfo.AvatarUrl,
Gold = user.Assets.Gold,
type = secondPlayerType,
IsLeave = false,
IsReady = false
});
room.state = 1;
}
_redisService.SetChessRoom(room);
return Task.FromResult<(bool isok, string msg, ChessGameRoom room)>((true, "", room));
},
expiry: 10
);
}
public async Task<(bool success, string message, ChessGameRoom room)> JoinGameAsync(string gameId, string pwd, string userId, string cid)
{
var user = await _userService.GetUser(userId);
if (user == null)
return (false, "用户不存在", null);
return await _distributedLock.TryExecuteAsync(
$"{RedisKey.DistributedLockPrefix}chess:room:{gameId}",
() =>
{
var room = _redisService.GetChessRoom(gameId);
if (room == null || room.state == 3)
{
return Task.FromResult((false, "房间不存在", (ChessGameRoom)null));
}
if (string.IsNullOrEmpty(room.password))
{
return Task.FromResult((false, "房间未设置密码,无法进入", (ChessGameRoom)null));
}
if (room.password != pwd)
{
return Task.FromResult((false, "密码错误", (ChessGameRoom)null));
}
if (room.users.Any(c => c.userId == userId))
{
var existing = room.users.First(c => c.userId == userId);
existing.Cid = cid;
existing.IsLeave = false;
existing.DisconnectTime = 0;
room.robotCount = Math.Clamp(room.robotCount, 0, Math.Max(0, 2 - room.users.Count));
_redisService.SetChessRoom(room);
return Task.FromResult((true, "", room));
}
if (room.state == 3 && room.IsGameEnded && room.users.Count < 2)
{
var secondPlayerType = room.gameType == 1 ? 2 : 1;
room.users.Add(new RedisChessGameUser
{
Cid = cid,
userId = userId,
Gold = user.Assets.Gold,
userName = user.BaseInfo.UserName,
userAvatar = user.BaseInfo.AvatarUrl,
type = secondPlayerType,
IsLeave = false,
IsReady = false
});
room.robotCount = 0;
room.state = 1;
room.IsGameEnded = false;
room.gold = 0;
_redisService.SetChessRoom(room);
return Task.FromResult((true, "", room));
}
if (room.users.Count + room.robotCount >= 2)
{
return Task.FromResult((false, "房间已满", (ChessGameRoom)null));
}
room.users.Add(new RedisChessGameUser
{
Cid = cid,
userId = userId,
Gold = user.Assets.Gold,
userName = user.BaseInfo.UserName,
userAvatar = user.BaseInfo.AvatarUrl,
type = room.gameType == 1 ? 2 : 1,
IsLeave = false,
IsReady = false
});
room.robotCount = 0;
_redisService.SetChessRoom(room);
return Task.FromResult((true, "", room));
},
expiry: 10
);
}
public List<ChessGameRoom> GetRoomList(int partition, int maxRooms = 100)
{
var existingRooms = _redisService.GetAllChessRooms();
if (existingRooms == null || existingRooms.Count == 0)
return new List<ChessGameRoom>();
return existingRooms
.Where(c => c != null
&& (partition <= 0 || GetChessRoomPartition(c.RoomId) == partition)
&& !(c.state == 1
&& string.IsNullOrWhiteSpace(c.createUserId)
&& (c.users == null || c.users.Count == 0)))
.OrderBy(c => c.RoomId)
.Take(maxRooms)
.ToList();
}
private static int GetChessRoomPartition(string roomId)
{
if (string.IsNullOrWhiteSpace(roomId) || roomId.Length < 4)
return 0;
var partitionText = roomId.Substring(1, roomId.Length - 3);
return int.TryParse(partitionText, out var partition) ? partition : 0;
}
public (bool success, string message, ChessGameRoom room) StartGame(string gameId, string userId)
{
var room = _redisService.GetChessRoom(gameId);
if (room == null || room.state == 3)
return (false, "房间不存在", null);
if (room.state != 1)
return (false, "游戏已开始", null);
if (room.createUserId != userId)
return (false, "只有房主才能开始游戏", null);
if (room.users.Count < 2)
return (false, "人数不足,无法开始", null);
return (true, "", room);
}
public (bool success, string message, bool allReady) GameReady(string gameId, string userId)
{
if (string.IsNullOrWhiteSpace(gameId) || string.IsNullOrWhiteSpace(userId))
return (false, "房间或玩家参数不能为空", false);
return _distributedLock.TryExecute(
$"{RedisKey.DistributedLockPrefix}chess:room:{gameId}",
() =>
{
var room = _redisService.GetChessRoom(gameId);
if (room == null || room.state == 3)
return (false, "房间不存在", false);
var user = room.users.FirstOrDefault(c => c.userId == userId);
if (user == null)
return (false, "玩家不存在", false);
if (room.gold == 0)
return (false, "未设置金币", false);
user.IsReady = true;
var allReady = room.users.Count >= 2 && room.users.All(c => c.IsReady);
if (allReady)
room.state = 2;
_redisService.SetChessRoom(room);
return (true, "", allReady);
},
expiry: 10,
retry: true,
retryDelay: 20);
}
public async Task<(bool success, string message, ChessGameRoom room)> EndGame(string gameId, string winUserId)
{
return await _distributedLock.TryExecuteAsync(
$"{RedisKey.DistributedLockPrefix}chess:room:{gameId}",
async () =>
{
var room = _redisService.GetChessRoom(gameId);
if (room == null)
return (false, "房间不存在", null);
if (room.state != 2 || room.IsGameEnded)
return (true, "游戏已结束", room);
if (!string.IsNullOrWhiteSpace(winUserId) && !room.users.Any(u => u.userId == winUserId))
return (false, "胜者不在房间中", (ChessGameRoom)null);
room.state = 3;
room.IsGameEnded = true;
_redisService.SetChessRoom(room);
if (!string.IsNullOrWhiteSpace(winUserId))
{
var loser = room.users.FirstOrDefault(u => u.userId != winUserId);
var winner = room.users.FirstOrDefault(u => u.userId == winUserId);
var winnerName = winner?.userName ?? "";
var loserName = loser?.userName ?? "";
var loserId = loser?.userId ?? "";
var winnerEntity = winner != null ? await _userService.GetUser(winner.userId) : null;
var loserEntity = loser != null ? await _userService.GetUser(loser.userId) : null;
var realLoserGold = loserEntity?.Assets.Gold ?? 0;
var actualBet = Math.Min(room.gold, realLoserGold);
if (actualBet > 0)
{
if (loserEntity != null)
{
var deductRemark = $"房间号({room.RoomId}) {winnerName}({winner?.userId})赢得对局 {loserName}({loserId})输 金额{actualBet}";
var deductResult = await _userService.UpdateAssets(new UserAssetParam()
{
ChangeType = UserAssetChangeTypeEnum.减少,
Gold = actualBet,
TotalRechargeGoldDelta = -actualBet,
Remark = deductRemark,
Source = RewardSource.象棋,
UserId = loserEntity.Id,
RoomInfo = room.RoomId,
OtherUserId = winUserId
});
if (!deductResult.isok)
{
room.state = 2;
room.IsGameEnded = false;
_redisService.SetChessRoom(room);
return (false, "结算失败:" + deductResult.msg, room);
}
loser.Gold = Math.Max(0, realLoserGold - actualBet);
}
if (winnerEntity != null)
{
var winRemark = $"房间号({room.RoomId}) {winnerName}({winner?.userId})赢得对局 {loserName}({loserId})输 金额{actualBet}";
var winResult = await _userService.UpdateAssets(new UserAssetParam()
{
ChangeType = UserAssetChangeTypeEnum.增加,
Gold = actualBet,
TotalRechargeGoldDelta = actualBet,
Remark = winRemark,
Source = RewardSource.象棋,
UserId = winnerEntity.Id,
RoomInfo = room.RoomId,
OtherUserId = loserId
});
if (!winResult.isok)
{
if (loserEntity != null)
{
await _userService.UpdateAssets(new UserAssetParam()
{
ChangeType = UserAssetChangeTypeEnum.增加,
Gold = actualBet,
TotalRechargeGoldDelta = actualBet,
Remark = $"房间号({room.RoomId}) 结算异常回退 {winnerName}({winner?.userId}) 金额{actualBet}",
Source = RewardSource.象棋,
UserId = loserEntity.Id,
RoomInfo = room.RoomId,
OtherUserId = winUserId
});
}
}
winner.Gold = winnerEntity.Assets.Gold + actualBet;
}
var newWinnerEntity = winnerEntity != null ? await _userService.GetUser(winnerEntity.Id) : null;
var newLoserEntity = loserEntity != null ? await _userService.GetUser(loserEntity.Id) : null;
if (winnerEntity != null)
{
var newWinnerGold = newWinnerEntity?.Assets.Gold ?? winnerEntity.Assets.Gold;
_capPublisher.Publish("BackgroundOperation.NotifyUser", new BackgroundOperationNotifyMessage
{
UserId = winnerEntity.Id,
CurrencyType = 1,
ChangeType = 1,
Amount = actualBet,
NewGold = newWinnerGold,
Source = "象棋对局胜利",
Remark = $"房间号({room.RoomId})赢得{actualBet}金币"
});
}
if (loserEntity != null)
{
var newLoserGold = newLoserEntity?.Assets.Gold ?? loser.Gold;
_capPublisher.Publish("BackgroundOperation.NotifyUser", new BackgroundOperationNotifyMessage
{
UserId = loserEntity.Id,
CurrencyType = 1,
ChangeType = 2,
Amount = actualBet,
NewGold = newLoserGold,
Source = "象棋对局失败",
Remark = $"房间号({room.RoomId})输掉{actualBet}金币"
});
}
}
}
var userIds = room.users?.Select(u => u.userId).Where(id => !string.IsNullOrWhiteSpace(id)).ToList()
?? new List<string>();
room.gold = 0;
room.gameType = 0;
room.robotCount = 0;
room.EndGameRequests?.Clear();
room.PendingWinUserId = null;
room.TimeoutLoserUserId = "";
room.LastActiveTime = 0;
room.users.Clear();
_redisService.SetChessRoom(room);
foreach (var userId in userIds)
{
try
{
await UpdateUserGameType(userId, 0);
}
catch (Exception ex)
{
_logger.LogError(ex, "[象棋] EndGame 清除游戏状态失败 userId={UserId}", userId);
}
}
return (true, "", room);
},
expiry: 30,
retry: false);
}
public (bool success, string message, ChessGameRoom room) RestartGame(string gameId, string userId)
{
var room = _redisService.GetChessRoom(gameId);
if (room == null)
{
return (false, "房间不存在", null);
}
if (room.state == 3 && room.IsGameEnded)
{
room.state = 1;
room.IsGameEnded = false;
room.gold = 0;
room.robotCount = 0;
room.EndGameRequests?.Clear();
room.PendingWinUserId = null;
room.TimeoutLoserUserId = "";
room.LastActiveTime = 0;
if (room.users == null) room.users = new List<RedisChessGameUser>();
var existingUser = room.users.FirstOrDefault(u => u.userId == userId);
if (existingUser == null)
{
room.users.Add(new RedisChessGameUser
{
userId = userId,
userName = "",
type = room.gameType,
IsLeave = false,
IsReady = false
});
}
else
{
existingUser.IsReady = false;
existingUser.IsLeave = false;
existingUser.DisconnectTime = 0;
}
_redisService.SetChessRoom(room);
return (true, "", room);
}
if (!room.IsGameEnded)
{
return (false, "对局尚未结束,无法重新开始", null);
}
var user = room.users.FirstOrDefault(u => u.userId == userId);
if (user == null)
{
return (false, "对局已结束,房间已释放,请重新创建房间", null);
}
room.state = 1;
room.IsGameEnded = false;
room.gold = 0;
room.EndGameRequests?.Clear();
room.PendingWinUserId = null;
room.TimeoutLoserUserId = "";
room.LastActiveTime = 0;
foreach (var u in room.users)
{
u.IsReady = false;
}
_redisService.SetChessRoom(room);
return (true, "", room);
}
public async Task<(bool success, string message, ChessGameRoom room, bool allConfirmed)> RequestEndGame(string gameId, string userId, string winUserId)
{
var room = _redisService.GetChessRoom(gameId);
if (room == null || room.state == 3)
{
return (false, "房间不存在", null, false);
}
if (room.state != 2)
{
return (false, "游戏未开始", null, false);
}
var user = room.users.FirstOrDefault(u => u.userId == userId);
if (user == null)
{
return (false, "参数异常", null, false);
}
if (!string.IsNullOrWhiteSpace(winUserId) && !room.users.Any(u => u.userId == winUserId))
return (false, "胜者不在房间中", null, false);
if (room.EndGameRequests == null)
room.EndGameRequests = new Dictionary<string, long>();
room.EndGameRequests[userId] = DateTimeOffset.UtcNow.ToUnixTimeSeconds();
if (!string.IsNullOrEmpty(winUserId) && string.IsNullOrEmpty(room.PendingWinUserId))
{
room.PendingWinUserId = winUserId;
}
_redisService.SetChessRoom(room);
var roomUserIds = room.users.Select(u => u.userId).ToHashSet();
var confirmedCount = room.EndGameRequests.Keys.Count(roomUserIds.Contains);
if (confirmedCount >= room.users.Count && room.users.Count >= 2)
{
string finalWinUserId = room.PendingWinUserId ?? "";
room.EndGameRequests.Clear();
room.PendingWinUserId = null;
_redisService.SetChessRoom(room);
var result = await EndGame(gameId, finalWinUserId);
return (result.success, result.message, result.room, true);
}
return (true, "等待对方确认结束", room, false);
}
public async Task<(bool isTimeout, string loserUserId)> CheckRoomTimeout(string gameId)
{
var room = _redisService.GetChessRoom(gameId);
if (room == null || room.state != 2)
{
return (false, "");
}
var now = DateTimeOffset.UtcNow.ToUnixTimeSeconds();
var timeout = room.TimeoutSeconds > 0 ? room.TimeoutSeconds : 60;
foreach (var user in room.users)
{
if (user.IsLeave && user.DisconnectTime > 0 && (now - user.DisconnectTime) > timeout)
{
var winUserId = room.users.FirstOrDefault(u => u.userId != user.userId)?.userId ?? "";
room.TimeoutLoserUserId = user.userId;
_redisService.SetChessRoom(room);
await EndGame(gameId, winUserId);
return (true, user.userId);
}
}
return (false, "");
}
public async Task<(bool isTimeout, string loserUserId)> CheckRoomAfkTimeout(string gameId)
{
var room = _redisService.GetChessRoom(gameId);
if (room == null || room.state != 2 || room.users.Count < 2)
{
return (false, "");
}
var now = DateTimeOffset.UtcNow.ToUnixTimeSeconds();
var afkUsers = room.users.Where(u => u.IsAfk && u.AfkTime > 0).OrderBy(u => u.AfkTime).ToList();
if (afkUsers.Count == 2)
{
var firstAfkUser = afkUsers[0];
var winUserId = room.users.FirstOrDefault(u => u.userId != firstAfkUser.userId)?.userId ?? "";
await EndGame(gameId, winUserId);
return (true, firstAfkUser.userId);
}
if (afkUsers.Count == 1)
{
var afkUser = afkUsers[0];
var timeout = room.AfkTimeoutSeconds > 0 ? room.AfkTimeoutSeconds : 120;
if ((now - afkUser.AfkTime) > timeout)
{
var winUserId = room.users.FirstOrDefault(u => u.userId != afkUser.userId)?.userId ?? "";
await EndGame(gameId, winUserId);
return (true, afkUser.userId);
}
}
return (false, "");
}
public async Task UpdateUserActiveTime(string gameId, string userId)
{
var room = _redisService.GetChessRoom(gameId);
if (room == null || room.state != 2)
{
return;
}
var user = room.users.FirstOrDefault(u => u.userId == userId);
if (user == null)
{
return;
}
room.LastActiveTime = DateTimeOffset.UtcNow.ToUnixTimeSeconds();
_redisService.SetChessRoom(room);
}
public async Task SetPlayerAfk(string gameId, string userId)
{
var room = string.IsNullOrWhiteSpace(gameId) ? null : _redisService.GetChessRoom(gameId);
var user = room?.users?.FirstOrDefault(u => u.userId == userId);
if (user == null)
{
return;
}
user.IsAfk = true;
user.AfkTime = DateTimeOffset.UtcNow.ToUnixTimeSeconds();
_redisService.SetChessRoom(room);
await Task.CompletedTask;
}
public async Task CancelPlayerAfk(string gameId, string userId)
{
var room = string.IsNullOrWhiteSpace(gameId) ? null : _redisService.GetChessRoom(gameId);
var user = room?.users?.FirstOrDefault(u => u.userId == userId);
if (user == null)
{
return;
}
user.IsAfk = false;
user.AfkTime = 0;
_redisService.SetChessRoom(room);
await Task.CompletedTask;
}
public bool ExitRoom(ChessGameRoom room)
{
room.users = new List<RedisChessGameUser>();
room.state = 3;
room.password = "";
room.createUserId = "";
room.gold = 0;
room.gameType = 0;
room.robotCount = 0;
room.IsGameEnded = false;
room.EndGameRequests?.Clear();
room.PendingWinUserId = null;
room.TimeoutLoserUserId = "";
room.LastActiveTime = 0;
_redisService.SetChessRoom(room);
return true;
}
public (bool isok, string msg, ChessGameRoom room) ExitRoom(string gameId, string userId)
{
var room = _redisService.GetChessRoom(gameId);
if (room == null)
{
return (false, "房间不存在", null);
}
if (room.state == 3 && (room.users == null || room.users.Count == 0))
{
ExitRoom(room);
return (true, "房间已清空", room);
}
var user = room.users.FirstOrDefault(c => c.userId == userId);
if (user == null)
{
return (false, "玩家不存在", null);
}
if (room.state == 2)
{
user.IsLeave = true;
user.DisconnectTime = DateTimeOffset.UtcNow.ToUnixTimeSeconds();
user.Cid = string.Empty;
if (room.users.All(u => u.IsLeave))
{
ExitRoom(room);
return (true, "所有玩家已退出,房间已重置", room);
}
_redisService.SetChessRoom(room);
return (true, "玩家已退出,等待其他玩家", room);
}
if (room.createUserId == userId)
{
ExitRoom(room);
return (true, "房主退出,房间已清空", room);
}
room.users.Remove(user);
if (room.users.Count == 0 || (room.state == 3 && room.users.Count <= 1))
{
ExitRoom(room);
return (true, "房间已清空", room);
}
room.gold = 0;
room.robotCount = Math.Clamp(room.robotCount, 0, Math.Max(0, 2 - room.users.Count));
_redisService.SetChessRoom(room);
return (true, "", room);
}
public (bool isok, string msg, ChessGameRoom room) AdminKickPlayer(string gameId, string userId)
{
var room = _redisService.GetChessRoom(gameId);
if (room == null)
return (false, "房间不存在", null);
if (room.state == 2)
return (false, "游戏进行中不能直接踢人,请先结束对局", room);
var user = room.users?.FirstOrDefault(c => c.userId == userId);
if (user == null)
return (false, "玩家不存在", room);
room.users.Remove(user);
if (room.users.Count == 0)
{
ExitRoom(room);
return (true, "玩家已踢出,房间已重置", room);
}
if (room.createUserId == userId)
room.createUserId = room.users[0].userId;
room.state = 1;
room.gold = 0;
room.IsGameEnded = false;
room.EndGameRequests?.Clear();
room.PendingWinUserId = null;
room.TimeoutLoserUserId = string.Empty;
room.LastActiveTime = 0;
room.robotCount = Math.Clamp(room.robotCount, 0, Math.Max(0, 2 - room.users.Count));
foreach (var remainingUser in room.users)
remainingUser.IsReady = false;
_redisService.SetChessRoom(room);
return (true, "玩家已踢出", room);
}
public async Task UpdateUserGameType(string userId, int gameType, string roomNumber = "")
{
try
{
var user = await _userService.GetUser(userId);
if (user != null)
{
user.Static.CurrentGameType = gameType;
user.Static.RoomNumber = gameType > 0 ? (roomNumber ?? string.Empty) : string.Empty;
await _userService.UpdateUser(user);
}
}
catch (Exception ex)
{
_logger.LogError(ex, "更新用户当前游戏类型失败 userId={UserId} gameType={GameType} roomNumber={RoomNumber}", userId, gameType, roomNumber);
}
}
public (bool success, string message, ChessGameRoom room) GoldConfig(string gameId, long gold, string userId)
{
var room = _redisService.GetChessRoom(gameId);
if (room == null || room.state == 3)
{
return (false, "房间不存在", null);
}
var gameconfig= _redisService.GetGameConfig();
if (gameconfig==null)
{
return (false, "游戏配置不存在", null);
}
if(gold<gameconfig.ChessConfig.MinBetGold)
return (false, $"金币不能小于{gameconfig.ChessConfig.MinBetGold}", null);
if (!room.users.Any(c => c.type == 2 && c.userId == userId))
return (false, "只有红方才可以配置金币", null);
var redPlayer = room.users.FirstOrDefault(c => c.type == 2);
if (redPlayer != null && redPlayer.Gold < gold)
return (false, "金币不足", null);
room.gold = gold;
_redisService.SetChessRoom(room);
return (true, "", room);
}
public ChessGameRoom GetUserRoom(string cid)
{
var rooms = _redisService.GetAllChessRooms();
if (rooms == null) return null;
return rooms.FirstOrDefault(c => c.users.Any(d => d.Cid == cid && (c.state == 1 || c.state == 2)));
}
public ChessGameRoom GetRoom(string gameId)
{
return _redisService.GetChessRoom(gameId);
}
public List<ChessGameRoom> GetAllPlayingRooms()
{
var allRooms = _redisService.GetAllChessRooms();
if (allRooms == null)
return new List<ChessGameRoom>();
return allRooms.Where(r => r != null && r.state == 2).ToList();
}
}
}