using ServerCore; using ServerBase; using ServerCommon; namespace GameServer; public class CaliumConverterAction : EntityActionBase { public CaliumConverterAction(Player owner) : base(owner) { } public override async Task onInit() => await Task.FromResult(new Result()); public override void onClear() { return; } public async Task<(double calium, double currency)> calculationConvertCalium(Dictionary useMaterials) { var total_fluxEtheron = 0.0; // 1. 플럭스 에테론 변환 처리 foreach (var material in useMaterials) { if (!MetaData.Instance._CaliumConverterMaterialTable.TryGetValue(material.Key, out var material_data)) continue; var fluxEtheron = material_data.Value * material.Value; total_fluxEtheron = CaliumStorageHelper.AddDoubleByLong(total_fluxEtheron, fluxEtheron); } // 2. calium 계산 : fluxEtheron * 기본 변환율 * 에너지 효율 / 소수점 버림 처리 var calium_storage_entity = GameServerApp.getServerLogic().findGlobalEntity(); NullReferenceCheckHelper.throwIfNull(calium_storage_entity, () => $"calium_storage_entity is null !!! : {getOwner().toBasicString()}"); var calium_storage_action = calium_storage_entity.getEntityAction(); NullReferenceCheckHelper.throwIfNull(calium_storage_action, () => $"calium_storage_action is null !!! : {getOwner().toBasicString()}"); var efficiency = await calium_storage_action.getCaliumConverterEfficiency(); var calium = total_fluxEtheron * (double)MetaHelper.GameConfigMeta.CaliumConverterConversionRate * efficiency; calium = CaliumStorageHelper.roundDownDefaultDigitsFromDouble(calium); // 3. 요구 재화 계산 : 소수점 올림 처리 var currency = total_fluxEtheron * (double)ServerCommon.MetaHelper.GameConfigMeta.CaliumConverterCommissionRate; currency = Math.Ceiling(currency); return (calium, currency); } public Result checkConvertConditions(Dictionary useMaterials, double convertCalium, double currency) { var server_logic = GameServerApp.getServerLogic(); var player = getOwner() as Player; NullReferenceCheckHelper.throwIfNull(player, () => $"player is null !!!"); var result = new Result(); string err_msg; var calium_storage_entity = server_logic.findGlobalEntity(); var calium_storage_action = calium_storage_entity?.getEntityAction(); NullReferenceCheckHelper.throwIfNull(calium_storage_action, () => $"calium_storage_action is null !!!"); // 1. Calium 총량 체크 var total_calium = calium_storage_action.getTotalCalium(CaliumStorageType.Converter); if (total_calium < 0) { err_msg = $"fail to convert calium!!! : loading calium - {checkConvertConditions}"; result.setFail(ServerErrorCode.FailToLoadCalium, err_msg); Log.getLogger().error(err_msg); return result; } if (convertCalium > total_calium) { err_msg = $"fail to convert calium!!! : lack of total calium - calium[{convertCalium}] / total[{total_calium}]"; result.setFail(ServerErrorCode.LackOfTotalCalium, err_msg); Log.getLogger().error(err_msg); return result; } // 2. 1일 제한 용량 체크 var user_calium_attribute = player.getEntityAttribute(); NullReferenceCheckHelper.throwIfNull(user_calium_attribute, () => $"user_calium_attribute is null !!! - {player.toBasicString()}"); var daily_calium = CaliumStorageHelper.roundHalfUpDefaultDigitsFromDouble(user_calium_attribute.DailyCalium); if (convertCalium > daily_calium) { err_msg = $"fail to convert calium!!! : lack of daily calium - calium[{convertCalium}] / daily[{user_calium_attribute.DailyCalium}] / roundUp[{daily_calium}]"; result.setFail(ServerErrorCode.LackOfDailyCalium, err_msg); Log.getLogger().error(err_msg); return result; } // 3. 재화 보유 체크 if (! checkCurrencyForConvertCalium(currency)) { err_msg = $"fail to convert calium!!! : lack of currency - currency[{currency}]"; result.setFail(ServerErrorCode.LackOfCommissionCurrency, err_msg); Log.getLogger().error(err_msg); return result; } // 4. 아이템 보유 체크 if (!checkItemForConvertCalium(useMaterials)) { err_msg = $"fail to convert calium!!! : lack of meterial - useMaterials[{useMaterials}]"; result.setFail(ServerErrorCode.LackOfCommissionMaterials, err_msg); Log.getLogger().error(err_msg); return result; } return result; } private bool checkCurrencyForConvertCalium(double currency) { var money_attribute = getOwner().getEntityAttribute(); NullReferenceCheckHelper.throwIfNull(money_attribute, () => $"money_attribute is null !!!"); var owner_currency = MetaHelper.GameConfigMeta.CaliumConverterCommissionType switch { CurrencyType.Gold => money_attribute.Gold, CurrencyType.Sapphire => money_attribute.Sapphire, CurrencyType.Ruby => money_attribute.Ruby, _ => 0.0 }; return currency <= owner_currency; } private bool checkItemForConvertCalium(Dictionary useMaterials) { foreach (var material in useMaterials) { var inventory_action = getOwner().getEntityAction(); if (!MetaData.Instance._CaliumConverterMaterialTable.TryGetValue(material.Key, out var material_data)) { return false; } NullReferenceCheckHelper.throwIfNull(inventory_action, () => $"inventory_action is null !!!"); var own_count = inventory_action.getItemStackCountAllByMetaId((uint)material_data.ItemId); if (material.Value > own_count) return false; } return true; } public async Task<(Result result, IEnumerable? items)> deleteMaterials(Dictionary useMaterials) { var result = new Result(); string err_msg; var inventory_action = getOwner().getEntityAction(); NullReferenceCheckHelper.throwIfNull(inventory_action, () => $"inventory_action is null !!!"); var items = new List(); foreach (var material in useMaterials) { if (!MetaData.Instance._CaliumConverterMaterialTable.TryGetValue(material.Key, out var material_data)) { err_msg = $"fail to convert calium !!! : invalid material slot id - input slotId[{material.Key}]"; result.setFail(ServerErrorCode.InvalidMaterialSlotId, err_msg); Log.getLogger().error(result.toBasicString()); return (result, null); } (result, var item) = await inventory_action.tryDeleteItemByMetaId((uint)material_data.ItemId, (ushort)material.Value); if (result.isFail()) { err_msg = $"fail to convert calium !!! : lack of material count - input slotId[{material.Key}] / cout[{material.Value}]"; result.setFail(ServerErrorCode.LackOfCommissionMaterials, err_msg); Log.getLogger().error(result.toBasicString()); return (result, null); } items.AddRange(item); } return (result, items); } public async Task changeCurrency(double obtainCalium, CurrencyType currencyType, double spendCurrency) { var result = new Result(); var money_action = getOwner().getEntityAction(); NullReferenceCheckHelper.throwIfNull(money_action, () => $"money_action is null !!!"); // 1. calium 획득 result = await money_action.changeMoney(CurrencyType.Calium, obtainCalium, useCaliumEvent: false); if (result.isFail()) return result; // 2. 변환을 위한 재화 소모 result = await money_action.changeMoney(currencyType, -1 * spendCurrency, useCaliumEvent: false); return result; } public Result changeDailyCalium(Player player, double calium) { var result = new Result(); // 1. 개인 daily calium 수량 수정 var user_calium_attribute = player.getEntityAttribute(); NullReferenceCheckHelper.throwIfNull(user_calium_attribute, () => $"user_calium_attribute is null !!! - calium:{calium} / {player.toBasicString()}"); user_calium_attribute.DailyCalium -= calium; user_calium_attribute.modifiedEntityAttribute(); return result; } }