fCraft.Player.IoLoop C# (CSharp) Method

IoLoop() private method

private IoLoop ( ) : void
return void
        private void IoLoop()
        {
            try {
                Server.RaiseSessionConnectedEvent( this );

                // try to log the player in, otherwise die.
                if ( !LoginSequence() )
                    return;

                BandwidthUseMode = Info.BandwidthUseMode;

                // set up some temp variables
                Packet packet = new Packet();

                int pollCounter = 0,
                    pingCounter = 0;

                // main i/o loop
                while ( canSend ) {
                    int packetsSent = 0;

                    // detect player disconnect
                    if ( pollCounter > SocketPollInterval ) {
                        if ( !client.Connected ||
                            ( client.Client.Poll( 1000, SelectMode.SelectRead ) && client.Client.Available == 0 ) ) {
                            if ( Info != null ) {
                                Logger.Log( LogType.Debug,
                                            "Player.IoLoop: Lost connection to player {0} ({1}).", Name, IP );
                            } else {
                                Logger.Log( LogType.Debug,
                                            "Player.IoLoop: Lost connection to unidentified player at {0}.", IP );
                            }
                            LeaveReason = LeaveReason.ClientQuit;
                            return;
                        }
                        if ( pingCounter > PingInterval ) {
                            writer.WritePing();
                            BytesSent++;
                            pingCounter = 0;
                            MeasureBandwidthUseRates();
                        }
                        pingCounter++;
                        pollCounter = 0;
                        if ( IsUsingWoM ) {
                            MessageNowPrefixed( "", "^detail.user=" + InfoCommands.GetCompassString( Position.R ) );
                        }
                    }
                    pollCounter++;

                    if ( DateTime.UtcNow.Subtract( lastMovementUpdate ) > movementUpdateInterval ) {
                        UpdateVisibleEntities();
                        lastMovementUpdate = DateTime.UtcNow;
                    }

                    // send output to player
                    while ( canSend && packetsSent < Server.MaxSessionPacketsPerTick ) {
                        if ( !priorityOutputQueue.TryDequeue( out packet ) )
                            if ( !outputQueue.TryDequeue( out packet ) )
                                break;

                        if ( IsDeaf && packet.OpCode == OpCode.Message )
                            continue;

                        writer.Write( packet.Data );
                        BytesSent += packet.Data.Length;
                        packetsSent++;

                        if ( packet.OpCode == OpCode.Kick ) {
                            writer.Flush();
                            if ( LeaveReason == LeaveReason.Unknown )
                                LeaveReason = LeaveReason.Kick;
                            return;
                        }

                        if ( DateTime.UtcNow.Subtract( lastMovementUpdate ) > movementUpdateInterval ) {
                            UpdateVisibleEntities();
                            lastMovementUpdate = DateTime.UtcNow;
                        }
                    }

                    // check if player needs to change worlds
                    if ( canSend ) {
                        lock ( joinWorldLock ) {
                            if ( forcedWorldToJoin != null ) {
                                while ( priorityOutputQueue.TryDequeue( out packet ) ) {
                                    writer.Write( packet.Data );
                                    BytesSent += packet.Data.Length;
                                    packetsSent++;
                                    if ( packet.OpCode == OpCode.Kick ) {
                                        writer.Flush();
                                        if ( LeaveReason == LeaveReason.Unknown )
                                            LeaveReason = LeaveReason.Kick;
                                        return;
                                    }
                                }
                                if ( !JoinWorldNow( forcedWorldToJoin, useWorldSpawn, worldChangeReason ) ) {
                                    Logger.Log( LogType.Warning,
                                                "Player.IoLoop: Player was asked to force-join a world, but it was full." );
                                    KickNow( "World is full.", LeaveReason.ServerFull );
                                }
                                forcedWorldToJoin = null;
                            }
                        }

                        if ( DateTime.UtcNow.Subtract( lastMovementUpdate ) > movementUpdateInterval ) {
                            UpdateVisibleEntities();
                            lastMovementUpdate = DateTime.UtcNow;
                        }
                    }

                    // get input from player
                    while ( canReceive && stream.DataAvailable ) {
                        byte opcode = reader.ReadByte();
                        switch ( ( OpCode )opcode ) {
                            case OpCode.Message:
                                if ( !ProcessMessagePacket() )
                                    return;
                                break;

                            case OpCode.Teleport:
                                ProcessMovementPacket();
                                break;

                            case OpCode.SetBlockClient:
                                ProcessSetBlockPacket();
                                break;

                            case OpCode.Ping:
                                BytesReceived++;
                                continue;

                            default:
                                Logger.Log( LogType.SuspiciousActivity,
                                            "Player {0} was kicked after sending an invalid opcode ({1}).",
                                            Name, opcode );
                                KickNow( "Unknown packet opcode " + opcode,
                                         LeaveReason.InvalidOpcodeKick );
                                return;
                        }

                        if ( DateTime.UtcNow.Subtract( lastMovementUpdate ) > movementUpdateInterval ) {
                            UpdateVisibleEntities();
                            lastMovementUpdate = DateTime.UtcNow;
                        }
                    }

                    Thread.Sleep( SleepDelay );
                }
            } catch ( IOException ) {
                LeaveReason = LeaveReason.ClientQuit;
            } catch ( SocketException ) {
                LeaveReason = LeaveReason.ClientQuit;
            #if !DEBUG
            } catch ( Exception ex ) {
                LeaveReason = LeaveReason.ServerError;
                Logger.LogAndReportCrash( "Error in Player.IoLoop", "800Craft", ex, false );
            #endif
            } finally {
                canQueue = false;
                canSend = false;
                Disconnect();
            }
        }