diff --git a/Service/Application.Domain.Entity/game/user/unit_user_run.cs b/Service/Application.Domain.Entity/game/user/unit_user_run.cs new file mode 100644 index 0000000..e8ae7f0 --- /dev/null +++ b/Service/Application.Domain.Entity/game/user/unit_user_run.cs @@ -0,0 +1,69 @@ +using SqlSugar; +using System; + +namespace Application.Domain.Entity +{ + [Tenant("Kg.SeaTime.Game")] + public class unit_user_run + { + /// + /// userId + /// + [SugarColumn(IsPrimaryKey = true, Length = 50)] + public string userId { get; set; } + + /// + /// 区服 + /// + [SugarColumn(IsNullable = true)] + public int? areaId { get; set; } + + /// + /// 路线 + /// + [SugarColumn(Length = 255, IsNullable = true)] + public string? lineCode { get; set; } + + /// + /// onMap + /// + [SugarColumn(Length = 10, IsNullable = true)] + public string? onMap { get; set; } + + /// + /// toMap + /// + [SugarColumn(Length = 10, IsNullable = true)] + public string? toMap { get; set; } + + /// + /// 距离 + /// + [SugarColumn(IsNullable = true)] + public int? distance { get; set; } + + /// + /// 位置 + /// + [SugarColumn(IsNullable = true)] + public int? position { get; set; } + + /// + /// 深度 + /// + [SugarColumn(IsNullable = true)] + public int? depth { get; set; } + + /// + /// 状态 + /// + [SugarColumn(IsNullable = true)] + public int? status { get; set; } + + /// + /// 更新时间 + /// + [SugarColumn(IsNullable = true)] + public long? upTime { get; set; } + } +} \ No newline at end of file diff --git a/Service/Application.Domain.Entity/game/user/unit_user_ship.cs b/Service/Application.Domain.Entity/game/user/unit_user_ship.cs index 92f84f7..790a786 100644 --- a/Service/Application.Domain.Entity/game/user/unit_user_ship.cs +++ b/Service/Application.Domain.Entity/game/user/unit_user_ship.cs @@ -41,5 +41,11 @@ namespace Application.Domain.Entity /// [SugarColumn(IsNullable = true)] public int? weight { get; set; } + + /// + /// copper + /// + [SugarColumn(IsNullable = true)] + public int? copper { get; set; } } } \ No newline at end of file diff --git a/Service/Application.Domain/Services/Interface/Map/IGameMapService.cs b/Service/Application.Domain/Services/Interface/Map/IGameMapService.cs index 0dba7d9..ced31fa 100644 --- a/Service/Application.Domain/Services/Interface/Map/IGameMapService.cs +++ b/Service/Application.Domain/Services/Interface/Map/IGameMapService.cs @@ -5,6 +5,7 @@ public interface IGameMapService #region 城市地图数据 Task GetCityInfo(int cityId); + Task GetCityInfoByMapId(string mapId); Task> GetCityData(); Task> GetCityMap(int cityId); Task> GetCityShowMap(int cityId); @@ -41,5 +42,15 @@ public interface IGameMapService Task> CreateAutoMap(string start, string end); + #endregion + + #region 航海 + + Task GetUserRun(string userId); + Task StopUserRun(string userId); + Task SaveUserRunInfo(string userId, int areaId, string onMap, string toMap); + + Task UpdateUserRunInfo(unit_user_run data); + #endregion } \ No newline at end of file diff --git a/Service/Application.Domain/Services/Service/Map/GameMapService.cs b/Service/Application.Domain/Services/Service/Map/GameMapService.cs index d824e64..232bd1a 100644 --- a/Service/Application.Domain/Services/Service/Map/GameMapService.cs +++ b/Service/Application.Domain/Services/Service/Map/GameMapService.cs @@ -17,6 +17,18 @@ public class GameMapService(ISqlSugarClient DbClient, IRedisCache redis) : IGame return data; } + public async Task GetCityInfoByMapId(string mapId) + { + var data = await GetMapInfo(mapId); + if (data != null) + { + return await GetCityInfo((int)data.cityId); + } + else + { + return new game_city(); + } + } public async Task> GetCityData() { @@ -88,6 +100,7 @@ public class GameMapService(ISqlSugarClient DbClient, IRedisCache redis) : IGame return 0; } } + public async Task> GetMapNpc(string mapId) { @@ -566,4 +579,102 @@ public class GameMapService(ISqlSugarClient DbClient, IRedisCache redis) : IGame } #endregion + + #region 航海 + + public async Task GetUserRun(string userId) + { + string key = string.Format(UserCache.BaseCacheKey, "UserMapRun"); + if (await redis.HExistsHashAsync(key, userId)) + { + return await redis.GetHashAsync(key, userId); + } + + var db = DbClient.AsTenant().GetConnectionWithAttr(); + var data = await db.Queryable().Where(it => it.userId == userId).SingleAsync(); + if (data == null) + { + data = await ResetUserRun(userId,false); + } + + await redis.AddHashAsync(key, userId, data); + return data; + } + + private async Task ClearUserRunCache(string userId) + { + string key = string.Format(UserCache.BaseCacheKey, "UserMapRun"); + await redis.DelHashAsync(key, userId); + } + + private async Task ResetUserRun(string userId, bool ClearCache = true) + { + unit_user_run runInfo = new unit_user_run(); + runInfo.userId = userId; + runInfo.areaId = 0; + runInfo.lineCode = ""; + runInfo.onMap = ""; + runInfo.toMap = ""; + runInfo.distance = 0; + runInfo.position = 0; + runInfo.depth = 0; + runInfo.status = 0; + runInfo.upTime = TimeExtend.GetTimeStampSeconds; + var db = DbClient.AsTenant().GetConnectionWithAttr(); + bool result = await db.Saveable(runInfo).ExecuteCommandAsync() > 0; + if (result) + { + if (ClearCache) + { + await ClearUserRunCache(userId); + } + + return runInfo; + } + + return null; + } + + public async Task StopUserRun(string userId) + { + var data = await ResetUserRun(userId, true); + return data == null ? false : true; + } + + public async Task SaveUserRunInfo(string userId, int areaId, string onMap, string toMap) + { + unit_user_run runInfo = new unit_user_run(); + runInfo.userId = userId; + runInfo.areaId = areaId; + runInfo.lineCode = StringAssist.GetSortKey(onMap, toMap); + runInfo.onMap = onMap; + runInfo.toMap = toMap; + int mile = GameTool.ComputeMile(onMap, toMap); + runInfo.distance = mile; + runInfo.position = 0; + runInfo.depth = 0; + runInfo.status = 1; + runInfo.upTime = TimeExtend.GetTimeStampSeconds; + var db = DbClient.AsTenant().GetConnectionWithAttr(); + bool result = await db.Saveable(runInfo).ExecuteCommandAsync() > 0; + if (result) + { + await ClearUserRunCache(userId); + } + + return result; + } + public async Task UpdateUserRunInfo(unit_user_run data) + { + string key = string.Format(UserCache.BaseCacheKey, "UserMapRun"); + bool result = await redis.AddHashAsync(key, data.userId, data); + if (result) + { + var db = DbClient.AsTenant().GetConnectionWithAttr(); + await db.Updateable(data).ExecuteCommandAsync(); + } + + return result; + } + #endregion } \ No newline at end of file diff --git a/Service/Application.Web/Controllers/Map/MapController.cs b/Service/Application.Web/Controllers/Map/MapController.cs index 5a5cbf1..e2b33a5 100644 --- a/Service/Application.Web/Controllers/Map/MapController.cs +++ b/Service/Application.Web/Controllers/Map/MapController.cs @@ -46,6 +46,15 @@ public class MapController : ControllerBase int area = StateHelper.areaId; game_city_map mapInfo = new game_city_map(); + #region 前置条件处理 + var userRunInfo = await _mapService.GetUserRun(userId); + if (userRunInfo.status != 0) + { + return PoAction.Message("正在航行状态", 103); + } + + #endregion + #region 地图导向处理 bool isSelfMap = false; @@ -97,7 +106,18 @@ public class MapController : ControllerBase #endregion - object ret = new { mapInfo, cityInfo, npcData, chatData, cityShow, nearUser, noReadMsg = noReadMsg[3] }; + + + object ret = new + { + mapInfo, + cityInfo, + npcData, + chatData, + cityShow, + nearUser, + noReadMsg = noReadMsg[3] + }; return PoAction.Ok(ret); } @@ -298,7 +318,7 @@ public class MapController : ControllerBase } var MySeaMap = await _mapService.GetUserCityMapData(userId); - if (MySeaMap.Any(it => it.cityId == cityId)==false) + if (MySeaMap.Any(it => it.cityId == cityId) == false) { return PoAction.Message("您暂未获取该城市海图!"); } @@ -345,6 +365,210 @@ public class MapController : ControllerBase } } + /// + /// 用户航海接口 + /// + /// + /// + /// + [HttpGet] + public async Task UserRunMap(int npcId, int cityId) + { + string userId = StateHelper.userId; + + #region NPC验证 + + var npcInfo = await _mapService.GetNpcInfo(npcId); + if (npcInfo == null) + { + return PoAction.Message("Npc不存在!"); + } + + if (npcInfo.status != 1) + { + return PoAction.Message("Npc不存在!"); + } + + if (!npcInfo.bus.Any(it => it.code == nameof(GameEnum.NpcBusCode.MapTo))) + { + return PoAction.Message("业务不可用!"); + } + + var onMap = await _mapService.GetUserOnMap(userId); + if (npcInfo.mapId != onMap.mapId) + { + return PoAction.Message("Npc不存在!"); + } + + #endregion + + var cityInfo = await _mapService.GetCityInfo(cityId); + if (cityInfo == null) + { + return PoAction.Message("城市不存在!"); + } + + + var onMapInfo = await _mapService.GetMapInfo(onMap.mapId); + if (onMapInfo.cityId == cityId) + { + return PoAction.Message("您已在当前城市,无需航行!"); + } + + var MySeaMap = await _mapService.GetUserCityMapData(userId); + if (MySeaMap.Any(it => it.cityId == cityId) == false) + { + return PoAction.Message("您暂未获取该城市海图!"); + } + + var userShip = await _weightService.GetUserShip(userId); + if (userShip.Count == 0) + { + return PoAction.Message("购买船只后才可以航行哦!"); + } + + var runInfo = await _mapService.GetUserRun(userId); + if (runInfo.status != 0) + { + return PoAction.Message("您已经在航线上啦!"); + } + + bool isCanTo = false; + var MyLev = await _attrService.GetUserLev(userId); + if (MyLev < 80) + { + isCanTo = true; + } + + int need = 0; + if (isCanTo == false) //判断费用 + { + var myAcc = await _accService.GetUserAccInfo(userId, nameof(AccEnum.AccType.copper)); + int jl = GameTool.ComputeMile(onMap.mapId, cityInfo.toMap); + need = userShip.Max(it => (int)it.copper) * jl; + if (myAcc < need) + { + return PoAction.Message("铜贝不足!"); + } + + isCanTo = true; + } + + if (isCanTo) + { + if (await _mapService.SaveUserRunInfo(userId, StateHelper.areaId, onMap.mapId, cityInfo.toMap)) + { + if (need > 0) + { + await _accService.UpdateUserCopper(userId, 0, need, $"传送到【{cityInfo.cityName}】费用"); + } + + return PoAction.Ok(true); + } + else + { + return PoAction.Message("传送失败,请稍后尝试!"); + } + } + else + { + return PoAction.Message("传送失败,请稍后尝试!"); + } + } + + + /// + /// 获取用户航行状态 + /// + /// + [HttpGet] + public async Task GetUserRun() + { + var userId = StateHelper.userId; + var runInfo = await _mapService.GetUserRun(userId); + if (runInfo.status != 1) + { + return PoAction.Message("不在航行状态", 100); + } + + var onCity = await _mapService.GetCityInfoByMapId(runInfo.onMap); + var toCity = await _mapService.GetCityInfoByMapId(runInfo.toMap); + int isShip = 0; + int safety = 0; + + return PoAction.Ok(new + { + onCity = onCity.cityName, + toCity = toCity.cityName, + distance = runInfo.distance, + position = runInfo.position, + isShip = isShip, + safety = safety + }); + } + + /// + /// 取消航行 + /// + /// + [HttpGet] + public async Task StopUserRun() + { + var userId = StateHelper.userId; + var runInfo = await _mapService.GetUserRun(userId); + if (runInfo.status != 1) + { + return PoAction.Message("不在航行状态", 100); + } + + if (await _mapService.StopUserRun(userId)) + { + return PoAction.Ok(true); + } + else + { + return PoAction.Message("取消失败,请稍后尝试!"); + } + } + + [HttpGet] + public async Task UserMapRuning() + { + var userId = StateHelper.userId; + var runInfo = await _mapService.GetUserRun(userId); + if (runInfo.status != 1) + { + return PoAction.Message("不在航行状态", 100); + } + var userShip = await _weightService.GetUserShip(userId); + if (userShip.Count == 0) + { + return PoAction.Message("购买船只后才可以航行哦!"); + } + + int spend = userShip.Sum(it => (int)it.speed) / userShip.Count; + if ((runInfo.position + spend) >= runInfo.distance) + { + await _mapService.StopUserRun(userId); + var onMap = await _mapService.GetUserOnMap(userId); + await _mapService.UpdateUserOnMap(onMap, runInfo.toMap); + return PoAction.Message("航行完成!", 100); + } + else + { + runInfo.position += spend; + runInfo.upTime = TimeExtend.GetTimeStampSeconds; + if (await _mapService.UpdateUserRunInfo(runInfo)) + { + return PoAction.Ok(true); + } + else + { + return PoAction.Message("航行错误,请重试!"); + } + } + } + #endregion #region npc相关 diff --git a/Web/src/pages/map/index.vue b/Web/src/pages/map/index.vue index b38fefa..c7d27c7 100644 --- a/Web/src/pages/map/index.vue +++ b/Web/src/pages/map/index.vue @@ -120,6 +120,9 @@ const BindData = async (map: string): Promise => { console.log(result.data); } + else if (result.code == 103) { + PageExtend.Redirect("/map/runing"); + } else { MessageExtend.ShowDialog("异常错误", result.msg); } diff --git a/Web/src/pages/map/run.vue b/Web/src/pages/map/run.vue index 41a40c8..4561547 100644 --- a/Web/src/pages/map/run.vue +++ b/Web/src/pages/map/run.vue @@ -1 +1,75 @@ - \ No newline at end of file + + \ No newline at end of file diff --git a/Web/src/pages/map/runing.vue b/Web/src/pages/map/runing.vue new file mode 100644 index 0000000..83cb20f --- /dev/null +++ b/Web/src/pages/map/runing.vue @@ -0,0 +1,104 @@ + + \ No newline at end of file diff --git a/Web/src/pages/map/to.vue b/Web/src/pages/map/to.vue index c053286..3b923b4 100644 --- a/Web/src/pages/map/to.vue +++ b/Web/src/pages/map/to.vue @@ -26,7 +26,6 @@ definePageMeta({ }) const area = ref>([]); const city = ref>([]);; -const copper = ref(''); const tips = ref(''); const cityId = ref(0); onMounted(async () => { diff --git a/Web/src/services/map/MapService.ts b/Web/src/services/map/MapService.ts index 137c4c4..6811016 100644 --- a/Web/src/services/map/MapService.ts +++ b/Web/src/services/map/MapService.ts @@ -47,6 +47,38 @@ export class MapService { return await ApiService.Request("get", "/Map/Map/UserToMap", { npcId, cityId }); } + /** + * 用户航海接口 + * GET /Map/Map/UserRunMap + */ + static async UserRunMap(npcId: number, cityId: number) { + return await ApiService.Request("get", "/Map/Map/UserRunMap", { npcId, cityId }); + } + + /** + * 获取用户航行状态 + * GET /Map/Map/GetUserRun + */ + static async GetUserRun() { + return await ApiService.Request("get", "/Map/Map/GetUserRun"); + } + + /** + * 取消航行 + * GET /Map/Map/StopUserRun + */ + static async StopUserRun() { + return await ApiService.Request("get", "/Map/Map/StopUserRun"); + } + + /** + * UserMapRuning + * GET /Map/Map/UserMapRuning + */ + static async UserMapRuning() { + return await ApiService.Request("get", "/Map/Map/UserMapRuning"); + } + /** * 获取NPC相关信息 * GET /Map/Map/GetNpcInfo diff --git a/Web/src/utility‌/GameTool.ts b/Web/src/utility‌/GameTool.ts index 314ce84..452b716 100644 --- a/Web/src/utility‌/GameTool.ts +++ b/Web/src/utility‌/GameTool.ts @@ -110,5 +110,21 @@ export class GameTool { return result; } + public static GetSeaMapSafetyName(safety: number) { + let result = "安全海域"; + switch (safety) { + case 0: + result = "安全海域"; + break; + case 1: + result = "普通海域"; + break; + case 2: + result = "危险海域"; + break; + } + return result; + } + } \ No newline at end of file