433 lines
15 KiB
C#
433 lines
15 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
using System.Linq;
|
|
using System.Text;
|
|
using System.Threading.Tasks;
|
|
using System.Runtime.InteropServices;
|
|
|
|
|
|
using Newtonsoft.Json;
|
|
|
|
|
|
using ServerCore;
|
|
using ServerBase;
|
|
using ServerCommon.BusinessLogDomain;
|
|
|
|
|
|
using SESSION_ID = System.Int32;
|
|
using WORLD_ID = System.UInt32;
|
|
using META_ID = System.UInt32;
|
|
using ENTITY_GUID = System.String;
|
|
using ACCOUNT_ID = System.String;
|
|
using OWNER_GUID = System.String;
|
|
using USER_GUID = System.String;
|
|
using CHARACTER_GUID = System.String;
|
|
using ITEM_GUID = System.String;
|
|
using Amazon.S3.Model;
|
|
|
|
|
|
namespace ServerCommon;
|
|
|
|
public static class MoneyAttributeExtensions
|
|
{
|
|
public static double getCurrencyFromType(this MoneyAttribute attribute, CurrencyType type)
|
|
{
|
|
var currency = type switch
|
|
{
|
|
CurrencyType.Gold => attribute.Gold,
|
|
CurrencyType.Sapphire => attribute.Sapphire,
|
|
CurrencyType.Calium => attribute.Calium,
|
|
CurrencyType.Ruby => attribute.Ruby,
|
|
_ => 0
|
|
};
|
|
|
|
return currency;
|
|
}
|
|
|
|
public static void setCurrencyFromType(this MoneyAttribute attribute, CurrencyType type, double currency)
|
|
{
|
|
var result = type switch
|
|
{
|
|
CurrencyType.Gold => attribute.Gold = currency,
|
|
CurrencyType.Sapphire => attribute.Sapphire = currency,
|
|
CurrencyType.Calium => attribute.Calium = currency,
|
|
CurrencyType.Ruby => attribute.Ruby = currency,
|
|
_ => throw new ArgumentOutOfRangeException(nameof(type), type, null)
|
|
};
|
|
}
|
|
}
|
|
|
|
public class MoneyAttribute : EntityAttributeBase, ICopyEntityAttributeFromDoc, IMergeWithEntityAttribute, IWithCommonResultFiller
|
|
{
|
|
[JsonProperty]
|
|
public double Gold
|
|
{
|
|
get { return m_gold; }
|
|
set
|
|
{
|
|
var recorder = getEntityRecorder();
|
|
if (null != recorder)
|
|
{
|
|
recorder.applyDeltaCounter(EntityDeltaType.MoneyGold, value - m_gold, value);
|
|
}
|
|
m_gold = value;
|
|
}
|
|
}
|
|
private double m_gold = 0;
|
|
|
|
|
|
[JsonProperty]
|
|
public double Sapphire
|
|
{
|
|
get { return m_sapphire; }
|
|
set
|
|
{
|
|
var recorder = getEntityRecorder();
|
|
if (null != recorder)
|
|
{
|
|
recorder.applyDeltaCounter(EntityDeltaType.MoneySaphire, value - m_sapphire, value);
|
|
}
|
|
m_sapphire = value;
|
|
}
|
|
}
|
|
private double m_sapphire = 0;
|
|
|
|
[JsonProperty]
|
|
public double Calium
|
|
{
|
|
get { return m_calium; }
|
|
set
|
|
{
|
|
var recorder = getEntityRecorder();
|
|
if (null != recorder)
|
|
{
|
|
recorder.applyDeltaCounter(EntityDeltaType.MoneyCalium, value - m_calium, value);
|
|
}
|
|
m_calium = value;
|
|
}
|
|
}
|
|
private double m_calium = 0;
|
|
|
|
[JsonProperty]
|
|
public double Ruby
|
|
{
|
|
get { return m_ruby; }
|
|
set
|
|
{
|
|
var recorder = getEntityRecorder();
|
|
if (null != recorder)
|
|
{
|
|
recorder.applyDeltaCounter(EntityDeltaType.MoneyRuby, value - m_ruby, value);
|
|
}
|
|
m_ruby = value;
|
|
}
|
|
}
|
|
private double m_ruby = 0;
|
|
|
|
|
|
//=========================================================================================
|
|
// 기본 생성자
|
|
//=========================================================================================
|
|
public MoneyAttribute(UserBase owner)
|
|
: base(owner, true)
|
|
{
|
|
}
|
|
|
|
public override void onClear()
|
|
{
|
|
Gold = 0;
|
|
Sapphire = 0;
|
|
Calium = 0;
|
|
Ruby = 0;
|
|
|
|
getAttributeState().reset();
|
|
}
|
|
|
|
public override EntityAttributeBase onCloned()
|
|
{
|
|
var owner = getOwner() as UserBase;
|
|
NullReferenceCheckHelper.throwIfNull(owner, () => "owner is null !!!");
|
|
|
|
var cloned = new MoneyAttribute(owner);
|
|
cloned.Gold = Gold;
|
|
cloned.Sapphire = Sapphire;
|
|
cloned.Calium = Calium;
|
|
cloned.Ruby = Ruby;
|
|
|
|
return cloned;
|
|
}
|
|
|
|
public override IEntityAttributeTransactor onNewEntityAttributeTransactor()
|
|
{
|
|
return new MoneyAttributeTransactor(getOwner());
|
|
}
|
|
|
|
public override async Task<(Result, DynamoDbDocBase?)> toDocBase(bool isForQuery = true)
|
|
{
|
|
var result = new Result();
|
|
|
|
var owner = getOwner();
|
|
NullReferenceCheckHelper.throwIfNull(owner, () => $"owner is null !!!");
|
|
|
|
var user_attribute = owner.getEntityAttribute<UserAttribute>();
|
|
NullReferenceCheckHelper.throwIfNull(user_attribute, () => $"user_attribute is null !!! - {owner.toBasicString()}");
|
|
|
|
var user_guid = user_attribute.UserGuid;
|
|
|
|
//=====================================================================================
|
|
// Attribute => try pending Doc
|
|
//=====================================================================================
|
|
var try_pending_doc = getTryPendingDocBase() as MoneyDoc;
|
|
if (null == try_pending_doc)
|
|
{
|
|
var to_copy_doc = new MoneyDoc(OwnerEntityType.User, user_guid);
|
|
|
|
var origin_doc = getOriginDocBase<MoneyAttribute>();
|
|
if (null != origin_doc)
|
|
{
|
|
to_copy_doc.copyTimestampsFromOriginDocBase(origin_doc);
|
|
}
|
|
|
|
try_pending_doc = to_copy_doc;
|
|
|
|
setTryPendingDocBase(try_pending_doc);
|
|
}
|
|
|
|
var to_copy_money_attrib = try_pending_doc.getAttrib<MoneyAttrib>();
|
|
NullReferenceCheckHelper.throwIfNull(to_copy_money_attrib, () => $"to_copy_money_attrib is null !!! - {owner.toBasicString()}");
|
|
|
|
to_copy_money_attrib.Gold = Gold;
|
|
to_copy_money_attrib.Sapphire = Sapphire;
|
|
to_copy_money_attrib.Calium = Calium;
|
|
to_copy_money_attrib.Ruby = Ruby;
|
|
|
|
if (false == isForQuery)
|
|
{
|
|
return (result, try_pending_doc);
|
|
}
|
|
|
|
//=====================================================================================
|
|
// Doc QueryType 반영
|
|
//=====================================================================================
|
|
(result, var to_query_doc) = await applyDoc4Query(try_pending_doc);
|
|
if (result.isFail())
|
|
{
|
|
return (result, null);
|
|
}
|
|
|
|
return (result, to_query_doc);
|
|
}
|
|
|
|
public void onFillCommonResult(EntityCommonResult commonResult, EntityAttributeBase origin, QueryBatchBase? queryBatch = null)
|
|
{
|
|
var owner = getOwner();
|
|
NullReferenceCheckHelper.throwIfNull(owner, () => $"owner is null !!!");
|
|
|
|
var before = origin as MoneyAttribute;
|
|
NullReferenceCheckHelper.throwIfNull(before, () => $"before is null !!! - {owner.toBasicString()}");
|
|
var after = this as MoneyAttribute;
|
|
NullReferenceCheckHelper.throwIfNull(after, () => $"after is null !!! - {owner.toBasicString()}");
|
|
|
|
var recorder = after.getEntityRecorder();
|
|
NullReferenceCheckHelper.throwIfNull(recorder, () => $"recorder is null !!! - {owner.toBasicString()}");
|
|
|
|
var money_result = commonResult.Money;
|
|
NullReferenceCheckHelper.throwIfNull(money_result, () => $"money_result is null !!! - {owner.toBasicString()}");
|
|
|
|
var target_types = EnumHelper.getValuesBeginEndBetweenWord<EntityDeltaType>("Money_");
|
|
foreach (var type in target_types)
|
|
{
|
|
var currency_type = type.toCurrencyType();
|
|
if (CurrencyType.None == currency_type)
|
|
{
|
|
var err_msg = $"Failed to toCurrencyType() !!! : EntityDeltaType:{type} - {owner.toBasicString()}";
|
|
Log.getLogger().error(err_msg);
|
|
continue;
|
|
}
|
|
|
|
var found_delta_counter = recorder.findDeltaCounter(type);
|
|
if (null != found_delta_counter)
|
|
{
|
|
var currency_type_key = (Int32)currency_type;
|
|
var delta_count = found_delta_counter.getDeltaCount();
|
|
|
|
if (false == money_result.Moneys.TryGetValue(currency_type_key, out var found_money))
|
|
{
|
|
found_money = new Money();
|
|
money_result.Moneys[currency_type_key] = found_money;
|
|
}
|
|
found_money.Amount = found_delta_counter.getTotalCount();
|
|
|
|
if (false == money_result.Deltas.TryGetValue(currency_type_key, out var found_money_delta_amount))
|
|
{
|
|
found_money_delta_amount = new MoneyDeltaAmount();
|
|
money_result.Deltas[currency_type_key] = found_money_delta_amount;
|
|
}
|
|
found_money_delta_amount.DeltaType = AmountDeltaType.Merge;
|
|
found_money_delta_amount.Amount = delta_count;
|
|
|
|
appendOrWriteBusinessLog4Money(currency_type, delta_count, found_money.Amount, queryBatch);
|
|
}
|
|
}
|
|
}
|
|
|
|
private void appendOrWriteBusinessLog4Money( CurrencyType currencyType, double deltaCount, double amount
|
|
, QueryBatchBase? queryBatch = null )
|
|
{
|
|
var owner = getOwner();
|
|
|
|
var delta_type = AmountDeltaType.None;
|
|
if (deltaCount > 0)
|
|
{
|
|
delta_type = AmountDeltaType.Acquire;
|
|
}
|
|
else if (deltaCount < 0)
|
|
{
|
|
delta_type = AmountDeltaType.Consume;
|
|
}
|
|
|
|
var currency_delta_log = new CurrencyDeltaUpdateBusinessLog( currencyType
|
|
, delta_type, deltaCount, amount );
|
|
if (null != queryBatch)
|
|
{
|
|
queryBatch.appendBusinessLog(currency_delta_log);
|
|
}
|
|
else
|
|
{
|
|
var log_actor = owner as IWithLogActor;
|
|
NullReferenceCheckHelper.throwIfNull(log_actor, () => $"log_actor is null !!! - {owner.toBasicString()}");
|
|
|
|
BusinessLogger.collectLog(log_actor, currency_delta_log);
|
|
}
|
|
}
|
|
|
|
public Result onMerge(EntityAttributeBase otherEntityAttribute)
|
|
{
|
|
var owner = getOwner();
|
|
NullReferenceCheckHelper.throwIfNull(owner, () => $"owner is null !!!");
|
|
|
|
var result = new Result();
|
|
var err_msg = string.Empty;
|
|
|
|
//=====================================================================================
|
|
// OtherAttribute => Attribute
|
|
//=====================================================================================
|
|
var money_attribute = otherEntityAttribute as MoneyAttribute;
|
|
if (null == money_attribute)
|
|
{
|
|
err_msg = $"Failed to cast MoneyAttribute !!!, money_attribute is null - {toBasicString()}, {owner.toBasicString()}";
|
|
result.setFail(ServerErrorCode.ClassTypeCastIsNull, err_msg);
|
|
Log.getLogger().error(result.toBasicString());
|
|
|
|
return result;
|
|
}
|
|
|
|
Gold = money_attribute.Gold;
|
|
Sapphire = money_attribute.Sapphire;
|
|
Calium = money_attribute.Calium;
|
|
Ruby = money_attribute.Ruby;
|
|
|
|
//=====================================================================================
|
|
// Attribute Try Pending Doc => Origin Doc
|
|
//=====================================================================================
|
|
var try_pending_doc = money_attribute.getTryPendingDocBase() as MoneyDoc;
|
|
if (null != try_pending_doc)
|
|
{
|
|
money_attribute.resetTryPendingDocBase();
|
|
|
|
syncOriginDocBaseWithNewDoc<MoneyAttribute>(try_pending_doc);
|
|
}
|
|
|
|
var origin_doc_base = getOriginDocBase<MoneyAttribute>() as MoneyDoc;
|
|
if (null == origin_doc_base)
|
|
{
|
|
// DB 에 저장되어 있지 않는 경우 OriginDoc은 null 이다 !!!
|
|
return result;
|
|
}
|
|
|
|
var money_attrib = origin_doc_base.getAttrib<MoneyAttrib>();
|
|
NullReferenceCheckHelper.throwIfNull(money_attrib, () => $"money_attrib is null !!! - {toBasicString()}, {owner.toBasicString()}");
|
|
|
|
money_attrib.Gold = Gold;
|
|
money_attrib.Sapphire = Sapphire;
|
|
money_attrib.Calium = Calium;
|
|
money_attrib.Ruby = Ruby;
|
|
|
|
return result;
|
|
}
|
|
|
|
public bool copyEntityAttributeFromDoc(DynamoDbDocBase newDocBase)
|
|
{
|
|
var owner = getOwner();
|
|
ArgumentNullReferenceCheckHelper.throwIfNull(owner, () => $"owner is null !!!");
|
|
|
|
var err_msg = string.Empty;
|
|
|
|
var to_cast_string = typeof(ItemDoc).Name;
|
|
|
|
var money_doc = newDocBase as MoneyDoc;
|
|
if (null == money_doc)
|
|
{
|
|
err_msg = $"money_doc is null !!!, in copyEntityAttributeFromDoc() : docName:{nameof(MoneyDoc)} - {owner.toBasicString()}";
|
|
Log.getLogger().error(err_msg);
|
|
return false;
|
|
}
|
|
|
|
//=====================================================================================
|
|
// New Doc => Origin Doc
|
|
//=====================================================================================
|
|
syncOriginDocBaseWithNewDoc<MoneyAttribute>(money_doc);
|
|
|
|
//=====================================================================================
|
|
// Origin Doc => Attribute
|
|
//=====================================================================================
|
|
var money_attrib = money_doc.getAttrib<MoneyAttrib>();
|
|
NullReferenceCheckHelper.throwIfNull(money_attrib, () => $"money_attrib is null !!! - {owner.toBasicString()}");
|
|
|
|
Gold = money_attrib.Gold;
|
|
Sapphire = money_attrib.Sapphire;
|
|
Calium = money_attrib.Calium;
|
|
Ruby = money_attrib.Ruby;
|
|
|
|
return true;
|
|
}
|
|
}
|
|
|
|
public class MoneyAttributeTransactor : EntityAttributeTransactorBase<MoneyAttribute>, ICopyEntityAttributeTransactorFromEntityAttribute
|
|
{
|
|
public MoneyAttributeTransactor(EntityBase owner)
|
|
: base(owner)
|
|
{
|
|
}
|
|
|
|
public bool copyEntityAttributeTransactorFromEntityAttribute(EntityAttributeBase? entityAttributeBase)
|
|
{
|
|
var err_msg = string.Empty;
|
|
|
|
var to_cast_string = typeof(MoneyAttribute).Name;
|
|
|
|
var copy_from_money_attribute = entityAttributeBase as MoneyAttribute;
|
|
if (null == copy_from_money_attribute)
|
|
{
|
|
err_msg = $"Failed to copyEntityAttributeTransactorFromEntityAttribute() !!!, copy_from_money_attribute is null :{to_cast_string}";
|
|
Log.getLogger().error(err_msg);
|
|
return false;
|
|
}
|
|
|
|
var copy_to_money_attribute = getClonedEntityAttribute() as MoneyAttribute;
|
|
if (null == copy_to_money_attribute)
|
|
{
|
|
err_msg = $"Failed to copyEntityAttributeTransactorFromEntityAttribute() !!!, copy_to_money_attribute is null :{to_cast_string}";
|
|
Log.getLogger().error(err_msg);
|
|
return false;
|
|
}
|
|
|
|
copy_to_money_attribute.Gold = copy_to_money_attribute.Gold;
|
|
copy_to_money_attribute.Sapphire = copy_to_money_attribute.Sapphire;
|
|
copy_to_money_attribute.Calium = copy_to_money_attribute.Calium;
|
|
copy_to_money_attribute.Ruby = copy_to_money_attribute.Ruby;
|
|
|
|
return true;
|
|
}
|
|
}
|