초기커밋

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;
}
}

View 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));
}
}
}

View File

@@ -0,0 +1,257 @@
using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using Amazon.DynamoDBv2.Model;
using Google.Protobuf.WellKnownTypes;
using ServerCore; using ServerBase;
using ServerCommon;
using DYNAMO_DB_TABLE_FULL_NAME = System.String;
using SESSION_ID = System.Int32;
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 DBQUgcNpcLikeSelectedFlagUpdate : QueryExecutorBase
{
private string m_combination_key_for_pk = string.Empty;
private string m_combination_key_for_sk = string.Empty;
private bool m_is_update_last_date = false;
private PrimaryKey m_primary_key = new();
//=====================================================================================
// 0 < deltaCount => 증가
// 0 > deltaCount => 감소
//=====================================================================================
public DBQUgcNpcLikeSelectedFlagUpdate( string combinationKeyForPK
, string combinationKeyForSK
, bool isUpdateLastDate = false)
: base(typeof(DBQUgcNpcLikeSelectedFlagUpdate).Name)
{
m_combination_key_for_pk = combinationKeyForPK;
m_combination_key_for_sk = combinationKeyForSK;
m_is_update_last_date = isUpdateLastDate;
}
//=====================================================================================
// DB 쿼리 직전에 준비해야 할 로직들을 작성한다.
//=====================================================================================
public override async Task<Result> onPrepareQuery()
{
await Task.CompletedTask;
var result = new Result();
var err_msg = string.Empty;
var owner = getOwner();
(result, var make_primary_key) = await DynamoDBDocBaseHelper.makePrimaryKey<UgcNpcLikeSelectedFlagDoc>(m_combination_key_for_pk, m_combination_key_for_sk);
if (result.isFail())
{
return result;
}
NullReferenceCheckHelper.throwIfNull(make_primary_key, () => $"make_primary_key is null !!! - {owner.toBasicString()}");
m_primary_key = make_primary_key;
return result;
}
//=====================================================================================
// onPrepareQuery()를 성공할 경우 호출된다.
//=====================================================================================
public override async Task<Result> onQuery()
{
var result = new Result();
var err_msg = string.Empty;
var owner = getOwner();
var query_batch = getQueryBatch();
NullReferenceCheckHelper.throwIfNull(query_batch, () => $"query_batch is null !!! - {owner.toBasicString()}");
var query_runner_with_item_request = query_batch.getQueryRunner();
NullReferenceCheckHelper.throwIfNull(query_runner_with_item_request, () => $"query_runner_with_item_request is null !!! - {owner.toBasicString()}");
var db_connector = query_batch.getDynamoDbConnector();
var selected_flag_query_config = db_connector.makeQueryConfigForReadByPKSK(m_primary_key.PK, m_primary_key.SK);
(result, var found_selected_flag_docs) = await db_connector.simpleQueryDocTypesWithQueryOperationConfig<UgcNpcLikeSelectedFlagDoc>(selected_flag_query_config, eventTid: query_batch.getTransId());
if (result.isFail())
{
return result;
}
if (0 == found_selected_flag_docs.Count)
{
// UgcNpcLikeSelectedFlagDoc 없다면 PutItemRequest를 처리 한다.
var doc = new UgcNpcLikeSelectedFlagDoc(OwnerEntityType.User, m_combination_key_for_pk, m_combination_key_for_sk);
var attrib = doc.getAttrib<UgcNpcLikeSelectedFlagAttrib>();
NullReferenceCheckHelper.throwIfNull(attrib, () => $"attrib is null !!!");
attrib.IsSelectedFlag = true;
if (m_is_update_last_date) attrib.LastCheckDate = DateTimeHelper.Current;
(result, var result_document) = await doc.onCopyToDocument();
if (result.isFail())
{
err_msg = $"Failed to onCopyToDocument() !!! : {result.toBasicString()}, {doc.toDocTypePKSK()} - {owner.toBasicString()}";
Log.getLogger().error(err_msg);
return result;
}
// PutItemRequest 생성하는 simple 계열의 함수를 DynamoDbClientHelper에 추가한다.
var put_item_request = new PutItemRequest();
put_item_request.TableName = db_connector.getTableFullName(doc.TableName);
put_item_request.Item = result_document.ToAttributeMap();
var query_context = put_item_request.createItemRequestQueryContext(QueryType.Insert);
result = await query_runner_with_item_request.tryRegisterQueryContext(query_context);
}
else
{
// UgcNpcLikeSelectedFlagDoc 있다면 UpdateItemRequest를 처리 한다.
var selected_flag_attrib = found_selected_flag_docs[0].getAttrib<UgcNpcLikeSelectedFlagAttrib>();
NullReferenceCheckHelper.throwIfNull(selected_flag_attrib, () => $"selected_flag_attrib is null !!! - {owner.toBasicString()}");
var to_update_flag = (true == selected_flag_attrib.IsSelectedFlag ? false : true);
var change_attrib_data = new Dictionary<string, string>();
change_attrib_data.Add(nameof(UgcNpcLikeSelectedFlagAttrib.IsSelectedFlag), to_update_flag.ToString());
if(m_is_update_last_date) change_attrib_data.Add(nameof(UgcNpcLikeSelectedFlagAttrib.LastCheckDate), DateTimeHelper.Current.ToString(CultureInfo.InvariantCulture));
// UpdateItemRequest를 생성하는 simple 계열의 함수를 DynamoDbClientHelper에 추가한다.
(result, var update_item_request) = makeUpdateItemRequest( db_connector
, db_connector.getTableFullName(found_selected_flag_docs[0].TableName)
, m_primary_key.toKeyWithAttributeValue()
, change_attrib_data );
if (result.isFail())
{
return result;
}
NullReferenceCheckHelper.throwIfNull(update_item_request, () => $"update_item_request is null !!! - {owner.toBasicString()}");
var query_context = update_item_request.createItemRequestQueryContext(QueryType.Upsert);
result = await query_runner_with_item_request.tryRegisterQueryContext(query_context);
}
return result;
}
private (Result, UpdateItemRequest?) makeUpdateItemRequest( DynamoDbClient dbClient
, DYNAMO_DB_TABLE_FULL_NAME tableFullName
, Dictionary<string, AttributeValue> attributeValueWithPrimaryKey
, Dictionary<string, string> changeAttribs)
{
var result = new Result();
var owner = getOwner();
NullReferenceCheckHelper.throwIfNull(owner, () => $"owner is null !!!");
var update_item_request = new UpdateItemRequest();
update_item_request.TableName = tableFullName;
update_item_request.Key = attributeValueWithPrimaryKey;
update_item_request.ExpressionAttributeNames = new Dictionary<string, string>();
var target_doc = new UgcNpcLikeSelectedFlagDoc();
var attrib_path_json_string = target_doc.toJsonStringOfAttribs();
var expressionAttributeValues = new Dictionary<string, AttributeValue>();
var update_expression = "SET ";
var expression_idx = 0;
if (changeAttribs.Count <= 0)
{
var err_msg = $"Failed to DynamoDbClientHelper.toAttributeExpressionFromJson() !!! : attribPath:{attrib_path_json_string} - {owner.toBasicString()}";
result.setFail(ServerErrorCode.AttribPathMakeFailed, err_msg);
Log.getLogger().error(result.toBasicString());
return (result, null);
}
foreach (var data in changeAttribs)
{
var target_key = JsonHelper.getJsonPropertyName<UgcNpcLikeSelectedFlagAttrib>(data.Key);
(var is_success, var attribute_expression) = DynamoDbClientHelper.toAttributeExpressionFromJson(attrib_path_json_string, target_key);
if(false == is_success)
{
var err_msg = $"Failed to DynamoDbClientHelper.toAttributeExpressionFromJson() !!! : attribPath:{attrib_path_json_string}, targetKey:{target_key} - {owner.toBasicString()}";
result.setFail(ServerErrorCode.AttribPathMakeFailed, err_msg);
Log.getLogger().error(result.toBasicString());
continue;
}
var expressionAttributeNames = DynamoDbClientHelper.toExpressionAttributeNamesFromJson(attrib_path_json_string, target_key);
foreach (var name in expressionAttributeNames)
{
update_item_request.ExpressionAttributeNames.TryAdd(name.Key, name.Value);
}
if (expression_idx > 0) update_expression += ",";
update_expression += $" {attribute_expression} = :newValue_{expression_idx}";
expressionAttributeValues.Add($":newValue_{expression_idx}", new AttributeValue { S = data.Value });
expression_idx++;
}
update_item_request.UpdateExpression = update_expression;
update_item_request.ExpressionAttributeValues = expressionAttributeValues;
update_item_request.ReturnValues = "ALL_NEW";
return (result, update_item_request);
}
//=====================================================================================
// DB 쿼리를 성공하고, doFnCommit()가 QueryResultType.NotCalledQueryFunc를 반환할 경우 호출된다.
//=====================================================================================
public override async Task onQueryResponseCommit()
{
await Task.CompletedTask;
return;
}
//=====================================================================================
// DB 쿼리를 실패하고, doFnRollback()가 QueryResultType.NotCalledQueryFunc를 반환할 경우 호출된다.
//=====================================================================================
public override async Task onQueryResponseRollback(Result errorResult)
{
await Task.CompletedTask;
return;
}
public override Player getOwner()
{
var owner = base.getOwner() as Player;
NullReferenceCheckHelper.throwIfNull(owner, () => $"owner is null !!!");
return owner;
}
}
}

View File

@@ -0,0 +1,188 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using Amazon.DynamoDBv2.Model;
using ServerCore; using ServerBase;
using ServerCommon;
using DYNAMO_DB_TABLE_FULL_NAME = System.String;
using SESSION_ID = System.Int32;
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 DBQUgcNpcLikeSelecteeCountUpdate : QueryExecutorBase
{
private string m_combination_key_for_pk = string.Empty;
private Int32 m_delta_count = 0;
private PrimaryKey m_primary_key = new();
//=====================================================================================
// 0 < deltaCount => 증가
// 0 > deltaCount => 감소
//=====================================================================================
public DBQUgcNpcLikeSelecteeCountUpdate( string combinationKeyForPK
, Int32 deltaCount )
: base(typeof(DBQUgcNpcLikeSelecteeCountUpdate).Name)
{
m_combination_key_for_pk = combinationKeyForPK;
m_delta_count = deltaCount;
}
//=====================================================================================
// DB 쿼리 직전에 준비해야 할 로직들을 작성한다.
//=====================================================================================
public override async Task<Result> onPrepareQuery()
{
await Task.CompletedTask;
var result = new Result();
var err_msg = string.Empty;
var owner = getOwner();
NullReferenceCheckHelper.throwIfNull(owner, () => $"owner is null !!!");
(result, var make_primary_key) = await DynamoDBDocBaseHelper.makePrimaryKey<UgcNpcLikeSelecteeCountDoc>(m_combination_key_for_pk);
if (result.isFail())
{
return result;
}
NullReferenceCheckHelper.throwIfNull(make_primary_key, () => $"make_primary_key is null !!! - {owner.toBasicString()}");
m_primary_key = make_primary_key;
return result;
}
//=====================================================================================
// onPrepareQuery()를 성공할 경우 호출된다.
//=====================================================================================
public override async Task<Result> onQuery()
{
await Task.CompletedTask;
var result = new Result();
var err_msg = string.Empty;
var owner = getOwner();
var query_batch = getQueryBatch() as QueryBatch<QueryRunnerWithItemRequest>;
NullReferenceCheckHelper.throwIfNull(query_batch, () => $"query_batch is null !!! - {owner.toBasicString()}");
var query_runner_with_item_request = query_batch.getQueryRunner();
NullReferenceCheckHelper.throwIfNull(query_runner_with_item_request, () => $"query_runner_with_item_request is null !!! - {owner.toBasicString()}");
var db_connector = query_batch.getDynamoDbConnector();
var table = db_connector.getTableByDoc<UgcNpcLikeSelecteeCountDoc>();
var delta_count = m_delta_count;
(result, var update_item_request) = makeUpdateItemRequest( db_connector
, table.TableName
, m_primary_key.toKeyWithAttributeValue()
, nameof(UgcNpcLikeSelecteeCountAttrib.LikeCount)
, delta_count );
if (result.isFail())
{
return result;
}
NullReferenceCheckHelper.throwIfNull(update_item_request, () => $"update_item_request is null !!! - {owner.toBasicString()}");
var query_context = update_item_request.createItemRequestQueryContext(QueryType.Upsert);
result = await query_runner_with_item_request.tryRegisterQueryContext(query_context);
return result;
}
private (Result, UpdateItemRequest?) makeUpdateItemRequest( DynamoDbClient dbClient, DYNAMO_DB_TABLE_FULL_NAME tableFullName
, Dictionary<string, AttributeValue> attributeValueWithPrimaryKey
, string targetAttribName
, Int32 deltaCount )
{
var result = new Result();
var owner = getOwner();
var update_item_request = new UpdateItemRequest();
update_item_request.TableName = tableFullName;
update_item_request.Key = attributeValueWithPrimaryKey;
var target_doc = new UgcNpcLikeSelecteeCountDoc();
var attrib_path_json_string = target_doc.toJsonStringOfAttribs();
var target_key = JsonHelper.getJsonPropertyName<UgcNpcLikeSelecteeCountAttrib>(targetAttribName);
(var is_success, var attribute_expression) = DynamoDbClientHelper.toAttributeExpressionFromJson(attrib_path_json_string, target_key);
if (false == is_success)
{
var err_msg = $"Failed to DynamoDbClientHelper.toAttributeExpressionFromJson() !!! : attribPath:{attrib_path_json_string}, targetKey:{target_key} - {owner.toBasicString()}";
result.setFail(ServerErrorCode.AttribPathMakeFailed, err_msg);
Log.getLogger().error(result.toBasicString());
return (result, null);
}
// ExpressionAttributeNames를 설정 한다.
update_item_request.ExpressionAttributeNames = DynamoDbClientHelper.toExpressionAttributeNamesFromJson(attrib_path_json_string, target_key);
var update_expression = $"SET {attribute_expression} = if_not_exists({attribute_expression}, :start) + :incr";
update_item_request.UpdateExpression = update_expression;
var expressionAttributeValues = new Dictionary<string, AttributeValue>
{
{ ":incr", new AttributeValue { N = deltaCount.ToString() } },
{ ":start", new AttributeValue { N = "0" } }
};
update_item_request.ExpressionAttributeValues = expressionAttributeValues;
update_item_request.ReturnValues = "ALL_NEW";
return (result, update_item_request);
}
//=====================================================================================
// DB 쿼리를 성공하고, doFnCommit()가 QueryResultType.NotCalledQueryFunc를 반환할 경우 호출된다.
//=====================================================================================
public override async Task onQueryResponseCommit()
{
await Task.CompletedTask;
return;
}
//=====================================================================================
// DB 쿼리를 실패하고, doFnRollback()가 QueryResultType.NotCalledQueryFunc를 반환할 경우 호출된다.
//=====================================================================================
public override async Task onQueryResponseRollback(Result errorResult)
{
await Task.CompletedTask;
return;
}
public override Player getOwner()
{
var owner = base.getOwner() as Player;
NullReferenceCheckHelper.throwIfNull(owner, () => $"owner is null !!!");
return owner;
}
}
}

View File

@@ -0,0 +1,170 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using ServerCore; using ServerBase;
using ServerCommon;
using UGC_NPC_META_GUID = System.String;
namespace GameServer
{
public class DBQUgcNpcReadAll : QueryExecutorBase
{
private string m_combination_key_for_pk = string.Empty;
private string m_pk = string.Empty;
private readonly List<UgcNpcDoc> m_to_read_npc_docs = new();
private readonly List<AppearanceCustomizeDoc> m_to_read_appearance_customize_docs = new();
private readonly HashSet<UGC_NPC_META_GUID> m_attached_ugc_npc_meta_guid = new();
public DBQUgcNpcReadAll(string combinationKeyForPK)
: base(typeof(DBQUgcNpcReadAll).Name)
{
m_combination_key_for_pk = combinationKeyForPK;
}
//=====================================================================================
// DB 쿼리 직전에 준비해야 할 로직들을 작성한다.
//=====================================================================================
public override async Task<Result> onPrepareQuery()
{
await Task.CompletedTask;
var result = new Result();
var err_msg = string.Empty;
var owner = getOwner();
(result, var make_primary_key) = await DynamoDBDocBaseHelper.makePrimaryKey<UgcNpcDoc>(m_combination_key_for_pk);
if (result.isFail())
{
return result;
}
NullReferenceCheckHelper.throwIfNull(make_primary_key, () => $"make_primary_key is null !!! - {owner.toBasicString()}");
m_pk = make_primary_key.PK;
return result;
}
//=====================================================================================
// onPrepareQuery()를 성공할 경우 호출된다.
//=====================================================================================
public override async Task<Result> onQuery()
{
await Task.CompletedTask;
var result = new Result();
var err_msg = string.Empty;
var owner = getOwner();
var server_logic = GameServerApp.getServerLogic();
var player_action = owner.getEntityAction<PlayerAction>();
NullReferenceCheckHelper.throwIfNull(player_action, () => $"player_action is null !!! - {owner.toBasicString()}");
var query_batch = getQueryBatch();
NullReferenceCheckHelper.throwIfNull(query_batch, () => $"query_batch is null !!!");
var db_connector = query_batch.getDynamoDbConnector();
var query_config = db_connector.makeQueryConfigForReadByPKOnly(m_pk);
(result, var read_docs) = await db_connector.simpleQueryDocTypesWithQueryOperationConfig<UgcNpcDoc>(query_config, eventTid: query_batch.getTransId());
if (result.isFail())
{
return result;
}
var ugc_npc_creation_or_load_action = owner.getEntityAction<UgcNpcCreationOrLoadAction>();
NullReferenceCheckHelper.throwIfNull(ugc_npc_creation_or_load_action, () => $"ugc_npc_creation_or_load_action is null !!! - {owner.toBasicString()}");
foreach (var read_ugc_npc_doc in read_docs)
{
var ugc_npc_attrib = read_ugc_npc_doc.getAttrib<UgcNpcAttrib>();
NullReferenceCheckHelper.throwIfNull(ugc_npc_attrib, () => $"ugc_npc_attrib is null !!! - {owner.toBasicString()}");
var found_ugc_npc_in_game_zone = server_logic.findUgcNpcInGameZone(ugc_npc_attrib.UgcNpcMetaGuid);
if(null != found_ugc_npc_in_game_zone)
{
result = await player_action.tryAttachUgcNpcInGameZone(found_ugc_npc_in_game_zone);
if(result.isFail())
{
return result;
}
m_attached_ugc_npc_meta_guid.Add(ugc_npc_attrib.UgcNpcMetaGuid);
}
else
{
result = await ugc_npc_creation_or_load_action.tryLoadUgcNpcFromDoc(read_ugc_npc_doc);
if (result.isFail())
{
return result;
}
result = await ugc_npc_creation_or_load_action.tryLoadApprearanceCustomize(db_connector, ugc_npc_attrib.UgcNpcMetaGuid);
if (result.isFail())
{
return result;
}
result = await ugc_npc_creation_or_load_action.tryLoadBeaconShopItem(db_connector, ugc_npc_attrib.UgcNpcMetaGuid);
if (result.isFail())
{
return result;
}
result = await ugc_npc_creation_or_load_action.tryLoadBeaconShopProfile(db_connector, ugc_npc_attrib.UgcNpcMetaGuid);
if (result.isFail())
{
return result;
}
m_to_read_npc_docs.Add(read_ugc_npc_doc);
}
}
return result;
}
public HashSet<UGC_NPC_META_GUID> getAttachedUgcNpcGuids() => m_attached_ugc_npc_meta_guid;
public List<UgcNpcDoc> getToReadUgcNpcDocs() => m_to_read_npc_docs;
//=====================================================================================
// DB 쿼리를 성공하고, doFnCommit()가 QueryResultType.NotCalledQueryFunc를 반환할 경우 호출된다.
//=====================================================================================
public override async Task onQueryResponseCommit()
{
await Task.CompletedTask;
return;
}
//=====================================================================================
// DB 쿼리를 실패하고, doFnRollback()가 QueryResultType.NotCalledQueryFunc를 반환할 경우 호출된다.
//=====================================================================================
public override async Task onQueryResponseRollback(Result errorResult)
{
await Task.CompletedTask;
return;
}
public override Player getOwner()
{
var owner = base.getOwner() as Player;
NullReferenceCheckHelper.throwIfNull(owner, () => $"owner is null !!!");
return owner;
}
}
}

View File

@@ -0,0 +1,92 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Nettention.Proud;
using ServerCore; using ServerBase;
using ServerCommon;
using ServerCommon.BusinessLogDomain;
using GameServer;
namespace GameServer
{
public static class BeaconBusinessLogHelper
{
public static BeaconLogInfo toBeaconLogInfo(this UgcNpc ugcNpc)
{
var ugc_npc_attribute = ugcNpc.getEntityAttribute<UgcNpcAttribute>();
NullReferenceCheckHelper.throwIfNull(ugc_npc_attribute, () => $"ugc_npc_attribute is null !!! - {ugcNpc.toBasicString()}");
var log_info = new BeaconLogInfo();
log_info.setLogInfo(ugc_npc_attribute);
return log_info;
}
public static BeaconLogInfo toBeaconLogInfo(this UgcNpcAttribute ugcNpcAttribute)
{
var log_info = new BeaconLogInfo();
log_info.setLogInfo(ugcNpcAttribute);
return log_info;
}
//=====================================================================================
// 비즈니스 로그 주요 함수
//=====================================================================================
public static void setLogInfo(this BeaconLogInfo log, UgcNpcAttribute ugcNpcAttribute)
{
ArgumentNullReferenceCheckHelper.throwIfNull(ugcNpcAttribute, () => $"ugcNpcAttribute is null !!!");
var net_server = GameServerApp.getServerLogic().getProudNetListener().getNetServer();
NullReferenceCheckHelper.throwIfNull(net_server, () => $"net_server is null !!! - {ugcNpcAttribute.toBasicString()}");
var ugc_npc_pk = string.Empty;
var ugc_npc_sk = string.Empty;
(var result, var ugc_npc_doc) = ugcNpcAttribute.toDocBase(false).GetAwaiter().GetResult();
NullReferenceCheckHelper.throwIfNull(ugc_npc_doc, () => $"ugc_npc_doc is null !!! - {ugcNpcAttribute.toBasicString()}");
if (result.isFail())
{
var err_msg = $"Failed to toDocBase() !!!, in BeaconBusinessLogHelper.setLogInfo() : {result.toBasicString()} - {ugcNpcAttribute.toBasicString()}";
Log.getLogger().error(err_msg);
}
else
{
ugc_npc_pk = ugc_npc_doc.getPK();
ugc_npc_sk = ugc_npc_doc.getSK();
}
var ugc_npc_attrib = ugc_npc_doc.getAttrib<UgcNpcAttrib>();
NullReferenceCheckHelper.throwIfNull(ugc_npc_attrib, () => $"ugc_npc_attrib is null !!! - {ugcNpcAttribute.toBasicString()}");
log.setLogProperty(
ugc_npc_attrib.UgcNpcMetaGuid
, ugc_npc_pk
, ugc_npc_sk
, ugc_npc_attrib.Nickname
, ugc_npc_attrib.OwnerEntityType
, ugc_npc_attrib.OwnerGuid
, ugc_npc_attrib.LanguageType
, ugc_npc_attrib.State
, ugc_npc_attrib.AnchorMetaGuid
, ugc_npc_attrib.MetaIdOfEntityStateType
, ugc_npc_attrib.LocatedInstanceGuid
, ugc_npc_attrib.LocatedInstanceMetaId
, ugc_npc_attrib.IsRegisteredAiChatServer
, ugcNpcAttribute.getCurrentPos()
);
}
}
}

View File

@@ -0,0 +1,530 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using ServerCore;
using ServerBase;
using ServerCommon;
using ServerCommon.BusinessLogDomain;
using MetaAssets;
using SESSION_ID = System.Int32;
using WORLD_META_ID = System.UInt32;
using META_ID = System.UInt32;
using ENTITY_GUID = System.String;
using ACCOUNT_ID = System.String;
using OWNER_GUID = System.String;
using USER_GUID = System.String;
using CHARACTER_GUID = System.String;
using ITEM_GUID = System.String;
using NPC_UNIQUE_ID = System.String;
using UGC_NPC_META_GUID = System.String;
namespace GameServer;
public static class UgcNpcHelper
{
public static async Task<(Result, Int64)> getLikeCountOfUgcNpc(UGC_NPC_META_GUID ugcNpcMetaGuid, Player player)
{
var server_logic = GameServerApp.getServerLogic();
ArgumentNullException.ThrowIfNull(server_logic, $"server_logic is null !!! - {player.toBasicString()}");
var result = new Result();
var err_msg = string.Empty;
var dynamo_db_client = server_logic.getDynamoDbClient();
var selectee_count_doc = new UgcNpcLikeSelecteeCountDoc(OwnerEntityType.UgcNpc, ugcNpcMetaGuid);
var selectee_count_query_config = dynamo_db_client.makeQueryConfigForReadByPKSK(selectee_count_doc.getPK(), selectee_count_doc.getSK());
(result, var npc_like_selectee_count_doc) = await dynamo_db_client.simpleQueryDocTypeWithQueryOperationConfig<UgcNpcLikeSelecteeCountDoc>(selectee_count_query_config);
if (result.isFail())
{
err_msg = $"Failed to simpleQueryDocTypeWithQueryOperationConfig() !!!, Not found UgcNpcLikeSelecteeCountDoc : {selectee_count_doc.toBasicString()} - {player.toBasicString()}";
result.setFail(ServerErrorCode.UgcNpcLikeSelecteeCountNotFound, err_msg);
Log.getLogger().error(result.toBasicString());
return (result, 0);
}
NullReferenceCheckHelper.throwIfNull(npc_like_selectee_count_doc, () => $"npc_like_selectee_count_doc is null !!! - {player.toBasicString()}");
var ugc_npc_like_selectee_count_attrib = npc_like_selectee_count_doc.getAttrib<UgcNpcLikeSelecteeCountAttrib>();
NullReferenceCheckHelper.throwIfNull(ugc_npc_like_selectee_count_attrib, () => $"ugc_npc_like_selectee_count_attrib is null !!! - {player.toBasicString()}");
return (result, ugc_npc_like_selectee_count_attrib.LikeCount);
}
public static async Task<(Result, Int64)> getDialogCountOfUgcNpc(UGC_NPC_META_GUID ugcNpcMetaGuid, Player player)
{
var result = new Result();
var err_msg = string.Empty;
var ai_chat_action = player.getEntityAction<AIChatAction>();
NullReferenceCheckHelper.throwIfNull(ai_chat_action, () => $"ai_chat_action is null !!! - {player.toBasicString()}");
(result, var ai_chat_character) = await ai_chat_action.getCharacterByTargetGuid(ugcNpcMetaGuid);
if(result.isFail()) return (result, 0);
NullReferenceCheckHelper.throwIfNull(ai_chat_character, () => $"ai_chat_character is null !!! - {player.toBasicString()}");
return (result, ai_chat_character.data.chat_count);
}
public static async Task<(Result, BoolType)> getLikeCheckFlagOfUgcNpc(UGC_NPC_META_GUID ugcNpcMetaGuid, Player player)
{
var server_logic = GameServerApp.getServerLogic();
var result = new Result();
var err_msg = string.Empty;
var dynamo_db_client = server_logic.getDynamoDbClient();
var selected_flag_doc = new UgcNpcLikeSelectedFlagDoc(OwnerEntityType.User, player.getUserGuid(), ugcNpcMetaGuid);
var selected_flag_query_config = dynamo_db_client.makeQueryConfigForReadByPKSK(selected_flag_doc.getPK(), selected_flag_doc.getSK());
(result, var npc_like_selected_flag_docs) = await dynamo_db_client.simpleQueryDocTypesWithQueryOperationConfig<UgcNpcLikeSelectedFlagDoc>(selected_flag_query_config);
if (result.isFail() || npc_like_selected_flag_docs.Count == 0)
{
err_msg = $"Failed to simpleQueryDocTypeWithQueryOperationConfig() !!!, Not found UgcNpcLikeSelectedFlagDoc : {selected_flag_doc.toBasicString()} - {player.toBasicString()}";
result.setFail(ServerErrorCode.UgcNpcLikeSelectedFlagNotFound, err_msg);
Log.getLogger().error(result.toBasicString());
return (result, 0);
}
var npc_like_selected_flag_attrib = npc_like_selected_flag_docs[0].getAttrib<UgcNpcLikeSelectedFlagAttrib>();
NullReferenceCheckHelper.throwIfNull(npc_like_selected_flag_attrib, () => $"npc_like_selected_flag_attrib is null !!! - {player.toBasicString()}");
return (result, npc_like_selected_flag_attrib.IsSelectedFlag == true ? BoolType.True : BoolType.False);
}
public static async Task<(Result, List<UgcNpc>?)> loadUgcNpcFromMyhome(Map currMap, string myhomeGuid)
{
ArgumentNullReferenceCheckHelper.throwIfNull(currMap, () => $"currMap is null !!! - myHomeGuid:{myhomeGuid}");
var result = new Result();
var err_msg = string.Empty;
var ugc_npcs = new List<UgcNpc>();
var server_logic = GameServerApp.getServerLogic();
var db_client = server_logic.getDynamoDbClient();
var location_unique_id = currMap.makeLOCATION_UNIQUE_IDByMetaId(myhomeGuid);
var event_tid = Guid.NewGuid().ToString("N");
var npc_location_in_target_doc = new NpcLocationInTargetDoc(location_unique_id, myhomeGuid);
var query_config = db_client.makeQueryConfigForReadByPKOnly(npc_location_in_target_doc.getPK());
(result, var read_docs) = await db_client.simpleQueryDocTypesWithQueryOperationConfig<NpcLocationInTargetDoc>(query_config);
if (result.isFail())
{
return (result, null);
}
NullReferenceCheckHelper.throwIfNull(read_docs, () => $"read_docs is null !!! - myHomeGuid:{myhomeGuid}");
NpcLocationInTargetAttrib? npc_location_in_target_attrib;
foreach (var doc in read_docs)
{
npc_location_in_target_attrib = doc.getAttrib<NpcLocationInTargetAttrib>();
NullReferenceCheckHelper.throwIfNull(npc_location_in_target_attrib, () => $"npc_location_in_target_attrib is null !!!");
var owner_entity_type = npc_location_in_target_attrib.OwnerEntityType;
var owner_guid = npc_location_in_target_attrib.OwnerGuid;
var ugc_npc_guid = npc_location_in_target_attrib.NpcUniqueId;
///////////////////////////////////////////////////////////////////////////////////////
// 1. Player가 로드한 or GameZone에 배치된 UgcNpc 객체를 찾는다.
///////////////////////////////////////////////////////////////////////////////////////
(result, var found_ugc_npc, var ugc_npc_owner) = await NpcHelper.findUgcNpc(ugc_npc_guid, owner_guid);
if (found_ugc_npc != null)
{
var found_ugc_npc_attribute = found_ugc_npc.getEntityAttribute<UgcNpcAttribute>();
NullReferenceCheckHelper.throwIfNull(found_ugc_npc_attribute, () => $"found_ugc_npc_attribute is null !!!");
if (found_ugc_npc_attribute.AnchorMetaGuid != npc_location_in_target_attrib.AnchorMetaGuid)
{
await db_client.simpleDeleteDocumentWithDocType(doc, event_tid);
continue;
}
found_ugc_npc_attribute.setCurrentPos(npc_location_in_target_attrib.NpcLocation.CurrentPos);
ugc_npcs.Add(found_ugc_npc);
continue;
}
///////////////////////////////////////////////////////////////////////////////////////
// 2. DB에서 UgcNpc 정보를 읽는다.
///////////////////////////////////////////////////////////////////////////////////////
(result, var loaded_ugc_npc) = await tryLoadUgcNpcInfoFromDb(owner_entity_type, owner_guid, ugc_npc_guid);
if(result.isSuccess())
{
NullReferenceCheckHelper.throwIfNull(loaded_ugc_npc, () => $"loaded_ugc_npc is null !!! - myHomeGuid:{myhomeGuid}");
var loaded_ugc_npc_attribute = loaded_ugc_npc.getEntityAttribute<UgcNpcAttribute>();
NullReferenceCheckHelper.throwIfNull(loaded_ugc_npc_attribute, () => $"loaded_ugc_npc_attribute is null !!! - myHomeGuid:{myhomeGuid}");
if (loaded_ugc_npc_attribute.AnchorMetaGuid != npc_location_in_target_attrib.AnchorMetaGuid)
{
await db_client.simpleDeleteDocumentWithDocType(doc, event_tid);
err_msg = $"UgcNpc located not match anchor meta guid !!! : UgcNpc.AnchorMetaGuid:{loaded_ugc_npc_attribute.AnchorMetaGuid} != NpcLocation.AnchorMetaGuid:{npc_location_in_target_attrib.AnchorMetaGuid} - {loaded_ugc_npc.toBasicString()}";
Log.getLogger().error(err_msg);
continue;
}
loaded_ugc_npc_attribute.setCurrentPos(npc_location_in_target_attrib.NpcLocation.CurrentPos);
ugc_npcs.Add(loaded_ugc_npc);
}
}
return (result, ugc_npcs);
}
public static async Task<(Result, UgcNpc?)> tryLoadUgcNpcInfoFromDb( OwnerEntityType ownerEntityType, OWNER_GUID ownerGuid
, UGC_NPC_META_GUID ugcNpcMetaGuid )
{
var server_logic = GameServerApp.getServerLogic();
var db_client = server_logic.getDynamoDbClient();
var result = new Result();
var err_msg = string.Empty;
///////////////////////////////////////////////////////////////////////////////////////
// 1. UgcNpcDoc 정보를 읽는다.
///////////////////////////////////////////////////////////////////////////////////////
(result, var make_primary_key) = await DynamoDBDocBaseHelper.makePrimaryKey<UgcNpcDoc>(ownerGuid, ugcNpcMetaGuid);
if (result.isFail())
{
return (result, null);
}
NullReferenceCheckHelper.throwIfNull(make_primary_key, () => $"make_primary_key is null !!! - ugcNpcMetaGuid:{ugcNpcMetaGuid}, ownerGuid:{ownerGuid}");
var ugc_npc_query_config = db_client.makeQueryConfigForReadByPKSK(make_primary_key.PK, make_primary_key.SK);
NullReferenceCheckHelper.throwIfNull(ugc_npc_query_config, () => $"ugc_npc_query_config is null !!! - ugcNpcMetaGuid:{ugcNpcMetaGuid}, ownerGuid:{ownerGuid}");
(result, var ugc_npc_docs) = await db_client.simpleQueryDocTypesWithQueryOperationConfig<UgcNpcDoc>(ugc_npc_query_config);
if (result.isFail() || ugc_npc_docs.Count <= 0 || ugc_npc_docs.Count > 1)
{
return (result, null);
}
NullReferenceCheckHelper.throwIfNull(ugc_npc_docs, () => $"ugc_npc_docs is null !!! - ugcNpcMetaGuid:{ugcNpcMetaGuid}, ownerGuid:{ownerGuid}");
var read_ugc_npc_doc_from_db = ugc_npc_docs[0];
NullReferenceCheckHelper.throwIfNull(read_ugc_npc_doc_from_db, () => $"read_ugc_npc_doc_from_db is null !!! - ugcNpcMetaGuid:{ugcNpcMetaGuid}, ownerGuid:{ownerGuid}");
var ugc_npc = new UgcNpc(ownerGuid);
await ugc_npc.onInit();
var ugc_npc_attribute = ugc_npc.getEntityAttribute<UgcNpcAttribute>();
NullReferenceCheckHelper.throwIfNull(ugc_npc_attribute, () => $"ugc_npc_attribute is null !!! - ugcNpcMetaGuid:{ugcNpcMetaGuid}, ownerGuid:{ownerGuid}");
if (false == ugc_npc_attribute.copyEntityAttributeFromDoc(read_ugc_npc_doc_from_db))
{
err_msg = $"Failed to copyEntityAttributeFromDoc() !!! to:{ugc_npc_attribute.getTypeName()}, from:{read_ugc_npc_doc_from_db.getTypeName()}";
result.setFail(ServerErrorCode.DynamoDbDocCopyToEntityAttributeFailed, err_msg);
Log.getLogger().error(result.toBasicString());
return (result, null);
}
///////////////////////////////////////////////////////////////////////////////////////
// 2. ItemDoc 정보를 읽는다.
///////////////////////////////////////////////////////////////////////////////////////
var combination_key_for_pk = ugcNpcMetaGuid;
(result, make_primary_key) = await DynamoDBDocBaseHelper.makePrimaryKey<ItemDoc>(combination_key_for_pk);
if (result.isFail())
{
return (result, null);
}
NullReferenceCheckHelper.throwIfNull(make_primary_key, () => $"make_primary_key is null !!! - {ugc_npc.toBasicString()}");
var item_query_config = db_client.makeQueryConfigForReadByPKOnly(make_primary_key.PK);
NullReferenceCheckHelper.throwIfNull(item_query_config, () => $"make_primary_key is null !!! - {ugc_npc.toBasicString()}");
(result, var item_docs) = await db_client.simpleQueryDocTypesWithQueryOperationConfig<ItemDoc>(item_query_config);
if (result.isFail())
{
return (result, null);
}
NullReferenceCheckHelper.throwIfNull(item_docs, () => $"make_primary_key is null !!! - {ugc_npc.toBasicString()}");
var inventory_action = ugc_npc.getEntityAction<UgcNpcInventoryAction>();
NullReferenceCheckHelper.throwIfNull(inventory_action, () => $"inventory_action is null !!! : {ugc_npc.toBasicString()}");
var reserved_slots_of_equip = new Dictionary<InvenEquipType, HashSet<Int16>>();
var retry_equip_items = new List<Item>();
foreach (var item_doc in item_docs)
{
(var equip_result, var to_add_item) = await inventory_action.tryTakableToBagWithEquip(item_doc, reserved_slots_of_equip);
if (equip_result.isFail())
{
if (null != to_add_item)
{
retry_equip_items.Add(to_add_item);
}
continue;
}
}
///////////////////////////////////////////////////////////////////////////////////////
// 2.1. 장착을 실패한 아이템을 장착이 가능한 빈슬롯에 장착 시킨다.
///////////////////////////////////////////////////////////////////////////////////////
foreach (var retry_item in retry_equip_items)
{
var item_meta = retry_item.getItemMeta();
ArgumentNullException.ThrowIfNull(item_meta, $"item_meta is null !!! - {ugc_npc.toBasicString()}");
(var equip_result, var equipable_slot) = inventory_action.getEquipableSlotOfEquipInven(item_meta, reserved_slots_of_equip);
if (equip_result.isFail())
{
continue;
}
equip_result = await inventory_action.tryTakableToEquip(retry_item, (Int16)equipable_slot);
if (equip_result.isFail())
{
continue;
}
}
///////////////////////////////////////////////////////////////////////////////////////
// 3. AppearanceCustomizeDoc 정보를 읽는다.
///////////////////////////////////////////////////////////////////////////////////////
var appearance_customize_action = ugc_npc.getEntityAction<BeaconAppearanceCustomizeAction>();
ArgumentNullException.ThrowIfNull(appearance_customize_action, $"appearance_customize_action is null !!! - {ugc_npc.toBasicString()}");
(result, make_primary_key) = await DynamoDBDocBaseHelper.makePrimaryKey<AppearanceCustomizeDoc>(ugcNpcMetaGuid);
if (result.isFail())
{
return (result, null);
}
NullReferenceCheckHelper.throwIfNull(make_primary_key, () => $"make_primary_key is null !!! - {ugc_npc.toBasicString()}");
var appearance_customize_query_config = db_client.makeQueryConfigForReadByPKSK(make_primary_key.PK);
// DB에 AppearanceCustomize 정보 없는 경우도 있을 수 있다 !!!
(var appearance_customize_result, var appearance_customize_read_doc) = await db_client.simpleQueryDocTypeWithQueryOperationConfig<AppearanceCustomizeDoc>(appearance_customize_query_config);
if(appearance_customize_result.isSuccess())
{
NullReferenceCheckHelper.throwIfNull(appearance_customize_read_doc, () => $"appearance_customize_read_doc is null !!! - {ugc_npc.toBasicString()}");
var beacon_appearance_customize_action = ugc_npc.getEntityAction<BeaconAppearanceCustomizeAction>();
NullReferenceCheckHelper.throwIfNull(beacon_appearance_customize_action, () => $"beacon_appearance_customize_action is null !!! - {ugc_npc.toBasicString()}");
appearance_customize_result = await beacon_appearance_customize_action.tryLoadAppearanceCustomizeFromDoc(appearance_customize_read_doc);
if (appearance_customize_result.isFail())
{
err_msg = $"Failed to tryLoadAppearanceCustomizeFromDoc() !!! : {appearance_customize_result.toBasicString()} - {ugc_npc.toBasicString()}";
Log.getLogger().error(err_msg);
}
}
///////////////////////////////////////////////////////////////////////////////////////
// 4. BeaconShopItemDoc 정보를 읽는다.
///////////////////////////////////////////////////////////////////////////////////////
var beacon_shop_item_combination_key_for_pk = ugcNpcMetaGuid;
(result, make_primary_key) = await DynamoDBDocBaseHelper.makePrimaryKey<BeaconShopItemDoc>(beacon_shop_item_combination_key_for_pk);
if (result.isFail())
{
return (result, null);
}
NullReferenceCheckHelper.throwIfNull(make_primary_key, () => $"make_primary_key is null !!! - {ugc_npc.toBasicString()}");
var beacon_shop_item_query_config = db_client.makeQueryConfigForReadByPKOnly(make_primary_key.PK);
NullReferenceCheckHelper.throwIfNull(beacon_shop_item_query_config, () => $"make_primary_key is null !!! - {ugc_npc.toBasicString()}");
(result, var beacon_item_docs) = await db_client.simpleQueryDocTypesWithQueryOperationConfig<BeaconShopItemDoc>(beacon_shop_item_query_config);
if (result.isFail())
{
return (result, null);
}
NullReferenceCheckHelper.throwIfNull(beacon_item_docs, () => $"make_primary_key is null !!! - {ugc_npc.toBasicString()}");
var ugc_npc_beacon_shop_action = ugc_npc.getEntityAction<UgcNpcBeaconShopAction>();
foreach (var item_doc in beacon_item_docs)
{
result = await ugc_npc_beacon_shop_action.addBeaconShopItem(item_doc);
if (result.isFail())
{
return (result, null);
}
}
///////////////////////////////////////////////////////////////////////////////////////
// 5. BeaconShopProfileDoc 정보를 읽는다.
///////////////////////////////////////////////////////////////////////////////////////
var beacon_shop_profile_combination_key_for_pk = ugcNpcMetaGuid;
(result, make_primary_key) = await DynamoDBDocBaseHelper.makePrimaryKey<BeaconShopProfileDoc>(beacon_shop_profile_combination_key_for_pk);
if (result.isFail())
{
return (result, null);
}
NullReferenceCheckHelper.throwIfNull(make_primary_key, () => $"make_primary_key is null !!! - {ugc_npc.toBasicString()}");
var beacon_shop_profile_query_config = db_client.makeQueryConfigForReadByPKOnly(make_primary_key.PK);
NullReferenceCheckHelper.throwIfNull(beacon_shop_profile_query_config, () => $"beacon_shop_profile_query_config is null !!! - {ugc_npc.toBasicString()}");
(result, var beacon_profile_docs) = await db_client.simpleQueryDocTypesWithQueryOperationConfig<BeaconShopProfileDoc>(beacon_shop_profile_query_config);
if (result.isFail())
{
return (result, null);
}
NullReferenceCheckHelper.throwIfNull(beacon_profile_docs, () => $"beacon_profile_docs is null !!! - {ugc_npc.toBasicString()}");
var beacon_shop_profile_attribute = ugc_npc.getEntityAttribute<BeaconShopProfileAttribute>();
NullReferenceCheckHelper.throwIfNull(beacon_shop_profile_attribute, () => $"beacon_shop_profile_attribute is null !!! - {ugc_npc.toBasicString()}");
if (beacon_profile_docs.Count <= 0)
{
var beaconShopProfileDoc = new BeaconShopProfileDoc(ugcNpcMetaGuid);
var beaconShopProfileAttrib = beaconShopProfileDoc.getAttrib<BeaconShopProfileAttrib>();
NullReferenceCheckHelper.throwIfNull(beaconShopProfileAttrib, () => $"beaconShopProfileAttrib is null !!! - {ugc_npc.toBasicString()}");
beaconShopProfileAttrib.BeaconGuid = ugcNpcMetaGuid;
result = await db_client.simpleInsertDocumentWithDocType(beaconShopProfileDoc);
if (result.isFail())
{
err_msg = $"Failed to simpleUpsertDocumentWithDocType<BeaconShopProfileDoc> !!! - {ugc_npc.toBasicString()}";
Log.getLogger().error(err_msg);
return (result, null);
}
(result, beacon_profile_docs) = await db_client.simpleQueryDocTypesWithQueryOperationConfig<BeaconShopProfileDoc>(beacon_shop_profile_query_config);
if (result.isFail())
{
return (result, null);
}
}
beacon_shop_profile_attribute.copyEntityAttributeFromDoc(beacon_profile_docs[0]);
return (result, ugc_npc);
}
public static string toPersonaWithJsonString(string WorldScenario, string Description)
{
var world_scenario = $"WorldScenario";
var description = $"description";
var persona = $"{{\"{world_scenario}\":\"{WorldScenario}\", \"{description}\":\"{Description}\"}}";
return persona;
}
public static List<AIChatSocialActionConfig> toSocialActionConfigWithAIChatServer(META_ID DefaultSocialActionMetaId, List<META_ID> HabitSocialActionMetaIds)
{
int social_action_weight = 0;
var social_action_config = new List<AIChatSocialActionConfig>();
foreach (var social_action_data in MetaData.Instance._SocialActionTable.Values)
{
if (social_action_data.is_ingame == false)
continue;
social_action_weight = ServerCommon.Constant.DEFAULT_SOCIAL_ACTION_WEIGHT;
foreach (var incation_data in HabitSocialActionMetaIds)
{
if (incation_data == social_action_data.SocialActionId)
{
social_action_weight = ServerCommon.Constant.HABIT_SOCIAL_ACTION_WEIGHT;
break;
}
}
if (social_action_data.is_ai_default == false &&
DefaultSocialActionMetaId != social_action_data.SocialActionId &&
social_action_weight == ServerCommon.Constant.DEFAULT_SOCIAL_ACTION_WEIGHT)
{
continue;
}
social_action_config.Add(new AIChatSocialActionConfig() { id = social_action_data.SocialActionId, weight = social_action_weight });
}
return social_action_config;
}
public static string makeBeaconAppProfileS3Key(string serviceFolderName, string beaconGuid)
{
return $"{serviceFolderName}/{beaconGuid}/profile.png";
}
public static async Task<(Result, string)> getBeaconAppProfileUploadPresignedUrl(string beaconGuid)
{
var result = new Result();
var err_msg = string.Empty;
var presinged_url = string.Empty;
var server_logic = GameServerApp.getServerLogic();
if (server_logic.getServerConfig().OfflineMode)
{
err_msg = $"Server is Offline Mode !!!";
result.setFail(ServerErrorCode.FunctionNotImplemented, err_msg);
Log.getLogger().error(result.toBasicString());
return (result, presinged_url);
}
else
{
var server_config = server_logic.getServerConfig();
var bucket_name = server_config.AWS.S3.BeaconAppProfileBucketName;
var service_folder_name = server_config.AWS.S3.ServiceFolderName;
var beacon_app_profile_s3_key = makeBeaconAppProfileS3Key(service_folder_name, beaconGuid);
var s3_client = server_logic.getS3Connector();
(result, presinged_url) = await s3_client.getBeaconAppProfileUploadPresignedUrl(bucket_name, beacon_app_profile_s3_key);
if (result.isFail())
{
err_msg = $"Failed to getBeaconAppProfileUploadPresignedUrl() !!! : {result.toBasicString()}";
Log.getLogger().error(err_msg);
return (result, presinged_url);
}
}
return (result, presinged_url);
}
public static Result checkBeaconShopItem(Player player, List<UgcAnchorInfo> ugcNpcAnchorInfos)
{
var result = new Result();
var err_msg = string.Empty;
var player_action = player.getEntityAction<PlayerAction>();
foreach (var ugc_npc_anchor_info in ugcNpcAnchorInfos)
{
var ugc_npc_guid = ugc_npc_anchor_info.EntityGuid;
var ugc_npc = player_action.findUgcNpc(ugc_npc_guid);
ArgumentNullException.ThrowIfNull(ugc_npc, $"ugc_npc is null !!! - {player.toBasicString()}");
var ugc_npc_beacon_shop_action = ugc_npc.getEntityAction<UgcNpcBeaconShopAction>();
if (ugc_npc_beacon_shop_action.hasBeaconShopItem())
{
err_msg = $"UgcNpc has Beacon Shop Item !!! : ugcNpcGuid:{ugc_npc_guid} - {player.toBasicString()}";
result.setFail(ServerErrorCode.UgcNpcHasBeaconShopItem, err_msg);
Log.getLogger().error(result.toBasicString());
return result;
}
}
return result;
}
}

View File

@@ -0,0 +1,114 @@
using Google.Protobuf;
using Google.Protobuf.WellKnownTypes;
using ServerCore;
using ServerBase;
using ServerCommon;
using ServerCommon.BusinessLogDomain;
using MetaAssets;
using static ClientToGameRes.Types;
namespace GameServer.PacketHandler;
[PacketHandler(typeof(ClientToGameReq), typeof(ClientToGameReq.Types.C2GS_REQ_BEACON_APP_PROFILE_UPLOAD_ADDRESS), typeof(BeaconAppProfileUploadAddressPacketHandler), typeof(GameLoginListener))]
internal class BeaconAppProfileUploadAddressPacketHandler : PacketRecvHandler
{
public static bool send_S2C_ACK_BEACON_APP_PROFILE_UPLOAD_ADDRESS(Player owner, Result result, GS2C_ACK_BEACON_APP_PROFILE_UPLOAD_ADDRESS res)
{
var ack_packet = new ClientToGame();
ack_packet.Response = new ClientToGameRes();
ack_packet.Response.ErrorCode = result.ErrorCode;
ack_packet.Response.AckBeaconAppProfileUploadAddress = res;
if (false == GameServerApp.getServerLogic().onSendPacket(owner, ack_packet))
{
return false;
}
return true;
}
public override async Task<Result> onProcessPacket(ISession entityWithSession, Google.Protobuf.IMessage recvMessage)
{
var result = new Result();
var err_msg = string.Empty;
var player = entityWithSession as Player;
NullReferenceCheckHelper.throwIfNull(player, () => $"player is null !!!");
var server_logic = GameServerApp.getServerLogic();
var req_msg = recvMessage as ClientToGame;
NullReferenceCheckHelper.throwIfNull(req_msg, () => $"req_msg is null !!! - {player.toBasicString()}");
var request = req_msg.Request.ReqBeaconAppProfileLoadAddress;
var res = new GS2C_ACK_BEACON_APP_PROFILE_UPLOAD_ADDRESS();
var player_action = player.getEntityAction<PlayerAction>();
NullReferenceCheckHelper.throwIfNull(player_action, () => $"player_action is null !!! - {player.toBasicString()}");
var ugc_npc = player_action.findUgcNpc(request.BeaconGuid);
if (ugc_npc == null)
{
err_msg = $"UgcNpc Not Found UgcNpc Guid : {request.BeaconGuid} - {player.toBasicString()}";
result.setFail(ServerErrorCode.UgcNpcNotFound, err_msg);
Log.getLogger().error(err_msg);
send_S2C_ACK_BEACON_APP_PROFILE_UPLOAD_ADDRESS(player, result, res);
return result;
}
var fn_transaction_runner = async delegate ()
{
var result = new Result();
var user_contents_setting_attribute = player.getEntityAttribute<UserContentsSettingAttribute>();
NullReferenceCheckHelper.throwIfNull(user_contents_setting_attribute, () => $"user_contents_setting_attribute is null !!! - {player.toBasicString()}");
var beacon_app_profile_upload_cooltime_sec = MetaHelper.GameConfigMeta.BeaconAppProfileCooltime;
if (user_contents_setting_attribute.BeaconAppProfileUploadTime.AddSeconds(beacon_app_profile_upload_cooltime_sec) > DateTime.UtcNow)
{
err_msg = $"Beacon App Profile Upload is Cool Time !!! : LatestUploadTime{user_contents_setting_attribute.BeaconAppProfileUploadTime} - {player.toBasicString()}";
result.setFail(ServerErrorCode.BeaconAppProfileUploadCoolTime, err_msg);
Log.getLogger().error(err_msg);
send_S2C_ACK_BEACON_APP_PROFILE_UPLOAD_ADDRESS(player, result, res);
return result;
}
(result, var url) = await UgcNpcHelper.getBeaconAppProfileUploadPresignedUrl(request.BeaconGuid);
if (result.isFail())
{
err_msg = $"Failed to getMyhomeUgcInfo() !!! : {result.toBasicString()}";
Log.getLogger().error(err_msg);
send_S2C_ACK_BEACON_APP_PROFILE_UPLOAD_ADDRESS(player, result, res);
return result;
}
user_contents_setting_attribute.BeaconAppProfileUploadTime = DateTime.UtcNow;
user_contents_setting_attribute.modifiedEntityAttribute();
res.UploadAddress = url;
send_S2C_ACK_BEACON_APP_PROFILE_UPLOAD_ADDRESS(player, result, res);
return result;
};
result = await player.runTransactionRunnerSafely(TransactionIdType.PrivateContents, "BeaconAppProfileUploadAddress", fn_transaction_runner);
if (result.isFail())
{
err_msg = $"Failed to runTransactionRunnerSafely() !!! : {result.toBasicString()} - {player.toBasicString()}";
Log.getLogger().error(err_msg);
}
return result;
}
}

View File

@@ -0,0 +1,180 @@
using Google.Protobuf;
using Google.Protobuf.WellKnownTypes;
using ServerCore;
using ServerBase;
using ServerCommon;
using ServerCommon.BusinessLogDomain;
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;
using UGC_NPC_META_GUID = System.String;
namespace GameServer.PacketHandler;
[PacketHandler(typeof(ClientToGameReq), typeof(C2GS_REQ_BEACON_SELL), typeof(BeaconSellPacketHandler), typeof(GameLoginListener))]
public class BeaconSellPacketHandler : PacketRecvHandler
{
public override async Task onProcessPacketException( ISession entityWithSession, Google.Protobuf.IMessage recvMessage
, Result errorResult )
{
await Task.CompletedTask;
ArgumentNullReferenceCheckHelper.throwIfNull(entityWithSession);
var player = entityWithSession as Player;
NullReferenceCheckHelper.throwIfNull(player, () => $"player is null !!! - {entityWithSession.toBasicString()}");
var recv_msg = recvMessage as ClientToGame;
NullReferenceCheckHelper.throwIfNull(recv_msg, () => $"recv_msg is null !!! - {player.toBasicString()}");
var request = recv_msg.Request.ReqBeaconSell;
NullReferenceCheckHelper.throwIfNull(request, () => $"request is null !!! - {player.toBasicString()}");
send_GS2C_ACK_BEACON_SELL(player, errorResult, request.ToSellUgcNpcMetaGuid);
}
public static bool send_GS2C_ACK_BEACON_SELL( Player player, Result result
, UGC_NPC_META_GUID toSellUgcNpcMetaGuid )
{
var ack_packet = new ClientToGame();
ack_packet.Response = new ClientToGameRes();
ack_packet.Response.ErrorCode = result.ErrorCode;
var ack_msg = new GS2C_ACK_BEACON_SELL();
ack_packet.Response.AckBeaconSell = ack_msg;
var err_msg = string.Empty;
ack_msg.ToSellUgcNpcMetaGuid = toSellUgcNpcMetaGuid;
if (ServerErrorCode.Success == result.ErrorCode)
{
var found_transaction_runner = player.findTransactionRunner(TransactionIdType.PrivateContents);
if (null == found_transaction_runner)
{
err_msg = $"Not found TransactionRunner !!! : {player.toBasicString()}";
Log.getLogger().error(err_msg);
}
else
{
ack_msg.CommonResult = found_transaction_runner.getCommonResult();
}
}
if (false == GameServerApp.getServerLogic().onSendPacket(player, ack_packet))
{
return false;
}
return true;
}
public override async Task<Result> onProcessPacket(ISession entityWithSession, Google.Protobuf.IMessage recvMessage)
{
var result = new Result();
var err_msg = string.Empty;
var player = entityWithSession as Player;
NullReferenceCheckHelper.throwIfNull(player, () => $"player is null !!!");
var recv_msg = recvMessage as ClientToGame;
NullReferenceCheckHelper.throwIfNull(recv_msg, () => $"recv_msg is null !!! - {player.toBasicString()}");
var request = recv_msg.Request.ReqBeaconSell;
NullReferenceCheckHelper.throwIfNull(request, () => $"request is null !!! - {player.toBasicString()}");
var server_logic = GameServerApp.getServerLogic();
NullReferenceCheckHelper.throwIfNull(server_logic, () => $"server_logic is null !!! - {player.toBasicString()}");
var to_sell_beacon_meta_guid = request.ToSellUgcNpcMetaGuid;
var player_action = player.getEntityAction<PlayerAction>();
NullReferenceCheckHelper.throwIfNull(player_action, () => $"player_action is null !!! - {player.toBasicString()}");
var selected_character = player_action.getSelectedCharacter();
if (null == selected_character)
{
err_msg = $"Not selected Character !!! - {player.toBasicString()}";
result.setFail(ServerErrorCode.CharacterNotSelected, err_msg);
Log.getLogger().error(result.toBasicString());
send_GS2C_ACK_BEACON_SELL(player, result, request.ToSellUgcNpcMetaGuid);
return result;
}
var fn_ugc_npc_sell = async delegate ()
{
var result = new Result();
var found_beacon = player_action.findUgcNpc(to_sell_beacon_meta_guid);
if (null == found_beacon)
{
err_msg = $"Not found Beacon !!! : BeaconMetaGuid:{to_sell_beacon_meta_guid} - {player.toBasicString()}";
result.setFail(ServerErrorCode.UgcNpcNotFound, err_msg);
send_GS2C_ACK_BEACON_SELL(player, result, to_sell_beacon_meta_guid);
return result;
}
result = await player_action.trySellUgcNpc(to_sell_beacon_meta_guid);
if (result.isFail())
{
send_GS2C_ACK_BEACON_SELL(player, result, to_sell_beacon_meta_guid);
return result;
}
var batch = new QueryBatchEx<QueryRunnerWithDocument>( player, LogActionType.BeaconSell
, server_logic.getDynamoDbClient()
, true);
{
batch.addQuery(new DBQWriteToAttributeAllWithTransactionRunner());
batch.addQuery(new QueryFinal(), async (_query) =>
{
await Task.CompletedTask;
var is_success = player_action.getHadUgcNpcs().TryRemove(to_sell_beacon_meta_guid, out _);
if (false == is_success)
{
err_msg = $"Failed to TryRemove() !!! : {found_beacon.toBasicString()} - {player.toBasicString()}";
Log.getLogger().error(err_msg);
}
return QueryBatchBase.QueryResultType.Success;
});
}
result = await QueryHelper.sendQueryAndBusinessLog(batch);
if (result.isFail())
{
send_GS2C_ACK_BEACON_SELL(player, result, to_sell_beacon_meta_guid);
return result;
}
send_GS2C_ACK_BEACON_SELL(player, result, to_sell_beacon_meta_guid);
return result;
};
result = await player.runTransactionRunnerSafely(TransactionIdType.PrivateContents, "BeaconSell", fn_ugc_npc_sell);
if (result.isFail())
{
err_msg = $"Failed to runTransactionRunnerSafely() !!! : {result.toBasicString()} - {player.toBasicString()}";
Log.getLogger().error(err_msg);
}
return result;
}
}

View File

@@ -0,0 +1,161 @@
using Google.Protobuf;
using Google.Protobuf.WellKnownTypes;
using ServerCore;
using ServerBase;
using ServerCommon;
using ServerCommon.BusinessLogDomain;
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.PacketHandler;
[PacketHandler(typeof(ClientToGameReq), typeof(C2GS_REQ_UGC_NPC_CREATION), typeof(UgcNpcCreationPacketHandler), typeof(GameLoginListener))]
public class UgcNpcCreationPacketHandler : PacketRecvHandler
{
public override async Task onProcessPacketException( ISession entityWithSession, Google.Protobuf.IMessage recvMessage
, Result errorResult )
{
await Task.CompletedTask;
var player = entityWithSession as Player;
ArgumentNullReferenceCheckHelper.throwIfNull(player, () => $"player is null !!! - {entityWithSession.toBasicString()}");
var recv_msg = recvMessage as ClientToGame;
ArgumentNullReferenceCheckHelper.throwIfNull(recv_msg, () => $"recv_msg is null !!! - {player.toBasicString()}");
var request = recv_msg.Request.ReqUgcNpcCreation;
ArgumentNullReferenceCheckHelper.throwIfNull(request, () => $"request is null !!! - {player.toBasicString()}");
send_GS2C_ACK_UGC_NPC_CREATION(player, errorResult);
}
public static bool send_GS2C_ACK_UGC_NPC_CREATION( Player player, Result result
, GS2C_ACK_UGC_NPC_CREATION? ackMessage = null )
{
var ack_packet = new ClientToGame();
ack_packet.Response = new ClientToGameRes();
ack_packet.Response.ErrorCode = result.ErrorCode;
ack_packet.Response.AckUgcNpcCreation = new();
if(ServerErrorCode.Success == result.ErrorCode)
{
ArgumentNullReferenceCheckHelper.throwIfNull(ackMessage, () => $"ackMessage is null !!! - {player.toBasicString()}");
ack_packet.Response.AckUgcNpcCreation = ackMessage;
}
if (false == GameServerApp.getServerLogic().onSendPacket(player, ack_packet))
{
return false;
}
return true;
}
public override async Task<Result> onProcessPacket(ISession entityWithSession, Google.Protobuf.IMessage recvMessage)
{
var result = new Result();
var err_msg = string.Empty;
var player = entityWithSession as Player;
ArgumentNullReferenceCheckHelper.throwIfNull(player, () => $"player is null !!!");
var recv_msg = recvMessage as ClientToGame;
ArgumentNullReferenceCheckHelper.throwIfNull(recv_msg, () => $"recv_msg is null !!! - {player.toBasicString()}");
var request = recv_msg.Request.ReqUgcNpcCreation;
ArgumentNullReferenceCheckHelper.throwIfNull(request, () => $"request is null !!! - {player.toBasicString()}");
result = await tryUgcNpcCreation(player, request);
if(result.isFail())
{
return result;
}
return result;
}
public static async Task<Result> tryUgcNpcCreation(Player player, C2GS_REQ_UGC_NPC_CREATION request)
{
var result = new Result();
var err_msg = string.Empty;
var player_action = player.getEntityAction<PlayerAction>();
NullReferenceCheckHelper.throwIfNull(player_action, () => $"player_action is null !!! - {player.toBasicString()}");
var selected_character = player_action.getSelectedCharacter();
if (null == selected_character)
{
err_msg = $"Not selected Character !!! - {player.toBasicString()}";
result.setFail(ServerErrorCode.CharacterNotSelected, err_msg);
Log.getLogger().error(result.toBasicString());
send_GS2C_ACK_UGC_NPC_CREATION(player, result);
return result;
}
var fn_ugc_npc_creation = async delegate ()
{
var result = new Result();
var ugc_npc_creation_or_load_action = player.getEntityAction<UgcNpcCreationOrLoadAction>();
NullReferenceCheckHelper.throwIfNull(ugc_npc_creation_or_load_action, () => $"ugc_npc_creation_or_load_action is null !!! - {player.toBasicString()}");
(result, var to_create_ugc_npc) = await ugc_npc_creation_or_load_action.tryCreateUgcNpc(request);
if (result.isFail())
{
err_msg = $"Failed to tryCreateUgcNpc() !!! : {result.toBasicString()} - {player.toBasicString()}";
Log.getLogger().error(err_msg);
send_GS2C_ACK_UGC_NPC_CREATION(player, result);
return result;
}
var server_logic = GameServerApp.getServerLogic();
NullReferenceCheckHelper.throwIfNull(server_logic, () => $"server_logic is null !!! - {player.toBasicString()}");
var batch = new QueryBatchEx<QueryRunnerWithDocument>( player, LogActionType.BeaconCreate
, server_logic.getDynamoDbClient()
, true );
{
batch.addQuery(new DBQEntityWrite(await ugc_npc_creation_or_load_action.getDocs4UgcNpcCreation()));
batch.addQuery(new DBQWriteToAttributeAllWithTransactionRunner());
batch.addQuery(new QueryFinal(), ugc_npc_creation_or_load_action.completedUgcNpcCreation);
}
result = await QueryHelper.sendQueryAndBusinessLog(batch);
if (result.isFail())
{
send_GS2C_ACK_UGC_NPC_CREATION(player, result);
return result;
}
send_GS2C_ACK_UGC_NPC_CREATION(player, result, ugc_npc_creation_or_load_action.toAckUgcNpcCreation());
return result;
};
result = await player.runTransactionRunnerSafely(TransactionIdType.PrivateContents, "UgcNpcCreation", fn_ugc_npc_creation);
if (result.isFail())
{
err_msg = $"Failed to runTransactionRunnerSafely() !!! : {result.toBasicString()} - {player.toBasicString()}";
Log.getLogger().error(err_msg);
}
return result;
}
}

View File

@@ -0,0 +1,165 @@
using Google.Protobuf;
using Google.Protobuf.WellKnownTypes;
using ServerCore;
using ServerBase;
using ServerCommon;
using ServerCommon.BusinessLogDomain;
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.PacketHandler;
[PacketHandler(typeof(ClientToGameReq), typeof(C2GS_REQ_UGC_NPC_EDIT), typeof(UgcNpcEditPacketHandler), typeof(GameLoginListener))]
public class UgcNpcEditPacketHandler : PacketRecvHandler
{
public static bool send_GS2C_ACK_UGC_NPC_EDIT( Player player, Result result
, GS2C_ACK_UGC_NPC_EDIT? ackMessage = null)
{
var ack_packet = new ClientToGame();
ack_packet.Response = new ClientToGameRes();
ack_packet.Response.ErrorCode = result.ErrorCode;
ack_packet.Response.AckUgcNpcEdit = new GS2C_ACK_UGC_NPC_EDIT();
if (ServerErrorCode.Success == result.ErrorCode)
{
ArgumentNullReferenceCheckHelper.throwIfNull(ackMessage, () => $"ackMessage is null !!! - {player.toBasicString()}");
ack_packet.Response.AckUgcNpcEdit = ackMessage;
}
if (false == GameServerApp.getServerLogic().onSendPacket(player, ack_packet))
{
return false;
}
return true;
}
public override async Task<Result> onProcessPacket(ISession entityWithSession, Google.Protobuf.IMessage recvMessage)
{
var result = new Result();
var err_msg = string.Empty;
var player = entityWithSession as Player;
ArgumentNullReferenceCheckHelper.throwIfNull(player, () => $"player is null !!!");
var recv_msg = recvMessage as ClientToGame;
ArgumentNullReferenceCheckHelper.throwIfNull(recv_msg, () => $"recv_msg is null !!! - {player.toBasicString()}");
var request = recv_msg.Request.ReqUgcNpcEdit;
ArgumentNullReferenceCheckHelper.throwIfNull(request, () => $"request is null !!! - {player.toBasicString()}");
result = await tryUgcNpcEdit(player, request);
if (result.isFail())
{
return result;
}
return result;
}
public static async Task<Result> tryUgcNpcEdit(Player player, C2GS_REQ_UGC_NPC_EDIT request)
{
var result = new Result();
var err_msg = string.Empty;
var player_action = player.getEntityAction<PlayerAction>();
NullReferenceCheckHelper.throwIfNull(player_action, () => $"player_action is null !!! - {player.toBasicString()}");
var selected_character = player_action.getSelectedCharacter();
if (null == selected_character)
{
err_msg = $"Not selected Character !!! - {player.toBasicString()}";
result.setFail(ServerErrorCode.CharacterNotSelected, err_msg);
Log.getLogger().error(result.toBasicString());
send_GS2C_ACK_UGC_NPC_EDIT(player, result);
return result;
}
var fn_ugc_npc_edit = async delegate ()
{
var result = new Result();
var player_action = player.getEntityAction<PlayerAction>();
ArgumentNullException.ThrowIfNull(player_action, $"player_action is null !!! - {player.toBasicString()}");
var to_edit_ugc_npc_meta_guid = request.ToEditUgcNpcMetaGuid;
var found_ugc_npc = player_action.findUgcNpc(to_edit_ugc_npc_meta_guid);
if(null == found_ugc_npc)
{
err_msg = $"Not found UgcNpc !!! : UgcNpcMetaGuid:{to_edit_ugc_npc_meta_guid} - {player.toBasicString()}";
result.setFail(ServerErrorCode.UgcNpcNotFound, err_msg);
Log.getLogger().error(result.toBasicString());
send_GS2C_ACK_UGC_NPC_EDIT(player, result);
return result;
}
var ugc_npc_edit_action = found_ugc_npc.getEntityAction <UgcNpcEditAction>();
NullReferenceCheckHelper.throwIfNull(ugc_npc_edit_action, () => $"ugc_npc_edit_action is null !!! - {player.toBasicString()}");
(result, var to_edit_ugc_npc) = await ugc_npc_edit_action.tryEditUgcNpc(request);
if (result.isFail())
{
err_msg = $"Failed to tryEditUgcNpc() !!! : {result.toBasicString()} - {player.toBasicString()}";
Log.getLogger().error(err_msg);
send_GS2C_ACK_UGC_NPC_EDIT(player, result);
return result;
}
var server_logic = GameServerApp.getServerLogic();
ArgumentNullException.ThrowIfNull(server_logic, $"server_logic is null !!! - {player.toBasicString()}");
var batch = new QueryBatchEx<QueryRunnerWithDocument>( player, LogActionType.BeaconEdit
, server_logic.getDynamoDbClient()
, true );
{
batch.addQuery(new DBQWriteToAttributeAllWithTransactionRunner());
batch.addQuery(new QueryFinal(), ugc_npc_edit_action.completedUgcNpcEdit);
}
result = await QueryHelper.sendQueryAndBusinessLog(batch);
if (result.isFail())
{
send_GS2C_ACK_UGC_NPC_EDIT(player, result);
return result;
}
(result, var ack_ugc_npc_edit) = await ugc_npc_edit_action.toAckUgcNpcEdit();
if(result.isFail())
{
send_GS2C_ACK_UGC_NPC_EDIT(player, result);
return result;
}
send_GS2C_ACK_UGC_NPC_EDIT(player, result, ack_ugc_npc_edit);
return result;
};
result = await player.runTransactionRunnerSafely(TransactionIdType.PrivateContents, "UgcNpcCreation", fn_ugc_npc_edit);
if (result.isFail())
{
err_msg = $"Failed to runTransactionRunnerSafely() !!! : {result.toBasicString()} - {player.toBasicString()}";
Log.getLogger().error(err_msg);
}
return result;
}
}

View File

@@ -0,0 +1,174 @@
using Google.Protobuf;
using Google.Protobuf.WellKnownTypes;
using ServerCore;
using ServerBase;
using ServerCommon;
using ServerCommon.BusinessLogDomain;
using MetaAssets;
using static ClientToGameRes.Types;
using UGCNPC_GUID = System.String;
using USER_GUID = System.String;
namespace GameServer.PacketHandler;
[PacketHandler(typeof(ClientToGameReq), typeof(ClientToGameReq.Types.C2GS_REQ_UGC_NPC_LIKE), typeof(UgcNpcLikePacketHandler), typeof(GameLoginListener))]
public class UgcNpcLikePacketHandler : PacketRecvHandler
{
public static bool send_S2C_ACK_UGC_NPC_LIKE(Player player, Result result, UGCNPC_GUID npc_guid = "", USER_GUID owner_guid = "", bool isLike = false)
{
var ack_packet = new ClientToGame();
ack_packet.Response = new ClientToGameRes();
ack_packet.Response.ErrorCode = result.ErrorCode;
ack_packet.Response.AckUgcNpcLike = new GS2C_ACK_UGC_NPC_LIKE();
if (result.isSuccess())
{
ack_packet.Response.AckUgcNpcLike.NpcGuid = npc_guid;
ack_packet.Response.AckUgcNpcLike.OwnerGuid = owner_guid;
ack_packet.Response.AckUgcNpcLike.IsLike = isLike == true ? BoolType.True : BoolType.False;
}
if (false == GameServerApp.getServerLogic().onSendPacket(player, ack_packet))
{
return false;
}
return true;
}
public override async Task<Result> onProcessPacket(ISession entityWithSession, IMessage recvMessage)
{
var result = new Result();
var err_msg = string.Empty;
var server_logic = GameServerApp.getServerLogic();
var player = entityWithSession as Player;
ArgumentNullReferenceCheckHelper.throwIfNull(player, () => $"player is null !!!");
var game_msg = recvMessage as ClientToGame;
ArgumentNullReferenceCheckHelper.throwIfNull(game_msg, () => $"game_msg is null !!! - {player.toBasicString()}");
var request = game_msg.Request.ReqUgcNpcLike;
ArgumentNullReferenceCheckHelper.throwIfNull(request, () => $"request is null !!! - {player.toBasicString()}");
var dynamo_db_client = server_logic.getDynamoDbClient();
var selectee_count_doc = new UgcNpcLikeSelecteeCountDoc(OwnerEntityType.UgcNpc, request.NpcGuid);
var selectee_count_query_config = dynamo_db_client.makeQueryConfigForReadByPKSK(selectee_count_doc.getPK(), selectee_count_doc.getSK());
(result, var npc_like_selectee_count_docs) = await dynamo_db_client.simpleQueryDocTypesWithQueryOperationConfig<UgcNpcLikeSelecteeCountDoc>(selectee_count_query_config);
if(npc_like_selectee_count_docs.Count == 0)
{
err_msg = $"QueryCount 0 is simpleQueryDocTypesWithQueryOperationConfig() !!!, Not found UgcNpcLikeSelecteeCountDoc : {selectee_count_doc.toBasicString()} - {player.toBasicString()}";
result.setFail(ServerErrorCode.UgcNpcLikeSelecteeCountNotFound, err_msg);
Log.getLogger().error(result.toBasicString());
send_S2C_ACK_UGC_NPC_LIKE(player, result);
return result;
}
var game_zone_action = player.getEntityAction<GameZoneAction>();
NullReferenceCheckHelper.throwIfNull(game_zone_action, () => $"GameZoneAction is null !!! - {player.toBasicString()}");
var map = game_zone_action.getLinkedToMap();
if(map == null)
{
err_msg = $"Map is null !!! - {player.toBasicString()}";
result.setFail(ServerErrorCode.MapIsNull, err_msg);
Log.getLogger().error(result.toBasicString());
send_S2C_ACK_UGC_NPC_LIKE(player, result);
return result;
}
var npc = map.findUgcNpc(request.NpcGuid);
if (npc == null)
{
err_msg = $"Failed to findUgcNpc() !!!, Not registered UgcNpc in GameZone !!! : {player.toBasicString()}";
result.setFail(ServerErrorCode.UgcNpcNotRegisteredInGameZone, err_msg);
Log.getLogger().error(result.toBasicString());
send_S2C_ACK_UGC_NPC_LIKE(player, result);
return result;
}
bool is_update_like = true;
var selected_flag_doc = new UgcNpcLikeSelectedFlagDoc(OwnerEntityType.User, player.getUserGuid(), request.NpcGuid);
var selected_flag_query_config = dynamo_db_client.makeQueryConfigForReadByPKSK(selected_flag_doc.getPK(), selected_flag_doc.getSK());
(result, var npc_like_selected_flag_docs) = await dynamo_db_client.simpleQueryDocTypesWithQueryOperationConfig<UgcNpcLikeSelectedFlagDoc>(selected_flag_query_config);
if (0 < npc_like_selected_flag_docs.Count)
{
var npc_like_selected_flag_attrib = npc_like_selected_flag_docs[0].getAttrib<UgcNpcLikeSelectedFlagAttrib>();
NullReferenceCheckHelper.throwIfNull(npc_like_selected_flag_attrib, () => $"npc_like_selected_flag_attrib is null !!! - {player.toBasicString()}");
is_update_like = npc_like_selected_flag_attrib.IsSelectedFlag == true ? false : true;
}
var fn_ugc_npc_like = async delegate ()
{
var result = new Result();
var delta_count = is_update_like ? 1 : -1;
var rank_entity = server_logic.findGlobalEntity<UgcNpcRankEntity>();
NullReferenceCheckHelper.throwIfNull(rank_entity, () => $"rank_entity is null !!! - {player.toBasicString()}");
var organize_last_date = UgcNpcRankHelper.makeCurrentOrganizationDate();
var flag_last_date = DateTimeHelper.MinTime;
if (0 < npc_like_selected_flag_docs.Count)
{
var ugc_npc_like_selected_flag_attrib = npc_like_selected_flag_docs[0].getAttrib<UgcNpcLikeSelectedFlagAttrib>();
NullReferenceCheckHelper.throwIfNull(ugc_npc_like_selected_flag_attrib, () => $"ugc_npc_like_selected_flag_attrib is null !!! - {player.toBasicString()}");
flag_last_date = ugc_npc_like_selected_flag_attrib.LastCheckDate;
}
var is_update_last_date = flag_last_date == DateTimeHelper.MinTime || organize_last_date < flag_last_date;
// rank score 설정
var like_rank_action = rank_entity.getEntityAction<UgcNpcLikeRankAction>();
NullReferenceCheckHelper.throwIfNull(like_rank_action, () => $"like_rank_action is null !!! - {player.toBasicString()}");
await like_rank_action.setRankScore(player.getUserGuid(), request.OwnerGuid, request.NpcGuid, is_update_like);
var batch = new QueryBatchEx<QueryRunnerWithItemRequest>( player, LogActionType.UpdateUgcNpcLike
, server_logic.getDynamoDbClient()
, true );
{
batch.addQuery(new DBQUgcNpcLikeSelectedFlagUpdate(player.getUserGuid(), request.NpcGuid, is_update_last_date));
batch.addQuery(new DBQUgcNpcLikeSelecteeCountUpdate(request.NpcGuid, delta_count));
}
result = await QueryHelper.sendQueryAndBusinessLog(batch);
if (result.isFail())
{
return result;
}
send_S2C_ACK_UGC_NPC_LIKE(player, result, request.NpcGuid, request.OwnerGuid, is_update_like);
return result;
};
var transaction_name = "UgcNpcLike";
result = await player.runTransactionRunnerSafelyWithTransGuid( player.getUserGuid()
, TransactionIdType.PrivateContents, transaction_name
, fn_ugc_npc_like);
if (result.isFail())
{
err_msg = $"Failed to runTransactionRunnerSafelyWithTransGuid() !!! : {result.toBasicString()} - transactionName:{transaction_name}, {player.toBasicString()}";
Log.getLogger().error(err_msg);
}
return result;
}
}

View File

@@ -0,0 +1,121 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.CompilerServices;
using System.Text;
using System.Threading.Tasks;
using ServerCommon;
using ServerCore; using ServerBase;
using static ClientToGameMessage.Types;
using USER_GUID = System.String;
namespace GameServer
{
public static class UgcNpcNotifyHelper
{
public static void send_GS2C_NTF_UGC_NPC_ALL_LOAD( this Player player )
{
ArgumentNullReferenceCheckHelper.throwIfNull(player, () => $"player is null !!!");
var player_action = player.getEntityAction<PlayerAction>();
NullReferenceCheckHelper.throwIfNull(player_action, () => $"player_action is null !!! - {player.toBasicString()}");
var ntf = new GS2C_NTF_UGC_NPC_ALL_LOAD();
ntf.HasUgcNpcSummaries.Add(player_action.toUgcNpcSummaryAll4Client().toMapField());
ntf.HasUgcNpcItems.Add(player_action.toUgcNpcItemsAll4Client().toMapField());
ClientToGame packet = new ClientToGame();
packet.Message = new ClientToGameMessage();
packet.Message.NtfUgcNpcAllLoad = ntf;
player.sendPacket(packet);
}
public static void send_GS2C_NTF_UGC_NPC_DELETION( Player player, string deletedUgcNpcMetaGuid, CommonResult commonResult)
{
var ntf = new GS2C_NTF_UGC_NPC_DELETION();
ntf.DeletedUgcNpcMetaGuid = deletedUgcNpcMetaGuid;
ntf.CommonResult = commonResult;
ClientToGame packet = new ClientToGame();
packet.Message = new ClientToGameMessage();
packet.Message.NtfUgcNpcDeletion = ntf;
player.sendPacket(packet);
}
public static void send_GS2C_NTF_BEACON_DETAIL_INFO( Player player
, UgcNpcSummary ugcNpcSummary
, Int64 likeCount, Int64 dialogCount )
{
var ntf = new GS2C_NTF_BEACON_DETAIL_INFO();
ntf.UgcNpcMetaGuid = ugcNpcSummary.UgcNpcMetaGuid;
ntf.OwnerUserGuid = ugcNpcSummary.OwnerUserGuid;
ntf.UgcNpcSummary = ugcNpcSummary;
ntf.LikeCount = likeCount;
ntf.DialogCount = dialogCount;
ClientToGame packet = new ClientToGame();
packet.Message = new ClientToGameMessage();
packet.Message.NtfBeaconDetailInfo = ntf;
player.sendPacket(packet);
}
public static void send_GS2C_NTF_BEACON_INTERACTION_INFO( Player player
, UgcNpc ugcNpc
, UgcNpcInteraction ugcNpcInteraction )
{
var ntf = new GS2C_NTF_BEACON_INTERACTION_INFO();
ntf.EntityInstantGuid = ugcNpcInteraction.UgcNpcMetaGuid;
ntf.UgcNpcInteraction = ugcNpcInteraction;
ClientToGame packet = new ClientToGame();
packet.Message = new ClientToGameMessage();
packet.Message.NtfBeaconInteractionInfo = ntf;
player.sendPacket(packet);
}
public static void send_GS2C_NTF_BEACON_COMPACT_UPDATE( Player player
, UgcNpc ugcNpc
, UgcNpcCompact ugcNpcCompact)
{
var ntf = new GS2C_NTF_BEACON_COMPACT_UPDATE();
ntf.UgcNpcMetaGuid = ugcNpcCompact.UgcNpcMetaGuid;
ntf.OwnerUserGuid = ugcNpcCompact.OwnerUserGuid;
ntf.UgcNpcCompact = ugcNpcCompact;
ClientToGame packet = new ClientToGame();
packet.Message = new ClientToGameMessage();
packet.Message.NtfBeaconCompactUpdate = ntf;
player.sendPacket(packet);
}
public static void send_GS2MQS_NTF_BEACON_COMPACT_SYNC( GameServerLogic serverLogic
, string targetServerName
, USER_GUID userGuid
, UgcNpcCompact ugcNpcCompact, string locatedInstanceGuid )
{
var mg_server = serverLogic.getRabbitMqConnector() as RabbitMQ4Game;
NullReferenceCheckHelper.throwIfNull(mg_server, () => $"mg_server is null !!! - userGuid:{userGuid}");
var s2s_ntf_msg = new ServerMessage();
var ntf_beacon_compact_sync = new ServerMessage.Types.GS2MQS_NTF_BEACON_COMPACT_SYNC();
s2s_ntf_msg.NtfBeaconCompactSync = ntf_beacon_compact_sync;
ntf_beacon_compact_sync.UserGuid = userGuid;
ntf_beacon_compact_sync.UgcNpcCompact = ugcNpcCompact;
ntf_beacon_compact_sync.LocatedInstanceGuid = locatedInstanceGuid;
mg_server.SendMessage(targetServerName, s2s_ntf_msg);
}
}
}

View File

@@ -0,0 +1,157 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using ServerCore;
using ServerBase;
using ServerCommon;
using ServerCommon.BusinessLogDomain;
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.PacketHandler;
//=============================================================================================
// C2GS_REQ_NPC_TOUCH 적용 후 하기 코드 제거 한다. - kangms
//=============================================================================================
[PacketHandler(typeof(ClientToGameReq), typeof(C2GS_REQ_UGC_NPC_TOUCH), typeof(UgcNpcTouchPacketHandler), typeof(GameLoginListener))]
public class UgcNpcTouchPacketHandler : PacketRecvHandler
{
public static bool send_GS2C_ACK_UGC_NPC_TOUCH( Player player, Result result
, GS2C_ACK_UGC_NPC_TOUCH? ackMessage = null)
{
var ack_packet = new ClientToGame();
ack_packet.Response = new ClientToGameRes();
ack_packet.Response.ErrorCode = result.ErrorCode;
ack_packet.Response.AckUgcNpcTouch = new();
if (ServerErrorCode.Success == result.ErrorCode)
{
ArgumentNullReferenceCheckHelper.throwIfNull(ackMessage, () => $"ackMessage is null !!! - {player.toBasicString()}");
ack_packet.Response.AckUgcNpcTouch = ackMessage;
}
if (false == GameServerApp.getServerLogic().onSendPacket(player, ack_packet))
{
return false;
}
return true;
}
public override async Task<Result> onProcessPacket(ISession entityWithSession, Google.Protobuf.IMessage recvMessage)
{
var result = new Result();
var err_msg = string.Empty;
var player = entityWithSession as Player;
ArgumentNullReferenceCheckHelper.throwIfNull(player, () => $"player is null !!!");
var recv_msg = recvMessage as ClientToGame;
ArgumentNullReferenceCheckHelper.throwIfNull(recv_msg, () => $"recv_msg is null !!! - {player.toBasicString()}");
var request = recv_msg.Request.ReqUgcNpcTouch;
ArgumentNullReferenceCheckHelper.throwIfNull(request, () => $"request is null !!! - {player.toBasicString()}");
result = await tryUgcNpcTouch(player, request);
if (result.isFail())
{
return result;
}
return result;
}
public static async Task<Result> tryUgcNpcTouch(Player player, C2GS_REQ_UGC_NPC_TOUCH request)
{
var result = new Result();
var err_msg = string.Empty;
var player_action = player.getEntityAction<PlayerAction>();
NullReferenceCheckHelper.throwIfNull(player_action, () => $"player_action is null !!! - {player.toBasicString()}");
var selected_character = player_action.getSelectedCharacter();
if (null == selected_character)
{
err_msg = $"Not selected Character !!! - {player.toBasicString()}";
result.setFail(ServerErrorCode.CharacterNotSelected, err_msg);
Log.getLogger().error(result.toBasicString());
send_GS2C_ACK_UGC_NPC_TOUCH(player, result);
return result;
}
var found_ugc_npc = player_action.findUgcNpc(request.ToTouchUgcNpcMetaGuid);
if(null == found_ugc_npc)
{
err_msg = $"Not found Ugc Npc !!! : ugcNpcMetaGuid:{request.ToTouchUgcNpcMetaGuid} - {player.toBasicString()}";
result.setFail(ServerErrorCode.UgcNpcNotFound, err_msg);
Log.getLogger().error(result.toBasicString());
send_GS2C_ACK_UGC_NPC_TOUCH(player, result);
return result;
}
var fn_ugc_npc_touch = async delegate ()
{
var result = new Result();
var ugc_npc_action = found_ugc_npc.getEntityAction<UgcNpcAction>();
NullReferenceCheckHelper.throwIfNull(ugc_npc_action, () => $"ugc_npc_action is null !!! - {player.toBasicString()}");
result = await ugc_npc_action.tryRegisterCharacterWithAiChatServer(player);
if (result.isFail())
{
err_msg = $"Failed to tryCreateUgcNpc() !!! : {result.toBasicString()} - {player.toBasicString()}";
Log.getLogger().error(err_msg);
send_GS2C_ACK_UGC_NPC_TOUCH(player, result);
return result;
}
result = await player_action.commitTransaction(TransactionIdType.PrivateContents);
if (result.isFail())
{
err_msg = $"Failed to commitTransaction() !!! : {result.toBasicString()} - {player.toBasicString()}";
Log.getLogger().error(err_msg);
send_GS2C_ACK_UGC_NPC_TOUCH(player, result);
return result;
}
var ack_packet = new GS2C_ACK_UGC_NPC_TOUCH();
ack_packet.UgcNpcMetaGuid = request.ToTouchUgcNpcMetaGuid;
send_GS2C_ACK_UGC_NPC_TOUCH(player, result, ack_packet);
return result;
};
result = await player.runTransactionRunnerSafely(TransactionIdType.PrivateContents, "UgcNpcTouch", fn_ugc_npc_touch);
if (result.isFail())
{
err_msg = $"Failed to runTransactionRunnerSafely() !!! : {result.toBasicString()} - {player.toBasicString()}";
Log.getLogger().error(err_msg);
}
return result;
}
}

View File

@@ -0,0 +1,324 @@
using ServerCommon;
using ServerCore; using ServerBase;
using META_ID = System.UInt32;
using ITEM_GUID = System.String;
using static ClientToGameReq.Types;
namespace GameServer;
[ChatCommandAttribute("ugcnpccreate", typeof(ChatCommandUgcNpcCreate), AuthAdminLevelType.Developer, AuthAdminLevelType.GmNormal, AuthAdminLevelType.GmSuper)]
internal class ChatCommandUgcNpcCreate : ChatCommandBase
{
public override async Task invoke(Player player, string token, string[] args)
{
Log.getLogger().info($"Call ugcnpccreate !!! - {player.toBasicString()}");
var result = new Result();
var err_msg = string.Empty;
if (args.Length < 3)
{
err_msg = $"Not enough argument !!! : argCount:{args.Length} == 3 - {player.toBasicString()}";
Log.getLogger().error(err_msg);
return;
}
if ( false == int.TryParse(args[1], out int body_item_meta_id)
|| false == bool.TryParse(args[2], out bool is_show_tattoo )
)
{
err_msg = $"Invalid argument !!! - {player.toBasicString()}";
Log.getLogger().error(err_msg);
return;
}
var nickname = args[0];
if (true == nickname.isNullOrWhiteSpace())
{
err_msg = $"Nickname is empty !!! - {player.toBasicString()}";
Log.getLogger().error(err_msg);
return;
}
var user_inventory_action = player.getEntityAction<UserInventoryAction>();
NullReferenceCheckHelper.throwIfNull(user_inventory_action, () => $"user_inventory_action is null !!! - {player.toBasicString()}");
var found_body_items = user_inventory_action.tryGetItemAllByItemMetaId((META_ID)body_item_meta_id);
if (0 >= found_body_items.Count)
{
err_msg = $"Not found Body Item !!! : bodyItemMetaId:{body_item_meta_id} - {player.toBasicString()}";
Log.getLogger().error(err_msg);
return;
}
var item_attribute_base = found_body_items[0].getEntityAttribute<ItemAttributeBase>();
NullReferenceCheckHelper.throwIfNull(item_attribute_base, () => $"item_attribute_base is null !!! - {player.toBasicString()}");
var body_item_guid = item_attribute_base.ItemGuid;
var cloth_item_guids = new List<ITEM_GUID>();
var cloth_item_sample_meta_ids = new List<META_ID>() { 15230180, 15231430, 15230420, 15131035 };
foreach (var cloth_item_meta_id in cloth_item_sample_meta_ids)
{
var found_cloth_items = user_inventory_action.tryGetItemAllByItemMetaId(cloth_item_meta_id);
if (0 >= found_cloth_items.Count)
{
err_msg = $"Not found Cloth Item !!! : clothItemMetaId:{cloth_item_meta_id} - {player.toBasicString()}";
Log.getLogger().error(err_msg);
return;
}
item_attribute_base = found_cloth_items[0].getEntityAttribute<ItemAttributeBase>();
NullReferenceCheckHelper.throwIfNull(item_attribute_base, () => $"item_attribute_base is null !!! - {player.toBasicString()}");
var cloth_item_guid = item_attribute_base.ItemGuid;
cloth_item_guids.Add(cloth_item_guid);
}
var tattoo_item_guids = new List<ITEM_GUID>();
var tattoo_item_sample_meta_ids = new List<META_ID>() { 11851003, 11851005, 11851008 };
foreach (var tattoo_item_meta_id in tattoo_item_sample_meta_ids)
{
var found_tattoo_items = user_inventory_action.tryGetItemAllByItemMetaId(tattoo_item_meta_id);
if (0 >= found_tattoo_items.Count)
{
err_msg = $"Not found Tattoo Item !!! : tattooItemMetaId:{tattoo_item_meta_id} - {player.toBasicString()}";
Log.getLogger().error(err_msg);
return;
}
item_attribute_base = found_tattoo_items[0].getEntityAttribute<ItemAttributeBase>();
NullReferenceCheckHelper.throwIfNull(item_attribute_base, () => $"item_attribute_base is null !!! - {player.toBasicString()}");
var tattoo_item_guid = item_attribute_base.ItemGuid;
tattoo_item_guids.Add(tattoo_item_guid);
}
var default_action_sample_meta_id = 110004;
var social_action_sample_meta_ids = new List<META_ID>() { 110009, 110013, 110017 };
var dialogue_social_action_sample_meta_ids = new List<META_ID>() { 110054 };
var beacon_tag_meta_ids = new List<META_ID>() { 1, 2, 3, 4, 5, 6, 7 };
var tattoo_slot_visibles = is_show_tattoo == true
? new Dictionary<int, BoolType>() { { (int)TattooSlotType._1, BoolType.True }, { (int)TattooSlotType._2, BoolType.True }, { (int)TattooSlotType._3, BoolType.True } }
: new Dictionary<int, BoolType>() { { (int)TattooSlotType._1, BoolType.False }, { (int)TattooSlotType._2, BoolType.False }, { (int)TattooSlotType._3, BoolType.False } };
var server_logic = GameServerApp.getServerLogic();
NullReferenceCheckHelper.throwIfNull(server_logic, () => $"server_logic is null !!! - {player.toBasicString()}");
var db_connector = server_logic.getDynamoDbClient();
NullReferenceCheckHelper.throwIfNull(db_connector, () => $"db_connector is null !!! - {player.toBasicString()}");
var session = player as IEntityWithSession;
NullReferenceCheckHelper.throwIfNull(session, () => $"session is null !!! - {player.toBasicString()}");
//=====================================================================================
// 패킷 구성
//=====================================================================================
var packet = new ClientToGame();
packet.Request = new ClientToGameReq();
var request = new C2GS_REQ_UGC_NPC_CREATION();
packet.Request.ReqUgcNpcCreation = request;
request.Nickname = nickname;
request.Title = "Test Ugc Npc by Cheat !!!";
request.Description = "I AI Ugc Npc !!!";
request.WorldScenario = "good luck !!!";
request.BodyItemGuid = body_item_guid;
request.MaterialItemGuids.AddRange(cloth_item_guids);
request.MaterialItemGuids.AddRange(tattoo_item_guids);
request.DefaultSocialActionId = default_action_sample_meta_id;
request.HabitSocialActionIds.AddRange(social_action_sample_meta_ids.Select(x => (int)x).ToList());
request.DialogueSocialActionIds.AddRange(dialogue_social_action_sample_meta_ids.Select(x => (int)x).ToList());
request.TattooSlotVisibles.Add(tattoo_slot_visibles.toMapField());
request.HashTagMetaIds.Add(beacon_tag_meta_ids.Select(x => (int)x).ToList());
result = await server_logic.onCallProtocolHandler(session, packet);
if (result.isFail())
{
err_msg = $"Failed to onCallProtocolHandler() !!! : {result.toBasicString()} - {player.toBasicString()}";
Log.getLogger().error(err_msg);
return;
}
}
}
[ChatCommandAttribute("ugcnpcdelete", typeof(ChatCommandUgcNpcDelete), AuthAdminLevelType.Developer, AuthAdminLevelType.GmNormal, AuthAdminLevelType.GmSuper)]
internal class ChatCommandUgcNpcDelete : ChatCommandBase
{
public override async Task invoke(Player player, string token, string[] args)
{
Log.getLogger().info($"Call ugcnpcdelete !!! - {player.toBasicString()}");
var result = new Result();
var err_msg = string.Empty;
if (args.Length < 1)
{
err_msg = $"Not enough argument !!! : argCount:{args.Length} == 3 - {player.toBasicString()}";
Log.getLogger().error(err_msg);
return;
}
var to_delete_nickname = args[0];
if (true == to_delete_nickname.isNullOrWhiteSpace())
{
err_msg = $"To delete Nickname is empty !!! - {player.toBasicString()}";
Log.getLogger().error(err_msg);
return;
}
var player_action = player.getEntityAction<PlayerAction>();
NullReferenceCheckHelper.throwIfNull(player_action, () => $"player_action is null !!!");
result = await player_action.tryDeleteUgcNpc(to_delete_nickname);
if (result.isFail())
{
Log.getLogger().error(result.toBasicString());
}
}
}
[ChatCommandAttribute("ugcnpclikecheck", typeof(ChatCommandUgcNpcLikeCheck), AuthAdminLevelType.Developer, AuthAdminLevelType.GmNormal, AuthAdminLevelType.GmSuper)]
internal class ChatCommandUgcNpcLikeCheck : ChatCommandBase
{
public override async Task invoke(Player player, string token, string[] args)
{
Log.getLogger().info($"Call ugcnpclikecheck !!! - {player.toBasicString()}");
var result = new Result();
var err_msg = string.Empty;
if (args.Length < 2)
{
err_msg = $"Not enough argument !!! : argCount:{args.Length} == 2 - {player.toBasicString()}";
Log.getLogger().error(err_msg);
return;
}
var target_user_nickname = args[0];
if (true == target_user_nickname.isNullOrWhiteSpace())
{
err_msg = $"target_user_nickname is empty !!! - {player.toBasicString()}";
Log.getLogger().error(err_msg);
return;
}
var target_ugc_npc_nickname = args[1];
if (true == target_ugc_npc_nickname.isNullOrWhiteSpace())
{
err_msg = $"target_ugc_npc_nickname is empty !!! - {player.toBasicString()}";
Log.getLogger().error(err_msg);
return;
}
var server_logic = GameServerApp.getServerLogic();
NullReferenceCheckHelper.throwIfNull(server_logic, () => $"server_logic is null !!! - {player.toBasicString()}");
var db_connector = server_logic.getDynamoDbClient();
NullReferenceCheckHelper.throwIfNull(db_connector, () => $"db_connector is null !!! - {player.toBasicString()}");
(result, var found_user_info) = await EntitySearchHelper.findUserInfoByUserNickname(db_connector, target_user_nickname);
if (result.isFail())
{
err_msg = $"Failed to findUserInfoByUserNickname() !!! : userNickname:{target_user_nickname} - {player.toBasicString()}";
Log.getLogger().error(err_msg);
return;
}
NullReferenceCheckHelper.throwIfNull(found_user_info, () => $"found_user_info is null !!! - {player.toBasicString()}");
(result, var found_ugc_npc_info) = await EntitySearchHelper.findUgcNpcInfoByUgcNpcNickname(db_connector
, OwnerEntityType.User, found_user_info.UserGuid
, target_ugc_npc_nickname);
if (result.isFail())
{
err_msg = $"Failed to findUgcNpcInfoByUgcNpcNickname() !!! : userNickname:{target_user_nickname} - {player.toBasicString()}";
Log.getLogger().error(err_msg);
return;
}
NullReferenceCheckHelper.throwIfNull(found_ugc_npc_info, () => $"found_ugc_npc_info is null !!! - {player.toBasicString()}");
var session = player as IEntityWithSession;
NullReferenceCheckHelper.throwIfNull(session, () => $"session is null !!! - {player.toBasicString()}");
//=====================================================================================
// 패킷 구성
//=====================================================================================
var packet = new ClientToGame();
packet.Request = new ClientToGameReq();
var request = new C2GS_REQ_UGC_NPC_LIKE();
packet.Request.ReqUgcNpcLike = request;
request.NpcGuid = found_ugc_npc_info.UgcNpcAttrib.UgcNpcMetaGuid;
request.OwnerGuid = found_ugc_npc_info.UgcNpcAttrib.OwnerGuid;
result = await server_logic.onCallProtocolHandler(session, packet);
if (result.isFail())
{
err_msg = $"Failed to onCallProtocolHandler() !!! : {result.toBasicString()} - {player.toBasicString()}";
Log.getLogger().error(err_msg);
return;
}
}
}
[ChatCommandAttribute("beaconsell", typeof(ChatCommandBeaconSell), AuthAdminLevelType.Developer, AuthAdminLevelType.GmNormal, AuthAdminLevelType.GmSuper)]
internal class ChatCommandBeaconSell : ChatCommandBase
{
public override async Task invoke(Player player, string token, string[] args)
{
Log.getLogger().info($"Call beaconsell !!! - {player.toBasicString()}");
var result = new Result();
var err_msg = string.Empty;
if (args.Length < 1)
{
err_msg = $"Not enough argument !!! : argCount:{args.Length} == 3 - {player.toBasicString()}";
Log.getLogger().error(err_msg);
return;
}
var to_sell_nickname = args[0];
if (true == to_sell_nickname.isNullOrWhiteSpace())
{
err_msg = $"To sell Nickname is empty !!! - {player.toBasicString()}";
Log.getLogger().error(err_msg);
return;
}
var player_action = player.getEntityAction<PlayerAction>();
NullReferenceCheckHelper.throwIfNull(player_action, () => $"player_action is null !!!");
var found_ugc_npc = player_action.findUgcNpcByNickname(to_sell_nickname);
if(null == found_ugc_npc)
{
err_msg = $"Not found Beacon !!! : beaconNickName:{to_sell_nickname} - {player.toBasicString()}";
Log.getLogger().error(err_msg);
return;
}
var server_logic = GameServerApp.getServerLogic();
NullReferenceCheckHelper.throwIfNull(server_logic, () => $"server_logic is null !!! - {player.toBasicString()}");
var session = player as IEntityWithSession;
NullReferenceCheckHelper.throwIfNull(session, () => $"session is null !!! - {player.toBasicString()}");
//=====================================================================================
// 패킷 구성
//=====================================================================================
var packet = new ClientToGame();
packet.Request = new ClientToGameReq();
var request = new C2GS_REQ_BEACON_SELL();
packet.Request.ReqBeaconSell = request;
request.ToSellUgcNpcMetaGuid = found_ugc_npc.getUgcNpcMetaGuid();
result = await server_logic.onCallProtocolHandler(session, packet);
if (result.isFail())
{
err_msg = $"Failed to onCallProtocolHandler() !!! : {result.toBasicString()} - {player.toBasicString()}";
Log.getLogger().error(err_msg);
return;
}
}
}