From a1dbce8a96ccfd80fc26cc60d6767a2c1020dba3 Mon Sep 17 00:00:00 2001 From: Putoo <290555932@qq.com> Date: Sun, 5 Jul 2026 18:51:01 +0800 Subject: [PATCH] 111 --- .../logdb/db/game_fight_data.cs | 2 + .../Application.Domain.csproj | 8 + .../BusEvents/BusEventsEnum.cs | 16 ++ .../BusEvents/BusEventsSubscriber.cs | 17 ++ Service/Application.Domain/GlobalUsings.cs | 1 + .../Interface/Fight/IGameFightService.cs | 6 +- .../Service/Fight/GameFightService.cs | 189 +++++++++++++++--- .../Application.Service.Pub.csproj | 1 + .../Controllers/Pub/FightController.cs | 134 +++++++++++-- Service/Application.Web/Program.cs | 12 +- Web/src/pages/fight/index.vue | 27 ++- Web/src/pages/fight/result.vue | 90 ++++++++- Web/src/pages/prop/monster.vue | 2 +- Web/src/services/Index/FightService.ts | 8 + Web/src/utility‌/FightTool.ts | 2 - 15 files changed, 468 insertions(+), 47 deletions(-) create mode 100644 Service/Application.Domain/BusEvents/BusEventsEnum.cs create mode 100644 Service/Application.Domain/BusEvents/BusEventsSubscriber.cs diff --git a/Service/Application.Domain.Entity/logdb/db/game_fight_data.cs b/Service/Application.Domain.Entity/logdb/db/game_fight_data.cs index e376d71..9871963 100644 --- a/Service/Application.Domain.Entity/logdb/db/game_fight_data.cs +++ b/Service/Application.Domain.Entity/logdb/db/game_fight_data.cs @@ -60,6 +60,8 @@ namespace Application.Domain.Entity [SugarColumn(IsNullable = true)] public int? state { get; set; } + [SugarColumn(Length = 50, IsNullable = true)] + public string? winCode { get; set; } /// /// 胜利方 /// diff --git a/Service/Application.Domain/Application.Domain.csproj b/Service/Application.Domain/Application.Domain.csproj index 12fb8c3..874083e 100644 --- a/Service/Application.Domain/Application.Domain.csproj +++ b/Service/Application.Domain/Application.Domain.csproj @@ -10,4 +10,12 @@ + + + + + + + + diff --git a/Service/Application.Domain/BusEvents/BusEventsEnum.cs b/Service/Application.Domain/BusEvents/BusEventsEnum.cs new file mode 100644 index 0000000..5e23a03 --- /dev/null +++ b/Service/Application.Domain/BusEvents/BusEventsEnum.cs @@ -0,0 +1,16 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Application.Domain +{ + public class BusEventsEnum + { + public enum BusEventsName + { + PutFightAward,//战斗奖励事件 + } + } +} \ No newline at end of file diff --git a/Service/Application.Domain/BusEvents/BusEventsSubscriber.cs b/Service/Application.Domain/BusEvents/BusEventsSubscriber.cs new file mode 100644 index 0000000..ceffe71 --- /dev/null +++ b/Service/Application.Domain/BusEvents/BusEventsSubscriber.cs @@ -0,0 +1,17 @@ +namespace Application.Domain +{ + public class BusEventsSubscriber : IEventSubscriber + { + /// + /// 处理贡献提成 + /// + /// + [EventSubscribe(BusEventsEnum.BusEventsName.PutFightAward, NumRetries = 0)] + public async Task HandleQueueBonus(EventHandlerExecutingContext context) + { + var data = context.GetPayload(); + var fightService = App.GetService(); + await fightService.HandleFight(data); + } + } +} \ No newline at end of file diff --git a/Service/Application.Domain/GlobalUsings.cs b/Service/Application.Domain/GlobalUsings.cs index 25af9a9..d0b90ab 100644 --- a/Service/Application.Domain/GlobalUsings.cs +++ b/Service/Application.Domain/GlobalUsings.cs @@ -4,3 +4,4 @@ global using Application.Domain.Entity; global using Photon.Core.Redis; global using Photon.Core.Assist; global using Application.Service.Pub; +global using Jaina; diff --git a/Service/Application.Domain/Services/Interface/Fight/IGameFightService.cs b/Service/Application.Domain/Services/Interface/Fight/IGameFightService.cs index 11bb29a..db5c875 100644 --- a/Service/Application.Domain/Services/Interface/Fight/IGameFightService.cs +++ b/Service/Application.Domain/Services/Interface/Fight/IGameFightService.cs @@ -15,11 +15,15 @@ public interface IGameFightService string scene, string mapId, string userId, long exp = 0, long copper = 0, long petExp = 0, string award = "", string pars = ""); - Task SetFightWin(string fightId, string winUser); + Task SetFightWin(game_fight_data fightData, string winUser); #endregion #region 战斗相关 + Task GetUserFightHarm(string userId); + Task SetUserFightHarm(string userId, int harm); + Task HandleFight(game_fight_data eventData); + #endregion } \ No newline at end of file diff --git a/Service/Application.Domain/Services/Service/Fight/GameFightService.cs b/Service/Application.Domain/Services/Service/Fight/GameFightService.cs index 2bd724a..ad91fee 100644 --- a/Service/Application.Domain/Services/Service/Fight/GameFightService.cs +++ b/Service/Application.Domain/Services/Service/Fight/GameFightService.cs @@ -36,6 +36,12 @@ public class GameFightService(ISqlSugarClient DbClient, IRedisCache redis) : IGa return result; } + private async Task RemoveUserFight(string userId) + { + string key = string.Format(FightCache.FightCacheKey, "UserFight"); + bool result = await redis.AddHashAsync(key, userId, new List()); + } + #endregion #region 战斗信息 @@ -55,7 +61,7 @@ public class GameFightService(ISqlSugarClient DbClient, IRedisCache redis) : IGa } - public async Task AddFightHarm(string fightId,string userId, long harm) + public async Task AddFightHarm(string fightId, string userId, long harm) { string key = string.Format(FightCache.FightCacheKeys, "FightData:Harm", fightId); if (await redis.HExistsHashAsync(key, userId)) @@ -69,19 +75,24 @@ public class GameFightService(ISqlSugarClient DbClient, IRedisCache redis) : IGa await redis.AddHashAsync(key, userId, harm); } } - - public async Task RemoveFightHarm(string fightId,string userId) + + public async Task RemoveFightHarm(string fightId, string userId) { string key = string.Format(FightCache.FightCacheKeys, "FightData:Harm", fightId); await redis.DelHashAsync(key, userId); } - private async Task ClearFightInfoCache(string fightId, string keyId) + private async Task ClearFightInfoCache(string fightId, string keyId, bool remMonsterBool = false) { - string key1 = string.Format(FightCache.FightCacheKeys, "FightData:Info", fightId); - string key2 = string.Format(FightCache.FightCacheKeys, "FightData:Blood", keyId); - await redis.DelAsync(key1, key2); + List keys = new List(); + keys.Add(string.Format(FightCache.FightCacheKeys, "FightData:Info", fightId)); + if (remMonsterBool) + { + keys.Add(string.Format(FightCache.FightCacheKeys, "FightData:Blood", keyId)); + } + + await redis.DelAsync(keys.ToArray()); } public async Task AddFight(string fightId, string areaCode, string keyId, string mainId, string code, @@ -153,28 +164,116 @@ public class GameFightService(ISqlSugarClient DbClient, IRedisCache redis) : IGa return result; } - public async Task SetFightWin(string fightId, string winUser) + public async Task SetFightWin(game_fight_data fightData, string winUser) { bool result = false; - var data = await GetFightInfo(fightId); - if (data != null) + long okTime = TimeExtend.GetTimeStampSeconds; + var db = DbClient.AsTenant().GetConnectionWithAttr(); + if (fightData.code == nameof(GameEnum.FightCode.PVE)) { - long okTime = TimeExtend.GetTimeStampSeconds; - data.state = 1; - data.winUser = winUser; - data.okTime = okTime; - var db = DbClient.AsTenant().GetConnectionWithAttr(); - result = await db.Updateable().SetColumns(it => it.state == 1) - .SetColumns(it => it.winUser == winUser) - .SetColumns(it => it.okTime == okTime) - .Where(it => it.fightId == fightId).ExecuteCommandAsync() > 0; + if (fightData.userId == winUser) + { + var data = await db.Queryable() + .Where(it => + it.keyId == fightData.keyId && it.state == 0 && it.code == nameof(GameEnum.FightCode.PVE)) + .ToListAsync(); + + foreach (var item in data) + { + db.Updateable().SetColumns(it => it.state == 1) + .SetColumns(it => it.winUser == winUser) + .SetColumns(it => it.winCode == nameof(UserEnum.AttrCode.Person)) + .SetColumnsIF(item.userId == winUser, it => it.okTime == okTime) + .Where(it => it.fightId == item.fightId).AddQueue(); + } + + result = await db.SaveQueuesAsync() > 0; + if (result) + { + foreach (var item in data) + { + await ClearFightInfoCache(item.fightId, item.keyId, true); + } + + fightData.state = 1; + fightData.winCode = nameof(UserEnum.AttrCode.Person); + fightData.winUser = winUser; + fightData.okTime = okTime; + //此处调用战斗结束相关 + var _eventPublisher = App.GetService(); + await _eventPublisher.PublishAsync(new ChannelEventSource(BusEventsEnum.BusEventsName.PutFightAward, + fightData)); + } + } + else + { + //清理相关pvp数据 + result = await HandleFightUserDataByPvp(fightData.fightId, fightData.keyId, + nameof(UserEnum.AttrCode.Monster), winUser, fightData.userId, okTime); + if (result) + { + await RemoveUserFight(fightData.userId); + } + } + } + else if (fightData.code == nameof(GameEnum.FightCode.PVP)) + { + string lowUser = fightData.userId == winUser ? fightData.mainId : fightData.userId; + result = await HandleFightUserDataByPvp(fightData.fightId, fightData.keyId, + nameof(UserEnum.AttrCode.Person), winUser, lowUser, okTime); + if (result) + { + await RemoveUserFight(lowUser); + } } + return result; + } + + private async Task HandleFightUserDataByPvp(string fightId, string keyId, string winCode, string winUser, + string lowUser, long okTime) + { + bool result = true; + var db = DbClient.AsTenant().GetConnectionWithAttr(); + var data = await db.Queryable() + .Where(it => it.state == 0 && + ((it.keyId.Contains(lowUser) && it.code == nameof(GameEnum.FightCode.PVP)) || + (it.userId == lowUser && it.code == nameof(GameEnum.FightCode.PVE)))) + .ToListAsync(); + + foreach (var item in data) + { + db.Updateable().SetColumns(it => it.state == 1) + .SetColumns(it => it.winCode == winCode) + .SetColumns(it => it.winUser == winUser) + .SetColumnsIF(item.userId == winUser && winCode == nameof(UserEnum.AttrCode.Person), + it => it.okTime == okTime) + .Where(it => it.fightId == item.fightId).AddQueue(); + } + + result = await db.SaveQueuesAsync() > 0; if (result) { - await ClearFightInfoCache(fightId, data.keyId); - //此处调用战斗结束相关 - await HandleFight(data); + foreach (var item in data) + { + await ClearFightInfoCache(item.fightId, item.keyId, false); + } + + if (winCode == nameof(UserEnum.AttrCode.Person)) + { + var winFight = data.Find(it => it.userId == winUser); + if (winFight != null) + { + winFight.state = 1; + winFight.code = winCode; + winFight.winUser = winUser; + winFight.okTime = okTime; + + var _eventPublisher = App.GetService(); + await _eventPublisher.PublishAsync(new ChannelEventSource(BusEventsEnum.BusEventsName.PutFightAward, + winFight)); + } + } } return result; @@ -184,8 +283,52 @@ public class GameFightService(ISqlSugarClient DbClient, IRedisCache redis) : IGa #region 战斗相关 - private async Task HandleFight(game_fight_data data) + public async Task GetUserFightHarm(string userId) { + int result = 0; + string key = string.Format(FightCache.FightCacheKey, "UserHarm"); + if (await redis.HExistsHashAsync(key, userId)) + { + result = await redis.GetHashAsync(key, userId); + } + + if (result > 0) + { + await redis.AddHashAsync(key, userId, 0); + } + + return result; + } + + public async Task SetUserFightHarm(string userId, int harm) + { + string key = string.Format(FightCache.FightCacheKey, "UserHarm"); + await redis.AddHashAsync(key, userId, harm); + } + + public async Task HandleFight(game_fight_data fightData) + { + string winUser = fightData.winUser; + + #region 发放基础奖励 + + if (fightData.exp > 0) + { + var attrService = App.GetService(); + await attrService.UpdateUserExp(winUser, (long)fightData.exp, 1); + } + + if (fightData.copper > 0) + { + var accService = App.GetService(); + await accService.UpdateUserCopper(winUser, 1, (long)fightData.copper, "击杀怪物"); + } + + if (fightData.petExp > 0) //宠物经验 + { + } + + #endregion } #endregion diff --git a/Service/Application.Service.Pub/Application.Service.Pub.csproj b/Service/Application.Service.Pub/Application.Service.Pub.csproj index 07bdb7a..5d8edfc 100644 --- a/Service/Application.Service.Pub/Application.Service.Pub.csproj +++ b/Service/Application.Service.Pub/Application.Service.Pub.csproj @@ -7,6 +7,7 @@ + diff --git a/Service/Application.Web/Controllers/Pub/FightController.cs b/Service/Application.Web/Controllers/Pub/FightController.cs index 36c454f..745b0e8 100644 --- a/Service/Application.Web/Controllers/Pub/FightController.cs +++ b/Service/Application.Web/Controllers/Pub/FightController.cs @@ -17,10 +17,11 @@ public class FightController : ControllerBase private readonly IGameMapService _mapService; private readonly IUnitUserAccService _accService; private readonly IGameGoodsService _goodsService; + private readonly IUnitUserService _userService; public FightController(IGameFightService fightService, IGameMonsterService monsterService, IUnitUserAttrService attrService, IGameMapService mapService, IUnitUserAccService accService, - IGameGoodsService goodsService) + IGameGoodsService goodsService, IUnitUserService userService) { _fightService = fightService; _monsterService = monsterService; @@ -28,6 +29,7 @@ public class FightController : ControllerBase _mapService = mapService; _accService = accService; _goodsService = goodsService; + _userService = userService; } /// @@ -136,7 +138,7 @@ public class FightController : ControllerBase return PoAction.Message("战斗结束", 100); } - #region 此处处理战斗 + #region 此处处理战斗 FightResultModel fightResult = new FightResultModel() { @@ -144,19 +146,20 @@ public class FightController : ControllerBase }; if (!string.IsNullOrEmpty(parms.data)) { - fightResult = JsonConvert.DeserializeObject(parms.data); + fightResult = JsonConvert.DeserializeObject(parms.data); } - #endregion - + //更新攻击 if (fightResult.result == 0) { myHarm = fightResult.myHarm; + myHarm += await _fightService.GetUserFightHarm(userId); otHarm = fightResult.otHarm; await _attrService.UpdateUserBlood(userId, 1, fightResult.myHarm); } + var myAttr = await _attrService.GetUserAttrModel(userId, fight.scene); UserAttrModel otAttr = new UserAttrModel(); if (fight.code == nameof(GameEnum.FightCode.PVE)) @@ -172,19 +175,36 @@ public class FightController : ControllerBase } else { - otAttr = await _attrService.GetUserAttrModel(fight.mainId, fight.scene); if (fightResult.result == 0) { + await _fightService.SetUserFightHarm(fight.mainId, fightResult.otHarm); await _attrService.UpdateUserBlood(fight.mainId, 1, fightResult.otHarm); } + otAttr = await _attrService.GetUserAttrModel(fight.mainId, fight.scene); } - + //结束战斗都此处直接返回 - if (otAttr.blood < 1||myAttr.blood<1) + if (otAttr.blood < 1 || myAttr.blood < 1) { + await _fightService.RemoveUserFight(userId, fightId); + if (otAttr.blood < 1) + { + await _fightService.SetFightWin(fight, userId); + } + else + { + await _fightService.SetFightWin(fight, fight.mainId); + } await _fightService.RemoveUserFight(userId, fightId); return PoAction.Message("战斗结束", 100); } + else + { + //自动使用药品 + + + } + //获取个人药品栏 var myDrug = await _attrService.GetUserDrug(userId); //获取个人负面 @@ -192,7 +212,7 @@ public class FightController : ControllerBase //冷却时间 int cool = 1000; - if (myAttr.agility > otAttr.agility&&otAttr.agility>0) + if (myAttr.agility > otAttr.agility && otAttr.agility > 0) { decimal diff = myAttr.agility - otAttr.agility; decimal bl = diff / otAttr.agility; @@ -206,10 +226,10 @@ public class FightController : ControllerBase { cool = Convert.ToInt32(cool * (1 + atkCoolData.count * 0.1M)); } - + //更新伤害提示 - - + + int exitCopper = otAttr.lev * 5; var result = new { @@ -274,6 +294,7 @@ public class FightController : ControllerBase { if (await _fightService.RemoveUserFight(userId, fightId)) { + await _fightService.SetFightWin(fight, fight.mainId); await _fightService.RemoveFightHarm(fightId, userId); //移除伤害 var nextFight = myFight.FindAll(it => it != fightId); string nextId = nextFight.Count > 0 ? nextFight[0] : ""; @@ -305,6 +326,7 @@ public class FightController : ControllerBase { return PoAction.Message("战斗不存在!"); } + var fight = await _fightService.GetFightInfo(fightId); if (fight == null) { @@ -317,7 +339,7 @@ public class FightController : ControllerBase await _fightService.RemoveUserFight(userId, fightId); return PoAction.Message("战斗结束!"); } - + var myDrug = await _attrService.GetUserDrug(userId); var onDrug = myDrug.drug.Find(it => it.id == drugId); if (onDrug == null) @@ -355,7 +377,93 @@ public class FightController : ControllerBase { return PoAction.Message("药品使用失败!"); } + } + + /// + /// 战斗信息 + /// + /// + /// + [HttpGet] + public async Task GetFightMsg(string fightId) + { + string userId = StateHelper.userId; + var myFight = await _fightService.GetUserFight(userId); + + var fight = await _fightService.GetFightInfo(fightId); + if (fight == null) + { + return PoAction.Message("战斗不存在!"); + } + + if (fight.userId != userId) + { + return PoAction.Message("战斗不存在!"); + } + + if (fight.state == 0) + { + return PoAction.Message("战斗未完成", 100); + } + + int isWin = 0; + if (fight.winUser == fight.mainId) + { + isWin = 0; + } + else if(fight.winUser==userId) + { + isWin = 1; + } + else + { + isWin = 2; + } + + string otName = string.Empty; + if (isWin == 0) + { + if (fight.code == nameof(GameEnum.FightCode.PVP)) + { + var userInfo = await _userService.GetUserInfoByUserId(fight.winUser); + otName = userInfo.nick; + } + else + { + var monsterInfo = await _monsterService.GetMonsterInfo(fight.winUser); + otName = monsterInfo.name; + } + } + else if (isWin == 1) + { + if (fight.code == nameof(GameEnum.FightCode.PVP)) + { + var userInfo = await _userService.GetUserInfoByUserId(fight.mainId); + otName = userInfo.nick; + } + else + { + var monsterInfo = await _monsterService.GetMonsterInfo(fight.mainId); + otName = monsterInfo.name; + } + } + else + { + if (fight.winCode == nameof(UserEnum.AttrCode.Person)) + { + var userInfo = await _userService.GetUserInfoByUserId(fight.winUser); + otName = userInfo.nick; + } + else + { + var monsterInfo = await _monsterService.GetMonsterInfo(fight.winUser); + otName = monsterInfo.name; + } + } + + var myAttr = await _attrService.GetUserAttrModel(userId, fight.scene); + return PoAction.Ok(new { isWin, otName, blood = myAttr.blood, upBlood = myAttr.upBlood, fight }); } } \ No newline at end of file diff --git a/Service/Application.Web/Program.cs b/Service/Application.Web/Program.cs index 6671f31..050b8c4 100644 --- a/Service/Application.Web/Program.cs +++ b/Service/Application.Web/Program.cs @@ -1,4 +1,3 @@ - using Microsoft.OpenApi.Models; using Photon.Core.Redis; @@ -82,6 +81,17 @@ builder.Services.AddCors(options => #endregion 配置跨域处理,允许所有来源 +#region 事务总线 +// 注册 EventBus 服务 +builder.Services.AddEventBus(builder => +{ + // 注册 ToDo 事件订阅者 + builder.AddSubscriber(); +}); + + +#endregion + builder.Services.AddSignalR(); var app = builder.Build(); diff --git a/Web/src/pages/fight/index.vue b/Web/src/pages/fight/index.vue index b2fbb8b..b2e2d98 100644 --- a/Web/src/pages/fight/index.vue +++ b/Web/src/pages/fight/index.vue @@ -1,7 +1,7 @@