Snaparazzi/Assets/Scripts/GameManager.cs

581 lines
18 KiB
C#
Raw Normal View History

2024-01-27 15:25:53 +00:00
using System;
using System.Collections;
2024-01-27 12:19:56 +00:00
using System.Collections.Generic;
2024-01-27 22:50:57 +00:00
using System.Linq;
2024-01-27 15:32:12 +00:00
using Firebase.Database;
using Firebase.Extensions;
2024-01-27 21:26:23 +00:00
using Newtonsoft.Json;
2024-01-27 12:46:54 +00:00
using TMPro;
using Unity.VisualScripting;
2024-01-27 12:19:56 +00:00
using UnityEngine;
using UnityEngine.UI;
2024-01-27 12:19:56 +00:00
2024-01-27 12:46:54 +00:00
/// <summary>
/// This is the game state manager on the phone side
/// </summary>
2024-01-27 12:19:56 +00:00
public class GameManager : MonoBehaviour
{
2024-01-27 20:07:49 +00:00
private List<Player> players = new();
2024-01-27 19:01:45 +00:00
public Player currentPlayer = null;
2024-01-27 15:25:53 +00:00
[Header("Other component")]
2024-01-27 12:46:54 +00:00
public float explanationTime = 4f;
2024-01-27 18:54:06 +00:00
[Header("Home Connection Component")]
2024-01-27 15:25:53 +00:00
public TMP_InputField roomCodeField;
2024-01-27 12:46:54 +00:00
public TextMeshProUGUI roomError;
2024-01-27 15:25:53 +00:00
public TMP_InputField playerNameField;
2024-01-27 12:46:54 +00:00
public TextMeshProUGUI nameError;
public Button submitNewPlayer;
2024-01-27 15:25:53 +00:00
[Header("WaitingRoom Component")]
public TextMeshProUGUI listPlayersUI;
public GameObject submitStartGame;
2024-01-27 23:59:12 +00:00
[Header("Explanation Component")]
public TextMeshProUGUI counterExplanation;
[Header("MakeProposition Component")]
public TextMeshProUGUI counterMakeProposition;
2024-01-27 23:59:12 +00:00
[Header("EndGame Components")]
[SerializeField] private GameObject endGameFirstPlayer;
[SerializeField] private GameObject endGameOtherPlayers;
2024-01-27 15:25:53 +00:00
[Header("Pages")]
public GameObject HomeConnection;
public GameObject WaitingRoom;
public GameObject BeforeStart;
public GameObject TakePicture;
public GameObject VotePicture;
public GameObject WaitingOtherPlayers;
public GameObject EndGame;
2024-01-27 15:32:12 +00:00
private DatabaseReference realtimeDB;
2024-01-27 18:58:02 +00:00
public Room myRoom;
2024-01-27 16:54:37 +00:00
private DatabaseReference myOnlineRoom;
private DateTime endOfViewDate = DateTime.MinValue;
2024-01-27 15:32:12 +00:00
private void Awake()
{
submitNewPlayer.interactable = false;
2024-01-27 15:32:12 +00:00
FirebaseInitializer.Instance.onFirebaseReady += Initialize;
}
2024-01-27 12:46:54 +00:00
private void Start()
{
InitializeHomePage();
}
private void InitializeHomePage()
2024-01-27 12:46:54 +00:00
{
2024-01-27 15:25:53 +00:00
HomeConnection.SetActive(true);
2024-01-28 00:55:35 +00:00
WaitingRoom.SetActive(false);
BeforeStart.SetActive(false);
TakePicture.SetActive(false);
VotePicture.SetActive(false);
WaitingOtherPlayers.SetActive(false);
EndGame.SetActive(false);
submitStartGame.SetActive(false);
submitNewPlayer.interactable = true;
2024-01-28 00:55:35 +00:00
2024-01-28 14:09:28 +00:00
if (PlayerPrefs.HasKey("lastplayername"))
playerNameField.text = PlayerPrefs.GetString("lastplayername");
2024-01-27 12:46:54 +00:00
}
2024-01-27 23:21:38 +00:00
2024-01-27 21:26:23 +00:00
private void OnApplicationQuit()
{
2024-01-28 14:09:28 +00:00
if (myOnlineRoom == null)
return;
2024-01-27 22:50:57 +00:00
myOnlineRoom.Child("players").Child(currentPlayer.id).RemoveValueAsync().ContinueWithOnMainThread(task =>
{
Debug.Log($"delete player {currentPlayer.name}");
2024-01-27 23:21:38 +00:00
if (myOnlineRoom != null)
2024-01-27 23:06:41 +00:00
{
myOnlineRoom.ValueChanged -= OnRoomUpdate;
}
2024-01-27 22:50:57 +00:00
});
2024-01-27 21:26:23 +00:00
}
2024-01-27 12:46:54 +00:00
2024-01-27 23:59:12 +00:00
private void Update()
{
if (myRoom.currentState == (int)GameState.Explanation && endOfViewDate != DateTime.MinValue)
2024-01-27 23:59:12 +00:00
{
TimeSpan duration = endOfViewDate - DateTime.Now;
counterExplanation.text = ((int)duration.TotalSeconds).ToString("D1");
2024-01-27 23:59:12 +00:00
if (duration.TotalMilliseconds <= 0)
{
Debug.Log("It's time to make proposition !");
endOfViewDate = DateTime.MinValue;
}
}
if (myRoom.currentState == (int)GameState.MakeProposition && endOfViewDate != DateTime.MinValue)
{
TimeSpan duration = endOfViewDate - DateTime.Now;
counterMakeProposition.text = ((int)duration.TotalSeconds).ToString("D1");
if (duration.TotalMilliseconds <= 0)
{
Debug.Log("It's time to finish proposition !");
endOfViewDate = DateTime.MinValue;
2024-01-27 23:59:12 +00:00
}
}
2024-01-28 16:36:00 +00:00
if (myRoom.currentState == (int)GameState.MakeVote && endOfViewDate != DateTime.MinValue)
{
TimeSpan duration = endOfViewDate - DateTime.Now;
counterMakeProposition.text = ((int)duration.TotalSeconds).ToString("D1");
if (duration.TotalMilliseconds <= 0)
{
Debug.Log("It's time to finish proposition !");
endOfViewDate = DateTime.MinValue;
}
}
2024-01-27 23:59:12 +00:00
}
2024-01-27 15:32:12 +00:00
private void Initialize()
{
FirebaseInitializer.Instance.onFirebaseReady -= Initialize;
realtimeDB = FirebaseDatabase.DefaultInstance.RootReference;
2024-01-27 17:18:03 +00:00
submitNewPlayer.interactable = true;
Debug.Log("Realtime DB initialized");
2024-01-27 15:32:12 +00:00
}
2024-01-27 12:46:54 +00:00
/// <summary>
/// Send your name and game room to the server
/// </summary>
2024-01-27 15:32:12 +00:00
public void PlayerValidateNameAndServerRoom(string _name, string _code)
2024-01-27 12:46:54 +00:00
{
2024-01-27 18:57:11 +00:00
nameError.gameObject.SetActive(false);
roomError.gameObject.SetActive(false);
2024-01-27 20:07:49 +00:00
2024-01-27 16:54:37 +00:00
if (string.IsNullOrEmpty(_name))
{
Debug.LogError("Player name is empty", this);
2024-01-27 18:57:11 +00:00
nameError.text = "You have to put a valid name";
nameError.gameObject.SetActive(true);
2024-01-27 16:54:37 +00:00
return;
}
if (string.IsNullOrEmpty(_code))
{
Debug.LogError("Room code is empty", this);
2024-01-27 18:57:11 +00:00
roomError.text = "You have to put a room code";
roomError.gameObject.SetActive(true);
2024-01-27 16:54:37 +00:00
return;
}
2024-01-27 20:07:49 +00:00
2024-01-27 17:50:04 +00:00
currentPlayer = new Player(_name);
2024-01-28 14:09:28 +00:00
PlayerPrefs.SetString("lastplayername", _name);
2024-02-01 22:10:21 +00:00
PlayerPrefs.Save();
2024-01-27 16:54:37 +00:00
2024-01-27 12:46:54 +00:00
//check if the room exists, if not display an error message
2024-01-27 16:54:37 +00:00
CheckIfRoomExists(_code, room =>
2024-01-27 15:32:12 +00:00
{
2024-01-27 16:54:37 +00:00
if (room == null)
2024-01-27 15:32:12 +00:00
{
2024-01-27 16:54:37 +00:00
Debug.LogError("The room doesn't exists");
roomError.text = "Error: the room doesn't exists";
roomError.gameObject.SetActive(true);
2024-01-27 15:32:12 +00:00
}
2024-01-27 16:54:37 +00:00
else
2024-01-27 15:32:12 +00:00
{
2024-01-27 17:50:04 +00:00
myOnlineRoom = realtimeDB.Child("rooms").Child(_code);
2024-01-27 23:59:12 +00:00
//subscribe to it
myOnlineRoom.ValueChanged += OnRoomUpdate;
2024-01-27 16:54:37 +00:00
//if room exists, join it
JoinRoom(() =>
2024-01-27 15:32:12 +00:00
{
2024-01-27 22:50:57 +00:00
myRoom.currentState = (int)GameState.WaitingForOtherPlayersToJoin;
2024-01-27 17:50:04 +00:00
players.Add(currentPlayer);
WaitingRoom.SetActive(true);
HomeConnection.SetActive(false);
2024-01-27 16:54:37 +00:00
});
2024-01-27 15:32:12 +00:00
}
});
2024-01-27 12:19:56 +00:00
}
2024-01-27 16:54:37 +00:00
private void CheckIfRoomExists(string _roomCode, Action<Room> callback_Room)
{
realtimeDB.Child("rooms").Child(_roomCode).GetValueAsync().ContinueWithOnMainThread(task =>
2024-01-27 15:32:12 +00:00
{
if (task.IsFaulted)
{
Debug.LogException(task.Exception);
}
else if (task.IsCompleted)
{
DataSnapshot snapshot = task.Result;
if (snapshot == null)
{
2024-01-27 16:54:37 +00:00
callback_Room?.Invoke(null);
2024-01-27 15:32:12 +00:00
}
else
{
2024-01-27 16:54:37 +00:00
callback_Room?.Invoke(JsonUtility.FromJson<Room>(snapshot.GetRawJsonValue()));
2024-01-27 15:32:12 +00:00
}
}
});
2024-01-27 15:25:53 +00:00
2024-01-27 16:54:37 +00:00
}
2024-01-27 15:25:53 +00:00
2024-01-27 16:54:37 +00:00
/// <summary>
/// Add this player to the room
/// </summary>
private void JoinRoom(Action callback_OnRoomJoined)
{
string JSON = JsonUtility.ToJson(currentPlayer);
2024-01-27 17:50:04 +00:00
Debug.Log(JSON);
try
2024-01-27 16:54:37 +00:00
{
2024-01-27 17:50:04 +00:00
myOnlineRoom.Child("players").Child(currentPlayer.id).SetRawJsonValueAsync(JSON).ContinueWithOnMainThread(task =>
2024-01-27 16:54:37 +00:00
{
2024-01-27 17:50:04 +00:00
if (task.IsFaulted)
{
Debug.LogException(task.Exception);
}
else
{
Debug.Log($"{currentPlayer.name} has been added to the room", this);
callback_OnRoomJoined?.Invoke();
}
});
}
catch (Exception ex)
{
Debug.LogException(ex);
}
2024-01-27 12:19:56 +00:00
}
2024-01-27 12:46:54 +00:00
/// <summary>
/// Call this only by the first player
/// </summary>
public void StartGame()
2024-01-27 12:19:56 +00:00
{
2024-01-27 20:07:49 +00:00
// send Start Game
2024-01-28 01:40:12 +00:00
myRoom.SetPlayersAreReady(1);
2024-01-27 21:26:23 +00:00
string JSON = JsonUtility.ToJson(myRoom);
Debug.Log(JSON);
try
{
2024-01-28 01:40:12 +00:00
SendCurrentState(GameState.Explanation, () =>
2024-01-27 21:26:23 +00:00
{
2024-01-27 22:50:57 +00:00
Debug.Log($"start the game", this);
myRoom.currentState = (int)GameState.Explanation;
WaitingRoom.SetActive(false);
BeforeStart.SetActive(true);
2024-01-27 21:26:23 +00:00
});
}
catch (Exception ex)
{
Debug.LogException(ex);
}
2024-01-27 12:19:56 +00:00
}
2024-01-27 12:46:54 +00:00
/// <summary>
/// Automatically called when something change in your room
/// </summary>
2024-01-27 18:57:11 +00:00
private void OnRoomUpdate(object sender, ValueChangedEventArgs e)
2024-01-27 12:46:54 +00:00
{
GameState lastState = (GameState)myRoom.currentState;
2024-01-27 18:57:11 +00:00
try
{
2024-01-28 00:55:35 +00:00
if (e?.Snapshot?.GetRawJsonValue() != null)
2024-01-27 23:59:12 +00:00
{
2024-01-28 00:55:35 +00:00
string JSON = e.Snapshot.GetRawJsonValue();
2024-02-04 11:23:12 +00:00
Debug.Log($"Room has been updated : {JSON}", this);
2024-01-27 23:59:12 +00:00
myRoom = JsonConvert.DeserializeObject<Room>(e.Snapshot.GetRawJsonValue());
}
2024-01-27 18:57:11 +00:00
}
catch (Exception ex)
{
Debug.LogException(ex);
}
2024-01-27 23:21:38 +00:00
if (myRoom == null)
{
2024-02-04 11:23:12 +00:00
Debug.LogError("Got an update for an empty room.", this);
2024-01-27 22:50:57 +00:00
return;
}
Debug.Log($"lasState = {lastState}. Currentstep = {(GameState)myRoom.currentState}", this);
if (myRoom.currentState != (int)lastState)
{
OnNewGameState();
}
//call this every time we are on this state
switch (myRoom.currentState)
{
case (int)GameState.WaitingForOtherPlayersToJoin:
{
2024-02-01 21:57:10 +00:00
List<Player> players = myRoom.GetOrderedPlayerList();
UpdateDisplayedListUser(players);
if (players.Count >= 3 && CheckIfIAmTheFirst(players))
{
submitStartGame.SetActive(true);
}
break;
}
default:
break;
}
}
/// <summary>
/// Call this when Game state change
/// </summary>
private void OnNewGameState()
{
2024-01-27 22:50:57 +00:00
switch (myRoom.currentState)
2024-01-27 15:25:53 +00:00
{
2024-01-28 01:52:40 +00:00
case (int)GameState.EnteringName:
{
InitializeHomePage();
2024-01-27 22:50:57 +00:00
break;
}
case (int)GameState.Explanation:
{
2024-02-04 11:23:12 +00:00
Debug.Log("Explanation time.", this);
2024-02-04 11:23:12 +00:00
WaitingOtherPlayers.SetActive(false);
TakePicture.SetActive(false);
2024-01-27 23:59:12 +00:00
WaitingRoom.SetActive(false);
VotePicture.SetActive(false);
EndGame.SetActive(false);
2024-01-27 23:59:12 +00:00
BeforeStart.SetActive(true);
endOfViewDate = DateTime.Now.AddSeconds(4);
2024-01-27 22:50:57 +00:00
break;
}
case (int)GameState.MakeProposition:
{
Debug.Log("It's photo time !", this);
WaitingOtherPlayers.SetActive(false);
BeforeStart.SetActive(false);
WaitingRoom.SetActive(false);
VotePicture.SetActive(false);
EndGame.SetActive(false);
TakePicture.SetActive(true);
endOfViewDate = DateTime.Now.AddSeconds(60);
2024-01-27 15:25:53 +00:00
break;
}
2024-01-28 15:43:01 +00:00
case (int)GameState.MakeVote:
{
Debug.Log("It's voting time !", this);
WaitingOtherPlayers.SetActive(false);
BeforeStart.SetActive(false);
WaitingRoom.SetActive(false);
TakePicture.SetActive(false);
EndGame.SetActive(false);
VotePicture.SetActive(true);
2024-02-04 13:30:11 +00:00
Debug.Log("subscribe to question ID");
myOnlineRoom.Child("currentQuestionId").ValueChanged += OnCurrentQuestionChanged;
2024-01-28 21:42:02 +00:00
break;
}
case (int)GameState.Score:
{
Debug.Log("it's scoring time !", this);
2024-02-04 13:30:11 +00:00
Debug.Log("unsubscribe to question ID");
myOnlineRoom.Child("currentQuestionId").ValueChanged -= OnCurrentQuestionChanged;
WaitingOtherPlayers.SetActive(false);
BeforeStart.SetActive(false);
WaitingRoom.SetActive(false);
TakePicture.SetActive(false);
VotePicture.SetActive(false);
EndGame.SetActive(true);
endGameFirstPlayer.SetActive(CheckIfIAmTheFirst(myRoom.GetPlayerList()));
endGameOtherPlayers.SetActive(!CheckIfIAmTheFirst(myRoom.GetPlayerList()));
2024-01-28 15:43:01 +00:00
break;
}
2024-01-27 15:25:53 +00:00
}
}
2024-01-27 12:46:54 +00:00
/// <summary>
/// Call this to wait for other players
/// </summary>
public void WaitForPlayers()
{
if (TakePicture.activeInHierarchy)
{
TakePicture.SetActive(false);
}
if (VotePicture.activeInHierarchy)
{
VotePicture.SetActive(false);
}
WaitingOtherPlayers.SetActive(true);
}
2024-01-27 15:25:53 +00:00
2024-01-27 21:26:23 +00:00
private void UpdateDisplayedListUser(List<Player> players)
2024-01-27 15:25:53 +00:00
{
listPlayersUI.text = string.Empty;
for (int i = 0; i < players.Count; i++)
{
listPlayersUI.text += "\n" + players[i].name;
}
2024-01-27 12:46:54 +00:00
}
2024-01-27 23:06:23 +00:00
/// <summary>
/// return true if you are the fist player
/// </summary>
/// <param name="players"></param>
/// <returns></returns>
private bool CheckIfIAmTheFirst(List<Player> players)
2024-01-27 21:26:23 +00:00
{
2024-01-27 22:50:57 +00:00
bool isFirst = false;
2024-01-27 21:26:23 +00:00
if (players.Count > 1)
{
2024-01-28 00:15:05 +00:00
List<Player> sortedList = players.OrderBy(x => x.creationDate).ToList();
2024-01-27 22:50:57 +00:00
2024-01-28 00:15:05 +00:00
if (sortedList[0].id == currentPlayer.id)
2024-01-27 22:50:57 +00:00
{
isFirst = true;
2024-01-27 23:21:38 +00:00
}
2024-01-27 21:26:23 +00:00
}
return isFirst;
2024-01-27 21:26:23 +00:00
}
2024-01-28 01:40:12 +00:00
public void SendCurrentState(GameState state, Action callback_oncCurrentStateSent)
2024-01-27 22:50:57 +00:00
{
myOnlineRoom.Child("currentState").SetValueAsync((int)state).ContinueWithOnMainThread(task =>
{
if (task.IsFaulted)
{
Debug.LogException(task.Exception);
}
else
{
callback_oncCurrentStateSent?.Invoke();
}
}); ;
2024-01-27 12:46:54 +00:00
2024-01-27 22:50:57 +00:00
}
2024-01-27 16:56:03 +00:00
public void OnClickSubmitSignIn()
{
string playerName = playerNameField.text;
string roomCode = roomCodeField.text;
submitNewPlayer.interactable = false;
2024-01-27 16:56:03 +00:00
PlayerValidateNameAndServerRoom(playerName, roomCode);
}
2024-01-28 01:52:40 +00:00
public void onClickSamePlayers()
{
2024-02-04 12:02:58 +00:00
Debug.Log("Play with same players !", this);
Room newRoom = myRoom.Copy();
2024-02-04 11:04:24 +00:00
newRoom.currentState = (int)GameState.Explanation;
newRoom.questions.Clear();
newRoom.currentQuestionId = 0;
string json = JsonConvert.SerializeObject(newRoom);
2024-01-28 01:52:40 +00:00
myOnlineRoom.SetRawJsonValueAsync(json).ContinueWithOnMainThread(task =>
{
if (task.IsFaulted)
{
Debug.LogException(task.Exception);
}
});
}
public void onClickNewPlayers()
{
2024-02-04 12:02:58 +00:00
Debug.Log("Play with new players !", this);
Room newRoom = myRoom.Copy();
2024-02-04 12:02:58 +00:00
newRoom.currentState = (int)GameState.EnteringName;
newRoom.currentQuestionId = 0;
newRoom.questions = null;
newRoom.players = null;
string json = JsonConvert.SerializeObject(newRoom);
2024-01-28 01:52:40 +00:00
myOnlineRoom.SetRawJsonValueAsync(json).ContinueWithOnMainThread(task =>
{
if (task.IsFaulted)
{
Debug.LogException(task.Exception);
}
});
}
2024-01-28 16:07:57 +00:00
2024-01-28 21:42:02 +00:00
private void OnCurrentQuestionChanged(object sender, ValueChangedEventArgs onlineValue)
{
2024-02-04 12:11:24 +00:00
if (onlineValue == null || onlineValue.Snapshot == null || onlineValue.Snapshot.Value == null || myRoom.questions == null || myRoom.questions.Count == 0)
2024-02-04 12:02:58 +00:00
return;
int questionId = onlineValue.Snapshot.Value.ConvertTo<int>();
Debug.Log($"new question ! Q{(onlineValue.Snapshot.Value.ConvertTo<int>())}");
Question q = myRoom.questions[questionId];
2024-01-28 21:42:02 +00:00
2024-02-01 21:57:10 +00:00
//do not vote for your question
if (myRoom.GetQuestionsByPlayer(currentPlayer).Contains(q))
2024-02-01 21:57:10 +00:00
{
WaitingOtherPlayers.SetActive(true);
VotePicture.SetActive(false);
}
else
2024-01-28 21:42:02 +00:00
{
VotePicture.SetActive(true);
2024-02-01 21:57:10 +00:00
WaitingOtherPlayers.SetActive(false);
VotePicture.GetComponent<PropositionHandler>().ShowQuestion(q);
2024-01-28 21:42:02 +00:00
}
}
2024-01-29 20:30:09 +00:00
/// <summary>
/// Call this function from the vote button in the scene
/// </summary>
/// <param name="propositionNumber"></param>
2024-01-28 16:07:57 +00:00
public void OnClickProposition(int propositionNumber)
{
/*
2024-01-29 20:30:09 +00:00
Debug.Log($"Room has {myRoom.questions.Count} questions. the current Question is Q({myRoom.currentQuestionId}).");
Debug.Log($"Q({myRoom.currentQuestionId}) has {myRoom.questions[myRoom.currentQuestionId].propositions.Count} propositions.");
Debug.Log($"Player click on proposition {propositionNumber}.");
Debug.Log($"it has {myRoom.questions[myRoom.currentQuestionId].propositions[propositionNumber].voters.Count} voters.");
*/
2024-01-29 20:30:09 +00:00
List<string> voters = myRoom.questions[myRoom.currentQuestionId].propositions[propositionNumber].voters;
if (voters == null)
voters = new List<string>();
2024-01-28 16:07:57 +00:00
voters.Add(currentPlayer.id);
myOnlineRoom.Child("questions").Child(myRoom.currentQuestionId.ToString()).Child("propositions").Child(propositionNumber.ToString()).Child("voters").SetValueAsync(voters);
2024-01-29 20:30:09 +00:00
2024-01-28 21:42:02 +00:00
WaitingOtherPlayers.SetActive(true);
VotePicture.SetActive(false);
2024-01-28 16:07:57 +00:00
}
2024-01-27 12:19:56 +00:00
}
public enum GameState
{
2024-01-27 21:24:50 +00:00
EnteringName = 0,
WaitingForOtherPlayersToJoin = 1,
Explanation = 2,
MakeProposition = 3,
MakeVote = 4,
Score = 5
2024-01-27 12:19:56 +00:00
}