139 lines
5.4 KiB
C#
139 lines
5.4 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
using System.Linq;
|
|
using System.Threading;
|
|
using System.Threading.Tasks;
|
|
using ChessGameService;
|
|
using ChessGameDomain;
|
|
using Microsoft.AspNetCore.SignalR;
|
|
using Microsoft.Extensions.Hosting;
|
|
using Microsoft.Extensions.Logging;
|
|
|
|
namespace ChessGameHost.Services
|
|
{
|
|
public class ChessTimeoutService : BackgroundService
|
|
{
|
|
private readonly ILogger<ChessTimeoutService> _logger;
|
|
|
|
private readonly IChessGameService _chessService;
|
|
|
|
private readonly IHubContext<ChessGameHub> _hubContext;
|
|
|
|
public ChessTimeoutService(
|
|
ILogger<ChessTimeoutService> logger,
|
|
IChessGameService chessService,
|
|
IHubContext<ChessGameHub> hubContext)
|
|
{
|
|
_logger = logger;
|
|
_chessService = chessService;
|
|
_hubContext = hubContext;
|
|
}
|
|
|
|
protected override async Task ExecuteAsync(CancellationToken stoppingToken)
|
|
{
|
|
while (!stoppingToken.IsCancellationRequested)
|
|
{
|
|
try
|
|
{
|
|
await CheckAllRoomsTimeout();
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
_logger.LogError(ex, "检查象棋断线/挂起超时时发生错误");
|
|
}
|
|
|
|
await Task.Delay(TimeSpan.FromSeconds(10), stoppingToken);
|
|
}
|
|
}
|
|
|
|
private async Task CheckAllRoomsTimeout()
|
|
{
|
|
var playingRooms = _chessService.GetAllPlayingRooms();
|
|
if (playingRooms == null || !playingRooms.Any())
|
|
return;
|
|
|
|
var now = DateTimeOffset.UtcNow.ToUnixTimeSeconds();
|
|
|
|
foreach (var room in playingRooms)
|
|
{
|
|
foreach (var user in room.users)
|
|
{
|
|
if (user.IsLeave && user.DisconnectTime > 0)
|
|
{
|
|
var timeout = room.TimeoutSeconds > 0 ? room.TimeoutSeconds : 60;
|
|
if ((now - user.DisconnectTime) > timeout)
|
|
{
|
|
var winUserId = room.users
|
|
.FirstOrDefault(u => u.userId != user.userId)?.userId ?? "";
|
|
|
|
var settledConnectionIds = room.users
|
|
.Where(u => !string.IsNullOrWhiteSpace(u.Cid))
|
|
.Select(u => u.Cid)
|
|
.Distinct()
|
|
.ToList();
|
|
var (success, message, endRoom) = await _chessService.EndGame(room.RoomId, winUserId);
|
|
if (!success || endRoom == null)
|
|
{
|
|
break;
|
|
}
|
|
|
|
await _hubContext.Clients.Group(room.RoomId).SendAsync("GameEnd", new
|
|
{
|
|
winUserId,
|
|
room = endRoom
|
|
});
|
|
await _hubContext.Clients.Group(ChessGameHub.LobbyGroup).SendAsync("ExitRoomNotice", endRoom);
|
|
await _hubContext.Clients.Clients(settledConnectionIds).SendAsync("ExitRoomNotice", endRoom);
|
|
foreach (var connectionId in settledConnectionIds)
|
|
{
|
|
await _hubContext.Groups.RemoveFromGroupAsync(connectionId, room.RoomId);
|
|
await _hubContext.Groups.AddToGroupAsync(connectionId, ChessGameHub.LobbyGroup);
|
|
}
|
|
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
var latestRoom = _chessService.GetRoom(room.RoomId);
|
|
if (latestRoom != null && latestRoom.state == 2)
|
|
await CheckRoomAfk(latestRoom);
|
|
}
|
|
}
|
|
|
|
private async Task CheckRoomAfk(ChessGameRoom room)
|
|
{
|
|
if (room.state != 2 || room.users == null || room.users.Count < 2)
|
|
return;
|
|
|
|
if (!room.users.Any(u => u.IsAfk))
|
|
return;
|
|
|
|
var settledConnectionIds = room.users
|
|
.Where(u => !string.IsNullOrWhiteSpace(u.Cid))
|
|
.Select(u => u.Cid)
|
|
.Distinct()
|
|
.ToList();
|
|
|
|
var (isTimeout, loserUserId) = await _chessService.CheckRoomAfkTimeout(room.RoomId);
|
|
if (!isTimeout || string.IsNullOrEmpty(loserUserId))
|
|
return;
|
|
|
|
var winUserId = room.users.FirstOrDefault(u => u.userId != loserUserId)?.userId ?? "";
|
|
var endRoom = _chessService.GetRoom(room.RoomId);
|
|
await _hubContext.Clients.Group(room.RoomId).SendAsync("GameEnd", new
|
|
{
|
|
winUserId,
|
|
room = endRoom
|
|
});
|
|
await _hubContext.Clients.Group(ChessGameHub.LobbyGroup).SendAsync("ExitRoomNotice", endRoom);
|
|
await _hubContext.Clients.Clients(settledConnectionIds).SendAsync("ExitRoomNotice", endRoom);
|
|
foreach (var connectionId in settledConnectionIds)
|
|
{
|
|
await _hubContext.Groups.RemoveFromGroupAsync(connectionId, room.RoomId);
|
|
await _hubContext.Groups.AddToGroupAsync(connectionId, ChessGameHub.LobbyGroup);
|
|
}
|
|
}
|
|
}
|
|
}
|