초기커밋
This commit is contained in:
868
GameServer/Contents/UgcNpc/Action/UgcNpcCreationOrLoadAction.cs
Normal file
868
GameServer/Contents/UgcNpc/Action/UgcNpcCreationOrLoadAction.cs
Normal 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;
|
||||
}
|
||||
}
|
||||
655
GameServer/Contents/UgcNpc/Action/UgcNpcEditAction.cs
Normal file
655
GameServer/Contents/UgcNpc/Action/UgcNpcEditAction.cs
Normal file
@@ -0,0 +1,655 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using System.Numerics;
|
||||
|
||||
|
||||
using Amazon.S3.Model;
|
||||
|
||||
|
||||
using ServerCore; using ServerBase;
|
||||
using ServerCommon;
|
||||
using ServerCommon.BusinessLogDomain;
|
||||
using static ServerCommon.MetaHelper;
|
||||
|
||||
|
||||
using MetaAssets;
|
||||
|
||||
|
||||
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 ITEM_GUID = System.String;
|
||||
|
||||
|
||||
|
||||
namespace GameServer
|
||||
{
|
||||
public class UgcNpcEditAction : EntityActionBase
|
||||
{
|
||||
private UgcNpc? m_reserved_ugc_npc_for_edit_nullable;
|
||||
|
||||
private readonly Dictionary<InvenEquipType, HashSet<Int16>> m_reserved_slot_types = new();
|
||||
|
||||
public UgcNpcEditAction(UgcNpc 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 resetReserved4UgcNpcEdit()
|
||||
{
|
||||
m_reserved_ugc_npc_for_edit_nullable = null;
|
||||
}
|
||||
|
||||
private async Task<Result> checkEditConditions(C2GS_REQ_UGC_NPC_EDIT request)
|
||||
{
|
||||
await Task.CompletedTask;
|
||||
|
||||
var owner = getOwner() as UgcNpc;
|
||||
NullReferenceCheckHelper.throwIfNull(owner, () => $"owner is null !!!");
|
||||
NullReferenceCheckHelper.throwIfNull(request, () => $"request is null !!! - {owner.toBasicString()}");
|
||||
|
||||
var result = new Result();
|
||||
var err_msg = string.Empty;
|
||||
|
||||
var master = owner.onGetMasterEntity();
|
||||
if(null == master)
|
||||
{
|
||||
err_msg = $"Not found Master !!! - {owner.toBasicString()}";
|
||||
result.setFail(ServerErrorCode.MasterNotFound, err_msg);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
var ugc_npc_attribute = owner.getOriginEntityAttribute<UgcNpcAttribute>();
|
||||
NullReferenceCheckHelper.throwIfNull(ugc_npc_attribute, () => $"ugc_npc_attribute is null !!! - {owner.toBasicString()}");
|
||||
var ugc_npc_inventory_action = owner.getEntityAction<UgcNpcInventoryAction>();
|
||||
NullReferenceCheckHelper.throwIfNull(ugc_npc_inventory_action, () => $"ugc_npc_inventory_action is null !!! - {owner.toBasicString()}");
|
||||
var user_inventory_action = master.getEntityAction<UserInventoryAction>();
|
||||
NullReferenceCheckHelper.throwIfNull(user_inventory_action, () => $"user_inventory_action is null !!! - {owner.toBasicString()}");
|
||||
|
||||
//=====================================================================================
|
||||
// 1. 중복된 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;
|
||||
}
|
||||
|
||||
//=====================================================================================
|
||||
// 2. 문자열 길이 제한 체크 하기
|
||||
//=====================================================================================
|
||||
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;
|
||||
}
|
||||
|
||||
//=====================================================================================
|
||||
// 3. 소셜 액션 체크 하기
|
||||
//=====================================================================================
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
//=====================================================================================
|
||||
// 4. 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;
|
||||
}
|
||||
|
||||
//=====================================================================================
|
||||
// 5. 재료 아이템 체크 하기 : 의상 & 타투
|
||||
//=====================================================================================
|
||||
var to_chek_cloth_item_count = GameConfigMeta.NpcCreateDressRequirement;
|
||||
var to_chek_tattoo_item_count = GameConfigMeta.NpcCreateTattooRequirement;
|
||||
|
||||
if (false == MetaData.Instance.Meta.BeaconNpcMetaTable.BeaconNpcMetaDataListbyId.TryGetValue((Int32)ugc_npc_attribute.BodyItemMetaId, out var found_beacon_npc_meta))
|
||||
{
|
||||
err_msg = $"Not found BeaconNpcMetaData !!! : bodyItem < maxCount:{GameConfigMeta.MaxNpcIntroductionChar} - {owner.toBasicString()}";
|
||||
result.setFail(ServerErrorCode.UgcNpcIntroductionLengthExceed, 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)
|
||||
{
|
||||
found_item = ugc_npc_inventory_action.tryGetEquipItemByItemGuid(material_item_guid);
|
||||
if(null == found_item)
|
||||
{
|
||||
err_msg = $"Not found Material Item for Ugc Npc !!! : itemGuid:{material_item_guid} - {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;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
public async Task<(Result, UgcNpc?)> tryEditUgcNpc(C2GS_REQ_UGC_NPC_EDIT request)
|
||||
{
|
||||
var ugc_npc = getOwner() as UgcNpc;
|
||||
NullReferenceCheckHelper.throwIfNull(ugc_npc, () => $"ugc_npc is null !!!");
|
||||
|
||||
var result = new Result();
|
||||
var err_msg = string.Empty;
|
||||
|
||||
var master = ugc_npc.onGetMasterEntity() as Player;
|
||||
if (null == master)
|
||||
{
|
||||
err_msg = $"Not found Master !!! - {ugc_npc.toBasicString()}";
|
||||
result.setFail(ServerErrorCode.MasterNotFound, err_msg);
|
||||
|
||||
return (result, null);
|
||||
}
|
||||
|
||||
// 직전에 예약되어 있는 슬롯을 모두 초기화 한다.
|
||||
clearReservedSlotTypes();
|
||||
|
||||
var account_attribute = master.getOriginEntityAttribute<AccountAttribute>();
|
||||
NullReferenceCheckHelper.throwIfNull(request, () => $"request is null !!! - {ugc_npc.toBasicString()}");
|
||||
|
||||
var user_inventory_action = master.getEntityAction<UserInventoryAction>();
|
||||
NullReferenceCheckHelper.throwIfNull(user_inventory_action, () => $"user_inventory_action is null !!! - {ugc_npc.toBasicString()}");
|
||||
|
||||
//=====================================================================================
|
||||
// 1. 기본적인 편집 조건 체크 하기
|
||||
//=====================================================================================
|
||||
result = await checkEditConditions(request);
|
||||
if (result.isFail())
|
||||
{
|
||||
return (result, null);
|
||||
}
|
||||
|
||||
//=====================================================================================
|
||||
// 2. 금전 소모 처리
|
||||
//=====================================================================================
|
||||
var money_action = master.getEntityAction<MoneyAction>();
|
||||
NullReferenceCheckHelper.throwIfNull(request, () => $"request is null !!! - {master.toBasicString()}");
|
||||
|
||||
var req_currency_type = (CurrencyType)ServerCommon.MetaHelper.GameConfigMeta.NpcEditCurrency;
|
||||
result = await money_action.spendMoney(req_currency_type, GameConfigMeta.NpcEditCost);
|
||||
if (result.isFail())
|
||||
{
|
||||
return (result, null);
|
||||
}
|
||||
|
||||
//=====================================================================================
|
||||
// 3. 기타 재설정
|
||||
//=====================================================================================
|
||||
var ugc_npc_attribute = ugc_npc.getEntityAttribute<UgcNpcAttribute>();
|
||||
NullReferenceCheckHelper.throwIfNull(ugc_npc_attribute, () => $"ugc_npc_attribute is null !!! - {master.toBasicString()}");
|
||||
|
||||
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.modifiedEntityAttribute();
|
||||
|
||||
//=====================================================================================
|
||||
// 4. User의 보유 아이템들을 ugc npc로 소유권 이전 시킨다. (의상 & 타투 아이템 및 타투 Visible 설정)
|
||||
//=====================================================================================
|
||||
result = await tryTakableItemFromUser( request.MaterialItemGuids.ToList()
|
||||
, request.TattooSlotVisibles.ToDictionary<Int32, BoolType>()
|
||||
, m_reserved_slot_types
|
||||
, master );
|
||||
if (result.isFail())
|
||||
{
|
||||
return (result, null);
|
||||
}
|
||||
|
||||
m_reserved_ugc_npc_for_edit_nullable = ugc_npc;
|
||||
|
||||
return (result, ugc_npc);
|
||||
}
|
||||
|
||||
public async Task<Result> tryTakableItemFromUser( List<ITEM_GUID> materialItemGuids, Dictionary<Int32, BoolType> tattooSlotVisibles
|
||||
, Dictionary<InvenEquipType, HashSet<Int16>> reservedSlotTypes
|
||||
, Player master)
|
||||
{
|
||||
var ugc_npc = getOwner() as UgcNpc;
|
||||
NullReferenceCheckHelper.throwIfNull(ugc_npc, () => $"ugc_npc is null !!!");
|
||||
|
||||
var result = new Result();
|
||||
var err_msg = string.Empty;
|
||||
|
||||
var user_inventory_action = master.getEntityAction<UserInventoryAction>();
|
||||
NullReferenceCheckHelper.throwIfNull(user_inventory_action, () => $"user_inventory_action is null !!! - {master.toBasicString()}");
|
||||
var ugc_npc_inventory_action = ugc_npc.getEntityAction<UgcNpcInventoryAction>();
|
||||
NullReferenceCheckHelper.throwIfNull(ugc_npc_inventory_action, () => $"ugc_npc_inventory_action is null !!! - {ugc_npc.toBasicString()}");
|
||||
|
||||
//=====================================================================================
|
||||
// 1. 삭제해야 하는 아이템 목록을 Ugc Npc 장착 인벤에서 제거 한다.
|
||||
//=====================================================================================
|
||||
// 장착된 모든 아이템을 얻는다.
|
||||
var ugc_npc_equip_items = ugc_npc_inventory_action.getEquipItemAll();
|
||||
|
||||
// 삭제해야 하는 ITEM_GUID 목록을 추출 한다.
|
||||
var to_delete_item_guids = KeyComparer.getKeysOnlyInSecond( materialItemGuids
|
||||
, ugc_npc_equip_items.Select(x => {
|
||||
var ugc_npc_item_attribute = x.getEntityAttributeWithReadOnly<UgcNpcItemAttribute>();
|
||||
NullReferenceCheckHelper.throwIfNull(ugc_npc_item_attribute, () => $"ugc_npc_item_attribute is null !!! - {ugc_npc.toBasicString()}");
|
||||
return ugc_npc_item_attribute.ItemGuid;
|
||||
}).ToList()
|
||||
);
|
||||
|
||||
foreach(var to_delete_item_guid in to_delete_item_guids)
|
||||
{
|
||||
(result, var deleted_item) = await ugc_npc_inventory_action.tryDeleteItemByGuid(to_delete_item_guid);
|
||||
if (result.isFail())
|
||||
{
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
//=====================================================================================
|
||||
// 2. 추가해야 하는 아이템 목록을 Ugc Npc 장착 인벤에 추가 한다. User => UgcNpc
|
||||
//=====================================================================================
|
||||
// 소유자를 변경해야 하는 ITEM_GUID 목록을 추출 한다.
|
||||
var to_change_owner_item_guids = KeyComparer.getKeysOnlyInSecond( ugc_npc_equip_items.Select(x => {
|
||||
var ugc_npc_item_attribute = x.getEntityAttributeWithReadOnly<UgcNpcItemAttribute>();
|
||||
NullReferenceCheckHelper.throwIfNull(ugc_npc_item_attribute, () => $"ugc_npc_item_attribute is null !!! - {ugc_npc.toBasicString()}");
|
||||
return ugc_npc_item_attribute.ItemGuid;
|
||||
}).ToList()
|
||||
, materialItemGuids
|
||||
);
|
||||
|
||||
foreach (var to_change_owner_item_guid in to_change_owner_item_guids)
|
||||
{
|
||||
var found_item = user_inventory_action.tryGetItemByItemGuid(to_change_owner_item_guid);
|
||||
if(null == found_item)
|
||||
{
|
||||
err_msg = $"Not found Item for Owner Change !!!, in UserInventory : itemGuid:{to_change_owner_item_guid} - {ugc_npc.toBasicString()}";
|
||||
result.setFail(ServerErrorCode.ItemNotFound, err_msg);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
var item_meta = found_item.getItemMeta();
|
||||
NullReferenceCheckHelper.throwIfNull(item_meta, () => $"item_meta is null !!! - {master.toBasicString()}");
|
||||
|
||||
var backup_item_attribute = found_item.getClonedEntityAttribute<UserItemAttribute>();
|
||||
NullReferenceCheckHelper.throwIfNull(backup_item_attribute, () => $"backup_item_attribute is null !!! - {master.toBasicString()}");
|
||||
|
||||
(result, var deleted_item) = await user_inventory_action.tryDeleteItemByGuid(to_change_owner_item_guid);
|
||||
if (result.isFail())
|
||||
{
|
||||
return result;
|
||||
}
|
||||
|
||||
(result, ItemDoc? to_create_item_doc_of_ugc_npc) = await backup_item_attribute.changeOwnerAndCreateItemDoc(OwnerEntityType.UgcNpc, ugc_npc.getUgcNpcMetaGuid());
|
||||
if (result.isFail())
|
||||
{
|
||||
return result;
|
||||
}
|
||||
NullReferenceCheckHelper.throwIfNull(to_create_item_doc_of_ugc_npc, () => $"to_create_item_doc_of_ugc_npc is null !!! - {master.toBasicString()}");
|
||||
|
||||
(result, var equipable_slot) = ugc_npc_inventory_action.getEquipableSlotOfEquipInven(item_meta, reservedSlotTypes);
|
||||
if (result.isFail())
|
||||
{
|
||||
return result;
|
||||
}
|
||||
|
||||
(result, _) = await ugc_npc_inventory_action.tryTakableToBagWithEquip(to_create_item_doc_of_ugc_npc, equipable_slot);
|
||||
if (result.isFail())
|
||||
{
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
//=====================================================================================
|
||||
// 2. 타투 아이템 보이기/안보이기 설정
|
||||
//=====================================================================================
|
||||
var tattoo_inven = ugc_npc_inventory_action.getEquipInvens()[InvenEquipType.Tattoo] as TattooEquipInven;
|
||||
NullReferenceCheckHelper.throwIfNull(tattoo_inven, () => $"tattoo_inven is null !!! - {master.toBasicString()}");
|
||||
|
||||
foreach (var each in tattooSlotVisibles)
|
||||
{
|
||||
var slot_index = each.Key;
|
||||
var slot_visible = each.Value;
|
||||
|
||||
if (false == InvenEquipType.Tattoo.isEquipableTattooSlotType((TattooSlotType)slot_index, ugc_npc.getEntityType()))
|
||||
{
|
||||
err_msg = $"Not found TattooSlotType !!! : slotType:{slot_index} - {toBasicString()}, {master.toBasicString()}";
|
||||
result.setFail(ServerErrorCode.TattooEquipRuleTattooSlotTypeNotFound, err_msg);
|
||||
Log.getLogger().error(result.toBasicString());
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
var custom_defined_ui_action = ugc_npc.getEntityAction<CustomDefinedUiAction>();
|
||||
NullReferenceCheckHelper.throwIfNull(custom_defined_ui_action, () => $"custom_defined_ui_action is null !!! - {toBasicString()}, {master.toBasicString()}");
|
||||
|
||||
var tattoo_slot = (TattooSlotType)slot_index;
|
||||
result = await custom_defined_ui_action.setTattooVisible(tattoo_slot, (slot_visible == BoolType.True ? true : false));
|
||||
if(result.isFail())
|
||||
{
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
public async Task<QueryBatchBase.QueryResultType> completedUgcNpcEdit(QueryExecutorBase queryExecutorBase)
|
||||
{
|
||||
await Task.CompletedTask;
|
||||
|
||||
var owner = getOwner() as UgcNpc;
|
||||
NullReferenceCheckHelper.throwIfNull(owner, () => $"owner is null !!!");
|
||||
|
||||
var result = new Result();
|
||||
var err_msg = string.Empty;
|
||||
|
||||
var query_result = QueryBatchBase.QueryResultType.Success;
|
||||
|
||||
var master = owner.onGetMasterEntity() as Player;
|
||||
if (null == master)
|
||||
{
|
||||
err_msg = $"Not found Master !!! - {owner.toBasicString()}";
|
||||
result.setFail(ServerErrorCode.MasterNotFound, err_msg);
|
||||
Log.getLogger().error(result.toBasicString());
|
||||
|
||||
return query_result;
|
||||
}
|
||||
|
||||
// AiChatServer에 UgcNpc를 시도 한다.
|
||||
result = await tryEditCharacterWithAiChatServer(master);
|
||||
if (result.isFail())
|
||||
{
|
||||
err_msg = $"Failed to tryEditCharacterWithAiChatServer() !!!, {result.toBasicString()} - {master.toBasicString()}";
|
||||
Log.getLogger().error(err_msg);
|
||||
}
|
||||
|
||||
var query_batch = queryExecutorBase.getQueryBatch();
|
||||
NullReferenceCheckHelper.throwIfNull(query_batch, () => $"query_batch is null !!! - {master.toBasicString()}");
|
||||
var log_action = query_batch.getLogAction();
|
||||
NullReferenceCheckHelper.throwIfNull(log_action, () => $"log_action is null !!! - {master.toBasicString()}");
|
||||
|
||||
// 비즈니스 로그 추가
|
||||
queryExecutorBase.appendBusinessLog(new BeaconBusinessLog(log_action, owner.toBeaconLogInfo()));
|
||||
|
||||
return QueryBatchBase.QueryResultType.Success;
|
||||
}
|
||||
|
||||
public async Task<Result> tryEditCharacterWithAiChatServer(Player master)
|
||||
{
|
||||
var ugc_npc = getOwner() as UgcNpc;
|
||||
NullReferenceCheckHelper.throwIfNull(ugc_npc, () => $"ugc_npc is null !!!");
|
||||
|
||||
var server_logic = GameServerApp.getServerLogic();
|
||||
|
||||
var result = new Result();
|
||||
var err_msg = string.Empty;
|
||||
|
||||
var ugc_npc_action = ugc_npc.getEntityAction<UgcNpcAction>();
|
||||
NullReferenceCheckHelper.throwIfNull(ugc_npc_action, () => $"ugc_npc_action is null !!! - {ugc_npc.toBasicStringWithMaster()}");
|
||||
|
||||
var ai_chat_action = master.getEntityAction<AIChatAction>();
|
||||
NullReferenceCheckHelper.throwIfNull(ai_chat_action, () => $"ai_chat_action is null !!! - {master.toBasicString()}");
|
||||
|
||||
var ugc_npc_attribute = ugc_npc.getEntityAttribute<UgcNpcAttribute>();
|
||||
NullReferenceCheckHelper.throwIfNull(ugc_npc_attribute, () => $"ugc_npc_attribute is null !!! - {ugc_npc.toBasicStringWithMaster()}");
|
||||
|
||||
if(false == ugc_npc_attribute.IsRegisteredAiChatServer)
|
||||
{
|
||||
err_msg = $"Not registered UgcNpc at AiChatServer !!! : ugcNpcMetaGuid:{ugc_npc_attribute.UgcNpcMetaGuid}, ugcNpcNickname:{ugc_npc_attribute.Nickname}, "
|
||||
+ $" - {ugc_npc.toBasicStringWithMaster()}";
|
||||
Log.getLogger().error(err_msg);
|
||||
|
||||
result = await ai_chat_action.registerCharacter(ugc_npc_action.toRegisterInfoWithAiChatServer());
|
||||
if (result.isFail())
|
||||
{
|
||||
err_msg = $"Failed to AiChatAction.registerCharacter() !!!, {result.toBasicString()}";
|
||||
Log.getLogger().error(err_msg);
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
result = await ai_chat_action.updateCharacter(ugc_npc_action.toRegisterInfoWithAiChatServer());
|
||||
if (result.isFail())
|
||||
{
|
||||
err_msg = $"Failed to AiChatAction.updateCharacter() !!!, {result.toBasicString()}";
|
||||
Log.getLogger().error(err_msg);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
ugc_npc_attribute.IsRegisteredAiChatServer = true;
|
||||
ugc_npc_attribute.modifiedEntityAttribute();
|
||||
|
||||
(result, var ugc_npc_doc) = await ugc_npc_attribute.toDocBase();
|
||||
if (result.isFail() || null == ugc_npc_doc)
|
||||
{
|
||||
return result;
|
||||
}
|
||||
|
||||
var dynamo_db_client = server_logic.getDynamoDbClient();
|
||||
NullReferenceCheckHelper.throwIfNull(dynamo_db_client, () => $"dynamo_db_client is null !!! - {ugc_npc.toBasicStringWithMaster()}");
|
||||
|
||||
result = await dynamo_db_client.simpleUpsertDocumentWithDocType(ugc_npc_doc);
|
||||
if (result.isFail())
|
||||
{
|
||||
err_msg = $"Failed to DynamoDbClient.simpleUpsertDocumentWithDocType() !!! : {result.toBasicString()} - {ugc_npc.toBasicStringWithMaster()}";
|
||||
Log.getLogger().error(err_msg);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
public async Task<(Result, GS2C_ACK_UGC_NPC_EDIT?)> toAckUgcNpcEdit()
|
||||
{
|
||||
var ugc_npc = getOwner() as UgcNpc;
|
||||
NullReferenceCheckHelper.throwIfNull(ugc_npc, () => $"ugc_npc is null !!!");
|
||||
|
||||
var result = new Result();
|
||||
var err_msg = string.Empty;
|
||||
|
||||
var master = ugc_npc.onGetMasterEntity();
|
||||
if (null == master)
|
||||
{
|
||||
err_msg = $"Not found Master !!! - {ugc_npc.toBasicString()}";
|
||||
result.setFail(ServerErrorCode.MasterNotFound, err_msg);
|
||||
|
||||
return (result, null);
|
||||
}
|
||||
|
||||
NullReferenceCheckHelper.throwIfNull(m_reserved_ugc_npc_for_edit_nullable, () => $"m_reserved_ugc_npc_for_edit_nullable is null !!! - {ugc_npc.toBasicString()}");
|
||||
|
||||
var ugc_npc_attribute = m_reserved_ugc_npc_for_edit_nullable.getEntityAttribute<UgcNpcAttribute>();
|
||||
NullReferenceCheckHelper.throwIfNull(ugc_npc_attribute, () => $"ugc_npc_attribute is null !!! - {ugc_npc.toBasicString()}");
|
||||
|
||||
var ugc_npc_inventory_action = m_reserved_ugc_npc_for_edit_nullable.getEntityAction<UgcNpcInventoryAction>();
|
||||
NullReferenceCheckHelper.throwIfNull(ugc_npc_inventory_action, () => $"ugc_npc_inventory_action is null !!! - {ugc_npc.toBasicString()}");
|
||||
|
||||
var ack = new GS2C_ACK_UGC_NPC_EDIT();
|
||||
ack.EditedUgcNpcMetaGuid = ugc_npc_attribute.UgcNpcMetaGuid;
|
||||
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.HashTagMetaIds.Add(ugc_npc_attribute.HashTagMetaIds.Select<META_ID, Int32>(x => (Int32)x).ToList());
|
||||
|
||||
resetReserved4UgcNpcEdit();
|
||||
|
||||
var found_transaction_runner = master.findTransactionRunner(TransactionIdType.PrivateContents);
|
||||
if (null == found_transaction_runner)
|
||||
{
|
||||
err_msg = $"Not found TransactionRunner !!! : {toBasicString()} - {ugc_npc.toBasicString()}";
|
||||
Log.getLogger().warn(err_msg);
|
||||
|
||||
return (result, null);
|
||||
}
|
||||
|
||||
ack.CommonResult = found_transaction_runner.getCommonResult();
|
||||
|
||||
return await Task.FromResult((result, ack));
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user