using Google.Protobuf; using Google.Protobuf.WellKnownTypes; 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 PARTY_GUID = System.String; using Amazon.S3.Model; namespace GameServer; public class UserLoader : EntityLoaderBase { private List m_progress_farming_summaries = new(); private string m_transact_guid = string.Empty; private ServerCommon.BusinessLogDomain.UserLogInfo m_user_log = new(); public UserLoader(Player owner) : base(owner) { } protected virtual async Task onResetUser() { var result = new Result(); var player = getOwner() as Player; NullReferenceCheckHelper.throwIfNull(player, () => $"player is null !!!"); var user_create_or_load_action = player.getEntityAction(); NullReferenceCheckHelper.throwIfNull(user_create_or_load_action, () => $"user_create_or_load_action is null !!! - {player.toBasicString()}"); user_create_or_load_action.onClearUserCreators(); await player.onResetUser(); } public override async Task onPrepareLoad() { await Task.CompletedTask; var result = new Result(); var err_msg = string.Empty; var player = getOwner() as Player; NullReferenceCheckHelper.throwIfNull(player, () => $"player is null !!!"); var account_attribute = player.getEntityAttribute(); NullReferenceCheckHelper.throwIfNull(account_attribute, () => $"account_attribute is null !!! - {player.toBasicString()}"); var account_base_doc = account_attribute.getOriginDocBase() as AccountBaseDoc; if (null == account_base_doc) { err_msg = $"Not load AccountBaseDoc !!! - {player.toBasicString()}"; result.setFail(ServerErrorCode.AccountBaseDocNotLoad, err_msg); Log.getLogger().error(result.toBasicString()); return result; } setCompetedPrepareLoad(true); return result; } public override async Task onTriggerEffect() { var player = getOwner() as Player; NullReferenceCheckHelper.throwIfNull(player, () => $"player is null !!!"); var result = new Result(); var err_msg = string.Empty; if (false == isCompletedPrepareLoad()) { err_msg = $"Not completed isCompletedPrepareLoad() !!! - {toBasicString()}, {player.toBasicString()}"; result.setFail(ServerErrorCode.UserPrepareLoadNotCompleted, err_msg); return result; } m_transact_guid = Guid.NewGuid().ToString("N"); // Player 초기화 작업 await onResetUser(); //===================================================================================== // Cache to Attribute //===================================================================================== result = await onLoadEntityAttributeFromCache(); if (result.isFail()) { return result; } //===================================================================================== // Doc to Attribute //===================================================================================== result = await onLoadEntityAttriubteFromDoc(); if (result.isFail()) { return result; } //===================================================================================== // Contents Load //===================================================================================== result = await onContentsLoading(); if (result.isFail()) { return result; } return result; } protected async Task onContentsLoading() { var owner = getOwner() as Player; NullReferenceCheckHelper.throwIfNull(owner, () => $"owner is null !!!"); var result = new Result(); var err_msg = string.Empty; var user_create_or_loading_action = owner.getEntityAction(); NullReferenceCheckHelper.throwIfNull(user_create_or_loading_action, () => $"user_create_or_loading_action is null !!! - {owner.toBasicString()}"); if(true == user_create_or_loading_action.isFirstLogin()) { var account_attribute = owner.getEntityAttribute(); NullReferenceCheckHelper.throwIfNull(account_attribute, () => $"account_attribute is null !!! - {owner.toBasicString()}"); if(0 < account_attribute.SsoAccountAuthJWT.Length) { result = await onLoadNftFromUrl(owner); if (result.isFail()) { err_msg = $"Failed to onLoadNftFromUrl() !!! : {result.toBasicString()} - {owner.toBasicString()}"; Log.getLogger().error(err_msg); return result; } } } LandAuctionManager.It.sendLandAuctionAllToUserGuid(owner); return result; } protected virtual async Task onLoadEntityAttributeFromCache() { var result = new Result(); var owner = getOwner() as Player; NullReferenceCheckHelper.throwIfNull(owner, () => $"owner is null !!!"); var game_login_action = owner.getEntityAction(); NullReferenceCheckHelper.throwIfNull(game_login_action, () => $"game_login_action is null !!! - {owner.toBasicString()}"); var login_cache_request = game_login_action.getLoginCacheRequest(); NullReferenceCheckHelper.throwIfNull(login_cache_request, () => $"login_cache_request is null !!! - {owner.toBasicString()}"); var login_cache = login_cache_request.getLoginCache(); NullReferenceCheckHelper.throwIfNull(login_cache, () => $"login_cache is null !!! - {owner.toBasicString()}"); var user_attribute = owner.getEntityAttribute(); NullReferenceCheckHelper.throwIfNull(user_attribute, () => $"user_attribute is null !!! - {owner.toBasicString()}"); result = await ServerBase.DataCopyHelper.copyEntityAttributeFromCaches(user_attribute, (new List() { login_cache })); if (result.isFail()) { return result; } var location_action = owner.getEntityAction(); NullReferenceCheckHelper.throwIfNull(location_action, () => $"location_action is null !!! - {owner.toBasicString()}"); result = await location_action.tryLoadEntityAttributeFromCache(); if (result.isFail()) { return result; } return result; } protected virtual async Task onLoadEntityAttriubteFromDoc() { var result = new Result(); var owner = getOwner() as Player; NullReferenceCheckHelper.throwIfNull(owner, () => $"owner is null !!!"); result = await onLoadUserFromDoc(owner); if (result.isFail()) { return result; } result = await onLoadUgcNpcFromDoc(owner); if (result.isFail()) { return result; } await onLoadFarmingEffectFromDoc(owner); var user_land_auction_action = owner.getEntityAction(); NullReferenceCheckHelper.throwIfNull(user_land_auction_action, () => $"user_land_auction_action is null !!! - {owner.toBasicString()}"); result = await user_land_auction_action.tryLoadLandAuctionBidPriceAllFromDb(); if (result.isFail()) { return result; } result = await onLoadMyhomeFromDoc(owner); if (result.isFail()) { return result; } result = await onLoadPackageFromDoc(owner); if(result.isFail()) return result; result = await onLoadAiChatFromDoc(owner); if (result.isFail()) return result; result = await onLoadSeasonPassFromDoc(owner); if (result.isFail()) return result; var server_logic = GameServerApp.getServerLogic(); var nickname_attribute = owner.getEntityAttribute(); NullReferenceCheckHelper.throwIfNull(nickname_attribute, () => $"nickname_attribute is null !!! - {owner.toBasicString()}"); var player_manager = server_logic.getPlayerManager(); var buff_action = owner.getEntityAction(); NullReferenceCheckHelper.throwIfNull(buff_action, () => $"buff_action is null !!! - {owner.toBasicString()}"); result = await buff_action.loadBuff(); if (result.isFail()) { return result; } // 유저의 Nickname을 PlayerManager에 SubKey로 등록 한다. result = player_manager.trySubKeyBindToPrimaryKey(nickname_attribute.Nickname, owner.getUserGuid(), owner); if (result.isFail()) { return result; } return result; } protected virtual async Task onLoadUserFromDoc(Player owner) { var result = new Result(); var server_logic = GameServerApp.getServerLogic(); var user_attribute = owner.getEntityAttribute(); NullReferenceCheckHelper.throwIfNull(user_attribute, () => $"user_attribute is null !!! - {owner.toBasicString()}"); var entity_attribute_owner = owner; var batch = new QueryBatchEx( owner, LogActionType.UserLoading , server_logic.getDynamoDbClient() , false, getTransactGuid() ); { var user_guid = user_attribute.UserGuid; batch.addQuery(new DBQEntityReadToAttribute(entity_attribute_owner, user_guid, new[] { typeof(CraftHelpAttribute) })); batch.addQuery(new DBQEntityReadToAttribute(entity_attribute_owner, user_guid, new[] { typeof(NicknameAttribute) })); batch.addQuery(new DBQEntityReadToAttribute(entity_attribute_owner, user_guid, new[] { typeof(LevelAttribute) })); batch.addQuery(new DBQEntityReadToAttribute(entity_attribute_owner, user_guid, new[] { typeof(MoneyAttribute) })); batch.addQuery(new DBQEntityReadToAttribute(entity_attribute_owner, user_guid, new[] { typeof(CaliumAttribute) })); batch.addQuery(new DBQEntityReadToAttribute(entity_attribute_owner, user_guid, new[] { typeof(MailProfileAttribute) })); batch.addQuery(new DBQEntityReadToAttribute(entity_attribute_owner, user_guid, new[] { typeof(GameOptionAttribute) })); batch.addQuery(new DBQEntityReadToAttribute(entity_attribute_owner, user_guid, new[] { typeof(CharacterProfileAttribute) })); batch.addQuery(new DBQEntityReadToAttribute(entity_attribute_owner, user_guid, new[] { typeof(LocationAttribute) })); batch.addQuery(new DBQEntityReadToAttribute(entity_attribute_owner, user_guid, new[] { typeof(EscapePositionAttribute) })); batch.addQuery(new DBQEntityReadToAttribute(entity_attribute_owner, user_guid, new[] { typeof(SeasonPassAttribute) })); batch.addQuery(new DBQEntityReadToAttribute(entity_attribute_owner, user_guid, new[] { typeof(UserContentsSettingAttribute) })); batch.addQuery(new DBQEntityReadToAttribute(entity_attribute_owner, user_guid, new[] { typeof(PackageLastOrderRecodeAttribute) })); batch.addQuery(new DBQEntityReadToAttribute(entity_attribute_owner, user_guid, new[] { typeof(PackageRepeatAttribute) })); batch.addQuery(new DBQEntityReadToAttribute(entity_attribute_owner, user_guid, new[] { typeof(AiChatAttribute) })); batch.addQuery(new DBQItemReadAll(OwnerEntityType.User)); batch.addQuery(new DBQShopProductTradingMeterReadAll(user_guid)); batch.addQuery(new DBQRentalReadAll(user_guid)); batch.addQuery(new DBQOwnedBuildingReadAll(user_guid)); batch.addQuery(new DBQOwnedLandReadAll(user_guid)); batch.addQuery(new DBQSocailActionReadAll(user_guid)); batch.addQuery(new DBQToolActionRead(user_guid)); batch.addQuery(new DBQRoomReadAll(user_guid)); batch.addQuery(new DBQMinimapMarkerReadAll(user_guid)); batch.addQuery(new DBQItemFirstPurchaseHistoryReadAll(user_guid)); batch.addQuery(new DBQRentalInstanceVisitReadAll(user_guid)); batch.addQuery(new DBQDailyQuestCheckReadAll(user_guid));//legacy batch.addQuery(new DBQSwitchingPropReadAll(user_guid)); batch.addQuery(new DBQQuestPeriodRepeatReadAll(user_guid)); batch.addQuery(new DBQCartReadAll(user_guid)); batch.addQuery(new DBQMailReadAll(user_guid)); batch.addQuery(new DBQCraftReadAll(user_guid)); batch.addQuery(new DBQCraftRecipeReadAll(user_guid)); batch.addQuery(new DBQTaskReservationReadAll(user_guid)); batch.addQuery(new DBQPackageRepeatReadAll(user_guid)); batch.addQuery(new DBQClaimReadAll(user_guid)); batch.addQuery(new DBQFriendsReadAll(user_guid)); //friendFolder는 클라와 협의후 customDefineUI 로 변경하고 이후 DBQFriendFoldersReadAll은 미사용 예정 batch.addQuery(new DBQFriendFoldersReadAll(user_guid)); batch.addQuery(new DBQQuestsReadAll(user_guid)); batch.addQuery(new DBQEndQuestsReadAll(user_guid)); batch.addQuery(new DBQQuestMailsReadAll(user_guid)); batch.addQuery(new DBQBlockUsersReadAll(user_guid)); batch.addQuery(new DBQRepeatQuestRead(user_guid)); batch.addQuery(new DBQCustomDefinedUiReadAll(OwnerEntityType.User)); batch.addQuery(new DBQUgqDailyRewardCountRead(user_guid)); batch.addQuery(new DBQBeaconShopSoldReadAll(user_guid)); batch.addQuery(new QueryFinal()); } result = await QueryHelper.sendQueryAndBusinessLog(batch); if (result.isFail()) { return result; } return result; } protected virtual async Task onLoadUgcNpcFromDoc(Player owner) { var result = new Result(); var server_logic = GameServerApp.getServerLogic(); var user_attribute = owner.getEntityAttribute(); NullReferenceCheckHelper.throwIfNull(user_attribute, () => $"user_attribute is null !!! - {owner.toBasicString()}"); var entity_attribute_owner = owner; var batch = new QueryBatchEx( owner, LogActionType.UserLoading , server_logic.getDynamoDbClient() , false, getTransactGuid() ); { var user_guid = user_attribute.UserGuid; batch.addQuery(new DBQUgcNpcReadAll(user_guid)); batch.addQuery(new DBQItemReadAll(OwnerEntityType.UgcNpc)); batch.addQuery(new DBQCustomDefinedUiReadAll(OwnerEntityType.UgcNpc)); batch.addQuery(new QueryFinal()); } result = await QueryHelper.sendQueryAndBusinessLog(batch); if (result.isFail()) { return result; } return result; } protected virtual async Task onLoadFarmingEffectFromDoc(Player owner) { var result = new Result(); var err_msg = string.Empty; var server_logic = GameServerApp.getServerLogic(); // by Player await FarmingHelper.tryFinalyzeUncompletedFarmingByOwner(owner); // by UgcNpc All var player_action = owner.getEntityAction(); NullReferenceCheckHelper.throwIfNull(player_action, () => $"player_action is null !!! - {owner.toBasicString()}"); var ugc_npcs = player_action.getHadUgcNpcs(); foreach (var each in ugc_npcs) { var ugc_npc = each.Value; (result, var is_farming_force_release) = await FarmingHelper.tryFinalyzeUncompletedFarmingByOwner(ugc_npc, this); if (result.isFail()) { err_msg = $"Failed to tryFinalyzeUncompletedFarmingByOwner() !!! : {result.toBasicString()} - {ugc_npc.toBasicString()}, {owner.toBasicString()}"; ServerCore.Log.getLogger().error(err_msg); } if(true == is_farming_force_release) { // 파밍을 강제 해제 한다. !!! var farming_action = ugc_npc.getEntityAction(); NullReferenceCheckHelper.throwIfNull(farming_action, () => $"farming_action is null !!! - {ugc_npc.toBasicString()}, {owner.toBasicString()}"); var reset_result = await farming_action.resetFarmingState(); if (reset_result.isFail()) { err_msg = $"Failed to resetFarmingState() !!! : {reset_result.toBasicString()} - {ugc_npc.toBasicString()}, {owner.toBasicString()}"; ServerCore.Log.getLogger().error(err_msg); } else { err_msg = $"Farming force released !!!, in onLoadFarmingEffectFromDoc() - {ugc_npc.toBasicString()}, {owner.toBasicString()}"; Log.getLogger().debug(err_msg); } } } } protected virtual async Task onLoadMyhomeFromDoc(Player owner) { var result = new Result(); var server_logic = GameServerApp.getServerLogic(); var user_attribute = owner.getEntityAttribute(); NullReferenceCheckHelper.throwIfNull(user_attribute, () => $"user_attribute is null !!! - {owner.toBasicString()}"); var batch = new QueryBatchEx( owner, LogActionType.UserLoading , server_logic.getDynamoDbClient() , false, getTransactGuid() ); { var user_guid = user_attribute.UserGuid; batch.addQuery(new DBQMyhomeReadAll(user_guid)); batch.addQuery(new DBQItemReadAll(OwnerEntityType.Myhome)); batch.addQuery(new QueryFinal(), tryUpdateUserLoadStep); } result = await QueryHelper.sendQueryAndBusinessLog(batch); if (result.isFail()) { return result; } return result; } protected virtual async Task onLoadSeasonPassFromDoc(Player owner) { var result = new Result(); var server_logic = GameServerApp.getServerLogic(); var season_pass_action = owner.getEntityAction(); NullReferenceCheckHelper.throwIfNull(season_pass_action, () => $"season_pass_action is null !!! - {owner.toBasicString()}"); result = await season_pass_action.tryUpdateSeasonPass(getTransactGuid()); if (result.isFail()) { return result; } return result; } protected async Task tryUpdateUserLoadStep(QueryExecutorBase queryExecutorBase) { await Task.CompletedTask; var err_msg = string.Empty; var owner = getOwner() as Player; NullReferenceCheckHelper.throwIfNull(owner, () => $"owner is null !!!"); var user_create_or_load_action = owner.getEntityAction(); NullReferenceCheckHelper.throwIfNull(user_create_or_load_action, () => $"user_create_or_load_action is null !!! - {owner.toBasicString()}"); var query_batch = queryExecutorBase.getQueryBatch(); NullReferenceCheckHelper.throwIfNull(query_batch, () => $"query_batch is null !!! - {owner.toBasicString()}"); var log_action = query_batch.getLogAction(); NullReferenceCheckHelper.throwIfNull(log_action, () => $"log_action is null !!! - {owner.toBasicString()}"); m_user_log.setInfo(owner.toUserLogInfo()); // 비즈니스 로그 추가 query_batch.appendBusinessLog(new UserBusinessLog(log_action, m_user_log)); user_create_or_load_action.onClear(); getLoadResult().setSuccess(); setCompleted(); return QueryBatchBase.QueryResultType.Success; } protected virtual async Task onLoadPackageFromDoc(Player owner) { var result = new Result(); var package_action = owner.getEntityAction(); NullReferenceCheckHelper.throwIfNull(package_action, () => $"package_action is null !!! - {owner.toBasicString()}"); result = await package_action.InsertPackageLastOrderRecodeDoc(); if (result.isFail()) { return result; } await package_action.tryOrderNewProductList(); return result; } protected virtual async Task onLoadAiChatFromDoc(Player owner) { var result = new Result(); var ai_chat_attribute = owner.getEntityAttribute(); NullReferenceCheckHelper.throwIfNull(ai_chat_attribute, () => $"ai_chat_attribute is null !!! - {owner.toBasicString()}"); var ai_chat_doc = ai_chat_attribute.getOriginDocBase(); if (ai_chat_doc == null) { var server_logic = GameServerApp.getServerLogic(); var dynamo_db_client = server_logic.getDynamoDbClient(); ArgumentNullException.ThrowIfNull(dynamo_db_client); result = await dynamo_db_client.simpleInsertDocumentWithDocType(new AiChatDoc(owner.getUserGuid())); if (result.isFail()) { var err_msg = $"Failed to simpleInsertDocumentWithDocType !!! - {owner.toBasicString()}"; Log.getLogger().error(err_msg); return result; } } return result; } protected virtual async Task onLoadNftFromUrl(Player owner) { var result = new Result(); var err_msg = string.Empty; var server_logic = GameServerApp.getServerLogic(); var account_attribute = owner.getEntityAttribute(); NullReferenceCheckHelper.throwIfNull(account_attribute, () => $"account_attribute is null !!! - {owner.toBasicString()}"); var to_check_item_meta_id = MetaHelper.GameConfigMeta.CPNFTHolderKeyItem; if(0 >= to_check_item_meta_id) { err_msg = $"Invalid ItemMetaId !!!, GameConfigMeta.CPNFTHolderKeyItem !!! : {to_check_item_meta_id} - {owner.toBasicString()}"; Log.getLogger().error(err_msg); return result; } (var nft_result, var is_found) = await NFTHelper.hasStakedNft(account_attribute.SsoAccountAuthJWT); if (nft_result.isFail()) { err_msg = $"Failed to NFTHelper.hasStakedNft() !!! : {nft_result.toBasicString()} - {owner.toBasicString()}"; Log.getLogger().error(err_msg); } else { var to_write_docs = new List(); var user_inventory_action = owner.getEntityAction(); NullReferenceCheckHelper.throwIfNull(user_inventory_action, () => $"user_inventory_action is null !!! - {owner.toBasicString()}"); if (false == is_found) { // 보유중인 CPNFTHolderKeyItem 을 모두 삭제 한다. (var delete_result, var to_delete_items) = await user_inventory_action.tryDeleteItemByMetaId((META_ID)to_check_item_meta_id); if (delete_result.isFail()) { err_msg = $"Failed to tryDeleteItemByMetaId() !!! : {delete_result.toBasicString()} - {owner.toBasicString()}"; Log.getLogger().error(err_msg); return result; } foreach(var delete_item in to_delete_items) { var item_attribute = delete_item.getEntityAttribute(); NullReferenceCheckHelper.throwIfNull(item_attribute, () => $"item_attribute is null !!! - {owner.toBasicString()}"); (var doc_result, var doc) = await item_attribute.toDocBase(); if(doc_result.isFail()) { err_msg = $"Failed to toDocBase() !!!, at tryDeleteItemByMetaId() : {doc_result.toBasicString()} - {item_attribute.toBasicString()}, {owner.toBasicString()}"; Log.getLogger().error(err_msg); continue; } NullReferenceCheckHelper.throwIfNull(doc, () => $"doc is null !!! - {owner.toBasicString()}"); to_write_docs.Add(doc); } } else { // 보유중인 CPNFTHolderKeyItem 이 없다면, 지급해 준다. !!! if (false == user_inventory_action.hasItemByMetaId((META_ID)to_check_item_meta_id)) { (var add_result, var to_add_items) = await user_inventory_action.tryTakalbleToBag((META_ID)to_check_item_meta_id); if(add_result.isFail()) { err_msg = $"Failed to tryTakalbleToBag() !!! : {add_result.toBasicString()} - {owner.toBasicString()}"; Log.getLogger().error(err_msg); } foreach (var add_item in to_add_items) { var item_attribute = add_item.getEntityAttribute(); NullReferenceCheckHelper.throwIfNull(item_attribute, () => $"item_attribute is null !!! - {owner.toBasicString()}"); (var doc_result, var doc) = await item_attribute.toDocBase(); if (doc_result.isFail()) { err_msg = $"Failed to toDocBase() !!!, at tryTakalbleToBag() : {doc_result.toBasicString()} - {item_attribute.toBasicString()}, {owner.toBasicString()}"; Log.getLogger().error(err_msg); continue; } NullReferenceCheckHelper.throwIfNull(doc, () => $"doc is null !!! - {owner.toBasicString()}"); to_write_docs.Add(doc); } } } var batch = new QueryBatchEx( owner, LogActionType.UserLoading , server_logic.getDynamoDbClient() , false, getTransactGuid() ); { batch.addQuery(new DBQEntityWrite(to_write_docs)); batch.addQuery(new QueryFinal()); } result = await QueryHelper.sendQueryAndBusinessLog(batch); if (result.isFail()) { return result; } } return result; } public void pushProgressFarmingSummary(FarmingSummary progressFarmingSummary) { m_progress_farming_summaries.Add(progressFarmingSummary); } public List getProgressFarmingSummaryAll() => m_progress_farming_summaries; public string getTransactGuid() => m_transact_guid; }