Files
2025-05-01 07:20:41 +09:00

579 lines
26 KiB
C#

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
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 ServerCore; using ServerBase;
using MetaAssets;
using Amazon.S3.Model;
using static ServerCommon.MetaHelper;
namespace GameServer
{
public class ItemAction : EntityActionBase
{
public ItemAction(ItemBase owner)
: base(owner)
{
}
public override async Task<Result> onInit()
{
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 alert_action = owner.getEntityAction<EntityAlertAction>();
NullReferenceCheckHelper.throwIfNull(alert_action, () => $"alert_action is null !!! - {owner.toBasicString()}, {parent.toBasicString()}");
alert_action.attachAlertFunction(EntityAlertTriggerType.ItemExpireWarningBefore, onAlertItemExpireWaringBefore);
alert_action.attachAlertFunction(EntityAlertTriggerType.ItemExpire, onAlertItemExpire);
return await Task.FromResult(result);
}
public override void onClear()
{
return;
}
public async Task<(Result, List<DynamoDbDocBase>, EntityAlertMethodType)> onAlertItemExpireWaringBefore(EntityAlertTriggerType triggerType)
{
var owner = getOwner() as Item;
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();
var doc_bases = new List<DynamoDbDocBase>();
Player? player = null;
if (parent is Player root_player)
{
player = root_player;
}
else if (parent is UgcNpc ugc_npc)
{
player = ugc_npc.onGetMasterEntity() as Player;
}
if (null == player)
{
err_msg = $"Failed to cast Player !!!, in ItemAction.onTick() - {owner.toBasicString()}, {parent.toBasicString()}";
result.setFail(ServerErrorCode.ClassTypeCastIsNull, err_msg);
Log.getLogger().error(result.toBasicString());
return (result, doc_bases, EntityAlertMethodType.None);
}
var system_mail_key = "Item_Expiring_Soon";
if (MetaData.Instance.SystemMailMetaData.TryGetValue(system_mail_key, out var systemMailMetaData) == false)
{
err_msg = $"Not found SystemMailMeta !!! : mailKey:{system_mail_key} - {owner.toBasicString()}, {parent.toBasicString()}";
result.setFail(ServerErrorCode.SystemMailMetaDataNotFound, err_msg);
Log.getLogger().error(err_msg);
return (result, doc_bases, EntityAlertMethodType.None);
}
var item_meta = owner.getItemMeta();
NullReferenceCheckHelper.throwIfNull(item_meta, () => $"item_meta is null !!! - {parent.toBasicString()}");
var meta_id = (META_ID)item_meta.ItemId;
var user_nickname = player.getUserNickname();
var contents_arguments = new List<string>();
contents_arguments.Add(item_meta.getStringKeyOfItemName());
(result, var new_mail_doc) = await Mail.createSystemMailWithMeta( player.getUserGuid(), user_nickname, systemMailMetaData, contents_arguments
, new List<ServerCommon.MailItem>(), GameConfigMeta.SystemMailStoragePeriod );
if (result.isFail())
{
err_msg = $"Failed to createSystemMailWithMeta() !!! : {result.toBasicString()} - {owner.toBasicString()}, {parent.toBasicString()}";
Log.getLogger().error(err_msg);
return (result, doc_bases, EntityAlertMethodType.None);
}
NullReferenceCheckHelper.throwIfNull(new_mail_doc, () => $"new_mail_doc is null !!! - {player.toBasicString()}");
doc_bases.Add(new_mail_doc);
var item_attribute_base = owner.getEntityAttribute<ItemAttributeBase>();
NullReferenceCheckHelper.throwIfNull(item_attribute_base, () => $"item_attribute_base is null !!! - {player.toBasicString()}");
var alert_record_attribute = owner.getEntityAttribute<EntityAlertRecordAttribute>();
NullReferenceCheckHelper.throwIfNull(alert_record_attribute, () => $"alert_record_attribute is null !!! - {player.toBasicString()}");
alert_record_attribute.AlertKey = EntityAlertRecordDoc.makeALERT_KEY(triggerType, meta_id);
alert_record_attribute.AlertedTime = DateTimeHelper.Current;
alert_record_attribute.OwnerEntityType = owner.onGetOwnerEntityType();
alert_record_attribute.OwnerGuid = item_attribute_base.ItemGuid;
alert_record_attribute.EntityAlertTriggerType = triggerType;
alert_record_attribute.MetaId = meta_id;
alert_record_attribute.modifiedEntityAttribute(true);
return (result, doc_bases, EntityAlertMethodType.Mail);
}
public async Task<(Result, List<DynamoDbDocBase>, EntityAlertMethodType)> onAlertItemExpire(EntityAlertTriggerType triggerType)
{
var owner = getOwner() as Item;
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();
var doc_bases = new List<DynamoDbDocBase>();
Player? player = null;
if (parent is Player root_player)
{
player = root_player;
}
else if (parent is UgcNpc ugc_npc)
{
player = ugc_npc.onGetMasterEntity() as Player;
}
if (null == player)
{
err_msg = $"Failed to cast Player !!!, in ItemAction.onTick() - {owner.toBasicString()}, {parent.toBasicString()}";
result.setFail(ServerErrorCode.ClassTypeCastIsNull, err_msg);
Log.getLogger().error(result.toBasicString());
return (result, doc_bases, EntityAlertMethodType.None);
}
var system_mail_key = "Item_Expired_Deleted";
if (MetaData.Instance.SystemMailMetaData.TryGetValue(system_mail_key, out var systemMailMetaData) == false)
{
err_msg = $"Not found SystemMailMeta !!! : mailKey:{system_mail_key} - {owner.toBasicString()}, {parent.toBasicString()}";
result.setFail(ServerErrorCode.SystemMailMetaDataNotFound, err_msg);
Log.getLogger().error(err_msg);
return (result, doc_bases, EntityAlertMethodType.None);
}
var item_meta = owner.getItemMeta();
NullReferenceCheckHelper.throwIfNull(item_meta, () => $"item_meta is null !!! - {parent.toBasicString()}");
var meta_id = (META_ID)item_meta.ItemId;
var user_nickname = player.getUserNickname();
var contents_arguments = new List<string>();
contents_arguments.Add(item_meta.getStringKeyOfItemName());
(result, var new_mail_doc) = await Mail.createSystemMailWithMeta(player.getUserGuid(), user_nickname, systemMailMetaData, contents_arguments
, new List<ServerCommon.MailItem>(), GameConfigMeta.SystemMailStoragePeriod);
if (result.isFail())
{
err_msg = $"Failed to createSystemMailWithMeta() !!! : {result.toBasicString()} - {owner.toBasicString()}, {parent.toBasicString()}";
Log.getLogger().error(err_msg);
return (result, doc_bases, EntityAlertMethodType.None);
}
NullReferenceCheckHelper.throwIfNull(new_mail_doc, () => $"new_mail_doc is null !!! - {player.toBasicString()}");
doc_bases.Add(new_mail_doc);
var item_attribute_base = owner.getEntityAttribute<ItemAttributeBase>();
NullReferenceCheckHelper.throwIfNull(item_attribute_base, () => $"item_attribute_base is null !!! - {player.toBasicString()}");
var alert_record_attribute = owner.getEntityAttribute<EntityAlertRecordAttribute>();
NullReferenceCheckHelper.throwIfNull(alert_record_attribute, () => $"alert_record_attribute is null !!! - {player.toBasicString()}");
alert_record_attribute.AlertKey = EntityAlertRecordDoc.makeALERT_KEY(triggerType, meta_id);
alert_record_attribute.AlertedTime = DateTimeHelper.Current;
alert_record_attribute.OwnerEntityType = owner.onGetOwnerEntityType();
alert_record_attribute.OwnerGuid = item_attribute_base.ItemGuid;
alert_record_attribute.EntityAlertTriggerType = triggerType;
alert_record_attribute.MetaId = meta_id;
alert_record_attribute.modifiedEntityAttribute(true);
return (result, doc_bases, EntityAlertMethodType.Mail);
}
public async Task<(Result, bool, List<Item>?)> tryLevelUpByTattoo()
{
var result = new Result();
var err_msg = string.Empty;
var owner = getOwner() as Item;
ArgumentNullException.ThrowIfNull(owner);
var parent = owner.getRootParent();
ArgumentNullException.ThrowIfNull(parent);
var inventory_action = parent.getEntityAction<InventoryActionBase>();
ArgumentNullException.ThrowIfNull(inventory_action);
inventory_action.getEquipInvens().TryGetValue(InvenEquipType.Tattoo, out var found_equip_inven);
var tattoo_inven = found_equip_inven as TattooEquipInven;
ArgumentNullException.ThrowIfNull(tattoo_inven);
var tattoo_inven_data = tattoo_inven.getData();
ArgumentNullException.ThrowIfNull(tattoo_inven_data);
var item_attribute = owner.getEntityAttribute<ItemAttributeBase>();
ArgumentNullException.ThrowIfNull(item_attribute);
bool is_equiped_tatoo_slot = false;
var tattoo_slot_type = (TattooSlotType)item_attribute.EquipedPos;
var found_using_tattoo_slot = tattoo_inven_data.findEntityBaseInSlotType(tattoo_slot_type) as Item;
if (null != found_using_tattoo_slot)
{
is_equiped_tatoo_slot = true;
}
var item_meta = owner.getItemMeta();
ArgumentNullException.ThrowIfNull(item_meta);
var curr_level = item_attribute.Level;
var next_level = item_attribute.Level + 1;
// 다음 레벨에 해당하는 메타 데이터를 참조 한다.
if (false == MetaData.Instance._ItemLevelEnchantMetaTable.TryGetValue(next_level, out var found_new_item_level_enchant_meta))
{
err_msg = $"Not found new ItemLevelEchantMeta !!!, current level is Max : newLevel:{next_level}, currLevel:{curr_level} - {owner.toBasicString()}, {parent.toBasicString()}";
result.setFail(ServerErrorCode.ItemLevelCurrentMax, err_msg);
return (result, false, null);
}
var found_new_enchant = found_new_item_level_enchant_meta?.GetConsumeItem(item_meta.Rarity);
if (found_new_enchant == null)
{
err_msg = $"Not found next Enchant Data !!! : itemRarity:{item_meta.Rarity} - {owner.toBasicString()}, {parent.toBasicString()}";
result.setFail(ServerErrorCode.ItemEnchantNotFoundInMeta, err_msg);
return (result, false, null);
}
(result, var deleted_items) = await inventory_action.tryDeleteItemByMetaId((META_ID)found_new_enchant.ConsumeItemID, (UInt16)found_new_enchant.ConsumeItemCount);
if(result.isFail())
{
return (result, false, null);
}
var is_success_enchant = false;
if (found_new_enchant.Probability >= RandomHelper.next(0, 10000) == true)
{
if(true == is_equiped_tatoo_slot)
{
var ability_action = parent.getEntityAction<AbilityAction>();
ArgumentNullException.ThrowIfNull(ability_action);
result = await ability_action.setAbilities(owner, (Int16)next_level, false);
if (result.isFail())
{
return (result, false, null);
}
await ability_action.setAbilities(owner, (Int16)(item_attribute.Level), true);
}
is_success_enchant = true;
item_attribute.Level = (UInt16)next_level;
item_attribute.modifiedEntityAttribute();
}
var updated_items = new List<Item>();
updated_items.AddRange(deleted_items);
updated_items.Add(owner);
return (result, is_success_enchant, updated_items);
}
public async Task<(Result, List<Item>?)> tryChangeAttributeByTattoo(Int16 targetSlotIndex)
{
var result = new Result();
var err_msg = string.Empty;
var owner = getOwner() as Item;
ArgumentNullException.ThrowIfNull(owner);
var parent = owner.getRootParent();
ArgumentNullException.ThrowIfNull(parent);
var inventory_action = parent.getEntityAction<InventoryActionBase>();
ArgumentNullException.ThrowIfNull(inventory_action);
inventory_action.getEquipInvens().TryGetValue(InvenEquipType.Tattoo, out var found_equip_inven);
var tattoo_inven = found_equip_inven as TattooEquipInven;
ArgumentNullException.ThrowIfNull(tattoo_inven);
var tattoo_inven_data = tattoo_inven.getData();
ArgumentNullException.ThrowIfNull(tattoo_inven_data);
var item_attribute = owner.getEntityAttribute<ItemAttributeBase>();
ArgumentNullException.ThrowIfNull(item_attribute);
bool is_equiped_tatoo_slot = false;
var tattoo_slot_type = (TattooSlotType)item_attribute.EquipedPos;
var found_using_tattoo_slot = tattoo_inven_data.findEntityBaseInSlotType(tattoo_slot_type) as Item;
if (null != found_using_tattoo_slot)
{
is_equiped_tatoo_slot = true;
}
var item_meta = owner.getItemMeta();
ArgumentNullException.ThrowIfNull(item_meta, $"item_meta is null !!! - {parent.toBasicString()}");
if (false == MetaData.Instance.Meta.AttributeEnchantMetaTable.AttributeEnchantMetaDataListbyRarity.TryGetValue(item_meta.Rarity, out var found_attribute_enchant_meta))
{
err_msg = $"Not found AttributeEnchantMeta !!! : itemRarity:{item_meta.Rarity} - {owner.toBasicString()}, {parent.toBasicString()}";
result.setFail(ServerErrorCode.ItemAttributeEnchantMetaNotFound, err_msg);
return (result, null);
}
if (false == MetaData.Instance._ItemLevelEnchantMetaTable.TryGetValue(item_attribute.Level, out var found_item_level_enchant_meta))
{
err_msg = $"Not found new ItemLevelEchantMeta !!! : newLevel:{item_attribute.Level} - {owner.toBasicString()}, {parent.toBasicString()}";
result.setFail(ServerErrorCode.ItemLevelEnchantNotFoundInMeta, err_msg);
return (result, null);
}
var found_enchant = found_item_level_enchant_meta.GetConsumeItem(item_meta.Rarity);
if (found_enchant == null)
{
err_msg = $"Not found new Enchant Data !!! : itemRarity:{item_meta.Rarity} - {owner.toBasicString()}, {parent.toBasicString()}";
result.setFail(ServerErrorCode.ItemEnchantNotFoundInMeta, err_msg);
return (result, null);
}
(result, var deleted_items) = await inventory_action.tryDeleteItemByMetaId((META_ID)found_attribute_enchant_meta.ItemID, (UInt16)found_attribute_enchant_meta.ItemCount);
if(result.isFail())
{
return (result, null);
}
if(0 == targetSlotIndex)
{
result = owner.fillupMakeAttributeIds(item_meta, out var selected_attribute_ids);
if(result.isFail())
{
return (result, null);
}
if(true == is_equiped_tatoo_slot)
{
var ability_action = parent.getEntityAction<AbilityAction>();
ArgumentNullException.ThrowIfNull(ability_action);
result = await ability_action.setAbilities(owner, (Int16)item_attribute.Level, true);
if(result.isFail())
{
return (result, null);
}
item_attribute.Attributes = selected_attribute_ids;
result = await ability_action.setAbilities(owner, (Int16)item_attribute.Level, false);
if (result.isFail())
{
return (result, null);
}
}
else
{
item_attribute.Attributes = selected_attribute_ids;
}
}
else
{
(result, var change_attribute_id) = await owner.fillupChangeAttributeIds();
if (result.isFail())
{
return (result, null);
}
if (true == is_equiped_tatoo_slot)
{
var ability_action = parent.getEntityAction<AbilityAction>();
ArgumentNullException.ThrowIfNull(ability_action);
var attriubte_id = item_attribute.Attributes[targetSlotIndex];
result = await ability_action.changeAbilities( owner
, new Dictionary<int, int>() { { targetSlotIndex, attriubte_id } }
, true );
if(result.isFail())
{
return (result, null);
}
item_attribute.Attributes[targetSlotIndex] = (UInt16)change_attribute_id;
result = await ability_action.changeAbilities( owner
, new Dictionary<int, int>() { { targetSlotIndex, change_attribute_id } }
, false );
if(result.isFail())
{
return (result, null);
}
}
else
{
item_attribute.Attributes[targetSlotIndex] = (UInt16)change_attribute_id;
}
}
item_attribute.modifiedEntityAttribute();
var updated_items = new List<Item>();
updated_items.AddRange(deleted_items);
updated_items.Add(owner);
return (result, updated_items);
}
public async Task<bool> isExpiredItem()
{
var owner = getOwner() as Item;
ArgumentNullException.ThrowIfNull(owner);
var parent = owner.getRootParent();
ArgumentNullException.ThrowIfNull(parent);
var item_meta = owner.getItemMeta();
NullReferenceCheckHelper.throwIfNull(item_meta, () => $"item_meta is null !!! - {parent.toBasicString()}");
if( EExpireType.DELAY != item_meta.ExpireType
|| 0 >= item_meta.ExpireTimeSec )
{
return false;
}
var item_attribute_base = owner.getEntityAttribute<ItemAttributeBase>();
NullReferenceCheckHelper.throwIfNull(item_attribute_base, () => $"item_attribute_base is null !!! - {parent.toBasicString()}");
(var result, DynamoDbDocBase? doc_base) = await item_attribute_base.toDocBase(false);
if(result.isFail())
{
var err_msg = $"Failed to toDocBase() !!!, in isExpiredItem() : {result.toBasicString()} - {owner.toBasicString()}, {parent.toBasicString()}";
Log.getLogger().error(err_msg);
return false;
}
NullReferenceCheckHelper.throwIfNull(doc_base, () => $"doc_base is null !!! - {owner.toBasicString()}, {parent.toBasicString()}");
var created_time = doc_base.getCreatedDateTime().ProcessedTime;
if (false == created_time.isValidTime())
{
var err_msg = $"Failed to isValidTime() !!!, in isExpiredItem() : {result.toBasicString()} - {owner.toBasicString()}, {parent.toBasicString()}";
Log.getLogger().error(err_msg);
return false;
}
var to_expire_date_time = created_time.AddSeconds(item_meta.ExpireTimeSec);
if(false == DateTimeHelper.hasTimeReached(to_expire_date_time))
{
await onAlertItemExpireBeforeHourTime(created_time, to_expire_date_time);
return false;
}
return true;
}
public async Task onAlertItemExpireBeforeHourTime(DateTime createdTime, DateTime toExpireTime)
{
var owner = getOwner() as Item;
NullReferenceCheckHelper.throwIfNull(owner, () => $"owner is null !!! - {toBasicString()}");
var parent = owner.getRootParent();
NullReferenceCheckHelper.throwIfNull(parent, () => $"parent is null !!! - {owner.toBasicString()}");
var past_time = MetaHelper.GameConfigMeta.ItemExpireAlertBeforeHourTime * -1;
var alert_time = toExpireTime.AddHours(past_time);
if (false == DateTimeHelper.hasTimeReached(alert_time))
{
return;
}
var entity_alert_auction = owner.getEntityAction<EntityAlertAction>();
NullReferenceCheckHelper.throwIfNull(entity_alert_auction, () => $"entity_alert_auction is null !!! - {owner.toBasicString()}, {parent.toBasicString()}");
await entity_alert_auction.onAlert(EntityAlertTriggerType.ItemExpireWarningBefore);
}
public override async Task onTick()
{
await Task.CompletedTask;
var owner = getOwner() as Item;
NullReferenceCheckHelper.throwIfNull(owner, () => $"owner is null !!! - {toBasicString()}");
var parent = owner.getRootParent();
NullReferenceCheckHelper.throwIfNull(parent, () => $"parent is null !!! - {owner.toBasicString()}");
var err_msg = string.Empty;
var result = new Result();
var item_attribute_base = owner.getEntityAttribute<ItemAttributeBase>();
NullReferenceCheckHelper.throwIfNull(item_attribute_base, () => $"item_attribute_base is null !!! - {owner.toBasicString()}");
Player? player = null;
if (parent is Player root_player)
{
player = root_player;
}
else if (parent is UgcNpc ugc_npc)
{
player = ugc_npc.onGetMasterEntity() as Player;
}
if (null == player)
{
err_msg = $"Failed to cast Player !!!, in ItemAction.onTick() - {owner.toBasicString()}, {parent.toBasicString()}";
result.setFail(ServerErrorCode.ClassTypeCastIsNull, err_msg);
Log.getLogger().error(result.toBasicString());
return;
}
var target_item_guid = item_attribute_base.ItemGuid;
var item_stack_count = item_attribute_base.ItemStackCount;
if (true == await isExpiredItem())
{
var entity_alert_auction = owner.getEntityAction<EntityAlertAction>();
NullReferenceCheckHelper.throwIfNull(entity_alert_auction, () => $"entity_alert_auction is null !!! - {owner.toBasicString()}, {parent.toBasicString()}");
await entity_alert_auction.onAlert(EntityAlertTriggerType.ItemExpire);
(result, _) = await PacketHandler.ItemDeletePacketHandler.tryDeleteItemWithTransactionRunner( player
, target_item_guid
, item_stack_count
, LogActionType.ItemDestoryByExpiration );
if (result.isFail())
{
err_msg = $"Failed to tryDeleteItemWithTransactionRunner() !!!, in onTick() : {result.toBasicString()} - {owner.toBasicString()}, {parent.toBasicString()}";
Log.getLogger().error(err_msg);
return;
}
var user_create_or_load_action = player.getEntityAction<UserCreateOrLoadAction>();
NullReferenceCheckHelper.throwIfNull(user_create_or_load_action, () => $"user_create_or_load_action is null !!! - {player.toBasicString()}");
ItemNotifyHelper.send_S2C_NTF_ITEM_DELETE(player, target_item_guid, item_stack_count);
}
}
}
}