초기커밋

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