public static void SyncNPCHomes()
        {
            var msg = NewNetMessage.PrepareThreadInstance();

            msg.SyncAllNPCHomes();
            msg.Broadcast();
        }
        public static void SyncPlayers() /* always sends all updates to all players */
        {
            var msg = NewNetMessage.PrepareThreadInstance();

            for (int i = 0; i < 255; i++)
            {
                if (Terraria.Netplay.Clients[i].State() == SlotState.PLAYING)
                {
                    msg.Clear();
                    msg.BuildPlayerUpdate(i);
                    msg.BroadcastExcept(i);
                }
            }

            msg.Clear();

            for (int i = 0; i < 255; i++)
            {
                if (Terraria.Netplay.Clients[i].State() != SlotState.PLAYING)
                {
                    msg.SynchBegin(i, 0);
                }
            }

            msg.Broadcast();
        }
 public static void SendSection(int whoAmi, int sectionX, int sectionY, bool skipSent = false)
 {
     if (sectionX >= 0 && sectionY >= 0 && sectionX < Main.maxSectionsX && sectionY < Main.maxSectionsY)
     {
         if (!skipSent || !Terraria.Netplay.Clients[whoAmi].TileSections[sectionX, sectionY])
         {
             Terraria.Netplay.Clients[whoAmi].TileSections[sectionX, sectionY] = true;
             int number = sectionX * 200;
             int num    = sectionY * 150;
             int num2   = 150;
             for (int i = num; i < num + 150; i += num2)
             {
                 NewNetMessage.SendData(10, whoAmi, -1, "", number, (float)i, 200f, (float)num2, 0);
             }
             for (int j = 0; j < 200; j++)
             {
                 if (Main.npc[j].active && Main.npc[j].townNPC)
                 {
                     int sectionX2 = Netplay.GetSectionX((int)(Main.npc[j].position.X / 16f));
                     int sectionY2 = Netplay.GetSectionY((int)(Main.npc[j].position.Y / 16f));
                     if (sectionX2 == sectionX && sectionY2 == sectionY)
                     {
                         NewNetMessage.SendData(23, whoAmi, -1, "", j, 0f, 0f, 0f, 0);
                     }
                 }
             }
         }
     }
 }
        public static void SendTileSquare(int whoAmi, int tileX, int tileY, int size)
        {
            int   num = (size - 1) / 2;
            float x   = tileX - num;
            float y   = tileY - num;

            NewNetMessage.SendData(20, whoAmi, -1, System.String.Empty, size, x, y, 0f);
        }
 public static void SendTileSquare(int whoAmi, int x, int y, int size, bool centered)
 {
     if (centered)
     {
         SendTileSquare(whoAmi, x, y, size);
     }
     else
     {
         NewNetMessage.SendData(20, whoAmi, -1, System.String.Empty, size, x, y, 0f);
     }
 }
 public static NewNetMessage PrepareThreadInstance(int size)
 {
     if (threadInstance == null || threadInstance.buf.Length < size)
     {
         threadInstance = new NewNetMessage(size);
     }
     else
     {
         threadInstance.sink.Position = 0;
         threadInstance.lenAt         = 0;
     }
     return(threadInstance);
 }
        public static void SendWater(int x, int y)
        {
            if (disableLiquidUpdates)
            {
                return;
            }

            if (useLiquidUpdateBuffer)
            {
                //LiquidUpdateBuffer.QueueUpdate(x, y);
                LiquidBuffer.AddBuffer(x, y);
                return;
            }

            byte[] bytes = null;

            for (int i = 0; i < 255; i++)
            {
                var slot = Terraria.Netplay.Clients[i] as ServerSlot;
                if (slot.state >= SlotState.PLAYING && slot.Connected)
                {
                    int X = x / 200;
                    int Y = y / 150;
                    if (X < (Main.maxTilesX / 200) && Y < (Main.maxTilesY / 150))
                    {
                        if (Terraria.Netplay.Clients[i].TileSections[X, Y])
                        {
                            if (bytes == null)
                            {
                                var msg = NewNetMessage.PrepareThreadInstance();
                                msg.FlowLiquid(x, y);
                                bytes = msg.Output;
                            }
                            slot.Send(bytes);
                        }
                    }
                    else
                    {
                        ProgramLog.Log("Water Index out of Bounds:");
                        ProgramLog.Log(string.Format("X: {0} Y: {1}, Axis: {2}, {3}", X, Y, Main.maxTilesX, Main.maxTilesY));
                    }
                }
            }
        }
        public static void OnPlayerLeft(Player player, ServerSlot slot, bool announced)
        {
            player.active = false;

            if (announced)
            {
                ProgramLog.Log("{0} @ {1}: LEAVE {2}", slot.remoteAddress, slot.Id, player.name);

                var msg = NewNetMessage.PrepareThreadInstance();

                msg.SynchBegin(player.whoAmI, 0 /*inactive*/);

                if (player.DisconnectReason != null)
                {
                    msg.PlayerChat(255, string.Concat(player.Name, " disconnected (", player.DisconnectReason, ")."), 255, 165, 0);
                }
                else
                {
                    msg.PlayerChat(255, string.Concat(player.name, " has left."), 255, 240, 20);
                }

                msg.BroadcastExcept(player.whoAmI);
            }

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

            var args = new HookArgs.PlayerLeftGame
            {
                Slot = slot.Id
            };

            HookPoints.PlayerLeftGame.Invoke(ref ctx, ref args);
        }
        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 static NewNetMessage PrepareThreadInstance(int size)
 {
     if (threadInstance == null || threadInstance.buf.Length < size)
     {
         threadInstance = new NewNetMessage(size);
     }
     else
     {
         threadInstance.sink.Position = 0;
         threadInstance.lenAt = 0;
     }
     return threadInstance;
 }
 static void FreeSectionBuffer(NewNetMessage buf)
 {
     buf.Clear();
     lock (sectionPool)
         sectionPool.Push(buf);
 }
        protected override ArraySegment<byte> SerializeMessage(Message msg)
        {
            switch (msg.kind)
            {
                case 10:
                    {
                        // TODO: optimize further
                        var buf = TakeSectionBuffer();
                        var sX = (msg.param >> 16) * 200;
                        var sY = (msg.param & 0xffff) * 150;

                        int uncompressed = 0;

                        for (int y = sY; y < sY + 150; y++)
                        {
                            if (CompressionVersion == 1)
                            {
                                uncompressed += buf.TileRowSize(200, sX, y);
                                buf.TileRowCompressed(200, sX, y);
                            }
                            else
                                buf.SendTileRowCompressed(sX, y, 200, 150, true);

                        }

                        if (uncompressed > 0)
                        {
                            var c = System.Threading.Interlocked.Add(ref _compressed, buf.Written);
                            var u = System.Threading.Interlocked.Add(ref _uncompressed, uncompressed);
                            ProgramLog.Log("Total section compression ratio: {2:0.00}% ({0:0.0}MB -> {1:0.0}MB)", u / 1024.0 / 1024.0, c / 1024.0 / 1024.0, c * 100.0 / u);
                        }

                        sectionBuffer = buf;
                        //ProgramLog.Log ("{0} @ {1}: Sending section ({2}, {3}) of {4} bytes.", RemoteAddress, assignedSlot, sX, sY, buf.Segment.Count);

                        return buf.Segment;
                    }
            }
            return new ArraySegment<byte>();
        }
 protected void FreeSectionBuffer()
 {
     if (sectionBuffer != null)
     {
         var buf = sectionBuffer;
         sectionBuffer = null;
         FreeSectionBuffer(buf);
     }
 }