添加项目文件。
This commit is contained in:
@@ -0,0 +1,20 @@
|
||||
using AutoMapper;
|
||||
using CommonDomain.BaseModel;
|
||||
using FishRoomService.RoomSend.Response;
|
||||
using RedisService.Param;
|
||||
using UserDomain.Entity;
|
||||
using UserService.Param;
|
||||
using UserService.Response;
|
||||
|
||||
namespace FishRoomService
|
||||
{
|
||||
public class AutoMapperConfig : Profile
|
||||
{
|
||||
public AutoMapperConfig()
|
||||
{
|
||||
|
||||
CreateMap<RedisGameRoom, GameRoomReponse>();
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net8.0</TargetFramework>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<Nullable>enable</Nullable>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="AutoMapper" Version="14.0.0" />
|
||||
<PackageReference Include="DotNetCore.CAP" Version="8.3.4" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.SignalR.Core" Version="1.2.9" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\CommonService\CommonService.csproj" />
|
||||
<ProjectReference Include="..\RedisService\RedisService.csproj" />
|
||||
<ProjectReference Include="..\UserSrc\UserService\UserService.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
@@ -0,0 +1,54 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using CommonDomain.Enum;
|
||||
using FishRoomService.RoomService;
|
||||
using Microsoft.AspNetCore.SignalR;
|
||||
using RedisService;
|
||||
|
||||
namespace FishRoomService.Hubs
|
||||
{
|
||||
public class FishRoomHub : Hub
|
||||
{
|
||||
private readonly IRedisService _redisService;
|
||||
private readonly IFishingRoomService _fishingRoomService;
|
||||
|
||||
public FishRoomHub(IRedisService redisService, IFishingRoomService fishingRoomService)
|
||||
{
|
||||
_redisService = redisService;
|
||||
_fishingRoomService = fishingRoomService;
|
||||
|
||||
}
|
||||
|
||||
public override async Task OnConnectedAsync()
|
||||
{
|
||||
await base.OnConnectedAsync();
|
||||
}
|
||||
|
||||
public override async Task OnDisconnectedAsync(Exception? exception)
|
||||
{
|
||||
await base.OnDisconnectedAsync(exception);
|
||||
}
|
||||
|
||||
|
||||
|
||||
public async Task GetRoomList(string userId, GameTypeEnum gameType, int roomLevel, int roomPartition)
|
||||
{
|
||||
string cid = Context.ConnectionId;
|
||||
|
||||
await _fishingRoomService.GetRoomList(cid, userId, gameType, roomLevel, roomPartition);
|
||||
|
||||
}
|
||||
|
||||
public async Task GetRoomInfo(string roomId)
|
||||
{
|
||||
string cid = Context.ConnectionId;
|
||||
var room = _redisService.GetGameRoom(roomId);
|
||||
|
||||
await Clients.Caller.SendAsync("GetRoomInfoResult", room);
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using RedisService.Param;
|
||||
|
||||
namespace FishRoomService.MQ
|
||||
{
|
||||
public interface IRoomMQService
|
||||
{
|
||||
Task RoomChange(RedisGameRoom room);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,79 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using AutoMapper;
|
||||
using Common.Utils;
|
||||
using CommonDomain;
|
||||
using CommonDomain.BaseModel;
|
||||
using CommonService;
|
||||
using DotNetCore.CAP;
|
||||
using FishRoomService.Hubs;
|
||||
using FishRoomService.RoomSend;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using MongoRepository;
|
||||
using RedisService.Param;
|
||||
using RedisService;
|
||||
using UserDomain.Entity;
|
||||
using UserService;
|
||||
using UserService.Param;
|
||||
using UserService.User;
|
||||
|
||||
namespace FishRoomService.MQ
|
||||
{
|
||||
|
||||
public class RoomMQService : IRoomMQService, ICapSubscribe
|
||||
{
|
||||
private readonly IFishingRoomSendService _service;
|
||||
private readonly IHubSend<FishRoomHub> _hubSend;
|
||||
private readonly IRedisService _redisService;
|
||||
private readonly ILogger<RoomMQService> _logger;
|
||||
|
||||
public RoomMQService(IFishingRoomSendService service, IHubSend<FishRoomHub> hubSend, IRedisService redisService, ILogger<RoomMQService> logger)
|
||||
{
|
||||
_service = service;
|
||||
_hubSend = hubSend;
|
||||
_redisService = redisService;
|
||||
_logger = logger;
|
||||
}
|
||||
|
||||
|
||||
|
||||
[CapSubscribe(TopicKeys.房间变化)]
|
||||
public async Task RoomChange(RedisGameRoom room)
|
||||
{
|
||||
|
||||
_service.RoomChange(room);
|
||||
|
||||
}
|
||||
|
||||
[CapSubscribe(TopicKeys.用户资产同步前端)]
|
||||
public async Task UserAssetSync(UserAssetSyncParam param)
|
||||
{
|
||||
try
|
||||
{
|
||||
var session = _redisService.GetRedisUserCId(param.UserId);
|
||||
var cid = session?.FishRoomCId;
|
||||
if (string.IsNullOrWhiteSpace(cid) && string.IsNullOrWhiteSpace(session?.RoomId))
|
||||
cid = session?.CId;
|
||||
if (string.IsNullOrWhiteSpace(cid))
|
||||
return;
|
||||
await _hubSend.SendUserCIdAsync(cid, "AssetUpdated", new
|
||||
{
|
||||
param.CurrencyType,
|
||||
param.ChangeType,
|
||||
param.Amount,
|
||||
param.NewGold,
|
||||
param.NewDiamond,
|
||||
param.Source,
|
||||
param.Remark
|
||||
});
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.LogError(ex, "房间AssetUpdated推送失败 userId={UserId}", param?.UserId);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
using AutoMapper;
|
||||
using CommonService;
|
||||
using FishRoomService.Hubs;
|
||||
using FishRoomService.RoomSend.Response;
|
||||
using RedisService.Param;
|
||||
|
||||
namespace FishRoomService.RoomSend
|
||||
{
|
||||
public class FishingRoomSendService : IFishingRoomSendService
|
||||
{
|
||||
|
||||
public readonly IHubSend<FishRoomHub> _roomSend;
|
||||
public readonly IMapper _mapper;
|
||||
|
||||
public FishingRoomSendService(IHubSend<FishRoomHub> roomSend, IMapper mapper)
|
||||
{
|
||||
_roomSend = roomSend;
|
||||
_mapper = mapper;
|
||||
}
|
||||
|
||||
public void GetRoomListResult(string cid, List<RedisGameRoom> rooms)
|
||||
{
|
||||
var list = _mapper.Map<List<GameRoomReponse>>(rooms);
|
||||
|
||||
if (list != null)
|
||||
list = list.OrderBy(c => c.RoomNumber).ToList();
|
||||
_roomSend.SendUserCId(cid, "GetRoomListResult", list);
|
||||
}
|
||||
|
||||
public void RoomChange(RedisGameRoom room)
|
||||
{
|
||||
string partition = $"{(int)room.GameType}{room.RoomLevel}{room.RoomPartition}";
|
||||
_roomSend.SendGroup(partition, "RoomChange", room);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using RedisService.Param;
|
||||
|
||||
namespace FishRoomService.RoomSend
|
||||
{
|
||||
public interface IFishingRoomSendService
|
||||
{
|
||||
void GetRoomListResult(string cid, List<RedisGameRoom> rooms);
|
||||
|
||||
void RoomChange(RedisGameRoom room);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace FishRoomService.RoomSend.Response
|
||||
{
|
||||
public class GameRoomReponse
|
||||
{
|
||||
public string RoomId { get; set; } = string.Empty;
|
||||
|
||||
public int MaxPlayerCount { get; set; } = 4;
|
||||
|
||||
public int CurrentOnlinePlayerCount { get; set; } = 0;
|
||||
|
||||
|
||||
public int RobotCount { get; set; } = 0;
|
||||
|
||||
public int RoomNumber { get; set; } = 0;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,185 @@
|
||||
using System.Collections.Concurrent;
|
||||
using System.Text.Json;
|
||||
using AutoMapper;
|
||||
using CommonDomain.BaseModel;
|
||||
using CommonDomain;
|
||||
using CommonDomain.Enum;
|
||||
using CommonService;
|
||||
using DotNetCore.CAP;
|
||||
using FishRoomService.Hubs;
|
||||
using FishRoomService.RoomSend;
|
||||
using MongoRepository;
|
||||
using RedisHelper;
|
||||
using RedisService;
|
||||
using RedisService.Param;
|
||||
using UserService.User;
|
||||
|
||||
namespace FishRoomService.RoomService
|
||||
{
|
||||
public class FishingRoomService : IFishingRoomService
|
||||
{
|
||||
|
||||
private readonly ICapPublisher _capPublisher;
|
||||
private readonly IRedisService _redisService;
|
||||
private readonly IHubSend<FishRoomHub> _hubRoom;
|
||||
private readonly IFishingRoomSendService _sendResult;
|
||||
private GameConfig _gameConfig;
|
||||
private readonly IUserService _userService;
|
||||
private readonly IMapper _mapper;
|
||||
private readonly IDistributedLock _distributedLock;
|
||||
private readonly IMongoBaseRepository<BotProfileEntity> _botProfileRepo;
|
||||
private readonly IMongoBaseRepository<EmptyRoomRateConfig> _emptyRoomRateRepo;
|
||||
private List<BotProfileEntity> _initBotProfiles;
|
||||
|
||||
|
||||
public FishingRoomService(ICapPublisher capPublisher, IRedisService redisService, IHubSend<FishRoomHub> hubRoom, IFishingRoomSendService sendResult, IUserService userService, IMapper mapper, IDistributedLock distributedLock, IMongoBaseRepository<BotProfileEntity> botProfileRepo, IMongoBaseRepository<EmptyRoomRateConfig> emptyRoomRateRepo)
|
||||
{
|
||||
_capPublisher = capPublisher;
|
||||
_redisService = redisService;
|
||||
_hubRoom = hubRoom;
|
||||
_sendResult = sendResult;
|
||||
_userService = userService;
|
||||
_botProfileRepo = botProfileRepo;
|
||||
_emptyRoomRateRepo = emptyRoomRateRepo;
|
||||
_gameConfig = redisService.GetGameConfig();
|
||||
if (_gameConfig == null)
|
||||
{
|
||||
var jsonPath = Path.Combine("Config", "gameconfig.json");
|
||||
if (File.Exists(jsonPath))
|
||||
{
|
||||
var json = File.ReadAllText(jsonPath);
|
||||
_gameConfig = JsonSerializer.Deserialize<GameConfig>(json);
|
||||
}
|
||||
if (_gameConfig == null)
|
||||
{
|
||||
_gameConfig = new GameConfig { RoomConfigs = new List<RoomConfig>() };
|
||||
}
|
||||
}
|
||||
_mapper = mapper;
|
||||
_distributedLock = distributedLock;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
public async Task GetRoomList(string cid, string userId, GameTypeEnum gameType, int roomLevel, int roomPartition)
|
||||
{
|
||||
string partition = $"{(int)gameType}{roomLevel}{roomPartition}";
|
||||
var userRedid = _redisService.GetRedisUserCId(userId);
|
||||
if (userRedid != null)
|
||||
{
|
||||
if (!string.IsNullOrWhiteSpace(userRedid.PartitionId))
|
||||
_hubRoom.RemoveGroup(cid, userRedid.PartitionId);
|
||||
userRedid.PartitionId = partition;
|
||||
userRedid.FishRoomCId = cid;
|
||||
if (string.IsNullOrWhiteSpace(userRedid.RoomId))
|
||||
userRedid.CId = cid;
|
||||
}
|
||||
else
|
||||
{
|
||||
userRedid = new RedisUserCid() { UserId = userId, PartitionId = partition, CId = cid, FishRoomCId = cid };
|
||||
}
|
||||
|
||||
_redisService.SetRedisUserCId(userRedid);
|
||||
|
||||
_hubRoom.AddGroup(cid, partition);
|
||||
|
||||
var roomList = _redisService.GetGameRoomList(partition);
|
||||
|
||||
if (roomList == null || roomList.Count() == 0)
|
||||
{
|
||||
await InitRoom(gameType, roomLevel, _gameConfig);
|
||||
roomList = _redisService.GetGameRoomList(partition);
|
||||
}
|
||||
|
||||
_sendResult.GetRoomListResult(cid, roomList.ToList());
|
||||
|
||||
}
|
||||
|
||||
|
||||
public async Task<List<RedisGameRoom>> InitRoom(GameTypeEnum gameType = GameTypeEnum.None, int roomLevel = 0, GameConfig gameConfig = null)
|
||||
{
|
||||
gameConfig ??= _gameConfig;
|
||||
|
||||
List<RedisGameRoom> result = new List<RedisGameRoom>();
|
||||
gameConfig ??= _gameConfig;
|
||||
|
||||
_initBotProfiles = RoomBotFactory.FixedBotSeatsEnabled
|
||||
? _botProfileRepo.FilterBy(p => true).ToList()
|
||||
: null;
|
||||
|
||||
var roomConfig = gameConfig?.RoomConfigs ?? new List<RoomConfig>();
|
||||
if (gameType != GameTypeEnum.None)
|
||||
roomConfig = roomConfig.Where(c => c.GameType == gameType).ToList();
|
||||
if (roomLevel > 0)
|
||||
roomConfig = roomConfig.Where(c => c.RoomLevel == roomLevel).ToList();
|
||||
if (roomConfig == null || roomConfig.Count() == 0)
|
||||
return result;
|
||||
|
||||
foreach (var item in roomConfig)
|
||||
{
|
||||
var rateConfig = _emptyRoomRateRepo
|
||||
.FilterBy(c => c.GameType == item.GameType && c.RoomLevel == item.RoomLevel && !c.IsDelete)
|
||||
.FirstOrDefault();
|
||||
var botsEnabled = gameConfig.BotConfig?.Enabled == true;
|
||||
var emptyRate = botsEnabled ? Math.Clamp(rateConfig?.EmptyRoomRate ?? 0, 0, 100) : 100;
|
||||
var totalRoomCount = item.RoomPartitionNum * item.RoomCount;
|
||||
var roomsWithBots = emptyRate > 0
|
||||
? (int)Math.Floor(totalRoomCount * (100 - emptyRate) / 100.0)
|
||||
: totalRoomCount;
|
||||
var botRoomIndexes = Enumerable.Range(0, totalRoomCount)
|
||||
.OrderBy(_ => global::System.Random.Shared.Next())
|
||||
.Take(roomsWithBots)
|
||||
.ToHashSet();
|
||||
|
||||
for (var i = 1; i <= item.RoomPartitionNum; i++)
|
||||
{
|
||||
_redisService.RemoveGameRoom($"{(int)item.GameType}{item.RoomLevel}{i}");
|
||||
|
||||
for (int c = 0; c < item.RoomCount; c++)
|
||||
{
|
||||
RedisGameRoom room = new RedisGameRoom()
|
||||
{
|
||||
RoomName = item.RoomName,
|
||||
GameType = item.GameType,
|
||||
RoomLevel = item.RoomLevel,
|
||||
RoomPartition = i,
|
||||
RoomNumber = c,
|
||||
MaxPlayerCount = (item.GameType == GameTypeEnum.星际迷航 || item.GameType == GameTypeEnum.中国象棋) ? 2 : 4,
|
||||
CurrentOnlinePlayerCount = 0,
|
||||
|
||||
};
|
||||
var roomIndex = (i - 1) * item.RoomCount + c;
|
||||
room.RobotCount = botsEnabled && botRoomIndexes.Contains(roomIndex)
|
||||
? global::System.Random.Shared.Next(1, room.MaxPlayerCount)
|
||||
: 0;
|
||||
room.RoomId = $"{(int)room.GameType}{room.RoomLevel}{room.RoomPartition}{c.ToString("00")}";
|
||||
|
||||
if (room.RobotCount > 0 && RoomBotFactory.FixedBotSeatsEnabled)
|
||||
{
|
||||
var fixedBots = RoomBotFactory.CreateFixedSeatBots(room, item, gameConfig, _initBotProfiles);
|
||||
if (fixedBots.Count > 0)
|
||||
{
|
||||
room.Players.AddRange(fixedBots);
|
||||
room.RobotCount = fixedBots.Count;
|
||||
}
|
||||
}
|
||||
|
||||
result.Add(room);
|
||||
}
|
||||
}
|
||||
}
|
||||
foreach (var item in result)
|
||||
{
|
||||
_redisService.SetGameRoom(item);
|
||||
}
|
||||
|
||||
return result;
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using CommonDomain;
|
||||
using CommonDomain.Enum;
|
||||
using RedisService.Param;
|
||||
|
||||
namespace FishRoomService.RoomService
|
||||
{
|
||||
public interface IFishingRoomService
|
||||
{
|
||||
|
||||
|
||||
Task GetRoomList(string cid, string userId, GameTypeEnum gameType, int roomLevel, int roomPartition);
|
||||
|
||||
|
||||
Task<List<RedisGameRoom>> InitRoom(GameTypeEnum gameType = GameTypeEnum.None, int roomLevel = 0, GameConfig gameConfig = null);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user