Files
caliverse_server/GameServer/Contents/Party/PacketHandler/CreatePartyInstancePacketHandler.cs
2025-05-01 07:20:41 +09:00

226 lines
9.8 KiB
C#

using Google.Protobuf;
using Google.Protobuf.WellKnownTypes;
using ServerCore;
using ServerBase;
using ServerCommon;
using ServerCommon.BusinessLogDomain;
using MetaAssets;
namespace GameServer.PacketHandler;
[PacketHandler(typeof(ClientToGameReq), typeof(ClientToGameReq.Types.CreatePartyInstanceReq), typeof(CreatePartyInstancePacketHandler), typeof(GameLoginListener))]
public class CreatePartyInstancePacketHandler : PacketRecvHandler
{
private void send_S2C_ACK_CREATE_PARTY_INSTANCE(Player owner, Result result, string spendItemGuid)
{
var ack_packet = new ClientToGame
{
Response = new ClientToGameRes
{
ErrorCode = result.ErrorCode,
CreatePartyInstanceRes = new()
}
};
if (result.isSuccess())
{
var spent = new ItemGuidCount();
spent.ItemGuid = spendItemGuid;
spent.ItemCount = 1;
ack_packet.Response.CreatePartyInstanceRes.Items.Add(spent);
}
GameServerApp.getServerLogic().onSendPacket(owner, ack_packet);
}
public override async Task<Result> onProcessPacket(ISession entityWithSession, IMessage recvMessage)
{
var result = new Result();
string err_msg;
var entity_player = entityWithSession as Player;
NullReferenceCheckHelper.throwIfNull(entity_player, () => $"entity_player is null !!!");
// 1. 기본 정보 체크
var request = (recvMessage as ClientToGame)?.Request.CreatePartyInstanceReq;
if (null == request)
{
err_msg = $"Failed to get request type !!! : {nameof(ClientToGame.Request.CreatePartyInstanceReq)}";
result.setFail(ServerErrorCode.InvalidArgument, err_msg);
Log.getLogger().error(result.toBasicString());
send_S2C_ACK_CREATE_PARTY_INSTANCE(entity_player, result, string.Empty);
return result;
}
// 2. 소속 파티 Guid 조회
var personal_party_action = entity_player.getEntityAction<PersonalPartyAction>();
NullReferenceCheckHelper.throwIfNull(personal_party_action, () => $"personal_party_action is null !!! - {entity_player.toBasicString()}");
var personal_party = personal_party_action.getPersonalParty();
if (null == personal_party)
{
err_msg = $"Failed to get party info !!! - not party member - {entity_player.getUserGuid()}";
result.setFail(ServerErrorCode.NotParty, err_msg);
Log.getLogger().error(err_msg);
send_S2C_ACK_CREATE_PARTY_INSTANCE(entity_player, result, string.Empty);
return result;
}
var global_party = GameServerApp.getServerLogic().findGlobalEntity<GlobalParty>();
NullReferenceCheckHelper.throwIfNull(global_party, () => $"global_party is null !!! - {entity_player.toBasicString()}");
var party = global_party.getParty(personal_party.getPartyGuid());
NullReferenceCheckHelper.throwIfNull(party, () => $"party is null !!! - {entity_player.toBasicString()}");
// 3. 파티장 체크
var party_action = party.getEntityAction<GlobalPartyDetailAction>();
NullReferenceCheckHelper.throwIfNull(party_action, () => $"party_action is null !!! - {entity_player.toBasicString()}");
var is_leader = party_action.isLeader(entity_player.getUserGuid());
if (!is_leader)
{
err_msg = $"Failed to create party instance !!! : not party leader - {entity_player.getUserGuid()}";
result.setFail(ServerErrorCode.NotPartyLeader, err_msg);
Log.getLogger().error(err_msg);
send_S2C_ACK_CREATE_PARTY_INSTANCE(entity_player, result, string.Empty);
return result;
}
// 4. Party Instance 생성 처리
result = await entity_player.runTransactionRunnerSafely(TransactionIdType.PrivateContents, "CreatePartyInstance", createPartyInstanceDelegate);
if (result.isFail())
{
send_S2C_ACK_CREATE_PARTY_INSTANCE(entity_player, result, string.Empty);
}
return result;
async Task<Result> createPartyInstanceDelegate() =>
await createPartyInstanceAsync(entity_player, request, party);
}
private async Task<Result> createPartyInstanceAsync(Player owner, ClientToGameReq.Types.CreatePartyInstanceReq request, GlobalPartyDetail party)
{
var result = new Result();
string err_msg;
// 1. party instance 정보 획득
var instance_info = getPartyInstanceInfo(request);
if (instance_info.result.isFail() || instance_info.concert_data == null) return instance_info.result;
// 2. Instance 생성
var instance_room_id = await InstanceRoomHandler.CreatePartyInstance(party.PartyGuid, instance_info.instance_id);
if (string.IsNullOrEmpty(instance_room_id))
{
err_msg = "Failed to create party instance !!!";
result.setFail(ServerErrorCode.CreateRoomFail, err_msg);
Log.getLogger().error(err_msg);
return result;
}
// 3. 파티 채널 생성권 소모
(result, var item) = await spendCreatePartyInstanceItem(owner);
if(result.isFail()) return result;
// 4. 파티에 party instance 저장 ( PartyInstanceInfo )
var party_info_action = party.getEntityAction<GlobalPartyDetailInstanceAction>();
NullReferenceCheckHelper.throwIfNull(party_info_action, () => $"party_info_action is null !!! - {owner.toBasicString()}");
var start_time = DateTime.UtcNow.AddSeconds(MetaHelper.GameConfigMeta.PartyConcertWaitingTimeSec).ToTimestamp();
var end_time = start_time.ToDateTime().AddSeconds(instance_info.concert_data.ConcertLength).ToTimestamp();
result = await party_info_action.registerPartyInstance(instance_info.instance_id, instance_room_id, start_time, end_time, 0, true);
if (result.isFail()) return result;
var batch = new QueryBatchEx<QueryRunnerWithDocument>( owner, LogActionType.CreatePartyInstance, GameServerApp.getServerLogic().getDynamoDbClient());
batch.addQuery(new DBQWriteToAttributeAllWithTransactionRunner());
batch.addQuery(new QueryFinal());
// 5. Business Log 기록
writeBusinessLog(batch, party, item);
return await QueryHelper.sendQueryAndBusinessLog(batch);
}
private (Result result, int instance_id, MetaAssets.InstanceConcertMetaData? concert_data) getPartyInstanceInfo(ClientToGameReq.Types.CreatePartyInstanceReq request)
{
var result = new Result();
string err_msg;
// 1. Instance ID 획득
(result, var room_map_tree, _) = MapHelper.tryGetRoomMapTree(request.LandId, request.Floor, request.BuildingId);
if (result.isFail() || room_map_tree == null)
{
err_msg = $"Failed to tryGetRoomMapTree() !!! : {result.toBasicString()}";
Log.getLogger().error(err_msg);
return (result, 0, null);
}
var instance_id = room_map_tree.InstanceMetaId;
// 2. Indun data 획득
if (!MetaData.Instance._IndunTable.TryGetValue(instance_id, out var indun_data))
{
err_msg = $"Failed to create party instance !!! : Not Found IndunData. instanceId:{instance_id}";
result.setFail(ServerErrorCode.InstanceMetaDataNotFound, err_msg);
Log.getLogger().error(err_msg);
return (result, 0, null);
}
// 3. indun data 체크
if (indun_data.placeType() != EPlaceType.Concert || indun_data.OverLimit == 0)
{
err_msg = $"Failed to create party instance !!! : invalid instance info. instanceId:{instance_id}";
result.setFail(ServerErrorCode.NotUsablePlace, err_msg);
Log.getLogger().error(err_msg);
return (result, 0, null);
}
// 4. Concert 정보 획득
if (MetaData.Instance._ConcertTable.TryGetValue(indun_data.MapId, out var concert_data) == false)
{
err_msg = $"Failed to create party instance !!! : not found Concert id:{indun_data.MapId}";
result.setFail(ServerErrorCode.NotFoundTable, err_msg);
Log.getLogger().error(err_msg);
return (result, 0, null);
}
return (result, instance_id, concert_data);
}
private async Task<(Result, Item?)> spendCreatePartyInstanceItem(Player owner)
{
var inventory_action = owner.getEntityAction<InventoryActionBase>();
NullReferenceCheckHelper.throwIfNull(inventory_action, () => $"inventory_action is null !!! - {owner.toBasicString()}");
(var result, var delete_instance_items) = await inventory_action.tryDeleteItemByMetaId((uint)ServerCommon.Constant.PARTY_INSTANCE_CREATE_ITEM_ID, (ushort)MetaHelper.GameConfigMeta.ItemAmountPartyInstance);
if (result.isFail()) return (result, null);
var item = delete_instance_items.FirstOrDefault();
return (result, item);
}
private void writeBusinessLog(QueryBatchBase queryBatchBase, GlobalPartyDetail party, Item? delItem)
{
// 1. 파티 정보
var party_log_data = PartyBusinessLogHelper.toPartyLogData(party.PartyGuid, false);
var party_business_log = new PartyBusinessLog(party_log_data);
queryBatchBase.appendBusinessLog(party_business_log);
// 2. 파티 인스턴스 정보
var party_instance_log_data = PartyBusinessLogHelper.toPartyInstanceLogData(party.PartyGuid, true);
var party_instance_business_log = new PartyInstanceBusinessLog(party_instance_log_data);
queryBatchBase.appendBusinessLog(party_instance_business_log);
}
}