Files
caliverse_server/GameServer/Entity/Inventory/Base/Action/InventoryActionBase.cs
2025-05-01 07:23:28 +09:00

1849 lines
88 KiB
C#

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Collections.Concurrent;
using Axion.Collections.Concurrent;
using Amazon.S3.Model;
using NeoSmart.AsyncLock;
using MySqlConnector;
using MetaAssets;
using ServerCore; using ServerBase;
using ServerCommon;
using SESSION_ID = System.Int32;
using WORLD_META_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 GameServer
{
public abstract partial class InventoryActionBase : EntityActionBase
{
private readonly BagInven m_bag_inven;
private readonly ConcurrentDictionary<InvenEquipType, EntityBase> m_equip_invens = new();
private AsyncLock m_async_lock = new();
public static Int64 ENTITY_UPDATE_INTERVAL_MSEC = ConstValue.default_1_min_to_sec * ConstValue.default_1000_millisec;
private SimpleTimer m_entity_update_timer = new(ENTITY_UPDATE_INTERVAL_MSEC);
public InventoryActionBase(EntityBase owner)
: base(owner)
{
m_bag_inven = new BagInven(owner);
m_entity_update_timer.activate();
}
public void clear()
{
var owner = getOwner();
NullReferenceCheckHelper.throwIfNull(owner, () => $"owner is null !!!");
m_bag_inven.clearItemAll();
m_bag_inven.resetItemCountInTabs();
var target_inven_equip_types = EnumHelper.getValuesWithoutScopeAll<InvenEquipType>();
foreach (var inven_equip_type in target_inven_equip_types)
{
if (false == getEquipInvens().TryGetValue(inven_equip_type, out var found_equip_inven))
{
continue;
}
var inven_accessor = found_equip_inven as IWithInventoryAccessor;
if (inven_accessor == null)
{
var err_msg = $"Failed to cast IWithInventoryAccessor !!! : invenEquipType:{inven_equip_type} - {owner.toBasicString()}";
Log.getLogger().error(err_msg);
continue;
}
inven_accessor.clearItemAll();
}
}
public async Task clearItemAllFromMemory()
{
var owner = getOwner();
NullReferenceCheckHelper.throwIfNull(owner, () => $"owner is null !!!");
var err_msg = string.Empty;
(var result, var _) = await tryDeleteItemAll();
if (result.isFail())
{
err_msg = $"Failed to tryDeleteItemAll() !!! : {result.toBasicString()} - {owner.toBasicString()}";
Log.getLogger().error(err_msg);
}
m_bag_inven.resetItemCountInTabs();
}
public Item? tryGetItemByItemGuid(ITEM_GUID itemGuid)
{
var found_item = m_bag_inven.findEntityBase(itemGuid);
return found_item as Item;
}
public List<Item> tryGetItemAllByItemMetaId(META_ID itemMetaId)
{
return m_bag_inven.getItemAllByMetaId(itemMetaId);
}
public Int32 getItemCountAllByMetaId(META_ID itemMetaId)
{
return m_bag_inven.getItemCountAllByMetaId(itemMetaId);
}
public Int32 getItemStackCountAllByMetaId(META_ID itemMetaId)
{
return m_bag_inven.getItemStackCountAllByMetaId(itemMetaId);
}
public Item? tryGetEquipItemByItemGuid(ITEM_GUID itemGuid)
{
var owner = getOwner();
NullReferenceCheckHelper.throwIfNull(owner, () => $"owner is null !!!");
var equip_items = new List<Item>();
var err_msg = string.Empty;
var target_inven_equip_types = EnumHelper.getValuesWithoutScopeAll<InvenEquipType>();
foreach (var inven_equip_type in target_inven_equip_types)
{
if (false == getEquipInvens().TryGetValue(inven_equip_type, out var found_equip_inven))
{
continue;
}
var inven_accessor = found_equip_inven as IWithInventoryAccessor;
if (inven_accessor == null)
{
err_msg = $"Failed to cast IWithInventoryAccessor !!! : invenEquipType:{inven_equip_type} - {owner.toBasicString()}";
Log.getLogger().error(err_msg);
continue;
}
foreach (var item_base in inven_accessor.getHasItemBases())
{
var curr_item = item_base as Item;
NullReferenceCheckHelper.throwIfNull(curr_item, () => $"curr_item is null !!! - {owner.toBasicString()}");
var item_attribute_base = curr_item.getEntityAttributeWithReadOnly<ItemAttributeBase>();
NullReferenceCheckHelper.throwIfNull(item_attribute_base, () => $"item_attribute_base is null !!! - {owner.toBasicString()}");
if( item_attribute_base.ItemGuid == itemGuid
&& item_attribute_base.ItemStackCount > 0 )
{
return curr_item;
}
}
}
return null;
}
public async Task<(Result, Item?)> tryGetEquipItemByInvenEquipType<TSlotType>( InvenEquipType invenEquipType, TSlotType targetSlotType
, bool isFailOnItemNotFound = true )
where TSlotType : Enum
{
var owner = getOwner();
NullReferenceCheckHelper.throwIfNull(owner, () => $"owner is null !!!");
var result = new Result();
var err_msg = string.Empty;
if (false == getEquipInvens().TryGetValue(invenEquipType, out var found_equip_inven))
{
err_msg = $"Not found EquipInven !!! : invenEquipType:{invenEquipType} - {owner.toBasicString()}";
result.setFail(ServerErrorCode.EquipInvenNotFound, err_msg);
Log.getLogger().error(result.toBasicString());
return (result, null);
}
var equip_inven = found_equip_inven as InventoryBase<TSlotType>;
NullReferenceCheckHelper.throwIfNull(equip_inven, () => $"equip_inven is null !!! - {owner.toBasicString()}");
var has_slots_with_entity_bases = equip_inven.getHasSlotsWithEntityBases();
NullReferenceCheckHelper.throwIfNull(has_slots_with_entity_bases, () => $"has_slots_with_entity_bases is null !!! - {owner.toBasicString()}");
if(false == has_slots_with_entity_bases.TryGetValue(targetSlotType, out var found_entity_base))
{
if(true == isFailOnItemNotFound)
{
err_msg = $"Not found SlotType !!! : slotType:{targetSlotType} - {owner.toBasicString()}";
result.setFail(ServerErrorCode.SlotTypeNotFound, err_msg);
Log.getLogger().error(result.toBasicString());
}
return (result, null);
}
var found_item = found_entity_base as Item;
NullReferenceCheckHelper.throwIfNull(found_item, () => $"found_item is null !!! - {owner.toBasicString()}");
return await Task.FromResult((result, found_item));
}
public async Task<(Result, Item?)> tryUseItemByGuid(ITEM_GUID itemGuid, UInt16 toDeleteCount)
{
var owner = getOwner();
NullReferenceCheckHelper.throwIfNull(owner, () => $"owner is null !!!");
var result = new Result();
(result, var found_delete_item) = await tryDeleteItemByGuid(itemGuid, toDeleteCount);
if (result.isFail())
{
return (result, found_delete_item);
}
NullReferenceCheckHelper.throwIfNull(found_delete_item, () => $"found delete item is null !!! - {owner.toBasicString()}");
var item_use_action = found_delete_item.getEntityAction<ItemUseAction>();
NullReferenceCheckHelper.throwIfNull(item_use_action, () => $"item_use_action is null !!! - {owner.toBasicString()}");
result = await item_use_action.onUseItem();
if (result.isFail())
{
return (result, found_delete_item);
}
return (result, found_delete_item);
}
//=========================================================================================
// 아이템을 가방에만 지급 하기
// 아이템 StackMaxCount가 1보다 크면 meta로 새로 만들면서 스텍을 쌓아준다.
//=========================================================================================
public async Task<(Result, List<Item>?)> tryTakableToBagWithNewItem(ItemDoc doc)
{
var owner = getOwner();
NullReferenceCheckHelper.throwIfNull(owner, () => $"owner is null !!!");
ArgumentNullReferenceCheckHelper.throwIfNull(doc, () => $"doc is null !!! - {owner.toBasicString()}");
var result = new Result();
var err_msg = string.Empty;
var doc_item_attrib = doc.getAttrib<ItemAttrib>();
NullReferenceCheckHelper.throwIfNull(doc_item_attrib, () => $"doc_item_attrib is null !!! - {owner.toBasicString()}");
if (MetaData.Instance._ItemTable.TryGetValue((int)doc_item_attrib.ItemMetaId, out var item_meta_data) == false)
{
err_msg = $"Not found meta of Item !!! : ItemMetaId:{doc_item_attrib.ItemMetaId} - {owner.toBasicString()}";
result.setFail(ServerErrorCode.ItemMetaDataNotFound, err_msg);
Log.getLogger().error(err_msg);
return (result, null);
}
if(item_meta_data.StackMaxCount > 1)
{
return await tryTakalbleToBag(doc_item_attrib.ItemMetaId, doc_item_attrib.ItemStackCount);
}
(result, var item) = await tryTakableToBag(doc);
if (result.isFail() || item == null)
{
return (result, null);
}
return (result, new List<Item>() { item });
}
//=========================================================================================
// 아이템을 가방에만 지급 하기 (from Memory)
//=========================================================================================
public async Task<(Result, Item?)> tryTakableToBag(ItemDoc doc)
{
var owner = getOwner();
NullReferenceCheckHelper.throwIfNull(owner, () => $"owner is null !!!");
ArgumentNullReferenceCheckHelper.throwIfNull(doc, () => $"doc is null !!! - {owner.toBasicString()}");
var result = new Result();
var err_msg = string.Empty;
var doc_item_attrib = doc.getAttrib<ItemAttrib>();
NullReferenceCheckHelper.throwIfNull(doc_item_attrib, () => $"doc_item_attrib is null !!! - {owner.toBasicString()}");
// InvenEquipType 비장작 상태인 경우만 허용 한다. !!! - kangms
if (InvenEquipType.None != doc_item_attrib.EquipedInvenType)
{
err_msg = $"Not found InventoryRule !!! : ItemMetaId:{doc_item_attrib.ItemMetaId}, itemGuid:{doc_item_attrib.OwnerGuid} - {owner.toBasicString()}";
result.setFail(ServerErrorCode.InvenEquipTypeInvalid, err_msg);
Log.getLogger().error(result.toBasicString());
return (result, null);
}
(result, var took_in_item) = await m_bag_inven.tryTakableInItemBase(doc, true);
if (result.isFail())
{
return (result, null);
}
NullReferenceCheckHelper.throwIfNull(took_in_item, () => $"took_in_item is null !!! - {owner.toBasicString()}");
return (result, took_in_item);
}
//=========================================================================================
// 아이템을 가방에 지급하고 장착 하기 (from Memory)
//=========================================================================================
public async Task<(Result, Item?)> tryTakableToBagWithEquip(ItemDoc doc, Int16 toEquipSlotPos)
{
var owner = getOwner();
NullReferenceCheckHelper.throwIfNull(owner, () => $"owner is null !!!");
ArgumentNullReferenceCheckHelper.throwIfNull(doc, () => $"doc is null !!! - {owner.toBasicString()}");
var result = new Result();
var err_msg = string.Empty;
var doc_item_attrib = doc.getAttrib<ItemAttrib>();
NullReferenceCheckHelper.throwIfNull(doc_item_attrib, () => $"doc_item_attrib is null !!! - {owner.toBasicString()}");
(result, var took_in_item) = await m_bag_inven.tryTakableInItemBase(doc, true);
if (result.isFail())
{
return (result, null);
}
NullReferenceCheckHelper.throwIfNull(took_in_item, () => $"took_in_item is null !!! - {owner.toBasicString()}");
result = await tryTakableToEquip(took_in_item, toEquipSlotPos);
if (result.isFail())
{
return (result, null);
}
return (result, took_in_item);
}
//=========================================================================================
// 아이템을 가방에 지급하고 장착 하기 (from DB)
//=========================================================================================
public async Task<(Result, Item?)> tryTakableToBagWithEquip(ItemDoc doc, Dictionary<InvenEquipType, HashSet<Int16>> reservedSlotTypes)
{
var owner = getOwner();
NullReferenceCheckHelper.throwIfNull(owner, () => $"owner is null !!!");
ArgumentNullReferenceCheckHelper.throwIfNull(doc, () => $"doc is null !!! - {owner.toBasicString()}");
var server_logic = GameServerApp.getServerLogic();
var dynamo_db_client = server_logic.getDynamoDbClient();
var result = new Result();
var err_msg = string.Empty;
(result, var took_in_item) = await m_bag_inven.tryTakableInItemBase(doc);
if (result.isFail())
{
return (result, null);
}
NullReferenceCheckHelper.throwIfNull(took_in_item, () => $"took_in_item is null !!! - {owner.toBasicString()}");
var item_meta = took_in_item.getItemMeta();
NullReferenceCheckHelper.throwIfNull(item_meta, () => $"item_meta is null !!! - {owner.toBasicString()}");
var item_attribute = took_in_item.getEntityAttribute<ItemAttributeBase>();
NullReferenceCheckHelper.throwIfNull(item_attribute, () => $"item_attribute is null !!! - {owner.toBasicString()}");
// InvenEquipType 장착 상태인 경우만 장착 시켜준다 !!! - kangms
if (InvenEquipType.None != item_attribute.EquipedInvenType)
{
var equiped_pos = item_attribute.EquipedPos;
result = await tryTakableToEquip(took_in_item, (Int16)equiped_pos);
if (result.isFail())
{
return (result, took_in_item);
}
if(false == reservedSlotTypes.TryGetValue(item_attribute.EquipedInvenType, out var reserved_slots))
{
reserved_slots = new HashSet<Int16>();
reservedSlotTypes.Add(item_attribute.EquipedInvenType, reserved_slots);
}
reserved_slots.Add((Int16)equiped_pos);
}
return (result, took_in_item);
}
//=========================================================================================
// 아이템을 가방에 지급 하기 (from Meta)
//=========================================================================================
public async Task<(Result, List<Item>)> tryTakalbleToBag(META_ID itemMetaId, UInt16 toAddCount = 1)
{
var owner = getOwner();
NullReferenceCheckHelper.throwIfNull(owner, () => $"owner is null !!!");
var result = new Result();
var err_msg = string.Empty;
(result, var reserved_items) = await m_bag_inven.tryTakableInItemBase(itemMetaId, toAddCount);
if (result.isFail())
{
return (result, reserved_items);
}
NullReferenceCheckHelper.throwIfNull(reserved_items, () => $"reserved_items is null !!! - {owner.toBasicString()}");
return (result, reserved_items);
}
//=========================================================================================
// 아이템을 가방에 지급하고 장착 하기 (from Meta)
//=========================================================================================
public async Task<(Result, List<Item>)> tryTakableToBagWithEquip(META_ID itemMetaId, UInt16 toAddCount = 1, Int16 slotPos = -1)
{
var owner = getOwner();
NullReferenceCheckHelper.throwIfNull(owner, () => $"owner is null !!!");
var result = new Result();
var err_msg = string.Empty;
(result, var reserved_items) = await m_bag_inven.tryTakableInItemBase(itemMetaId, toAddCount);
if (result.isFail() || 0 >= reserved_items.Count)
{
return (result, reserved_items);
}
NullReferenceCheckHelper.throwIfNull(reserved_items, () => $"reserved_items is null !!! - {owner.toBasicString()}");
foreach (var item in reserved_items)
{
result = await tryTakableToEquip(item, slotPos);
if (result.isFail())
{
return (result, reserved_items);
}
}
return (result, reserved_items);
}
//=========================================================================================
// 아이템을 장착 하기
//=========================================================================================
public async Task<Result> tryTakableToEquip(Item item, Int16 slotPos = -1)
{
var owner = getOwner();
NullReferenceCheckHelper.throwIfNull(owner, () => $"owner is null !!!");
ArgumentNullReferenceCheckHelper.throwIfNull(item, () => $"item is null !!! - {owner.toBasicString()}");
var result = new Result();
var err_msg = string.Empty;
var item_doc_attrib = item.getEntityAttribute<ItemAttributeBase>();
NullReferenceCheckHelper.throwIfNull(item_doc_attrib, () => $"item_doc_attrib is null !!! - {owner.toBasicString()}");
var inven_rule = GameServerApp.getServerLogic().findRule<InventoryRule>();
if (null == inven_rule)
{
err_msg = $"Not found InventoryRule !!! : ItemMetaId:{item_doc_attrib.ItemMetaId} - {owner.toBasicString()}";
result.setFail(ServerErrorCode.InventoryRuleNotFound, err_msg);
Log.getLogger().error(result.toBasicString());
return result;
}
var item_meta = item.getItemMeta();
NullReferenceCheckHelper.throwIfNull(item_meta, () => $"item_meta is null !!! - {owner.toBasicString()}");
var equip_rule_bases = inven_rule.getEquipRuleBasesByItemLargeType(item_meta.TypeLarge);
if (null == equip_rule_bases)
{
err_msg = $"Not found EquipRuleBase !!! : ItemMetaId:{item_doc_attrib.ItemMetaId} - {owner.toBasicString()}";
Log.getLogger().warn(err_msg);
}
else
{
foreach (var equip_rule in equip_rule_bases)
{
(result, var equip_slot_type) = await tryTakableToEquipByRule(equip_rule, item, slotPos);
if (result.isFail())
{
err_msg = $"Failed to tryTakableToEquipByRule() !!! : {result.toBasicString()}, invenEquipType:{equip_rule.InvenEquipType}, equipSlot:{equip_slot_type} - {owner.toBasicString()}";
Log.getLogger().warn(err_msg);
continue;
}
return result;
}
}
return result;
}
//=========================================================================================
// 아이템 장착 정책을 참조하여 아이템 장착 하기
//=========================================================================================
private async Task<(Result, Int16)> tryTakableToEquipByRule(EquipRuleBase equipRuleBase, Item toEquipItem, Int16 slotPos)
{
var owner = getOwner();
NullReferenceCheckHelper.throwIfNull(owner, () => $"owner is null !!!");
ArgumentNullReferenceCheckHelper.throwIfNull(equipRuleBase, () => $"equipRuleBase is null !!! - {owner.toBasicString()}");
ArgumentNullReferenceCheckHelper.throwIfNull(toEquipItem, () => $"toEquipItem is null !!! - {owner.toBasicString()}");
await Task.CompletedTask;
var result = new Result();
var err_msg = string.Empty;
if (false == m_equip_invens.TryGetValue(equipRuleBase.InvenEquipType, out var found_equip_inven))
{
err_msg = $"Not found EquipInven !!! : invenEquipType:{equipRuleBase.InvenEquipType}, {toEquipItem.toBasicString()} - {owner.toBasicString()}";
result.setFail(ServerErrorCode.EquipInvenNotFound, err_msg);
Log.getLogger().error(result.toBasicString());
return (result, -1);
}
NullReferenceCheckHelper.throwIfNull(found_equip_inven, () => $"found_equip_inven is null !!! - {owner.toBasicString()}");
var item_attribute = toEquipItem.getEntityAttribute<ItemAttributeBase>();
NullReferenceCheckHelper.throwIfNull(item_attribute, () => $"item_attribute is null !!! - {owner.toBasicString()}");
var to_equip_pos = -1;
var item_meta = toEquipItem.getItemMeta();
NullReferenceCheckHelper.throwIfNull(item_meta, () => $"item_meta is null !!! - {owner.toBasicString()}");
var item_small_type = item_meta.TypeSmall;
switch (equipRuleBase.InvenEquipType)
{
case InvenEquipType.Tool:
{
var tool_equip_rule = equipRuleBase as ToolEquipRule;
NullReferenceCheckHelper.throwIfNull(tool_equip_rule, () => $"tool_equip_rule is null !!! - {owner.toBasicString()}");
var found_tool_slot_type = tool_equip_rule.UsableToolSlotTypes.FirstOrDefault(x => x == (ToolSlotType)slotPos, ToolSlotType.None);
if (ToolSlotType.None == found_tool_slot_type)
{
err_msg = $"Not found ToolSlotType !!! : ToolSlotType:{(ToolSlotType)slotPos}, itemSmallType:{item_small_type}, {toEquipItem.toBasicString()} - {owner.toBasicString()}";
result.setFail(ServerErrorCode.ToolEquipRuleToolSlotTypeNotFound, err_msg);
Log.getLogger().error(result.toBasicString());
return (result, -1);
}
var equip_inven = found_equip_inven as ToolEquipInven;
NullReferenceCheckHelper.throwIfNull(equip_inven, () => $"equip_inven is null !!! - {owner.toBasicString()}");
result = equip_inven.tryIsEquipableOrEquipWithEntityBase(found_tool_slot_type, toEquipItem);
if (result.isFail())
{
return (result, (Int16)found_tool_slot_type);
}
to_equip_pos = (Int16)found_tool_slot_type;
} break;
case InvenEquipType.Cloth:
{
var cloth_equip_rule = equipRuleBase as ClothEquipRule;
NullReferenceCheckHelper.throwIfNull(cloth_equip_rule, () => $"cloth_equip_rule is null !!! - {owner.toBasicString()}");
if (false == cloth_equip_rule.m_slots_by_item_type.TryGetValue(item_small_type, out var found_cloth_slot_types))
{
err_msg = $"Not found ClothSlotType !!! : itemSmallType:{item_small_type}, {toEquipItem.toBasicString()} - {owner.toBasicString()}";
result.setFail(ServerErrorCode.ClothEquipRuleClothSlotTypeNotFound, err_msg);
Log.getLogger().error(result.toBasicString());
return (result, -1);
}
NullReferenceCheckHelper.throwIfNull(found_cloth_slot_types, () => $"found_cloth_slot_types is null !!! - {owner.toBasicString()}");
var equip_inven = found_equip_inven as ClothEquipInven;
NullReferenceCheckHelper.throwIfNull(equip_inven, () => $"equip_inven is null !!! - {owner.toBasicString()}");
foreach (var cloth_slot_type in found_cloth_slot_types)
{
result = equip_inven.tryIsEquipableOrEquipWithEntityBase(cloth_slot_type, toEquipItem);
if (result.isFail())
{
return (result, (Int16)cloth_slot_type);
}
to_equip_pos = (Int16)cloth_slot_type;
break;
}
} break;
case InvenEquipType.Tattoo:
{
var tattoo_equip_rule = equipRuleBase as TattooEquipRule;
NullReferenceCheckHelper.throwIfNull(tattoo_equip_rule, () => $"tattoo_equip_rule is null !!! - {owner.toBasicString()}");
var found_tattoo_slot_type = tattoo_equip_rule.getUsableTattooSlotPos(owner.getEntityType()).FirstOrDefault(x => x == (TattooSlotType)slotPos, TattooSlotType.None);
if (TattooSlotType.None == found_tattoo_slot_type)
{
err_msg = $"Not found TattooSlotType !!! : TattooSlotType:{(TattooSlotType)slotPos}, itemSmallType:{item_small_type}, {toEquipItem.toBasicString()} - {owner.toBasicString()}";
result.setFail(ServerErrorCode.TattooEquipRuleTattooSlotTypeNotFound, err_msg);
Log.getLogger().error(result.toBasicString());
return (result, -1);
}
var equip_inven = found_equip_inven as TattooEquipInven;
NullReferenceCheckHelper.throwIfNull(equip_inven, () => $"equip_inven is null !!! - {owner.toBasicString()}");
result = equip_inven.tryIsEquipableOrEquipWithEntityBase(found_tattoo_slot_type, toEquipItem);
if (result.isFail())
{
return (result, (Int16)found_tattoo_slot_type);
}
to_equip_pos = (Int16)found_tattoo_slot_type;
// tattoo 의 ability 를 user 의 ability 에 추가
var ability_action = owner.getEntityAction<AbilityAction>();
NullReferenceCheckHelper.throwIfNull(ability_action, () => $"ability_action is null !!! - {owner.toBasicString()}");
result = await ability_action.setAbilities(toEquipItem, (Int16)item_attribute.Level, false);
if (result.isFail())
{
return (result, (Int16)found_tattoo_slot_type);
}
} break;
}
item_attribute.EquipedInvenType = equipRuleBase.InvenEquipType;
item_attribute.EquipedPos = (UInt16)to_equip_pos;
item_attribute.modifiedEntityAttribute();
return (result, (Int16)to_equip_pos);
}
//=========================================================================================
// 아이템 삭제 하기 (from META + Count)
// toDeleteCount == 0 일 경우 보유중인 itemMetaId 의 모두 찾아 삭제 한다.
//=========================================================================================
public async Task<(Result, List<Item>)> tryDeleteItemByMetaId(META_ID itemMetaId, UInt32 toDeleteCount = UInt32.MaxValue)
{
var owner = getOwner();
NullReferenceCheckHelper.throwIfNull(owner, () => $"owner is null !!!");
// 1. 가방에서 아이템들을 제거 한다.
var (result, reserved_items) = await m_bag_inven.tryTakableOutItemBase(itemMetaId, toDeleteCount);
if (result.isFail())
{
return (result, reserved_items);
}
NullReferenceCheckHelper.throwIfNull(reserved_items, () => $"reserved_items is null !!! - {owner.toBasicString()}");
foreach (var reserved_item in reserved_items)
{
var item_attribute = reserved_item.getEntityAttribute<ItemAttributeBase>();
NullReferenceCheckHelper.throwIfNull(item_attribute, () => $"item_attribute is null !!! - {owner.toBasicString()}");
// 2. 장착 인벤으로 설정되어 있는 경우, 장착을 해제 한다.
if (InvenEquipType.None != item_attribute.EquipedInvenType)
{
(result, var unequiped_item) = await tryTakableOutFromEquip(reserved_item);
if (result.isFail())
{
return (result, reserved_items);
}
NullReferenceCheckHelper.throwIfNull(unequiped_item, () => $"unequiped_item is null !!! - {owner.toBasicString()}");
}
}
return (result, reserved_items);
}
//=========================================================================================
// 아이템 삭제 하기 (from ITEM_GUID + Count)
//=========================================================================================
public async Task<(Result, Item?)> tryDeleteItemByGuid(ITEM_GUID itemGuid, UInt16 toDeleteCount = 1)
{
var owner = getOwner();
NullReferenceCheckHelper.throwIfNull(owner, () => $"owner is null !!!");
// 1. 가방에서 아이템을 제거 한다.
var (result, reserved_item) = await m_bag_inven.tryTakableOutItemBase(itemGuid, toDeleteCount);
if (result.isFail())
{
return (result, null);
}
NullReferenceCheckHelper.throwIfNull(reserved_item, () => $"reserved_item is null !!! - {owner.toBasicString()}");
var item_attribute = reserved_item.getEntityAttribute<ItemAttributeBase>();
NullReferenceCheckHelper.throwIfNull(item_attribute, () => $"item_attribute is null !!! - {owner.toBasicString()}");
// 2. 장착 인벤으로 설정되어 있는 경우, 장착을 해제 한다.
if (InvenEquipType.None != item_attribute.EquipedInvenType)
{
(result, var unequiped_item) = await tryTakableOutFromEquip(reserved_item);
if (result.isFail())
{
return (result, null);
}
NullReferenceCheckHelper.throwIfNull(unequiped_item, () => $"unequiped_item is null !!! - {owner.toBasicString()}");
}
return (result, reserved_item);
}
public async Task<(Result, Item?)> tryTakableOutFromEquip(Item item)
{
var owner = getOwner();
NullReferenceCheckHelper.throwIfNull(owner, () => $"owner is null !!!");
var result = new Result();
var err_msg = string.Empty;
var item_attribute = item.getEntityAttribute<ItemAttributeBase>();
NullReferenceCheckHelper.throwIfNull(item_attribute, () => $"item_attribute is null !!! - {owner.toBasicString()}");
var inven_rule = GameServerApp.getServerLogic().findRule<InventoryRule>();
if (null == inven_rule)
{
err_msg = $"Not found InventoryRule !!! : ItemMetaId:{item_attribute.ItemMetaId} - {owner.toBasicString()}";
result.setFail(ServerErrorCode.InventoryRuleNotFound, err_msg);
Log.getLogger().error(result.toBasicString());
return (result, null);
}
var item_meta = item.getItemMeta();
NullReferenceCheckHelper.throwIfNull(item_meta, () => $"item_meta is null !!! - {owner.toBasicString()}");
var equip_rule_bases = inven_rule.getEquipRuleBasesByItemLargeType(item_meta.TypeLarge);
if (null == equip_rule_bases)
{
err_msg = $"Not found EquipRuleBase !!! : ItemTypeLarge:{item_meta.TypeLarge}, ItemMetaId:{item_attribute.ItemMetaId} - {owner.toBasicString()}";
Log.getLogger().warn(err_msg);
}
else
{
foreach (var equip_rule in equip_rule_bases)
{
(var unequip_result, var unequip_slot_type) = await tryTakableOutFromEquipByRule(equip_rule, item);
if (unequip_result.isFail())
{
err_msg = $"Failed to tryTakableOutFromEquipByRule() !!! : {unequip_result.toBasicString()}, invenEquipType:{equip_rule.InvenEquipType}, unequipSlot:{unequip_slot_type} - {owner.toBasicString()}";
Log.getLogger().warn(err_msg);
continue;
}
return (result, item);
}
}
return (result, item);
}
private async Task<(Result, Int16)> tryTakableOutFromEquipByRule(EquipRuleBase equipRuleBase, Item toUnequipItem)
{
var owner = getOwner();
NullReferenceCheckHelper.throwIfNull(owner, () => $"owner is null !!!");
ArgumentNullReferenceCheckHelper.throwIfNull(equipRuleBase, () => $"equipRuleBase is null !!! - {owner.toBasicString()}");
ArgumentNullReferenceCheckHelper.throwIfNull(toUnequipItem, () => $"toUnequipItem is null !!! - {owner.toBasicString()}");
await Task.CompletedTask;
var result = new Result();
var err_msg = string.Empty;
var to_unequip_pos = 0;
if (false == m_equip_invens.TryGetValue(equipRuleBase.InvenEquipType, out var found_equip_inven))
{
err_msg = $"Not found EquipInven !!! : invenEquipType:{equipRuleBase.InvenEquipType}, {toUnequipItem.toBasicString()} - {owner.toBasicString()}";
result.setFail(ServerErrorCode.EquipInvenNotFound, err_msg);
Log.getLogger().error(result.toBasicString());
return (result, -1);
}
NullReferenceCheckHelper.throwIfNull(found_equip_inven, () => $"found_equip_inven is null !!! - {owner.toBasicString()}");
var item_attribute = toUnequipItem.getEntityAttribute<ItemAttributeBase>();
NullReferenceCheckHelper.throwIfNull(item_attribute, () => $"item_attribute is null !!! - {owner.toBasicString()}");
var slot_pos = item_attribute.EquipedPos;
var item_meta = toUnequipItem.getItemMeta();
NullReferenceCheckHelper.throwIfNull(item_meta, () => $"item_meta is null !!! - {owner.toBasicString()}");
var item_small_type = item_meta.TypeSmall;
switch (equipRuleBase.InvenEquipType)
{
case InvenEquipType.Tool:
{
var tool_equip_rule = equipRuleBase as ToolEquipRule;
NullReferenceCheckHelper.throwIfNull(tool_equip_rule, () => $"tool_equip_rule is null !!! - {owner.toBasicString()}");
var found_tool_slot_type = tool_equip_rule.UsableToolSlotTypes.FirstOrDefault(x => x == (ToolSlotType)slot_pos, ToolSlotType.None);
if (ToolSlotType.None == found_tool_slot_type)
{
err_msg = $"Not found ToolSlotType !!! : ToolSlotType:{(ToolSlotType)slot_pos}, itemSmallType:{item_small_type}, {toUnequipItem.toBasicString()} - {owner.toBasicString()}";
result.setFail(ServerErrorCode.ToolEquipRuleToolSlotTypeNotFound, err_msg);
Log.getLogger().error(result.toBasicString());
return (result, -1);
}
var tool_equip_inven = found_equip_inven as ToolEquipInven;
NullReferenceCheckHelper.throwIfNull(tool_equip_inven, () => $"tool_equip_inven is null !!! - {owner.toBasicString()}");
result = tool_equip_inven.tryUnequipableOrUnequipWithEntityBase(found_tool_slot_type, out _);
if (result.isFail())
{
return (result, (Int16)found_tool_slot_type);
}
to_unequip_pos = (Int16)found_tool_slot_type;
var root_parent = owner.getRootParent();
NullReferenceCheckHelper.throwIfNull(root_parent, () => $"root_parent is null !!! - {owner.toBasicString()}");
var item_tool_action = root_parent.getEntityAction<ItemToolAction>();
if(null != item_tool_action)
{
var tool_result = await item_tool_action.tryUnactivateItemTool();
if (tool_result.isFail())
{
err_msg = $"Failed to tryUnactivateItemTool() : {tool_result.toBasicString()} - {owner.toBasicString()}";
Log.getLogger().error(err_msg);
}
}
} break;
case InvenEquipType.Cloth:
{
var cloth_equip_rule = equipRuleBase as ClothEquipRule;
NullReferenceCheckHelper.throwIfNull(cloth_equip_rule, () => $"cloth_equip_rule is null !!! - {owner.toBasicString()}");
if (false == cloth_equip_rule.m_slots_by_item_type.TryGetValue(item_small_type, out var found_cloth_slot_types))
{
err_msg = $"Not found ClothSlotType !!! : itemSmallType:{item_small_type}, {toUnequipItem.toBasicString()} - {owner.toBasicString()}";
result.setFail(ServerErrorCode.ClothEquipRuleClothSlotTypeNotFound, err_msg);
Log.getLogger().error(result.toBasicString());
return (result, -1);
}
var cloth_equip_inven = found_equip_inven as ClothEquipInven;
NullReferenceCheckHelper.throwIfNull(cloth_equip_inven, () => $"cloth_equip_inven is null !!! - {owner.toBasicString()}");
foreach (var cloth_slot_type in found_cloth_slot_types)
{
result = cloth_equip_inven.tryUnequipableOrUnequipWithEntityBase(cloth_slot_type, out _);
if (result.isFail())
{
return (result, (Int16)cloth_slot_type);
}
to_unequip_pos = (Int16)cloth_slot_type;
break;
}
} break;
case InvenEquipType.Tattoo:
{
var tattoo_equip_rule = equipRuleBase as TattooEquipRule;
NullReferenceCheckHelper.throwIfNull(tattoo_equip_rule, () => $"tattoo_equip_rule is null !!! - {owner.toBasicString()}");
var found_tattoo_slot_type = tattoo_equip_rule.getUsableTattooSlotPos(owner.getEntityType()).FirstOrDefault(x => x == (TattooSlotType)slot_pos, TattooSlotType.None);
if (TattooSlotType.None == found_tattoo_slot_type)
{
err_msg = $"Not found TattooSlotType !!! : TattooSlotType:{(TattooSlotType)slot_pos}, itemSmallType:{item_small_type}, {toUnequipItem.toBasicString()} - {owner.toBasicString()}";
result.setFail(ServerErrorCode.TattooEquipRuleTattooSlotTypeNotFound, err_msg);
Log.getLogger().error(result.toBasicString());
return (result, -1);
}
var tattoo_equip_inven = found_equip_inven as TattooEquipInven;
NullReferenceCheckHelper.throwIfNull(tattoo_equip_inven, () => $"tattoo_equip_inven is null !!! - {owner.toBasicString()}");
result = tattoo_equip_inven.tryUnequipableOrUnequipWithEntityBase(found_tattoo_slot_type, out _);
if (result.isFail())
{
return (result, (Int16)found_tattoo_slot_type);
}
to_unequip_pos = (Int16)found_tattoo_slot_type;
// tattoo 의 ability 를 user 의 ability 에 추가
var ability_action = getOwner().getEntityAction<AbilityAction>();
NullReferenceCheckHelper.throwIfNull(ability_action, () => $"ability_action is null !!! - {owner.toBasicString()}");
result = await ability_action.setAbilities(toUnequipItem, (Int16)item_attribute.Level, true);
if (result.isFail())
{
return (result, (Int16)found_tattoo_slot_type);
}
} break;
}
item_attribute.EquipedInvenType = InvenEquipType.None;
item_attribute.EquipedPos = 0;
item_attribute.modifiedEntityAttribute();
return (result, (Int16)to_unequip_pos);
}
public async Task<(Result, List<Item>?)> tryDeleteItemAll()
{
var owner = getOwner();
NullReferenceCheckHelper.throwIfNull(owner, () => $"owner is null !!!");
var bag_inven = getBagInven();
NullReferenceCheckHelper.throwIfNull(bag_inven, () => $"bag_inven is null !!! - {owner.toBasicString()}");
var bag_slot_data = bag_inven.getData();
NullReferenceCheckHelper.throwIfNull(bag_slot_data, () => $"bag_slot_data is null !!! - {owner.toBasicString()}");
var result = new Result();
var to_delete_items = new List<Item>();
var bag_items = bag_slot_data.getEntityBases();
NullReferenceCheckHelper.throwIfNull(bag_items, () => $"bag_items is null !!! - {owner.toBasicString()}");
foreach (var bag_item in bag_items)
{
var has_item = bag_item as Item;
NullReferenceCheckHelper.throwIfNull(has_item, () => $"has_item is null !!! - {owner.toBasicString()}");
var item_attribute = has_item.getEntityAttribute<ItemAttributeBase>();
NullReferenceCheckHelper.throwIfNull(item_attribute, () => $"item_attribute is null !!! - {owner.toBasicString()}");
var to_delete_item_guid = item_attribute.ItemGuid;
var to_delete_item_count = item_attribute.ItemStackCount;
(result, var item) = await tryDeleteItemByGuid(to_delete_item_guid, to_delete_item_count);
if (result.isFail())
{
return (result, null);
}
to_delete_items.Add(has_item);
}
var equiped_items = getEquipItemAll();
NullReferenceCheckHelper.throwIfNull(equiped_items, () => $"equiped_items is null !!! - {owner.toBasicString()}");
foreach (var equiped_item in equiped_items)
{
var item_attribute = equiped_item.getEntityAttribute<ItemAttributeBase>();
NullReferenceCheckHelper.throwIfNull(item_attribute, () => $"item_attribute is null !!! - {owner.toBasicString()}");
var to_delete_item_guid = item_attribute.ItemGuid;
var to_delete_item_count = item_attribute.ItemStackCount;
(result, var item) = await tryDeleteItemByGuid(to_delete_item_guid, to_delete_item_count);
if (result.isFail())
{
return (result, null);
}
to_delete_items.Add(equiped_item);
}
return (result, to_delete_items);
}
public async Task<(Result, Item?, Item?)> tryDivideItem(ITEM_GUID itemGuid, UInt16 toDivideCount = 1)
{
var owner = getOwner();
NullReferenceCheckHelper.throwIfNull(owner, () => $"owner is null !!!");
var parent = owner.getRootParent();
NullReferenceCheckHelper.throwIfNull(parent, () => $"parent is null !!! - {owner.toBasicString()}");
var (result, divided_item, new_item) = await m_bag_inven.tryDivideItem(itemGuid, toDivideCount);
if (result.isFail())
{
return (result, null, null);
}
NullReferenceCheckHelper.throwIfNull(divided_item, () => $"reserved_item is null !!! - {parent.toBasicString()}");
return (result, divided_item, new_item);
}
public async Task<Result> tryResetAttributeByTattoo()
{
var owner = getOwner();
NullReferenceCheckHelper.throwIfNull(owner, () => $"owner is null !!!");
var parent = owner.getRootParent();
NullReferenceCheckHelper.throwIfNull(parent, () => $"parent is null !!! - {owner.toBasicString()}");
var result = new Result();
var err_msg = string.Empty;
if (false == m_equip_invens.TryGetValue(InvenEquipType.Tattoo, out var found_equip_inven))
{
err_msg = $"Not found InvenEquipType.Tattoo !!! - {parent.toBasicString()}";
result.setFail(ServerErrorCode.EquipInvenNotFound, err_msg);
Log.getLogger().error(result.toBasicString());
return result;
}
var inven_accessor = found_equip_inven as IWithInventoryAccessor;
NullReferenceCheckHelper.throwIfNull(inven_accessor, () => $"inven_accessor is null !!! - {owner.toBasicString()}");
foreach (var item in inven_accessor.getHasItemBases())
{
var item_attribute = item.getEntityAttribute<ItemAttributeBase>();
NullReferenceCheckHelper.throwIfNull(item_attribute, () => $"item_attribute is null !!! - {owner.toBasicString()}");
var ability_action = owner.getEntityAction<AbilityAction>();
NullReferenceCheckHelper.throwIfNull(ability_action, () => $"ability_action is null !!! - {owner.toBasicString()}");
result = await ability_action.setAbilities(item, (Int16)item_attribute.Level, false);
if (result.isFail())
{
return result;
}
}
return result;
}
protected async Task onUpdateItemAll()
{
var owner = getOwner();
NullReferenceCheckHelper.throwIfNull(owner, () => $"owner is null !!!");
var parent = owner.getRootParent();
NullReferenceCheckHelper.throwIfNull(parent, () => $"parent is null !!! - {owner.toBasicString()}");
var err_msg = string.Empty;
var result = new Result();
if (false == m_entity_update_timer.isOn()) { return; }
var has_item_guids = getBagInven().getHasSlotsWithEntityBases().Keys.ToList();
foreach (var target_item_guid in has_item_guids)
{
var found_item_base = getBagInven().findEntityBase(target_item_guid);
if(null == found_item_base)
{
err_msg = $"Not found Item !!! : itemGuid:{target_item_guid} - {parent.toBasicString()}";
Log.getLogger().debug(err_msg);
continue;
}
var item_action = found_item_base.getEntityAction<ItemAction>();
NullReferenceCheckHelper.throwIfNull(item_action, () => $"item_action is null !!! - {parent.toBasicString()}");
await item_action.onTick();
}
}
public override async Task onTick()
{
await onUpdateItemAll();
}
public abstract Item onAllocItem();
public async Task<Result> onMergeInventory(List<ReservedSlotOnInven> reservedSlotOnInvens, TransactionRunner transactionRunner)
{
var owner = getOwner();
NullReferenceCheckHelper.throwIfNull(owner, () => $"owner is null !!!");
ArgumentNullReferenceCheckHelper.throwIfNull(reservedSlotOnInvens, () => $"reservedSlotOnInvens is null !!! - {owner.toBasicString()}");
ArgumentNullReferenceCheckHelper.throwIfNull(transactionRunner, () => $"transactionRunner is null !!! - {owner.toBasicString()}");
var result = new Result();
var err_msg = string.Empty;
foreach(var reserved_inven in reservedSlotOnInvens)
{
var entity_inven_type = reserved_inven.getEntityType();
switch (entity_inven_type)
{
case EntityType.BagInven:
{
foreach(var each_slot in reserved_inven.getReservedSlots())
{
var bag_tab_type_key = each_slot.Key;
var reserved_slot = each_slot.Value;
bool is_bag_tab_type = true;
// 1. 가방에 보관된 예약 아이템을 적용 한다.
var to_equip_item = reserved_slot.getEquipEntity() as Item;
if (null != to_equip_item)
{
result = m_bag_inven.onMergeTakeInItem(to_equip_item);
if (result.isFail())
{
continue;
}
var item_attribute = to_equip_item.getEntityAttributeWithReadOnly<ItemAttributeBase>();
NullReferenceCheckHelper.throwIfNull(item_attribute, () => $"item_attribute is null !!! - {owner.toBasicString()}");
err_msg = $"Successfully called onMergeTakeInItem() !!! : itemGuid:{item_attribute.ItemGuid}, itemMetaId:{item_attribute.ItemMetaId}, itemCount:{item_attribute.ItemStackCount} - {owner.toBasicString()}";
Log.getLogger().info(err_msg);
await transactionRunner.onApplyCommonResultOfInsertedItem(to_equip_item);
is_bag_tab_type = false;
}
// 2. 가방에 보관 해제된 예약 아이템을 적용 한다.
var to_unequip_item = reserved_slot.getUnequipEntity() as Item;
if (null != to_unequip_item)
{
result = m_bag_inven.onMergeTakeOutItem(to_unequip_item);
if (result.isFail())
{
continue;
}
var item_attribute = to_unequip_item.getEntityAttributeWithReadOnly<ItemAttributeBase>();
NullReferenceCheckHelper.throwIfNull(item_attribute, () => $"item_attribute is null !!! - {owner.toBasicString()}");
err_msg = $"Successfully called onMergeTakeOutItem() !!! : itemGuid:{item_attribute.ItemGuid}, itemMetaId:{item_attribute.ItemMetaId}, itemCount:{item_attribute.ItemStackCount} - {owner.toBasicString()}";
Log.getLogger().info(err_msg);
await transactionRunner.onApplyCommonResultOfDeletedItem(to_unequip_item);
is_bag_tab_type = false;
}
// 3. 장착/해제 아이템 관련 처리가 아닌 경우 : BagTabType의 예약된 보관 개수를 적용 한다.
if (true == is_bag_tab_type)
{
// 3. 예약된 BagTabType의 슬롯 갯수를 적용 한다.
var bag_tab_type = EnumHelper.convertEnumTypeAndValueStringToEnum<BagTabType>(bag_tab_type_key, BagTabType.None);
if (BagTabType.None == bag_tab_type)
{
err_msg = $"Failed to convertEnumTypeAndValueStringToEnum() !!! : BagTabTypeKey:{bag_tab_type_key} - {owner.toBasicString()}";
result.setFail(ServerErrorCode.BagTabTypeInvalid, err_msg);
Log.getLogger().error(result.toBasicString());
continue;
}
if (false == m_bag_inven.getBagTabs().TryGetValue(bag_tab_type, out var found_bag_tab))
{
err_msg = $"Failed to TryGetValue() !!! : BagTabTypeKey:{bag_tab_type} - {owner.toBasicString()}";
result.setFail(ServerErrorCode.BagTabTypeNotFound, err_msg);
Log.getLogger().error(result.toBasicString());
continue;
}
NullReferenceCheckHelper.throwIfNull(found_bag_tab, () => $"found_bag_tab is null !!! - {owner.toBasicString()}");
var curr_count = found_bag_tab.TakeInItemCount;
var reserved_count = reserved_slot.getReservedCount();
if (false == found_bag_tab.onMergeTakeInItemCount(reserved_count))
{
err_msg = $"Failed to onMergeTakeInItemCount() !!! : reservedCount:{reserved_count}, currCount:{curr_count}, BagTabType:{bag_tab_type}, {found_bag_tab.toBasicString()} - {owner.toBasicString()}";
result.setFail(ServerErrorCode.BagTabCountMergeFailed, err_msg);
Log.getLogger().error(result.toBasicString());
continue;
}
else
{
err_msg = $"Successfully called onMergeTakeInItemCount() !!! : reservedCount:{reserved_count}, currCount:{curr_count}, BagTabType:{bag_tab_type}, {found_bag_tab.toBasicString()} - {owner.toBasicString()}";
Log.getLogger().info(err_msg);
}
}
}
}break;
case EntityType.ClothEquipInven:
case EntityType.ToolEquipInven:
case EntityType.TattooEquipInven:
{
var inven_equip_type = reserved_inven.getEntityType().toInvenEquipType();
if(InvenEquipType.None == inven_equip_type)
{
err_msg = $"Failed to toInvenEquipType() !!! : entityType:{entity_inven_type} - {owner.toBasicString()}";
result.setFail(ServerErrorCode.InvenEquipTypeInvalid, err_msg);
Log.getLogger().error(result.toBasicString());
continue;
}
if(false == m_equip_invens.TryGetValue(inven_equip_type, out var found_equip_inven))
{
err_msg = $"Not found EquipInven() !!! : entityType:{entity_inven_type} - {owner.toBasicString()}";
result.setFail(ServerErrorCode.EquipInvenNotFound, err_msg);
Log.getLogger().error(result.toBasicString());
continue;
}
var inven_accessor = found_equip_inven as IWithInventoryAccessor;
NullReferenceCheckHelper.throwIfNull(inven_accessor, () => $"inven_accessor is null !!!");
foreach (var each_slot in reserved_inven.getReservedSlots())
{
var reserved_key = each_slot.Key;
var reserved_slot = each_slot.Value;
var delta_count = reserved_slot.getReservedCount();
var error_code = ServerErrorCode.Success;
if (0 >= delta_count)
{
var unequip_item = reserved_slot.getUnequipEntity() as Item;
NullReferenceCheckHelper.throwIfNull(unequip_item, () => $"unequip_item is null !!! - {owner.toBasicString()}");
var item_attribute = unequip_item.getEntityAttributeWithReadOnly<ItemAttributeBase>();
NullReferenceCheckHelper.throwIfNull(item_attribute, () => $"item_attribute is null !!! - {owner.toBasicString()}");
error_code = inven_accessor.tryUnequipWithItemBase(reserved_key, out _);
if (error_code.isFail())
{
err_msg = $"Failed to onTryUnequipWithEntityBase() !!! : {error_code.toBasicString()}, deltaCount:{delta_count} - {owner.toBasicString()}";
result.setFail(error_code, err_msg);
Log.getLogger().error(result.toBasicString());
}
else
{
err_msg = $"Successfully called onTryUnequipWithEntityBase() !!! : deltaCount:{delta_count}, itemGuid:{item_attribute.ItemGuid}, itemMetaId:{item_attribute.ItemMetaId} - {owner.toBasicString()}";
Log.getLogger().info(err_msg);
} }
if (0 <= delta_count)
{
var equip_item = reserved_slot.getEquipEntity() as Item;
NullReferenceCheckHelper.throwIfNull(equip_item, () => $"equip_item is null !!! - {owner.toBasicString()}");
var item_attribute = equip_item.getEntityAttributeWithReadOnly<ItemAttributeBase>();
NullReferenceCheckHelper.throwIfNull(item_attribute, () => $"item_attribute is null !!! - {owner.toBasicString()}");
error_code = inven_accessor.tryEquipWithItemBase(reserved_key, equip_item);
if (error_code.isFail())
{
err_msg = $"Failed to onTryEquipWithEntityBase() !!! : {error_code.toBasicString()}, deltaCount:{delta_count}, itemGuid:{item_attribute.ItemGuid}, itemMetaId:{item_attribute.ItemMetaId} - {owner.toBasicString()}";
result.setFail(error_code, err_msg);
Log.getLogger().error(result.toBasicString());
}
else
{
err_msg = $"Successfully called onTryEquipWithEntityBase() !!! : deltaCount:{delta_count}, itemGuid:{item_attribute.ItemGuid}, itemMetaId:{item_attribute.ItemMetaId} - {owner.toBasicString()}";
Log.getLogger().info(err_msg);
} }
}
} break;
default:
{
err_msg = $"Invalid EntityType of reservedSlotOnInvens !!! : entityType:{entity_inven_type} - {owner.toBasicString()}";
result.setFail(ServerErrorCode.InventoryEntityTypeInvalid, err_msg);
Log.getLogger().error(result.toBasicString());
continue;
}
}
}
return result;
}
public (Result, Int16) getEquipableSlotOfEquipInven( MetaAssets.ItemMetaData itemMeta
, Dictionary<InvenEquipType, HashSet<Int16>> reservedSlotTypes )
{
var owner = getOwner();
NullReferenceCheckHelper.throwIfNull(owner, () => $"owner is null !!!");
ArgumentNullReferenceCheckHelper.throwIfNull(itemMeta, () => $"itemMeta is null !!! - {owner.toBasicString()}");
var result = new Result();
var err_msg = string.Empty;
var server_logic = GameServerApp.getServerLogic();
var inven_rule = server_logic.findRule<InventoryRule>();
if (null == inven_rule)
{
err_msg = $"Not found InventoryRule !!! : ItemMetaId:{itemMeta.ItemId} - {owner.toBasicString()}";
result.setFail(ServerErrorCode.InventoryRuleNotFound, err_msg);
Log.getLogger().error(result.toBasicString());
return (result, -1);
}
var equip_rule_bases = inven_rule.getEquipRuleBasesByItemLargeType(itemMeta.TypeLarge);
if (null == equip_rule_bases)
{
err_msg = $"Not found EquipRuleBase !!! : ItemMetaId:{itemMeta.ItemId} - {owner.toBasicString()}";
Log.getLogger().warn(err_msg);
return (result, -1);
}
foreach (var equip_rule_base in equip_rule_bases)
{
if (false == getEquipInvens().TryGetValue(equip_rule_base.InvenEquipType, out var found_equip_inven))
{
err_msg = $"Not found EquipInven !!! : invenEquipType:{equip_rule_base.InvenEquipType}, ItemMetaId:{itemMeta.ItemId} - {owner.toBasicString()}";
result.setFail(ServerErrorCode.EquipInvenNotFound, err_msg);
Log.getLogger().error(result.toBasicString());
return (result, -1);
}
NullReferenceCheckHelper.throwIfNull(found_equip_inven, () => $"found_equip_inven is null !!! - {owner.toBasicString()}");
if (false == reservedSlotTypes.TryGetValue(equip_rule_base.InvenEquipType, out var found_reserved_slot_type))
{
found_reserved_slot_type = new HashSet<Int16>();
reservedSlotTypes.TryAdd(equip_rule_base.InvenEquipType, found_reserved_slot_type);
}
var item_small_type = itemMeta.TypeSmall;
switch (equip_rule_base.InvenEquipType)
{
case InvenEquipType.Tool:
{
var tool_inven = getEquipInvens()[InvenEquipType.Tool] as ToolEquipInven;
NullReferenceCheckHelper.throwIfNull(tool_inven, () => $"tool_inven is null !!! - {owner.toBasicString()}");
var tool_equip_rule = equip_rule_base as ToolEquipRule;
NullReferenceCheckHelper.throwIfNull(tool_equip_rule, () => $"tool_equip_rule is null !!! - {owner.toBasicString()}");
foreach (var tool_slot_type in tool_equip_rule.UsableToolSlotTypes)
{
if (true == tool_inven.getHasSlotsWithEntityBases().TryGetValue(tool_slot_type, out var found_item))
{
var item_attibute = found_item.getEntityAttribute<ItemAttributeBase>();
NullReferenceCheckHelper.throwIfNull(item_attibute, () => $"item_attibute is null !!! - {owner.toBasicString()}");
if(0 < item_attibute.ItemStackCount)
{
continue;
}
}
Int16 slot_pos = (Int16)tool_slot_type;
if (true == found_reserved_slot_type.Contains(slot_pos))
{
continue;
}
found_reserved_slot_type.Add(slot_pos);
return (result, slot_pos);
}
}
break;
case InvenEquipType.Cloth:
{
var cloth_inven = getEquipInvens()[InvenEquipType.Cloth] as ClothEquipInven;
NullReferenceCheckHelper.throwIfNull(cloth_inven, () => $"cloth_inven is null !!! - {owner.toBasicString()}");
var cloth_equip_rule = equip_rule_base as ClothEquipRule;
NullReferenceCheckHelper.throwIfNull(cloth_equip_rule, () => $"cloth_equip_rule is null !!! - {owner.toBasicString()}");
if (false == cloth_equip_rule.m_slots_by_item_type.TryGetValue(item_small_type, out var found_cloth_slot_types))
{
err_msg = $"Not found ClothSlotType !!! : itemSmallType:{item_small_type}, ItemMetaId:{itemMeta.ItemId} - {owner.toBasicString()}";
result.setFail(ServerErrorCode.ClothEquipRuleClothSlotTypeNotFound, err_msg);
Log.getLogger().error(result.toBasicString());
return (result, -1);
}
foreach (var cloth_slot_type in found_cloth_slot_types)
{
if (true == cloth_inven.getHasSlotsWithEntityBases().TryGetValue(cloth_slot_type, out var found_item))
{
var item_attibute = found_item.getEntityAttribute<ItemAttributeBase>();
NullReferenceCheckHelper.throwIfNull(item_attibute, () => $"item_attibute is null !!! - {owner.toBasicString()}");
if (0 < item_attibute.ItemStackCount)
{
continue;
}
}
Int16 slot_pos = (Int16)cloth_slot_type;
if (true == found_reserved_slot_type.Contains(slot_pos))
{
continue;
}
found_reserved_slot_type.Add(slot_pos);
return (result, slot_pos);
}
}
break;
case InvenEquipType.Tattoo:
{
var tatoo_inven = getEquipInvens()[InvenEquipType.Tattoo] as TattooEquipInven;
NullReferenceCheckHelper.throwIfNull(tatoo_inven, () =>$"tatoo_inven is null !!! - {owner.toBasicString()}");
var tattoo_equip_rule = equip_rule_base as TattooEquipRule;
NullReferenceCheckHelper.throwIfNull(tattoo_equip_rule, () => $"tattoo_equip_rule is null !!! - {owner.toBasicString()}");
foreach (var tattoo_slot_type in tattoo_equip_rule.getUsableTattooSlotPos(owner.getEntityType()))
{
if (true == tatoo_inven.getHasSlotsWithEntityBases().TryGetValue(tattoo_slot_type, out var found_item))
{
var item_attibute = found_item.getEntityAttribute<ItemAttributeBase>();
NullReferenceCheckHelper.throwIfNull(item_attibute, () => $"item_attibute is null !!! - {owner.toBasicString()}");
if (0 < item_attibute.ItemStackCount)
{
continue;
}
}
Int16 slot_pos = (Int16)tattoo_slot_type;
if (true == found_reserved_slot_type.Contains(slot_pos))
{
continue;
}
found_reserved_slot_type.Add(slot_pos);
return (result, slot_pos);
}
}
break;
}
}
err_msg = $"Not found EquipInven !!! : ItemMetaId:{itemMeta.ItemId} - {owner.toBasicString()}";
result.setFail(ServerErrorCode.EquipInvenNotFound, err_msg);
return (result, -1);
}
public List<Item> getEquipItemAll()
{
var owner = getOwner();
NullReferenceCheckHelper.throwIfNull(owner, () => $"owner is null !!!");
var equip_items = new List<Item>();
var err_msg = string.Empty;
var target_inven_equip_types = EnumHelper.getValuesWithoutScopeAll<InvenEquipType>();
foreach (var inven_equip_type in target_inven_equip_types)
{
if (false == getEquipInvens().TryGetValue(inven_equip_type, out var found_equip_inven))
{
continue;
}
var equip_inven = found_equip_inven as IWithInventoryAccessor;
if (equip_inven == null)
{
err_msg = $"Failed to cast IWithInventoryAccessor !!! : invenEquipType:{found_equip_inven.getTypeName()} - {owner.toBasicString()}";
Log.getLogger().error(err_msg);
continue;
}
foreach (var entity_base in equip_inven.getHasItemBases())
{
var curr_item = entity_base as Item;
NullReferenceCheckHelper.throwIfNull(curr_item, () => $"curr_item is null !!! - {owner.toBasicString()}");
var item_attribute = curr_item.getEntityAttribute<ItemAttributeBase>();
NullReferenceCheckHelper.throwIfNull(item_attribute, () => $"item_attribute is null !!! - {owner.toBasicString()}");
if(0 >= item_attribute.ItemStackCount)
{
continue;
}
equip_items.Add(curr_item);
}
}
return equip_items;
}
public List<Item> getBagItemAll()
{
var owner = getOwner();
NullReferenceCheckHelper.throwIfNull(owner, () => $"owner is null !!!");
var bag_items = new List<Item>();
var err_msg = string.Empty;
var bag_inven = getBagInven();
NullReferenceCheckHelper.throwIfNull(bag_inven, () => $"bag_inven is null !!! - {owner.toBasicString()}");
foreach (var item_base in bag_inven.getHasItemBases())
{
var curr_item = item_base as Item;
NullReferenceCheckHelper.throwIfNull(curr_item, () => $"curr_item is null !!! - {owner.toBasicString()}");
var item_attribute = curr_item.getEntityAttribute<ItemAttributeBase>();
NullReferenceCheckHelper.throwIfNull(item_attribute, () => $"item_attribute is null !!! - {owner.toBasicString()}");
if (0 >= item_attribute.ItemStackCount)
{
continue;
}
bag_items.Add(curr_item);
}
return bag_items;
}
public bool hasItemByMetaId(META_ID itemMetaId, UInt32 toCheckCount = 1)
{
var owner = getOwner();
NullReferenceCheckHelper.throwIfNull(owner, () => $"owner is null !!!");
var err_msg = string.Empty;
var bag_inven = getBagInven();
NullReferenceCheckHelper.throwIfNull(bag_inven, () => $"bag_inven is null !!! - item meta id: {itemMetaId} / {owner.toBasicString()}");
return bag_inven.hasItemByMetaId(itemMetaId, toCheckCount);
}
public ConcurrentDictionary<META_ID, UInt16> getItemsCountByMetaIds(List<META_ID> itemMetaIds)
{
var owner = getOwner();
NullReferenceCheckHelper.throwIfNull(owner, () => $"owner is null !!!");
var err_msg = string.Empty;
var bag_inven = getBagInven();
NullReferenceCheckHelper.throwIfNull(bag_inven, () => $"bag_inven is null !!! - item meta ids: {itemMetaIds} / {owner.toBasicString()}");
return bag_inven.getItemsCountByMetaIds(itemMetaIds);
}
public (Result, InvenBagType, BagTabType) toBagTypeAndTabType(ItemMetaData itemMetaData)
{
var owner = getOwner();
NullReferenceCheckHelper.throwIfNull(owner, () => $"owner is null !!!");
ArgumentNullReferenceCheckHelper.throwIfNull(itemMetaData, () => $"metaData is null !!! - {owner.toBasicString()}");
var server_logic = GameServerApp.getServerLogic();
var inventory_rule = server_logic.findRule<InventoryRule>();
NullReferenceCheckHelper.throwIfNull(inventory_rule, () => $"inventory_rule is null !!! - {owner.toBasicString()}");
var result = new Result();
var err_msg = string.Empty;
var found_bag_rules = inventory_rule.getBagRulesByItemLargeType(itemMetaData.TypeLarge);
if ( null != found_bag_rules
&& found_bag_rules.Count > 0 )
{
foreach (var bag_rule in found_bag_rules)
{
var target_bag_type = bag_rule.InvenBagType;
var usable_bag_tab_type = target_bag_type.toUsableBagTabType().toNFTTabOffset(itemMetaData);
return (result, target_bag_type, usable_bag_tab_type);
}
}
err_msg = $"Not found InventoryRule !!! : ItemMetaId:{itemMetaData.ItemId} - {owner.toBasicString()}";
result.setFail(ServerErrorCode.InventoryRuleNotFound, err_msg);
Log.getLogger().error(result.toBasicString());
return (result, InvenBagType.None, BagTabType.None);
}
public global::Inventory? toBagInven4Client()
{
var owner = getOwner();
NullReferenceCheckHelper.throwIfNull(owner, () => $"owner is null !!!");
var server_logic = GameServerApp.getServerLogic();
var inventory_rule = server_logic.findRule<InventoryRule>();
NullReferenceCheckHelper.throwIfNull(inventory_rule, () => $"inventory_rule is null !!! - {owner.toBasicString()}");
var inventory_ui = new global::Inventory();
foreach(var item_base in m_bag_inven.getHasItemBases())
{
var item = item_base as Item;
NullReferenceCheckHelper.throwIfNull(item, () => $"item is null !!! - {owner.toBasicString()}");
var item_ui = item.toItemData4Client();
NullReferenceCheckHelper.throwIfNull(item_ui, () => $"item_ui is null !!! - {owner.toBasicString()}");
var item_meta = item.getItemMeta();
NullReferenceCheckHelper.throwIfNull(item_meta, () => $"item_meta is null !!! - {owner.toBasicString()}");
var found_bag_rules = inventory_rule.getBagRulesByItemLargeType(item_meta.TypeLarge);
if (found_bag_rules == null)
{
var err_msg = $"Not found InventoryRule !!! : ItemMetaId:{item_meta.ItemId} - {owner.toBasicString()}";
Log.getLogger().error(err_msg);
continue;
}
foreach (var bag_rule in found_bag_rules)
{
var target_bag_type = bag_rule.InvenBagType;
var usable_bag_tab_type = target_bag_type.toUsableBagTabType().toNFTTabOffset(item_meta);
switch(usable_bag_tab_type)
{
case BagTabType._0:
inventory_ui.EtcItem.Add(item_ui);
break;
case BagTabType._1:
inventory_ui.CostumeItem.Add(item_ui);
break;
case BagTabType._2:
inventory_ui.InteriorItem.Add(item_ui);
break;
case BagTabType._3:
inventory_ui.BeautyItem.Add(item_ui);
break;
case BagTabType._4:
inventory_ui.TattooItem.Add(item_ui);
break;
case BagTabType._5:
inventory_ui.EtcItemNft.Add(item_ui);
break;
case BagTabType._6:
inventory_ui.CostumeItemNft.Add(item_ui);
break;
case BagTabType._7:
inventory_ui.InteriorItemNft.Add(item_ui);
break;
case BagTabType._8:
inventory_ui.BeautyItemNft.Add(item_ui);
break;
case BagTabType._9:
inventory_ui.TattooItemNft.Add(item_ui);
break;
default:
var err_msg = $"Invalid BagTabType !!! : BagTabType:{usable_bag_tab_type}, {item.toBasicString()} - {owner.toBasicString()}";
Log.getLogger().error(err_msg);
break;
}
}
}
return inventory_ui;
}
public ClothInfo? toClothInven4Client()
{
var owner = getOwner();
NullReferenceCheckHelper.throwIfNull(owner, () => $"owner is null !!!");
var result = new Result();
var item_cloth_action = owner.getEntityAction<ItemClothAction>();
NullReferenceCheckHelper.throwIfNull(item_cloth_action, () => $"item_cloth_action is null !!! - {owner.toBasicString()}");
var inven_cloth = m_equip_invens[InvenEquipType.Cloth] as ClothEquipInven;
NullReferenceCheckHelper.throwIfNull(inven_cloth, () => $"inven_cloth is null !!! - {owner.toBasicString()}");
var cloth_info = new ClothInfo();
var cloth_slot_types = EnumHelper.getValues<ClothSlotType>();
foreach (var cloth_slot_type in cloth_slot_types)
{
var found_cloth = inven_cloth.getData().findEntityBaseInSlotType(cloth_slot_type) as Item;
if (null == found_cloth)
{
continue;
}
result = item_cloth_action.fillupCloth(cloth_slot_type, found_cloth, ref cloth_info);
if (result.isFail())
{
var err_msg = $"Failed to fillupCloth() !!! : {result.toBasicString()} - {owner.toBasicString()}";
Log.getLogger().error(err_msg);
}
}
return cloth_info;
}
public List<TattooSlotInfo> toTattooInven4Client()
{
var owner = getOwner();
NullReferenceCheckHelper.throwIfNull(owner, () => $"owner is null !!!");
var result = new Result();
var item_tattoo_action = owner.getEntityAction<ItemTattooAction>();
NullReferenceCheckHelper.throwIfNull(item_tattoo_action, () => $"item_tattoo_action is null !!! - {owner.toBasicString()}");
var tattoo_slots = new List<TattooSlotInfo>();
var inven_tattoo = m_equip_invens[InvenEquipType.Tattoo] as TattooEquipInven;
NullReferenceCheckHelper.throwIfNull(inven_tattoo, () => $"inven_tattoo is null !!! - {owner.toBasicString()}");
var custom_defined_ui_action = owner.getEntityAction<CustomDefinedUiAction>();
NullReferenceCheckHelper.throwIfNull(custom_defined_ui_action, () => $"custom_defined_ui_action is null !!! - {owner.toBasicString()}");
var tattoo_slot_types = InvenEquipType.Tattoo.toEquipableTattooSlotTypes(owner.getEntityType());
foreach (var tattoo_slot_type in tattoo_slot_types)
{
var tattoo_slot = new TattooSlotInfo();
tattoo_slot.ItemInfo = new();
if (false == custom_defined_ui_action.getTattooVisible(tattoo_slot_type, out var found_visible))
{
found_visible = true;
}
tattoo_slot.IsVisible = found_visible == true ? 1 : 0;
tattoo_slots.Add(tattoo_slot);
var found_tattoo = inven_tattoo.getData().findEntityBaseInSlotType(tattoo_slot_type) as Item;
if (null == found_tattoo)
{
continue;
}
item_tattoo_action.fillupTattooSlotInfo(tattoo_slot_type, found_tattoo, ref tattoo_slot);
}
return tattoo_slots;
}
public List<MyTattooSlotInfo> toTattooSimple4Client()
{
var owner = getOwner();
NullReferenceCheckHelper.throwIfNull(owner, () => $"owner is null !!!");
var result = new Result();
var item_tattoo_action = owner.getEntityAction<ItemTattooAction>();
NullReferenceCheckHelper.throwIfNull(item_tattoo_action, () => $"item_tattoo_action is null !!! - {owner.toBasicString()}");
var tattoo_simples = new List<MyTattooSlotInfo>();
var inven_tattoo = m_equip_invens[InvenEquipType.Tattoo] as TattooEquipInven;
NullReferenceCheckHelper.throwIfNull(inven_tattoo, () => $"inven_tattoo is null !!! - {owner.toBasicString()}");
var custom_defined_ui_action = owner.getEntityAction<CustomDefinedUiAction>();
NullReferenceCheckHelper.throwIfNull(custom_defined_ui_action, () => $"custom_defined_ui_action is null !!! - {owner.toBasicString()}");
var tattoo_slot_types = InvenEquipType.Tattoo.toEquipableTattooSlotTypes(owner.getEntityType());
foreach (var tattoo_slot_type in tattoo_slot_types)
{
var tattoo_simple = new MyTattooSlotInfo();
if(false == custom_defined_ui_action.getTattooVisible(tattoo_slot_type, out var found_visible))
{
found_visible = true;
}
tattoo_simple.IsVisible = found_visible == true ? 1 : 0;
tattoo_simples.Add(tattoo_simple);
var found_tattoo = inven_tattoo.getData().findEntityBaseInSlotType(tattoo_slot_type);
if (null == found_tattoo)
{
continue;
}
var item_attribute = found_tattoo.getEntityAttribute<ItemAttributeBase>();
NullReferenceCheckHelper.throwIfNull(item_attribute, () => $"ItemAttributeBase is null !!! - {owner.toBasicString()}");
tattoo_simple.ItemGuid = item_attribute.ItemGuid;
}
return tattoo_simples;
}
public List<string> toToolSlotInven4Client()
{
var owner = getOwner();
NullReferenceCheckHelper.throwIfNull(owner, () => $"owner is null !!!");
var tool_guids = new List<string>();
var item_tool_action = owner.getEntityAction<ItemToolAction>();
NullReferenceCheckHelper.throwIfNull(item_tool_action, () => $"item_tool_action is null !!! - {owner.toBasicString()}");
var inven_tool = m_equip_invens[InvenEquipType.Tool] as ToolEquipInven;
NullReferenceCheckHelper.throwIfNull(inven_tool, () => $"inven_tool is null !!! - {owner.toBasicString()}");
var cloth_info = new ClothInfo();
var tool_slot_types = EnumHelper.getValuesWithoutScopeAll<ToolSlotType>();
foreach (var tool_slot_type in tool_slot_types)
{
var found_tool = inven_tool.getData().findEntityBaseInSlotType(tool_slot_type) as Item;
if (null == found_tool)
{
tool_guids.Add(string.Empty);
}
else
{
var item_attribute = found_tool.getEntityAttribute<ItemAttributeBase>();
NullReferenceCheckHelper.throwIfNull(item_attribute, () => $"item_attribute is null !!! - {owner.toBasicString()}");
tool_guids.Add(item_attribute.ItemGuid);
}
}
return tool_guids;
}
public List<Int32> toSlotMaxCountOfBagAll4Client()
{
var owner = getOwner();
NullReferenceCheckHelper.throwIfNull(owner, () => $"owner is null !!!");
var slot_max_counts = new List<Int32>();
foreach (var each in m_bag_inven.getBagTabs())
{
var bag_tab = each.Value as BagTab;
NullReferenceCheckHelper.throwIfNull(bag_tab, () => $"bag_tab is null !!! - {owner.toBasicString()}");
slot_max_counts.Add(bag_tab.getSlotMaxCount());
}
return slot_max_counts;
}
public void writeLog()
{
var err_msg = string.Empty;
var owner = getOwner();
NullReferenceCheckHelper.throwIfNull(owner, () => $"owner is null !!!");
var bag_inven = getBagInven();
NullReferenceCheckHelper.throwIfNull(bag_inven, () => $"bag_inven is null !!! - {owner.toBasicString()}");
bag_inven.onWriteLog();
var target_inven_equip_types = EnumHelper.getValuesWithoutScopeAll<InvenEquipType>();
foreach (var inven_equip_type in target_inven_equip_types)
{
if (false == getEquipInvens().TryGetValue(inven_equip_type, out var found_equip_inven))
{
continue;
}
var equip_inven = found_equip_inven as IWithInventoryAccessor;
if (equip_inven == null)
{
err_msg = $"Failed to cast IWithInventoryAccessor !!! : invenEquipType:{found_equip_inven.getTypeName()} - {owner.toBasicString()}";
Log.getLogger().error(err_msg);
continue;
}
equip_inven.onWriteLog();
}
}
public BagInven getBagInven() => m_bag_inven;
public ConcurrentDictionary<InvenEquipType, EntityBase> getEquipInvens() => m_equip_invens;
public async Task<IDisposable> getAsyncLock() => await m_async_lock.LockAsync();
}
}