private void OnLeftSpawnButtonPressed() { if (leftNetworkSquare.isNetworkSpawned) { leftNetworkSquare.UnspawnOnNetwork(); } else { if (m_NetworkManager.isServer) { using (PooledBitStream stream = PooledBitStream.Get()) { using (PooledBitWriter writer = PooledBitWriter.Get(stream)) { writer.WriteSinglePacked(m_LeftObjectPositioner.rect.center.x); writer.WriteSinglePacked(m_LeftObjectPositioner.rect.center.y); } leftNetworkSquare.SpawnOnNetwork(stream); } } else { leftNetworkSquare.SpawnOnNetwork(); } } }
void InvokeApplyTransform(ulong clientId, Vector3 position, Quaternion rotation, string channelName) { using (PooledBitStream stream = PooledBitStream.Get()) { using (PooledBitWriter writer = PooledBitWriter.Get(stream)) { if (TransformTypeToSync == TransformType.Transform2D) { if (SyncPosition && SyncRotation) { writer.WriteVector2Packed(position); writer.WriteSinglePacked(rotation.eulerAngles.z); } else if (SyncPosition) { writer.WriteVector2Packed(position); } else if (SyncRotation) { writer.WriteSinglePacked(rotation.eulerAngles.z); } InvokeClientRpcOnClientPerformance("ApplyTransform2D", clientId, stream, channelName, Security.SecuritySendFlags.None); } else if (TransformTypeToSync == TransformType.Transform3D) { if (SyncPosition && SyncRotation) { writer.WriteVector3Packed(position); if (FullRotation) { writer.WriteVector3Packed(rotation.eulerAngles); } else { writer.WriteSingle(rotation.eulerAngles.y); } } else if (SyncPosition) { writer.WriteVector3Packed(position); } else if (SyncRotation) { if (FullRotation) { writer.WriteVector3Packed(rotation.eulerAngles); } else { writer.WriteSingle(rotation.eulerAngles.y); } } InvokeClientRpcOnClientPerformance("ApplyTransform", clientId, stream, channelName, Security.SecuritySendFlags.None); } } } }
public void Write(Stream stream) { using (PooledBitWriter writer = PooledBitWriter.Get(stream)) { writer.WriteByte((byte)ImposterCount); writer.WriteSinglePacked(MovementSpeed); writer.WriteSinglePacked(VoteDuration); writer.WriteUInt16Packed((ushort)TaskCount); } }
/// <summary> /// Returns a base64 encoded version of the config /// </summary> /// <returns></returns> public string ToBase64() { NetworkConfig config = this; using (PooledBitStream stream = PooledBitStream.Get()) { using (PooledBitWriter writer = PooledBitWriter.Get(stream)) { writer.WriteString(config.protocalVersion); writer.WriteInt32Packed(config.receiveTickrate); writer.WriteInt32Packed(config.maxReceiveEventsPerTickRate); writer.WriteInt32Packed(config.eventTickrate); writer.WriteInt32Packed(config.clientConnectionBufferTimeout); writer.WriteInt32Packed(config.secondsHistory); writer.WriteBool(config.enableTimeResync); writer.WriteBool(config.ensureNetworkedVarLengthSafety); writer.WriteBits((byte)config.rpcHashSize, 3); writer.WriteBool(recycleNetworkIDs); writer.WriteSinglePacked(networkIDRecycleDelay); writer.WriteBool(enableNetworkedVar); writer.WriteBool(clientSendSceneEvents); writer.WriteBool(serverSendSceneEvents); stream.PadStream(); return Convert.ToBase64String(stream.ToArray()); } } }
/// <summary> /// Spawns a object from the pool at a given position and rotation. Can only be called from server. /// </summary> /// <param name="poolName">The name of the pool</param> /// <param name="position">The position to spawn the object at</param> /// <param name="rotation">The rotation to spawn the object at</param> /// <returns></returns> public static NetworkedObject SpawnPoolObject(string poolName, Vector3 position, Quaternion rotation) { if (!NetworkingManager.singleton.isServer) { if (LogHelper.CurrentLogLevel <= LogLevel.Normal) { LogHelper.LogWarning("Object spawning can only occur on server"); } return(null); } NetworkedObject netObject = Pools[PoolNamesToIndexes[poolName]].SpawnObject(position, rotation); using (PooledBitStream stream = PooledBitStream.Get()) { using (PooledBitWriter writer = PooledBitWriter.Get(stream)) { writer.WriteUInt32Packed(netObject.NetworkId); writer.WriteSinglePacked(position.x); writer.WriteSinglePacked(position.y); writer.WriteSinglePacked(position.z); writer.WriteSinglePacked(rotation.eulerAngles.x); writer.WriteSinglePacked(rotation.eulerAngles.y); writer.WriteSinglePacked(rotation.eulerAngles.z); InternalMessageHandler.Send(MLAPIConstants.MLAPI_SPAWN_POOL_OBJECT, "MLAPI_INTERNAL", stream); } } return(netObject); }
private void FixedUpdate() { if (!IsOwner) { return; } CheckSendRate(); #pragma warning disable IDE0018 // Inline variable declaration, Unity's Mono version doesn't support it int stateHash; float normalizedTime; #pragma warning restore IDE0018 // Inline variable declaration, Unity's Mono version doesn't support it if (!CheckAnimStateChanged(out stateHash, out normalizedTime)) { return; } using (PooledBitStream stream = PooledBitStream.Get()) { using (PooledBitWriter writer = PooledBitWriter.Get(stream)) { writer.WriteInt32Packed(stateHash); writer.WriteSinglePacked(normalizedTime); WriteParameters(stream, false); if (IsServer) { if (EnableProximity) { List <uint> clientsInProximity = new List <uint>(); foreach (KeyValuePair <uint, NetworkedClient> client in NetworkingManager.Singleton.ConnectedClients) { if (Vector3.Distance(transform.position, client.Value.PlayerObject.transform.position) <= ProximityRange) { clientsInProximity.Add(client.Key); } } InvokeClientRpc(ApplyAnimParamMsg, clientsInProximity, stream); } else { InvokeClientRpcOnEveryoneExcept(ApplyAnimMsg, OwnerClientId, stream); } } else { InvokeServerRpc(SubmitAnimMsg, stream); } } } }
internal static void SendSpawnCallForObject(ulong clientId, NetworkedObject netObject, Stream payload) { using (PooledBitStream stream = PooledBitStream.Get()) { using (PooledBitWriter writer = PooledBitWriter.Get(stream)) { writer.WriteBool(netObject.IsPlayerObject); writer.WriteUInt64Packed(netObject.NetworkId); writer.WriteUInt64Packed(netObject.OwnerClientId); if (NetworkingManager.Singleton.NetworkConfig.UsePrefabSync) { writer.WriteUInt64Packed(netObject.PrefabHash); } else { writer.WriteBool(netObject.IsSceneObject == null ? true : netObject.IsSceneObject.Value); if (netObject.IsSceneObject == null || netObject.IsSceneObject.Value) { writer.WriteUInt64Packed(netObject.NetworkedInstanceId); } else { writer.WriteUInt64Packed(netObject.PrefabHash); } } writer.WriteBool(netObject.DestroyWithScene); writer.WriteSinglePacked(netObject.transform.position.x); writer.WriteSinglePacked(netObject.transform.position.y); writer.WriteSinglePacked(netObject.transform.position.z); writer.WriteSinglePacked(netObject.transform.rotation.eulerAngles.x); writer.WriteSinglePacked(netObject.transform.rotation.eulerAngles.y); writer.WriteSinglePacked(netObject.transform.rotation.eulerAngles.z); writer.WriteBool(payload != null); if (payload != null) { writer.WriteInt32Packed((int)payload.Length); } if (NetworkingManager.Singleton.NetworkConfig.EnableNetworkedVar) { netObject.WriteNetworkedVarData(stream, clientId); } if (payload != null) { stream.CopyFrom(payload); } } InternalMessageHandler.Send(clientId, MLAPIConstants.MLAPI_ADD_OBJECT, "MLAPI_INTERNAL", stream, SecuritySendFlags.None, null); } }
private void FixedUpdate() { if (!IsOwner) { return; } CheckSendRate(); int stateHash; float normalizedTime; if (!CheckAnimStateChanged(out stateHash, out normalizedTime)) { return; } using (PooledBitStream stream = PooledBitStream.Get()) { using (PooledBitWriter writer = PooledBitWriter.Get(stream)) { writer.WriteInt32Packed(stateHash); writer.WriteSinglePacked(normalizedTime); WriteParameters(stream, false); if (IsServer) { if (EnableProximity) { List <ulong> clientsInProximity = new List <ulong>(); foreach (KeyValuePair <ulong, NetworkedClient> client in NetworkingManager.Singleton.ConnectedClients) { if (client.Value.PlayerObject == null || Vector3.Distance(transform.position, client.Value.PlayerObject.transform.position) <= ProximityRange) { clientsInProximity.Add(client.Key); } } InvokeClientRpcPerformance(ApplyAnimParamMsg, clientsInProximity, stream); } else { InvokeClientRpcOnEveryoneExceptPerformance(ApplyAnimMsg, OwnerClientId, stream); } } else { InvokeServerRpcPerformance(SubmitAnimMsg, stream); } } } }
public void Write(PooledBitWriter writer) { writer.WriteSinglePacked(timestamp); writer.WriteSinglePacked(position.x); writer.WriteSinglePacked(position.y); writer.WriteSinglePacked(position.z); writer.WriteSinglePacked(rotation.eulerAngles.x); writer.WriteSinglePacked(rotation.eulerAngles.y); writer.WriteSinglePacked(rotation.eulerAngles.z); writer.WriteUInt64Packed(parentId); writer.WriteInt32Packed(movingObjectId); }
/// <summary> /// Returns a base64 encoded version of the config /// </summary> /// <returns></returns> public string ToBase64() { NetworkConfig config = this; using (PooledBitStream stream = PooledBitStream.Get()) { using (PooledBitWriter writer = PooledBitWriter.Get(stream)) { writer.WriteUInt16Packed(config.ProtocolVersion); writer.WriteUInt16Packed((ushort)config.RegisteredScenes.Count); for (int i = 0; i < config.RegisteredScenes.Count; i++) { writer.WriteString(config.RegisteredScenes[i]); } writer.WriteInt32Packed(config.ServerTargetFramerate); writer.WriteInt32Packed(config.NetworkedTransformTickrate); writer.WriteInt32Packed(config.ClientCommandTickrate); writer.WriteInt32Packed(config.MaxReceiveEventsPerTickRate); writer.WriteInt32Packed(config.LagCompensationTickRate); writer.WriteInt32Packed(config.EventTickrate); writer.WriteInt32Packed(config.ClientConnectionBufferTimeout); writer.WriteBool(config.ConnectionApproval); writer.WriteInt32Packed(config.SecondsHistory); writer.WriteBool(config.EnableEncryption); writer.WriteBool(config.SignKeyExchange); writer.WriteInt32Packed(config.LoadSceneTimeOut); writer.WriteBool(config.EnableTimeResync); writer.WriteBool(config.EnsureNetworkedVarLengthSafety); writer.WriteBits((byte)config.RpcHashSize, 2); writer.WriteBool(ForceSamePrefabs); writer.WriteBool(UsePrefabSync); writer.WriteBool(EnableSceneManagement); writer.WriteBool(RecycleNetworkIds); writer.WriteSinglePacked(NetworkIdRecycleDelay); writer.WriteBool(EnableNetworkedVar); writer.WriteBool(AllowRuntimeSceneChanges); writer.WriteBool(EnableNetworkLogs); stream.PadStream(); return(Convert.ToBase64String(stream.ToArray())); } } }
internal static void WriteSpawnCallForObject(MLAPI.Serialization.BitStream stream, ulong clientId, NetworkedObject netObject, Stream payload) { using (PooledBitWriter writer = PooledBitWriter.Get(stream)) { writer.WriteBool(netObject.IsPlayerObject); writer.WriteUInt64Packed(netObject.NetworkId); writer.WriteUInt64Packed(netObject.OwnerClientId); if (NetworkingManager.Singleton.NetworkConfig.UsePrefabSync) { writer.WriteUInt64Packed(netObject.PrefabHash); } else { writer.WriteBool(netObject.IsSceneObject == null ? true : netObject.IsSceneObject.Value); if (netObject.IsSceneObject == null || netObject.IsSceneObject.Value) { writer.WriteUInt64Packed(netObject.NetworkedInstanceId); } else { writer.WriteUInt64Packed(netObject.PrefabHash); } } writer.WriteSinglePacked(netObject.transform.position.x); writer.WriteSinglePacked(netObject.transform.position.y); writer.WriteSinglePacked(netObject.transform.position.z); writer.WriteSinglePacked(netObject.transform.rotation.eulerAngles.x); writer.WriteSinglePacked(netObject.transform.rotation.eulerAngles.y); writer.WriteSinglePacked(netObject.transform.rotation.eulerAngles.z); writer.WriteBool(payload != null); if (payload != null) { writer.WriteInt32Packed((int)payload.Length); } if (NetworkingManager.Singleton.NetworkConfig.EnableNetworkedVar) { netObject.WriteNetworkedVarData(stream, clientId); } if (payload != null) { stream.CopyFrom(payload); } } }
private void SetRotation(ulong clientID, Stream stream) { using (PooledBitReader reader = PooledBitReader.Get(stream)) { float rotation = reader.ReadSinglePacked(); //This is where we verify movement using (PooledBitStream writeStream = PooledBitStream.Get()) { using (PooledBitWriter writer = PooledBitWriter.Get(writeStream)) { writer.WriteSinglePacked(rotation); InvokeClientRPCAllExcept(ApplyRotation, ownerID, writeStream, "Rotate Channel"); } } } }
private void SyncTime() { if (enableLogging) { Debug.Log("Syncing Time To Clients"); } using (PooledBitStream stream = PooledBitStream.Get()) { using (PooledBitWriter writer = PooledBitWriter.Get(stream)) { writer.WriteSinglePacked(Time.realtimeSinceStartup); MessageSender.SendToAll(MessageType.NETWORK_TIME_SYNC, timeSyncChannel, stream); } } if (enableLogging) { Debug.Log("Time synced"); } }
private void CheckForMissedSends() { for (int i = 0; i < NetworkingManager.Singleton.ConnectedClientsList.Count; i++) { if (!clientSendInfo.ContainsKey(NetworkingManager.Singleton.ConnectedClientsList[i].ClientId)) { clientSendInfo.Add(NetworkingManager.Singleton.ConnectedClientsList[i].ClientId, new ClientSendInfo() { clientId = NetworkingManager.Singleton.ConnectedClientsList[i].ClientId, lastMissedPosition = null, lastMissedRotation = null, lastSent = 0 }); } ClientSendInfo info = clientSendInfo[NetworkingManager.Singleton.ConnectedClientsList[i].ClientId]; Vector3? receiverPosition = NetworkingManager.Singleton.ConnectedClientsList[i].PlayerObject == null ? null : new Vector3?(NetworkingManager.Singleton.ConnectedClientsList[i].PlayerObject.transform.position); Vector3? senderPosition = NetworkingManager.Singleton.ConnectedClients[OwnerClientId].PlayerObject == null ? null : new Vector3?(NetworkingManager.Singleton.ConnectedClients[OwnerClientId].PlayerObject.transform.position); if ((receiverPosition == null || senderPosition == null && NetworkingManager.Singleton.NetworkTime - info.lastSent >= (1f / FixedSendsPerSecond)) || NetworkingManager.Singleton.NetworkTime - info.lastSent >= GetTimeForLerp(receiverPosition.Value, senderPosition.Value)) { Vector3?pos = NetworkingManager.Singleton.ConnectedClients[OwnerClientId].PlayerObject == null ? null : new Vector3?(NetworkingManager.Singleton.ConnectedClients[OwnerClientId].PlayerObject.transform.position); Vector3?rot = NetworkingManager.Singleton.ConnectedClients[OwnerClientId].PlayerObject == null ? null : new Vector3?(NetworkingManager.Singleton.ConnectedClients[OwnerClientId].PlayerObject.transform.rotation.eulerAngles); if (pos != null && rot != null) { info.lastSent = NetworkingManager.Singleton.NetworkTime; info.lastMissedPosition = null; info.lastMissedRotation = null; using (PooledBitStream stream = PooledBitStream.Get()) { using (PooledBitWriter writer = PooledBitWriter.Get(stream)) { writer.WriteSinglePacked(pos.Value.x); writer.WriteSinglePacked(pos.Value.y); writer.WriteSinglePacked(pos.Value.z); writer.WriteSinglePacked(rot.Value.x); writer.WriteSinglePacked(rot.Value.y); writer.WriteSinglePacked(rot.Value.z); InvokeClientRpcOnClientPerformance(ApplyTransform, NetworkingManager.Singleton.ConnectedClientsList[i].ClientId, stream, string.IsNullOrEmpty(Channel) ? "MLAPI_DEFAULT_MESSAGE" : Channel); } } } } } }
private void WriteParameters(Stream stream, bool autoSend) { using (PooledBitWriter writer = PooledBitWriter.Get(stream)) { if (animatorParameters == null) { animatorParameters = animator.parameters; } for (int i = 0; i < animatorParameters.Length; i++) { if (autoSend && !GetParameterAutoSend(i)) { continue; } AnimatorControllerParameter par = animatorParameters[i]; if (par.type == AnimatorControllerParameterType.Int) { writer.WriteUInt32Packed((uint)animator.GetInteger(par.nameHash)); SetSendTrackingParam(par.name + ":" + animator.GetInteger(par.nameHash), i); } if (par.type == AnimatorControllerParameterType.Float) { writer.WriteSinglePacked(animator.GetFloat(par.nameHash)); SetSendTrackingParam(par.name + ":" + animator.GetFloat(par.nameHash), i); } if (par.type == AnimatorControllerParameterType.Bool) { writer.WriteBool(animator.GetBool(par.nameHash)); SetSendTrackingParam(par.name + ":" + animator.GetBool(par.nameHash), i); } } } }
private void SendRotation(float newRotation) { if (networkManager.networkTime - lastSendTime >= (1.0f / m_FixedSendsPerSecond) && Mathf.Abs(transform.localEulerAngles.z - lastSendRotation) > m_MinRotationDifference) { lastSendTime = networkManager.networkTime; lastSendRotation = transform.localEulerAngles.z; using (PooledBitStream stream = PooledBitStream.Get()) { using (PooledBitWriter writer = PooledBitWriter.Get(stream)) writer.WriteSinglePacked(transform.localEulerAngles.z); if (isServer) { InvokeClientRPCAllExcept(ApplyRotation, ownerID, stream, "Rotate Channel"); } else { InvokeServerRPC(SetRotation, stream, "Rotate Channel"); } } } }
private void CheckForMissedSends() { for (int i = 0; i < NetworkingManager.Singleton.ConnectedClientsList.Count; i++) { if (!clientSendInfo.ContainsKey(NetworkingManager.Singleton.ConnectedClientsList[i].ClientId)) { clientSendInfo.Add(NetworkingManager.Singleton.ConnectedClientsList[i].ClientId, new ClientSendInfo() { clientId = NetworkingManager.Singleton.ConnectedClientsList[i].ClientId, lastMissedPosition = null, lastMissedRotation = null, lastSent = 0 }); } ClientSendInfo info = clientSendInfo[NetworkingManager.Singleton.ConnectedClientsList[i].ClientId]; Vector3 receiverPosition = NetworkingManager.Singleton.ConnectedClientsList[i].PlayerObject.transform.position; Vector3 senderPosition = NetworkingManager.Singleton.ConnectedClients[OwnerClientId].PlayerObject.transform.position; if (NetworkingManager.Singleton.NetworkTime - info.lastSent >= GetTimeForLerp(receiverPosition, senderPosition)) { Vector3 pos = NetworkingManager.Singleton.ConnectedClients[OwnerClientId].PlayerObject.transform.position; Vector3 rot = NetworkingManager.Singleton.ConnectedClients[OwnerClientId].PlayerObject.transform.rotation.eulerAngles; info.lastSent = NetworkingManager.Singleton.NetworkTime; info.lastMissedPosition = null; info.lastMissedRotation = null; using (PooledBitStream stream = PooledBitStream.Get()) { using (PooledBitWriter writer = PooledBitWriter.Get(stream)) { writer.WriteSinglePacked(pos.x); writer.WriteSinglePacked(pos.y); writer.WriteSinglePacked(pos.z); writer.WriteSinglePacked(rot.x); writer.WriteSinglePacked(rot.y); writer.WriteSinglePacked(rot.z); InvokeClientRpcOnClientPerformance(ApplyTransform, NetworkingManager.Singleton.ConnectedClientsList[i].ClientId, stream); } } } } }
private void SubmitTransform(uint clientId, Stream stream) { if (!enabled) { return; } using (PooledBitReader reader = PooledBitReader.Get(stream)) { float xPos = reader.ReadSinglePacked(); float yPos = reader.ReadSinglePacked(); float zPos = reader.ReadSinglePacked(); float xRot = reader.ReadSinglePacked(); float yRot = reader.ReadSinglePacked(); float zRot = reader.ReadSinglePacked(); if (IsMoveValidDelegate != null && !IsMoveValidDelegate(lerpEndPos, new Vector3(xPos, yPos, zPos))) { //Invalid move! //TODO: Add rubber band (just a message telling them to go back) return; } using (PooledBitStream writeStream = PooledBitStream.Get()) { using (PooledBitWriter writer = PooledBitWriter.Get(writeStream)) { writer.WriteSinglePacked(xPos); writer.WriteSinglePacked(yPos); writer.WriteSinglePacked(zPos); writer.WriteSinglePacked(xRot); writer.WriteSinglePacked(yRot); writer.WriteSinglePacked(zRot); if (EnableRange) { for (int i = 0; i < NetworkingManager.singleton.ConnectedClientsList.Count; i++) { if (!clientSendInfo.ContainsKey(NetworkingManager.singleton.ConnectedClientsList[i].ClientId)) { clientSendInfo.Add(NetworkingManager.singleton.ConnectedClientsList[i].ClientId, new ClientSendInfo() { clientId = NetworkingManager.singleton.ConnectedClientsList[i].ClientId, lastMissedPosition = null, lastMissedRotation = null, lastSent = 0 }); } ClientSendInfo info = clientSendInfo[NetworkingManager.singleton.ConnectedClientsList[i].ClientId]; Vector3 receiverPosition = NetworkingManager.singleton.ConnectedClientsList[i].PlayerObject.transform.position; Vector3 senderPosition = NetworkingManager.singleton.ConnectedClients[OwnerClientId].PlayerObject.transform.position; if (NetworkingManager.singleton.NetworkTime - info.lastSent >= GetTimeForLerp(receiverPosition, senderPosition)) { info.lastSent = NetworkingManager.singleton.NetworkTime; info.lastMissedPosition = null; info.lastMissedRotation = null; InvokeClientRpcOnClient(ApplyTransform, NetworkingManager.singleton.ConnectedClientsList[i].ClientId, writeStream); } else { info.lastMissedPosition = new Vector3(xPos, yPos, zPos); info.lastMissedRotation = Quaternion.Euler(xRot, yRot, zRot); } } } else { InvokeClientRpcOnEveryoneExcept(ApplyTransform, OwnerClientId, writeStream); } } } } }
internal static void SpawnObject(NetworkedObject netObject, uint?clientOwnerId = null, Stream payload = null, bool destroyWithScene = false) { if (netObject.isSpawned) { if (LogHelper.CurrentLogLevel <= LogLevel.Normal) { LogHelper.LogWarning("Object already spawned"); } return; } else if (!netManager.isServer) { if (LogHelper.CurrentLogLevel <= LogLevel.Normal) { LogHelper.LogWarning("Only server can spawn objects"); } return; } else if (SpawnManager.GetNetworkedPrefabIndexOfName(netObject.NetworkedPrefabName) == -1) { if (LogHelper.CurrentLogLevel <= LogLevel.Normal) { LogHelper.LogWarning("The prefab name " + netObject.NetworkedPrefabName + " does not exist as a networkedPrefab"); } return; } else if (!netManager.NetworkConfig.HandleObjectSpawning) { if (LogHelper.CurrentLogLevel <= LogLevel.Normal) { LogHelper.LogWarning("NetworkConfig is set to not handle object spawning"); } return; } uint netId = GetNetworkObjectId(); netObject.NetworkId = netId; SpawnedObjects.Add(netId, netObject); SpawnedObjectsList.Add(netObject); netObject.isSpawned = true; netObject.destroyWithScene = destroyWithScene; netObject.sceneSpawnedInIndex = NetworkSceneManager.CurrentActiveSceneIndex; if (clientOwnerId != null) { netObject.OwnerClientId = clientOwnerId.Value; NetworkingManager.singleton.ConnectedClients[clientOwnerId.Value].OwnedObjects.Add(netObject); } if (payload == null) { netObject.InvokeBehaviourNetworkSpawn(null); } else { netObject.InvokeBehaviourNetworkSpawn(payload); } foreach (var client in netManager.ConnectedClients) { using (PooledBitStream stream = PooledBitStream.Get()) { using (PooledBitWriter writer = PooledBitWriter.Get(stream)) { writer.WriteBool(false); writer.WriteUInt32Packed(netObject.NetworkId); writer.WriteUInt32Packed(netObject.OwnerClientId); writer.WriteUInt64Packed(netObject.NetworkedPrefabHash); writer.WriteBool(netObject.destroyWithScene == null ? true : netObject.destroyWithScene.Value); writer.WriteBool(netObject.SceneDelayedSpawn); writer.WriteUInt32Packed(netObject.sceneSpawnedInIndex); writer.WriteSinglePacked(netObject.transform.position.x); writer.WriteSinglePacked(netObject.transform.position.y); writer.WriteSinglePacked(netObject.transform.position.z); writer.WriteSinglePacked(netObject.transform.rotation.eulerAngles.x); writer.WriteSinglePacked(netObject.transform.rotation.eulerAngles.y); writer.WriteSinglePacked(netObject.transform.rotation.eulerAngles.z); writer.WriteBool(payload != null); if (payload != null) { writer.WriteInt32Packed((int)payload.Length); } netObject.WriteNetworkedVarData(stream, client.Key); if (payload != null) { stream.CopyFrom(payload); } InternalMessageHandler.Send(client.Key, MLAPIConstants.MLAPI_ADD_OBJECT, "MLAPI_INTERNAL", stream, SecuritySendFlags.None); } } } }
private void SubmitTransform(ulong clientId, Stream stream) { if (!enabled) { return; } using (PooledBitReader reader = PooledBitReader.Get(stream)) { float xPos = reader.ReadSinglePacked(); float yPos = reader.ReadSinglePacked(); float zPos = reader.ReadSinglePacked(); float xRot = reader.ReadSinglePacked(); float yRot = reader.ReadSinglePacked(); float zRot = reader.ReadSinglePacked(); if (IsMoveValidDelegate != null && !IsMoveValidDelegate(lerpEndPos, new Vector3(xPos, yPos, zPos))) { //Invalid move! //TODO: Add rubber band (just a message telling them to go back) return; } using (PooledBitStream writeStream = PooledBitStream.Get()) { using (PooledBitWriter writer = PooledBitWriter.Get(writeStream)) { writer.WriteSinglePacked(xPos); writer.WriteSinglePacked(yPos); writer.WriteSinglePacked(zPos); writer.WriteSinglePacked(xRot); writer.WriteSinglePacked(yRot); writer.WriteSinglePacked(zRot); if (EnableRange) { for (int i = 0; i < NetworkingManager.Singleton.ConnectedClientsList.Count; i++) { if (!clientSendInfo.ContainsKey(NetworkingManager.Singleton.ConnectedClientsList[i].ClientId)) { clientSendInfo.Add(NetworkingManager.Singleton.ConnectedClientsList[i].ClientId, new ClientSendInfo() { clientId = NetworkingManager.Singleton.ConnectedClientsList[i].ClientId, lastMissedPosition = null, lastMissedRotation = null, lastSent = 0 }); } ClientSendInfo info = clientSendInfo[NetworkingManager.Singleton.ConnectedClientsList[i].ClientId]; Vector3? receiverPosition = NetworkingManager.Singleton.ConnectedClientsList[i].PlayerObject == null ? null : new Vector3?(NetworkingManager.Singleton.ConnectedClientsList[i].PlayerObject.transform.position); Vector3? senderPosition = NetworkingManager.Singleton.ConnectedClients[OwnerClientId].PlayerObject == null ? null : new Vector3?(NetworkingManager.Singleton.ConnectedClients[OwnerClientId].PlayerObject.transform.position); if ((receiverPosition == null || senderPosition == null && NetworkingManager.Singleton.NetworkTime - info.lastSent >= (1f / FixedSendsPerSecond)) || NetworkingManager.Singleton.NetworkTime - info.lastSent >= GetTimeForLerp(receiverPosition.Value, senderPosition.Value)) { info.lastSent = NetworkingManager.Singleton.NetworkTime; info.lastMissedPosition = null; info.lastMissedRotation = null; InvokeClientRpcOnClientPerformance(ApplyTransform, NetworkingManager.Singleton.ConnectedClientsList[i].ClientId, writeStream, string.IsNullOrEmpty(Channel) ? "MLAPI_DEFAULT_MESSAGE" : Channel); } else { info.lastMissedPosition = new Vector3(xPos, yPos, zPos); info.lastMissedRotation = Quaternion.Euler(xRot, yRot, zRot); } } } else { InvokeClientRpcOnEveryoneExceptPerformance(ApplyTransform, OwnerClientId, writeStream, string.IsNullOrEmpty(Channel) ? "MLAPI_DEFAULT_MESSAGE" : Channel); } } } } }
private void Update() { if (IsOwner) { if (NetworkingManager.Singleton.NetworkTime - lastSendTime >= (1f / FixedSendsPerSecond) && (Vector3.Distance(transform.position, lastSentPos) > MinMeters || Quaternion.Angle(transform.rotation, lastSentRot) > MinDegrees)) { lastSendTime = NetworkingManager.Singleton.NetworkTime; lastSentPos = transform.position; lastSentRot = transform.rotation; using (PooledBitStream stream = PooledBitStream.Get()) { using (PooledBitWriter writer = PooledBitWriter.Get(stream)) { writer.WriteSinglePacked(transform.position.x); writer.WriteSinglePacked(transform.position.y); writer.WriteSinglePacked(transform.position.z); writer.WriteSinglePacked(transform.rotation.eulerAngles.x); writer.WriteSinglePacked(transform.rotation.eulerAngles.y); writer.WriteSinglePacked(transform.rotation.eulerAngles.z); if (IsServer) { InvokeClientRpcOnEveryoneExceptPerformance(ApplyTransform, OwnerClientId, stream, string.IsNullOrEmpty(Channel) ? "MLAPI_DEFAULT_MESSAGE" : Channel); } else { InvokeServerRpcPerformance(SubmitTransform, stream, string.IsNullOrEmpty(Channel) ? "MLAPI_DEFAULT_MESSAGE" : Channel); } } } } } else { //If we are server and interpolation is turned on for server OR we are not server and interpolation is turned on if ((IsServer && InterpolateServer && InterpolatePosition) || (!IsServer && InterpolatePosition)) { if (Vector3.Distance(transform.position, lerpEndPos) > SnapDistance) { //Snap, set T to 1 (100% of the lerp) lerpT = 1f; } float sendDelay = (IsServer || !EnableRange || !AssumeSyncedSends || NetworkingManager.Singleton.ConnectedClients[NetworkingManager.Singleton.LocalClientId].PlayerObject == null) ? (1f / FixedSendsPerSecond) : GetTimeForLerp(transform.position, NetworkingManager.Singleton.ConnectedClients[NetworkingManager.Singleton.LocalClientId].PlayerObject.transform.position); lerpT += Time.unscaledDeltaTime / sendDelay; if (ExtrapolatePosition && Time.unscaledTime - lastRecieveTime < sendDelay * MaxSendsToExtrapolate) { transform.position = Vector3.LerpUnclamped(lerpStartPos, lerpEndPos, lerpT); } else { transform.position = Vector3.Lerp(lerpStartPos, lerpEndPos, lerpT); } if (ExtrapolatePosition && Time.unscaledTime - lastRecieveTime < sendDelay * MaxSendsToExtrapolate) { transform.rotation = Quaternion.SlerpUnclamped(lerpStartRot, lerpEndRot, lerpT); } else { transform.rotation = Quaternion.Slerp(lerpStartRot, lerpEndRot, lerpT); } } } if (IsServer && EnableRange && EnableNonProvokedResendChecks) { CheckForMissedSends(); } }
private void Update() { if (!IsOwner) { return; } if (agent.destination != lastDestination) { lastDestination = agent.destination; using (PooledBitStream stream = PooledBitStream.Get()) { using (PooledBitWriter writer = PooledBitWriter.Get(stream)) { writer.WriteSinglePacked(agent.destination.x); writer.WriteSinglePacked(agent.destination.y); writer.WriteSinglePacked(agent.destination.z); writer.WriteSinglePacked(agent.velocity.x); writer.WriteSinglePacked(agent.velocity.y); writer.WriteSinglePacked(agent.velocity.z); writer.WriteSinglePacked(transform.position.x); writer.WriteSinglePacked(transform.position.y); writer.WriteSinglePacked(transform.position.z); if (!EnableProximity) { InvokeClientRpcOnEveryone(OnNavMeshStateUpdate, stream); } else { List <uint> proximityClients = new List <uint>(); foreach (KeyValuePair <uint, NetworkedClient> client in NetworkingManager.Singleton.ConnectedClients) { if (Vector3.Distance(client.Value.PlayerObject.transform.position, transform.position) <= ProximityRange) { proximityClients.Add(client.Key); } } InvokeClientRpc(OnNavMeshStateUpdate, proximityClients, stream); } } } } if (NetworkingManager.Singleton.NetworkTime - lastCorrectionTime >= CorrectionDelay) { using (PooledBitStream stream = PooledBitStream.Get()) { using (PooledBitWriter writer = PooledBitWriter.Get(stream)) { writer.WriteSinglePacked(agent.velocity.x); writer.WriteSinglePacked(agent.velocity.y); writer.WriteSinglePacked(agent.velocity.z); writer.WriteSinglePacked(transform.position.x); writer.WriteSinglePacked(transform.position.y); writer.WriteSinglePacked(transform.position.z); if (!EnableProximity) { InvokeClientRpcOnEveryone(OnNavMeshCorrectionUpdate, stream); } else { List <uint> proximityClients = new List <uint>(); foreach (KeyValuePair <uint, NetworkedClient> client in NetworkingManager.Singleton.ConnectedClients) { if (Vector3.Distance(client.Value.PlayerObject.transform.position, transform.position) <= ProximityRange) { proximityClients.Add(client.Key); } } InvokeClientRpc(OnNavMeshCorrectionUpdate, proximityClients, stream); } } } lastCorrectionTime = NetworkingManager.Singleton.NetworkTime; } }
//Server only internal static void SpawnPlayerObject(NetworkedObject netObject, uint clientId, Stream payload = null) { if (netObject.isSpawned) { if (LogHelper.CurrentLogLevel <= LogLevel.Normal) { LogHelper.LogWarning("Object already spawned"); } return; } else if (!netManager.isServer) { if (LogHelper.CurrentLogLevel <= LogLevel.Normal) { LogHelper.LogWarning("Only server can spawn objects"); } return; } else if (!netManager.NetworkConfig.NetworkPrefabIds.ContainsKey(netObject.NetworkedPrefabName)) { if (LogHelper.CurrentLogLevel <= LogLevel.Normal) { LogHelper.LogWarning("The prefab name " + netObject.NetworkedPrefabName + " does not exist as a networkedPrefab"); } return; } else if (!netManager.NetworkConfig.HandleObjectSpawning) { if (LogHelper.CurrentLogLevel <= LogLevel.Normal) { LogHelper.LogWarning("NetworkConfig is set to not handle object spawning"); } return; } else if (netManager.ConnectedClients[clientId].PlayerObject != null) { if (LogHelper.CurrentLogLevel <= LogLevel.Normal) { LogHelper.LogWarning("Client already have a player object"); } return; } uint netId = GetNetworkObjectId(); netObject.NetworkId = netId; SpawnedObjects.Add(netId, netObject); SpawnedObjectsList.Add(netObject); netObject.isSpawned = true; netObject.sceneObject = false; netObject.isPlayerObject = true; netManager.ConnectedClients[clientId].PlayerObject = netObject; if (payload == null) { netObject.InvokeBehaviourNetworkSpawn(null); } else { netObject.InvokeBehaviourNetworkSpawn(payload); } foreach (var client in netManager.ConnectedClients) { using (PooledBitStream stream = PooledBitStream.Get()) { using (PooledBitWriter writer = PooledBitWriter.Get(stream)) { writer.WriteBool(true); writer.WriteUInt32Packed(netObject.NetworkId); writer.WriteUInt32Packed(netObject.OwnerClientId); writer.WriteInt32Packed(netManager.NetworkConfig.NetworkPrefabIds[netObject.NetworkedPrefabName]); writer.WriteBool(netObject.sceneObject == null ? true : netObject.sceneObject.Value); writer.WriteSinglePacked(netObject.transform.position.x); writer.WriteSinglePacked(netObject.transform.position.y); writer.WriteSinglePacked(netObject.transform.position.z); writer.WriteSinglePacked(netObject.transform.rotation.eulerAngles.x); writer.WriteSinglePacked(netObject.transform.rotation.eulerAngles.y); writer.WriteSinglePacked(netObject.transform.rotation.eulerAngles.z); writer.WriteBool(payload != null); netObject.WriteNetworkedVarData(stream, client.Key); if (payload != null) { stream.CopyFrom(payload); } InternalMessageHandler.Send(client.Key, MLAPIConstants.MLAPI_ADD_OBJECT, "MLAPI_INTERNAL", stream); } } } }
private void HandleApproval(ulong sendingClientID, bool approved) { if (approved) //Inform new client it got approved { //Move pending client to connected client if (m_PendingClientsDictionary.Remove(sendingClientID)) { for (int i = 0; i < m_PendingClients.Count; i++) { if (m_PendingClients[i].clientID == sendingClientID) { m_PendingClients.RemoveAt(i); break; } } } m_ConnectedClients.Add(sendingClientID); // This packet is unreliable, but if it gets through it should provide a much better sync than the potentially huge approval message. SyncTime(); //Do message using (PooledBitStream stream = PooledBitStream.Get()) { using (PooledBitWriter writer = PooledBitWriter.Get(stream)) { writer.WriteUInt64Packed(sendingClientID); writer.WriteSinglePacked(Time.realtimeSinceStartup); writer.WriteUInt32Packed(0); MessageSender.Send(sendingClientID, MessageType.NETWORK_CONNECTION_APPROVED, networkInternalChannel, stream); } } //Let our modules know of a new client connected for (int i = 0; i < m_Modules.Count; i++) { m_Modules[i].OnClientConnect(sendingClientID); } //Invoke public client connect event onClientConnect?.Invoke(sendingClientID); } else { //Remove pending client if (m_PendingClientsDictionary.Remove(sendingClientID)) { for (int i = 0; i < m_PendingClients.Count; i++) { if (m_PendingClients[i].clientID == sendingClientID) { m_PendingClients.RemoveAt(i); break; } } } transport.DisconnectRemoteClient(sendingClientID); } }
internal static void WriteSpawnCallForObject(Serialization.BitStream stream, ulong clientId, NetworkedObject netObject, Stream payload) { using (PooledBitWriter writer = PooledBitWriter.Get(stream)) { writer.WriteBool(netObject.IsPlayerObject); writer.WriteUInt64Packed(netObject.NetworkId); writer.WriteUInt64Packed(netObject.OwnerClientId); NetworkedObject parent = null; if (!netObject.AlwaysReplicateAsRoot && netObject.transform.parent != null) { parent = netObject.transform.parent.GetComponent <NetworkedObject>(); } if (parent == null) { writer.WriteBool(false); } else { writer.WriteBool(true); writer.WriteUInt64Packed(parent.NetworkId); } if (!NetworkingManager.Singleton.NetworkConfig.EnableSceneManagement || NetworkingManager.Singleton.NetworkConfig.UsePrefabSync) { writer.WriteUInt64Packed(netObject.PrefabHash); } else { writer.WriteBool(netObject.IsSceneObject == null ? true : netObject.IsSceneObject.Value); if (netObject.IsSceneObject == null || netObject.IsSceneObject.Value) { writer.WriteUInt64Packed(netObject.NetworkedInstanceId); } else { writer.WriteUInt64Packed(netObject.PrefabHash); } } if (netObject.IncludeTransformWhenSpawning == null || netObject.IncludeTransformWhenSpawning(clientId)) { writer.WriteBool(true); writer.WriteSinglePacked(netObject.transform.position.x); writer.WriteSinglePacked(netObject.transform.position.y); writer.WriteSinglePacked(netObject.transform.position.z); writer.WriteSinglePacked(netObject.transform.rotation.eulerAngles.x); writer.WriteSinglePacked(netObject.transform.rotation.eulerAngles.y); writer.WriteSinglePacked(netObject.transform.rotation.eulerAngles.z); } else { writer.WriteBool(false); } writer.WriteBool(payload != null); if (payload != null) { writer.WriteInt32Packed((int)payload.Length); } if (NetworkingManager.Singleton.NetworkConfig.EnableNetworkedVar) { netObject.WriteNetworkedVarData(stream, clientId); netObject.WriteSyncedVarData(stream, clientId); } if (payload != null) { stream.CopyFrom(payload); } } }
private static void OnSceneUnloadServer(Guid switchSceneGuid) { // Justification: Rare alloc, could(should?) reuse List <NetworkedObject> newSceneObjects = new List <NetworkedObject>(); { NetworkedObject[] networkedObjects = MonoBehaviour.FindObjectsOfType <NetworkedObject>(); for (int i = 0; i < networkedObjects.Length; i++) { if (networkedObjects[i].IsSceneObject == null) { SpawnManager.SpawnNetworkedObjectLocally(networkedObjects[i], SpawnManager.GetNetworkObjectId(), true, false, null, null, false, 0, false, true); newSceneObjects.Add(networkedObjects[i]); } } } for (int j = 0; j < NetworkingManager.Singleton.ConnectedClientsList.Count; j++) { if (NetworkingManager.Singleton.ConnectedClientsList[j].ClientId != NetworkingManager.Singleton.ServerClientId) { using (PooledBitStream stream = PooledBitStream.Get()) { using (PooledBitWriter writer = PooledBitWriter.Get(stream)) { writer.WriteUInt32Packed(CurrentActiveSceneIndex); writer.WriteByteArray(switchSceneGuid.ToByteArray()); uint sceneObjectsToSpawn = 0; for (int i = 0; i < newSceneObjects.Count; i++) { if (newSceneObjects[i].observers.Contains(NetworkingManager.Singleton.ConnectedClientsList[j].ClientId)) { sceneObjectsToSpawn++; } } writer.WriteUInt32Packed(sceneObjectsToSpawn); for (int i = 0; i < newSceneObjects.Count; i++) { if (newSceneObjects[i].observers.Contains(NetworkingManager.Singleton.ConnectedClientsList[j].ClientId)) { if (NetworkingManager.Singleton.NetworkConfig.UsePrefabSync) { writer.WriteBool(newSceneObjects[i].IsPlayerObject); writer.WriteUInt64Packed(newSceneObjects[i].NetworkId); writer.WriteUInt64Packed(newSceneObjects[i].OwnerClientId); writer.WriteUInt64Packed(newSceneObjects[i].PrefabHash); writer.WriteBool(newSceneObjects[i].DestroyWithScene); writer.WriteSinglePacked(newSceneObjects[i].transform.position.x); writer.WriteSinglePacked(newSceneObjects[i].transform.position.y); writer.WriteSinglePacked(newSceneObjects[i].transform.position.z); writer.WriteSinglePacked(newSceneObjects[i].transform.rotation.eulerAngles.x); writer.WriteSinglePacked(newSceneObjects[i].transform.rotation.eulerAngles.y); writer.WriteSinglePacked(newSceneObjects[i].transform.rotation.eulerAngles.z); if (NetworkingManager.Singleton.NetworkConfig.EnableNetworkedVar) { newSceneObjects[i].WriteNetworkedVarData(stream, NetworkingManager.Singleton.ConnectedClientsList[j].ClientId); } } else { writer.WriteBool(newSceneObjects[i].IsPlayerObject); writer.WriteUInt64Packed(newSceneObjects[i].NetworkId); writer.WriteUInt64Packed(newSceneObjects[i].OwnerClientId); writer.WriteUInt64Packed(newSceneObjects[i].NetworkedInstanceId); writer.WriteBool(newSceneObjects[i].DestroyWithScene); if (NetworkingManager.Singleton.NetworkConfig.EnableNetworkedVar) { newSceneObjects[i].WriteNetworkedVarData(stream, NetworkingManager.Singleton.ConnectedClientsList[j].ClientId); } } } } } InternalMessageHandler.Send(NetworkingManager.Singleton.ConnectedClientsList[j].ClientId, MLAPIConstants.MLAPI_SWITCH_SCENE, "MLAPI_INTERNAL", stream, SecuritySendFlags.None, null); } } } //Tell server that scene load is completed if (NetworkingManager.Singleton.IsHost) { OnClientSwitchSceneCompleted(NetworkingManager.Singleton.LocalClientId, switchSceneGuid); } isSwitching = false; if (OnSceneSwitched != null) { OnSceneSwitched(); } }
void InvokeApplyTransformOnEveryone(Vector3 position, Quaternion rotation, string channelName) { using (PooledBitStream stream = PooledBitStream.Get()) { using (PooledBitWriter writer = PooledBitWriter.Get(stream)) { if (TransformTypeToSync == TransformType.Transform2D) { if (SyncPosition && SyncRotation) { writer.WriteVector2Packed(position); writer.WriteSinglePacked(rotation.eulerAngles.z); } else if (SyncPosition) { writer.WriteVector2Packed(position); } else if (SyncRotation) { writer.WriteSinglePacked(rotation.eulerAngles.z); } } else if (TransformTypeToSync == TransformType.Transform3D) { if (SyncPosition && SyncRotation) { writer.WriteVector3Packed(position); if (FullRotation) { writer.WriteVector3Packed(rotation.eulerAngles); } else { writer.WriteSinglePacked(rotation.eulerAngles.y); } } else if (SyncPosition) { writer.WriteVector3Packed(position); } else if (SyncRotation) { if (FullRotation) { writer.WriteVector3Packed(rotation.eulerAngles); } else { writer.WriteSinglePacked(rotation.eulerAngles.y); } } } if (EnableMinDistanceBetweenClients) { Vector3?senderPosition = transform.position; for (int i = 0; i < NetworkingManager.Singleton.ConnectedClientsList.Count; i++) { Vector3?receiverPosition = NetworkingManager.Singleton.ConnectedClientsList[i].PlayerObject == null ? null : new Vector3?(NetworkingManager.Singleton.ConnectedClientsList[i].PlayerObject.transform.position); if (receiverPosition == null || senderPosition == null || Vector3.Distance((Vector3)senderPosition, (Vector3)receiverPosition) < MinDistanceBetweenClients) { InvokeClientRpcOnClientPerformance(TransformTypeToSync == TransformType.Transform2D ? "ApplyTransform2D" : "ApplyTransform", NetworkingManager.Singleton.ConnectedClientsList[i].ClientId, stream, channelName, Security.SecuritySendFlags.None); } } } else { InvokeClientRpcOnEveryonePerformance(TransformTypeToSync == TransformType.Transform2D ? "ApplyTransform2D" : "ApplyTransform", stream, channelName, Security.SecuritySendFlags.None); } } } }