초기커밋
This commit is contained in:
847
ServerBase/Entity/Transaction/TransactionRunner.cs
Normal file
847
ServerBase/Entity/Transaction/TransactionRunner.cs
Normal file
@@ -0,0 +1,847 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.Concurrent;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using System.Runtime.ConstrainedExecution;
|
||||
|
||||
|
||||
|
||||
using NLog;
|
||||
using Amazon.DynamoDBv2.Model;
|
||||
using Newtonsoft.Json;
|
||||
using Pipelines.Sockets.Unofficial.Buffers;
|
||||
using StackExchange.Redis;
|
||||
using Google.Protobuf.Collections;
|
||||
using ServerControlCenter;
|
||||
using Amazon.S3.Model;
|
||||
|
||||
|
||||
|
||||
using ServerCore; using ServerBase;
|
||||
|
||||
|
||||
|
||||
using SESSION_ID = System.Int32;
|
||||
using WORLD_ID = System.UInt32;
|
||||
using META_ID = System.UInt32;
|
||||
using TRANSACTION_NAME = System.String;
|
||||
using TRANSACTION_GUID = System.String;
|
||||
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;
|
||||
|
||||
|
||||
namespace ServerBase;
|
||||
|
||||
public class ReservedSlotOnInven
|
||||
{
|
||||
public class ReservedSlot
|
||||
{
|
||||
private Int16 m_reserved_count = 0;
|
||||
|
||||
private EntityBase? m_equip_entity_nullable;
|
||||
private EntityBase? m_unequip_entity_nullable;
|
||||
|
||||
public ReservedSlot()
|
||||
{ }
|
||||
|
||||
public void incReservedCount(Int16 reservedItemCount)
|
||||
{
|
||||
m_reserved_count += reservedItemCount;
|
||||
}
|
||||
|
||||
public void decReservedCount(Int16 reservedItemCount)
|
||||
{
|
||||
m_reserved_count -= reservedItemCount;
|
||||
}
|
||||
|
||||
public Int16 getReservedCount() => m_reserved_count;
|
||||
|
||||
public void setEquipEntity(EntityBase? entityBase) => m_equip_entity_nullable = entityBase;
|
||||
|
||||
public EntityBase? getEquipEntity() => m_equip_entity_nullable;
|
||||
|
||||
public void setUnequipEntity(EntityBase? entityBase) => m_unequip_entity_nullable = entityBase;
|
||||
|
||||
public EntityBase? getUnequipEntity() => m_unequip_entity_nullable;
|
||||
}
|
||||
|
||||
private EntityType m_entity_inven_type = EntityType.None;
|
||||
|
||||
private readonly Dictionary<string, ReservedSlot> m_reserved_slots = new();
|
||||
|
||||
public ReservedSlotOnInven(EntityType entityInvenType)
|
||||
{
|
||||
m_entity_inven_type = entityInvenType;
|
||||
}
|
||||
|
||||
public void addOrInc(string slotKey, Int16 incReservedCount)
|
||||
{
|
||||
if(false == m_reserved_slots.TryGetValue(slotKey, out var found_reserved_slot))
|
||||
{
|
||||
found_reserved_slot = new ReservedSlot();
|
||||
m_reserved_slots.Add(slotKey, found_reserved_slot);
|
||||
}
|
||||
|
||||
found_reserved_slot.incReservedCount(incReservedCount);
|
||||
}
|
||||
|
||||
public void addOrDec(string slotKey, Int16 decReservedCount)
|
||||
{
|
||||
if (false == m_reserved_slots.TryGetValue(slotKey, out var found_reserved_slot))
|
||||
{
|
||||
found_reserved_slot = new ReservedSlot();
|
||||
m_reserved_slots.Add(slotKey, found_reserved_slot);
|
||||
}
|
||||
|
||||
found_reserved_slot.decReservedCount(decReservedCount);
|
||||
}
|
||||
|
||||
public Dictionary<string, ReservedSlot> getReservedSlots() => m_reserved_slots;
|
||||
|
||||
public EntityType getEntityType() => m_entity_inven_type;
|
||||
}
|
||||
|
||||
|
||||
public partial class TransactionRunner : IDisposable
|
||||
{
|
||||
private readonly EntityBase m_owner;
|
||||
|
||||
private readonly string m_trans_id = string.Empty;
|
||||
|
||||
private readonly TransactionIdType m_transaction_id_type = TransactionIdType.None;
|
||||
|
||||
private readonly ConcurrentDictionary<Type, ConcurrentDictionary<ENTITY_GUID, IEntityAttributeTransactor>> m_entity_attribute_transactors = new();
|
||||
|
||||
private readonly ConcurrentQueue<IEntityAttributeTransactor> m_to_db_query_transactors = new(); // Db Query용 (순서 보장 중요)
|
||||
|
||||
private readonly ConcurrentDictionary<EntityBase, ConcurrentDictionary<EntityType, ReservedSlotOnInven>> m_reserved_inven_slots_of_owners = new();
|
||||
|
||||
private readonly ConcurrentDictionary<string, EntityCommonResult> m_entity_common_results = new();
|
||||
|
||||
//IRemoteTransaction
|
||||
private readonly List<Func<Task>> m_remote_transaction_funcs = new();
|
||||
|
||||
private string m_transaction_name;
|
||||
|
||||
private bool m_is_binding = false;
|
||||
|
||||
public TransactionRunner(EntityBase owner, TransactionIdType idType, string transactionName)
|
||||
{
|
||||
m_owner = owner;
|
||||
|
||||
m_trans_id = System.Guid.NewGuid().ToString("N");
|
||||
m_transaction_id_type = idType;
|
||||
m_transaction_name = transactionName;
|
||||
}
|
||||
|
||||
public TransactionRunner(EntityBase owner, string transId, TransactionIdType idType, string transactionName)
|
||||
{
|
||||
m_owner = owner;
|
||||
|
||||
m_trans_id = transId;
|
||||
m_transaction_id_type = idType;
|
||||
m_transaction_name = transactionName;
|
||||
}
|
||||
|
||||
public Result beginTransaction()
|
||||
{
|
||||
var result = new Result();
|
||||
var err_msg = string.Empty;
|
||||
|
||||
result = m_owner.bindTransactionRunner(this);
|
||||
if(result.isFail())
|
||||
{
|
||||
return result;
|
||||
}
|
||||
|
||||
setBinding();
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
public void clearTransaction()
|
||||
{
|
||||
m_entity_attribute_transactors.Clear();
|
||||
m_reserved_inven_slots_of_owners.Clear();
|
||||
m_to_db_query_transactors.Clear();
|
||||
}
|
||||
|
||||
// override IDisposable.Dispose
|
||||
public void Dispose()
|
||||
{
|
||||
var err_msg = string.Empty;
|
||||
|
||||
if (false == isBinding())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
var owner = getOwner();
|
||||
NullReferenceCheckHelper.throwIfNull(owner, () => $"owner is null !!!");
|
||||
|
||||
if (false == m_owner.unbindTransactionRunner(this))
|
||||
{
|
||||
err_msg = $"Failed to unbindTransactionRunner() !!! : {toBasicString()} - {owner.toBasicString()}";
|
||||
Log.getLogger().error(err_msg);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
public void resetTransaction(string transactionName)
|
||||
{
|
||||
clearTransaction();
|
||||
m_transaction_name = transactionName;
|
||||
}
|
||||
|
||||
public async Task<Result> onCommitResults(QueryBatchBase? queryBatch = null)
|
||||
{
|
||||
await Task.CompletedTask;
|
||||
|
||||
var owner = getOwner();
|
||||
NullReferenceCheckHelper.throwIfNull(owner, () => $"owner is null !!!");
|
||||
|
||||
var result = new Result();
|
||||
var err_msg = string.Empty;
|
||||
|
||||
var transactors = getEntityAttributeTransactorAll();
|
||||
|
||||
// 메모리를 동기화 한다.
|
||||
foreach (var to_sync_merge in transactors)
|
||||
{
|
||||
var origin_entity_attribute = to_sync_merge.getOriginEntityAttribute();
|
||||
NullReferenceCheckHelper.throwIfNull(origin_entity_attribute, () => $"origin_entity_attribute is null !!! - {owner.toBasicString()}");
|
||||
|
||||
var to_merge_attribute = origin_entity_attribute as IMergeWithEntityAttribute;
|
||||
if (null == to_merge_attribute)
|
||||
{
|
||||
err_msg = $"Failed to cast IMergeWithEntityAttribute !!! : OriginEntityAttribute:{origin_entity_attribute.toBasicString()} - {owner.toBasicString()}";
|
||||
Log.getLogger().error(err_msg);
|
||||
continue;
|
||||
}
|
||||
|
||||
var cloned_entity_attribute = to_sync_merge.getClonedEntityAttribute();
|
||||
if (null == cloned_entity_attribute)
|
||||
{
|
||||
err_msg = $"getClonedEntityAttribute() is null !!! : OriginEntityAttribute:{origin_entity_attribute.toBasicString()} - {owner.toBasicString()}";
|
||||
Log.getLogger().error(err_msg);
|
||||
continue;
|
||||
}
|
||||
|
||||
var comon_result_filler = cloned_entity_attribute as IWithCommonResultFiller;
|
||||
if (null != comon_result_filler)
|
||||
{
|
||||
(result, var entity_common_result) = getOrNewEntityCommonResult(cloned_entity_attribute);
|
||||
if (result.isFail())
|
||||
{
|
||||
Log.getLogger().fatal(result.toBasicString());
|
||||
}
|
||||
else
|
||||
{
|
||||
NullReferenceCheckHelper.throwIfNull(entity_common_result, () => $"entity_common_result is null !!! - {owner.toBasicString()}");
|
||||
comon_result_filler.onFillCommonResult(entity_common_result, origin_entity_attribute, queryBatch);
|
||||
}
|
||||
}
|
||||
|
||||
result = to_merge_attribute.onMerge(cloned_entity_attribute);
|
||||
if (result.isFail())
|
||||
{
|
||||
err_msg = $"Failed to onMerge() !!! : {result.toBasicString()} - {owner.toBasicString()}";
|
||||
Log.getLogger().debug(err_msg);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
var reserved_iven_slots_of_owners = getReservedInvenSlotAllOfOwners();
|
||||
foreach(var each in reserved_iven_slots_of_owners)
|
||||
{
|
||||
var inven_owner = each.Key;
|
||||
var reserved_inven_slots = each.Value;
|
||||
|
||||
var to_merge_inventory = inven_owner as IMergeWithInventory;
|
||||
if (null != to_merge_inventory)
|
||||
{
|
||||
result = await to_merge_inventory.onMerge(reserved_inven_slots.Values.ToList<ReservedSlotOnInven>(), this);
|
||||
if (result.isFail())
|
||||
{
|
||||
err_msg = $"Failed to IMergeWithInventory.onMerge() !!! : {result.toBasicString()} - {inven_owner.toBasicString()}, {owner.toBasicString()}";
|
||||
Log.getLogger().fatal(err_msg);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
reserved_iven_slots_of_owners.Clear();
|
||||
|
||||
await tryStartRemoteTransaction();
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
public async Task<Result> onCommitResults4DbQuery(List<IEntityAttributeTransactor> dbQueriedTransactors, QueryBatchBase? queryBatch = null)
|
||||
{
|
||||
await Task.CompletedTask;
|
||||
|
||||
var owner = getOwner();
|
||||
NullReferenceCheckHelper.throwIfNull(owner, () => $"owner is null !!!");
|
||||
NullReferenceCheckHelper.throwIfNull(dbQueriedTransactors, () => $"dbQueriedTransactors is null !!! - {owner.toBasicString()}");
|
||||
|
||||
var result = new Result();
|
||||
var err_msg = string.Empty;
|
||||
|
||||
foreach (var to_sync_merge in dbQueriedTransactors)
|
||||
{
|
||||
var origin_entity_attribute = to_sync_merge.getOriginEntityAttribute();
|
||||
NullReferenceCheckHelper.throwIfNull(origin_entity_attribute, () => $"origin_entity_attribute is null !!! - {owner.toBasicString()}");
|
||||
|
||||
var to_merge_attribute = origin_entity_attribute as IMergeWithEntityAttribute;
|
||||
if (null == to_merge_attribute)
|
||||
{
|
||||
err_msg = $"Failed to cast IMergeWithEntityAttribute !!! : OriginEntityAttribute:{origin_entity_attribute.toBasicString()} - {owner.toBasicString()}";
|
||||
Log.getLogger().error(err_msg);
|
||||
continue;
|
||||
}
|
||||
|
||||
var cloned_entity_attribute = to_sync_merge.getClonedEntityAttribute();
|
||||
if (null == cloned_entity_attribute)
|
||||
{
|
||||
err_msg = $"getClonedEntityAttribute() is null !!! : OriginEntityAttribute:{origin_entity_attribute.toBasicString()} - {owner.toBasicString()}";
|
||||
Log.getLogger().error(err_msg);
|
||||
continue;
|
||||
}
|
||||
|
||||
if(true == m_entity_attribute_transactors.TryGetValue(origin_entity_attribute.GetType(), out var found_transactors))
|
||||
{
|
||||
// DB 처리후 여기서 origin_entity_attribute Merge를 하므로
|
||||
// onCommitResults() 함수로 중복된 Merge를 시도할 수 있으므로 m_entity_attribute_transactors 에서 제거 한다. - kangms
|
||||
found_transactors.Remove(origin_entity_attribute.getOwner().getEntityGuid(), out _);
|
||||
}
|
||||
|
||||
var comon_result_filler = cloned_entity_attribute as IWithCommonResultFiller;
|
||||
if (null != comon_result_filler)
|
||||
{
|
||||
(result, var entity_common_result) = getOrNewEntityCommonResult(cloned_entity_attribute);
|
||||
if (result.isFail())
|
||||
{
|
||||
Log.getLogger().fatal(result.toBasicString());
|
||||
}
|
||||
else
|
||||
{
|
||||
NullReferenceCheckHelper.throwIfNull(entity_common_result, () => $"entity_common_result is null !!! - {owner.toBasicString()}");
|
||||
comon_result_filler.onFillCommonResult(entity_common_result, origin_entity_attribute, queryBatch);
|
||||
}
|
||||
}
|
||||
|
||||
result = to_merge_attribute.onMerge(cloned_entity_attribute);
|
||||
if (result.isFail())
|
||||
{
|
||||
err_msg = $"Failed to onMerge() !!! : {result.toBasicString()} - {owner.toBasicString()}";
|
||||
Log.getLogger().error(err_msg);
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
var reserved_iven_slots_of_owners = getReservedInvenSlotAllOfOwners();
|
||||
foreach (var each in reserved_iven_slots_of_owners)
|
||||
{
|
||||
var inven_owner = each.Key;
|
||||
var reserved_inven_slots = each.Value;
|
||||
|
||||
var to_merge_inventory = inven_owner as IMergeWithInventory;
|
||||
if (null != to_merge_inventory)
|
||||
{
|
||||
result = await to_merge_inventory.onMerge(reserved_inven_slots.Values.ToList<ReservedSlotOnInven>(), this);
|
||||
if (result.isFail())
|
||||
{
|
||||
err_msg = $"Failed to IMergeWithInventory.onMerge() !!! : {result.toBasicString()} - {inven_owner.toBasicString()}, {owner.toBasicString()}";
|
||||
Log.getLogger().error(err_msg);
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
||||
}
|
||||
reserved_iven_slots_of_owners.Clear();
|
||||
|
||||
await tryStartRemoteTransaction();
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
public ConcurrentDictionary<ENTITY_GUID, IEntityAttributeTransactor> getEntityAttributeTransactorAll(Type targetEntityAttribute)
|
||||
{
|
||||
var err_msg = string.Empty;
|
||||
|
||||
var entity_attribute_transactors = new List<IEntityAttributeTransactor>();
|
||||
|
||||
if(false == m_entity_attribute_transactors.TryGetValue(targetEntityAttribute, out var found_transactors))
|
||||
{
|
||||
return new ConcurrentDictionary<ENTITY_GUID, IEntityAttributeTransactor>();
|
||||
}
|
||||
|
||||
return found_transactors;
|
||||
}
|
||||
|
||||
public ConcurrentDictionary<ENTITY_GUID, IEntityAttributeTransactor> getEntityAttributeTransactorAll<TEntityAttributeType>()
|
||||
where TEntityAttributeType : EntityAttributeBase
|
||||
{
|
||||
var err_msg = string.Empty;
|
||||
|
||||
var entity_attribute_transactors = new List<IEntityAttributeTransactor>();
|
||||
|
||||
var target_type = typeof(TEntityAttributeType);
|
||||
|
||||
if(false == m_entity_attribute_transactors.TryGetValue(target_type, out var found_transactors))
|
||||
{
|
||||
return new ConcurrentDictionary<ENTITY_GUID, IEntityAttributeTransactor>();
|
||||
}
|
||||
|
||||
return found_transactors;
|
||||
}
|
||||
|
||||
public List<IEntityAttributeTransactor> getEntityAttributeTransactorAll()
|
||||
{
|
||||
var err_msg = string.Empty;
|
||||
|
||||
var entity_attribute_transactors = new List<IEntityAttributeTransactor>();
|
||||
|
||||
foreach (var each_attribute_type in m_entity_attribute_transactors)
|
||||
{
|
||||
foreach (var each_attribute_transactor in each_attribute_type.Value)
|
||||
{
|
||||
var transactor_entity_guid = each_attribute_transactor.Key;
|
||||
var transactor = each_attribute_transactor.Value;
|
||||
if (null == transactor)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
entity_attribute_transactors.Add(transactor);
|
||||
}
|
||||
}
|
||||
|
||||
return entity_attribute_transactors;
|
||||
}
|
||||
|
||||
public List<IEntityAttributeTransactor> getEntityAttributeTransactorAll4DbQuery()
|
||||
{
|
||||
var err_msg = string.Empty;
|
||||
|
||||
var transactors = new List<IEntityAttributeTransactor>();
|
||||
|
||||
while (false == m_to_db_query_transactors.IsEmpty)
|
||||
{
|
||||
if (true == m_to_db_query_transactors.TryDequeue(out var transactor))
|
||||
{
|
||||
transactors.Add(transactor);
|
||||
}
|
||||
}
|
||||
|
||||
return transactors;
|
||||
}
|
||||
|
||||
public TEntityAttribute? getEntityAttribute<TEntityAttribute>(TEntityAttribute fromOriginEntityAttributeBase)
|
||||
where TEntityAttribute : EntityAttributeBase
|
||||
{
|
||||
var owner = getOwner();
|
||||
NullReferenceCheckHelper.throwIfNull(owner, () => $"owner is null !!!");
|
||||
ArgumentNullReferenceCheckHelper.throwIfNull(fromOriginEntityAttributeBase, () => $"fromOriginEntityAttributeBase is null !!! - {owner.toBasicString()}");
|
||||
|
||||
var to_add_type = fromOriginEntityAttributeBase.GetType();
|
||||
var entity_guid = fromOriginEntityAttributeBase.getOwner().getEntityGuid();
|
||||
|
||||
ConcurrentDictionary<ENTITY_GUID, IEntityAttributeTransactor>? found_transactors;
|
||||
|
||||
lock (m_entity_attribute_transactors)
|
||||
{
|
||||
if (false == m_entity_attribute_transactors.TryGetValue(to_add_type, out found_transactors))
|
||||
{
|
||||
found_transactors = new();
|
||||
m_entity_attribute_transactors[to_add_type] = found_transactors;
|
||||
}
|
||||
}
|
||||
|
||||
IEntityAttributeTransactor found_transactor;
|
||||
|
||||
var add_transactor = delegate (ENTITY_GUID entityGuid)
|
||||
{
|
||||
found_transactor = fromOriginEntityAttributeBase.onNewEntityAttributeTransactor();
|
||||
|
||||
if (false == found_transactor.cloneFromOriginEntityAttribute(fromOriginEntityAttributeBase))
|
||||
{
|
||||
var err_msg = $"Failed to cloneFromOriginEntityAttribute() !!! - {toBasicString()}, {owner.toBasicString()}";
|
||||
Log.getLogger().error(err_msg);
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
m_to_db_query_transactors.Enqueue(found_transactor);
|
||||
|
||||
return found_transactor;
|
||||
};
|
||||
|
||||
found_transactor = found_transactors.GetOrAdd(entity_guid, add_transactor!);
|
||||
if (null == found_transactor)
|
||||
{
|
||||
var err_msg = $"Failed to GetOrAdd() !!! : {fromOriginEntityAttributeBase.toBasicString()} - {toBasicString()}, {owner.toBasicString()}";
|
||||
Log.getLogger().error(err_msg);
|
||||
}
|
||||
else
|
||||
{
|
||||
return found_transactor.getClonedEntityAttribute() as TEntityAttribute;
|
||||
}
|
||||
|
||||
return fromOriginEntityAttributeBase as TEntityAttribute;
|
||||
}
|
||||
|
||||
public TEntityAttribute? getEntityAttributeWithReadOnly<TEntityAttribute>(TEntityAttribute fromOriginEntityAttributeBase)
|
||||
where TEntityAttribute : EntityAttributeBase
|
||||
{
|
||||
var owner = getOwner();
|
||||
NullReferenceCheckHelper.throwIfNull(owner, () => $"owner is null !!!");
|
||||
ArgumentNullReferenceCheckHelper.throwIfNull(fromOriginEntityAttributeBase, () => $"fromOriginEntityAttributeBase is null !!! - {owner.toBasicString()}");
|
||||
|
||||
var to_add_type = fromOriginEntityAttributeBase.GetType();
|
||||
var entity_guid = fromOriginEntityAttributeBase.getOwner().getEntityGuid();
|
||||
|
||||
ConcurrentDictionary<ENTITY_GUID, IEntityAttributeTransactor>? found_transactors;
|
||||
|
||||
lock (m_entity_attribute_transactors)
|
||||
{
|
||||
m_entity_attribute_transactors.TryGetValue(to_add_type, out found_transactors);
|
||||
|
||||
IEntityAttributeTransactor? found_transactor = null;
|
||||
|
||||
if (null != found_transactors)
|
||||
{
|
||||
found_transactors.TryGetValue(entity_guid, out found_transactor);
|
||||
}
|
||||
|
||||
if (null != found_transactor)
|
||||
{
|
||||
return found_transactor.getClonedEntityAttribute() as TEntityAttribute;
|
||||
}
|
||||
|
||||
return fromOriginEntityAttributeBase as TEntityAttribute;
|
||||
}
|
||||
}
|
||||
|
||||
public Result tryIncReserveSlotCount(EntityBase invenOwner, EntityType entityInvenType, string slotType)
|
||||
{
|
||||
var owner = getOwner();
|
||||
NullReferenceCheckHelper.throwIfNull(owner, () => $"owner is null !!!");
|
||||
ArgumentNullReferenceCheckHelper.throwIfNull(invenOwner, () => $"invenOwner is null !!! - {owner.toBasicString()}");
|
||||
|
||||
var result = new Result();
|
||||
|
||||
ConcurrentDictionary<EntityType, ReservedSlotOnInven>? found_reserved_inven_slots;
|
||||
|
||||
lock (m_reserved_inven_slots_of_owners)
|
||||
{
|
||||
if (false == m_reserved_inven_slots_of_owners.TryGetValue(invenOwner, out found_reserved_inven_slots))
|
||||
{
|
||||
found_reserved_inven_slots = new ConcurrentDictionary<EntityType, ReservedSlotOnInven>();
|
||||
m_reserved_inven_slots_of_owners[invenOwner] = found_reserved_inven_slots;
|
||||
}
|
||||
}
|
||||
|
||||
var add_recorder = delegate (EntityType invenType)
|
||||
{
|
||||
var reserved_slot = new ReservedSlotOnInven(entityInvenType);
|
||||
reserved_slot.addOrInc(slotType, 1);
|
||||
|
||||
return reserved_slot;
|
||||
};
|
||||
|
||||
var update_recorder = delegate (EntityType invenType, ReservedSlotOnInven currValue)
|
||||
{
|
||||
if (false == currValue.getReservedSlots().TryGetValue(slotType, out var found_reserved_slot))
|
||||
{
|
||||
found_reserved_slot = new ReservedSlotOnInven.ReservedSlot();
|
||||
currValue.getReservedSlots().Add(slotType, found_reserved_slot);
|
||||
}
|
||||
|
||||
found_reserved_slot.incReservedCount(1);
|
||||
|
||||
return currValue;
|
||||
};
|
||||
|
||||
found_reserved_inven_slots.AddOrUpdate(entityInvenType, add_recorder, update_recorder);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
public Result tryDecToReserveSlotCount(EntityBase invenOwner, EntityType entityInvenType, string slotType)
|
||||
{
|
||||
var owner = getOwner();
|
||||
NullReferenceCheckHelper.throwIfNull(owner, () => $"owner is null !!!");
|
||||
ArgumentNullReferenceCheckHelper.throwIfNull(invenOwner, () => $"invenOwner is null !!! - {owner.toBasicString()}");
|
||||
|
||||
var result = new Result();
|
||||
|
||||
ConcurrentDictionary<EntityType, ReservedSlotOnInven>? found_reserved_inven_slots;
|
||||
|
||||
lock (m_reserved_inven_slots_of_owners)
|
||||
{
|
||||
if (false == m_reserved_inven_slots_of_owners.TryGetValue(invenOwner, out found_reserved_inven_slots))
|
||||
{
|
||||
found_reserved_inven_slots = new ConcurrentDictionary<EntityType, ReservedSlotOnInven>();
|
||||
m_reserved_inven_slots_of_owners[invenOwner] = found_reserved_inven_slots;
|
||||
}
|
||||
}
|
||||
|
||||
var add_recorder = delegate (EntityType invenType)
|
||||
{
|
||||
var reserved_slot = new ReservedSlotOnInven(entityInvenType);
|
||||
reserved_slot.addOrDec(slotType, 1);
|
||||
|
||||
return reserved_slot;
|
||||
};
|
||||
|
||||
var update_recorder = delegate (EntityType invenType, ReservedSlotOnInven currValue)
|
||||
{
|
||||
if (false == currValue.getReservedSlots().TryGetValue(slotType, out var found_reserved_slot))
|
||||
{
|
||||
found_reserved_slot = new ReservedSlotOnInven.ReservedSlot();
|
||||
currValue.getReservedSlots().Add(slotType, found_reserved_slot);
|
||||
}
|
||||
|
||||
found_reserved_slot.decReservedCount(1);
|
||||
|
||||
return currValue;
|
||||
};
|
||||
|
||||
found_reserved_inven_slots.AddOrUpdate(entityInvenType, add_recorder, update_recorder);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
public Result tryEquipToReserveSlotWithEntityBase(EntityBase invenOwner, EntityType entityInvenType, string slotType, EntityBase? entityBase)
|
||||
{
|
||||
var owner = getOwner();
|
||||
NullReferenceCheckHelper.throwIfNull(owner, () => $"owner is null !!!");
|
||||
ArgumentNullReferenceCheckHelper.throwIfNull(invenOwner, () => $"invenOwner is null !!! - {owner.toBasicString()}");
|
||||
|
||||
var result = new Result();
|
||||
var err_msg = string.Empty;
|
||||
|
||||
ConcurrentDictionary<EntityType, ReservedSlotOnInven>? found_reserved_inven_slots;
|
||||
|
||||
lock (m_reserved_inven_slots_of_owners)
|
||||
{
|
||||
if (false == m_reserved_inven_slots_of_owners.TryGetValue(invenOwner, out found_reserved_inven_slots))
|
||||
{
|
||||
found_reserved_inven_slots = new ConcurrentDictionary<EntityType, ReservedSlotOnInven>();
|
||||
m_reserved_inven_slots_of_owners[invenOwner] = found_reserved_inven_slots;
|
||||
}
|
||||
}
|
||||
|
||||
var slot_key = slotType;
|
||||
|
||||
var add_recorder = delegate (EntityType invenType)
|
||||
{
|
||||
var reserved_slot_on_inven = new ReservedSlotOnInven(entityInvenType);
|
||||
reserved_slot_on_inven.addOrInc(slot_key, 1);
|
||||
reserved_slot_on_inven.getReservedSlots()[slot_key].setEquipEntity(entityBase);
|
||||
|
||||
return reserved_slot_on_inven;
|
||||
};
|
||||
|
||||
var update_recorder = delegate (EntityType invenType, ReservedSlotOnInven currValue)
|
||||
{
|
||||
if (false == currValue.getReservedSlots().TryGetValue(slot_key, out var found_reserved_slot))
|
||||
{
|
||||
found_reserved_slot = new ReservedSlotOnInven.ReservedSlot();
|
||||
currValue.getReservedSlots()[slot_key] = found_reserved_slot;
|
||||
}
|
||||
|
||||
var equip_entity = found_reserved_slot.getEquipEntity();
|
||||
if (null != equip_entity)
|
||||
{
|
||||
err_msg = $"Already reserved equip item !!! : reservedEquipItem:{equip_entity.toBasicString()} - {entityBase?.toBasicString()}, {toBasicString()}, {owner.toBasicString()}";
|
||||
result.setFail(ServerErrorCode.SlotsAlreadyReservedEquip, err_msg);
|
||||
Log.getLogger().warn(result.toBasicString());
|
||||
|
||||
return currValue;
|
||||
}
|
||||
|
||||
found_reserved_slot.incReservedCount(1);
|
||||
found_reserved_slot.setEquipEntity(entityBase);
|
||||
|
||||
return currValue;
|
||||
};
|
||||
|
||||
found_reserved_inven_slots.AddOrUpdate(entityInvenType, add_recorder, update_recorder);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
public Result tryUnequipToReserveSlotWithEntityBase(EntityBase invenOwner, EntityType entityInvenType, string slotType, EntityBase? entityBase)
|
||||
{
|
||||
var owner = getOwner();
|
||||
NullReferenceCheckHelper.throwIfNull(owner, () => $"owner is null !!!");
|
||||
ArgumentNullReferenceCheckHelper.throwIfNull(invenOwner, () => $"invenOwner is null !!! - {owner.toBasicString()}");
|
||||
|
||||
var result = new Result();
|
||||
var err_msg = string.Empty;
|
||||
|
||||
var slot_key = slotType;
|
||||
|
||||
ConcurrentDictionary<EntityType, ReservedSlotOnInven>? found_reserved_inven_slots = null;
|
||||
|
||||
lock (m_reserved_inven_slots_of_owners)
|
||||
{
|
||||
if (false == m_reserved_inven_slots_of_owners.TryGetValue(invenOwner, out found_reserved_inven_slots))
|
||||
{
|
||||
found_reserved_inven_slots = new ConcurrentDictionary<EntityType, ReservedSlotOnInven>();
|
||||
m_reserved_inven_slots_of_owners[invenOwner] = found_reserved_inven_slots;
|
||||
}
|
||||
}
|
||||
|
||||
var add_recorder = delegate (EntityType invenType)
|
||||
{
|
||||
var reserved_slot_on_inven = new ReservedSlotOnInven(entityInvenType);
|
||||
reserved_slot_on_inven.addOrDec(slot_key, 1);
|
||||
reserved_slot_on_inven.getReservedSlots()[slot_key].setUnequipEntity(entityBase);
|
||||
|
||||
return reserved_slot_on_inven;
|
||||
};
|
||||
|
||||
var update_recorder = delegate (EntityType invenType, ReservedSlotOnInven currValue)
|
||||
{
|
||||
if (false == currValue.getReservedSlots().TryGetValue(slot_key, out var found_reserved_slot))
|
||||
{
|
||||
found_reserved_slot = new ReservedSlotOnInven.ReservedSlot();
|
||||
currValue.getReservedSlots()[slot_key] = found_reserved_slot;
|
||||
}
|
||||
|
||||
var unequip_entity = found_reserved_slot.getUnequipEntity();
|
||||
if (null != unequip_entity)
|
||||
{
|
||||
err_msg = $"Already reserved unequip item !!! : reservedUnequipItem:{unequip_entity.toBasicString()} - {entityBase?.toBasicString()}, {toBasicString()}, {owner.toBasicString()}";
|
||||
result.setFail(ServerErrorCode.SlotsAlreadyReservedUnequip, err_msg);
|
||||
Log.getLogger().warn(result.toBasicString());
|
||||
|
||||
return currValue;
|
||||
}
|
||||
|
||||
found_reserved_slot.decReservedCount(1);
|
||||
found_reserved_slot.setUnequipEntity(entityBase);
|
||||
|
||||
return currValue;
|
||||
};
|
||||
|
||||
found_reserved_inven_slots.AddOrUpdate(entityInvenType, add_recorder, update_recorder);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
public Result tryEquipToReserveSlot(EntityBase invenOwner, EntityType entityInvenType, string slotType)
|
||||
{
|
||||
return tryEquipToReserveSlotWithEntityBase(invenOwner, entityInvenType, slotType, null);
|
||||
}
|
||||
|
||||
public Result tryUnequipToReserveSlot(EntityBase invenOwner, EntityType entityInvenType, string slotType)
|
||||
{
|
||||
return tryUnequipToReserveSlotWithEntityBase(invenOwner, entityInvenType, slotType, null);
|
||||
}
|
||||
|
||||
public ReservedSlotOnInven.ReservedSlot? findReservedSlot(EntityBase invenOwner, EntityType entityInvenType, string slotType)
|
||||
{
|
||||
if(false == m_reserved_inven_slots_of_owners.TryGetValue(invenOwner, out var found_reserved_inven_slots))
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
if (true == found_reserved_inven_slots.TryGetValue(entityInvenType, out var found_reserved_slot_on_inven))
|
||||
{
|
||||
if(found_reserved_slot_on_inven.getReservedSlots().TryGetValue(slotType, out var found_reserved_slot))
|
||||
{
|
||||
return found_reserved_slot;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public (Result, EntityCommonResult?) getOrNewEntityCommonResult(EntityAttributeBase entityAttribute)
|
||||
{
|
||||
var owner = getOwner();
|
||||
NullReferenceCheckHelper.throwIfNull(owner, () => $"owner is null !!!");
|
||||
ArgumentNullReferenceCheckHelper.throwIfNull(entityAttribute, () => $"entityAttribute is null !!! - {owner.toBasicString()}");
|
||||
|
||||
var entity_of_owner_entity_type = entityAttribute.getEntityOfOwnerEntityType();
|
||||
NullReferenceCheckHelper.throwIfNull(entity_of_owner_entity_type, () => $"entity_of_owner_entity_type is null !!! - {owner.toBasicString()}");
|
||||
|
||||
var result = new Result();
|
||||
var err_msg = string.Empty;
|
||||
|
||||
var owner_guid = entity_of_owner_entity_type.onGetDbGuid();
|
||||
if(owner_guid.isNullOrWhiteSpace())
|
||||
{
|
||||
err_msg = $"Invlid OwnerGuid of onGetDbGuid() !!! : entityAttribute:{entityAttribute.toBasicString()} - {owner.toBasicString()}";
|
||||
result.setFail(ServerErrorCode.OwnerGuidInvalid, err_msg);
|
||||
Log.getLogger().fatal(result.toBasicString());
|
||||
|
||||
return (result, null);
|
||||
}
|
||||
|
||||
if (false == m_entity_common_results.TryGetValue(owner_guid, out var found_entity_common_result))
|
||||
{
|
||||
found_entity_common_result = new EntityCommonResult();
|
||||
found_entity_common_result.EntityType = entity_of_owner_entity_type.getEntityType();
|
||||
found_entity_common_result.EntityGuid = owner_guid;
|
||||
found_entity_common_result.Money = new MoneyResult();
|
||||
found_entity_common_result.Exp = new ExpResult();
|
||||
found_entity_common_result.Item = new ItemResult();
|
||||
|
||||
m_entity_common_results[owner_guid] = found_entity_common_result;
|
||||
}
|
||||
|
||||
return (result, found_entity_common_result);
|
||||
}
|
||||
|
||||
public CommonResult getCommonResult()
|
||||
{
|
||||
var common_result = new CommonResult();
|
||||
|
||||
foreach(var each in m_entity_common_results)
|
||||
{
|
||||
common_result.EntityCommonResults.Add(each.Value);
|
||||
}
|
||||
|
||||
return common_result;
|
||||
}
|
||||
|
||||
public void addRemoteChargeAIPoint(IRemoteTransaction remoteTransaction, double beamDelta)
|
||||
{
|
||||
var fn_buy_cart = new Func<Task>(() =>
|
||||
{
|
||||
return remoteTransaction.callRemoteChargeAIPoint(beamDelta);
|
||||
});
|
||||
|
||||
m_remote_transaction_funcs.Add(fn_buy_cart);
|
||||
}
|
||||
|
||||
public void addNotifyCaliumEvent(IRemoteTransaction remoteTransaction, string eventName, CurrencyType currencyType, double delta)
|
||||
{
|
||||
var fn = new Func<Task>(() => remoteTransaction.callNotifyCaliumEvent(eventName, currencyType, delta));
|
||||
m_remote_transaction_funcs.Add(fn);
|
||||
}
|
||||
|
||||
public async Task tryStartRemoteTransaction()
|
||||
{
|
||||
foreach(var remote_transaction_funcs in m_remote_transaction_funcs)
|
||||
{
|
||||
await remote_transaction_funcs();
|
||||
}
|
||||
}
|
||||
|
||||
public string toBasicString()
|
||||
{
|
||||
return $"TransactionRunnger - transId:{m_trans_id}, transactionIdType:{m_transaction_id_type}, transactionName:{m_transaction_name}";
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user