private static void ProcessPlayerData(int bufferId, int start, int length)
        {
            var buffer = NetMessage.buffer[bufferId];

            var player = Main.player[bufferId];
            var isConnection = player == null || player.Connection == null;
            if (isConnection)
            {
                player = new Player();
                player.IPAddress = Netplay.Clients[bufferId].Socket.GetRemoteAddress().GetIdentifier();
            }
            player.whoAmI = bufferId;

            if (bufferId == Main.myPlayer && !Main.ServerSideCharacter)
            {
                return;
            }

            var data = new HookArgs.PlayerDataReceived()
            {
                IsConnecting = isConnection
            };

            data.Parse(buffer.readBuffer, start, length);
            //            Skip(read);
            //
            //            if (data.Hair >= MAX_HAIR_ID)
            //            {
            //                data.Hair = 0;
            //            }
            //
            var ctx = new HookContext
            {
                Connection = player.Connection.Socket,
                Player = player,
                Sender = player,
            };
            //
            HookPoints.PlayerDataReceived.Invoke(ref ctx, ref data);
            //
            if (ctx.CheckForKick())
                return;

            if (!data.NameChecked)
            {
                string error;
                if (!data.CheckName(out error))
                {
                    player.Connection.Kick(error);
                    return;
                }
            }

            string address = player.IPAddress.Split(':')[0];
            //            if (!data.BansChecked)
            //            {
            //                if (Server.Bans.Contains(address) || Server.Bans.Contains(data.Name))
            //                {
            //                    ProgramLog.Admin.Log("Prevented banned user {0} from accessing the server.", data.Name);
            //                    conn.Kick("You are banned from this server.");
            //                    return;
            //                }
            //            }
            //
            //            if (!data.WhitelistChecked && Server.WhitelistEnabled)
            //            {
            //                if (!Server.Whitelist.Contains(address) && !Server.Whitelist.Contains(data.Name))
            //                {
            //                    ProgramLog.Admin.Log("Prevented non whitelisted user {0} from accessing the server.", data.Name);
            //                    conn.Kick("You do not have access to this server.");
            //                    return;
            //                }
            //            }

            data.Apply(player);

            if (isConnection)
            {
                if (ctx.Result == HookResult.ASK_PASS)
                {
            //                    conn.State = SlotState.PLAYER_AUTH;

            //                    var msg = NewNetMessage.PrepareThreadInstance();
            //                    msg.PasswordRequest();
            //                    conn.Send(msg.Output);
                    NetMessage.SendData((int)Packet.PASSWORD_REQUEST, bufferId);

                    return;
                }
                else // HookResult.DEFAULT
                {
                    // don't allow replacing connections for guests, but do for registered users
            //                    if (conn.State < SlotState.PLAYING)
                    {
                        var lname = player.Name.ToLower();

                        foreach (var otherPlayer in Main.player)
                        {
            //                            var otherSlot = Terraria.Netplay.Clients[otherPlayer.whoAmI];
                            if (otherPlayer.Name != null && lname == otherPlayer.Name.ToLower()) // && otherSlot.State >= SlotState.CONNECTED)
                            {
                                player.Kick("A \"" + otherPlayer.Name + "\" is already on this server.");
                                return;
                            }
                        }
                    }

                    //conn.Queue = (int)loginEvent.Priority; // actual queueing done on world request message

                    // and now decide whether to queue the connection
                    //SlotManager.Schedule (conn, (int)loginEvent.Priority);

                    NetMessage.SendData(4, -1, -1, player.Name, bufferId);
                }
            }

            return;

            //            int num6 = (int)buffer.reader.ReadByte();
            //            if (Main.netMode == 2)
            //            {
            //                num6 = bufferId;
            //            }
            //            if (num6 == Main.myPlayer && !Main.ServerSideCharacter)
            //            {
            //                return;
            //            }
            //            Player player = Main.player[num6];
            //            player.whoAmI = num6;
            //            player.skinVariant = (int)buffer.reader.ReadByte();
            //            player.skinVariant = (int)MathHelper.Clamp((float)player.skinVariant, 0, 7);
            //            player.hair = (int)buffer.reader.ReadByte();
            //            if (player.hair >= 134)
            //            {
            //                player.hair = 0;
            //            }
            //            player.name = buffer.reader.ReadString().Trim().Trim();
            //            player.hairDye = buffer.reader.ReadByte();
            //            BitsByte bitsByte = buffer.reader.ReadByte();
            //            for (int num7 = 0; num7 < 8; num7++)
            //            {
            //                player.hideVisual[num7] = bitsByte[num7];
            //            }
            //            bitsByte = buffer.reader.ReadByte();
            //            for (int num8 = 0; num8 < 2; num8++)
            //            {
            //                player.hideVisual[num8 + 8] = bitsByte[num8];
            //            }
            //            player.hideMisc = buffer.reader.ReadByte();
            //            player.hairColor = buffer.reader.ReadRGB();
            //            player.skinColor = buffer.reader.ReadRGB();
            //            player.eyeColor = buffer.reader.ReadRGB();
            //            player.shirtColor = buffer.reader.ReadRGB();
            //            player.underShirtColor = buffer.reader.ReadRGB();
            //            player.pantsColor = buffer.reader.ReadRGB();
            //            player.shoeColor = buffer.reader.ReadRGB();
            //            BitsByte bitsByte2 = buffer.reader.ReadByte();
            //            player.difficulty = 0;
            //            if (bitsByte2[0])
            //            {
            //                Player expr_B25 = player;
            //                expr_B25.difficulty += 1;
            //            }
            //            if (bitsByte2[1])
            //            {
            //                Player expr_B3F = player;
            //                expr_B3F.difficulty += 2;
            //            }
            //            if (player.difficulty > 2)
            //            {
            //                player.difficulty = 2;
            //            }
            //            player.extraAccessory = bitsByte2[2];
            //            if (Main.netMode != 2)
            //            {
            //                return;
            //            }
            //            bool flag = false;
            //            if (Netplay.Clients[bufferId].State < 10)
            //            {
            //                for (int num9 = 0; num9 < 255; num9++)
            //                {
            //                    if (num9 != num6 && player.name == Main.player[num9].name && Netplay.Clients[num9].IsActive)
            //                    {
            //                        flag = true;
            //                    }
            //                }
            //            }
            //            if (flag)
            //            {
            //                NetMessage.SendData(2, bufferId, -1, player.name + " " + Lang.mp[5], 0, 0, 0, 0, 0, 0, 0);
            //                return;
            //            }
            //            if (player.name.Length > Player.nameLen)
            //            {
            //                NetMessage.SendData(2, bufferId, -1, "Name is too long.", 0, 0, 0, 0, 0, 0, 0);
            //                return;
            //            }
            //            if (player.name == "")
            //            {
            //                NetMessage.SendData(2, bufferId, -1, "Empty name.", 0, 0, 0, 0, 0, 0, 0);
            //                return;
            //            }
            //
            //            var ctx = new HookContext
            //                {
            //                    Connection = player.conn,
            //                    Player = player,
            //                    Sender = player,
            //                };
            //
            //            HookPoints.PlayerDataReceived.Invoke (ref ctx, ref data);
            //
            //            if (ctx.CheckForKick ())
            //                return;
            //
            //            if (! data.NameChecked)
            //            {
            //                string error;
            //                if (! data.CheckName (out error))
            //                {
            //                    conn.Kick (error);
            //                    return;
            //                }
            //            }
            //
            //            if (! data.BansChecked)
            //            {
            //                string address = conn.RemoteAddress.Split(':')[0];
            //
            //                if (Server.BanList.containsException (address) || Server.BanList.containsException (data.Name))
            //                {
            //                    ProgramLog.Admin.Log ("Prevented user {0} from accessing the server.", data.Name);
            //                    conn.Kick ("You are banned from this server.");
            //                    return;
            //                }
            //            }
            //
            //            data.Apply (player);
            //
            //            if (ctx.Result == HookResult.ASK_PASS)
            //            {
            //                conn.State = SlotState.PLAYER_AUTH;
            //
            //                var msg = NetMessage.PrepareThreadInstance ();
            //                msg.PasswordRequest ();
            //                conn.Send (msg.Output);
            //
            //                return;
            //            }
            //            else // HookResult.DEFAULT
            //            {
            //                // don't allow replacing connections for guests, but do for registered users
            //                if (conn.State < SlotState.PLAYING)
            //                {
            //                    var lname = player.Name.ToLower();
            //
            //                    foreach (var otherPlayer in Main.players)
            //                    {
            //                        var otherSlot = NetPlay.slots[otherPlayer.whoAmi];
            //                        if (otherPlayer.Name != null && lname == otherPlayer.Name.ToLower() && otherSlot.state >= SlotState.CONNECTED)
            //                        {
            //                            conn.Kick ("A \"" + otherPlayer.Name + "\" is already on this server.");
            //                            return;
            //                        }
            //                    }
            //                }
            //
            //                //conn.Queue = (int)loginEvent.Priority; // actual queueing done on world request message
            //
            //                // and now decide whether to queue the connection
            //                //SlotManager.Schedule (conn, (int)loginEvent.Priority);
            //
            //                //NetMessage.SendData (4, -1, -1, player.Name, whoAmI);
            //            }
            //
            //            Netplay.Clients[bufferId].Name = player.name;
            //            NetMessage.SendData(4, -1, bufferId, player.name, num6, 0, 0, 0, 0, 0, 0);
        }
        public override void Process(ClientConnection conn, byte[] readBuffer, int length, int num)
        {
            int start = num - 1;

            if (conn.State == SlotState.ASSIGNING_SLOT)
            {
                // TODO: verify that data didn't change.
                int who = conn.SlotIndex;
                NewNetMessage.SendData(4, -1, who, conn.Player.Name, who);
                return;
            }

            //if (conn.Player != null)
            //{
            //    conn.Kick("Player data sent twice.");
            //    return;
            //}

            //var player = new Player();
            var player = conn.Player;
            var connecting = conn.Player == null;
            if (connecting)
            {
                player = new Player();
                conn.Player = player;
                player.Connection = conn;
                player.IPAddress = conn.RemoteAddress;
                player.whoAmi = conn.SlotIndex;
            }

            var data = new HookArgs.PlayerDataReceived()
            {
                IsConnecting = connecting
            };

            var read = data.Parse(readBuffer, num + 1 /* PlayerId */, length);
            Skip(read);

            if (data.Hair >= MAX_HAIR_ID)
            {
                data.Hair = 0;
            }

            var ctx = new HookContext
            {
                Connection = conn,
                Player = player,
                Sender = player,
            };

            HookPoints.PlayerDataReceived.Invoke(ref ctx, ref data);

            if (ctx.CheckForKick())
                return;

            if (!data.NameChecked)
            {
                string error;
                if (!data.CheckName(out error))
                {
                    conn.Kick(error);
                    return;
                }
            }

            string address = conn.RemoteAddress.Split(':')[0];
            if (!data.BansChecked)
            {
                if (Server.Bans.Contains(address) || Server.Bans.Contains(data.Name))
                {
                    ProgramLog.Admin.Log("Prevented banned user {0} from accessing the server.", data.Name);
                    conn.Kick("You are banned from this server.");
                    return;
                }
            }

            if (!data.WhitelistChecked && Server.WhitelistEnabled)
            {
                if (!Server.Whitelist.Contains(address) && !Server.Whitelist.Contains(data.Name))
                {
                    ProgramLog.Admin.Log("Prevented non whitelisted user {0} from accessing the server.", data.Name);
                    conn.Kick("You do not have access to this server.");
                    return;
                }
            }

            data.Apply(player);

            if (connecting)
                if (ctx.Result == HookResult.ASK_PASS)
                {
                    conn.State = SlotState.PLAYER_AUTH;

                    var msg = NewNetMessage.PrepareThreadInstance();
                    msg.PasswordRequest();
                    conn.Send(msg.Output);

                    return;
                }
                else // HookResult.DEFAULT
                {
                    // don't allow replacing connections for guests, but do for registered users
                    if (conn.State < SlotState.PLAYING)
                    {
                        var lname = player.Name.ToLower();

                        foreach (var otherPlayer in Main.player)
                        {
                            var otherSlot = Terraria.Netplay.Clients[otherPlayer.whoAmi];
                            if (otherPlayer.Name != null && lname == otherPlayer.Name.ToLower() && otherSlot.State() >= SlotState.CONNECTED)
                            {
                                conn.Kick("A \"" + otherPlayer.Name + "\" is already on this server.");
                                return;
                            }
                        }
                    }

                    //conn.Queue = (int)loginEvent.Priority; // actual queueing done on world request message

                    // and now decide whether to queue the connection
                    //SlotManager.Schedule (conn, (int)loginEvent.Priority);

                    //NewNetMessage.SendData (4, -1, -1, player.Name, whoAmI);
                }

            //int num3 = (int)ReadByte(readBuffer);
            //if (Main.netMode == 2)
            //{
            //    num3 = this.whoAmI;
            //}
            //if (num3 == Main.myPlayer && !Main.ServerSideCharacter)
            //{
            //    return;
            //}
            //Player player2 = Main.player[num3];
            //player2.whoAmi = num3;
            //if (ReadByte() == 0)
            //{
            //    player2.male = true;
            //}
            //else
            //{
            //    player2.male = false;
            //}
            //player2.hair = (int)ReadByte(readBuffer);
            //if (player2.hair >= 123)
            //{
            //    player2.hair = 0;
            //}
            //player2.name = ReadString().Trim();
            //player2.hairDye = ReadByte(readBuffer);
            //player2.hideVisual = ReadByte(readBuffer);
            //player2.hairColor = ReadRGB();
            //player2.skinColor = ReadRGB();
            //player2.eyeColor = ReadRGB();
            //player2.shirtColor = ReadRGB();
            //player2.underShirtColor = ReadRGB();
            //player2.pantsColor = ReadRGB();
            //player2.shoeColor = ReadRGB();
            //player2.difficulty = ReadByte(readBuffer);
            //if (Main.netMode != 2)
            //{
            //    return;
            //}
            //bool flag = false;
            //if (tdsm.api.Callbacks.Netplay.slots[this.whoAmI].state < 10)
            //{
            //    for (int n = 0; n < 255; n++)
            //    {
            //        if (n != num3 && player2.name == Main.player[n].name && tdsm.api.Callbacks.Netplay.slots[n].active)
            //        {
            //            flag = true;
            //        }
            //    }
            //}
            //if (flag)
            //{
            //    NewNetMessage.SendData(2, this.whoAmI, -1, player2.name + " " + Lang.mp[5], 0, 0f, 0f, 0f, 0);
            //    return;
            //}
            //if (player2.name.Length > Player.nameLen)
            //{
            //    NewNetMessage.SendData(2, this.whoAmI, -1, "Name is too long.", 0, 0f, 0f, 0f, 0);
            //    return;
            //}
            //if (player2.name == String.Empty)
            //{
            //    NewNetMessage.SendData(2, this.whoAmI, -1, "Empty name.", 0, 0f, 0f, 0f, 0);
            //    return;
            //}
            //tdsm.api.Callbacks.Netplay.slots[this.whoAmI].oldName = player2.name;
            //tdsm.api.Callbacks.Netplay.slots[this.whoAmI].name = player2.name;
            //NewNetMessage.SendData(4, -1, this.whoAmI, player2.name, num3, 0f, 0f, 0f, 0);
            //return;
        }