Files
caliverse_server/GameServer/Entity/Effect/Farming/Action/FarmingEffectAction.cs
2025-05-01 07:20:41 +09:00

1070 lines
49 KiB
C#

using ServerCore;
using ServerBase;
using ServerCommon;
using ServerCommon.BusinessLogDomain;
using ANCHOR_META_GUID = System.String;
using OWNER_GUID = System.String;
using META_ID = System.UInt32;
using GUARD_KEY = System.String;
namespace GameServer;
public class FarmingEffectAction : EntityActionBase
{
private AnchorInfo? m_anchor_info_nullable = null;
private ServerCommon.BusinessLogDomain.FarmingLogInfo m_farming_log_info = new();
private ServerCommon.BusinessLogDomain.FarmingRewardLogInfo m_farming_reward_log_info = new();
public FarmingEffectAction(FarmingEffect farmingEffect)
: base(farmingEffect)
{
}
public override async Task<Result> onInit()
{
await Task.CompletedTask;
var result = new Result();
return result;
}
public override void onClear()
{
return;
}
public async Task<Result> tryStartEffect( ANCHOR_META_GUID anchorMetaGuid, Int16 farmingActionTryCount)
{
var owner = getOwner() as FarmingEffect;
NullReferenceCheckHelper.throwIfNull(owner, () => $"owner is null !!!");
var root_parent = owner.getRootParent();
var curr_map = owner.getCurrMap();
var result = new Result();
var err_msg = string.Empty;
var found_anchor_info = curr_map.findAnchorInfo(anchorMetaGuid);
if(null == found_anchor_info)
{
err_msg = $"Not found Anchor for Farming !!! : toFindAnchorMetaGuid:{anchorMetaGuid} - {curr_map.toBasicString()}, {root_parent.toBasicString()}";
result.setFail(ServerErrorCode.FarmingAnchorNotFound, err_msg);
Log.getLogger().error(result.toBasicString());
return result;
}
result = await isAbleToFarming(anchorMetaGuid, farmingActionTryCount);
if(result.isFail())
{
return result;
}
Player? master = null;
if(root_parent is Player player)
{
master = player;
}
else if(root_parent is UgcNpc ugc_npc)
{
master = ugc_npc.onGetMasterEntity() as Player;
}
if (null == master)
{
err_msg = $"Not found Master !!! : masterGuid:{root_parent.getMasterGuid()} - {owner.toBasicString()}";
result.setFail(ServerErrorCode.MasterNotFound, err_msg);
Log.getLogger().error(result.toBasicString());
return result;
}
// FarmingStateType.StandBy 상태 체크 한다.
var farming_effect_attribute = owner.getEntityAttribute<FarmingEffectAttribute>();
NullReferenceCheckHelper.throwIfNull(farming_effect_attribute, () => $"farming_effect_attribute is null !!! - {owner.toBasicString()}");
if (FarmingStateType.StandBy != farming_effect_attribute.FarmingState)
{
err_msg = $"Not state StandBy Farming !!! : masterGuid:{root_parent.getMasterGuid()} - {owner.toBasicString()}";
result.setFail(ServerErrorCode.FarmingStandByNotState, err_msg);
Log.getLogger().error(result.toBasicString());
return result;
}
// 결제할 Owner를 설정하고, 요구 수수료를 차감 한다.
(result, var payer, var req_currency_type, var req_use_fee_price) = await calculateReqUseFeePrice(anchorMetaGuid, farmingActionTryCount);
if (result.isFail())
{
return result;
}
NullReferenceCheckHelper.throwIfNull(payer, () => $"payer is null !!! - {owner.toBasicString()}");
var money_action = payer.getEntityAction<MoneyAction>();
NullReferenceCheckHelper.throwIfNull(money_action, () => $"money_action is null !!! - {payer.toBasicString()}");
result = await money_action.spendMoney(req_currency_type, req_use_fee_price);
if (result.isFail())
{
return result;
}
// FarmingEffectAttribute 정보를 설정 한다.
farming_effect_attribute.AnchorMetaGuid = anchorMetaGuid;
farming_effect_attribute.LocationUniqueId = curr_map.getLocationUniqueId();
farming_effect_attribute.FarmingPropMetaId = (META_ID)found_anchor_info.AnchorProp.TableId;
farming_effect_attribute.OwnerEntityType = master.onGetOwnerEntityType();
farming_effect_attribute.OwnerGuid = master.onGetGuidOfOwnerEntityType();
farming_effect_attribute.FarmingSummonedEntityType = toFarmingSummonedEntityType();
farming_effect_attribute.FarmingEntityGuid = toFarmingGuid();
farming_effect_attribute.FarmingState = FarmingStateType.Progress;
farming_effect_attribute.FarmingActionReqTryCount = farmingActionTryCount;
var start_time = DateTimeHelper.Current;
farming_effect_attribute.FarmingStartTime = start_time;
farming_effect_attribute.FarmingEndTime = toFarmingEndTime(start_time, anchorMetaGuid, farmingActionTryCount);
farming_effect_attribute.newEntityAttribute();
var farming_effect_link_pksk = FarmingEffectDoc.makeLINK_PKSK(anchorMetaGuid, farming_effect_attribute.LocationUniqueId);
// FarmingEffectLocationInTargetAttribute 정보를 설정 한다.
var farming_effect_location_in_target_attribute = owner.getEntityAttribute<FarmingEffectLocationInTargetAttribute>();
NullReferenceCheckHelper.throwIfNull(farming_effect_location_in_target_attribute, () => $"farming_effect_location_in_target_attribute is null !!! - {owner.toBasicString()}");
var server_logic = GameServerApp.getServerLogic();
var location_target_type = server_logic.getServerType().toLocationTargetType();
farming_effect_location_in_target_attribute.LocationUniqueId = curr_map.getLocationUniqueId();
farming_effect_location_in_target_attribute.AnchorMetaGuid = anchorMetaGuid;
farming_effect_location_in_target_attribute.UserGuid = master.getUserGuid();
farming_effect_location_in_target_attribute.UserNickname = master.getUserNickname();
farming_effect_location_in_target_attribute.FarmingEffectDocLinkPKSK = farming_effect_link_pksk;
farming_effect_location_in_target_attribute.newEntityAttribute();
// FarmingEffectOwnerAttribute 정보를 설정 한다.
var farming_effect_owner_attribute = owner.getEntityAttribute<FarmingEffectOwnerAttribute>();
NullReferenceCheckHelper.throwIfNull(farming_effect_owner_attribute, () => $"farming_effect_owner_attribute is null !!! - {owner.toBasicString()}");
farming_effect_owner_attribute.OwnerEntityType = owner.onGetOwnerEntityType();
farming_effect_owner_attribute.OwnerGuid = owner.onGetGuidOfOwnerEntityType();
farming_effect_owner_attribute.FarmingEffectDocLinkPKSK = farming_effect_link_pksk;
farming_effect_owner_attribute.newEntityAttribute();
// FarmingEffectAction에 AnchorInfo를 설정 한다.
attachAnchorInfo(found_anchor_info);
(var farming_doc_result, var doc_base) = await farming_effect_attribute.toDocBase(false);
if(farming_doc_result.isFail())
{
err_msg = $"Failed to toDocBase() !!!, in tryStartEffect() : {farming_doc_result.toBasicString()} - {owner.toBasicString()}, masterGuid:{root_parent.getMasterGuid()}";
Log.getLogger().error(err_msg);
}
else
{
var farming_doc = doc_base as FarmingEffectDoc;
NullReferenceCheckHelper.throwIfNull(farming_doc, () => $"farming_doc is null !!! - {owner.toBasicString()}");
m_farming_log_info.setLogInfo(farming_doc, master.onGetGuidOfOwnerEntityType(), (UInt32)req_use_fee_price);
}
return result;
}
public async Task<Result> isAbleToFarming(ANCHOR_META_GUID anchorMetaGuid, Int32 farmingActionTryCount)
{
var owner = getOwner() as FarmingEffect;
NullReferenceCheckHelper.throwIfNull(owner, () => $"owner is null !!!");
var root_parent = owner.getRootParent();
var result = new Result();
var err_msg = string.Empty;
var farming_action = root_parent.getEntityAction<FarmingAction>();
NullReferenceCheckHelper.throwIfNull(farming_action, () => $"farming_action is null !!! - {owner.toBasicString()}");
// 1. 중복 파밍 예외를 체크 한다.
if(true == farming_action.isFarmingHere())
{
err_msg = $"Farming by me !!! : AnchorMetaGuid:{anchorMetaGuid} - {owner.toBasicString()}";
result.setFail(ServerErrorCode.FarmingByMe, err_msg);
return result;
}
// 2. 메타 데이터 기준 예외를 체크 한다.
var curr_map = owner.getCurrMap();
var found_anchor_info = curr_map.findAnchorInfo(anchorMetaGuid);
NullReferenceCheckHelper.throwIfNull(found_anchor_info, () => $"found_anchor_info is null !!! - {owner.toBasicString()}");
if (false == MetaData.Instance._FarmingPropMetaTable.TryGetValue(found_anchor_info.AnchorProp.TableId, out var found_farming_prop_meta))
{
err_msg = $"Not found FarmingPropMeta in FarmingPropMetaTable !!! : FarmingPropMetaId:{found_anchor_info.AnchorProp.TableId} - {curr_map.toBasicString()}, {owner.toBasicString()}";
result.setFail(ServerErrorCode.FarmingPropMetaDataNotFound, err_msg);
Log.getLogger().error(result.toBasicString());
return result;
}
// 2.1. 파밍 가능 횟수를 체크 한다.
var max_count = found_farming_prop_meta.FarmingMaxCount;
if ( farmingActionTryCount < 1
|| found_farming_prop_meta.FarmingMaxCount < farmingActionTryCount)
{
err_msg = $"Invalid Farming Try Count !!! : 0 < tryCount:{farmingActionTryCount} <= maxCount:{max_count} - FarmingPropMetaId:{found_anchor_info.AnchorProp.TableId}, {curr_map.toBasicString()}, {owner.toBasicString()}";
result.setFail(ServerErrorCode.FarmingTryCountInvalid, err_msg);
Log.getLogger().error(result.toBasicString());
return result;
}
// 2.2. 요구 능력치를 체크 한다.
var ability_action = root_parent.getEntityAction<AbilityAction>();
NullReferenceCheckHelper.throwIfNull(ability_action, () => $"ability_action is null !!! - {owner.toBasicString()}");
var to_check_abilities = found_farming_prop_meta.AttributeCondition.ToDictionary(item => item.AttributeName, item => item.AttributeValue);
result = ability_action.hasAbilities(to_check_abilities);
if (result.isFail())
{
return result;
}
// 2.3. 결제할 Owner를 설정하고, 요구 수수료를 계산 한다.
(result, var payer, var req_currency_type, var req_use_fee_price) = await calculateReqUseFeePrice(anchorMetaGuid, farmingActionTryCount);
if(result.isFail())
{
return result;
}
NullReferenceCheckHelper.throwIfNull(payer, () => $"payer is null !!! - {owner.toBasicString()}");
// 2.4. 요구 비용을 체크 한다.
var money_action = payer.getEntityAction<MoneyAction>();
NullReferenceCheckHelper.throwIfNull(money_action, () => $"money_action is null !!! - {owner.toBasicString()}");
var currency_type = found_farming_prop_meta.UsageFeeType;
if(false == money_action.hasMoney(currency_type, req_use_fee_price))
{
var has_money = money_action.getMoney(currency_type);
err_msg = $"Not enough Money !!! : currencyType:{currency_type}, currMoney:{has_money} >= reqMoney:{has_money} - FarmingPropMetaId:{found_anchor_info.AnchorProp.TableId}, {owner.toBasicString()}";
result.setFail(ServerErrorCode.MoneyNotEnough, err_msg);
Log.getLogger().error(result.toBasicString());
return result;
}
return await Task.FromResult(result);
}
public async Task<(Result, Player?, CurrencyType, double)> calculateReqUseFeePrice(ANCHOR_META_GUID anchorMetaGuid, Int32 farmingActionTryCount)
{
var owner = getOwner() as FarmingEffect;
NullReferenceCheckHelper.throwIfNull(owner, () => $"owner is null !!!");
var root_parent = owner.getRootParent();
var result = new Result();
var err_msg = string.Empty;
// 1. 메타 데이터 기준 예외를 체크 한다.
var curr_map = owner.getCurrMap();
var found_anchor_info = curr_map.findAnchorInfo(anchorMetaGuid);
NullReferenceCheckHelper.throwIfNull(found_anchor_info, () => $"found_anchor_info is null !!! - {owner.toBasicString()}");
if (false == MetaData.Instance._FarmingPropMetaTable.TryGetValue(found_anchor_info.AnchorProp.TableId, out var found_farming_prop_meta))
{
err_msg = $"Not found FarmingPropMeta in FarmingPropMetaTable !!! : FarmingPropMetaId:{found_anchor_info.AnchorProp.TableId} - {curr_map.toBasicString()}, {owner.toBasicString()}";
result.setFail(ServerErrorCode.FarmingPropMetaDataNotFound, err_msg);
Log.getLogger().error(result.toBasicString());
return (result, null, CurrencyType.None, 0);
}
// 2. 파밍 가능 횟수를 체크 한다.
var max_count = found_farming_prop_meta.FarmingMaxCount;
if ( farmingActionTryCount < 1
|| found_farming_prop_meta.FarmingMaxCount < farmingActionTryCount)
{
err_msg = $"Invalid Farming Try Count !!! : 0 < tryCount:{farmingActionTryCount} <= maxCount:{max_count} - FarmingPropMetaId:{found_anchor_info.AnchorProp.TableId}, {curr_map.toBasicString()}, {owner.toBasicString()}";
result.setFail(ServerErrorCode.FarmingTryCountInvalid, err_msg);
Log.getLogger().error(result.toBasicString());
return (result, null, CurrencyType.None, 0);
}
// 3. 결제할 Owner를 설정하고, 요구 수수료를 계산 한다.
Player? payer = null;
double req_use_fee_price = 0;
if (root_parent is Player player)
{
payer = player;
// 유저 선택시 수수료를 계산 한다.
req_use_fee_price = found_farming_prop_meta.UsageFeePrice * farmingActionTryCount;
}
else if (root_parent is UgcNpc ugc_npc)
{
var ugc_npc_attribute = ugc_npc.getEntityAttribute<UgcNpcAttribute>();
NullReferenceCheckHelper.throwIfNull(ugc_npc_attribute, () => $"ugc_npc_attribute is null !!! - {owner.toBasicString()}");
var curr_state = ugc_npc_attribute.State;
if (EntityStateType.None != curr_state)
{
err_msg = $"UgcNpc is Busy !!! : currState:{curr_state}, AnchorMetaGuid:{anchorMetaGuid} - {curr_map.toBasicString()}, {owner.toBasicString()}";
result.setFail(ServerErrorCode.NpcIsBusy, err_msg);
return (result, null, CurrencyType.None, 0);
}
payer = ugc_npc.onGetMasterEntity() as Player;
NullReferenceCheckHelper.throwIfNull(payer, () => $"payer is null !!! - {owner.toBasicString()}");
// UgcNpc 선택시 수수료를 계산 한다.
var use_fee_price = found_farming_prop_meta.UsageFeePrice * farmingActionTryCount;
double ratio_100 = ConstValue.default_100_ratio_f.toDoubleWithEpsilon(2);
double usage_fee_price_npc_sale = found_farming_prop_meta.UsageFeePriceNpcSale;
req_use_fee_price = Double.Max(0, use_fee_price - use_fee_price * usage_fee_price_npc_sale * ratio_100);
}
else
{
err_msg = $"Invalid EntityType !!! : EntityType:{root_parent.getEntityType()} - {curr_map.toBasicString()}, {owner.toBasicString()}";
result.setFail(ServerErrorCode.EntityTypeInvalid, err_msg);
Log.getLogger().error(result.toBasicString());
return (result, null, CurrencyType.None, 0);
}
req_use_fee_price = CurrencyControlHelper.roundMoneyByCurrencyType(found_farming_prop_meta.UsageFeeType, req_use_fee_price);
return await Task.FromResult((result, payer, found_farming_prop_meta.UsageFeeType, req_use_fee_price));
}
public async Task<(Result, FarmingEffect?, ReceivedMailDoc?)> tryCancelFarming( ANCHOR_META_GUID anchorMetaGuid )
{
var owner = getOwner() as FarmingEffect;
NullReferenceCheckHelper.throwIfNull(owner, () => $"owner is null !!!");
var root_parent = owner.getRootParent();
var curr_map = owner.getCurrMap();
var result = new Result();
var err_msg = string.Empty;
result = await isAbleToCancel(anchorMetaGuid);
if(result.isFail())
{
return (result, null, null);
}
(result, ReceivedMailDoc? to_receive_mail_doc_nullable) = await tryStopFarming(anchorMetaGuid);
if (result.isFail())
{
return (result, null, null);
}
return (result, owner, to_receive_mail_doc_nullable);
}
public async Task<Result> isAbleToCancel(ANCHOR_META_GUID anchorMetaGuid)
{
var owner = getOwner() as FarmingEffect;
NullReferenceCheckHelper.throwIfNull(owner, () => $"owner is null !!!");
var root_parent = owner.getRootParent();
var curr_map = owner.getCurrMap();
var curr_anchor_info = getAnchorInfo();
NullReferenceCheckHelper.throwIfNull(curr_anchor_info, () => $"curr_anchor_info is null !!! - {owner.toBasicString()}");
var result = new Result();
var err_msg = string.Empty;
// FarmingEffectOwnerAttribute 정보 설정 하기
var farming_effect_owner_attribute = owner.getEntityAttribute<FarmingEffectOwnerAttribute>();
NullReferenceCheckHelper.throwIfNull(farming_effect_owner_attribute, () => $"farming_effect_owner_attribute is null !!! - {owner.toBasicString()}");
var owner_entity_type = farming_effect_owner_attribute.OwnerEntityType;
var owner_guid = farming_effect_owner_attribute.OwnerGuid;
switch (owner_entity_type)
{
case OwnerEntityType.User:
{
var player = root_parent as Player;
NullReferenceCheckHelper.throwIfNull(player, () => $"player is null !!! - {owner.toBasicString()}");
var user_guid = player.getUserGuid();
if (user_guid != owner_guid)
{
err_msg = $"Not match owner of Farming !!! : currOwnerGuid:{owner_guid} == reqUserGuid:{user_guid} - {owner.toBasicString()}";
result.setFail(ServerErrorCode.FarmingOwnerNotMatch, err_msg);
Log.getLogger().error(result.toBasicString());
return result;
}
}
break;
case OwnerEntityType.UgcNpc:
{
var ugc_npc = root_parent as UgcNpc;
NullReferenceCheckHelper.throwIfNull(ugc_npc, () => $"ugc_npc is null !!! - {owner.toBasicString()}");
var ugc_npc_meta_guid = ugc_npc.getUgcNpcMetaGuid();
if (ugc_npc_meta_guid != owner_guid)
{
err_msg = $"Not match owner of Farming !!! : currOwnerGuid:{owner_guid} == reqUgcNpcMetaGuid:{ugc_npc_meta_guid} - {owner.toBasicString()}";
result.setFail(ServerErrorCode.FarmingOwnerNotMatch, err_msg);
Log.getLogger().error(result.toBasicString());
return result;
}
}
break;
}
if (PropState.Progress != curr_anchor_info.PropState)
{
err_msg = $"Not state Farming !!! : currState:{curr_anchor_info.PropState} - {curr_map.toBasicString()}, {owner.toBasicString()}";
result.setFail(ServerErrorCode.FarmingNotState, err_msg);
Log.getLogger().error(result.toBasicString());
return result;
}
return await Task.FromResult(result);
}
public async Task<(Result, ReceivedMailDoc?)> tryStopFarming(ANCHOR_META_GUID anchorMetaGuid)
{
var owner = getOwner() as FarmingEffect;
NullReferenceCheckHelper.throwIfNull(owner, () => $"owner is null !!!");
var root_parent = owner.getRootParent();
var result = new Result();
var err_msg = string.Empty;
var curr_anchor_info = getAnchorInfo();
var farming_prop_meta_id = curr_anchor_info.AnchorProp.TableId;
if (false == MetaData.Instance._FarmingPropMetaTable.TryGetValue(farming_prop_meta_id, out var found_farming_prop_meta))
{
err_msg = $"Not found FarmingPropMeta in FarmingPropMetaTable !!! : FarmingPropMetaId:{curr_anchor_info.AnchorProp.TableId} - {owner.toBasicString()}";
result.setFail(ServerErrorCode.FarmingPropMetaDataNotFound, err_msg);
Log.getLogger().error(result.toBasicString());
return (result, null);
}
if (root_parent is UgcNpc ugc_npc)
{
var ugc_npc_action = ugc_npc.getEntityAction<UgcNpcAction>();
NullReferenceCheckHelper.throwIfNull(ugc_npc_action, () => $"ugc_npc_action is null !!! - {owner.toBasicString()}");
if (false == MapHelper.getAnchor(curr_anchor_info.AnchorGuid, out var anchor))
{
err_msg = $"Not found FarmingAnchor in Map !!! : FarmingAnchorGuid:{curr_anchor_info.AnchorGuid} - {owner.toBasicString()}";
result.setFail(ServerErrorCode.FarmingAnchorNotFound, err_msg);
Log.getLogger().error(result.toBasicString());
return (result, null);
}
var base_pos = new System.Numerics.Vector3(curr_anchor_info.AnchorPos.X, curr_anchor_info.AnchorPos.Y, curr_anchor_info.AnchorPos.Z);
var delta_pos = new System.Numerics.Vector3(found_farming_prop_meta.FarmingEndPosX, found_farming_prop_meta.FarmingEndPosY, found_farming_prop_meta.FarmingEndPosZ);
var target_position = ugc_npc_action.makeToLocatePosition( base_pos, anchor.Rotation.Pitch, anchor.Rotation.Yaw, anchor.Rotation.Roll
, delta_pos, found_farming_prop_meta.FarmingEndRotate );
ugc_npc_action.modifyStateInfo( EntityStateType.None, target_position );
result = await ugc_npc_action.tryRemoveInGameZone();
if (result.isFail())
{
return (result, null);
}
}
(result, ReceivedMailDoc? to_receive_mail_doc_nullable) = await tryRewardFarming( anchorMetaGuid, DateTimeHelper.Current );
if (result.isFail())
{
return (result, null);
}
var farming_attribute = owner.getEntityAttribute<FarmingEffectAttribute>();
NullReferenceCheckHelper.throwIfNull(farming_attribute, () => $"farming_attribute is null !!! - {owner.toBasicString()}");
(var farming_doc_result, var doc_base) = await farming_attribute.toDocBase(false);
if (farming_doc_result.isFail())
{
err_msg = $"Failed to toDocBase() !!!, in tryStopFarming() : {farming_doc_result.toBasicString()} - {owner.toBasicString()}, masterGuid:{root_parent.getMasterGuid()}";
Log.getLogger().error(err_msg);
}
else
{
var farming_doc = doc_base as FarmingEffectDoc;
NullReferenceCheckHelper.throwIfNull(farming_doc, () => $"farming_doc is null !!! - {owner.toBasicString()}");
var farming_location_attribute = owner.getEntityAttribute<FarmingEffectLocationInTargetAttribute>();
NullReferenceCheckHelper.throwIfNull(farming_location_attribute, () => $"farming_location_attribute is null !!! - {owner.toBasicString()}");
m_farming_log_info.setLogInfo(farming_doc, farming_location_attribute.UserGuid);
}
// FarmingEffectOwnerAttribute 정보 삭제 설정
var farming_effect_owner_attribute = owner.getEntityAttribute<FarmingEffectOwnerAttribute>();
NullReferenceCheckHelper.throwIfNull(farming_effect_owner_attribute, () => $"farming_effect_owner_attribute is null !!! - {owner.toBasicString()}");
farming_effect_owner_attribute.deleteEntityAttribute();
// FarmingEffectLocationInTargetAttribute 정보 삭제 설정
var farming_effect_location_in_target_attribute = owner.getEntityAttribute<FarmingEffectLocationInTargetAttribute>();
NullReferenceCheckHelper.throwIfNull(farming_effect_location_in_target_attribute, () => $"farming_effect_location_in_target_attribute is null !!! - {owner.toBasicString()}");
farming_effect_location_in_target_attribute.deleteEntityAttribute();
// FarmingEffectAttribute 정보 삭제 설정
var farming_effect_attribute = owner.getEntityAttribute<FarmingEffectAttribute>();
NullReferenceCheckHelper.throwIfNull(farming_effect_attribute, () => $"farming_effect_attribute is null !!! - {owner.toBasicString()}");
farming_effect_attribute.deleteEntityAttribute();
return (result, to_receive_mail_doc_nullable);
}
public async Task<(Result, ReceivedMailDoc?)> tryRewardFarming( ANCHOR_META_GUID anchorMetaGuid
, DateTime farmingEndTime)
{
var owner = getOwner() as FarmingEffect;
NullReferenceCheckHelper.throwIfNull(owner, () => $"owner is null !!!");
var root_parent = owner.getRootParent();
var curr_map = owner.getCurrMap();
var curr_anchor_info = getAnchorInfo();
var result = new Result();
var err_msg = string.Empty;
if (false == MetaData.Instance._FarmingPropMetaTable.TryGetValue(curr_anchor_info.AnchorProp.TableId, out var found_farming_prop_meta))
{
err_msg = $"Not found FarmingPropMeta in FarmingPropMetaTable !!! : FarmingPropMetaId:{curr_anchor_info.AnchorProp.TableId} - {curr_map.toBasicString()}, {owner.toBasicString()}";
result.setFail(ServerErrorCode.FarmingPropMetaDataNotFound, err_msg);
Log.getLogger().error(result.toBasicString());
return (result, null);
}
var reward_gacha_group_id = found_farming_prop_meta.RewardGachaGroupID;
if (false == MetaData.Instance._GachaMetaTable.TryGetValue(reward_gacha_group_id, out var found_gacha_meta))
{
err_msg = $"Not found GachaMeta in GachaMetaTable !!! : RewardGachaGroupId:{reward_gacha_group_id} - {curr_map.toBasicString()}, {owner.toBasicString()}";
result.setFail(ServerErrorCode.RewardInfoNotExist, err_msg);
return (result, null);
}
Player? master = null;
if (root_parent is Player player)
{
master = player;
}
else if (root_parent is UgcNpc ugc_npc)
{
master = ugc_npc.onGetMasterEntity() as Player;
}
if (null == master)
{
err_msg = $"Not found Master !!! : masterGuid:{root_parent.getMasterGuid()} : {owner.toBasicString()}";
result.setFail(ServerErrorCode.MasterNotFound, err_msg);
Log.getLogger().error(result.toBasicString());
return (result, null);
}
var user_guid = master.getUserGuid();
var user_nickname = master.getUserNickname();
// FarmingEffectAttribute 정보 설정 하기
var farming_effect_attribute = owner.getEntityAttribute<FarmingEffectAttribute>();
NullReferenceCheckHelper.throwIfNull(farming_effect_attribute, () => $"farming_effect_attribute is null !!! - {owner.toBasicString()}");
ReceivedMailDoc? to_receive_mail_doc_nullable = null;
(result, DynamoDbDocBase? make_doc) = await farming_effect_attribute.toDocBase(false);
if (result.isFail())
{
err_msg = $"Failed to makeDoc() !!! : {result.toBasicString()} - anchorMetaGuid:{anchorMetaGuid}, {owner.toBasicString()}";
Log.getLogger().error(err_msg);
return (result, null);
}
var farming_effect_doc = make_doc as FarmingEffectDoc;
NullReferenceCheckHelper.throwIfNull(farming_effect_doc, () => $"farming_effect_attrfarming_effect_docibute is null !!! - {owner.toBasicString()}");
(result, to_receive_mail_doc_nullable) = await FarmingHelper.tryReward( farming_effect_doc
, farmingEndTime, new TimeSpan()
, (UInt16)found_farming_prop_meta.InteractionCoolTime
, (META_ID)reward_gacha_group_id, found_gacha_meta
, user_guid, user_nickname );
if(result.isFail())
{
err_msg = $"Failed to tryReward() !!! : {result.toBasicString()} - anchorMetaGuid:{anchorMetaGuid}, {owner.toBasicString()}";
Log.getLogger().error(err_msg);
return (result, null);
}
if(false == farming_effect_attribute.copyEntityAttributeFromDoc(farming_effect_doc))
{
err_msg = $"Failed to copyEntityAttributeFromDoc() !!!, to:{farming_effect_attribute.getTypeName()}, from:{farming_effect_doc.getTypeName()}";
result.setFail(ServerErrorCode.DynamoDbDocCopyToEntityAttributeFailed, err_msg);
Log.getLogger().error(result.toBasicString());
return (result, null);
}
var farming_location_attribute = owner.getEntityAttribute<FarmingEffectLocationInTargetAttribute>();
NullReferenceCheckHelper.throwIfNull(farming_location_attribute, () => $"farming_location_attribute is null !!! - {owner.toBasicString()}");
var reward_meta_type = (found_gacha_meta != null ? found_gacha_meta.getTypeName() : string.Empty);
m_farming_reward_log_info.setLogInfo(farming_effect_doc, farming_location_attribute.UserGuid, reward_meta_type, (META_ID)reward_gacha_group_id);
return await Task.FromResult((result, to_receive_mail_doc_nullable));
}
public virtual async Task<Result> onUpdateFarming()
{
var owner = getOwner() as FarmingEffect;
NullReferenceCheckHelper.throwIfNull(owner, () => $"owner is null !!!");
var result = new Result();
var err_msg = string.Empty;
var root_parent = owner.getRootParent();
var curr_map = owner.getCurrMap();
var server_logic = GameServerApp.getServerLogic();
var db_client = server_logic.getDynamoDbClient();
var curr_anchor_info = getAnchorInfo();
// FarmingEffectAttribute 정보 설정 하기
var farming_effect_attribute = owner.getEntityAttribute<FarmingEffectAttribute>();
NullReferenceCheckHelper.throwIfNull(farming_effect_attribute, () => $"farming_effect_attribute is null !!! - {owner.toBasicString()}");
var current_time = DateTimeHelper.Current;
// 파밍 시간 만료를 체크 한다.
if ( FarmingStateType.Progress == farming_effect_attribute.FarmingState
&& farming_effect_attribute.FarmingEndTime <= current_time)
{
(result, var master_profile) = await farming_effect_attribute.getMasterProfile<Player>();
if (result.isFail())
{
err_msg = $"Failed to getMasterProile() !!! : {result.toBasicString()} - {owner.toBasicString()}";
Log.getLogger().error(err_msg);
return result;
}
NullReferenceCheckHelper.throwIfNull(master_profile, () => $"master_profile is null !!! - {owner.toBasicString()}");
farming_effect_attribute.modifiedEntityAttribute();
(result, var doc_base) = await farming_effect_attribute.toDocBase();
if (result.isFail())
{
err_msg = $"Failed to farming_effect_attribute.toDocBase() !!! : {result.toBasicString()} - {curr_map.toBasicString()}, {owner.toBasicString()}";
Log.getLogger().error(err_msg);
return result;
}
var farming_effect_doc = doc_base as FarmingEffectDoc;
NullReferenceCheckHelper.throwIfNull(farming_effect_doc, () => $"farming_effect_doc is null !!! - {owner.toBasicString()}");
result = await FarmingHelper.tryRewardAndPurge( farming_effect_doc
, farming_effect_attribute.FarmingEndTime, new TimeSpan()
, master_profile.MasterGuid, master_profile.MasterNickname
, LogActionType.FarmingComplete );
if (result.isFail())
{
err_msg = $"Failed to FarmingHelper.tryRewardFarming() !!! : {result.toBasicString()} - {curr_map.toBasicString()}, {owner.toBasicString()}";
Log.getLogger().error(err_msg);
return result;
}
var origin_entity_attribute = owner.getOriginEntityAttribute<FarmingEffectAttribute>();
NullReferenceCheckHelper.throwIfNull(origin_entity_attribute, () => $"origin_entity_attribute is null !!! - {owner.toBasicString()}");
origin_entity_attribute.copyEntityAttributeFromDoc(farming_effect_doc);
curr_map.PropModifyNoti(curr_anchor_info.AnchorGuid);
var farming_summary = owner.toFarmingSummary();
FarmingNotifyHelper.send_GS2C_NTF_FARMING_END(curr_map, curr_anchor_info, farming_summary);
var player_manager = server_logic.getPlayerManager();
if (false == player_manager.tryGetUserByPrimaryKey(master_profile.MasterGuid, out var found_user))
{
var login_cache_request = new LoginCacheOtherUserRequest(server_logic, server_logic.getRedisConnector(), master_profile.MasterGuid);
await login_cache_request.fetchLogin();
var login_cache = login_cache_request.getLoginCache();
if (login_cache != null)
{
FarmingNotifyHelper.send_GS2MQS_NTF_FARMING_END( server_logic
, login_cache.CurrentServer
, master_profile.MasterGuid, farming_summary
, false );
}
}
result = await tryRemoveFarmingEntity(root_parent);
if (result.isFail())
{
err_msg = $"Failed to tryRemoveFarmingEntity() !!! : {result.toBasicString()} - {owner.toBasicString()}";
Log.getLogger().error(err_msg);
return result;
}
var remove_result = await curr_map.tryRemoveFarming(owner);
if (remove_result.isFail())
{
err_msg = $"Failed to tryRemoveInGameZone() !!! : {remove_result.toBasicString()} - {owner.toBasicString()}";
Log.getLogger().error(err_msg);
}
}
else
{
result = await tryUpdateFarmig();
if (result.isFail())
{
err_msg = $"Failed to tryUpdateFarmig() !!! : {result.toBasicString()} - {owner.toBasicString()}";
Log.getLogger().error(err_msg);
return result;
}
}
return result;
}
public async Task<Result> tryUpdateFarmig()
{
var owner = getOwner() as FarmingEffect;
NullReferenceCheckHelper.throwIfNull(owner, () => $"owner is null !!!");
var result = new Result();
var err_msg = string.Empty;
var to_update_time = DateTimeHelper.Current;
var root_parent = owner.getRootParent();
var curr_map = owner.getCurrMap();
var server_logic = GameServerApp.getServerLogic();
var db_client = server_logic.getDynamoDbClient();
// FarmingEffectAttribute 정보 설정 하기
var farming_effect_attribute = owner.getEntityAttribute<FarmingEffectAttribute>();
NullReferenceCheckHelper.throwIfNull(farming_effect_attribute, () => $"farming_effect_attribute is null !!! - {owner.toBasicString()}");
if(ServerCommon.Constant.FARMING_LAST_UPDATE_STORE_INTERVAL_MSEC < DateTimeHelper.differFromToMilliSeconds(farming_effect_attribute.FarmingLastUpdateTime, to_update_time))
{
farming_effect_attribute.modifiedEntityAttribute();
(result, var doc_base) = await farming_effect_attribute.toDocBase();
if (result.isFail())
{
err_msg = $"Failed to cloned_farming_effect_attribute.toDocBase() !!! : {result.toBasicString()} - {owner.toBasicString()}";
Log.getLogger().error(err_msg);
return result;
}
var farming_effect_doc = doc_base as FarmingEffectDoc;
NullReferenceCheckHelper.throwIfNull(farming_effect_doc, () => $"farming_effect_doc is null !!! - {owner.toBasicString()}");
result = await db_client.simpleUpdateDocumentWithDocType<FarmingEffectDoc>(farming_effect_doc);
if (result.isFail())
{
err_msg = $"Failed to simpleUpsertDocumentWithDocType() !!! in tryUpdateFarmig() : {result.toBasicString()} - {owner.toBasicString()}";
Log.getLogger().error(err_msg);
farming_effect_attribute.FarmingState = FarmingStateType.CoolingTime;
// 예외 상황 !!!
// 서버 메모리와 DB가 일치 않는다 !!!
// 일단 DB 기준으로 메모리를 맞춘다 !!! - kangms
result = await tryRemoveFarmingEntity(root_parent);
if (result.isFail())
{
err_msg = $"Failed to tryRemoveFarmingEntity() !!! in tryUpdateFarmig() : {result.toBasicString()} - {owner.toBasicString()}";
Log.getLogger().error(err_msg);
}
var remove_result = await curr_map.tryRemoveFarming(owner);
if (remove_result.isFail())
{
err_msg = $"Failed to tryRemoveInGameZone() !!! in tryUpdateFarmig() : {remove_result.toBasicString()} - {owner.toBasicString()}";
Log.getLogger().error(err_msg);
}
return result;
}
var origin_entity_attribute = owner.getOriginEntityAttribute<FarmingEffectAttribute>();
NullReferenceCheckHelper.throwIfNull(origin_entity_attribute, () => $"origin_entity_attribute is null !!! - {owner.toBasicString()}");
origin_entity_attribute.copyEntityAttributeFromDoc(farming_effect_doc);
}
return result;
}
public async Task<Result> tryRemoveFarmingEntity(EntityBase farmingEntity)
{
var owner = getOwner() as FarmingEffect;
NullReferenceCheckHelper.throwIfNull(owner, () => $"owner is null !!!");
var server_logic = GameServerApp.getServerLogic();
var db_client = server_logic.getDynamoDbClient();
var curr_anchor_info = getAnchorInfo();
var anchor_meta_guid = curr_anchor_info.AnchorGuid;
var meta_id_of_anchor = (META_ID)curr_anchor_info.AnchorProp.TableId;
var result = new Result();
var err_msg = string.Empty;
if (false == MetaData.Instance._FarmingPropMetaTable.TryGetValue((int)meta_id_of_anchor, out var found_farming_prop_meta))
{
err_msg = $"Not found FarmingPropMeta in FarmingPropMetaTable !!! : FarmingPropMetaId:{meta_id_of_anchor} - {owner.toBasicString()}";
result.setFail(ServerErrorCode.FarmingPropMetaDataNotFound, err_msg);
Log.getLogger().error(result.toBasicString());
return result;
}
if (farmingEntity is Player player)
{
var farming_action = player.getEntityAction<FarmingAction>();
NullReferenceCheckHelper.throwIfNull(farming_action, () => $"farming_action is null !!! - {owner.toBasicString()}");
farming_action.detachFarmingEffect(owner);
}
else if (farmingEntity is UgcNpc ugc_npc)
{
var ugc_npc_action = ugc_npc.getEntityAction<UgcNpcAction>();
NullReferenceCheckHelper.throwIfNull(ugc_npc_action, () => $"ugc_npc_action is null !!! - {owner.toBasicString()}");
if (false == MapHelper.getAnchor(anchor_meta_guid, out var anchor))
{
err_msg = $"Not found FarmingAnchor in Map !!! : FarmingAnchorGuid:{anchor_meta_guid} - {owner.toBasicString()}";
result.setFail(ServerErrorCode.FarmingAnchorNotFound, err_msg);
Log.getLogger().error(result.toBasicString());
return result;
}
var farming_action = ugc_npc.getEntityAction<FarmingAction>();
NullReferenceCheckHelper.throwIfNull(farming_action, () => $"farming_action is null !!! - {owner.toBasicString()}");
farming_action.detachFarmingEffect(owner);
var base_pos = new System.Numerics.Vector3(curr_anchor_info.AnchorPos.X, curr_anchor_info.AnchorPos.Y, curr_anchor_info.AnchorPos.Z);
var delta_pos = new System.Numerics.Vector3(found_farming_prop_meta.FarmingEndPosX, found_farming_prop_meta.FarmingEndPosY, found_farming_prop_meta.FarmingEndPosZ);
var target_position = ugc_npc_action.makeToLocatePosition( base_pos, anchor.Rotation.Pitch, anchor.Rotation.Yaw, anchor.Rotation.Roll
, delta_pos, found_farming_prop_meta.FarmingEndRotate );
ugc_npc_action.modifyStateInfo( EntityStateType.None, target_position );
var ugc_ncp_result = await ugc_npc_action.tryRemoveInGameZone();
if (ugc_ncp_result.isFail())
{
err_msg = $"Failed to tryRemoveInGameZone() !!! in onUpdateFarming() : {ugc_ncp_result.toBasicString()} - {owner.toBasicString()}";
Log.getLogger().error(err_msg);
}
var ugc_npc_attribute = ugc_npc.getEntityAttribute<UgcNpcAttribute>();
NullReferenceCheckHelper.throwIfNull(ugc_npc_attribute, () => $"ugc_npc_attribute is null !!! - {owner.toBasicString()}");
(result, var ugc_npc_doc) = await ugc_npc_attribute.toDocBase();
if (result.isFail() || null == ugc_npc_doc)
{
err_msg = $"Failed to toDocBase() or Doc is null !!! in onUpdateFarming() : {result.toBasicString()} - {owner.toBasicString()}";
Log.getLogger().error(err_msg);
return result;
}
result = await DynamoDBDocBaseHelper.simpleUpdateDocumentWithDocType(db_client, ugc_npc_doc);
if (result.isFail())
{
err_msg = $"Failed to simpleUpsertDocumentWithDocType() !!! in onUpdateFarming() : {result.toBasicString()} - {owner.toBasicString()}";
Log.getLogger().error(err_msg);
return result;
}
var origin_entity_attribute = ugc_npc.getOriginEntityAttribute<UgcNpcAttribute>();
NullReferenceCheckHelper.throwIfNull(origin_entity_attribute, () => $"origin_entity_attribute is null !!! - {owner.toBasicString()}");
origin_entity_attribute.copyEntityAttributeFromDoc(ugc_npc_doc);
Log.getLogger().info($"UgcNpc reset of State !!! in tryRemoveFarmingEntity() : {ugc_npc.toStateString()} - {ugc_npc.toBasicString()}");
var master_guid = ugc_npc.getMasterGuid();
var player_manager = server_logic.getPlayerManager();
if (false == player_manager.tryGetUserByPrimaryKey(master_guid, out var found_user))
{
var login_cache_request = new LoginCacheOtherUserRequest(server_logic, server_logic.getRedisConnector(), master_guid);
await login_cache_request.fetchLogin();
var login_cache = login_cache_request.getLoginCache();
if (login_cache != null)
{
UgcNpcNotifyHelper.send_GS2MQS_NTF_BEACON_COMPACT_SYNC( server_logic
, login_cache.CurrentServer
, master_guid, ugc_npc_action.toUgcNpcCompact()
, origin_entity_attribute.LocatedInstanceGuid );
}
}
else
{
UgcNpcNotifyHelper.send_GS2C_NTF_BEACON_COMPACT_UPDATE(found_user, ugc_npc, ugc_npc_action.toUgcNpcCompact());
}
}
return result;
}
public DateTime toFarmingEndTime(DateTime startTime, ANCHOR_META_GUID anchorMetaGuid, Int16 farmingActionTryCount)
{
var owner = getOwner() as FarmingEffect;
NullReferenceCheckHelper.throwIfNull(owner, () => $"owner is null !!!");
var root_parent = owner.getRootParent();
var curr_map = owner.getCurrMap();
var found_anchor_info = curr_map.findAnchorInfo(anchorMetaGuid);
NullReferenceCheckHelper.throwIfNull(found_anchor_info, () => $"found_anchor_info is null !!! - {owner.toBasicString()}");
if (false == MetaData.Instance._FarmingPropMetaTable.TryGetValue(found_anchor_info.AnchorProp.TableId, out var found_farming_prop_meta))
{
var err_msg = $"Not found FarmingPropMeta in FarmingPropMetaTable !!! : FarmingPropMetaId:{found_anchor_info.AnchorProp.TableId} - {owner.toBasicString()}";
Log.getLogger().error(err_msg);
return DateTimeHelper.MinTime;
}
var farming_reward_sec = 0;
var entity_type = root_parent.getEntityType();
switch (entity_type)
{
case EntityType.Player:
var player = root_parent as Player;
NullReferenceCheckHelper.throwIfNull(player, () => $"player is null !!! - {root_parent.toBasicString()}");
farming_reward_sec = found_farming_prop_meta.RewardCycleTimeUser * farmingActionTryCount;
break;
case EntityType.UgcNpc:
var ugc_npc = root_parent as UgcNpc;
NullReferenceCheckHelper.throwIfNull(ugc_npc, () => $"ugc_npc is null !!! - {root_parent.toBasicString()}");
farming_reward_sec = found_farming_prop_meta.RewardCycleTimeNpc * farmingActionTryCount;
break;
default:
var err_msg = $"Invalid EntityType of FarmingEndTime !!! : entityType:{entity_type} - {root_parent.toBasicString()}";
Log.getLogger().error(err_msg);
return DateTimeHelper.MinTime;
}
return startTime.AddSeconds(farming_reward_sec);
}
public OWNER_GUID toFarmingGuid()
{
var owner = getOwner() as FarmingEffect;
NullReferenceCheckHelper.throwIfNull(owner, () => $"owner is null !!!");
var root_parent = owner.getRootParent();
var entity_type = root_parent.getEntityType();
switch (entity_type)
{
case EntityType.Player:
var player = root_parent as Player;
NullReferenceCheckHelper.throwIfNull(player, () => $"player is null !!! - {root_parent.toBasicString()}");
return player.getUserGuid();
case EntityType.UgcNpc:
case EntityType.Beacon:
var ugc_npc = root_parent as UgcNpc;
NullReferenceCheckHelper.throwIfNull(ugc_npc, () => $"ugc_npc is null !!! - {root_parent.toBasicString()}");
return ugc_npc.getUgcNpcMetaGuid();
default:
var err_msg = $"Invalid EntityType of FarmingGuid !!! : entityType:{entity_type} - {root_parent.toBasicString()}";
Log.getLogger().error(err_msg);
break;
}
return string.Empty;
}
public FarmingSummonedEntityType toFarmingSummonedEntityType()
{
var owner = getOwner() as FarmingEffect;
NullReferenceCheckHelper.throwIfNull(owner, () => $"owner is null !!!");
var root_parent = owner.getRootParent();
var entity_type = root_parent.getEntityType();
switch(entity_type)
{
case EntityType.Player:
return FarmingSummonedEntityType.User;
case EntityType.UgcNpc:
return FarmingSummonedEntityType.Beacon;
default:
var err_msg = $"Invalid EntityType of FarmingSummonedEntityType !!! : entityType:{entity_type} - {root_parent.toBasicString()}";
Log.getLogger().error(err_msg);
break;
}
return FarmingSummonedEntityType.None;
}
public void attachAnchorInfo(AnchorInfo anchoInfo)
{
var owner = getOwner() as FarmingEffect;
NullReferenceCheckHelper.throwIfNull(owner, () => $"owner is null !!!");
m_anchor_info_nullable = anchoInfo;
}
public AnchorInfo getAnchorInfo()
{
NullReferenceCheckHelper.throwIfNull(m_anchor_info_nullable, () => $"m_anchor_info_nullable is null !!!");
return m_anchor_info_nullable;
}
public FarmingRewardLogInfo getFarmingRewardLogInfo() => m_farming_reward_log_info;
public FarmingLogInfo getFarmingLogInfo() => m_farming_log_info;
}