/// <summary> /// 可疊數量如果歸0->不刪除紀錄,直接更新成0(背包計算上已處理這塊) /// 不可疊->直接砍掉該筆紀錄 /// </summary> /// <param name="uid"></param> /// <param name="items"></param> /// <param name="fromType"></param> /// <param name="from"></param> /// <returns></returns> public static async ETTask <EquipmentResult> DeleteEquipment(long uid, List <EquipmentInfo> items, EquipmentFrom fromType, int from, bool deleteAnyhow = false) { // 回傳結構 var equipmentResult = new EquipmentResult(); // 抓取使用者背包限制資料 User user = await UserDataHelper.FindOneUser(uid); // 無使用者? if (user == null) { equipmentResult.error = ErrorCode.ERR_AccountDoesntExist; return(equipmentResult); } // 先把相關資料搜尋出來 var eids = items.Select(e => e.ConfigId).ToList(); var results = await dbProxy.Query <Equipment>(entity => entity.uid == uid && eids.Contains(entity.configId)); var equipments = results.OfType <Equipment>().ToList(); // 用企劃表id進行分組 var dictConfigId = OtherHelper.Group(equipments, entity => entity.configId); //// 用企劃表type進行分組(TODO:記得擋背包類型下最大存放數) //var dictConfigType = OtherHelper.Group(equipments, entity => entity.configType); // 批處理 var saveBatch = new List <ComponentWithId>(); var logBatch = new List <ComponentWithId>(); var deleteBatch = new List <long>(); var refreshBagType = new List <int>(); for (int i = 0; i < items.Count; i++) { var item = items[i]; if (item.Count <= 0) { equipmentResult.error = ErrorCode.ERR_EquipmentInvalidCount; return(equipmentResult); } if (TryGetEquipmentConfig(item.ConfigId, out CharacterConfig equipmentConfig)) { // 道具是否可用? if (!equipmentConfig.IsAvailable()) { equipmentResult.error = ErrorCode.ERR_EquipmentUnavailable; return(equipmentResult); } if (!dictConfigId.TryGetValue(equipmentConfig.Id, out var userEqs)) { userEqs = new List <Equipment>(0); } // 道具是否可疊加? if (equipmentConfig.IsStackEquipment()) { var maxCount = equipmentConfig.MaxCountOnSlot; // 可疊不該有兩筆以上的記錄 if (userEqs.Count > 1) { // 記在ErrorLog裡 Log.Error(new Exception($"ERR_EquipmentRecordError> Uid:{uid}, Type:{equipmentConfig.Type}, ConfigId:{equipmentConfig.Id}")); await _MergeEquipment(uid, userEqs.ToArray()); // 合併資料後用遞迴再跑一次 return(await DeleteEquipment(uid, items.Skip(i).ToList(), fromType, from)); } // 判斷有無記錄? else if (userEqs.Count == 0) { equipmentResult.error = ErrorCode.ERR_EquipmentBagIsEmpty; return(equipmentResult); } // 存在一筆紀錄了 else { var userEq = userEqs[0]; if (userEq.count < item.Count) { equipmentResult.error = ErrorCode.ERR_EquipmentNotEnough; return(equipmentResult); } userEq.count -= item.Count; saveBatch.Add(userEq); var log = ComponentFactory.Create <EquipmentLog>(); log.from = from; log.fromType = fromType; log.count = item.Count; var dbLog = _GetSaveEquipmentDBLog(uid, userEq, log, DBLog.LogType.SubtractEquipment); logBatch.Add(dbLog); } } else { if (deleteAnyhow) { var configs = userEqs; if (configs.Count < item.Count) { equipmentResult.error = ErrorCode.ERR_EquipmentNotEnough; return(equipmentResult); } for (int k = 0; k < item.Count; k++) { var config = configs[k]; if (!deleteBatch.Contains(config.Id)) { deleteBatch.Add(config.Id); } } } else { if (!deleteBatch.Contains(item.Id)) { deleteBatch.Add(item.Id); } } } if (!refreshBagType.Contains(equipmentConfig.Type)) { refreshBagType.Add(equipmentConfig.Type); } } else { equipmentResult.error = ErrorCode.ERR_EquipmentNotDefined; return(equipmentResult); } } var result = new RepeatedField <EquipmentInfo>(); // 批刪除 // 不可疊加就根據Id直接砍,Log額外再紀錄 if (deleteBatch.Count != 0) { foreach (var v in dictConfigId) { var dels = OtherHelper.SearchAll(v.Value, entity => deleteBatch.Contains(entity.Id)); var delLog = ComponentFactory.Create <EquipmentLog>(); delLog.from = from; delLog.fromType = fromType; var dbLog = _GetDeleteBatchNoStackEquipmentDBLog(uid, dels, delLog); logBatch.Add(dbLog); } await dbProxy.DeleteJson <Equipment>(entity => deleteBatch.Contains(entity.Id)); foreach (var id in deleteBatch) { result.Add(new EquipmentInfo { Id = id, Count = 0, }); } } // 批儲存資料 if (saveBatch.Count != 0) { await dbProxy.SaveBatch(saveBatch); foreach (var item in saveBatch) { result.Add(((Equipment)item).ToEquipmentInfo()); } } // 批儲存Log if (logBatch.Count != 0) { await dbProxy.SaveBatch(logBatch); } if (refreshBagType.Count != 0) { await user.RecalculateBagCount(refreshBagType); } equipmentResult.error = ErrorCode.ERR_Success; equipmentResult.equipmentInfos = result; equipmentResult.userBagInfo = ToUserBagCapacity(user.userBagCapacity); return(equipmentResult); }
/// <summary> /// 重新計算背包數 /// </summary> /// <param name="user"></param> /// <param name="equipmentTypes"></param> /// <returns></returns> private static async ETTask RecalculateBagCount(this User user, List <int> equipmentTypes) { var userBagCapacity = user.userBagCapacity; var results = await dbProxy.Query <Equipment>(entity => entity.uid == user.Id && equipmentTypes.Contains(entity.configType)); var dict = OtherHelper.Group(results.OfType <Equipment>().ToList(), entity => entity.configType); var logBag = new BsonDocument(); var logCharSetting = new BsonDocument(); var isDecorationExisted = false; for (int a = 0; a < equipmentTypes.Count; a++) { var type = equipmentTypes[a]; var equipmentType = (Equipment.EquipmentType)type; if (!dict.TryGetValue(type, out var equipments)) { equipments = new List <Equipment>(0); } // 初始化 int usedCount = 0; var usedCountString = GetUsedCountString(equipmentType); for (int i = 0; i < equipments.Count; i++) { var equipment = equipments[i]; if (TryGetEquipmentConfig(equipment.configId, out CharacterConfig characterConfig)) { // 不可疊直接++ if (!characterConfig.IsStackEquipment()) { // 現在的不可疊裝備至少有一件符合(TODO:能裝備的裝備一定要不可疊) // TODO:腳色裝備的記錄改用裝備的_id if (equipment.configId == user.playerCharSetting.DecorationId) { isDecorationExisted = true; } usedCount++; } else { if (characterConfig.MaxCountOnSlot < 0) { usedCount++; } else { var remainder = equipment.count % characterConfig.MaxCountOnSlot; var slotCount = equipment.count / characterConfig.MaxCountOnSlot + (remainder == 0 ? 0 : 1); usedCount += slotCount; } } } else { Log.Error($"Equipment config id:{equipment.configId} is not defined!"); continue; } } if (userBagCapacity[usedCountString] != usedCount) { logBag[usedCountString] = usedCount; userBagCapacity[usedCountString] = usedCount; } } if (!isDecorationExisted) { user.playerCharSetting.DecorationId = 0; } await UserDataHelper.UpsertUser(user, DBLog.LogType.UpdateUserBagSlotCount, logBag); }
public static async ETTask <EquipmentResult> CreateEquipment(long uid, List <EquipmentInfo> items, EquipmentFrom fromType, int from) { // 回傳結構 var equipmentResult = new EquipmentResult(); // 抓取使用者背包限制資料 User user = await UserDataHelper.FindOneUser(uid); // 無使用者? if (user == null) { equipmentResult.error = ErrorCode.ERR_AccountDoesntExist; return(equipmentResult); } // 先把相關資料搜尋出來 var eids = items.Select(e => e.ConfigId).ToList(); var ret = await dbProxy.Query <Equipment>(entity => entity.uid == uid && eids.Contains(entity.configId)); var results = ret.OfType <Equipment>().ToList(); // 用企劃表id進行分組 var dictConfigId = OtherHelper.Group(results, entity => entity.configId); // 用企劃表type進行分組(TODO:記得擋背包類型下最大存放數) //var dictConfigType = OtherHelper.Group(results, entity => entity.configType); // 批處理 var saveBatch = new List <ComponentWithId>(); var logBatch = new List <ComponentWithId>(); var refreshBagType = new List <int>(); for (int i = 0; i < items.Count; i++) { var item = items[i]; if (item.Count <= 0) { equipmentResult.error = ErrorCode.ERR_EquipmentInvalidCount; return(equipmentResult); } if (TryGetEquipmentConfig(item.ConfigId, out CharacterConfig equipmentConfig)) { // 道具是否可用? if (!equipmentConfig.IsAvailable()) { equipmentResult.error = ErrorCode.ERR_EquipmentUnavailable; return(equipmentResult); } if (!dictConfigId.TryGetValue(equipmentConfig.Id, out var userEqs)) { userEqs = new List <Equipment>(0); } // 道具是否可疊加? if (equipmentConfig.IsStackEquipment()) { var maxCount = equipmentConfig.MaxCountOnSlot; // 可疊不該有兩筆以上的記錄 if (userEqs.Count > 1) { // 記在ErrorLog裡 Log.Error(new Exception($"ERR_EquipmentRecordError> Uid:{uid}, Type:{equipmentConfig.Type}, ConfigId:{equipmentConfig.Id}")); await _MergeEquipment(uid, userEqs.ToArray()); // 合併資料後用遞迴再跑一次 return(await CreateEquipment(uid, items.Skip(i).ToList(), fromType, from)); } // 判斷有無記錄? else if (userEqs.Count == 0) { // 判斷背包容量 if (user.IsOverOrEqualBagMaxSlotCount((Equipment.EquipmentType)equipmentConfig.Type)) { equipmentResult.error = ErrorCode.ERR_EquipmentBagOverLimit; return(equipmentResult); } else { if (equipmentConfig.IsOverOwnedEquipmentLimit(item.Count)) { equipmentResult.error = ErrorCode.ERR_EquipmentOverOwnedLimit; return(equipmentResult); } var userEq = ComponentFactory.CreateWithId <Equipment>(IdGenerater.GenerateId()); userEq.uid = uid; userEq.configType = equipmentConfig.Type; userEq.configId = item.ConfigId; userEq.count = item.Count; saveBatch.Add(userEq); var log = ComponentFactory.Create <EquipmentLog>(); log.from = from; log.fromType = fromType; log.count = item.Count; var dbLog = _GetSaveEquipmentDBLog(uid, userEq, log, DBLog.LogType.AddEquipment); logBatch.Add(dbLog); } } // 存在一筆紀錄了 else { var userEq = userEqs[0]; userEq.count += item.Count; if (equipmentConfig.IsOverOwnedEquipmentLimit(userEq.count)) { equipmentResult.error = ErrorCode.ERR_EquipmentOverOwnedLimit; return(equipmentResult); } saveBatch.Add(userEq); var log = ComponentFactory.Create <EquipmentLog>(); log.from = from; log.fromType = fromType; log.count = item.Count; var dbLog = _GetSaveEquipmentDBLog(uid, userEq, log, DBLog.LogType.AddEquipment); logBatch.Add(dbLog); } } else { // 不可疊加就直接創,Log額外再紀錄 if (equipmentConfig.IsOverOwnedEquipmentLimit(userEqs.Count + item.Count)) { equipmentResult.error = ErrorCode.ERR_EquipmentOverOwnedLimit; return(equipmentResult); } var equipments = new List <Equipment>(); for (int j = 0; j < item.Count; j++) { var userEq = ComponentFactory.CreateWithId <Equipment>(IdGenerater.GenerateId()); userEq.uid = uid; userEq.configType = equipmentConfig.Type; userEq.configId = equipmentConfig.Id; userEq.count = 1; equipments.Add(userEq); } saveBatch.AddRange(equipments); var log = ComponentFactory.Create <EquipmentLog>(); log.from = from; log.fromType = fromType; var dbLog = _GetSaveBatchEquipmentDBLog(uid, equipments, log); logBatch.Add(dbLog); } if (!refreshBagType.Contains(equipmentConfig.Type)) { refreshBagType.Add(equipmentConfig.Type); } } else { equipmentResult.error = ErrorCode.ERR_EquipmentNotDefined; return(equipmentResult); } } // 批儲存 if (saveBatch.Count != 0) { await dbProxy.SaveBatch(saveBatch); await dbProxy.SaveBatch(logBatch); } if (refreshBagType.Count != 0) { await user.RecalculateBagCount(refreshBagType); } equipmentResult.error = ErrorCode.ERR_Success; equipmentResult.userBagInfo = ToUserBagCapacity(user.userBagCapacity); equipmentResult.equipmentInfos = saveBatch.Aggregate(new RepeatedField <EquipmentInfo>(), (list, item) => { list.Add(((Equipment)item).ToEquipmentInfo()); return(list); }); return(equipmentResult); }