Advertisement
Guest User

Untitled

a guest
Sep 16th, 2019
124
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C# 11.54 KB | None | 0 0
  1. // --------------------------------------------------------------------------------------------------------------------
  2. // <copyright file="PhotonHandler.cs" company="Exit Games GmbH">
  3. //   Part of: Photon Unity Networking
  4. // </copyright>
  5. // --------------------------------------------------------------------------------------------------------------------
  6.  
  7. using System;
  8. using System.Collections;
  9. using System.Diagnostics;
  10. using ExitGames.Client.Photon;
  11. using UnityEngine;
  12. using Debug = UnityEngine.Debug;
  13. using Hashtable = ExitGames.Client.Photon.Hashtable;
  14. using SupportClassPun = ExitGames.Client.Photon.SupportClass;
  15.  
  16. #if UNITY_5_5_OR_NEWER
  17. using UnityEngine.Profiling;
  18. #endif
  19.  
  20.  
  21. #if UNITY_WEBGL
  22. #pragma warning disable 0649
  23. #endif
  24.  
  25. /// <summary>
  26. /// Internal Monobehaviour that allows Photon to run an Update loop.
  27. /// </summary>
  28. internal class PhotonHandler : MonoBehaviour
  29. {
  30.     public static PhotonHandler SP;
  31.  
  32.     public int updateInterval;  // time [ms] between consecutive SendOutgoingCommands calls
  33.  
  34.     public int updateIntervalOnSerialize;  // time [ms] between consecutive RunViewUpdate calls (sending syncs, etc)
  35.  
  36.     private int nextSendTickCount = 0;
  37.  
  38.     private int nextSendTickCountOnSerialize = 0;
  39.    
  40.     private static bool sendThreadShouldRun;
  41.  
  42.     private static Stopwatch timerToStopConnectionInBackground;
  43.  
  44.     protected internal static bool AppQuits;
  45.  
  46.     protected internal static Type PingImplementation = null;
  47.  
  48.     protected void Awake()
  49.     {
  50.         if (SP != null && SP != this && SP.gameObject != null)
  51.         {
  52.             GameObject.DestroyImmediate(SP.gameObject);
  53.         }
  54.  
  55.         SP = this;
  56.         DontDestroyOnLoad(this.gameObject);
  57.  
  58.         this.updateInterval = 1000 / PhotonNetwork.sendRate;
  59.         this.updateIntervalOnSerialize = 1000 / PhotonNetwork.sendRateOnSerialize;
  60.  
  61.         PhotonHandler.StartFallbackSendAckThread();
  62.     }
  63.  
  64.  
  65.     #if UNITY_5_4_OR_NEWER
  66.  
  67.     protected void Start()
  68.     {
  69.         UnityEngine.SceneManagement.SceneManager.sceneLoaded += (scene, loadingMode) =>
  70.         {
  71.             PhotonNetwork.networkingPeer.NewSceneLoaded();
  72.             PhotonNetwork.networkingPeer.SetLevelInPropsIfSynced(SceneManagerHelper.ActiveSceneName, false);
  73.             PhotonNetwork.networkingPeer.IsReloadingLevel = false;
  74.         };
  75.     }
  76.  
  77.     #else
  78.  
  79.     /// <summary>Called by Unity after a new level was loaded.</summary>
  80.     protected void OnLevelWasLoaded(int level)
  81.     {
  82.         PhotonNetwork.networkingPeer.NewSceneLoaded();
  83.         PhotonNetwork.networkingPeer.SetLevelInPropsIfSynced(SceneManagerHelper.ActiveSceneName, false);
  84.         PhotonNetwork.networkingPeer.IsReloadingLevel = false;
  85.         PhotonNetwork.networkingPeer.AsynchLevelLoadCall = false;
  86.     }
  87.  
  88.     #endif
  89.  
  90.  
  91.     /// <summary>Called by Unity when the application is closed. Disconnects.</summary>
  92.     protected void OnApplicationQuit()
  93.     {
  94.         PhotonHandler.AppQuits = true;
  95.         PhotonHandler.StopFallbackSendAckThread();
  96.         PhotonNetwork.Disconnect();
  97.     }
  98.  
  99.     /// <summary>
  100.     /// Called by Unity when the application gets paused (e.g. on Android when in background).
  101.     /// </summary>
  102.     /// <remarks>
  103.     /// Sets a disconnect timer when PhotonNetwork.BackgroundTimeout > 0.1f. See PhotonNetwork.BackgroundTimeout.
  104.     ///
  105.     /// Some versions of Unity will give false values for pause on Android (and possibly on other platforms).
  106.     /// </remarks>
  107.     /// <param name="pause">If the app pauses.</param>
  108.     protected void OnApplicationPause(bool pause)
  109.     {
  110.         if (PhotonNetwork.BackgroundTimeout > 0.1f)
  111.         {
  112.             if (timerToStopConnectionInBackground == null)
  113.             {
  114.                 timerToStopConnectionInBackground = new Stopwatch();
  115.             }
  116.             timerToStopConnectionInBackground.Reset();
  117.  
  118.             if (pause)
  119.             {
  120.                 timerToStopConnectionInBackground.Start();
  121.             }
  122.             else
  123.             {
  124.                 timerToStopConnectionInBackground.Stop();
  125.             }
  126.         }
  127.     }
  128.  
  129.     /// <summary>Called by Unity when the play mode ends. Used to cleanup.</summary>
  130.     protected void OnDestroy()
  131.     {
  132.         //Debug.Log("OnDestroy on PhotonHandler.");
  133.         PhotonHandler.StopFallbackSendAckThread();
  134.         //PhotonNetwork.Disconnect();
  135.     }
  136.  
  137.     protected void Update()
  138.     {
  139.         if (PhotonNetwork.networkingPeer == null)
  140.         {
  141.             Debug.LogError("NetworkPeer broke!");
  142.             return;
  143.         }
  144.  
  145.         if (PhotonNetwork.connectionStateDetailed == ClientState.PeerCreated || PhotonNetwork.connectionStateDetailed == ClientState.Disconnected || PhotonNetwork.offlineMode)
  146.         {
  147.             return;
  148.         }
  149.  
  150.         // the messageQueue might be paused. in that case a thread will send acknowledgements only. nothing else to do here.
  151.         if (!PhotonNetwork.isMessageQueueRunning)
  152.         {
  153.             return;
  154.         }
  155.  
  156.         bool doDispatch = true;
  157.         while (PhotonNetwork.isMessageQueueRunning && doDispatch)
  158.         {
  159.             // DispatchIncomingCommands() returns true of it found any command to dispatch (event, result or state change)
  160.             Profiler.BeginSample("DispatchIncomingCommands");
  161.             doDispatch = PhotonNetwork.networkingPeer.DispatchIncomingCommands();
  162.             Profiler.EndSample();
  163.         }
  164.  
  165.         int currentMsSinceStart = (int)(Time.realtimeSinceStartup * 1000);  // avoiding Environment.TickCount, which could be negative on long-running platforms
  166.         if (PhotonNetwork.isMessageQueueRunning && currentMsSinceStart > this.nextSendTickCountOnSerialize)
  167.         {
  168.             PhotonNetwork.networkingPeer.RunViewUpdate();
  169.             this.nextSendTickCountOnSerialize = currentMsSinceStart + this.updateIntervalOnSerialize;
  170.             this.nextSendTickCount = 0;     // immediately send when synchronization code was running
  171.         }
  172.  
  173.         currentMsSinceStart = (int)(Time.realtimeSinceStartup * 1000);
  174.         if (currentMsSinceStart > this.nextSendTickCount)
  175.         {
  176.             bool doSend = true;
  177.             while (PhotonNetwork.isMessageQueueRunning && doSend)
  178.             {
  179.                 // Send all outgoing commands
  180.                 Profiler.BeginSample("SendOutgoingCommands");
  181.                 doSend = PhotonNetwork.networkingPeer.SendOutgoingCommands();
  182.                 Profiler.EndSample();
  183.             }
  184.  
  185.             this.nextSendTickCount = currentMsSinceStart + this.updateInterval;
  186.         }
  187.     }
  188.  
  189.     protected void OnJoinedRoom()
  190.     {
  191.         PhotonNetwork.networkingPeer.LoadLevelIfSynced();
  192.     }
  193.  
  194.     protected void OnCreatedRoom()
  195.     {
  196.         PhotonNetwork.networkingPeer.SetLevelInPropsIfSynced(SceneManagerHelper.ActiveSceneName, false);
  197.     }
  198.  
  199.     public static void StartFallbackSendAckThread()
  200.     {
  201.         #if !UNITY_WEBGL
  202.         if (sendThreadShouldRun)
  203.         {
  204.             return;
  205.         }
  206.  
  207.         sendThreadShouldRun = true;
  208.         SupportClassPun.StartBackgroundCalls(FallbackSendAckThread);   // thread will call this every 100ms until method returns false
  209.         #endif
  210.     }
  211.  
  212.     public static void StopFallbackSendAckThread()
  213.     {
  214.         #if !UNITY_WEBGL
  215.         sendThreadShouldRun = false;
  216.         #endif
  217.     }
  218.  
  219.     /// <summary>A thread which runs independent from the Update() calls. Keeps connections online while loading or in background. See PhotonNetwork.BackgroundTimeout.</summary>
  220.     public static bool FallbackSendAckThread()
  221.     {
  222.         if (sendThreadShouldRun && !PhotonNetwork.offlineMode && PhotonNetwork.networkingPeer != null)
  223.         {
  224.             // check if the client should disconnect after some seconds in background
  225.             if (timerToStopConnectionInBackground != null && PhotonNetwork.BackgroundTimeout > 0.1f)
  226.             {
  227.                 if (timerToStopConnectionInBackground.ElapsedMilliseconds > PhotonNetwork.BackgroundTimeout * 1000)
  228.                 {
  229.                     if (PhotonNetwork.connected)
  230.                     {
  231.                         PhotonNetwork.Disconnect();
  232.                     }
  233.                     timerToStopConnectionInBackground.Stop();
  234.                     timerToStopConnectionInBackground.Reset();
  235.                     return sendThreadShouldRun;
  236.                 }
  237.             }
  238.  
  239.             if (!PhotonNetwork.isMessageQueueRunning || PhotonNetwork.networkingPeer.ConnectionTime - PhotonNetwork.networkingPeer.LastSendOutgoingTime > 200)
  240.             {
  241.                 PhotonNetwork.networkingPeer.SendAcksOnly();
  242.             }
  243.         }
  244.  
  245.         return sendThreadShouldRun;
  246.     }
  247.  
  248.  
  249.     #region Photon Cloud Ping Evaluation
  250.  
  251.  
  252.     private const string PlayerPrefsKey = "PUNCloudBestRegion";
  253.  
  254.     internal static CloudRegionCode BestRegionCodeInPreferences
  255.     {
  256.         get
  257.         {
  258.             string prefsRegionCode = PlayerPrefs.GetString(PlayerPrefsKey, "");
  259.             if (!string.IsNullOrEmpty(prefsRegionCode))
  260.             {
  261.                 CloudRegionCode loadedRegion = Region.Parse(prefsRegionCode);
  262.                 return loadedRegion;
  263.             }
  264.  
  265.             return CloudRegionCode.none;
  266.         }
  267.         set
  268.         {
  269.             if (value == CloudRegionCode.none)
  270.             {
  271.                 PlayerPrefs.DeleteKey(PlayerPrefsKey);
  272.             }
  273.             else
  274.             {
  275.                 PlayerPrefs.SetString(PlayerPrefsKey, value.ToString());
  276.             }
  277.         }
  278.     }
  279.  
  280.  
  281.     internal protected static void PingAvailableRegionsAndConnectToBest()
  282.     {
  283.         SP.StartCoroutine(SP.PingAvailableRegionsCoroutine(true));
  284.     }
  285.  
  286.  
  287.     internal IEnumerator PingAvailableRegionsCoroutine(bool connectToBest)
  288.     {
  289.         while (PhotonNetwork.networkingPeer.AvailableRegions == null)
  290.         {
  291.             if (PhotonNetwork.connectionStateDetailed != ClientState.ConnectingToNameServer && PhotonNetwork.connectionStateDetailed != ClientState.ConnectedToNameServer)
  292.             {
  293.                 Debug.LogError("Call ConnectToNameServer to ping available regions.");
  294.                 yield break; // break if we don't connect to the nameserver at all
  295.             }
  296.  
  297.             Debug.Log("Waiting for AvailableRegions. State: " + PhotonNetwork.connectionStateDetailed + " Server: " + PhotonNetwork.Server + " PhotonNetwork.networkingPeer.AvailableRegions " + (PhotonNetwork.networkingPeer.AvailableRegions != null));
  298.             yield return new WaitForSeconds(0.25f); // wait until pinging finished (offline mode won't ping)
  299.         }
  300.  
  301.         if (PhotonNetwork.networkingPeer.AvailableRegions == null || PhotonNetwork.networkingPeer.AvailableRegions.Count == 0)
  302.         {
  303.             Debug.LogError("No regions available. Are you sure your appid is valid and setup?");
  304.             yield break; // break if we don't get regions at all
  305.         }
  306.  
  307.         PhotonPingManager pingManager = new PhotonPingManager();
  308.         foreach (Region region in PhotonNetwork.networkingPeer.AvailableRegions)
  309.         {
  310.             SP.StartCoroutine(pingManager.PingSocket(region));
  311.         }
  312.  
  313.         while (!pingManager.Done)
  314.         {
  315.             yield return new WaitForSeconds(0.1f); // wait until pinging finished (offline mode won't ping)
  316.         }
  317.  
  318.  
  319.         Region best = pingManager.BestRegion;
  320.         PhotonHandler.BestRegionCodeInPreferences = best.Code;
  321.  
  322.         Debug.Log("Found best region: '" + best.Code + "' ping: " + best.Ping + ". Calling ConnectToRegionMaster() is: " + connectToBest);
  323.  
  324.         if (connectToBest)
  325.         {
  326.             PhotonNetwork.networkingPeer.ConnectToRegionMaster(best.Code);
  327.         }
  328.     }
  329.  
  330.  
  331.  
  332.     #endregion
  333.  
  334. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement