초기커밋

This commit is contained in:
2025-05-01 07:20:41 +09:00
commit 98bb2e3c5c
2747 changed files with 646947 additions and 0 deletions

View File

@@ -0,0 +1,868 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Text.RegularExpressions;
using Amazon.S3.Model;
using ServerCore; using ServerBase;
using ServerCommon;
using ServerCommon.BusinessLogDomain;
using static ServerCommon.MetaHelper;
using MetaAssets;
using static ClientToGameMessage.Types;
using static ClientToGameReq.Types;
using static ClientToGameRes.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 UGC_NPC_META_GUID = System.String;
using ITEM_GUID = System.String;
namespace GameServer
{
public class UgcNpcCreationOrLoadAction : EntityActionBase
{
private UgcNpc? m_reserved_ugc_npc_for_creation_nullable;
private readonly Dictionary<InvenEquipType, HashSet<Int16>> m_reserved_slot_types = new();
private ServerCommon.BusinessLogDomain.BeaconCreateLogInfo m_beacon_create_log_info = new();
private ServerCommon.BusinessLogDomain.BeaconLogInfo m_beacon_log_info = new();
public UgcNpcCreationOrLoadAction(Player owner)
: base(owner)
{
}
public override Task<Result> onInit()
{
var result = new Result();
return Task.FromResult(result);
}
public override void onClear()
{
return;
}
public void clearReservedSlotTypes()
{
m_reserved_slot_types.Clear();
}
public void resetReserved4UgcNpcCreation()
{
m_reserved_ugc_npc_for_creation_nullable = null;
}
public async Task<Result> tryLoadUgcNpcFromDoc(UgcNpcDoc ugcNpcDoc)
{
var owner = getOwner() as Player;
NullReferenceCheckHelper.throwIfNull(owner, () => $"owner is null !!!");
ArgumentNullReferenceCheckHelper.throwIfNull(ugcNpcDoc, () => $"ugcNpcDoc is null !!! - {owner.toBasicString()}");
var result = new Result();
var err_msg = string.Empty;
var to_load_ugc_npc = new UgcNpc(owner.getUserGuid());
result = await to_load_ugc_npc.onInit();
if (result.isFail())
{
return result;
}
var player_action = owner.getEntityAction<PlayerAction>();
ArgumentNullReferenceCheckHelper.throwIfNull(player_action, () => $"player_action is null !!! - {owner.toBasicString()}");
result = await player_action.tryLoadUgcNpc(to_load_ugc_npc, ugcNpcDoc);
if (result.isFail())
{
return result;
}
var ugc_npc_attribute = to_load_ugc_npc.getEntityAttribute<UgcNpcAttribute>();
ArgumentNullReferenceCheckHelper.throwIfNull(ugc_npc_attribute, () => $"ugc_npc_attribute is null !!! - {owner.toBasicString()}");
m_beacon_log_info.setInfo(ugc_npc_attribute.toBeaconLogInfo());
return result;
}
public async Task<Result> tryLoadUgcNpcInGameZone(UgcNpc ugcNpcInGameZone)
{
var owner = getOwner() as Player;
NullReferenceCheckHelper.throwIfNull(owner, () => $"owner is null !!!");
ArgumentNullReferenceCheckHelper.throwIfNull(ugcNpcInGameZone, () => $"ugcNpcInGameZone is null !!! - {owner.toBasicString()}");
var result = new Result();
var err_msg = string.Empty;
var player_action = owner.getEntityAction<PlayerAction>();
NullReferenceCheckHelper.throwIfNull(player_action, () => $"player_action is null !!! - {owner.toBasicString()}");
result = await player_action.tryAttachUgcNpcInGameZone(ugcNpcInGameZone);
if (result.isFail())
{
return result;
}
return result;
}
public async Task<Result> tryLoadApprearanceCustomize(DynamoDbClient dbClient, UGC_NPC_META_GUID ugcNpcMetaGuid)
{
var owner = getOwner() as Player;
NullReferenceCheckHelper.throwIfNull(owner, () => $"owner is null !!!");
ArgumentNullReferenceCheckHelper.throwIfNull(dbClient, () => $"dbClient is null !!! - {owner.toBasicString()}");
var result = new Result();
var err_msg = string.Empty;
(result, var make_primary_key) = await DynamoDBDocBaseHelper.makePrimaryKey<AppearanceCustomizeDoc>(ugcNpcMetaGuid);
if (result.isFail())
{
return result;
}
NullReferenceCheckHelper.throwIfNull(make_primary_key, () => $"make_primary_key is null !!! - {owner.toBasicString()}");
var appearance_customize_query_config = dbClient.makeQueryConfigForReadByPKSK(make_primary_key.PK);
// DB에 AppearanceCustomize 정보 없는 경우도 있을 수 있다 !!!
(var appearance_customize_result, var appearance_customize_read_doc) = await dbClient.simpleQueryDocTypeWithQueryOperationConfig<AppearanceCustomizeDoc>(appearance_customize_query_config);
if (appearance_customize_result.isSuccess())
{
NullReferenceCheckHelper.throwIfNull(appearance_customize_read_doc, () => $"appearance_customize_read_doc is null !!! - {owner.toBasicString()}");
appearance_customize_result = await tryLoadApprearanceCustomizeFromDoc(ugcNpcMetaGuid, appearance_customize_read_doc);
if (appearance_customize_result.isFail())
{
return result;
}
}
return result;
}
protected async Task<Result> tryLoadApprearanceCustomizeFromDoc(UGC_NPC_META_GUID ugcNpcMetaGuid, AppearanceCustomizeDoc appearanceCustomizeDoc)
{
var owner = getOwner() as Player;
NullReferenceCheckHelper.throwIfNull(owner, () => $"owner is null !!!");
ArgumentNullReferenceCheckHelper.throwIfNull(appearanceCustomizeDoc, () => $"appearanceCustomizeDoc is null !!! - {owner.toBasicString()}");
var result = new Result();
var err_msg = string.Empty;
var player_action = owner.getEntityAction<PlayerAction>();
ArgumentNullReferenceCheckHelper.throwIfNull(player_action, () => $"player_action is null !!! - {owner.toBasicString()}");
var found_ugc_npc = player_action.findUgcNpc(ugcNpcMetaGuid);
if(null == found_ugc_npc)
{
err_msg = $"Not found UgcNpc !!! : UgcNpcMetaGuid:{ugcNpcMetaGuid} - {owner.toBasicString()}";
result.setFail(ServerErrorCode.UgcNpcNotFound, err_msg);
return result;
}
var beacon_appearance_customize_action = found_ugc_npc.getEntityAction<BeaconAppearanceCustomizeAction>();
ArgumentNullReferenceCheckHelper.throwIfNull(beacon_appearance_customize_action, () => $"beacon_appearance_customize_action is null !!! - {owner.toBasicString()}");
result = await beacon_appearance_customize_action.tryLoadAppearanceCustomizeFromDoc(appearanceCustomizeDoc);
if(result.isFail())
{
return result;
}
return result;
}
public async Task<Result> tryLoadBeaconShopItem(DynamoDbClient dbClient, UGC_NPC_META_GUID ugcNpcMetaGuid)
{
var owner = getOwner() as Player;
NullReferenceCheckHelper.throwIfNull(owner, () => $"owner is null !!!");
ArgumentNullReferenceCheckHelper.throwIfNull(dbClient, () => $"dbClient is null !!! - {owner.toBasicString()}");
var result = new Result();
var err_msg = string.Empty;
(result, var make_primary_key) = await DynamoDBDocBaseHelper.makePrimaryKey<BeaconShopItemDoc>(ugcNpcMetaGuid);
if (result.isFail())
{
return result;
}
NullReferenceCheckHelper.throwIfNull(make_primary_key, () => $"make_primary_key is null !!! - {owner.toBasicString()}");
var beacon_shop_item_query_config = dbClient.makeQueryConfigForReadByPKOnly(make_primary_key.PK);
(var beacon_shop_item_result, var beacon_shop_item_read_docs) = await dbClient.simpleQueryDocTypesWithQueryOperationConfig<BeaconShopItemDoc>(beacon_shop_item_query_config);
if (beacon_shop_item_result.isSuccess())
{
NullReferenceCheckHelper.throwIfNull(beacon_shop_item_read_docs, () => $"beacon_shop_item_read_docs is null !!! - {owner.toBasicString()}");
beacon_shop_item_result = await tryLoadBeaconShopItemDocFromDoc(beacon_shop_item_read_docs, ugcNpcMetaGuid);
if (beacon_shop_item_result.isFail())
{
return result;
}
}
return result;
}
protected async Task<Result> tryLoadBeaconShopItemDocFromDoc(List<BeaconShopItemDoc> beaconShopItemDocs, UGC_NPC_META_GUID ugcNpcMetaGuid)
{
var owner = getOwner() as Player;
NullReferenceCheckHelper.throwIfNull(owner, () => $"owner is null !!!");
ArgumentNullReferenceCheckHelper.throwIfNull(beaconShopItemDocs, () => $"beaconShopItemDocs is null !!! - {owner.toBasicString()}");
var result = new Result();
var err_msg = string.Empty;
var player_action = owner.getEntityAction<PlayerAction>();
ArgumentNullReferenceCheckHelper.throwIfNull(player_action, () => $"player_action is null !!! - {owner.toBasicString()}");
var found_ugc_npc = player_action.findUgcNpc(ugcNpcMetaGuid);
if (null == found_ugc_npc)
{
err_msg = $"Not found UgcNpc !!! : UgcNpcMetaGuid:{ugcNpcMetaGuid} - {owner.toBasicString()}";
result.setFail(ServerErrorCode.UgcNpcNotFound, err_msg);
return result;
}
var ugc_npc_beacon_shop_action = found_ugc_npc.getEntityAction<UgcNpcBeaconShopAction>();
foreach (var read_doc in beaconShopItemDocs)
{
result = await ugc_npc_beacon_shop_action.addBeaconShopItem(read_doc);
if (result.isFail())
{
return result;
}
}
return result;
}
public async Task<Result> tryLoadBeaconShopProfile(DynamoDbClient dbClient, UGC_NPC_META_GUID ugcNpcMetaGuid)
{
var owner = getOwner() as Player;
NullReferenceCheckHelper.throwIfNull(owner, () => $"owner is null !!!");
ArgumentNullReferenceCheckHelper.throwIfNull(dbClient, () => $"dbClient is null !!! - {owner.toBasicString()}");
var result = new Result();
var err_msg = string.Empty;
(result, var make_primary_key) = await DynamoDBDocBaseHelper.makePrimaryKey<BeaconShopProfileDoc>(ugcNpcMetaGuid);
if (result.isFail())
{
return result;
}
NullReferenceCheckHelper.throwIfNull(make_primary_key, () => $"make_primary_key is null !!! - {owner.toBasicString()}");
var beacon_shop_item_query_config = dbClient.makeQueryConfigForReadByPKOnly(make_primary_key.PK);
(var beacon_shop_item_result, var beacon_shop_profile_read_docs) = await dbClient.simpleQueryDocTypesWithQueryOperationConfig<BeaconShopProfileDoc>(beacon_shop_item_query_config);
if (beacon_shop_item_result.isSuccess())
{
NullReferenceCheckHelper.throwIfNull(beacon_shop_profile_read_docs, () => $"beacon_shop_profile_read_docs is null !!! - {owner.toBasicString()}");
if (beacon_shop_profile_read_docs.Count <= 0)
{
var beaconShopProfileDoc = new BeaconShopProfileDoc(ugcNpcMetaGuid);
var beaconShopProfileAttrib = beaconShopProfileDoc.getAttrib<BeaconShopProfileAttrib>();
NullReferenceCheckHelper.throwIfNull(beaconShopProfileAttrib, () => $"beaconShopProfileAttrib is null !!! - {owner.toBasicString()}");
beaconShopProfileAttrib.BeaconGuid = ugcNpcMetaGuid;
result = await dbClient.simpleInsertDocumentWithDocType(beaconShopProfileDoc);
if (result.isFail())
{
err_msg = $"Failed to simpleUpsertDocumentWithDocType<BeaconShopProfileDoc> !!! - {owner.toBasicString()}";
Log.getLogger().error(err_msg);
return result;
}
(beacon_shop_item_result, beacon_shop_profile_read_docs) = await dbClient.simpleQueryDocTypesWithQueryOperationConfig<BeaconShopProfileDoc>(beacon_shop_item_query_config);
}
beacon_shop_item_result = tryLoadBeaconShopProfileDocFromDoc(beacon_shop_profile_read_docs, ugcNpcMetaGuid);
if (beacon_shop_item_result.isFail())
{
return result;
}
}
return result;
}
protected Result tryLoadBeaconShopProfileDocFromDoc(List<BeaconShopProfileDoc> beaconShopProfileDocs, UGC_NPC_META_GUID ugcNpcMetaGuid)
{
var owner = getOwner() as Player;
NullReferenceCheckHelper.throwIfNull(owner, () => $"owner is null !!!");
ArgumentNullReferenceCheckHelper.throwIfNull(beaconShopProfileDocs, () => $"beaconShopProfileDocs is null !!! - {owner.toBasicString()}");
var result = new Result();
var err_msg = string.Empty;
var player_action = owner.getEntityAction<PlayerAction>();
ArgumentNullReferenceCheckHelper.throwIfNull(player_action, () => $"player_action is null !!! - {owner.toBasicString()}");
var found_ugc_npc = player_action.findUgcNpc(ugcNpcMetaGuid);
if (null == found_ugc_npc)
{
err_msg = $"Not found UgcNpc !!! : UgcNpcMetaGuid:{ugcNpcMetaGuid} - {owner.toBasicString()}";
result.setFail(ServerErrorCode.UgcNpcNotFound, err_msg);
return result;
}
var beacon_shop_profile_attribute = found_ugc_npc.getEntityAttribute<BeaconShopProfileAttribute>();
NullReferenceCheckHelper.throwIfNull(beacon_shop_profile_attribute, () => $"beacon_shop_profile_attribute is null !!! - {found_ugc_npc.toBasicString()}");
beacon_shop_profile_attribute.copyEntityAttributeFromDoc(beaconShopProfileDocs[0]);
beacon_shop_profile_attribute.copyEntityAttributeFromDoc(beaconShopProfileDocs[0]);
if (beacon_shop_profile_attribute.BeaconGuid == string.Empty)
beacon_shop_profile_attribute.BeaconGuid = ugcNpcMetaGuid;
return result;
}
private async Task<Result> checkCreateConditions(C2GS_REQ_UGC_NPC_CREATION request)
{
await Task.CompletedTask;
var owner = getOwner() as Player;
NullReferenceCheckHelper.throwIfNull(owner, () => $"owner is null !!!");
ArgumentNullReferenceCheckHelper.throwIfNull(request, () => $"request is null !!! - {owner.toBasicString()}");
var result = new Result();
var err_msg = string.Empty;
var user_inventory_action = owner.getEntityAction<UserInventoryAction>();
NullReferenceCheckHelper.throwIfNull(user_inventory_action, () => $"user_inventory_action is null !!! - {owner.toBasicString()}");
//=====================================================================================
// 1. Body Item 보유 확인 하기
//=====================================================================================
var found_body_item = user_inventory_action.tryGetItemByItemGuid(request.BodyItemGuid);
if (null == found_body_item)
{
err_msg = $"Not found Body Item !!! : bodyItemGuid:{request.BodyItemGuid} - {owner.toBasicString()}";
result.setFail(ServerErrorCode.ItemNotFound, err_msg);
return result;
}
var item_meta_data = found_body_item.getItemMeta();
NullReferenceCheckHelper.throwIfNull(item_meta_data, () => $"item_meta_data is null !!! - {owner.toBasicString()}");
if(item_meta_data.TypeSmall != EItemSmallType.BEACON_BODY)
{
err_msg = $"Not Beacon Body Item !!! : EItemSmallType.BEACON_BODY == {item_meta_data.TypeSmall}, bodyItemGuid:{request.BodyItemGuid} - {owner.toBasicString()}";
result.setFail(ServerErrorCode.BeaconBodyItemInvalid, err_msg);
return result;
}
//=====================================================================================
// 2. 중복된 ITEM_GUID 존재 체크 하기
//=====================================================================================
var found_duplicated_guids = InventoryRuleHelper.findContainDuplicatedItemGuid(request.MaterialItemGuids.ToList());
if (0 < found_duplicated_guids.Count)
{
err_msg = $"ItemGuid duplicated !!! - {owner.toBasicString()}";
result.setFail(ServerErrorCode.ItemGuidDuplicated, err_msg);
return result;
}
var player_action = owner.getEntityAction<PlayerAction>();
NullReferenceCheckHelper.throwIfNull(player_action, () => $"player_action is null !!! - {owner.toBasicString()}");
//=====================================================================================
// 3. Ugc Npc 개수 제한 체크 하기
//=====================================================================================
if (player_action.getHadUgcNpcCount() >= GameConfigMeta.BeaconCreateMaxCount)
{
err_msg = $"UgcNpc max count exceed !!! : currCount:{player_action.getHadUgcNpcCount()} <= maxCount:{GameConfigMeta.BeaconCreateMaxCount} - {owner.toBasicString()}";
result.setFail(ServerErrorCode.UgcNpcMaxCountExceed, err_msg);
return result;
}
//=====================================================================================
// 4. Ugc Npc 닉네임 제한 체크 하기
//=====================================================================================
var error_code = isValidNickname(request.Nickname);
if (error_code.isFail())
{
err_msg = $"Not valid UgcNpc Nickname !!! : {error_code.toBasicString()}, nick:{request.Nickname} - {owner.toBasicString()}";
result.setFail(error_code, err_msg);
Log.getLogger().error(result.toBasicString());
return result;
}
//=====================================================================================
// 5. 문자열 길이 제한 체크 하기
//=====================================================================================
if (request.Description.Length > GameConfigMeta.MaxNpcDescriptionChar)
{
err_msg = $"UgcNpc Description max count exceed !!! : currCount:{request.Description.Length} < maxCount:{GameConfigMeta.MaxNpcDescriptionChar} - {owner.toBasicString()}";
result.setFail(ServerErrorCode.UgcNpcDescriptionLengthExceed, err_msg);
return result;
}
if (request.WorldScenario.Length > GameConfigMeta.MaxNpcBackGroundChar)
{
err_msg = $"UgcNpc WorldScenario max count exceed !!! : currCount:{request.WorldScenario.Length} < maxCount:{GameConfigMeta.MaxNpcBackGroundChar} - {owner.toBasicString()}";
result.setFail(ServerErrorCode.UgcNpcWordScenarioLengthExceed, err_msg);
return result;
}
if (request.Greeting.Length > GameConfigMeta.MaxNpcGreetingChar)
{
err_msg = $"UgcNpc Greeting max count exceed !!! : currCount:{request.Greeting.Length} < maxCount:{GameConfigMeta.MaxNpcGreetingChar} - {owner.toBasicString()}";
result.setFail(ServerErrorCode.UgcNpcGreetingLengthExceed, err_msg);
return result;
}
if (request.Introduction.Length > GameConfigMeta.MaxNpcIntroductionChar)
{
err_msg = $"UgcNpc Introduction max count exceed !!! : currCount:{request.Introduction.Length} < maxCount:{GameConfigMeta.MaxNpcIntroductionChar} - {owner.toBasicString()}";
result.setFail(ServerErrorCode.UgcNpcIntroductionLengthExceed, err_msg);
return result;
}
//=====================================================================================
// 6. 재료 아이템 체크 하기 : 의상 & 타투
//=====================================================================================
var to_chek_cloth_item_count = GameConfigMeta.NpcCreateDressRequirement;
var to_chek_tattoo_item_count = GameConfigMeta.NpcCreateTattooRequirement;
var found_user_item_attribute = found_body_item.getEntityAttribute<UserItemAttribute>();
NullReferenceCheckHelper.throwIfNull(found_user_item_attribute, () => $"found_user_item_attribute is null !!! - {owner.toBasicString()}");
if(false == MetaData.Instance.Meta.BeaconNpcMetaTable.BeaconNpcMetaDataListbyId.TryGetValue((Int32)found_user_item_attribute.ItemMetaId, out var found_beacon_npc_meta))
{
err_msg = $"Not found BeaconNpcMetaData !!! : bodyItemMetaId:{found_user_item_attribute.ItemMetaId} - {owner.toBasicString()}";
result.setFail(ServerErrorCode.UgcNpcMetaDataNotFound, err_msg);
return result;
}
var default_cloth_item_meta_ids = found_beacon_npc_meta.DefaultWears.toMetaIds();
var default_cloth_item_count = default_cloth_item_meta_ids.Count;
var selected_cloth_item_count = 0;
var selected_tattoo_item_count = 0;
foreach (var material_item_guid in request.MaterialItemGuids)
{
var found_item = user_inventory_action.tryGetItemByItemGuid(material_item_guid);
if (null == found_item)
{
err_msg = $"Not found Material Item for UgcNpc create !!! - {owner.toBasicString()}";
result.setFail(ServerErrorCode.ItemNotFound, err_msg);
return result;
}
var item_meta = found_item.getItemMeta();
NullReferenceCheckHelper.throwIfNull(item_meta, () => $"item_meta is null !!! - {owner.toBasicString()}");
if (true == item_meta.isClothType())
{
selected_cloth_item_count++;
to_chek_cloth_item_count--;
Int32.Max(to_chek_cloth_item_count, 0);
}
else if (true == item_meta.isTattooType())
{
selected_tattoo_item_count++;
to_chek_tattoo_item_count--;
Int32.Max(to_chek_tattoo_item_count, 0);
}
if(0 == to_chek_cloth_item_count && 0 == to_chek_tattoo_item_count)
{
break;
}
}
if (0 < Int32.Max(to_chek_cloth_item_count - default_cloth_item_count, 0))
{
err_msg = $"Not enough Cloth Item for Ugc Npc !!!"
+ $" : defaultClothItemCount:{default_cloth_item_count} + selectedClothItemCount:{selected_cloth_item_count} <= toCheckClothItemCount:{to_chek_cloth_item_count} - {owner.toBasicString()}";
result.setFail(ServerErrorCode.UgcNpcClothItemNotEnough, err_msg);
return result;
}
if (0 < to_chek_tattoo_item_count)
{
err_msg = $"Not enough Tattoo Item for Ugc Npc !!!"
+ $" : selectedTattooItemCount:{selected_tattoo_item_count} <= toCheckTattooItemCount:{to_chek_tattoo_item_count} - {owner.toBasicString()}";
result.setFail(ServerErrorCode.UgcNpcTattooItemNotEnough, err_msg);
return result;
}
//=====================================================================================
// 6. 소셜 액션 체크 하기
//=====================================================================================
if (false == MetaData.Instance._SocialActionTable.TryGetValue(request.DefaultSocialActionId, out var social_action_meta_data))
{
err_msg = $"Not found Default SocialAction MetaId !!! : SocialMetaId:{request.DefaultSocialActionId} - {owner.toBasicString()}";
result.setFail(ServerErrorCode.SocialActionMetaDataNotFound, err_msg);
Log.getLogger().error(result.toBasicString());
return result;
}
if (request.HabitSocialActionIds.Count > GameConfigMeta.MaxNpcFrequentSocial)
{
err_msg = $"Ugc Npc Habit SocialAction Count Exceed !!! : currCount:{request.HabitSocialActionIds.Count} < maxCount:{GameConfigMeta.MaxNpcFrequentSocial} - {owner.toBasicString()}";
result.setFail(ServerErrorCode.UgcNpcHabitSocialActionCountExceed, err_msg);
Log.getLogger().error(result.toBasicString());
return result;
}
foreach (var social_action_meta_id in request.HabitSocialActionIds)
{
if (false == MetaData.Instance._SocialActionTable.TryGetValue(social_action_meta_id, out social_action_meta_data))
{
err_msg = $"Not found Habit SocialAction MetaId !!! : SocialMetaId:{social_action_meta_id} - {owner.toBasicString()}";
result.setFail(ServerErrorCode.SocialActionMetaDataNotFound, err_msg);
Log.getLogger().error(result.toBasicString());
return result;
}
}
if (request.DialogueSocialActionIds.Count > GameConfigMeta.MaxNpcDialogueSocial)
{
err_msg = $"Ugc Npc Dialogue SocialAction Count Exceed !!! : currCount:{request.DialogueSocialActionIds.Count} < maxCount:{GameConfigMeta.MaxNpcDialogueSocial} - {owner.toBasicString()}";
result.setFail(ServerErrorCode.UgcNpcDialogueSocialActionCountExceed, err_msg);
Log.getLogger().error(result.toBasicString());
return result;
}
foreach (var social_action_meta_id in request.DialogueSocialActionIds)
{
if (false == MetaData.Instance._SocialActionTable.TryGetValue(social_action_meta_id, out social_action_meta_data))
{
err_msg = $"Not found Inaction SocialAction MetaId !!! : SocialMetaId:{social_action_meta_id} - {owner.toBasicString()}";
result.setFail(ServerErrorCode.SocialActionMetaDataNotFound, err_msg);
Log.getLogger().error(result.toBasicString());
return result;
}
}
//=====================================================================================
// 7. Npc Tag 체크 하기
//=====================================================================================
if (request.HashTagMetaIds.Count > GameConfigMeta.MaxNpcTag)
{
err_msg = $"Ugc Npc Tag Count Exceed !!! : currCount:{request.HashTagMetaIds.Count} < maxCount:{GameConfigMeta.MaxNpcTag} - {owner.toBasicString()}";
result.setFail(ServerErrorCode.UgcNpcMaxTagExceed, err_msg);
Log.getLogger().error(result.toBasicString());
return result;
}
return result;
}
public async Task<(Result, UgcNpc?)> tryCreateUgcNpc(C2GS_REQ_UGC_NPC_CREATION request)
{
var owner = getOwner() as Player;
NullReferenceCheckHelper.throwIfNull(owner, () => $"owner is null !!!");
ArgumentNullReferenceCheckHelper.throwIfNull(request, () => $"request is null !!! - {owner.toBasicString()}");
// 직전에 예약되어 있는 슬롯을 모두 초기화 한다.
clearReservedSlotTypes();
var result = new Result();
var err_msg = string.Empty;
var account_attribute = owner.getEntityAttribute<AccountAttribute>();
NullReferenceCheckHelper.throwIfNull(account_attribute, () => $"account_attribute is null !!! - {owner.toBasicString()}");
var user_inventory_action = owner.getEntityAction<UserInventoryAction>();
NullReferenceCheckHelper.throwIfNull(user_inventory_action, () => $"user_inventory_action is null !!! - {owner.toBasicString()}");
//=====================================================================================
// 1. 기본적인 생성 조건 체크 하기
//=====================================================================================
result = await checkCreateConditions(request);
if (result.isFail())
{
return (result, null);
}
//=====================================================================================
// 2. 금전 소모 처리
//=====================================================================================
var money_action = owner.getEntityAction<MoneyAction>();
NullReferenceCheckHelper.throwIfNull(money_action, () => $"money_action is null !!! - {owner.toBasicString()}");
var req_currency_type = (CurrencyType)ServerCommon.MetaHelper.GameConfigMeta.NpcCreateCurrency;
var req_cost = GameConfigMeta.NpcCreateCost * -1;
result = await money_action.changeMoney(req_currency_type, req_cost);
if(result.isFail())
{
return (result, null);
}
//=====================================================================================
// 3. 바디 아이템 소모 처리
//=====================================================================================
(result, Item? deleted_body_item) = await user_inventory_action.tryDeleteItemByGuid(request.BodyItemGuid);
if (result.isFail())
{
return (result, null);
}
NullReferenceCheckHelper.throwIfNull(deleted_body_item, () => $"deleted_body_item is null !!! - {owner.toBasicString()}");
var body_item_attribute_base = deleted_body_item.getEntityAttribute<ItemAttributeBase>();
NullReferenceCheckHelper.throwIfNull(body_item_attribute_base, () => $"body_item_attribute_base is null !!! - {owner.toBasicString()}");
//=====================================================================================
// 4. UgcNpc 생성
//=====================================================================================
var ugc_npc = new UgcNpc(owner.getUserGuid());
result = await ugc_npc.onInit();
if (result.isFail())
{
return (result, null);
}
//=====================================================================================
// 5. ugc npc 생성 정보 설정 하기
//=====================================================================================
var ugc_npc_attribute = ugc_npc.getEntityAttribute<UgcNpcAttribute>();
NullReferenceCheckHelper.throwIfNull(ugc_npc_attribute, () => $"ugc_npc_attribute is null !!! - {owner.toBasicString()}");
ugc_npc_attribute.OwnerEntityType = OwnerEntityType.User;
ugc_npc_attribute.OwnerGuid = owner.getUserGuid();
ugc_npc_attribute.LanguageType = account_attribute.LanguageType;
ugc_npc_attribute.UgcNpcMetaGuid = request.BodyItemGuid;
ugc_npc_attribute.Nickname = request.Nickname;
ugc_npc_attribute.Title = request.Title;
ugc_npc_attribute.Greeting = request.Greeting;
ugc_npc_attribute.Introduction = request.Introduction;
ugc_npc_attribute.Description = request.Description;
ugc_npc_attribute.WorldScenario = request.WorldScenario;
ugc_npc_attribute.DefaultSocialActionMetaId = (META_ID)request.DefaultSocialActionId;
ugc_npc_attribute.HabitSocialActionMetaIds = request.HabitSocialActionIds.Select<Int32, META_ID>(x => (META_ID)x).ToList();
ugc_npc_attribute.DialogueSocialActionMetaIds = request.DialogueSocialActionIds.Select<Int32, META_ID>(x => (META_ID)x).ToList();
ugc_npc_attribute.HashTagMetaIds = request.HashTagMetaIds.Select<Int32, META_ID>(x => (META_ID)x).ToList();
ugc_npc_attribute.BodyItemMetaId = body_item_attribute_base.ItemMetaId;
ugc_npc_attribute.newEntityAttribute();
//=====================================================================================
// 6. User의 보유 아이템들을 ugc npc로 소유권 이전 시킨다. (의상 & 타투 아이템 및 타투 Visible 설정)
//=====================================================================================
var ugc_npc_action = ugc_npc.getEntityAction<UgcNpcAction>();
NullReferenceCheckHelper.throwIfNull(ugc_npc_action, () => $"ugc_npc_action is null !!! - {owner.toBasicString()}");
result = await ugc_npc_action.tryTakableItemFromUser( request.MaterialItemGuids.ToList()
, request.TattooSlotVisibles.ToDictionary<Int32, BoolType>()
, m_reserved_slot_types
, owner );
if (result.isFail())
{
return (result, null);
}
m_reserved_ugc_npc_for_creation_nullable = ugc_npc;
return (result, ugc_npc);
}
public async Task<QueryBatchBase.QueryResultType> completedUgcNpcCreation(QueryExecutorBase queryExecutorBase)
{
await Task.CompletedTask;
var owner = getOwner() as Player;
NullReferenceCheckHelper.throwIfNull(owner, () => $"owner is null !!!");
ArgumentNullReferenceCheckHelper.throwIfNull(queryExecutorBase, () => $"queryExecutorBase is null !!! - {owner.toBasicString()}");
var result = new Result();
var err_msg = string.Empty;
var player_action = owner.getEntityAction<PlayerAction>();
NullReferenceCheckHelper.throwIfNull(player_action, () => $"player_action is null !!! - {owner.toBasicString()}");
var reserved_to_create_ugc_npc = getReservedUgcNpcForCreation();
NullReferenceCheckHelper.throwIfNull(reserved_to_create_ugc_npc, () => $"reserved_to_create_ugc_npc is null !!! - {owner.toBasicString()}");
var ugc_npc_attribute = reserved_to_create_ugc_npc.getOriginEntityAttribute<UgcNpcAttribute>();
NullReferenceCheckHelper.throwIfNull(ugc_npc_attribute, () => $"ugc_npc_attribute is null !!! - {owner.toBasicString()}");
var origin_ugc_npc_doc = ugc_npc_attribute.getOriginDocBase<UgcNpcAttribute>() as UgcNpcDoc;
NullReferenceCheckHelper.throwIfNull(origin_ugc_npc_doc, () => $"origin_ugc_npc_doc is null !!! - {owner.toBasicString()}");
result = await player_action.tryLoadUgcNpc(reserved_to_create_ugc_npc, origin_ugc_npc_doc);
if (result.isFail())
{
Log.getLogger().error(result.toBasicString());
}
var ugc_npc_action = reserved_to_create_ugc_npc.getEntityAction<UgcNpcAction>();
NullReferenceCheckHelper.throwIfNull(ugc_npc_action, () => $"ugc_npc_action is null !!! - {owner.toBasicString()}");
// AiChatServer에 UgcNpc를 등록 시도 한다.
result = await ugc_npc_action.tryRegisterCharacterWithAiChatServer(owner);
if (result.isFail())
{
err_msg = $"Failed to tryRegisterCharacterWithAiChatServer() !!! : {result.toBasicString()} - {owner.toBasicString()}";
Log.getLogger().error(err_msg);
}
// origin 메모리에 반영한다.
result = await player_action.commitTransaction(TransactionIdType.PrivateContents);
if (result.isFail())
{
err_msg = $"Failed to commitTransaction() !!! : {result.toBasicString()} - {owner.toBasicString()}";
Log.getLogger().error(err_msg);
}
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()}");
// 비즈니스 로그 추가
queryExecutorBase.appendBusinessLog(new BeaconCreateBusinessLog(log_action, DateTimeHelper.Current, m_beacon_create_log_info));
queryExecutorBase.appendBusinessLog(new BeaconBusinessLog(log_action, reserved_to_create_ugc_npc.toBeaconLogInfo()));
return QueryBatchBase.QueryResultType.Success;
}
public ServerErrorCode isValidNickname(string nickName)
{
// 첫번째 글자가 숫자인지 체크 한다.
if (Regex.IsMatch(nickName[0].ToString(), "[0-9]") == true)
{
return ServerErrorCode.UserNicknameNotAllowedNumberAtFirstChars;
}
// 특수문자가 포함되어 있는지 체크 한다.
if (true == nickName.isContainSpecialChars(out _))
{
return ServerErrorCode.UserNicknameNotAllowWithSpecialChars;
}
// 길이 체크
if (nickName.Length < MetaHelper.GameConfigMeta.UserNicknameMinLength ||
nickName.Length > MetaHelper.GameConfigMeta.UserNicknameMaxLength)
{
return ServerErrorCode.UserNicknameAllowedMin2ToMax12;
}
// 금지어 여부를 체크 한다.
if (StringRuleHelper.isBanWord(nickName, true) == true)
{
Log.getLogger().info($"User Nickname is Ban !!! : nickname:{nickName}");
return ServerErrorCode.UserNicknameBan;
}
return ServerErrorCode.Success;
}
public async Task<List<DynamoDbDocBase>> getDocs4UgcNpcCreation()
{
var owner = getOwner() as Player;
NullReferenceCheckHelper.throwIfNull(owner, () => $"owner is null !!!");
var to_create_docs = new List<DynamoDbDocBase>();
var user_attribute = owner.getEntityAttribute<UserAttribute>();
NullReferenceCheckHelper.throwIfNull(user_attribute, () => $"user_attribute is null !!! - {owner.toBasicString()}");
var reserved_ugc_npc_for_creation = getReservedUgcNpcForCreation();
NullReferenceCheckHelper.throwIfNull(reserved_ugc_npc_for_creation, () => $"reserved_ugc_npc_for_creation is null !!! - {owner.toBasicString()}");
var ugc_npc_attribute = reserved_ugc_npc_for_creation.getEntityAttribute<UgcNpcAttribute>();
NullReferenceCheckHelper.throwIfNull(ugc_npc_attribute, () => $"ugc_npc_attribute is null !!! - {owner.toBasicString()}");
// UgcNpc 닉네임 관련 DB 정보를 생성 한다.
{
var to_create_doc = new UgcNpcNicknameRegistryDoc(OwnerEntityType.User, user_attribute.UserGuid, ugc_npc_attribute.Nickname, ugc_npc_attribute.UgcNpcMetaGuid);
await to_create_doc.newDoc4Query();
to_create_docs.Add(to_create_doc);
}
// UgcNpc 좋아요 선택받은 개수 관련 DB 정보를 생성 한다.
{
var to_create_doc = new UgcNpcLikeSelecteeCountDoc(OwnerEntityType.UgcNpc, ugc_npc_attribute.UgcNpcMetaGuid);
await to_create_doc.newDoc4Query();
to_create_docs.Add(to_create_doc);
}
return to_create_docs;
}
public GS2C_ACK_UGC_NPC_CREATION toAckUgcNpcCreation()
{
var owner = getOwner() as Player;
NullReferenceCheckHelper.throwIfNull(owner, () => $"owner is null !!!");
NullReferenceCheckHelper.throwIfNull(m_reserved_ugc_npc_for_creation_nullable, () => $"m_reserved_ugc_npc_for_creation_nullable is null !!! - {owner.toBasicString()}");
var ugc_npc_attribute = m_reserved_ugc_npc_for_creation_nullable.getEntityAttribute<UgcNpcAttribute>();
NullReferenceCheckHelper.throwIfNull(ugc_npc_attribute, () => $"ugc_npc_attribute is null !!! - {owner.toBasicString()}");
var ugc_npc_inventory_action = m_reserved_ugc_npc_for_creation_nullable.getEntityAction<UgcNpcInventoryAction>();
NullReferenceCheckHelper.throwIfNull(ugc_npc_inventory_action, () => $"ugc_npc_inventory_action is null !!! - {owner.toBasicString()}");
var ack = new GS2C_ACK_UGC_NPC_CREATION();
ack.UgcNpcMetaGuid = ugc_npc_attribute.UgcNpcMetaGuid;
ack.Nickname = ugc_npc_attribute.Nickname;
ack.Title = ugc_npc_attribute.Title;
ack.Greeting = ugc_npc_attribute.Greeting;
ack.Introduction = ugc_npc_attribute.Introduction;
ack.Description = ugc_npc_attribute.Description;
ack.WorldScenario = ugc_npc_attribute.WorldScenario;
ack.DefaultSocialActionId = (Int32)ugc_npc_attribute.DefaultSocialActionMetaId;
ack.HabitSocialActionIds.AddRange(ugc_npc_attribute.HabitSocialActionMetaIds.Select<META_ID, Int32>(x => (Int32)x).ToList());
ack.DialogueSocialActionIds.AddRange(ugc_npc_attribute.DialogueSocialActionMetaIds.Select<META_ID, Int32>(x => (Int32)x).ToList());
ack.TattooSlotInfos.Add(ugc_npc_inventory_action.toTattooAll4Client().toMapField());
ack.HashTagMetaIds.Add(ugc_npc_attribute.HashTagMetaIds.Select<META_ID, Int32>(x => (Int32)x).ToList());
resetReserved4UgcNpcCreation();
var found_transaction_runner = owner.findTransactionRunner(TransactionIdType.PrivateContents);
if(null == found_transaction_runner)
{
var err_msg = $"Not found TransactionRunner !!! : {toBasicString()} - {owner.toBasicString()}";
Log.getLogger().warn(err_msg);
return ack;
}
ack.CommonResult = found_transaction_runner.getCommonResult();
return ack;
}
public UgcNpc? getReservedUgcNpcForCreation() => m_reserved_ugc_npc_for_creation_nullable;
}
}