FlappyBirdMP/Assets/Scripts/NetGameManager.cs
2025-07-05 00:53:04 +05:30

203 lines
5.5 KiB
C#

using System.Collections;
using System.Collections.Generic;
using Mirror;
using UnityEngine;
using TMPro;
public class NetGameManager : NetworkBehaviour
{
public const int WAITING_TIME = 120;
public static NetGameManager instance;
void Awake()
{
instance = this;
}
[SyncVar]
public bool gameStarted = false;
[SyncVar]
public bool playerSpawned = false;
[SyncVar]
public int masterScore=0;
[SyncVar]
public int clientScore= 0;
PlayerType winner;
public TMP_Text statusText;
public GameOverScreen gameOverScreen;
float waitingTimer = WAITING_TIME;
void Start(){
}
void Update()
{
if(isServer){
UpdateServer();
}
}
float gameTimer =0f;
void UpdateServer(){
PlayerController[] players = FindObjectsOfType<PlayerController>();
if(!gameStarted){
if(players.Length > 1){
gameStarted=true;
RpcSetGameStarted(true);
StartCoroutine(StartGame());
}else{
if(players.Length == 1){
if(waitingTimer > 0){
waitingTimer -= Time.deltaTime;
SetStatusText("Waiting for another player...\nRemaining time: " + waitingTimer.ToString("F0") + " seconds");
}else{
SetStatusText("Opponent abandoned the game");
GameOver(players[0].playerType);
}
}
}
}else{
if(players.Length == 1){
if(playerSpawned){
SetStatusText("Opponent left the game");
GameOver(players[0].playerType);
}else{
gameStarted=false;
SetStatusText("Waiting for another player...");
}
}
if(playerSpawned && !gameOver){
gameTimer += Time.deltaTime;
}
}
}
[ClientRpc]
void RpcSetGameStarted(bool started){
gameStarted = started;
}
void SetStatusText(string text)
{
if (!isServer) { return; }
statusText.text = text;
RpcSetStatusText(text);
}
[ClientRpc]
void RpcSetStatusText(string text)
{
statusText.text = text;
}
public IEnumerator StartGame()
{
int counter = 10;
PlayerController[] players = FindObjectsOfType<PlayerController>();
while (counter > 0)
{
players = FindObjectsOfType<PlayerController>();
if (players.Length <= 1)
{
yield break;
}
SetStatusText("Game starts in " + counter);
yield return new WaitForSeconds(1f);
counter--;
}
SetStatusText("Game Started");
playerSpawned = true;
yield return new WaitForSeconds(1f);
SetStatusText("");
}
bool gameOver = false;
public void GameOver(PlayerController player){
winner = player.playerType;
GameOver(winner);
}
public void GameOver(PlayerType winner){
if(gameOver){return;}
SetStatusText($"Player {(winner == PlayerType.Master ? "1" : "2")} wins!");
Debug.Log("Game Over " + winner);
gameOver = true;
string winnerKey = winner == PlayerType.Master ? "master" : "client";
StartCoroutine(CoroutineGameOver(winnerKey));
RpcGameOver(winnerKey);
}
[ClientRpc]
void RpcGameOver(string winnerKey){
bool won = (winnerKey == "master" && GameData.isMaster) || (winnerKey == "client" && !GameData.isMaster);
gameOverScreen.Show(won);
Debug.Log("Game Over " + winnerKey);
}
IEnumerator CoroutineGameOver(string winnerKey){
string winnerPubkey = winnerKey == "master" ? GameData.betData.owner : GameData.betData.joiner;
string winnerId = winnerKey == "master" ? GameData.betData.owner_id : GameData.betData.joiner_id;
int masterScore=0, clientScore =0;
Dictionary<string, string> data = new Dictionary<string, string>(){
{"gameAddress", GameData.address},
{"winnerPublicKey", winnerPubkey},
{"winnerUsername", winnerId},
{"wager", (GameData.betData.wager * 1e8).ToString()},
{"game_id", GameData.betData.id.ToString()},
{"loserUsername", winnerKey == "master" ? GameData.betData.joiner_id : GameData.betData.owner_id},
{"masterScore", masterScore.ToString()},
{"clientScore", clientScore.ToString()},
{"masterId", GameData.betData.owner_id},
{"clientId", GameData.betData.joiner_id}
};
string queryString = "?";
foreach(KeyValuePair<string, string> entry in data) {
queryString += entry.Key + "=" + WWW.EscapeURL(entry.Value) + "&";
}
queryString = queryString.TrimEnd('&');
string validator_url = GameData.isDev ? Constants.VALIDATOR_URL_DEV : Constants.VALIDATOR_URL_PROD;
string url = validator_url + "finalize" + queryString;
Debug.Log("Finalizing game on " + url);
WWW www = new WWW(url);
yield return www;
if(www.error == null){
RpcProcessed();
}
Debug.Log("Processed game, quitting in 10 seconds...");
yield return new WaitForSeconds(10f);
Application.Quit();
}
[ClientRpc]
void RpcProcessed(){
gameOverScreen.Processed();
}
}