초기커밋

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,402 @@
using System.Collections.Concurrent;
using Google.Protobuf;
using Google.Protobuf.WellKnownTypes;
using ServerCore;
using ServerBase;
using ServerCommon;
using ServerCommon.BusinessLogDomain;
using MetaAssets;
using PARTY_GUID = System.String;
using USER_GUID = System.String;
namespace GameServer;
public class GlobalPartyAction : EntityActionBase
{
private ConcurrentDictionary<string, GlobalPartyDetail> m_parties { get; set; } = new();
public GlobalPartyAction(GlobalParty owner) : base(owner)
{
}
public override async Task<Result> onInit()
{
await Task.CompletedTask;
var result = new Result();
return result;
}
public override void onClear()
{
return;
}
public GlobalPartyDetail? getGlobalPartyDetail(PARTY_GUID party_guid)
{
if (string.IsNullOrEmpty(party_guid)) return null;
return m_parties.GetValueOrDefault(party_guid);
}
private void setGlobalPartyDetail(GlobalPartyDetail detail) => m_parties.TryAdd(detail.PartyGuid, detail);
public async Task<Result> createParty(PARTY_GUID party_guid, string leader_guid, string leader_nickname)
{
var result = new Result();
var owner = getOwner() as GlobalParty;
NullReferenceCheckHelper.throwIfNull(owner, () => $"GlobalParty is null !! - party_guid:{party_guid}");
var detail = new GlobalPartyDetail(owner, party_guid);
await detail.onInit();
// redis 등록
var detail_action = detail.getEntityAction<GlobalPartyDetailAction>();
NullReferenceCheckHelper.throwIfNull(detail_action, () => $"GlobalPartyDetailAction is null !! - party_guid:{party_guid}");
result = await detail_action.createPartyDetailInfo(leader_guid, leader_nickname);
// 메모리 등록
setGlobalPartyDetail(detail);
return result;
}
private async Task<Result> loadParty(PARTY_GUID party_guid)
{
var owner = getOwner() as GlobalParty;
NullReferenceCheckHelper.throwIfNull(owner, () => $"global party is null !!! - party guid: {party_guid}");
var detail = new GlobalPartyDetail(owner, party_guid);
await detail.onInit();
var detail_action = detail.getEntityAction<GlobalPartyDetailAction>();
NullReferenceCheckHelper.throwIfNull(detail_action, () => $"global party detail action is null !!! - {owner.toBasicString()}");
var result = await detail_action.loadAllFromCache();
if (result.isFail()) return result;
setGlobalPartyDetail(detail);
// 1-1. party server 정보에 server 추가
var global_party_server_action = detail.getEntityAction<GlobalPartyDetailServerAction>();
NullReferenceCheckHelper.throwIfNull(global_party_server_action, () => $"global party detail server action is null !!! - {owner.toBasicString()}");
result = await global_party_server_action.addPartyServer(GameServerApp.getServerLogic().getServerName());
if (result.isFail()) return result;
// 1-2. 서버 변경 알림
result = await global_party_server_action.notifyChangePartyServerToServers(BoolType.True, GameServerApp.getServerLogic().getServerName());
return result;
}
public async Task<(string? leader_guid, string? leader_nickname, int? member_count)> getPartyLeaderGuidAndMemberCount(PARTY_GUID party_guid)
{
var owner = getOwner() as GlobalParty;
NullReferenceCheckHelper.throwIfNull(owner, () => $"global party is null !!! - party guid: {party_guid}");
var detail = getGlobalPartyDetail(party_guid);
// 메모리에 파티정보가 있으면, 활용
if (null != detail)
{
var origin_detail_action = detail.getEntityAction<GlobalPartyDetailAction>();
NullReferenceCheckHelper.throwIfNull(origin_detail_action, () => $"global party detail action is null !!! - {owner.toBasicString()}");
var origin_detail_member_action = detail.getEntityAction<GlobalPartyDetailMemberAction>();
NullReferenceCheckHelper.throwIfNull(origin_detail_member_action, () => $"global party detail member action is null !!! - {owner.toBasicString()}");
return (origin_detail_action.getLeaderGuid(), origin_detail_action.getLeaderNickname(), origin_detail_member_action.getMemberCount());
}
// 메모리에 파티 정보가 없으면, load 하여 활용 ( 단, 메모리 저장은 하지 않음 - 서버내 없는 파티 정보 조회 )
detail = new GlobalPartyDetail(owner, party_guid);
await detail.onInit();
var detail_action = detail.getEntityAction<GlobalPartyDetailAction>();
NullReferenceCheckHelper.throwIfNull(detail_action, () => $"global party detail action is null !!! - {owner.toBasicString()}");
var detail_member_action = detail.getEntityAction<GlobalPartyDetailMemberAction>();
NullReferenceCheckHelper.throwIfNull(detail_member_action, () => $"global party detail member action is null !!! - {owner.toBasicString()}");
var result = await detail_action.loadPartyCache();
if (result.isFail()) return (null, null, null);
result = await detail_action.loadPartyMemberCache();
if (result.isFail()) return (null, null, null);
return (detail_action.getLeaderGuid(), detail_action.getLeaderNickname(), detail_member_action.getMemberCount());
}
public async Task<Result> joinParty(PARTY_GUID party_guid, PartyMemberInfo user)
{
var result = new Result();
var owner = getOwner() as GlobalParty;
if (null == owner)
{
var err_msg = $"Fail to find global entity !!! : {nameof(GlobalParty)}";
result.setFail(ServerErrorCode.EntityBaseNotFound, err_msg );
Log.getLogger().error(err_msg);
return result;
}
var party = getGlobalPartyDetail(party_guid);
// 1. 없으면, Redis 에서 Load 하여 채워 넣음
if (null == party)
{
result = await loadParty(party_guid);
if (result.isFail()) return result;
party = getGlobalPartyDetail(party_guid);
}
NullReferenceCheckHelper.throwIfNull(party, () => $"GlobalDetailParty is null !! - party_guid:{party_guid}");
// 2. member 추가
var global_party_member_action = party.getEntityAction<GlobalPartyDetailMemberAction>();
NullReferenceCheckHelper.throwIfNull(global_party_member_action, () => $"GlobalPartyDetailMemberAction is null !! - party_guid:{party_guid}");
var add_member = await global_party_member_action.addJoinMember(user);
if (add_member.result.isFail()) return add_member.result;
// 3. Party p2p group host 전달 ( to client )
var party_action = party.getEntityAction<GlobalPartyDetailAction>();
NullReferenceCheckHelper.throwIfNull(party_action, () => $"global party detail action is null !!! - {party.toBasicString()}");
_ = await party_action.joinPartyP2PGroup(user.UserGuid);
_ = await party_action.checkPartyP2PState(user.UserGuid, true, true);
if (add_member.isAready == true) return add_member.result;
// 4. 파티 정보 전달
var send_party_members = new List<USER_GUID>();
var member_count = global_party_member_action.getMemberCount();
if (member_count == 2)
{
send_party_members.Add(party_action.getLeaderGuid());
}
send_party_members.Add(user.UserGuid);
await party_action.sendPartyInfo(send_party_members, party_action.getLeaderGuid(), false);
// 5. Party Instance 정보 전달
var party_instance_attribute = party.getEntityAttribute<PartyInstanceAttribute>();
NullReferenceCheckHelper.throwIfNull(party_instance_attribute, () => $"party instance attribute is null !!! - {party.toBasicString()}");
if (party_instance_attribute.InstanceId > 0)
{
party_action.sendPartyInstance(user.UserGuid);
}
return add_member.result;
}
public async Task<Result> leaveParty(PARTY_GUID party_guid, USER_GUID leave_user_guid, BoolType is_ban)
{
var result = new Result();
var global_party = getOwner() as GlobalParty;
NullReferenceCheckHelper.throwIfNull(global_party, () => $"global party is null !!! - party guid: {party_guid}");
var party = global_party.getParty(party_guid);
ArgumentNullException.ThrowIfNull(party);
// 1. 파티 멤버에서 삭제
var party_member_action = party.getEntityAction<GlobalPartyDetailMemberAction>();
NullReferenceCheckHelper.throwIfNull(party_member_action, () => $"GlobalPartyDetailMemberAction is null !! - party_guid:{party_guid}, {party.toBasicString()}");
var delete_party_member = await party_member_action.deleteJoinMember(leave_user_guid, true);
if (delete_party_member.result.isFail()) return delete_party_member.result;
// 2. p2p 그룹에서 제외
var party_action = party.getEntityAction<GlobalPartyDetailAction>();
ArgumentNullException.ThrowIfNull(party_action);
_ = party_action.leavePartyP2PGroup(leave_user_guid);
_ = party_action.checkPartyP2PState(leave_user_guid, false, false);
// 3. 파티 탈퇴 알림
notifyLeavePartyMember(party, leave_user_guid, is_ban);
// 4. 초대 메시지 발송 체크 : 초대 메시지에 응답하여 Party 가 결정될 수 있기 때문에 파티원이 1명이어도 Party 를 파괴시키지 않음
var invite_send_action = party.getEntityAction<GlobalPartyInvitePartySendAction>();
NullReferenceCheckHelper.throwIfNull(invite_send_action, () => $"global party invite party send action is null !!! - {party.toBasicString()}");
var sends = await invite_send_action.getInviteSendsCount();
if (sends > 0 && delete_party_member.party_member_count >= 1)
{
Log.getLogger().debug($"Not Destory Party: Send Invite Count - {sends}");
return result;
}
// 5. 파티원이 1명으로 파티 파괴
if (delete_party_member.party_member_count <= 1)
{
result = await destroyParty(party_guid, true);
}
// 6. party server 체크
else
{
result = await checkPartyServer(party, leave_user_guid);
}
return result;
}
public async Task<Result> destroyParty(PARTY_GUID party_guid, bool is_notify_to_servers)
{
var global_party = getOwner() as GlobalParty;
ArgumentNullException.ThrowIfNull(global_party);
var party = global_party.getParty(party_guid);
if (null == party) return new Result();
// 0. business log 준비
var party_log_data = PartyBusinessLogHelper.toPartyLogData(party_guid, false);
var party_business_log = new PartyBusinessLog(new LogActionEx(LogActionType.DestroyParty), party_log_data);
// 1. party info 제거
var party_info_action = party.getEntityAction<GlobalPartyDetailInfoAction>();
NullReferenceCheckHelper.throwIfNull(party_info_action, () => $"global party detail info action is null !!! - {party.toBasicString()}");
_ = await party_info_action.deleteParty();
// 2. party member 제거
var party_member_action = party.getEntityAction<GlobalPartyDetailMemberAction>();
NullReferenceCheckHelper.throwIfNull(party_member_action, () => $"global party detail member action is null !!! - {party.toBasicString()}");
var members = party_member_action.getMembers();
_ = await party_member_action.deletePartyMembers();
// 3. party server 제거
var party_server_action = party.getEntityAction<GlobalPartyDetailServerAction>();
NullReferenceCheckHelper.throwIfNull(party_server_action, () => $"global party detail server action is null !!! - {party.toBasicString()}");
var servers = party_server_action.getServers();
_ = await party_server_action.deleteAllPartyServers();
// 4. invite party send 제거
var party_invite_party_send_action = party.getEntityAction<GlobalPartyInvitePartySendAction>();
NullReferenceCheckHelper.throwIfNull(party_invite_party_send_action, () => $"global party invite party send action is null !!! - {party.toBasicString()}");
_ = await party_invite_party_send_action.deleteInvitePartySends();
// 5. instance 제거
var party_instance_action = party.getEntityAction<GlobalPartyDetailInstanceAction>();
NullReferenceCheckHelper.throwIfNull(party_instance_action, () => $"global party detail instance action is null !!! - {party.toBasicString()}");
_ = await party_instance_action.deletePartyInstance();
// 5. p2pgroup 제거
var party_action = party.getEntityAction<GlobalPartyDetailAction>();
NullReferenceCheckHelper.throwIfNull(party_action, () => $"global party detail action is null !!! - {party.toBasicString()}");
_ = party_action.destroyPartyP2PGroup();
// 6. member 들의 Party 정보 제거
await clearPersonalPartyWithMembers(members.ToList());
// 7. party 제거
m_parties.Remove(party_guid, out _);
// 8. Server 에 알림
if (is_notify_to_servers)
{
var server_message = new ServerMessage
{
NtfDestroyParty = new() { DestroyPartyGuid = party_guid }
};
PartyHelper.BroadcastToServers(servers.ToList(), server_message, true);
}
// 9. Client 에게 알림
var client_message = new ClientToGame
{
Message = new()
{
DestroyPartyNoti = new()
}
};
PartyHelper.BroadcastToClients(members.ToList(), client_message, new List<string>());
BusinessLogger.collectLog(party, party_business_log);
return new Result();
}
private void notifyLeavePartyMember(GlobalPartyDetail party, USER_GUID leave_user_guid, BoolType is_ban)
{
// 1. 파티원 탈퇴에 따른 알림 ( to server )
var server_message = new ServerMessage
{
LeavePartyMemberNoti = new()
{
IsBan = is_ban,
PartyGuid = party.PartyGuid,
LeavePartyUserGuid = leave_user_guid
}
};
PartyHelper.BroadcastToServers(party, server_message, true);
// 2. 파티원 탈퇴에 따른 알림 ( to client )
var client_message = new ClientToGame
{
Message = new()
{
LeavePartyMemberNoti = new()
{
IsBan = is_ban,
LeavePartyUserGuid = leave_user_guid
}
}
};
PartyHelper.BroadcastToClients(party, client_message, new List<string>());
}
public async Task<Result> checkPartyServer(GlobalPartyDetail party, USER_GUID leave_user_guid)
{
var result = new Result();
// 1. 서버 내 파티원 체크
var party_member_action = party.getEntityAction<GlobalPartyDetailMemberAction>();
NullReferenceCheckHelper.throwIfNull(party_member_action, () => $"GlobalPartyDetailMemberAction is null !!! - {party.toBasicString()}");
var exist_members_without_me = party_member_action.checkExistPartyMembers(leave_user_guid);
if (exist_members_without_me) return result;
// 2. 서버 정보 제거
var party_server_action = party.getEntityAction<GlobalPartyDetailServerAction>();
NullReferenceCheckHelper.throwIfNull(party_server_action, () => $"GlobalPartyDetailServerAction is null !!! - {party.toBasicString()}");
result = await party_server_action.deletePartyServer(GameServerApp.getServerLogic().getServerName());
if (result.isFail()) return result;
// 3. 서버 정보 제거 알림
result = await party_server_action.notifyChangePartyServerToServers(BoolType.False, GameServerApp.getServerLogic().getServerName());
// 4. 파티 정보 제거
m_parties.Remove(party.PartyGuid, out _);
return result;
}
private async Task clearPersonalPartyWithMembers(IReadOnlyList<USER_GUID> members)
{
var player_manager = GameServerApp.getServerLogic().getPlayerManager();
foreach (var user in members)
{
if (!player_manager.tryGetUserByPrimaryKey(user, out var member)) continue;
if (null == member) continue;
var personal_party_action = member.getEntityAction<PersonalPartyAction>();
if (null == personal_party_action) continue;
await personal_party_action.clearPersonalParty();
}
}
}

View File

@@ -0,0 +1,552 @@
using Google.Protobuf.WellKnownTypes;
using Nettention.Proud
;
using ServerCore;
using ServerBase;
using ServerCommon;
using ServerCommon.BusinessLogDomain;
using MetaAssets;
using USER_GUID = System.String;
namespace GameServer;
public class GlobalPartyDetailAction : EntityActionBase
{
public GlobalPartyDetailAction(GlobalPartyDetail owner) : base(owner)
{
}
public override async Task<Result> onInit()
{
await Task.CompletedTask;
var result = new Result();
return result;
}
public override void onClear()
{
return;
}
public async Task<Result> keepParty()
{
// 1. party keep
var party_action = getOwner().getEntityAction<GlobalPartyDetailInfoAction>();
NullReferenceCheckHelper.throwIfNull(party_action, () => $"GlobalPartyDetailInfoAction is null !!! - {getOwner().toBasicString()}");
await party_action.keep();
// 2. party member keep
var party_member_action = getOwner().getEntityAction<GlobalPartyDetailMemberAction>();
NullReferenceCheckHelper.throwIfNull(party_member_action, () => $"GlobalPartyDetailMemberAction is null !!! - {getOwner().toBasicString()}");
await party_member_action.keep();
// 3. party server keep
var party_server_action = getOwner().getEntityAction<GlobalPartyDetailServerAction>();
NullReferenceCheckHelper.throwIfNull(party_server_action, () => $"GlobalPartyDetailServerAction is null !!! - {getOwner().toBasicString()}");
await party_server_action.keep();
// 4. party invite send keep
var party_invite_send_action = getOwner().getEntityAction<GlobalPartyInvitePartySendAction>();
NullReferenceCheckHelper.throwIfNull(party_invite_send_action, () => $"GlobalPartyInvitePartySendAction is null !!! - {getOwner().toBasicString()}");
await party_invite_send_action.keep();
// 5. party instance keep
var party_instance_action = getOwner().getEntityAction<GlobalPartyDetailInstanceAction>();
NullReferenceCheckHelper.throwIfNull(party_instance_action, () => $"GlobalPartyDetailInstanceAction is null !!! - {getOwner().toBasicString()}");
await party_instance_action.keep();
return new Result();
}
public bool isLeader(USER_GUID user_guid)
{
var detail = getOwner() as GlobalPartyDetail;
NullReferenceCheckHelper.throwIfNull(detail, () => $"global party detail is null !!! - {getOwner().toBasicString()}");
var party_attribute = detail.getEntityAttribute<PartyAttribute>();
NullReferenceCheckHelper.throwIfNull(party_attribute, () => $"PartyAttribute is null !!! - user guid:{user_guid}, {detail.toBasicString()}");
return party_attribute.PartyLeaderCharGuid == user_guid;
}
public USER_GUID getLeaderGuid()
{
var detail = getOwner() as GlobalPartyDetail;
NullReferenceCheckHelper.throwIfNull(detail, () => $"global party detail is null !!! - {getOwner().toBasicString()}");
var party_attribute = detail.getEntityAttribute<PartyAttribute>();
NullReferenceCheckHelper.throwIfNull(party_attribute, () => $"PartyAttribute is null !!! - {detail.toBasicString()}");
return party_attribute.PartyLeaderCharGuid;
}
public string getLeaderNickname()
{
var detail = getOwner() as GlobalPartyDetail;
NullReferenceCheckHelper.throwIfNull(detail, () => $"global party detail is null !!! - {getOwner().toBasicString()}");
var party_attribute = detail.getEntityAttribute<PartyAttribute>();
NullReferenceCheckHelper.throwIfNull(party_attribute, () => $"PartyAttribute is null !!! - {detail.toBasicString()}");
return party_attribute.PartyLeaderNickname;
}
public async Task<(Result result, string change_leader_guid)> changePartyLeader()
{
var result = new Result();
var party = getOwner() as GlobalPartyDetail;
NullReferenceCheckHelper.throwIfNull(party, () => $"global party detail is null !!! - {getOwner().toBasicString()}");
var party_member_attribute = party.getEntityAttribute<PartyMemberAttribute>();
NullReferenceCheckHelper.throwIfNull(party_member_attribute, () => $"PartyMemberAttribute is null !! - party_guid:{party.PartyGuid}");
// 1. 파티장 자동 변경 ( 조건 1. jointime 이 가장 오래된 유저 )
var origin_leader_guid = getLeaderGuid();
var next_leader_guid = origin_leader_guid;
var join_time = DateTime.UtcNow.ToTimestamp();
foreach (var member in party_member_attribute.getPartyMembers())
{
if (origin_leader_guid == member.Value.UserGuid) continue;
if (join_time < member.Value.JoinTime) continue;
next_leader_guid = member.Value.UserGuid;
join_time = member.Value.JoinTime;
}
// 2. 파티장 변경 처리
var party_detail_info_action = party.getEntityAction<GlobalPartyDetailInfoAction>();
NullReferenceCheckHelper.throwIfNull(party_detail_info_action, () => $"GlobalPartyDetailInfoAction is null !! - party_guid:{party.PartyGuid}");
result = await party_detail_info_action.changePartyLeader(next_leader_guid, true);
// 3. 파티장 변경 알림
var message = new ServerMessage
{
ChangePartyLeaderNoti = new ServerMessage.Types.ChangePartyLeaderNoti()
{
PartyGuid = party.PartyGuid,
NewPartyLeaderGuid = next_leader_guid
}
};
PartyHelper.BroadcastToServers(party, message, false);
return (result, next_leader_guid);
}
public HostID getP2PHostId()
{
var party_attribute = getOwner().getEntityAttribute<PartyAttribute>();
ArgumentNullException.ThrowIfNull(party_attribute);
return party_attribute.P2PGroup;
}
public void sendPartyInstance(USER_GUID user_guid)
{
var result = new Result();
var party_instance_attribute = getOwner().getEntityAttribute<PartyInstanceAttribute>();
NullReferenceCheckHelper.throwIfNull(party_instance_attribute, () => $"PartyInstanceAttribute is null !! - {getOwner().toBasicString()}");
if (party_instance_attribute.InstanceId <= 0) {
return;
}
var client_message = new ClientToGame();
client_message.Message = new();
client_message.Message.PartyInstanceInfoNoti = new();
client_message.Message.PartyInstanceInfoNoti.InstanceId = party_instance_attribute.InstanceId;
client_message.Message.PartyInstanceInfoNoti.StartTime = party_instance_attribute.StartTime;
client_message.Message.PartyInstanceInfoNoti.EndTime = party_instance_attribute.EndTime;
client_message.Message.PartyInstanceInfoNoti.JoinMemberCount = party_instance_attribute.JoinMemberCount;
client_message.Message.PartyInstanceInfoNoti.IsEnd = party_instance_attribute.InstanceId == 0 ? BoolType.True : BoolType.False;
var player_manager = GameServerApp.getServerLogic().getPlayerManager();
if (! player_manager.tryGetUserByPrimaryKey(user_guid, out var user_entity) || null == user_entity)
{
var err_msg = $"Failed to send party instance !!! : not logged in server - {user_guid}";
result.setFail(ServerErrorCode.UserNotLogin,err_msg);
Log.getLogger().error(err_msg);
return;
}
PartyHelper.sendToClient(client_message, user_entity.getHostId());
}
public async Task<Result> sendPartyInfo(IReadOnlyList<USER_GUID> sendUsers, USER_GUID leaderGuid, bool exceptAnotherServer)
{
var party = getOwner() as GlobalPartyDetail;
NullReferenceCheckHelper.throwIfNull(party, () => $"party is null !!");
var party_info_action = party.getEntityAction<GlobalPartyDetailInfoAction>();
NullReferenceCheckHelper.throwIfNull(party_info_action, () => $"GlobalPartyDetailInfoAction is null !! - {party.toBasicString()}");
var party_member_action = party.getEntityAction<GlobalPartyDetailMemberAction>();
NullReferenceCheckHelper.throwIfNull(party_member_action, () => $"GlobalPartyDetailMemberAction is null !! - {party.toBasicString()}");
var player_manager = GameServerApp.getServerLogic().getPlayerManager();
foreach (var send in sendUsers)
{
if (player_manager.tryGetUserByPrimaryKey(send, out var player))
{
var client_message = new ClientToGame();
client_message.Message = new();
client_message.Message.JoinPartyInfoNoti = new();
client_message.Message.JoinPartyInfoNoti.PartyName = party_info_action.getPartyName();
client_message.Message.JoinPartyInfoNoti.PartyLeaderGuid = getLeaderGuid();
client_message.Message.JoinPartyInfoNoti.PartyLeaderNickname = getLeaderNickname();
client_message.Message.JoinPartyInfoNoti.PartyMemberList.AddRange(party_member_action.getMembers4PartyInfo().ToList());
if (leaderGuid != send)
{
client_message.Message.JoinPartyInfoNoti.ServerConnectInfo = await tryMoveToLeaderServer(leaderGuid, send);
}
if (null == player) continue;
PartyHelper.sendToClient(client_message, player.getHostId());
await QuestManager.It.QuestCheck(player, new QuestParty(EQuestEventTargetType.PARTY, EQuestEventNameType.ENTERED));
continue;
}
if (exceptAnotherServer) continue;
var server_message = new ServerMessage();
server_message.NtfPartyInfo = new();
server_message.NtfPartyInfo.PartyGuid = party.PartyGuid;
server_message.NtfPartyInfo.PartyMemberGuids.Add(send);
await PartyHelper.sendToServerByTargetClient(send, server_message);
}
return await Task.FromResult(new Result());
}
public async Task<Result> joinPartyP2PGroup(USER_GUID user_guid)
{
var result = new Result();
var player_manager = GameServerApp.getServerLogic().getPlayerManager();
if (! player_manager.tryGetUserByPrimaryKey(user_guid, out var user_entity))
{
var err_msg = $"Failed to join party p2p group !!! : not logged in server - {user_guid}";
result.setFail(ServerErrorCode.UserNotLogin,err_msg);
Log.getLogger().error(err_msg);
return result;
}
var p2p_group = getP2PHostId();
GameServerApp.getServerLogic().getProudNetListener().getNetServer().JoinP2PGroup(user_entity.getHostId(), p2p_group);
var client_message = new ClientToGame();
client_message.Message = new();
client_message.Message.PartyP2PGroupHostIdNoti = new();
client_message.Message.PartyP2PGroupHostIdNoti.PartyP2PGroupHostId = (int)p2p_group;
PartyHelper.sendToClient(client_message, user_entity.getHostId());
return await Task.FromResult(new Result());
}
public async Task<Result> checkPartyP2PState(USER_GUID userGuid, bool isJoin, bool includeSendingMe)
{
// 1. 타 유저에게 내 정보 전송
_ = await sendPartyP2PState(userGuid, isJoin);
if (!includeSendingMe) return await Task.FromResult(new Result());
// 2. 타 유저들의 정보를 내게 전송
var party = getOwner() as GlobalPartyDetail;
NullReferenceCheckHelper.throwIfNull(party, () => "GlobalPartyDetail is null");
var party_member_action = party.getEntityAction<GlobalPartyDetailMemberAction>();
NullReferenceCheckHelper.throwIfNull(party_member_action, () => $"GlobalPartyDetailMemberAction is null !! - {party.toBasicString()}");
var player_manager = GameServerApp.getServerLogic().getPlayerManager();
var client_message = new ClientToGame();
client_message.Message = new();
client_message.Message.PartyMemberP2PStateNoti = new();
var members = party_member_action.getMembers();
foreach (var member in members)
{
if (member == userGuid) continue;
client_message.Message.PartyMemberP2PStateNoti.MemberGuid = member;
client_message.Message.PartyMemberP2PStateNoti.IsP2P = player_manager.tryGetUserByPrimaryKey(member, out _) ? BoolType.True : BoolType.False;
PartyHelper.sendToClient(client_message, userGuid);
}
return await Task.FromResult(new Result());
}
private async Task<Result> sendPartyP2PState(USER_GUID userGuid, bool isJoin)
{
var client_message = new ClientToGame();
client_message.Message = new();
client_message.Message.PartyMemberP2PStateNoti = new();
client_message.Message.PartyMemberP2PStateNoti.MemberGuid = userGuid;
client_message.Message.PartyMemberP2PStateNoti.IsP2P = isJoin ? BoolType.True : BoolType.False;
var party = getOwner() as GlobalPartyDetail;
NullReferenceCheckHelper.throwIfNull(party, () => "GlobalPartyDetail is null");
PartyHelper.BroadcastToClients(party, client_message, new List<USER_GUID> { userGuid });
return await Task.FromResult(new Result());
}
public bool leavePartyP2PGroup(USER_GUID user_guid)
{
var player_manager = GameServerApp.getServerLogic().getPlayerManager();
if (player_manager.tryGetUserByPrimaryKey(user_guid, out var user))
{
return GameServerApp.getServerLogic().getProudNetListener().getNetServer().LeaveP2PGroup(user.getHostId(), getP2PHostId());
}
return false;
}
public bool destroyPartyP2PGroup()
{
var p2p_group = getP2PHostId();
return GameServerApp.getServerLogic().getProudNetListener().getNetServer().DestroyP2PGroup(p2p_group);
}
public async Task<Result> createPartyDetailInfo(string leader_guid, string leader_nickname)
{
var result = new Result();
var party = getOwner() as GlobalPartyDetail;
if (null == party)
{
var err_msg = $"Fail to get entity base : {nameof(GlobalPartyDetail)}";
result.setFail(ServerErrorCode.EntityBaseNotFound, err_msg);
Log.getLogger().error(err_msg);
return result;
}
// 1. party 정보 create
var party_info_action = party.getEntityAction<GlobalPartyDetailInfoAction>();
NullReferenceCheckHelper.throwIfNull(party_info_action, () => $"GlobalPartyDetailInfoAction is null !! - {party.toBasicString()}");
result = await party_info_action.createParty(leader_guid, leader_nickname);
if (result.isFail()) return result;
// 2. leader member 정보 설정
var party_member_action = party.getEntityAction<GlobalPartyDetailMemberAction>();
NullReferenceCheckHelper.throwIfNull(party_member_action, () => $"GlobalPartyDetailMemberAction is null !! - {party.toBasicString()}");
var change = await party_member_action.changeMember(PartyHelper.makePartyMember(leader_guid, leader_nickname));
if (change.result.isFail()) return result;
// 3. party server 정보 설정
var party_server_action = party.getEntityAction<GlobalPartyDetailServerAction>();
NullReferenceCheckHelper.throwIfNull(party_server_action, () => $"GlobalPartyDetailServerAction is null !! - {party.toBasicString()}");
result = await party_server_action.addPartyServer(GameServerApp.getServerLogic().getServerName());
if (result.isFail()) return result;
return result;
}
public async Task<Result> loadAllFromCache()
{
var result = new Result();
var party = getOwner() as GlobalPartyDetail;
ArgumentNullException.ThrowIfNull(party);
// 1. party 정보 Load
result = await loadPartyCache();
if (result.isFail()) return result;
// 2. party member 정보 Load
result = await loadPartyMemberCache();
if (result.isFail()) return result;
// 3. party server 정보 Load
result = await loadPartyServerCache();
if (result.isFail()) return result;
// 4. party invite send 정보 load
result = await loadPartyInvitePartySendCache();
if (result.isFail()) return result;
// 5. party instance 정보 load ( 없을 수 있으므로 result 무시 )
_ = await loadPartyInstanceCache();
return result;
}
public async Task<Result> loadPartyCache()
{
var party = getOwner() as GlobalPartyDetail;
NullReferenceCheckHelper.throwIfNull(party, () => "GlobalPartyDetail is null");
var party_info_action = party.getEntityAction<GlobalPartyDetailInfoAction>();
NullReferenceCheckHelper.throwIfNull(party_info_action, () => $"GlobalPartyDetailInfoAction is null !! - {party.toBasicString()}");
var result = await party_info_action.loadParty();
return result;
}
public async Task<Result> loadPartyMemberCache()
{
var party = getOwner() as GlobalPartyDetail;
NullReferenceCheckHelper.throwIfNull(party, () => "GlobalPartyDetail is null");
var party_member_action = party.getEntityAction<GlobalPartyDetailMemberAction>();
NullReferenceCheckHelper.throwIfNull(party_member_action, () => $"GlobalPartyDetailMemberAction is null !! - {party.toBasicString()}");
var result = await party_member_action.loadPartyMember();
return result;
}
private async Task<Result> loadPartyServerCache()
{
var party = getOwner() as GlobalPartyDetail;
NullReferenceCheckHelper.throwIfNull(party, () => "GlobalPartyDetail is null");
var party_server_action = party.getEntityAction<GlobalPartyDetailServerAction>();
NullReferenceCheckHelper.throwIfNull(party_server_action, () => $"GlobalPartyDetailServerAction is null !! - {party.toBasicString()}");
var result = await party_server_action.loadPartyServer();
return result;
}
private async Task<Result> loadPartyInvitePartySendCache()
{
var party = getOwner() as GlobalPartyDetail;
NullReferenceCheckHelper.throwIfNull(party, () => "GlobalPartyDetail is null");
var party_invite_party_send_action = party.getEntityAction<GlobalPartyInvitePartySendAction>();
NullReferenceCheckHelper.throwIfNull(party_invite_party_send_action, () => $"GlobalPartyInvitePartySendAction is null !! - {party.toBasicString()}");
var result = await party_invite_party_send_action.loadPartyInvitePartySend(party.PartyGuid);
return result;
}
private async Task<Result> loadPartyInstanceCache()
{
var party = getOwner() as GlobalPartyDetail;
NullReferenceCheckHelper.throwIfNull(party, () => "GlobalPartyDetail is null");
var party_instance_action = party.getEntityAction<GlobalPartyDetailInstanceAction>();
NullReferenceCheckHelper.throwIfNull(party_instance_action, () => $"GlobalPartyDetailInstanceAction is null !! - {party.toBasicString()}");
var result = await party_instance_action.loadPartyInstance();
return result;
}
private async Task<ServerConnectInfo?> tryMoveToLeaderServer(USER_GUID leaderGuid, USER_GUID userGuid)
{
var server_logic = GameServerApp.getServerLogic();
var result = new Result();
string err_msg;
// 1. party leader 세션 체크
var leader_login_cache = await PartyHelper.getOtherUserLoginCache(leaderGuid);
if (null == leader_login_cache)
{
err_msg = $"Failed to get party leader session !!! - {leaderGuid}";
result.setFail(ServerErrorCode.NotFoundParty, err_msg);
Log.getLogger().error(err_msg);
return null;
}
// 2. 조건 체크
if (false == await checkConditionLeaderServer(leader_login_cache.CurrentServer)) return null;
// 3. 서버 정보 조회
(result, var server_info) = await server_logic.getServerInfoByServerName(leader_login_cache.CurrentServer);
if (null == server_info) return null;
if (server_info.Sessions + server_info.Reservation + server_info.ReturnCount >= server_info.Capacity)
{
return null;
}
// 4. 예약 요청
var message = new ServerMessage.Types.GS2GS_REQ_RESERVATION_ENTER_TO_SERVER();
message.MoveType = ServerMoveType.Force;
message.RequestServerName = server_logic.getServerName();
message.RequestUserGuid = userGuid;
var reserved = await server_logic.getReservationManager().registerReservationEnterToServer(message, server_info.Name);
// 5. 예약 실패 체크
if (null == reserved)
{
err_msg = $"Failed to reservation enter to game server!!! - {server_info.Name}";
Log.getLogger().error(err_msg);
result.setFail(ServerErrorCode.FailedToReservationEnter, err_msg);
return null;
}
// 6. 이동 처리
var player_manager = server_logic.getPlayerManager();
if (!player_manager.tryGetUserByPrimaryKey(userGuid, out var player)) return null;
result = await player.runTransactionRunnerSafely(TransactionIdType.PrivateContents, "JoinParty", moveDelegate);
if (result.isFail())
{
Log.getLogger().error(result.toBasicString());
return null;
}
// 7. 이동 정보 체크
var account_attribute = player.getEntityAttribute<AccountAttribute>();
ArgumentNullException.ThrowIfNull(account_attribute);
var res = new ServerConnectInfo();
res.ServerAddr = account_attribute.ToConnectGameServerAddress.IP;
res.ServerPort = account_attribute.ToConnectGameServerAddress.Port;
res.Otp = account_attribute.OtpForServerConnect;
return res;
async Task<Result> moveDelegate() => await moveAsync(player, server_info);
}
private async Task<bool> checkConditionLeaderServer(string leaderServerName)
{
var server_logic = GameServerApp.getServerLogic();
(var result, var leader_server) = await server_logic.getServerInfoByServerName(leaderServerName);
if (null == leader_server) return false;
// 1. join user 가 channel 에 있는지 확인
if (server_logic.getServerType().toServerType() != ServerType.Channel) return false;
// 2. leader 와 동일한 channel 서버에 있는지 확인
if (leaderServerName == server_logic.getServerName()) return false;
// 3. leader 가 channel 에 있는지 확인
if (leaderServerName.toServerType() != ServerType.Channel) return false;
// 4. leader 와 동일한 world id 에 있는지 확인
if (server_logic.getWorldId() != leader_server.WorldId) return false;
return true;
}
private async Task<Result> moveAsync(Player player, ServerInfo serverInfo)
{
// 1. 파티 리더 위치로 이동 ( to Channel )
var result = await GameZoneMoveHelper.moveToAnotherChannel(player, serverInfo, null);
if (result.isFail()) return result;
var batch = new QueryBatchEx<QueryRunnerWithDocument>(player, LogActionType.None, GameServerApp.getServerLogic().getDynamoDbClient());
{
batch.addQuery(new DBQWriteToAttributeAllWithTransactionRunner());
batch.addQuery(new QueryFinal());
}
return await QueryHelper.sendQueryAndBusinessLog(batch);
}
}

View File

@@ -0,0 +1,399 @@
using Google.Protobuf;
using Google.Protobuf.WellKnownTypes;
using ServerCore;
using ServerBase;
using ServerCommon;
using ServerCommon.BusinessLogDomain;
using MetaAssets;
using USER_GUID = System.String;
namespace GameServer;
public class GlobalPartyDetailInfoAction : EntityActionBase
{
private readonly PartyCacheRequest m_party_cache_request;
private TaskCompletionSource m_vote_finish_task_source { get; set; } = new();
public GlobalPartyDetailInfoAction(GlobalPartyDetail owner) : base(owner)
{
m_party_cache_request =
new PartyCacheRequest(owner.PartyGuid, GameServerApp.getServerLogic().getRedisConnector());
}
public override async Task<Result> onInit() => await Task.FromResult(new Result());
public override void onClear()
{
return;
}
public async Task keep()
{
await m_party_cache_request.keepPartyCache();
}
public async Task<Result> loadParty()
{
var result = new Result();
var party_attribute = getOwner().getEntityAttribute<PartyAttribute>();
NullReferenceCheckHelper.throwIfNull(party_attribute, () => $"PartyAttribute is null !! - {getOwner().toBasicString()}");
result = await m_party_cache_request.fetchPartyCache();
if (result.isFail()) return result;
result = await ServerBase.DataCopyHelper.copyEntityAttributeFromCaches(party_attribute, new List<CacheBase> { m_party_cache_request.getPartyCache()! });
if (result.isFail())
{
Log.getLogger().error(result.toBasicString());
}
return result;
}
public async Task<Result> createParty(USER_GUID leader_guid, string leader_nickname)
{
var result = new Result();
var party_attribute = getOwner().getEntityAttribute<PartyAttribute>();
NullReferenceCheckHelper.throwIfNull(party_attribute, () => $"PartyAttribute is null !! - {getOwner().toBasicString()}");
// 1. cache 생성
result = await m_party_cache_request.createPartyCache(leader_guid, leader_nickname);
if (result.isFail()) return result;
// 2. attribute 복사
result = await ServerBase.DataCopyHelper.copyEntityAttributeFromCaches(party_attribute, new List<CacheBase> { m_party_cache_request.getPartyCache()! });
if (result.isFail())
{
Log.getLogger().error(result.toBasicString());
}
return result;
}
public async Task<Result> deleteParty()
{
// 1. cache 제거
var result = await m_party_cache_request.deletePartyCache();
if (result.isFail())
{
Log.getLogger().error(result.toBasicString());
}
// 2. attribute 제거
var party_attribute = getOwner().getEntityAttribute<PartyAttribute>();
NullReferenceCheckHelper.throwIfNull(party_attribute, () => $"PartyAttribute is null !! - {getOwner().toBasicString()}");
party_attribute.onClear();
return result;
}
public async Task<Result> changePartyLeader(USER_GUID next_leader_guid, bool is_upsert_cache)
{
var result = new Result();
// 1. attribute 수정
var party_attribute = getOwner().getEntityAttribute<PartyAttribute>();
NullReferenceCheckHelper.throwIfNull(party_attribute, () => $"PartyAttribute is null !! - {getOwner().toBasicString()}");
party_attribute.PartyLeaderCharGuid = next_leader_guid;
// 2. cache 수정
var party_cache = m_party_cache_request.getPartyCache();
NullReferenceCheckHelper.throwIfNull(party_cache, () => $"Party Cache is null !! - party name:{party_attribute.PartyName}");
party_cache.PartyLeaderCharGuid = next_leader_guid;
if(is_upsert_cache) result = await m_party_cache_request.upsertPartyCache();
return result;
}
public async Task<Result> changePartyName(string new_party_name, bool is_upsert_cache)
{
var result = new Result();
// 1. attribute 수정
var party_attribute = getOwner().getEntityAttribute<PartyAttribute>();
NullReferenceCheckHelper.throwIfNull(party_attribute, () => $"PartyAttribute is null !! - {getOwner().toBasicString()}");
party_attribute.PartyName = new_party_name;
// cache 수정
var party_cache = m_party_cache_request.getPartyCache();
NullReferenceCheckHelper.throwIfNull(party_cache, () => $"Party Cache is null !! - party name:{party_attribute.PartyName}");
party_cache.PartyName = new_party_name;
if(is_upsert_cache) result = await m_party_cache_request.upsertPartyCache();
return result;
}
public string getPartyName()
{
var party_attribute = getOwner().getEntityAttribute<PartyAttribute>();
NullReferenceCheckHelper.throwIfNull(party_attribute, () => $"PartyAttribute is null !! - {getOwner().toBasicString()}");
return party_attribute.PartyName;
}
public async Task<Result> VoteParty(VoteType vote, USER_GUID voter_guid)
{
var result = new Result();
string err_msg;
var party = getOwner() as GlobalPartyDetail;
NullReferenceCheckHelper.throwIfNull(party, () => $"global party detail is null !!");
var party_attribute = party.getEntityAttribute<PartyAttribute>();
NullReferenceCheckHelper.throwIfNull(party_attribute, () => $"PartyAttribute is null !! - {getOwner().toBasicString()}");
// 1. 진행 중인 Vote 확인
if (null == party_attribute.PartyVote)
{
err_msg = $"Failed to reply party vote !!! - not start party vote - {party.PartyGuid}";
result.setFail(ServerErrorCode.NoStartPartyVote, err_msg);
Log.getLogger().error(err_msg);
return result;
}
// 2. 투표 허용 시간 확인
var allow_vote_time = DateTime.UtcNow.AddSeconds(-1 * MetaHelper.GameConfigMeta.VoteTimeLimitSec + 5 );
if (party_attribute.PartyVote.StartVoteTime < allow_vote_time.ToTimestamp())
{
err_msg = $"Failed to reply party vote !!! - already passed party vote time - {party.PartyGuid}";
result.setFail(ServerErrorCode.AlreadyPassPartyVoteTime, err_msg);
Log.getLogger().error(err_msg);
return result;
}
// 3. 기 투표 여부 체크
if (party_attribute.PartyVote.Votes.TryGetValue(voter_guid, out var saved_vote) && saved_vote != VoteType.None)
{
err_msg = $"Failed to reply party vote !!! - already reply party vote - {voter_guid}";
result.setFail(ServerErrorCode.AlreadyReplyPartyVote, err_msg);
Log.getLogger().error(err_msg);
return result;
}
party_attribute.PartyVote.Votes[voter_guid] = vote;
// 4. 투표 종료 체크 ( party leader 가 있는 서버만 )
var player_message = GameServerApp.getServerLogic().getPlayerManager();
if (player_message.tryGetUserByPrimaryKey(party_attribute.PartyLeaderCharGuid, out _))
{
var is_finished = party_attribute.PartyVote.Votes.All(voted_type => voted_type.Value != VoteType.None);
if (is_finished) m_vote_finish_task_source.TrySetResult();
return result;
}
var message = new ServerMessage();
message.ReplyPartyVoteNoti = new();
message.ReplyPartyVoteNoti.PartyGuid = party.PartyGuid;
message.ReplyPartyVoteNoti.PartyVoterGuid = voter_guid;
message.ReplyPartyVoteNoti.Vote = vote;
await PartyHelper.sendToServerByTargetClient(party_attribute.PartyLeaderCharGuid, message);
return result;
}
public PartyVoteInfo? getPartyVoteInfo()
{
var party = getOwner() as GlobalPartyDetail;
NullReferenceCheckHelper.throwIfNull(party, () => $"global party detail is null !!");
var party_attribute = party.getEntityAttribute<PartyAttribute>();
NullReferenceCheckHelper.throwIfNull(party_attribute, () => $"PartyAttribute is null !! - {getOwner().toBasicString()}");
return party_attribute.PartyVote;
}
public async Task<(Result result, PartyVoteInfo? vote)> registerPartyVote(string vote_title, Timestamp start_vote_time, bool is_start)
{
var result = new Result();
var party = getOwner() as GlobalPartyDetail;
NullReferenceCheckHelper.throwIfNull(party, () => $"global party detail is null !!");
var party_attribute = party.getEntityAttribute<PartyAttribute>();
NullReferenceCheckHelper.throwIfNull(party_attribute, () => $"PartyAttribute is null !! - {party.toBasicString()}");
var party_member_action = party.getEntityAction<GlobalPartyDetailMemberAction>();
NullReferenceCheckHelper.throwIfNull(party_member_action, () => $"GlobalPartyDetailMemberAction is null !! - {party.toBasicString()}");
// 1. vote condition 체크
result = await checkVoteCondition(party, vote_title);
if (result.isFail()) return (result, null);
// 2. vote 정보 저장 : 시작시점의 유저 리스트 등록 - 추가(제외) / 감소(기권)
var members = party_member_action.getMembers();
var vote = new PartyVoteInfo
{
VoteTitle = vote_title,
StartVoteTime = start_vote_time
};
foreach (var member in members)
{
vote.Votes.Add(member, VoteType.None);
}
party_attribute.PartyVote = vote;
// 3. cache 저장
var cache = m_party_cache_request.getPartyCache();
NullReferenceCheckHelper.throwIfNull(cache, () => $"Party Cache is null !! - party name:{party_attribute.PartyName} / {party.toBasicString()}");
cache.LastVoteTime = start_vote_time;
party_attribute.LastVoteTime = start_vote_time;
if (is_start)
{
result = await m_party_cache_request.upsertPartyCache();
if (result.isFail())
{
party_attribute.PartyVote = null;
return (result, null);
}
// 4. Wait Vote Task 실행 ( fire and forget )
_ = Task.Run(waitPartyVoteFinish);
}
return (result, vote);
}
private async Task<Result> checkVoteCondition(GlobalPartyDetail party, string vote_title)
{
var result = new Result();
string err_msg;
var party_attribute = party.getEntityAttribute<PartyAttribute>();
NullReferenceCheckHelper.throwIfNull(party_attribute, () => $"PartyAttribute is null !! - {party.toBasicString()}");
// 1. vote title 길이 체크
if (vote_title.Length > MetaHelper.GameConfigMeta.MaxVoteAgendaInput)
{
err_msg = $"fail to start party vote !!! : invalid vote title length - {vote_title.Length}";
result.setFail(ServerErrorCode.InvalidPartyStringLength, err_msg);
Log.getLogger().error(err_msg);
return result;
}
// 2. 진행 중인 Vote 체크
if (null != party_attribute.PartyVote)
{
err_msg = $"Failed to start party vote !!! : exist party vote - {party_attribute.PartyVote.VoteTitle}";
result.setFail(ServerErrorCode.AlreadyStartPartyVote, err_msg);
Log.getLogger().error(err_msg);
return result;
}
// 3. Last Vote Time 체크
var last_vote_time = party_attribute.LastVoteTime ?? DateTimeHelper.MinTime.ToTimestamp();
if (last_vote_time > DateTime.UtcNow.AddSeconds(-1 * MetaHelper.GameConfigMeta.VoteCoolTimeSec).ToTimestamp())
{
err_msg = $"Failed to start party vote !!! : invalid party vote time - {vote_title}";
result.setFail(ServerErrorCode.InvalidPartyVoteTime, err_msg);
Log.getLogger().error(err_msg);
return result;
}
return await Task.FromResult(result);
}
private async Task waitPartyVoteFinish()
{
var cts = new CancellationTokenSource(TimeSpan.FromSeconds(MetaHelper.GameConfigMeta.VoteTimeLimitSec + 1));
m_vote_finish_task_source = new();
cts.Token.Register(() => { m_vote_finish_task_source.TrySetCanceled(); });
try
{
await m_vote_finish_task_source.Task;
}
catch (OperationCanceledException)
{
// Ignore...
}
catch (Exception e)
{
Log.getLogger().error($"Failed to wait party vote !!! : exception finish task - {e}");
return;
}
// 1. 파티 정보 획득
var party = getOwner() as GlobalPartyDetail;
NullReferenceCheckHelper.throwIfNull(party, () => $"global party detail is null !!");
// 2. 투표 결과 수집
var party_attribute = party.getEntityAttribute<PartyAttribute>();
NullReferenceCheckHelper.throwIfNull(party_attribute, () => $"PartyAttribute is null !! - {party.toBasicString()}");
// 3. 결과 수집
var agreement = party_attribute.getVoteCount(VoteType.Agreement);
var disAgreement = party_attribute.getVoteCount(VoteType.DisAgreement);
var abstain = party_attribute.getVoteCount(VoteType.Abstain);
abstain += party_attribute.getVoteCount(VoteType.None);
// 4. 결과 통보 ( to server )
var server_message = new ServerMessage();
server_message.PartyVoteResultNoti = new();
server_message.PartyVoteResultNoti.PartyGuid = party.PartyGuid;
server_message.PartyVoteResultNoti.VoteTitle = party_attribute.PartyVote?.VoteTitle ?? string.Empty;
server_message.PartyVoteResultNoti.ResultTrue = agreement;
server_message.PartyVoteResultNoti.ResultFalse = disAgreement;
server_message.PartyVoteResultNoti.Abstain = abstain;
PartyHelper.BroadcastToServers(party, server_message, true);
// 4. 결과 통보 ( to client )
var client_message = new ClientToGame();
client_message.Message = new();
client_message.Message.PartyVoteResultNoti = new();
client_message.Message.PartyVoteResultNoti.VoteTitle = party_attribute.PartyVote?.VoteTitle ?? string.Empty;
client_message.Message.PartyVoteResultNoti.ResultTrue = agreement;
client_message.Message.PartyVoteResultNoti.ResultFalse = disAgreement;
client_message.Message.PartyVoteResultNoti.Abstain = abstain;
PartyHelper.BroadcastToClients(party, client_message, new List<string>());
// 5. Business Log 기록
writeBusinessLog(party);
// 6. 투표 데이터 삭제
party_attribute.PartyVote = null;
}
private void writeBusinessLog(GlobalPartyDetail party)
{
var log_invokers = new List<ILogInvoker>(2);
// 1. 파티정보
var party_log_data = PartyBusinessLogHelper.toPartyLogData(party.PartyGuid, false);
var party_business_log = new PartyBusinessLog(party_log_data);
log_invokers.Add(party_business_log);
// 2. 파티 투표 정보
var party_vote_log = PartyBusinessLogHelper.toPartyVoteLogData(party.PartyGuid, false);
var party_vote_business_log = new PartyVoteBusinessLog(party_vote_log);
log_invokers.Add(party_vote_business_log);
BusinessLogger.collectLogs(new LogActionEx(LogActionType.EndPartyVote), party, log_invokers);
}
}

View File

@@ -0,0 +1,239 @@
using Google.Protobuf;
using Google.Protobuf.WellKnownTypes;
using ServerCore;
using ServerBase;
using ServerCommon;
using ServerCommon.BusinessLogDomain;
using MetaAssets;
namespace GameServer;
public class GlobalPartyDetailInstanceAction : EntityActionBase
{
private readonly PartyInstanceCacheRequest m_party_instance_cache_request;
public GlobalPartyDetailInstanceAction(GlobalPartyDetail owner) : base(owner)
{
m_party_instance_cache_request =
new PartyInstanceCacheRequest(owner.PartyGuid, GameServerApp.getServerLogic().getRedisConnector());
}
public override async Task<Result> onInit()
{
await Task.CompletedTask;
var result = new Result();
return result;
}
public override void onClear()
{
return;
}
public async Task<Result> keep()
{
return await m_party_instance_cache_request.keepPartyInstanceCache();
}
public async Task<Result> loadPartyInstance()
{
var attribute = getOwner().getEntityAttribute<PartyInstanceAttribute>();
NullReferenceCheckHelper.throwIfNull(attribute, () => $"PartyInstanceAttribute is null !! - {getOwner().toBasicString()}");
var result = await m_party_instance_cache_request.fetchPartyInstanceCache();
if (result.isFail()) return result;
result = await ServerBase.DataCopyHelper.copyEntityAttributeFromCaches(attribute,
new List<CacheBase> { m_party_instance_cache_request.getPartyInstanceCache()! });
if (result.isFail())
{
Log.getLogger().error(result.toBasicString());
}
return result;
}
public async Task<Result> registerPartyInstance(int instanceId, string roomId, Timestamp startTime, Timestamp endTime, int joinCount, bool isNotify)
{
var result = new Result();
var party = getOwner() as GlobalPartyDetail;
NullReferenceCheckHelper.throwIfNull(party, () => "global party detail is null !!!");
var party_instance_attribute = getOwner().getEntityAttribute<PartyInstanceAttribute>();
NullReferenceCheckHelper.throwIfNull(party_instance_attribute, () => $"PartyInstanceAttribute is null !! - {party.toBasicString()}");
// 1. cache 생성
result = await m_party_instance_cache_request.createPartyInstanceCache(instanceId, roomId, startTime, endTime, joinCount);
if (result.isFail()) return result;
// 2. attribute 복사
result = await ServerBase.DataCopyHelper.copyEntityAttributeFromCaches(party_instance_attribute,
new List<CacheBase> { m_party_instance_cache_request.getPartyInstanceCache()! });
if (result.isFail())
{
Log.getLogger().error(result.toBasicString());
}
if (false == isNotify) return result;
// 8. instance 정보 알림 ( to Servers )
var server_message = new ServerMessage();
server_message.PartyInstanceInfoNoti = new();
server_message.PartyInstanceInfoNoti.PartyGuid = party.PartyGuid;
PartyHelper.BroadcastToServers(party, server_message, true);
// 9. instance 정보 알림 ( to Clients )
var client_message = new ClientToGame();
client_message.Message = new();
client_message.Message.PartyInstanceInfoNoti = new();
client_message.Message.PartyInstanceInfoNoti.InstanceId = instanceId;
client_message.Message.PartyInstanceInfoNoti.StartTime = startTime;
client_message.Message.PartyInstanceInfoNoti.EndTime = endTime;
client_message.Message.PartyInstanceInfoNoti.JoinMemberCount = joinCount;
client_message.Message.PartyInstanceInfoNoti.IsEnd = BoolType.False;
PartyHelper.BroadcastToClients(party, client_message, new List<string>());
return result;
}
public async Task<Result> deletePartyInstance()
{
// 1. cache 제거
var result = await m_party_instance_cache_request.deletePartyInstanceCache();
if (result.isFail())
{
Log.getLogger().error(result.toBasicString());
}
// 2. attribute 제거
var attribute = getOwner().getEntityAttribute<PartyInstanceAttribute>();
NullReferenceCheckHelper.throwIfNull(attribute, () => $"PartyInstanceAttribute is null !! - {getOwner().toBasicString()}");
attribute.onClear();
return result;
}
public bool isExist()
{
var attribute = getOwner().getEntityAttribute<PartyInstanceAttribute>();
NullReferenceCheckHelper.throwIfNull(attribute, () => $"PartyInstanceAttribute is null !! - {getOwner().toBasicString()}");
return attribute.InstanceId > 0;
}
public Timestamp getStartTime()
{
var attribute = getOwner().getEntityAttribute<PartyInstanceAttribute>();
NullReferenceCheckHelper.throwIfNull(attribute, () => $"PartyInstanceAttribute is null !! - {getOwner().toBasicString()}");
return attribute.StartTime;
}
public async Task<Result> finishPartyInstance(int joinCount = 0)
{
return await changePartyInstance(DateTimeHelper.MinTime.ToTimestamp(), DateTimeHelper.MinTime.ToTimestamp(), joinCount, true, true);
}
public async Task<Result> changePartyInstance(Timestamp startTime, Timestamp endTime, int joinCount, bool isFinish, bool notifyStartInstance)
{
var result = new Result();
// 1. cache 수정
var cache = m_party_instance_cache_request.getPartyInstanceCache();
NullReferenceCheckHelper.throwIfNull(cache, () => $"Party Instance Cache is null !!! - {getOwner().toBasicString()}");
cache.JoinMemberCount = joinCount;
cache.StartTime = startTime;
cache.EndTime = endTime;
if (isFinish)
{
cache.InstanceId = 0;
cache.RoomId = string.Empty;
}
result = await m_party_instance_cache_request.upsertPartyInstanceCache();
if (result.isFail()) return result;
// 2. attribute 수정
var attribute = getOwner().getEntityAttribute<PartyInstanceAttribute>();
NullReferenceCheckHelper.throwIfNull(attribute, () => $"PartyInstanceAttribute is null !! - {getOwner().toBasicString()}");
attribute.JoinMemberCount = cache.JoinMemberCount;
attribute.StartTime = startTime;
attribute.EndTime = endTime;
if (isFinish)
{
attribute.InstanceId = 0;
attribute.RoomId = string.Empty;
}
if (notifyStartInstance)
{
sendPartyInstanceInfoToMembers();
}
return result;
}
public async Task changeJoinMemberCount(int joinCount, bool notify)
{
// 1. cache 수정
var cache = m_party_instance_cache_request.getPartyInstanceCache();
NullReferenceCheckHelper.throwIfNull(cache, () => $"Party Instance Cache is null !!! - {getOwner().toBasicString()}");
cache.JoinMemberCount = joinCount;
await m_party_instance_cache_request.upsertPartyInstanceCache();
// 2. attribute 수정
var attribute = getOwner().getEntityAttribute<PartyInstanceAttribute>();
NullReferenceCheckHelper.throwIfNull(attribute, () => $"PartyInstanceAttribute is null !! - {getOwner().toBasicString()}");
attribute.JoinMemberCount = cache.JoinMemberCount;
if (notify)
{
sendPartyInstanceInfoToMembers();
}
}
private void sendPartyInstanceInfoToMembers()
{
// 1. server message
var party = getOwner() as GlobalPartyDetail;
NullReferenceCheckHelper.throwIfNull(party, () => "Party Detail is null");
var attribute = getOwner().getEntityAttribute<PartyInstanceAttribute>();
NullReferenceCheckHelper.throwIfNull(attribute, () => $"PartyInstanceAttribute is null !! - {party.toBasicString()}");
var server_message = new ServerMessage();
server_message.PartyInstanceInfoNoti = new();
server_message.PartyInstanceInfoNoti.PartyGuid = party.PartyGuid;
PartyHelper.BroadcastToServers(party, server_message, true);
// 2. client message
var client_message = new ClientToGame();
client_message.Message = new();
client_message.Message.PartyInstanceInfoNoti = new();
client_message.Message.PartyInstanceInfoNoti.InstanceId = attribute.InstanceId;
client_message.Message.PartyInstanceInfoNoti.JoinMemberCount = attribute.JoinMemberCount;
client_message.Message.PartyInstanceInfoNoti.StartTime = attribute.StartTime;
client_message.Message.PartyInstanceInfoNoti.EndTime = attribute.EndTime;
client_message.Message.PartyInstanceInfoNoti.IsEnd = attribute.InstanceId == 0 ? BoolType.True : BoolType.False;
PartyHelper.BroadcastToClients(party, client_message, new List<string>());
}
}

View File

@@ -0,0 +1,548 @@
using Google.Protobuf;
using Google.Protobuf.WellKnownTypes;
using Newtonsoft.Json;
using ServerCore;
using ServerBase;
using ServerCommon;
using ServerCommon.BusinessLogDomain;
using MetaAssets;
using USER_GUID = System.String;
namespace GameServer;
public class GlobalPartyDetailMemberAction : EntityActionBase
{
private readonly PartyMemberCacheRequest m_party_member_cache_request;
public GlobalPartyDetailMemberAction(GlobalPartyDetail owner) : base(owner)
{
m_party_member_cache_request =
new PartyMemberCacheRequest(owner.PartyGuid, GameServerApp.getServerLogic().getRedisConnector());
}
public override async Task<Result> onInit()
{
await Task.CompletedTask;
var result = new Result();
return result;
}
public override void onClear()
{
}
public async Task<Result> keep()
{
return await m_party_member_cache_request.keepPartyMemberCache();
}
public PartyMemberInfo? getMember(USER_GUID user_guid)
{
var party_member_attribute = getOwner().getEntityAttribute<PartyMemberAttribute>();
NullReferenceCheckHelper.throwIfNull(party_member_attribute, () => $"PartyMemberAttribute is null !! - {getOwner().toBasicString()}");
return party_member_attribute.getPartyMembers().GetValueOrDefault(user_guid);
}
public IEnumerable<USER_GUID> getMembers()
{
var party_member_attribute = getOwner().getEntityAttribute<PartyMemberAttribute>();
NullReferenceCheckHelper.throwIfNull(party_member_attribute, () => $"PartyMemberAttribute is null !! - {getOwner().toBasicString()}");
return party_member_attribute.getPartyMembers().Select(member => member.Key).ToList();
}
public bool isPartyMember(USER_GUID user_guid)
{
var attribute = getOwner().getEntityAttribute<PartyMemberAttribute>();
NullReferenceCheckHelper.throwIfNull(attribute, () => $"PartyMemberAttribute is null !! - {getOwner().toBasicString()}");
var member = attribute.getPartyMember(user_guid);
return null != member;
}
public int getMemberCount()
{
var party_member_attribute = getOwner().getEntityAttribute<PartyMemberAttribute>();
NullReferenceCheckHelper.throwIfNull(party_member_attribute, () => $"PartyMemberAttribute is null !! - {getOwner().toBasicString()}");
return party_member_attribute.getPartyMembers().Count;
}
public bool checkExistPartyMembers(USER_GUID except_member_user)
{
var attribute = getOwner().getEntityAttribute<PartyMemberAttribute>();
NullReferenceCheckHelper.throwIfNull(attribute, () => $"PartyMemberAttribute is null !! - {getOwner().toBasicString()}");
var player_manager = GameServerApp.getServerLogic().getPlayerManager();
foreach (var member in attribute.getPartyMembers())
{
if (member.Key == except_member_user) continue;
if (false == player_manager.tryGetUserByPrimaryKey(member.Key, out var player)) continue;
return true;
}
return false;
}
public async Task<Result> loadPartyMember()
{
var party_member_attribute = getOwner().getEntityAttribute<PartyMemberAttribute>();
NullReferenceCheckHelper.throwIfNull(party_member_attribute, () => $"PartyMemberAttribute is null !! - {getOwner().toBasicString()}");
var result = await m_party_member_cache_request.fetchPartyMemberCache();
if (result.isFail()) return result;
result = await ServerBase.DataCopyHelper.copyEntityAttributeFromCaches(party_member_attribute, new List<CacheBase> { m_party_member_cache_request.getPartyMemberCache()! });
if (result.isFail())
{
Log.getLogger().error(result.toBasicString());
}
return result;
}
public IEnumerable<PartyMemberState> getMembers4PartyInfo()
{
var party = getOwner() as GlobalPartyDetail;
NullReferenceCheckHelper.throwIfNull(party, () => $"global party detail is null !!");
var party_member_attribute = party.getEntityAttribute<PartyMemberAttribute>();
NullReferenceCheckHelper.throwIfNull(party_member_attribute, () => $"PartyMemberAttribute is null !! - {party.toBasicString()}");
var states = new List<PartyMemberState>();
foreach (var member in party_member_attribute.getPartyMembers())
{
var state = new PartyMemberState();
state.MemberGuid = member.Value.UserGuid;
state.MemberNickname = member.Value.Nickname;
state.MarkId = member.Value.MarkId;
state.LocationInfo = member.Value.LocationInfo;
states.Add(state);
}
return states;
}
public async Task<(Result result, bool? isAready)> addJoinMember(PartyMemberInfo user)
{
var change = await changeMember(user);
if (change.result.isFail()) return (change.result, null);
// 0. 데이터가 없으면, 기존 참가 인원으로 위치변경만 노티
if (null == change.info)
{
sendPartyMemberLocation(user);
return (change.result, true);
}
var party = getOwner() as GlobalPartyDetail;
ArgumentNullException.ThrowIfNull(party);
// 1. 파티 참가 멤버 알림 ( to server )
var server_message = new ServerMessage
{
JoinPartyMemberNoti = new()
{
PartyGuid = party.PartyGuid,
JoinPartyMemberInfo = JsonConvert.SerializeObject(change.info)
}
};
PartyHelper.BroadcastToServers(party, server_message, true);
// 2. 파티 참가 멤버 알림 ( to client )
var client_message = new ClientToGame();
client_message.Message = new();
client_message.Message.JoinPartyMemberNoti = new();
client_message.Message.JoinPartyMemberNoti.JoinPartyMemberGuid = change.info.UserGuid;
client_message.Message.JoinPartyMemberNoti.JoinMemberInfo = new PartyMemberState();
client_message.Message.JoinPartyMemberNoti.JoinMemberInfo.MarkId = change.info.MarkId;
client_message.Message.JoinPartyMemberNoti.JoinMemberInfo.MemberGuid = change.info.UserGuid;
client_message.Message.JoinPartyMemberNoti.JoinMemberInfo.MemberNickname = change.info.Nickname;
client_message.Message.JoinPartyMemberNoti.JoinMemberInfo.LocationInfo = change.info.LocationInfo;
PartyHelper.BroadcastToClients(party, client_message, new List<string> { user.UserGuid });
return (change.result, false);
}
public async Task<Result> deletePartyMembers()
{
// 1. cache 제거
var result = await m_party_member_cache_request.deletePartyMemberCache();
if (result.isFail())
{
Log.getLogger().error(result.toBasicString());
}
// 2. attribute 수정
var party_member_attribute = getOwner().getEntityAttribute<PartyMemberAttribute>();
NullReferenceCheckHelper.throwIfNull(party_member_attribute, () => $"PartyMemberAttribute is null !! - {getOwner().toBasicString()}");
party_member_attribute.onClear();
return result;
}
public async Task<(Result result, int party_member_count)> deleteJoinMember(USER_GUID delete_user_guid, bool is_upsert_cache)
{
var result = new Result();
var party = getOwner() as GlobalPartyDetail;
NullReferenceCheckHelper.throwIfNull(party, () => $"global party detail is null !!");
// 1. attribute 수정
var party_member_attribute = getOwner().getEntityAttribute<PartyMemberAttribute>();
NullReferenceCheckHelper.throwIfNull(party_member_attribute, () => $"PartyMemberAttribute is null !! - {party.toBasicString()}");
if (!party_member_attribute.deletePartyMember(delete_user_guid))
{
var err_msg = $"Failed to delete party memeber !!! : {delete_user_guid}";
result.setFail(ServerErrorCode.NotPartyMember, err_msg);
Log.getLogger().error(err_msg);
return (result, party_member_attribute.getPartyMembers().Count);
}
// 2. cache 수정
var member_cache = m_party_member_cache_request.getPartyMemberCache();
NullReferenceCheckHelper.throwIfNull(member_cache, () => $"member cache is null !!! - user_guid:{delete_user_guid}");
member_cache.deleteJoinMember(delete_user_guid);
if(is_upsert_cache) result = await m_party_member_cache_request.deleteJoinMember(delete_user_guid);
return (result, party_member_attribute.getPartyMembers().Count);
}
public async Task<Result> changeMemberMaker(USER_GUID user_guid, int new_marker_id, bool is_cash_upsert)
{
var result = new Result();
string err_msg;
var party_member_attribute = getOwner().getEntityAttribute<PartyMemberAttribute>();
NullReferenceCheckHelper.throwIfNull(party_member_attribute, () => $"PartyMemberAttribute is null !! - {getOwner().toBasicString()}");
var exist_user = party_member_attribute.getPartyMember(user_guid);
if (null == exist_user)
{
err_msg = $"Failed to get party member !!! : not party member - {user_guid}";
result.setFail(ServerErrorCode.NotPartyMember, err_msg);
Log.getLogger().error(err_msg);
return result;
}
// 1. cache 수정
var member_cache = m_party_member_cache_request.getPartyMemberCache();
NullReferenceCheckHelper.throwIfNull(member_cache, () => $"member cache is null !!! - userGuid:{user_guid}");
if (!member_cache.PartyMembers.TryGetValue(user_guid, out var member))
{
err_msg = $"Failed to get party member !!! : not party member - {user_guid}";
result.setFail(ServerErrorCode.NotPartyMember, err_msg);
Log.getLogger().error(err_msg);
return result;
}
member.MarkId = new_marker_id;
if (is_cash_upsert)
{
result = await m_party_member_cache_request.changeJoinMember(member);
if (result.isFail()) return result;
}
// 2. attribute 수정
exist_user.MarkId = new_marker_id;
return result;
}
public async Task<(Result result, PartyMemberInfo? info)> changeMember(PartyMemberInfo user)
{
var party_member_attribute = getOwner().getEntityAttribute<PartyMemberAttribute>();
NullReferenceCheckHelper.throwIfNull(party_member_attribute, () => $"PartyMemberAttribute is null !! - {getOwner().toBasicString()}");
var exist_user = party_member_attribute.getPartyMember(user.UserGuid);
if (null != exist_user)
{
user.MarkId = exist_user.MarkId;
user.JoinTime = exist_user.JoinTime;
}
// 1. cache 수정
var result = await m_party_member_cache_request.changeJoinMember(user);
if (result.isFail()) return (result, null);
// 2. attribute 데이터 수정
party_member_attribute.setPartyMember(user);
// 3. exist_user 가 있으면, 기존 참가 유저
return null != exist_user ? (result, null) : (result, user);
}
public IEnumerable<string> getSummonMembers()
{
var member_attribute = getOwner().getEntityAttribute<PartyMemberAttribute>();
NullReferenceCheckHelper.throwIfNull(member_attribute, () => $"PartyMemberAttribute is null !! - {getOwner().toBasicString()}");
return (from member in member_attribute.getPartyMembers()
where member.Value.Summon.IsAlreadySummon select member.Key).ToList();
}
public async Task<(Result result, Item? delete_item)> summonMemberAsync(USER_GUID summon_user_guid, SummonInfo summon)
{
var result = new Result();
string err_msg;
var party = getOwner() as GlobalPartyDetail;
NullReferenceCheckHelper.throwIfNull(party, () => $"global party detail is null !! ");
var member_attribute = getOwner().getEntityAttribute<PartyMemberAttribute>();
NullReferenceCheckHelper.throwIfNull(member_attribute, () => $"PartyMemberAttribute is null !! - {getOwner().toBasicString()}");
// 1. summon user login_cache 조회
var server_logic = GameServerApp.getServerLogic();
var summon_user_login_cache_request =
new LoginCacheOtherUserRequest(server_logic, server_logic.getRedisConnector(), summon_user_guid);
result = await summon_user_login_cache_request.fetchLogin();
if (result.isFail()) return (result, null);
var summon_user_login_cache = summon_user_login_cache_request.getLoginCache();
if (null == summon_user_login_cache)
{
err_msg = $"Failed to summon party member !!! : summon user not logged in - {summon_user_guid}";
result.setFail(ServerErrorCode.UserNotLogin, err_msg);
Log.getLogger().error(err_msg);
return (result, null);
}
var player_manager = server_logic.getPlayerManager();
// 2. 소환석 제거
var summon_result = await spentSummonItemAsync(player_manager, party);
if (summon_result.result.isFail()) return (summon_result.result, null);
// 3. summon 수정
var member = member_attribute.getPartyMember(summon_user_guid);
NullReferenceCheckHelper.throwIfNull(member, () => $"party member is null !!! - userGuid:{summon_user_guid}");
member.Summon = summon;
result = await m_party_member_cache_request.changeJoinMember(member);
if (result.isFail())
{
return (result, null);
}
// 4. 대상 에게 summon 전송
result = summon_user_login_cache.CurrentServer == server_logic.getServerName()
? sendSummonMessageToClient(player_manager, summon_user_guid)
: sendSummonMessageToServer(party, player_manager, summon_user_guid,
summon_user_login_cache.CurrentServer);
if (result.isFail())
{
return (result, null);
}
return (result, summon_result.delete_summon_item);
}
public async Task<Result> clearSummonMemberAsync(USER_GUID summon_user_guid, bool isNotify)
{
var result = new Result();
var party = getOwner() as GlobalPartyDetail;
NullReferenceCheckHelper.throwIfNull(party, () => $"global party detail is null !!!");
var member_attribute = getOwner().getEntityAttribute<PartyMemberAttribute>();
NullReferenceCheckHelper.throwIfNull(member_attribute, () => $"PartyMemberAttribute is null !! - {party.toBasicString()}");
// 1. summon 수정
var member = member_attribute.getPartyMember(summon_user_guid);
NullReferenceCheckHelper.throwIfNull(member, () => $"party member is null !!! - userGuid:{summon_user_guid}");
member.Summon = new();
result = await m_party_member_cache_request.changeJoinMember(member);
if (result.isFail()) return result;
// 2. 알림 처리
if (isNotify)
{
var message = new ServerMessage();
message.NtfClearPartySummon = new();
message.NtfClearPartySummon.PartyGuid = party.PartyGuid;
message.NtfClearPartySummon.MemberUserGuid = summon_user_guid;
PartyHelper.BroadcastToServers(party, message, true);
}
return result;
}
public async Task<(Result result, int cancelSummonCount)> cancelAllSummonAsync()
{
var result = new Result();
var owner = getOwner() as GlobalPartyDetail;
NullReferenceCheckHelper.throwIfNull(owner, () => $"global party detail is null !!");
var member_attribute = getOwner().getEntityAttribute<PartyMemberAttribute>();
NullReferenceCheckHelper.throwIfNull(member_attribute, () => $"PartyMemberAttribute is null !! - {owner.toBasicString()}");
var server_message = new ServerMessage
{
CancelSummonPartyMemberNoti = new ServerMessage.Types.CancelSummonPartyMemberNoti
{
PartyGuid = owner.PartyGuid
}
};
// 1. summon 수정
foreach (var member in member_attribute.getPartyMembers())
{
if (!member.Value.Summon.IsAlreadySummon) continue;
member.Value.Summon.clear();
server_message.CancelSummonPartyMemberNoti.CancelSummonUserGuids.Add(member.Key);
result = await m_party_member_cache_request.changeJoinMember(member.Value);
server_message.CancelSummonPartyMemberNoti.CancelSummonUserGuids.Add(member.Value.UserGuid);
}
// 2. notify 전송
if (server_message.CancelSummonPartyMemberNoti.CancelSummonUserGuids.Count > 0)
{
PartyHelper.BroadcastToServers(owner, server_message, false);
}
return (result, server_message.CancelSummonPartyMemberNoti.CancelSummonUserGuids.Count);
}
private Result sendSummonMessageToClient(PlayerManager player_manager, USER_GUID summon_user_guid)
{
var result = new Result();
// 1. summon user 조회
if (!player_manager.tryGetUserByPrimaryKey(summon_user_guid, out var summon_user))
{
var err_msg = $"Failed to summon party member !!! : summon user not logged in - {summon_user_guid}";
result.setFail(ServerErrorCode.UserNotLogin, err_msg);
Log.getLogger().error(err_msg);
return result;
}
// 2. client 전송
var client_message = new ClientToGame();
client_message.Message = new ClientToGameMessage();
client_message.Message.SummonPartyMemberNoti = new ClientToGameMessage.Types.SummonPartyMemberNoti();
PartyHelper.sendToClient(client_message, summon_user.getHostId());
return result;
}
private Result sendSummonMessageToServer(GlobalPartyDetail party, PlayerManager player_manager, USER_GUID summon_user_guid, string target_server)
{
var result = new Result();
// 1. party leader 조회
var party_action = party.getEntityAction<GlobalPartyDetailAction>();
NullReferenceCheckHelper.throwIfNull(party_action, () => $"GlobalPartyDetailAction is null !! - {getOwner().toBasicString()}");
if (!player_manager.tryGetUserByPrimaryKey(party_action.getLeaderGuid(), out var leader))
{
var err_msg = $"Failed to summon party member !!! : leader not logged in - {leader?.getUserGuid()}";
result.setFail(ServerErrorCode.UserNotLogin, err_msg);
Log.getLogger().error(err_msg);
return result;
}
// 2. leader 위치 조회
var leader_location = leader.getEntityAction<LocationAction>()?.getCurrentPos();
if (null == leader_location)
{
var err_msg = $"Failed to summon party member !!! : leader not logged in - {leader.getUserGuid()}";
result.setFail(ServerErrorCode.UserNotLogin, err_msg);
Log.getLogger().error(err_msg);
return result;
}
// 3. server 전송
var server_message = new ServerMessage();
server_message.SummonPartyMemberNoti = new ServerMessage.Types.SummonPartyMemberNoti();
server_message.SummonPartyMemberNoti.SummonPartyGuid = party.PartyGuid;
server_message.SummonPartyMemberNoti.SummonUserGuid = summon_user_guid;
server_message.SummonPartyMemberNoti.SummonServerName = GameServerApp.getServerLogic().getServerName();
server_message.SummonPartyMemberNoti.SummonPos = leader_location;
PartyHelper.sendToServer(server_message, target_server);
return result;
}
private async Task<(Result result, Item? delete_summon_item)> spentSummonItemAsync(PlayerManager player_manager, GlobalPartyDetail party)
{
var result = new Result();
var party_action = party.getEntityAction<GlobalPartyDetailAction>();
NullReferenceCheckHelper.throwIfNull(party_action, () => $"GlobalPartyDetailAction is null !! - {getOwner().toBasicString()}");
if (!player_manager.tryGetUserByPrimaryKey(party_action.getLeaderGuid(), out var leader))
{
var err_msg = $"Failed to summon party member !!! : leader not logged in - {party_action.getLeaderGuid()}";
result.setFail(ServerErrorCode.PartyLeaderLoggedOut, err_msg);
Log.getLogger().error(err_msg);
return (result, null);
}
var inventory_action = leader.getEntityAction<InventoryActionBase>();
NullReferenceCheckHelper.throwIfNull(inventory_action, () => $"InventoryActionBase is null !! - {leader.toBasicString()}");;
var delete_summon_item = await inventory_action.tryDeleteItemByMetaId((uint)MetaHelper.GameConfigMeta.SummonStoneItemMetaId, (ushort)MetaHelper.GameConfigMeta.ItemAmountPartySummon);
if (delete_summon_item.Item1.isFail()) return (delete_summon_item.Item1, null);
var delete_item = delete_summon_item.Item2.FirstOrDefault();
return (delete_summon_item.Item1, delete_item);
}
private void sendPartyMemberLocation(PartyMemberInfo user)
{
var party = getOwner() as GlobalPartyDetail;
NullReferenceCheckHelper.throwIfNull(party, () => $"global party detail is null !! ");;
// 1. 파티 참가 멤버 알림 ( to server )
var server_message = new ServerMessage
{
PartyMemberLocationNoti = new()
{
PartyGuid = party.PartyGuid,
PartyMemberGuid = user.UserGuid
}
};
PartyHelper.BroadcastToServers(party, server_message, true);
// 2. 파티 참가 멤버 알림 ( to client )
var client_message = new ClientToGame();
client_message.Message = new();
client_message.Message.PartyMemberLocationNoti = new();
client_message.Message.PartyMemberLocationNoti.MemberGuid = user.UserGuid;
client_message.Message.PartyMemberLocationNoti.LocationInfo = user.LocationInfo;
PartyHelper.BroadcastToClients(party, client_message, new List<string>());
}
}

View File

@@ -0,0 +1,144 @@
using Google.Protobuf;
using Google.Protobuf.WellKnownTypes;
using ServerCore;
using ServerBase;
using ServerCommon;
using ServerCommon.BusinessLogDomain;
using MetaAssets;
namespace GameServer;
public class GlobalPartyDetailServerAction : EntityActionBase
{
private readonly PartyServerCacheRequest m_party_server_cache_request;
public GlobalPartyDetailServerAction(GlobalPartyDetail owner) : base(owner)
{
m_party_server_cache_request =
new PartyServerCacheRequest(owner.PartyGuid, GameServerApp.getServerLogic().getRedisConnector());
}
public override async Task<Result> onInit()
{
await Task.CompletedTask;
var result = new Result();
return result;
}
public override void onClear()
{
return;
}
public async Task<Result> keep()
{
return await m_party_server_cache_request.keepPartyServerCache();
}
public async Task<Result> loadPartyServer()
{
var party_server_attribute = getOwner().getEntityAttribute<PartyServerAttribute>();
NullReferenceCheckHelper.throwIfNull(party_server_attribute, () => $"PartyServerAttribute is null !! - {getOwner().toBasicString()}");
var result = await m_party_server_cache_request.fetchPartyServerCache();
if (result.isFail()) return result;
result = await ServerBase.DataCopyHelper.copyEntityAttributeFromCaches(party_server_attribute, new List<CacheBase> { m_party_server_cache_request.getPartyServerCache()! });
if (result.isFail())
{
Log.getLogger().error(result.toBasicString());
}
return result;
}
public IEnumerable<string> getServers()
{
var party_server_attribute = getOwner().getEntityAttribute<PartyServerAttribute>();
NullReferenceCheckHelper.throwIfNull(party_server_attribute, () => $"PartyServerAttribute is null !! - {getOwner().toBasicString()}");
return party_server_attribute.getPartyServers().ToList();
}
public async Task<Result> addPartyServer(string addServerName)
{
var party_server_attribute = getOwner().getEntityAttribute<PartyServerAttribute>();
NullReferenceCheckHelper.throwIfNull(party_server_attribute, () => $"PartyServerAttribute is null !! - {getOwner().toBasicString()}");
var result = await m_party_server_cache_request.addPartyServerCache(addServerName);
if (result.isFail()) return result;
party_server_attribute.addPartyServer(addServerName);
return result;
}
public async Task<Result> deletePartyServer(string delete_server_name)
{
// 1. cache 제거
var result = await m_party_server_cache_request.deletePartyServerCache(delete_server_name);
if (result.isFail()) return result;
// 2. attribute 수정
var attribute = getOwner().getEntityAttribute<PartyServerAttribute>();
NullReferenceCheckHelper.throwIfNull(attribute, () => $"PartyServerAttribute is null !! - {getOwner().toBasicString()}");
attribute.deleteServer(delete_server_name);
return result;
}
public async Task<Result> deleteAllPartyServers()
{
// 1. cache 제거
var result = await m_party_server_cache_request.deleteAllPartyServerCache();
if (result.isFail())
{
Log.getLogger().error(result.toBasicString());
}
// 2. attribute 수정
var party_server_attribute = getOwner().getEntityAttribute<PartyServerAttribute>();
NullReferenceCheckHelper.throwIfNull(party_server_attribute, () => $"PartyServerAttribute is null !! - {getOwner().toBasicString()}");
party_server_attribute.onClear();
return result;
}
public async Task<Result> notifyChangePartyServerToServers(BoolType isAddition, string srcServerName)
{
var party = getOwner() as GlobalPartyDetail;
NullReferenceCheckHelper.throwIfNull(party, () => $"party deltail is null !!!");
var party_server_attribute = getOwner().getEntityAttribute<PartyServerAttribute>();
NullReferenceCheckHelper.throwIfNull(party_server_attribute, () => $"PartyServerAttribute is null !! - {party.toBasicString()}");
var rabbit_mq = GameServerApp.getServerLogic().getRabbitMqConnector() as RabbitMqConnector;
NullReferenceCheckHelper.throwIfNull(rabbit_mq, () => $"rabbit mq is null !!! - {getOwner().toBasicString()}");
var message = new ServerMessage
{
ChangePartyServerNameNoti = new()
{
PartyGuid = party.PartyGuid,
IsAddition = isAddition,
ServerName = srcServerName
}
};
foreach (var dest_server in party_server_attribute.getPartyServers())
{
if (srcServerName == dest_server) continue;
rabbit_mq.SendMessage(dest_server, message);
}
return await Task.FromResult(new Result());
}
}

View File

@@ -0,0 +1,200 @@
using Google.Protobuf;
using Google.Protobuf.WellKnownTypes;
using ServerCore;
using ServerBase;
using ServerCommon;
using ServerCommon.BusinessLogDomain;
using MetaAssets;
using PARTY_GUID = System.String;
using USER_GUID = System.String;
namespace GameServer;
public class GlobalPartyInvitePartySendAction : EntityActionBase
{
private readonly PartyInvitePartySendCacheRequest m_party_invite_party_send_cache_request;
public GlobalPartyInvitePartySendAction(GlobalPartyDetail owner) : base(owner)
{
m_party_invite_party_send_cache_request =
new PartyInvitePartySendCacheRequest(owner.PartyGuid, GameServerApp.getServerLogic().getRedisConnector());
}
public override async Task<Result> onInit()
{
await Task.CompletedTask;
var result = new Result();
return result;
}
public override void onClear()
{
return;
}
public async Task<Result> keep()
{
return await m_party_invite_party_send_cache_request.keepInvitePartySendCache();
}
public async Task<Result> loadPartyInvitePartySend(PARTY_GUID party_guid)
{
var result = new Result();
if (PARTY_GUID.IsNullOrEmpty(party_guid))
{
var err_msg = $"Fail to load party invite party send !!! : argument is null - {nameof(loadPartyInvitePartySend)}";
result.setFail(ServerErrorCode.InvalidArgument, err_msg);
Log.getLogger().error(err_msg);
return result;
}
var party_invite_party_send = getOwner().getEntityAttribute<PartyInvitePartySendsAttribute>();
NullReferenceCheckHelper.throwIfNull(party_invite_party_send, () => $"PartyInvitePartySendsAttribute is null !! - {getOwner().toBasicString()}");
result = await m_party_invite_party_send_cache_request.fetchInvitePartySendCache();
if (result.isFail()) return result;
result = await ServerBase.DataCopyHelper.copyEntityAttributeFromCaches(party_invite_party_send, new List<CacheBase> { m_party_invite_party_send_cache_request.getPartyInvitePartySendCache()! });
if (result.isFail())
{
Log.getLogger().error(result.toBasicString());
}
return result;
}
public async Task<Result> deleteInvitePartySends()
{
// 1. cache 제거
var result = await m_party_invite_party_send_cache_request.deleteAllInvitePartySendCache();
if (result.isFail())
{
Log.getLogger().error(result.toBasicString());
}
// 2. attribute 수정
var party_invite_send_attribute = getOwner().getEntityAttribute<PartyInvitePartySendsAttribute>();
NullReferenceCheckHelper.throwIfNull(party_invite_send_attribute, () => $"PartyInvitePartySendsAttribute is null !! - {getOwner().toBasicString()}");
party_invite_send_attribute.onClear();
return result;
}
public async Task<Result> deleteInvitePartySend(USER_GUID invitee_guid)
{
// 1. attribute 수정
var party_invite_send_attribute = getOwner().getEntityAttribute<PartyInvitePartySendsAttribute>();
NullReferenceCheckHelper.throwIfNull(party_invite_send_attribute, () => $"PartyInvitePartySendsAttribute is null !! - {getOwner().toBasicString()}");
party_invite_send_attribute.deleteInvitePartySend(invitee_guid);
// 2. cache 에서 제거
var result = await m_party_invite_party_send_cache_request.deleteInvitePartySendCache(new List<string> { invitee_guid });
return result;
}
public async Task<bool> isExistCheck(string user_guid)
{
await organizeSendAttribute();
var party_invite_party_send = getOwner().getEntityAttribute<PartyInvitePartySendsAttribute>();
NullReferenceCheckHelper.throwIfNull(party_invite_party_send, () => $"PartyInvitePartySendsAttribute is null !! - {getOwner().toBasicString()}");
var sends = party_invite_party_send.getPartyInvitePartySends();
return sends.Any(send => send.Key == user_guid);
}
public async Task<int> getInviteSendsCount()
{
var list = await getPartyInvitePartySends();
return list.Count;
}
public async Task<Dictionary<string, DateTime>> getPartyInvitePartySends()
{
await organizeSendAttribute();
var attribute = getOwner().getEntityAttribute<PartyInvitePartySendsAttribute>();
NullReferenceCheckHelper.throwIfNull(attribute, () => $"PartyInvitePartySendsAttribute is null !! - {getOwner().toBasicString()}");
var sends = attribute.getPartyInvitePartySends();
var list = sends.ToDictionary(send => send.Key, send => send.Value);
return list;
}
public async Task<Result> sendInviteParty(IReadOnlyDictionary<string, string>? invite_users)
{
var result = new Result();
var party = getOwner() as GlobalPartyDetail;
NullReferenceCheckHelper.throwIfNull(party, () => $"global party detail is null !! ");
var send_users = invite_users?.Select(invitee => invitee.Key).ToList();
if (null == send_users)
{
var err_msg = $"Failed to send invite party !!! : invite_users is null - {nameof(sendInviteParty)}";
result.setFail(ServerErrorCode.FailToSendInviteMember, err_msg);
Log.getLogger().error(err_msg);
return result;
}
// 2. redis 저장
result = await m_party_invite_party_send_cache_request.addInvitePartySendCache(send_users);
if (result.isFail())
{
return result;
}
// 3. attribute 변경
var party_invite_party_send = getOwner().getEntityAttribute<PartyInvitePartySendsAttribute>();
NullReferenceCheckHelper.throwIfNull(party_invite_party_send, () => $"PartyInvitePartySendsAttribute is null !! - {party.toBasicString()}");
party_invite_party_send.addInvitePartySends(send_users);
// 1. mq message 생성
var message = new ServerMessage();
message.InvitePartyNoti = new();
message.InvitePartyNoti.InvitePartyLeaderGuid = getPartyLeaderGuid();
message.InvitePartyNoti.InvitePartyGuid = party.PartyGuid;
var rabbit_mq = GameServerApp.getServerLogic().getRabbitMqConnector() as RabbitMqConnector;
ArgumentNullException.ThrowIfNull(rabbit_mq);
// 4. invite 유저에게 메시지 전달
NullReferenceCheckHelper.throwIfNull(invite_users, () => $"party invite users is null !!! - {party.toBasicString()}");
foreach (var invitee in invite_users)
{
message.InvitePartyNoti.InviteUserGuid = invitee.Key;
rabbit_mq.SendMessage(invitee.Value, message);
}
return result;
}
private USER_GUID getPartyLeaderGuid()
{
var party_attribute = getOwner().getEntityAttribute<PartyAttribute>();
NullReferenceCheckHelper.throwIfNull(party_attribute, () => $"PartyAttribute is null !! - {getOwner().toBasicString()}");
return party_attribute.PartyLeaderCharGuid;
}
private async Task organizeSendAttribute()
{
var delete_sends = await m_party_invite_party_send_cache_request.organizeInvitePartySendCache();
if (null == delete_sends) return;
var party_invite_party_send = getOwner().getEntityAttribute<PartyInvitePartySendsAttribute>();
NullReferenceCheckHelper.throwIfNull(party_invite_party_send, () => $"PartyInvitePartySendsAttribute is null !! - {getOwner().toBasicString()}");
party_invite_party_send.deleteInvitePartySends(delete_sends);
}
}

View File

@@ -0,0 +1,50 @@
using Google.Protobuf;
using Google.Protobuf.WellKnownTypes;
using ServerCore;
using ServerBase;
using ServerCommon;
using ServerCommon.BusinessLogDomain;
using MetaAssets;
using PARTY_GUID = System.String;
namespace GameServer;
public class GlobalParty : EntityBase
{
public GlobalParty() : base(EntityType.GlobalParty)
{
}
public override async Task<Result> onInit()
{
// action
addEntityAction(new GlobalPartyAction(this));
return await base.onInit();
}
public override string toBasicString()
{
return $"{this.getTypeName()}";
}
public override string toSummaryString()
{
return $"{this.getTypeName()}";
}
public GlobalPartyDetail? getParty(PARTY_GUID party_guid)
{
var action = getEntityAction<GlobalPartyAction>();
NullReferenceCheckHelper.throwIfNull(action, () => $"GlobalPartyAction is null !! - party_guid:{party_guid}");
var party = action.getGlobalPartyDetail(party_guid);
return party;
}
}

View File

@@ -0,0 +1,73 @@
using Nettention.Proud;
using ServerCore;
using ServerBase;
using ServerCommon;
using ServerCommon.BusinessLogDomain;
using MetaAssets;
using PARTY_GUID = System.String;
namespace GameServer;
public class GlobalPartyDetail : EntityBase, IWithLogActor
{
public PARTY_GUID PartyGuid { get; }
public GlobalPartyDetail(GlobalParty parent, string party_guid)
: base(EntityType.GlobalPartyDetail, parent)
{
PartyGuid = party_guid;
}
public override async Task<Result> onInit()
{
// attribute
addEntityAttribute(new PartyAttribute(this, GameServerApp.getServerLogic().getProudNetListener().getNetServer()!));
addEntityAttribute(new PartyMemberAttribute(this));
addEntityAttribute(new PartyServerAttribute(this));
addEntityAttribute(new PartyInstanceAttribute(this));
addEntityAttribute(new PartyInvitePartySendsAttribute(this));
// action
addEntityAction(new GlobalPartyDetailAction(this));
addEntityAction(new GlobalPartyDetailInfoAction(this));
addEntityAction(new GlobalPartyDetailMemberAction(this));
addEntityAction(new GlobalPartyDetailServerAction(this));
addEntityAction(new GlobalPartyDetailInstanceAction(this));
addEntityAction(new GlobalPartyInvitePartySendAction(this));
return await base.onInit();
}
public override string toBasicString()
{
return $"{this.getTypeName()} - {getRootParent()?.toBasicString()}";
}
public override string toSummaryString()
{
return $"{this.getTypeName()} - {getRootParent()?.toBasicString()}";
}
public virtual ILogActor toLogActor()
{
var server_logic = ServerLogicApp.getServerLogicApp();
var log_info = new GlobalPartyActorLog();
if (server_logic == null)
return log_info;
log_info.initLogInfo(
// 서버 정보
server_logic.getServerConfig().getRegionId()
, server_logic.getServerConfig().getWorldId()
, server_logic.getServerType().toServerType()
);
return log_info;
}
}

View File

@@ -0,0 +1,33 @@
using Google.Protobuf;
using Google.Protobuf.WellKnownTypes;
using ServerCore;
using ServerBase;
using ServerCommon;
using ServerCommon.BusinessLogDomain;
using MetaAssets;
namespace GameServer;
public static class PartyExtensions
{
public static async Task<Result> joinParty(this Player owner)
{
var result = new Result();
// 1. 파티 정보
var party_action = owner.getEntityAction<PersonalPartyAction>();
NullReferenceCheckHelper.throwIfNull(party_action, () => $"party_action is null !!! - {owner.toBasicString()}");
result = await party_action.tryLoadParty();
if (result.isFail())
{
Log.getLogger().error(result.toBasicString());
}
return result;
}
}

View File

@@ -0,0 +1,171 @@
using Nettention.Proud;
using Google.Protobuf;
using Google.Protobuf.WellKnownTypes;
using ServerCore;
using ServerBase;
using ServerCommon;
using ServerCommon.BusinessLogDomain;
using MetaAssets;
using USER_GUID = System.String;
using PARTY_GUID = System.String;
namespace GameServer;
public class PartyHelper
{
public static void sendToClient(ClientToGame message, HostID target_client)
{
GameServerApp.getServerLogic().onSendPacketToHost(target_client, RmiContext.ReliableSend, message);
}
public static void sendToClient(ClientToGame message, USER_GUID userGuid)
{
var player_manager = GameServerApp.getServerLogic().getPlayerManager();
if (!player_manager.tryGetUserByPrimaryKey(userGuid, out var player)) return;
sendToClient(message, player.getHostId());
}
public static void BroadcastToClients(GlobalPartyDetail party, ClientToGame message, IReadOnlyList<USER_GUID> except_users)
{
var party_action = party.getEntityAction<GlobalPartyDetailAction>();
ArgumentNullException.ThrowIfNull(party_action);
var party_member_attribute = party.getEntityAttribute<PartyMemberAttribute>();
ArgumentNullException.ThrowIfNull(party_member_attribute);
var users = party_member_attribute.getPartyMembers().Select(member => member.Key).ToList();
BroadcastToClients(users, message, except_users);
}
public static void BroadcastToClients(IReadOnlyList<USER_GUID> target_users, ClientToGame message,
IReadOnlyList<USER_GUID> except_users)
{
var target_clients = new List<HostID>();
var player_manager = GameServerApp.getServerLogic().getPlayerManager();
foreach (var user in target_users)
{
if (except_users.Contains(user)) continue;
if (!player_manager.tryGetUserByPrimaryKey(user, out var member)) continue;
target_clients.Add(member.getHostId());
}
GameServerApp.getServerLogic().onSendPacketToHosts(target_clients.ToArray(), RmiContext.ReliableSend, message);
}
public static void sendToServer(ServerMessage message, string dest_server)
{
var rabbit_mq = GameServerApp.getServerLogic().getRabbitMqConnector() as RabbitMqConnector;
ArgumentNullException.ThrowIfNull(rabbit_mq);
rabbit_mq.SendMessage(dest_server, message);
}
public static async Task sendToServerByTargetClient(USER_GUID target_user_guid, ServerMessage message)
{
var login_cache = await getOtherUserLoginCache(target_user_guid);
if (null == login_cache) return;
sendToServer(message, login_cache.CurrentServer);
}
public static void BroadcastToServers(GlobalPartyDetail party, ServerMessage message, bool except_me)
{
var party_server_attribute = party.getEntityAttribute<PartyServerAttribute>();
ArgumentNullException.ThrowIfNull(party_server_attribute);
BroadcastToServers(party_server_attribute.getPartyServers().ToList(), message, except_me);
}
public static void BroadcastToServers(IReadOnlyList<PARTY_GUID> servers, ServerMessage message, bool except_me)
{
var rabbit_mq = GameServerApp.getServerLogic().getRabbitMqConnector() as RabbitMqConnector;
ArgumentNullException.ThrowIfNull(rabbit_mq);
foreach (var server in servers)
{
if (except_me && server == GameServerApp.getServerLogic().getServerName()) continue;
rabbit_mq.SendMessage(server, message);
}
}
public static async Task<string?> getUserNicknameFromGuid(USER_GUID userGuid)
{
var find = await NicknameDoc.findNicknameFromGuid(userGuid);
NullReferenceCheckHelper.throwIfNull(find);
NullReferenceCheckHelper.throwIfNull(find.attrib, () => $"find.attrib is null !!!");
return find.result.isFail() ? null : find.attrib.Nickname;
}
public static LoginCacheRequest? getOwnUserLoginCacheRequest(Player player)
{
var game_login_action = player.getEntityAction<GameLoginAction>();
var login_cache_request = game_login_action.getLoginCacheRequest();
return login_cache_request;
}
public static async Task<LoginCache?> getOtherUserLoginCache(USER_GUID user_guid)
{
var login_cache_request =
new LoginCacheOtherUserRequest(GameServerApp.getServerLogic(), GameServerApp.getServerLogic().getRedisConnector(), user_guid);
var result = await login_cache_request.fetchLogin();
return result.isFail() ? null : login_cache_request.getLoginCache();
}
public static async Task<LoginCache?> getOtherUserLoginCache(UserBase requester, USER_GUID user_guid)
{
var login_cache_request =
new LoginCacheOtherUserRequest(requester, GameServerApp.getServerLogic().getRedisConnector(), user_guid);
var result = await login_cache_request.fetchLogin();
return result.isFail() ? null : login_cache_request.getLoginCache();
}
public static PartyMemberInfo makePartyMember(string user_guid, string nickname)
{
var server_logic = GameServerApp.getServerLogic();
var user = new PartyMemberInfo();
user.Summon = new();
user.UserGuid = user_guid;
user.Nickname = nickname;
user.JoinTime = Timestamp.FromDateTime(DateTime.UtcNow);
if (false == server_logic.getPlayerManager().tryGetUserByPrimaryKey(user_guid, out var player))
{
user.LocationInfo = new UserLocationInfo();
user.LocationInfo.Id = 0;
user.LocationInfo.IsChannel = server_logic.getServerType().toServerType() == ServerType.Channel ? 1 : 0;
user.LocationInfo.ChannelNumber = (1 == user.LocationInfo.IsChannel) ? (int)server_logic.getChannelNo() : 0;
}
else
{
user.LocationInfo = player.getUserLocationInfo();
}
return user;
}
public static float calculateDistance(Pos standard, Pos target)
{
var from_vector = new System.Numerics.Vector3(standard.X, standard.Y, standard.Z);
var to_vector = new System.Numerics.Vector3(target.X, target.Y, target.Z);
return Vector3Helper.distance(from_vector, to_vector);
}
public static string getPartyGuidFromPartyInstanceRoomId(string roomId)
{
var split = roomId.Split(":");
if (split.Length < 2) return string.Empty;
return split[1];
}
}