diff --git a/Assets/PerfectWorld/Scripts/Managers/EC_ManPlayer.cs b/Assets/PerfectWorld/Scripts/Managers/EC_ManPlayer.cs
index f387e0a2ca..707a76639d 100644
--- a/Assets/PerfectWorld/Scripts/Managers/EC_ManPlayer.cs
+++ b/Assets/PerfectWorld/Scripts/Managers/EC_ManPlayer.cs
@@ -33,18 +33,6 @@ namespace PerfectWorld.Scripts.Managers
{
if (CECGameRun.Instance == null) return true;
if (CECGameRun.Instance.GetHostPlayer() == null) return true;
- // Duel invite: show accept/reject popup (origin uses MSG_PM_DUELOPT with command DUEL_RECV_REQUEST = 214)
- // dwParam2 is ushort (pCmdHeader from GameSession); use Convert to avoid InvalidCastException when unboxing
- if ((int)Msg.dwMsg == EC_MsgDef.MSG_PM_DUELOPT && Convert.ToInt32(Msg.dwParam2) == CommandID.DUEL_RECV_REQUEST && Msg.dwParam1 is byte[] pDataBuf && pDataBuf.Length >= 4)
- {
- int inviterId = BitConverter.ToInt32(pDataBuf, 0);
- CECUIManager.Instance?.ShowMessageBox(
- title: "",
- message: "You have received a duel request. Do you accept?",
- messageBoxType: MessageBoxType.BothYesNoButton,
- onClickedYes: () => UnityGameSession.c2s_CmdDuelReply(true, inviterId),
- onClickedNo: () => UnityGameSession.c2s_CmdDuelReply(false, inviterId));
- }
CECGameRun.Instance.GetHostPlayer().ProcessMessage(Msg);
}
else if (Msg.iSubID < 0)
diff --git a/Assets/PerfectWorld/Scripts/Network/CSNetwork/C2SCommand/C2SCommandFactory.cs b/Assets/PerfectWorld/Scripts/Network/CSNetwork/C2SCommand/C2SCommandFactory.cs
index b4e93c6fac..6082666510 100644
--- a/Assets/PerfectWorld/Scripts/Network/CSNetwork/C2SCommand/C2SCommandFactory.cs
+++ b/Assets/PerfectWorld/Scripts/Network/CSNetwork/C2SCommand/C2SCommandFactory.cs
@@ -818,6 +818,18 @@ namespace CSNetwork.C2SCommand
return SerializeCommand(CommandID.TEAM_INVITE, new cmd_team_new_member { idMember = idPlayer });
}
+ /// C2S: accept team invite from leader. idLeader = who sent the invite, team_seq = invite sequence from TEAM_LEADER_INVITE.
+ public static Octets CreateTeamAgreeInviteCommand(int idLeader, int team_seq)
+ {
+ return SerializeCommand(CommandID.TEAM_AGREE_INVITE, new cmd_team_agree_invite { idLeader = idLeader, team_seq = team_seq });
+ }
+
+ /// C2S: reject team invite from leader.
+ public static Octets CreateTeamRejectInviteCommand(int idLeader)
+ {
+ return SerializeCommand(CommandID.TEAM_REJECT_INVITE, new cmd_team_reject_invite { idLeader = idLeader });
+ }
+
/// C2S: request duel with target player (same payload shape as team invite).
public static Octets CreateDuelRequestCommand(int idTarget)
{
diff --git a/Assets/PerfectWorld/Scripts/Network/CSNetwork/GPDataType.cs b/Assets/PerfectWorld/Scripts/Network/CSNetwork/GPDataType.cs
index 2fcbaa4fc5..67ca8d2495 100644
--- a/Assets/PerfectWorld/Scripts/Network/CSNetwork/GPDataType.cs
+++ b/Assets/PerfectWorld/Scripts/Network/CSNetwork/GPDataType.cs
@@ -2208,6 +2208,21 @@ namespace CSNetwork.GPDataType
public int idMember;
}
+ /// C2S: accept team invite. idLeader = who sent the invite, team_seq = invite sequence.
+ [StructLayout(LayoutKind.Sequential, Pack = 1)]
+ public struct cmd_team_agree_invite
+ {
+ public int idLeader;
+ public int team_seq;
+ }
+
+ /// C2S: reject team invite. idLeader = who sent the invite.
+ [StructLayout(LayoutKind.Sequential, Pack = 1)]
+ public struct cmd_team_reject_invite
+ {
+ public int idLeader;
+ }
+
/// C2S duel reply (origin: who = inviter id, param = 0 accept / non-zero reject reason).
[StructLayout(LayoutKind.Sequential, Pack = 1)]
public struct cmd_duel_reply
diff --git a/Assets/PerfectWorld/Scripts/Network/CSNetwork/GameSession.cs b/Assets/PerfectWorld/Scripts/Network/CSNetwork/GameSession.cs
index 2cd0e8486d..073a93dabf 100644
--- a/Assets/PerfectWorld/Scripts/Network/CSNetwork/GameSession.cs
+++ b/Assets/PerfectWorld/Scripts/Network/CSNetwork/GameSession.cs
@@ -840,6 +840,9 @@ namespace CSNetwork
case CommandID.TEAM_MEMBER_DATA:
EC_ManMessage.PostMessage(EC_MsgDef.MSG_HST_TEAMMEMBERDATA, (int)MANAGER_INDEX.MAN_PLAYER, 0, pDataBuf, pCmdHeader);
break;
+ case CommandID.TEAM_LEADER_INVITE:
+ EC_ManMessage.PostMessage(EC_MsgDef.MSG_HST_TEAMINVITE, (int)MANAGER_INDEX.MAN_PLAYER, 0, pDataBuf, pCmdHeader);
+ break;
case CommandID.TEAM_MEMBER_LEAVE:
EC_ManMessage.PostMessage(EC_MsgDef.MSG_PM_LEAVETEAM, (int)MANAGER_INDEX.MAN_PLAYER, -1, pDataBuf, pCmdHeader);
break;
@@ -1863,6 +1866,20 @@ namespace CSNetwork
SendProtocol(g);
}
+ public void c2s_SendCmdTeamAgreeInvite(int idLeader, int team_seq)
+ {
+ var g = new gamedatasend();
+ g.Data = C2SCommandFactory.CreateTeamAgreeInviteCommand(idLeader, team_seq);
+ SendProtocol(g);
+ }
+
+ public void c2s_SendCmdTeamRejectInvite(int idLeader)
+ {
+ var g = new gamedatasend();
+ g.Data = C2SCommandFactory.CreateTeamRejectInviteCommand(idLeader);
+ SendProtocol(g);
+ }
+
public void c2s_SendCmdDuelRequest(int idTarget)
{
var g = new gamedatasend();
diff --git a/Assets/PerfectWorld/Scripts/Network/UnityGameSession.cs b/Assets/PerfectWorld/Scripts/Network/UnityGameSession.cs
index 2ea519aff2..6d4da53a7c 100644
--- a/Assets/PerfectWorld/Scripts/Network/UnityGameSession.cs
+++ b/Assets/PerfectWorld/Scripts/Network/UnityGameSession.cs
@@ -599,6 +599,14 @@ namespace BrewMonster.Network
{
Instance._gameSession.c2s_SendCmdTeamInvite(idPlayer);
}
+ public static void c2s_CmdTeamAgreeInvite(int idLeader, int team_seq)
+ {
+ Instance._gameSession.c2s_SendCmdTeamAgreeInvite(idLeader, team_seq);
+ }
+ public static void c2s_CmdTeamRejectInvite(int idLeader)
+ {
+ Instance._gameSession.c2s_SendCmdTeamRejectInvite(idLeader);
+ }
public static void c2s_CmdDuelRequest(int idTarget)
{
Instance._gameSession.c2s_SendCmdDuelRequest(idTarget);
diff --git a/Assets/Scripts/CECHostPlayer.cs b/Assets/Scripts/CECHostPlayer.cs
index 63405d1aee..cede52a8c3 100644
--- a/Assets/Scripts/CECHostPlayer.cs
+++ b/Assets/Scripts/CECHostPlayer.cs
@@ -608,6 +608,7 @@ namespace BrewMonster
case EC_MsgDef.MSG_HST_JOINTEAM: OnMsgHstJoinTeam(Msg); break;
case EC_MsgDef.MSG_HST_LEAVETEAM: OnMsgHstLeaveTeam(Msg); break;
case EC_MsgDef.MSG_HST_NEWTEAMMEM: OnMsgHstNewTeamMem(Msg); break;
+ case EC_MsgDef.MSG_HST_TEAMINVITE: OnMsgHstTeamInvite(Msg); break;
case EC_MsgDef.MSG_HST_TEAMMEMBERDATA: OnMsgHstTeamMemberData(Msg); break;
case EC_MsgDef.MSG_PM_DUELOPT: OnMsgHstDuelOpt(Msg); break;
case EC_MsgDef.MSG_HST_CLEARTESSERA: OnMsgHstClearTessera(Msg); break;
@@ -653,6 +654,18 @@ namespace BrewMonster
idOpp = BitConverter.ToInt32(data, 0);
switch (cmdId)
{
+ case CommandID.DUEL_RECV_REQUEST:
+ // Duel invite: show accept/reject popup (origin MSG_PM_DUELOPT with command DUEL_RECV_REQUEST = 214)
+ if (idOpp != 0)
+ {
+ CECUIManager.Instance?.ShowMessageBox(
+ title: "",
+ message: "You have received a duel request. Do you accept?",
+ messageBoxType: MessageBoxType.BothYesNoButton,
+ onClickedYes: () => UnityGameSession.c2s_CmdDuelReply(true, idOpp),
+ onClickedNo: () => UnityGameSession.c2s_CmdDuelReply(false, idOpp));
+ }
+ break;
case CommandID.DUEL_PREPARE:
m_pvp.iDuelState = Duel_state.DUEL_ST_PREPARE;
m_pvp.idDuelOpp = idOpp;
@@ -683,6 +696,32 @@ namespace BrewMonster
}
}
+ /// Host received a team invite (MSG_HST_TEAMINVITE). Payload is cmd_team_leader_invite: idLeader, seq, pickFlag. Shows accept/reject message box and sends reply.
+ private void OnMsgHstTeamInvite(ECMSG Msg)
+ {
+ byte[] data = Msg.dwParam1 as byte[];
+ int idLeader = 0;
+ int team_seq = 0;
+ if (data != null && data.Length >= 8)
+ {
+ idLeader = BitConverter.ToInt32(data, 0);
+ team_seq = BitConverter.ToInt32(data, 4);
+ }
+ else if (data != null && data.Length >= 4)
+ {
+ idLeader = BitConverter.ToInt32(data, 0);
+ }
+ if (idLeader == 0)
+ return;
+ int seqCapture = team_seq;
+ CECUIManager.Instance?.ShowMessageBox(
+ title: "",
+ message: "You have received a team invite. Do you accept?",
+ messageBoxType: MessageBoxType.BothYesNoButton,
+ onClickedYes: () => UnityGameSession.c2s_CmdTeamAgreeInvite(idLeader, seqCapture),
+ onClickedNo: () => UnityGameSession.c2s_CmdTeamRejectInvite(idLeader));
+ }
+
/// Called when MSG_PM_PLAYERDUELOPT (229) is received; server may send duel start to both participants. If host is one of the two ids, set duel state.
public void OnMsgPlayerDuelStart(byte[] data)
{