using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using Newtonsoft.Json; using Amazon.DynamoDBv2; using Amazon.DynamoDBv2.Model; using Amazon.DynamoDBv2.DocumentModel; using Amazon.Runtime; using ServerCore; using ServerBase; using ServerCommon; using ServerCommon.BusinessLogDomain; 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 Pipelines.Sockets.Unofficial.Buffers; namespace GameServer { public class DBQCharacterReadAll : QueryExecutorBase { private string m_combination_key_for_pk = string.Empty; private string m_pk = string.Empty; private readonly List m_to_read_character_base_docs = new(); public DBQCharacterReadAll(string combinationKeyForPK) : base(typeof(DBQCharacterReadAll).Name) { m_combination_key_for_pk = combinationKeyForPK; } //===================================================================================== // DB 쿼리 직전에 준비해야 할 로직들을 작성한다. //===================================================================================== public override async Task onPrepareQuery() { await Task.CompletedTask; var result = new Result(); var err_msg = string.Empty; var owner = getOwner(); NullReferenceCheckHelper.throwIfNull(owner, () => "owner is null !!!"); var doc = new CharacterBaseDoc(); doc.setCombinationKeyForPK(m_combination_key_for_pk); var error_code = doc.onApplyPKSK(); if(error_code.isFail()) { err_msg = $"Failed to onApplyPKSK() !!! : {error_code.toBasicString()} - {toBasicString()}, {owner.toBasicString()}"; result.setFail(error_code, err_msg); Log.getLogger().error(result.toBasicString()); return result; } m_pk = doc.getPK(); return result; } //===================================================================================== // onPrepareQuery()를 성공할 경우 호출된다. //===================================================================================== public override async Task onQuery() { await Task.CompletedTask; var result = new Result(); var err_msg = string.Empty; var owner = getOwner() as Player; NullReferenceCheckHelper.throwIfNull(owner, () => "owner is null !!!"); var query_batch = getQueryBatch(); NullReferenceCheckHelper.throwIfNull(query_batch, () => "query_batch is null !!!"); var db_connector = query_batch.getDynamoDbConnector(); var query_config = db_connector.makeQueryConfigForReadByPKOnly(m_pk); (result, var read_docs) = await db_connector.simpleQueryDocTypesWithQueryOperationConfig(query_config, eventTid: query_batch.getTransId()); if(result.isFail()) { return result; } var character_max_create_count = MetaHelper.GameConfigMeta.CharacterCreateMaxCount; if (read_docs.Count > character_max_create_count) { err_msg = $"Character Max Count Exceeded !!! : loadedCount:{read_docs.Count} <= CharacterMaxCount:{character_max_create_count} - {toBasicString()}, {owner.toBasicString()}"; Log.getLogger().error(err_msg); } // 1. 기본 캐릭터가 선택 되어 있는지 체크 한다. var user_attribute = owner.getEntityAttribute(); NullReferenceCheckHelper.throwIfNull(user_attribute, () => "user_attribute is null !!!"); var selected_character_guid = user_attribute.SelectedCharacterGuid; if(true == selected_character_guid.isNullOrWhiteSpace()) { err_msg = $"Not selected Character !!! : loadedCharacterCount:{read_docs.Count}, CharacterMaxCount:{character_max_create_count} - {toBasicString()}, {owner.toBasicString()}"; result.setFail(ServerErrorCode.CharacterNotSelected, err_msg); Log.getLogger().error(result.toBasicString()); return result; } // 2. 선택된 캐릭터가 존재하는지 체크 한다. var found_selected_character_base_doc = read_docs.Find(x => x.getAttrib()?.CharacterGuid == selected_character_guid); if (null == found_selected_character_base_doc) { err_msg = $"Not found Character !!! : selectedCharacterGuid:{selected_character_guid}, loadedCharacterCount:{read_docs.Count}, CharacterMaxCount:{MetaHelper.GameConfigMeta.CharacterCreateMaxCount} - {toBasicString()}, {owner.toBasicString()}"; result.setFail(ServerErrorCode.CharacterNotFound, err_msg); Log.getLogger().error(result.toBasicString()); return result; } // 3. 선택된 캐릭터를 먼저 로딩 한다. var user_create_or_load_action = owner.getEntityAction(); NullReferenceCheckHelper.throwIfNull(user_attribute, () => "user_attribute is null !!!"); result = await user_create_or_load_action.tryLoadCharacterByChracterBaseDoc(found_selected_character_base_doc); if(result.isFail()) { return result; } m_to_read_character_base_docs.Add(found_selected_character_base_doc); read_docs.Remove(found_selected_character_base_doc); character_max_create_count -= 1; // 4. 나머지 캐릭터를 로딩 한다. for(var i = 0; i < character_max_create_count; i++) { var remain_character_base_doc = read_docs[i]; result = await user_create_or_load_action.tryLoadCharacterByChracterBaseDoc(remain_character_base_doc); if (result.isFail()) { return result; } m_to_read_character_base_docs.Add(remain_character_base_doc); } return result; } public List getToReadCharacterBaseDocs() => m_to_read_character_base_docs; //===================================================================================== // DB 쿼리를 성공하고, doFnCommit()가 QueryResultType.NotCalledQueryFunc를 반환할 경우 호출된다. //===================================================================================== public override async Task onQueryResponseCommit() { await Task.CompletedTask; return; } //===================================================================================== // DB 쿼리를 실패하고, doFnRollback()가 QueryResultType.NotCalledQueryFunc를 반환할 경우 호출된다. //===================================================================================== public override async Task onQueryResponseRollback(Result errorResult) { await Task.CompletedTask; return; } public new Player? getOwner() => getQueryBatch()?.getLogActor() as Player; } }