- Directory.Build.props: 生成 XML 注释供 Swagger 展示中文说明 - AdminHost/FishGameHost: 接入 Swashbuckle,路由 adminswagger / roomswagger - 后台前端 config.js 改为同源相对地址,适配反向代理 - socket.html(SignalR 协议文档)纳入仓库 - deploy/: 本机构建(容器内编译,规避杀软)、服务器替换脚本、Nginx 配置
275 lines
12 KiB
C#
275 lines
12 KiB
C#
using System.Text.Json;
|
|
using AutoMapper;
|
|
using Common.Utils;
|
|
using CommonService;
|
|
using FishGameService.GameSend;
|
|
using FishGameService.Hubs;
|
|
using FishGameService.Services;
|
|
using Microsoft.Extensions.Logging;
|
|
using RedisService.Param;
|
|
using StackExchange.Redis;
|
|
|
|
namespace Service.Fishing
|
|
{
|
|
public class FishingSendService : IFishingSendService
|
|
{
|
|
|
|
public readonly IHubSend<FishGameHub> _hubSend;
|
|
public readonly IMapper _mapper;
|
|
private readonly ISubscriber _subscriber;
|
|
private readonly ILogger<FishingSendService> _logger;
|
|
|
|
public FishingSendService(IHubSend<FishGameHub> hubSend, IMapper mapper, IConnectionMultiplexer redis, ILogger<FishingSendService> logger)
|
|
{
|
|
_hubSend = hubSend;
|
|
_mapper = mapper;
|
|
_subscriber = redis.GetSubscriber();
|
|
_logger = logger;
|
|
}
|
|
public void BindSuccess(string cid)
|
|
{
|
|
_hubSend.SendUserCId(cid, "BindSuccess", "绑定成功");
|
|
}
|
|
public void ErrorMessage(string cid, int code, string msg)
|
|
{
|
|
_hubSend.SendUserCId(cid, "Exception", new { code, message = msg });
|
|
}
|
|
|
|
|
|
|
|
public void KillNotice(string FishId, string userName, long gold = 0)
|
|
{
|
|
var msg = JsonSerializer.Serialize(new { Target = "All", Event = "KillNotice", Data = new { FishId, userName, gold } });
|
|
_subscriber.Publish("fishgame:global", msg);
|
|
}
|
|
|
|
public void KillNotice(string FishId, string userName, long gold, string fishName, long multiplier,
|
|
string gameTypeName, string roomName, long timestamp)
|
|
{
|
|
var text = $"恭喜玩家{userName}在{gameTypeName}{roomName}捕获 {fishName}*{multiplier}炮倍 {gold}大奖";
|
|
var data = new
|
|
{
|
|
Text = text,
|
|
UserName = userName,
|
|
GameTypeName = gameTypeName,
|
|
RoomName = roomName,
|
|
FishName = fishName,
|
|
Multiple = multiplier,
|
|
Gold = gold,
|
|
Time = timestamp,
|
|
FishId
|
|
};
|
|
var msg = JsonSerializer.Serialize(new { Target = "All", Event = "KillNotice", Data = data });
|
|
_subscriber.Publish("fishgame:global", msg);
|
|
}
|
|
|
|
public async Task SendRoomInfo(string cid, RedisGameRoom roomInfo, List<ActiveFish> activeFishes = null)
|
|
{
|
|
object payload;
|
|
List<object> compatibilityFishPayload = null;
|
|
if (activeFishes != null && activeFishes.Count > 0)
|
|
{
|
|
var now = DateTimeOffset.UtcNow;
|
|
var activeFishPayload = activeFishes
|
|
.Where(f => string.IsNullOrWhiteSpace(f.FishArrayNumber))
|
|
.Select(f => (object)new
|
|
{
|
|
fishId = f.FishId,
|
|
fishIds = new[] { f.FishId },
|
|
fishNumber = f.FishNumber,
|
|
routeId = f.ClientRouteId,
|
|
fishArrayNumber = string.Empty,
|
|
createdAt = new DateTimeOffset(f.CreatedAt).ToUnixTimeMilliseconds(),
|
|
createdTime = f.CreatedAt.ToString("yyyy-MM-dd HH:mm:ss.fff"),
|
|
expireAt = new DateTimeOffset(f.ExpireAt).ToUnixTimeMilliseconds(),
|
|
expireTime = f.ExpireAt.ToString("yyyy-MM-dd HH:mm:ss.fff"),
|
|
remainingSeconds = (int)Math.Max(0, (new DateTimeOffset(f.ExpireAt) - now).TotalSeconds)
|
|
})
|
|
.Concat(
|
|
activeFishes
|
|
.Where(f => !string.IsNullOrWhiteSpace(f.FishArrayNumber))
|
|
.GroupBy(f => f.FishArrayNumber)
|
|
.Select(group =>
|
|
{
|
|
var first = group.First();
|
|
return (object)new
|
|
{
|
|
fishId = first.FishId,
|
|
fishIds = group.Select(f => f.FishId).ToList(),
|
|
fishNumber = string.Empty,
|
|
routeId = first.ClientRouteId,
|
|
fishArrayNumber = first.FishArrayNumber,
|
|
createdAt = new DateTimeOffset(first.CreatedAt).ToUnixTimeMilliseconds(),
|
|
createdTime = first.CreatedAt.ToString("yyyy-MM-dd HH:mm:ss.fff"),
|
|
expireAt = new DateTimeOffset(group.Min(f => f.ExpireAt)).ToUnixTimeMilliseconds(),
|
|
expireTime = group.Min(f => f.ExpireAt).ToString("yyyy-MM-dd HH:mm:ss.fff"),
|
|
remainingSeconds = (int)Math.Max(0, (new DateTimeOffset(group.Min(f => f.ExpireAt)) - now).TotalSeconds)
|
|
};
|
|
}))
|
|
.ToList();
|
|
compatibilityFishPayload = activeFishes
|
|
.Where(f => string.IsNullOrWhiteSpace(f.FishArrayNumber) && f.FishType == 1)
|
|
.Select(f => (object)new
|
|
{
|
|
fishId = f.FishId,
|
|
fishIds = new[] { f.FishId },
|
|
fishNumber = f.FishNumber,
|
|
routeId = f.ClientRouteId,
|
|
fishArrayNumber = string.Empty,
|
|
createdAt = new DateTimeOffset(f.CreatedAt).ToUnixTimeMilliseconds(),
|
|
createdTime = f.CreatedAt.ToString("yyyy-MM-dd HH:mm:ss.fff"),
|
|
expireAt = new DateTimeOffset(f.ExpireAt).ToUnixTimeMilliseconds(),
|
|
expireTime = f.ExpireAt.ToString("yyyy-MM-dd HH:mm:ss.fff"),
|
|
remainingSeconds = (int)Math.Max(0, (new DateTimeOffset(f.ExpireAt) - now).TotalSeconds)
|
|
}).ToList();
|
|
|
|
payload = new
|
|
{
|
|
roomInfo.RoomId,
|
|
roomInfo.RoomName,
|
|
roomInfo.GameType,
|
|
roomInfo.RoomLevel,
|
|
roomInfo.RoomPartition,
|
|
roomInfo.RoomNumber,
|
|
roomInfo.MaxPlayerCount,
|
|
roomInfo.CurrentOnlinePlayerCount,
|
|
roomInfo.RobotCount,
|
|
roomInfo.Players,
|
|
roomInfo.CreateUserId,
|
|
roomInfo.SystemFactor,
|
|
activeFishes = activeFishPayload
|
|
};
|
|
|
|
|
|
}
|
|
else
|
|
{
|
|
payload = roomInfo;
|
|
}
|
|
await _hubSend.SendUserCIdAsync(cid, "RoomInfo", payload);
|
|
if (compatibilityFishPayload != null && compatibilityFishPayload.Count > 0)
|
|
{
|
|
_ = SendInitialFishAfterSceneReady(cid, roomInfo.RoomId, compatibilityFishPayload);
|
|
}
|
|
}
|
|
|
|
private async Task SendInitialFishAfterSceneReady(string cid, string roomId, List<object> initialFishPayload)
|
|
{
|
|
try
|
|
{
|
|
await Task.Delay(300);
|
|
var syncNow = DateTimeOffset.UtcNow;
|
|
await _hubSend.SendUserCIdAsync(cid, "OnFishSpawn", new
|
|
{
|
|
type = "init",
|
|
timestamp = syncNow.ToUnixTimeMilliseconds(),
|
|
serverTime = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.fff"),
|
|
fish = initialFishPayload
|
|
});
|
|
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
_logger.LogWarning(ex,
|
|
"[Socket][FishSpawnData] 首屏鱼延迟补发失败 roomId={RoomId} targetCid={Cid} fishCount={FishCount}",
|
|
roomId, cid, initialFishPayload.Count);
|
|
}
|
|
}
|
|
public void RoomKillNotice(string roomId, string fishNumber, string userId, long gold, string fishId, long timespan, double beishu = 1,long skillsGold=0,int fishScore=1, object param = null, object drop = null, long gainExp = 0, long exp = 0, int level = 0, long expMax = 0)
|
|
{
|
|
|
|
var killtime=DateTime.Now.ToTimeStamp();
|
|
|
|
_hubSend.SendGroup(roomId, "RoomKillNotice", new { fishNumber, userId, gold, fishId, timespan, killtime, msg = $"时间:{killtime - timespan}秒", beishu, skillsGold, fishScore, param, drop, gainExp, exp, level, expMax });
|
|
}
|
|
|
|
|
|
public void RoomDisconnectNotice(string roomId, string userId)
|
|
{
|
|
_hubSend.SendGroup(roomId, "RoomDisconnectNotice", userId);
|
|
}
|
|
|
|
public void RoomJoinNotice(string roomId, RedisGamePlayer player)
|
|
{
|
|
_hubSend.SendGroup(roomId, "RoomJoinNotice", player);
|
|
}
|
|
|
|
public void ChangeGunMultipleNotice(string roomId, string userId, int multiple)
|
|
{
|
|
_hubSend.SendGroup(roomId, "ChangeGunMultipleNotice", new { userId, multiple });
|
|
}
|
|
|
|
public void RoomFireNotice(string roomId, string userId, List<string> bulletIds, long gold, int count, object extra = null, bool isBot = false)
|
|
{
|
|
_hubSend.SendGroup(roomId, "RoomFireNotice", new { userId, bulletIds, gold, count, extra, isBot });
|
|
}
|
|
|
|
public Task RoomFireNoticeAsync(string roomId, string callerCid, string userId, List<string> bulletIds, long gold, int count, object extra = null, bool isBot = false)
|
|
{
|
|
var payload = new { userId, bulletIds, gold, count, extra, isBot };
|
|
return Task.WhenAll(
|
|
_hubSend.SendUserCIdAsync(callerCid, "RoomFireNotice", payload),
|
|
_hubSend.GroupExceptAsync(callerCid, roomId, "RoomFireNotice", payload));
|
|
}
|
|
|
|
|
|
public void SyncPlayerGold(string cid, long gold)
|
|
{
|
|
_hubSend.SendUserCId(cid, "SyncPlayerGold", gold);
|
|
}
|
|
public void SendPlayerInfo(string cid, RedisGamePlayer player)
|
|
{
|
|
_hubSend.SendUserCId(cid, "SendPlayerInfoResult", player?.Gold);
|
|
}
|
|
|
|
|
|
public void RoomLeaveNotice(string roomId, string userId)
|
|
{
|
|
_hubSend.SendGroup(roomId, "RoomLeaveNotice", userId);
|
|
}
|
|
|
|
|
|
public void BotLeaveRoomNotice(string roomId, string userId)
|
|
{
|
|
_hubSend.SendGroup(roomId, "BotLeaveRoomNotice", new { userId });
|
|
}
|
|
|
|
|
|
public void ChangeControllerUser(string roomId, string userId)
|
|
{
|
|
_hubSend.SendGroup(roomId, "ChangeControllerUser", userId);
|
|
}
|
|
|
|
public void HostDisconnectNotice(string roomId)
|
|
{
|
|
_hubSend.SendGroup(roomId, "HostDisconnect", null);
|
|
}
|
|
|
|
|
|
public void SyncGameData(string roomId, object data)
|
|
{
|
|
_hubSend.SendGroup(roomId, "SyncGameData", data);
|
|
}
|
|
|
|
public void UsePropNotice(string roomId, string userId, string propNumber)
|
|
{
|
|
_hubSend.SendGroup(roomId, "UsePropNotice", new { userId, propNumber });
|
|
}
|
|
|
|
public void TorpedoResultNotice(string roomId, string userId, string propNumber, long gold, string color)
|
|
{
|
|
_hubSend.SendGroup(roomId, "TorpedoResultNotice", new { userId, propNumber, gold, color });
|
|
}
|
|
|
|
public void PlayerAfkNotice(string roomId, string userId)
|
|
{
|
|
_hubSend.SendGroup(roomId, "PlayerAfkNotice", new { userId });
|
|
}
|
|
|
|
public void PlayerCancelAfkNotice(string roomId, string userId)
|
|
{
|
|
_hubSend.SendGroup(roomId, "PlayerCancelAfkNotice", new { userId });
|
|
}
|
|
}
|
|
}
|