321 lines
12 KiB
C#
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;
|
|
}
|
|
} |