// --------------------------------------------------------------------------------------------------------------------
//
// Part of: Photon Unity Networking
//
// --------------------------------------------------------------------------------------------------------------------
//#define GUI_ENABLED
using System.Collections;
using UnityEngine;
using Hashtable = ExitGames.Client.Photon.Hashtable;
///
/// This component establishes a common, shared room-start-time and RoomTime and RoomTimestamp. Both go up without wrapping around (for ~48 days).
///
///
/// When entering a new room, this script will take a moment to establish the start timestamp. While this is done, all values are 0.
/// Uses a Custom Property in a room to sync a start time for a multiplayer game.
///
/// The internally used roomStartTimestamp is only valid in "this" room and only on the one Game Server where
/// it was established initially. This means: This is not useful for asynchronous gameplay!
///
public class InRoomTime : MonoBehaviour
{
private int roomStartTimestamp;
private const string StartTimeKey = "#rt"; // the name of our "room time" custom property.
/// A common, synced timer as double (similar to Unity's Time.time) for a room, starting close to 0 and not wrapping around.
/// When IsoomTimeSet is false, RoomTimestamp and RoomTime will both be zero.
public double RoomTime
{
get
{
uint u = (uint)this.RoomTimestamp;
double t = u;
return t/1000;
}
}
/// A common, synced timer for a room, starting close to 0 and not wrapping around.
/// When IsoomTimeSet is false, RoomTimestamp and RoomTime will both be zero.
public int RoomTimestamp
{
get { return PhotonNetwork.inRoom ? PhotonNetwork.ServerTimestamp - this.roomStartTimestamp : 0; }
}
/// True if the client is in a room and if that room's start time is defined (by any player).
/// When IsoomTimeSet is false, RoomTimestamp and RoomTime will both be zero.
public bool IsRoomTimeSet
{
get { return PhotonNetwork.inRoom && PhotonNetwork.room.CustomProperties.ContainsKey(StartTimeKey); }
}
internal IEnumerator SetRoomStartTimestamp()
{
//Debug.Log("SetRoomStartTimestamp() IsRoomTimeSet: " + IsRoomTimeSet + " PhotonNetwork.isMasterClient: " + PhotonNetwork.isMasterClient);
if (IsRoomTimeSet || !PhotonNetwork.isMasterClient)
{
//Debug.Log("Not setting time.");
yield break;
}
// in some cases, when you enter a room, the server time is not available immediately.
if (PhotonNetwork.ServerTimestamp == 0)
{
yield return 0;
}
ExitGames.Client.Photon.Hashtable startTimeProp = new Hashtable(); // only use ExitGames.Client.Photon.Hashtable for Photon
startTimeProp[StartTimeKey] = PhotonNetwork.ServerTimestamp;
//Debug.Log("Setting roomStartTimestamp property to: " + startTimeProp[StartTimeKey]);
PhotonNetwork.room.SetCustomProperties(startTimeProp); // implement OnPhotonCustomRoomPropertiesChanged(Hashtable propertiesThatChanged) to get this change everywhere
}
/// Called by PUN when this client entered a room (no matter if joined or created).
public void OnJoinedRoom()
{
StartCoroutine("SetRoomStartTimestamp");
}
///
/// In theory, the client which created the room might crash/close before it sets the start time.
/// Just to make extremely sure this never happens, a new masterClient will check if it has to
/// start a new round.
///
public void OnMasterClientSwitched(PhotonPlayer newMasterClient)
{
StartCoroutine("SetRoomStartTimestamp");
}
/// Called by PUN when new properties for the room were set (by any client in the room).
public void OnPhotonCustomRoomPropertiesChanged(Hashtable propertiesThatChanged)
{
if (propertiesThatChanged.ContainsKey(StartTimeKey))
{
this.roomStartTimestamp = (int)propertiesThatChanged[StartTimeKey];
//Debug.Log("Got prop for roomStartTimestamp: " + roomStartTimestamp);
}
}
#if GUI_ENABLED
public Rect TextPos = new Rect(0, 150, 200, 300); // default gui position. inspector overrides this!
public void OnGUI()
{
// simple gui for output
GUILayout.BeginArea(TextPos);
GUILayout.Label(string.Format("RoomTime: {0:0.000}", RoomTime));
GUILayout.Label(string.Format("RoomTimestamp: {0:0.000}", RoomTimestamp));
GUILayout.EndArea();
}
#endif
}