Exemplo n.º 1
0
        // This runs in a seperate thread, be careful accessing anything outside of it's thread
        // or you may get an AccessViolation/crash.
        private void ThreadWorker(Object parameters)
        {
            if (Verbosity > 0)
            {
                Debug.Log("Ignorance Client: Initializing. Please stand by...");
            }

            ThreadParamInfo      setupInfo;
            Address              clientAddress = new Address();
            Peer                 clientPeer;  // The peer object that represents the client's connection.
            Host                 clientHost;  // NOT related to Mirror "Client Host". This is the client's ENet Host Object.
            Event                clientEvent; // Used when clients get events on the network.
            IgnoranceClientStats icsu = default;
            bool                 alreadyNotifiedAboutDisconnect = false;

            // Unused for now
            // bool emergencyStop = false;

            // Grab the setup information.
            if (parameters.GetType() == typeof(ThreadParamInfo))
            {
                setupInfo = (ThreadParamInfo)parameters;
            }
            else
            {
                Debug.LogError("Ignorance Client: Startup failure; Invalid thread parameters. Aborting.");
                return;
            }

            // Attempt to initialize ENet inside the thread.
            if (Library.Initialize())
            {
                Debug.Log("Ignorance Client: ENet Native successfully initialized.");
            }
            else
            {
                Debug.LogError("Ignorance Client: Failed to initialize ENet Native. This threads' f****d.");
                return;
            }

            // Attempt to connect to our target.
            clientAddress.SetHost(setupInfo.Address);
            clientAddress.Port = (ushort)setupInfo.Port;

            using (clientHost = new Host())
            {
                // TODO: Maybe try catch this
                clientHost.Create();
                clientPeer = clientHost.Connect(clientAddress, setupInfo.Channels);

                while (Commands.TryDequeue(out IgnoranceCommandPacket commandPacket))
                {
                    switch (commandPacket.Type)
                    {
                    default:
                        break;

                    case IgnoranceCommandType.ClientWantsToStop:
                        CeaseOperation = true;
                        break;

                    case IgnoranceCommandType.ClientStatusRequest:
                        // Respond with statistics so far.
                        if (!clientPeer.IsSet)
                        {
                            break;
                        }

                        icsu.RTT = clientPeer.RoundTripTime;

                        icsu.BytesReceived = clientPeer.BytesReceived;
                        icsu.BytesSent     = clientPeer.BytesSent;

                        icsu.PacketsReceived = clientHost.PacketsReceived;
                        icsu.PacketsSent     = clientPeer.PacketsSent;
                        icsu.PacketsLost     = clientPeer.PacketsLost;

                        StatusUpdates.Enqueue(icsu);
                        break;
                    }
                }

                // Process network events as long as we're not ceasing operation.
                while (!CeaseOperation)
                {
                    bool pollComplete = false;

                    // Step 1: Sending to Server
                    while (Outgoing.TryDequeue(out IgnoranceOutgoingPacket outgoingPacket))
                    {
                        // TODO: Revise this, could we tell the Peer to disconnect right here?
                        // Stop early if we get a client stop packet.
                        // if (outgoingPacket.Type == IgnorancePacketType.ClientWantsToStop) break;

                        int ret = clientPeer.Send(outgoingPacket.Channel, ref outgoingPacket.Payload);

                        if (ret < 0 && setupInfo.Verbosity > 0)
                        {
                            Debug.LogWarning($"Ignorance Client: ENet error {ret} while sending packet to Server via Peer {outgoingPacket.NativePeerId}.");
                        }
                    }

                    // If something outside the thread has told us to stop execution, then we need to break out of this while loop.
                    // while loop to break out of is while(!CeaseOperation).
                    if (CeaseOperation)
                    {
                        break;
                    }

                    // Step 2: Receive Data packets
                    // This loops until polling is completed. It may take a while, if it's
                    // a slow networking day.
                    while (!pollComplete)
                    {
                        Packet incomingPacket;
                        Peer   incomingPeer;
                        int    incomingPacketLength;

                        // Any events worth checking out?
                        if (clientHost.CheckEvents(out clientEvent) <= 0)
                        {
                            // If service time is met, break out of it.
                            if (clientHost.Service(setupInfo.PollTime, out clientEvent) <= 0)
                            {
                                break;
                            }

                            // Poll is done.
                            pollComplete = true;
                        }

                        // Setup the packet references.
                        incomingPeer = clientEvent.Peer;

                        // Now, let's handle those events.
                        switch (clientEvent.Type)
                        {
                        case EventType.None:
                        default:
                            break;

                        case EventType.Connect:
                            if (setupInfo.Verbosity > 0)
                            {
                                Debug.Log("Ignorance Client: ENet has connected to the server.");
                            }

                            ConnectionEvents.Enqueue(new IgnoranceConnectionEvent
                            {
                                EventType    = 0x00,
                                NativePeerId = incomingPeer.ID,
                                IP           = incomingPeer.IP,
                                Port         = incomingPeer.Port
                            });
                            break;

                        case EventType.Disconnect:
                        case EventType.Timeout:
                            if (setupInfo.Verbosity > 0)
                            {
                                Debug.Log("Ignorance Client: ENet has been disconnected from the server.");
                            }

                            ConnectionEvents.Enqueue(new IgnoranceConnectionEvent {
                                EventType = 0x01
                            });
                            CeaseOperation = true;
                            alreadyNotifiedAboutDisconnect = true;
                            break;

                        case EventType.Receive:
                            // Receive event type usually includes a packet; so cache its reference.
                            incomingPacket = clientEvent.Packet;

                            if (!incomingPacket.IsSet)
                            {
                                if (setupInfo.Verbosity > 0)
                                {
                                    Debug.LogWarning($"Ignorance Client: A receive event did not supply us with a packet to work with. This should never happen.");
                                }
                                break;
                            }

                            incomingPacketLength = incomingPacket.Length;

                            // Never consume more than we can have capacity for.
                            if (incomingPacketLength > setupInfo.PacketSizeLimit)
                            {
                                if (setupInfo.Verbosity > 0)
                                {
                                    Debug.LogWarning($"Ignorance Client: Incoming packet is too big. My limit is {setupInfo.PacketSizeLimit} byte(s) whilest this packet is {incomingPacketLength} bytes.");
                                }

                                incomingPacket.Dispose();
                                break;
                            }

                            IgnoranceIncomingPacket incomingQueuePacket = new IgnoranceIncomingPacket
                            {
                                Channel      = clientEvent.ChannelID,
                                NativePeerId = incomingPeer.ID,
                                Payload      = incomingPacket
                            };

                            Incoming.Enqueue(incomingQueuePacket);
                            break;
                        }
                    }

                    // If something outside the thread has told us to stop execution, then we need to break out of this while loop.
                    // while loop to break out of is while(!CeaseOperation).
                    if (CeaseOperation)
                    {
                        break;
                    }
                }

                Debug.Log("Ignorance Client: Thread shutdown commencing. Disconnecting and flushing connection.");

                // Flush the client and disconnect.
                clientPeer.Disconnect(0);
                clientHost.Flush();

                // Fix for client stuck in limbo, since the disconnection event may not be fired until next loop.
                if (!alreadyNotifiedAboutDisconnect)
                {
                    ConnectionEvents.Enqueue(new IgnoranceConnectionEvent {
                        EventType = 0x01
                    });
                    alreadyNotifiedAboutDisconnect = true;
                }
            }

            // Fix for client stuck in limbo, since the disconnection event may not be fired until next loop, again.
            if (!alreadyNotifiedAboutDisconnect)
            {
                ConnectionEvents.Enqueue(new IgnoranceConnectionEvent {
                    EventType = 0x01
                });
            }

            // Deinitialize
            Library.Deinitialize();

            if (setupInfo.Verbosity > 0)
            {
                Debug.Log("Ignorance Client: Shutdown complete.");
            }
        }
Exemplo n.º 2
0
        private void ThreadWorker(Object parameters)
        {
            // Thread cache items
            ThreadParamInfo setupInfo;
            Address         serverAddress = new Address();
            Host            serverENetHost;
            Event           serverENetEvent;

            Peer[] serverPeerArray;

            // Grab the setup information.
            if (parameters.GetType() == typeof(ThreadParamInfo))
            {
                setupInfo = (ThreadParamInfo)parameters;
            }
            else
            {
                return;
            }

            // Attempt to initialize ENet inside the thread.
            if (Library.Initialize())
            {
            }
            else
            {
                return;
            }

            // Configure the server address.
            serverAddress.SetHost(setupInfo.Address);
            serverAddress.Port = (ushort)setupInfo.Port;
            serverPeerArray    = new Peer[setupInfo.Peers];

            using (serverENetHost = new Host())
            {
                // Create the server object.
                serverENetHost.Create(serverAddress, setupInfo.Peers, setupInfo.Channels);

                // Loop until we're told to cease operations.
                while (!CeaseOperation)
                {
                    // Intermission: Command Handling
                    while (Commands.TryDequeue(out IgnoranceCommandPacket commandPacket))
                    {
                        switch (commandPacket.Type)
                        {
                        default:
                            break;

                        // Boot a Peer off the Server.
                        case IgnoranceCommandType.ServerKickPeer:
                            uint targetPeer = commandPacket.PeerId;

                            if (!serverPeerArray[targetPeer].IsSet)
                            {
                                continue;
                            }

                            IgnoranceConnectionEvent iced = new IgnoranceConnectionEvent()
                            {
                                WasDisconnect = true,
                                NativePeerId  = targetPeer
                            };

                            DisconnectionEvents.Enqueue(iced);

                            // Disconnect and reset the peer array's entry for that peer.
                            serverPeerArray[targetPeer].DisconnectNow(0);
                            serverPeerArray[targetPeer] = default;
                            break;
                        }
                    }

                    // Step One:
                    // ---> Sending to peers
                    while (Outgoing.TryDequeue(out IgnoranceOutgoingPacket outgoingPacket))
                    {
                        // Only create a packet if the server knows the peer.
                        if (serverPeerArray[outgoingPacket.NativePeerId].IsSet)
                        {
                            int ret = serverPeerArray[outgoingPacket.NativePeerId].Send(outgoingPacket.Channel, ref outgoingPacket.Payload);
                        }
                        else
                        {
                            // A peer might have disconnected, this is OK - just log the packet if set to paranoid.
                        }
                    }

                    // Step 2
                    // <--- Receiving from peers
                    bool pollComplete = false;

                    while (!pollComplete)
                    {
                        Packet incomingPacket;
                        Peer   incomingPeer;
                        int    incomingPacketLength;

                        // Any events happening?
                        if (serverENetHost.CheckEvents(out serverENetEvent) <= 0)
                        {
                            // If service time is met, break out of it.
                            if (serverENetHost.Service(setupInfo.PollTime, out serverENetEvent) <= 0)
                            {
                                break;
                            }

                            pollComplete = true;
                        }

                        // Setup the packet references.
                        incomingPeer = serverENetEvent.Peer;

                        switch (serverENetEvent.Type)
                        {
                        // Idle.
                        case EventType.None:
                        default:
                            break;

                        // Connection Event.
                        case EventType.Connect:
                            IgnoranceConnectionEvent ice = new IgnoranceConnectionEvent()
                            {
                                NativePeerId = incomingPeer.ID,
                                IP           = incomingPeer.IP,
                                Port         = incomingPeer.Port
                            };

                            ConnectionEvents.Enqueue(ice);

                            // Assign a reference to the Peer.
                            serverPeerArray[incomingPeer.ID] = incomingPeer;
                            break;

                        // Disconnect/Timeout. Mirror doesn't care if it's either, so we lump them together.
                        case EventType.Disconnect:
                        case EventType.Timeout:
                            if (!serverPeerArray[incomingPeer.ID].IsSet)
                            {
                                break;
                            }

                            IgnoranceConnectionEvent iced = new IgnoranceConnectionEvent()
                            {
                                WasDisconnect = true,
                                NativePeerId  = incomingPeer.ID
                            };

                            DisconnectionEvents.Enqueue(iced);

                            // Reset the peer array's entry for that peer.
                            serverPeerArray[incomingPeer.ID] = default;
                            break;

                        case EventType.Receive:
                            // Receive event type usually includes a packet; so cache its reference.
                            incomingPacket = serverENetEvent.Packet;
                            if (!incomingPacket.IsSet)
                            {
                                break;
                            }

                            incomingPacketLength = incomingPacket.Length;

                            // Firstly check if the packet is too big. If it is, do not process it - drop it.
                            if (incomingPacketLength > setupInfo.PacketSizeLimit)
                            {
                                incomingPacket.Dispose();
                                break;
                            }

                            IgnoranceIncomingPacket incomingQueuePacket = new IgnoranceIncomingPacket
                            {
                                Channel      = serverENetEvent.ChannelID,
                                NativePeerId = incomingPeer.ID,
                                Payload      = incomingPacket,
                            };

                            // Enqueue.
                            Incoming.Enqueue(incomingQueuePacket);
                            break;
                        }
                    }
                }


                // Cleanup and flush everything.
                serverENetHost.Flush();

                // Kick everyone.
                for (int i = 0; i < serverPeerArray.Length; i++)
                {
                    if (!serverPeerArray[i].IsSet)
                    {
                        continue;
                    }
                    serverPeerArray[i].DisconnectNow(0);
                }
            }

            // Flush again to ensure ENet gets those Disconnection stuff out.
            // May not be needed; better to err on side of caution


            Library.Deinitialize();
        }
Exemplo n.º 3
0
        // This runs in a seperate thread, be careful accessing anything outside of it's thread
        // or you may get an AccessViolation/crash.
        private void ThreadWorker(Object parameters)
        {
            if (Verbosity > 0)
            {
                Debug.Log("Client Worker Thread: Startup");
            }

            ThreadParamInfo      setupInfo;
            Address              clientAddress = new Address();
            Peer                 clientPeer;
            Host                 clientENetHost;
            Event                clientENetEvent;
            IgnoranceClientStats icsu = default;

            // Grab the setup information.
            if (parameters.GetType() == typeof(ThreadParamInfo))
            {
                setupInfo = (ThreadParamInfo)parameters;
            }
            else
            {
                Debug.LogError("Thread worker startup failure: Invalid thread parameters. Aborting.");
                return;
            }

            // Attempt to initialize ENet inside the thread.
            if (Library.Initialize())
            {
                Debug.Log("Client Worker Thread: Initialized ENet.");
            }
            else
            {
                Debug.LogError("Client Worker Thread: Failed to initialize ENet. This threads' f****d.");
                return;
            }

            // Attempt to connect to our target.
            clientAddress.SetHost(setupInfo.Address);
            clientAddress.Port = (ushort)setupInfo.Port;

            using (clientENetHost = new Host())
            {
                // TODO: Maybe try catch this
                clientENetHost.Create();
                clientPeer = clientENetHost.Connect(clientAddress, setupInfo.Channels);

                while (!CeaseOperation)
                {
                    bool pollComplete = false;

                    // Step 0: Handle commands.
                    while (Commands.TryDequeue(out IgnoranceCommandPacket commandPacket))
                    {
                        switch (commandPacket.Type)
                        {
                        default:
                            break;

                        case IgnoranceCommandType.ClientWantsToStop:
                            CeaseOperation = true;
                            break;

                        case IgnoranceCommandType.ClientRequestsStatusUpdate:
                            // Respond with statistics so far.
                            if (!clientPeer.IsSet)
                            {
                                break;
                            }

                            icsu.RTT = clientPeer.RoundTripTime;

                            icsu.BytesReceived = clientPeer.BytesReceived;
                            icsu.BytesSent     = clientPeer.BytesSent;

                            icsu.PacketsReceived = clientENetHost.PacketsReceived;
                            icsu.PacketsSent     = clientPeer.PacketsSent;
                            icsu.PacketsLost     = clientPeer.PacketsLost;

                            StatusUpdates.Enqueue(icsu);
                            break;
                        }
                    }
                    // Step 1: Send out data.
                    // ---> Sending to Server
                    while (Outgoing.TryDequeue(out IgnoranceOutgoingPacket outgoingPacket))
                    {
                        // TODO: Revise this, could we tell the Peer to disconnect right here?
                        // Stop early if we get a client stop packet.
                        // if (outgoingPacket.Type == IgnorancePacketType.ClientWantsToStop) break;

                        int ret = clientPeer.Send(outgoingPacket.Channel, ref outgoingPacket.Payload);

                        if (ret < 0 && setupInfo.Verbosity > 0)
                        {
                            Debug.LogWarning($"Client Worker Thread: Failed sending a packet to Peer {outgoingPacket.NativePeerId}, error code {ret}");
                        }
                    }

                    // Step 2:
                    // <----- Receive Data packets
                    // This loops until polling is completed. It may take a while, if it's
                    // a slow networking day.
                    while (!pollComplete)
                    {
                        Packet incomingPacket;
                        Peer   incomingPeer;
                        int    incomingPacketLength;

                        // Any events worth checking out?
                        if (clientENetHost.CheckEvents(out clientENetEvent) <= 0)
                        {
                            // If service time is met, break out of it.
                            if (clientENetHost.Service(setupInfo.PollTime, out clientENetEvent) <= 0)
                            {
                                break;
                            }

                            // Poll is done.
                            pollComplete = true;
                        }

                        // Setup the packet references.
                        incomingPeer = clientENetEvent.Peer;

                        // Now, let's handle those events.
                        switch (clientENetEvent.Type)
                        {
                        case EventType.None:
                        default:
                            break;

                        case EventType.Connect:
                            ConnectionEvents.Enqueue(new IgnoranceConnectionEvent()
                            {
                                NativePeerId = incomingPeer.ID,
                                IP           = incomingPeer.IP,
                                Port         = incomingPeer.Port
                            });
                            break;

                        case EventType.Disconnect:
                        case EventType.Timeout:
                            ConnectionEvents.Enqueue(new IgnoranceConnectionEvent()
                            {
                                WasDisconnect = true
                            });
                            break;


                        case EventType.Receive:
                            // Receive event type usually includes a packet; so cache its reference.
                            incomingPacket = clientENetEvent.Packet;

                            if (!incomingPacket.IsSet)
                            {
                                if (setupInfo.Verbosity > 0)
                                {
                                    Debug.LogWarning($"Client Worker Thread: A receive event did not supply us with a packet to work with. This should never happen.");
                                }
                                break;
                            }

                            incomingPacketLength = incomingPacket.Length;

                            // Never consume more than we can have capacity for.
                            if (incomingPacketLength > setupInfo.PacketSizeLimit)
                            {
                                if (setupInfo.Verbosity > 0)
                                {
                                    Debug.LogWarning($"Client Worker Thread: Received a packet too large, {incomingPacketLength} bytes while our limit is {setupInfo.PacketSizeLimit} bytes.");
                                }

                                incomingPacket.Dispose();
                                break;
                            }

                            IgnoranceIncomingPacket incomingQueuePacket = new IgnoranceIncomingPacket
                            {
                                Channel      = clientENetEvent.ChannelID,
                                NativePeerId = incomingPeer.ID,
                                Payload      = incomingPacket
                            };

                            Incoming.Enqueue(incomingQueuePacket);
                            break;
                        }
                    }
                }

                // Flush the client and disconnect.
                clientPeer.Disconnect(0);
                clientENetHost.Flush();
            }

            // Deinitialize
            Library.Deinitialize();
            if (setupInfo.Verbosity > 0)
            {
                Debug.Log("Client Worker Thread: Shutdown.");
            }
        }
Exemplo n.º 4
0
        private void ThreadWorker(Object parameters)
        {
            if (Verbosity > 0)
            {
                Debug.Log("Ignorance Server: Initializing. Please stand by...");
            }

            // Thread cache items
            ThreadParamInfo setupInfo;
            Address         serverAddress = new Address();
            Host            serverENetHost;
            Event           serverENetEvent;

            Peer[] serverPeerArray;

            // Grab the setup information.
            if (parameters.GetType() == typeof(ThreadParamInfo))
            {
                setupInfo = (ThreadParamInfo)parameters;
            }
            else
            {
                Debug.LogError("Ignorance Server: Startup failure; Invalid thread parameters. Aborting.");
                return;
            }

            // Attempt to initialize ENet inside the thread.
            if (Library.Initialize())
            {
                Debug.Log("Ignorance Server: ENet Native successfully initialized.");
            }
            else
            {
                Debug.LogError("Ignorance Server: Failed to initialize ENet Native. This threads' f****d.");
                return;
            }

            // Configure the server address.
            serverAddress.SetHost(setupInfo.Address);
            serverAddress.Port = (ushort)setupInfo.Port;
            serverPeerArray    = new Peer[setupInfo.Peers];

            using (serverENetHost = new Host())
            {
                // Create the server object.
                serverENetHost.Create(serverAddress, setupInfo.Peers, setupInfo.Channels);

                // Loop until we're told to cease operations.
                while (!CeaseOperation)
                {
                    // Intermission: Command Handling
                    while (Commands.TryDequeue(out IgnoranceCommandPacket commandPacket))
                    {
                        switch (commandPacket.Type)
                        {
                        default:
                            break;

                        // Boot a Peer off the Server.
                        case IgnoranceCommandType.ServerKickPeer:
                            uint targetPeer = commandPacket.PeerId;

                            if (!serverPeerArray[targetPeer].IsSet)
                            {
                                continue;
                            }

                            if (setupInfo.Verbosity > 0)
                            {
                                Debug.Log($"Ignorance Server: Booting ENet Peer {targetPeer} off this server instance.");
                            }

                            IgnoranceConnectionEvent iced = new IgnoranceConnectionEvent
                            {
                                EventType    = 0x01,
                                NativePeerId = targetPeer
                            };

                            DisconnectionEvents.Enqueue(iced);

                            // Disconnect and reset the peer array's entry for that peer.
                            serverPeerArray[targetPeer].DisconnectNow(0);
                            serverPeerArray[targetPeer] = default;
                            break;
                        }
                    }

                    // Step One:
                    // ---> Sending to peers
                    while (Outgoing.TryDequeue(out IgnoranceOutgoingPacket outgoingPacket))
                    {
                        // Only create a packet if the server knows the peer.
                        if (serverPeerArray[outgoingPacket.NativePeerId].IsSet)
                        {
                            int ret = serverPeerArray[outgoingPacket.NativePeerId].Send(outgoingPacket.Channel, ref outgoingPacket.Payload);

                            if (ret < 0 && setupInfo.Verbosity > 0)
                            {
                                Debug.LogWarning($"Ignorance Server: ENet error {ret} while sending packet to Peer {outgoingPacket.NativePeerId}.");
                            }
                        }
                        else
                        {
                            // A peer might have disconnected, this is OK - just log the packet if set to paranoid.
                            if (setupInfo.Verbosity > 1)
                            {
                                Debug.LogWarning("Ignorance Server: Can't send packet, a native peer object is not set. This may be normal if the Peer has disconnected before this send cycle.");
                            }
                        }
                    }

                    // Step 2
                    // <--- Receiving from peers
                    bool pollComplete = false;

                    while (!pollComplete)
                    {
                        Packet incomingPacket;
                        Peer   incomingPeer;
                        int    incomingPacketLength;

                        // Any events happening?
                        if (serverENetHost.CheckEvents(out serverENetEvent) <= 0)
                        {
                            // If service time is met, break out of it.
                            if (serverENetHost.Service(setupInfo.PollTime, out serverENetEvent) <= 0)
                            {
                                break;
                            }

                            pollComplete = true;
                        }

                        // Setup the packet references.
                        incomingPeer = serverENetEvent.Peer;

                        // What type are you?
                        switch (serverENetEvent.Type)
                        {
                        // Idle.
                        case EventType.None:
                        default:
                            break;

                        // Connection Event.
                        case EventType.Connect:
                            if (setupInfo.Verbosity > 1)
                            {
                                Debug.Log($"Ignorance Server: Hello new peer with ID {incomingPeer.ID}!");
                            }

                            IgnoranceConnectionEvent ice = new IgnoranceConnectionEvent()
                            {
                                NativePeerId = incomingPeer.ID,
                                IP           = incomingPeer.IP,
                                Port         = incomingPeer.Port
                            };

                            ConnectionEvents.Enqueue(ice);

                            // Assign a reference to the Peer.
                            serverPeerArray[incomingPeer.ID] = incomingPeer;
                            break;

                        // Disconnect/Timeout. Mirror doesn't care if it's either, so we lump them together.
                        case EventType.Disconnect:
                        case EventType.Timeout:
                            if (!serverPeerArray[incomingPeer.ID].IsSet)
                            {
                                break;
                            }

                            if (setupInfo.Verbosity > 1)
                            {
                                Debug.Log($"Ignorance Server: Bye bye Peer {incomingPeer.ID}; They have disconnected.");
                            }

                            IgnoranceConnectionEvent iced = new IgnoranceConnectionEvent
                            {
                                EventType    = 0x01,
                                NativePeerId = incomingPeer.ID
                            };

                            DisconnectionEvents.Enqueue(iced);

                            // Reset the peer array's entry for that peer.
                            serverPeerArray[incomingPeer.ID] = default;
                            break;

                        case EventType.Receive:
                            // Receive event type usually includes a packet; so cache its reference.
                            incomingPacket = serverENetEvent.Packet;
                            if (!incomingPacket.IsSet)
                            {
                                if (setupInfo.Verbosity > 0)
                                {
                                    Debug.LogWarning($"Ignorance Server: A receive event did not supply us with a packet to work with. This should never happen.");
                                }
                                break;
                            }

                            incomingPacketLength = incomingPacket.Length;

                            // Firstly check if the packet is too big. If it is, do not process it - drop it.
                            if (incomingPacketLength > setupInfo.PacketSizeLimit)
                            {
                                if (setupInfo.Verbosity > 0)
                                {
                                    Debug.LogWarning($"Ignorance Server: Incoming packet is too big. My limit is {setupInfo.PacketSizeLimit} byte(s) whilest this packet is {incomingPacketLength} bytes.");
                                }

                                incomingPacket.Dispose();
                                break;
                            }

                            IgnoranceIncomingPacket incomingQueuePacket = new IgnoranceIncomingPacket
                            {
                                Channel      = serverENetEvent.ChannelID,
                                NativePeerId = incomingPeer.ID,
                                Payload      = incomingPacket,
                            };

                            // Enqueue.
                            Incoming.Enqueue(incomingQueuePacket);
                            break;
                        }
                    }
                }

                if (Verbosity > 0)
                {
                    Debug.Log("Ignorance Server: Thread shutdown commencing. Flushing connections.");
                }

                // Cleanup and flush everything.
                serverENetHost.Flush();

                // Kick everyone.
                for (int i = 0; i < serverPeerArray.Length; i++)
                {
                    if (!serverPeerArray[i].IsSet)
                    {
                        continue;
                    }
                    serverPeerArray[i].DisconnectNow(0);
                }
            }

            if (setupInfo.Verbosity > 0)
            {
                Debug.Log("Ignorance Server: Shutdown complete.");
            }

            Library.Deinitialize();
        }