using ExitGames.Client.Photon; using System; using System.Collections; using System.Collections.Generic; using System.Reflection; using UnityEngine; internal class NetworkingPeer : LoadBalancingPeer, IPhotonPeerListener { protected internal string AppId; private string tokenCache; public AuthModeOption AuthMode; public EncryptionMode EncryptionMode; public const string NameServerHost = "ns.exitgames.com"; public const string NameServerHttp = "http://ns.exitgamescloud.com:80/photon/n"; private static readonly Dictionary ProtocolToNameServerPort = new Dictionary { { ConnectionProtocol.Udp, 5058 }, { ConnectionProtocol.Tcp, 4533 }, { ConnectionProtocol.WebSocket, 9093 }, { ConnectionProtocol.WebSocketSecure, 19093 } }; public bool IsInitialConnect; public bool insideLobby; protected internal List LobbyStatistics = new List(); public Dictionary mGameList = new Dictionary(); public RoomInfo[] mGameListCopy = new RoomInfo[0]; private string playername = string.Empty; private bool mPlayernameHasToBeUpdated; private Room currentRoom; private JoinType lastJoinType; protected internal EnterRoomParams enterRoomParamsCache; private bool didAuthenticate; private string[] friendListRequested; private int friendListTimestamp; private bool isFetchingFriendList; public Dictionary mActors = new Dictionary(); public PhotonPlayer[] mOtherPlayerListCopy = new PhotonPlayer[0]; public PhotonPlayer[] mPlayerListCopy = new PhotonPlayer[0]; public bool hasSwitchedMC; private HashSet allowedReceivingGroups = new HashSet(); private HashSet blockSendingGroups = new HashSet(); protected internal Dictionary photonViewList = new Dictionary(); private readonly PhotonStream readStream = new PhotonStream(write: false, null); private readonly PhotonStream pStream = new PhotonStream(write: true, null); private readonly Dictionary dataPerGroupReliable = new Dictionary(); private readonly Dictionary dataPerGroupUnreliable = new Dictionary(); protected internal short currentLevelPrefix; protected internal bool loadingLevelAndPausedNetwork; protected internal const string CurrentSceneProperty = "curScn"; public static bool UsePrefabCache = true; internal IPunPrefabPool ObjectPool; public static Dictionary PrefabCache = new Dictionary(); private Dictionary> monoRPCMethodsCache = new Dictionary>(); private readonly Dictionary rpcShortcuts; private static readonly string OnPhotonInstantiateString = 18.ToString(); private Dictionary tempInstantiationData = new Dictionary(); public static int ObjectsInOneUpdate = 10; public const int SyncViewId = 0; public const int SyncCompressed = 1; public const int SyncNullValues = 2; public const int SyncFirstValue = 3; protected internal string AppVersion => string.Format("{0}_{1}", PhotonNetwork.gameVersion, "1.80"); public AuthenticationValues AuthValues { get; set; } private string TokenForInit { get { if (AuthMode == AuthModeOption.Auth) { return null; } return (AuthValues == null) ? null : AuthValues.Token; } } public bool IsUsingNameServer { get; protected internal set; } public string NameServerAddress => GetNameServerAddress(); public string MasterServerAddress { get; protected internal set; } public string GameServerAddress { get; protected internal set; } protected internal ServerConnection Server { get; private set; } public ClientState State { get; internal set; } public TypedLobby lobby { get; set; } private bool requestLobbyStatistics => PhotonNetwork.EnableLobbyStatistics && Server == ServerConnection.MasterServer; public string PlayerName { get { return playername; } set { if (!string.IsNullOrEmpty(value) && !value.Equals(playername)) { if (LocalPlayer != null) { LocalPlayer.NickName = value; } playername = value; if (CurrentRoom != null) { SendPlayerName(); } } } } public Room CurrentRoom { get { if (currentRoom != null && currentRoom.IsLocalClientInside) { return currentRoom; } return null; } private set { currentRoom = value; } } public PhotonPlayer LocalPlayer { get; internal set; } public int PlayersOnMasterCount { get; internal set; } public int PlayersInRoomsCount { get; internal set; } public int RoomsCount { get; internal set; } protected internal int FriendListAge => (!isFetchingFriendList && friendListTimestamp != 0) ? (Environment.TickCount - friendListTimestamp) : 0; public bool IsAuthorizeSecretAvailable => AuthValues != null && !string.IsNullOrEmpty(AuthValues.Token); public List AvailableRegions { get; protected internal set; } public CloudRegionCode CloudRegion { get; protected internal set; } public int mMasterClientId { get { if (PhotonNetwork.offlineMode) { return LocalPlayer.ID; } return (CurrentRoom != null) ? CurrentRoom.MasterClientId : 0; } private set { if (CurrentRoom != null) { CurrentRoom.MasterClientId = value; } } } public NetworkingPeer(string playername, ConnectionProtocol connectionProtocol) : base(connectionProtocol) { base.Listener = this; base.LimitOfUnreliableCommands = 40; lobby = TypedLobby.Default; PlayerName = playername; LocalPlayer = new PhotonPlayer(isLocal: true, -1, this.playername); AddNewPlayer(LocalPlayer.ID, LocalPlayer); rpcShortcuts = new Dictionary(PhotonNetwork.PhotonServerSettings.RpcList.Count); for (int i = 0; i < PhotonNetwork.PhotonServerSettings.RpcList.Count; i++) { string key = PhotonNetwork.PhotonServerSettings.RpcList[i]; rpcShortcuts[key] = i; } State = ClientState.PeerCreated; } private string GetNameServerAddress() { ConnectionProtocol transportProtocol = base.TransportProtocol; int value = 0; ProtocolToNameServerPort.TryGetValue(transportProtocol, out value); string arg = string.Empty; switch (transportProtocol) { case ConnectionProtocol.WebSocket: arg = "ws://"; break; case ConnectionProtocol.WebSocketSecure: arg = "wss://"; break; } return string.Format("{0}{1}:{2}", arg, "ns.exitgames.com", value); } public override bool Connect(string serverAddress, string applicationName) { Debug.LogError("Avoid using this directly. Thanks."); return false; } public bool ReconnectToMaster() { if (AuthValues == null) { Debug.LogWarning("ReconnectToMaster() with AuthValues == null is not correct!"); AuthValues = new AuthenticationValues(); } AuthValues.Token = tokenCache; return Connect(MasterServerAddress, ServerConnection.MasterServer); } public bool ReconnectAndRejoin() { if (AuthValues == null) { Debug.LogWarning("ReconnectAndRejoin() with AuthValues == null is not correct!"); AuthValues = new AuthenticationValues(); } AuthValues.Token = tokenCache; if (!string.IsNullOrEmpty(GameServerAddress) && enterRoomParamsCache != null) { lastJoinType = JoinType.JoinRoom; enterRoomParamsCache.RejoinOnly = true; return Connect(GameServerAddress, ServerConnection.GameServer); } return false; } public bool Connect(string serverAddress, ServerConnection type) { if (PhotonHandler.AppQuits) { Debug.LogWarning("Ignoring Connect() because app gets closed. If this is an error, check PhotonHandler.AppQuits."); return false; } if (State == ClientState.Disconnecting) { Debug.LogError("Connect() failed. Can't connect while disconnecting (still). Current state: " + PhotonNetwork.connectionStateDetailed); return false; } SetupProtocol(type); bool flag = base.Connect(serverAddress, string.Empty, TokenForInit); if (flag) { switch (type) { case ServerConnection.NameServer: State = ClientState.ConnectingToNameServer; break; case ServerConnection.MasterServer: State = ClientState.ConnectingToMasterserver; break; case ServerConnection.GameServer: State = ClientState.ConnectingToGameserver; break; } } return flag; } public bool ConnectToNameServer() { if (PhotonHandler.AppQuits) { Debug.LogWarning("Ignoring Connect() because app gets closed. If this is an error, check PhotonHandler.AppQuits."); return false; } IsUsingNameServer = true; CloudRegion = CloudRegionCode.none; if (State == ClientState.ConnectedToNameServer) { return true; } SetupProtocol(ServerConnection.NameServer); if (!base.Connect(NameServerAddress, "ns", TokenForInit)) { return false; } State = ClientState.ConnectingToNameServer; return true; } public bool ConnectToRegionMaster(CloudRegionCode region) { if (PhotonHandler.AppQuits) { Debug.LogWarning("Ignoring Connect() because app gets closed. If this is an error, check PhotonHandler.AppQuits."); return false; } IsUsingNameServer = true; CloudRegion = region; if (State == ClientState.ConnectedToNameServer) { return CallAuthenticate(); } SetupProtocol(ServerConnection.NameServer); if (!base.Connect(NameServerAddress, "ns", TokenForInit)) { return false; } State = ClientState.ConnectingToNameServer; return true; } protected internal void SetupProtocol(ServerConnection serverType) { ConnectionProtocol connectionProtocol = base.TransportProtocol; if (AuthMode == AuthModeOption.AuthOnceWss) { if (serverType != ServerConnection.NameServer) { if (PhotonNetwork.logLevel >= PhotonLogLevel.ErrorsOnly) { Debug.LogWarning("Using PhotonServerSettings.Protocol when leaving the NameServer (AuthMode is AuthOnceWss): " + PhotonNetwork.PhotonServerSettings.Protocol); } connectionProtocol = PhotonNetwork.PhotonServerSettings.Protocol; } else { if (PhotonNetwork.logLevel >= PhotonLogLevel.ErrorsOnly) { Debug.LogWarning("Using WebSocket to connect NameServer (AuthMode is AuthOnceWss)."); } connectionProtocol = ConnectionProtocol.WebSocketSecure; } } Type type = Type.GetType("ExitGames.Client.Photon.SocketWebTcp, Assembly-CSharp", throwOnError: false); if (type == null) { type = Type.GetType("ExitGames.Client.Photon.SocketWebTcp, Assembly-CSharp-firstpass", throwOnError: false); } if (type != null) { SocketImplementationConfig[ConnectionProtocol.WebSocket] = type; SocketImplementationConfig[ConnectionProtocol.WebSocketSecure] = type; } if (PhotonHandler.PingImplementation == null) { PhotonHandler.PingImplementation = typeof(PingMono); } if (base.TransportProtocol != connectionProtocol) { if (PhotonNetwork.logLevel >= PhotonLogLevel.ErrorsOnly) { Debug.LogWarning("Protocol switch from: " + base.TransportProtocol + " to: " + connectionProtocol + "."); } base.TransportProtocol = connectionProtocol; } } public override void Disconnect() { if (base.PeerState == PeerStateValue.Disconnected) { if (!PhotonHandler.AppQuits) { Debug.LogWarning($"Can't execute Disconnect() while not connected. Nothing changed. State: {State}"); } } else { State = ClientState.Disconnecting; base.Disconnect(); } } private bool CallAuthenticate() { object authenticationValues = AuthValues; if (authenticationValues == null) { AuthenticationValues authenticationValues2 = new AuthenticationValues(); authenticationValues2.UserId = PlayerName; authenticationValues = authenticationValues2; } AuthenticationValues authValues = (AuthenticationValues)authenticationValues; if (AuthMode == AuthModeOption.Auth) { return OpAuthenticate(AppId, AppVersion, authValues, CloudRegion.ToString(), requestLobbyStatistics); } return OpAuthenticateOnce(AppId, AppVersion, authValues, CloudRegion.ToString(), EncryptionMode, PhotonNetwork.PhotonServerSettings.Protocol); } private void DisconnectToReconnect() { switch (Server) { case ServerConnection.NameServer: State = ClientState.DisconnectingFromNameServer; base.Disconnect(); break; case ServerConnection.MasterServer: State = ClientState.DisconnectingFromMasterserver; base.Disconnect(); break; case ServerConnection.GameServer: State = ClientState.DisconnectingFromGameserver; base.Disconnect(); break; } } public bool GetRegions() { if (Server != ServerConnection.NameServer) { return false; } bool flag = OpGetRegions(AppId); if (flag) { AvailableRegions = null; } return flag; } public override bool OpFindFriends(string[] friendsToFind) { if (isFetchingFriendList) { return false; } friendListRequested = friendsToFind; isFetchingFriendList = true; return base.OpFindFriends(friendsToFind); } public bool OpCreateGame(EnterRoomParams enterRoomParams) { bool flag = enterRoomParams.OnGameServer = (Server == ServerConnection.GameServer); enterRoomParams.PlayerProperties = GetLocalActorProperties(); if (!flag) { enterRoomParamsCache = enterRoomParams; } lastJoinType = JoinType.CreateRoom; return base.OpCreateRoom(enterRoomParams); } public override bool OpJoinRoom(EnterRoomParams opParams) { if (!(opParams.OnGameServer = (Server == ServerConnection.GameServer))) { enterRoomParamsCache = opParams; } lastJoinType = ((!opParams.CreateIfNotExists) ? JoinType.JoinRoom : JoinType.JoinOrCreateRoom); return base.OpJoinRoom(opParams); } public override bool OpJoinRandomRoom(OpJoinRandomRoomParams opJoinRandomRoomParams) { enterRoomParamsCache = new EnterRoomParams(); enterRoomParamsCache.Lobby = opJoinRandomRoomParams.TypedLobby; enterRoomParamsCache.ExpectedUsers = opJoinRandomRoomParams.ExpectedUsers; lastJoinType = JoinType.JoinRandomRoom; return base.OpJoinRandomRoom(opJoinRandomRoomParams); } public virtual bool OpLeave() { if (State != ClientState.Joined) { Debug.LogWarning("Not sending leave operation. State is not 'Joined': " + State); return false; } return OpCustom(254, null, sendReliable: true, 0); } public override bool OpRaiseEvent(byte eventCode, object customEventContent, bool sendReliable, RaiseEventOptions raiseEventOptions) { if (PhotonNetwork.offlineMode) { return false; } return base.OpRaiseEvent(eventCode, customEventContent, sendReliable, raiseEventOptions); } private void ReadoutProperties(ExitGames.Client.Photon.Hashtable gameProperties, ExitGames.Client.Photon.Hashtable pActorProperties, int targetActorNr) { if (pActorProperties != null && pActorProperties.Count > 0) { if (targetActorNr > 0) { PhotonPlayer playerWithId = GetPlayerWithId(targetActorNr); if (playerWithId != null) { ExitGames.Client.Photon.Hashtable hashtable = ReadoutPropertiesForActorNr(pActorProperties, targetActorNr); playerWithId.InternalCacheProperties(hashtable); SendMonoMessage(PhotonNetworkingMessage.OnPhotonPlayerPropertiesChanged, playerWithId, hashtable); } } else { foreach (object key in pActorProperties.Keys) { int num = (int)key; ExitGames.Client.Photon.Hashtable hashtable2 = (ExitGames.Client.Photon.Hashtable)pActorProperties[key]; string name = (string)hashtable2[(byte)byte.MaxValue]; PhotonPlayer photonPlayer = GetPlayerWithId(num); if (photonPlayer == null) { photonPlayer = new PhotonPlayer(isLocal: false, num, name); AddNewPlayer(num, photonPlayer); } photonPlayer.InternalCacheProperties(hashtable2); SendMonoMessage(PhotonNetworkingMessage.OnPhotonPlayerPropertiesChanged, photonPlayer, hashtable2); } } } if (CurrentRoom != null && gameProperties != null) { CurrentRoom.InternalCacheProperties(gameProperties); SendMonoMessage(PhotonNetworkingMessage.OnPhotonCustomRoomPropertiesChanged, gameProperties); if (PhotonNetwork.automaticallySyncScene) { LoadLevelIfSynced(); } } } private ExitGames.Client.Photon.Hashtable ReadoutPropertiesForActorNr(ExitGames.Client.Photon.Hashtable actorProperties, int actorNr) { if (actorProperties.ContainsKey(actorNr)) { return (ExitGames.Client.Photon.Hashtable)actorProperties[actorNr]; } return actorProperties; } public void ChangeLocalID(int newID) { if (LocalPlayer == null) { Debug.LogWarning($"LocalPlayer is null or not in mActors! LocalPlayer: {LocalPlayer} mActors==null: {mActors == null} newID: {newID}"); } if (mActors.ContainsKey(LocalPlayer.ID)) { mActors.Remove(LocalPlayer.ID); } LocalPlayer.InternalChangeLocalID(newID); mActors[LocalPlayer.ID] = LocalPlayer; RebuildPlayerListCopies(); } private void LeftLobbyCleanup() { mGameList = new Dictionary(); mGameListCopy = new RoomInfo[0]; if (insideLobby) { insideLobby = false; SendMonoMessage(PhotonNetworkingMessage.OnLeftLobby); } } private void LeftRoomCleanup() { bool flag = CurrentRoom != null; bool flag2 = (CurrentRoom == null) ? PhotonNetwork.autoCleanUpPlayerObjects : CurrentRoom.AutoCleanUp; hasSwitchedMC = false; CurrentRoom = null; mActors = new Dictionary(); mPlayerListCopy = new PhotonPlayer[0]; mOtherPlayerListCopy = new PhotonPlayer[0]; allowedReceivingGroups = new HashSet(); blockSendingGroups = new HashSet(); mGameList = new Dictionary(); mGameListCopy = new RoomInfo[0]; isFetchingFriendList = false; ChangeLocalID(-1); if (flag2) { LocalCleanupAnythingInstantiated(destroyInstantiatedGameObjects: true); PhotonNetwork.manuallyAllocatedViewIds = new List(); } if (flag) { SendMonoMessage(PhotonNetworkingMessage.OnLeftRoom); } } protected internal void LocalCleanupAnythingInstantiated(bool destroyInstantiatedGameObjects) { if (tempInstantiationData.Count > 0) { Debug.LogWarning("It seems some instantiation is not completed, as instantiation data is used. You should make sure instantiations are paused when calling this method. Cleaning now, despite this."); } if (destroyInstantiatedGameObjects) { HashSet hashSet = new HashSet(); foreach (PhotonView value in photonViewList.Values) { if (value.isRuntimeInstantiated) { hashSet.Add(value.gameObject); } } foreach (GameObject item in hashSet) { RemoveInstantiatedGO(item, localOnly: true); } } tempInstantiationData.Clear(); PhotonNetwork.lastUsedViewSubId = 0; PhotonNetwork.lastUsedViewSubIdStatic = 0; } private void GameEnteredOnGameServer(OperationResponse operationResponse) { if (operationResponse.ReturnCode != 0) { switch (operationResponse.OperationCode) { case 227: if (PhotonNetwork.logLevel >= PhotonLogLevel.Informational) { Debug.Log("Create failed on GameServer. Changing back to MasterServer. Msg: " + operationResponse.DebugMessage); } SendMonoMessage(PhotonNetworkingMessage.OnPhotonCreateRoomFailed, operationResponse.ReturnCode, operationResponse.DebugMessage); break; case 226: if (PhotonNetwork.logLevel >= PhotonLogLevel.Informational) { Debug.Log("Join failed on GameServer. Changing back to MasterServer. Msg: " + operationResponse.DebugMessage); if (operationResponse.ReturnCode == 32758) { Debug.Log("Most likely the game became empty during the switch to GameServer."); } } SendMonoMessage(PhotonNetworkingMessage.OnPhotonJoinRoomFailed, operationResponse.ReturnCode, operationResponse.DebugMessage); break; case 225: if (PhotonNetwork.logLevel >= PhotonLogLevel.Informational) { Debug.Log("Join failed on GameServer. Changing back to MasterServer. Msg: " + operationResponse.DebugMessage); if (operationResponse.ReturnCode == 32758) { Debug.Log("Most likely the game became empty during the switch to GameServer."); } } SendMonoMessage(PhotonNetworkingMessage.OnPhotonRandomJoinFailed, operationResponse.ReturnCode, operationResponse.DebugMessage); break; } DisconnectToReconnect(); } else { Room room = new Room(enterRoomParamsCache.RoomName, null); room.IsLocalClientInside = true; CurrentRoom = room; State = ClientState.Joined; if (operationResponse.Parameters.ContainsKey(252)) { int[] actorsInRoom = (int[])operationResponse.Parameters[252]; UpdatedActorList(actorsInRoom); } int newID = (int)operationResponse[254]; ChangeLocalID(newID); ExitGames.Client.Photon.Hashtable pActorProperties = (ExitGames.Client.Photon.Hashtable)operationResponse[249]; ExitGames.Client.Photon.Hashtable gameProperties = (ExitGames.Client.Photon.Hashtable)operationResponse[248]; ReadoutProperties(gameProperties, pActorProperties, 0); if (!CurrentRoom.serverSideMasterClient) { CheckMasterClient(-1); } if (mPlayernameHasToBeUpdated) { SendPlayerName(); } switch (operationResponse.OperationCode) { case 227: SendMonoMessage(PhotonNetworkingMessage.OnCreatedRoom); break; } } } private void AddNewPlayer(int ID, PhotonPlayer player) { if (!mActors.ContainsKey(ID)) { mActors[ID] = player; RebuildPlayerListCopies(); } else { Debug.LogError("Adding player twice: " + ID); } } private void RemovePlayer(int ID, PhotonPlayer player) { mActors.Remove(ID); if (!player.IsLocal) { RebuildPlayerListCopies(); } } private void RebuildPlayerListCopies() { mPlayerListCopy = new PhotonPlayer[mActors.Count]; mActors.Values.CopyTo(mPlayerListCopy, 0); List list = new List(); for (int i = 0; i < mPlayerListCopy.Length; i++) { PhotonPlayer photonPlayer = mPlayerListCopy[i]; if (!photonPlayer.IsLocal) { list.Add(photonPlayer); } } mOtherPlayerListCopy = list.ToArray(); } private void ResetPhotonViewsOnSerialize() { foreach (PhotonView value in photonViewList.Values) { value.lastOnSerializeDataSent = null; } } private void HandleEventLeave(int actorID, EventData evLeave) { if (PhotonNetwork.logLevel >= PhotonLogLevel.Informational) { Debug.Log("HandleEventLeave for player ID: " + actorID + " evLeave: " + evLeave.ToStringFull()); } PhotonPlayer playerWithId = GetPlayerWithId(actorID); if (playerWithId == null) { Debug.LogError($"Received event Leave for unknown player ID: {actorID}"); } else { bool isInactive = playerWithId.IsInactive; if (evLeave.Parameters.ContainsKey(233)) { playerWithId.IsInactive = (bool)evLeave.Parameters[233]; if (playerWithId.IsInactive && isInactive) { Debug.LogWarning("HandleEventLeave for player ID: " + actorID + " isInactive: " + playerWithId.IsInactive + ". Stopping handling if inactive."); return; } } if (evLeave.Parameters.ContainsKey(203)) { if ((int)evLeave[203] != 0) { mMasterClientId = (int)evLeave[203]; UpdateMasterClient(); } } else if (!CurrentRoom.serverSideMasterClient) { CheckMasterClient(actorID); } if (!playerWithId.IsInactive || isInactive) { if (CurrentRoom != null && CurrentRoom.AutoCleanUp) { DestroyPlayerObjects(actorID, localOnly: true); } RemovePlayer(actorID, playerWithId); SendMonoMessage(PhotonNetworkingMessage.OnPhotonPlayerDisconnected, playerWithId); } } } private void CheckMasterClient(int leavingPlayerId) { bool flag = mMasterClientId == leavingPlayerId; bool flag2 = leavingPlayerId > 0; if (!flag2 || flag) { int num; if (mActors.Count <= 1) { num = LocalPlayer.ID; } else { num = 2147483647; foreach (int key in mActors.Keys) { if (key < num && key != leavingPlayerId) { num = key; } } } mMasterClientId = num; if (flag2) { SendMonoMessage(PhotonNetworkingMessage.OnMasterClientSwitched, GetPlayerWithId(num)); } } } protected internal void UpdateMasterClient() { SendMonoMessage(PhotonNetworkingMessage.OnMasterClientSwitched, PhotonNetwork.masterClient); } private static int ReturnLowestPlayerId(PhotonPlayer[] players, int playerIdToIgnore) { if (players == null || players.Length == 0) { return -1; } int num = 2147483647; foreach (PhotonPlayer photonPlayer in players) { if (photonPlayer.ID != playerIdToIgnore && photonPlayer.ID < num) { num = photonPlayer.ID; } } return num; } protected internal bool SetMasterClient(int playerId, bool sync) { if (mMasterClientId == playerId || !mActors.ContainsKey(playerId)) { return false; } if (sync && !OpRaiseEvent(208, new ExitGames.Client.Photon.Hashtable { { (byte)1, playerId } }, sendReliable: true, null)) { return false; } hasSwitchedMC = true; CurrentRoom.MasterClientId = playerId; SendMonoMessage(PhotonNetworkingMessage.OnMasterClientSwitched, GetPlayerWithId(playerId)); return true; } public bool SetMasterClient(int nextMasterId) { ExitGames.Client.Photon.Hashtable hashtable = new ExitGames.Client.Photon.Hashtable(); hashtable.Add((byte)248, nextMasterId); ExitGames.Client.Photon.Hashtable gameProperties = hashtable; hashtable = new ExitGames.Client.Photon.Hashtable(); hashtable.Add((byte)248, mMasterClientId); ExitGames.Client.Photon.Hashtable expectedProperties = hashtable; return OpSetPropertiesOfRoom(gameProperties, expectedProperties); } protected internal PhotonPlayer GetPlayerWithId(int number) { if (mActors == null) { return null; } PhotonPlayer value = null; mActors.TryGetValue(number, out value); return value; } private void SendPlayerName() { if (State == ClientState.Joining) { mPlayernameHasToBeUpdated = true; } else if (LocalPlayer != null) { LocalPlayer.NickName = PlayerName; ExitGames.Client.Photon.Hashtable hashtable = new ExitGames.Client.Photon.Hashtable(); hashtable[(byte)byte.MaxValue] = PlayerName; if (LocalPlayer.ID > 0) { OpSetPropertiesOfActor(LocalPlayer.ID, hashtable); mPlayernameHasToBeUpdated = false; } } } private ExitGames.Client.Photon.Hashtable GetLocalActorProperties() { if (PhotonNetwork.player != null) { return PhotonNetwork.player.AllProperties; } ExitGames.Client.Photon.Hashtable hashtable = new ExitGames.Client.Photon.Hashtable(); hashtable[(byte)byte.MaxValue] = PlayerName; return hashtable; } public void DebugReturn(DebugLevel level, string message) { switch (level) { case DebugLevel.ERROR: Debug.LogError(message); return; case DebugLevel.WARNING: Debug.LogWarning(message); return; case DebugLevel.INFO: if (PhotonNetwork.logLevel >= PhotonLogLevel.Informational) { Debug.Log(message); return; } break; } if (level == DebugLevel.ALL && PhotonNetwork.logLevel == PhotonLogLevel.Full) { Debug.Log(message); } } public void OnOperationResponse(OperationResponse operationResponse) { if (PhotonNetwork.networkingPeer.State == ClientState.Disconnecting) { if (PhotonNetwork.logLevel >= PhotonLogLevel.Informational) { Debug.Log("OperationResponse ignored while disconnecting. Code: " + operationResponse.OperationCode); } } else { if (operationResponse.ReturnCode == 0) { if (PhotonNetwork.logLevel >= PhotonLogLevel.Informational) { Debug.Log(operationResponse.ToString()); } } else if (operationResponse.ReturnCode == -3) { Debug.LogError("Operation " + operationResponse.OperationCode + " could not be executed (yet). Wait for state JoinedLobby or ConnectedToMaster and their callbacks before calling operations. WebRPCs need a server-side configuration. Enum OperationCode helps identify the operation."); } else if (operationResponse.ReturnCode == 32752) { Debug.LogError("Operation " + operationResponse.OperationCode + " failed in a server-side plugin. Check the configuration in the Dashboard. Message from server-plugin: " + operationResponse.DebugMessage); } else if (operationResponse.ReturnCode == 32760) { Debug.LogWarning("Operation failed: " + operationResponse.ToStringFull()); } else { Debug.LogError("Operation failed: " + operationResponse.ToStringFull() + " Server: " + Server); } if (operationResponse.Parameters.ContainsKey(221)) { if (AuthValues == null) { AuthValues = new AuthenticationValues(); } AuthValues.Token = (operationResponse[221] as string); tokenCache = AuthValues.Token; } switch (operationResponse.OperationCode) { case 252: case 253: break; case 230: case 231: if (operationResponse.ReturnCode != 0) { if (operationResponse.ReturnCode == -2) { Debug.LogError(string.Format("If you host Photon yourself, make sure to start the 'Instance LoadBalancing' " + base.ServerAddress)); } else if (operationResponse.ReturnCode == 32767) { Debug.LogError($"The appId this client sent is unknown on the server (Cloud). Check settings. If using the Cloud, check account."); SendMonoMessage(PhotonNetworkingMessage.OnFailedToConnectToPhoton, DisconnectCause.InvalidAuthentication); } else if (operationResponse.ReturnCode == 32755) { Debug.LogError($"Custom Authentication failed (either due to user-input or configuration or AuthParameter string format). Calling: OnCustomAuthenticationFailed()"); SendMonoMessage(PhotonNetworkingMessage.OnCustomAuthenticationFailed, operationResponse.DebugMessage); } else { Debug.LogError($"Authentication failed: '{operationResponse.DebugMessage}' Code: {operationResponse.ReturnCode}"); } State = ClientState.Disconnecting; Disconnect(); if (operationResponse.ReturnCode == 32757) { if (PhotonNetwork.logLevel >= PhotonLogLevel.Informational) { Debug.LogWarning($"Currently, the limit of users is reached for this title. Try again later. Disconnecting"); } SendMonoMessage(PhotonNetworkingMessage.OnPhotonMaxCccuReached); SendMonoMessage(PhotonNetworkingMessage.OnConnectionFail, DisconnectCause.MaxCcuReached); } else if (operationResponse.ReturnCode == 32756) { if (PhotonNetwork.logLevel >= PhotonLogLevel.Informational) { Debug.LogError($"The used master server address is not available with the subscription currently used. Got to Photon Cloud Dashboard or change URL. Disconnecting."); } SendMonoMessage(PhotonNetworkingMessage.OnConnectionFail, DisconnectCause.InvalidRegion); } else if (operationResponse.ReturnCode == 32753) { if (PhotonNetwork.logLevel >= PhotonLogLevel.Informational) { Debug.LogError($"The authentication ticket expired. You need to connect (and authenticate) again. Disconnecting."); } SendMonoMessage(PhotonNetworkingMessage.OnConnectionFail, DisconnectCause.AuthenticationTicketExpired); } } else { if (Server == ServerConnection.NameServer || Server == ServerConnection.MasterServer) { if (operationResponse.Parameters.ContainsKey(225)) { string text = (string)operationResponse.Parameters[225]; if (!string.IsNullOrEmpty(text)) { if (AuthValues == null) { AuthValues = new AuthenticationValues(); } AuthValues.UserId = text; PhotonNetwork.player.UserId = text; if (PhotonNetwork.logLevel >= PhotonLogLevel.Informational) { DebugReturn(DebugLevel.INFO, $"Received your UserID from server. Updating local value to: {text}"); } } } if (operationResponse.Parameters.ContainsKey(202)) { playername = (string)operationResponse.Parameters[202]; if (PhotonNetwork.logLevel >= PhotonLogLevel.Informational) { DebugReturn(DebugLevel.INFO, $"Received your NickName from server. Updating local value to: {playername}"); } } if (operationResponse.Parameters.ContainsKey(192)) { SetupEncryption((Dictionary)operationResponse.Parameters[192]); } } if (Server == ServerConnection.NameServer) { MasterServerAddress = (operationResponse[230] as string); DisconnectToReconnect(); } else if (Server == ServerConnection.MasterServer) { if (AuthMode != 0) { OpSettings(requestLobbyStatistics); } if (PhotonNetwork.autoJoinLobby) { State = ClientState.Authenticated; OpJoinLobby(lobby); } else { State = ClientState.ConnectedToMaster; SendMonoMessage(PhotonNetworkingMessage.OnConnectedToMaster); } } else if (Server == ServerConnection.GameServer) { State = ClientState.Joining; enterRoomParamsCache.PlayerProperties = GetLocalActorProperties(); enterRoomParamsCache.OnGameServer = true; if (lastJoinType == JoinType.JoinRoom || lastJoinType == JoinType.JoinRandomRoom || lastJoinType == JoinType.JoinOrCreateRoom) { OpJoinRoom(enterRoomParamsCache); } else if (lastJoinType == JoinType.CreateRoom) { OpCreateGame(enterRoomParamsCache); } } if (operationResponse.Parameters.ContainsKey(245)) { Dictionary dictionary = (Dictionary)operationResponse.Parameters[245]; if (dictionary != null) { SendMonoMessage(PhotonNetworkingMessage.OnCustomAuthenticationResponse, dictionary); } } } break; case 220: if (operationResponse.ReturnCode == 32767) { Debug.LogError($"The appId this client sent is unknown on the server (Cloud). Check settings. If using the Cloud, check account."); SendMonoMessage(PhotonNetworkingMessage.OnFailedToConnectToPhoton, DisconnectCause.InvalidAuthentication); State = ClientState.Disconnecting; Disconnect(); } else if (operationResponse.ReturnCode != 0) { Debug.LogError("GetRegions failed. Can't provide regions list. Error: " + operationResponse.ReturnCode + ": " + operationResponse.DebugMessage); } else { string[] array3 = operationResponse[210] as string[]; string[] array4 = operationResponse[230] as string[]; if (array3 == null || array4 == null || array3.Length != array4.Length) { Debug.LogError("The region arrays from Name Server are not ok. Must be non-null and same length. " + (array3 == null) + " " + (array4 == null) + "\n" + operationResponse.ToStringFull()); } else { AvailableRegions = new List(array3.Length); for (int j = 0; j < array3.Length; j++) { string text3 = array3[j]; if (!string.IsNullOrEmpty(text3)) { text3 = text3.ToLower(); CloudRegionCode cloudRegionCode = Region.Parse(text3); bool flag = true; if (PhotonNetwork.PhotonServerSettings.HostType == ServerSettings.HostingOption.BestRegion && PhotonNetwork.PhotonServerSettings.EnabledRegions != 0) { CloudRegionFlag cloudRegionFlag = Region.ParseFlag(text3); flag = ((PhotonNetwork.PhotonServerSettings.EnabledRegions & cloudRegionFlag) != (CloudRegionFlag)0); if (!flag && PhotonNetwork.logLevel >= PhotonLogLevel.Informational) { Debug.Log("Skipping region because it's not in PhotonServerSettings.EnabledRegions: " + cloudRegionCode); } } if (flag) { AvailableRegions.Add(new Region { Code = cloudRegionCode, HostAndPort = array4[j] }); } } } if (PhotonNetwork.PhotonServerSettings.HostType == ServerSettings.HostingOption.BestRegion) { PhotonHandler.PingAvailableRegionsAndConnectToBest(); } } } break; case 227: if (Server == ServerConnection.GameServer) { GameEnteredOnGameServer(operationResponse); } else if (operationResponse.ReturnCode != 0) { if (PhotonNetwork.logLevel >= PhotonLogLevel.Informational) { Debug.LogWarning($"CreateRoom failed, client stays on masterserver: {operationResponse.ToStringFull()}."); } State = ((!insideLobby) ? ClientState.ConnectedToMaster : ClientState.JoinedLobby); SendMonoMessage(PhotonNetworkingMessage.OnPhotonCreateRoomFailed, operationResponse.ReturnCode, operationResponse.DebugMessage); } else { string text2 = (string)operationResponse[byte.MaxValue]; if (!string.IsNullOrEmpty(text2)) { enterRoomParamsCache.RoomName = text2; } GameServerAddress = (string)operationResponse[230]; DisconnectToReconnect(); } break; case 226: if (Server != ServerConnection.GameServer) { if (operationResponse.ReturnCode != 0) { if (PhotonNetwork.logLevel >= PhotonLogLevel.Informational) { Debug.Log($"JoinRoom failed (room maybe closed by now). Client stays on masterserver: {operationResponse.ToStringFull()}. State: {State}"); } SendMonoMessage(PhotonNetworkingMessage.OnPhotonJoinRoomFailed, operationResponse.ReturnCode, operationResponse.DebugMessage); } else { GameServerAddress = (string)operationResponse[230]; DisconnectToReconnect(); } } else { GameEnteredOnGameServer(operationResponse); } break; case 225: if (operationResponse.ReturnCode != 0) { if (operationResponse.ReturnCode == 32760) { if (PhotonNetwork.logLevel >= PhotonLogLevel.Full) { Debug.Log("JoinRandom failed: No open game. Calling: OnPhotonRandomJoinFailed() and staying on master server."); } } else if (PhotonNetwork.logLevel >= PhotonLogLevel.Informational) { Debug.LogWarning($"JoinRandom failed: {operationResponse.ToStringFull()}."); } SendMonoMessage(PhotonNetworkingMessage.OnPhotonRandomJoinFailed, operationResponse.ReturnCode, operationResponse.DebugMessage); } else { string roomName = (string)operationResponse[byte.MaxValue]; enterRoomParamsCache.RoomName = roomName; GameServerAddress = (string)operationResponse[230]; DisconnectToReconnect(); } break; case 229: State = ClientState.JoinedLobby; insideLobby = true; SendMonoMessage(PhotonNetworkingMessage.OnJoinedLobby); break; case 228: State = ClientState.Authenticated; LeftLobbyCleanup(); break; case 254: DisconnectToReconnect(); break; case 251: { ExitGames.Client.Photon.Hashtable pActorProperties = (ExitGames.Client.Photon.Hashtable)operationResponse[249]; ExitGames.Client.Photon.Hashtable gameProperties = (ExitGames.Client.Photon.Hashtable)operationResponse[248]; ReadoutProperties(gameProperties, pActorProperties, 0); break; } case 222: { bool[] array = operationResponse[1] as bool[]; string[] array2 = operationResponse[2] as string[]; if (array != null && array2 != null && friendListRequested != null && array.Length == friendListRequested.Length) { List list = new List(friendListRequested.Length); for (int i = 0; i < friendListRequested.Length; i++) { FriendInfo friendInfo = new FriendInfo(); friendInfo.Name = friendListRequested[i]; friendInfo.Room = array2[i]; friendInfo.IsOnline = array[i]; list.Insert(i, friendInfo); } PhotonNetwork.Friends = list; } else { Debug.LogError("FindFriends failed to apply the result, as a required value wasn't provided or the friend list length differed from result."); } friendListRequested = null; isFetchingFriendList = false; friendListTimestamp = Environment.TickCount; if (friendListTimestamp == 0) { friendListTimestamp = 1; } SendMonoMessage(PhotonNetworkingMessage.OnUpdatedFriendList); break; } case 219: SendMonoMessage(PhotonNetworkingMessage.OnWebRpcResponse, operationResponse); break; default: Debug.LogWarning($"OperationResponse unhandled: {operationResponse.ToString()}"); break; } } } public void OnStatusChanged(StatusCode statusCode) { if (PhotonNetwork.logLevel >= PhotonLogLevel.Informational) { Debug.Log($"OnStatusChanged: {statusCode.ToString()} current State: {State}"); } switch (statusCode) { case StatusCode.QueueOutgoingReliableWarning: case StatusCode.QueueOutgoingUnreliableWarning: case StatusCode.QueueOutgoingAcksWarning: case StatusCode.QueueSentWarning: break; case StatusCode.SendError: break; case StatusCode.Connect: if (State == ClientState.ConnectingToNameServer) { if (PhotonNetwork.logLevel >= PhotonLogLevel.Full) { Debug.Log("Connected to NameServer."); } Server = ServerConnection.NameServer; if (AuthValues != null) { AuthValues.Token = null; } } if (State == ClientState.ConnectingToGameserver) { if (PhotonNetwork.logLevel >= PhotonLogLevel.Full) { Debug.Log("Connected to gameserver."); } Server = ServerConnection.GameServer; State = ClientState.ConnectedToGameserver; } if (State == ClientState.ConnectingToMasterserver) { if (PhotonNetwork.logLevel >= PhotonLogLevel.Full) { Debug.Log("Connected to masterserver."); } Server = ServerConnection.MasterServer; State = ClientState.Authenticating; if (IsInitialConnect) { IsInitialConnect = false; SendMonoMessage(PhotonNetworkingMessage.OnConnectedToPhoton); } } if (base.TransportProtocol != ConnectionProtocol.WebSocketSecure) { if (Server == ServerConnection.NameServer || AuthMode == AuthModeOption.Auth) { EstablishEncryption(); } break; } if (DebugOut == DebugLevel.INFO) { Debug.Log("Skipping EstablishEncryption. Protocol is secure."); } goto case StatusCode.EncryptionEstablished; case StatusCode.EncryptionEstablished: if (Server == ServerConnection.NameServer) { State = ClientState.ConnectedToNameServer; if (!didAuthenticate && CloudRegion == CloudRegionCode.none) { OpGetRegions(AppId); } } if ((Server == ServerConnection.NameServer || (AuthMode != AuthModeOption.AuthOnce && AuthMode != AuthModeOption.AuthOnceWss)) && !didAuthenticate && (!IsUsingNameServer || CloudRegion != CloudRegionCode.none)) { didAuthenticate = CallAuthenticate(); if (didAuthenticate) { State = ClientState.Authenticating; } } break; case StatusCode.EncryptionFailedToEstablish: { Debug.LogError("Encryption wasn't established: " + statusCode + ". Going to authenticate anyways."); object authenticationValues = AuthValues; if (authenticationValues == null) { AuthenticationValues authenticationValues2 = new AuthenticationValues(); authenticationValues2.UserId = PlayerName; authenticationValues = authenticationValues2; } AuthenticationValues authValues = (AuthenticationValues)authenticationValues; OpAuthenticate(AppId, AppVersion, authValues, CloudRegion.ToString(), requestLobbyStatistics); break; } case StatusCode.Disconnect: didAuthenticate = false; isFetchingFriendList = false; if (Server == ServerConnection.GameServer) { LeftRoomCleanup(); } if (Server == ServerConnection.MasterServer) { LeftLobbyCleanup(); } if (State == ClientState.DisconnectingFromMasterserver) { if (Connect(GameServerAddress, ServerConnection.GameServer)) { State = ClientState.ConnectingToGameserver; } } else if (State == ClientState.DisconnectingFromGameserver || State == ClientState.DisconnectingFromNameServer) { SetupProtocol(ServerConnection.MasterServer); if (Connect(MasterServerAddress, ServerConnection.MasterServer)) { State = ClientState.ConnectingToMasterserver; } } else { if (AuthValues != null) { AuthValues.Token = null; } State = ClientState.PeerCreated; SendMonoMessage(PhotonNetworkingMessage.OnDisconnectedFromPhoton); } break; case StatusCode.SecurityExceptionOnConnect: case StatusCode.ExceptionOnConnect: { State = ClientState.PeerCreated; if (AuthValues != null) { AuthValues.Token = null; } DisconnectCause disconnectCause = (DisconnectCause)statusCode; SendMonoMessage(PhotonNetworkingMessage.OnFailedToConnectToPhoton, disconnectCause); break; } case StatusCode.Exception: if (IsInitialConnect) { Debug.LogError("Exception while connecting to: " + base.ServerAddress + ". Check if the server is available."); if (base.ServerAddress == null || base.ServerAddress.StartsWith("127.0.0.1")) { Debug.LogWarning("The server address is 127.0.0.1 (localhost): Make sure the server is running on this machine. Android and iOS emulators have their own localhost."); if (base.ServerAddress == GameServerAddress) { Debug.LogWarning("This might be a misconfiguration in the game server config. You need to edit it to a (public) address."); } } State = ClientState.PeerCreated; DisconnectCause disconnectCause = (DisconnectCause)statusCode; SendMonoMessage(PhotonNetworkingMessage.OnFailedToConnectToPhoton, disconnectCause); } else { State = ClientState.PeerCreated; DisconnectCause disconnectCause = (DisconnectCause)statusCode; SendMonoMessage(PhotonNetworkingMessage.OnConnectionFail, disconnectCause); } Disconnect(); break; case StatusCode.TimeoutDisconnect: if (IsInitialConnect) { Debug.LogWarning(statusCode + " while connecting to: " + base.ServerAddress + ". Check if the server is available."); DisconnectCause disconnectCause = (DisconnectCause)statusCode; SendMonoMessage(PhotonNetworkingMessage.OnFailedToConnectToPhoton, disconnectCause); } else { DisconnectCause disconnectCause = (DisconnectCause)statusCode; SendMonoMessage(PhotonNetworkingMessage.OnConnectionFail, disconnectCause); } if (AuthValues != null) { AuthValues.Token = null; } Disconnect(); break; case StatusCode.ExceptionOnReceive: case StatusCode.DisconnectByServer: case StatusCode.DisconnectByServerUserLimit: case StatusCode.DisconnectByServerLogic: if (IsInitialConnect) { Debug.LogWarning(statusCode + " while connecting to: " + base.ServerAddress + ". Check if the server is available."); DisconnectCause disconnectCause = (DisconnectCause)statusCode; SendMonoMessage(PhotonNetworkingMessage.OnFailedToConnectToPhoton, disconnectCause); } else { DisconnectCause disconnectCause = (DisconnectCause)statusCode; SendMonoMessage(PhotonNetworkingMessage.OnConnectionFail, disconnectCause); } if (AuthValues != null) { AuthValues.Token = null; } Disconnect(); break; case StatusCode.QueueIncomingReliableWarning: case StatusCode.QueueIncomingUnreliableWarning: Debug.Log(statusCode + ". This client buffers many incoming messages. This is OK temporarily. With lots of these warnings, check if you send too much or execute messages too slow. " + ((!PhotonNetwork.isMessageQueueRunning) ? "Your isMessageQueueRunning is false. This can cause the issue temporarily." : string.Empty)); break; default: Debug.LogError("Received unknown status code: " + statusCode); break; } } public void OnEvent(EventData photonEvent) { if (PhotonNetwork.logLevel >= PhotonLogLevel.Informational) { Debug.Log($"OnEvent: {photonEvent.ToString()}"); } int num = -1; PhotonPlayer photonPlayer = null; if (photonEvent.Parameters.ContainsKey(254)) { num = (int)photonEvent[254]; photonPlayer = GetPlayerWithId(num); } switch (photonEvent.Code) { case 228: break; case 209: { int[] array = (int[])photonEvent.Parameters[245]; int num3 = array[0]; int num4 = array[1]; PhotonView photonView = PhotonView.Find(num3); if (photonView == null) { Debug.LogWarning("Can't find PhotonView of incoming OwnershipRequest. ViewId not found: " + num3); } else { if (PhotonNetwork.logLevel == PhotonLogLevel.Informational) { Debug.Log("Ev OwnershipRequest " + photonView.ownershipTransfer + ". ActorNr: " + num + " takes from: " + num4 + ". Current owner: " + photonView.ownerId + " isOwnerActive: " + photonView.isOwnerActive + ". MasterClient: " + mMasterClientId + ". This client's player: " + PhotonNetwork.player.ToStringFull()); } switch (photonView.ownershipTransfer) { case OwnershipOption.Fixed: Debug.LogWarning("Ownership mode == fixed. Ignoring request."); break; case OwnershipOption.Takeover: if (num4 == photonView.ownerId || (num4 == 0 && photonView.ownerId == mMasterClientId)) { photonView.OwnerShipWasTransfered = true; photonView.ownerId = num; if (PhotonNetwork.logLevel == PhotonLogLevel.Informational) { Debug.LogWarning(photonView + " ownership transfered to: " + num); } } break; case OwnershipOption.Request: if ((num4 == PhotonNetwork.player.ID || PhotonNetwork.player.IsMasterClient) && (photonView.ownerId == PhotonNetwork.player.ID || (PhotonNetwork.player.IsMasterClient && !photonView.isOwnerActive))) { SendMonoMessage(PhotonNetworkingMessage.OnOwnershipRequest, photonView, photonPlayer); } break; } } break; } case 210: { int[] array6 = (int[])photonEvent.Parameters[245]; Debug.Log("Ev OwnershipTransfer. ViewID " + array6[0] + " to: " + array6[1] + " Time: " + Environment.TickCount % 1000); int viewID = array6[0]; int ownerId = array6[1]; PhotonView photonView2 = PhotonView.Find(viewID); if (photonView2 != null) { photonView2.OwnerShipWasTransfered = true; photonView2.ownerId = ownerId; } break; } case 230: { mGameList = new Dictionary(); ExitGames.Client.Photon.Hashtable hashtable2 = (ExitGames.Client.Photon.Hashtable)photonEvent[222]; foreach (object key in hashtable2.Keys) { string text2 = (string)key; mGameList[text2] = new RoomInfo(text2, (ExitGames.Client.Photon.Hashtable)hashtable2[key]); } mGameListCopy = new RoomInfo[mGameList.Count]; mGameList.Values.CopyTo(mGameListCopy, 0); SendMonoMessage(PhotonNetworkingMessage.OnReceivedRoomListUpdate); break; } case 229: { ExitGames.Client.Photon.Hashtable hashtable = (ExitGames.Client.Photon.Hashtable)photonEvent[222]; foreach (object key2 in hashtable.Keys) { string text = (string)key2; RoomInfo roomInfo = new RoomInfo(text, (ExitGames.Client.Photon.Hashtable)hashtable[key2]); if (roomInfo.removedFromList) { mGameList.Remove(text); } else { mGameList[text] = roomInfo; } } mGameListCopy = new RoomInfo[mGameList.Count]; mGameList.Values.CopyTo(mGameListCopy, 0); SendMonoMessage(PhotonNetworkingMessage.OnReceivedRoomListUpdate); break; } case 226: PlayersInRoomsCount = (int)photonEvent[229]; PlayersOnMasterCount = (int)photonEvent[227]; RoomsCount = (int)photonEvent[228]; break; case byte.MaxValue: { ExitGames.Client.Photon.Hashtable properties = (ExitGames.Client.Photon.Hashtable)photonEvent[249]; if (photonPlayer == null) { bool isLocal = LocalPlayer.ID == num; AddNewPlayer(num, new PhotonPlayer(isLocal, num, properties)); ResetPhotonViewsOnSerialize(); } else { photonPlayer.InternalCacheProperties(properties); photonPlayer.IsInactive = false; } if (num == LocalPlayer.ID) { int[] actorsInRoom = (int[])photonEvent[252]; UpdatedActorList(actorsInRoom); if (lastJoinType == JoinType.JoinOrCreateRoom && LocalPlayer.ID == 1) { SendMonoMessage(PhotonNetworkingMessage.OnCreatedRoom); } SendMonoMessage(PhotonNetworkingMessage.OnJoinedRoom); } else { SendMonoMessage(PhotonNetworkingMessage.OnPhotonPlayerConnected, mActors[num]); } break; } case 254: HandleEventLeave(num, photonEvent); break; case 253: { int num2 = (int)photonEvent[253]; ExitGames.Client.Photon.Hashtable gameProperties = null; ExitGames.Client.Photon.Hashtable pActorProperties = null; if (num2 == 0) { gameProperties = (ExitGames.Client.Photon.Hashtable)photonEvent[251]; } else { pActorProperties = (ExitGames.Client.Photon.Hashtable)photonEvent[251]; } ReadoutProperties(gameProperties, pActorProperties, num2); break; } case 200: ExecuteRpc(photonEvent[245] as ExitGames.Client.Photon.Hashtable, photonPlayer); break; case 201: case 206: { ExitGames.Client.Photon.Hashtable hashtable4 = (ExitGames.Client.Photon.Hashtable)photonEvent[245]; int networkTime = (int)hashtable4[(byte)0]; short correctPrefix = -1; byte b = 10; int num6 = 1; if (hashtable4.ContainsKey((byte)1)) { correctPrefix = (short)hashtable4[(byte)1]; num6 = 2; } byte b2 = b; while (b2 - b < hashtable4.Count - num6) { OnSerializeRead(hashtable4[b2] as object[], photonPlayer, networkTime, correctPrefix); b2 = (byte)(b2 + 1); } break; } case 202: DoInstantiate((ExitGames.Client.Photon.Hashtable)photonEvent[245], photonPlayer, null); break; case 203: if (photonPlayer == null || !photonPlayer.IsMasterClient) { Debug.LogError("Error: Someone else(" + photonPlayer + ") then the masterserver requests a disconnect!"); } else { PhotonNetwork.LeaveRoom(); } break; case 207: { ExitGames.Client.Photon.Hashtable hashtable3 = (ExitGames.Client.Photon.Hashtable)photonEvent[245]; int num7 = (int)hashtable3[(byte)0]; if (num7 >= 0) { DestroyPlayerObjects(num7, localOnly: true); } else { if ((int)DebugOut >= 3) { Debug.Log("Ev DestroyAll! By PlayerId: " + num); } DestroyAll(localOnly: true); } break; } case 204: { ExitGames.Client.Photon.Hashtable hashtable3 = (ExitGames.Client.Photon.Hashtable)photonEvent[245]; int num5 = (int)hashtable3[(byte)0]; PhotonView value = null; if (photonViewList.TryGetValue(num5, out value)) { RemoveInstantiatedGO(value.gameObject, localOnly: true); } else if ((int)DebugOut >= 1) { Debug.LogError("Ev Destroy Failed. Could not find PhotonView with instantiationId " + num5 + ". Sent by actorNr: " + num); } break; } case 208: { ExitGames.Client.Photon.Hashtable hashtable3 = (ExitGames.Client.Photon.Hashtable)photonEvent[245]; int playerId = (int)hashtable3[(byte)1]; SetMasterClient(playerId, sync: false); break; } case 224: { string[] array2 = photonEvent[213] as string[]; byte[] array3 = photonEvent[212] as byte[]; int[] array4 = photonEvent[229] as int[]; int[] array5 = photonEvent[228] as int[]; LobbyStatistics.Clear(); for (int i = 0; i < array2.Length; i++) { TypedLobbyInfo typedLobbyInfo = new TypedLobbyInfo(); typedLobbyInfo.Name = array2[i]; typedLobbyInfo.Type = (LobbyType)array3[i]; typedLobbyInfo.PlayerCount = array4[i]; typedLobbyInfo.RoomCount = array5[i]; LobbyStatistics.Add(typedLobbyInfo); } SendMonoMessage(PhotonNetworkingMessage.OnLobbyStatisticsUpdate); break; } case 251: if (PhotonNetwork.OnEventCall != null) { object content2 = photonEvent[245]; PhotonNetwork.OnEventCall(photonEvent.Code, content2, num); } else { Debug.LogWarning("Warning: Unhandled Event ErrorInfo (251). Set PhotonNetwork.OnEventCall to the method PUN should call for this event."); } break; case 223: if (AuthValues == null) { AuthValues = new AuthenticationValues(); } AuthValues.Token = (photonEvent[221] as string); tokenCache = AuthValues.Token; break; default: if (photonEvent.Code < 200) { if (PhotonNetwork.OnEventCall != null) { object content = photonEvent[245]; PhotonNetwork.OnEventCall(photonEvent.Code, content, num); } else { Debug.LogWarning("Warning: Unhandled event " + photonEvent + ". Set PhotonNetwork.OnEventCall."); } } break; } } public void OnMessage(object messages) { } private void SetupEncryption(Dictionary encryptionData) { if (AuthMode == AuthModeOption.Auth && DebugOut == DebugLevel.ERROR) { Debug.LogWarning("SetupEncryption() called but ignored. Not XB1 compiled. EncryptionData: " + encryptionData.ToStringFull()); } else { if (DebugOut == DebugLevel.INFO) { Debug.Log("SetupEncryption() got called. " + encryptionData.ToStringFull()); } switch ((byte)encryptionData[0]) { case 0: { byte[] secret = (byte[])encryptionData[1]; InitPayloadEncryption(secret); break; } case 10: { byte[] encryptionSecret = (byte[])encryptionData[1]; byte[] hmacSecret = (byte[])encryptionData[2]; InitDatagramEncryption(encryptionSecret, hmacSecret); break; } default: throw new ArgumentOutOfRangeException(); } } } protected internal void UpdatedActorList(int[] actorsInRoom) { foreach (int num in actorsInRoom) { if (LocalPlayer.ID != num && !mActors.ContainsKey(num)) { AddNewPlayer(num, new PhotonPlayer(isLocal: false, num, string.Empty)); } } } private void SendVacantViewIds() { Debug.Log("SendVacantViewIds()"); List list = new List(); foreach (PhotonView value in photonViewList.Values) { if (!value.isOwnerActive) { list.Add(value.viewID); } } Debug.Log("Sending vacant view IDs. Length: " + list.Count); OpRaiseEvent(211, list.ToArray(), sendReliable: true, null); } public static void SendMonoMessage(PhotonNetworkingMessage methodString, params object[] parameters) { HashSet hashSet = (PhotonNetwork.SendMonoMessageTargets == null) ? PhotonNetwork.FindGameObjectsWithComponent(PhotonNetwork.SendMonoMessageTargetType) : PhotonNetwork.SendMonoMessageTargets; string methodName = methodString.ToString(); object value = (parameters == null || parameters.Length != 1) ? parameters : parameters[0]; foreach (GameObject item in hashSet) { if (item != null) { item.SendMessage(methodName, value, SendMessageOptions.DontRequireReceiver); } } } protected internal void ExecuteRpc(ExitGames.Client.Photon.Hashtable rpcData, PhotonPlayer sender) { if (rpcData == null || !rpcData.ContainsKey((byte)0)) { Debug.LogError("Malformed RPC; this should never occur. Content: " + SupportClass.DictionaryToString(rpcData)); } else { int num = (int)rpcData[(byte)0]; int num2 = 0; if (rpcData.ContainsKey((byte)1)) { num2 = (short)rpcData[(byte)1]; } string text; if (rpcData.ContainsKey((byte)5)) { int num3 = (byte)rpcData[(byte)5]; if (num3 > PhotonNetwork.PhotonServerSettings.RpcList.Count - 1) { Debug.LogError("Could not find RPC with index: " + num3 + ". Going to ignore! Check PhotonServerSettings.RpcList"); return; } text = PhotonNetwork.PhotonServerSettings.RpcList[num3]; } else { text = (string)rpcData[(byte)3]; } object[] array = null; if (rpcData.ContainsKey((byte)4)) { array = (object[])rpcData[(byte)4]; } if (array == null) { array = new object[0]; } PhotonView photonView = GetPhotonView(num); if (photonView == null) { int num4 = num / PhotonNetwork.MAX_VIEW_IDS; bool flag = num4 == LocalPlayer.ID; bool flag2 = num4 == sender.ID; if (flag) { Debug.LogWarning("Received RPC \"" + text + "\" for viewID " + num + " but this PhotonView does not exist! View was/is ours." + ((!flag2) ? " Remote called." : " Owner called.") + " By: " + sender.ID); } else { Debug.LogWarning("Received RPC \"" + text + "\" for viewID " + num + " but this PhotonView does not exist! Was remote PV." + ((!flag2) ? " Remote called." : " Owner called.") + " By: " + sender.ID + " Maybe GO was destroyed but RPC not cleaned up."); } } else if (photonView.prefix != num2) { Debug.LogError("Received RPC \"" + text + "\" on viewID " + num + " with a prefix of " + num2 + ", our prefix is " + photonView.prefix + ". The RPC has been ignored."); } else if (string.IsNullOrEmpty(text)) { Debug.LogError("Malformed RPC; this should never occur. Content: " + SupportClass.DictionaryToString(rpcData)); } else { if (PhotonNetwork.logLevel >= PhotonLogLevel.Full) { Debug.Log("Received RPC: " + text); } if (photonView.group == 0 || allowedReceivingGroups.Contains(photonView.group)) { Type[] array2 = new Type[0]; if (array.Length > 0) { array2 = new Type[array.Length]; int num5 = 0; foreach (object obj in array) { if (obj == null) { array2[num5] = null; } else { array2[num5] = obj.GetType(); } num5++; } } int num6 = 0; int num7 = 0; if (!PhotonNetwork.UseRpcMonoBehaviourCache || photonView.RpcMonoBehaviours == null || photonView.RpcMonoBehaviours.Length == 0) { photonView.RefreshRpcMonoBehaviourCache(); } for (int j = 0; j < photonView.RpcMonoBehaviours.Length; j++) { MonoBehaviour monoBehaviour = photonView.RpcMonoBehaviours[j]; if (monoBehaviour == null) { Debug.LogError("ERROR You have missing MonoBehaviours on your gameobjects!"); } else { Type type = monoBehaviour.GetType(); List value = null; if (!monoRPCMethodsCache.TryGetValue(type, out value)) { List methods = SupportClass.GetMethods(type, typeof(PunRPC)); monoRPCMethodsCache[type] = methods; value = methods; } if (value != null) { for (int k = 0; k < value.Count; k++) { MethodInfo methodInfo = value[k]; if (methodInfo.Name.Equals(text)) { num7++; ParameterInfo[] cachedParemeters = methodInfo.GetCachedParemeters(); if (cachedParemeters.Length == array2.Length) { if (CheckTypeMatch(cachedParemeters, array2)) { num6++; object obj2 = methodInfo.Invoke(monoBehaviour, array); if (PhotonNetwork.StartRpcsAsCoroutine && methodInfo.ReturnType == typeof(IEnumerator)) { monoBehaviour.StartCoroutine((IEnumerator)obj2); } } } else if (cachedParemeters.Length - 1 == array2.Length) { if (CheckTypeMatch(cachedParemeters, array2) && cachedParemeters[cachedParemeters.Length - 1].ParameterType == typeof(PhotonMessageInfo)) { num6++; int timestamp = (int)rpcData[(byte)2]; object[] array3 = new object[array.Length + 1]; array.CopyTo(array3, 0); array3[array3.Length - 1] = new PhotonMessageInfo(sender, timestamp, photonView); object obj3 = methodInfo.Invoke(monoBehaviour, array3); if (PhotonNetwork.StartRpcsAsCoroutine && methodInfo.ReturnType == typeof(IEnumerator)) { monoBehaviour.StartCoroutine((IEnumerator)obj3); } } } else if (cachedParemeters.Length == 1 && cachedParemeters[0].ParameterType.IsArray) { num6++; object obj4 = methodInfo.Invoke(monoBehaviour, new object[1] { array }); if (PhotonNetwork.StartRpcsAsCoroutine && methodInfo.ReturnType == typeof(IEnumerator)) { monoBehaviour.StartCoroutine((IEnumerator)obj4); } } } } } } } if (num6 != 1) { string text2 = string.Empty; foreach (Type type2 in array2) { if (text2 != string.Empty) { text2 += ", "; } text2 = ((type2 != null) ? (text2 + type2.Name) : (text2 + "null")); } if (num6 == 0) { if (num7 == 0) { Debug.LogError("PhotonView with ID " + num + " has no method \"" + text + "\" marked with the [PunRPC](C#) or @PunRPC(JS) property! Args: " + text2); } else { Debug.LogError("PhotonView with ID " + num + " has no method \"" + text + "\" that takes " + array2.Length + " argument(s): " + text2); } } else { Debug.LogError("PhotonView with ID " + num + " has " + num6 + " methods \"" + text + "\" that takes " + array2.Length + " argument(s): " + text2 + ". Should be just one?"); } } } } } } private bool CheckTypeMatch(ParameterInfo[] methodParameters, Type[] callParameterTypes) { if (methodParameters.Length < callParameterTypes.Length) { return false; } for (int i = 0; i < callParameterTypes.Length; i++) { Type parameterType = methodParameters[i].ParameterType; if (callParameterTypes[i] != null && !parameterType.IsAssignableFrom(callParameterTypes[i]) && (!parameterType.IsEnum || !Enum.GetUnderlyingType(parameterType).IsAssignableFrom(callParameterTypes[i]))) { return false; } } return true; } internal ExitGames.Client.Photon.Hashtable SendInstantiate(string prefabName, Vector3 position, Quaternion rotation, int group, int[] viewIDs, object[] data, bool isGlobalObject) { int num = viewIDs[0]; ExitGames.Client.Photon.Hashtable hashtable = new ExitGames.Client.Photon.Hashtable(); hashtable[(byte)0] = prefabName; if (position != Vector3.zero) { hashtable[(byte)1] = position; } if (rotation != Quaternion.identity) { hashtable[(byte)2] = rotation; } if (group != 0) { hashtable[(byte)3] = group; } if (viewIDs.Length > 1) { hashtable[(byte)4] = viewIDs; } if (data != null) { hashtable[(byte)5] = data; } if (currentLevelPrefix > 0) { hashtable[(byte)8] = currentLevelPrefix; } hashtable[(byte)6] = PhotonNetwork.ServerTimestamp; hashtable[(byte)7] = num; RaiseEventOptions raiseEventOptions = new RaiseEventOptions(); raiseEventOptions.CachingOption = ((!isGlobalObject) ? EventCaching.AddToRoomCache : EventCaching.AddToRoomCacheGlobal); OpRaiseEvent(202, hashtable, sendReliable: true, raiseEventOptions); return hashtable; } internal GameObject DoInstantiate(ExitGames.Client.Photon.Hashtable evData, PhotonPlayer photonPlayer, GameObject resourceGameObject) { string text = (string)evData[(byte)0]; int timestamp = (int)evData[(byte)6]; int num = (int)evData[(byte)7]; Vector3 position = (!evData.ContainsKey((byte)1)) ? Vector3.zero : ((Vector3)evData[(byte)1]); Quaternion rotation = Quaternion.identity; if (evData.ContainsKey((byte)2)) { rotation = (Quaternion)evData[(byte)2]; } int num2 = 0; if (evData.ContainsKey((byte)3)) { num2 = (int)evData[(byte)3]; } short prefix = 0; if (evData.ContainsKey((byte)8)) { prefix = (short)evData[(byte)8]; } int[] array = (!evData.ContainsKey((byte)4)) ? new int[1] { num } : ((int[])evData[(byte)4]); object[] array2 = (!evData.ContainsKey((byte)5)) ? null : ((object[])evData[(byte)5]); if (num2 != 0 && !allowedReceivingGroups.Contains(num2)) { return null; } if (ObjectPool != null) { GameObject gameObject = ObjectPool.Instantiate(text, position, rotation); PhotonView[] photonViewsInChildren = gameObject.GetPhotonViewsInChildren(); if (photonViewsInChildren.Length != array.Length) { throw new Exception("Error in Instantiation! The resource's PhotonView count is not the same as in incoming data."); } for (int i = 0; i < photonViewsInChildren.Length; i++) { photonViewsInChildren[i].didAwake = false; photonViewsInChildren[i].viewID = 0; photonViewsInChildren[i].prefix = prefix; photonViewsInChildren[i].instantiationId = num; photonViewsInChildren[i].isRuntimeInstantiated = true; photonViewsInChildren[i].instantiationDataField = array2; photonViewsInChildren[i].didAwake = true; photonViewsInChildren[i].viewID = array[i]; } gameObject.SendMessage(OnPhotonInstantiateString, new PhotonMessageInfo(photonPlayer, timestamp, null), SendMessageOptions.DontRequireReceiver); return gameObject; } if (resourceGameObject == null) { if (!UsePrefabCache || !PrefabCache.TryGetValue(text, out resourceGameObject)) { resourceGameObject = (GameObject)Resources.Load(text, typeof(GameObject)); if (UsePrefabCache) { PrefabCache.Add(text, resourceGameObject); } } if (resourceGameObject == null) { Debug.LogError("PhotonNetwork error: Could not Instantiate the prefab [" + text + "]. Please verify you have this gameobject in a Resources folder."); return null; } } PhotonView[] photonViewsInChildren2 = resourceGameObject.GetPhotonViewsInChildren(); if (photonViewsInChildren2.Length != array.Length) { throw new Exception("Error in Instantiation! The resource's PhotonView count is not the same as in incoming data."); } for (int j = 0; j < array.Length; j++) { photonViewsInChildren2[j].viewID = array[j]; photonViewsInChildren2[j].prefix = prefix; photonViewsInChildren2[j].instantiationId = num; photonViewsInChildren2[j].isRuntimeInstantiated = true; } StoreInstantiationData(num, array2); GameObject gameObject2 = UnityEngine.Object.Instantiate(resourceGameObject, position, rotation); for (int k = 0; k < array.Length; k++) { photonViewsInChildren2[k].viewID = 0; photonViewsInChildren2[k].prefix = -1; photonViewsInChildren2[k].prefixBackup = -1; photonViewsInChildren2[k].instantiationId = -1; photonViewsInChildren2[k].isRuntimeInstantiated = false; } RemoveInstantiationData(num); gameObject2.SendMessage(OnPhotonInstantiateString, new PhotonMessageInfo(photonPlayer, timestamp, null), SendMessageOptions.DontRequireReceiver); return gameObject2; } private void StoreInstantiationData(int instantiationId, object[] instantiationData) { tempInstantiationData[instantiationId] = instantiationData; } public object[] FetchInstantiationData(int instantiationId) { object[] value = null; if (instantiationId == 0) { return null; } tempInstantiationData.TryGetValue(instantiationId, out value); return value; } private void RemoveInstantiationData(int instantiationId) { tempInstantiationData.Remove(instantiationId); } public void DestroyPlayerObjects(int playerId, bool localOnly) { if (playerId <= 0) { Debug.LogError("Failed to Destroy objects of playerId: " + playerId); } else { if (!localOnly) { OpRemoveFromServerInstantiationsOfPlayer(playerId); OpCleanRpcBuffer(playerId); SendDestroyOfPlayer(playerId); } HashSet hashSet = new HashSet(); foreach (PhotonView value in photonViewList.Values) { if (value != null && value.CreatorActorNr == playerId) { hashSet.Add(value.gameObject); } } foreach (GameObject item in hashSet) { RemoveInstantiatedGO(item, localOnly: true); } foreach (PhotonView value2 in photonViewList.Values) { if (value2.ownerId == playerId) { value2.ownerId = value2.CreatorActorNr; } } } } public void DestroyAll(bool localOnly) { if (!localOnly) { OpRemoveCompleteCache(); SendDestroyOfAll(); } LocalCleanupAnythingInstantiated(destroyInstantiatedGameObjects: true); } protected internal void RemoveInstantiatedGO(GameObject go, bool localOnly) { if (go == null) { Debug.LogError("Failed to 'network-remove' GameObject because it's null."); } else { PhotonView[] componentsInChildren = go.GetComponentsInChildren(includeInactive: true); if (componentsInChildren == null || componentsInChildren.Length <= 0) { Debug.LogError("Failed to 'network-remove' GameObject because has no PhotonView components: " + go); } else { PhotonView photonView = componentsInChildren[0]; int creatorActorNr = photonView.CreatorActorNr; int instantiationId = photonView.instantiationId; if (!localOnly) { if (!photonView.isMine) { Debug.LogError("Failed to 'network-remove' GameObject. Client is neither owner nor masterClient taking over for owner who left: " + photonView); return; } if (instantiationId < 1) { Debug.LogError("Failed to 'network-remove' GameObject because it is missing a valid InstantiationId on view: " + photonView + ". Not Destroying GameObject or PhotonViews!"); return; } } if (!localOnly) { ServerCleanInstantiateAndDestroy(instantiationId, creatorActorNr, photonView.isRuntimeInstantiated); } for (int num = componentsInChildren.Length - 1; num >= 0; num--) { PhotonView photonView2 = componentsInChildren[num]; if (!(photonView2 == null)) { if (photonView2.instantiationId >= 1) { LocalCleanPhotonView(photonView2); } if (!localOnly) { OpCleanRpcBuffer(photonView2); } } } if (PhotonNetwork.logLevel >= PhotonLogLevel.Full) { Debug.Log("Network destroy Instantiated GO: " + go.name); } if (ObjectPool != null) { PhotonView[] photonViewsInChildren = go.GetPhotonViewsInChildren(); for (int i = 0; i < photonViewsInChildren.Length; i++) { photonViewsInChildren[i].viewID = 0; } ObjectPool.Destroy(go); } else { UnityEngine.Object.Destroy(go); } } } } private void ServerCleanInstantiateAndDestroy(int instantiateId, int creatorId, bool isRuntimeInstantiated) { ExitGames.Client.Photon.Hashtable hashtable = new ExitGames.Client.Photon.Hashtable(); hashtable[(byte)7] = instantiateId; RaiseEventOptions raiseEventOptions = new RaiseEventOptions(); raiseEventOptions.CachingOption = EventCaching.RemoveFromRoomCache; raiseEventOptions.TargetActors = new int[1] { creatorId }; RaiseEventOptions raiseEventOptions2 = raiseEventOptions; OpRaiseEvent(202, hashtable, sendReliable: true, raiseEventOptions2); ExitGames.Client.Photon.Hashtable hashtable2 = new ExitGames.Client.Photon.Hashtable(); hashtable2[(byte)0] = instantiateId; raiseEventOptions2 = null; if (!isRuntimeInstantiated) { raiseEventOptions2 = new RaiseEventOptions(); raiseEventOptions2.CachingOption = EventCaching.AddToRoomCacheGlobal; Debug.Log("Destroying GO as global. ID: " + instantiateId); } OpRaiseEvent(204, hashtable2, sendReliable: true, raiseEventOptions2); } private void SendDestroyOfPlayer(int actorNr) { ExitGames.Client.Photon.Hashtable hashtable = new ExitGames.Client.Photon.Hashtable(); hashtable[(byte)0] = actorNr; OpRaiseEvent(207, hashtable, sendReliable: true, null); } private void SendDestroyOfAll() { ExitGames.Client.Photon.Hashtable hashtable = new ExitGames.Client.Photon.Hashtable(); hashtable[(byte)0] = -1; OpRaiseEvent(207, hashtable, sendReliable: true, null); } private void OpRemoveFromServerInstantiationsOfPlayer(int actorNr) { RaiseEventOptions raiseEventOptions = new RaiseEventOptions(); raiseEventOptions.CachingOption = EventCaching.RemoveFromRoomCache; raiseEventOptions.TargetActors = new int[1] { actorNr }; RaiseEventOptions raiseEventOptions2 = raiseEventOptions; OpRaiseEvent(202, null, sendReliable: true, raiseEventOptions2); } protected internal void RequestOwnership(int viewID, int fromOwner) { Debug.Log("RequestOwnership(): " + viewID + " from: " + fromOwner + " Time: " + Environment.TickCount % 1000); OpRaiseEvent(209, new int[2] { viewID, fromOwner }, sendReliable: true, new RaiseEventOptions { Receivers = ReceiverGroup.All }); } protected internal void TransferOwnership(int viewID, int playerID) { Debug.Log("TransferOwnership() view " + viewID + " to: " + playerID + " Time: " + Environment.TickCount % 1000); OpRaiseEvent(210, new int[2] { viewID, playerID }, sendReliable: true, new RaiseEventOptions { Receivers = ReceiverGroup.All }); } public bool LocalCleanPhotonView(PhotonView view) { view.removedFromLocalViewList = true; return photonViewList.Remove(view.viewID); } public PhotonView GetPhotonView(int viewID) { PhotonView value = null; photonViewList.TryGetValue(viewID, out value); if (value == null) { PhotonView[] array = UnityEngine.Object.FindObjectsOfType(typeof(PhotonView)) as PhotonView[]; foreach (PhotonView photonView in array) { if (photonView.viewID == viewID) { if (photonView.didAwake) { Debug.LogWarning("Had to lookup view that wasn't in photonViewList: " + photonView); } return photonView; } } } return value; } public void RegisterPhotonView(PhotonView netView) { if (!Application.isPlaying) { photonViewList = new Dictionary(); } else if (netView.viewID == 0) { Debug.Log("PhotonView register is ignored, because viewID is 0. No id assigned yet to: " + netView); } else { PhotonView value = null; if (photonViewList.TryGetValue(netView.viewID, out value)) { if (!(netView != value)) { return; } Debug.LogError($"PhotonView ID duplicate found: {netView.viewID}. New: {netView} old: {value}. Maybe one wasn't destroyed on scene load?! Check for 'DontDestroyOnLoad'. Destroying old entry, adding new."); RemoveInstantiatedGO(value.gameObject, localOnly: true); } photonViewList.Add(netView.viewID, netView); if (PhotonNetwork.logLevel >= PhotonLogLevel.Full) { Debug.Log("Registered PhotonView: " + netView.viewID); } } } public void OpCleanRpcBuffer(int actorNumber) { RaiseEventOptions raiseEventOptions = new RaiseEventOptions(); raiseEventOptions.CachingOption = EventCaching.RemoveFromRoomCache; raiseEventOptions.TargetActors = new int[1] { actorNumber }; RaiseEventOptions raiseEventOptions2 = raiseEventOptions; OpRaiseEvent(200, null, sendReliable: true, raiseEventOptions2); } public void OpRemoveCompleteCacheOfPlayer(int actorNumber) { RaiseEventOptions raiseEventOptions = new RaiseEventOptions(); raiseEventOptions.CachingOption = EventCaching.RemoveFromRoomCache; raiseEventOptions.TargetActors = new int[1] { actorNumber }; RaiseEventOptions raiseEventOptions2 = raiseEventOptions; OpRaiseEvent(0, null, sendReliable: true, raiseEventOptions2); } public void OpRemoveCompleteCache() { RaiseEventOptions raiseEventOptions = new RaiseEventOptions(); raiseEventOptions.CachingOption = EventCaching.RemoveFromRoomCache; raiseEventOptions.Receivers = ReceiverGroup.MasterClient; RaiseEventOptions raiseEventOptions2 = raiseEventOptions; OpRaiseEvent(0, null, sendReliable: true, raiseEventOptions2); } private void RemoveCacheOfLeftPlayers() { Dictionary dictionary = new Dictionary(); dictionary[244] = (byte)0; dictionary[247] = (byte)7; OpCustom(253, dictionary, sendReliable: true, 0); } public void CleanRpcBufferIfMine(PhotonView view) { if (view.ownerId != LocalPlayer.ID && !LocalPlayer.IsMasterClient) { Debug.LogError("Cannot remove cached RPCs on a PhotonView thats not ours! " + view.owner + " scene: " + view.isSceneView); } else { OpCleanRpcBuffer(view); } } public void OpCleanRpcBuffer(PhotonView view) { ExitGames.Client.Photon.Hashtable hashtable = new ExitGames.Client.Photon.Hashtable(); hashtable[(byte)0] = view.viewID; RaiseEventOptions raiseEventOptions = new RaiseEventOptions(); raiseEventOptions.CachingOption = EventCaching.RemoveFromRoomCache; RaiseEventOptions raiseEventOptions2 = raiseEventOptions; OpRaiseEvent(200, hashtable, sendReliable: true, raiseEventOptions2); } public void RemoveRPCsInGroup(int group) { foreach (PhotonView value in photonViewList.Values) { if (value.group == group) { CleanRpcBufferIfMine(value); } } } public void SetLevelPrefix(short prefix) { currentLevelPrefix = prefix; } internal void RPC(PhotonView view, string methodName, PhotonTargets target, PhotonPlayer player, bool encrypt, params object[] parameters) { if (!blockSendingGroups.Contains(view.group)) { if (view.viewID < 1) { Debug.LogError("Illegal view ID:" + view.viewID + " method: " + methodName + " GO:" + view.gameObject.name); } if (PhotonNetwork.logLevel >= PhotonLogLevel.Full) { Debug.Log("Sending RPC \"" + methodName + "\" to target: " + target + " or player:" + player + "."); } ExitGames.Client.Photon.Hashtable hashtable = new ExitGames.Client.Photon.Hashtable(); hashtable[(byte)0] = view.viewID; if (view.prefix > 0) { hashtable[(byte)1] = (short)view.prefix; } hashtable[(byte)2] = PhotonNetwork.ServerTimestamp; int value = 0; if (rpcShortcuts.TryGetValue(methodName, out value)) { hashtable[(byte)5] = (byte)value; } else { hashtable[(byte)3] = methodName; } if (parameters != null && parameters.Length > 0) { hashtable[(byte)4] = parameters; } if (player != null) { if (LocalPlayer.ID == player.ID) { ExecuteRpc(hashtable, player); } else { RaiseEventOptions raiseEventOptions = new RaiseEventOptions(); raiseEventOptions.TargetActors = new int[1] { player.ID }; raiseEventOptions.Encrypt = encrypt; RaiseEventOptions raiseEventOptions2 = raiseEventOptions; OpRaiseEvent(200, hashtable, sendReliable: true, raiseEventOptions2); } } else { switch (target) { case PhotonTargets.All: { RaiseEventOptions raiseEventOptions = new RaiseEventOptions(); raiseEventOptions.InterestGroup = (byte)view.group; raiseEventOptions.Encrypt = encrypt; RaiseEventOptions raiseEventOptions9 = raiseEventOptions; OpRaiseEvent(200, hashtable, sendReliable: true, raiseEventOptions9); ExecuteRpc(hashtable, LocalPlayer); break; } case PhotonTargets.Others: { RaiseEventOptions raiseEventOptions = new RaiseEventOptions(); raiseEventOptions.InterestGroup = (byte)view.group; raiseEventOptions.Encrypt = encrypt; RaiseEventOptions raiseEventOptions8 = raiseEventOptions; OpRaiseEvent(200, hashtable, sendReliable: true, raiseEventOptions8); break; } case PhotonTargets.AllBuffered: { RaiseEventOptions raiseEventOptions = new RaiseEventOptions(); raiseEventOptions.CachingOption = EventCaching.AddToRoomCache; raiseEventOptions.Encrypt = encrypt; RaiseEventOptions raiseEventOptions6 = raiseEventOptions; OpRaiseEvent(200, hashtable, sendReliable: true, raiseEventOptions6); ExecuteRpc(hashtable, LocalPlayer); break; } case PhotonTargets.OthersBuffered: { RaiseEventOptions raiseEventOptions = new RaiseEventOptions(); raiseEventOptions.CachingOption = EventCaching.AddToRoomCache; raiseEventOptions.Encrypt = encrypt; RaiseEventOptions raiseEventOptions4 = raiseEventOptions; OpRaiseEvent(200, hashtable, sendReliable: true, raiseEventOptions4); break; } case PhotonTargets.MasterClient: if (mMasterClientId == LocalPlayer.ID) { ExecuteRpc(hashtable, LocalPlayer); } else { RaiseEventOptions raiseEventOptions = new RaiseEventOptions(); raiseEventOptions.Receivers = ReceiverGroup.MasterClient; raiseEventOptions.Encrypt = encrypt; RaiseEventOptions raiseEventOptions7 = raiseEventOptions; OpRaiseEvent(200, hashtable, sendReliable: true, raiseEventOptions7); } break; case PhotonTargets.AllViaServer: { RaiseEventOptions raiseEventOptions = new RaiseEventOptions(); raiseEventOptions.InterestGroup = (byte)view.group; raiseEventOptions.Receivers = ReceiverGroup.All; raiseEventOptions.Encrypt = encrypt; RaiseEventOptions raiseEventOptions5 = raiseEventOptions; OpRaiseEvent(200, hashtable, sendReliable: true, raiseEventOptions5); if (PhotonNetwork.offlineMode) { ExecuteRpc(hashtable, LocalPlayer); } break; } case PhotonTargets.AllBufferedViaServer: { RaiseEventOptions raiseEventOptions = new RaiseEventOptions(); raiseEventOptions.InterestGroup = (byte)view.group; raiseEventOptions.Receivers = ReceiverGroup.All; raiseEventOptions.CachingOption = EventCaching.AddToRoomCache; raiseEventOptions.Encrypt = encrypt; RaiseEventOptions raiseEventOptions3 = raiseEventOptions; OpRaiseEvent(200, hashtable, sendReliable: true, raiseEventOptions3); if (PhotonNetwork.offlineMode) { ExecuteRpc(hashtable, LocalPlayer); } break; } default: Debug.LogError("Unsupported target enum: " + target); break; } } } } public void SetReceivingEnabled(int group, bool enabled) { if (group <= 0) { Debug.LogError("Error: PhotonNetwork.SetReceivingEnabled was called with an illegal group number: " + group + ". The group number should be at least 1."); } else if (enabled) { if (!allowedReceivingGroups.Contains(group)) { allowedReceivingGroups.Add(group); byte[] groupsToAdd = new byte[1] { (byte)group }; OpChangeGroups(null, groupsToAdd); } } else if (allowedReceivingGroups.Contains(group)) { allowedReceivingGroups.Remove(group); byte[] groupsToRemove = new byte[1] { (byte)group }; OpChangeGroups(groupsToRemove, null); } } public void SetReceivingEnabled(int[] enableGroups, int[] disableGroups) { List list = new List(); List list2 = new List(); if (enableGroups != null) { foreach (int num in enableGroups) { if (num <= 0) { Debug.LogError("Error: PhotonNetwork.SetReceivingEnabled was called with an illegal group number: " + num + ". The group number should be at least 1."); } else if (!allowedReceivingGroups.Contains(num)) { allowedReceivingGroups.Add(num); list.Add((byte)num); } } } if (disableGroups != null) { foreach (int num2 in disableGroups) { if (num2 <= 0) { Debug.LogError("Error: PhotonNetwork.SetReceivingEnabled was called with an illegal group number: " + num2 + ". The group number should be at least 1."); } else if (list.Contains((byte)num2)) { Debug.LogError("Error: PhotonNetwork.SetReceivingEnabled disableGroups contains a group that is also in the enableGroups: " + num2 + "."); } else if (allowedReceivingGroups.Contains(num2)) { allowedReceivingGroups.Remove(num2); list2.Add((byte)num2); } } } OpChangeGroups((list2.Count <= 0) ? null : list2.ToArray(), (list.Count <= 0) ? null : list.ToArray()); } public void SetSendingEnabled(int group, bool enabled) { if (!enabled) { blockSendingGroups.Add(group); } else { blockSendingGroups.Remove(group); } } public void SetSendingEnabled(int[] enableGroups, int[] disableGroups) { if (enableGroups != null) { foreach (int item in enableGroups) { if (blockSendingGroups.Contains(item)) { blockSendingGroups.Remove(item); } } } if (disableGroups != null) { foreach (int item2 in disableGroups) { if (!blockSendingGroups.Contains(item2)) { blockSendingGroups.Add(item2); } } } } public void NewSceneLoaded() { if (loadingLevelAndPausedNetwork) { loadingLevelAndPausedNetwork = false; PhotonNetwork.isMessageQueueRunning = true; } List list = new List(); foreach (KeyValuePair photonView in photonViewList) { PhotonView value = photonView.Value; if (value == null) { list.Add(photonView.Key); } } for (int i = 0; i < list.Count; i++) { int key = list[i]; photonViewList.Remove(key); } if (list.Count > 0 && PhotonNetwork.logLevel >= PhotonLogLevel.Informational) { Debug.Log("New level loaded. Removed " + list.Count + " scene view IDs from last level."); } } public void RunViewUpdate() { if (PhotonNetwork.connected && !PhotonNetwork.offlineMode && mActors != null && mActors.Count > 1) { int num = 0; RaiseEventOptions raiseEventOptions = new RaiseEventOptions(); foreach (PhotonView value3 in photonViewList.Values) { if (value3.synchronization != 0 && value3.isMine && value3.gameObject.activeInHierarchy && !blockSendingGroups.Contains(value3.group)) { object[] array = OnSerializeWrite(value3); if (array != null) { if (value3.synchronization == ViewSynchronization.ReliableDeltaCompressed || value3.mixedModeIsReliable) { ExitGames.Client.Photon.Hashtable value = null; if (!dataPerGroupReliable.TryGetValue(value3.group, out value)) { value = new ExitGames.Client.Photon.Hashtable(ObjectsInOneUpdate); dataPerGroupReliable[value3.group] = value; } value.Add((byte)(value.Count + 10), array); num++; if (value.Count >= ObjectsInOneUpdate) { num -= value.Count; raiseEventOptions.InterestGroup = (byte)value3.group; value[(byte)0] = PhotonNetwork.ServerTimestamp; if (currentLevelPrefix >= 0) { value[(byte)1] = currentLevelPrefix; } OpRaiseEvent(206, value, sendReliable: true, raiseEventOptions); value.Clear(); } } else { ExitGames.Client.Photon.Hashtable value2 = null; if (!dataPerGroupUnreliable.TryGetValue(value3.group, out value2)) { value2 = new ExitGames.Client.Photon.Hashtable(ObjectsInOneUpdate); dataPerGroupUnreliable[value3.group] = value2; } value2.Add((byte)(value2.Count + 10), array); num++; if (value2.Count >= ObjectsInOneUpdate) { num -= value2.Count; raiseEventOptions.InterestGroup = (byte)value3.group; value2[(byte)0] = PhotonNetwork.ServerTimestamp; if (currentLevelPrefix >= 0) { value2[(byte)1] = currentLevelPrefix; } OpRaiseEvent(201, value2, sendReliable: false, raiseEventOptions); value2.Clear(); } } } } } if (num != 0) { foreach (int key in dataPerGroupReliable.Keys) { raiseEventOptions.InterestGroup = (byte)key; ExitGames.Client.Photon.Hashtable hashtable = dataPerGroupReliable[key]; if (hashtable.Count != 0) { hashtable[(byte)0] = PhotonNetwork.ServerTimestamp; if (currentLevelPrefix >= 0) { hashtable[(byte)1] = currentLevelPrefix; } OpRaiseEvent(206, hashtable, sendReliable: true, raiseEventOptions); hashtable.Clear(); } } foreach (int key2 in dataPerGroupUnreliable.Keys) { raiseEventOptions.InterestGroup = (byte)key2; ExitGames.Client.Photon.Hashtable hashtable2 = dataPerGroupUnreliable[key2]; if (hashtable2.Count != 0) { hashtable2[(byte)0] = PhotonNetwork.ServerTimestamp; if (currentLevelPrefix >= 0) { hashtable2[(byte)1] = currentLevelPrefix; } OpRaiseEvent(201, hashtable2, sendReliable: false, raiseEventOptions); hashtable2.Clear(); } } } } } private object[] OnSerializeWrite(PhotonView view) { if (view.synchronization == ViewSynchronization.Off) { return null; } PhotonMessageInfo info = new PhotonMessageInfo(LocalPlayer, PhotonNetwork.ServerTimestamp, view); pStream.ResetWriteStream(); pStream.SendNext(view.viewID); pStream.SendNext(false); pStream.SendNext(null); view.SerializeView(pStream, info); if (pStream.Count <= 3) { return null; } if (view.synchronization == ViewSynchronization.Unreliable) { return pStream.ToArray(); } object[] array = pStream.ToArray(); if (view.synchronization == ViewSynchronization.UnreliableOnChange) { if (AlmostEquals(array, view.lastOnSerializeDataSent)) { if (view.mixedModeIsReliable) { return null; } view.mixedModeIsReliable = true; view.lastOnSerializeDataSent = array; } else { view.mixedModeIsReliable = false; view.lastOnSerializeDataSent = array; } return array; } if (view.synchronization == ViewSynchronization.ReliableDeltaCompressed) { object[] result = DeltaCompressionWrite(view.lastOnSerializeDataSent, array); view.lastOnSerializeDataSent = array; return result; } return null; } private void OnSerializeRead(object[] data, PhotonPlayer sender, int networkTime, short correctPrefix) { int num = (int)data[0]; PhotonView photonView = GetPhotonView(num); if (photonView == null) { Debug.LogWarning("Received OnSerialization for view ID " + num + ". We have no such PhotonView! Ignored this if you're leaving a room. State: " + State); } else if (photonView.prefix > 0 && correctPrefix != photonView.prefix) { Debug.LogError("Received OnSerialization for view ID " + num + " with prefix " + correctPrefix + ". Our prefix is " + photonView.prefix); } else if (photonView.group == 0 || allowedReceivingGroups.Contains(photonView.group)) { if (photonView.synchronization == ViewSynchronization.ReliableDeltaCompressed) { object[] array = DeltaCompressionRead(photonView.lastOnSerializeDataReceived, data); if (array == null) { if (PhotonNetwork.logLevel >= PhotonLogLevel.Informational) { Debug.Log("Skipping packet for " + photonView.name + " [" + photonView.viewID + "] as we haven't received a full packet for delta compression yet. This is OK if it happens for the first few frames after joining a game."); } return; } photonView.lastOnSerializeDataReceived = array; data = array; } if (sender.ID != photonView.ownerId && (!photonView.OwnerShipWasTransfered || photonView.ownerId == 0) && photonView.currentMasterID == -1) { photonView.ownerId = sender.ID; } readStream.SetReadStream(data, 3); photonView.DeserializeView(info: new PhotonMessageInfo(sender, networkTime, photonView), stream: readStream); } } private object[] DeltaCompressionWrite(object[] previousContent, object[] currentContent) { if (currentContent == null || previousContent == null || previousContent.Length != currentContent.Length) { return currentContent; } if (currentContent.Length <= 3) { return null; } previousContent[1] = false; int num = 0; Queue queue = null; for (int i = 3; i < currentContent.Length; i++) { object obj = currentContent[i]; object two = previousContent[i]; if (AlmostEquals(obj, two)) { num++; previousContent[i] = null; } else { previousContent[i] = obj; if (obj == null) { if (queue == null) { queue = new Queue(currentContent.Length); } queue.Enqueue(i); } } } if (num > 0) { if (num == currentContent.Length - 3) { return null; } previousContent[1] = true; if (queue != null) { previousContent[2] = queue.ToArray(); } } previousContent[0] = currentContent[0]; return previousContent; } private object[] DeltaCompressionRead(object[] lastOnSerializeDataReceived, object[] incomingData) { if (!(bool)incomingData[1]) { return incomingData; } if (lastOnSerializeDataReceived == null) { return null; } int[] array = incomingData[2] as int[]; for (int i = 3; i < incomingData.Length; i++) { if ((array == null || !array.Contains(i)) && incomingData[i] == null) { object obj = incomingData[i] = lastOnSerializeDataReceived[i]; } } return incomingData; } private bool AlmostEquals(object[] lastData, object[] currentContent) { if (lastData == null && currentContent == null) { return true; } if (lastData == null || currentContent == null || lastData.Length != currentContent.Length) { return false; } for (int i = 0; i < currentContent.Length; i++) { object one = currentContent[i]; object two = lastData[i]; if (!AlmostEquals(one, two)) { return false; } } return true; } private bool AlmostEquals(object one, object two) { if (one == null || two == null) { return one == null && two == null; } if (!one.Equals(two)) { if (one is Vector3) { Vector3 target = (Vector3)one; Vector3 second = (Vector3)two; if (target.AlmostEquals(second, PhotonNetwork.precisionForVectorSynchronization)) { return true; } } else if (one is Vector2) { Vector2 target2 = (Vector2)one; Vector2 second2 = (Vector2)two; if (target2.AlmostEquals(second2, PhotonNetwork.precisionForVectorSynchronization)) { return true; } } else if (one is Quaternion) { Quaternion target3 = (Quaternion)one; Quaternion second3 = (Quaternion)two; if (target3.AlmostEquals(second3, PhotonNetwork.precisionForQuaternionSynchronization)) { return true; } } else if (one is float) { float target4 = (float)one; float second4 = (float)two; if (target4.AlmostEquals(second4, PhotonNetwork.precisionForFloatSynchronization)) { return true; } } return false; } return true; } protected internal static bool GetMethod(MonoBehaviour monob, string methodType, out MethodInfo mi) { mi = null; if (monob == null || string.IsNullOrEmpty(methodType)) { return false; } List methods = SupportClass.GetMethods(monob.GetType(), null); for (int i = 0; i < methods.Count; i++) { MethodInfo methodInfo = methods[i]; if (methodInfo.Name.Equals(methodType)) { mi = methodInfo; return true; } } return false; } protected internal void LoadLevelIfSynced() { if (PhotonNetwork.automaticallySyncScene && !PhotonNetwork.isMasterClient && PhotonNetwork.room != null && PhotonNetwork.room.CustomProperties.ContainsKey("curScn")) { object obj = PhotonNetwork.room.CustomProperties["curScn"]; if (obj is int) { if (SceneManagerHelper.ActiveSceneBuildIndex != (int)obj) { PhotonNetwork.LoadLevel((int)obj); } } else if (obj is string && SceneManagerHelper.ActiveSceneName != (string)obj) { PhotonNetwork.LoadLevel((string)obj); } } } protected internal void SetLevelInPropsIfSynced(object levelId) { if (PhotonNetwork.automaticallySyncScene && PhotonNetwork.isMasterClient && PhotonNetwork.room != null) { if (levelId == null) { Debug.LogError("Parameter levelId can't be null!"); } else { if (PhotonNetwork.room.CustomProperties.ContainsKey("curScn")) { object obj = PhotonNetwork.room.CustomProperties["curScn"]; if ((obj is int && SceneManagerHelper.ActiveSceneBuildIndex == (int)obj) || (obj is string && SceneManagerHelper.ActiveSceneName != null && SceneManagerHelper.ActiveSceneName.Equals((string)obj))) { return; } } ExitGames.Client.Photon.Hashtable hashtable = new ExitGames.Client.Photon.Hashtable(); if (levelId is int) { hashtable["curScn"] = (int)levelId; } else if (levelId is string) { hashtable["curScn"] = (string)levelId; } else { Debug.LogError("Parameter levelId must be int or string!"); } PhotonNetwork.room.SetCustomProperties(hashtable); SendOutgoingCommands(); } } } public void SetApp(string appId, string gameVersion) { AppId = appId.Trim(); if (!string.IsNullOrEmpty(gameVersion)) { PhotonNetwork.gameVersion = gameVersion.Trim(); } } public bool WebRpc(string uriPath, object parameters) { Dictionary dictionary = new Dictionary(); dictionary.Add(209, uriPath); dictionary.Add(208, parameters); return OpCustom(219, dictionary, sendReliable: true); } }