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

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;
}
}