|
|
@ -1,22 +1,23 @@ |
|
|
using Build_God_Api.DB; |
|
|
using Build_God_Api.DB; |
|
|
using Build_God_Api.Dto; |
|
|
using Build_God_Api.Dto; |
|
|
|
|
|
using Build_God_Api.Services.Game; |
|
|
using SqlSugar; |
|
|
using SqlSugar; |
|
|
|
|
|
|
|
|
namespace Build_God_Api.Services |
|
|
namespace Build_God_Api.Services |
|
|
{ |
|
|
{ |
|
|
public interface IMonsterService |
|
|
public interface IMonsterService |
|
|
{ |
|
|
{ |
|
|
Task<bool> Add(Monster item); |
|
|
Task<bool> Add(MonsterSaveDto item); |
|
|
|
|
|
|
|
|
Task<bool> Delete(int id); |
|
|
Task<bool> Delete(int id); |
|
|
|
|
|
|
|
|
Task<bool> Update(Monster item); |
|
|
Task<bool> Update(MonsterSaveDto item); |
|
|
|
|
|
|
|
|
Task<Monster?> GetById(int id); |
|
|
Task<MonsterResponseDto?> GetById(int id); |
|
|
|
|
|
|
|
|
Task<PagedResult<Monster>> GetAll(SearchMonsterDto dto); |
|
|
Task<PagedResult<MonsterResponseDto>> GetAll(SearchMonsterDto dto); |
|
|
|
|
|
|
|
|
Task<bool> ExistsByNameAsync(string name); |
|
|
Task<bool> ExistsByNameAsync(string name, int? exceptMonsterId = null); |
|
|
|
|
|
|
|
|
Task<bool> AddReward(MonsterReward reward); |
|
|
Task<bool> AddReward(MonsterReward reward); |
|
|
|
|
|
|
|
|
@ -27,21 +28,107 @@ namespace Build_God_Api.Services |
|
|
Task<List<MonsterReward>> GetRewards(int monsterId); |
|
|
Task<List<MonsterReward>> GetRewards(int monsterId); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
public class MonsterService(ISqlSugarClient db, ICurrentUserService currentUserService) : IMonsterService |
|
|
public class MonsterService( |
|
|
|
|
|
ISqlSugarClient db, |
|
|
|
|
|
ICurrentUserService currentUserService, |
|
|
|
|
|
IMonsterAttributeCalculateService monsterAttributeCalculate) : IMonsterService |
|
|
{ |
|
|
{ |
|
|
private readonly ISqlSugarClient _db = db; |
|
|
private readonly ISqlSugarClient _db = db; |
|
|
private readonly ICurrentUserService _currentUserService = currentUserService; |
|
|
private readonly ICurrentUserService _currentUserService = currentUserService; |
|
|
|
|
|
private readonly IMonsterAttributeCalculateService _monsterAttributeCalculate = monsterAttributeCalculate; |
|
|
|
|
|
|
|
|
public async Task<bool> Add(Monster item) |
|
|
private static MonsterRewardDto MapReward(MonsterReward r) => new() |
|
|
|
|
|
{ |
|
|
|
|
|
Id = r.Id, |
|
|
|
|
|
MonsterId = r.MonsterId, |
|
|
|
|
|
RewardType = (int)r.Type, |
|
|
|
|
|
ItemId = r.ItemId, |
|
|
|
|
|
ItemName = r.ItemName, |
|
|
|
|
|
Count = r.Count |
|
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
private async Task<MonsterResponseDto> ToResponseAsync( |
|
|
|
|
|
Monster m, |
|
|
|
|
|
IReadOnlyList<MonsterEquipment> equipmentRows, |
|
|
|
|
|
List<MonsterRewardDto>? rewards, |
|
|
|
|
|
Dictionary<int, string> templateNames) |
|
|
|
|
|
{ |
|
|
|
|
|
var stats = await _monsterAttributeCalculate.CalculateAsync(m, equipmentRows); |
|
|
|
|
|
var equipDtos = equipmentRows.Select(e => new MonsterEquipmentDto |
|
|
|
|
|
{ |
|
|
|
|
|
Id = e.Id, |
|
|
|
|
|
MonsterId = e.MonsterId, |
|
|
|
|
|
EquipmentTemplateId = e.EquipmentTemplateId, |
|
|
|
|
|
Attributes = string.IsNullOrEmpty(e.Attributes) ? "[]" : e.Attributes, |
|
|
|
|
|
EquipmentTemplateName = templateNames.GetValueOrDefault(e.EquipmentTemplateId) |
|
|
|
|
|
}).ToList(); |
|
|
|
|
|
|
|
|
|
|
|
return new MonsterResponseDto |
|
|
|
|
|
{ |
|
|
|
|
|
Id = m.Id, |
|
|
|
|
|
Name = m.Name, |
|
|
|
|
|
Description = m.Description, |
|
|
|
|
|
ConfiguredExp = m.ConfiguredExp, |
|
|
|
|
|
ProfessionId = m.ProfessionId, |
|
|
|
|
|
LevelId = m.LevelId, |
|
|
|
|
|
Type = (int)m.Type, |
|
|
|
|
|
Icon = m.Icon, |
|
|
|
|
|
Health = (int)stats.MaxHP, |
|
|
|
|
|
Attack = (int)stats.Attack, |
|
|
|
|
|
Defense = (int)stats.Defend, |
|
|
|
|
|
CriticalRate = stats.CriticalRate, |
|
|
|
|
|
Rewards = rewards, |
|
|
|
|
|
Equipment = equipDtos |
|
|
|
|
|
}; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
private async Task<Dictionary<int, string>> LoadTemplateNamesAsync(IEnumerable<int> templateIds) |
|
|
|
|
|
{ |
|
|
|
|
|
var ids = templateIds.Distinct().ToList(); |
|
|
|
|
|
if (ids.Count == 0) return new Dictionary<int, string>(); |
|
|
|
|
|
var templates = await _db.Queryable<EquipmentTemplate>().Where(t => ids.Contains(t.Id)).ToListAsync(); |
|
|
|
|
|
return templates.ToDictionary(t => t.Id, t => t.Name); |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
public async Task<bool> Add(MonsterSaveDto item) |
|
|
{ |
|
|
{ |
|
|
var exists = await ExistsByNameAsync(item.Name); |
|
|
var exists = await ExistsByNameAsync(item.Name); |
|
|
if (exists) |
|
|
if (exists) |
|
|
{ |
|
|
{ |
|
|
throw new Exception($"已存在名为 {item.Name} 的怪兽"); |
|
|
throw new Exception($"已存在名为 {item.Name} 的怪兽"); |
|
|
} |
|
|
} |
|
|
item.CreatedOn = DateTime.UtcNow; |
|
|
|
|
|
item.CreatedBy = _currentUserService.UserId; |
|
|
var monster = new Monster |
|
|
await _db.Insertable(item).ExecuteCommandAsync(); |
|
|
{ |
|
|
|
|
|
Name = item.Name, |
|
|
|
|
|
Description = item.Description, |
|
|
|
|
|
ConfiguredExp = item.ConfiguredExp, |
|
|
|
|
|
ProfessionId = item.ProfessionId, |
|
|
|
|
|
LevelId = item.LevelId, |
|
|
|
|
|
Type = (MonsterType)item.Type, |
|
|
|
|
|
Icon = item.Icon, |
|
|
|
|
|
CreatedOn = DateTime.UtcNow, |
|
|
|
|
|
CreatedBy = _currentUserService.UserId, |
|
|
|
|
|
UpdatedOn = DateTime.UtcNow, |
|
|
|
|
|
UpdatedBy = _currentUserService.UserId |
|
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
var monsterId = await _db.Insertable(monster).ExecuteReturnIdentityAsync(); |
|
|
|
|
|
|
|
|
|
|
|
foreach (var eq in item.Equipment) |
|
|
|
|
|
{ |
|
|
|
|
|
await _db.Insertable(new MonsterEquipment |
|
|
|
|
|
{ |
|
|
|
|
|
MonsterId = monsterId, |
|
|
|
|
|
EquipmentTemplateId = eq.EquipmentTemplateId, |
|
|
|
|
|
Attributes = string.IsNullOrWhiteSpace(eq.Attributes) ? "[]" : eq.Attributes, |
|
|
|
|
|
CreatedOn = DateTime.UtcNow, |
|
|
|
|
|
CreatedBy = _currentUserService.UserId, |
|
|
|
|
|
UpdatedOn = DateTime.UtcNow, |
|
|
|
|
|
UpdatedBy = _currentUserService.UserId |
|
|
|
|
|
}).ExecuteCommandAsync(); |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
return true; |
|
|
return true; |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
@ -50,49 +137,117 @@ namespace Build_God_Api.Services |
|
|
var monster = await _db.Queryable<Monster>().FirstAsync(x => x.Id == id) |
|
|
var monster = await _db.Queryable<Monster>().FirstAsync(x => x.Id == id) |
|
|
?? throw new Exception("没找到对应的怪兽"); |
|
|
?? throw new Exception("没找到对应的怪兽"); |
|
|
|
|
|
|
|
|
|
|
|
await _db.Deleteable<MonsterEquipment>().Where(x => x.MonsterId == id).ExecuteCommandAsync(); |
|
|
await _db.Deleteable<MonsterReward>().Where(x => x.MonsterId == id).ExecuteCommandAsync(); |
|
|
await _db.Deleteable<MonsterReward>().Where(x => x.MonsterId == id).ExecuteCommandAsync(); |
|
|
await _db.Deleteable(monster).ExecuteCommandAsync(); |
|
|
await _db.Deleteable(monster).ExecuteCommandAsync(); |
|
|
return true; |
|
|
return true; |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
public async Task<bool> ExistsByNameAsync(string name) |
|
|
public async Task<bool> ExistsByNameAsync(string name, int? exceptMonsterId = null) |
|
|
{ |
|
|
{ |
|
|
return await _db.Queryable<Monster>().AnyAsync(x => x.Name == name); |
|
|
return await _db.Queryable<Monster>() |
|
|
|
|
|
.Where(x => x.Name == name) |
|
|
|
|
|
.WhereIF(exceptMonsterId != null, x => x.Id != exceptMonsterId!.Value) |
|
|
|
|
|
.AnyAsync(); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
public async Task<PagedResult<Monster>> GetAll(SearchMonsterDto dto) |
|
|
public async Task<PagedResult<MonsterResponseDto>> GetAll(SearchMonsterDto dto) |
|
|
{ |
|
|
{ |
|
|
var characterLevelId = await _db.Queryable<Character>().Where(c => c.Id == dto.CharacterId).Select(c => c.LevelId).FirstAsync(); |
|
|
int? characterLevelId = null; |
|
|
|
|
|
if (dto.CharacterId is int cid && cid > 0) |
|
|
|
|
|
{ |
|
|
|
|
|
characterLevelId = await _db.Queryable<Character>() |
|
|
|
|
|
.Where(c => c.Id == cid) |
|
|
|
|
|
.Select(c => c.LevelId) |
|
|
|
|
|
.FirstAsync(); |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
var query = _db.Queryable<Monster>() |
|
|
var query = _db.Queryable<Monster>() |
|
|
.WhereIF(dto.MonsterType != null, x => (int)x.Type == dto.MonsterType) |
|
|
.WhereIF(dto.MonsterType != null, x => (int)x.Type == dto.MonsterType) |
|
|
.WhereIF(dto.LevelId != null, x => x.LevelId == dto.LevelId) |
|
|
.WhereIF(dto.LevelId != null, x => x.LevelId == dto.LevelId) |
|
|
.WhereIF(dto.CharacterId != null, x => x.LevelId == characterLevelId) |
|
|
.WhereIF(characterLevelId != null, x => x.LevelId == characterLevelId) |
|
|
.OrderBy(x => x.CreatedOn, OrderByType.Desc); |
|
|
.OrderBy(x => x.CreatedOn, OrderByType.Desc); |
|
|
|
|
|
|
|
|
var list = await query.Skip((dto.PageNumber - 1) * dto.PageSize).Take(dto.PageSize).ToListAsync(); |
|
|
var list = await query.Clone().Skip((dto.PageNumber - 1) * dto.PageSize).Take(dto.PageSize).ToListAsync(); |
|
|
var total = await query.CountAsync(); |
|
|
var total = await query.Clone().CountAsync(); |
|
|
|
|
|
|
|
|
|
|
|
var monsterIds = list.Select(m => m.Id).ToList(); |
|
|
|
|
|
var allEquipment = monsterIds.Count == 0 |
|
|
|
|
|
? new List<MonsterEquipment>() |
|
|
|
|
|
: await _db.Queryable<MonsterEquipment>().Where(e => monsterIds.Contains(e.MonsterId)).ToListAsync(); |
|
|
|
|
|
var allRewards = monsterIds.Count == 0 |
|
|
|
|
|
? new List<MonsterReward>() |
|
|
|
|
|
: await _db.Queryable<MonsterReward>().Where(r => monsterIds.Contains(r.MonsterId)).ToListAsync(); |
|
|
|
|
|
|
|
|
|
|
|
var templateNames = await LoadTemplateNamesAsync(allEquipment.Select(e => e.EquipmentTemplateId)); |
|
|
|
|
|
var rewardGroups = allRewards.GroupBy(r => r.MonsterId).ToDictionary(g => g.Key, g => g.Select(MapReward).ToList()); |
|
|
|
|
|
var equipGroups = allEquipment.GroupBy(e => e.MonsterId).ToDictionary(g => g.Key, g => g.ToList()); |
|
|
|
|
|
|
|
|
return new PagedResult<Monster> |
|
|
var items = new List<MonsterResponseDto>(); |
|
|
|
|
|
foreach (var m in list) |
|
|
|
|
|
{ |
|
|
|
|
|
equipGroups.TryGetValue(m.Id, out var eqList); |
|
|
|
|
|
eqList ??= []; |
|
|
|
|
|
rewardGroups.TryGetValue(m.Id, out var rewList); |
|
|
|
|
|
items.Add(await ToResponseAsync(m, eqList, rewList, templateNames)); |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
return new PagedResult<MonsterResponseDto> |
|
|
{ |
|
|
{ |
|
|
PageNumber = dto.PageNumber, |
|
|
PageNumber = dto.PageNumber, |
|
|
TotalCount = total, |
|
|
TotalCount = total, |
|
|
Items = list |
|
|
Items = items |
|
|
}; |
|
|
}; |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
public async Task<Monster?> GetById(int id) |
|
|
public async Task<MonsterResponseDto?> GetById(int id) |
|
|
{ |
|
|
{ |
|
|
return await _db.Queryable<Monster>().FirstAsync(x => x.Id == id); |
|
|
var m = await _db.Queryable<Monster>().FirstAsync(x => x.Id == id); |
|
|
|
|
|
if (m == null) return null; |
|
|
|
|
|
|
|
|
|
|
|
var equipment = await _db.Queryable<MonsterEquipment>().Where(e => e.MonsterId == id).ToListAsync(); |
|
|
|
|
|
var rewards = await _db.Queryable<MonsterReward>().Where(r => r.MonsterId == id).ToListAsync(); |
|
|
|
|
|
var templateNames = await LoadTemplateNamesAsync(equipment.Select(e => e.EquipmentTemplateId)); |
|
|
|
|
|
return await ToResponseAsync(m, equipment, rewards.Select(MapReward).ToList(), templateNames); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
public async Task<bool> Update(Monster item) |
|
|
public async Task<bool> Update(MonsterSaveDto item) |
|
|
{ |
|
|
{ |
|
|
var monster = await _db.Queryable<Monster>().FirstAsync(x => x.Id == item.Id) |
|
|
var monster = await _db.Queryable<Monster>().FirstAsync(x => x.Id == item.Id) |
|
|
?? throw new Exception("没找到对应的怪兽"); |
|
|
?? throw new Exception("没找到对应的怪兽"); |
|
|
item.UpdatedOn = DateTime.UtcNow; |
|
|
|
|
|
item.UpdatedBy = _currentUserService.UserId; |
|
|
if (!string.Equals(monster.Name, item.Name, StringComparison.Ordinal) && |
|
|
await _db.Updateable(item).ExecuteCommandAsync(); |
|
|
await ExistsByNameAsync(item.Name, item.Id)) |
|
|
|
|
|
{ |
|
|
|
|
|
throw new Exception($"已存在名为 {item.Name} 的怪兽"); |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
monster.Name = item.Name; |
|
|
|
|
|
monster.Description = item.Description; |
|
|
|
|
|
monster.ConfiguredExp = item.ConfiguredExp; |
|
|
|
|
|
monster.ProfessionId = item.ProfessionId; |
|
|
|
|
|
monster.LevelId = item.LevelId; |
|
|
|
|
|
monster.Type = (MonsterType)item.Type; |
|
|
|
|
|
monster.Icon = item.Icon; |
|
|
|
|
|
monster.UpdatedOn = DateTime.UtcNow; |
|
|
|
|
|
monster.UpdatedBy = _currentUserService.UserId; |
|
|
|
|
|
await _db.Updateable(monster).ExecuteCommandAsync(); |
|
|
|
|
|
|
|
|
|
|
|
await _db.Deleteable<MonsterEquipment>().Where(x => x.MonsterId == item.Id).ExecuteCommandAsync(); |
|
|
|
|
|
foreach (var eq in item.Equipment) |
|
|
|
|
|
{ |
|
|
|
|
|
await _db.Insertable(new MonsterEquipment |
|
|
|
|
|
{ |
|
|
|
|
|
MonsterId = item.Id, |
|
|
|
|
|
EquipmentTemplateId = eq.EquipmentTemplateId, |
|
|
|
|
|
Attributes = string.IsNullOrWhiteSpace(eq.Attributes) ? "[]" : eq.Attributes, |
|
|
|
|
|
CreatedOn = DateTime.UtcNow, |
|
|
|
|
|
CreatedBy = _currentUserService.UserId, |
|
|
|
|
|
UpdatedOn = DateTime.UtcNow, |
|
|
|
|
|
UpdatedBy = _currentUserService.UserId |
|
|
|
|
|
}).ExecuteCommandAsync(); |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
return true; |
|
|
return true; |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
|