1467 lines
70 KiB
C#
1467 lines
70 KiB
C#
using System.Globalization;
|
|
using System.Collections.Concurrent;
|
|
|
|
|
|
using Amazon.DynamoDBv2.Model;
|
|
|
|
|
|
using ServerCore;
|
|
using ServerBase;
|
|
using ServerCommon;
|
|
|
|
|
|
using META_ID = System.UInt32;
|
|
using BEACON_GUID = System.String;
|
|
using ITEM_GUID = System.String;
|
|
using USER_GUID = System.String;
|
|
using Amazon.S3.Model;
|
|
|
|
|
|
namespace GameServer;
|
|
|
|
public class BeaconShopAction : EntityActionBase
|
|
{
|
|
private BeaconShopRepository m_beacon_shop_repository;
|
|
private ConcurrentDictionary<BEACON_GUID, List<BeaconShopSoldRecord>> m_beacon_shop_sold_records = new();
|
|
private ConcurrentDictionary<BEACON_GUID, BeaconShopSoldPrice> m_beacon_shop_sold_price = new();
|
|
private bool m_isUpdateSold = false;
|
|
|
|
public BeaconShopAction(Player owner)
|
|
: base(owner)
|
|
{
|
|
var server_logic = GameServerApp.getServerLogic();
|
|
m_beacon_shop_repository = new BeaconShopRepository( server_logic.getMongoDbConnector().getMongoClient()
|
|
, server_logic.getServerConfig().MongoDbConfig );
|
|
}
|
|
|
|
public override Task<Result> onInit()
|
|
{
|
|
var result = new Result();
|
|
|
|
return Task.FromResult(result);
|
|
}
|
|
|
|
public override void onClear()
|
|
{
|
|
m_beacon_shop_sold_records.Clear();
|
|
m_beacon_shop_sold_price.Clear();
|
|
}
|
|
|
|
public void setUpdateSoldRecord()
|
|
{
|
|
m_isUpdateSold = true;
|
|
}
|
|
|
|
private bool checkDailyRegisterCount(UgcNpc ugcNpc)
|
|
{
|
|
var beacon_shop_profile_attribute = ugcNpc.getOriginEntityAttribute<BeaconShopProfileAttribute>();
|
|
NullReferenceCheckHelper.throwIfNull(beacon_shop_profile_attribute, () => $"beacon_shop_profile_attribute is null !!! - {ugcNpc.toBasicString()}");
|
|
|
|
if (beacon_shop_profile_attribute.RegisterUpdateDay < DateTime.UtcNow.Date.AddHours(ServerCommon.MetaHelper.GameConfigMeta.BeaconShopDailyRegistrationResetTime))
|
|
{
|
|
return true;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
private void updateDailyRegisterCount(BeaconShopProfileAttribute beacon_shop_profile_attribute)
|
|
{
|
|
if (beacon_shop_profile_attribute.RegisterUpdateDay < DateTime.UtcNow.Date.AddHours(ServerCommon.MetaHelper.GameConfigMeta.BeaconShopDailyRegistrationResetTime))
|
|
{
|
|
beacon_shop_profile_attribute.DailyRegisterCount = 0;
|
|
beacon_shop_profile_attribute.RegisterUpdateDay = DateTime.UtcNow.Date.AddHours(ServerCommon.MetaHelper.GameConfigMeta.BeaconShopDailyRegistrationResetTime);
|
|
beacon_shop_profile_attribute.modifiedEntityAttribute(true);
|
|
}
|
|
}
|
|
|
|
public async Task<Result> AddBeaconShopSoldRecordsFromDocs(List<BeaconShopSoldRecordDoc> beaconShopSoldRecordDocs)
|
|
{
|
|
var result = new Result();
|
|
var err_msg = string.Empty;
|
|
|
|
m_beacon_shop_sold_records.Clear();
|
|
|
|
var player = getOwner() as Player;
|
|
NullReferenceCheckHelper.throwIfNull(player, () => $"player is null !!!");
|
|
|
|
foreach (var beacon_shop_sold_record_doc in beaconShopSoldRecordDocs)
|
|
{
|
|
var beacon_shop_record_attrib = beacon_shop_sold_record_doc.getAttrib<BeaconShopSoldRecordAttrib>();
|
|
NullReferenceCheckHelper.throwIfNull(beacon_shop_record_attrib, () => $"beacon_shop_record_attrib is null !!!");
|
|
|
|
if (m_beacon_shop_sold_records.TryGetValue(beacon_shop_record_attrib.BeaconGuid, out var beacon_shop_sold_record_list) == false)
|
|
{
|
|
beacon_shop_sold_record_list = new List<BeaconShopSoldRecord>();
|
|
if (m_beacon_shop_sold_records.TryAdd(beacon_shop_record_attrib.BeaconGuid, beacon_shop_sold_record_list) == false)
|
|
{
|
|
err_msg = $"Failed to add beacon_shop_sold_record attribute : {nameof(BeaconShopSoldRecordAttribute)}";
|
|
result.setFail(ServerErrorCode.EntityAttributeIsNull, err_msg);
|
|
Log.getLogger().error(result.toBasicString());
|
|
return result;
|
|
}
|
|
}
|
|
|
|
(result, var beacon_shop_sold_record) = await BeaconShopSoldRecord.createBeaconShopSoldRecordFromDoc(player, beacon_shop_sold_record_doc);
|
|
if (beacon_shop_sold_record is null)
|
|
{
|
|
err_msg = $"Failed to create beacon_shop_sold_record from doc";
|
|
Log.getLogger().error(err_msg);
|
|
continue;
|
|
}
|
|
|
|
beacon_shop_sold_record_list.Add(beacon_shop_sold_record);
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
public async Task<Result> AddBeaconShopSoldPriceFromDocs(List<BeaconShopSoldPriceDoc> beaconShopSoldPriceDocs)
|
|
{
|
|
var result = new Result();
|
|
var err_msg = string.Empty;
|
|
|
|
m_beacon_shop_sold_price.Clear();
|
|
|
|
var player = getOwner() as Player;
|
|
NullReferenceCheckHelper.throwIfNull(player, () => $"player is null !!!");
|
|
|
|
foreach (var beacon_shop_sold_price_doc in beaconShopSoldPriceDocs)
|
|
{
|
|
var beacon_shop_price_attrib = beacon_shop_sold_price_doc.getAttrib<BeaconShopSoldPriceAttrib>();
|
|
NullReferenceCheckHelper.throwIfNull(beacon_shop_price_attrib, () => $"beacon_shop_price_attrib is null !!!");
|
|
|
|
(result, var beacon_shop_sold_price) = await BeaconShopSoldPrice.createBeaconShopSoldPriceFromDoc(player, beacon_shop_sold_price_doc);
|
|
if (beacon_shop_sold_price is null)
|
|
{
|
|
err_msg = $"Failed to create beacon shop sold price from doc";
|
|
Log.getLogger().error(err_msg);
|
|
return result;
|
|
}
|
|
|
|
m_beacon_shop_sold_price[beacon_shop_price_attrib.BeaconGuid] = beacon_shop_sold_price;
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
public async Task<Result> tryRegisterItemToBeaconShop(ITEM_GUID itemGuid, UInt16 itemAmount, double SellingPrice, BEACON_GUID BeaconGuid)
|
|
{
|
|
var result = new Result();
|
|
var err_msg = string.Empty;
|
|
var player = getOwner() as Player;
|
|
NullReferenceCheckHelper.throwIfNull(player, () => $"player is null !!!");
|
|
|
|
var server_logic = GameServerApp.getServerLogic();
|
|
NullReferenceCheckHelper.throwIfNull(server_logic, () => $"server_logic is null !!! - {player.toBasicString()}");
|
|
|
|
var player_action = player.getEntityAction<PlayerAction>();
|
|
var ugc_npc = player_action.findUgcNpc(BeaconGuid);
|
|
if (null == ugc_npc)
|
|
{
|
|
err_msg = $"Not found Beacon !!! : BeaconGuid:{BeaconGuid} - {player.toBasicString()}";
|
|
result.setFail(ServerErrorCode.UgcNpcNotFound, err_msg);
|
|
return result;
|
|
}
|
|
|
|
(result, META_ID item_meta_id, double req_money) = checkRegisterItemToBeaconShop(itemGuid, itemAmount, SellingPrice, ugc_npc);
|
|
if (result.isFail())
|
|
{
|
|
return result;
|
|
}
|
|
|
|
if (isRentalSafeTime(ugc_npc) == false)
|
|
{
|
|
err_msg = $"Rental Safe Time is over - {player.toBasicString()}";
|
|
result.setFail(ServerErrorCode.BeaconShopOverRentalSafeTime, err_msg);
|
|
return result;
|
|
}
|
|
|
|
var fn_start_register_beacon_shop_item = async delegate ()
|
|
{
|
|
var result = new Result();
|
|
var err_msg = string.Empty;
|
|
|
|
var invokers = new List<ILogInvoker>();
|
|
var selling_finish_time = DateTime.UtcNow.AddHours(ServerCommon.MetaHelper.GameConfigMeta.BeaconShopSellPeriod);
|
|
|
|
var ugc_npc = player_action.findUgcNpc(BeaconGuid);
|
|
if (null == ugc_npc)
|
|
{
|
|
err_msg = $"Not found Beacon !!! : BeaconGuid:{BeaconGuid} - {player.toBasicString()}";
|
|
result.setFail(ServerErrorCode.UgcNpcNotFound, err_msg);
|
|
return result;
|
|
}
|
|
|
|
var beacon_attribute = ugc_npc.getEntityAttribute<UgcNpcAttribute>();
|
|
NullReferenceCheckHelper.throwIfNull(beacon_attribute, () => $"beacon_attribute is null !!!");
|
|
|
|
var ugc_npc_beacon_shop_action = ugc_npc.getEntityAction<UgcNpcBeaconShopAction>();
|
|
|
|
//1. 일일 등록 횟수 등록
|
|
var beacon_shop_profile_attribute = ugc_npc.getEntityAttribute<BeaconShopProfileAttribute>();
|
|
NullReferenceCheckHelper.throwIfNull(beacon_shop_profile_attribute, () => $"beacon_shop_profile_attribute is null !!!");
|
|
|
|
updateDailyRegisterCount(beacon_shop_profile_attribute);
|
|
|
|
beacon_shop_profile_attribute.DailyRegisterCount += 1;
|
|
beacon_shop_profile_attribute.modifiedEntityAttribute();
|
|
|
|
//2. 아이템 제거
|
|
var inventory_action = player.getEntityAction<InventoryActionBase>();
|
|
(result, var changed_item) = await inventory_action.tryDeleteItemByGuid(itemGuid, itemAmount);
|
|
if(result.isFail() || changed_item == null)
|
|
{
|
|
if (result.isSuccess())
|
|
result.setFail(ServerErrorCode.BeaconShopException, err_msg);
|
|
err_msg = $"Failed to delete Item !!! : itemGuid:{itemGuid}, itemAmount:{itemAmount}, itemMetaId:{item_meta_id} - {player.toBasicString()}";
|
|
PacketHandler.BeaconShopRegisterItemPacketHandler.send_S2C_ACK_BEACON_SHOP_REGISTER_ITEM(player, result, null);
|
|
return result;
|
|
}
|
|
|
|
var new_item_attribute = changed_item.getEntityAttribute<ItemAttributeBase>();
|
|
NullReferenceCheckHelper.throwIfNull(new_item_attribute, () => $"new_item_attribute is null !!!");
|
|
|
|
//3. 비컨샵 데이터 생성
|
|
(result, var beacon_shop_item) = await BeaconShopItem.createBeaconShop(ugc_npc, player.getUserGuid(), BeaconGuid, selling_finish_time, SellingPrice, itemAmount, new_item_attribute);
|
|
if (result.isFail() || beacon_shop_item == null)
|
|
{
|
|
if (result.isSuccess())
|
|
result.setFail(ServerErrorCode.BeaconShopException, err_msg);
|
|
err_msg = $"Failed to create BeaconShopItem !!! : BeaconGuid:{BeaconGuid} - {player.toBasicString()}";
|
|
PacketHandler.BeaconShopRegisterItemPacketHandler.send_S2C_ACK_BEACON_SHOP_REGISTER_ITEM(player, result, null);
|
|
return result;
|
|
}
|
|
|
|
var beacon_shop_attribute = beacon_shop_item.getEntityAttribute<BeaconShopItemAttribute>();
|
|
NullReferenceCheckHelper.throwIfNull(beacon_shop_attribute, () => $"beacon_shop_attribute is null !!!");
|
|
|
|
//4. 등록 수수료 차감
|
|
var money_action = player.getEntityAction<MoneyAction>();
|
|
var item_meta_data = changed_item.getItemMeta();
|
|
NullReferenceCheckHelper.throwIfNull(item_meta_data, () => $"item_meta_data is null !!!");
|
|
|
|
result = await money_action.spendMoney(CurrencyType.Gold, req_money);
|
|
if (result.isFail())
|
|
{
|
|
err_msg = $"Not enough register gold !!! : reqGold:{req_money}, itemGuid:{itemGuid}, reqUnitGoldFee:{item_meta_data.BeaconShopGoldFee} * count:{itemAmount} - {player.toBasicString()}";
|
|
PacketHandler.BeaconShopRegisterItemPacketHandler.send_S2C_ACK_BEACON_SHOP_REGISTER_ITEM(player, result, null);
|
|
return result;
|
|
}
|
|
|
|
//5. mongo에 등록 (아이템 검색용도)
|
|
var beaconShopMongoDoc = new BeaconShopMongoDoc()
|
|
{
|
|
ItemGuid = beacon_shop_attribute.ItemGuid,
|
|
TagId = (int)beacon_shop_attribute.ItemMetaId,
|
|
BeaconGuid = beacon_attribute.UgcNpcMetaGuid,
|
|
BeaconNickName = beacon_attribute.Nickname,
|
|
BeaconTitle = beacon_attribute.Title,
|
|
BeaconBodyItemMetaId = (int)beacon_attribute.BodyItemMetaId,
|
|
PriceForUnit = SellingPrice,
|
|
Amount = beacon_shop_attribute.ItemStackCount,
|
|
OwnerGuid = player.getUserGuid(),
|
|
OwnerNickName = player.getUserNickname(),
|
|
BeaconMyHomeGuid = beacon_attribute.LocatedInstanceGuid,
|
|
SellingFinishTime = selling_finish_time,
|
|
};
|
|
|
|
// 6. BeaconShopSoldPriceDoc이 존재하는 지 체크하고, 없으면 생성 한다 !!!
|
|
var sold_price_doc = new BeaconShopSoldPriceDoc(player.getUserGuid(), beacon_attribute.UgcNpcMetaGuid);
|
|
result = await sold_price_doc.newDoc4Query();
|
|
if (result.isFail()) { return result; }
|
|
result = await server_logic.getDynamoDbClient().createIfNotExist<BeaconShopSoldPriceDoc>(sold_price_doc
|
|
, (sold_price_doc) =>
|
|
{
|
|
var sold_price_attrib = sold_price_doc.getAttrib<BeaconShopSoldPriceAttrib>();
|
|
NullReferenceCheckHelper.throwIfNull(sold_price_attrib, () => $"sold_price_attrib is null !!! - {player.toBasicString()}");
|
|
sold_price_attrib.UserGuid = player.getUserGuid();
|
|
sold_price_attrib.BeaconGuid = beacon_attribute.UgcNpcMetaGuid;
|
|
sold_price_attrib.GivenPrice = 0;
|
|
sold_price_attrib.TaxPrice = 0;
|
|
}
|
|
);
|
|
if (result.isFail()) { return result; }
|
|
|
|
var task_log_data = BeaconShopBusinessLogHelper.toLogInfo(beaconShopMongoDoc, beacon_shop_attribute.IsActiveSelling);
|
|
invokers.Add(new BeaconShopBusinessLog(task_log_data));
|
|
|
|
result = await m_beacon_shop_repository.insert(beaconShopMongoDoc);
|
|
if (result.isFail())
|
|
{
|
|
err_msg = $"Failed to create BeaconShopItem !!! : BeaconGuid:{BeaconGuid} - {player.toBasicString()}";
|
|
PacketHandler.BeaconShopRegisterItemPacketHandler.send_S2C_ACK_BEACON_SHOP_REGISTER_ITEM(player, result, null);
|
|
return result;
|
|
}
|
|
|
|
var batch = new QueryBatchEx<QueryRunnerWithDocument>( player, LogActionType.BeaconShopRegisterItem
|
|
, server_logic.getDynamoDbClient(), true );
|
|
{
|
|
batch.addQuery(new DBQWriteToAttributeAllWithTransactionRunner());
|
|
}
|
|
|
|
batch.appendBusinessLogs(invokers);
|
|
|
|
result = await QueryHelper.sendQueryAndBusinessLog(batch);
|
|
if (result.isFail())
|
|
{
|
|
PacketHandler.BeaconShopRegisterItemPacketHandler.send_S2C_ACK_BEACON_SHOP_REGISTER_ITEM(player, result, null);
|
|
return result;
|
|
}
|
|
|
|
ugc_npc_beacon_shop_action.addBeaconShopItem(beacon_shop_attribute.ItemGuid, beacon_shop_item);
|
|
|
|
var found_transaction_runner = player.findTransactionRunner(TransactionIdType.PrivateContents);
|
|
if (null == found_transaction_runner)
|
|
{
|
|
err_msg = $"Not found TransactionRunner !!! : {toBasicString()} - {player.toBasicString()}";
|
|
Log.getLogger().warn(err_msg);
|
|
PacketHandler.BeaconShopReturnItemPacketHandler.send_S2C_ACK_BEACON_SHOP_RETURN_ITEM(player, result);
|
|
return result;
|
|
}
|
|
|
|
var hasBeaconShopItem = ugc_npc_beacon_shop_action.hasBeaconShopItem();
|
|
|
|
BeaconShopHelper.send_GS2GS_NTF_UPDATE_BEACON_SHOP_ITEM(player.getUserGuid(), BeaconGuid, hasBeaconShopItem);
|
|
|
|
PacketHandler.BeaconShopRegisterItemPacketHandler.send_S2C_ACK_BEACON_SHOP_REGISTER_ITEM(player, result, beacon_shop_item, found_transaction_runner.getCommonResult());
|
|
return result;
|
|
};
|
|
|
|
result = await player.runTransactionRunnerSafely(TransactionIdType.PrivateContents, "RegisterItemToBeaconShop", fn_start_register_beacon_shop_item);
|
|
if (result.isFail())
|
|
{
|
|
err_msg = $"Failed to runTransactionRunnerSafely() !!! : {result.toBasicString()} - {player.toBasicString()}";
|
|
Log.getLogger().error(err_msg);
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
public async Task<Result> BeaconShopReturnItem(ITEM_GUID itemGuid, BEACON_GUID beaconGuid)
|
|
{
|
|
var result = new Result();
|
|
var err_msg = string.Empty;
|
|
var player = getOwner() as Player;
|
|
NullReferenceCheckHelper.throwIfNull(player, () => $"player is null !!!");
|
|
|
|
var server_logic = GameServerApp.getServerLogic();
|
|
NullReferenceCheckHelper.throwIfNull(server_logic, () => $"server_logic is null !!! - {player.toBasicString()}");
|
|
|
|
(result, var found_ugc_npc, var ugc_npc_owner) = await NpcHelper.findUgcNpc(beaconGuid, player.getUserGuid());
|
|
if (found_ugc_npc == null)
|
|
{
|
|
if (result.isSuccess())
|
|
result.setFail(ServerErrorCode.UgcNpcNotFound, err_msg);
|
|
err_msg = $"Not found Beacon !!! : itemGuid:{itemGuid} beaconOwner:{player.getUserGuid()} - {player.toBasicString()}";
|
|
return result;
|
|
}
|
|
|
|
var ugc_npc_beacon_shop_action = found_ugc_npc.getEntityAction<UgcNpcBeaconShopAction>();
|
|
|
|
//1. 아이템 찾기
|
|
var found_item = ugc_npc_beacon_shop_action.getBeaconShopItem(itemGuid);
|
|
if (found_item == null)
|
|
{
|
|
err_msg = $"Failed to tryGetItemByItemGuid BeaconShopItem !!! : itemGuid : {itemGuid}, {player.toBasicString()}";
|
|
result.setFail(ServerErrorCode.ItemNotFound, err_msg);
|
|
PacketHandler.BeaconShopReturnItemPacketHandler.send_S2C_ACK_BEACON_SHOP_RETURN_ITEM(player, result);
|
|
return result;
|
|
}
|
|
|
|
//2. 판매 아이템 활성화 확인
|
|
var beacon_shop_item_attribute = found_item.getEntityAttribute<BeaconShopItemAttribute>();
|
|
NullReferenceCheckHelper.throwIfNull(beacon_shop_item_attribute, () => $"beacon_shop_item_attribute is null !!! - {player.toBasicString()}");
|
|
if (beacon_shop_item_attribute.IsActiveSelling == true)
|
|
{
|
|
if (isRentalSafeTime(found_ugc_npc) == false)
|
|
{
|
|
err_msg = $"Rental Safe Time is over - {player.toBasicString()}";
|
|
result.setFail(ServerErrorCode.BeaconShopOverRentalSafeTime, err_msg);
|
|
return result;
|
|
}
|
|
}
|
|
|
|
var fn_start_return_item = async delegate ()
|
|
{
|
|
using (var runner_with_scope = new EntityTransactionRunnerWithScopLock(found_ugc_npc))
|
|
{
|
|
result = await runner_with_scope.tryInvokeWithAsyncLock(() => BeaconShopReturnItemUpdate(itemGuid, beaconGuid));
|
|
if (result.isFail())
|
|
{
|
|
return result;
|
|
}
|
|
|
|
Log.getLogger().debug($"Successed tryInvokeWithAsyncLock BeaconShopReturnItemUpdate - {found_ugc_npc.toBasicString()}");
|
|
}
|
|
|
|
return result;
|
|
};
|
|
|
|
result = await player.runTransactionRunnerSafely(TransactionIdType.PrivateContents, "ReturnItemFromBeaconShop", fn_start_return_item);
|
|
if (result.isFail())
|
|
{
|
|
err_msg = $"Failed to runTransactionRunnerSafely() !!! : {result.toBasicString()} - {player.toBasicString()}";
|
|
Log.getLogger().error(err_msg);
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
private async Task<Result> BeaconShopReturnItemUpdate(ITEM_GUID itemGuid, BEACON_GUID beaconGuid)
|
|
{
|
|
var result = new Result();
|
|
var err_msg = string.Empty;
|
|
var invokers = new List<ILogInvoker>();
|
|
|
|
var player = getOwner() as Player;
|
|
NullReferenceCheckHelper.throwIfNull(player, () => $"player is null !!!");
|
|
var server_logic = GameServerApp.getServerLogic();
|
|
NullReferenceCheckHelper.throwIfNull(server_logic, () => $"server_logic is null !!! - {player.toBasicString()}");
|
|
|
|
var player_action = player.getEntityAction<PlayerAction>();
|
|
var ugc_npc = player_action.findUgcNpc(beaconGuid);
|
|
if (null == ugc_npc)
|
|
{
|
|
err_msg = $"Not found Beacon !!! : BeaconGuid:{beaconGuid} - {player.toBasicString()}";
|
|
result.setFail(ServerErrorCode.UgcNpcNotFound, err_msg);
|
|
PacketHandler.BeaconShopReturnItemPacketHandler.send_S2C_ACK_BEACON_SHOP_RETURN_ITEM(player, result);
|
|
return result;
|
|
}
|
|
|
|
var beacon_attribute = ugc_npc.getEntityAttribute<UgcNpcAttribute>();
|
|
NullReferenceCheckHelper.throwIfNull(beacon_attribute, () => $"beacon_attribute is null !!!");
|
|
|
|
var ugc_npc_beacon_shop_action = ugc_npc.getEntityAction<UgcNpcBeaconShopAction>();
|
|
|
|
//1. 아이템 찾기
|
|
var found_item = ugc_npc_beacon_shop_action.getBeaconShopItem(itemGuid);
|
|
if (found_item == null)
|
|
{
|
|
err_msg = $"Failed to tryGetItemByItemGuid BeaconShopItem !!! : itemGuid : {itemGuid}, {player.toBasicString()}";
|
|
result.setFail(ServerErrorCode.ItemNotFound, err_msg);
|
|
PacketHandler.BeaconShopReturnItemPacketHandler.send_S2C_ACK_BEACON_SHOP_RETURN_ITEM(player, result);
|
|
return result;
|
|
}
|
|
|
|
//2. 지급할 아이템 복사 & Guid 생성
|
|
var cloned_beacon_item_attribute = found_item.getClonedEntityAttribute<BeaconShopItemAttribute>();
|
|
NullReferenceCheckHelper.throwIfNull(cloned_beacon_item_attribute, () => $"cloned_beacon_item_attribute is null !!!");
|
|
(result, var item_doc) = await cloned_beacon_item_attribute.toDocBase(false);
|
|
NullReferenceCheckHelper.throwIfNull(item_doc, () => $"item_doc is null !!!");
|
|
var beacon_shop_item_doc = item_doc as BeaconShopItemDoc;
|
|
NullReferenceCheckHelper.throwIfNull(beacon_shop_item_doc, () => $"beacon_shop_item_doc is null !!!");
|
|
var new_item_doc = BeaconShopHelper.toItemDocFromBeaconShopItemDoc(beacon_shop_item_doc, cloned_beacon_item_attribute.ItemStackCount);
|
|
|
|
//3. Inventory로 아이템 지급
|
|
var inventory_action = player.getEntityAction<InventoryActionBase>();
|
|
(result, var new_items) = await inventory_action.tryTakableToBagWithNewItem(new_item_doc);
|
|
if (result.isFail() || new_items == null)
|
|
{
|
|
if (result.isSuccess())
|
|
result.setFail(ServerErrorCode.BeaconShopException, err_msg);
|
|
err_msg = $"Failed to tryTakableToBagWithNewItem !!! : itemGuid:{itemGuid} - {player.toBasicString()}";
|
|
PacketHandler.BeaconShopReturnItemPacketHandler.send_S2C_ACK_BEACON_SHOP_RETURN_ITEM(player, result);
|
|
return result;
|
|
}
|
|
|
|
//4. mongo에서 제거
|
|
await m_beacon_shop_repository.delete(itemGuid);
|
|
|
|
var task_log_data = BeaconShopBusinessLogHelper.toLogInfo(cloned_beacon_item_attribute, beacon_attribute, player.getUserGuid());
|
|
invokers.Add(new BeaconShopBusinessLog(task_log_data));
|
|
|
|
var batch = new QueryBatchEx<QueryRunnerWithItemRequest>( player, LogActionType.BeaconShopReturnItem
|
|
, server_logic.getDynamoDbClient(), true);
|
|
{
|
|
batch.addQuery(new DBQBeaconShopItemDelete(beaconGuid, itemGuid, cloned_beacon_item_attribute.ItemStackCount));
|
|
batch.addQuery(new DBQWriteToAttributeAllWithTransactionRunner());
|
|
}
|
|
|
|
batch.appendBusinessLogs(invokers);
|
|
|
|
result = await QueryHelper.sendQueryAndBusinessLog(batch);
|
|
if (result.isFail())
|
|
{
|
|
PacketHandler.BeaconShopReturnItemPacketHandler.send_S2C_ACK_BEACON_SHOP_RETURN_ITEM(player, result);
|
|
ugc_npc_beacon_shop_action.setUpdateBeaconShopItem();
|
|
player.send_S2C_NTF_BEACON_SHOP_REFRESH(beaconGuid, BoolType.True);
|
|
return result;
|
|
}
|
|
|
|
ugc_npc_beacon_shop_action.removeBeaconShopItem(itemGuid);
|
|
|
|
var found_transaction_runner = player.findTransactionRunner(TransactionIdType.PrivateContents);
|
|
if (null == found_transaction_runner)
|
|
{
|
|
err_msg = $"Not found TransactionRunner !!! : {toBasicString()} - {player.toBasicString()}";
|
|
Log.getLogger().warn(err_msg);
|
|
PacketHandler.BeaconShopReturnItemPacketHandler.send_S2C_ACK_BEACON_SHOP_RETURN_ITEM(player, result);
|
|
return result;
|
|
}
|
|
|
|
PacketHandler.BeaconShopReturnItemPacketHandler.send_S2C_ACK_BEACON_SHOP_RETURN_ITEM(player, result, itemGuid, beaconGuid, found_transaction_runner.getCommonResult());
|
|
return result;
|
|
}
|
|
|
|
public async Task<Result> BeaconShopPurchaseItem(ITEM_GUID itemGuid, UInt16 itemAmount, BEACON_GUID beaconGuid, USER_GUID beaconOwnerGuid)
|
|
{
|
|
var result = new Result();
|
|
var err_msg = string.Empty;
|
|
var player = getOwner() as Player;
|
|
NullReferenceCheckHelper.throwIfNull(player, () => $"player is null !!!");
|
|
|
|
var server_logic = GameServerApp.getServerLogic();
|
|
NullReferenceCheckHelper.throwIfNull(server_logic, () => $"server_logic is null !!! - {player.toBasicString()}");
|
|
|
|
(result, var found_ugc_npc, var ugc_npc_owner) = await NpcHelper.findUgcNpc(beaconGuid, beaconOwnerGuid);
|
|
if (found_ugc_npc == null)
|
|
{
|
|
if (result.isSuccess())
|
|
result.setFail(ServerErrorCode.UgcNpcNotFound, err_msg);
|
|
err_msg = $"Not found Beacon !!! : itemGuid:{itemGuid} beaconOwner:{beaconOwnerGuid} - {player.toBasicString()}";
|
|
return result;
|
|
}
|
|
|
|
var ugc_npc_beacon_shop_action = found_ugc_npc.getEntityAction<UgcNpcBeaconShopAction>();
|
|
var beacon_shop_item = ugc_npc_beacon_shop_action.getBeaconShopItem(itemGuid);
|
|
if (beacon_shop_item == null)
|
|
{
|
|
err_msg = $"Not found Beacon Shop Item !!! : itemGuid:{itemGuid} beaconOwner:{beaconOwnerGuid} - {player.toBasicString()}";
|
|
result.setFail(ServerErrorCode.BeaconShopNotFoundItem, err_msg);
|
|
return result;
|
|
}
|
|
|
|
// 판매 아이템 활성화 확인
|
|
var beacon_shop_item_attribute = beacon_shop_item.getEntityAttribute<BeaconShopItemAttribute>();
|
|
NullReferenceCheckHelper.throwIfNull(beacon_shop_item_attribute, () => $"beacon_shop_item_attribute is null !!! - {player.toBasicString()}");
|
|
if (beacon_shop_item_attribute.IsActiveSelling == false)
|
|
{
|
|
err_msg = $"Is Deactive Selling Item !! - {player.toBasicString()}";
|
|
result.setFail(ServerErrorCode.BeaconShopDeactiveItemForSell, err_msg);
|
|
return result;
|
|
}
|
|
|
|
if (isRentalMyhome(found_ugc_npc) == false)
|
|
{
|
|
err_msg = $"Beacon is not in myHome !!! - {player.toBasicString()}";
|
|
result.setFail(ServerErrorCode.BeaconShopBeaconIsNotInRentalHome, err_msg);
|
|
return result;
|
|
}
|
|
|
|
if (isRentalSafeTime(found_ugc_npc) == false)
|
|
{
|
|
err_msg = $"Rental Safe Time is over - {player.toBasicString()}";
|
|
result.setFail(ServerErrorCode.BeaconShopOverRentalSafeTime, err_msg);
|
|
return result;
|
|
}
|
|
|
|
var fn_start_purchase_item = async delegate ()
|
|
{
|
|
var result = new Result();
|
|
var err_msg = string.Empty;
|
|
|
|
using (var runner_with_scope = new EntityTransactionRunnerWithScopLock(found_ugc_npc))
|
|
{
|
|
result = await runner_with_scope.tryInvokeWithAsyncLock(() => BeaconShopItemPurchaseUpdate(itemGuid, itemAmount, beaconGuid, beaconOwnerGuid));
|
|
if (result.isFail())
|
|
{
|
|
return result;
|
|
}
|
|
|
|
Log.getLogger().debug($"Successed tryInvokeWithAsyncLock BeaconShopItemPurchaseUpdate - {found_ugc_npc.toBasicString()}");
|
|
}
|
|
|
|
return result;
|
|
};
|
|
|
|
result = await player.runTransactionRunnerSafely(TransactionIdType.PrivateContents, "PurchaseBeaconShopItem", fn_start_purchase_item);
|
|
if (result.isFail())
|
|
{
|
|
err_msg = $"Failed to runTransactionRunnerSafely() !!! : {result.toBasicString()} - {player.toBasicString()}";
|
|
Log.getLogger().error(err_msg);
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
private async Task<Result> BeaconShopItemPurchaseUpdate(ITEM_GUID itemGuid, UInt16 itemAmount, BEACON_GUID beaconGuid, USER_GUID beaconOwnerGuid)
|
|
{
|
|
var result = new Result();
|
|
var err_msg = string.Empty;
|
|
|
|
var server_logic = GameServerApp.getServerLogic();
|
|
var invokers = new List<ILogInvoker>();
|
|
|
|
var dbClient = server_logic.getDynamoDbClient();
|
|
|
|
var player = getOwner() as Player;
|
|
NullReferenceCheckHelper.throwIfNull(player, () => $"player is null !!!");
|
|
|
|
// 1. 아이템 갯수 확인
|
|
(result, var found_ugc_npc, var ugc_npc_owner) = await NpcHelper.findUgcNpc(beaconGuid, beaconOwnerGuid);
|
|
if (found_ugc_npc == null)
|
|
{
|
|
if (result.isSuccess())
|
|
result.setFail(ServerErrorCode.UgcNpcNotFound, err_msg);
|
|
err_msg = $"Not found Beacon !!! : itemGuid:{itemGuid} beaconOwner:{beaconOwnerGuid} - {player.toBasicString()}";
|
|
PacketHandler.BeaconShopPurchaseItemPacketHandler.send_S2C_ACK_BEACON_SHOP_PURCHASE_ITEM(player, result);
|
|
return result;
|
|
}
|
|
|
|
var ugc_npc_attribute = found_ugc_npc.getEntityAttribute<UgcNpcAttribute>();
|
|
NullReferenceCheckHelper.throwIfNull(ugc_npc_attribute, () => $"ugc_npc_attribute is null !!! - {player.toBasicString()}");
|
|
|
|
USER_GUID beacon_owner_guid = ugc_npc_attribute.OwnerGuid;
|
|
|
|
var ugc_npc_beacon_shop_action = found_ugc_npc.getEntityAction<UgcNpcBeaconShopAction>();
|
|
|
|
var beacon_shop_item = ugc_npc_beacon_shop_action.getBeaconShopItem(itemGuid);
|
|
if (beacon_shop_item == null)
|
|
{
|
|
err_msg = $"Not found Beacon Shop Item !!! : itemGuid:{itemGuid} beaconOwner:{beaconOwnerGuid} - {player.toBasicString()}";
|
|
result.setFail(ServerErrorCode.BeaconShopLackOfItemAmount, err_msg);
|
|
PacketHandler.BeaconShopPurchaseItemPacketHandler.send_S2C_ACK_BEACON_SHOP_PURCHASE_ITEM(player, result);
|
|
return result;
|
|
}
|
|
|
|
var beacon_shop_item_attribute = beacon_shop_item.getEntityAttribute<BeaconShopItemAttribute>();
|
|
NullReferenceCheckHelper.throwIfNull(beacon_shop_item_attribute, () => $"beacon_shop_item_attribute is null !!! - {player.toBasicString()}");
|
|
|
|
int left_item_stack_count = beacon_shop_item_attribute.ItemStackCount - itemAmount;
|
|
if (left_item_stack_count < 0)
|
|
{
|
|
err_msg = $"Item is already sold out !!! : itemGuid:{itemGuid} beaconOwner:{beaconOwnerGuid} - {player.toBasicString()}";
|
|
result.setFail(ServerErrorCode.BeaconShopLackOfItemAmount, err_msg);
|
|
PacketHandler.BeaconShopPurchaseItemPacketHandler.send_S2C_ACK_BEACON_SHOP_PURCHASE_ITEM(player, result);
|
|
return result;
|
|
}
|
|
|
|
// 2. 판매 시간 확인
|
|
if(beacon_shop_item_attribute.SellingFinishTime <= DateTime.UtcNow)
|
|
{
|
|
err_msg = $"Item selling time is over !!! : finishTime:{beacon_shop_item_attribute.SellingFinishTime}, itemGuid:{itemGuid} beaconOwner:{beaconOwnerGuid} - {player.toBasicString()}";
|
|
result.setFail(ServerErrorCode.BeaconShopLackOfItemAmount, err_msg);
|
|
PacketHandler.BeaconShopPurchaseItemPacketHandler.send_S2C_ACK_BEACON_SHOP_PURCHASE_ITEM(player, result);
|
|
return result;
|
|
}
|
|
|
|
// 3. 비용 차감
|
|
var money_action = player.getEntityAction<MoneyAction>();
|
|
result = await money_action.changeMoney(CurrencyType.Calium, -1 * beacon_shop_item_attribute.PriceForUnit * itemAmount);
|
|
if (result.isFail())
|
|
{
|
|
err_msg = $"Not enough calium !!! : itemGuid:{itemGuid}, need Calium fee : {beacon_shop_item_attribute.PriceForUnit * itemAmount} - {player.toBasicString()}";
|
|
PacketHandler.BeaconShopPurchaseItemPacketHandler.send_S2C_ACK_BEACON_SHOP_PURCHASE_ITEM(player, result);
|
|
return result;
|
|
}
|
|
|
|
// 4. 지급할 아이템 복사 & Guid 생성& 갯수 변경
|
|
var cloned_beacon_item_attribute = beacon_shop_item.getClonedEntityAttribute<BeaconShopItemAttribute>();
|
|
NullReferenceCheckHelper.throwIfNull(cloned_beacon_item_attribute, () => $"cloned_beacon_item_attribute is null !!!");
|
|
(result, var item_doc) = await cloned_beacon_item_attribute.toDocBase(false);
|
|
NullReferenceCheckHelper.throwIfNull(item_doc, () => $"item_doc is null !!!");
|
|
var beacon_shop_item_doc = item_doc as BeaconShopItemDoc;
|
|
NullReferenceCheckHelper.throwIfNull(beacon_shop_item_doc, () => $"beacon_shop_item_doc is null !!!");
|
|
var beacon_shop_item_attrib = beacon_shop_item_doc.getAttrib<BeaconShopItemAttrib>();
|
|
NullReferenceCheckHelper.throwIfNull(beacon_shop_item_attrib, () => $"beacon_shop_item_attrib is null !!!");
|
|
var new_item_doc = BeaconShopHelper.toItemDocFromBeaconShopItemDoc(beacon_shop_item_doc, itemAmount);
|
|
|
|
// 5. 아이템 지급
|
|
var inventory_action = player.getEntityAction<InventoryActionBase>();
|
|
(result, var new_items) = await inventory_action.tryTakableToBagWithNewItem(new_item_doc);
|
|
if (result.isFail() || new_items == null)
|
|
{
|
|
if (result.isSuccess())
|
|
result.setFail(ServerErrorCode.BeaconShopException, err_msg);
|
|
err_msg = $"Failed to tryTakableToBagWithNewItem !!! : itemGuid:{itemGuid} - {player.toBasicString()}";
|
|
PacketHandler.BeaconShopPurchaseItemPacketHandler.send_S2C_ACK_BEACON_SHOP_PURCHASE_ITEM(player, result);
|
|
return result;
|
|
}
|
|
|
|
// 6. 칼리움 판매금 계산
|
|
double sold_price = CaliumStorageHelper.MultiplyDoubleByLong(beacon_shop_item_attribute.PriceForUnit, (double)itemAmount);
|
|
double tax_price = Math.Ceiling(ServerCommon.MetaHelper.GameConfigMeta.BeaconShopSellFee * 100 * sold_price) / 100;
|
|
double given_price = CaliumStorageHelper.SubTractDoubleByLong(sold_price, tax_price);
|
|
|
|
// 7. 구매 기록 남김
|
|
var beacon_shop_item_history_doc = await BeaconShopHelper.CreateBeaconShopSoldRecord(beacon_shop_item_attribute, player.getUserNickname(), itemAmount, sold_price, tax_price, given_price);
|
|
if(beacon_shop_item_history_doc == null)
|
|
{
|
|
result.setFail(ServerErrorCode.BeaconShopException, err_msg);
|
|
err_msg = $"Failed to Create CreateBeaconShopSoldRecord doc !!! : itemGuid:{itemGuid} - {player.toBasicString()}";
|
|
PacketHandler.BeaconShopPurchaseItemPacketHandler.send_S2C_ACK_BEACON_SHOP_PURCHASE_ITEM(player, result);
|
|
return result;
|
|
}
|
|
|
|
// 8. mongo에 업데이트
|
|
(result, var beacon_shop_mongo_doc) = await m_beacon_shop_repository.updateAmount(itemGuid, -1 * itemAmount);
|
|
if (result.isFail() || beacon_shop_mongo_doc == null)
|
|
{
|
|
if (result.isSuccess())
|
|
result.setFail(ServerErrorCode.BeaconShopException, err_msg);
|
|
err_msg = $"Failed to delete BeaconShopItem !!! : ItemGuid:{itemGuid}, BeaconGuid:{beaconGuid} - {player.toBasicString()}";
|
|
PacketHandler.BeaconShopPurchaseItemPacketHandler.send_S2C_ACK_BEACON_SHOP_PURCHASE_ITEM(player, result);
|
|
return result;
|
|
}
|
|
|
|
// 9. BeaconShopSoldPriceUpdate
|
|
(result, var query_context) = BeaconShopSoldPriceUpdate(beacon_owner_guid, beaconGuid, given_price, tax_price, 1);
|
|
if (result.isFail() || query_context == null)
|
|
{
|
|
if (result.isSuccess())
|
|
result.setFail(ServerErrorCode.BeaconShopException, err_msg);
|
|
err_msg = $"Failed to BeaconShopSoldPriceUpdate !!! : OwnerGuid:{beacon_owner_guid}, ItemGuid:{itemGuid}, BeaconGuid:{beaconGuid}, GibenPrice:{given_price}, TaxPrice:{tax_price} - {player.toBasicString()}";
|
|
PacketHandler.BeaconShopPurchaseItemPacketHandler.send_S2C_ACK_BEACON_SHOP_PURCHASE_ITEM(player, result);
|
|
return result;
|
|
}
|
|
|
|
var task_log_data = BeaconShopBusinessLogHelper.toLogInfo(cloned_beacon_item_attribute, ugc_npc_attribute, player.getUserGuid());
|
|
invokers.Add(new BeaconShopBusinessLog(task_log_data));
|
|
|
|
var task_price_log_data = BeaconShopBusinessLogHelper.toLogInfo(beacon_owner_guid, beaconGuid, given_price, tax_price);
|
|
invokers.Add(new BeaconShopSoldPriceBusinessLog(task_price_log_data));
|
|
|
|
var batch = new QueryBatchEx<QueryRunnerWithItemRequest>( player, LogActionType.BeaconShopPurchaseItem
|
|
, dbClient
|
|
, true);
|
|
{
|
|
batch.addQuery(new DBQEntityWrite(beacon_shop_item_history_doc));
|
|
batch.addQuery(new DBQBeaconShopItemUpdate(beaconGuid, itemGuid, -1 * itemAmount));
|
|
batch.addQuery(new DBQWriteToAttributeAllWithTransactionRunner());
|
|
|
|
batch.addQuery(new DBQWithItemRequestQueryContext(query_context));
|
|
}
|
|
|
|
batch.appendBusinessLogs(invokers);
|
|
|
|
result = await QueryHelper.sendQueryAndBusinessLog(batch);
|
|
if (result.isFail())
|
|
{
|
|
PacketHandler.BeaconShopReturnItemPacketHandler.send_S2C_ACK_BEACON_SHOP_RETURN_ITEM(player, result);
|
|
ugc_npc_beacon_shop_action.setUpdateBeaconShopItem();
|
|
player.send_S2C_NTF_BEACON_SHOP_REFRESH(beaconGuid, BoolType.True);
|
|
return result;
|
|
}
|
|
|
|
var beacon_shop_item_origin_attribute = beacon_shop_item.getOriginEntityAttribute<BeaconShopItemAttribute>();
|
|
NullReferenceCheckHelper.throwIfNull(beacon_shop_item_origin_attribute, () => $"beacon_shop_item_origin_attribute is null !!! - {player.toBasicString()}");
|
|
|
|
beacon_shop_item_origin_attribute.ItemStackCount -= itemAmount;
|
|
if(beacon_shop_item_origin_attribute.ItemStackCount == 0)
|
|
{
|
|
await dbClient.simpleDeleteDocumentWithDocType(beacon_shop_item_doc);
|
|
ugc_npc_beacon_shop_action.removeBeaconShopItem(itemGuid);
|
|
}
|
|
|
|
var found_transaction_runner = player.findTransactionRunner(TransactionIdType.PrivateContents);
|
|
if (null == found_transaction_runner)
|
|
{
|
|
err_msg = $"Not found TransactionRunner !!! : {toBasicString()} - {player.toBasicString()}";
|
|
Log.getLogger().warn(err_msg);
|
|
PacketHandler.BeaconShopReturnItemPacketHandler.send_S2C_ACK_BEACON_SHOP_RETURN_ITEM(player, result);
|
|
return result;
|
|
}
|
|
|
|
PacketHandler.BeaconShopPurchaseItemPacketHandler.send_S2C_ACK_BEACON_SHOP_PURCHASE_ITEM(player, result, itemGuid, beaconGuid, left_item_stack_count, found_transaction_runner.getCommonResult());
|
|
|
|
var hasBeaconShopItem = ugc_npc_beacon_shop_action.hasBeaconShopItem();
|
|
|
|
BeaconShopHelper.send_GS2GS_NTF_UPDATE_BEACON_SHOP_ITEM(beacon_owner_guid, beaconGuid, hasBeaconShopItem);
|
|
|
|
var player_manager = server_logic.getPlayerManager();
|
|
if (player_manager.tryGetUserByPrimaryKey(beacon_owner_guid, out var found_user) == true)
|
|
{
|
|
var found_user_beacon_shop_action = found_user.getEntityAction<BeaconShopAction>();
|
|
found_user_beacon_shop_action.setUpdateSoldRecord();
|
|
}
|
|
else
|
|
{
|
|
var login_cache_request = new LoginCacheOtherUserRequest(player, server_logic.getRedisConnector(), beacon_owner_guid);
|
|
await login_cache_request.fetchLogin();
|
|
var login_cache = login_cache_request.getLoginCache();
|
|
if (login_cache != null)
|
|
{
|
|
BeaconShopHelper.send_GS2GS_NTF_UPDATE_SOLD_RECORD(login_cache.CurrentServer, beacon_owner_guid);
|
|
}
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
private bool isRentalMyhome(UgcNpc ugcNpc)
|
|
{
|
|
var player = getOwner() as Player;
|
|
NullReferenceCheckHelper.throwIfNull(player, () => $"player is null !!!");
|
|
|
|
var beacon_attribute = ugcNpc.getEntityAttribute<UgcNpcAttribute>();
|
|
NullReferenceCheckHelper.throwIfNull(beacon_attribute, () => $"beacon_attribute is null !!!");
|
|
|
|
var rental_agent_action = player.getEntityAction<RentalAgentAction>();
|
|
|
|
if (beacon_attribute.State != EntityStateType.UsingByMyHome ||
|
|
rental_agent_action.isRentalMyhome(beacon_attribute.LocatedInstanceGuid) == false)
|
|
{
|
|
return false;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
// 랜탈 기간이 안전한 시간 내 인지 확인
|
|
private bool isRentalSafeTime(UgcNpc ugcNpc)
|
|
{
|
|
var player = getOwner() as Player;
|
|
NullReferenceCheckHelper.throwIfNull(player, () => $"player is null !!!");
|
|
|
|
var beacon_attribute = ugcNpc.getEntityAttribute<UgcNpcAttribute>();
|
|
NullReferenceCheckHelper.throwIfNull(beacon_attribute, () => $"beacon_attribute is null !!!");
|
|
|
|
var rental_agent_action = player.getEntityAction<RentalAgentAction>();
|
|
|
|
var rental_finish_time = rental_agent_action.getRentalMyhomeFinishTime(beacon_attribute.LocatedInstanceGuid);
|
|
if (rental_finish_time.HasValue == false)
|
|
{
|
|
return false;
|
|
}
|
|
|
|
var now = DateTime.UtcNow;
|
|
if (rental_finish_time.Value.AddSeconds(-5) < now)
|
|
{
|
|
return false;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
public async Task<Result> BeaconShopDeactiveItems(BEACON_GUID beaconGuid, USER_GUID beaconOwnerGuid, List<ILogInvoker> invokers)
|
|
{
|
|
var result = new Result();
|
|
var err_msg = string.Empty;
|
|
|
|
var player = getOwner() as Player;
|
|
NullReferenceCheckHelper.throwIfNull(player, () => $"player is null !!!");
|
|
|
|
// 1. 아이템 비활성화
|
|
(result, var found_ugc_npc, var ugc_npc_owner) = await NpcHelper.findUgcNpc(beaconGuid, beaconOwnerGuid);
|
|
if (found_ugc_npc == null)
|
|
{
|
|
if (result.isSuccess())
|
|
result.setFail(ServerErrorCode.UgcNpcNotFound, err_msg);
|
|
err_msg = $"Not found Beacon !!! : beaconOwner:{beaconOwnerGuid} - {player.toBasicString()}";
|
|
return result;
|
|
}
|
|
|
|
var ugc_npc_attribute = found_ugc_npc.getEntityAttribute<UgcNpcAttribute>();
|
|
NullReferenceCheckHelper.throwIfNull(ugc_npc_attribute, () => $"ugc_npc_attribute is null !!! - {player.toBasicString()}");
|
|
|
|
var ugc_npc_beacon_shop_action = found_ugc_npc.getEntityAction<UgcNpcBeaconShopAction>();
|
|
ugc_npc_beacon_shop_action.setDeactiveAllItems();
|
|
|
|
//2. mongo에서 제거 & 비지니스 로그 작성
|
|
var beacon_shop_item_list = ugc_npc_beacon_shop_action.getHasBeaconShopItem();
|
|
foreach (var beacon_shop_item in beacon_shop_item_list)
|
|
{
|
|
var beacon_shop_item_attribute = beacon_shop_item.getEntityAttribute<BeaconShopItemAttribute>();
|
|
NullReferenceCheckHelper.throwIfNull(beacon_shop_item_attribute, () => $"beacon_shop_item_attribute is null !!! - {toBasicString()}");
|
|
|
|
await m_beacon_shop_repository.delete(beacon_shop_item_attribute.ItemGuid);
|
|
|
|
var task_log_data = BeaconShopBusinessLogHelper.toLogInfo(beacon_shop_item_attribute, ugc_npc_attribute, player.getUserGuid());
|
|
invokers.Add(new BeaconShopBusinessLog(task_log_data));
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
|
|
private (Result, DynamoDbItemRequestQueryContext?) BeaconShopSoldPriceUpdate(string combinationKeyForPK, string combinationKeyForSK, double givenPrice, double taxPrice, int numOfReceiptNotReceived)
|
|
{
|
|
var result = new Result();
|
|
var err_msg = string.Empty;
|
|
|
|
var to_change_attrib_actions = new Dictionary<string, DynamoDbItemRequestHelper.AttribAction>();
|
|
|
|
var givenAttribValueAction = givenPrice > 0 ? DynamoDbItemRequestHelper.AttribValueAction.Increase : DynamoDbItemRequestHelper.AttribValueAction.Decrease;
|
|
var taxAttribValueAction = taxPrice > 0 ? DynamoDbItemRequestHelper.AttribValueAction.Increase : DynamoDbItemRequestHelper.AttribValueAction.Decrease;
|
|
var numOfReceiptNotReceivedAttribValueAction = numOfReceiptNotReceived > 0 ? DynamoDbItemRequestHelper.AttribValueAction.Increase : DynamoDbItemRequestHelper.AttribValueAction.Decrease;
|
|
|
|
to_change_attrib_actions.Add(nameof(BeaconShopSoldPriceAttrib.GivenPrice)
|
|
, new DynamoDbItemRequestHelper.AttribAction
|
|
{
|
|
ValueAction = givenAttribValueAction,
|
|
Value = new AttributeValue { N = Math.Abs(givenPrice).ToString(CultureInfo.InvariantCulture) }
|
|
});
|
|
|
|
to_change_attrib_actions.Add(nameof(BeaconShopSoldPriceAttrib.TaxPrice)
|
|
, new DynamoDbItemRequestHelper.AttribAction
|
|
{
|
|
ValueAction = taxAttribValueAction,
|
|
Value = new AttributeValue { N = Math.Abs(taxPrice).ToString(CultureInfo.InvariantCulture) }
|
|
});
|
|
|
|
to_change_attrib_actions.Add(nameof(BeaconShopSoldPriceAttrib.NumOfReceiptNotReceived)
|
|
, new DynamoDbItemRequestHelper.AttribAction
|
|
{
|
|
ValueAction = numOfReceiptNotReceivedAttribValueAction,
|
|
Value = new AttributeValue { N = Math.Abs(numOfReceiptNotReceived).ToString(CultureInfo.InvariantCulture) }
|
|
});
|
|
|
|
var refund_bid_price_doc = new BeaconShopSoldPriceDoc(combinationKeyForPK, combinationKeyForSK);
|
|
(result, var query_context) = DynamoDbItemRequestHelper.makeUpdateItemRequestWithDoc<BeaconShopSoldPriceAttrib>(refund_bid_price_doc, to_change_attrib_actions);
|
|
if (result.isFail())
|
|
{
|
|
return (result, null);
|
|
}
|
|
NullReferenceCheckHelper.throwIfNull(query_context, () => $"query_context is null !!!");
|
|
|
|
return (result, query_context);
|
|
}
|
|
|
|
public async Task<Result> BeaconShopGetSoldRecords(BEACON_GUID BeaconGuid)
|
|
{
|
|
var result = new Result();
|
|
var err_msg = string.Empty;
|
|
var player = getOwner() as Player;
|
|
NullReferenceCheckHelper.throwIfNull(player, () => $"player is null !!!");
|
|
|
|
var server_logic = GameServerApp.getServerLogic();
|
|
NullReferenceCheckHelper.throwIfNull(server_logic, () => $"server_logic is null !!! - {player.toBasicString()}");
|
|
|
|
result = await updateBeaconShopSold();
|
|
if (result.isFail())
|
|
{
|
|
err_msg = $"Failed to updateBeaconShopSold !!! : {player.toBasicString()}";
|
|
Log.getLogger().warn(err_msg);
|
|
return result;
|
|
}
|
|
|
|
double total_given_price = 0;
|
|
|
|
m_beacon_shop_sold_records.TryGetValue(BeaconGuid, out var beacon_shop_sold_record_list);
|
|
if(m_beacon_shop_sold_price.TryGetValue(BeaconGuid, out var beacon_shop_sold_price) == true)
|
|
{
|
|
var beacon_shop_price_attribute = beacon_shop_sold_price.getEntityAttribute<BeaconShopSoldPriceAttribute>();
|
|
NullReferenceCheckHelper.throwIfNull(beacon_shop_price_attribute, () => $"beacon_shop_price_attribute is null !!! - {player.toBasicString()}");
|
|
total_given_price = beacon_shop_price_attribute.GivenPrice;
|
|
}
|
|
|
|
PacketHandler.BeaconShopSoldRecordInfoPacketHandler.send_S2C_ACK_BEACON_SHOP_GET_SOLD_RECORDS(player, result, beacon_shop_sold_record_list, total_given_price);
|
|
|
|
return result;
|
|
}
|
|
|
|
public async Task<Result> ProcessBeaconShopDeleteRecord()
|
|
{
|
|
var result = new Result();
|
|
var err_msg = string.Empty;
|
|
var player = getOwner() as Player;
|
|
NullReferenceCheckHelper.throwIfNull(player, () => "player is null !!!");
|
|
var server_logic = GameServerApp.getServerLogic();
|
|
|
|
var fn_delete_record = async delegate ()
|
|
{
|
|
var result = new Result();
|
|
var invokers = new List<ILogInvoker>();
|
|
|
|
bool delete_record = false;
|
|
|
|
var delete_beacon_shop_sold_records = new ConcurrentDictionary<BEACON_GUID, List<BeaconShopSoldRecord>>();
|
|
|
|
foreach (var beacon_shop_record_list in m_beacon_shop_sold_records.Values)
|
|
{
|
|
var deleteCount = beacon_shop_record_list.Count - ServerCommon.MetaHelper.GameConfigMeta.BeaconShopPaymentListMaxCount;
|
|
if(deleteCount <= 0)
|
|
continue;
|
|
|
|
delete_record = true;
|
|
|
|
foreach(var beacon_shop_record in beacon_shop_record_list)
|
|
{
|
|
if(deleteCount <= 0)
|
|
break;
|
|
|
|
deleteCount -= 1;
|
|
|
|
var beacon_shop_sold_record_attribute = beacon_shop_record.getEntityAttribute<BeaconShopSoldRecordAttribute>();
|
|
NullReferenceCheckHelper.throwIfNull(beacon_shop_sold_record_attribute, () => "beacon_shop_sold_record_attribute is null !!!");
|
|
|
|
beacon_shop_sold_record_attribute.deleteEntityAttribute();
|
|
|
|
var task_log_data = BeaconShopBusinessLogHelper.toLogInfo(beacon_shop_sold_record_attribute);
|
|
invokers.Add(new BeaconShopSoldRecordBusinessLog(task_log_data));
|
|
|
|
if(delete_beacon_shop_sold_records.TryGetValue(beacon_shop_sold_record_attribute.BeaconGuid, out var deleteBeaconShopSoldRecordList) == false)
|
|
{
|
|
deleteBeaconShopSoldRecordList = new List<BeaconShopSoldRecord>();
|
|
delete_beacon_shop_sold_records[beacon_shop_sold_record_attribute.BeaconGuid] = deleteBeaconShopSoldRecordList;
|
|
}
|
|
|
|
deleteBeaconShopSoldRecordList.Add(beacon_shop_record);
|
|
}
|
|
}
|
|
|
|
if(delete_record == false)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
var batch = new QueryBatchEx<QueryRunnerWithDocument>( player, LogActionType.BeaconShopDeleteRecord
|
|
, server_logic.getDynamoDbClient() );
|
|
{
|
|
batch.addQuery(new DBQWriteToAttributeAllWithTransactionRunner());
|
|
}
|
|
|
|
batch.appendBusinessLogs(invokers);
|
|
|
|
result = await QueryHelper.sendQueryAndBusinessLog(batch);
|
|
if (result.isFail())
|
|
{
|
|
return result;
|
|
}
|
|
|
|
foreach(var delete_beacon_shop_sold_record in delete_beacon_shop_sold_records)
|
|
{
|
|
if(m_beacon_shop_sold_records.TryGetValue(delete_beacon_shop_sold_record.Key, out var beaconShopSoldRecords) == false)
|
|
continue;
|
|
|
|
foreach(var delete_sold_record in delete_beacon_shop_sold_record.Value)
|
|
{
|
|
beaconShopSoldRecords.Remove(delete_sold_record);
|
|
}
|
|
}
|
|
|
|
return result;
|
|
};
|
|
|
|
result = await player.runTransactionRunnerSafely(TransactionIdType.PrivateContents, "BeaconShopDeleteRecord", fn_delete_record);
|
|
if (result.isFail())
|
|
{
|
|
err_msg = $"Failed to runTransactionRunnerSafely()!!! : {result.toBasicString()} - {player.toBasicString()}";
|
|
Log.getLogger().error(err_msg);
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
public async Task<Result> BeaconShopReceivePaymentForSales(BEACON_GUID BeaconGuid)
|
|
{
|
|
var result = new Result();
|
|
var err_msg = string.Empty;
|
|
var player = getOwner() as Player;
|
|
NullReferenceCheckHelper.throwIfNull(player, () => $"player is null !!!");
|
|
|
|
var server_logic = GameServerApp.getServerLogic();
|
|
NullReferenceCheckHelper.throwIfNull(server_logic, () => $"server_logic is null !!! - {player.toBasicString()}");
|
|
|
|
var fn_start_beacon_shop_receive_payment_for_sales = async delegate ()
|
|
{
|
|
var result = new Result();
|
|
var err_msg = string.Empty;
|
|
|
|
var calium_storage_entity = GameServerApp.getServerLogic().findGlobalEntity<CaliumStorageEntity>();
|
|
NullReferenceCheckHelper.throwIfNull(calium_storage_entity, () => $"calium_storage_entity is null !!! - {player.toBasicString()}");
|
|
|
|
var invokers = new List<ILogInvoker>();
|
|
|
|
if(m_beacon_shop_sold_price.TryGetValue(BeaconGuid, out var beaconShopSoldPrice) == false)
|
|
{
|
|
err_msg = $"Failed reload Beacon Shop Sold Price !!! : BeaconGuid:{BeaconGuid} - {player.toBasicString()}";
|
|
result.setFail(ServerErrorCode.BeaconShopNotFoundSoldPrice, err_msg);
|
|
PacketHandler.BeaconShopReceivePaymentForSalesPacketHandler.send_S2C_ACK_BEACON_SHOP_RECEIVE_PAYMENT_FOR_SALES(player, result);
|
|
return result;
|
|
}
|
|
|
|
var beacon_shop_sold_price_attribute = beaconShopSoldPrice.getEntityAttribute<BeaconShopSoldPriceAttribute>();
|
|
NullReferenceCheckHelper.throwIfNull(beacon_shop_sold_price_attribute, () => $"beacon_shop_sold_price_attribute is null !!! - {player.toBasicString()}");
|
|
|
|
// 1. 돈 지급
|
|
var money_action = player.getEntityAction<MoneyAction>();
|
|
result = await money_action.changeMoney(CurrencyType.Calium, beacon_shop_sold_price_attribute.GivenPrice);
|
|
if (result.isFail())
|
|
{
|
|
err_msg = $"Failed to changeMoney !!! : change price delta :{beacon_shop_sold_price_attribute.GivenPrice} - {player.toBasicString()}";
|
|
PacketHandler.BeaconShopReceivePaymentForSalesPacketHandler.send_S2C_ACK_BEACON_SHOP_RECEIVE_PAYMENT_FOR_SALES(player, result);
|
|
return result;
|
|
}
|
|
|
|
// 2. BeaconShopSoldPriceUpdate
|
|
(result, var query_context) = BeaconShopSoldPriceUpdate(beacon_shop_sold_price_attribute.UserGuid, beacon_shop_sold_price_attribute.BeaconGuid, -1 * beacon_shop_sold_price_attribute.GivenPrice, -1 * beacon_shop_sold_price_attribute.TaxPrice, -1 * beacon_shop_sold_price_attribute.NumOfReceiptNotReceived);
|
|
if (result.isFail() || query_context == null)
|
|
{
|
|
if (result.isSuccess())
|
|
result.setFail(ServerErrorCode.BeaconShopException, err_msg);
|
|
err_msg = $"Failed to BeaconShopSoldPriceUpdate !!! : OwnerGuid:{beacon_shop_sold_price_attribute.UserGuid}, BeaconGuid:{beacon_shop_sold_price_attribute.BeaconGuid}, GibenPrice:{-1 * beacon_shop_sold_price_attribute.GivenPrice}, TaxPrice:{-1 * beacon_shop_sold_price_attribute.TaxPrice} - {player.toBasicString()}";
|
|
PacketHandler.BeaconShopPurchaseItemPacketHandler.send_S2C_ACK_BEACON_SHOP_PURCHASE_ITEM(player, result);
|
|
return result;
|
|
}
|
|
|
|
var task_price_log_data = BeaconShopBusinessLogHelper.toLogInfo(beacon_shop_sold_price_attribute.UserGuid, beacon_shop_sold_price_attribute.BeaconGuid, -1 * beacon_shop_sold_price_attribute.GivenPrice, -1 * beacon_shop_sold_price_attribute.TaxPrice);
|
|
invokers.Add(new BeaconShopSoldPriceBusinessLog(task_price_log_data));
|
|
|
|
var batch = new QueryBatchEx<QueryRunnerWithItemRequest>( player, LogActionType.BeaconShopReceivePaymentForSales
|
|
, server_logic.getDynamoDbClient(), true);
|
|
{
|
|
batch.addQuery(new DBQWriteToAttributeAllWithTransactionRunner());
|
|
batch.addQuery(new DBQWithItemRequestQueryContext(query_context));
|
|
}
|
|
|
|
batch.appendBusinessLogs(invokers);
|
|
|
|
result = await QueryHelper.sendQueryAndBusinessLog(batch);
|
|
if (result.isFail())
|
|
{
|
|
PacketHandler.BeaconShopReceivePaymentForSalesPacketHandler.send_S2C_ACK_BEACON_SHOP_RECEIVE_PAYMENT_FOR_SALES(player, result);
|
|
return result;
|
|
}
|
|
|
|
var found_transaction_runner = player.findTransactionRunner(TransactionIdType.PrivateContents);
|
|
if (null == found_transaction_runner)
|
|
{
|
|
err_msg = $"Not found TransactionRunner !!! : {toBasicString()} - {player.toBasicString()}";
|
|
Log.getLogger().warn(err_msg);
|
|
PacketHandler.BeaconShopReturnItemPacketHandler.send_S2C_ACK_BEACON_SHOP_RETURN_ITEM(player, result);
|
|
return result;
|
|
}
|
|
|
|
// 칼리움 소각
|
|
var trans_id = found_transaction_runner.getTransId();
|
|
|
|
var calium_event_action = calium_storage_entity.getEntityAction<CaliumEventAction>();
|
|
NullReferenceCheckHelper.throwIfNull(calium_event_action, () => $"calium_event_action is null !!! - {player.toBasicString()}");
|
|
await calium_event_action.sendCaliumBurnEvent(player, trans_id, player.getUserNickname(), LogActionType.BeaconShopReceivePaymentForSales.ToString(), -1 * beacon_shop_sold_price_attribute.TaxPrice);
|
|
|
|
var beacon_shop_sold_price_origin_attribute = beaconShopSoldPrice.getOriginEntityAttribute<BeaconShopSoldPriceAttribute>();
|
|
NullReferenceCheckHelper.throwIfNull(beacon_shop_sold_price_origin_attribute, () => $"beacon_shop_sold_price_origin_attribute is null !!! - {player.toBasicString()}");
|
|
|
|
beacon_shop_sold_price_origin_attribute.GivenPrice = 0;
|
|
beacon_shop_sold_price_origin_attribute.TaxPrice = 0;
|
|
beacon_shop_sold_price_origin_attribute.NumOfReceiptNotReceived = 0;
|
|
|
|
PacketHandler.BeaconShopReceivePaymentForSalesPacketHandler.send_S2C_ACK_BEACON_SHOP_RECEIVE_PAYMENT_FOR_SALES(player, result, BeaconGuid, found_transaction_runner.getCommonResult());
|
|
|
|
return result;
|
|
};
|
|
|
|
result = await player.runTransactionRunnerSafely(TransactionIdType.PrivateContents, "BeaconShopReceivePaymentForSales", fn_start_beacon_shop_receive_payment_for_sales);
|
|
if (result.isFail())
|
|
{
|
|
err_msg = $"Failed to runTransactionRunnerSafely() !!! : {result.toBasicString()} - {player.toBasicString()}";
|
|
Log.getLogger().error(err_msg);
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
public async Task<Result> BeaconShopSearchItem(META_ID item_meta_id)
|
|
{
|
|
var result = new Result();
|
|
var err_msg = string.Empty;
|
|
var player = getOwner() as Player;
|
|
NullReferenceCheckHelper.throwIfNull(player, () => $"player is null !!!");
|
|
|
|
var server_logic = GameServerApp.getServerLogic();
|
|
NullReferenceCheckHelper.throwIfNull(server_logic, () => $"server_logic is null !!! - {player.toBasicString()}");
|
|
|
|
(result, var beacon_shop_mongo_doc_list) = await m_beacon_shop_repository.get((int)item_meta_id);
|
|
if(result.isFail() || beacon_shop_mongo_doc_list == null)
|
|
{
|
|
if (result.isSuccess())
|
|
result.setFail(ServerErrorCode.BeaconShopFailedGetBoardItem, err_msg);
|
|
PacketHandler.BeaconShopSearchItemPacketHandler.send_S2C_ACK_BEACON_SHOP_SEARCH_ITEM(player, result, null);
|
|
return result;
|
|
}
|
|
PacketHandler.BeaconShopSearchItemPacketHandler.send_S2C_ACK_BEACON_SHOP_SEARCH_ITEM(player, result, beacon_shop_mongo_doc_list);
|
|
|
|
return result;
|
|
}
|
|
|
|
public async Task<Result> BeaconShopGetItemInfos(BEACON_GUID beaconGuid, USER_GUID beaconOwnerGuid)
|
|
{
|
|
var result = new Result();
|
|
var err_msg = string.Empty;
|
|
var player = getOwner() as Player;
|
|
NullReferenceCheckHelper.throwIfNull(player, () => $"player is null !!!");
|
|
|
|
var server_logic = GameServerApp.getServerLogic();
|
|
NullReferenceCheckHelper.throwIfNull(server_logic, () => $"server_logic is null !!! - {player.toBasicString()}");
|
|
|
|
(result, var found_ugc_npc, var ugc_npc_owner) = await NpcHelper.findUgcNpc(beaconGuid, beaconOwnerGuid);
|
|
if (found_ugc_npc == null)
|
|
{
|
|
err_msg = $"Not found Beacon !!! : beaconGuid:{beaconGuid} beaconOwner:{beaconOwnerGuid} - {player.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 !!!");
|
|
|
|
await ProcessUpdateDailyRegisterCount(found_ugc_npc);
|
|
|
|
(result, var beacon_shop_item_reload_data) = await ReloadBeaconShop(beaconGuid, beaconOwnerGuid);
|
|
if (result.isFail())
|
|
{
|
|
return result;
|
|
}
|
|
|
|
result = await updateBeaconShopSold();
|
|
if (result.isFail())
|
|
{
|
|
err_msg = $"Failed to updateBeaconShopSold !!! : {player.toBasicString()}";
|
|
Log.getLogger().warn(err_msg);
|
|
return result;
|
|
}
|
|
|
|
int numOfReceiptNotReceived = getBeaconShopNumOfReceiptNotReceived(beaconGuid);
|
|
|
|
PacketHandler.BeaconShopGetItemInfosPacketHandler.send_S2C_ACK_BEACON_SHOP_GET_ITEM_INFOS(player, result, beacon_shop_item_reload_data, beacon_shop_profile_attribute.DailyRegisterCount, numOfReceiptNotReceived);
|
|
return result;
|
|
}
|
|
|
|
public int getBeaconShopNumOfReceiptNotReceived(BEACON_GUID beaconGuid)
|
|
{
|
|
if (m_beacon_shop_sold_price.TryGetValue(beaconGuid, out var beaconShopSoldPrice) == true)
|
|
{
|
|
var beacon_shop_sold_price_attribute = beaconShopSoldPrice.getEntityAttribute<BeaconShopSoldPriceAttribute>();
|
|
NullReferenceCheckHelper.throwIfNull(beacon_shop_sold_price_attribute, () => $"beacon_shop_sold_price_attribute is null !!! - {getOwner().toBasicString()}");
|
|
return beacon_shop_sold_price_attribute.NumOfReceiptNotReceived;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
private async Task<Result> ProcessUpdateDailyRegisterCount(UgcNpc found_ugc_npc)
|
|
{
|
|
var result = new Result();
|
|
var err_msg = string.Empty;
|
|
var player = getOwner() as Player;
|
|
NullReferenceCheckHelper.throwIfNull(player, () => "player is null !!!");
|
|
var server_logic = GameServerApp.getServerLogic();
|
|
|
|
if (checkDailyRegisterCount(found_ugc_npc) == true)
|
|
{
|
|
var fn_update_daily_count = async delegate ()
|
|
{
|
|
var result = new Result();
|
|
var invokers = new List<ILogInvoker>();
|
|
|
|
var beacon_shop_profile_attribute = found_ugc_npc.getEntityAttribute<BeaconShopProfileAttribute>();
|
|
NullReferenceCheckHelper.throwIfNull(beacon_shop_profile_attribute, () => $"beacon_shop_profile_attribute is null !!! - {player.toBasicString()}");
|
|
|
|
updateDailyRegisterCount(beacon_shop_profile_attribute);
|
|
|
|
var batch = new QueryBatchEx<QueryRunnerWithDocument>( player, LogActionType.BeaconShopUpdateDailyCount
|
|
, server_logic.getDynamoDbClient());
|
|
{
|
|
batch.addQuery(new DBQWriteToAttributeAllWithTransactionRunner());
|
|
}
|
|
|
|
batch.appendBusinessLogs(invokers);
|
|
|
|
result = await QueryHelper.sendQueryAndBusinessLog(batch);
|
|
if (result.isFail())
|
|
{
|
|
return result;
|
|
}
|
|
|
|
return result;
|
|
};
|
|
|
|
result = await player.runTransactionRunnerSafely(TransactionIdType.PrivateContents, "BeaconShopUpdateDailyCount", fn_update_daily_count);
|
|
if (result.isFail())
|
|
{
|
|
err_msg = $"Failed to runTransactionRunnerSafely()!!! : {result.toBasicString()} - {player.toBasicString()}";
|
|
Log.getLogger().error(err_msg);
|
|
}
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
private (Result, META_ID, double) checkRegisterItemToBeaconShop(string itemGuid, int itemAmount, double SellingPrice, UgcNpc ugcNpc)
|
|
{
|
|
var result = new Result();
|
|
var err_msg = string.Empty;
|
|
var player = getOwner() as Player;
|
|
NullReferenceCheckHelper.throwIfNull(player, () => $"player is null !!!");
|
|
|
|
var beacon_attribute = ugcNpc.getEntityAttribute<UgcNpcAttribute>();
|
|
NullReferenceCheckHelper.throwIfNull(beacon_attribute, () => $"beacon_attribute is null !!!");
|
|
|
|
// 1. 비컨 체크
|
|
if (isRentalMyhome(ugcNpc) == false)
|
|
{
|
|
err_msg = $"Beacon is not in myHome !!! : beacon State:{beacon_attribute.State} - {player.toBasicString()}";
|
|
result.setFail(ServerErrorCode.BeaconShopBeaconIsNotInRentalHome, err_msg);
|
|
return (result, 0, 0);
|
|
}
|
|
|
|
// 2. 아이템 체크
|
|
var inventory_action = player.getEntityAction<InventoryActionBase>();
|
|
var target_item = inventory_action.tryGetItemByItemGuid(itemGuid);
|
|
if (target_item == null)
|
|
{
|
|
err_msg = $"Not found item !!! : target item guid :{itemGuid} - {player.toBasicString()}";
|
|
result.setFail(ServerErrorCode.BeaconShopNotFoundItem, err_msg);
|
|
return (result, 0, 0);
|
|
}
|
|
|
|
if(target_item.getItemStackCount() < itemAmount)
|
|
{
|
|
err_msg = $"Not enough item !!! : target item meta id :{target_item.getItemMetaId()}, target item stack count : {target_item.getItemStackCount()}, request count : {itemAmount} - {player.toBasicString()}";
|
|
result.setFail(ServerErrorCode.BeaconShopNotEnoughItem, err_msg);
|
|
return (result, 0, 0);
|
|
}
|
|
|
|
var target_item_meta_data = target_item.getItemMeta();
|
|
if(target_item_meta_data == null)
|
|
{
|
|
err_msg = $"Not found item meta !!! : target item meta id :{target_item.getItemMetaId()}, target item stack count : {target_item.getItemStackCount()}, request count : {itemAmount} - {player.toBasicString()}";
|
|
result.setFail(ServerErrorCode.BeaconShopNotFoundMetaData, err_msg);
|
|
return (result, 0, 0);
|
|
}
|
|
|
|
if (target_item_meta_data.is_BeaconShop == false)
|
|
{
|
|
err_msg = $"Invalid item for Selling !!! : item meta id : {target_item.getItemMetaId()} - {player.toBasicString()}";
|
|
result.setFail(ServerErrorCode.BeaconShopInvalidItemForSell, err_msg);
|
|
return (result, 0, 0);
|
|
}
|
|
|
|
// 3. 재화 체크
|
|
if (ServerCommon.MetaHelper.GameConfigMeta.BeaconShopMinCaliumPrice > SellingPrice)
|
|
{
|
|
err_msg = $"Lower then Min price : request SellingPrice : {SellingPrice} - {player.toBasicString()}";
|
|
result.setFail(ServerErrorCode.BeaconShopLowSellingPrice, err_msg);
|
|
return (result, 0, 0);
|
|
}
|
|
|
|
if(ServerCommon.MetaHelper.GameConfigMeta.BeaconShopMaxCaliumPrice < SellingPrice)
|
|
{
|
|
err_msg = $"over then Min price : request SellingPrice : {SellingPrice} - {player.toBasicString()}";
|
|
result.setFail(ServerErrorCode.BeaconShopOverSellingPrice, err_msg);
|
|
return (result, 0, 0);
|
|
}
|
|
|
|
var req_unit_money = (double)target_item_meta_data.BeaconShopGoldFee;
|
|
var req_money = req_unit_money.calculateRoundedMoneyByCurrency(CurrencyType.Gold, itemAmount);
|
|
var money_action = player.getEntityAction<MoneyAction>();
|
|
if (money_action.hasMoney(CurrencyType.Gold, req_money) == false)
|
|
{
|
|
err_msg = $"!!! : target item meta id :{target_item.getItemMetaId()}, target item stack count : {target_item.getItemStackCount()}, request count : {itemAmount} - {player.toBasicString()}";
|
|
result.setFail(ServerErrorCode.BeaconShopNotEnoughRegisterFee, err_msg);
|
|
return (result, 0, 0);
|
|
}
|
|
|
|
// 4. 일일 등록 횟수 제한
|
|
var beacon_shop_profile_attribute = ugcNpc.getEntityAttribute<BeaconShopProfileAttribute>();
|
|
NullReferenceCheckHelper.throwIfNull(beacon_shop_profile_attribute, () => $"beacon_shop_profile_attribute is null !!!");
|
|
|
|
if( checkDailyRegisterCount(ugcNpc) == false
|
|
&& ServerCommon.MetaHelper.GameConfigMeta.BeaconShopDailyRegistration <= beacon_shop_profile_attribute.DailyRegisterCount)
|
|
{
|
|
err_msg = $"Beacon Shop daily registration count is over !!! DailyRegisterCount : {beacon_shop_profile_attribute.DailyRegisterCount} ";
|
|
result.setFail(ServerErrorCode.BeaconShopOverOneDayRegisterLimit, err_msg);
|
|
return (result, 0, 0);
|
|
}
|
|
|
|
return (result, (META_ID)target_item_meta_data.ItemId, req_money);
|
|
}
|
|
|
|
private async Task<Result> reloadBeaconShopSolds()
|
|
{
|
|
var result = new Result();
|
|
var err_msg = string.Empty;
|
|
|
|
var player = getOwner() as Player;
|
|
NullReferenceCheckHelper.throwIfNull(player, () => $"player is null !!!");
|
|
|
|
var server_logic = GameServerApp.getServerLogic();
|
|
var dynamo_db_client = server_logic.getDynamoDbClient();
|
|
|
|
var doc = new BeaconShopSoldRecordDoc(player.getUserGuid());
|
|
var query_config = dynamo_db_client.makeQueryConfigForReadByPKOnly(doc.getPK());
|
|
(result, var read_docs) = await dynamo_db_client.simpleQueryDocTypesWithQueryOperationConfig<BeaconShopSoldRecordDoc>(query_config);
|
|
if (result.isFail())
|
|
{
|
|
return result;
|
|
}
|
|
|
|
result = await AddBeaconShopSoldRecordsFromDocs(read_docs);
|
|
if(result.isFail())
|
|
{
|
|
return result;
|
|
}
|
|
|
|
var price_doc = new BeaconShopSoldPriceDoc(player.getUserGuid());
|
|
var price_query_config = dynamo_db_client.makeQueryConfigForReadByPKOnly(price_doc.getPK());
|
|
(result, var price_read_docs) = await dynamo_db_client.simpleQueryDocTypesWithQueryOperationConfig<BeaconShopSoldPriceDoc>(price_query_config);
|
|
if (result.isFail())
|
|
{
|
|
return result;
|
|
}
|
|
|
|
result = await AddBeaconShopSoldPriceFromDocs(price_read_docs);
|
|
if (result.isFail())
|
|
{
|
|
return result;
|
|
}
|
|
|
|
await ProcessBeaconShopDeleteRecord();
|
|
|
|
return result;
|
|
}
|
|
|
|
private async Task<(Result, List<BeaconShopItem>?)> ReloadBeaconShop(BEACON_GUID beaconGuid, USER_GUID beaconOwnerGuid)
|
|
{
|
|
var result = new Result();
|
|
var err_msg = string.Empty;
|
|
var player = getOwner() as Player;
|
|
NullReferenceCheckHelper.throwIfNull(player, () => $"player is null !!!");
|
|
|
|
var server_logic = GameServerApp.getServerLogic();
|
|
NullReferenceCheckHelper.throwIfNull(server_logic, () => $"server_logic is null !!! - {player.toBasicString()}");
|
|
|
|
(result, var found_ugc_npc, var ugc_npc_owner) = await NpcHelper.findUgcNpc(beaconGuid, beaconOwnerGuid);
|
|
if (found_ugc_npc == null)
|
|
{
|
|
if (result.isSuccess())
|
|
result.setFail(ServerErrorCode.UgcNpcNotFound, err_msg);
|
|
|
|
err_msg = $"Not found Beacon !!! : beaconGuid:{beaconGuid} beaconOwner:{beaconOwnerGuid} - {player.toBasicString()}";
|
|
return (result, null);
|
|
}
|
|
|
|
var ugc_npc_beacon_shop_action = found_ugc_npc.getEntityAction<UgcNpcBeaconShopAction>();
|
|
NullReferenceCheckHelper.throwIfNull(ugc_npc_beacon_shop_action, () => $"ugc_npc_beacon_shop_action is null !!! - {toBasicString()}");
|
|
|
|
result = await ugc_npc_beacon_shop_action.ReloadBeaconShopInventoryFromDb();
|
|
if (result.isFail())
|
|
{
|
|
err_msg = $"Failed to Reload BeaconShop from Db !!! : beaconGuid:{beaconGuid} beaconOwner:{beaconOwnerGuid} - {player.toBasicString()}";
|
|
Log.getLogger().error(err_msg);
|
|
return (result, null);
|
|
}
|
|
|
|
return (result, ugc_npc_beacon_shop_action.getHasBeaconShopItem());
|
|
}
|
|
|
|
private async Task<Result> updateBeaconShopSold()
|
|
{
|
|
var result = new Result();
|
|
|
|
if (m_isUpdateSold == true)
|
|
{
|
|
result = await reloadBeaconShopSolds();
|
|
if (result.isFail())
|
|
{
|
|
return result;
|
|
}
|
|
|
|
m_isUpdateSold = false;
|
|
}
|
|
|
|
return result;
|
|
}
|
|
}
|