Files
2025-05-01 07:20:41 +09:00

321 lines
12 KiB
C#

using ServerCore;
using ServerBase;
using ServerCommon;
namespace GameServer;
public class MoneyAction : EntityActionBase, IRemoteTransaction
{
public MoneyAction(Player owner)
: base(owner)
{
}
public override async Task<Result> onInit()
{
await Task.CompletedTask;
var result = new Result();
return result;
}
public override void onClear()
{
return;
}
//=============================================================================================
// delta 만큼 금전을 쓴다.
//=============================================================================================
public async Task<Result> spendMoney(CurrencyType currencyType, double delta, bool isTrimExcess = false, bool useCaliumEvent = true)
{
var result = new Result();
if (ServerCore.TypeHelper.NumericSignType.Positive == ServerCore.TypeHelper.checkNumericSignType<double>(delta))
{
delta *= -1;
}
if (0 > delta)
{
result = await changeMoney(currencyType, delta, isTrimExcess, useCaliumEvent);
if (result.isFail())
{
return result;
}
}
return result;
}
//=============================================================================================
// delta 만큼 금전을 얻는다.
//=============================================================================================
public async Task<Result> earnMoney(CurrencyType currencyType, double delta, bool isTrimExcess = false)
{
var result = new Result();
if (ServerCore.TypeHelper.NumericSignType.Negative == ServerCore.TypeHelper.checkNumericSignType<double>(delta))
{
delta *= -1;
}
if (0 < delta)
{
result = await changeMoney(currencyType, delta, isTrimExcess);
if (result.isFail())
{
return result;
}
}
return result;
}
//=============================================================================================
// delta 만큼 금전을 변경(음수, 양수) 한다.
//=============================================================================================
public async Task<Result> changeMoney(CurrencyType currencyType, double delta, bool isTrimExcess = false, bool useCaliumEvent = true)
{
var result = new Result();
var owner = getOwner() as Player;
NullReferenceCheckHelper.throwIfNull(owner, () => $"player is null !!!");
delta = CurrencyControlHelper.roundMoneyByCurrencyType(currencyType, delta);
if (currencyType == CurrencyType.Beam)
{
var found_transaction_runner = owner.findTransactionRunner(TransactionIdType.PrivateContents);
found_transaction_runner?.addRemoteChargeAIPoint(this, delta);
return result;
}
result = changeMoneyFromCurrencyType(currencyType, delta, isTrimExcess);
if (result.isSuccess() && useCaliumEvent)
{
var found_transaction_runner = owner.findTransactionRunner(TransactionIdType.PrivateContents);
var event_name = found_transaction_runner?.getTransactionName() ?? "None";
found_transaction_runner?.addNotifyCaliumEvent(this, event_name, currencyType, delta);
}
return await Task.FromResult(result);
}
private Result changeMoneyFromCurrencyType(CurrencyType type, double delta, bool isTrimExcess = false)
{
var result = new Result();
var err_msg = string.Empty;
var owner = getOwner() as Player;
NullReferenceCheckHelper.throwIfNull(owner, () => $"player is null !!!");
if (MetaData.Instance._CurrencyMetaTableByCurrencyType.TryGetValue(type, out var currencyMetaData) == false)
{
err_msg = $"Not found CurrencyMetaData !!! : currencyType:{type} - {owner.toBasicString()}";
result.setFail(ServerErrorCode.CurrencyMetaDataNotFound, err_msg);
Log.getLogger().error(result.toBasicString());
return result;
}
var money_attribute = owner.getEntityAttribute<MoneyAttribute>();
NullReferenceCheckHelper.throwIfNull(money_attribute, () => $"money_attribute is null !!! - {owner.toBasicString()}");
var currency = money_attribute.getCurrencyFromType(type);
var change = currency + delta;
if (change < 0)
{
err_msg = $"Failed to change getCurrencyFromType() !!!, not enough Money : deltaMoney:{delta}, changeCurrency:{change}, currencyType:{type} - {owner.toBasicString()}";
result.setFail(ServerErrorCode.MoneyNotEnough, err_msg);
Log.getLogger().error(result.toBasicString());
return result;
}
if (change >= currencyMetaData.MaxCount)
{
MoneyNotifyHelper.send_GS2C_NTF_CURRENCY_MAX_ALERT(owner, type, currencyMetaData.MaxCount);
if (change > currencyMetaData.MaxCount
&& false == isTrimExcess)
{
err_msg = $"Money exceeded Max Count !!! : toDelta:{delta}, toChange:{change} <= MaxCount:{currencyMetaData.MaxCount}, currencyType:{type} - {owner.toBasicString()}";
result.setFail(ServerErrorCode.MoneyMaxCountExceeded, err_msg);
Log.getLogger().error(result.toBasicString());
return result;
}
var trim_money = change - currencyMetaData.MaxCount;
change = double.Min(change, currencyMetaData.MaxCount);
err_msg = $"Exceeded MaxCount of Money !!!, Trimming Money : currencyType:{type}, changeMoney:{change}, trimMoney:{trim_money}, deltaMoney:{delta}, maxMoney:{currencyMetaData.MaxCount} - {owner.toBasicString()}";
Log.getLogger().info(err_msg);
}
money_attribute.setCurrencyFromType(type, change);
money_attribute.modifiedEntityAttribute();
return result;
}
public bool hasMoney(CurrencyType currencyType, double toCheckAmount)
{
var owner = getOwner() as Player;
NullReferenceCheckHelper.throwIfNull(owner, () => $"player is null !!!");
var money_attribute = owner.getEntityAttribute<MoneyAttribute>();
NullReferenceCheckHelper.throwIfNull(money_attribute, () => $"money_attribute is null !!! - {owner.toBasicString()}");
var has_money = money_attribute.getCurrencyFromType(currencyType);
if (has_money < toCheckAmount)
{
return false;
}
return true;
}
public double getMoney(CurrencyType currencyType)
{
var owner = getOwner() as Player;
NullReferenceCheckHelper.throwIfNull(owner, () => $"player is null !!!");
var money_attribute = owner.getEntityAttribute<MoneyAttribute>();
NullReferenceCheckHelper.throwIfNull(money_attribute, () => $"money_attribute is null !!! - {owner.toBasicString()}");
return money_attribute.getCurrencyFromType(currencyType);
}
public CharInfo toCurrency4Client()
{
var owner = getOwner() as Player;
NullReferenceCheckHelper.throwIfNull(owner, () => $"player is null !!!");
var money_attribute = owner.getEntityAttribute<MoneyAttribute>();
NullReferenceCheckHelper.throwIfNull(money_attribute, () => $"money_attribute is null !!! - {owner.toBasicString()}");
var char_info = new CharInfo();
char_info.Gold = money_attribute.Gold;
char_info.Sapphire = money_attribute.Sapphire;
char_info.Calium = money_attribute.Calium;
char_info.Ruby = money_attribute.Ruby;
return char_info;
}
public async Task<Result> callRemoteChargeAIPoint(double beamDelta)
{
var result = new Result();
var err_msg = string.Empty;
var player = getOwner() as Player;
NullReferenceCheckHelper.throwIfNull(player, () => "player is null !!!");
var ai_chat_action = player.getEntityAction<AIChatAction>();
NullReferenceCheckHelper.throwIfNull(ai_chat_action, () => $"ai_chat_action is null !!! - {player.toBasicString()}");
if (beamDelta <= 0)
{
return result;
}
var order_guid = Guid.NewGuid().ToString("N");
result = await ai_chat_action.pointCharge(new AIChatPointCharge() { userGuid = player.getUserGuid(), points = beamDelta, orderGuid = order_guid, pointType = ServerCommon.Constant.AI_CHAT_FREE_POINT, description = "" });
if (result.ErrorCode == ServerErrorCode.AiChatServerRetryChargePoint)
{
var task_reservation_action = player.getEntityAction<TaskReservationAction>();
NullReferenceCheckHelper.throwIfNull(task_reservation_action, () => $"task_reservation_action is null !!! - {player.toBasicString()}");
(result, var task_reservation) = await TaskReservation.createTaskReservationForBeamCharge(player, beamDelta, ServerCommon.Constant.AI_CHAT_FREE_POINT, Guid.NewGuid().ToString("N"));
if(result.isFail() || null == task_reservation)
{
err_msg = $"Failed to create task reservation for beam charge !!! : beamDelta - {beamDelta}, player:{player.toBasicString()}";
Log.getLogger().error(err_msg);
return result;
}
task_reservation_action.AddTask(task_reservation);
}
else if (result.isSuccess())
{
MoneyNotifyHelper.send_GS2C_NTF_BEAM_CHARGE(player);
}
return result;
}
public async Task<Result> callNotifyCaliumEvent(string eventName, CurrencyType currencyType, double delta)
{
var result = new Result();
var err_msg = string.Empty;
var player = getOwner() as Player;
NullReferenceCheckHelper.throwIfNull(player, () => "player is null !!!");
// 1. 조건 체크
var is_condition = checkConditionCaliumEvent(currencyType, delta);
if (false == is_condition) return result;
var sapphire_delta = 0.0;
var calium_delta = 0.0;
var event_type = CaliumEventType.none;
// 1. 기본 정보 설정
if (currencyType == CurrencyType.Sapphire)
{
event_type = CaliumEventType.extra_get;
sapphire_delta = delta;
}
else
{
event_type = CaliumEventType.calium_burn;
calium_delta = delta;
}
// 2. 이벤트 전송 ( 실패시 재시도 처리 ) : Fire And Forget
_ = Task.Run(async () =>
{
var calium_storage_entity = GameServerApp.getServerLogic().findGlobalEntity<CaliumStorageEntity>();
NullReferenceCheckHelper.throwIfNull(calium_storage_entity, () => $"calium_storage_entity");
var calium_event_action = calium_storage_entity.getEntityAction<CaliumEventAction>();
NullReferenceCheckHelper.throwIfNull(calium_event_action, () => $"calium_event_action is null !!! - {calium_storage_entity.toBasicString()} / {player.toBasicString()}");
var send = await calium_event_action.sendCaliumEventFromPlayer(player, event_type, eventName,
sapphire_delta, calium_delta);
if (false == send.is_success)
{
err_msg =
$"failed to echo system from moneyAction !! event_type[{event_type}] / sapphireDelta[{sapphire_delta}] caliumDelta[{calium_delta}]";
result.setFail(ServerErrorCode.FailToSendEchoSystem, err_msg);
Log.getLogger().error(result.toBasicString());
}
});
return await Task.FromResult(result);
}
private bool checkConditionCaliumEvent(CurrencyType currencyType, double delta)
{
// 조건 1. 재화 타입이 Calium or Sapphire 가 아니면 리턴
if (currencyType != CurrencyType.Sapphire && currencyType != CurrencyType.Calium) return false;
// 조건 2. 재화 타입이 Calium 이고 delta 가 양수 이면 리턴
if (currencyType == CurrencyType.Calium && delta > 0) return false;
// 조건 3. 재화 타입이 sapphire 이고, 양수 이면 리턴
if (currencyType == CurrencyType.Sapphire && delta > 0) return false;
return true;
}
}