This commit is contained in:
Putoo
2026-05-25 18:41:27 +08:00
parent 590f7c5290
commit 0afbf6e39a
32 changed files with 2137 additions and 101 deletions

View File

@@ -1,5 +1,6 @@
<wpf:ResourceDictionary xml:space="preserve" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:s="clr-namespace:System;assembly=mscorlib" xmlns:ss="urn:shemas-jetbrains-com:settings-storage-xaml" xmlns:wpf="http://schemas.microsoft.com/winfx/2006/xaml/presentation">
<s:String x:Key="/Default/CodeInspection/ExcludedFiles/FilesAndFoldersToSkip2/=7020124F_002D9FFC_002D4AC3_002D8F3D_002DAAB8E0240759_002Ff_003AIRedisCache_002Ecs_002Fl_003AC_0021_003FUsers_003F29055_003FAppData_003FRoaming_003FJetBrains_003FRider2025_002E3_003Fresharper_002Dhost_003FDecompilerCache_003Fdecompiler_003F55e5569a0f314a0db6a665eafad446dd6800_003F9e_003F88bbb06d_003FIRedisCache_002Ecs/@EntryIndexedValue">ForceIncluded</s:String>
<s:String x:Key="/Default/CodeInspection/ExcludedFiles/FilesAndFoldersToSkip2/=7020124F_002D9FFC_002D4AC3_002D8F3D_002DAAB8E0240759_002Ff_003AISqlSugarClient_002Ecs_002Fl_003AC_0021_003FUsers_003F29055_003FAppData_003FRoaming_003FJetBrains_003FRider2025_002E3_003Fresharper_002Dhost_003FDecompilerCache_003Fdecompiler_003F6c0f22f0a47643a3b2a40899acd2044c2e3a00_003F5b_003F113fef0a_003FISqlSugarClient_002Ecs/@EntryIndexedValue">ForceIncluded</s:String>
<s:String x:Key="/Default/CodeInspection/ExcludedFiles/FilesAndFoldersToSkip2/=7020124F_002D9FFC_002D4AC3_002D8F3D_002DAAB8E0240759_002Ff_003AJwtExtensions_002Ecs_002Fl_003AC_0021_003FUsers_003F29055_003FAppData_003FRoaming_003FJetBrains_003FRider2025_002E3_003Fresharper_002Dhost_003FDecompilerCache_003Fdecompiler_003F6b089d08a87d4ddd82371ae63e754ba05000_003F26_003Fd6433acb_003FJwtExtensions_002Ecs/@EntryIndexedValue">ForceIncluded</s:String>
<s:String x:Key="/Default/CodeInspection/ExcludedFiles/FilesAndFoldersToSkip2/=7020124F_002D9FFC_002D4AC3_002D8F3D_002DAAB8E0240759_002Ff_003AJwtHelper_002Ecs_002Fl_003AC_0021_003FUsers_003F29055_003FAppData_003FRoaming_003FJetBrains_003FRider2025_002E3_003Fresharper_002Dhost_003FDecompilerCache_003Fdecompiler_003F6b089d08a87d4ddd82371ae63e754ba05000_003Fe2_003F86047f24_003FJwtHelper_002Ecs/@EntryIndexedValue">ForceIncluded</s:String>
<s:String x:Key="/Default/CodeInspection/ExcludedFiles/FilesAndFoldersToSkip2/=7020124F_002D9FFC_002D4AC3_002D8F3D_002DAAB8E0240759_002Ff_003AJwtSecurityTokenHandler_002Ecs_002Fl_003AC_0021_003FUsers_003F29055_003FAppData_003FRoaming_003FJetBrains_003FRider2025_002E3_003Fresharper_002Dhost_003FSourcesCache_003Ff9d3fc33fd2fba97d4e718534a67f1d3c61e492634cd51c4798ce5621f780f3_003FJwtSecurityTokenHandler_002Ecs/@EntryIndexedValue">ForceIncluded</s:String>

View File

@@ -63,8 +63,8 @@ namespace Application.Domain.Entity
/// <summary>
/// qualityAttr
/// </summary>
[SugarColumn(Length = 2000, IsNullable = true)]
public string? qualityAttr { get; set; }
[SugarColumn( IsNullable = true,IsJson = true)]
public List<AttrItem>? qualityAttr { get; set; }
/// <summary>
/// sex
@@ -172,7 +172,7 @@ namespace Application.Domain.Entity
/// useEndTime
/// </summary>
[SugarColumn(IsNullable = true)]
public DateTime? useEndTime { get; set; }
public long? useEndTime { get; set; }
/// <summary>
/// weight
@@ -189,8 +189,8 @@ namespace Application.Domain.Entity
/// <summary>
/// sysPrice
/// </summary>
[SugarColumn(Length = 10, IsNullable = true)]
public decimal? sysPrice { get; set; }
[SugarColumn(IsNullable = true)]
public int? sysPrice { get; set; }
/// <summary>
/// canEqualUp
@@ -199,28 +199,28 @@ namespace Application.Domain.Entity
public int? canEqualUp { get; set; }
/// <summary>
/// EquAttr
/// 装备属性
/// </summary>
[SugarColumn(IsNullable = true)]
public string? EquAttr { get; set; }
[SugarColumn(IsNullable = true,IsJson = true)]
public List<AttrItem>? EquAttr { get; set; }
/// <summary>
/// EquMent
/// 附魔属性
/// </summary>
[SugarColumn(IsNullable = true)]
public string? EquMent { get; set; }
[SugarColumn(IsNullable = true,IsJson = true)]
public EquMent? EquMent { get; set; }
/// <summary>
/// EquAwaken
/// 觉醒属性
/// </summary>
[SugarColumn(IsNullable = true)]
public string? EquAwaken { get; set; }
[SugarColumn(IsNullable = true,IsJson = true)]
public List<EquAwaken>? EquAwaken { get; set; }
/// <summary>
/// GemMent
/// 宝石属性
/// </summary>
[SugarColumn(IsNullable = true)]
public string? GemMent { get; set; }
[SugarColumn(IsNullable = true,IsJson = true)]
public List<EquGem>? GemMent { get; set; }
/// <summary>
/// isDeal
@@ -235,33 +235,21 @@ namespace Application.Domain.Entity
public int? isGive { get; set; }
/// <summary>
/// score
/// </summary>
[SugarColumn(IsNullable = true)]
public int? score { get; set; }
/// <summary>
/// start
/// 星级
/// </summary>
[SugarColumn(IsNullable = true)]
public int? start { get; set; }
/// <summary>
/// exp
/// 0不需要鉴定 1需要鉴定
/// </summary>
[SugarColumn(IsNullable = true)]
public int? exp { get; set; }
public int? isAppr { get; set; }
/// <summary>
/// startAttr
/// 是否穿戴
/// </summary>
[SugarColumn(IsNullable = true)]
public string? startAttr { get; set; }
/// <summary>
/// swallow
/// </summary>
[SugarColumn(IsNullable = true)]
public string? swallow { get; set; }
public int? isOn { get; set; }
}
}

View File

@@ -45,8 +45,8 @@ namespace Application.Domain.Entity
/// <summary>
/// count
/// </summary>
[SugarColumn(Length = 65, IsNullable = true)]
public decimal? count { get; set; }
[SugarColumn(IsNullable = true)]
public long? count { get; set; }
/// <summary>
/// weight
@@ -57,8 +57,8 @@ namespace Application.Domain.Entity
/// <summary>
/// sysPrice
/// </summary>
[SugarColumn(Length = 18, IsNullable = true)]
public decimal? sysPrice { get; set; }
[SugarColumn(IsNullable = true)]
public int? sysPrice { get; set; }
/// <summary>
/// 0不可交易1可交易

View File

@@ -0,0 +1,36 @@
namespace Application.Domain.Entity;
public class AttrItem
{
private System.String _code;
/// <summary>
///
/// </summary>
public System.String code
{ get { return this._code; } set { this._code = value; } }
private System.String _compute;
/// <summary>
///
/// </summary>
public System.String compute
{ get { return this._compute; } set { this._compute = value; } }
private System.Decimal _parameter;
/// <summary>
///
/// </summary>
public System.Decimal parameter
{ get { return this._parameter; } set { this._parameter = value; } }
private System.String _tip;
/// <summary>
///
/// </summary>
public System.String tip
{ get { return this._tip; } set { this._tip = value; } }
}

View File

@@ -0,0 +1,37 @@
namespace Application.Domain.Entity;
public class EquAwaken
{
private System.String _atId;
/// <summary>
///
/// </summary>
public System.String atId
{ get { return this._atId; } set { this._atId = value; } }
private System.Int32 _lev;
/// <summary>
///
/// </summary>
public System.Int32 lev
{ get { return this._lev; } set { this._lev = value; } }
private System.String _name;
/// <summary>
///
/// </summary>
public System.String name
{ get { return this._name; } set { this._name = value; } }
private List<AttrItem> _awaken;
/// <summary>
///
/// </summary>
[SqlSugar.SugarColumn(ColumnDataType = "varchar(max)", IsJson = true)]
public List<AttrItem> awaken
{ get { return this._awaken; } set { this._awaken = value; } }
}

View File

@@ -0,0 +1,50 @@
namespace Application.Domain.Entity;
public class EquGem
{
private System.String _Id;
/// <summary>
///
/// </summary>
public System.String Id
{ get { return this._Id; } set { this._Id = value; } }
private System.Int32 _goodsId;
/// <summary>
///
/// </summary>
public System.Int32 goodsId
{ get { return this._goodsId; } set { this._goodsId = value; } }
private System.String _goodsName;
/// <summary>
///
/// </summary>
public System.String goodsName
{ get { return this._goodsName; } set { this._goodsName = value; } }
private System.Int32? _isDeal;
/// <summary>
///
/// </summary>
public System.Int32? isDeal
{ get { return this._isDeal; } set { this._isDeal = value; } }
public EquGemItem gemItem { get; set; }
}
public class EquGemItem
{
private System.String _place;
/// <summary>
///
/// </summary>
public System.String place
{ get { return this._place; } set { this._place = value; } }
public List<AttrItem> GemAttr { get; set; }
}

View File

@@ -0,0 +1,45 @@
namespace Application.Domain.Entity;
public class EquMent
{
private System.String _name;
/// <summary>
///
/// </summary>
public System.String name
{ get { return this._name; } set { this._name = value; } }
private System.Int32 _goodsId;
/// <summary>
///
/// </summary>
public System.Int32 goodsId
{ get { return this._goodsId; } set { this._goodsId = value; } }
private System.Int32? _isDeal;
/// <summary>
///
/// </summary>
public System.Int32? isDeal
{ get { return this._isDeal; } set { this._isDeal = value; } }
private System.Int32? _isGive;
/// <summary>
///
/// </summary>
public System.Int32? isGive
{ get { return this._isGive; } set { this._isGive = value; } }
private List<AttrItem> _EquAttr;
/// <summary>
///
/// </summary>
[SqlSugar.SugarColumn(ColumnDataType = "varchar(max)", IsJson = true)]
public List<AttrItem> EquAttr
{ get { return this._EquAttr; } set { this._EquAttr = value; } }
}

View File

@@ -0,0 +1,171 @@
using SqlSugar;
using System;
namespace Application.Domain.Entity
{
[Tenant("Kg.SeaTime.Resource")]
public class game_equ
{
/// <summary>
/// equId
/// </summary>
[SugarColumn(IsPrimaryKey = true)]
public int equId { get; set; }
/// <summary>
/// equName
/// </summary>
[SugarColumn(Length = 50, IsNullable = true)]
public string? equName { get; set; }
/// <summary>
/// lev
/// </summary>
[SugarColumn(IsNullable = true)]
public int? lev { get; set; }
/// <summary>
/// quality
/// </summary>
[SugarColumn(IsNullable = true)]
public int? quality { get; set; }
/// <summary>
/// code
/// </summary>
[SugarColumn(Length = 50, IsNullable = true)]
public string? code { get; set; }
/// <summary>
/// sex
/// </summary>
[SugarColumn(Length = 50, IsNullable = true)]
public string? sex { get; set; }
/// <summary>
/// img
/// </summary>
[SugarColumn(Length = 50, IsNullable = true)]
public string? img { get; set; }
/// <summary>
/// minAtk
/// </summary>
[SugarColumn(IsNullable = true)]
public int? minAtk { get; set; }
/// <summary>
/// maxAtk
/// </summary>
[SugarColumn(IsNullable = true)]
public int? maxAtk { get; set; }
/// <summary>
/// defense
/// </summary>
[SugarColumn(Length = 50, IsNullable = true)]
public string? defense { get; set; }
/// <summary>
/// agility
/// </summary>
[SugarColumn(Length = 50, IsNullable = true)]
public string? agility { get; set; }
/// <summary>
/// blood
/// </summary>
[SugarColumn(Length = 50, IsNullable = true)]
public string? blood { get; set; }
/// <summary>
/// morale
/// </summary>
[SugarColumn(Length = 50, IsNullable = true)]
public string? morale { get; set; }
/// <summary>
/// 0非套装
/// </summary>
[SugarColumn(Length = 50, IsNullable = true)]
public string? suitCode { get; set; }
/// <summary>
/// durability
/// </summary>
[SugarColumn(IsNullable = true)]
public int? durability { get; set; }
/// <summary>
/// 是否可强化
/// </summary>
[SugarColumn(IsNullable = true)]
public int? isIntensify { get; set; }
/// <summary>
/// holeCount
/// </summary>
[SugarColumn(IsNullable = true)]
public int? holeCount { get; set; }
/// <summary>
/// 0永久 其他为小时
/// </summary>
[SugarColumn(IsNullable = true)]
public int? useTime { get; set; }
/// <summary>
/// weight
/// </summary>
[SugarColumn(IsNullable = true)]
public int? weight { get; set; }
/// <summary>
/// remark
/// </summary>
[SugarColumn(IsNullable = true)]
public string? remark { get; set; }
/// <summary>
/// source
/// </summary>
[SugarColumn(Length = 255, IsNullable = true)]
public string? source { get; set; }
/// <summary>
/// sysPrice
/// </summary>
[SugarColumn(IsNullable = true)]
public int? sysPrice { get; set; }
/// <summary>
/// equAttr
/// </summary>
[SugarColumn(IsNullable = true,IsJson = true)]
public List<AttrItem>? equAttr { get; set; }
/// <summary>
/// 可穿戴数量
/// </summary>
[SugarColumn(IsNullable = true)]
public int? canEqualUp { get; set; }
/// <summary>
/// 0不可交易1可交易
/// </summary>
[SugarColumn(IsNullable = true)]
public int? isDeal { get; set; }
/// <summary>
/// 0不可赠送 1可赠送
/// </summary>
[SugarColumn(IsNullable = true)]
public int? isGive { get; set; }
/// <summary>
/// 0不需要鉴定 1需要鉴定
/// </summary>
[SugarColumn(IsNullable = true)]
public int? isAppr { get; set; }
}
}

View File

@@ -58,7 +58,7 @@ namespace Application.Domain.Entity
/// sysPrice
/// </summary>
[SugarColumn(Length = 18, IsNullable = true)]
public decimal? sysPrice { get; set; }
public int? sysPrice { get; set; }
/// <summary>
/// content

View File

@@ -0,0 +1,6 @@
namespace Application.Domain;
public static class EquEnum
{
}

View File

@@ -7,5 +7,12 @@ public static class GoodsEnum
Drug,//药品
Prop,//物品
Cargo,//货物
Gem,//宝石
Mak,//材料
Palace,//九宫
Paper,//图纸
Card,//附魔卡片
Mark,//圣痕
Pack,//宝箱
}
}

View File

@@ -2,5 +2,22 @@
public interface IGameEquService
{
#region
Task<game_equ> GetEquInfo(int equId);
#endregion
#region
Task<List<unit_user_equ>> GetUserEquData(string userId, int type, string equName, int PageIndex, int PageSize,
RefAsync<int> Total);
Task<List<unit_user_equ>> GetUserEquData(string userId, int equId);
Task<bool> AddUserEqu(string userId, int equId, int count, string remark);
Task<bool> DeductUserEqu(string userId, List<unit_user_equ> equData, string remark);
Task<bool> DeductUserEqu(string userId, int equId, int count, string remark);
#endregion
}

View File

@@ -15,7 +15,7 @@ public interface IGameGoodsService
Task<unit_user_goods> GetUserGoodsInfo(string userId, int goodsId);
Task<int> GetUserGoodsCount(string userId, int goodsId);
Task<List<unit_user_goods>> GetUserGoodsData(string userId, List<string> code, string search, int page,
Task<List<unit_user_goods>> GetUserGoodsData(string userId, List<string> code, List<string> noCode, string search, int page,
int limit, RefAsync<int> total);
Task<bool> UpdateUserGoods(string userId, int op, int goodsId, int count, string remark = "");

View File

@@ -5,8 +5,10 @@ public interface IGameMapService
#region
Task<game_city> GetCityInfo(int cityId);
Task<List<game_city>> GetCityData();
Task<List<game_city_map>> GetCityMap(int cityId);
Task<List<game_city_map>> GetCityShowMap(int cityId);
Task<game_city_map> GetMapInfo(string mapId);
Task<List<game_city_map>> GetMapCity(int cityId);
Task<int> GetMapCityByMapId(string mapId);
Task<List<game_city_npc>> GetMapNpc(string mapId);
Task<game_city_npc> GetNpcInfo(int npcId);
@@ -17,7 +19,9 @@ public interface IGameMapService
Task<string> GetUserOnMapId(string userId);
Task<unit_user_online> GetUserOnMap(string userId);
Task UpdateUserOnMap(string userId, string ip, string mapId);
Task<bool> UpdateUserOnMap(unit_user_online data, string mapId);
Task SetUserMapDefult(string userId);
Task<game_city_map> GetToMapInfo(string userId, string toMap, bool isUpUserMap = true, bool isChangeCity = false);
#endregion
#region
@@ -27,5 +31,12 @@ public interface IGameMapService
Task<List<UserModel>> GetMapUser(string mapId, int area, int showArea, List<string> noUser, int page,
int limit, RefAsync<int> total);
#endregion
#region
Task<List<MapLine>> CreateAutoMap(string start, string end);
#endregion
}

View File

@@ -0,0 +1,7 @@
namespace Application.Domain;
public interface IUnitUserAttrService
{
Task<unit_user_blood> GetUserBlood(string userId);
Task<bool> UpdateUserBlood(string userId, int op, int count, bool mustUp = false);
}

View File

@@ -2,4 +2,237 @@
public class GameEquService(ISqlSugarClient DbClient, IRedisCache redis) : IGameEquService, ITransient
{
#region
public async Task<game_equ> GetEquInfo(int equId)
{
string key = string.Format(BaseCache.BaseCacheKeys, "EquData", "EquInfo");
var data = await redis.GetHashAsync<game_equ>(key, equId.ToString());
if (data == null)
{
var db = DbClient.AsTenant().GetConnectionWithAttr<game_equ>();
data = await db.Queryable<game_equ>().Where(it => it.equId == equId).SingleAsync();
await redis.AddHashAsync(key, equId.ToString(), data);
}
return data;
}
#endregion
#region
public async Task<List<unit_user_equ>> GetUserEquData(string userId, int type, string equName, int PageIndex,
int PageSize, RefAsync<int> Total)
{
long onTime = TimeExtend.GetTimeStampSeconds;
var db = DbClient.AsTenant().GetConnectionWithAttr<unit_user_equ>();
return await db.Queryable<unit_user_equ>().Where(it => it.userId == userId)
.WhereIF(type == 2, it => it.useEndTime < onTime)
.WhereIF(type == 1, it => it.isOn == 1)
.WhereIF(type == 3, it => it.isAppr == 0)
.WhereIF(!string.IsNullOrEmpty(equName),
it => it.equName.Contains(equName) || it.unitEquName.Contains(equName))
.OrderByDescending(it => it.lev)
.OrderByDescending(it => it.ueId).ToPageListAsync(PageIndex, PageSize, Total);
}
public async Task<List<unit_user_equ>> GetUserEquData(string userId, int equId)
{
long onTime = TimeExtend.GetTimeStampSeconds;
var db = DbClient.AsTenant().GetConnectionWithAttr<unit_user_equ>();
return await db.Queryable<unit_user_equ>().Where(it => it.userId == userId && it.equId == equId).ToListAsync();
}
public async Task<bool> AddUserEqu(string userId, int equId, int count, string remark)
{
bool result = false;
var equ = await GetEquInfo(equId);
if (equ != null)
{
List<unit_user_equ> adds = new List<unit_user_equ>();
for (int i = 0; i < count; i++)
{
unit_user_equ ue = new unit_user_equ();
string ueId = StringAssist.NewGuid;
ue.ueId = ueId;
ue.userId = userId;
ue.owerId = userId;
ue.equId = equ.equId;
ue.equName = equ.equName;
ue.unitEquName = equ.equName;
ue.img = equ.img;
ue.sign = "";
if (equ.isAppr == 0)
{
ue.minAtk = equ.minAtk;
ue.maxAtk = equ.maxAtk;
ue.Defense = Convert.ToInt32(equ.defense);
ue.Agility = Convert.ToInt32(equ.agility);
ue.Morale = Convert.ToInt32(equ.morale);
ue.Blood = Convert.ToInt32(equ.blood);
ue.isAppr = 1;
}
else
{
ue.minAtk = 0;
ue.maxAtk = 0;
ue.Defense = 0;
ue.Agility = 0;
ue.Morale = 0;
ue.Blood = 0;
ue.isAppr = 0;
}
ue.code = equ.code;
ue.suitCode = equ.suitCode;
ue.lev = equ.lev;
ue.durability = equ.durability;
ue.maxdurability = equ.durability;
ue.isIntensify = equ.isIntensify;
ue.intensifyLev = 0;
ue.isLock = 0;
ue.holeCount = equ.holeCount;
ue.sex = equ.sex;
ue.quality = 0;
ue.qualityName = "普通";
ue.qualityAttr = new List<AttrItem>();
ue.weight = equ.weight;
ue.sysPrice = equ.sysPrice;
ue.EquAttr = equ.equAttr;
ue.canEqualUp = equ.canEqualUp;
ue.isDeal = equ.isDeal;
ue.isGive = equ.isGive;
ue.opTime = 0;
ue.start = 0;
ue.EquMent = new EquMent();
ue.EquAwaken = new List<EquAwaken>();
ue.GemMent = new List<EquGem>();
ue.useEndTime = TimeExtend.GetTimeStampBySeconds(DateTime.Now.AddYears(20));
adds.Add(ue);
}
if (adds.Count > 0)
{
var db = DbClient.AsTenant().GetConnectionWithAttr<unit_user_equ>();
result = await db.Insertable(adds).ExecuteCommandAsync() > 0;
}
if (result)
{
//添加日志
await AddEquLog(adds, 1, remark, userId, true);
//更新负重
int weightCount = Convert.ToInt32(equ.weight) * count;
if (weightCount > 0)
{
var attrService = App.GetService<IUnitUserWeight>();
await attrService.UpdateUserWeight(userId, 1, weightCount);
}
}
}
return result;
}
public async Task<bool> DeductUserEqu(string userId, List<unit_user_equ> equData, string remark)
{
bool result = false;
List<string> DelEqu = new List<string>();
List<unit_user_equ_log> logs = new List<unit_user_equ_log>();
int weightCount = 0;
foreach (var item in equData)
{
weightCount += (int)item.weight;
DelEqu.Add(item.ueId);
//生成日志集合
unit_user_equ_log log = new unit_user_equ_log();
log.logId = StringAssist.NewGuid;
log.ueId = item.ueId;
log.userId = item.userId;
log.code = nameof(GameEnum.LogCode.);
log.equData = item;
log.remark = remark;
log.addTime = DateTime.Now;
logs.Add(log);
}
if (DelEqu.Count > 0)
{
var db = DbClient.AsTenant().GetConnectionWithAttr<unit_user_equ>();
result = await db.Deleteable<unit_user_equ>().Where(i => DelEqu.Contains(i.ueId)).ExecuteCommandAsync() > 0;
if (result) //生成成功
{
//更新负重
if (weightCount > 0)
{
var attrService = App.GetService<IUnitUserWeight>();
await attrService.UpdateUserWeight(userId, 0, weightCount);
}
if (logs.Count > 0)
{
await AddEquLog(logs);
}
}
}
return result;
}
public async Task<bool> DeductUserEqu(string userId, int equId, int count, string remark)
{
var userEqu = await GetUserEquData(userId, equId);
if (userEqu.Count < 1)
{
return false;
}
userEqu = userEqu.FindAll(it => it.isLock == 0);
if (userEqu.Count < count)
{
return false;
}
userEqu = userEqu.OrderBy(it => (int)it.intensifyLev)
.OrderBy(it => it.quality)
.ToList();
var opData = userEqu.Take(count).ToList();
return await DeductUserEqu(userId, opData, remark);
}
private async Task AddEquLog(List<unit_user_equ> ues, int code, string remark, string userId,
bool isAddAttr = false)
{
List<unit_user_equ_log> adds = new List<unit_user_equ_log>();
foreach (var item in ues)
{
unit_user_equ_log bagLog = new unit_user_equ_log();
bagLog.logId = StringAssist.NewGuid;
bagLog.userId = userId;
bagLog.ueId = item.ueId;
bagLog.code = code == 0
? bagLog.code = nameof(GameEnum.LogCode.)
: bagLog.code = nameof(GameEnum.LogCode.);
if (isAddAttr)
{
bagLog.equData = item;
}
bagLog.addTime = DateTime.Now;
bagLog.remark = remark;
adds.Add(bagLog);
}
var db = DbClient.AsTenant().GetConnectionWithAttr<unit_user_equ_log>();
await db.Insertable(adds).ExecuteCommandAsync();
}
private async Task AddEquLog(List<unit_user_equ_log> logs)
{
var db = DbClient.AsTenant().GetConnectionWithAttr<unit_user_equ_log>();
await db.Insertable(logs).ExecuteCommandAsync();
}
#endregion
}

View File

@@ -55,12 +55,13 @@ public class GameGoodsService(ISqlSugarClient DbClient, IRedisCache redis) : IGa
return info == null ? 0 : (int)info.count;
}
public async Task<List<unit_user_goods>> GetUserGoodsData(string userId, List<string> code, string search, int page,
public async Task<List<unit_user_goods>> GetUserGoodsData(string userId, List<string> code, List<string> noCode, string search, int page,
int limit, RefAsync<int> total)
{
var db = DbClient.AsTenant().GetConnectionWithAttr<unit_user_goods>();
return await db.Queryable<unit_user_goods>().Where(it => it.userId == userId && it.count > 0)
.WhereIF(code.Count > 0, it => code.Contains(it.code))
.WhereIF(noCode.Count > 0, it => !noCode.Contains(it.code))
.WhereIF(!string.IsNullOrEmpty(search), it => it.goodsName.Contains(search))
.OrderBy(it => it.lev, OrderByType.Desc)
.OrderBy(it => it.count, OrderByType.Desc)

View File

@@ -6,7 +6,7 @@ public class GameMapService(ISqlSugarClient DbClient, IRedisCache redis) : IGame
public async Task<game_city> GetCityInfo(int cityId)
{
string key = string.Format(BaseCache.BaseCacheKeys, "MapCityData", "CityData");
string key = string.Format(BaseCache.BaseCacheKeys, "CityData", "CityInfo");
var data = await redis.GetHashAsync<game_city>(key, cityId.ToString());
if (data == null)
{
@@ -18,9 +18,53 @@ public class GameMapService(ISqlSugarClient DbClient, IRedisCache redis) : IGame
return data;
}
public async Task<List<game_city>> GetCityData()
{
string key = string.Format(BaseCache.BaseCacheKeys, "CityData", "CityData");
var data = await redis.GetAsync<List<game_city>>(key);
if (data == null)
{
var db = DbClient.AsTenant().GetConnectionWithAttr<game_city>();
data = await db.Queryable<game_city>().ToListAsync();
await redis.SetAsync(key, data);
}
return data;
}
public async Task<List<game_city_map>> GetCityMap(int cityId)
{
string key = string.Format(BaseCache.BaseCacheKeys, "CityData", "CityMap");
var data = await redis.GetHashAsync<List<game_city_map>>(key, cityId.ToString());
if (data == null)
{
var db = DbClient.AsTenant().GetConnectionWithAttr<game_city_map>();
data = await db.Queryable<game_city_map>().Where(it => it.cityId == cityId).ToListAsync();
await redis.AddHashAsync(key, cityId.ToString(), data);
}
return data;
}
public async Task<List<game_city_map>> GetCityShowMap(int cityId)
{
string key = string.Format(BaseCache.BaseCacheKeys, "CityData", "CityShowMap");
var data = await redis.GetHashAsync<List<game_city_map>>(key, cityId.ToString());
if (data == null)
{
var db = DbClient.AsTenant().GetConnectionWithAttr<game_city_map>();
data = await db.Queryable<game_city_map>().Where(it => it.cityId == cityId && it.show == 1).ToListAsync();
await redis.AddHashAsync(key, cityId.ToString(), data);
}
return data;
}
public async Task<game_city_map> GetMapInfo(string mapId)
{
string key = string.Format(BaseCache.BaseCacheKeys, "MapCityData", "MapData");
string key = string.Format(BaseCache.BaseCacheKeys, "CityData", "MapData");
var data = await redis.GetHashAsync<game_city_map>(key, mapId);
if (data == null)
{
@@ -32,19 +76,6 @@ public class GameMapService(ISqlSugarClient DbClient, IRedisCache redis) : IGame
return data;
}
public async Task<List<game_city_map>> GetMapCity(int cityId)
{
string key = string.Format(BaseCache.BaseCacheKeys, "MapCityData", "CityShowMap");
var data = await redis.GetHashAsync<List<game_city_map>>(key, cityId.ToString());
if (data == null)
{
var db = DbClient.AsTenant().GetConnectionWithAttr<game_city_map>();
data = await db.Queryable<game_city_map>().Where(it => it.cityId == cityId && it.show == 1).ToListAsync();
await redis.AddHashAsync(key, cityId.ToString(), data);
}
return data;
}
public async Task<int> GetMapCityByMapId(string mapId)
{
@@ -61,7 +92,7 @@ public class GameMapService(ISqlSugarClient DbClient, IRedisCache redis) : IGame
public async Task<List<game_city_npc>> GetMapNpc(string mapId)
{
string key = string.Format(BaseCache.BaseCacheKeys, "MapCityData", "NpcData");
string key = string.Format(BaseCache.BaseCacheKeys, "CityData", "NpcData");
var data = await redis.GetHashAsync<List<game_city_npc>>(key, mapId);
if (data == null)
{
@@ -75,7 +106,7 @@ public class GameMapService(ISqlSugarClient DbClient, IRedisCache redis) : IGame
public async Task<game_city_npc> GetNpcInfo(int npcId)
{
string key = string.Format(BaseCache.BaseCacheKeys, "MapCityData", "NpcInfo");
string key = string.Format(BaseCache.BaseCacheKeys, "CityData", "NpcInfo");
var data = await redis.GetHashAsync<game_city_npc>(key, npcId.ToString());
if (data == null)
{
@@ -131,6 +162,119 @@ public class GameMapService(ISqlSugarClient DbClient, IRedisCache redis) : IGame
}
}
public async Task<bool> UpdateUserOnMap(unit_user_online data, string mapId)
{
data.mapId = mapId;
data.upTime = TimeAssist.GetTimeStampNum;
string key = string.Format(UserCache.BaseCacheKey, "UserOnline");
if (await redis.AddHashAsync(key, data.userId, data))
{
var db = DbClient.AsTenant().GetConnectionWithAttr<unit_user_online>();
await db.Updateable<unit_user_online>(data).ExecuteCommandAsync();
}
return true;
}
public async Task SetUserMapDefult(string userId)
{
var userMap = await GetUserOnMap(userId);
var MapInfo = await GetMapInfo(userMap.mapId);
if (MapInfo != null)
{
await UpdateUserOnMap(userMap, MapInfo.retMap);
}
}
public async Task<game_city_map> GetToMapInfo(string userId, string toMap, bool isUpUserMap = true,
bool isChangeCity = false)
{
bool result = false;
var onMapUser = await GetUserOnMap(userId);
var onMap = onMapUser.mapId;
var onMapInfo = await GetMapInfo(onMap);
var mapInfo = await GetMapInfo(toMap);
if (onMap == toMap) //相同地图不更新
{
if (isUpUserMap)
{
await UpdateUserOnMap(onMapUser, toMap);
}
return mapInfo;
}
else
{
//更新挂机,结束挂机
}
if (mapInfo == null)
{
var myOnMap = await GetMapInfo(onMap);
return myOnMap;
}
if (isChangeCity)
{
result = true;
}
else
{
if (mapInfo.show == 1)
{
result = true;
}
else
{
string[] onMaps = onMap.Split('_');
int onMapX = Convert.ToInt32(onMaps[0]);
int onMapY = Convert.ToInt32(onMaps[1]);
if (onMapX == mapInfo.x)
{
if (onMapY == (mapInfo.y - 1) || onMapY == (mapInfo.y + 1))
{
result = true;
}
}
else
{
if (onMapY == mapInfo.y)
{
if (onMapX == (mapInfo.x - 1) || onMapX == (mapInfo.x + 1))
{
result = true;
}
}
}
}
//当传送有效时,此处判断是否跨城市
if (result)
{
result = onMapInfo.cityId == mapInfo.cityId;
}
}
if (isUpUserMap && result)
{
result = await UpdateUserOnMap(onMapUser, toMap);
}
if (result)
{
if (mapInfo.lockTime > 0)
{
// await SetUserMapLock(userId, (int)mapInfo.lockTime); //增加地图锁定
}
return mapInfo;
}
else
{
return onMapInfo;
}
}
#endregion
#region
@@ -173,6 +317,199 @@ public class GameMapService(ISqlSugarClient DbClient, IRedisCache redis) : IGame
.ToList();
}
#endregion
#region
private async Task<List<game_city>> GetCityDataExcludeParent()
{
string key = string.Format(BaseCache.BaseCacheKeys, "MapPathData", "CityParent");
var data = await redis.GetAsync<List<game_city>>(key);
if (data == null)
{
var db = DbClient.AsTenant().GetConnectionWithAttr<game_city>();
data = await db.Queryable<game_city>().Where(it => it.parent != 0).ToListAsync();
await redis.SetAsync(key, data);
}
return data;
}
private async Task<List<game_city_map>> GetAllMaoToData()
{
string key = string.Format(BaseCache.BaseCacheKeys, "MapPathData", "CityInterCityPortal");
if (await redis.ExistsAsync(key))
{
return await redis.GetAsync<List<game_city_map>>(key);
}
List<game_city_map> result = new List<game_city_map>();
var cityData = await GetCityDataExcludeParent();
foreach (var item in cityData)
{
if (!string.IsNullOrEmpty(item.toMap))
{
var map = await GetMapInfo(item.toMap);
if (map != null)
{
result.Add(map);
}
}
}
await redis.SetAsync(key, result);
return result;
}
/// <summary>
/// 城市信息
/// </summary>
/// <returns></returns>
private async Task<List<CityNode>> GetCityNode()
{
string key = string.Format(BaseCache.BaseCacheKeys, "MapPathData", "CityNode");
var data = await redis.GetAsync<List<CityNode>>(key);
if (data == null)
{
data = new List<CityNode>();
var cityData = await GetCityDataExcludeParent(); //获取所有城市
foreach (var city in cityData)
{
var mdMap = await GetMapInfo(city.toMap);
if (mdMap != null)
{
var cityTemp = new CityNode(city.cityId, city.cityName, new Point((int)mdMap.x, (int)mdMap.y),
mdMap.mapName, (int)city.x_s, (int)city.x_e, (int)city.y_s, (int)city.y_e);
data.Add(cityTemp);
}
}
await redis.SetAsync(key, data);
}
return data;
}
/// <summary>
/// 城市网络
/// </summary>
/// <returns></returns>
private async Task<Dictionary<int, List<game_city_map>>> GetCityRoadNetwork()
{
string key = string.Format(BaseCache.BaseCacheKeys, "MapPathData", "CityRoadNetwork");
var data = await redis.GetAsync<Dictionary<int, List<game_city_map>>>(key);
if (data == null)
{
data = new Dictionary<int, List<game_city_map>>();
var cityData = await GetCityDataExcludeParent(); //获取所有城市
foreach (var city in cityData)
{
//添加地图
var mapData = await GetCityMap(city.cityId);
data.Add(city.cityId, mapData);
}
await redis.SetAsync(key, data);
}
return data;
}
/// <summary>
/// 传送点信息
/// </summary>
/// <returns></returns>
private async Task<List<InterCityPortal>> GetCityInterCityPortal()
{
string key = string.Format(BaseCache.BaseCacheKeys, "CityData", "CityInterCityPortal");
var data = await redis.GetAsync<List<InterCityPortal>>(key);
if (data == null)
{
data = new List<InterCityPortal>();
var toAddr = await GetAllMaoToData(); //获取所有传送点
var cityData = await GetCityDataExcludeParent(); //获取所有城市
foreach (var item in toAddr)
{
var toMapInfo = await GetMapInfo(item.retMap);
//获取反向传送点
var retAddr = cityData.Find(it => it.cityId == (int)item.cityId);
data.Add(new InterCityPortal(item.mapId, (int)item.cityId, new Point((int)item.x, (int)item.y),
(int)toMapInfo.cityId, item.mapName, 1, retAddr.toMap));
}
await redis.SetAsync(key, data);
}
return data;
}
private async Task<List<MapLine>> FinderMapLine(Point start, Point end)
{
//初始化
var globalNetwork = new GlobalRoadNetwork();
//注册城市
var NodeData = await GetCityNode();
NodeData.ForEach(item => { globalNetwork.AddCity(item); });
//注册传送点
var CityInterCityPortal = await GetCityInterCityPortal();
CityInterCityPortal.ForEach(item => { globalNetwork.AddPortal(item); });
var pathFinder = new CrossCityPathFinder(globalNetwork); //初始化寻找器
//注册城市网络
List<CityRoadNetwork> NetworkData = new List<CityRoadNetwork>();
var NetworkCityData = await GetCityRoadNetwork();
foreach (var cityNet in NetworkCityData)
{
var cityNetwork = new CityRoadNetwork(cityNet.Key);
foreach (var map in cityNet.Value)
{
cityNetwork.AddWalkablePoint((int)map.x, (int)map.y);
}
NetworkData.Add(cityNetwork);
}
NetworkData.ForEach(item => { pathFinder.AddCityRoadNetwork(item); });
//获取所有城市ID
var cityData = await GetCityDataExcludeParent();
List<int> cityRoute = cityData.Select(it => it.cityId).ToList();
var path = pathFinder.FindCrossCityPath(start, end);
List<MapLine> result = new List<MapLine>();
if (path != null)
{
foreach (var item in path)
{
if (item.StepType == PathStepType.Move)
{
MapLine line = new MapLine();
line.x = item.Position.X;
line.y = item.Position.Y;
line.mapId = $"{line.x}_{line.y}";
result.Add(line);
}
}
}
return result;
}
public async Task<List<MapLine>> CreateAutoMap(string start, string end)
{
//获取所有起始点
var startMap = await GetMapInfo(start);
var endMap = await GetMapInfo(end);
Point startPoint = new Point((int)startMap.x, (int)startMap.y);
Point endPoint = new Point((int)endMap.x, (int)endMap.y);
var result = await FinderMapLine(startPoint, endPoint);
if (result.Count > 0)
{
result.RemoveAt(0);
}
return result;
}
#endregion
}

View File

@@ -0,0 +1,62 @@
namespace Application.Domain;
public class UnitUserAttrService(ISqlSugarClient DbClient, IRedisCache redis) : IUnitUserAttrService, ITransient
{
#region
public async Task<unit_user_blood> GetUserBlood(string userId)
{
string key = string.Format(UserCache.BaseCacheKeys, "AttrData","Blood");
var data = await redis.GetHashAsync<unit_user_blood>(key, userId);
if (data == null)
{
var db = DbClient.AsTenant().GetConnectionWithAttr<unit_user_blood>();
data = await db.Queryable<unit_user_blood>().Where(it => it.userId == userId).SingleAsync();
await redis.AddHashAsync(key, userId, data);
}
return data;
}
public async Task<bool> UpdateUserBlood(string userId, int op, int count, bool mustUp = false)
{
bool result = false;
unit_user_blood data = new unit_user_blood();
string key = string.Format(UserCache.BaseCacheKeys, "AttrData","Blood");
if (op == 2)
{
data.userId = userId;
data.blood = count;
}
else
{
data = await GetUserBlood(userId);
if (op == 0)
{
data.blood -= count;
}
else if (op == 1)
{
data.blood += count;
}
}
data.blood = data.blood < 0 ? 0 : data.blood;
result = await redis.AddHashAsync(key, userId, data);
if (mustUp)
{
var db = DbClient.AsTenant().GetConnectionWithAttr<unit_user_blood>();
result = await db.Updateable<unit_user_blood>()
.SetColumnsIF(op == 0, it => it.blood == it.blood - count)
.SetColumnsIF(op == 1, it => it.blood == it.blood + count)
.SetColumnsIF(op == 2, it => it.blood == count)
.Where(it => it.userId == userId).ExecuteCommandAsync() > 0;
}
return result;
}
#endregion
}

View File

@@ -0,0 +1,8 @@
namespace Application.Domain;
public class MapLine
{
public string mapId { get; set; }
public int x { get; set; }
public int y { get; set; }
}

View File

@@ -0,0 +1,692 @@
namespace Application.Domain;
// ===================== 核心定义:全局坐标体系 =====================
/// <summary>
/// 全局坐标结构体(所有城市共享唯一坐标)
/// </summary>
public struct Point
{
public int X; // 全局X坐标
public int Y; // 全局Y坐标
public Point(int x, int y)
{
X = x;
Y = y;
}
public override bool Equals(object obj)
{
return obj is Point point && X == point.X && Y == point.Y;
}
public override int GetHashCode()
{
return HashCode.Combine(X, Y);
}
public static bool operator ==(Point a, Point b) => a.X == b.X && a.Y == b.Y;
public static bool operator !=(Point a, Point b) => !(a == b);
public override string ToString() => $"({X},{Y})";
}
/// <summary>
/// 城市节点(全局坐标管辖范围)
/// </summary>
public class CityNode
{
public int CityId { get; set; } // 城市ID
public string CityName { get; set; } // 城市名称
public Point CoreAnchor { get; set; } // 核心锚点(全局坐标)
public string CoreAnchorName { get; set; } // 核心锚点名称
public int MinX { get; set; } // 城市管辖范围-最小X全局
public int MaxX { get; set; } // 城市管辖范围-最大X全局
public int MinY { get; set; } // 城市管辖范围-最小Y全局
public int MaxY { get; set; } // 城市管辖范围-最大Y全局
public List<InterCityPortal> Portals { get; set; } // 所属传送点(全局坐标)
public CityNode(int cityId, string cityName, Point coreAnchor, string coreAnchorName,
int minX, int maxX, int minY, int maxY)
{
CityId = cityId;
CityName = cityName;
CoreAnchor = coreAnchor;
CoreAnchorName = coreAnchorName;
MinX = minX;
MaxX = maxX;
MinY = minY;
MaxY = maxY;
Portals = new List<InterCityPortal>();
}
/// <summary>
/// 校验全局坐标是否属于当前城市管辖范围
/// </summary>
public bool IsPointInCity(Point point)
{
return point.X >= MinX && point.X <= MaxX && point.Y >= MinY && point.Y <= MaxY;
}
public void AddPortal(InterCityPortal portal)
{
if (!Portals.Any(p => p.PortalId == portal.PortalId))
Portals.Add(portal);
}
}
/// <summary>
/// 城际传送点全局坐标PortalId改为字符串
/// </summary>
public class InterCityPortal
{
public string PortalId { get; set; } // 1. 改为字符串类型
public int BelongCityId { get; set; } // 所属城市ID
public Point Position { get; set; } // 传送点全局坐标
public int TargetCityId { get; set; } // 目标城市ID
public string PortalName { get; set; } // 传送点名称
public int Priority { get; set; } = 1; // 优先级
public string? ReversePortalId { get; set; } // 反向传送点ID字符串
public InterCityPortal(string portalId, int belongCityId, Point pos, int targetCityId, string name,
int priority = 1, string? reversePortalId = null)
{
PortalId = portalId;
BelongCityId = belongCityId;
Position = pos;
TargetCityId = targetCityId;
PortalName = name;
Priority = priority;
ReversePortalId = reversePortalId;
}
}
/// <summary>
/// 全局路网(基于全局坐标管理城市+传送点)
/// </summary>
public class GlobalRoadNetwork
{
public Dictionary<int, CityNode> CityDict { get; private set; }
public Dictionary<string, InterCityPortal> PortalDict { get; private set; } // 适配字符串PortalId
public GlobalRoadNetwork()
{
CityDict = new Dictionary<int, CityNode>();
PortalDict = new Dictionary<string, InterCityPortal>(); // 改为字符串Key
}
public void AddCity(CityNode city)
{
if (!CityDict.ContainsKey(city.CityId))
CityDict.Add(city.CityId, city);
}
public void AddPortal(InterCityPortal portal)
{
if (!PortalDict.ContainsKey(portal.PortalId))
{
PortalDict.Add(portal.PortalId, portal);
if (CityDict.ContainsKey(portal.BelongCityId))
CityDict[portal.BelongCityId].AddPortal(portal);
}
}
/// <summary>
/// 根据全局坐标获取所属城市
/// </summary>
public CityNode GetCityByGlobalPoint(Point point)
{
return CityDict.Values.FirstOrDefault(city => city.IsPointInCity(point));
}
/// <summary>
/// 获取最优传送点(修复反向寻路筛选逻辑)
/// </summary>
public InterCityPortal GetOptimalPortal(int startCityId, int targetCityId, Point startPos,
Dictionary<int, CityRoadNetwork> cityNetworks, bool isReverse = false)
{
if (!CityDict.ContainsKey(startCityId) || !cityNetworks.ContainsKey(startCityId))
return null;
var startCity = CityDict[startCityId];
var startCityNetwork = cityNetworks[startCityId];
// 修复反向寻路筛选逻辑:
// - 正向:当前城市传送点 → 目标城市
// - 反向:目标城市传送点 → 当前城市(但从当前城市视角找)
var candidatePortals = isReverse
? CityDict.Values
.Where(c => c.CityId == targetCityId)
.SelectMany(c => c.Portals)
.Where(p => p.TargetCityId == startCityId)
.Where(p => startCityNetwork.IsPointWalkable(p.Position))
.Where(p => startCityNetwork.FindPathInCity(startPos, p.Position) != null)
: startCity.Portals
.Where(p => p.TargetCityId == targetCityId)
.Where(p => startCityNetwork.IsPointWalkable(p.Position))
.Where(p => startCityNetwork.FindPathInCity(startPos, p.Position) != null);
// 计算距离并排序
var sortedPortals = candidatePortals
.Select(p => new
{
Portal = p,
Distance = GetManhattanDistance(startPos, p.Position)
})
.OrderBy(p => p.Portal.Priority)
.ThenBy(p => p.Distance);
return sortedPortals.FirstOrDefault()?.Portal;
}
/// <summary>
/// 获取反向传送点适配字符串PortalId
/// </summary>
public InterCityPortal GetReversePortal(InterCityPortal portal)
{
if (!string.IsNullOrEmpty(portal.ReversePortalId) && PortalDict.ContainsKey(portal.ReversePortalId))
return PortalDict[portal.ReversePortalId];
return null;
}
/// <summary>
/// 校验全局坐标合法性(属于某城市+该城市内可通行)
/// </summary>
public bool IsPointValid(Point point, Dictionary<int, CityRoadNetwork> cityNetworks)
{
var city = GetCityByGlobalPoint(point);
if (city == null || !cityNetworks.ContainsKey(city.CityId))
return false;
return cityNetworks[city.CityId].IsPointWalkable(point);
}
/// <summary>
/// 修复使用BFS获取所有连通的城市链支持多中转
/// </summary>
public List<int> GetConnectedCityChain(int startCityId, int endCityId)
{
if (startCityId == endCityId)
return new List<int> { startCityId };
// BFS队列存储(当前城市ID, 路径)
var queue = new Queue<Tuple<int, List<int>>>();
var visited = new HashSet<int>();
queue.Enqueue(Tuple.Create(startCityId, new List<int> { startCityId }));
visited.Add(startCityId);
while (queue.Count > 0)
{
var current = queue.Dequeue();
int currCityId = current.Item1;
List<int> path = current.Item2;
// 获取当前城市所有可达的传送点目标城市
var reachableCities = CityDict[currCityId].Portals
.Select(p => p.TargetCityId)
.Distinct()
.Where(c => !visited.Contains(c));
foreach (int nextCityId in reachableCities)
{
var newPath = new List<int>(path) { nextCityId };
// 找到终点,返回路径
if (nextCityId == endCityId)
return newPath;
visited.Add(nextCityId);
queue.Enqueue(Tuple.Create(nextCityId, newPath));
}
}
return null; // 无可达路线
}
private int GetManhattanDistance(Point a, Point b)
{
return Math.Abs(a.X - b.X) + Math.Abs(a.Y - b.Y);
}
}
public class AStarNode : IComparable<AStarNode>
{
public Point Position { get; set; }
public AStarNode Parent { get; set; }
public int G { get; set; } // 起点到当前节点的代价
public int H { get; set; } // 当前节点到终点的预估代价
public int F => G + H; // 总代价
// 实现IComparable接口解决SortedSet重复元素问题
public int CompareTo(AStarNode other)
{
if (other == null) return 1;
// 先按F值排序再按H值最后按坐标避免重复
int fCompare = F.CompareTo(other.F);
if (fCompare != 0) return fCompare;
int hCompare = H.CompareTo(other.H);
if (hCompare != 0) return hCompare;
int xCompare = Position.X.CompareTo(other.Position.X);
return xCompare != 0 ? xCompare : Position.Y.CompareTo(other.Position.Y);
}
}
/// <summary>
/// 单城市路网(基于全局坐标管理可通行区域)
/// </summary>
public class CityRoadNetwork
{
public int CityId { get; set; }
public Dictionary<Point, bool> WalkablePoints { get; private set; } // 全局坐标可通行列表
public CityRoadNetwork(int cityId)
{
CityId = cityId;
WalkablePoints = new Dictionary<Point, bool>();
}
/// <summary>
/// 添加全局坐标可通行点
/// </summary>
public void AddWalkablePoint(int x, int y, bool walkable = true)
{
var point = new Point(x, y);
WalkablePoints[point] = walkable;
}
/// <summary>
/// 批量添加全局坐标可通行区域
/// </summary>
public void AddWalkableRect(int minX, int maxX, int minY, int maxY, bool walkable = true)
{
if (minX > maxX || minY > maxY)
throw new ArgumentException("矩形范围不合法min不能大于max");
for (int x = minX; x <= maxX; x++)
for (int y = minY; y <= maxY; y++)
AddWalkablePoint(x, y, walkable);
}
/// <summary>
/// 校验全局坐标是否可走
/// </summary>
public bool IsPointWalkable(Point point)
{
return WalkablePoints.TryGetValue(point, out bool walkable) && walkable;
}
/// <summary>
/// 修复后的A*寻路(基于全局坐标)
/// </summary>
public List<Point> FindPathInCity(Point start, Point end)
{
// 基础校验
if (!WalkablePoints.ContainsKey(start) || !WalkablePoints.ContainsKey(end))
return null;
if (!IsPointWalkable(start) || !IsPointWalkable(end))
return null;
if (start == end)
return new List<Point> { start };
// 开放列表(排序集合)和关闭列表
var openSet = new SortedSet<AStarNode>();
var openDict = new Dictionary<Point, AStarNode>(); // 快速查找
var closeDict = new Dictionary<Point, AStarNode>();
// 初始化起点
var startNode = new AStarNode
{
Position = start,
Parent = null,
G = 0,
H = GetManhattanDistance(start, end)
};
openSet.Add(startNode);
openDict[start] = startNode;
// 四方向移动
var dirs = new[] { new Point(0, 1), new Point(0, -1), new Point(1, 0), new Point(-1, 0) };
while (openSet.Count > 0)
{
// 获取F值最小的节点
var currentNode = openSet.Min;
openSet.Remove(currentNode);
openDict.Remove(currentNode.Position);
closeDict[currentNode.Position] = currentNode;
// 到达终点,回溯路径
if (currentNode.Position == end)
{
var path = new List<Point>();
var node = currentNode;
while (node != null)
{
path.Add(node.Position);
node = node.Parent;
}
path.Reverse();
return path;
}
// 遍历邻接节点
foreach (var dir in dirs)
{
var neighborPos = new Point(currentNode.Position.X + dir.X, currentNode.Position.Y + dir.Y);
// 跳过不可通行或已关闭的节点
if (!IsPointWalkable(neighborPos) || closeDict.ContainsKey(neighborPos))
continue;
// 计算新的G值
int newG = currentNode.G + 1;
// 邻接节点不存在或找到更优路径
if (!openDict.TryGetValue(neighborPos, out var neighborNode) || newG < neighborNode.G)
{
// 如果节点已存在,先移除
if (neighborNode != null)
{
openSet.Remove(neighborNode);
openDict.Remove(neighborPos);
}
// 创建/更新节点
neighborNode = new AStarNode
{
Position = neighborPos,
Parent = currentNode,
G = newG,
H = GetManhattanDistance(neighborPos, end)
};
openSet.Add(neighborNode);
openDict[neighborPos] = neighborNode;
}
}
}
// 无路径
return null;
}
private int GetManhattanDistance(Point a, Point b)
{
return Math.Abs(a.X - b.X) + Math.Abs(a.Y - b.Y);
}
}
// ===================== 路径步骤定义 =====================
public enum PathStepType
{
Move,
Teleport
}
public class PathStep
{
public int CityId { get; set; }
public Point Position { get; set; } // 全局坐标
public PathStepType StepType { get; set; }
public int? TargetCityId { get; set; }
public Point? TargetAnchor { get; set; } // 目标锚点全局坐标
public string? TargetAnchorName { get; set; }
public string ToWapDesc(GlobalRoadNetwork globalNetwork)
{
var cityName = globalNetwork?.CityDict?.ContainsKey(CityId) == true
? globalNetwork.CityDict[CityId].CityName
: "未知城市";
return StepType switch
{
PathStepType.Move => $"【{cityName}】移动到全局坐标{Position}",
PathStepType.Teleport => GetTeleportDesc(globalNetwork, cityName),
_ => string.Empty
};
}
private string GetTeleportDesc(GlobalRoadNetwork globalNetwork, string currentCityName)
{
if (globalNetwork == null || !TargetCityId.HasValue)
return $"【{currentCityName}】通过传送阵→【未知城市】未知锚点";
var targetCityName = globalNetwork.CityDict.ContainsKey(TargetCityId.Value)
? globalNetwork.CityDict[TargetCityId.Value].CityName
: "未知城市";
var anchorName = string.IsNullOrEmpty(TargetAnchorName) ? "未知锚点" : TargetAnchorName;
var anchorPos = TargetAnchor.HasValue ? $"(全局坐标{TargetAnchor}" : "";
return $"【{currentCityName}】通过传送阵→【{targetCityName}】{anchorName}{anchorPos}";
}
}
// ===================== 跨城寻路核心服务(全自动适配) =====================
public class CrossCityPathFinder
{
private readonly GlobalRoadNetwork _globalNetwork;
private readonly Dictionary<int, CityRoadNetwork> _cityNetworks;
public CrossCityPathFinder(GlobalRoadNetwork globalNetwork)
{
_globalNetwork = globalNetwork;
_cityNetworks = new Dictionary<int, CityRoadNetwork>();
}
public void AddCityRoadNetwork(CityRoadNetwork cityNetwork)
{
if (!_cityNetworks.ContainsKey(cityNetwork.CityId))
_cityNetworks.Add(cityNetwork.CityId, cityNetwork);
}
/// <summary>
/// 核心方法:输入起止点,全自动判定同城/跨城/多城市,自动适配正向/反向
/// </summary>
public List<PathStep> FindCrossCityPath(Point startPos, Point endPos)
{
// 1. 基础校验:识别起止点所属城市
var startCity = _globalNetwork.GetCityByGlobalPoint(startPos);
var endCity = _globalNetwork.GetCityByGlobalPoint(endPos);
if (startCity == null || endCity == null)
{
return null;
}
// 2. 同城寻路
if (startCity.CityId == endCity.CityId)
{
return FindSameCityPath(startCity.CityId, startPos, endPos);
}
// 3. 跨城/多城市寻路使用修复后的BFS路径链
var cityChain = _globalNetwork.GetConnectedCityChain(startCity.CityId, endCity.CityId);
if (cityChain == null || cityChain.Count < 2)
{
return null;
}
// 自动适配正向/反向
var cityStartPoints = new Dictionary<int, Point>
{
{ startCity.CityId, startPos },
{ endCity.CityId, endPos }
};
// 自动判断是否需要反向寻路
var isReverse = IsNeedReverseRoute(startCity.CityId, endCity.CityId);
return FindMultiCityPath(cityChain, cityStartPoints, isReverse);
}
/// <summary>
/// 同城寻路
/// </summary>
private List<PathStep> FindSameCityPath(int cityId, Point startPos, Point endPos)
{
if (!_globalNetwork.IsPointValid(startPos, _cityNetworks) ||
!_globalNetwork.IsPointValid(endPos, _cityNetworks))
{
return null;
}
var cityPath = _cityNetworks[cityId].FindPathInCity(startPos, endPos);
return cityPath?.Select(p => new PathStep
{
CityId = cityId,
Position = p,
StepType = PathStepType.Move
}).ToList();
}
/// <summary>
/// 多城市寻路(自动适配正向/反向)
/// </summary>
private List<PathStep> FindMultiCityPath(List<int> cityChain, Dictionary<int, Point> cityStartPoints,
bool isReverse)
{
var finalPath = new List<PathStep>();
var actualChain = isReverse ? cityChain.AsEnumerable().Reverse().ToList() : cityChain;
for (int i = 0; i < actualChain.Count - 1; i++)
{
int currCityId = actualChain[i];
int nextCityId = actualChain[i + 1];
Point currStartPoint = cityStartPoints.ContainsKey(currCityId)
? cityStartPoints[currCityId]
: _globalNetwork.CityDict[currCityId].CoreAnchor;
// 校验起点坐标归属
var currCity = _globalNetwork.CityDict[currCityId];
if (!currCity.IsPointInCity(currStartPoint))
{
return null;
}
if (!_globalNetwork.IsPointValid(currStartPoint, _cityNetworks))
return null;
// 获取最优传送点(自动传入反向标识)
var optimalPortal =
_globalNetwork.GetOptimalPortal(currCityId, nextCityId, currStartPoint, _cityNetworks, isReverse);
if (optimalPortal == null)
{
return null;
}
// 当前城市内:起点 → 传送点
var currToPortal = _cityNetworks[currCityId].FindPathInCity(currStartPoint, optimalPortal.Position);
if (currToPortal == null)
return null;
finalPath.AddRange(currToPortal.Select(p => new PathStep
{
CityId = currCityId,
Position = p,
StepType = PathStepType.Move
}));
// 跨城传送
var nextCity = _globalNetwork.CityDict[nextCityId];
finalPath.Add(new PathStep
{
CityId = currCityId,
Position = optimalPortal.Position,
StepType = PathStepType.Teleport,
TargetCityId = nextCityId,
TargetAnchor = nextCity.CoreAnchor,
TargetAnchorName = nextCity.CoreAnchorName
});
// 更新下一个城市的起点
if (!cityStartPoints.ContainsKey(nextCityId))
cityStartPoints.Add(nextCityId, nextCity.CoreAnchor);
// 最后一段:核心锚点→终点
if (i == actualChain.Count - 2)
{
Point nextEndPoint = cityStartPoints[nextCityId];
var anchorToEnd = _cityNetworks[nextCityId].FindPathInCity(nextCity.CoreAnchor, nextEndPoint);
if (anchorToEnd == null)
return null;
finalPath.AddRange(anchorToEnd.Select(p => new PathStep
{
CityId = nextCityId,
Position = p,
StepType = PathStepType.Move
}));
}
}
return finalPath;
}
/// <summary>
/// 自动判断是否需要反向寻路
/// </summary>
private bool IsNeedReverseRoute(int startCityId, int endCityId)
{
// 检查正向传送点
var startCity = _globalNetwork.CityDict[startCityId];
var hasForward = startCity.Portals.Any(p => p.TargetCityId == endCityId);
// 正向无则反向
if (!hasForward)
{
var endCity = _globalNetwork.CityDict[endCityId];
var hasReverse = endCity.Portals.Any(p => p.TargetCityId == startCityId);
return hasReverse;
}
return false;
}
/// <summary>
/// 辅助方法:获取城市名称
/// </summary>
private string GetCityName(CityNode city)
{
return city?.CityName ?? "未知城市";
}
/// <summary>
/// 简化路径描述(用于展示)
/// </summary>
public List<string> SimplifyPathForWap(List<PathStep> fullPath)
{
if (fullPath == null || fullPath.Count == 0)
return new List<string>();
var simplified = new List<string>();
PathStep? lastTeleport = null;
foreach (var step in fullPath)
{
if (step.StepType == PathStepType.Teleport)
{
simplified.Add(step.ToWapDesc(_globalNetwork));
lastTeleport = step;
}
else if (lastTeleport == null && step == fullPath.First())
{
var cityName = _globalNetwork.CityDict.ContainsKey(step.CityId)
? _globalNetwork.CityDict[step.CityId].CityName
: "未知城市";
simplified.Add($"【{cityName}】从起点(全局坐标{step.Position})出发");
}
else if (step == fullPath.Last())
{
var cityName = _globalNetwork.CityDict.ContainsKey(step.CityId)
? _globalNetwork.CityDict[step.CityId].CityName
: "未知城市";
simplified.Add($"【{cityName}】到达终点(全局坐标{step.Position}");
}
}
return simplified;
}
}

View File

@@ -14,12 +14,15 @@ public class MapController : ControllerBase
private readonly IUnitUserService _userService;
private readonly IGameMapService _mapService;
private readonly IGameChatService _chatService;
private readonly IUnitUserAttrService _attrService;
public MapController(IUnitUserService userService, IGameMapService mapService, IGameChatService chatService)
public MapController(IUnitUserService userService, IGameMapService mapService, IGameChatService chatService,
IUnitUserAttrService attrService)
{
_userService = userService;
_mapService = mapService;
_chatService = chatService;
_attrService = attrService;
}
/// <summary>
@@ -32,17 +35,35 @@ public class MapController : ControllerBase
{
string userId = StateHelper.userId;
int area = StateHelper.areaId;
var onMap = await _mapService.GetUserOnMap(userId);
game_city_map mapInfo = new game_city_map();
if (string.IsNullOrEmpty(map))
#region
bool isSelfMap = false;
if (!isSelfMap)
{
//血量为0得时候地图点为本身
var myBlood = await _attrService.GetUserBlood(userId);
if (myBlood.blood < 1)
{
//设置默认地图点
await _mapService.SetUserMapDefult(userId);
isSelfMap = true;
}
}
if (isSelfMap)
{
var onMap = await _mapService.GetUserOnMap(userId);
mapInfo = await _mapService.GetMapInfo(onMap.mapId);
}
else
{
mapInfo = await _mapService.GetMapInfo(map);
mapInfo = await _mapService.GetToMapInfo(userId, map, false);
}
#endregion
//公聊信息
string teamId = "";
string groupId = "";
@@ -56,7 +77,7 @@ public class MapController : ControllerBase
3); //获取附近的人
var cityInfo = await _mapService.GetCityInfo((int)mapInfo.cityId); //城市信息
var cityShow = await _mapService.GetMapCity(cityInfo.cityId); //城内地图
var cityShow = await _mapService.GetCityShowMap(cityInfo.cityId); //城内地图
#region 线
@@ -90,9 +111,55 @@ public class MapController : ControllerBase
return PoAction.Message("地图不存在!");
}
var data = await _mapService.GetMapUser(onMap.mapId, areaId, (int)mapInfo.lookArea, new List<string> { userId }, page,
var data = await _mapService.GetMapUser(onMap.mapId, areaId, (int)mapInfo.lookArea, new List<string> { userId },
page,
10, Total);
return PoAction.Ok(new { data, total = Total.Value });
}
/// <summary>
/// 获取当前城市所有地图
/// </summary>
/// <returns></returns>
[HttpGet]
public async Task<IPoAction> GetUserOnCityMap(string? search)
{
string userId = StateHelper.userId;
var onMap = await _mapService.GetUserOnMap(userId);
var mapInfo = await _mapService.GetMapInfo(onMap.mapId);
var data = await _mapService.GetCityMap((int)mapInfo.cityId);
if (!string.IsNullOrEmpty(search))
{
data = data.FindAll(it => it.mapName.Contains(search));
}
return PoAction.Ok(data);
}
/// <summary>
/// 获取自动寻路路径
/// </summary>
/// <param name="toMap"></param>
/// <returns></returns>
[HttpGet]
public async Task<IPoAction> GetAutoMapPath(string? toMap)
{
if (string.IsNullOrEmpty(toMap))
{
return PoAction.Message("目标地点不能为空!");
}
string userId = StateHelper.userId;
var onMap = await _mapService.GetUserOnMap(userId);
var result = await _mapService.CreateAutoMap(onMap.mapId, toMap);
if (result.Count > 0)
{
return PoAction.Ok(result);
}
else
{
return PoAction.Message("无法自动寻路!");
}
}
}

View File

@@ -10,10 +10,14 @@
public class BagController : ControllerBase
{
private readonly IUnitUserWeight _weightService;
private readonly IGameGoodsService _goodsService;
private readonly IGameEquService _equService;
public BagController(IUnitUserWeight weightService)
public BagController(IUnitUserWeight weightService, IGameGoodsService goodsService, IGameEquService equService)
{
_weightService = weightService;
_goodsService = goodsService;
_equService = equService;
}
/// <summary>
@@ -35,4 +39,86 @@ public class BagController : ControllerBase
return PoAction.Ok(new { onWeight, maxWeight, cowry, gold, copper });
}
/// <summary>
/// 获取用户道具数据
/// </summary>
/// <param name="type"></param>
/// <param name="type"></param>
/// <param name="ch"></param>
/// <param name="page"></param>
/// <returns></returns>
[HttpGet]
public async Task<IPoAction> GetUserBagProp(int type, int ch, string? query, int page)
{
RefAsync<int> total = 0;
string userId = StateHelper.userId;
if (type == 0)
{
int _t = 0;
switch (ch)
{
case 1:
_t = 1;
break;
case 2:
_t = 2;
break;
case 3:
_t = 3;
break;
}
var data = await _equService.GetUserEquData(userId, _t, query, page, 10, total);
return PoAction.Ok(new { data, total.Value });
}
else if (type == 1)
{
List<string> code = new List<string>() { nameof(GoodsEnum.Code.Drug) };
var data = await _goodsService.GetUserGoodsData(userId, code, new List<string>(), query, page, 10, total);
return PoAction.Ok(new { data, total.Value });
}
else if (type == 2)
{
List<string> code = new List<string>();
List<string> noCode = new List<string>() { nameof(GoodsEnum.Code.Drug) };
switch (ch)
{
case 1:
code.Add(nameof(GoodsEnum.Code.Gem));
break;
case 2:
code.Add(nameof(GoodsEnum.Code.Palace));
break;
case 3:
code.Add(nameof(GoodsEnum.Code.Mark));
break;
case 4:
code.Add(nameof(GoodsEnum.Code.Pack));
break;
case 5:
code.Add(nameof(GoodsEnum.Code.Mak));
break;
case 6:
code.Add(nameof(GoodsEnum.Code.Paper));
break;
case 7:
code.Add(nameof(GoodsEnum.Code.Card));
break;
case 8:
code.Add(nameof(GoodsEnum.Code.Cargo));
break;
case 9:
code.Add(nameof(GoodsEnum.Code.Prop));
break;
}
var data = await _goodsService.GetUserGoodsData(userId, code, noCode, query, page, 10, total);
return PoAction.Ok(new { data, total.Value });
}
else
{
return PoAction.Ok(new { data = new List<string>(), total.Value });
}
}
}

View File

@@ -62,7 +62,6 @@ const visible = ref(props.isShow)
.popup-content {
margin-top: -35px;
padding: 15px 15px;
color: #e0e0e0;
font-size: 15px;
line-height: 1.6;
min-height: 80px;

View File

@@ -4,6 +4,7 @@
<div class="common">
<Abar href="/">首页</Abar>-
<Abar href="/">挂机</Abar>-
<Abar href="/treasure">聚宝盆</Abar>-
<a target="_blank" href="https://work.weixin.qq.com/kfid/kfc86bc348120aea3e7">反馈</a>
</div>

View File

@@ -9,6 +9,10 @@ export class PageExtend {
return value ? String(value) : ''
}
public static GetPageIndex(page: number, limit: number, index: number) {
return (page - 1) * limit + index;
}
// 回到顶部函数 默认平滑滚动到顶部
public static ScrollToTop(behavior: ScrollBehavior = 'smooth') {
if (typeof window !== 'undefined') {

View File

@@ -53,7 +53,7 @@ export class TimeExtend {
* 获取当前秒级时间戳
*/
public static GetSecondStamp(): number {
return Math.floor(Date.now() / 1000)
return Math.floor(Date.now() / 1000) + 28800
}
/**

View File

@@ -27,7 +27,8 @@
<div v-if="type == '0'">
<Acheak @click="ChangeChildBag('0')" :on-value="type_ch" on-cheak="0">全部</Acheak>.<Acheak
@click="ChangeChildBag('1')" :on-value="type_ch" on-cheak="1">穿戴</Acheak>.<Acheak
@click="ChangeChildBag('2')" :on-value="type_ch" on-cheak="2"></Acheak>
@click="ChangeChildBag('2')" :on-value="type_ch" on-cheak="2"></Acheak>.<Acheak
@click="ChangeChildBag('3')" :on-value="type_ch" on-cheak="3">未鉴定</Acheak>
</div>
<div v-if="type == '2'">
<Acheak @click="ChangeChildBag('0')" :on-value="type_ch" on-cheak="0">全部</Acheak>.<Acheak
@@ -45,7 +46,37 @@
</div>
<div class="content">
暂无.
<div class="common" v-if="type == '0'">
<div class="item" v-for="(item, index) in data" :key="index">
{{ PageExtend.GetPageIndex(currentPage, 10, index + 1) }}.
<Abar href="">{{ item.equName }}({{item.lev}})</Abar>
<span v-if="item.isOn == 1">(穿)</span>
<span v-if="item.isAppr == 0">(未鉴定)</span>
<span v-if="item.useEndTime < onTime" style="color: red;">(过期)</span>
<span v-if="item.durability < 1" style="color: red;">(损坏)</span>
<span v-if="item.isLock == 1" style="color: green;">()</span>
</div>
</div>
<div class="common" v-if="type == '1'">
<div class="item" v-for="(item, index) in data" :key="index">
{{ PageExtend.GetPageIndex(currentPage, 10, index + 1) }}.
<Abar href="">{{ item.goodsName }}</Abar>({{ item.count }})
</div>
</div>
<div class="common" v-if="type == '2'">
<div class="item" v-for="(item, index) in data" :key="index">
{{ PageExtend.GetPageIndex(currentPage, 10, index + 1) }}.
<span v-if="item.code == 'Card'">
<Abar href="">{{ item.goodsName }}</Abar>({{ item.count }})
</span>
<span v-else>
<Abar href="">{{ item.goodsName }}</Abar>({{ item.count }})
</span>
</div>
</div>
<span v-if="data.length == 0">暂无.</span>
</div>
<div class="content">
<Pagination :currentPage="currentPage" :limit="10" :total="total" @pageChange="handlePageChange" />
@@ -65,17 +96,17 @@ const data = ref<Array<any>>([]);
const type = ref('0');
const type_ch = ref('0');
const serch = ref('');
const onTime = ref(0);
onMounted(async () => {
try {
onTime.value = TimeExtend.GetSecondStamp();
let result = await BagService.GetUserBagData();
if (result.code == 0) {
bagInfo.value = result.data;
await BindData();
}
console.log(result);
}
finally {
PageLoading.Close();
@@ -83,11 +114,11 @@ onMounted(async () => {
})
const BindData = async (): Promise<void> => {
let result = await MapService.GetMapUser(currentPage.value);
let result = await BagService.GetUserBagProp(Number(type.value), Number(type_ch.value), serch.value, currentPage.value)
if (result.code == 0) {
data.value = result.data.data;
total.value = result.data.total;
console.log(result);
console.log(data.value);
}
else {
MessageExtend.ShowDialog("提示", result.msg);
@@ -109,6 +140,7 @@ const ChangeChildBag = async (ch: string): Promise<void> => {
/**刷新 */
const Refresh = async (): Promise<void> => {
serch.value = '';
onTime.value = TimeExtend.GetSecondStamp();
MessageExtend.LoadingToast("刷新中...");
currentPage.value = 1;
await BindData();

View File

@@ -26,15 +26,20 @@
<div class="content">
请选择出口:<br />
<span v-if="mapDong.mapId != ''">东:<Abutton @click="BindData(mapDong.mapId)">{{ mapDong.name }}</Abutton></span>
<span v-if="mapXi.mapId != ''">西:<Abutton @click="BindData(mapXi.mapId)">{{ mapXi.name }}</Abutton></span>
<span v-if="mapDong.mapId != ''">东:<Abutton @click="BindData(mapDong.mapId)">{{ mapDong.name }}</Abutton>
<b v-if="toMapPathData.some(it => it.mapId == mapDong.mapId)">🚩</b>
</span>
<span v-if="mapXi.mapId != ''">西:<Abutton @click="BindData(mapXi.mapId)">{{ mapXi.name }}</Abutton>
<b v-if="toMapPathData.some(it => it.mapId == mapXi.mapId)">🚩</b></span>
<br v-if="mapDong.mapId != '' || mapXi.mapId != ''">
<span v-if="mapNan.mapId != ''">南:<Abutton @click="BindData(mapNan.mapId)">{{ mapNan.name }}</Abutton></span>
<span v-if="mapBei.mapId != ''">北:<Abutton @click="BindData(mapBei.mapId)">{{ mapBei.name }}</Abutton></span>
<span v-if="mapNan.mapId != ''">南:<Abutton @click="BindData(mapNan.mapId)">{{ mapNan.name }}</Abutton>
<b v-if="toMapPathData.some(it => it.mapId == mapNan.mapId)">🚩</b></span>
<span v-if="mapBei.mapId != ''">北:<Abutton @click="BindData(mapBei.mapId)">{{ mapBei.name }}</Abutton>
<b v-if="toMapPathData.some(it => it.mapId == mapBei.mapId)">🚩</b></span>
</div>
<div class="content">
<Abutton @click="ShowCityProp">城内地图</Abutton>.<Abar href="/">寻路</Abar><br />
<Abutton @click="ShowCityProp">城内地图</Abutton>.<Abutton @click="ShowMapPathProp">寻路</Abutton>
</div>
<div class="content">
{{ mapInfo.tips }}
@@ -53,6 +58,26 @@
</span>
</div>
</GamePopup>
<!--寻路-->
<GamePopup v-model:show="showPath" title="【自动寻路】">
<!-- 自定义内容 -->
<div class="content">
<div class="common serch" style="font-size: 16px; margin-top: 10px;">
搜索:&nbsp;<input type="text" class="search-ipt" v-model="mapPathSerch">&nbsp;
<button class="ipt-btn" name="serch" @click="ShowMapPathProp">搜索</button>
</div>
<div class="mapList" style="max-height: 300px;">
<span v-for="(item, index) in cityMapData" :key="index">
{{ index + 1 }}.
<Abutton @click="ChangeMapPath(item.mapId)">{{ item.mapName }}</Abutton>({{ item.x }},{{ item.y }})
<br>
</span>
<span v-if="cityMapData.length == 0">暂无地图.</span>
</div>
</div>
</GamePopup>
</template>
<script setup lang="ts">
definePageMeta({
@@ -132,4 +157,62 @@ const ChangeMap = async (mapId: string): Promise<void> => {
showCity.value = false;
};
/**寻路 */
const cityMapData = ref<Array<any>>([]);
const toMapPathData = ref<Array<any>>([]);
const showPath = ref(false);
const mapPathSerch = ref('');
let changPathLock = true;//寻路锁
const ShowMapPathProp = () => {
//加载数据
MapService.GetUserOnCityMap(mapPathSerch.value).then(res => {
if (res.code == 0) {
showPath.value = true;
mapPathSerch.value = '';
cityMapData.value = res.data;
}
else {
MessageExtend.ShowDialog("提示", res.msg);
}
});
}
const ChangeMapPath = async (mapId: string): Promise<void> => {
if (changPathLock) {
changPathLock = false;
//此处获取寻路路径信息
let result = await MapService.GetAutoMapPath(mapId);
changPathLock = true;
showPath.value = false;
if (result.code == 0) {
toMapPathData.value = []
toMapPathData.value = result.data;
StartToMap()
}
else {
MessageExtend.ShowDialog("提示", result.msg);
}
}
};
const timer = ref(0) // 定时器实例
const RunMap = async (): Promise<void> => {
if (toMapPathData.value.length > 0) {
var toPath = toMapPathData.value.shift();
await BindData(toPath.mapId);
toMapPathData.value = toMapPathData.value.filter(item => item !== toPath.mapId)
}
else {
clearInterval(timer.value);
MessageExtend.LoadingClose();
MessageExtend.Notify("寻路完成,已达到目的地!", "success");
}
}
const StartToMap = () => {
MessageExtend.LoadingToast("自动寻路中...");
timer.value = setInterval(async () => {
await RunMap()
}, 1000)
}
</script>

View File

@@ -0,0 +1,31 @@
<template>
<div class="content">聚宝盆</div>
<div class="content">
金元宝:51000 <br>
余额:5.22 <br>
抽奖次数:3 [<Abar>领取</Abar>] <br>
<Abar href="">我要抽奖</Abar>.<Abar>设置支付宝</Abar>
</div>
<div class="content">
我要提现:<br>
周一:<Abutton>提现(0.3)</Abutton><br>
周二:<Abutton>提现(0.3)</Abutton><br>
周三:<Abutton>提现(0.3)</Abutton><br>
周四:<Abutton>提现(0.3)</Abutton><br>
周五:<Abutton>提现(0.3)</Abutton><br>
周六:<Abutton>提现(0.3)</Abutton><br>
周日:<Abutton>提现(1)</Abutton><br>
</div>
<div class="content">
超级提现:<br>
<Abutton>提现(20)</Abutton><br>
<Abutton>提现(50)</Abutton><br>
<Abutton>提现(100)</Abutton><br>
</div>
<div class="content">
说明:<br>
1.每天完成日常任务可以领取抽奖次数<br>
2.抽奖将获得不同数额得金元宝每日0点按照100001结算到余额<br>
3.在羁绊时间内每天可通过支付宝提现领取游戏福利红包<br>
</div>
</template>

View File

@@ -14,4 +14,20 @@ export class MapService {
static async GetMapUser(page: number) {
return await ApiService.Request("get", "/Map/Map/GetMapUser", { page });
}
/**
* 获取当前城市所有地图
* GET /Map/Map/GetUserOnCityMap
*/
static async GetUserOnCityMap(search: string) {
return await ApiService.Request("get", "/Map/Map/GetUserOnCityMap", { search });
}
/**
* 获取自动寻路路径
* GET /Map/Map/GetAutoMapPath
*/
static async GetAutoMapPath(toMap: string) {
return await ApiService.Request("get", "/Map/Map/GetAutoMapPath", { toMap });
}
}

View File

@@ -6,4 +6,12 @@ export class BagService {
static async GetUserBagData() {
return await ApiService.Request("get", "/User/Bag/GetUserBagData");
}
/**
* GetUserBagProp
* GET /User/Bag/GetUserBagProp
*/
static async GetUserBagProp(type: number, ch: number, query: string, page: number) {
return await ApiService.Request("get", "/User/Bag/GetUserBagProp", { type, ch, query, page });
}
}