示例#1
0
 /// <summary>
 /// Updates a single tile on the server if it is a valid conversion from one tile or wall type to another (eg stone -> corrupt stone)
 /// </summary>
 /// <param name="tile">The tile to update</param>
 /// <param name="newTile">The NetTile containing new tile properties</param>
 internal void ProcessConversionSpreads(ITile tile, NetTile newTile)
 {
     // Update if the existing tile or wall is convertible and the new tile or wall is a valid conversion
     if (
         ((TileID.Sets.Conversion.Stone[tile.type] || Main.tileMoss[tile.type]) && (TileID.Sets.Conversion.Stone[newTile.Type] || Main.tileMoss[newTile.Type])) ||
         ((tile.type == 0 || tile.type == 59) && (newTile.Type == 0 || newTile.Type == 59)) ||
         TileID.Sets.Conversion.Grass[tile.type] && TileID.Sets.Conversion.Grass[newTile.Type] ||
         TileID.Sets.Conversion.Ice[tile.type] && TileID.Sets.Conversion.Ice[newTile.Type] ||
         TileID.Sets.Conversion.Sand[tile.type] && TileID.Sets.Conversion.Sand[newTile.Type] ||
         TileID.Sets.Conversion.Sandstone[tile.type] && TileID.Sets.Conversion.Sandstone[newTile.Type] ||
         TileID.Sets.Conversion.HardenedSand[tile.type] && TileID.Sets.Conversion.HardenedSand[newTile.Type] ||
         TileID.Sets.Conversion.Thorn[tile.type] && TileID.Sets.Conversion.Thorn[newTile.Type] ||
         TileID.Sets.Conversion.Moss[tile.type] && TileID.Sets.Conversion.Moss[newTile.Type] ||
         TileID.Sets.Conversion.MossBrick[tile.type] && TileID.Sets.Conversion.MossBrick[newTile.Type] ||
         WallID.Sets.Conversion.Stone[tile.wall] && WallID.Sets.Conversion.Stone[newTile.Wall] ||
         WallID.Sets.Conversion.Grass[tile.wall] && WallID.Sets.Conversion.Grass[newTile.Wall] ||
         WallID.Sets.Conversion.Sandstone[tile.wall] && WallID.Sets.Conversion.Sandstone[newTile.Wall] ||
         WallID.Sets.Conversion.HardenedSand[tile.wall] && WallID.Sets.Conversion.HardenedSand[newTile.Wall] ||
         WallID.Sets.Conversion.PureSand[tile.wall] && WallID.Sets.Conversion.PureSand[newTile.Wall] ||
         WallID.Sets.Conversion.NewWall1[tile.wall] && WallID.Sets.Conversion.NewWall1[newTile.Wall] ||
         WallID.Sets.Conversion.NewWall2[tile.wall] && WallID.Sets.Conversion.NewWall2[newTile.Wall] ||
         WallID.Sets.Conversion.NewWall3[tile.wall] && WallID.Sets.Conversion.NewWall3[newTile.Wall] ||
         WallID.Sets.Conversion.NewWall4[tile.wall] && WallID.Sets.Conversion.NewWall4[newTile.Wall]
         )
     {
         TShock.Log.ConsoleDebug("Bouncer / SendTileRect processing a conversion update - [{0}|{1}] -> [{2}|{3}]", tile.type, tile.wall, newTile.Type, newTile.Wall);
         UpdateServerTileState(tile, newTile);
     }
 }
示例#2
0
        /// <summary>
        /// Processes a single tile from the tile rect packet
        /// </summary>
        /// <param name="realX">X position at the top left of the object</param>
        /// <param name="realY">Y position at the top left of the object</param>
        /// <param name="newTile">The NetTile containing new tile properties</param>
        /// <param name="rectWidth">The width of the rectangle being processed</param>
        /// <param name="rectLength">The length of the rectangle being processed</param>
        /// <param name="args">SendTileRectEventArgs containing event information</param>
        internal void ProcessSingleTile(int realX, int realY, NetTile newTile, byte rectWidth, byte rectLength, GetDataHandlers.SendTileRectEventArgs args)
        {
            // Some boots allow growing flowers on grass. This process sends a 1x1 tile rect to grow the flowers
            // The rect size must be 1 and the player must have an accessory that allows growing flowers in order for this rect to be valid
            if (rectWidth == 1 && rectLength == 1 && args.Player.Accessories.Any(a => a != null && FlowerBootItems.Contains(a.type)))
            {
                ProcessFlowerBoots(realX, realY, newTile, args);
                return;
            }

            ITile tile = Main.tile[realX, realY];

            if (tile.type == TileID.LandMine && !newTile.Active)
            {
                UpdateServerTileState(tile, newTile);
            }

            if (tile.type == TileID.WirePipe)
            {
                UpdateServerTileState(tile, newTile);
            }

            ProcessConversionSpreads(Main.tile[realX, realY], newTile);

            // All other single tile updates should not be processed.
        }
示例#3
0
        /// <summary>
        /// Updates a single tile's world state with a change from the tile rect packet
        /// </summary>
        /// <param name="tile">The tile to update</param>
        /// <param name="newTile">The NetTile containing the change</param>
        public static void UpdateServerTileState(ITile tile, NetTile newTile)
        {
            tile.active(newTile.Active);
            tile.type = newTile.Type;

            if (newTile.FrameImportant)
            {
                tile.frameX = newTile.FrameX;
                tile.frameY = newTile.FrameY;
            }

            if (newTile.HasWall)
            {
                tile.wall = newTile.Wall;
            }

            if (newTile.HasLiquid)
            {
                tile.liquid = newTile.Liquid;
                tile.liquidType(newTile.LiquidType);
            }

            tile.wire(newTile.Wire);
            tile.wire2(newTile.Wire2);
            tile.wire3(newTile.Wire3);
            tile.wire4(newTile.Wire4);

            tile.halfBrick(newTile.IsHalf);

            if (newTile.HasColor)
            {
                tile.color(newTile.TileColor);
            }

            if (newTile.HasWallColor)
            {
                tile.wallColor(newTile.WallColor);
            }

            byte slope = 0;

            if (newTile.Slope)
            {
                slope += 1;
            }
            if (newTile.Slope2)
            {
                slope += 2;
            }
            if (newTile.Slope3)
            {
                slope += 4;
            }

            tile.slope(slope);

            TShock.Log.ConsoleDebug("Bouncer / SendTileRect updated a tile from type {0} to {1}", tile.type, newTile.Type);
        }
示例#4
0
        private void OnSendTileSquare(TSPlayer player, BinaryReader reader)
        {
            var size = reader.ReadUInt16();

            if (size != 1)
            {
                return;
            }

            reader.ReadInt16();
            reader.ReadInt16();
            var tile = new NetTile(reader.BaseStream);

            if (tile.Type == TileID.Mannequin || tile.Type == TileID.Womannequin)
            {
                var baseFrameX = tile.FrameX / 100;
                ILookup <int, Item> lookup;
                if (tile.FrameY == 0)
                {
                    lookup = _headSlotLookup;
                }
                else if (tile.FrameY == 18)
                {
                    lookup = _bodySlotLookup;
                }
                else
                {
                    lookup = _legSlotLookup;
                }

                var armorItem = lookup[baseFrameX].FirstOrDefault();
                if (armorItem != null)
                {
                    var balanceSheet = player.GetOrCreateBalanceSheet();
                    balanceSheet.AddTransaction(Transaction.WorldSlot, armorItem.type, -1);
                }
            }
            else if (tile.Type == TileID.WeaponsRack)
            {
                var baseFrameX = tile.FrameX - 5000 * (tile.FrameX / 5000);
                // When placing a weapon an a weapon rack, the client will send two SendTileSquare packets; the first
                // gives the item ID, and the second gives the item prefix. We know which one is the item ID since the
                // base frameX is over 100.
                if (baseFrameX > 100)
                {
                    player.SetWeaponRackItemId(baseFrameX - 100);
                }
                else
                {
                    var balanceSheet     = player.GetOrCreateBalanceSheet();
                    var weaponRackItemId = player.GetWeaponRackItemId();
                    balanceSheet.AddTransaction(Transaction.WorldSlot, weaponRackItemId, -1, (byte)baseFrameX);
                }
            }
        }
示例#5
0
        /// <summary>
        /// Reads a set of NetTiles from a memory stream
        /// </summary>
        /// <param name="stream"></param>
        /// <param name="width"></param>
        /// <param name="length"></param>
        /// <returns></returns>
        static NetTile[,] ReadNetTilesFromStream(System.IO.MemoryStream stream, byte width, byte length)
        {
            NetTile[,] tiles = new NetTile[width, length];
            for (int x = 0; x < width; x++)
            {
                for (int y = 0; y < length; y++)
                {
                    tiles[x, y] = new NetTile(stream);
                }
            }

            return(tiles);
        }
示例#6
0
        /// <summary>
        /// Reads a set of NetTiles from a memory stream
        /// </summary>
        /// <param name="stream"></param>
        /// <param name="size"></param>
        /// <returns></returns>
        static NetTile[,] ReadNetTilesFromStream(System.IO.MemoryStream stream, short size)
        {
            NetTile[,] tiles = new NetTile[size, size];
            for (int x = 0; x < size; x++)
            {
                for (int y = 0; y < size; y++)
                {
                    tiles[x, y] = new NetTile(stream);
                }
            }

            return(tiles);
        }
示例#7
0
        /// <summary>
        /// Applies changes to a tile if a tile rect for flower-growing boots is valid
        /// </summary>
        /// <param name="realX">The tile x position of the tile rect packet - this is where the flowers are intending to grow</param>
        /// <param name="realY">The tile y position of the tile rect packet - this is where the flowers are intending to grow</param>
        /// <param name="newTile">The NetTile containing information about the flowers that are being grown</param>
        /// <param name="args">SendTileRectEventArgs containing event information</param>
        internal void ProcessFlowerBoots(int realX, int realY, NetTile newTile, GetDataHandlers.SendTileRectEventArgs args)
        {
            // We need to get the tile below the tile rect to determine what grass types are allowed
            if (!WorldGen.InWorld(realX, realY + 1))
            {
                // If the tile below the tile rect isn't valid, we return here and don't update the server tile state
                return;
            }

            ITile tile = Main.tile[realX, realY + 1];

            if (!GrassToPlantMap.TryGetValue(tile.type, out List <ushort> plantTiles) && !plantTiles.Contains(newTile.Type))
            {
                // If the tile below the tile rect isn't a valid plant tile (eg grass) then we don't update the server tile state
                return;
            }

            UpdateServerTileState(Main.tile[realX, realY], newTile);
        }
示例#8
0
        private static bool HandleSendTileSquare(GetDataHandlerArgs args)
        {
            var player = args.Player;
            var size   = args.Data.ReadInt16();
            var tileX  = args.Data.ReadInt16();
            var tileY  = args.Data.ReadInt16();

            var tiles = new NetTile[size, size];

            for (int x = 0; x < size; x++)
            {
                for (int y = 0; y < size; y++)
                {
                    tiles[x, y] = new NetTile(args.Data);
                }
            }

            for (int x = 0; x < size; x++)
            {
                int realx = tileX + x;
                if (realx < 0 || realx >= Main.maxTilesX)
                {
                    continue;
                }

                for (int y = 0; y < size; y++)
                {
                    int realy = tileY + y;
                    if (realy < 0 || realy >= Main.maxTilesY)
                    {
                        continue;
                    }

                    if (tiles[x, y].Type == Terraria.ID.TileID.LogicSensor && PlotMarker.BlockModify(args.Player, realx, realy))
                    {
                        args.Player.SendTileSquare(realx, realy, 1);
                        return(true);
                    }
                }
            }

            return(false);
        }
示例#9
0
        public static void CheckModifiedTiles(int i, int j, Stream stream)
        {
            if (modifiedTile.Where(t => t.i == i && t.j == j).ToArray().Length != 0)
            {
                return;
            }

            ITile tile = Main.tile[i, j];

            stream.Seek(0, SeekOrigin.Begin);
            var  newTile = new NetTile(stream);
            byte Slope   = 0;

            if (newTile.Slope)
            {
                Slope += 1;
            }
            if (newTile.Slope2)
            {
                Slope += 2;
            }
            if (newTile.Slope3)
            {
                Slope += 4;
            }
            modifiedTile.Add(new TileData()
            {
                i         = i,
                j         = j,
                type      = tile.type,
                slope     = Slope,
                active    = tile.active(),
                halfBrick = newTile.IsHalf,
                wall      = tile.wall
            });
        }
示例#10
0
        /// <summary>
        /// Iterates over each tile in the tile rectangle and performs processing on individual tiles or multi-tile Tile Objects
        /// </summary>
        /// <param name="tiles"></param>
        /// <param name="processed"></param>
        /// <param name="args"></param>
        internal void IterateTileRect(NetTile[,] tiles, bool[,] processed, GetDataHandlers.SendTileRectEventArgs args)
        {
            int  tileX  = args.TileX;
            int  tileY  = args.TileY;
            byte width  = args.Width;
            byte length = args.Length;

            for (int x = 0; x < width; x++)
            {
                for (int y = 0; y < length; y++)
                {
                    // Do not process already processed tiles
                    if (processed[x, y])
                    {
                        continue;
                    }

                    int realX = tileX + x;
                    int realY = tileY + y;

                    // Do not process tiles outside of the world boundaries
                    if ((realX < 0 || realX >= Main.maxTilesX) ||
                        (realY < 0 || realY > Main.maxTilesY))
                    {
                        processed[x, y] = true;
                        continue;
                    }

                    // Do not process tiles that the player cannot update
                    if (!args.Player.HasBuildPermission(realX, realY) ||
                        !args.Player.IsInRange(realX, realY))
                    {
                        processed[x, y] = true;
                        continue;
                    }

                    NetTile        newTile = tiles[x, y];
                    TileObjectData data;

                    // If the new tile has an associated TileObjectData object, we take the tile and the surrounding tiles that make up the tile object
                    // and process them as a tile object
                    if (newTile.Type < TileObjectData._data.Count && TileObjectData._data[newTile.Type] != null)
                    {
                        data = TileObjectData._data[newTile.Type];
                        NetTile[,] newTiles;
                        int objWidth  = data.Width;
                        int objHeight = data.Height;
                        int offsetY   = 0;

                        if (newTile.Type == TileID.TrapdoorClosed)
                        {
                            // Trapdoors can modify a 2x3 space. When it closes it will have leftover tiles either on top or bottom.
                            // If we don't update these tiles, the trapdoor gets confused and disappears.
                            // So we capture all 6 possible tiles and offset ourselves 1 tile above the closed trapdoor to capture the entire 2x3 area
                            objWidth  = 2;
                            objHeight = 3;
                            offsetY   = -1;
                        }

                        // Ensure the tile object fits inside the rect before processing it
                        if (!DoesTileObjectFitInTileRect(x, y, objWidth, objHeight, width, length, offsetY, processed))
                        {
                            continue;
                        }

                        newTiles = new NetTile[objWidth, objHeight];

                        for (int i = 0; i < objWidth; i++)
                        {
                            for (int j = 0; j < objHeight; j++)
                            {
                                newTiles[i, j] = tiles[x + i, y + j + offsetY];
                                processed[x + i, y + j + offsetY] = true;
                            }
                        }
                        ProcessTileObject(newTile.Type, realX, realY + offsetY, objWidth, objHeight, newTiles, args);
                        continue;
                    }

                    // If the new tile does not have an associated tile object, process it as an individual tile
                    ProcessSingleTile(realX, realY, newTile, width, length, args);
                    processed[x, y] = true;
                }
            }
        }
示例#11
0
        /// <summary>
        /// Updates a single tile's world state with a set of changes from the networked tile state
        /// </summary>
        /// <param name="tile">The tile to update</param>
        /// <param name="newTile">The NetTile containing the change</param>
        /// <param name="updateType">The type of data to merge into world state</param>
        public static void UpdateServerTileState(ITile tile, NetTile newTile, TileDataType updateType)
        {
            //This logic (updateType & TDT.Tile) != 0 is the way Terraria does it (see: Tile.cs/Clear(TileDataType))
            //& is not a typo - we're performing a binary AND test to see if a given flag is set.

            if ((updateType & TileDataType.Tile) != 0)
            {
                tile.active(newTile.Active);
                tile.type = newTile.Type;

                if (newTile.FrameImportant)
                {
                    tile.frameX = newTile.FrameX;
                    tile.frameY = newTile.FrameY;
                }
                else if (tile.type != newTile.Type || !tile.active())
                {
                    //This is vanilla logic - if the tile changed types (or wasn't active) the frame values might not be valid - so we reset them to -1.
                    tile.frameX = -1;
                    tile.frameY = -1;
                }
            }

            if ((updateType & TileDataType.Wall) != 0)
            {
                tile.wall = newTile.Wall;
            }

            if ((updateType & TileDataType.TilePaint) != 0)
            {
                tile.color(newTile.TileColor);
            }

            if ((updateType & TileDataType.WallPaint) != 0)
            {
                tile.wallColor(newTile.WallColor);
            }

            if ((updateType & TileDataType.Liquid) != 0)
            {
                tile.liquid = newTile.Liquid;
                tile.liquidType(newTile.LiquidType);
            }

            if ((updateType & TileDataType.Slope) != 0)
            {
                tile.halfBrick(newTile.IsHalf);
                tile.slope(newTile.Slope);
            }

            if ((updateType & TileDataType.Wiring) != 0)
            {
                tile.wire(newTile.Wire);
                tile.wire2(newTile.Wire2);
                tile.wire3(newTile.Wire3);
                tile.wire4(newTile.Wire4);
            }

            if ((updateType & TileDataType.Actuator) != 0)
            {
                tile.actuator(newTile.IsActuator);
                tile.inActive(newTile.Inactive);
            }
        }
示例#12
0
        private static bool HandleSendTileSquare(GetDataHandlerArgs args)
        {
            var size  = args.Data.ReadInt16();
            var tileX = args.Data.ReadInt32();
            var tileY = args.Data.ReadInt32();

            if (size > 5)
            {
                return(true);
            }

            if ((DateTime.UtcNow - args.Player.LastThreat).TotalMilliseconds < 5000)
            {
                args.Player.SendTileSquare(tileX, tileY, size);
                return(true);
            }

            if (TShock.CheckIgnores(args.Player))
            {
                args.Player.SendTileSquare(tileX, tileY);
                return(true);
            }

            var tiles = new NetTile[size, size];

            for (int x = 0; x < size; x++)
            {
                for (int y = 0; y < size; y++)
                {
                    tiles[x, y] = new NetTile(args.Data);
                }
            }

            bool changed = false;

            for (int x = 0; x < size; x++)
            {
                int realx = tileX + x;
                if (realx < 0 || realx >= Main.maxTilesX)
                {
                    continue;
                }

                for (int y = 0; y < size; y++)
                {
                    int realy = tileY + y;
                    if (realy < 0 || realy >= Main.maxTilesY)
                    {
                        continue;
                    }

                    var tile    = Main.tile[realx, realy];
                    var newtile = tiles[x, y];
                    if (TShock.CheckTilePermission(args.Player, x, y))
                    {
                        continue;
                    }
                    if ((tile.type == 128 && newtile.Type == 128) || (tile.type == 105 && newtile.Type == 105))
                    {
                        if (TShock.Config.EnableInsecureTileFixes)
                        {
                            return(false);
                        }
                    }

                    if (tile.type == 0x17 && newtile.Type == 0x2)
                    {
                        tile.type = 0x2;
                        changed   = true;
                    }
                    else if (tile.type == 0x19 && newtile.Type == 0x1)
                    {
                        tile.type = 0x1;
                        changed   = true;
                    }
                    else if ((tile.type == 0xF && newtile.Type == 0xF) ||
                             (tile.type == 0x4F && newtile.Type == 0x4F))
                    {
                        tile.frameX = newtile.FrameX;
                        tile.frameY = newtile.FrameY;
                        changed     = true;
                    }
                    // Holy water/Unholy water
                    else if (tile.type == 1 && newtile.Type == 117)
                    {
                        tile.type = 117;
                        changed   = true;
                    }
                    else if (tile.type == 1 && newtile.Type == 25)
                    {
                        tile.type = 25;
                        changed   = true;
                    }
                    else if (tile.type == 117 && newtile.Type == 25)
                    {
                        tile.type = 25;
                        changed   = true;
                    }
                    else if (tile.type == 25 && newtile.Type == 117)
                    {
                        tile.type = 117;
                        changed   = true;
                    }
                    else if (tile.type == 2 && newtile.Type == 23)
                    {
                        tile.type = 23;
                        changed   = true;
                    }
                    else if (tile.type == 2 && newtile.Type == 109)
                    {
                        tile.type = 109;
                        changed   = true;
                    }
                    else if (tile.type == 23 && newtile.Type == 109)
                    {
                        tile.type = 109;
                        changed   = true;
                    }
                    else if (tile.type == 109 && newtile.Type == 23)
                    {
                        tile.type = 23;
                        changed   = true;
                    }
                    else if (tile.type == 23 && newtile.Type == 109)
                    {
                        tile.type = 109;
                        changed   = true;
                    }
                    else if (tile.type == 53 && newtile.Type == 116)
                    {
                        tile.type = 116;
                        changed   = true;
                    }
                    else if (tile.type == 53 && newtile.Type == 112)
                    {
                        tile.type = 112;
                        changed   = true;
                    }
                    else if (tile.type == 112 && newtile.Type == 116)
                    {
                        tile.type = 116;
                        changed   = true;
                    }
                    else if (tile.type == 116 && newtile.Type == 112)
                    {
                        tile.type = 112;
                        changed   = true;
                    }
                    else if (tile.type == 112 && newtile.Type == 53)
                    {
                        tile.type = 53;
                        changed   = true;
                    }
                    else if (tile.type == 109 && newtile.Type == 2)
                    {
                        tile.type = 2;
                        changed   = true;
                    }
                    else if (tile.type == 116 && newtile.Type == 53)
                    {
                        tile.type = 53;
                        changed   = true;
                    }
                    else if (tile.type == 117 && newtile.Type == 1)
                    {
                        tile.type = 1;
                        changed   = true;
                    }
                }
            }

            if (changed)
            {
                TSPlayer.All.SendTileSquare(tileX, tileY, size);
                WorldGen.RangeFrame(tileX, tileY, tileX + size, tileY + size);
            }
            return(true);
        }
示例#13
0
        private static bool HandleSendTileSquare(GetDataHandlerArgs args)
        {
            short size  = args.Data.ReadInt16();
            int   tilex = args.Data.ReadInt32();
            int   tiley = args.Data.ReadInt32();

            if (size > 5)
            {
                return(true);
            }

            var tiles = new NetTile[size, size];

            for (int x = 0; x < size; x++)
            {
                for (int y = 0; y < size; y++)
                {
                    tiles[x, y] = new NetTile(args.Data);
                }
            }

            bool changed = false;

            for (int x = 0; x < size; x++)
            {
                int realx = tilex + x;
                if (realx < 0 || realx >= Main.maxTilesX)
                {
                    continue;
                }

                for (int y = 0; y < size; y++)
                {
                    int realy = tiley + y;
                    if (realy < 0 || realy >= Main.maxTilesY)
                    {
                        continue;
                    }

                    var tile    = Main.tile[realx, realy];
                    var newtile = tiles[x, y];

                    if (tile.type == 0x17 && newtile.Type == 0x2)
                    {
                        tile.type = 0x2;
                        changed   = true;
                    }
                    else if (tile.type == 0x19 && newtile.Type == 0x1)
                    {
                        tile.type = 0x1;
                        changed   = true;
                    }
                    else if ((tile.type == 0xF && newtile.Type == 0xF) ||
                             (tile.type == 0x4F && newtile.Type == 0x4F))
                    {
                        tile.frameX = newtile.FrameX;
                        tile.frameY = newtile.FrameY;
                        changed     = true;
                    }
                }
            }

            if (changed)
            {
                TSPlayer.All.SendTileSquare(tilex, tiley, 3);
            }

            return(true);
        }
示例#14
0
 public override void Read(IStarboundStream stream)
 {
     Position = Vec2I.FromStream(stream);
     NetTile  = NetTile.FromStream(stream);
     //NetTile = stream.
 }