添加项目文件。

This commit is contained in:
2026-10-12 16:22:04 +08:00
parent 7c68a0ca0a
commit aad11be43d
1000 changed files with 120807 additions and 0 deletions
+20
View File
@@ -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>();
}
}
}
+21
View File
@@ -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>
+54
View File
@@ -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);
}
}
}
+14
View File
@@ -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);
}
}
+79
View File
@@ -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);
}
}