초기커밋
This commit is contained in:
352
ServerCommon/Entity/Inventory/InventoryBase.cs
Normal file
352
ServerCommon/Entity/Inventory/InventoryBase.cs
Normal 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;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user