1145 lines
41 KiB
C#
1145 lines
41 KiB
C#
using Google.Protobuf;
|
|
using Google.Protobuf.WellKnownTypes;
|
|
|
|
|
|
using ServerCore;
|
|
using ServerBase;
|
|
using ServerCommon;
|
|
using ServerCommon.BusinessLogDomain;
|
|
using MetaAssets;
|
|
|
|
|
|
using static ClientToGameRes.Types;
|
|
using static ClientToGameMessage.Types;
|
|
|
|
|
|
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;
|
|
|
|
|
|
namespace GameServer;
|
|
|
|
public class UserCreateOrLoadAction : EntityActionBase
|
|
{
|
|
private readonly List<EntityCreatorBase> m_user_create_triggers = new();
|
|
private readonly List<EntityLoaderBase> m_user_load_triggers = new();
|
|
|
|
private Character? m_reserved_chacter_for_creation_nullable;
|
|
|
|
private bool m_test_User = false;
|
|
|
|
private bool m_is_first_login = false;
|
|
private bool m_is_completed_start_load_user = false;
|
|
private bool m_is_completed_end_load_user = false;
|
|
|
|
public UserCreateOrLoadAction(Player owner)
|
|
: base(owner)
|
|
{
|
|
}
|
|
|
|
public override async Task<Result> onInit()
|
|
{
|
|
await Task.CompletedTask;
|
|
|
|
var result = new Result();
|
|
|
|
return result;
|
|
}
|
|
|
|
public override void onClear()
|
|
{
|
|
onClearUserCreators();
|
|
}
|
|
|
|
public void onClearUserCreators()
|
|
{
|
|
m_user_create_triggers.Clear();
|
|
}
|
|
|
|
public async Task<Result> tryCreateOrLoadUser()
|
|
{
|
|
var result = new Result();
|
|
var err_msg = string.Empty;
|
|
|
|
var owner = getOwner() as Player;
|
|
NullReferenceCheckHelper.throwIfNull(owner, () => $"owner is null !!!");
|
|
|
|
var server_logic = GameServerApp.getServerLogic();
|
|
NullReferenceCheckHelper.throwIfNull(server_logic, () => $"server_logic is null !!! - {owner.toBasicString()}");
|
|
var server_config = server_logic.getServerConfig();
|
|
NullReferenceCheckHelper.throwIfNull(server_config, () => $"server_config is null !!! - {owner.toBasicString()}");
|
|
|
|
var account_attribute = owner.getEntityAttribute<AccountAttribute>();
|
|
NullReferenceCheckHelper.throwIfNull(account_attribute, () => $"account_attribute is null !!! - {owner.toBasicString()}");
|
|
var user_attribute = owner.getEntityAttribute<UserAttribute>();
|
|
NullReferenceCheckHelper.throwIfNull(user_attribute, () => $"user_attribute is null !!! - {owner.toBasicString()}");
|
|
|
|
var account_id = account_attribute.AccountId;
|
|
var user_guid = account_attribute.UserGuid;
|
|
|
|
// 1. Cache 서버에서 로그인 User 정보를 읽어온다.
|
|
(result, var login_cache_request) = await tryLoadUserInfoFromCache();
|
|
if(result.isFail())
|
|
{
|
|
return result;
|
|
}
|
|
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()}");
|
|
|
|
// 2. User 정보 읽기 or 생성 한다.
|
|
(result, var found_user_base_doc) = await findUserInfoInDb(user_guid);
|
|
if (result.isSuccess())
|
|
{
|
|
// 2.1. 생성된 User 정보가 없는 경우 : User 정보를 생성 한다.
|
|
if (null == found_user_base_doc)
|
|
{
|
|
result = await prepareCreateUser();
|
|
if (result.isFail())
|
|
{
|
|
return result;
|
|
}
|
|
}
|
|
// 2.2. 생성된 User 정보가 있는 경우 : 캐릭터 정보가 있는지 체크하고 없으면 생성 한다.
|
|
else
|
|
{
|
|
// UserBaseDoc => UserAttribute 채우기
|
|
if (false == user_attribute.copyEntityAttributeFromDoc(found_user_base_doc))
|
|
{
|
|
err_msg = $"Failed to copyEntityAttributeFromDoc() !!!, to:{user_attribute.getTypeName()}, from:{found_user_base_doc.getTypeName()}";
|
|
result.setFail(ServerErrorCode.DynamoDbDocCopyToEntityAttributeFailed, err_msg);
|
|
Log.getLogger().error(result.toBasicString());
|
|
|
|
return result;
|
|
}
|
|
|
|
(result, _) = await tryGetOrCreateCharacter();
|
|
if (result.isFail())
|
|
{
|
|
return result;
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
return result;
|
|
}
|
|
|
|
user_attribute.GameLoginDateTime = owner.getLoginStartTime();
|
|
|
|
bool is_first_login = login_cache.ServerSwitchCount == 1 ? true : false;
|
|
|
|
// 3. 테스트 유저의 초기화 설정이 가능한 경우
|
|
if ( true == server_config.AuthRule.TestUserAllow // 테스트 User를 허용한 경우
|
|
&& false == hasUserCreateTrigger() // User 정보를 생성하고 있지 않는 경우
|
|
&& false == hasCharacterCreateTrigger() // Characger 정보를 생성하고 있지 않는 경우
|
|
&& true == isCreatedUserNickname() // User 닉네임이 생성된 경우
|
|
&& true == is_first_login ) // 게임 서버 첫번째 로그인인 경우
|
|
{
|
|
// 테스트 유저일 경우 초기화 설정을 적용 한다.
|
|
result = await initializeUser4Test();
|
|
if (result.isFail())
|
|
{
|
|
return result;
|
|
}
|
|
}
|
|
|
|
setFirstLogin(is_first_login);
|
|
|
|
// 4. User 읽기를 위한 준비 상태 체크 : 성공일 경우 유저 정보를 로딩한다.
|
|
result = await prepareLoadUser();
|
|
if (result.isSuccess())
|
|
{
|
|
// 4.1. User 정보를 로딩 한다.
|
|
result = await tryLoadUser();
|
|
if (result.isFail())
|
|
{
|
|
err_msg = $"Failed to tryLoadUser() !!! : {result.toBasicString()} - {owner.toBasicString()}";
|
|
Log.getLogger().error(err_msg);
|
|
|
|
return result;
|
|
}
|
|
}
|
|
|
|
// 5. User 관련 추가 처리후 로딩 한다.
|
|
result = await onLoadAfterUserActive();
|
|
if (result.isFail())
|
|
{
|
|
return result;
|
|
}
|
|
|
|
// 6. User의 각종 주요 정보들을 클라이언트에게 통지 한다.
|
|
await notifyUserInfo();
|
|
|
|
// 7. User 관련 추가 정보들을 클라이언트에게 통지 한다.
|
|
result = await onNotifyAfterUserActive();
|
|
if (result.isFail())
|
|
{
|
|
return result;
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
public async Task<(Result, UserBaseDoc?)> findUserInfoInDb(string userGuid)
|
|
{
|
|
var result = new Result();
|
|
var err_msg = string.Empty;
|
|
|
|
var owner = getOwner() as Player;
|
|
ArgumentNullException.ThrowIfNull(owner, $"owner is null !!!");
|
|
|
|
var server_logic = GameServerApp.getServerLogic();
|
|
NullReferenceCheckHelper.throwIfNull(server_logic, () => $"server_logic is null !!! - {owner.toBasicString()}");
|
|
var server_config = server_logic.getServerConfig();
|
|
NullReferenceCheckHelper.throwIfNull(server_config, () => $"server_config is null !!! - {owner.toBasicString()}");
|
|
var dynamo_db_client = server_logic.getDynamoDbClient();
|
|
NullReferenceCheckHelper.throwIfNull(dynamo_db_client, () => $"dynamo_db_client is null !!! - {owner.toBasicString()}");
|
|
|
|
(result, var user_primary_key) = await DynamoDBDocBaseHelper.makePrimaryKey<UserBaseDoc>(userGuid);
|
|
if (result.isFail())
|
|
{
|
|
return (result, null);
|
|
}
|
|
ArgumentNullException.ThrowIfNull(user_primary_key, $"user_primary_key is null !!! - {owner.toBasicString()}");
|
|
|
|
var query_config = dynamo_db_client.makeQueryConfigForReadByPKSK(user_primary_key.PK);
|
|
(result, var found_user_base_doc) = await dynamo_db_client.simpleQueryDocTypeWithQueryOperationConfig<UserBaseDoc>(query_config, false);
|
|
if (result.isFail())
|
|
{
|
|
return (result, null);
|
|
}
|
|
|
|
return (result, found_user_base_doc);
|
|
}
|
|
|
|
private async Task<(Result, CharacterBaseDoc?)> tryGetOrCreateCharacter()
|
|
{
|
|
var result = new Result();
|
|
var err_msg = string.Empty;
|
|
|
|
var owner = getOwner() as Player;
|
|
ArgumentNullException.ThrowIfNull(owner, $"owner is null !!!");
|
|
|
|
var server_logic = GameServerApp.getServerLogic();
|
|
NullReferenceCheckHelper.throwIfNull(server_logic, () => $"server_logic is null !!! - {owner.toBasicString()}");
|
|
var server_config = server_logic.getServerConfig();
|
|
NullReferenceCheckHelper.throwIfNull(server_config, () => $"server_config is null !!! - {owner.toBasicString()}");
|
|
var dynamo_db_client = server_logic.getDynamoDbClient();
|
|
NullReferenceCheckHelper.throwIfNull(dynamo_db_client, () => $"dynamo_db_client is null !!! - {owner.toBasicString()}");
|
|
|
|
var user_attribute = owner.getEntityAttribute<UserAttribute>();
|
|
NullReferenceCheckHelper.throwIfNull(user_attribute, () => $"user_attribute is null !!! - {owner.toBasicString()}");
|
|
|
|
var user_guid = user_attribute.UserGuid;
|
|
|
|
// 선택된 캐릭터 Guid가 존재하는지 체크 하고, CharacterBaseDoc도 존재하는지 체크 한다.
|
|
var character_guild = user_attribute.SelectedCharacterGuid;
|
|
if (true == character_guild.isNullOrWhiteSpace())
|
|
{
|
|
result = await prepareCreateCharacter();
|
|
if (result.isFail())
|
|
{
|
|
err_msg = $"Failed to prepareCreateCharacter() !!! : {result.toBasicString()} - {owner.toBasicString()}";
|
|
Log.getLogger().error(err_msg);
|
|
|
|
return (result, null);
|
|
}
|
|
}
|
|
|
|
(result, var character_primary_key) = await DynamoDBDocBaseHelper.makePrimaryKey<CharacterBaseDoc>(user_guid, character_guild);
|
|
if (result.isFail())
|
|
{
|
|
return (result, null);
|
|
}
|
|
ArgumentNullException.ThrowIfNull(character_primary_key, $"character_primary_key is null !!! - {owner.toBasicString()}");
|
|
|
|
var query_config = dynamo_db_client.makeQueryConfigForReadByPKSK(character_primary_key.PK, character_primary_key.SK);
|
|
(result, var found_character_base_doc) = await dynamo_db_client.simpleQueryDocTypeWithQueryOperationConfig<CharacterBaseDoc>(query_config);
|
|
if (result.isFail())
|
|
{
|
|
err_msg = $"Failed to simpleQueryDocTypeWithQueryOperationConfig<CharacterBaseDoc>() !!! : {result.toBasicString()} - {owner.toBasicString()}";
|
|
Log.getLogger().error(err_msg);
|
|
return (result, null);
|
|
}
|
|
|
|
return (result, found_character_base_doc);
|
|
}
|
|
|
|
private async Task<(Result, LoginCacheRequest?)> tryLoadUserInfoFromCache()
|
|
{
|
|
var result = new Result();
|
|
var err_msg = string.Empty;
|
|
|
|
var owner = getOwner() as Player;
|
|
ArgumentNullException.ThrowIfNull(owner, $"owner is null !!!");
|
|
|
|
var server_logic = GameServerApp.getServerLogic();
|
|
ArgumentNullException.ThrowIfNull(server_logic, $"server_logic is null !!! - {owner.toBasicString()}");
|
|
var server_config = server_logic.getServerConfig();
|
|
ArgumentNullException.ThrowIfNull(server_config, $"server_config is null !!! - {owner.toBasicString()}");
|
|
var dynamo_db_client = server_logic.getDynamoDbClient();
|
|
ArgumentNullException.ThrowIfNull(dynamo_db_client, $"dynamo_db_client is null !!! - {owner.toBasicString()}");
|
|
|
|
var account_attribute = owner.getEntityAttribute<AccountAttribute>();
|
|
ArgumentNullException.ThrowIfNull(account_attribute, $"account_attribute is null !!! - {owner.toBasicString()}");
|
|
|
|
var account_id = account_attribute.AccountId;
|
|
(result, var make_primary_key) = await DynamoDBDocBaseHelper.makePrimaryKey<AccountBaseDoc>(account_id);
|
|
if (result.isFail())
|
|
{
|
|
return (result, null);
|
|
}
|
|
ArgumentNullException.ThrowIfNull(make_primary_key, $"make_primary_key is null !!! - {owner.toBasicString()}");
|
|
|
|
// DB => AccountBaseDoc 채우기
|
|
var query_config = dynamo_db_client.makeQueryConfigForReadByPKSK(make_primary_key.PK);
|
|
(result, var found_account_base_doc) = await dynamo_db_client.simpleQueryDocTypeWithQueryOperationConfig<AccountBaseDoc>(query_config);
|
|
if (result.isFail())
|
|
{
|
|
err_msg = $"Failed to simpleQueryDocTypeWithQueryOperationConfig() !!! : {result.toBasicString()}, {make_primary_key.toBasicString()} - {owner.toBasicString()}";
|
|
Log.getLogger().error(err_msg);
|
|
|
|
return (result, null);
|
|
}
|
|
ArgumentNullException.ThrowIfNull(found_account_base_doc, $"found_account_base_doc is null !!! - {owner.toBasicString()}");
|
|
|
|
// AccountBaseDoc => Attribute 채우기
|
|
if (false == account_attribute.copyEntityAttributeFromDoc(found_account_base_doc))
|
|
{
|
|
err_msg = $"Failed to copyEntityAttributeFromDoc() !!!, to:{account_attribute.getTypeName()}, from:{found_account_base_doc.getTypeName()}";
|
|
result.setFail(ServerErrorCode.DynamoDbDocCopyToEntityAttributeFailed, err_msg);
|
|
Log.getLogger().error(result.toBasicString());
|
|
|
|
return (result, null);
|
|
}
|
|
|
|
var user_guid = account_attribute.UserGuid;
|
|
if (true == user_guid.isNullOrWhiteSpace())
|
|
{
|
|
err_msg = $"AccountAttribute.UserGuid is true == isNullOrWhiteSpace() !!! : userGuid:{user_guid} - {owner.toBasicString()}";
|
|
result.setFail(ServerErrorCode.UserGuidInvalid, err_msg);
|
|
Log.getLogger().error(result.toBasicString());
|
|
|
|
return (result, null);
|
|
}
|
|
|
|
if (false == server_logic.getPlayerManager().tryGetUserByPrimaryKey(user_guid, out _))
|
|
{
|
|
err_msg = $"Failed to PlayerManager.tryGetUserByPrimaryKey() !!!, User Not login : userGuid:{user_guid} - {owner.toBasicString()}";
|
|
Log.getLogger().error(result.toBasicString());
|
|
|
|
return (result, null);
|
|
}
|
|
|
|
var game_login_action = owner.getEntityAction<GameLoginAction>();
|
|
ArgumentNullException.ThrowIfNull(game_login_action, $"game_login_action is null !!! - {owner.toBasicString()}");
|
|
var user_create_or_load_action = owner.getEntityAction<UserCreateOrLoadAction>();
|
|
ArgumentNullException.ThrowIfNull(user_create_or_load_action, $"user_create_or_load_action is null !!! - {owner.toBasicString()}");
|
|
|
|
var login_cache_request = new LoginCacheRequest(owner, server_logic.getRedisConnector());
|
|
result = await login_cache_request.fetchLogin();
|
|
if (result.isFail())
|
|
{
|
|
return (result, null);
|
|
}
|
|
|
|
return (result, login_cache_request);
|
|
}
|
|
|
|
public async Task<Result> prepareCreateUser()
|
|
{
|
|
var result = new Result();
|
|
var err_msg = string.Empty;
|
|
|
|
var owner = getOwner() as Player;
|
|
NullReferenceCheckHelper.throwIfNull(owner, () => $"owner is null !!!");
|
|
|
|
bool is_create_test_user = false;
|
|
|
|
var server_logic = GameServerApp.getServerLogic();
|
|
NullReferenceCheckHelper.throwIfNull(server_logic, () => $"server_logic is null !!! - {owner.toBasicString()}");
|
|
|
|
var server_config = server_logic.getServerConfig();
|
|
NullReferenceCheckHelper.throwIfNull(server_config, () => $"server_config is null !!! - {owner.toBasicString()}");
|
|
|
|
// 테스트 계정 허용 상태인가?
|
|
if (true == server_config.AuthRule.TestUserAllow)
|
|
{
|
|
var account_attribute = owner.getEntityAttribute<AccountAttribute>();
|
|
NullReferenceCheckHelper.throwIfNull(account_attribute, () => $"account_attribute is null !!! - {owner.toBasicString()}");
|
|
|
|
var account_id = account_attribute.AccountId;
|
|
if (true == account_id.isTestAccount())
|
|
{
|
|
is_create_test_user = true;
|
|
}
|
|
}
|
|
|
|
if (true == is_create_test_user)
|
|
{
|
|
result = await prepareCreateUser4Test();
|
|
}
|
|
else
|
|
{
|
|
result = await prepareCreateUser4Default();
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
private async Task<Result> prepareCreateUser4Test()
|
|
{
|
|
var result = new Result();
|
|
|
|
var player = getOwner() as Player;
|
|
NullReferenceCheckHelper.throwIfNull(player, () => $"player is null !!!");
|
|
|
|
var test_user_creator = new TestUserCreator(player);
|
|
result = await test_user_creator.onPrepareCreate();
|
|
if (result.isFail())
|
|
{
|
|
return result;
|
|
}
|
|
|
|
m_user_create_triggers.Add(test_user_creator);
|
|
|
|
result = await prepareCreateCharacter4Test();
|
|
if (result.isFail())
|
|
{
|
|
return result;
|
|
}
|
|
|
|
Log.getLogger().info($"Step Prepare Create Test User & Character Success : prepareCreateUser4Test() - {player.toBasicString()}");
|
|
|
|
return result;
|
|
}
|
|
|
|
private async Task<Result> prepareCreateUser4Default()
|
|
{
|
|
var result = new Result();
|
|
|
|
var player = getOwner() as Player;
|
|
NullReferenceCheckHelper.throwIfNull(player, () => $"player is null !!!");
|
|
|
|
var default_user_creator = new DefaultUserCreator(player);
|
|
result = await default_user_creator.onPrepareCreate();
|
|
if (result.isFail())
|
|
{
|
|
return result;
|
|
}
|
|
|
|
m_user_create_triggers.Add(default_user_creator);
|
|
|
|
result = await prepareCreateCharacter4Default();
|
|
if (result.isFail())
|
|
{
|
|
return result;
|
|
}
|
|
|
|
Log.getLogger().info($"Step Prepare Create Default User & Character Success : prepareCreateUser4Default() - {player.toBasicString()}");
|
|
|
|
return result;
|
|
}
|
|
|
|
public bool hasUserCreateTrigger()
|
|
{
|
|
return 0 < m_user_create_triggers.Count;
|
|
}
|
|
|
|
public async Task<Result> tryCreateUser(string toCreateNickname)
|
|
{
|
|
var result = new Result();
|
|
|
|
var owner = getOwner() as Player;
|
|
NullReferenceCheckHelper.throwIfNull(owner, () => $"owner is null !!!");
|
|
|
|
var nickname_attribute = owner.getEntityAttribute<NicknameAttribute>();
|
|
NullReferenceCheckHelper.throwIfNull(nickname_attribute, () => $"nickname_attribute is null !!! - {owner.toBasicString()}");
|
|
|
|
nickname_attribute.Nickname = toCreateNickname;
|
|
nickname_attribute.modifiedEntityAttribute();
|
|
|
|
foreach (var event_trigger in m_user_create_triggers)
|
|
{
|
|
if ( (null == (event_trigger as DefaultUserCreator))
|
|
&& (null == (event_trigger as TestUserCreator)) )
|
|
{
|
|
continue;
|
|
}
|
|
|
|
return await event_trigger.onTriggerEffect();
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
public bool isCreatedUserNickname()
|
|
{
|
|
var result = new Result();
|
|
|
|
var owner = getOwner() as Player;
|
|
NullReferenceCheckHelper.throwIfNull(owner, () => $"owner is null !!!");
|
|
|
|
var account_attribute = owner.getEntityAttribute<AccountAttribute>();
|
|
NullReferenceCheckHelper.throwIfNull(account_attribute, () => $"account_attribute is null !!! - {owner.toBasicString()}");
|
|
|
|
var user_guid = account_attribute.UserGuid;
|
|
|
|
var server_logic = GameServerApp.getServerLogic();
|
|
NullReferenceCheckHelper.throwIfNull(server_logic, () => $"server_logic is null !!! - {owner.toBasicString()}");
|
|
var dynamo_db_client = server_logic.getDynamoDbClient();
|
|
NullReferenceCheckHelper.throwIfNull(dynamo_db_client, () => $"dynamo_db_client is null !!! - {owner.toBasicString()}");
|
|
|
|
(result, var user_primary_key) = DynamoDBDocBaseHelper.makePrimaryKey<NicknameDoc>(user_guid).GetAwaiter().GetResult();
|
|
if (result.isFail())
|
|
{
|
|
return false;
|
|
}
|
|
ArgumentNullException.ThrowIfNull(user_primary_key, $"user_primary_key is null !!! - {owner.toBasicString()}");
|
|
|
|
var query_config = dynamo_db_client.makeQueryConfigForReadByPKSK(user_primary_key.PK);
|
|
(result, _) = dynamo_db_client.simpleQueryDocTypeWithQueryOperationConfig<NicknameDoc>(query_config).GetAwaiter().GetResult();
|
|
if (result.isFail())
|
|
{
|
|
return false;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
public async Task<Result> prepareCreateCharacter()
|
|
{
|
|
var result = new Result();
|
|
var err_msg = string.Empty;
|
|
|
|
var player = getOwner() as Player;
|
|
NullReferenceCheckHelper.throwIfNull(player, () => $"player is null !!!");
|
|
|
|
bool is_create_test_user = false;
|
|
|
|
var server_logic = GameServerApp.getServerLogic();
|
|
var server_config = server_logic.getServerConfig();
|
|
|
|
// 테스트 계정 허용 상태인가?
|
|
if (true == server_config.AuthRule.TestUserAllow)
|
|
{
|
|
var account_attribute = player.getEntityAttribute<AccountAttribute>();
|
|
NullReferenceCheckHelper.throwIfNull(account_attribute, () => $"account_attribute is null !!! - {player.toBasicString()}");
|
|
|
|
var account_id = account_attribute.AccountId;
|
|
if (true == account_id.isTestAccount())
|
|
{
|
|
is_create_test_user = true;
|
|
}
|
|
}
|
|
|
|
if (true == is_create_test_user)
|
|
{
|
|
result = await prepareCreateCharacter4Test();
|
|
}
|
|
else
|
|
{
|
|
result = await prepareCreateCharacter4Default();
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
private async Task<Result> prepareCreateCharacter4Test()
|
|
{
|
|
var result = new Result();
|
|
|
|
var owner = getOwner() as Player;
|
|
NullReferenceCheckHelper.throwIfNull(owner, () => $"owner is null !!!");
|
|
|
|
var test_character_creator = new TestCharacterCreator(owner);
|
|
result = await test_character_creator.onPrepareCreate();
|
|
if (result.isFail())
|
|
{
|
|
return result;
|
|
}
|
|
|
|
m_user_create_triggers.Add(test_character_creator);
|
|
|
|
return result;
|
|
}
|
|
|
|
private async Task<Result> prepareCreateCharacter4Default()
|
|
{
|
|
var result = new Result();
|
|
|
|
var owner = getOwner() as Player;
|
|
NullReferenceCheckHelper.throwIfNull(owner, () => $"owner is null !!!");
|
|
|
|
var default_character_creator = new DefaultCharacterCreator(owner);
|
|
result = await default_character_creator.onPrepareCreate();
|
|
if (result.isFail())
|
|
{
|
|
return result;
|
|
}
|
|
|
|
m_user_create_triggers.Add(default_character_creator);
|
|
|
|
return result;
|
|
}
|
|
|
|
public bool hasCharacterCreateTrigger()
|
|
{
|
|
return 0 < m_user_create_triggers.Count;
|
|
}
|
|
|
|
public async Task<Result> tryCreateCharacter()
|
|
{
|
|
var result = new Result();
|
|
|
|
var owner = getOwner();
|
|
ArgumentNullException.ThrowIfNull(owner);
|
|
|
|
foreach (var event_trigger in m_user_create_triggers)
|
|
{
|
|
if ( (null == (event_trigger as DefaultCharacterCreator))
|
|
&& (null == (event_trigger as TestCharacterCreator)) )
|
|
{
|
|
continue;
|
|
}
|
|
|
|
return await event_trigger.onTriggerEffect();
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
public async Task<Result> initializeUser4Test()
|
|
{
|
|
var result = new Result();
|
|
|
|
var owner = getOwner() as Player;
|
|
NullReferenceCheckHelper.throwIfNull(owner, () => $"owner is null");
|
|
|
|
var account_attribute = owner.getEntityAttribute<AccountAttribute>();
|
|
NullReferenceCheckHelper.throwIfNull(account_attribute, () => $"account_attribute is null !!! - {owner.toBasicString()}");
|
|
|
|
var account_id = account_attribute.AccountId;
|
|
|
|
var user_attribute = owner.getEntityAttribute<UserAttribute>();
|
|
NullReferenceCheckHelper.throwIfNull(user_attribute, () => $"user_attribute is null !!! - {owner.toBasicString()}");
|
|
|
|
var user_guid = user_attribute.UserGuid;
|
|
|
|
var test_user_initializer = new TestUserInitializer(owner);
|
|
|
|
result = await test_user_initializer.onPrepareInitializer();
|
|
if(result.isFail())
|
|
{
|
|
return result;
|
|
}
|
|
|
|
m_test_User = test_user_initializer.isTestUser();
|
|
|
|
result = await test_user_initializer.onTriggerEffect();
|
|
if (result.isFail())
|
|
{
|
|
return result;
|
|
}
|
|
|
|
Log.getLogger().info($"Step Initialize Test User Success - {owner.toBasicString()}");
|
|
|
|
return result;
|
|
}
|
|
|
|
public async Task<Result> prepareLoadUser()
|
|
{
|
|
var result = new Result();
|
|
|
|
var player = getOwner() as Player;
|
|
NullReferenceCheckHelper.throwIfNull(player, () => $"player is null !!!");
|
|
|
|
var user_loader = new UserLoader(player);
|
|
result = await user_loader.onPrepareLoad();
|
|
if (result.isFail())
|
|
{
|
|
return result;
|
|
}
|
|
m_user_load_triggers.Add(user_loader);
|
|
|
|
var character_loader = new CharacterLoader(player);
|
|
result = await character_loader.onPrepareLoad();
|
|
if (result.isFail())
|
|
{
|
|
return result;
|
|
}
|
|
m_user_load_triggers.Add(character_loader);
|
|
|
|
if (true == hasUserCreateTrigger())
|
|
{
|
|
var err_msg = $"Failed to isCompletedUserCreate() !!! - {toBasicString()}, {player.toBasicString()}";
|
|
result.setFail(ServerErrorCode.UserCreateStepNotCompleted, err_msg);
|
|
Log.getLogger().warn(err_msg);
|
|
|
|
return result;
|
|
}
|
|
|
|
if(true == hasCharacterCreateTrigger())
|
|
{
|
|
result = await tryCreateCharacter();
|
|
if (result.isFail())
|
|
{
|
|
return result;
|
|
}
|
|
}
|
|
|
|
Log.getLogger().info($"Step Prepare Load User Success : prepareLoadUser() - {player.toBasicString()}");
|
|
|
|
return result;
|
|
}
|
|
|
|
public async Task<Result> tryCreateNickname(string newNickname)
|
|
{
|
|
var owner = getOwner() as Player;
|
|
NullReferenceCheckHelper.throwIfNull(owner, () => $"owner is null !!!");
|
|
|
|
var result = new Result();
|
|
var err_msg = string.Empty;
|
|
|
|
if (true == isCreatedUserNickname())
|
|
{
|
|
err_msg = $"Already created User Nickname !!! : {owner.toBasicString()}";
|
|
result.setFail(ServerErrorCode.UserNicknameAlreadyCreated, err_msg);
|
|
Log.getLogger().warn(result.toBasicString());
|
|
|
|
return result;
|
|
}
|
|
|
|
//=====================================================================================
|
|
// 1. User 닉네임 제한 체크 하기
|
|
//=====================================================================================
|
|
var error_code = StringRuleHelper.isValidNickname(newNickname);
|
|
if(error_code.isFail())
|
|
{
|
|
err_msg = $"Not valid User Nickname !!! : {error_code.toBasicString()}, nick:{newNickname} - {owner.toBasicString()}";
|
|
result.setFail(error_code, err_msg);
|
|
Log.getLogger().error(result.toBasicString());
|
|
|
|
return result;
|
|
}
|
|
|
|
result = await tryCreateUser(newNickname);
|
|
if (result.isFail())
|
|
{
|
|
return result;
|
|
}
|
|
|
|
result = await tryCreateCharacter();
|
|
if (result.isFail())
|
|
{
|
|
return result;
|
|
}
|
|
|
|
Log.getLogger().info($"Step Create UserNickname Success - {owner.toBasicString()}");
|
|
|
|
return result;
|
|
}
|
|
|
|
public async Task<Result> tryLoadUser()
|
|
{
|
|
var player = getOwner();
|
|
NullReferenceCheckHelper.throwIfNull(player, () => $"player is null !!!");
|
|
|
|
var result = new Result();
|
|
|
|
foreach (var loader in m_user_load_triggers)
|
|
{
|
|
result = await loader.onTriggerEffect();
|
|
if (result.isFail())
|
|
{
|
|
return result;
|
|
}
|
|
}
|
|
|
|
m_is_completed_start_load_user = true;
|
|
|
|
Log.getLogger().info($"Step Load User Success : tryLoadUser() - {player.toBasicString()}");
|
|
|
|
return result;
|
|
}
|
|
|
|
public async Task<Result> tryLoadCharacterByChracterBaseDoc(CharacterBaseDoc characterBaseDoc)
|
|
{
|
|
var result = new Result();
|
|
var err_msg = string.Empty;
|
|
|
|
var owner = getOwner() as Player;
|
|
ArgumentNullException.ThrowIfNull(owner);
|
|
|
|
var character_base_doc_attrib = characterBaseDoc.getAttrib<CharacterBaseAttrib>();
|
|
ArgumentNullException.ThrowIfNull(character_base_doc_attrib, $"character_base_doc_attrib is null !!! - {owner.toBasicString()}");
|
|
|
|
var character_guid = character_base_doc_attrib.CharacterGuid;
|
|
|
|
Character? to_load_character = null;
|
|
|
|
var reserved_character = getReservedCharacterForCreation();
|
|
if(null != reserved_character)
|
|
{
|
|
var character_attribute = reserved_character.getEntityAttribute<CharacterAttribute>();
|
|
ArgumentNullException.ThrowIfNull(character_attribute, $"character_attribute is null !!! - {owner.toBasicString()}");
|
|
|
|
if (character_guid == character_attribute.CharacterGuid)
|
|
{
|
|
to_load_character = reserved_character;
|
|
}
|
|
}
|
|
|
|
if(null == to_load_character)
|
|
{
|
|
to_load_character = new Character(owner);
|
|
result = await to_load_character.onInit();
|
|
if(result.isFail())
|
|
{
|
|
return result;
|
|
}
|
|
}
|
|
|
|
var player_action = owner.getEntityAction<PlayerAction>();
|
|
ArgumentNullException.ThrowIfNull(player_action, $"player_action is null !!! - {owner.toBasicString()}");
|
|
|
|
result = await player_action.tryLoadCharacter(to_load_character, characterBaseDoc);
|
|
if (result.isFail())
|
|
{
|
|
return result;
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
public async Task<Result> onLoadAfterUserActive()
|
|
{
|
|
var result = new Result();
|
|
|
|
var owner = getOwner() as Player;
|
|
ArgumentNullException.ThrowIfNull(owner, $"owner is null !!!");
|
|
|
|
var location_action = owner.getEntityAction<LocationAction>();
|
|
ArgumentNullException.ThrowIfNull(location_action, $"location_action is null !!! - {owner.toBasicString()}");
|
|
|
|
result = location_action.tryUpdateCurrentLocationAtLogin(m_is_first_login);
|
|
if (result.isFail())
|
|
{
|
|
return result;
|
|
}
|
|
|
|
var ugq_test_action = owner.getEntityAction<UgqTestAction>();
|
|
var ugq_result = await ugq_test_action.makeQuestFromTestUgq();
|
|
if (ugq_result.isFail())
|
|
{
|
|
Log.getLogger().error(ugq_result.toBasicString());
|
|
}
|
|
|
|
var repeat_quest_action = owner.getEntityAction<RepeatQuestAction>();
|
|
repeat_quest_action.checkAndAddNormalQuestCheckPool();
|
|
|
|
var package_action = owner.getEntityAction<PackageAction>();
|
|
result = await package_action.UpdateRepeatProduct();
|
|
if (result.isFail())
|
|
{
|
|
Log.getLogger().error(ugq_result.toBasicString());
|
|
return result;
|
|
}
|
|
|
|
Log.getLogger().info($"Step Load Etc Success : onLoadAfterUserActive() - {owner.toBasicString()}");
|
|
|
|
return result;
|
|
}
|
|
|
|
public async Task notifyUserInfo()
|
|
{
|
|
await Task.CompletedTask;
|
|
|
|
var owner = getOwner() as Player;
|
|
ArgumentNullException.ThrowIfNull(owner, $"owner is null !!!");
|
|
|
|
owner.send_S2C_ACK_SELECTED_CHARACTER_INFO();
|
|
await owner.send_S2C_NTF_LAND_INFOS();
|
|
await owner.send_S2C_NTF_BUILDING_INFOS();
|
|
owner.send_S2C_NTF_MAP_LINKED_INFOS();
|
|
owner.send_S2C_NTF_LOGIN_BUFF();
|
|
owner.send_S2C_NTF_OWNED_LAND_INFOS();
|
|
owner.send_S2C_NTF_OWNED_BUILDING_INFOS();
|
|
owner.send_S2C_MYHOME_INFO_NOTI();
|
|
owner.send_S2C_NTF_OWNED_SOCIAL_ACTION();
|
|
owner.send_S2C_NTF_MINIMAP_MARKER();
|
|
owner.send_GS2C_NTF_CUSTOM_DEFINED_UI_ALL();
|
|
owner.send_S2C_NTF_ITEM_FIRST_PURCHASE_HISTORY();
|
|
owner.send_S2C_NTF_FRIENDS();
|
|
owner.send_S2C_NTF_FRIEND_FOLDERS();
|
|
await owner.send_S2C_NTF_SENDED_FRIEND_REQUESTS();
|
|
await owner.send_S2C_NTF_RECEIVED_FRIEND_REQUESTS();
|
|
await owner.send_GS2C_NTF_BLOCK_USERS();
|
|
|
|
owner.send_GS2C_NTF_UGC_NPC_ALL_LOAD();
|
|
owner.send_GS2C_NTF_FARMING_ALL_LOAD();
|
|
owner.send_S2C_NTF_CRAFT_INFOS();
|
|
owner.send_S2C_NTF_SEASON_PASS_INFOS();
|
|
|
|
if (m_is_first_login == true)
|
|
{
|
|
owner.send_S2C_NTF_MYHOME_INFO();
|
|
owner.send_S2C_NTF_OWNED_RENTAL_INFOS();
|
|
owner.send_S2C_NTF_GAME_OPTION();
|
|
owner.send_S2C_NTF_NEW_MAIL();
|
|
owner.send_S2C_NTF_CART();
|
|
owner.send_S2C_NTF_CRAFT_RECIPES();
|
|
owner.send_GS2C_NTF_SYSTEM_QUEST_METAS();
|
|
await owner.send_GS2C_NTF_SYSTEM_QUESTS();
|
|
owner.send_GS2C_NTF_END_QUESTS();
|
|
await owner.send_GS2C_NTF_UGQS();
|
|
await owner.send_GS2C_NTF_UGQ_DAILY_REWARD();
|
|
}
|
|
|
|
await owner.send_GS2C_NTF_QUEST_UPDATE_BY_SERVER_MOVE();
|
|
|
|
updateCompletedLoadUser();
|
|
|
|
Log.getLogger().info($"Step Notify To Client Success : notifyUserInfo() - {owner.toBasicString()}");
|
|
}
|
|
|
|
public void updateCompletedLoadUser()
|
|
{
|
|
if (true == m_is_completed_start_load_user)
|
|
{
|
|
m_is_completed_end_load_user = true;
|
|
}
|
|
}
|
|
|
|
public async Task<Result> onNotifyAfterUserActive()
|
|
{
|
|
var result = new Result();
|
|
var err_msg = string.Empty;
|
|
|
|
var owner = getOwner() as Player;
|
|
ArgumentNullException.ThrowIfNull(owner, $"owner is null !!!");
|
|
|
|
var server_logic = GameServerApp.getServerLogic();
|
|
ArgumentNullException.ThrowIfNull(server_logic, $"server_logic is null !!! - {owner.toBasicString()}");
|
|
|
|
var location_attribute = owner.getEntityAttribute<LocationAttribute>();
|
|
ArgumentNullException.ThrowIfNull(location_attribute, $"location_attribute is null !!! - {owner.toBasicString()}");
|
|
|
|
await owner.joinParty();
|
|
|
|
if (server_logic.getServerType().toServerType() == ServerType.Channel)
|
|
{
|
|
var game_zone_action = owner.getEntityAction<GameZoneAction>();
|
|
ArgumentNullException.ThrowIfNull(game_zone_action, $"game_zone_action is null !!! - {owner.toBasicString()}");
|
|
|
|
result = game_zone_action.tryEnterGameZone(server_logic.getMap());
|
|
if (result.isFail())
|
|
{
|
|
return result;
|
|
}
|
|
|
|
result = await owner.changeInstanceRoomIdAtLoginCache(string.Empty);
|
|
if (result.isFail())
|
|
{
|
|
return result;
|
|
}
|
|
|
|
owner.send_S2C_NTF_SET_LOCATION();
|
|
}
|
|
else
|
|
{
|
|
var joined_room = await InstanceRoomManager.Instance.JoinRoom(owner, location_attribute.EnterIndunLocation.InstanceRoomId, location_attribute.EnterIndunLocation.InstanceMetaId);
|
|
if (joined_room == null)
|
|
{
|
|
err_msg = $"Failed to JoinRoom() !!! : roomId:{location_attribute.EnterIndunLocation.InstanceRoomId}, instanceMetaId{location_attribute.EnterIndunLocation.InstanceMetaId}, {owner.toBasicString()}";
|
|
result.setFail(ServerErrorCode.JoinRoomFail, err_msg);
|
|
Log.getLogger().error(err_msg);
|
|
|
|
return result;
|
|
}
|
|
|
|
var instance_room_id = location_attribute.CurrentIndunLocation.InstanceRoomId;
|
|
var instance_meta_id = location_attribute.CurrentIndunLocation.InstanceMetaId;
|
|
|
|
result = await owner.changeInstanceRoomIdAtLoginCache(instance_room_id);
|
|
if (result.isFail())
|
|
{
|
|
return result;
|
|
}
|
|
|
|
await InstanceRoomManager.Instance.SendJoinRoomSuccess(owner, instance_room_id);
|
|
|
|
if (MetaData.Instance._IndunTable.TryGetValue(instance_meta_id, out var instanceMetaData) == true &&
|
|
instanceMetaData.ContentsType == ContentsType.MyHome &&
|
|
MyhomeHelper.getMyhomeOwnerUserGuidAndMyhomeGuidFromRoomId(instance_room_id, out var myhome_owner_guid, out _).isSuccess())
|
|
{
|
|
if (myhome_owner_guid != owner.getUserGuid())
|
|
{
|
|
await owner.send_S2C_NTF_TARGET_CRAFT_INFOS(myhome_owner_guid);
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
await owner.sendLoginNotiToFriend(m_is_first_login);
|
|
await owner.loadSystemMail(m_is_first_login);
|
|
await owner.send_GS2C_NTF_QUEST_UPDATE_ALL();
|
|
await QuestManager.It.PeriodRepeatQuestCheck(owner);
|
|
await QuestManager.It.newAssignableQuestCheck(owner);
|
|
|
|
|
|
BattleRoomNotifyHelper.send_GS2C_NTF_BATTLE_EVENT(owner);
|
|
|
|
Log.getLogger().info($"Step Enter To Zone Success : onNotifyAfterUserActive() - {owner.toBasicString()}");
|
|
|
|
return result;
|
|
}
|
|
|
|
public TSimpleEventTriggerBase? getSimpleEventTriggerType<TSimpleEventTriggerBase>()
|
|
where TSimpleEventTriggerBase : SimpleEventTriggerBase
|
|
{
|
|
foreach(var create_trigger in m_user_create_triggers)
|
|
{
|
|
if(typeof(TSimpleEventTriggerBase) == create_trigger.GetType())
|
|
{
|
|
var trigger = create_trigger as TSimpleEventTriggerBase;
|
|
return trigger;
|
|
}
|
|
}
|
|
|
|
foreach (var load_trigger in m_user_load_triggers)
|
|
{
|
|
if (typeof(TSimpleEventTriggerBase) == load_trigger.GetType())
|
|
{
|
|
var trigger = load_trigger as TSimpleEventTriggerBase;
|
|
return trigger;
|
|
}
|
|
}
|
|
|
|
return null;
|
|
}
|
|
|
|
public AvatarInfo toSelectedCharacterAppearanceProfile4Client()
|
|
{
|
|
var owner = getOwner();
|
|
ArgumentNullException.ThrowIfNull(owner);
|
|
|
|
var avatar_info = new AvatarInfo();
|
|
var appearance_customize = new AppearanceCustomization();
|
|
avatar_info.AppearCustomize = appearance_customize;
|
|
|
|
foreach (var event_trigger in m_user_create_triggers)
|
|
{
|
|
if (( null == (event_trigger as DefaultCharacterCreator))
|
|
&& (null == (event_trigger as TestCharacterCreator)))
|
|
{
|
|
continue;
|
|
}
|
|
|
|
var found_doc = event_trigger.getToWriteDocBase<CharacterBaseDoc>();
|
|
if(null != found_doc)
|
|
{
|
|
var found_attrib = found_doc.getAttrib<CharacterBaseAttrib>();
|
|
if(null != found_attrib)
|
|
{
|
|
var profile = found_attrib.ApperanceProfileValue;
|
|
|
|
avatar_info.AvatarId = 1;
|
|
|
|
appearance_customize.BasicStyle = (int)profile.BasicStyle;
|
|
appearance_customize.BodyShape = (int)profile.BodyShape;
|
|
appearance_customize.HairStyle = (int)profile.HairStyle;
|
|
appearance_customize.CustomValues.AddRange(profile.CustomValues.Select(x => x).ToList());
|
|
|
|
avatar_info.Init = (uint)(profile.IsCustomCompleted == true ? 0 : 1);
|
|
|
|
return avatar_info;
|
|
}
|
|
}
|
|
}
|
|
|
|
return avatar_info;
|
|
}
|
|
|
|
public bool isLoadableUser()
|
|
{
|
|
if (true == hasUserCreateTrigger())
|
|
{
|
|
return false;
|
|
}
|
|
|
|
if (true == hasCharacterCreateTrigger())
|
|
{
|
|
return false;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
public bool isCompletedLoadUser() => m_is_completed_end_load_user;
|
|
|
|
public void fillUpUserInfo4Client(CharInfo userInfo)
|
|
{
|
|
var owner = getOwner() as Player;
|
|
ArgumentNullException.ThrowIfNull(owner, $"owner is null !!!");
|
|
|
|
foreach (var event_trigger in m_user_create_triggers)
|
|
{
|
|
if ( (null == (event_trigger as DefaultUserCreator))
|
|
&& (null == (event_trigger as TestUserCreator)) )
|
|
{
|
|
continue;
|
|
}
|
|
|
|
{
|
|
var found_doc = event_trigger.getToWriteDocBase<LevelDoc>();
|
|
if (null != found_doc)
|
|
{
|
|
var found_attrib = found_doc.getAttrib<LevelAttrib>();
|
|
ArgumentNullException.ThrowIfNull(found_attrib);
|
|
userInfo.Level = (Int32)found_attrib.Level;
|
|
userInfo.Exp = (Int32)found_attrib.Exp;
|
|
}
|
|
}
|
|
|
|
{
|
|
var found_doc = event_trigger.getToWriteDocBase<MoneyDoc>();
|
|
if (null != found_doc)
|
|
{
|
|
var found_attrib = found_doc.getAttrib<MoneyAttrib>();
|
|
if (null != found_attrib)
|
|
{
|
|
userInfo.Gold = found_attrib.Gold;
|
|
userInfo.Sapphire = found_attrib.Sapphire;
|
|
userInfo.Calium = found_attrib.Calium;
|
|
//userInfo.Ruby = found_attrib.Ruby;
|
|
}
|
|
}
|
|
}
|
|
|
|
return;
|
|
}
|
|
}
|
|
|
|
public bool isTestUser() { return m_test_User; }
|
|
|
|
public void setFirstLogin(bool isFirstLogin) => m_is_first_login = isFirstLogin;
|
|
|
|
public bool isFirstLogin() => m_is_first_login;
|
|
|
|
public void clearReservedCharacterForCreation() => m_reserved_chacter_for_creation_nullable = null;
|
|
|
|
public void setReservedCharacterForCreation(Character charactor) => m_reserved_chacter_for_creation_nullable = charactor;
|
|
|
|
public Character? getReservedCharacterForCreation() => m_reserved_chacter_for_creation_nullable;
|
|
}
|