초기커밋

This commit is contained in:
2025-05-01 07:20:41 +09:00
commit 98bb2e3c5c
2747 changed files with 646947 additions and 0 deletions

View File

@@ -0,0 +1,352 @@
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using ServerCore; using ServerBase;
using MetaAssets;
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 Google.Protobuf.WellKnownTypes;
namespace ServerCommon;
public abstract class InventoryBase<TSlotType> : SlotsWrapperBase<SlotsWithEntityBase<TSlotType>>, IWithInventoryAccessor
where TSlotType : notnull
{
public InventoryBase(EntityType entityType, EntityBase parent)
: base(entityType, parent)
{
}
public virtual Result onTryTakeInEntityBase(TSlotType entityGuid, EntityBase toTakeInEntityBase)
{
var err_msg = string.Empty;
var result = tryIsEquipableOrEquipWithEntityBase(entityGuid, toTakeInEntityBase);
if (result.isFail())
{
err_msg = $"Failed to onTryIsEquipableOrEquipWithEntityBase() !!! : {result.toBasicString()}";
Log.getLogger().error(err_msg);
return result;
}
return result;
}
public virtual Result onTryTakeOutEnityBase(ENTITY_GUID entityGuid, out EntityBase? takenOutEntityBase)
{
var err_msg = string.Empty;
takenOutEntityBase = null;
var result = tryUnequipableOrUnequipWithEntityBase(entityGuid, out var taken_out_entity_base);
if (result.isFail())
{
err_msg = $"Failed to onTryUnequipableOrUnequipWithEntityBase() !!! : {result.toBasicString()}";
Log.getLogger().error(err_msg);
return result;
}
takenOutEntityBase = taken_out_entity_base;
return result;
}
public (Result, List<ItemAttributeBase>, UInt16) findItemAttributeBaseAllByMetaId(META_ID itemMetaId, UInt32 toCheckItemCount = UInt32.MaxValue)
{
var parent = getDirectParent();
NullReferenceCheckHelper.throwIfNull(parent, () => $"paren is null !!!");
var inven_data = getData();
NullReferenceCheckHelper.throwIfNull(inven_data, () => $"inven_data is null !!! - {parent.toBasicString()}");
var err_msg = string.Empty;
var result = new Result();
var target_item_attributes = new List<ItemAttributeBase>();
if (0 >= itemMetaId)
{
err_msg = $"Invalid ItemMetaId !!! : itemMetaId:{itemMetaId} > 0 - {parent.toBasicString()}";
result.setFail(ServerErrorCode.MetaIdInvalid, err_msg);
Log.getLogger().error(result.toBasicString());
return (result, target_item_attributes, 0);
}
// 1. 아이템 메타 정보를 얻는다.
if (false == MetaData.Instance._ItemTable.TryGetValue((int)itemMetaId, out var itemMetaData))
{
err_msg = $"Not found ItemMeta !!! : itemMetaId:{itemMetaId} - {parent.toBasicString()}";
result.setFail(ServerErrorCode.ItemMetaDataNotFound, err_msg);
Log.getLogger().error(result.toBasicString());
return (result, target_item_attributes, 0);
}
// 2. 동일한 종류의 현재 Origin ItemAttributeBase 목록을 얻는다.
var found_origin_item_attributes = getHasSlotsWithEntityBases().Where(x =>
{
var item_attribute_base = x.Value.getOriginEntityAttribute<ItemAttributeBase>();
NullReferenceCheckHelper.throwIfNull(item_attribute_base, () => $"item_attribute_base is null !!! - {parent.toBasicString()}");
if ( item_attribute_base.ItemMetaId == itemMetaId
&& item_attribute_base.ItemStackCount > 0)
{
return true;
}
return false;
}).Select(x =>
{
var item_attribute_base = x.Value.getOriginEntityAttribute<ItemAttributeBase>();
NullReferenceCheckHelper.throwIfNull(item_attribute_base, () => $"item_attribute_base is null !!! - {parent.toBasicString()}");
return (item_attribute_base.ItemGuid, item_attribute_base);
}).ToDictionary();
// 3. 동일한 종류의 예약된 Cloned ItemAttributeBase 목록을 얻는다.
var found_cloned_item_attributes = new Dictionary<ITEM_GUID, ItemAttributeBase>();
var found_transaction_runner = parent.findTransactionRunner(TransactionIdType.PrivateContents);
if (null != found_transaction_runner)
{
var entity_attribute_transactors = found_transaction_runner.getEntityAttributeTransactorAll(parent.onGetAvailableItemAttributeType());
found_cloned_item_attributes = entity_attribute_transactors.Where(x =>
{
var item_attribute_base = x.Value.getClonedEntityAttribute() as ItemAttributeBase;
NullReferenceCheckHelper.throwIfNull(item_attribute_base, () => $"item_attribute_base is null !!! - {parent.toBasicString()}");
if ( item_attribute_base.ItemMetaId == itemMetaId
&& item_attribute_base.ItemStackCount >= 0 )
{
return true;
}
return false;
}).Select(x =>
{
var item_attribute = x.Value.getClonedEntityAttribute() as ItemAttributeBase;
NullReferenceCheckHelper.throwIfNull(item_attribute, () => $"item_attribute is null !!! - {parent.toBasicString()}");
return (item_attribute.ItemGuid, item_attribute);
}).ToDictionary();
}
// 4. Cloned 정보가 있거나, Origin 정보만 있는 경우 대상 아이템으로 추가한다 !!!
var all_keys = found_origin_item_attributes.Keys.Concat(found_cloned_item_attributes.Keys).Distinct();
foreach (var key in all_keys)
{
// 4.1. Cloned 정보가 있는데, 삭제 대상일 경우는 Origin & Cloned 모두 무시 한다.
if(true == found_cloned_item_attributes.TryGetValue(key, out var found_cloned_attribute))
{
var stack_count = found_cloned_attribute.ItemStackCount;
if (0 >= stack_count)
{
// 4.1.1. Cloned 정보가 삭제 대상일 경우 추가하지 않는다. (삭제될거니까...)
continue;
}
else
{
// 4.1.2. Cloned 정보의 아이템 개수가 존재 한다면 추가 한다.
target_item_attributes.Add(found_cloned_attribute);
}
}
// 4.2. Origin 정보만 있는 경우 추가 한다.
else if (found_origin_item_attributes.ContainsKey(key) && false == found_cloned_item_attributes.ContainsKey(key))
{
var only_origin_item_attribute = found_origin_item_attributes[key];
target_item_attributes.Add(only_origin_item_attribute);
}
}
// 5. 조건에 총족된 대상 아이템들의 StackCount 합산 개수를 얻는다.
var item_has_count = target_item_attributes.Sum(x => {
return x.ItemStackCount;
});
return (result, target_item_attributes, (UInt16)item_has_count);
}
public EntityBase? findEntityBase(TSlotType toFindEntityBaseKey)
{
var parent = getDirectParent();
NullReferenceCheckHelper.throwIfNull(parent, () => $"parent is null !!!");
var inven_data = getData();
NullReferenceCheckHelper.throwIfNull(inven_data, () => $"inven_data is null !!! - {parent.toBasicString()}");
var found_entity_base = inven_data.findEntityBaseInSlotType(toFindEntityBaseKey);
if (null == found_entity_base)
{
return null;
}
return found_entity_base;
}
public override void onWriteLog()
{
var parent = getDirectParent();
NullReferenceCheckHelper.throwIfNull(parent, () => $"parent is null !!!");
var has_items = getHasSlotsWithEntityBases();
NullReferenceCheckHelper.throwIfNull(has_items, () => $"has_items is null !!! - {parent.toBasicString()}");
foreach (var each in has_items)
{
var slot_type = each.Key;
META_ID item_meta_id = 0;
var item_guid = string.Empty;
var item_stack_count = 0;
var item_max_stack_count = 0;
var item_base = each.Value as ItemBase;
if (null != item_base)
{
var item_attibute_base = item_base.getEntityAttribute<ItemAttributeBase>();
NullReferenceCheckHelper.throwIfNull(item_attibute_base, () => $"item_attibute_base is null !!!");
item_meta_id = (META_ID)item_attibute_base.ItemMetaId;
item_guid = item_attibute_base.ItemGuid;
item_stack_count = item_attibute_base.ItemStackCount;
if (true == MetaData.Instance._ItemTable.TryGetValue((int)item_meta_id, out var found_item_meta))
{
item_max_stack_count = found_item_meta.StackMaxCount;
}
}
var err_msg = $"SlotType:{slot_type}, ItemMetaId:{item_meta_id}, StackCount:{item_stack_count}, MaxStackCount:{item_max_stack_count}, ItemGuid:{item_guid}";
Log.getLogger().info(err_msg);
}
}
public ConcurrentDictionary<TSlotType, EntityBase> getHasSlotsWithEntityBases()
{
var parent = getDirectParent();
NullReferenceCheckHelper.throwIfNull(parent, () => $"parent is null !!!");
var inven_data = getData();
NullReferenceCheckHelper.throwIfNull(inven_data, () => $"inven_data is null !!! - {parent.toBasicString()}");
var slots = inven_data.getSlots() as ConcurrentDictionary<TSlotType, EntityBase>;
NullReferenceCheckHelper.throwIfNull(slots, () => $"slots is null !!! - {parent.toBasicString()}");
return slots;
}
public List<EntityBase> getHasEntityBases()
{
var parent = getDirectParent();
NullReferenceCheckHelper.throwIfNull(parent, () => $"parent is null !!!");
var inven_data = getData();
NullReferenceCheckHelper.throwIfNull(inven_data, () => $"inven_data is null !!! - {parent.toBasicString()}");
var slots_with_entity_bases = getHasSlotsWithEntityBases();
NullReferenceCheckHelper.throwIfNull(slots_with_entity_bases, () => $"slots_with_entity_bases is null !!! - {parent.toBasicString()}");
return slots_with_entity_bases.Select(x => x.Value).ToList();
}
// IWithInventoryAccessor.clearItemAll()
public void clearItemAll()
{
var parent = getDirectParent();
NullReferenceCheckHelper.throwIfNull(parent, () => $"paren is null !!!");
var inven_data = getData();
NullReferenceCheckHelper.throwIfNull(inven_data, () => $"inven_data is null !!! - {parent.toBasicString()}");
var slots = inven_data.getSlots() as ConcurrentDictionary<TSlotType, EntityBase>;
NullReferenceCheckHelper.throwIfNull(slots, () => $"slots is null !!! - {parent.toBasicString()}");
slots.Clear();
}
// IWithInventoryAccessor.getHasItemBases()
public List<ItemBase> getHasItemBases()
{
var parent = getDirectParent();
NullReferenceCheckHelper.throwIfNull(parent, () => $"parent is null !!!");
return getHasSlotsWithEntityBases().Select(x =>
{
var item_base = x.Value as ItemBase;
NullReferenceCheckHelper.throwIfNull(item_base, () => $"item_base is null !!! - {parent.toBasicString()}");
return item_base;
}).ToList();
}
// IWithInventoryAccessor.tryEquipWithItemBase()
public ServerErrorCode tryEquipWithItemBase(string slotType, ItemBase itemBase)
{
var parent = getDirectParent();
NullReferenceCheckHelper.throwIfNull(parent, () => $"parent is null !!!");
var inven_data = getData();
NullReferenceCheckHelper.throwIfNull(inven_data, () => $"inven_data is null !!! - {parent.toBasicString()}");
var err_msg = string.Empty;
if(false == slotType.fillupEnumTypeAndValueStringToEnum<TSlotType>("None", out var target_slot_type) || null == target_slot_type)
{
err_msg = $"Failed to fillupEnumTypeAndValueStringToEnum<TSlotType>() !!!, SlotType of Target Inventory : targetSlotType:{slotType} - {parent.toBasicString()}";
Log.getLogger().error(err_msg);
return ServerErrorCode.StringConvertToEnumFailed;
}
return inven_data.onTryEquipWithEntityBase(target_slot_type, itemBase);
}
// IWithInventoryAccessor.tryUnequipWithItemBase()
public ServerErrorCode tryUnequipWithItemBase(string slotType, out ItemBase? itemBase)
{
itemBase = null;
var parent = getDirectParent();
NullReferenceCheckHelper.throwIfNull(parent, () => $"parent is null !!!");
var inven_data = getData();
NullReferenceCheckHelper.throwIfNull(inven_data, () => $"inven_data is null !!! - {parent.toBasicString()}");
var err_msg = string.Empty;
if (false == slotType.fillupEnumTypeAndValueStringToEnum<TSlotType>("None", out var target_slot_type) || null == target_slot_type)
{
err_msg = $"Failed to fillupEnumTypeAndValueStringToEnum<TSlotType>() !!!, SlotType of Target Inventory : targetSlotType:{slotType} - {parent.toBasicString()}";
Log.getLogger().error(err_msg);
return ServerErrorCode.StringConvertToEnumFailed;
}
var result_code = inven_data.onTryUnequipWithEntityBase(target_slot_type, out EntityBase? entity_base);
if (ServerErrorCode.Success == result_code)
{
itemBase = entity_base as ItemBase;
}
return result_code;
}
}

View File

@@ -0,0 +1,339 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Amazon.Runtime.Internal.Transform;
using ServerCore; using ServerBase;
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;
namespace ServerCommon
{
public abstract class RuleBase
{
public HashSet<MetaAssets.EItemLargeType> EquipableItemLargeTypes { get; set; } = new();
public HashSet<MetaAssets.EItemSmallType> EquipableItemSmallTypes { get; set; } = new();
public EntityDynamoDbSortKeyType EntitySKType { get; set; } = EntityDynamoDbSortKeyType.None;
public RuleBase() { }
}
public class BagRule : RuleBase
{
public InvenBagType InvenBagType { get; set; } = InvenBagType.None;
public BagTabType UsableBagTabType { get; set; } = BagTabType.None;
public BagRule()
{ }
}
public abstract class EquipRuleBase : RuleBase
{
public InvenEquipType InvenEquipType { get; set; } = InvenEquipType.None;
public abstract Result onConfigure(InvenEquipType equipType);
}
public class ToolEquipRule : EquipRuleBase
{
public List<ToolSlotType> UsableToolSlotTypes { get; set; } = new();
public ToolEquipRule()
{ }
public override Result onConfigure(InvenEquipType equipType)
{
var result = new Result();
var err_msg = string.Empty;
foreach (var item_large_type in equipType.toEquipableItemLargeTypes())
{
if (false == EquipableItemLargeTypes.Add(item_large_type))
{
err_msg = $"Failed to Add() EquipableItemLargeTypes !!!, duplicated EItemLargeType : EItemLargeType:{item_large_type} - InvenEquipType:{equipType}";
result.setFail(ServerErrorCode.ToolEquipRuleItemLargeTypeDuplicated, err_msg);
Log.getLogger().error(result.toBasicString());
return result;
}
UsableToolSlotTypes = equipType.toEquipableToolSlotTypes();
}
return result;
}
}
public class ClothEquipRule : EquipRuleBase
{
public Dictionary<ClothSlotType, List<MetaAssets.EItemSmallType>> m_slots_by_cloth_slot_type = new();
public Dictionary<MetaAssets.EItemSmallType, List<ClothSlotType>> m_slots_by_item_type = new();
public ClothEquipRule()
{ }
public override Result onConfigure(InvenEquipType equipType)
{
var result = new Result();
var err_msg = string.Empty;
foreach (var item_large_type in equipType.toEquipableItemLargeTypes())
{
if (false == EquipableItemLargeTypes.Add(item_large_type))
{
err_msg = $"Failed to Add() EquipableItemLargeTypes !!!, duplicated EItemLargeType : EItemLargeType:{item_large_type} - InvenEquipType:{equipType}";
result.setFail(ServerErrorCode.ClothEquipRuleItemLargeTypeDuplicated, err_msg);
Log.getLogger().error(result.toBasicString());
return result;
}
var cloth_slot_types = EnumHelper.getValuesWithoutScopeAll<ClothSlotType>();
foreach(var slot_type in cloth_slot_types)
{
if (false == m_slots_by_cloth_slot_type.TryGetValue(slot_type, out var found_item_small_types))
{
found_item_small_types = new List<MetaAssets.EItemSmallType>();
m_slots_by_cloth_slot_type.Add(slot_type, found_item_small_types);
}
found_item_small_types = equipType.toEquipableItemSmallTypesWithClothSlotType(slot_type);
foreach(var item_small_type in found_item_small_types)
{
if (false == m_slots_by_item_type.TryGetValue(item_small_type, out var found_slot_types))
{
found_slot_types = new List<ClothSlotType>();
m_slots_by_item_type.Add(item_small_type, found_slot_types);
}
if(false == found_slot_types.Exists(x => x == slot_type))
{
found_slot_types.Add(slot_type);
}
EquipableItemSmallTypes.Add(item_small_type);
}
}
}
return result;
}
}
public class TattooEquipRule : EquipRuleBase
{
public List<TattooSlotType> UsableTattooSlotPosOfDefault { get; set; } = new();
public List<TattooSlotType> UsableTattooSlotPosOfUgcNpc { get; set; } = new();
public TattooEquipRule()
{ }
public override Result onConfigure(InvenEquipType equipType)
{
var result = new Result();
var err_msg = string.Empty;
foreach (var item_large_type in equipType.toEquipableItemLargeTypes())
{
if (false == EquipableItemLargeTypes.Add(item_large_type))
{
err_msg = $"Failed to Add() EquipableItemLargeTypes !!!, duplicated EItemLargeType : EItemLargeType:{item_large_type} - InvenEquipType:{equipType}";
result.setFail(ServerErrorCode.TattooEquipRuleItemLargeTypeDuplicated, err_msg);
Log.getLogger().error(result.toBasicString());
return result;
}
UsableTattooSlotPosOfDefault = equipType.toEquipableTattooSlotTypes();
UsableTattooSlotPosOfUgcNpc = equipType.toEquipableTattooSlotTypes(EntityType.UgcNpc);
}
return result;
}
public List<TattooSlotType> getUsableTattooSlotPos(EntityType entityType)
{
if( EntityType.UgcNpc == entityType
|| EntityType.Beacon == entityType )
{
return UsableTattooSlotPosOfUgcNpc;
}
return UsableTattooSlotPosOfDefault;
}
}
public class InventoryRule : IRule
{
private readonly Dictionary<InvenBagType, BagRule> m_bag_rules = new();
private readonly Dictionary<MetaAssets.EItemLargeType, List<BagRule>> m_bag_rules_by_item_type = new();
private readonly Dictionary<InvenEquipType, EquipRuleBase> m_equip_rule_bases = new();
private readonly Dictionary<MetaAssets.EItemLargeType, List<EquipRuleBase>> m_equip_rule_bases_by_item_type = new();
public InventoryRule()
{
}
public async Task<Result> onInit()
{
var result = await configure();
if(result.isFail())
{
return result;
}
return result;
}
public async Task<Result> configure()
{
var result = new Result();
var err_msg = string.Empty;
var inven_bag_type_enums = EnumHelper.getValuesWithoutScopeAll<InvenBagType>();
foreach(var value in inven_bag_type_enums)
{
var bag_rule = new BagRule();
bag_rule.InvenBagType = value;
foreach(var item_type in value.toEquipableItemLargeTypes())
{
if(false == bag_rule.EquipableItemLargeTypes.Add(item_type))
{
err_msg = $"Failed to Add() EquipableItemLargeTypes !!!, duplicated EItemLargeType : EItemLargeType:{item_type} - InvenBagType:{value}";
result.setFail(ServerErrorCode.BagRuleItemLargeTypeDuplicated, err_msg);
Log.getLogger().error(result.toBasicString());
return result;
}
}
bag_rule.UsableBagTabType = value.toUsableBagTabType();
m_bag_rules.Add(value, bag_rule);
}
var item_type_to_bag_types = EnumHelper.getValuesWithoutScopeAll<MetaAssets.EItemLargeType>();
foreach (var item_type in item_type_to_bag_types)
{
foreach(var eache in m_bag_rules)
{
if(false == eache.Value.EquipableItemLargeTypes.Contains(item_type))
{
continue;
}
if(false == m_bag_rules_by_item_type.TryGetValue(item_type, out var found_bag_rules))
{
found_bag_rules = new List<BagRule>();
m_bag_rules_by_item_type.Add(item_type, found_bag_rules);
}
found_bag_rules.Add(eache.Value);
}
}
var inven_equip_type_enums = EnumHelper.getValuesWithoutScopeAll<InvenEquipType>();
foreach (var value in inven_equip_type_enums)
{
var equip_rule_base = newEquipRuleBaseByInvenEquipType(value);
if (equip_rule_base == null)
continue;
equip_rule_base.InvenEquipType = value;
result = equip_rule_base.onConfigure(value);
if(result.isFail())
{
return result;
}
equip_rule_base.EntitySKType = value.toEntitySKType();
m_equip_rule_bases.Add(value, equip_rule_base);
}
var item_type_to_equip_types = EnumHelper.getValuesWithoutScopeAll<MetaAssets.EItemLargeType>();
foreach (var item_type in item_type_to_equip_types)
{
foreach (var eache in m_equip_rule_bases)
{
if (false == eache.Value.EquipableItemLargeTypes.Contains(item_type))
{
continue;
}
if (false == m_equip_rule_bases_by_item_type.TryGetValue(item_type, out var found_equip_rule_bases))
{
found_equip_rule_bases = new List<EquipRuleBase>();
m_equip_rule_bases_by_item_type.Add(item_type, found_equip_rule_bases);
}
found_equip_rule_bases.Add(eache.Value);
}
}
return await Task.FromResult(result);
}
public EquipRuleBase? newEquipRuleBaseByInvenEquipType(InvenEquipType equipType)
{
switch(equipType)
{
case InvenEquipType.Tool:
return new ToolEquipRule();
case InvenEquipType.Cloth:
return new ClothEquipRule();
case InvenEquipType.Tattoo:
return new TattooEquipRule();
default:
var err_msg = $"Failed to newEquipRuleBaseByInvenEquipType() !!!, Invalid InvenEquipType : InvenEquipType:{equipType}";
Log.getLogger().error(err_msg);
return null;
}
}
public BagRule? getBagRuleByInvenBagType(InvenBagType bagType)
{
m_bag_rules.TryGetValue(bagType, out var found_bag_rules);
return found_bag_rules;
}
public EquipRuleBase? getEquipRuleBaseByInvenEquipType(InvenEquipType equipType)
{
m_equip_rule_bases.TryGetValue(equipType, out var found_equip_rule_bases);
return found_equip_rule_bases;
}
public List<BagRule>? getBagRulesByItemLargeType(MetaAssets.EItemLargeType itemType)
{
m_bag_rules_by_item_type.TryGetValue(itemType, out var found_bag_rules);
return found_bag_rules;
}
public List<EquipRuleBase>? getEquipRuleBasesByItemLargeType(MetaAssets.EItemLargeType itemType)
{
m_equip_rule_bases_by_item_type.TryGetValue(itemType, out var found_equip_rule_bases);
return found_equip_rule_bases;
}
public Dictionary<InvenBagType, BagRule> getBagRules() => m_bag_rules;
public Dictionary<InvenEquipType, EquipRuleBase> getEquipRuleBases() => m_equip_rule_bases;
}
}

View File

@@ -0,0 +1,207 @@
using System;
using System.Collections;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Axion.Collections.Concurrent;
using ServerCore; using ServerBase;
using SESSION_ID = System.Int32;
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;
namespace ServerCommon
{
public abstract class SlotsBase
{
private AtomicInt32 m_slot_max_count = new(0);
public virtual bool onInitSlots(int slotMaxCount)
{
m_slot_max_count.set(slotMaxCount);
return true;
}
public abstract UInt32 onGetCurrSlotCount();
public UInt32 getSlotMaxCount()
{
return (UInt32)m_slot_max_count.Value;
}
public virtual string toBasicString()
{
return $"{this.getTypeName()}, UsingSlotCount:{onGetCurrSlotCount()}, SlotMaxCount:{m_slot_max_count.Value}";
}
}
public class Slots<TSlotType> : SlotsBase, ISlotsWithType<TSlotType>
where TSlotType : Enum
{
private ConcurrentHashSet<TSlotType> m_slots = new();
public Slots()
{ }
public override bool onInitSlots(int slotMaxCount)
{
m_slots = new ConcurrentHashSet<TSlotType>(MultiThreadHelper.getThreadOptimalCount(), (int)slotMaxCount);
return true;
}
public virtual ServerErrorCode onIsEquipable(TSlotType targetSlot)
{
return (false == m_slots.Contains(targetSlot)) ? ServerErrorCode.Success : ServerErrorCode.SlotsAlreadyEquiped;
}
public virtual ServerErrorCode onTryEquip(TSlotType targetSlot)
{
return (true == m_slots.TryAdd(targetSlot, out _)) ? ServerErrorCode.Success : ServerErrorCode.SlotsAlreadyEquiped;
}
public virtual ServerErrorCode onIsUnequipable(TSlotType targetSlot)
{
return (true == m_slots.Contains(targetSlot)) ? ServerErrorCode.Success : ServerErrorCode.SlotsAlreadyUnequiped;
}
public virtual ServerErrorCode onTryUnequip(TSlotType targetSlot)
{
return (true == m_slots.TryRemove(targetSlot, out _)) ? ServerErrorCode.Success : ServerErrorCode.SlotsAlreadyUnequiped;
}
public virtual ServerErrorCode onTryEquipWithEntityBase(TSlotType targetSlot, EntityBase entityBase) => ServerErrorCode.FunctionNotImplemented;
public virtual ServerErrorCode onTryUnequipWithEntityBase(TSlotType targetSlot, out EntityBase? entityBase)
{
entityBase = null;
return ServerErrorCode.FunctionNotImplemented;
}
public virtual EntityBase? onFindEntityBase(TSlotType targetSlot)
{
return null;
}
public bool isExistSlotType(TSlotType slotType)
{
return true == m_slots.Contains(slotType);
}
public override UInt32 onGetCurrSlotCount()
{
return (UInt32)m_slots.Count;
}
public List<EntityBase> getEntityBases()
{
return new List<EntityBase>();
}
public ICollection getSlots() => m_slots;
}
public class SlotsWithEntityBase<TSlotType> : SlotsBase, ISlotsWithType<TSlotType>
where TSlotType : notnull
{
private ConcurrentDictionary<TSlotType, EntityBase> m_slots = new();
public SlotsWithEntityBase()
{
}
public override bool onInitSlots(int slotMaxCount)
{
m_slots = new ConcurrentDictionary<TSlotType, EntityBase>(MultiThreadHelper.getThreadOptimalCount(), (int)slotMaxCount);
return true;
}
public virtual ServerErrorCode onIsEquipable(TSlotType targetSlot)
{
return (false == m_slots.ContainsKey(targetSlot)) ? ServerErrorCode.Success : ServerErrorCode.SlotsAlreadyEquiped;
}
public virtual ServerErrorCode onTryEquipWithEntityBase(TSlotType targetSlot, EntityBase entityBase)
{
return (true == m_slots.TryAdd(targetSlot, entityBase)) ? ServerErrorCode.Success : ServerErrorCode.SlotsAlreadyEquiped;
}
public virtual ServerErrorCode onIsUnequipable(TSlotType targetSlot)
{
return (true == m_slots.ContainsKey(targetSlot)) ? ServerErrorCode.Success : ServerErrorCode.SlotsAlreadyUnequiped;
}
public virtual ServerErrorCode onTryUnequipWithEntityBase(TSlotType targetSlot, out EntityBase? removedEntityBase)
{
removedEntityBase = null;
if (false == m_slots.TryRemove(targetSlot, out var removed_entity_base))
{
return ServerErrorCode.SlotsAlreadyUnequiped;
}
removedEntityBase = removed_entity_base;
return ServerErrorCode.Success;
}
public virtual EntityBase? onFindEntityBase(TSlotType targetSlot)
{
return findEntityBaseInSlotType(targetSlot);
}
public EntityBase? findEntityBaseInSlotType(TSlotType targetSlot)
{
if(false == m_slots.TryGetValue(targetSlot, out var found_entity_base))
{
return null;
}
return found_entity_base;
}
public EntityBase? findEntityBaseBy(Func<EntityBase, bool> isFound)
{
foreach(var each in m_slots)
{
var is_success = isFound(each.Value);
if(true == is_success)
{
return each.Value;
}
}
return null;
}
public bool isExistSlotType(TSlotType slotType)
{
return true == m_slots.ContainsKey(slotType);
}
public override UInt32 onGetCurrSlotCount()
{
return (UInt32)m_slots.Count;
}
public List<EntityBase> getEntityBases()
{
return m_slots.Values.ToList();
}
public ICollection getSlots() => m_slots;
public virtual ServerErrorCode onTryEquip(TSlotType targetSlot) => ServerErrorCode.FunctionNotImplemented;
public virtual ServerErrorCode onTryUnequip(TSlotType targetSlot) => ServerErrorCode.FunctionNotImplemented;
}
}

View File

@@ -0,0 +1,266 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Pipelines.Sockets.Unofficial.Buffers;
using ServerCore; using ServerBase;
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;
namespace ServerCommon
{
public abstract partial class SlotsWrapperBase<TSlots> : EntityBase
where TSlots : ISlots, new()
{
private readonly TSlots m_slots;
public SlotsWrapperBase(EntityType entityType, EntityBase parent)
: base(entityType, parent)
{
m_slots = new TSlots();
}
public virtual bool onInitSlots(int slotMaxCount)
{
return m_slots.onInitSlots(slotMaxCount);
}
public Result tryIsEquipableOrEquip<TSlotType>(TSlotType targetSlotType)
where TSlotType : Enum
{
var result = new Result();
var err_msg = string.Empty;
var direct_parent = getDirectParent();
ArgumentNullException.ThrowIfNull(direct_parent, $"direct_parent is null !!!");
var slots = getData() as ISlotsWithType<TSlotType>;
ArgumentNullException.ThrowIfNull(slots, $"slots is null !!! - {direct_parent.toBasicString()}");
var parent = getRootParent();
if (null != parent)
{
// Transaction 활성화 상태일 경우
var transaction_runner = parent.findTransactionRunner(TransactionIdType.PrivateContents);
if (null != transaction_runner)
{
var slot_type = targetSlotType.ToString();
var to_check_slot_type = slot_type;
if (true == EnumHelper.isEnumType(to_check_slot_type))
{
slot_type = to_check_slot_type.convertEnumToEnumTypeAndValueString();
}
// 장착 슬롯에 슬롯과 EntityBase를 장착 해제 예약 한다.
result = transaction_runner.tryEquipToReserveSlot(direct_parent, getEntityType(), slot_type);
if (result.isFail())
{
return result;
}
err_msg = $"Succss tryEquipToReserveSlot() : targetSlotType:{slot_type} - {toBasicString()}, {parent.toBasicString()}";
Log.getLogger().info(err_msg);
return result;
}
}
var error_code = slots.onTryEquip(targetSlotType);
if (error_code.isFail())
{
err_msg = $"Failed to onTryEquip() !!! : targetSlotType:{targetSlotType} - {toBasicString()}, {parent?.toBasicString()}";
result.setFail(error_code, err_msg);
return result;
}
return result;
}
public Result tryIsEquipableOrEquipWithEntityBase<TSlotType>(TSlotType targetSlotType, EntityBase entityBase)
where TSlotType : notnull
{
var result = new Result();
var err_msg = string.Empty;
var direct_parent = getDirectParent();
ArgumentNullException.ThrowIfNull(direct_parent, $"direct_parent is null !!!");
var slots = getData() as ISlotsWithType<TSlotType>;
ArgumentNullException.ThrowIfNull(slots, $"slots is null !!! - {direct_parent.toBasicString()}");
var parent = getRootParent();
if (null != parent)
{
// Transaction 활성화 상태일 경우
var transaction_runner = parent.findTransactionRunner(TransactionIdType.PrivateContents);
if (null != transaction_runner)
{
var slot_type = targetSlotType.ToString();
NullReferenceCheckHelper.throwIfNull(slot_type, () => $"slot_type is null !!!");
var to_check_slot_type = slot_type;
NullReferenceCheckHelper.throwIfNull(to_check_slot_type, () => $"to_check_slot_type is null !!!");
if (true == EnumHelper.isEnumType(to_check_slot_type))
{
slot_type = to_check_slot_type.convertEnumToEnumTypeAndValueString();
}
// 장착 슬롯에 슬롯과 EntityBase를 장착 예약 한다.
result = transaction_runner.tryEquipToReserveSlotWithEntityBase(direct_parent, getEntityType(), slot_type, entityBase);
if (result.isFail())
{
return result;
}
err_msg = $"Succss tryEquipToReserveSlotWithEntityBase() : targetSlotType:{slot_type} - {toBasicString()}, {parent.toBasicString()}";
Log.getLogger().info(err_msg);
return result;
}
}
var error_code = slots.onTryEquipWithEntityBase(targetSlotType, entityBase);
if (error_code.isFail())
{
err_msg = $"Failed to onTryEquipWithEntityBase() !!! : {error_code.toBasicString()}, targetSlotType:{targetSlotType}, {entityBase.toBasicString()} - {toBasicString()}, {parent?.toBasicString()}";
result.setFail(error_code, err_msg);
return result;
}
return result;
}
public Result tryUnequipableOrUnequip<TSlotType>(TSlotType targetSlotType)
where TSlotType : Enum
{
var result = new Result();
var err_msg = string.Empty;
var direct_parent = getDirectParent();
ArgumentNullException.ThrowIfNull(direct_parent, $"direct_parent is null !!!");
var slots = getData() as ISlotsWithType<TSlotType>;
ArgumentNullException.ThrowIfNull(slots, $"slots is null !!! - {direct_parent.toBasicString()}");
var parent = getRootParent();
if (null != parent)
{
// Transaction 활성화 상태일 경우
var transaction_runner = parent.findTransactionRunner(TransactionIdType.PrivateContents);
if (null != transaction_runner)
{
var slot_type = targetSlotType.ToString();
var to_check_slot_type = slot_type;
if (true == EnumHelper.isEnumType(to_check_slot_type))
{
slot_type = to_check_slot_type.convertEnumToEnumTypeAndValueString();
}
// 장착 슬롯에 슬롯과 EntityBase를 장착 해제 예약 한다.
result = transaction_runner.tryUnequipToReserveSlot(direct_parent, getEntityType(), slot_type);
if (result.isFail())
{
return result;
}
err_msg = $"Success tryUnequipToReserveSlot() : targetSlotType:{slot_type} - {toBasicString()}, {parent.toBasicString()}";
Log.getLogger().info(err_msg);
return result;
}
}
var error_code = slots.onTryUnequip(targetSlotType);
if (error_code.isFail())
{
err_msg = $"Failed to onTryUnequip() !!! : targetSlotType:{targetSlotType} - {toBasicString()}, {parent?.toBasicString()}";
result.setFail(error_code, err_msg);
return result;
}
return result;
}
public Result tryUnequipableOrUnequipWithEntityBase<TSlotType>(TSlotType targetSlotType, out EntityBase? unequipedEntityBase)
where TSlotType : notnull
{
unequipedEntityBase = null;
var result = new Result();
var err_msg = string.Empty;
var direct_parent = getDirectParent();
ArgumentNullException.ThrowIfNull(direct_parent, $"direct_parent is null !!!");
var slots = getData() as ISlotsWithType<TSlotType>;
ArgumentNullException.ThrowIfNull(slots, $"slots is null !!! - {direct_parent.toBasicString()}");
var parent = getRootParent();
if (null != parent)
{
// Transaction 활성화 상태일 경우
var transaction_runner = parent.findTransactionRunner(TransactionIdType.PrivateContents);
if (null != transaction_runner)
{
var slot_type = targetSlotType.ToString();
NullReferenceCheckHelper.throwIfNull(slot_type, () => $"slot_type is null !!!");
var to_check_slot_type = slot_type;
NullReferenceCheckHelper.throwIfNull(to_check_slot_type, () => $"to_check_slot_type is null !!!");
if (true == EnumHelper.isEnumType(to_check_slot_type))
{
slot_type = to_check_slot_type.convertEnumToEnumTypeAndValueString();
}
// 장착 슬롯에 슬롯과 EntityBase를 장착 해제 예약 한다.
result = transaction_runner.tryUnequipToReserveSlotWithEntityBase(direct_parent, getEntityType(), slot_type, slots.onFindEntityBase(targetSlotType));
if (result.isFail())
{
return result;
}
err_msg = $"Success tryUnequipToReserveSlotWithEntityBase() : targetSlotType:{slot_type} - {toBasicString()}, {parent.toBasicString()}";
Log.getLogger().info(err_msg);
return result;
}
}
var error_code = slots.onTryUnequipWithEntityBase(targetSlotType, out var unequiped_entity_base);
if (error_code.isFail())
{
err_msg = $"Failed to onTryUnequipWithEntityBase() !!! : {error_code.toBasicString()}, targetSlotType:{targetSlotType} - {toBasicString()}, {parent?.toBasicString()}";
result.setFail(error_code, err_msg);
return result;
}
unequipedEntityBase = unequiped_entity_base;
return result;
}
public virtual void onWriteLog()
{
return;
}
public TSlots getData() => m_slots;
public override string toBasicString()
{
return $"{this.getTypeName()}, {m_slots.toBasicString()}";
}
}
}