using System; using System.Collections.Generic; using System.Diagnostics; using ExitGames.Client.Photon; using UnityEngine; using UnityEngine.SceneManagement; public static class PhotonNetwork { public delegate void EventCallback(byte eventCode, object content, int senderId); public const string versionPUN = "1.85"; internal static readonly PhotonHandler photonMono; internal static NetworkingPeer networkingPeer; public static readonly int MAX_VIEW_IDS; internal const string serverSettingsAssetFile = "PhotonServerSettings"; internal const string serverSettingsAssetPath = "Assets/Photon Unity Networking/Resources/PhotonServerSettings.asset"; public static ServerSettings PhotonServerSettings; public static bool InstantiateInRoomOnly; public static PhotonLogLevel logLevel; public static float precisionForVectorSynchronization; public static float precisionForQuaternionSynchronization; public static float precisionForFloatSynchronization; public static bool UseRpcMonoBehaviourCache; public static bool UsePrefabCache; public static Dictionary PrefabCache; public static HashSet SendMonoMessageTargets; public static Type SendMonoMessageTargetType; public static bool StartRpcsAsCoroutine; private static bool isOfflineMode; private static Room offlineModeRoom; [Obsolete("Used for compatibility with Unity networking only.")] public static int maxConnections; private static bool _mAutomaticallySyncScene; private static bool m_autoCleanUpPlayerObjects; private static int sendInterval; private static int sendIntervalOnSerialize; private static bool m_isMessageQueueRunning; private static bool UsePreciseTimer; private static Stopwatch startupStopwatch; public static float BackgroundTimeout; public static EventCallback OnEventCall; internal static int lastUsedViewSubId; internal static int lastUsedViewSubIdStatic; internal static List manuallyAllocatedViewIds; public static string gameVersion { get; set; } public static string ServerAddress { get { return (networkingPeer == null) ? "" : networkingPeer.ServerAddress; } } public static CloudRegionCode CloudRegion { get { return (networkingPeer == null || !connected || Server == ServerConnection.NameServer) ? CloudRegionCode.none : networkingPeer.CloudRegion; } } public static bool connected { get { if (offlineMode) { return true; } if (networkingPeer == null) { return false; } return !networkingPeer.IsInitialConnect && networkingPeer.State != ClientState.PeerCreated && networkingPeer.State != ClientState.Disconnected && networkingPeer.State != ClientState.Disconnecting && networkingPeer.State != ClientState.ConnectingToNameServer; } } public static bool connecting { get { return networkingPeer.IsInitialConnect && !offlineMode; } } public static bool connectedAndReady { get { if (!connected) { return false; } if (offlineMode) { return true; } switch (connectionStateDetailed) { case ClientState.PeerCreated: case ClientState.ConnectingToGameserver: case ClientState.Joining: case ClientState.ConnectingToMasterserver: case ClientState.Disconnecting: case ClientState.Disconnected: case ClientState.ConnectingToNameServer: case ClientState.Authenticating: return false; default: return true; } } } public static ConnectionState connectionState { get { if (offlineMode) { return ConnectionState.Connected; } if (networkingPeer == null) { return ConnectionState.Disconnected; } switch (networkingPeer.PeerState) { case PeerStateValue.Disconnected: return ConnectionState.Disconnected; case PeerStateValue.Connecting: return ConnectionState.Connecting; case PeerStateValue.Connected: return ConnectionState.Connected; case PeerStateValue.Disconnecting: return ConnectionState.Disconnecting; case PeerStateValue.InitializingApplication: return ConnectionState.InitializingApplication; default: return ConnectionState.Disconnected; } } } public static ClientState connectionStateDetailed { get { if (offlineMode) { return (offlineModeRoom == null) ? ClientState.ConnectedToMaster : ClientState.Joined; } if (networkingPeer == null) { return ClientState.Disconnected; } return networkingPeer.State; } } public static ServerConnection Server { get { return (networkingPeer == null) ? ServerConnection.NameServer : networkingPeer.Server; } } public static AuthenticationValues AuthValues { get { return (networkingPeer == null) ? null : networkingPeer.AuthValues; } set { if (networkingPeer != null) { networkingPeer.AuthValues = value; } } } public static Room room { get { if (isOfflineMode) { return offlineModeRoom; } return networkingPeer.CurrentRoom; } } public static PhotonPlayer player { get { if (networkingPeer == null) { return null; } return networkingPeer.LocalPlayer; } } public static PhotonPlayer masterClient { get { if (offlineMode) { return player; } if (networkingPeer == null) { return null; } return networkingPeer.GetPlayerWithId(networkingPeer.mMasterClientId); } } public static string playerName { get { return networkingPeer.PlayerName; } set { networkingPeer.PlayerName = value; } } public static PhotonPlayer[] playerList { get { if (networkingPeer == null) { return new PhotonPlayer[0]; } return networkingPeer.mPlayerListCopy; } } public static PhotonPlayer[] otherPlayers { get { if (networkingPeer == null) { return new PhotonPlayer[0]; } return networkingPeer.mOtherPlayerListCopy; } } public static List Friends { get; internal set; } public static int FriendsListAge { get { return (networkingPeer != null) ? networkingPeer.FriendListAge : 0; } } public static IPunPrefabPool PrefabPool { get { return networkingPeer.ObjectPool; } set { networkingPeer.ObjectPool = value; } } public static bool offlineMode { get { return isOfflineMode; } set { if (value == isOfflineMode) { return; } if (value && connected) { UnityEngine.Debug.LogError("Can't start OFFLINE mode while connected!"); return; } if (networkingPeer.PeerState != PeerStateValue.Disconnected) { networkingPeer.Disconnect(); } isOfflineMode = value; if (isOfflineMode) { networkingPeer.ChangeLocalID(-1); NetworkingPeer.SendMonoMessage(PhotonNetworkingMessage.OnConnectedToMaster); } else { offlineModeRoom = null; networkingPeer.ChangeLocalID(-1); } } } public static bool automaticallySyncScene { get { return _mAutomaticallySyncScene; } set { _mAutomaticallySyncScene = value; if (_mAutomaticallySyncScene && room != null) { networkingPeer.LoadLevelIfSynced(); } } } public static bool autoCleanUpPlayerObjects { get { return m_autoCleanUpPlayerObjects; } set { if (room != null) { UnityEngine.Debug.LogError("Setting autoCleanUpPlayerObjects while in a room is not supported."); } else { m_autoCleanUpPlayerObjects = value; } } } public static bool autoJoinLobby { get { return PhotonServerSettings.JoinLobby; } set { PhotonServerSettings.JoinLobby = value; } } public static bool EnableLobbyStatistics { get { return PhotonServerSettings.EnableLobbyStatistics; } set { PhotonServerSettings.EnableLobbyStatistics = value; } } public static List LobbyStatistics { get { return networkingPeer.LobbyStatistics; } private set { networkingPeer.LobbyStatistics = value; } } public static bool insideLobby { get { return networkingPeer.insideLobby; } } public static TypedLobby lobby { get { return networkingPeer.lobby; } set { networkingPeer.lobby = value; } } public static int sendRate { get { return 1000 / sendInterval; } set { sendInterval = 1000 / value; if (photonMono != null) { photonMono.updateInterval = sendInterval; } if (value < sendRateOnSerialize) { sendRateOnSerialize = value; } } } public static int sendRateOnSerialize { get { return 1000 / sendIntervalOnSerialize; } set { if (value > sendRate) { UnityEngine.Debug.LogError("Error: Can not set the OnSerialize rate higher than the overall SendRate."); value = sendRate; } sendIntervalOnSerialize = 1000 / value; if (photonMono != null) { photonMono.updateIntervalOnSerialize = sendIntervalOnSerialize; } } } public static bool isMessageQueueRunning { get { return m_isMessageQueueRunning; } set { if (value) { PhotonHandler.StartFallbackSendAckThread(); } networkingPeer.IsSendingOnlyAcks = !value; m_isMessageQueueRunning = value; } } public static int unreliableCommandsLimit { get { return networkingPeer.LimitOfUnreliableCommands; } set { networkingPeer.LimitOfUnreliableCommands = value; } } public static double time { get { uint serverTimestamp = (uint)ServerTimestamp; double num = serverTimestamp; return num / 1000.0; } } public static int ServerTimestamp { get { if (offlineMode) { if (UsePreciseTimer && startupStopwatch != null && startupStopwatch.IsRunning) { return (int)startupStopwatch.ElapsedMilliseconds; } return Environment.TickCount; } return networkingPeer.ServerTimeInMilliSeconds; } } public static bool isMasterClient { get { if (offlineMode) { return true; } return networkingPeer.mMasterClientId == player.ID; } } public static bool inRoom { get { return connectionStateDetailed == ClientState.Joined; } } public static bool isNonMasterClientInRoom { get { return !isMasterClient && room != null; } } public static int countOfPlayersOnMaster { get { return networkingPeer.PlayersOnMasterCount; } } public static int countOfPlayersInRooms { get { return networkingPeer.PlayersInRoomsCount; } } public static int countOfPlayers { get { return networkingPeer.PlayersInRoomsCount + networkingPeer.PlayersOnMasterCount; } } public static int countOfRooms { get { return networkingPeer.RoomsCount; } } public static bool NetworkStatisticsEnabled { get { return networkingPeer.TrafficStatsEnabled; } set { networkingPeer.TrafficStatsEnabled = value; } } public static int ResentReliableCommands { get { return networkingPeer.ResentReliableCommands; } } public static bool CrcCheckEnabled { get { return networkingPeer.CrcEnabled; } set { if (!connected && !connecting) { networkingPeer.CrcEnabled = value; } else { UnityEngine.Debug.Log("Can't change CrcCheckEnabled while being connected. CrcCheckEnabled stays " + networkingPeer.CrcEnabled); } } } public static int PacketLossByCrcCheck { get { return networkingPeer.PacketLossByCrc; } } public static int MaxResendsBeforeDisconnect { get { return networkingPeer.SentCountAllowance; } set { if (value < 3) { value = 3; } if (value > 10) { value = 10; } networkingPeer.SentCountAllowance = value; } } public static int QuickResends { get { return networkingPeer.QuickResendAttempts; } set { if (value < 0) { value = 0; } if (value > 3) { value = 3; } networkingPeer.QuickResendAttempts = (byte)value; } } static PhotonNetwork() { MAX_VIEW_IDS = 1000; PhotonServerSettings = (ServerSettings)Resources.Load("PhotonServerSettings", typeof(ServerSettings)); InstantiateInRoomOnly = true; logLevel = PhotonLogLevel.ErrorsOnly; precisionForVectorSynchronization = 9.9E-05f; precisionForQuaternionSynchronization = 1f; precisionForFloatSynchronization = 0.01f; UsePrefabCache = true; PrefabCache = new Dictionary(); SendMonoMessageTargetType = typeof(MonoBehaviour); StartRpcsAsCoroutine = true; isOfflineMode = false; offlineModeRoom = null; _mAutomaticallySyncScene = false; m_autoCleanUpPlayerObjects = true; sendInterval = 50; sendIntervalOnSerialize = 100; m_isMessageQueueRunning = true; UsePreciseTimer = false; BackgroundTimeout = 60f; lastUsedViewSubId = 0; lastUsedViewSubIdStatic = 0; manuallyAllocatedViewIds = new List(); if (PhotonServerSettings != null) { Application.runInBackground = PhotonServerSettings.RunInBackground; } GameObject gameObject = new GameObject(); photonMono = gameObject.AddComponent(); gameObject.name = "PhotonMono"; gameObject.hideFlags = HideFlags.HideInHierarchy; ConnectionProtocol protocol = PhotonServerSettings.Protocol; networkingPeer = new NetworkingPeer(string.Empty, protocol); networkingPeer.QuickResendAttempts = 2; networkingPeer.SentCountAllowance = 7; if (UsePreciseTimer) { UnityEngine.Debug.Log("Using Stopwatch as precision timer for PUN."); startupStopwatch = new Stopwatch(); startupStopwatch.Start(); networkingPeer.LocalMsTimestampDelegate = () => (int)startupStopwatch.ElapsedMilliseconds; } CustomTypes.Register(); } public static void SwitchToProtocol(ConnectionProtocol cp) { networkingPeer.TransportProtocol = cp; } public static bool ConnectUsingSettings(string gameVersion) { if (networkingPeer.PeerState != PeerStateValue.Disconnected) { UnityEngine.Debug.LogWarning("ConnectUsingSettings() failed. Can only connect while in state 'Disconnected'. Current state: " + networkingPeer.PeerState); return false; } if (PhotonServerSettings == null) { UnityEngine.Debug.LogError("Can't connect: Loading settings failed. ServerSettings asset must be in any 'Resources' folder as: PhotonServerSettings"); return false; } if (PhotonServerSettings.HostType == ServerSettings.HostingOption.NotSet) { UnityEngine.Debug.LogError("You did not select a Hosting Type in your PhotonServerSettings. Please set it up or don't use ConnectUsingSettings()."); return false; } if (logLevel == PhotonLogLevel.ErrorsOnly) { logLevel = PhotonServerSettings.PunLogging; } if (networkingPeer.DebugOut == DebugLevel.ERROR) { networkingPeer.DebugOut = PhotonServerSettings.NetworkLogging; } SwitchToProtocol(PhotonServerSettings.Protocol); networkingPeer.SetApp(PhotonServerSettings.AppID, gameVersion); if (PhotonServerSettings.HostType == ServerSettings.HostingOption.OfflineMode) { offlineMode = true; return true; } if (offlineMode) { UnityEngine.Debug.LogWarning("ConnectUsingSettings() disabled the offline mode. No longer offline."); } offlineMode = false; isMessageQueueRunning = true; networkingPeer.IsInitialConnect = true; if (PhotonServerSettings.HostType == ServerSettings.HostingOption.SelfHosted) { networkingPeer.IsUsingNameServer = false; networkingPeer.MasterServerAddress = ((PhotonServerSettings.ServerPort != 0) ? (PhotonServerSettings.ServerAddress + ":" + PhotonServerSettings.ServerPort) : PhotonServerSettings.ServerAddress); return networkingPeer.Connect(networkingPeer.MasterServerAddress, ServerConnection.MasterServer); } if (PhotonServerSettings.HostType == ServerSettings.HostingOption.BestRegion) { return ConnectToBestCloudServer(gameVersion); } return networkingPeer.ConnectToRegionMaster(PhotonServerSettings.PreferredRegion); } public static bool ConnectToMaster(string masterServerAddress, int port, string appID, string gameVersion) { if (networkingPeer.PeerState != PeerStateValue.Disconnected) { UnityEngine.Debug.LogWarning("ConnectToMaster() failed. Can only connect while in state 'Disconnected'. Current state: " + networkingPeer.PeerState); return false; } if (offlineMode) { offlineMode = false; UnityEngine.Debug.LogWarning("ConnectToMaster() disabled the offline mode. No longer offline."); } if (!isMessageQueueRunning) { isMessageQueueRunning = true; UnityEngine.Debug.LogWarning("ConnectToMaster() enabled isMessageQueueRunning. Needs to be able to dispatch incoming messages."); } networkingPeer.SetApp(appID, gameVersion); networkingPeer.IsUsingNameServer = false; networkingPeer.IsInitialConnect = true; networkingPeer.MasterServerAddress = ((port != 0) ? (masterServerAddress + ":" + port) : masterServerAddress); return networkingPeer.Connect(networkingPeer.MasterServerAddress, ServerConnection.MasterServer); } public static bool Reconnect() { if (string.IsNullOrEmpty(networkingPeer.MasterServerAddress)) { UnityEngine.Debug.LogWarning("Reconnect() failed. It seems the client wasn't connected before?! Current state: " + networkingPeer.PeerState); return false; } if (networkingPeer.PeerState != PeerStateValue.Disconnected) { UnityEngine.Debug.LogWarning("Reconnect() failed. Can only connect while in state 'Disconnected'. Current state: " + networkingPeer.PeerState); return false; } if (offlineMode) { offlineMode = false; UnityEngine.Debug.LogWarning("Reconnect() disabled the offline mode. No longer offline."); } if (!isMessageQueueRunning) { isMessageQueueRunning = true; UnityEngine.Debug.LogWarning("Reconnect() enabled isMessageQueueRunning. Needs to be able to dispatch incoming messages."); } networkingPeer.IsUsingNameServer = false; networkingPeer.IsInitialConnect = false; return networkingPeer.ReconnectToMaster(); } public static bool ReconnectAndRejoin() { if (networkingPeer.PeerState != PeerStateValue.Disconnected) { UnityEngine.Debug.LogWarning("ReconnectAndRejoin() failed. Can only connect while in state 'Disconnected'. Current state: " + networkingPeer.PeerState); return false; } if (offlineMode) { offlineMode = false; UnityEngine.Debug.LogWarning("ReconnectAndRejoin() disabled the offline mode. No longer offline."); } if (string.IsNullOrEmpty(networkingPeer.GameServerAddress)) { UnityEngine.Debug.LogWarning("ReconnectAndRejoin() failed. It seems the client wasn't connected to a game server before (no address)."); return false; } if (networkingPeer.enterRoomParamsCache == null) { UnityEngine.Debug.LogWarning("ReconnectAndRejoin() failed. It seems the client doesn't have any previous room to re-join."); return false; } if (!isMessageQueueRunning) { isMessageQueueRunning = true; UnityEngine.Debug.LogWarning("ReconnectAndRejoin() enabled isMessageQueueRunning. Needs to be able to dispatch incoming messages."); } networkingPeer.IsUsingNameServer = false; networkingPeer.IsInitialConnect = false; return networkingPeer.ReconnectAndRejoin(); } public static bool ConnectToBestCloudServer(string gameVersion) { if (networkingPeer.PeerState != PeerStateValue.Disconnected) { UnityEngine.Debug.LogWarning("ConnectToBestCloudServer() failed. Can only connect while in state 'Disconnected'. Current state: " + networkingPeer.PeerState); return false; } if (PhotonServerSettings == null) { UnityEngine.Debug.LogError("Can't connect: Loading settings failed. ServerSettings asset must be in any 'Resources' folder as: PhotonServerSettings"); return false; } if (PhotonServerSettings.HostType == ServerSettings.HostingOption.OfflineMode) { return ConnectUsingSettings(gameVersion); } networkingPeer.IsInitialConnect = true; networkingPeer.SetApp(PhotonServerSettings.AppID, gameVersion); CloudRegionCode bestRegionCodeInPreferences = PhotonHandler.BestRegionCodeInPreferences; if (bestRegionCodeInPreferences != CloudRegionCode.none) { UnityEngine.Debug.Log("Best region found in PlayerPrefs. Connecting to: " + bestRegionCodeInPreferences); return networkingPeer.ConnectToRegionMaster(bestRegionCodeInPreferences); } return networkingPeer.ConnectToNameServer(); } public static bool ConnectToRegion(CloudRegionCode region, string gameVersion) { if (networkingPeer.PeerState != PeerStateValue.Disconnected) { UnityEngine.Debug.LogWarning("ConnectToRegion() failed. Can only connect while in state 'Disconnected'. Current state: " + networkingPeer.PeerState); return false; } if (PhotonServerSettings == null) { UnityEngine.Debug.LogError("Can't connect: ServerSettings asset must be in any 'Resources' folder as: PhotonServerSettings"); return false; } if (PhotonServerSettings.HostType == ServerSettings.HostingOption.OfflineMode) { return ConnectUsingSettings(gameVersion); } networkingPeer.IsInitialConnect = true; networkingPeer.SetApp(PhotonServerSettings.AppID, gameVersion); if (region != CloudRegionCode.none) { UnityEngine.Debug.Log("ConnectToRegion: " + region); return networkingPeer.ConnectToRegionMaster(region); } return false; } public static void OverrideBestCloudServer(CloudRegionCode region) { PhotonHandler.BestRegionCodeInPreferences = region; } public static void RefreshCloudServerRating() { throw new NotImplementedException("not available at the moment"); } public static void NetworkStatisticsReset() { networkingPeer.TrafficStatsReset(); } public static string NetworkStatisticsToString() { if (networkingPeer == null || offlineMode) { return "Offline or in OfflineMode. No VitalStats available."; } return networkingPeer.VitalStatsToString(false); } [Obsolete("Used for compatibility with Unity networking only. Encryption is automatically initialized while connecting.")] public static void InitializeSecurity() { } private static bool VerifyCanUseNetwork() { if (connected) { return true; } UnityEngine.Debug.LogError("Cannot send messages when not connected. Either connect to Photon OR use offline mode!"); return false; } public static void Disconnect() { if (offlineMode) { offlineMode = false; offlineModeRoom = null; networkingPeer.State = ClientState.Disconnecting; networkingPeer.OnStatusChanged(StatusCode.Disconnect); } else if (networkingPeer != null) { networkingPeer.Disconnect(); } } public static bool FindFriends(string[] friendsToFind) { if (networkingPeer == null || isOfflineMode) { return false; } return networkingPeer.OpFindFriends(friendsToFind); } public static bool CreateRoom(string roomName) { return CreateRoom(roomName, null, null, null); } public static bool CreateRoom(string roomName, RoomOptions roomOptions, TypedLobby typedLobby) { return CreateRoom(roomName, roomOptions, typedLobby, null); } public static bool CreateRoom(string roomName, RoomOptions roomOptions, TypedLobby typedLobby, string[] expectedUsers) { if (offlineMode) { if (offlineModeRoom != null) { UnityEngine.Debug.LogError("CreateRoom failed. In offline mode you still have to leave a room to enter another."); return false; } EnterOfflineRoom(roomName, roomOptions, true); return true; } if (networkingPeer.Server != ServerConnection.MasterServer || !connectedAndReady) { UnityEngine.Debug.LogError("CreateRoom failed. Client is not on Master Server or not yet ready to call operations. Wait for callback: OnJoinedLobby or OnConnectedToMaster."); return false; } typedLobby = typedLobby ?? ((!networkingPeer.insideLobby) ? null : networkingPeer.lobby); EnterRoomParams enterRoomParams = new EnterRoomParams(); enterRoomParams.RoomName = roomName; enterRoomParams.RoomOptions = roomOptions; enterRoomParams.Lobby = typedLobby; enterRoomParams.ExpectedUsers = expectedUsers; return networkingPeer.OpCreateGame(enterRoomParams); } public static bool JoinRoom(string roomName) { return JoinRoom(roomName, null); } public static bool JoinRoom(string roomName, string[] expectedUsers) { if (offlineMode) { if (offlineModeRoom != null) { UnityEngine.Debug.LogError("JoinRoom failed. In offline mode you still have to leave a room to enter another."); return false; } EnterOfflineRoom(roomName, null, true); return true; } if (networkingPeer.Server != ServerConnection.MasterServer || !connectedAndReady) { UnityEngine.Debug.LogError("JoinRoom failed. Client is not on Master Server or not yet ready to call operations. Wait for callback: OnJoinedLobby or OnConnectedToMaster."); return false; } if (string.IsNullOrEmpty(roomName)) { UnityEngine.Debug.LogError("JoinRoom failed. A roomname is required. If you don't know one, how will you join?"); return false; } EnterRoomParams enterRoomParams = new EnterRoomParams(); enterRoomParams.RoomName = roomName; enterRoomParams.ExpectedUsers = expectedUsers; return networkingPeer.OpJoinRoom(enterRoomParams); } public static bool JoinOrCreateRoom(string roomName, RoomOptions roomOptions, TypedLobby typedLobby) { return JoinOrCreateRoom(roomName, roomOptions, typedLobby, null); } public static bool JoinOrCreateRoom(string roomName, RoomOptions roomOptions, TypedLobby typedLobby, string[] expectedUsers) { if (offlineMode) { if (offlineModeRoom != null) { UnityEngine.Debug.LogError("JoinOrCreateRoom failed. In offline mode you still have to leave a room to enter another."); return false; } EnterOfflineRoom(roomName, roomOptions, true); return true; } if (networkingPeer.Server != ServerConnection.MasterServer || !connectedAndReady) { UnityEngine.Debug.LogError("JoinOrCreateRoom failed. Client is not on Master Server or not yet ready to call operations. Wait for callback: OnJoinedLobby or OnConnectedToMaster."); return false; } if (string.IsNullOrEmpty(roomName)) { UnityEngine.Debug.LogError("JoinOrCreateRoom failed. A roomname is required. If you don't know one, how will you join?"); return false; } typedLobby = typedLobby ?? ((!networkingPeer.insideLobby) ? null : networkingPeer.lobby); EnterRoomParams enterRoomParams = new EnterRoomParams(); enterRoomParams.RoomName = roomName; enterRoomParams.RoomOptions = roomOptions; enterRoomParams.Lobby = typedLobby; enterRoomParams.CreateIfNotExists = true; enterRoomParams.PlayerProperties = player.CustomProperties; enterRoomParams.ExpectedUsers = expectedUsers; return networkingPeer.OpJoinRoom(enterRoomParams); } public static bool JoinRandomRoom() { return JoinRandomRoom(null, 0, MatchmakingMode.FillRoom, null, null); } public static bool JoinRandomRoom(Hashtable expectedCustomRoomProperties, byte expectedMaxPlayers) { return JoinRandomRoom(expectedCustomRoomProperties, expectedMaxPlayers, MatchmakingMode.FillRoom, null, null); } public static bool JoinRandomRoom(Hashtable expectedCustomRoomProperties, byte expectedMaxPlayers, MatchmakingMode matchingType, TypedLobby typedLobby, string sqlLobbyFilter, string[] expectedUsers = null) { if (offlineMode) { if (offlineModeRoom != null) { UnityEngine.Debug.LogError("JoinRandomRoom failed. In offline mode you still have to leave a room to enter another."); return false; } EnterOfflineRoom("offline room", null, true); return true; } if (networkingPeer.Server != ServerConnection.MasterServer || !connectedAndReady) { UnityEngine.Debug.LogError("JoinRandomRoom failed. Client is not on Master Server or not yet ready to call operations. Wait for callback: OnJoinedLobby or OnConnectedToMaster."); return false; } typedLobby = typedLobby ?? ((!networkingPeer.insideLobby) ? null : networkingPeer.lobby); OpJoinRandomRoomParams opJoinRandomRoomParams = new OpJoinRandomRoomParams(); opJoinRandomRoomParams.ExpectedCustomRoomProperties = expectedCustomRoomProperties; opJoinRandomRoomParams.ExpectedMaxPlayers = expectedMaxPlayers; opJoinRandomRoomParams.MatchingType = matchingType; opJoinRandomRoomParams.TypedLobby = typedLobby; opJoinRandomRoomParams.SqlLobbyFilter = sqlLobbyFilter; opJoinRandomRoomParams.ExpectedUsers = expectedUsers; return networkingPeer.OpJoinRandomRoom(opJoinRandomRoomParams); } public static bool ReJoinRoom(string roomName) { if (offlineMode) { UnityEngine.Debug.LogError("ReJoinRoom failed due to offline mode."); return false; } if (networkingPeer.Server != ServerConnection.MasterServer || !connectedAndReady) { UnityEngine.Debug.LogError("ReJoinRoom failed. Client is not on Master Server or not yet ready to call operations. Wait for callback: OnJoinedLobby or OnConnectedToMaster."); return false; } if (string.IsNullOrEmpty(roomName)) { UnityEngine.Debug.LogError("ReJoinRoom failed. A roomname is required. If you don't know one, how will you join?"); return false; } EnterRoomParams enterRoomParams = new EnterRoomParams(); enterRoomParams.RoomName = roomName; enterRoomParams.RejoinOnly = true; enterRoomParams.PlayerProperties = player.CustomProperties; return networkingPeer.OpJoinRoom(enterRoomParams); } private static void EnterOfflineRoom(string roomName, RoomOptions roomOptions, bool createdRoom) { offlineModeRoom = new Room(roomName, roomOptions); networkingPeer.ChangeLocalID(1); offlineModeRoom.MasterClientId = 1; if (createdRoom) { NetworkingPeer.SendMonoMessage(PhotonNetworkingMessage.OnCreatedRoom); } NetworkingPeer.SendMonoMessage(PhotonNetworkingMessage.OnJoinedRoom); } public static bool JoinLobby() { return JoinLobby(null); } public static bool JoinLobby(TypedLobby typedLobby) { if (connected && Server == ServerConnection.MasterServer) { if (typedLobby == null) { typedLobby = TypedLobby.Default; } bool flag = networkingPeer.OpJoinLobby(typedLobby); if (flag) { networkingPeer.lobby = typedLobby; } return flag; } return false; } public static bool LeaveLobby() { if (connected && Server == ServerConnection.MasterServer) { return networkingPeer.OpLeaveLobby(); } return false; } public static bool LeaveRoom() { if (offlineMode) { offlineModeRoom = null; NetworkingPeer.SendMonoMessage(PhotonNetworkingMessage.OnLeftRoom); return true; } if (room == null) { UnityEngine.Debug.LogWarning("PhotonNetwork.room is null. You don't have to call LeaveRoom() when you're not in one. State: " + connectionStateDetailed); } return networkingPeer.OpLeave(); } public static bool GetCustomRoomList(TypedLobby typedLobby, string sqlLobbyFilter) { return networkingPeer.OpGetGameList(typedLobby, sqlLobbyFilter); } public static RoomInfo[] GetRoomList() { if (offlineMode || networkingPeer == null) { return new RoomInfo[0]; } return networkingPeer.mGameListCopy; } public static void SetPlayerCustomProperties(Hashtable customProperties) { if (customProperties == null) { customProperties = new Hashtable(); foreach (object key in player.CustomProperties.Keys) { customProperties[(string)key] = null; } } if (room != null && room.IsLocalClientInside) { player.SetCustomProperties(customProperties); } else { player.InternalCacheProperties(customProperties); } } public static void RemovePlayerCustomProperties(string[] customPropertiesToDelete) { if (customPropertiesToDelete == null || customPropertiesToDelete.Length == 0 || player.CustomProperties == null) { player.CustomProperties = new Hashtable(); return; } foreach (string key in customPropertiesToDelete) { if (player.CustomProperties.ContainsKey(key)) { player.CustomProperties.Remove(key); } } } public static bool RaiseEvent(byte eventCode, object eventContent, bool sendReliable, RaiseEventOptions options) { if (!inRoom || eventCode >= 200) { UnityEngine.Debug.LogWarning("RaiseEvent() failed. Your event is not being sent! Check if your are in a Room and the eventCode must be less than 200 (0..199)."); return false; } return networkingPeer.OpRaiseEvent(eventCode, eventContent, sendReliable, options); } public static int AllocateViewID() { int num = AllocateViewID(player.ID); manuallyAllocatedViewIds.Add(num); return num; } public static int AllocateSceneViewID() { if (!isMasterClient) { UnityEngine.Debug.LogError("Only the Master Client can AllocateSceneViewID(). Check PhotonNetwork.isMasterClient!"); return -1; } int num = AllocateViewID(0); manuallyAllocatedViewIds.Add(num); return num; } private static int AllocateViewID(int ownerId) { if (ownerId == 0) { int num = lastUsedViewSubIdStatic; int num2 = ownerId * MAX_VIEW_IDS; for (int i = 1; i < MAX_VIEW_IDS; i++) { num = (num + 1) % MAX_VIEW_IDS; if (num != 0) { int num3 = num + num2; if (!networkingPeer.photonViewList.ContainsKey(num3)) { lastUsedViewSubIdStatic = num; return num3; } } } throw new Exception(string.Format("AllocateViewID() failed. Room (user {0}) is out of 'scene' viewIDs. It seems all available are in use.", ownerId)); } int num4 = lastUsedViewSubId; int num5 = ownerId * MAX_VIEW_IDS; for (int j = 1; j < MAX_VIEW_IDS; j++) { num4 = (num4 + 1) % MAX_VIEW_IDS; if (num4 != 0) { int num6 = num4 + num5; if (!networkingPeer.photonViewList.ContainsKey(num6) && !manuallyAllocatedViewIds.Contains(num6)) { lastUsedViewSubId = num4; return num6; } } } throw new Exception(string.Format("AllocateViewID() failed. User {0} is out of subIds, as all viewIDs are used.", ownerId)); } private static int[] AllocateSceneViewIDs(int countOfNewViews) { int[] array = new int[countOfNewViews]; for (int i = 0; i < countOfNewViews; i++) { array[i] = AllocateViewID(0); } return array; } public static void UnAllocateViewID(int viewID) { manuallyAllocatedViewIds.Remove(viewID); if (networkingPeer.photonViewList.ContainsKey(viewID)) { UnityEngine.Debug.LogWarning(string.Format("UnAllocateViewID() should be called after the PhotonView was destroyed (GameObject.Destroy()). ViewID: {0} still found in: {1}", viewID, networkingPeer.photonViewList[viewID])); } } public static GameObject Instantiate(string prefabName, Vector3 position, Quaternion rotation, byte group) { return Instantiate(prefabName, position, rotation, group, null); } public static GameObject Instantiate(string prefabName, Vector3 position, Quaternion rotation, byte group, object[] data) { if (!connected || (InstantiateInRoomOnly && !inRoom)) { UnityEngine.Debug.LogError("Failed to Instantiate prefab: " + prefabName + ". Client should be in a room. Current connectionStateDetailed: " + connectionStateDetailed); return null; } GameObject value; if (!UsePrefabCache || !PrefabCache.TryGetValue(prefabName, out value)) { value = (GameObject)Resources.Load(prefabName, typeof(GameObject)); if (UsePrefabCache) { PrefabCache.Add(prefabName, value); } } if (value == null) { UnityEngine.Debug.LogError("Failed to Instantiate prefab: " + prefabName + ". Verify the Prefab is in a Resources folder (and not in a subfolder)"); return null; } if (value.GetComponent() == null) { UnityEngine.Debug.LogError("Failed to Instantiate prefab:" + prefabName + ". Prefab must have a PhotonView component."); return null; } Component[] photonViewsInChildren = value.GetPhotonViewsInChildren(); int[] array = new int[photonViewsInChildren.Length]; for (int i = 0; i < array.Length; i++) { array[i] = AllocateViewID(player.ID); } Hashtable evData = networkingPeer.SendInstantiate(prefabName, position, rotation, group, array, data, false); return networkingPeer.DoInstantiate(evData, networkingPeer.LocalPlayer, value); } public static GameObject InstantiateSceneObject(string prefabName, Vector3 position, Quaternion rotation, byte group, object[] data) { if (!connected || (InstantiateInRoomOnly && !inRoom)) { UnityEngine.Debug.LogError("Failed to InstantiateSceneObject prefab: " + prefabName + ". Client should be in a room. Current connectionStateDetailed: " + connectionStateDetailed); return null; } if (!isMasterClient) { UnityEngine.Debug.LogError("Failed to InstantiateSceneObject prefab: " + prefabName + ". Client is not the MasterClient in this room."); return null; } GameObject value; if (!UsePrefabCache || !PrefabCache.TryGetValue(prefabName, out value)) { value = (GameObject)Resources.Load(prefabName, typeof(GameObject)); if (UsePrefabCache) { PrefabCache.Add(prefabName, value); } } if (value == null) { UnityEngine.Debug.LogError("Failed to InstantiateSceneObject prefab: " + prefabName + ". Verify the Prefab is in a Resources folder (and not in a subfolder)"); return null; } if (value.GetComponent() == null) { UnityEngine.Debug.LogError("Failed to InstantiateSceneObject prefab:" + prefabName + ". Prefab must have a PhotonView component."); return null; } Component[] photonViewsInChildren = value.GetPhotonViewsInChildren(); int[] array = AllocateSceneViewIDs(photonViewsInChildren.Length); if (array == null) { UnityEngine.Debug.LogError("Failed to InstantiateSceneObject prefab: " + prefabName + ". No ViewIDs are free to use. Max is: " + MAX_VIEW_IDS); return null; } Hashtable evData = networkingPeer.SendInstantiate(prefabName, position, rotation, group, array, data, true); return networkingPeer.DoInstantiate(evData, networkingPeer.LocalPlayer, value); } public static int GetPing() { return networkingPeer.RoundTripTime; } public static void FetchServerTimestamp() { if (networkingPeer != null) { networkingPeer.FetchServerTimestamp(); } } public static void SendOutgoingCommands() { if (VerifyCanUseNetwork()) { while (networkingPeer.SendOutgoingCommands()) { } } } public static bool CloseConnection(PhotonPlayer kickPlayer) { if (!VerifyCanUseNetwork()) { return false; } if (!player.IsMasterClient) { UnityEngine.Debug.LogError("CloseConnection: Only the masterclient can kick another player."); return false; } if (kickPlayer == null) { UnityEngine.Debug.LogError("CloseConnection: No such player connected!"); return false; } RaiseEventOptions raiseEventOptions = new RaiseEventOptions(); raiseEventOptions.TargetActors = new int[1] { kickPlayer.ID }; RaiseEventOptions raiseEventOptions2 = raiseEventOptions; return networkingPeer.OpRaiseEvent(203, null, true, raiseEventOptions2); } public static bool SetMasterClient(PhotonPlayer masterClientPlayer) { if (!inRoom || !VerifyCanUseNetwork() || offlineMode) { if (logLevel == PhotonLogLevel.Informational) { UnityEngine.Debug.Log("Can not SetMasterClient(). Not in room or in offlineMode."); } return false; } if (room.serverSideMasterClient) { Hashtable hashtable = new Hashtable(); hashtable.Add((byte)248, masterClientPlayer.ID); Hashtable gameProperties = hashtable; hashtable = new Hashtable(); hashtable.Add((byte)248, networkingPeer.mMasterClientId); Hashtable expectedProperties = hashtable; return networkingPeer.OpSetPropertiesOfRoom(gameProperties, expectedProperties); } if (!isMasterClient) { return false; } return networkingPeer.SetMasterClient(masterClientPlayer.ID, true); } public static void Destroy(PhotonView targetView) { if (targetView != null) { networkingPeer.RemoveInstantiatedGO(targetView.gameObject, !inRoom); } else { UnityEngine.Debug.LogError("Destroy(targetPhotonView) failed, cause targetPhotonView is null."); } } public static void Destroy(GameObject targetGo) { networkingPeer.RemoveInstantiatedGO(targetGo, !inRoom); } public static void DestroyPlayerObjects(PhotonPlayer targetPlayer) { if (player == null) { UnityEngine.Debug.LogError("DestroyPlayerObjects() failed, cause parameter 'targetPlayer' was null."); } DestroyPlayerObjects(targetPlayer.ID); } public static void DestroyPlayerObjects(int targetPlayerId) { if (VerifyCanUseNetwork()) { if (player.IsMasterClient || targetPlayerId == player.ID) { networkingPeer.DestroyPlayerObjects(targetPlayerId, false); } else { UnityEngine.Debug.LogError("DestroyPlayerObjects() failed, cause players can only destroy their own GameObjects. A Master Client can destroy anyone's. This is master: " + isMasterClient); } } } public static void DestroyAll() { if (isMasterClient) { networkingPeer.DestroyAll(false); } else { UnityEngine.Debug.LogError("Couldn't call DestroyAll() as only the master client is allowed to call this."); } } public static void RemoveRPCs(PhotonPlayer targetPlayer) { if (VerifyCanUseNetwork()) { if (!targetPlayer.IsLocal && !isMasterClient) { UnityEngine.Debug.LogError("Error; Only the MasterClient can call RemoveRPCs for other players."); } else { networkingPeer.OpCleanRpcBuffer(targetPlayer.ID); } } } public static void RemoveRPCs(PhotonView targetPhotonView) { if (VerifyCanUseNetwork()) { networkingPeer.CleanRpcBufferIfMine(targetPhotonView); } } public static void RemoveRPCsInGroup(int targetGroup) { if (VerifyCanUseNetwork()) { networkingPeer.RemoveRPCsInGroup(targetGroup); } } internal static void RPC(PhotonView view, string methodName, PhotonTargets target, bool encrypt, params object[] parameters) { if (!VerifyCanUseNetwork()) { return; } if (room == null) { UnityEngine.Debug.LogWarning("RPCs can only be sent in rooms. Call of \"" + methodName + "\" gets executed locally only, if at all."); } else if (networkingPeer != null) { if (room.serverSideMasterClient) { networkingPeer.RPC(view, methodName, target, null, encrypt, parameters); } else if (networkingPeer.hasSwitchedMC && target == PhotonTargets.MasterClient) { networkingPeer.RPC(view, methodName, PhotonTargets.Others, masterClient, encrypt, parameters); } else { networkingPeer.RPC(view, methodName, target, null, encrypt, parameters); } } else { UnityEngine.Debug.LogWarning("Could not execute RPC " + methodName + ". Possible scene loading in progress?"); } } internal static void RPC(PhotonView view, string methodName, PhotonPlayer targetPlayer, bool encrpyt, params object[] parameters) { if (!VerifyCanUseNetwork()) { return; } if (room == null) { UnityEngine.Debug.LogWarning("RPCs can only be sent in rooms. Call of \"" + methodName + "\" gets executed locally only, if at all."); return; } if (player == null) { UnityEngine.Debug.LogError("RPC can't be sent to target PhotonPlayer being null! Did not send \"" + methodName + "\" call."); } if (networkingPeer != null) { networkingPeer.RPC(view, methodName, PhotonTargets.Others, targetPlayer, encrpyt, parameters); } else { UnityEngine.Debug.LogWarning("Could not execute RPC " + methodName + ". Possible scene loading in progress?"); } } public static void CacheSendMonoMessageTargets(Type type) { if (type == null) { type = SendMonoMessageTargetType; } SendMonoMessageTargets = FindGameObjectsWithComponent(type); } public static HashSet FindGameObjectsWithComponent(Type type) { HashSet hashSet = new HashSet(); Component[] array = (Component[])UnityEngine.Object.FindObjectsOfType(type); for (int i = 0; i < array.Length; i++) { if (array[i] != null) { hashSet.Add(array[i].gameObject); } } return hashSet; } [Obsolete("Use SetInterestGroups(byte group, bool enabled) instead.")] public static void SetReceivingEnabled(int group, bool enabled) { if (VerifyCanUseNetwork()) { SetInterestGroups((byte)group, enabled); } } public static void SetInterestGroups(byte group, bool enabled) { if (VerifyCanUseNetwork()) { if (enabled) { byte[] enableGroups = new byte[1] { group }; networkingPeer.SetInterestGroups(null, enableGroups); } else { byte[] disableGroups = new byte[1] { group }; networkingPeer.SetInterestGroups(disableGroups, null); } } } [Obsolete("Use SetInterestGroups(byte[] disableGroups, byte[] enableGroups) instead. Mind the parameter order!")] public static void SetReceivingEnabled(int[] enableGroups, int[] disableGroups) { if (VerifyCanUseNetwork()) { byte[] array = null; byte[] array2 = null; if (enableGroups != null) { array2 = new byte[enableGroups.Length]; Array.Copy(enableGroups, array2, enableGroups.Length); } if (disableGroups != null) { array = new byte[disableGroups.Length]; Array.Copy(disableGroups, array, disableGroups.Length); } networkingPeer.SetInterestGroups(array, array2); } } public static void SetInterestGroups(byte[] disableGroups, byte[] enableGroups) { if (VerifyCanUseNetwork()) { networkingPeer.SetInterestGroups(disableGroups, enableGroups); } } [Obsolete("Use SetSendingEnabled(byte group, bool enabled). Interest Groups have a byte-typed ID. Mind the parameter order.")] public static void SetSendingEnabled(int group, bool enabled) { SetSendingEnabled((byte)group, enabled); } public static void SetSendingEnabled(byte group, bool enabled) { if (VerifyCanUseNetwork()) { networkingPeer.SetSendingEnabled(group, enabled); } } [Obsolete("Use SetSendingEnabled(byte group, bool enabled). Interest Groups have a byte-typed ID. Mind the parameter order.")] public static void SetSendingEnabled(int[] enableGroups, int[] disableGroups) { byte[] array = null; byte[] array2 = null; if (enableGroups != null) { array2 = new byte[enableGroups.Length]; Array.Copy(enableGroups, array2, enableGroups.Length); } if (disableGroups != null) { array = new byte[disableGroups.Length]; Array.Copy(disableGroups, array, disableGroups.Length); } SetSendingEnabled(array, array2); } public static void SetSendingEnabled(byte[] disableGroups, byte[] enableGroups) { if (VerifyCanUseNetwork()) { networkingPeer.SetSendingEnabled(disableGroups, enableGroups); } } public static void SetLevelPrefix(short prefix) { if (VerifyCanUseNetwork()) { networkingPeer.SetLevelPrefix(prefix); } } public static void LoadLevel(int levelNumber) { networkingPeer.SetLevelInPropsIfSynced(levelNumber); isMessageQueueRunning = false; networkingPeer.loadingLevelAndPausedNetwork = true; SceneManager.LoadScene(levelNumber); } public static void LoadLevel(string levelName) { networkingPeer.SetLevelInPropsIfSynced(levelName); isMessageQueueRunning = false; networkingPeer.loadingLevelAndPausedNetwork = true; SceneManager.LoadScene(levelName); } public static bool WebRpc(string name, object parameters) { return networkingPeer.WebRpc(name, parameters); } }