internal override void HandleChatMessage(INetworkMessageIn msg)
        {
            var message = msg.ReadString();

            ReceivedChatMessage(message);

            NetworkImplementation?.SendChatMessage(message);
        }
        protected INetworkMessageOut CreateMessage(NetworkMessageType type)
        {
            if (NetworkImplementation == null)
            {
                throw new NullReferenceException("NetworkImplementation was not initialized.");
            }

            return(NetworkImplementation.CreateMessage(type));
        }
        internal virtual void HandleConnectionApproval(INetworkMessageIn msg)
        {
            var approvalMessage = msg.ReadString();

            if (ApproveConnection(approvalMessage))
            {
                NetworkImplementation?.ApproveMessage(msg);
            }
            else
            {
                NetworkImplementation?.DisapproveMessage(msg);
            }
        }
        internal override void HandleStatusChangedConnected(INetworkMessageIn msg)
        {
            if (!_readyConnections.ContainsKey(msg.UniqueId))
            {
                _readyConnections.Add(msg.UniqueId, new ReadyConnection());

                NetworkImplementation?.ClientJoinedSession(msg);

                if (_lastLevelChange != null)
                {
                    var message = CreateLevelChangeMessage(_lastLevelChange);
                    SendMessageToId(msg.UniqueId, message, MessageDeliveryMethod.ReliableOrdered, 2);
                }
            }
        }
        public void Update(double totalMilliseconds)
        {
            if (NetworkImplementation == null)
            {
                throw new NullReferenceException("NetworkImplementation was not initialized.");
            }

            Updated = false;

            // todo: fix calculation here
            _currentUpdateSkip = totalMilliseconds - _startedUpdate;
            if (_currentUpdateSkip < _tickTimesPerSecond)
            {
                return;
            }

            _currentUpdateSkip = 0;
            _startedUpdate     = totalMilliseconds;

            Updated = true;

            if (!NetworkImplementation.IsConnected)
            {
                _methodCalls.Clear();
                return;
            }

            var traveled = false;

            Actors.RemoveAll(a => a.IsMarkedToDestroy);

            INetworkMessageIn?msg;

            while ((msg = NetworkImplementation.GetNextMessage()) != null)
            {
                switch (msg.GetMessageType())
                {
                case NetworkMessageType.ConnectionApproval:
                    HandleConnectionApproval(msg);
                    break;

                case NetworkMessageType.Connected:
                    HandleStatusChangedConnected(msg);
                    break;

                case NetworkMessageType.ActorReplication:
                    HandleActorReplication(msg);
                    break;

                case NetworkMessageType.PlayerCreation:
                    HandlePlayerCreation(msg);
                    break;

                case NetworkMessageType.ActorCreation:
                    HandleActorCreation(msg);
                    break;

                case NetworkMessageType.ActorRequestPlayerActor:
                    HandleActorRequestPlayerActor(msg);
                    break;

                case NetworkMessageType.ActorPropertiesReplication:
                    if (traveled)
                    {
                        break;
                    }
                    HandleActorPropertiesReplication(msg);
                    break;

                case NetworkMessageType.ActorRemoteMethodCall:
                    if (traveled)
                    {
                        break;
                    }
                    HandleActorRemoteMethodCall(msg);
                    break;

                case NetworkMessageType.ActorDestruction:
                    if (traveled)
                    {
                        break;
                    }
                    HandleActorDestruction(msg);
                    break;

                case NetworkMessageType.ServerTravel:
                    HandleServerTravel(msg);
                    traveled = true;
                    break;

                case NetworkMessageType.Disconnected:
                    HandleDisconnected(msg);
                    break;

                case NetworkMessageType.ClientDisconnected:
                    HandleClientDisconnected(msg);
                    break;

                case NetworkMessageType.ChatMessage:
                    HandleChatMessage(msg);
                    break;
                }

                msg.Recycle();
            }

            if (NetworkImplementation.HasConnections)
            {
                foreach (var call in _methodCalls.Values.SelectMany(actor => actor.Values))
                {
                    SendActorRemoteMethodCall(call.ActorRemoteId, call.MethodName, call.Reliable, call.Parameters);
                }
            }
            _methodCalls.Clear();

            EndUpdate(NetworkImplementation.HasConnections);
        }
 protected void SendMessageToIds(IEnumerable <long> uniqueIds, INetworkMessageOut message, MessageDeliveryMethod deliveryMethod, int channel)
 {
     NetworkImplementation?.SendMessageToIds(uniqueIds, message, deliveryMethod, channel);
 }
 protected void SendMessageToId(long uniqueId, INetworkMessageOut message, MessageDeliveryMethod deliveryMethod, int channel)
 {
     NetworkImplementation?.SendMessageToId(uniqueId, message, deliveryMethod, channel);
 }
 protected void SendMessageToSender(INetworkMessageIn to, INetworkMessageOut message, MessageDeliveryMethod deliveryMethod, int channel)
 {
     NetworkImplementation?.SendMessageToSender(to, message, deliveryMethod, channel);
 }