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 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(); 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 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(); var err_msg = string.Empty; var target_inven_equip_types = EnumHelper.getValuesWithoutScopeAll(); 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(); 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( 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; 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(); 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?)> 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(); 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 }); } //========================================================================================= // 아이템을 가방에만 지급 하기 (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(); 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(); 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> 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(); 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(); 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)> 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)> 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 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(); NullReferenceCheckHelper.throwIfNull(item_doc_attrib, () => $"item_doc_attrib is null !!! - {owner.toBasicString()}"); var inven_rule = GameServerApp.getServerLogic().findRule(); 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(); 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(); 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)> 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(); 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(); 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(); NullReferenceCheckHelper.throwIfNull(item_attribute, () => $"item_attribute is null !!! - {owner.toBasicString()}"); var inven_rule = GameServerApp.getServerLogic().findRule(); 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(); 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(); 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(); 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?)> 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(); 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(); 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(); 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 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(); NullReferenceCheckHelper.throwIfNull(item_attribute, () => $"item_attribute is null !!! - {owner.toBasicString()}"); var ability_action = owner.getEntityAction(); 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(); 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 onMergeInventory(List 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(); 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(); 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(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(); 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(); 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> 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(); 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(); 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(); 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(); 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(); 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 getEquipItemAll() { var owner = getOwner(); NullReferenceCheckHelper.throwIfNull(owner, () => $"owner is null !!!"); var equip_items = new List(); var err_msg = string.Empty; var target_inven_equip_types = EnumHelper.getValuesWithoutScopeAll(); 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(); 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 getBagItemAll() { var owner = getOwner(); NullReferenceCheckHelper.throwIfNull(owner, () => $"owner is null !!!"); var bag_items = new List(); 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(); 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 getItemsCountByMetaIds(List 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(); 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(); 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(); 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(); 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 toTattooInven4Client() { var owner = getOwner(); NullReferenceCheckHelper.throwIfNull(owner, () => $"owner is null !!!"); var result = new Result(); var item_tattoo_action = owner.getEntityAction(); NullReferenceCheckHelper.throwIfNull(item_tattoo_action, () => $"item_tattoo_action is null !!! - {owner.toBasicString()}"); var tattoo_slots = new List(); 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(); 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 toTattooSimple4Client() { var owner = getOwner(); NullReferenceCheckHelper.throwIfNull(owner, () => $"owner is null !!!"); var result = new Result(); var item_tattoo_action = owner.getEntityAction(); NullReferenceCheckHelper.throwIfNull(item_tattoo_action, () => $"item_tattoo_action is null !!! - {owner.toBasicString()}"); var tattoo_simples = new List(); 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(); 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(); NullReferenceCheckHelper.throwIfNull(item_attribute, () => $"ItemAttributeBase is null !!! - {owner.toBasicString()}"); tattoo_simple.ItemGuid = item_attribute.ItemGuid; } return tattoo_simples; } public List toToolSlotInven4Client() { var owner = getOwner(); NullReferenceCheckHelper.throwIfNull(owner, () => $"owner is null !!!"); var tool_guids = new List(); var item_tool_action = owner.getEntityAction(); 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(); 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(); NullReferenceCheckHelper.throwIfNull(item_attribute, () => $"item_attribute is null !!! - {owner.toBasicString()}"); tool_guids.Add(item_attribute.ItemGuid); } } return tool_guids; } public List toSlotMaxCountOfBagAll4Client() { var owner = getOwner(); NullReferenceCheckHelper.throwIfNull(owner, () => $"owner is null !!!"); var slot_max_counts = new List(); 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(); 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 getEquipInvens() => m_equip_invens; public async Task getAsyncLock() => await m_async_lock.LockAsync(); } }