using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Collections.Concurrent; using System.Numerics; using ServerCore; using ServerBase; using ServerCommon; using ServerCommon.BusinessLogDomain; using MetaAssets; 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 NPC_UNIQUE_ID = System.String; using UGC_NPC_META_GUID = System.String; using FARMING_PROP_DOC_SK = System.String; using ANCHOR_META_GUID = System.String; using MASTER_GUID = System.String; using GUARD_KEY = System.String; namespace GameServer; public class FarmingAction : EntityActionBase { private FarmingEffect? m_progress_farming_nullable = null; public FarmingAction(EntityBase owner) : base(owner) { } public override async Task onInit() { await Task.CompletedTask; var result = new Result(); return result; } public override void onClear() { return; } public async Task resetFarmingState(bool isApplyDb = true) { var result = new Result(); var err_msg = string.Empty; var owner = getOwner(); var server_logic = GameServerApp.getServerLogic(); var db_client = server_logic.getDynamoDbClient(); if (owner is UgcNpc ugc_npc) { var ugc_npc_action = ugc_npc.getEntityAction(); NullReferenceCheckHelper.throwIfNull(ugc_npc_action, () => $"ugc_npc_action is null !!! - {ugc_npc.toBasicString()}"); var ugc_npc_attribute = ugc_npc.getEntityAttribute(); NullReferenceCheckHelper.throwIfNull(ugc_npc_attribute, () => $"ugc_npc_attribute is null !!! - {ugc_npc.toBasicString()}"); if(EntityStateType.UsingByFarming == ugc_npc_attribute.State) { ugc_npc_action.resetPos(isApplyDb); if(true == isApplyDb) { (result, var ugc_npc_doc) = await ugc_npc_attribute.toDocBase(); if (result.isFail()) { return result; } NullReferenceCheckHelper.throwIfNull(ugc_npc_doc, () => $"ugc_npc_doc is null !!! - {ugc_npc.toBasicString()}"); result = await db_client.simpleUpdateDocumentWithDocType(ugc_npc_doc); if (result.isFail()) { err_msg = $"Failed to simpleUpdateDocumentWithDocType() !!! in resetFarmingState() : {result.toBasicString()} - {ugc_npc.toBasicString()}"; Log.getLogger().error(err_msg); return result; } var origin_entity_attribute = ugc_npc.getOriginEntityAttribute(); NullReferenceCheckHelper.throwIfNull(origin_entity_attribute, () => $"origin_entity_attribute is null !!! - {ugc_npc.toBasicString()}"); origin_entity_attribute.copyEntityAttributeFromDoc(ugc_npc_doc); Log.getLogger().debug($"UgcNpc reset of State !!! in resetFarmingState() : {ugc_npc.toStateString()} - {ugc_npc.toBasicString()}"); } } } return result; } public async Task<(Result, FarmingEffect?)> tryStartFarming( ANCHOR_META_GUID anchorMetaGuid, Int16 farmingActionTryCount ) { var result = new Result(); var err_msg = string.Empty; var owner = getOwner(); var game_zone_action = owner.getEntityAction(); NullReferenceCheckHelper.throwIfNull(game_zone_action, () => $"game_zone_action is null !!!"); var curr_map = game_zone_action.getLinkedToMap(); if(null == curr_map) { // 현재 UgcNpc 타입만 해당되는 로직 이다. // 추후 인던 관련 설계가 리펙토링되면 재정의된 Map 반환(Master가 입장한 Map 반환) 함수로 처리해야 한다. - kangms (result, curr_map) = owner.getCurrMapOfMaster(); if(result.isFail()) { return (result, null); } } NullReferenceCheckHelper.throwIfNull(curr_map, () => $"curr_map is null !!!"); // 파밍중인 Anchor 인가? var found_farming_effect = curr_map.findFarmingEffect(anchorMetaGuid); if(null != found_farming_effect) { err_msg = $"Already farming !!! : anchorMetaGuid:{anchorMetaGuid} - {curr_map.toBasicString()}, {owner.toBasicString()}"; result.setFail(ServerErrorCode.FarmingAlready, err_msg); return (result, null); } // 파밍 객체를 생성 한다. var farming_effect = new FarmingEffect( owner, curr_map); result = await farming_effect.onInit(); if (result.isFail()) { return (result, null); } var farming_effect_action = farming_effect.getEntityAction(); NullReferenceCheckHelper.throwIfNull(farming_effect_action, () => $"farming_effect_action is null !!! - {owner.toBasicString()}"); // 파밍을 시도해 본다 !!! result = await farming_effect_action.tryStartEffect( anchorMetaGuid, farmingActionTryCount ); if (result.isFail()) { return (result, null); } if (owner is UgcNpc ugc_npc) { var ugc_npc_action = ugc_npc.getEntityAction(); NullReferenceCheckHelper.throwIfNull(ugc_npc_action, () => $"ugc_npc_action is null !!! - {owner.toBasicString()}"); var curr_anchor_info = farming_effect_action.getAnchorInfo(); NullReferenceCheckHelper.throwIfNull(curr_anchor_info, () => $"curr_anchor_info is null !!! - {owner.toBasicString()}"); 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:{farming_prop_meta_id} - {curr_map.toBasicString()}, {owner.toBasicString()}"; result.setFail(ServerErrorCode.FarmingPropMetaDataNotFound, err_msg); Log.getLogger().error(result.toBasicString()); return (result, null); } if(false == MapHelper.getAnchor(curr_anchor_info.AnchorGuid, out var anchor)) { err_msg = $"Not found FarmingAnchor in Map !!! : FarmingAnchorGuid:{curr_anchor_info.AnchorGuid} - {curr_map.toBasicString()}, {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.FarmingStartPosX, found_farming_prop_meta.FarmingStartPosY, found_farming_prop_meta.FarmingStartPosZ); var target_position = ugc_npc_action.makeToLocatePosition( base_pos, anchor.Rotation.Pitch, anchor.Rotation.Yaw, anchor.Rotation.Roll , delta_pos, found_farming_prop_meta.FarmingStartRotate ); ugc_npc_action.modifyStateInfo( EntityStateType.UsingByFarming , target_position , anchorMetaGuid , (META_ID)farming_prop_meta_id , true ); ugc_npc_action.setCountingAsConnectedUser(true); result = await ugc_npc_action.tryLocateInGameZone(curr_map); if (result.isFail()) { return (result, null); } } return (result, farming_effect); } public async Task completedFarmingStart( QueryExecutorBase queryExecutorBase , Player player , FarmingEffect farmingEffect , DBQWriteToAttributeAllWithTransactionRunner transactionRunner ) { var game_zone_action = player.getEntityAction(); NullReferenceCheckHelper.throwIfNull(game_zone_action, () => $"game_zone_action is null !!!"); var curr_map = game_zone_action.getLinkedToMap(); NullReferenceCheckHelper.throwIfNull(curr_map, () => $"curr_map is null !!!"); var result = await curr_map.tryLocateFarming(farmingEffect); if (result.isSuccess()) { attachFarmingEffect(farmingEffect); await transactionRunner.onMergeAfterQueryCommit(); } var farming_effect_action = farmingEffect.getEntityAction(); NullReferenceCheckHelper.throwIfNull(farming_effect_action, () => $"farming_effect_action is null !!! - {player.toBasicString()}"); var query_batch = queryExecutorBase.getQueryBatch(); NullReferenceCheckHelper.throwIfNull(query_batch, () => $"query_batch is null !!! - {player.toBasicString()}"); var log_action = query_batch.getLogAction(); NullReferenceCheckHelper.throwIfNull(log_action, () => $"log_action is null !!! - {player.toBasicString()}"); queryExecutorBase.appendBusinessLog(new FarmingBusinessLog(log_action, farming_effect_action.getFarmingLogInfo())); if(farmingEffect.onGetOwnerEntityType() == OwnerEntityType.UgcNpc) { var ugc_npc = farmingEffect.getRootParent() as UgcNpc; NullReferenceCheckHelper.throwIfNull(ugc_npc, () => $"ugc_npc is null !!! - {player.toBasicString()}"); var ugc_npc_action = ugc_npc.getEntityAction(); NullReferenceCheckHelper.throwIfNull(ugc_npc_action, () => $"ugc_npc_action is null !!! - {player.toBasicString()}"); UgcNpcNotifyHelper.send_GS2C_NTF_BEACON_COMPACT_UPDATE(player, ugc_npc, ugc_npc_action.toUgcNpcCompact()); } } public async Task<(Result, FarmingEffect?, ReceivedMailDoc?)> tryCancelFarming( ANCHOR_META_GUID anchorMetaGuid ) { var result = new Result(); var err_msg = string.Empty; var owner = getOwner(); var game_zone_action = owner.getEntityAction(); NullReferenceCheckHelper.throwIfNull(game_zone_action, () => $"game_zone_action is null !!!"); var curr_map = game_zone_action.getLinkedToMap(); NullReferenceCheckHelper.throwIfNull(curr_map, () => $"curr_map is null !!!"); // 파밍중인 Anchor 인가? var found_farming_effect = curr_map.findFarmingEffect(anchorMetaGuid); if (null == found_farming_effect) { err_msg = $"Not state farming !!! : anchorMetaGuid:{anchorMetaGuid} - {curr_map.toBasicString()}, {owner.toBasicString()}"; result.setFail(ServerErrorCode.FarmingNotState, err_msg); return (result, null, null); } var farming_effect_action = found_farming_effect.getEntityAction(); NullReferenceCheckHelper.throwIfNull(farming_effect_action, () => $"farming_effect_action is null !!! - {owner.toBasicString()}"); // 파밍을 취소를 시도 한다. (result, var farming_effect, var to_receive_mail_doc_nullable) = await farming_effect_action.tryCancelFarming( anchorMetaGuid ); if (result.isFail()) { return (result, null, null); } return (result, farming_effect, to_receive_mail_doc_nullable); } public async Task completedFarmingCancel( QueryExecutorBase queryExecutorBase , Player player, Map currMap , FarmingEffect farmingEffect, ReceivedMailDoc? receivedMailDoc , DBQWriteToAttributeAllWithTransactionRunner transactionRunner ) { var result = await currMap.tryRemoveFarming(farmingEffect); if (result.isSuccess()) { var parent = farmingEffect.getRootParent(); NullReferenceCheckHelper.throwIfNull(parent, () => $"parent is null !!! - {player.toBasicString()}"); var farming_action = parent.getEntityAction(); NullReferenceCheckHelper.throwIfNull(farming_action, () => $"farming_action is null !!! - {player.toBasicString()}"); farming_action.detachFarmingEffect(farmingEffect); await transactionRunner.onMergeAfterQueryCommit(); } var found_user_mail_action = player.getEntityAction(); NullReferenceCheckHelper.throwIfNull(found_user_mail_action, () => $"found_user_mail_action is null !!! - {player.toBasicString()}"); if (null != receivedMailDoc) { found_user_mail_action.NewReceivedMail(); } var farming_effect_action = farmingEffect.getEntityAction(); NullReferenceCheckHelper.throwIfNull(farming_effect_action, () => $"farming_effect_action is null !!! - {player.toBasicString()}"); var query_batch = queryExecutorBase.getQueryBatch(); NullReferenceCheckHelper.throwIfNull(query_batch, () => $"query_batch is null !!! - {player.toBasicString()}"); var log_action = query_batch.getLogAction(); NullReferenceCheckHelper.throwIfNull(log_action, () => $"log_action is null !!! - {player.toBasicString()}"); queryExecutorBase.appendBusinessLog(new FarmingBusinessLog(log_action, farming_effect_action.getFarmingLogInfo())); queryExecutorBase.appendBusinessLog(new FarmingRewardBusinessLog(log_action, farming_effect_action.getFarmingRewardLogInfo())); if (farmingEffect.onGetOwnerEntityType() == OwnerEntityType.UgcNpc) { var ugc_npc = farmingEffect.getRootParent() as UgcNpc; NullReferenceCheckHelper.throwIfNull(ugc_npc, () => $"ugc_npc is null !!! - {player.toBasicString()}"); var ugc_npc_action = ugc_npc.getEntityAction(); NullReferenceCheckHelper.throwIfNull(ugc_npc_action, () => $"ugc_npc_action is null !!! - {player.toBasicString()}"); UgcNpcNotifyHelper.send_GS2C_NTF_BEACON_COMPACT_UPDATE(player, ugc_npc, ugc_npc_action.toUgcNpcCompact()); } } public void attachFarmingEffect(FarmingEffect farmingEffect) { var owner = getOwner(); m_progress_farming_nullable = farmingEffect; if(owner is Player player) { var player_action = player.getEntityAction(); NullReferenceCheckHelper.throwIfNull(player_action, () => $"player_action is null !!! - {owner.toBasicString()}"); var selected_character = player_action.getSelectedCharacter(); NullReferenceCheckHelper.throwIfNull(selected_character, () => $"selected_character is null !!! - {owner.toBasicString()}"); var character_action = selected_character.getEntityAction(); NullReferenceCheckHelper.throwIfNull(character_action, () => $"character_action is null !!! - {owner.toBasicString()}"); var farming_effect_attribute = farmingEffect.getEntityAttribute(); NullReferenceCheckHelper.throwIfNull(farming_effect_attribute, () => $"farming_effect_attribute is null !!! - {owner.toBasicString()}"); character_action.setStateInfo(EntityStateType.UsingByFarming, farming_effect_attribute.AnchorMetaGuid, farming_effect_attribute.FarmingPropMetaId); character_action.broadcastCharacterInfo(); } } public void detachFarmingEffect(FarmingEffect farmingEffect) { var owner = getOwner(); var to_detach_anchor_meta_guid = farmingEffect.getAnchorMetaGuid(); if (null == m_progress_farming_nullable) { var err_msg = $"m_progress_farming_nullable is null !!! : toDetachAnchorGuid:{to_detach_anchor_meta_guid} - {owner.toBasicString()}"; Log.getLogger().error(err_msg); return; } var curr_anchor_meta_guid = m_progress_farming_nullable.getAnchorMetaGuid(); if (curr_anchor_meta_guid != to_detach_anchor_meta_guid) { var err_msg = $"Not match AnchorMetaGuid of Farming !!! : currAnchorGuid:{curr_anchor_meta_guid} == toDetachAnchorGuid:{to_detach_anchor_meta_guid} - {owner.toBasicString()}"; Log.getLogger().error(err_msg); return; } if (owner is Player player) { var player_action = player.getEntityAction(); NullReferenceCheckHelper.throwIfNull(player_action, () => $"player_action is null !!! - {owner.toBasicString()}"); var selected_character = player_action.getSelectedCharacter(); NullReferenceCheckHelper.throwIfNull(selected_character, () => $"selected_character is null !!! - {owner.toBasicString()}"); var character_action = selected_character.getEntityAction(); NullReferenceCheckHelper.throwIfNull(character_action, () => $"character_action is null !!! - {owner.toBasicString()}"); character_action.setStateInfo(EntityStateType.None, string.Empty, 0); character_action.broadcastCharacterInfo(); } m_progress_farming_nullable = null; } public void detachFarmingEffectByAnchorMetaGuid(ANCHOR_META_GUID anchorMetaGuid) { var owner = getOwner(); var to_detach_anchor_meta_guid = anchorMetaGuid; if (null == m_progress_farming_nullable) { var err_msg = $"m_progress_farming_nullable is null !!! : toDetachAnchorGuid:{to_detach_anchor_meta_guid} - {owner.toBasicString()}"; Log.getLogger().error(err_msg); return; } var curr_anchor_meta_guid = m_progress_farming_nullable.getAnchorMetaGuid(); if (curr_anchor_meta_guid != to_detach_anchor_meta_guid) { var err_msg = $"Not match AnchorMetaGuid of Farming !!! : currAnchorGuid:{curr_anchor_meta_guid} == toDetachAnchorGuid:{to_detach_anchor_meta_guid} - {owner.toBasicString()}"; Log.getLogger().error(err_msg); return; } m_progress_farming_nullable = null; } public bool isFarmingHere() { return m_progress_farming_nullable != null; } public bool isFarmingState() { var owner = getOwner(); if (owner is Player player) { var player_action = player.getEntityAction(); NullReferenceCheckHelper.throwIfNull(player_action, () => $"player_action is null !!! - {owner.toBasicString()}"); var selected_character = player_action.getSelectedCharacter(); NullReferenceCheckHelper.throwIfNull(selected_character, () => $"selected_character is null !!! - {owner.toBasicString()}"); var character_action = selected_character.getEntityAction(); NullReferenceCheckHelper.throwIfNull(character_action, () => $"character_action is null !!! - {owner.toBasicString()}"); if(true == character_action.isFarming()) { return true; } } else if (owner is UgcNpc ugc_npc) { var ugc_npc_action = ugc_npc.getEntityAction(); NullReferenceCheckHelper.throwIfNull(ugc_npc_action, () => $"ugc_npc_action is null !!! - {owner.toBasicString()}"); var ugc_npc_attribute = ugc_npc.getEntityAttribute(); NullReferenceCheckHelper.throwIfNull(ugc_npc_attribute, () => $"ugc_npc_attribute is null !!! - {owner.toBasicString()}"); if (EntityStateType.UsingByFarming == ugc_npc_attribute.State) { return true; } } return false; } public FarmingEffect? getFarmingEffect() { return m_progress_farming_nullable; } }