10 changed files with 337 additions and 35 deletions
@ -0,0 +1,176 @@
|
||||
using AX.WebDrillServer.Data; |
||||
using AX.WebDrillServer.Extensions; |
||||
using AX.WebDrillServer.Middlewares.Jwts; |
||||
using AX.WebDrillServer.Models; |
||||
using AX.WebDrillServer.Services.FireDeductionHub; |
||||
using Microsoft.AspNetCore.Authorization; |
||||
using Microsoft.AspNetCore.SignalR; |
||||
using Microsoft.EntityFrameworkCore; |
||||
using Microsoft.Extensions.Caching.Memory; |
||||
using System.Collections.Concurrent; |
||||
using System.Security.Claims; |
||||
|
||||
namespace AX.WebDrillServer.Hubs |
||||
{ |
||||
//[Authorize] |
||||
public class FireDeductionHub : Hub |
||||
{ |
||||
private readonly RoomManager roomManager; |
||||
|
||||
private readonly ApplicationDbContext _dbContext; |
||||
|
||||
private readonly ILogger<FireDeductionHub> _logger; |
||||
|
||||
public FireDeductionHub( |
||||
ApplicationDbContext dbContext, |
||||
ILogger<FireDeductionHub> logger, |
||||
RoomManager roomManager) |
||||
{ |
||||
_dbContext = dbContext; |
||||
_logger = logger; |
||||
this.roomManager = roomManager; |
||||
} |
||||
public async Task<FireDeductionRoom> CreateRoom(RoomCreateDto createInfo, FireDeductionUser user) |
||||
{ |
||||
FireDeductionRoom room = new FireDeductionRoom(); |
||||
room.Owner = createInfo.UserId; |
||||
room.RoomId = Guid.NewGuid().ToString(); |
||||
room.RoomName = createInfo.RoomName; |
||||
room.Password = createInfo.RoomPassword; |
||||
room.Users.Add(user); |
||||
await Groups.AddToGroupAsync(user.ConnectionId, room.RoomId); |
||||
return room; |
||||
} |
||||
public async Task<bool> EnterRoom(string roomId, FireDeductionUser user, string? password = null) |
||||
{ |
||||
bool result = false; |
||||
|
||||
var room = roomManager.GetRoom(roomId); |
||||
if (room != null && room.Password == password) |
||||
{ |
||||
if (!room.Users.Contains(user)) |
||||
{ |
||||
result = true; |
||||
} |
||||
else |
||||
{ |
||||
throw new NotImplementedException("房间中已经存在该用户!"); |
||||
} |
||||
} |
||||
else |
||||
{ |
||||
throw new NotImplementedException("房间信息有误!"); |
||||
} |
||||
|
||||
|
||||
return result; |
||||
} |
||||
|
||||
public async Task<bool> LeaveRoom(string roomId, string userId) |
||||
{ |
||||
bool result = false; |
||||
await Task.Run(() => |
||||
{ |
||||
var room = roomManager.GetRoom(roomId); |
||||
if (room != null) |
||||
{ |
||||
var user = room.Users.FirstOrDefault(u => u.UserId == userId); |
||||
if (user != null) |
||||
{ |
||||
room.Users.Remove(user); |
||||
if (room.Users.Count == 0) |
||||
{ |
||||
//TODO:保持空房间xx分钟 |
||||
} |
||||
} |
||||
else |
||||
{ |
||||
throw new NotImplementedException("用户信息有误!"); |
||||
} |
||||
} |
||||
else |
||||
{ |
||||
throw new NotImplementedException("房间信息有误!"); |
||||
} |
||||
}); |
||||
|
||||
return result; |
||||
} |
||||
public async Task RoomSendMessage(string RoomId, string Message) |
||||
{ |
||||
await Clients.Group(RoomId).SendAsync(Message); |
||||
//TODO:保存数据 |
||||
} |
||||
|
||||
public async Task SendMessage(string user, string Message) |
||||
{ |
||||
await Clients.All.SendAsync(Message); |
||||
//TODO:保存数据 |
||||
} |
||||
|
||||
public override async Task OnConnectedAsync() |
||||
{ |
||||
try |
||||
{ |
||||
var userId = Context.UserIdentifier; |
||||
var userName = Context.GetNameOfCurrentUser(); |
||||
FireDeductionUser? user = roomManager.GetUser(userId!); |
||||
|
||||
if (user != null) |
||||
{ |
||||
user.Online = true; |
||||
var room = roomManager.GetRoomByUserId(user.UserId); |
||||
if (room != null) |
||||
{ |
||||
//断线重连 |
||||
} |
||||
} |
||||
else |
||||
{ |
||||
user = new FireDeductionUser(); |
||||
user.ConnectionId = Context.ConnectionId; |
||||
user.UserId = userId!; |
||||
user.UserName = userName!; |
||||
} |
||||
_logger.LogInformation("[{userId}][{name}] connected", userId, userName); |
||||
|
||||
await base.OnConnectedAsync(); |
||||
} |
||||
catch (Exception) |
||||
{ |
||||
throw; |
||||
} |
||||
} |
||||
|
||||
public override async Task OnDisconnectedAsync(Exception? exception) |
||||
{ |
||||
try |
||||
{ |
||||
var userId = Context.UserIdentifier; |
||||
var userName = Context.User?.FindFirstValue(JwtClaimTypes.Name); |
||||
if (userId == null) _logger.LogError("无效的 userId: [{userId}]!", userId); |
||||
|
||||
if (userId != null) |
||||
{ |
||||
var user = roomManager.GetUser(userId!); |
||||
if (user != null) |
||||
{ |
||||
user.Online = false; |
||||
var room = roomManager.GetRoomByUserId(user.UserId); |
||||
if (room != null) |
||||
{ |
||||
//断线 |
||||
} |
||||
} |
||||
} |
||||
|
||||
await base.OnDisconnectedAsync(exception); |
||||
_logger.LogInformation("[{userId}][{name}] 断开了连接", userId, userName); |
||||
} |
||||
catch (Exception) |
||||
{ |
||||
throw; |
||||
} |
||||
} |
||||
} |
||||
} |
@ -1,21 +0,0 @@
|
||||
namespace AX.WebDrillServer.Models |
||||
{ |
||||
/// <summary> |
||||
/// 房间表 |
||||
/// </summary> |
||||
public class Room : EntityBase |
||||
{ |
||||
/// <summary> |
||||
/// 密码 |
||||
/// </summary> |
||||
public string? Password { get; set; } |
||||
/// <summary> |
||||
/// 所属 |
||||
/// </summary> |
||||
public User? Owner { get; set; } |
||||
/// <summary> |
||||
/// 用户 |
||||
/// </summary> |
||||
public ICollection<User>? Users { get; set; } |
||||
} |
||||
} |
@ -0,0 +1,35 @@
|
||||
using Org.BouncyCastle.Asn1.X509; |
||||
|
||||
namespace AX.WebDrillServer.Services.FireDeductionHub |
||||
{ |
||||
public enum RoomState |
||||
{ |
||||
准备 = 0, |
||||
进行中, |
||||
结束 |
||||
} |
||||
/// <summary> |
||||
/// 沙盘推演房间 |
||||
/// </summary> |
||||
public class FireDeductionRoom |
||||
{ |
||||
public string RoomId { get; set; } = null!; |
||||
public string RoomName { get; set; } = null!; |
||||
/// <summary> |
||||
/// 房间密码 |
||||
/// </summary> |
||||
public string? Password; |
||||
public RoomState State { get; set; } = RoomState.准备; |
||||
/// <summary> |
||||
/// 房间最大人数 |
||||
/// </summary> |
||||
public int MaxPersons = 100; |
||||
/// <summary> |
||||
/// 房间所属,默认是创建者 |
||||
/// </summary> |
||||
public string Owner { get; set; } = null!; |
||||
public List<FireDeductionUser> Users { get; set; } = new List<FireDeductionUser>(); |
||||
public Dictionary<DateTime, string>? FrameData { get; set; } |
||||
public Dictionary<DateTime, string>? EventData { get; set; } |
||||
} |
||||
} |
@ -0,0 +1,14 @@
|
||||
namespace AX.WebDrillServer.Services.FireDeductionHub |
||||
{ |
||||
/// <summary> |
||||
/// 沙盘推演用户 |
||||
/// </summary> |
||||
public class FireDeductionUser |
||||
{ |
||||
public string UserId { get; set; } = null!; |
||||
public string UserName { get; set; } = null!; |
||||
public bool Online { get; set; } = true; |
||||
public bool Left { get; set; } |
||||
public string ConnectionId { get; set; } = null!; |
||||
} |
||||
} |
@ -0,0 +1,11 @@
|
||||
namespace AX.WebDrillServer.Services.FireDeductionHub |
||||
{ |
||||
public class RoomCreateDto |
||||
{ |
||||
public string UserId { get; set; } = null!; |
||||
public string? RoomPassword { get; set; } |
||||
public string RoomName { get; set; } = null!; |
||||
public int MaxPerson { get; set; } = 20; |
||||
|
||||
} |
||||
} |
@ -0,0 +1,79 @@
|
||||
namespace AX.WebDrillServer.Services.FireDeductionHub |
||||
{ |
||||
public class RoomManager |
||||
{ |
||||
|
||||
private List<FireDeductionRoom> fireDeductionRooms = new List<FireDeductionRoom>(); |
||||
private List<FireDeductionUser> fireDeductionUsers = new List<FireDeductionUser>(); |
||||
|
||||
|
||||
public FireDeductionRoom? GetRoom(string roomId) |
||||
{ |
||||
lock (this) |
||||
{ |
||||
return fireDeductionRooms.Where(r => r.RoomId == roomId).SingleOrDefault(); |
||||
} |
||||
} |
||||
public FireDeductionUser? GetUser(string userId) |
||||
{ |
||||
lock (this) |
||||
{ |
||||
return fireDeductionUsers.Where(r => r.UserId == userId).SingleOrDefault(); |
||||
} |
||||
} |
||||
public FireDeductionRoom? GetRoomByUserId(string userId) |
||||
{ |
||||
lock (this) |
||||
{ |
||||
return fireDeductionRooms.Where(r => r.Users.Where(u => u.UserId == userId).SingleOrDefault() != null).SingleOrDefault(); |
||||
} |
||||
} |
||||
public void AddRoom(FireDeductionRoom room) |
||||
{ |
||||
lock (this) |
||||
{ |
||||
if (!fireDeductionRooms.Contains(room)) |
||||
{ |
||||
fireDeductionRooms.Add(room); |
||||
} |
||||
} |
||||
} |
||||
public void RemoveRoom(string roomId) |
||||
{ |
||||
lock (this) |
||||
{ |
||||
for (int i = 0; i < fireDeductionRooms.Count; i++) |
||||
{ |
||||
if (fireDeductionRooms[i].RoomId == roomId) |
||||
{ |
||||
fireDeductionRooms.RemoveAt(i); |
||||
} |
||||
} |
||||
} |
||||
} |
||||
|
||||
public void AddUser(FireDeductionUser user) |
||||
{ |
||||
lock (this) |
||||
{ |
||||
if (!fireDeductionUsers.Contains(user)) |
||||
{ |
||||
fireDeductionUsers.Add(user); |
||||
} |
||||
} |
||||
} |
||||
public void RemoveUser(string userId) |
||||
{ |
||||
lock (this) |
||||
{ |
||||
for (int i = 0; i < fireDeductionUsers.Count; i++) |
||||
{ |
||||
if (fireDeductionUsers[i].UserId == userId) |
||||
{ |
||||
fireDeductionUsers.RemoveAt(i); |
||||
} |
||||
} |
||||
} |
||||
} |
||||
} |
||||
} |
Loading…
Reference in new issue