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 static void OnPlayerJoined(Player player)
        {
            var ctx = new HookContext
            {
                Connection = player.Connection,
                Player = player,
                Sender = player
            };

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

            ctx.SetResult(HookResult.DEFAULT, false);
            HookPoints.PlayerEnteredGame.Invoke(ref ctx, ref args);
            ctx.CheckForKick();
        }
        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;
            }
        }