public static bool OnGreetPlayer(int playerId)
        {
            var player = Main.player[playerId];

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

            var args = new HookArgs.PlayerPreGreeting
            {
                Slot = playerId,
                Motd = String.IsNullOrEmpty(Main.motd) ? (Lang.mp[18] + " " + Main.worldName) : Main.motd,
                MotdColour = new Microsoft.Xna.Framework.Color(255, 240, 20)
            };

            HookPoints.PlayerPreGreeting.Invoke(ref ctx, ref args);

            if (ctx.CheckForKick())
            {
                return false;
            }

            player.SendMessage(args.Motd, 255, args.MotdColour.R, args.MotdColour.G, args.MotdColour.B);

            string list = "";
            for (int i = 0; i < 255; i++)
            {
                if (Main.player[i].active)
                {
                    if (list == "")
                        list += Main.player[i].name;
                    else
                        list = list + ", " + Main.player[i].Name;
                }
            }

            player.SendMessage("Current players: " + list + ".", 255, 255, 240, 20);

            Tools.WriteLine("{0} @ {1}: ENTER {2}", Netplay.Clients[playerId].Socket.GetRemoteAddress(), playerId, player.name);

            var args2 = new HookArgs.PlayerEnteredGame
            {
                Slot = playerId
            };

            ctx.SetResult(HookResult.DEFAULT, false);
            HookPoints.PlayerEnteredGame.Invoke(ref ctx, ref args2);
            ctx.CheckForKick();

            return false; //We implemented our own, so do not continue on with vanilla
        }
        public ClientConnection(Socket sock)
            : base(sock)
        {
            if (SlotId == 0)
                SlotId = -1;

            var remoteEndPoint = (IPEndPoint)sock.RemoteEndPoint;
            _remoteAddress = new TcpAddress(remoteEndPoint.Address, remoteEndPoint.Port);

            sock.LingerState = new LingerOption(true, 10);

            var ctx = new HookContext
            {
                Connection = this
            };

            var args = new HookArgs.NewConnection();

            HookPoints.NewConnection.Invoke(ref ctx, ref args);

            if (ctx.CheckForKick())
                return;

            _isReceiving = true; //The connection was established, so we can begin reading
        }
        public override void Process(ClientConnection conn, byte[] readBuffer, int length, int num)
        {
            //var data = Encoding.ASCII.GetString (readBuffer, num, length - 1);
            //var lines = data.Split ('\n');

            //foreach (var line in lines)
            //{
            //    if (line == "tdcm1")
            //    {
            //        //player.HasClientMod = true;
            //        ProgramLog.Log ("{0} is a TDCM protocol version 1 client.", conn.RemoteAddress);
            //    }
            //    else if (line == "tdsmcomp1")
            //    {
            //        conn.CompressionVersion = 1;
            //        ProgramLog.Log ("{0} supports TDSM compression version 1.", conn.RemoteAddress);
            //    }
            //}

            ReadString(readBuffer);

            var ctx = new HookContext
            {
                Connection = conn,
            };

            var args = new HookArgs.DisconnectReceived
            {
            };

            HookPoints.DisconnectReceived.Invoke(ref ctx, ref args);

            ctx.CheckForKick();
        }
        public ClientConnection(Socket socket, int slot)
            : base(socket)
        {
            //var buf = NewNetMessage.buffer[id];
            //socket.SendBufferSize = 128000;
            connectedAt = time.Elapsed;

            if (slot >= 0) AssignSlot(slot);

            socket.LingerState = new LingerOption(true, 10);

            var ctx = new HookContext
            {
                Connection = this
            };

            var args = new HookArgs.NewConnection();

            HookPoints.NewConnection.Invoke(ref ctx, ref args);

            if (ctx.CheckForKick())
                return;

            lock (All)
            {
                indexInAll = All.Count;
                All.Add(this);
            }

            StartReceiving(new byte[4192]);
        }
        public override void Process(int whoAmI, byte[] readBuffer, int length, int num)
        {
            //TODO [KillProjectileReceived]

            int identity = (int)ReadInt16(readBuffer);
            int playerId = (int)ReadByte(readBuffer);

            if (playerId != whoAmI && Entry.EnableCheatProtection)
            {
                Terraria.Netplay.Clients[whoAmI].Kick("Cheating detected (KILL_PROJECTILE forgery).");
                return;
            }

            var index = Tools.FindExistingProjectileForUser(whoAmI, identity);
            if (index == -1) return;

            var player = Main.player[whoAmI];

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

            var args = new HookArgs.KillProjectileReceived
            {
                Id = identity,
                Owner = whoAmI,
                Index = index,
            };

            HookPoints.KillProjectileReceived.Invoke(ref ctx, ref args);

            if (ctx.CheckForKick())
            {
                return;
            }

            if (ctx.Result == HookResult.IGNORE)
            {
                return;
            }

            if (ctx.Result == HookResult.RECTIFY)
            {
                var msg = NewNetMessage.PrepareThreadInstance();
                msg.Projectile(Main.projectile[index]);
                msg.Send(whoAmI);
                return;
            }

            var projectile = Main.projectile[index];

            if (projectile.owner == whoAmI && projectile.identity == identity)
            {
                projectile.Kill();
                NewNetMessage.SendData(29, -1, whoAmI, String.Empty, identity, (float)whoAmI);
            }
        }
        public override void Process(int whoAmI, byte[] readBuffer, int length, int num)
        {
            int x = ReadInt16(readBuffer);
            int y = ReadInt16(readBuffer);

            var player = Main.player[whoAmI];

            if (Math.Abs(player.position.X / 16 - x) >= 7 || Math.Abs(player.position.Y / 16 - y) >= 7)
            {
                return;
            }

            int chestIndex = Chest.FindChest(x, y);

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

            var args = new HookArgs.ChestOpenReceived
            {
                X = x,
                Y = y,
                ChestIndex = chestIndex,
            };

            HookPoints.ChestOpenReceived.Invoke(ref ctx, ref args);

            if (ctx.CheckForKick())
            {
                return;
            }

            if (ctx.Result == HookResult.IGNORE)
            {
                return;
            }

            if (ctx.Result == HookResult.DEFAULT && chestIndex > -1)
            {
                var user = Chest.UsingChest(chestIndex);
                if (user >= 0 && user != whoAmI) return;

                for (int i = 0; i < Chest.maxItems; i++)
                {
                    NewNetMessage.SendData(32, whoAmI, -1, String.Empty, chestIndex, (float)i);
                }
                NewNetMessage.SendData(33, whoAmI, -1, String.Empty, chestIndex);
                Main.player[whoAmI].chest = chestIndex;
                return;
            }
        }
        public override void Process(int whoAmI, byte[] readBuffer, int length, int num)
        {
            int playerIndex = ReadByte(readBuffer);

            if (playerIndex != whoAmI && Entry.EnableCheatProtection)
            {
                Terraria.Netplay.Clients[whoAmI].Kick("Cheating detected (PLAYER_PVP_CHANGE forgery).");
                return;
            }

            var pvp = ReadByte(readBuffer) == 1;
            var player = Main.player[whoAmI];

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

            var args = new HookArgs.PvpSettingReceived
            {
                PvpFlag = pvp,
            };

            HookPoints.PvpSettingReceived.Invoke(ref ctx, ref args);

            if (ctx.CheckForKick())
            {
                return;
            }

            if (ctx.Result == HookResult.IGNORE)
            {
                return;
            }

            if (ctx.Result == HookResult.RECTIFY)
            {
                NewNetMessage.SendData(30, whoAmI, -1, String.Empty, whoAmI);
                return;
            }

            player.hostile = pvp;

            string message = (player.hostile) ? " has enabled PvP!" : " has disabled PvP!";

            NewNetMessage.SendData(30, -1, whoAmI, String.Empty, whoAmI);
            NewNetMessage.SendData(25, -1, -1, player.Name + message, 255, (float)Main.teamColor[player.team].R, (float)Main.teamColor[player.team].G, (float)Main.teamColor[player.team].B);
        }
        public override void Process(int whoAmI, byte[] readBuffer, int length, int num)
        {
            int start = num - 1;
            int playerIndex = ReadByte(readBuffer);

            if (playerIndex != whoAmI && Entry.EnableCheatProtection)
            {
                Terraria.Netplay.Clients[whoAmI].Kick("Cheating detected (KILL_PLAYER forgery).");
                return;
            }

            var player = Main.player[whoAmI];

            var ctx = new HookContext
            {
                Connection = (Terraria.Netplay.Clients[whoAmI] as ServerSlot).conn,
                Sender = player,
                Player = player,
            };

            var args = new HookArgs.ObituaryReceived
            {
                Direction = (int)ReadByte(readBuffer) - 1,
                Damage = ReadInt16(readBuffer),
                PvpFlag = ReadByte(readBuffer)
            };
            //string obituary;
            //if (!ParseString(readBuffer, num + 1, length - num - 1 + start, out obituary))
            //{
            //    tdsm.api.Callbacks.Netplay.slots[whoAmI].Kick("Invalid characters in obituary message.");
            //    return;
            //}
            args.Obituary = " " + ReadString(readBuffer);

            HookPoints.ObituaryReceived.Invoke(ref ctx, ref args);

            if (ctx.CheckForKick())
                return;

            if (ctx.Result == HookResult.IGNORE)
                return;

            ProgramLog.Log("{0} @ {1}: [Death] {2}{3}", player.IPAddress, whoAmI, player.Name ?? "<null>", args.Obituary);

            player.KillMe(args.Damage, args.Direction, args.PvpFlag == 1, args.Obituary);

            NewNetMessage.SendData(44, -1, whoAmI, args.Obituary, whoAmI, args.Direction, args.Damage, args.PvpFlag);
        }
        public static void OnPlayerEntering(Player player)
        {
            var ctx = new HookContext
            {
                Player = player,
                Sender = player
            };

            var args = new HookArgs.PlayerEnteringGame
            {
                Slot = player.whoAmI
            };

            ctx.SetResult(HookResult.DEFAULT, false);
            HookPoints.PlayerEnteringGame.Invoke(ref ctx, ref args);
            ctx.CheckForKick();
        }
        //TODO: redesign signs
        public override void Process(int whoAmI, byte[] readBuffer, int length, int num)
        {
            int start = num - 1;
            short signIndex = ReadInt16(readBuffer);
            int x = ReadInt16(readBuffer);
            int y = ReadInt16(readBuffer);

            short existing = (short)Sign.ReadSign(x, y);
            if (existing >= 0)
                signIndex = existing;

            //string SignText;
            //if (!ParseString(readBuffer, num, length - num + start, out SignText))
            //    return; // invalid characters
            var SignText = ReadString(readBuffer);

            var player = Main.player[whoAmI];

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

            var args = new HookArgs.SignTextSet
            {
                X = x,
                Y = y,
                SignIndex = signIndex,
                Text = SignText,
                OldSign = Main.sign[signIndex],
            };

            HookPoints.SignTextSet.Invoke(ref ctx, ref args);

            if (ctx.CheckForKick() || ctx.Result == HookResult.IGNORE)
                return;

            if (Main.sign[signIndex] == null) Main.sign[signIndex] = new Sign();
            Main.sign[signIndex].x = args.X;
            Main.sign[signIndex].y = args.Y;
            Sign.TextSign(signIndex, args.Text);
        }
        public override void Process(int whoAmI, byte[] readBuffer, int length, int num)
        {
            int playerId = ReadByte(readBuffer);
            byte action = ReadByte(readBuffer);

            if (playerId != whoAmI && Entry.EnableCheatProtection)
            {
                Terraria.Netplay.Clients[whoAmI].Kick("SummonSkeletron Player Forgery.");
                return;
            }

            if (action == 1)
            {
                var player = Main.player[whoAmI];

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

                var args = new HookArgs.PlayerTriggeredEvent
                {
                    Type = WorldEventType.BOSS,
                    Name = "Skeletron",
                };

                HookPoints.PlayerTriggeredEvent.Invoke(ref ctx, ref args);

                if (ctx.CheckForKick() || ctx.Result == HookResult.IGNORE)
                    return;

                //ProgramLog.Users.Log ("{0} @ {1}: Skeletron summoned by {2}.", player.IPAddress, whoAmI, player.Name);
                //NewNetMessage.SendData (Packet.PLAYER_CHAT, -1, -1, string.Concat (player.Name, " has summoned Skeletron!"), 255, 255, 128, 150);
                NPC.SpawnSkeletron();
            }
            else if (action == 2)
            {
                NewNetMessage.SendData(51, -1, whoAmI, String.Empty, playerId, action, 0f, 0f, 0);
            }
        }
        public override void Process(int whoAmI, byte[] readBuffer, int length, int num)
        {
            int x = (int)ReadInt16(readBuffer);
            int y = (int)ReadInt16(readBuffer);

            int signIndex = Sign.ReadSign(x, y);

            var player = Main.player[whoAmI];

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

            var args = new HookArgs.SignTextGet
            {
                X = x,
                Y = y,
                SignIndex = (short)signIndex,
                Text = (signIndex >= 0 && Main.sign[signIndex] != null) ? Main.sign[signIndex].text : null,
            };

            HookPoints.SignTextGet.Invoke(ref ctx, ref args);

            if (ctx.CheckForKick() || ctx.Result == HookResult.IGNORE)
                return;

            if (args.Text != null)
            {
                var msg = NewNetMessage.PrepareThreadInstance();
                msg.WriteSign(signIndex, x, y, args.Text);
                msg.Send(whoAmI);
            }
        }
        private static void ProcessLiquidFlow(int bufferId)
        {
            var buffer = NetMessage.buffer[bufferId];
            var player = Main.player[bufferId];

            int x = (int)buffer.reader.ReadInt16();
            int y = (int)buffer.reader.ReadInt16();
            byte liquid = buffer.reader.ReadByte();
            byte liquidType = buffer.reader.ReadByte();

            if (Main.netMode == 2 && Netplay.spamCheck)
            {
                int centerX = (int)(Main.player[bufferId].position.X + (float)(Main.player[bufferId].width / 2));
                int centerY = (int)(Main.player[bufferId].position.Y + (float)(Main.player[bufferId].height / 2));
                int range = 10;
                int minX = centerX - range;
                int maxX = centerX + range;
                int minY = centerY - range;
                int maxY = centerY + range;
                if (x < minX || x > maxX || y < minY || y > maxY)
                {
                    NetMessage.BootPlayer(bufferId, "Cheating attempt detected: Liquid spam");
                    return;
                }
            }

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

            var args = new HookArgs.LiquidFlowReceived
            {
                X = x,
                Y = y,
                Amount = liquid,
                Lava = liquidType == 1
            };

            HookPoints.LiquidFlowReceived.Invoke(ref ctx, ref args);

            if (ctx.CheckForKick())
                return;

            if (ctx.Result == HookResult.IGNORE)
                return;

            if (ctx.Result == HookResult.RECTIFY)
            {
            //                var msg = NewNetMessage.PrepareThreadInstance();
            //                msg.FlowLiquid(x, y);
            //                msg.Send(whoAmI);
                Terraria.NetMessage.SendData((int)Packet.FLOW_LIQUID, bufferId, -1, String.Empty, x, y);
                return;
            }

            if (Main.tile[x, y] == null)
            {
                Main.tile[x, y] = new Tile();
            }
            lock (Main.tile [x, y])
            {
                Main.tile[x, y].liquid = liquid;
                Main.tile[x, y].liquidType((int)liquidType);
                if (Main.netMode == 2)
                {
                    WorldGen.SquareTileFrame(x, y, true);
                }
                return;
            }
        }
        public override void Process(int whoAmI, byte[] readBuffer, int length, int num)
        {
            if (ReadByte(readBuffer) != whoAmI && Entry.EnableCheatProtection)
            {
                Terraria.Netplay.Clients[whoAmI].Kick("Cheating detected (PLAYER_STATE_UPDATE forgery).");
                return;
            }
            var player = Main.player[whoAmI];

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

            var args = new HookArgs.StateUpdateReceived();

            args.Parse(readBuffer, num + 1);

            HookPoints.StateUpdateReceived.Invoke(ref ctx, ref args);

            if (ctx.CheckForKick())
                return;

            //Player player5 = Main.player[whoAmI];
            //BitsByte bitsByte4 = ReadByte(readBuffer);
            //player5.controlUp = bitsByte4[0];
            //player5.controlDown = bitsByte4[1];
            //player5.controlLeft = bitsByte4[2];
            //player5.controlRight = bitsByte4[3];
            //player5.controlJump = bitsByte4[4];
            //player5.controlUseItem = bitsByte4[5];
            //player5.direction = (bitsByte4[6] ? 1 : -1);
            //BitsByte bitsByte5 = ReadByte(readBuffer);
            //if (bitsByte5[0])
            //{
            //    player5.pulley = true;
            //    player5.pulleyDir = (byte)(bitsByte5[1] ? 2 : 1);
            //}
            //else
            //{
            //    player5.pulley = false;
            //}
            //player5.selectedItem = (int)ReadByte(readBuffer);
            //player5.position = ReadVector2(readBuffer);
            //if (bitsByte5[2])
            //{
            //    player5.velocity = ReadVector2(readBuffer);
            //}
            //if (Main.netMode == 2 && tdsm.api.Callbacks.Netplay.slots[whoAmI].state == SlotState.PLAYING)
            //{
            //    NewNetMessage.SendData(13, -1, whoAmI, String.Empty, whoAmI, 0f, 0f, 0f, 0);
            //    return;
            //}

            args.ApplyParams(player);
            args.ApplyKeys(player);

            if (Terraria.Netplay.Clients[whoAmI].IsPlaying())
            {
                NewNetMessage.SendData(13, -1, whoAmI, String.Empty, whoAmI);
            }
        }
        public override void Process(int whoAmI, byte[] readBuffer, int length, int num)
        {
            int playerIndex = ReadByte(readBuffer);

            if (playerIndex != whoAmI && Entry.EnableCheatProtection)
            {
                Terraria.Netplay.Clients[whoAmI].Kick("Cheating detected (INVENTORY_DATA forgery).");
                return;
            }

            //TODO Implement the item banning

            if (playerIndex == Main.myPlayer && !Main.ServerSideCharacter)
                return;

            var player = Main.player[whoAmI];

            var ctx = new HookContext
            {
                Connection = (Terraria.Netplay.Clients[whoAmI] as ServerSlot).conn,
                Sender = player,
                Player = player
            };

            var args = new HookArgs.InventoryItemReceived
            {
                InventorySlot = (int)ReadByte(readBuffer),
                Amount = (int)ReadInt16(readBuffer),
                Prefix = (int)ReadByte(readBuffer),
                NetID = (int)ReadInt16(readBuffer),
                //Name = Networking.StringCache.FindOrMake (new ArraySegment<Byte> (readBuffer, num, length - 4)),
            };
            args.SetItem();

            HookPoints.InventoryItemReceived.Invoke(ref ctx, ref args);

            if (ctx.CheckForKick())
                return;

            if (ctx.Result == HookResult.IGNORE)
                return;

            lock (player)
            {
                if (args.InventorySlot < 59)
                {
                    player.inventory[args.InventorySlot] = new Item();
                    player.inventory[args.InventorySlot].netDefaults(args.NetID);
                    player.inventory[args.InventorySlot].stack = args.Amount;
                    player.inventory[args.InventorySlot].Prefix(args.Prefix);
                    if (playerIndex == Main.myPlayer && args.InventorySlot == 58)
                    {
                        Main.mouseItem = player.inventory[args.InventorySlot].Clone();
                    }
                }
                else
                {
                    if (args.InventorySlot >= 75 && args.InventorySlot <= 82)
                    {
                        int num7 = args.InventorySlot - 58 - 17;
                        player.dye[num7] = new Item();
                        player.dye[num7].netDefaults(args.NetID);
                        player.dye[num7].stack = args.Amount;
                        player.dye[num7].Prefix(args.Prefix);
                    }
                    else
                    {
                        int num8 = args.InventorySlot - 58 - 1;
                        player.armor[num8] = new Item();
                        player.armor[num8].netDefaults(args.NetID);
                        player.armor[num8].stack = args.Amount;
                        player.armor[num8].Prefix(args.Prefix);
                    }
                }

                if (playerIndex == whoAmI)
                {
                    NewNetMessage.SendData((int)Packet.INVENTORY_DATA, -1, whoAmI, String.Empty, playerIndex, (float)args.InventorySlot, (float)args.Prefix, 0f, 0);
                }
                return;
            }
        }
        private static void ProcessChat(int bufferId)
        {
            var buffer = NetMessage.buffer[bufferId];

            //Discard
            buffer.reader.ReadByte();
            buffer.reader.ReadRGB();

            var chatText = buffer.reader.ReadString();

            var player = Main.player[bufferId];
            var color = Color.White;

            if (Main.netMode != 2)
                return;

            var lowered = chatText.ToLower();
            if (lowered == Lang.mp[6] || lowered == Lang.mp[21])
            {
                var players = "";
                for (int i = 0; i < 255; i++)
                {
                    if (Main.player[i].active)
                    {
                        if (players.Length > 0)
                            players += ", ";
                        players += Main.player[i].name;
                    }
                }
                NetMessage.SendData(25, bufferId, -1, Lang.mp[7] + " " + players + ".", 255, 255, 240, 20, 0, 0, 0);
                return;
            }
            else if (lowered.StartsWith("/me "))
            {
                NetMessage.SendData(25, -1, -1, "*" + Main.player[bufferId].name + " " + chatText.Substring(4), 255, 200, 100, 0, 0, 0, 0);
                return;
            }
            else if (lowered == Lang.mp[8])
            {
                NetMessage.SendData(25, -1, -1, string.Concat(new object[]
                        {
                            "*",
                            Main.player[bufferId].name,
                            " ",
                            Lang.mp[9],
                            " ",
                            Main.rand.Next(1, 101)
                        }), 255, 255, 240, 20, 0, 0, 0);
                return;
            }
            else if (lowered.StartsWith("/p "))
            {
                int team = Main.player[bufferId].team;
                color = Main.teamColor[team];
                if (team != 0)
                {
                    for (int num74 = 0; num74 < 255; num74++)
                    {
                        if (Main.player[num74].team == team)
                        {
                            NetMessage.SendData(25, num74, -1, chatText.Substring(3), bufferId, (float)color.R, (float)color.G, (float)color.B, 0, 0, 0);
                        }
                    }
                    return;
                }
                NetMessage.SendData(25, bufferId, -1, Lang.mp[10], 255, 255, 240, 20, 0, 0, 0);
                return;
            }
            else
            {
                if (Main.player[bufferId].difficulty == 2)
                    color = Main.hcColor;
                else if (Main.player[bufferId].difficulty == 1)
                    color = Main.mcColor;

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

                var args = new HookArgs.PlayerChat
                {
                    Message = chatText,
                    Color = color
                };

                HookPoints.PlayerChat.Invoke(ref ctx, ref args);

                if (ctx.CheckForKick() || ctx.Result == HookResult.IGNORE)
                    return;

                NetMessage.SendData(25, -1, -1, chatText, bufferId, (float)color.R, (float)color.G, (float)color.B, 0, 0, 0);
                if (Main.dedServ)
                {
                    Tools.WriteLine("<" + Main.player[bufferId].name + "> " + chatText);
                }
            }
        }
        public override void Process(ClientConnection conn, byte[] readBuffer, int length, int num)
        {
            int start = num - 1;
            //string password = Encoding.ASCII.GetString(readBuffer, num, length - num + start);
            var password = ReadString(readBuffer);

            if (conn.State == SlotState.SERVER_AUTH)
            {
                var ctx = new HookContext
                {
                    Connection = conn,
                };

                var args = new HookArgs.ServerPassReceived
                {
                    Password = password
                };

                HookPoints.ServerPassReceived.Invoke(ref ctx, ref args);

                if (ctx.CheckForKick())
                    return;

                if (ctx.Result == HookResult.ASK_PASS)
                {
                    var msg = NewNetMessage.PrepareThreadInstance();
                    msg.PasswordRequest();
                    conn.Send(msg.Output);
                }
                else if (ctx.Result == HookResult.CONTINUE || password == Netplay.password)
                {
                    conn.State = SlotState.ACCEPTED;

                    var msg = NewNetMessage.PrepareThreadInstance();
                    msg.ConnectionResponse(253 /* dummy value, real slot assigned later */);
                    conn.Send(msg.Output);

                    return;
                }

                conn.Kick("Incorrect server password.");
            }
            else if (conn.State == SlotState.PLAYER_AUTH)
            {
                var name = conn.Player.Name ?? String.Empty;

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

                var args = new HookArgs.PlayerPassReceived
                {
                    Password = password,
                };

                HookPoints.PlayerPassReceived.Invoke(ref ctx, ref args);

                if (ctx.CheckForKick())
                    return;

                if (ctx.Result == HookResult.ASK_PASS)
                {
                    var msg = NewNetMessage.PrepareThreadInstance();
                    msg.PasswordRequest();
                    conn.Send(msg.Output);
                }
                else // HookResult.DEFAULT
                {
                    var lower = name.ToLower();
                    bool reserved = false;

                    //conn.Queue = (int)loginEvent.Priority;

                    foreach (var otherPlayer in Main.player)
                    {
                        //var otherSlot = Netplay.slots[otherPlayer.whoAmi];
                        var otherConn = otherPlayer.Connection;
                        if (otherPlayer.Name != null
                            && lower == otherPlayer.Name.ToLower()
                            && (otherConn as ClientConnection) != null
                            && (otherConn as ClientConnection).HasConnected())
                        {
                            if (!reserved)
                            {
                                reserved = SlotManager.HandoverSlot(otherConn, conn);
                            }
                            otherConn.Kick("Replaced by new connection.");
                        }
                    }

                    //conn.State = SlotState.SENDING_WORLD;

                    if (!reserved) // reserved slots get assigned immediately during the kick
                    {
                        SlotManager.Schedule(conn, conn.DesiredQueue);
                    }

                    //NewNetMessage.SendData (4, -1, whoAmI, name, whoAmI); // broadcast player data now

                    // replay packets from side buffer
                    //conn.conn.ProcessSideBuffer ();
                    //var buf = NewNetMessage.buffer[whoAmI];
                    //NewNetMessage.CheckBytes (whoAmI, buf.sideBuffer, ref buf.sideBufferBytes, ref buf.sideBufferMsgLen);
                    //buf.ResetSideBuffer ();

                    //NewNetMessage.SendData (7, whoAmI); // continue with world data
                }
            }
        }
        private static void ProcessReadSign(int bufferId)
        {
            var buffer = NetMessage.buffer[bufferId];
            var player = Main.player[bufferId];

            if (Main.netMode != 2)
            {
                return;
            }
            int x = (int)buffer.reader.ReadInt16();
            int y = (int)buffer.reader.ReadInt16();
            int id = Sign.ReadSign(x, y, true);

            if (id >= 0)
            {
                var ctx = new HookContext
                {
                    Connection = player.Connection.Socket,
                    Sender = player,
                    Player = player
                };

                var args = new HookArgs.SignTextGet
                {
                    X = x,
                    Y = y,
                    SignIndex = (short)id,
                    Text = (id >= 0 && Main.sign[id] != null) ? Main.sign[id].text : null,
                };

                HookPoints.SignTextGet.Invoke(ref ctx, ref args);

                if (ctx.CheckForKick() || ctx.Result == HookResult.IGNORE)
                    return;

                if (args.Text != null)
                {
                    NetMessage.SendData(47, bufferId, -1, "", id, (float)bufferId, 0, 0, 0, 0, 0);
                    return;
                }
            }
        }
        private static void ProcessTileBreak(int bufferId)
        {
            var buffer = NetMessage.buffer[bufferId];

            byte action = buffer.reader.ReadByte();
            int x = (int)buffer.reader.ReadInt16();
            int y = (int)buffer.reader.ReadInt16();
            short type = buffer.reader.ReadInt16();
            int style = (int)buffer.reader.ReadByte();
            bool fail = type == 1;

            if (!WorldGen.InWorld(x, y, 3))
            {
                return;
            }

            var player = Main.player[bufferId];

            //TODO implement the old methods
            var ctx = new HookContext
            {
                Connection = player.Connection,
                Sender = player,
                Player = player,
            };

            var args = new HookArgs.PlayerWorldAlteration
            {
                X = x,
                Y = y,
                Action = action,
                Type = type,
                Style = style
            };

            HookPoints.PlayerWorldAlteration.Invoke(ref ctx, ref args);

            if (ctx.CheckForKick())
                return;

            if (ctx.Result == HookResult.IGNORE)
                return;

            if (ctx.Result == HookResult.RECTIFY)
            {
                //Terraria.WorldGen.SquareTileFrame (x, y, true);
                NetMessage.SendTileSquare(bufferId, x, y, 1);
                return;
            }

            if (Main.tile[x, y] == null)
            {
                Main.tile[x, y] = new Tile();
            }

            if (Main.netMode == 2)
            {
                if (!fail)
                {
                    if (action == 0 || action == 2 || action == 4)
                    {
                        Netplay.Clients[bufferId].SpamDeleteBlock += 1;
                    }
                    if (action == 1 || action == 3)
                    {
                        Netplay.Clients[bufferId].SpamAddBlock += 1;
                    }
                }
                if (!Netplay.Clients[bufferId].TileSections[Netplay.GetSectionX(x), Netplay.GetSectionY(y)])
                {
                    fail = true;
                }
            }
            if (action == 0)
            {
                WorldGen.KillTile(x, y, fail, false, false);
            }
            if (action == 1)
            {
                WorldGen.PlaceTile(x, y, (int)type, false, true, -1, style);
            }
            if (action == 2)
            {
                WorldGen.KillWall(x, y, fail);
            }
            if (action == 3)
            {
                WorldGen.PlaceWall(x, y, (int)type, false);
            }
            if (action == 4)
            {
                WorldGen.KillTile(x, y, fail, false, true);
            }
            if (action == 5)
            {
                WorldGen.PlaceWire(x, y);
            }
            if (action == 6)
            {
                WorldGen.KillWire(x, y);
            }
            if (action == 7)
            {
                WorldGen.PoundTile(x, y);
            }
            if (action == 8)
            {
                WorldGen.PlaceActuator(x, y);
            }
            if (action == 9)
            {
                WorldGen.KillActuator(x, y);
            }
            if (action == 10)
            {
                WorldGen.PlaceWire2(x, y);
            }
            if (action == 11)
            {
                WorldGen.KillWire2(x, y);
            }
            if (action == 12)
            {
                WorldGen.PlaceWire3(x, y);
            }
            if (action == 13)
            {
                WorldGen.KillWire3(x, y);
            }
            if (action == 14)
            {
                WorldGen.SlopeTile(x, y, (int)type);
            }
            if (action == 15)
            {
                Minecart.FrameTrack(x, y, true, false);
            }
            if (Main.netMode != 2)
            {
                return;
            }
            NetMessage.SendData(17, -1, bufferId, "", (int)action, (float)x, (float)y, (float)type, style, 0, 0);
            if (action == 1 && type == 53)
            {
                NetMessage.SendTileSquare(-1, x, y, 1);
            }
        }
        public override void Process(int whoAmI, byte[] readBuffer, int length, int num)
        {
            byte method = ReadByte(readBuffer);
            int x = (int)ReadInt16(readBuffer);
            int y = (int)ReadInt16(readBuffer);
            int type = (int)ReadInt16(readBuffer);

            var player = Main.player[whoAmI];

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

            var args = new HookArgs.ChestBreakReceived
            {
                X = x,
                Y = y
            };

            HookPoints.ChestBreakReceived.Invoke(ref ctx, ref args);

            if (ctx.CheckForKick())
            {
                return;
            }

            if (ctx.Result == HookResult.IGNORE)
            {
                return;
            }

            if (ctx.Result == HookResult.RECTIFY)
            {
                NewNetMessage.SendTileSquare(whoAmI, x, y, 3);
                return;
            }

            {
                if (method == 0)
                {
                    int num92 = WorldGen.PlaceChest(x, y, 21, false, type);
                    if (num92 == -1)
                    {
                        NewNetMessage.SendData(34, whoAmI, -1, String.Empty, (int)method, (float)x, (float)y, (float)type, num92);
                        Item.NewItem(x * 16, y * 16, 32, 32, Chest.itemSpawn[type], 1, true, 0, false);
                        return;
                    }
                    NewNetMessage.SendData(34, -1, -1, String.Empty, (int)method, (float)x, (float)y, (float)type, num92);
                    return;
                }
                else
                {
                    Tile tile2 = Main.tile[x, y];
                    if (tile2.type != 21)
                    {
                        return;
                    }
                    if (tile2.frameX % 36 != 0)
                    {
                        x--;
                    }
                    if (tile2.frameY % 36 != 0)
                    {
                        y--;
                    }
                    int number = Chest.FindChest(x, y);
                    WorldGen.KillTile(x, y, false, false, false);
                    if (!tile2.active())
                    {
                        NewNetMessage.SendData(34, -1, -1, String.Empty, (int)method, (float)x, (float)y, 0f, number);
                        return;
                    }
                    return;
                }
            }
        }
        //        static long sameTiles = 0;
        //        static long diffTiles = 0;
        public override void Process(int whoAmI, byte[] readBuffer, int length, int num)
        {
            short size = ReadInt16(readBuffer);
            int startX = (int)ReadInt16(readBuffer);
            int startY = (int)ReadInt16(readBuffer);

            //TODO implement the old methods
            var player = Main.player[whoAmI];

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

            var args = new HookArgs.TileSquareReceived
            {
                X = startX,
                Y = startY,
                Size = size,
                readBuffer = readBuffer,
                start = num,
            };

            HookPoints.TileSquareReceived.Invoke(ref ctx, ref args);

            if (args.applied > 0)
            {
                WorldGen.RangeFrame(startX, startY, startX + (int)size, startY + (int)size);
                NewNetMessage.SendData((int)Packet.TILE_SQUARE, -1, whoAmI, String.Empty, (int)size, (float)startX, (float)startY, 0f, 0);
            }

            if (ctx.CheckForKick() || ctx.Result == HookResult.IGNORE)
                return;

            //			args.ForEach (player, this.EachTile);

            BitsByte bitsByte6 = 0;
            BitsByte bitsByte7 = 0;
            for (int num46 = startX; num46 < startX + (int)size; num46++)
            {
                for (int num47 = startY; num47 < startY + (int)size; num47++)
                {
                    if (Main.tile[num46, num47] == null)
                    {
                        Main.tile[num46, num47] = new Tile();
                    }
                    Tile tile = Main.tile[num46, num47];
                    bool flag5 = tile.active();
                    bitsByte6 = ReadByte(readBuffer);
                    bitsByte7 = ReadByte(readBuffer);
                    tile.active(bitsByte6[0]);
                    tile.wall = (byte)(bitsByte6[2] ? 1 : 0);
                    bool flag6 = bitsByte6[3];
                    if (Main.netMode != 2)
                    {
                        tile.liquid = (byte)(flag6 ? 1 : 0);
                    }
                    tile.wire(bitsByte6[4]);
                    tile.halfBrick(bitsByte6[5]);
                    tile.actuator(bitsByte6[6]);
                    tile.inActive(bitsByte6[7]);
                    tile.wire2(bitsByte7[0]);
                    tile.wire3(bitsByte7[1]);
                    if (bitsByte7[2])
                    {
                        tile.color(ReadByte(readBuffer));
                    }
                    if (bitsByte7[3])
                    {
                        tile.wallColor(ReadByte(readBuffer));
                    }
                    if (tile.active())
                    {
                        int type2 = (int)tile.type;
                        tile.type = ReadUInt16(readBuffer);
                        if (Main.tileFrameImportant[(int)tile.type])
                        {
                            tile.frameX = ReadInt16(readBuffer);
                            tile.frameY = ReadInt16(readBuffer);
                        }
                        else
                        {
                            if (!flag5 || (int)tile.type != type2)
                            {
                                tile.frameX = -1;
                                tile.frameY = -1;
                            }
                        }
                        byte b4 = 0;
                        if (bitsByte7[4])
                        {
                            b4 += 1;
                        }
                        if (bitsByte7[5])
                        {
                            b4 += 2;
                        }
                        if (bitsByte7[6])
                        {
                            b4 += 4;
                        }
                        tile.slope(b4);
                    }
                    if (tile.wall > 0)
                    {
                        tile.wall = ReadByte(readBuffer);
                    }
                    if (flag6)
                    {
                        tile.liquid = ReadByte(readBuffer);
                        tile.liquidType((int)ReadByte(readBuffer));
                    }
                }
            }
            WorldGen.RangeFrame(startX, startY, startX + (int)size, startY + (int)size);
            NewNetMessage.SendData((int)Packet.TILE_SQUARE, -1, whoAmI, String.Empty, (int)size, (float)startX, (float)startY, 0f, 0);
        }
        private static void ProcessChest(int bufferId)
        {
            var buffer = NetMessage.buffer[bufferId];
            var player = Main.player[bufferId];

            byte b7 = buffer.reader.ReadByte();
            int x = (int)buffer.reader.ReadInt16();
            int y = (int)buffer.reader.ReadInt16();
            int style = (int)buffer.reader.ReadInt16();

            if (Math.Abs(player.position.X / 16 - x) >= 7 || Math.Abs(player.position.Y / 16 - y) >= 7)
            {
                return;
            }

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

            var args = new HookArgs.ChestBreakReceived
            {
                X = x,
                Y = y
            };

            HookPoints.ChestBreakReceived.Invoke(ref ctx, ref args);

            if (ctx.CheckForKick())
            {
                return;
            }

            if (ctx.Result == HookResult.IGNORE)
            {
                return;
            }

            if (ctx.Result == HookResult.RECTIFY)
            {
                NetMessage.SendTileSquare(bufferId, x, y, 3);
                return;
            }

            if (Main.netMode == 2)
            {
                if (b7 == 0)
                {
                    int num105 = WorldGen.PlaceChest(x, y, 21, false, style);
                    if (num105 == -1)
                    {
                        NetMessage.SendData(34, bufferId, -1, "", (int)b7, (float)x, (float)y, (float)style, num105, 0, 0);
                        Item.NewItem(x * 16, y * 16, 32, 32, Chest.chestItemSpawn[style], 1, true, 0, false);
                        return;
                    }
                    NetMessage.SendData(34, -1, -1, "", (int)b7, (float)x, (float)y, (float)style, num105, 0, 0);
                    return;
                }
                else
                {
                    if (b7 == 2)
                    {
                        int num106 = WorldGen.PlaceChest(x, y, 88, false, style);
                        if (num106 == -1)
                        {
                            NetMessage.SendData(34, bufferId, -1, "", (int)b7, (float)x, (float)y, (float)style, num106, 0, 0);
                            Item.NewItem(x * 16, y * 16, 32, 32, Chest.dresserItemSpawn[style], 1, true, 0, false);
                            return;
                        }
                        NetMessage.SendData(34, -1, -1, "", (int)b7, (float)x, (float)y, (float)style, num106, 0, 0);
                        return;
                    }
                    else
                    {
                        Tile tile2 = Main.tile[x, y];
                        if (tile2.type == 21 && b7 == 1)
                        {
                            if (tile2.frameX % 36 != 0)
                            {
                                x--;
                            }
                            if (tile2.frameY % 36 != 0)
                            {
                                y--;
                            }
                            int number = Chest.FindChest(x, y);
                            WorldGen.KillTile(x, y, false, false, false);
                            if (!tile2.active())
                            {
                                NetMessage.SendData(34, -1, -1, "", (int)b7, (float)x, (float)y, 0, number, 0, 0);
                                return;
                            }
                            return;
                        }
                        else
                        {
                            if (tile2.type != 88 || b7 != 3)
                            {
                                return;
                            }
                            x -= (int)(tile2.frameX % 54 / 18);
                            if (tile2.frameY % 36 != 0)
                            {
                                y--;
                            }
                            int number2 = Chest.FindChest(x, y);
                            WorldGen.KillTile(x, y, false, false, false);
                            if (!tile2.active())
                            {
                                NetMessage.SendData(34, -1, -1, "", (int)b7, (float)x, (float)y, 0, number2, 0, 0);
                                return;
                            }
                            return;
                        }
                    }
                }
            }
            else
            {
                int num107 = (int)buffer.reader.ReadInt16();
                if (b7 == 0)
                {
                    if (num107 == -1)
                    {
                        WorldGen.KillTile(x, y, false, false, false);
                        return;
                    }
                    WorldGen.PlaceChestDirect(x, y, 21, style, num107);
                    return;
                }
                else
                {
                    if (b7 != 2)
                    {
                        Chest.DestroyChestDirect(x, y, num107);
                        WorldGen.KillTile(x, y, false, false, false);
                        return;
                    }
                    if (num107 == -1)
                    {
                        WorldGen.KillTile(x, y, false, false, false);
                        return;
                    }
                    WorldGen.PlaceDresserDirect(x, y, 88, style, num107);
                    return;
                }
            }
        }
        private static void ProcessChestOpen(int bufferId)
        {
            var buffer = NetMessage.buffer[bufferId];
            var player = Main.player[bufferId];

            if (Main.netMode != 2)
            {
                return;
            }
            int x = (int)buffer.reader.ReadInt16();
            int y = (int)buffer.reader.ReadInt16();

            if (Math.Abs(player.position.X / 16 - x) >= 7 || Math.Abs(player.position.Y / 16 - y) >= 7)
            {
                return;
            }

            int chestIndex = Chest.FindChest(x, y);
            if (chestIndex <= -1 || Chest.UsingChest(chestIndex) != -1)
            {
                return;
            }
            var ctx = new HookContext
            {
                Connection = player.Connection.Socket,
                Player = player,
                Sender = player
            };

            var args = new HookArgs.ChestOpenReceived
            {
                X = x,
                Y = y,
                ChestIndex = chestIndex
            };

            HookPoints.ChestOpenReceived.Invoke(ref ctx, ref args);

            if (ctx.CheckForKick())
            {
                return;
            }

            if (ctx.Result == HookResult.IGNORE)
            {
                return;
            }

            if (ctx.Result == HookResult.DEFAULT && chestIndex > -1)
            {
                for (int num97 = 0; num97 < 40; num97++)
                {
                    NetMessage.SendData(32, bufferId, -1, "", chestIndex, (float)num97, 0, 0, 0, 0, 0);
                }
                NetMessage.SendData(33, bufferId, -1, "", chestIndex, 0, 0, 0, 0, 0, 0);
                Main.player[bufferId].chest = chestIndex;
                if (Main.myPlayer == bufferId)
                {
                    Main.recBigList = false;
                }
                Recipe.FindRecipes();
                NetMessage.SendData(80, -1, bufferId, "", bufferId, (float)chestIndex, 0, 0, 0, 0, 0);
                if (Main.tile[x, y].frameX >= 36 && Main.tile[x, y].frameX < 72)
                {
                    AchievementsHelper.HandleSpecialEvent(Main.player[bufferId], 16);
                }
            }
        }
        private static void ProcessWriteSign(int bufferId)
        {
            var buffer = NetMessage.buffer[bufferId];
            var player = Main.player[bufferId];

            int signId = (int)buffer.reader.ReadInt16();
            int x = (int)buffer.reader.ReadInt16();
            int y = (int)buffer.reader.ReadInt16();
            string text = buffer.reader.ReadString();

            string existing = null;
            if (Main.sign[signId] != null)
            {
                existing = Main.sign[signId].text;
            }

            Main.sign[signId] = new Sign();
            Main.sign[signId].x = x;
            Main.sign[signId].y = y;

            Sign.TextSign(signId, text);
            int ply = (int)buffer.reader.ReadByte();

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

            var args = new HookArgs.SignTextSet
            {
                X = x,
                Y = y,
                SignIndex = signId,
                Text = text,
                OldSign = Main.sign[signId],
            };

            HookPoints.SignTextSet.Invoke(ref ctx, ref args);

            if (ctx.CheckForKick() || ctx.Result == HookResult.IGNORE)
                return;

            if (Main.netMode == 2 && existing != text)
            {
                ply = bufferId;
                NetMessage.SendData(47, -1, bufferId, "", signId, (float)ply, 0, 0, 0, 0, 0);
            }

            if (Main.netMode == 1 && ply == Main.myPlayer && Main.sign[signId] != null)
            {
                Main.playerInventory = false;
                Main.player[Main.myPlayer].talkNPC = -1;
                Main.npcChatCornerItem = 0;
                Main.editSign = false;
                Main.PlaySound(10, -1, -1, 1);
                Main.player[Main.myPlayer].sign = signId;
                Main.npcChatText = Main.sign[signId].text;
            }
        }
        public override void Process(int whoAmI, byte[] readBuffer, int length, int num)
        {
            int playerIndex = (int)ReadByte(readBuffer);

            if (playerIndex != whoAmI && Entry.EnableCheatProtection)
            {
                Terraria.Netplay.Clients[whoAmI].Kick("Cheating detected (PLAYER_JOIN_PARTY forgery).");
                return;
            }

            var teamIndex = ReadByte(readBuffer);
            var player = Main.player[whoAmI];
            int currentTeam = player.team;

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

            var args = new HookArgs.PartySettingReceived
            {
                Party = teamIndex
            };

            HookPoints.PartySettingReceived.Invoke(ref ctx, ref args);

            if (ctx.CheckForKick())
            {
                return;
            }

            if (ctx.Result == HookResult.IGNORE)
            {
                return;
            }

            if (ctx.Result == HookResult.RECTIFY)
            {
                NewNetMessage.SendData(45, whoAmI, -1, String.Empty, whoAmI);
                return;
            }

            string joinMessage = String.Empty;
            switch (teamIndex)
            {
                case 1:
                    joinMessage = " has joined the red party.";
                    break;
                case 2:
                    joinMessage = " has joined the green party.";
                    break;
                case 3:
                    joinMessage = " has joined the blue party.";
                    break;
                case 4:
                    joinMessage = " has joined the yellow party.";
                    break;
                default:
                    joinMessage = " is no longer in a party.";
                    break;
            }

            player.team = teamIndex;

            NewNetMessage.SendData(45, -1, whoAmI, String.Empty, playerIndex);

            for (int i = 0; i < 255; i++)
            {
                if (i == whoAmI
                    || (currentTeam > 0 && player.team == currentTeam)
                    || (teamIndex > 0 && player.team == teamIndex))
                {
                    NewNetMessage.SendData(25, i, -1, player.Name + joinMessage, 255, (float)Main.teamColor[teamIndex].R, (float)Main.teamColor[teamIndex].G, (float)Main.teamColor[teamIndex].B);
                }
            }
        }
        public override void Process(ClientConnection conn, byte[] readBuffer, int length, int num)
        {
            //            ServerSlot slot = Netplay.slots[whoAmI];
            //            PlayerLoginEvent loginEvent = new PlayerLoginEvent();
            //            loginEvent.Slot = slot;
            //            loginEvent.Sender = Main.player[whoAmI];
            //            Server.PluginManager.processHook(Plugin.Hooks.PLAYER_PRELOGIN, loginEvent);
            //            if ((loginEvent.Cancelled || loginEvent.Action == PlayerLoginAction.REJECT) && (slot.state & SlotState.DISCONNECTING) == 0)
            //            {
            //                slot.Kick ("Disconnected by server.");
            //                return;
            //            }

            string clientName = conn.RemoteAddress.Split(':')[0];
            //
            //            if (Server.BanList.containsException(clientName))
            //            {
            //                slot.Kick ("You are banned from this Server.");
            //                return;
            //            }

            //if (Program.properties.UseWhiteList && !Server.WhiteList.containsException(clientName))
            //{
            //    conn.Kick ("You are not on the WhiteList.");
            //    return;
            //}

            string version = StringCache.FindOrMake(new ArraySegment<byte>(readBuffer, num, length - 1));
            Skip(length);

            var ctx = new HookContext
            {
                Connection = conn,
            };

            var args = new HookArgs.ConnectionRequestReceived
            {
                Version = version
            };

            HookPoints.ConnectionRequestReceived.Invoke(ref ctx, ref args);

            if (ctx.CheckForKick())
                return;

            if (ctx.Result == HookResult.DEFAULT && !(version == "Terraria" + Globals.TerrariaRelease))
            {
                if (version.Length > 30) version = version.Substring(0, 30);
                ProgramLog.Log("Client version string: {0}", version);
                conn.Kick(string.Concat("This server requires Terraria ", Globals.TerrariaVersion));
                return;
            }

            var msg = NewNetMessage.PrepareThreadInstance();

            if (ctx.Result == HookResult.ASK_PASS || (Netplay.password != null && Netplay.password != String.Empty))
            {
                conn.State = SlotState.SERVER_AUTH;
                msg.PasswordRequest();
                conn.Send(msg.Output);
                return;
            }

            conn.State = SlotState.ACCEPTED;
            msg.ConnectionResponse(253 /* arbitrary fake value, true slot assigned later */);
            conn.Send(msg.Output);
        }
        public static void OnPlayerJoined(int plr)
        {
            var player = Main.player[plr];

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

            var args = new HookArgs.PlayerEnteringGame
            {
                Slot = plr,
            };

            HookPoints.PlayerEnteringGame.Invoke(ref ctx, ref args);

            if (ctx.CheckForKick())
            {
                return;
            }

            var msg = NewNetMessage.PrepareThreadInstance();
            if (ctx.Result == HookResult.DEFAULT)
            {
                var motd = (Main.motd ?? System.String.Empty).Split('@'); //"My greeting from properties".Split('@');
                for (int i = 0; i < motd.Length; i++)
                {
                    if (motd[i] != null && motd[i].Trim().Length > 0)
                    {
                        msg.PlayerChat(255, motd[i], 0, 0, 255);
                    }
                }

                string list = System.String.Empty;
                for (int i = 0; i < 255; i++)
                {
                    if (Main.player[i].active)
                    {
                        if (list == System.String.Empty)
                            list += Main.player[i].name;
                        else
                            list = list + ", " + Main.player[i].name;
                    }
                }

                msg.PlayerChat(255, "Current players: " + list + ".", 255, 240, 20);
                msg.Send(plr); // send these before the login event, so messages from plugins come after
            }

            var slot = Terraria.Netplay.Clients[plr] as ServerSlot;

            slot.announced = true;

            // to player
            msg.Clear();
            msg.SyncAllNPCHomes();
            msg.SendSyncOthersForPlayer(plr);

            ProgramLog.Log("{0} @ {1}: ENTER {2}", slot.remoteAddress, plr, player.name);

            //if (player.HasHackedData())
            //{
            //    player.Kick("No Hacked Health or Mana is allowed.");
            //    return;
            //}

            // to other players
            msg.Clear();
            msg.PlayerChat(255, player.name + " has joined.", 255, 240, 20);
            msg.ReceivingPlayerJoined(plr);
            msg.SendSyncPlayerForOthers(plr); // broadcasts the preceding message too

            var args2 = new HookArgs.PlayerEnteredGame
            {
                Slot = plr,
            };

            ctx.SetResult(HookResult.DEFAULT, false);
            HookPoints.PlayerEnteredGame.Invoke(ref ctx, ref args2);

            if (ctx.CheckForKick())
            {
                return;
            }
        }
        public override void Process(int whoAmI, byte[] readBuffer, int length, int num)
        {
            int x = (int)ReadInt16(readBuffer);
            int y = (int)ReadInt16(readBuffer);
            byte liquid = ReadByte(readBuffer);
            byte liquidType = ReadByte(readBuffer);

            var player = Main.player[whoAmI];

            if (Main.netMode == 2 && Netplay.spamCheck)
            {
                int num113 = whoAmI;
                int num114 = (int)(Main.player[num113].position.X + (float)(Main.player[num113].width / 2));
                int num115 = (int)(Main.player[num113].position.Y + (float)(Main.player[num113].height / 2));
                int num116 = 10;
                int num117 = num114 - num116;
                int num118 = num114 + num116;
                int num119 = num115 - num116;
                int num120 = num115 + num116;
                if (x < num117 || x > num118 || y < num119 || y > num120)
                {
                    //NewNetMessage.BootPlayer(whoAmI, "Cheating attempt detected: Liquid spam");
                    Main.player[num113].Kick("Cheating attempt detected: Liquid spam");
                    return;
                }
            }
            var ctx = new HookContext
            {
                Connection = player.Connection,
                Player = player,
                Sender = player,
            };

            var args = new HookArgs.LiquidFlowReceived
            {
                X = x,
                Y = y,
                Amount = liquid,
                Lava = liquidType == 1,
            };

            HookPoints.LiquidFlowReceived.Invoke(ref ctx, ref args);

            if (ctx.CheckForKick())
                return;

            if (ctx.Result == HookResult.IGNORE)
                return;

            if (ctx.Result == HookResult.RECTIFY)
            {
                var msg = NewNetMessage.PrepareThreadInstance();
                msg.FlowLiquid(x, y);
                msg.Send(whoAmI);
                return;
            }

            if (Main.tile[x, y] == null)
            {
                Main.tile[x, y] = new Tile();
            }
            lock (Main.tile[x, y])
            {
                Main.tile[x, y].liquid = liquid;
                Main.tile[x, y].liquidType((int)liquidType);
                if (Main.netMode == 2)
                {
                    WorldGen.SquareTileFrame(x, y, true);
                }
                return;
            }
        }
        private static void ProcessTileSquare(int bufferId)
        {
            var buffer = NetMessage.buffer[bufferId];
            var player = Main.player[bufferId];

            short size = buffer.reader.ReadInt16();
            int startX = (int)buffer.reader.ReadInt16();
            int startY = (int)buffer.reader.ReadInt16();
            if (!WorldGen.InWorld(startX, startY, 3))
            {
                return;
            }

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

            var args = new HookArgs.TileSquareReceived
            {
                X = startX,
                Y = startY,
                Size = size,
                readBuffer = buffer.readBuffer
            //                start = num
            };

            HookPoints.TileSquareReceived.Invoke(ref ctx, ref args);

            //            if (args.applied > 0)
            //            {
            //                WorldGen.RangeFrame(startX, startY, startX + (int)size, startY + (int)size);
            //                NetMessage.SendData((int)Packet.TILE_SQUARE, -1, bufferId, String.Empty, (int)size, (float)startX, (float)startY, 0f, 0);
            //            }

            if (ctx.CheckForKick() || ctx.Result == HookResult.IGNORE)
                return;

            BitsByte bitsByte10 = 0;
            BitsByte bitsByte11 = 0;
            for (int x = startX; x < startX + (int)size; x++)
            {
                for (int y = startY; y < startY + (int)size; y++)
                {
                    if (Main.tile[x, y] == null)
                    {
                        Main.tile[x, y] = new Tile();
                    }
                    Tile tile = Main.tile[x, y];
                    bool flag7 = tile.active();
                    bitsByte10 = buffer.reader.ReadByte();
                    bitsByte11 = buffer.reader.ReadByte();
                    tile.active(bitsByte10[0]);
                    tile.wall = (bitsByte10[2] ? (byte)1 : (byte)0);
                    bool flag8 = bitsByte10[3];
                    if (Main.netMode != 2)
                    {
                        tile.liquid = (flag8 ? (byte)1 : (byte)0);
                    }
                    tile.wire(bitsByte10[4]);
                    tile.halfBrick(bitsByte10[5]);
                    tile.actuator(bitsByte10[6]);
                    tile.inActive(bitsByte10[7]);
                    tile.wire2(bitsByte11[0]);
                    tile.wire3(bitsByte11[1]);
                    if (bitsByte11[2])
                    {
                        tile.color(buffer.reader.ReadByte());
                    }
                    if (bitsByte11[3])
                    {
                        tile.wallColor(buffer.reader.ReadByte());
                    }
                    if (tile.active())
                    {
                        int type3 = (int)tile.type;
                        tile.type = buffer.reader.ReadUInt16();
                        if (Main.tileFrameImportant[(int)tile.type])
                        {
                            tile.frameX = buffer.reader.ReadInt16();
                            tile.frameY = buffer.reader.ReadInt16();
                        }
                        else
                        {
                            if (!flag7 || (int)tile.type != type3)
                            {
                                tile.frameX = -1;
                                tile.frameY = -1;
                            }
                        }
                        byte b4 = 0;
                        if (bitsByte11[4])
                        {
                            b4 += 1;
                        }
                        if (bitsByte11[5])
                        {
                            b4 += 2;
                        }
                        if (bitsByte11[6])
                        {
                            b4 += 4;
                        }
                        tile.slope(b4);
                    }
                    if (tile.wall > 0)
                    {
                        tile.wall = buffer.reader.ReadByte();
                    }
                    if (flag8)
                    {
                        tile.liquid = buffer.reader.ReadByte();
                        tile.liquidType((int)buffer.reader.ReadByte());
                    }
                }
            }
            WorldGen.RangeFrame(startX, startY, startX + (int)size, startY + (int)size);
            if (Main.netMode == 2)
            {
                NetMessage.SendData((int)Packet.TILE_SQUARE, -1, bufferId, "", (int)size, (float)startX, (float)startY, 0, 0, 0, 0);
                return;
            }
        }
        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);
        }