1174 lines
50 KiB
C#
1174 lines
50 KiB
C#
using System;
|
|
using System.Collections.Concurrent;
|
|
using System.Collections.Generic;
|
|
using System.Linq;
|
|
using System.Text;
|
|
using System.Threading.Tasks;
|
|
|
|
|
|
using Amazon.Runtime.Internal.Transform;
|
|
|
|
|
|
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;
|
|
using Amazon.S3.Model;
|
|
using MetaAssets;
|
|
using Nettention.Proud;
|
|
|
|
|
|
|
|
namespace GameServer
|
|
{
|
|
public class BagTab
|
|
{
|
|
private readonly BagTabType m_bag_tab_type;
|
|
|
|
private InventoryBase<ENTITY_GUID> m_owner;
|
|
|
|
private readonly string m_usable_inven_bag_name;
|
|
|
|
public UInt16 TakeInItemCount { get; private set; } = 0;
|
|
|
|
public BagTab(InventoryBase<ENTITY_GUID> owner, BagTabType bagTabType)
|
|
{
|
|
m_owner = owner;
|
|
m_bag_tab_type = bagTabType;
|
|
m_usable_inven_bag_name = bagTabType.toUsableInvenBagName();
|
|
}
|
|
|
|
public bool tryCheckTakableInItem(Int16 toIncCount, Int16 reservedCount = 0)
|
|
{
|
|
if( getSlotMaxCount() < (TakeInItemCount + reservedCount + toIncCount) )
|
|
{
|
|
return false;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
public bool tryTakableInItem()
|
|
{
|
|
if (getSlotMaxCount() <= TakeInItemCount)
|
|
{
|
|
return false;
|
|
}
|
|
|
|
TakeInItemCount += 1;
|
|
return true;
|
|
}
|
|
|
|
public bool tryCheckTakableOutItem(Int16 toDecCount, Int16 reservedCount = 0)
|
|
{
|
|
if ( 0 > (TakeInItemCount + reservedCount - toDecCount) )
|
|
{
|
|
return false;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
public bool tryTakableOutItem()
|
|
{
|
|
if (0 >= TakeInItemCount)
|
|
{
|
|
return false;
|
|
}
|
|
|
|
TakeInItemCount -= 1;
|
|
return true;
|
|
}
|
|
|
|
public bool onMergeTakeInItemCount(Int16 reservedCount)
|
|
{
|
|
var inventory_base = getInventoryBase();
|
|
NullReferenceCheckHelper.throwIfNull(inventory_base, () => $"inventory_base is null !!!");
|
|
var root_parent = inventory_base.getRootParent();
|
|
NullReferenceCheckHelper.throwIfNull(root_parent, () => $"root_parent is null !!! - {inventory_base.toBasicString()}");
|
|
|
|
var to_update_count = TakeInItemCount + reservedCount;
|
|
|
|
if (to_update_count < 0 || InventoryRuleHelper.getBagTapMaxSlotCountByBagTabType(root_parent.getEntityType(), getBagTabType()) < to_update_count)
|
|
{
|
|
return false;
|
|
}
|
|
|
|
TakeInItemCount = (UInt16)to_update_count;
|
|
return true;
|
|
}
|
|
|
|
public BagTabType getBagTabType() => m_bag_tab_type;
|
|
|
|
public Int32 getSlotMaxCount()
|
|
{
|
|
var inventory_base = getInventoryBase();
|
|
NullReferenceCheckHelper.throwIfNull(inventory_base, () => $"inventory_base is null !!!");
|
|
var root_parent = inventory_base.getRootParent();
|
|
NullReferenceCheckHelper.throwIfNull(root_parent, () => $"root_parent is null !!! - {inventory_base.toBasicString()}");
|
|
|
|
return InventoryRuleHelper.getBagTapMaxSlotCountByBagTabType(root_parent.getEntityType(), getBagTabType());
|
|
}
|
|
|
|
public void resetItemCount()
|
|
{
|
|
TakeInItemCount = 0;
|
|
}
|
|
|
|
public InventoryBase<ENTITY_GUID> getInventoryBase() => m_owner;
|
|
|
|
public string toBasicString()
|
|
{
|
|
return $"{this.getTypeName()}, UsableInvenBagName:{m_usable_inven_bag_name}";
|
|
}
|
|
}
|
|
|
|
public class BagInven : InventoryBase<ITEM_GUID>
|
|
{
|
|
// BagTabType에 장착되어 아이템 있는 개수
|
|
private ConcurrentDictionary<BagTabType, BagTab> m_bag_tab_take_in_counts = new();
|
|
|
|
public BagInven(EntityBase owner)
|
|
: base(EntityType.BagInven, owner)
|
|
{
|
|
base.onInitSlots(ServerCommon.Constant.BagSlotDefaultMaxCount);
|
|
}
|
|
|
|
public override async Task<Result> onInit()
|
|
{
|
|
await Task.CompletedTask;
|
|
|
|
var parent = getDirectParent();
|
|
NullReferenceCheckHelper.throwIfNull(parent, () => $"parent is null !!!");
|
|
|
|
var result = new Result();
|
|
|
|
var bag_tab_types = EnumHelper.getValuesWithoutScopeAll<BagTabType>();
|
|
foreach (var bag_tab in bag_tab_types)
|
|
{
|
|
m_bag_tab_take_in_counts.TryAdd(bag_tab, new BagTab(this, bag_tab));
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
public void resetItemCountInTabs()
|
|
{
|
|
foreach(var each in m_bag_tab_take_in_counts)
|
|
{
|
|
var bag_tab = each.Value;
|
|
|
|
bag_tab.resetItemCount();
|
|
}
|
|
}
|
|
|
|
public async Task<(Result, List<Item>)> tryTakableInItemBase(META_ID toTakeInItemMetaId, UInt16 toTakeInCount)
|
|
{
|
|
await Task.CompletedTask;
|
|
|
|
var parent = getDirectParent();
|
|
NullReferenceCheckHelper.throwIfNull(parent, () => $"parent is null !!!");
|
|
var bag_item_data = getData();
|
|
NullReferenceCheckHelper.throwIfNull(bag_item_data, () => $"bag_item_data is null !!! - {parent.toBasicString()}");
|
|
|
|
var result = new Result();
|
|
var reserved_items = new List<Item>();
|
|
|
|
var err_msg = string.Empty;
|
|
|
|
// 1. 아이템 메타 정보를 얻는다.
|
|
if (false == MetaData.Instance._ItemTable.TryGetValue((int)toTakeInItemMetaId, out var itemMetaData))
|
|
{
|
|
err_msg = $"Not found ItemMeta !!! : itemMetaId:{toTakeInItemMetaId} - {parent.toBasicString()}";
|
|
result.setFail(ServerErrorCode.ItemMetaDataNotFound, err_msg);
|
|
Log.getLogger().error(result.toBasicString());
|
|
|
|
return (result, reserved_items);
|
|
}
|
|
|
|
if(true == itemMetaData.IsUiOnly)
|
|
{
|
|
err_msg = $"Returned without creation Item !!!, because UI-only item : itemMetaId:{toTakeInItemMetaId} - {parent.toBasicString()}";
|
|
Log.getLogger().debug(err_msg);
|
|
|
|
return (result, reserved_items);
|
|
}
|
|
|
|
// 2. 동일한 종류의 ItemAttributeBase 목록과 보유 개수를 얻는다.
|
|
(result, var target_item_attributes, var item_has_count) = findItemAttributeBaseAllByMetaId(toTakeInItemMetaId, toTakeInCount);
|
|
if (result.isFail())
|
|
{
|
|
return (result, reserved_items);
|
|
}
|
|
|
|
// 3. 해당 아이템의 최대 Stack 개수를 초과했는지 체크 한다.
|
|
var item_total_count = item_has_count + toTakeInCount;
|
|
if (item_total_count > itemMetaData.MaxCount)
|
|
{
|
|
err_msg = $"Item max count exceed !!! : totalCount:{item_total_count} <= maxCount:{itemMetaData.MaxCount}, itemMetaId:{toTakeInItemMetaId}, {parent.toBasicString()}";
|
|
result.setFail(ServerErrorCode.ItemMaxCountExceed, err_msg);
|
|
Log.getLogger().error(result.toBasicString());
|
|
|
|
return (result, reserved_items);
|
|
}
|
|
|
|
// 4. 아이템 Stack 개수가 큰 순서로 정렬 시킨다.
|
|
var remain_count = toTakeInCount;
|
|
target_item_attributes.OrderBy(x => { return x.ItemStackCount; });
|
|
|
|
// 5. 동일한 종류의 아이템에 최대 Stack 개수이내로 추가 한다.
|
|
foreach (var item_attribute in target_item_attributes)
|
|
{
|
|
if (remain_count <= 0)
|
|
{
|
|
break;
|
|
}
|
|
|
|
var max_count = itemMetaData.StackMaxCount;
|
|
|
|
var to_modify_item = item_attribute.getOwner() as Item;
|
|
NullReferenceCheckHelper.throwIfNull(to_modify_item, () => $"to_modify_item is null !!! - {parent.toBasicString()}");
|
|
|
|
var to_modify_item_attribute = to_modify_item.getEntityAttribute<ItemAttributeBase>();
|
|
NullReferenceCheckHelper.throwIfNull(to_modify_item_attribute, () => $"to_modify_item_attribute is null !!! - {parent.toBasicString()}");
|
|
|
|
var has_count = to_modify_item_attribute.ItemStackCount;
|
|
if (has_count >= itemMetaData.StackMaxCount)
|
|
{
|
|
continue;
|
|
}
|
|
|
|
var to_add_count = 0;
|
|
|
|
// 남은 아이템 개수도 추가 가능한지 체크 한다 !!!
|
|
if (has_count + remain_count > max_count)
|
|
{
|
|
to_add_count = max_count - has_count;
|
|
}
|
|
else
|
|
{
|
|
to_add_count = remain_count;
|
|
}
|
|
|
|
to_modify_item_attribute.ItemStackCount += (ushort)to_add_count;
|
|
remain_count -= (ushort)to_add_count;
|
|
|
|
to_modify_item_attribute.modifiedEntityAttribute();
|
|
|
|
reserved_items.Add(to_modify_item);
|
|
}
|
|
|
|
// 6. 추가해야 하는 아이템 개수가 있다면
|
|
if(0 < remain_count)
|
|
{
|
|
// 6.1. 아이템 생성하고 추가 한다.
|
|
var server_logic = GameServerApp.getServerLogic();
|
|
NullReferenceCheckHelper.throwIfNull(server_logic, () => $"server_logic is null !!! - {parent.toBasicString()}");
|
|
var inventory_rule = server_logic.findRule<InventoryRule>();
|
|
NullReferenceCheckHelper.throwIfNull(inventory_rule, () => $"inventory_rule is null !!! - {parent.toBasicString()}");
|
|
|
|
var inventory_action = parent.getEntityAction<InventoryActionBase>();
|
|
NullReferenceCheckHelper.throwIfNull(inventory_action, () => $"inventory_action is null !!! - {parent.toBasicString()}");
|
|
|
|
var to_create_count = remain_count;
|
|
while (to_create_count > 0)
|
|
{
|
|
var new_item = inventory_action.onAllocItem();
|
|
if(null == new_item)
|
|
{
|
|
err_msg = $"Failed to alloc Item by ItemMeta !!! : itemMetaId:{toTakeInItemMetaId}, count:{to_create_count} - {parent.toBasicString()}";
|
|
result.setFail(ServerErrorCode.ItemAllocFailed, err_msg);
|
|
|
|
return (result, reserved_items);
|
|
}
|
|
result = await new_item.createByItemMeta(toTakeInItemMetaId, to_create_count);
|
|
if (result.isFail())
|
|
{
|
|
err_msg = $"Failed to create Item !!! : {result.toBasicString()}";
|
|
Log.getLogger().error(err_msg);
|
|
|
|
return (result, reserved_items);
|
|
}
|
|
|
|
var item_item_meta = new_item.getItemMeta();
|
|
NullReferenceCheckHelper.throwIfNull(item_item_meta, () => $"item_item_meta is null !!! - {parent.toBasicString()}");
|
|
|
|
var found_bag_rules = inventory_rule.getBagRulesByItemLargeType(item_item_meta.TypeLarge);
|
|
NullReferenceCheckHelper.throwIfNull(found_bag_rules, () => $"found_bag_rules is null !!! - {parent.toBasicString()}");
|
|
|
|
foreach (var bag_rule in found_bag_rules)
|
|
{
|
|
result = tryIncItemCountInBagTap(new_item, bag_rule);
|
|
if (result.isFail())
|
|
{
|
|
err_msg = $"Failed to tryIncItemCountInBagTap() !!! : {result.toBasicString()} - {new_item.toBasicString()}, {parent.toBasicString()}";
|
|
Log.getLogger().error(err_msg);
|
|
|
|
return (result, reserved_items);
|
|
}
|
|
break;
|
|
}
|
|
|
|
to_create_count -= new_item.getItemStackCount();
|
|
|
|
var item_attribute = new_item.getEntityAttribute<ItemAttributeBase>();
|
|
NullReferenceCheckHelper.throwIfNull(item_attribute, () => $"item_attribute is null !!! - {new_item.toBasicString()}, {parent.toBasicString()}");
|
|
|
|
result = onTryTakeInEntityBase(item_attribute.ItemGuid, new_item);
|
|
if (result.isFail())
|
|
{
|
|
return (result, reserved_items);
|
|
}
|
|
|
|
reserved_items.Add(new_item);
|
|
}
|
|
}
|
|
|
|
return (result, reserved_items);
|
|
}
|
|
|
|
public async Task<(Result, Item?)> tryTakableInItemBase(ItemDoc doc, bool isWriteToDb = false)
|
|
{
|
|
var result = new Result();
|
|
var err_msg = string.Empty;
|
|
|
|
var parent = getDirectParent();
|
|
NullReferenceCheckHelper.throwIfNull(parent, () => $"parent is null !!!");
|
|
|
|
var server_logic = GameServerApp.getServerLogic();
|
|
NullReferenceCheckHelper.throwIfNull(server_logic, () => $"server_logic is null !!! - {parent.toBasicString()}");
|
|
var inventory_rule = server_logic.findRule<InventoryRule>();
|
|
NullReferenceCheckHelper.throwIfNull(inventory_rule, () => $"item_attribute is null !!! - {parent.toBasicString()}");
|
|
|
|
var item_doc_attrib = doc.getAttrib<ItemAttrib>();
|
|
NullReferenceCheckHelper.throwIfNull(item_doc_attrib, () => $"item_doc_attrib is null !!! - {parent.toBasicString()}");
|
|
|
|
var found_duplicated_item = findEntityBase(item_doc_attrib.ItemGuid);
|
|
if(null != found_duplicated_item)
|
|
{
|
|
err_msg = $"Found duplicated Item from ItemDoc !!! : duplicatedItem:{found_duplicated_item.toBasicString()} - {doc.toBasicString()}, {parent.toBasicString()}";
|
|
result.setFail(ServerErrorCode.ItemDocLoadDuplicatedItem, err_msg);
|
|
Log.getLogger().error(result.toBasicString());
|
|
|
|
return (result, null);
|
|
}
|
|
|
|
var inventory_action = parent.getEntityAction<InventoryActionBase>();
|
|
NullReferenceCheckHelper.throwIfNull(inventory_action, () => $"inventory_action is null !!! - {parent.toBasicString()}");
|
|
|
|
var new_item = inventory_action.onAllocItem();
|
|
if (null == new_item)
|
|
{
|
|
err_msg = $"Failed to alloc Item by ItemDoc !!! : itemGuid:{item_doc_attrib.ItemGuid}, itemMetaId:{item_doc_attrib.ItemMetaId} - {parent.toBasicString()}";
|
|
result.setFail(ServerErrorCode.ItemAllocFailed, err_msg);
|
|
|
|
return (result, null);
|
|
}
|
|
result = await new_item.createByItemDoc(doc, isWriteToDb);
|
|
if (result.isFail())
|
|
{
|
|
err_msg = $"Failed to create Item !!! : {result.toBasicString()}";
|
|
Log.getLogger().error(err_msg);
|
|
|
|
return (result, null);
|
|
}
|
|
|
|
var item_item_meta = new_item.getItemMeta();
|
|
NullReferenceCheckHelper.throwIfNull(item_item_meta, () => $"item_item_meta is null !!! - {parent.toBasicString()}");
|
|
|
|
var found_bag_rules = inventory_rule.getBagRulesByItemLargeType(item_item_meta.TypeLarge);
|
|
NullReferenceCheckHelper.throwIfNull(found_bag_rules, () => $"found_bag_rules is null !!! - {parent.toBasicString()}");
|
|
|
|
foreach (var bag_rule in found_bag_rules)
|
|
{
|
|
result = tryIncItemCountInBagTap(new_item, bag_rule);
|
|
if (result.isFail())
|
|
{
|
|
err_msg = $"Failed to tryIncItemCountInBagTap() !!! : {result.toBasicString()} - {new_item.toBasicString()}, {parent.toBasicString()}";
|
|
Log.getLogger().error(err_msg);
|
|
return (result, null);
|
|
}
|
|
break;
|
|
}
|
|
|
|
var item_attribute = new_item.getEntityAttribute<ItemAttributeBase>();
|
|
NullReferenceCheckHelper.throwIfNull(item_attribute, () => $"item_attribute is null !!! - {parent.toBasicString()}");
|
|
|
|
result = onTryTakeInEntityBase(item_attribute.ItemGuid, new_item);
|
|
if(result.isFail())
|
|
{
|
|
return (result, null);
|
|
}
|
|
|
|
return (result, new_item);
|
|
}
|
|
|
|
private Result tryIncItemCountInBagTap(Item toTakeInItem, BagRule bagRule)
|
|
{
|
|
var parent = getDirectParent();
|
|
NullReferenceCheckHelper.throwIfNull(parent, () => $"parent is null !!!");
|
|
NullReferenceCheckHelper.throwIfNull(toTakeInItem, () => $"toTakeInItem is null !!! - {parent.toBasicString()}");
|
|
NullReferenceCheckHelper.throwIfNull(bagRule, () => $"bagRule is null !!! - {parent.toBasicString()}");
|
|
|
|
var item_meta = toTakeInItem.getItemMeta();
|
|
NullReferenceCheckHelper.throwIfNull(item_meta, () => $"item_meta is null !!! - {parent.toBasicString()}");
|
|
|
|
var result = new Result();
|
|
var err_msg = string.Empty;
|
|
|
|
var target_bag_type = bagRule.InvenBagType;
|
|
var usable_bag_tab_type = target_bag_type.toUsableBagTabType().toNFTTabOffset(item_meta);
|
|
|
|
// Transaction 활성화 상태일 경우
|
|
var transaction_runner = parent.findTransactionRunner(TransactionIdType.PrivateContents);
|
|
if (null != transaction_runner)
|
|
{
|
|
if (true == m_bag_tab_take_in_counts.TryGetValue(usable_bag_tab_type, out var found_tab))
|
|
{
|
|
// 슬롯에 예약된 아이템 개수까지 확인하여 보관 가능 여부를 체크 한다.
|
|
var reserved_count = 0;
|
|
var found_reserved_slot = transaction_runner.findReservedSlot(parent, getEntityType(), usable_bag_tab_type.convertEnumToEnumTypeAndValueString());
|
|
if (null != found_reserved_slot)
|
|
{
|
|
reserved_count += found_reserved_slot.getReservedCount();
|
|
}
|
|
|
|
var inc_slot_count = 1;
|
|
if (false == found_tab.tryCheckTakableInItem((Int16)inc_slot_count, (Int16)reserved_count))
|
|
{
|
|
err_msg = $"Failed to tryCheckTakableInItem() !!!, Bag is reserved item full : incSlotCount:{inc_slot_count}, reservedSlotCount:{reserved_count}"
|
|
+ $" - {toTakeInItem.toBasicString()}, usableInvenBagName:{usable_bag_tab_type.toUsableInvenBagName()}, {parent.toBasicString()}";
|
|
result.setFail(ServerErrorCode.BagIsReservedItemFull, err_msg);
|
|
Log.getLogger().error(result.toBasicString());
|
|
|
|
return result;
|
|
}
|
|
}
|
|
|
|
// 예약 슬롯 개수를 증가 시킨다.
|
|
result = transaction_runner.tryIncReserveSlotCount(parent, getEntityType(), usable_bag_tab_type.convertEnumToEnumTypeAndValueString());
|
|
if (result.isFail())
|
|
{
|
|
return result;
|
|
}
|
|
|
|
err_msg = $"Succss tryEquipToReserveSlot() : targetSlotType:{usable_bag_tab_type.convertEnumToEnumTypeAndValueString()} - {toBasicString()}, {parent.toBasicString()}";
|
|
Log.getLogger().info(err_msg);
|
|
return result;
|
|
}
|
|
|
|
if (false == m_bag_tab_take_in_counts.TryGetValue(usable_bag_tab_type, out var found_bag_tab))
|
|
{
|
|
found_bag_tab = new BagTab(this, usable_bag_tab_type);
|
|
m_bag_tab_take_in_counts.TryAdd(usable_bag_tab_type, found_bag_tab);
|
|
}
|
|
|
|
if(false == found_bag_tab.tryTakableInItem())
|
|
{
|
|
err_msg = $"Failed to tryTakableInItem() !!!, Bag is item full - {toTakeInItem.toBasicString()}, {found_bag_tab.toBasicString()}, {parent.toBasicString()}";
|
|
result.setFail(ServerErrorCode.BagIsReservedItemFull, err_msg);
|
|
Log.getLogger().error(result.toBasicString());
|
|
|
|
return result;
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
public async Task<(Result, List<Item>)> tryTakableOutItemBase(META_ID toUnequipMetaId, UInt32 toTakeOutCount = UInt32.MaxValue)
|
|
{
|
|
var parent = getDirectParent();
|
|
NullReferenceCheckHelper.throwIfNull(parent, () => $"parent is null !!!");
|
|
|
|
var result = new Result();
|
|
var err_msg = string.Empty;
|
|
|
|
var reserved_items = new List<Item>();
|
|
|
|
// 1. 아이템 메타 정보를 얻는다.
|
|
if (false == MetaData.Instance._ItemTable.TryGetValue((int)toUnequipMetaId, out var itemMetaData))
|
|
{
|
|
err_msg = $"Not found ItemMeta !!! : itemMetaId:{toUnequipMetaId} - {parent.toBasicString()}";
|
|
result.setFail(ServerErrorCode.ItemMetaDataNotFound, err_msg);
|
|
Log.getLogger().error(result.toBasicString());
|
|
return (result, reserved_items);
|
|
}
|
|
|
|
// 2. 동일한 종류의 ItemAttributeBase 목록과 보유 개수를 얻는다.
|
|
(result, var target_item_attributes, var item_has_count) = findItemAttributeBaseAllByMetaId(toUnequipMetaId, toTakeOutCount);
|
|
if (result.isFail())
|
|
{
|
|
return (result, reserved_items);
|
|
}
|
|
|
|
// 3. 보유하고 있는 아이템 개수를 체크 한다.
|
|
if ( UInt32.MaxValue != toTakeOutCount
|
|
&& item_has_count < toTakeOutCount)
|
|
{
|
|
err_msg = $"Not enough Item Count !!! : totalCount:{item_has_count} > reqCount:{toTakeOutCount}, itemMetaId:{toUnequipMetaId}, {parent.toBasicString()}";
|
|
result.setFail(ServerErrorCode.ItemCountNotEnough, err_msg);
|
|
Log.getLogger().error(result.toBasicString());
|
|
return (result, reserved_items);
|
|
}
|
|
|
|
var to_take_out_items = new Dictionary<ItemAttributeBase, UInt16>();
|
|
|
|
var remain_count = toTakeOutCount;
|
|
if (UInt32.MaxValue == toTakeOutCount)
|
|
{
|
|
remain_count = (UInt16)target_item_attributes.Sum(x => x.ItemStackCount);
|
|
}
|
|
// 4. 아이템 개수가 많은 순서로 정렬 시킨다.
|
|
target_item_attributes.OrderBy(x => (x.ItemStackCount));
|
|
|
|
// 5. 동일한 종류의 아이템에서 Takeout할 아이템 개수만큼 차감한다.
|
|
foreach (var item_attribute in target_item_attributes)
|
|
{
|
|
if (remain_count <= 0)
|
|
{
|
|
break;
|
|
}
|
|
|
|
var to_modify_item = item_attribute.getOwner() as Item;
|
|
NullReferenceCheckHelper.throwIfNull(to_modify_item, () => $"to_modify_item is null !!! - {parent.toBasicString()}");
|
|
|
|
var to_modify_item_attribute = to_modify_item.getEntityAttribute<ItemAttributeBase>();
|
|
NullReferenceCheckHelper.throwIfNull(to_modify_item_attribute, () => $"to_modify_item_attribute is null !!! - {parent.toBasicString()}");
|
|
|
|
UInt16 to_take_out_count = 0;
|
|
|
|
// 5.1. Takeout 가능 개수를 계산 한다.
|
|
if (item_attribute.ItemStackCount > remain_count)
|
|
{
|
|
to_take_out_count = (UInt16)remain_count;
|
|
remain_count = 0;
|
|
}
|
|
else
|
|
{
|
|
to_take_out_count = item_attribute.ItemStackCount;
|
|
remain_count -= to_take_out_count;
|
|
}
|
|
|
|
to_take_out_items.Add(item_attribute, to_take_out_count);
|
|
}
|
|
|
|
foreach(var each in to_take_out_items)
|
|
{
|
|
var item_attribute = each.Key as ItemAttributeBase;
|
|
NullReferenceCheckHelper.throwIfNull(item_attribute, () => $"item_attribute is null !!! - {parent.toBasicString()}");
|
|
|
|
(result, var take_out_item) = await tryTakableOutItemBase(item_attribute.ItemGuid, each.Value);
|
|
if(result.isFail())
|
|
{
|
|
return (result, reserved_items);
|
|
}
|
|
NullReferenceCheckHelper.throwIfNull(take_out_item, () => $"take_out_item is null !!! - {parent.toBasicString()}");
|
|
|
|
reserved_items.Add(take_out_item);
|
|
}
|
|
|
|
return (result, reserved_items);
|
|
}
|
|
|
|
public async Task<(Result, Item?)> tryTakableOutItemBase(ITEM_GUID toUnequipItemGuid, UInt16 toTakeOutCount)
|
|
{
|
|
var parent = getDirectParent();
|
|
NullReferenceCheckHelper.throwIfNull(parent, () => $"parent is null !!!");
|
|
|
|
var result = new Result();
|
|
var err_msg = string.Empty;
|
|
|
|
var server_logic = GameServerApp.getServerLogic();
|
|
NullReferenceCheckHelper.throwIfNull(server_logic, () => $"server_logic is null !!! - {parent.toBasicString()}");
|
|
var inventory_rule = server_logic.findRule<InventoryRule>();
|
|
NullReferenceCheckHelper.throwIfNull(inventory_rule, () => $"inventory_rule is null !!! - {parent.toBasicString()}");
|
|
|
|
// 1. 가방에서 아이템을 찾는다.
|
|
var found_item = findEntityBase(toUnequipItemGuid) as Item;
|
|
if(null == found_item)
|
|
{
|
|
err_msg = $"Not found Item !!!, findEntityBase() : itemGuid:{toUnequipItemGuid} - {parent.toBasicString()}";
|
|
result.setFail(ServerErrorCode.ItemNotFound, err_msg);
|
|
Log.getLogger().error(result.toBasicString());
|
|
|
|
return (result, null);
|
|
}
|
|
|
|
var found_item_meta = found_item.getItemMeta();
|
|
NullReferenceCheckHelper.throwIfNull(found_item_meta, () => $"found_item_meta is null !!! - {parent.toBasicString()}");
|
|
|
|
// 2. 아이템 개수의 차감 가능 여부를 체크하고
|
|
// 아이템 개수 차감 => 아이템 삭제 => BagTab 개수 차감을 처리 한다.
|
|
var item_attribute = found_item.getEntityAttribute<ItemAttributeBase>();
|
|
NullReferenceCheckHelper.throwIfNull(item_attribute, () => $"item_attribute is null !!! - {parent.toBasicString()}");
|
|
|
|
if (item_attribute.ItemStackCount < toTakeOutCount)
|
|
{
|
|
err_msg = $"Not enough ItemStackCount !!! : hasCount:{item_attribute.ItemStackCount} > reqCount:{toTakeOutCount}, itemGuid:{toUnequipItemGuid} - {parent.toBasicString()}";
|
|
result.setFail(ServerErrorCode.ItemStackCountNotEnough, err_msg);
|
|
Log.getLogger().error(result.toBasicString());
|
|
|
|
return (result, null);
|
|
}
|
|
else if(item_attribute.ItemStackCount > toTakeOutCount)
|
|
{
|
|
item_attribute.ItemStackCount -= toTakeOutCount;
|
|
item_attribute.modifiedEntityAttribute();
|
|
}
|
|
else
|
|
{
|
|
result = onTryTakeOutEnityBase(toUnequipItemGuid, out _);
|
|
if(result.isFail())
|
|
{
|
|
return (result, null);
|
|
}
|
|
|
|
item_attribute.ItemStackCount = 0;
|
|
item_attribute.deleteEntityAttribute();
|
|
}
|
|
|
|
if (0 == item_attribute.ItemStackCount)
|
|
{
|
|
var found_bag_rules = inventory_rule.getBagRulesByItemLargeType(found_item_meta.TypeLarge);
|
|
NullReferenceCheckHelper.throwIfNull(found_bag_rules, () => $"found_bag_rules is null !!! - {parent.toBasicString()}");
|
|
|
|
foreach (var bag_rule in found_bag_rules)
|
|
{
|
|
result = tryDecItemCountInBagTap(found_item, bag_rule);
|
|
if (result.isFail())
|
|
{
|
|
err_msg = $"Failed to tryDecItemCountInBagTap() !!! : {result.toBasicString()} - {found_item.toBasicString()}, {parent.toBasicString()}";
|
|
Log.getLogger().error(err_msg);
|
|
return (result, null);
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
|
|
return await Task.FromResult((result, found_item));
|
|
}
|
|
|
|
private Result tryDecItemCountInBagTap(Item toRemoveItem, BagRule bagRule)
|
|
{
|
|
var parent = getDirectParent();
|
|
NullReferenceCheckHelper.throwIfNull(parent, () => $"parent is null !!!");
|
|
NullReferenceCheckHelper.throwIfNull(toRemoveItem, () => $"toRemoveItem is null !!! - {parent.toBasicString()}");
|
|
NullReferenceCheckHelper.throwIfNull(bagRule, () => $"bagRule is null !!! - {parent.toBasicString()}");
|
|
|
|
var item_meta = toRemoveItem.getItemMeta();
|
|
NullReferenceCheckHelper.throwIfNull(item_meta, () => $"item_meta is null !!! - {parent.toBasicString()}");
|
|
|
|
var result = new Result();
|
|
var err_msg = string.Empty;
|
|
|
|
var target_bag_type = bagRule.InvenBagType;
|
|
var usable_bag_tab_type = target_bag_type.toUsableBagTabType().toNFTTabOffset(item_meta);
|
|
|
|
|
|
// Transaction 활성화 상태일 경우
|
|
var transaction_runner = parent.findTransactionRunner(TransactionIdType.PrivateContents);
|
|
if (null != transaction_runner)
|
|
{
|
|
if (true == m_bag_tab_take_in_counts.TryGetValue(usable_bag_tab_type, out var found_tab))
|
|
{
|
|
// 슬롯에 예약된 아이템 개수까지 확인하여 차감 가능 여부를 체크 한다.
|
|
var reserved_count = 0;
|
|
var found_reserved_slot = transaction_runner.findReservedSlot(parent, getEntityType(), usable_bag_tab_type.convertEnumToEnumTypeAndValueString());
|
|
if (null != found_reserved_slot)
|
|
{
|
|
reserved_count += found_reserved_slot.getReservedCount();
|
|
}
|
|
|
|
var dec_slot_count = 1;
|
|
if (false == found_tab.tryCheckTakableOutItem((Int16)dec_slot_count, (Int16)reserved_count))
|
|
{
|
|
err_msg = $"Failed to tryCheckTakableOutItem() !!!, Bag is reserved item empty - decSlotCount:{dec_slot_count}, reservedSlotCount:{reserved_count} - {toRemoveItem.toBasicString()}, {parent.toBasicString()}";
|
|
result.setFail(ServerErrorCode.BagIsReservedItemEmpty, err_msg);
|
|
Log.getLogger().error(result.toBasicString());
|
|
|
|
return result;
|
|
}
|
|
}
|
|
|
|
// 예약 슬롯 개수를 감소 시킨다.
|
|
result = transaction_runner.tryDecToReserveSlotCount(parent, getEntityType(), usable_bag_tab_type.convertEnumToEnumTypeAndValueString());
|
|
if (result.isFail())
|
|
{
|
|
return result;
|
|
}
|
|
|
|
err_msg = $"Success tryUnequipToReserveSlot() : targetSlotType:{usable_bag_tab_type.convertEnumToEnumTypeAndValueString()} - {toBasicString()}, {parent.toBasicString()}";
|
|
Log.getLogger().info(err_msg);
|
|
return result;
|
|
}
|
|
|
|
if (false == m_bag_tab_take_in_counts.TryGetValue(usable_bag_tab_type, out var found_bag_tab))
|
|
{
|
|
found_bag_tab = new BagTab(this, usable_bag_tab_type);
|
|
m_bag_tab_take_in_counts.TryAdd(usable_bag_tab_type, found_bag_tab);
|
|
}
|
|
|
|
if (false == found_bag_tab.tryTakableOutItem())
|
|
{
|
|
err_msg = $"Failed to tryTakableOutItem() !!!, Bag is item empty - {toRemoveItem.toBasicString()}, {found_bag_tab.toBasicString()}, {parent.toBasicString()}";
|
|
result.setFail(ServerErrorCode.BagIsItemEmpty, err_msg);
|
|
Log.getLogger().error(result.toBasicString());
|
|
return result;
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
public async Task<(Result, Item?, Item?)> tryDivideItem(ITEM_GUID toDivideitemGuid, UInt16 toDivideCount = 1)
|
|
{
|
|
var result = new Result();
|
|
var err_msg = string.Empty;
|
|
|
|
var parent = getDirectParent();
|
|
NullReferenceCheckHelper.throwIfNull(parent, () => $"parent is null !!!");
|
|
|
|
(result, var divided_item) = await tryTakableOutItemBase(toDivideitemGuid, toDivideCount);
|
|
if (result.isFail())
|
|
{
|
|
return (result, null, null);
|
|
}
|
|
NullReferenceCheckHelper.throwIfNull(divided_item, () => $"take_out_item is null !!! - {parent.toBasicString()}");
|
|
|
|
var divided_item_meta = divided_item.getItemMeta();
|
|
NullReferenceCheckHelper.throwIfNull(divided_item_meta, () => $"server_logic is null !!! - {parent.toBasicString()}");
|
|
|
|
(result, var new_item) = await tryCreateItemByMeta((META_ID)divided_item_meta.ItemId, toDivideCount);
|
|
if (result.isFail())
|
|
{
|
|
return (result, null, null);
|
|
}
|
|
NullReferenceCheckHelper.throwIfNull(divided_item, () => $"take_out_item is null !!! - {parent.toBasicString()}");
|
|
|
|
return (result, divided_item, new_item);
|
|
}
|
|
|
|
async Task<(Result, Item?)> tryCreateItemByMeta(META_ID toCreateItemMetaId, UInt16 toCreateCount)
|
|
{
|
|
var result = new Result();
|
|
var err_msg = string.Empty;
|
|
|
|
var parent = getDirectParent();
|
|
NullReferenceCheckHelper.throwIfNull(parent, () => $"parent is null !!!");
|
|
|
|
var inventory_action = parent.getEntityAction<InventoryActionBase>();
|
|
NullReferenceCheckHelper.throwIfNull(inventory_action, () => $"inventory_action is null !!! - {parent.toBasicString()}");
|
|
|
|
var new_item = inventory_action.onAllocItem();
|
|
if (null == new_item)
|
|
{
|
|
err_msg = $"Failed to alloc Item by ItemMeta !!! : itemMetaId:{toCreateItemMetaId}, count:{toCreateCount} - {parent.toBasicString()}";
|
|
result.setFail(ServerErrorCode.ItemAllocFailed, err_msg);
|
|
|
|
return (result, null);
|
|
}
|
|
result = await new_item.createByItemMeta(toCreateItemMetaId, toCreateCount);
|
|
if (result.isFail())
|
|
{
|
|
err_msg = $"Failed to create Item !!! : {result.toBasicString()}";
|
|
Log.getLogger().error(err_msg);
|
|
|
|
return (result, null);
|
|
}
|
|
|
|
return (result, new_item);
|
|
}
|
|
|
|
public Result onMergeTakeInItem(Item takeInItem)
|
|
{
|
|
var parent = getDirectParent();
|
|
NullReferenceCheckHelper.throwIfNull(parent, () => $"parent is null !!!");
|
|
NullReferenceCheckHelper.throwIfNull(takeInItem, () => $"takeInItem is null !!! - {parent.toBasicString()}");
|
|
|
|
var result = new Result();
|
|
var err_msg = string.Empty;
|
|
|
|
var item_attribute = takeInItem.getEntityAttribute<ItemAttributeBase>();
|
|
NullReferenceCheckHelper.throwIfNull(item_attribute, () => $"item_attribute is null !!! - {parent.toBasicString()}");
|
|
|
|
var error_code = getData().onTryEquipWithEntityBase(item_attribute.ItemGuid, takeInItem);
|
|
if (error_code.isFail())
|
|
{
|
|
err_msg = $"Failed to onTryEquipWithEntityBase() !!! : {error_code.toBasicString()} - {parent.toBasicString()}";
|
|
result.setFail(error_code, err_msg);
|
|
Log.getLogger().error(result.toBasicString());
|
|
|
|
return result;
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
public Result onMergeTakeOutItem(Item takeOutItem)
|
|
{
|
|
var parent = getDirectParent();
|
|
NullReferenceCheckHelper.throwIfNull(parent, () => $"parent is null !!!");
|
|
NullReferenceCheckHelper.throwIfNull(takeOutItem, () => $"takeOutItem is null !!! - {parent.toBasicString()}");
|
|
|
|
var result = new Result();
|
|
var err_msg = string.Empty;
|
|
|
|
var item_attribute = takeOutItem.getEntityAttribute<ItemAttributeBase>();
|
|
NullReferenceCheckHelper.throwIfNull(item_attribute, () => $"item_attribute is null !!! - {parent.toBasicString()}");
|
|
|
|
var error_code = getData().onTryUnequipWithEntityBase(item_attribute.ItemGuid, out var unequiped_item);
|
|
if (error_code.isFail())
|
|
{
|
|
err_msg = $"Failed to onTryUnequipWithEntityBase() !!! : {error_code.toBasicString()} - {parent.toBasicString()}";
|
|
result.setFail(error_code, err_msg);
|
|
Log.getLogger().error(result.toBasicString());
|
|
|
|
return result;
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
public bool hasItemByMetaId(META_ID itemMetaId, UInt32 toCheckCount = 1)
|
|
{
|
|
var parent = getDirectParent();
|
|
NullReferenceCheckHelper.throwIfNull(parent, () => $"parent is null !!!");
|
|
|
|
var found_items = new List<Item>();
|
|
|
|
var has_items = getHasItemBases();
|
|
NullReferenceCheckHelper.throwIfNull(has_items, () => $"has_items is null !!! - {parent.toBasicString()}");
|
|
|
|
var found_item_count = 0;
|
|
|
|
foreach (var item_base in has_items)
|
|
{
|
|
var item = item_base as Item;
|
|
NullReferenceCheckHelper.throwIfNull(item, () => $"item is null !!! - {parent.toBasicString()}");
|
|
|
|
var item_meta = item.getItemMeta();
|
|
NullReferenceCheckHelper.throwIfNull(item_meta, () => $"item_meta is null !!! - {parent.toBasicString()}");
|
|
|
|
if (item_meta.ItemId != itemMetaId)
|
|
{
|
|
continue;
|
|
}
|
|
|
|
found_item_count += item.getItemStackCount();
|
|
|
|
if (toCheckCount <= found_item_count)
|
|
{
|
|
return true;
|
|
}
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
public ConcurrentDictionary<META_ID, UInt16> getItemsCountByMetaIds(List<META_ID> itemMetaIds)
|
|
{
|
|
var parent = getDirectParent();
|
|
NullReferenceCheckHelper.throwIfNull(parent, () => $"parent is null !!!");
|
|
|
|
var found_items = new ConcurrentDictionary<META_ID, UInt16>();
|
|
|
|
var has_items = getHasItemBases();
|
|
NullReferenceCheckHelper.throwIfNull(has_items, () => $"has_items is null !!! - {parent.toBasicString()}");
|
|
|
|
foreach (var item_base in has_items)
|
|
{
|
|
var item = item_base as Item;
|
|
NullReferenceCheckHelper.throwIfNull(item, () => $"item is null !!! - {parent.toBasicString()}");
|
|
|
|
var item_meta_id = item.getItemMetaId();
|
|
UInt16 item_stack_count = item.getItemStackCount();
|
|
|
|
foreach (var find_item_meta_id in itemMetaIds)
|
|
{
|
|
if(find_item_meta_id == item_meta_id)
|
|
{
|
|
if(found_items.TryGetValue(item_meta_id, out UInt16 item_count) == false)
|
|
{
|
|
found_items.TryAdd(item_meta_id, item_stack_count);
|
|
break;
|
|
}
|
|
|
|
found_items[item_meta_id] = (ushort)(item_count + item_stack_count);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
return found_items;
|
|
}
|
|
|
|
public Int32 getItemStackCountAllByMetaId(META_ID itemMetaId)
|
|
{
|
|
var parent = getDirectParent();
|
|
NullReferenceCheckHelper.throwIfNull(parent, () => $"parent is null !!!");
|
|
|
|
var item_stack_count_all = 0;
|
|
|
|
var has_items = getHasItemBases();
|
|
NullReferenceCheckHelper.throwIfNull(has_items, () => $"has_items is null !!! - {parent.toBasicString()}");
|
|
|
|
foreach (var item in has_items)
|
|
{
|
|
var item_meta = item.getItemMeta();
|
|
NullReferenceCheckHelper.throwIfNull(item_meta, () => $"item_meta is null !!! - {parent.toBasicString()}");
|
|
|
|
if (item_meta.ItemId != itemMetaId)
|
|
{
|
|
continue;
|
|
}
|
|
|
|
item_stack_count_all += item.getItemStackCount();
|
|
}
|
|
|
|
return item_stack_count_all;
|
|
}
|
|
|
|
public Int32 getItemCountAllByMetaId(META_ID itemMetaId)
|
|
{
|
|
var parent = getDirectParent();
|
|
NullReferenceCheckHelper.throwIfNull(parent, () => $"parent is null !!!");
|
|
|
|
var item_count_all = 0;
|
|
|
|
var has_items = getHasItemBases();
|
|
NullReferenceCheckHelper.throwIfNull(has_items, () => $"has_items is null !!! - {parent.toBasicString()}");
|
|
|
|
foreach (var item in has_items)
|
|
{
|
|
var item_meta = item.getItemMeta();
|
|
NullReferenceCheckHelper.throwIfNull(item_meta, () => $"item_meta is null !!! - {parent.toBasicString()}");
|
|
|
|
if (item_meta.ItemId != itemMetaId)
|
|
{
|
|
continue;
|
|
}
|
|
|
|
item_count_all += 1;
|
|
}
|
|
|
|
return item_count_all;
|
|
}
|
|
|
|
public List<Item> getItemAllByMetaId(META_ID itemMetaId)
|
|
{
|
|
var parent = getDirectParent();
|
|
NullReferenceCheckHelper.throwIfNull(parent, () => $"parent is null !!!");
|
|
|
|
var found_items = new List<Item>();
|
|
|
|
var has_items = getHasItemBases();
|
|
NullReferenceCheckHelper.throwIfNull(has_items, () => $"has_items is null !!! - {parent.toBasicString()}");
|
|
|
|
foreach (var item_base in has_items)
|
|
{
|
|
var item = item_base as Item;
|
|
NullReferenceCheckHelper.throwIfNull(item, () => $"item is null !!! - {parent.toBasicString()}");
|
|
|
|
var item_meta = item.getItemMeta();
|
|
NullReferenceCheckHelper.throwIfNull(item_meta, () => $"item_meta is null !!! - {parent.toBasicString()}");
|
|
|
|
if (item_meta.ItemId != itemMetaId)
|
|
{
|
|
continue;
|
|
}
|
|
|
|
found_items.Add(item);
|
|
}
|
|
|
|
return found_items;
|
|
}
|
|
|
|
public override void onWriteLog()
|
|
{
|
|
var parent = getDirectParent();
|
|
NullReferenceCheckHelper.throwIfNull(parent, () => $"parent is null !!!");
|
|
|
|
var err_msg = string.Empty;
|
|
|
|
var total_count = 0;
|
|
var total_max_count = 0;
|
|
|
|
foreach(var each in m_bag_tab_take_in_counts)
|
|
{
|
|
var bag_tab_type = each.Key;
|
|
var bag_tab = each.Value;
|
|
|
|
err_msg = $"BagTabType:{bag_tab_type}, TakeInCount:{bag_tab.TakeInItemCount}, SlotMaxCount:{bag_tab.getSlotMaxCount()}";
|
|
Log.getLogger().info(err_msg);
|
|
|
|
total_count += bag_tab.TakeInItemCount;
|
|
total_max_count += bag_tab.getSlotMaxCount();
|
|
}
|
|
|
|
var has_items = getHasItemBases();
|
|
NullReferenceCheckHelper.throwIfNull(has_items, () => $"has_items is null !!! - {parent.toBasicString()}");
|
|
|
|
err_msg = $"BagTab TotalTakeInCount:{total_count}, TotalSlotMaxCount:{total_max_count}, TotalItemCount:{has_items.Count}";
|
|
Log.getLogger().info(err_msg);
|
|
}
|
|
|
|
public async Task<Result> tryCheckTakableInBagInven(Dictionary<META_ID, Int16> toCheckTakableInItemCounts)
|
|
{
|
|
var parent = getDirectParent();
|
|
NullReferenceCheckHelper.throwIfNull(parent, () => $"parent is null !!!");
|
|
NullReferenceCheckHelper.throwIfNull(toCheckTakableInItemCounts, () => $"toCheckTakableInItemCounts is null !!! - {parent.toBasicString()}");
|
|
|
|
var result = new Result();
|
|
var err_msg = string.Empty;
|
|
|
|
bool is_found_value = (false == toCheckTakableInItemCounts.Any()) || toCheckTakableInItemCounts.Values.All(value => value <= 0);
|
|
if(true == is_found_value)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
var server_logic = GameServerApp.getServerLogic();
|
|
NullReferenceCheckHelper.throwIfNull(server_logic, () => $"server_logic is null !!! - {parent.toBasicString()}");
|
|
var inventory_rule = server_logic.findRule<InventoryRule>();
|
|
NullReferenceCheckHelper.throwIfNull(inventory_rule, () => $"inventory_rule is null !!! - {parent.toBasicString()}");
|
|
|
|
var is_found_target_bag_tab = false;
|
|
|
|
foreach (var each in toCheckTakableInItemCounts)
|
|
{
|
|
var item_meta_id = each.Key;
|
|
var item_count = each.Value;
|
|
|
|
// 1. 아이템 메타 정보를 얻는다.
|
|
if (false == MetaData.Instance._ItemTable.TryGetValue((Int32)item_meta_id, out var found_item_meta))
|
|
{
|
|
err_msg = $"Not found Item Meta !!! : itemMetaId:{item_meta_id} - {parent.toBasicString()}";
|
|
result.setFail(ServerErrorCode.ItemMetaDataNotFound, err_msg);
|
|
Log.getLogger().error(result.toBasicString());
|
|
|
|
return result;
|
|
}
|
|
|
|
// 2. 동일한 종류의 ItemAttributeBase 목록과 보유 개수를 얻는다.
|
|
(result, var target_item_attributes, var item_has_count) = findItemAttributeBaseAllByMetaId(item_meta_id, (ushort)item_count);
|
|
if (result.isFail())
|
|
{
|
|
return result;
|
|
}
|
|
|
|
var remain_count = item_count;
|
|
target_item_attributes.OrderByDescending(x => { return x.ItemStackCount; });
|
|
|
|
// 3. 동일한 종류의 아이템에 최대 Stack 개수이내로 추가 한다.
|
|
foreach (var item_attribute in target_item_attributes)
|
|
{
|
|
if (remain_count <= 0)
|
|
{
|
|
break;
|
|
}
|
|
|
|
var max_count = found_item_meta.StackMaxCount;
|
|
|
|
var to_modify_item = item_attribute.getOwner() as Item;
|
|
NullReferenceCheckHelper.throwIfNull(to_modify_item, () => $"to_modify_item is null !!! - {parent.toBasicString()}");
|
|
|
|
var to_modify_item_attribute = to_modify_item.getEntityAttribute<ItemAttributeBase>();
|
|
NullReferenceCheckHelper.throwIfNull(to_modify_item_attribute, () => $"to_modify_item_attribute is null !!! - {parent.toBasicString()}");
|
|
|
|
var has_count = to_modify_item_attribute.ItemStackCount;
|
|
if (has_count >= found_item_meta.StackMaxCount)
|
|
{
|
|
continue;
|
|
}
|
|
|
|
var to_add_count = 0;
|
|
if (has_count + remain_count > max_count)
|
|
{
|
|
to_add_count = max_count - has_count;
|
|
}
|
|
else
|
|
{
|
|
to_add_count = remain_count;
|
|
}
|
|
|
|
remain_count -= (short)to_add_count;
|
|
|
|
is_found_target_bag_tab = true;
|
|
}
|
|
|
|
if (0 < remain_count)
|
|
{
|
|
is_found_target_bag_tab = false;
|
|
|
|
var to_inc_slot_count = remain_count / found_item_meta.StackMaxCount;
|
|
to_inc_slot_count += ((remain_count % found_item_meta.StackMaxCount) > 0 ? 1 : 0);
|
|
|
|
var found_bag_rules = inventory_rule.getBagRulesByItemLargeType(found_item_meta.TypeLarge);
|
|
NullReferenceCheckHelper.throwIfNull(found_bag_rules, () => $"found_bag_rules is null !!! - {parent.toBasicString()}");
|
|
|
|
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(found_item_meta);
|
|
|
|
if (true == m_bag_tab_take_in_counts.TryGetValue(usable_bag_tab_type, out var found_tab))
|
|
{
|
|
is_found_target_bag_tab = true;
|
|
|
|
// 슬롯에 예약된 아이템 개수까지 확인하여 보관 가능 여부를 체크 한다.
|
|
var reserved_count = 0;
|
|
|
|
// Transaction 활성화 상태일 경우
|
|
var transaction_runner = parent.findTransactionRunner(TransactionIdType.PrivateContents);
|
|
if (null != transaction_runner)
|
|
{
|
|
var found_reserved_slot = transaction_runner.findReservedSlot(parent, getEntityType(), usable_bag_tab_type.convertEnumToEnumTypeAndValueString());
|
|
if (null != found_reserved_slot)
|
|
{
|
|
reserved_count += found_reserved_slot.getReservedCount();
|
|
}
|
|
}
|
|
|
|
if (false == found_tab.tryCheckTakableInItem((Int16)to_inc_slot_count, (Int16)reserved_count))
|
|
{
|
|
err_msg = $"Failed to tryCheckTakableInItem() !!!, Bag is reserved item full : incSlotCount:{remain_count}, reservedSlotCount:{reserved_count}"
|
|
+ $" - itemMetaId:{item_meta_id}, usableInvenBagName:{usable_bag_tab_type.toUsableInvenBagName()}, {parent.toBasicString()}";
|
|
result.setFail(ServerErrorCode.BagIsReservedItemFull, err_msg);
|
|
Log.getLogger().error(result.toBasicString());
|
|
|
|
return result;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
if(false == is_found_target_bag_tab)
|
|
{
|
|
err_msg = $"Not found target BagTab !!! - {parent.toBasicString()}";
|
|
result.setFail(ServerErrorCode.BagTabTypeNotFound, err_msg);
|
|
Log.getLogger().error(result.toBasicString());
|
|
|
|
return result;
|
|
}
|
|
|
|
return await Task.FromResult(result);
|
|
}
|
|
|
|
public ConcurrentDictionary<BagTabType, BagTab> getBagTabs() => m_bag_tab_take_in_counts;
|
|
|
|
public override string toSummaryString()
|
|
{
|
|
return $"{this.getTypeName()}, {getData().toBasicString()}";
|
|
}
|
|
}
|
|
}
|