snakes_mp/Assets/Scripts/GameManager.cs
2025-05-23 13:19:29 +05:30

310 lines
9.2 KiB
C#

using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using ExitGames.Client.Photon;
using Photon.Pun;
using Photon.Realtime;
using TMPro;
using UnityEngine;
using UnityEngine.Networking;
using UnityEngine.SceneManagement;
public class GameManager : MonoBehaviourPunCallbacks, IOnEventCallback
{
const int TIMEOUT_TIME = 120;
const int START_WAIT_TIME = 10;
const byte GAME_START_CODE = 1;
const byte GAME_OVER_CODE = 2;
DateTime startedTime = DateTime.UnixEpoch;
public bool gameStarted => startedTime != DateTime.UnixEpoch;
RaiseEventOptions raiseEventOptions = new RaiseEventOptions { Receivers = ReceiverGroup.All };
public SnakeController p1;
public SnakeController p2;
public GameObject wonScreen;
public GameObject lostScreen;
public TMP_Text mp_status_txt;
public TMP_Text scoreTxtYou,scoreTxtEnemy;
public GameObject fruitPrefab;
public List<GameObject> spawnedFruits = new List<GameObject>();
public int maxFruits = 10;
public float fruitSpawnInterval = 5f;
float fruitSpawnTimer = 0;
void Awake(){
p1.gameObject.SetActive(false);
p2.gameObject.SetActive(false);
}
void Start()
{
scoreTxtEnemy.text = scoreTxtYou.text = "-";
if(!PhotonNetwork.IsConnectedAndReady){
SceneManager.LoadScene(0);
}
spawnedFruits= new List<GameObject>();
StartCoroutine(SubmitGameData());
}
float startTimer = START_WAIT_TIME;
void Update()
{
if (!gameStarted)
{
if(Input.GetKeyDown(KeyCode.P)){
StartGame();
}
WaitForGameStart();
return;
}
TimeSpan timeSince = DateTime.Now - startedTime;
mp_status_txt.text = timeSince.Minutes + ":" + timeSince.Seconds.ToString("00");
UpdateScores();
if (PhotonNetwork.IsMasterClient)
{
p1.gameObject.SetActive(true);
p2.gameObject.SetActive(false);
SpawnFruits();
}
else
{
p1.gameObject.SetActive(false);
p2.gameObject.SetActive(true);
}
}
void UpdateScores(){
scoreTxtYou.text = getPlayerScore(PhotonNetwork.LocalPlayer).ToString();
scoreTxtEnemy.text = getPlayerScore(PhotonNetwork.PlayerListOthers.FirstOrDefault()).ToString();
}
void SpawnFruits(){
if(spawnedFruits.Count > maxFruits){return;}
if(spawnedFruits.Count <4){
//spawn 2
}else{
if(fruitSpawnTimer >0){
fruitSpawnTimer-=Time.deltaTime;
return;
}
}
fruitSpawnTimer = fruitSpawnInterval;
spawnedFruits.Add(PhotonNetwork.Instantiate(fruitPrefab.name, GetRandomPoint(),Quaternion.identity));
}
float timeoutTimer =0;
bool timedOut = false;
void WaitForGameStart()
{
if (PhotonNetwork.CurrentRoom.PlayerCount >= 2)
{
if (startTimer > 0)
{
startTimer -= Time.deltaTime;
mp_status_txt.text = $"Starting game in {startTimer.ToString("n0")} Seconds";
}
else
{
if (PhotonNetwork.IsMasterClient)
{
StartGame();
}
}
}
else
{
startTimer = START_WAIT_TIME;
mp_status_txt.text = "Waiting for an opponent\n";
if(timeoutTimer < TIMEOUT_TIME){
if(timedOut){
mp_status_txt.text += "Requesting Refund... Please Wait";
}else{
timeoutTimer+=Time.deltaTime;
mp_status_txt.text += "Time Remaining: " + (TIMEOUT_TIME - timeoutTimer).ToString("n0") + " Seconds";
}
}else{
StartCoroutine(SubmitRefundReq());
timeoutTimer=0;
timedOut = true;
}
}
}
int getPlayerScore(Player p){
return p.CustomProperties.ContainsKey("score") ? (int)p.CustomProperties["score"] : 0;
}
Vector2 GetRandomPoint(){
SnakeController p = (p1.gameObject.activeSelf) ? p1 : p2;
float x = p.transform.position.x - (int)(UnityEngine.Random.Range(-p.fieldSize.x/2f, p.fieldSize.x/2f));
float y = p.transform.position.y - (int)(UnityEngine.Random.Range(-p.fieldSize.y/2f, p.fieldSize.y/2f));
return new Vector2(x, y);
}
void StartGame(){
Debug.Log("Sending Raise Event");
PhotonNetwork.RaiseEvent(GAME_START_CODE, 1, raiseEventOptions, SendOptions.SendReliable);
startedTime = DateTime.Now;
}
public void DestroyFruit(Vector2 position){
if(PhotonNetwork.IsMasterClient){
destroyFruit(position);
}else{
photonView.RPC("RpcDestroyFruit", RpcTarget.All, position);
}
}
[PunRPC]
void RpcDestroyFruit(Vector2 position){
if(PhotonNetwork.IsMasterClient){
destroyFruit(position);
}
}
void destroyFruit(Vector2 position){
// Fruit[] fruits = FindObjectsOfType<Fruit>();
foreach(GameObject fruit in spawnedFruits){
if((Vector2)fruit.transform.position == position){
spawnedFruits.Remove(fruit);
PhotonNetwork.Destroy(fruit.gameObject);
break;
}
}
}
public void OnGameOver(){
PhotonNetwork.RaiseEvent(GAME_OVER_CODE, PhotonNetwork.IsMasterClient ? 1 : 0, raiseEventOptions, SendOptions.SendReliable);
}
public bool gameOver = false;
int winnerId = -1;
public void OnEvent(EventData photonEvent)
{
if (photonEvent.Code == GAME_START_CODE)
{
Debug.Log("Game Started");
startedTime = DateTime.Now;
}else if(photonEvent.Code == GAME_OVER_CODE){
if(winnerId >=0){
return;
}
Debug.Log("Game Over");
gameOver = true;
winnerId = (int)photonEvent.CustomData;
p1.gameObject.SetActive(false);
p2.gameObject.SetActive(false);
if(PhotonNetwork.IsMasterClient){
wonScreen.SetActive(winnerId== 0);
lostScreen.SetActive(winnerId != 0);
}else{
wonScreen.SetActive(winnerId != 0);
lostScreen.SetActive(winnerId== 0);
}
StartCoroutine(SubmitGameData());
}
}
public IEnumerator SubmitGameData()
{
// Create the leaderboard object
Leaderboard leaderboard = new Leaderboard
{
master = scoreTxtYou.text,
client = scoreTxtEnemy.text
};
// Create the submission object
Submission submission = new Submission
{
gameAddress = GameData.address,
playerType = PhotonNetwork.IsMasterClient ? "master" : "client",
username = GameData.user_id,
winner = gameOver ? (winnerId == 0 ? "master" : "client") : "",
leaderboard = leaderboard,
score = gameOver? (PhotonNetwork.IsMasterClient && winnerId == 0 ? 1 :0) : 0,
game_id = "snakes",
publicKey= GameData.pubkey,
wager = GameData.wager
};
// Convert submission to JSON
string json = JsonUtility.ToJson(submission);
byte[] jsonData = Encoding.UTF8.GetBytes(json);
// Send request to the server
using (UnityWebRequest request = new UnityWebRequest($"{Constants.VALIDATOR_URL}submit", "POST"))
{
request.uploadHandler = new UploadHandlerRaw(jsonData);
request.downloadHandler = new DownloadHandlerBuffer();
request.SetRequestHeader("Content-Type", "application/json");
yield return request.SendWebRequest();
#if UNITY_2020_1_OR_NEWER
if (request.result == UnityWebRequest.Result.Success)
#else
if (!request.isNetworkError && !request.isHttpError)
#endif
{
// Debug.Log("Submission successful");
// Debug.Log("Response: " + request.downloadHandler.text);
}
else
{
Debug.Log("Error submitting game data:");
Debug.Log(request.error);
}
}
}
public IEnumerator SubmitRefundReq()
{
// Send request to the server
using (UnityWebRequest request = new UnityWebRequest($"{Constants.VALIDATOR_URL}requestRefund?gameAddress=" + GameData.address, "GET"))
{
request.SetRequestHeader("Content-Type", "application/json");
yield return request.SendWebRequest();
#if UNITY_2020_1_OR_NEWER
if (request.result == UnityWebRequest.Result.Success)
#else
if (!request.isNetworkError && !request.isHttpError)
#endif
{
Debug.Log("Refund request submitted successfully");
JSBridge.instance.OnClose(-1);
}
else
{
Debug.Log("Error submitting refund request:");
Debug.Log(request.error);
}
}
}
}