internal static void OnFirstSceneSwitchSync(uint sceneIndex, Guid switchSceneGuid) { if (!SceneIndexToString.ContainsKey(sceneIndex) || !RegisteredSceneNames.Contains(SceneIndexToString[sceneIndex])) { if (NetworkLog.CurrentLogLevel <= LogLevel.Normal) { NetworkLog.LogWarning("Server requested a scene switch to a non-registered scene"); } return; } if (SceneManager.GetActiveScene().name == SceneIndexToString[sceneIndex]) { return; //This scene is already loaded. This usually happends at first load } s_LastScene = SceneManager.GetActiveScene(); string sceneName = SceneIndexToString[sceneIndex]; s_NextSceneName = sceneName; CurrentActiveSceneIndex = SceneNameToIndex[sceneName]; IsSpawnedObjectsPendingInDontDestroyOnLoad = true; SceneManager.LoadScene(sceneName); using (var buffer = PooledNetworkBuffer.Get()) using (var writer = PooledNetworkWriter.Get(buffer)) { writer.WriteByteArray(switchSceneGuid.ToByteArray()); InternalMessageSender.Send(NetworkManager.Singleton.ServerClientId, NetworkConstants.CLIENT_SWITCH_SCENE_COMPLETED, NetworkChannel.Internal, buffer); } s_IsSwitching = false; }
internal static void HandleConnectionRequest(ulong clientId, Stream stream) { using (PooledBitReader reader = PooledBitReader.Get(stream)) { ulong configHash = reader.ReadUInt64Packed(); if (!NetworkingManager.Singleton.NetworkConfig.CompareConfig(configHash)) { if (NetworkLog.CurrentLogLevel <= LogLevel.Normal) { NetworkLog.LogWarning("NetworkConfiguration mismatch. The configuration between the server and client does not match"); } NetworkingManager.Singleton.DisconnectClient(clientId); return; } if (NetworkingManager.Singleton.NetworkConfig.ConnectionApproval) { byte[] connectionBuffer = reader.ReadByteArray(); NetworkingManager.Singleton.InvokeConnectionApproval(connectionBuffer, clientId, (createPlayerObject, playerPrefabHash, approved, position, rotation) => { NetworkingManager.Singleton.HandleApproval(clientId, createPlayerObject, playerPrefabHash, approved, position, rotation); }); } else { NetworkingManager.Singleton.HandleApproval(clientId, NetworkingManager.Singleton.NetworkConfig.CreatePlayerPrefab, null, true, null, null); } } }
/// <summary> /// Sends unnamed message to a list of clients /// </summary> /// <param name="clientIds">The clients to send to, sends to everyone if null</param> /// <param name="stream">The message stream containing the data</param> /// <param name="channel">The channel to send the data on</param> /// <param name="security">The security settings to apply to the message</param> public static void SendUnnamedMessage(List <ulong> clientIds, BitStream stream, string channel = null, SecuritySendFlags security = SecuritySendFlags.None) { if (!NetworkingManager.Singleton.IsServer) { if (NetworkLog.CurrentLogLevel <= LogLevel.Error) { NetworkLog.LogWarning("Can not send unnamed messages to multiple users as a client"); } return; } if (clientIds == null) { for (int i = 0; i < NetworkingManager.Singleton.ConnectedClientsList.Count; i++) { InternalMessageSender.Send(NetworkingManager.Singleton.ConnectedClientsList[i].ClientId, MLAPIConstants.MLAPI_UNNAMED_MESSAGE, string.IsNullOrEmpty(channel) ? "MLAPI_DEFAULT_MESSAGE" : channel, stream, security, null); } } else { for (int i = 0; i < clientIds.Count; i++) { InternalMessageSender.Send(clientIds[i], MLAPIConstants.MLAPI_UNNAMED_MESSAGE, string.IsNullOrEmpty(channel) ? "MLAPI_DEFAULT_MESSAGE" : channel, stream, security, null); } } }
// Called on client internal static void OnSceneSwitch(uint sceneIndex, Guid switchSceneGuid, Stream objectStream) { if (!sceneIndexToString.ContainsKey(sceneIndex) || !registeredSceneNames.Contains(sceneIndexToString[sceneIndex])) { if (NetworkLog.CurrentLogLevel <= LogLevel.Normal) { NetworkLog.LogWarning("Server requested a scene switch to a non registered scene"); } return; } lastScene = SceneManager.GetActiveScene(); // Move ALL networked objects to the temp scene MoveObjectsToDontDestroyOnLoad(); isSpawnedObjectsPendingInDontDestroyOnLoad = true; string sceneName = sceneIndexToString[sceneIndex]; AsyncOperation sceneLoad = SceneManager.LoadSceneAsync(sceneName, LoadSceneMode.Single); nextSceneName = sceneName; sceneLoad.completed += (AsyncOperation asyncOp2) => { OnSceneLoaded(switchSceneGuid, objectStream); }; if (OnSceneSwitchStarted != null) { OnSceneSwitchStarted(sceneLoad); } }
internal static void OnFirstSceneSwitchSync(uint sceneIndex, Guid switchSceneGuid) { if (!sceneIndexToString.ContainsKey(sceneIndex) || !registeredSceneNames.Contains(sceneIndexToString[sceneIndex])) { if (NetworkLog.CurrentLogLevel <= LogLevel.Normal) { NetworkLog.LogWarning("Server requested a scene switch to a non registered scene"); } return; } else if (SceneManager.GetActiveScene().name == sceneIndexToString[sceneIndex]) { return; //This scene is already loaded. This usually happends at first load } lastScene = SceneManager.GetActiveScene(); string sceneName = sceneIndexToString[sceneIndex]; nextSceneName = sceneName; CurrentActiveSceneIndex = sceneNameToIndex[sceneName]; isSpawnedObjectsPendingInDontDestroyOnLoad = true; SceneManager.LoadScene(sceneName); using (PooledBitStream stream = PooledBitStream.Get()) { using (PooledBitWriter writer = PooledBitWriter.Get(stream)) { writer.WriteByteArray(switchSceneGuid.ToByteArray()); InternalMessageSender.Send(NetworkingManager.Singleton.ServerClientId, MLAPIConstants.MLAPI_CLIENT_SWITCH_SCENE_COMPLETED, "MLAPI_INTERNAL", stream, SecuritySendFlags.None, null); } } isSwitching = false; }
/// <summary> /// Sends the named message /// </summary> /// <param name="name">The message name to send</param> /// <param name="clientIds">The clients to send to, sends to everyone if null</param> /// <param name="stream">The message stream containing the data</param> /// <param name="channel">The channel to send the data on</param> /// <param name="security">The security settings to apply to the message</param> public static void SendNamedMessage(string name, List <ulong> clientIds, Stream stream, string channel = null, SecuritySendFlags security = SecuritySendFlags.None) { ulong hash = NetworkedBehaviour.HashMethodName(name); using (PooledBitStream messageStream = PooledBitStream.Get()) { using (PooledBitWriter writer = PooledBitWriter.Get(messageStream)) { writer.WriteUInt64Packed(hash); } messageStream.CopyFrom(stream); if (!NetworkingManager.Singleton.IsServer) { if (NetworkLog.CurrentLogLevel <= LogLevel.Error) { NetworkLog.LogWarning("Can not send named messages to multiple users as a client"); } return; } InternalMessageSender.Send(MLAPIConstants.MLAPI_NAMED_MESSAGE, string.IsNullOrEmpty(channel) ? "MLAPI_DEFAULT_MESSAGE" : channel, clientIds, messageStream, security, null); } }
internal static void HandleSyncedVar(ulong clientId, Stream stream) { using (PooledBitReader reader = PooledBitReader.Get(stream)) { ulong networkId = reader.ReadUInt64Packed(); ushort orderIndex = reader.ReadUInt16Packed(); if (SpawnManager.SpawnedObjects.ContainsKey(networkId)) { NetworkedBehaviour instance = SpawnManager.SpawnedObjects[networkId].GetBehaviourAtOrderIndex(orderIndex); if (instance == null) { if (NetworkLog.CurrentLogLevel <= LogLevel.Normal) { NetworkLog.LogWarning("SyncedVar message received for a non existant behaviour"); } return; } NetworkedBehaviour.HandleSyncedVarValue(instance.syncedVars, stream, clientId, instance); } else { if (NetworkLog.CurrentLogLevel <= LogLevel.Normal) { NetworkLog.LogWarning("SyncedVar message received for a non existant object with id: " + networkId); } return; } } }
internal static void HandleServerRPCResponse(ulong clientId, Stream stream) { using (PooledBitReader reader = PooledBitReader.Get(stream)) { ulong responseId = reader.ReadUInt64Packed(); if (ResponseMessageManager.ContainsKey(responseId)) { RpcResponseBase responseBase = ResponseMessageManager.GetByKey(responseId); ResponseMessageManager.Remove(responseId); responseBase.IsDone = true; responseBase.Result = reader.ReadObjectPacked(responseBase.Type); responseBase.IsSuccessful = true; } else { if (NetworkLog.CurrentLogLevel <= LogLevel.Normal) { NetworkLog.LogWarning("ServerRPCResponse message received for a non existant responseId: " + responseId + ". This response is lost."); } } } }
internal static void HandleServerRPC(ulong clientId, Stream stream) { using (PooledBitReader reader = PooledBitReader.Get(stream)) { ulong networkId = reader.ReadUInt64Packed(); ushort behaviourId = reader.ReadUInt16Packed(); ulong hash = reader.ReadUInt64Packed(); if (SpawnManager.SpawnedObjects.ContainsKey(networkId)) { NetworkedBehaviour behaviour = SpawnManager.SpawnedObjects[networkId].GetBehaviourAtOrderIndex(behaviourId); if (behaviour == null) { if (NetworkLog.CurrentLogLevel <= LogLevel.Normal) { NetworkLog.LogWarning("ServerRPC message received for a non existant behaviour. NetworkId: " + networkId + ", behaviourIndex: " + behaviourId); } } else { behaviour.OnRemoteServerRPC(hash, clientId, stream); } } else if (NetworkingManager.Singleton.IsServer || !NetworkingManager.Singleton.NetworkConfig.EnableMessageBuffering) { if (NetworkLog.CurrentLogLevel <= LogLevel.Normal) { NetworkLog.LogWarning("ServerRPC message received for a non existant object with id: " + networkId + ". This message is lost."); } } } }
/// <summary> /// Retrieves a PooledBitReader /// </summary> /// <param name="stream">The stream the reader should read from</param> /// <returns>A PooledBitReader</returns> public static PooledBitReader GetReader(Stream stream) { if (readers.Count == 0) { if (createdReaders == 254) { if (NetworkLog.CurrentLogLevel <= LogLevel.Normal) { NetworkLog.LogWarning("255 readers have been created. Did you forget to dispose?"); } } else if (createdReaders < 255) { createdReaders++; } return(new PooledBitReader(stream)); } PooledBitReader reader = readers.Dequeue(); reader.SetStream(stream); return(reader); }
internal static void Send(ulong clientId, byte messageType, string channelName, BitStream messageStream, SecuritySendFlags flags, NetworkedObject targetObject) { messageStream.PadStream(); if (NetworkingManager.Singleton.IsServer && clientId == NetworkingManager.Singleton.ServerClientId) { return; } if (targetObject != null && !targetObject.observers.Contains(clientId)) { if (NetworkLog.CurrentLogLevel <= LogLevel.Developer) { NetworkLog.LogWarning("Silently suppressed send call because it was directed to an object without visibility"); } return; } using (BitStream stream = MessagePacker.WrapMessage(messageType, clientId, messageStream, flags)) { NetworkProfiler.StartEvent(TickType.Send, (uint)stream.Length, channelName, MLAPIConstants.MESSAGE_NAMES[messageType]); NetworkingManager.Singleton.NetworkConfig.NetworkTransport.Send(clientId, new ArraySegment <byte>(stream.GetBuffer(), 0, (int)stream.Length), channelName); NetworkProfiler.EndEvent(); } }
/// <summary> /// Retrieves a PooledNetworkWriter /// </summary> /// <param name="stream">The stream the writer should write to</param> /// <returns>A PooledNetworkWriter</returns> public static PooledNetworkWriter GetWriter(Stream stream) { if (s_Writers.Count == 0) { if (s_CreatedWriters == 254) { if (NetworkLog.CurrentLogLevel <= LogLevel.Normal) { NetworkLog.LogWarning("255 writers have been created. Did you forget to dispose?"); } } else if (s_CreatedWriters < 255) { s_CreatedWriters++; } return(new PooledNetworkWriter(stream)); } PooledNetworkWriter writer = s_Writers.Dequeue(); writer.SetStream(stream); return(writer); }
internal static void HandleConnectionRequest(ulong clientId, Stream stream) { #if DEVELOPMENT_BUILD || UNITY_EDITOR s_HandleConnectionRequest.Begin(); #endif using (var reader = PooledNetworkReader.Get(stream)) { ulong configHash = reader.ReadUInt64Packed(); if (!NetworkManager.Singleton.NetworkConfig.CompareConfig(configHash)) { if (NetworkLog.CurrentLogLevel <= LogLevel.Normal) { NetworkLog.LogWarning($"{nameof(NetworkConfig)} mismatch. The configuration between the server and client does not match"); } NetworkManager.Singleton.DisconnectClient(clientId); return; } if (NetworkManager.Singleton.NetworkConfig.ConnectionApproval) { byte[] connectionBuffer = reader.ReadByteArray(); NetworkManager.Singleton.InvokeConnectionApproval(connectionBuffer, clientId, (createPlayerObject, playerPrefabHash, approved, position, rotation) => { NetworkManager.Singleton.HandleApproval(clientId, createPlayerObject, playerPrefabHash, approved, position, rotation); }); } else { NetworkManager.Singleton.HandleApproval(clientId, NetworkManager.Singleton.NetworkConfig.CreatePlayerPrefab, null, true, null, null); } } #if DEVELOPMENT_BUILD || UNITY_EDITOR s_HandleConnectionRequest.End(); #endif }
internal static ReflectionMethod Create(MethodInfo method, ParameterInfo[] parameters, int index) { RPCAttribute[] attributes = (RPCAttribute[])method.GetCustomAttributes(typeof(RPCAttribute), true); if (attributes.Length == 0) { return(null); } if (attributes.Length > 1) { if (NetworkLog.CurrentLogLevel <= LogLevel.Normal) { NetworkLog.LogWarning("Having more than one ServerRPC or ClientRPC attribute per method is not supported."); } } if (method.ReturnType != typeof(void) && !SerializationManager.IsTypeSupported(method.ReturnType)) { if (NetworkLog.CurrentLogLevel <= LogLevel.Error) { NetworkLog.LogWarning("Invalid return type of RPC. Has to be either void or RpcResponse<T> with a serializable type"); } } return(new ReflectionMethod(method, parameters, attributes[0], index)); }
// Called on client internal static void OnSceneSwitch(uint sceneIndex, Guid switchSceneGuid, Stream objectStream) { if (!SceneIndexToString.ContainsKey(sceneIndex) || !RegisteredSceneNames.Contains(SceneIndexToString[sceneIndex])) { if (NetworkLog.CurrentLogLevel <= LogLevel.Normal) { NetworkLog.LogWarning("Server requested a scene switch to a non-registered scene"); } return; } s_LastScene = SceneManager.GetActiveScene(); // Move ALL NetworkObjects to the temp scene MoveObjectsToDontDestroyOnLoad(); IsSpawnedObjectsPendingInDontDestroyOnLoad = true; string sceneName = SceneIndexToString[sceneIndex]; var sceneLoad = SceneManager.LoadSceneAsync(sceneName, LoadSceneMode.Single); s_NextSceneName = sceneName; sceneLoad.completed += asyncOp2 => OnSceneLoaded(switchSceneGuid, objectStream); OnSceneSwitchStarted?.Invoke(sceneLoad); }
public static void NotifyProfilerListeners() { if (!s_FailsafeCheck) { return; } s_FailsafeCheck = false; var data = PerformanceDataManager.GetData(); var eventHandler = OnPerformanceDataEvent; if (eventHandler != null) { if (data != null) { var transport = s_ProfilableTransportProvider.Transport; if (transport != null) { var transportProfilerData = transport.GetTransportProfilerData(); PerformanceDataManager.AddTransportData(transportProfilerData); } eventHandler.Invoke(data); } else { NetworkLog.LogWarning( "No data available. Did you forget to call PerformanceDataManager.BeginNewTick() first?"); } } }
internal static void HandleNetworkVariableUpdate(ulong clientId, Stream stream, Action <ulong, PreBufferPreset> bufferCallback, PreBufferPreset bufferPreset) { #if DEVELOPMENT_BUILD || UNITY_EDITOR s_HandleNetworkVariableUpdate.Begin(); #endif if (!NetworkManager.Singleton.NetworkConfig.EnableNetworkVariable) { if (NetworkLog.CurrentLogLevel <= LogLevel.Normal) { NetworkLog.LogWarning($"{nameof(NetworkConstants.NETWORK_VARIABLE_UPDATE)} update received but {nameof(NetworkConfig.EnableNetworkVariable)} is false"); } return; } using (var reader = PooledNetworkReader.Get(stream)) { ulong networkObjectId = reader.ReadUInt64Packed(); ushort networkBehaviourIndex = reader.ReadUInt16Packed(); if (NetworkSpawnManager.SpawnedObjects.ContainsKey(networkObjectId)) { var networkBehaviour = NetworkSpawnManager.SpawnedObjects[networkObjectId].GetNetworkBehaviourAtOrderIndex(networkBehaviourIndex); if (networkBehaviour == null) { if (NetworkLog.CurrentLogLevel <= LogLevel.Normal) { NetworkLog.LogWarning($"{nameof(NetworkConstants.NETWORK_VARIABLE_UPDATE)} message received for a non-existent behaviour. {nameof(networkObjectId)}: {networkObjectId}, {nameof(networkBehaviourIndex)}: {networkBehaviourIndex}"); } } else { NetworkBehaviour.HandleNetworkVariableUpdate(networkBehaviour.NetworkVariableFields, stream, clientId, networkBehaviour); } } else if (NetworkManager.Singleton.IsServer || !NetworkManager.Singleton.NetworkConfig.EnableMessageBuffering) { if (NetworkLog.CurrentLogLevel <= LogLevel.Normal) { NetworkLog.LogWarning($"{nameof(NetworkConstants.NETWORK_VARIABLE_UPDATE)} message received for a non-existent object with {nameof(networkObjectId)}: {networkObjectId}. This delta was lost."); } } else { if (NetworkLog.CurrentLogLevel <= LogLevel.Normal) { NetworkLog.LogWarning($"{nameof(NetworkConstants.NETWORK_VARIABLE_UPDATE)} message received for a non-existent object with {nameof(networkObjectId)}: {networkObjectId}. This delta will be buffered and might be recovered."); } bufferCallback(networkObjectId, bufferPreset); } } #if DEVELOPMENT_BUILD || UNITY_EDITOR s_HandleNetworkVariableUpdate.End(); #endif }
/// <summary> /// Switches to a scene with a given name. Can only be called from Server /// </summary> /// <param name="sceneName">The name of the scene to switch to</param> public static SceneSwitchProgress SwitchScene(string sceneName) { if (!NetworkingManager.Singleton.IsServer) { throw new NotServerException("Only server can start a scene switch"); } else if (isSwitching) { if (NetworkLog.CurrentLogLevel <= LogLevel.Normal) { NetworkLog.LogWarning("Scene switch already in progress"); } return(null); } else if (!registeredSceneNames.Contains(sceneName)) { if (NetworkLog.CurrentLogLevel <= LogLevel.Normal) { NetworkLog.LogWarning("The scene " + sceneName + " is not registered as a switchable scene."); } return(null); } SpawnManager.ServerDestroySpawnedSceneObjects(); //Destroy current scene objects before switching. isSwitching = true; lastScene = SceneManager.GetActiveScene(); SceneSwitchProgress switchSceneProgress = new SceneSwitchProgress(); sceneSwitchProgresses.Add(switchSceneProgress.guid, switchSceneProgress); currentSceneSwitchProgressGuid = switchSceneProgress.guid; // Move ALL networked objects to the temp scene MoveObjectsToDontDestroyOnLoad(); isSpawnedObjectsPendingInDontDestroyOnLoad = true; // Switch scene AsyncOperation sceneLoad = SceneManager.LoadSceneAsync(sceneName, LoadSceneMode.Single); nextSceneName = sceneName; sceneLoad.completed += (AsyncOperation asyncOp2) => { OnSceneLoaded(switchSceneProgress.guid, null); }; switchSceneProgress.SetSceneLoadOperation(sceneLoad); if (OnSceneSwitchStarted != null) { OnSceneSwitchStarted(sceneLoad); } return(switchSceneProgress); }
internal static void HandleClientRPCRequest(ulong clientId, Stream stream, string channelName, SecuritySendFlags security, Action <ulong, PreBufferPreset> bufferCallback, PreBufferPreset bufferPreset) { using (PooledBitReader reader = PooledBitReader.Get(stream)) { ulong networkId = reader.ReadUInt64Packed(); ushort behaviourId = reader.ReadUInt16Packed(); ulong hash = reader.ReadUInt64Packed(); ulong responseId = reader.ReadUInt64Packed(); if (SpawnManager.SpawnedObjects.ContainsKey(networkId)) { NetworkedBehaviour behaviour = SpawnManager.SpawnedObjects[networkId].GetBehaviourAtOrderIndex(behaviourId); if (behaviour == null) { if (NetworkLog.CurrentLogLevel <= LogLevel.Normal) { NetworkLog.LogWarning("ClientRPCRequest message received for a non existant behaviour. NetworkId: " + networkId + ", behaviourIndex: " + behaviourId); } } else { object result = behaviour.OnRemoteClientRPC(hash, clientId, stream); using (PooledBitStream responseStream = PooledBitStream.Get()) { using (PooledBitWriter responseWriter = PooledBitWriter.Get(responseStream)) { responseWriter.WriteUInt64Packed(responseId); responseWriter.WriteObjectPacked(result); } InternalMessageSender.Send(clientId, MLAPIConstants.MLAPI_CLIENT_RPC_RESPONSE, channelName, responseStream, security, null); } } } else if (NetworkingManager.Singleton.IsServer || !NetworkingManager.Singleton.NetworkConfig.EnableMessageBuffering) { if (NetworkLog.CurrentLogLevel <= LogLevel.Normal) { NetworkLog.LogWarning("ClientRPCRequest message received for a non existant object with id: " + networkId + ". This message is lost."); } } else { if (NetworkLog.CurrentLogLevel <= LogLevel.Normal) { NetworkLog.LogWarning("ClientRPCRequest message received for a non existant object with id: " + networkId + ". This message will be buffered and might be recovered."); } bufferCallback(networkId, bufferPreset); } } }
/// <summary> /// Sends unnamed message to a list of clients /// </summary> /// <param name="clientIds">The clients to send to, sends to everyone if null</param> /// <param name="buffer">The message stream containing the data</param> /// <param name="networkChannel">The channel to send the data on</param> public static void SendUnnamedMessage(List <ulong> clientIds, NetworkBuffer buffer, NetworkChannel networkChannel = NetworkChannel.Internal) { if (!NetworkManager.Singleton.IsServer) { if (NetworkLog.CurrentLogLevel <= LogLevel.Error) { NetworkLog.LogWarning("Can not send unnamed messages to multiple users as a client"); } return; } InternalMessageSender.Send(NetworkConstants.UNNAMED_MESSAGE, networkChannel, clientIds, buffer); }
/// <summary> /// Sends unnamed message to a list of clients /// </summary> /// <param name="clientIds">The clients to send to, sends to everyone if null</param> /// <param name="stream">The message stream containing the data</param> /// <param name="channel">The channel to send the data on</param> /// <param name="security">The security settings to apply to the message</param> public static void SendUnnamedMessage(List <ulong> clientIds, BitStream stream, string channel = null, SecuritySendFlags security = SecuritySendFlags.None) { if (!NetworkingManager.Singleton.IsServer) { if (NetworkLog.CurrentLogLevel <= LogLevel.Error) { NetworkLog.LogWarning("Can not send unnamed messages to multiple users as a client"); } return; } InternalMessageSender.Send(MLAPIConstants.MLAPI_UNNAMED_MESSAGE, string.IsNullOrEmpty(channel) ? "MLAPI_DEFAULT_MESSAGE" : channel, clientIds, stream, security, null); }
internal static void SetCurrentSceneIndex() { if (!sceneNameToIndex.ContainsKey(SceneManager.GetActiveScene().name)) { if (NetworkLog.CurrentLogLevel <= LogLevel.Normal) { NetworkLog.LogWarning("The current scene (" + SceneManager.GetActiveScene().name + ") is not regisered as a network scene."); } return; } currentSceneIndex = sceneNameToIndex[SceneManager.GetActiveScene().name]; CurrentActiveSceneIndex = currentSceneIndex; }
/// <summary> /// Retrieves an expandable PooledBitStream from the pool /// </summary> /// <returns>An expandable PooledBitStream</returns> public static PooledBitStream GetStream() { if (streams.Count == 0) { if (overflowStreams.Count > 0) { if (NetworkLog.CurrentLogLevel <= LogLevel.Developer) { NetworkLog.LogInfo("Retrieving PooledBitStream from overflow pool. Recent burst?"); } object weakStream = null; while (overflowStreams.Count > 0 && ((weakStream = overflowStreams.Dequeue().Target) == null)) { ; } if (weakStream != null) { PooledBitStream strongStream = (PooledBitStream)weakStream; strongStream.SetLength(0); strongStream.Position = 0; return(strongStream); } } if (createdStreams == 254) { if (NetworkLog.CurrentLogLevel <= LogLevel.Normal) { NetworkLog.LogWarning("255 streams have been created. Did you forget to dispose?"); } } else if (createdStreams < 255) { createdStreams++; } return(new PooledBitStream()); } PooledBitStream stream = streams.Dequeue(); stream.SetLength(0); stream.Position = 0; return(stream); }
/// <summary> /// Retrieves an expandable PooledNetworkBuffer from the pool /// </summary> /// <returns>An expandable PooledNetworkBuffer</returns> public static PooledNetworkBuffer GetBuffer() { if (s_Buffers.Count == 0) { if (s_OverflowBuffers.Count > 0) { if (NetworkLog.CurrentLogLevel <= LogLevel.Developer) { NetworkLog.LogInfo($"Retrieving {nameof(PooledNetworkBuffer)} from overflow pool. Recent burst?"); } object weakBuffer = null; while (s_OverflowBuffers.Count > 0 && ((weakBuffer = s_OverflowBuffers.Dequeue().Target) == null)) { ; } if (weakBuffer != null) { PooledNetworkBuffer strongBuffer = (PooledNetworkBuffer)weakBuffer; strongBuffer.SetLength(0); strongBuffer.Position = 0; return(strongBuffer); } } if (s_CreatedBuffers == k_MaxBitPoolBuffers) { if (NetworkLog.CurrentLogLevel <= LogLevel.Normal) { NetworkLog.LogWarning($"{k_MaxBitPoolBuffers} buffers have been created. Did you forget to dispose?"); } } else if (s_CreatedBuffers < k_MaxBitPoolBuffers) { s_CreatedBuffers++; } return(new PooledNetworkBuffer()); } PooledNetworkBuffer buffer = s_Buffers.Dequeue(); buffer.SetLength(0); buffer.Position = 0; return(buffer); }
internal void SetCurrentSceneIndex() { if (!SceneNameToIndex.TryGetValue(SceneManager.GetActiveScene().name, out CurrentSceneIndex)) { if (NetworkLog.CurrentLogLevel <= LogLevel.Normal) { NetworkLog.LogWarning($"The current scene ({SceneManager.GetActiveScene().name}) is not regisered as a network scene."); } return; } CurrentActiveSceneIndex = CurrentSceneIndex; }
internal static void HandleNetworkedVarUpdate(ulong clientId, Stream stream, Action <ulong, PreBufferPreset> bufferCallback, PreBufferPreset bufferPreset) { if (!NetworkingManager.Singleton.NetworkConfig.EnableNetworkedVar) { if (NetworkLog.CurrentLogLevel <= LogLevel.Normal) { NetworkLog.LogWarning("NetworkedVar update received but EnableNetworkedVar is false"); } return; } using (PooledBitReader reader = PooledBitReader.Get(stream)) { ulong networkId = reader.ReadUInt64Packed(); ushort orderIndex = reader.ReadUInt16Packed(); if (SpawnManager.SpawnedObjects.ContainsKey(networkId)) { NetworkedBehaviour instance = SpawnManager.SpawnedObjects[networkId].GetBehaviourAtOrderIndex(orderIndex); if (instance == null) { if (NetworkLog.CurrentLogLevel <= LogLevel.Normal) { NetworkLog.LogWarning("NetworkedVarUpdate message received for a non existant behaviour. NetworkId: " + networkId + ", behaviourIndex: " + orderIndex); } } else { NetworkedBehaviour.HandleNetworkedVarUpdate(instance.networkedVarFields, stream, clientId, instance); } } else if (NetworkingManager.Singleton.IsServer || !NetworkingManager.Singleton.NetworkConfig.EnableMessageBuffering) { if (NetworkLog.CurrentLogLevel <= LogLevel.Normal) { NetworkLog.LogWarning("NetworkedVarUpdate message received for a non existant object with id: " + networkId + ". This delta was lost."); } } else { if (NetworkLog.CurrentLogLevel <= LogLevel.Normal) { NetworkLog.LogWarning("NetworkedVarUpdate message received for a non existant object with id: " + networkId + ". This delta will be buffered and might be recovered."); } bufferCallback(networkId, bufferPreset); } } }
/// <summary> /// Sends unnamed message to a list of clients /// </summary> /// <param name="clientIds">The clients to send to, sends to everyone if null</param> /// <param name="buffer">The message stream containing the data</param> /// <param name="networkChannel">The channel to send the data on</param> public void SendUnnamedMessage(List <ulong> clientIds, NetworkBuffer buffer, NetworkChannel networkChannel = NetworkChannel.Internal) { if (!m_NetworkManager.IsServer) { if (NetworkLog.CurrentLogLevel <= LogLevel.Error) { NetworkLog.LogWarning("Can not send unnamed messages to multiple users as a client"); } return; } m_NetworkManager.MessageSender.Send(NetworkConstants.UNNAMED_MESSAGE, networkChannel, clientIds, buffer); PerformanceDataManager.Increment(ProfilerConstants.UnnamedMessageSent); }
internal static void Send(byte messageType, string channelName, ulong clientIdToIgnore, BitStream messageStream, SecuritySendFlags flags, NetworkedObject targetObject) { bool encrypted = ((flags & SecuritySendFlags.Encrypted) == SecuritySendFlags.Encrypted) && NetworkingManager.Singleton.NetworkConfig.EnableEncryption; bool authenticated = ((flags & SecuritySendFlags.Authenticated) == SecuritySendFlags.Authenticated) && NetworkingManager.Singleton.NetworkConfig.EnableEncryption; if (encrypted || authenticated) { for (int i = 0; i < NetworkingManager.Singleton.ConnectedClientsList.Count; i++) { if (NetworkingManager.Singleton.ConnectedClientsList[i].ClientId == clientIdToIgnore) { continue; } Send(NetworkingManager.Singleton.ConnectedClientsList[i].ClientId, messageType, channelName, messageStream, flags, targetObject); } } else { messageStream.PadStream(); using (BitStream stream = MessagePacker.WrapMessage(messageType, 0, messageStream, flags)) { NetworkProfiler.StartEvent(TickType.Send, (uint)stream.Length, channelName, MLAPIConstants.MESSAGE_NAMES[messageType]); for (int i = 0; i < NetworkingManager.Singleton.ConnectedClientsList.Count; i++) { if (NetworkingManager.Singleton.ConnectedClientsList[i].ClientId == clientIdToIgnore || (NetworkingManager.Singleton.IsServer && NetworkingManager.Singleton.ConnectedClientsList[i].ClientId == NetworkingManager.Singleton.ServerClientId)) { continue; } if (targetObject != null && !targetObject.observers.Contains(NetworkingManager.Singleton.ConnectedClientsList[i].ClientId)) { if (NetworkLog.CurrentLogLevel <= LogLevel.Developer) { NetworkLog.LogWarning("Silently suppressed send(ignore) call because it was directed to an object without visibility"); } continue; } NetworkingManager.Singleton.NetworkConfig.NetworkTransport.Send(NetworkingManager.Singleton.ConnectedClientsList[i].ClientId, new ArraySegment <byte>(stream.GetBuffer(), 0, (int)stream.Length), channelName); } NetworkProfiler.EndEvent(); } } }
internal static void HandleServerRPCRequest(ulong clientId, Stream stream, string channelName, SecuritySendFlags security) { using (PooledBitReader reader = PooledBitReader.Get(stream)) { ulong networkId = reader.ReadUInt64Packed(); ushort behaviourId = reader.ReadUInt16Packed(); ulong hash = reader.ReadUInt64Packed(); ulong responseId = reader.ReadUInt64Packed(); if (SpawnManager.SpawnedObjects.ContainsKey(networkId)) { NetworkedBehaviour behaviour = SpawnManager.SpawnedObjects[networkId].GetBehaviourAtOrderIndex(behaviourId); if (behaviour == null) { if (NetworkLog.CurrentLogLevel <= LogLevel.Normal) { NetworkLog.LogWarning("ServerRPCRequest message received for a non existant behaviour. NetworkId: " + networkId + ", behaviourIndex: " + behaviourId); } } else { object result = behaviour.OnRemoteServerRPC(hash, clientId, stream); using (PooledBitStream responseStream = PooledBitStream.Get()) { using (PooledBitWriter responseWriter = PooledBitWriter.Get(responseStream)) { responseWriter.WriteUInt64Packed(responseId); responseWriter.WriteObjectPacked(result); } InternalMessageSender.Send(clientId, MLAPIConstants.MLAPI_SERVER_RPC_RESPONSE, channelName, responseStream, security, SpawnManager.SpawnedObjects[networkId]); } } } else { if (NetworkLog.CurrentLogLevel <= LogLevel.Normal) { NetworkLog.LogWarning("ServerRPCRequest message received for a non existant object with id: " + networkId + ". This message is lost."); } } } }
internal object Invoke(NetworkedBehaviour target, ulong senderClientId, Stream stream) { if (requireOwnership == true && senderClientId != target.OwnerClientId) { if (NetworkLog.CurrentLogLevel <= LogLevel.Normal) { NetworkLog.LogWarning("Only owner can invoke ServerRPC that is marked to require ownership"); } return(null); } target.executingRpcSender = senderClientId; if (stream.Position == 0) { if (useDelegate) { return(InvokeDelegate(target, senderClientId, stream)); } else { return(InvokeReflected(target, stream)); } } else { // Create a new stream so that the stream they get ONLY contains user data and not MLAPI headers using (PooledBitStream userStream = PooledBitStream.Get()) { userStream.CopyUnreadFrom(stream); userStream.Position = 0; if (useDelegate) { return(InvokeDelegate(target, senderClientId, userStream)); } else { return(InvokeReflected(target, userStream)); } } } }