private void SendIdentityUpdateMessage(UnityNetworkObject unityNetworkObject, UserInfo user = null)
        {
            this.networkIdentityUpdate.NetworkId      = unityNetworkObject.NetworkId;
            this.networkIdentityUpdate.OwnerId        = unityNetworkObject.OwnerId;
            this.networkIdentityUpdate.IsEnabled      = unityNetworkObject.IsEnabled;
            this.networkIdentityUpdate.ResourceName   = unityNetworkObject.ResourceName;
            this.networkIdentityUpdate.Position       = unityNetworkObject.Position;
            this.networkIdentityUpdate.Rotation       = unityNetworkObject.Rotation;
            this.networkIdentityUpdate.CanChangeOwner = unityNetworkObject.CanChangeOwner;

            if (user != null)
            {
                this.gameServer.SendMessageToUser(user, this.networkIdentityUpdate);
            }
            else
            {
                this.gameServer.SendMessageToAll(this.networkIdentityUpdate);
            }
        }
        private void SendAllNetworkBehaviourDataToUser(UnityNetworkObject unityNetworkObject, UserInfo userInfo)
        {
            // Send all the network behaviour data we know about
            this.networkBehaviourMessage.NetworkId = unityNetworkObject.NetworkId;

            for (int i = 0; i < unityNetworkObject.BehaviourDatas.Count; i++)
            {
                var behaviourData = unityNetworkObject.BehaviourDatas[i];

                if (behaviourData?.Data?.Length > 0)
                {
                    this.networkBehaviourMessage.BehaviourIndex = i;
                    this.networkBehaviourMessage.DataBytes      = behaviourData.Data.Bytes;
                    this.networkBehaviourMessage.DataLength     = behaviourData.Data.Length;

                    this.gameServer.SendMessageToUser(userInfo, this.networkBehaviourMessage);
                }
            }
        }
        public void ServerReceivedMessage(UserInfo userInfo, Message message, bool reliable)
        {
            switch (message.GetId())
            {
            case NetworkIdentityRequestUpdate.Id:
            {
                var requestUpdateMessage = (NetworkIdentityRequestUpdate)message;
                var unityNetworkObject   = this.serverState.GetUnityNetworkObject(requestUpdateMessage.NetworkId);

                // Making sure a "Server" player has been selected
                if (this.serverId == InvalidId)
                {
                    Debug.Log("NetworkIdentityRequestUpdate is Migrating Server...");
                    this.MigrateServerToNewUser(this.GetNextServerUser(), NotifyType.AllOthers);
                }

                Debug.Log("NetworkIdentityRequestUpdate " + requestUpdateMessage.NetworkId);

                if (this.serverState.DestroyedSceneUnityNetworkObjects.Contains(requestUpdateMessage.NetworkId))
                {
                    // The object they're requesting an update on was destroyed, so sending a destroyed message
                    this.networkBehaviourDestoryed.DestroyedNetworkIds.Clear();
                    this.networkBehaviourDestoryed.DestroyedNetworkIds.Add(requestUpdateMessage.NetworkId);
                    this.gameServer.SendMessageToUser(userInfo, this.networkBehaviourDestoryed);
                }
                else if (unityNetworkObject == null)
                {
                    bool isSceneObject = requestUpdateMessage.ResourceName.IsNullOrWhitespace();

                    unityNetworkObject = new UnityNetworkObject
                    {
                        OwnerId               = isSceneObject ? this.serverId : userInfo.UserId,
                        NetworkId             = requestUpdateMessage.NetworkId,
                        IsEnabled             = requestUpdateMessage.IsEnabled,
                        Position              = requestUpdateMessage.Position,
                        Rotation              = requestUpdateMessage.Rotation,
                        ResourceName          = requestUpdateMessage.ResourceName,
                        BehaviourDatas        = new List <BehaviourData>(requestUpdateMessage.BehaviourCount),
                        DestoryOnDisconnect   = requestUpdateMessage.DestoryOnDisconnect,
                        CanChangeOwner        = requestUpdateMessage.CanChangeOwner,
                        InitialCanChangeOwner = requestUpdateMessage.CanChangeOwner,
                    };

                    for (int i = 0; i < requestUpdateMessage.BehaviourCount; i++)
                    {
                        unityNetworkObject.BehaviourDatas.Add(new BehaviourData());
                    }

                    if (isSceneObject)
                    {
                        this.serverState.SceneUnityNetworkObjects.Add(unityNetworkObject.NetworkId, unityNetworkObject);
                    }
                    else
                    {
                        this.serverState.DynamicUnityGameObjects.Add(unityNetworkObject.NetworkId, unityNetworkObject);
                    }

                    this.SendIdentityUpdateMessage(unityNetworkObject);
                }
                else
                {
                    this.SendIdentityUpdateMessage(unityNetworkObject, userInfo);
                    this.SendAllNetworkBehaviourDataToUser(unityNetworkObject, userInfo);
                }

                break;
            }

            case NetworkIdentitiesDestroyed.Id:
            {
                var destroyedMessage = (NetworkIdentitiesDestroyed)message;

                if (destroyedMessage.DestroyedNetworkIds?.Count > 0)
                {
                    for (int i = 0; i < destroyedMessage.DestroyedNetworkIds.Count; i++)
                    {
                        long networkId     = destroyedMessage.DestroyedNetworkIds[i];
                        var  networkObject = this.serverState.GetUnityNetworkObject(networkId);

                        if (networkObject != null)
                        {
                            if (networkObject.OwnerId == userInfo.UserId)
                            {
                                // If static, remove from static dictionary and add to destoryed static list
                                // If dynamic, just remove from dynamic dictionary
                                // Delete the object and forward to everyone
                            }
                        }
                    }
                }

                // If this came from the owner of the object, then add

                //

                // Ignore for now, can't get this till ownership changing exists
                break;
            }

            case NetworkIdentityUpdate.Id:
            {
                // Ignore for now, can't get this till ownership changing exists
                break;
            }

            case NetworkBehaviourMessage.Id:
            {
                var networkBehaviourMessage = (NetworkBehaviourMessage)message;

                var networkObject = this.serverState.GetUnityNetworkObject(networkBehaviourMessage.NetworkId);

                if (networkObject != null && networkObject.OwnerId == userInfo.UserId)
                {
                    if (networkObject.BehaviourDatas[networkBehaviourMessage.BehaviourIndex] == null)
                    {
                        networkObject.BehaviourDatas[networkBehaviourMessage.BehaviourIndex] = new BehaviourData();
                    }

                    var behaviourData = networkObject.BehaviourDatas[networkBehaviourMessage.BehaviourIndex];
                    behaviourData.Data.SetData(networkBehaviourMessage.DataBytes, networkBehaviourMessage.DataLength);

                    this.gameServer.SendMessageToAllExcept(userInfo, message, reliable);
                }

                break;
            }

            case NetworkBehaviourDataMessage.Id:
            {
                var networkBehaviourDataMessage = (NetworkBehaviourDataMessage)message;

                var networkObject = this.serverState.GetUnityNetworkObject(networkBehaviourDataMessage.NetworkId);

                if (networkObject != null)
                {
                    if (networkBehaviourDataMessage.SendType == NetworkBehaviourDataSendType.All)
                    {
                        this.gameServer.SendMessageToAll(networkBehaviourDataMessage);
                    }
                    else if (networkBehaviourDataMessage.SendType == NetworkBehaviourDataSendType.Others)
                    {
                        this.gameServer.SendMessageToAllExcept(userInfo, networkBehaviourDataMessage);
                    }
                    else
                    {
                        throw new NotImplementedException();
                    }
                }

                break;
            }

            case NetworkIdentityOwnershipRequest.Id:
            {
                var networkIdentityOwnershipRequest = (NetworkIdentityOwnershipRequest)message;

                UnityNetworkObject unityNetworkObject = this.serverState.GetUnityNetworkObject(networkIdentityOwnershipRequest.NetworkId);

                if (unityNetworkObject != null)
                {
                    if (unityNetworkObject.CanChangeOwner)
                    {
                        Debug.Log($"User {userInfo.UserId} requesting Ownership of {unityNetworkObject.NetworkId} Granted.");

                        unityNetworkObject.OwnerId        = userInfo.UserId;
                        unityNetworkObject.CanChangeOwner = false;
                    }
                    else
                    {
                        Debug.Log($"User {userInfo.UserId} requesting Ownership of {unityNetworkObject.NetworkId} Failed: CanChangeOwner = false.");
                    }

                    this.SendIdentityUpdateMessage(unityNetworkObject);                   // Telling everyone about the ownership change
                    this.SendAllNetworkBehaviourDataToUser(unityNetworkObject, userInfo); // Making sure the new owner has all the latest server info
                }

                break;
            }

            case NetworkIdentityReleaseOwnershipRequest.Id:
            {
                var networkIdentityReleaseOwnershipRequest = (NetworkIdentityReleaseOwnershipRequest)message;

                UnityNetworkObject unityNetworkObject = this.serverState.GetUnityNetworkObject(networkIdentityReleaseOwnershipRequest.NetworkId);

                if (unityNetworkObject != null && unityNetworkObject.OwnerId == userInfo.UserId)
                {
                    unityNetworkObject.CanChangeOwner = true;

                    //// TODO [bgish]: Possibly set the OwnerId to be whomever is the "Server"

                    this.SendIdentityUpdateMessage(unityNetworkObject);
                }

                break;
            }
            }
        }