qa report v2

This commit is contained in:
2026-09-06 21:36:26 +05:30
parent 78592e8d8e
commit 5ac8f92006
37 changed files with 507 additions and 223 deletions
+86 -35
View File
@@ -16,15 +16,43 @@ public class GameManager : NetworkBehaviour
public static MatchmadePlayer BluePlayer { get; set; }
/// <summary>Coin units from matchmaker <c>rc_prize</c>; used for in-game prize UI.</summary>
public static int MatchRcPrizeCoins { get; set; }
/// <summary>Clears match roster/team statics that survive scene unload (logout).</summary>
public static void ClearMatchSession()
{
MyTeam = default;
RedPlayer = null;
BluePlayer = null;
MatchRcPrizeCoins = 0;
RedFinishedMatch = true;
BlueFinishedMatch = true;
MatchWinningTeam = default;
MatchEndedByForfeit = false;
}
/// <summary>Participation CC amount shown on game over. Actual credit is decided by the winner PATCH.</summary>
public const int ParticipationCcAmount = 100;
/// <summary>Server-reported: red was still connected when the match ended (eligible for participation CC).</summary>
/// <summary>Server-reported: red was still connected when the match ended. Not inferred from winner.</summary>
public static bool RedFinishedMatch { get; private set; } = true;
/// <summary>Server-reported: blue was still connected when the match ended (eligible for participation CC).</summary>
/// <summary>Server-reported: blue was still connected when the match ended. Not inferred from winner.</summary>
public static bool BlueFinishedMatch { get; private set; } = true;
/// <summary>Local player stayed connected through match end and should see +CC on game over.</summary>
public static bool LocalPlayerEarnedParticipationCc =>
MyTeam == Team.Blue ? BlueFinishedMatch : RedFinishedMatch;
/// <summary>Winning side at settle. Used with <see cref="MatchEndedByForfeit"/> for game-over CC display.</summary>
public static Team MatchWinningTeam { get; private set; }
/// <summary>True for leave, disconnect, last-disconnect, and skip/auto-forfeit. Not shown in player UI.</summary>
public static bool MatchEndedByForfeit { get; private set; }
/// <summary>Local player should see +CC on game over: connected, and not the forfeit loser.</summary>
public static bool LocalPlayerEarnedParticipationCc
{
get
{
bool connected = MyTeam == Team.Blue ? BlueFinishedMatch : RedFinishedMatch;
if (!connected)
return false;
if (!MatchEndedByForfeit)
return true;
return MyTeam == MatchWinningTeam;
}
}
/// <summary>Set by dedicated server startup (e.g. CupidConnector parsing <c>-matchId</c>). PATCH is skipped if id ≤ 0 or secret is empty.</summary>
public static int DedicatedMatchId { get; private set; }
/// <summary>Sent as <c>X-Dedicated-Server-Secret</c>. From <c>-dedicatedSecret</c> arg or <c>DEDICATED_SERVER_SECRET</c> env.</summary>
@@ -437,7 +465,7 @@ public class GameManager : NetworkBehaviour
// Both gone → last player who disconnected wins immediately.
if (!_redConnected && !_blueConnected && _disconnectOrder.Count > 0)
EndMatch(_disconnectOrder[_disconnectOrder.Count - 1]);
EndMatch(_disconnectOrder[_disconnectOrder.Count - 1], forfeit: true);
}
IEnumerator CoDedicatedMatchJoinPatch(string baseUrl, int matchId, string secret, string json, bool collectAttempt)
@@ -578,12 +606,12 @@ public class GameManager : NetworkBehaviour
}
}
public IEnumerator DedicatedMatchPatchWinner(string baseUrl, int matchId, string secret, string winnerLower, bool redConnected, bool blueConnected)
public IEnumerator DedicatedMatchPatchWinner(string baseUrl, int matchId, string secret, string winnerLower, bool redConnected, bool blueConnected, int redScore, int blueScore, bool forfeit)
{
if (matchId <= 0 || string.IsNullOrEmpty(secret))
yield break;
string jsonBody = DedicatedMatschInternalApi.BuildWinnerPatchJson(winnerLower, redConnected, blueConnected);
string jsonBody = DedicatedMatschInternalApi.BuildWinnerPatchJson(winnerLower, redConnected, blueConnected, redScore, blueScore, forfeit);
using (var req = DedicatedMatschInternalApi.BuildWinnerRequest(baseUrl, matchId, secret, jsonBody))
{
yield return req.SendWebRequest();
@@ -591,7 +619,7 @@ public class GameManager : NetworkBehaviour
}
}
void ReportDedicatedMatchGameOver(Team winningTeam, bool redConnected, bool blueConnected)
void ReportDedicatedMatchGameOver(Team winningTeam, bool redConnected, bool blueConnected, bool forfeit)
{
if (!isServer || DedicatedMatchId <= 0 || string.IsNullOrEmpty(DedicatedMatchSecret) || _winnerSettled)
return;
@@ -601,30 +629,32 @@ public class GameManager : NetworkBehaviour
return;
}
_winnerSettled = true;
StartCoroutine(CoReportDedicatedMatchGameOver(winningTeam, redConnected, blueConnected));
StartCoroutine(CoReportDedicatedMatchGameOver(winningTeam, redConnected, blueConnected, forfeit));
}
IEnumerator CoReportDedicatedMatchGameOver(Team winningTeam, bool redConnected, bool blueConnected)
IEnumerator CoReportDedicatedMatchGameOver(Team winningTeam, bool redConnected, bool blueConnected, bool forfeit)
{
yield return DedicatedMatchPatch(DedicatedInternalApiBase, DedicatedMatchId, DedicatedMatchSecret, "{\"status\":3}");
string winner = winningTeam == Team.Red ? "red" : "blue";
yield return DedicatedMatchPatchWinner(DedicatedInternalApiBase, DedicatedMatchId, DedicatedMatchSecret, winner, redConnected, blueConnected);
yield return DedicatedMatchPatchWinner(DedicatedInternalApiBase, DedicatedMatchId, DedicatedMatchSecret, winner, redConnected, blueConnected, redScore, blueScore, forfeit);
}
/// <summary>Score or forfeit end: latch game over, report winner if escrowed, notify clients.</summary>
void EndMatch(Team winningTeam)
void EndMatch(Team winningTeam, bool forfeit)
{
if (!isServer || isGameEnded)
return;
isGameEnded = true;
ReplayRecorder.StopAndFlush();
if (GameTutorialManager.tutorialModeEnabled)
GameTutorialManager.RecordCpuL10Result(winningTeam != MyTeam);
bool redConnected = IsSideConnectedForParticipation(Team.Red);
bool blueConnected = IsSideConnectedForParticipation(Team.Blue);
Logger.Log($"Dedicated match: end winner={winningTeam} red_connected={redConnected} blue_connected={blueConnected}");
ApplyParticipationCcFlags(redConnected, blueConnected);
ReportDedicatedMatchGameOver(winningTeam, redConnected, blueConnected);
RpcGameOver(winningTeam, redConnected, blueConnected);
Logger.Log($"Dedicated match: end winner={winningTeam} red_connected={redConnected} blue_connected={blueConnected} red_score={redScore} blue_score={blueScore} forfeit={forfeit}");
ApplyParticipationCcFlags(redConnected, blueConnected, winningTeam, forfeit);
ReportDedicatedMatchGameOver(winningTeam, redConnected, blueConnected, forfeit);
RpcGameOver(winningTeam, redConnected, blueConnected, forfeit);
gameOver(winningTeam);
}
@@ -665,10 +695,12 @@ public class GameManager : NetworkBehaviour
return false;
}
static void ApplyParticipationCcFlags(bool redConnected, bool blueConnected)
static void ApplyParticipationCcFlags(bool redConnected, bool blueConnected, Team winningTeam, bool forfeit)
{
RedFinishedMatch = redConnected;
BlueFinishedMatch = blueConnected;
MatchWinningTeam = winningTeam;
MatchEndedByForfeit = forfeit;
}
void HandleDisconnectForfeitTimers()
@@ -681,14 +713,14 @@ public class GameManager : NetworkBehaviour
if (!_redConnected && _blueConnected && _redForfeitDeadline > 0f && now >= _redForfeitDeadline)
{
Logger.Log("Dedicated match: red forfeit grace expired — blue wins");
EndMatch(Team.Blue);
EndMatch(Team.Blue, forfeit: true);
return;
}
if (!_blueConnected && _redConnected && _blueForfeitDeadline > 0f && now >= _blueForfeitDeadline)
{
Logger.Log("Dedicated match: blue forfeit grace expired — red wins");
EndMatch(Team.Red);
EndMatch(Team.Red, forfeit: true);
return;
}
@@ -699,7 +731,7 @@ public class GameManager : NetworkBehaviour
{
Team winner = _disconnectOrder[_disconnectOrder.Count - 1];
Logger.Log("Dedicated match: both forfeit graces expired — last disconnect wins: " + winner);
EndMatch(winner);
EndMatch(winner, forfeit: true);
}
}
@@ -727,9 +759,10 @@ public class GameManager : NetworkBehaviour
bool blueConnected = IsSideConnectedForParticipation(Team.Blue);
_winnerSettled = true;
isGameEnded = true;
ApplyParticipationCcFlags(redConnected, blueConnected);
ApplyParticipationCcFlags(redConnected, blueConnected, winningTeam, forfeit: true);
Logger.Log("Dedicated match: blocking winner settle before shutdown → " + winningTeam
+ " red_connected=" + redConnected + " blue_connected=" + blueConnected);
+ " red_connected=" + redConnected + " blue_connected=" + blueConnected
+ " red_score=" + redScore + " blue_score=" + blueScore + " forfeit=true");
using (var statusReq = DedicatedMatschInternalApi.BuildRequest(
DedicatedInternalApiBase, DedicatedMatchId, DedicatedMatchSecret, "{\"status\":3}"))
@@ -741,7 +774,7 @@ public class GameManager : NetworkBehaviour
}
string winner = winningTeam == Team.Red ? "red" : "blue";
string jsonBody = DedicatedMatschInternalApi.BuildWinnerPatchJson(winner, redConnected, blueConnected);
string jsonBody = DedicatedMatschInternalApi.BuildWinnerPatchJson(winner, redConnected, blueConnected, redScore, blueScore, forfeit: true);
using (var winReq = DedicatedMatschInternalApi.BuildWinnerRequest(
DedicatedInternalApiBase, DedicatedMatchId, DedicatedMatchSecret, jsonBody))
{
@@ -1100,7 +1133,7 @@ public class GameManager : NetworkBehaviour
Team winner = GetOpposingTeam(skippingTeam);
Logger.Log($"Match: {skippingTeam} forfeited for skipping two consecutive turns — {winner} wins");
RpcHideSkipForfeitWarning(skippingTeam);
EndMatch(winner);
EndMatch(winner, forfeit: true);
return;
}
@@ -1294,9 +1327,9 @@ public class GameManager : NetworkBehaviour
if(blueScore >= 3){
EndMatch(Team.Blue);
EndMatch(Team.Blue, forfeit: false);
}else if(redScore >= 3){
EndMatch(Team.Red);
EndMatch(Team.Red, forfeit: false);
}else{
StartCoroutine(CoroutineOnGoal(team));
}
@@ -1344,8 +1377,8 @@ public class GameManager : NetworkBehaviour
}
[ClientRpc]
void RpcGameOver(Team team, bool redConnected, bool blueConnected){
ApplyParticipationCcFlags(redConnected, blueConnected);
void RpcGameOver(Team team, bool redConnected, bool blueConnected, bool forfeit){
ApplyParticipationCcFlags(redConnected, blueConnected, team, forfeit);
gameOver(team);
}
@@ -1488,7 +1521,7 @@ public class GameManager : NetworkBehaviour
Team winner = GetOpposingTeam(leavingTeam);
Logger.Log($"Match: {leavingTeam} forfeited by leave — {winner} wins");
EndMatch(winner);
EndMatch(winner, forfeit: true);
}
IEnumerator CoLeaveIfThirdPlayer()
@@ -1522,17 +1555,23 @@ public class GameManager : NetworkBehaviour
if (my == null || opp == null)
yield break;
if (GameTutorialManager.tutorialModeEnabled)
GameTutorialManager.ApplyCpuL10(opp);
string baseUrl = (DedicatedInternalApiBase ?? "").TrimEnd('/');
if (string.IsNullOrEmpty(baseUrl))
{
LevelLoadManager.myPlayer = my;
LevelLoadManager.opponentPlayer = opp;
yield break;
}
if (my.UserId > 0){
yield return CoFetchPlayerL10Apply(baseUrl, my);
}
if (opp.UserId > 0 && opp.UserId != my.UserId){
if (!GameTutorialManager.tutorialModeEnabled && opp.UserId > 0 && opp.UserId != my.UserId){
yield return CoFetchPlayerL10Apply(baseUrl, opp);
}
LevelLoadManager.myPlayer = my;
LevelLoadManager.opponentPlayer = opp;
@@ -1645,13 +1684,16 @@ static class DedicatedMatschInternalApi
return BuildPatchJson(url, secret, jsonBody);
}
public static string BuildWinnerPatchJson(string winnerLower, bool redConnected, bool blueConnected)
public static string BuildWinnerPatchJson(string winnerLower, bool redConnected, bool blueConnected, int redScore, int blueScore, bool forfeit)
{
return JsonUtility.ToJson(new DedicatedWinnerPatchRequest
{
winner = winnerLower,
red_connected = redConnected,
blue_connected = blueConnected
blue_connected = blueConnected,
red_score = redScore,
blue_score = blueScore,
forfeit = forfeit
});
}
@@ -1709,7 +1751,10 @@ static class DedicatedMatschInternalApi
Logger.Log("Dedicated winner PATCH economy: rc_prize=" + parsed.economy.rc_prize
+ " participant_cc=" + parsed.economy.participant_cc
+ " cc_awarded_red=" + parsed.economy.cc_awarded_red
+ " cc_awarded_blue=" + parsed.economy.cc_awarded_blue);
+ " cc_awarded_blue=" + parsed.economy.cc_awarded_blue
+ " mmr_delta=" + parsed.mmr_delta
+ " forfeit=" + parsed.forfeit
+ " already_settled=" + parsed.already_settled);
}
}
catch (Exception e)
@@ -1748,6 +1793,9 @@ class DedicatedWinnerPatchRequest
public string winner;
public bool red_connected;
public bool blue_connected;
public int red_score;
public int blue_score;
public bool forfeit;
}
[Serializable]
@@ -1766,7 +1814,10 @@ class DedicatedWinnerPatchResponse
public bool ok;
public int id;
public int winner_id;
public bool already_settled;
public DedicatedWinnerPatchEconomy economy;
public int mmr_delta;
public bool forfeit;
}
[Serializable]