public static Color GetTileColor(Tile tile, Color background, bool showWall = true, bool showTile = true, bool showLiquid = true, bool showWire = true) { var c = new Color(0, 0, 0, 0); if (tile.Wall > 0 && showWall) if (World.WallProperties.Count > tile.Wall) c = c.AlphaBlend(World.WallProperties[tile.Wall].Color); else c = c.AlphaBlend(Color.Magenta); // Add out-of-range colors else c = background; if (tile.IsActive && showTile) { if (World.TileProperties.Count > tile.Type) c = c.AlphaBlend(World.TileProperties[tile.Type].Color); else c = c.AlphaBlend(Color.Magenta); // Add out-of-range colors } if (tile.Liquid > 0 && showLiquid) c = c.AlphaBlend(tile.IsLava ? World.GlobalColors["Lava"] : World.GlobalColors["Water"]); if (tile.HasWire && showWire) c = c.AlphaBlend(World.GlobalColors["Wire"]); return c; }
public static int SaveTiles(Tile[,] tiles, int maxX, int maxY, BinaryWriter bw) { for (int x = 0; x < maxX; x++) { OnProgressChanged(null, new ProgressChangedEventArgs(x.ProgressPercentage(maxX), "Saving Tiles...")); for (int y = 0; y < maxY; y++) { Tile tile = tiles[x, y]; int dataIndex; int headerIndex; byte[] tileData = SerializeTileData(tile, out dataIndex, out headerIndex); // rle compression byte header1 = tileData[headerIndex]; short rle = 0; int nextY = y + 1; int remainingY = maxY - y - 1; while (remainingY > 0 && tile.Equals(tiles[x, nextY])) { rle = (short)(rle + 1); remainingY--; nextY++; } y = y + rle; if (rle > 0) { tileData[dataIndex++] = (byte)(rle & 255); if (rle <= 255) { // set bit[6] of header1 for byte size rle header1 = (byte)(header1 | 64); } else { // set bit[7] of header1 for int16 size rle header1 = (byte)(header1 | 128); // grab the upper half of the int16 and stick it in tiledata tileData[dataIndex++] = (byte)((rle & 65280) >> 8); } } tileData[headerIndex] = header1; // end rle compression bw.Write(tileData, headerIndex, dataIndex - headerIndex); } } return (int)bw.BaseStream.Position; }
private bool CheckTileMatch(ref Tile originTile, ref Tile nextTile) { switch (_wvm.TilePicker.PaintMode) { case PaintMode.TileAndWall: if ((originTile.Type != nextTile.Type || originTile.IsActive != nextTile.IsActive) && _wvm.TilePicker.TileStyleActive) return false; if (originTile.Wall != nextTile.Wall && _wvm.TilePicker.WallStyleActive) return false; if (originTile.BrickStyle != nextTile.BrickStyle && _wvm.TilePicker.BrickStyleActive) return false; if (_wvm.TilePicker.TilePaintActive && (originTile.Type != nextTile.Type || originTile.IsActive != nextTile.IsActive)) return false; if (_wvm.TilePicker.WallPaintActive && (originTile.Wall != nextTile.Wall || (originTile.IsActive && World.TileProperties[originTile.Type].IsSolid) || (nextTile.IsActive && World.TileProperties[nextTile.Type].IsSolid))) return false; if (_wvm.TilePicker.ExtrasActive) return false; break; case PaintMode.Wire: return false; case PaintMode.Liquid: if ((originTile.LiquidAmount > 0 != nextTile.LiquidAmount > 0) || originTile.LiquidType != nextTile.LiquidType || (originTile.IsActive && World.TileProperties[originTile.Type].IsSolid) || (nextTile.IsActive && World.TileProperties[nextTile.Type].IsSolid)) return false; break; } return true; }
public static void AppendTileFlagsFromByte(ref Tile tile, byte flags) { if ((flags & (byte)TileFlags.IsActive) == (byte)TileFlags.IsActive) tile.IsActive = true; if ((flags & (byte)TileFlags.IsLava) == (byte)TileFlags.IsLava) tile.IsLava = true; if ((flags & (byte)TileFlags.HasWire) == (byte)TileFlags.HasWire) tile.HasWire = true; if ((flags & (byte)TileFlags.IsHoney) == (byte)TileFlags.IsHoney) tile.IsHoney = true; if ((flags & (byte)TileFlags.HasWire2) == (byte)TileFlags.HasWire2) tile.HasWire2 = true; if ((flags & (byte)TileFlags.HasWire3) == (byte)TileFlags.HasWire3) tile.HasWire3 = true; if ((flags & (byte)TileFlags.Actuator) == (byte)TileFlags.Actuator) tile.Actuator = true; if ((flags & (byte)TileFlags.InActive) == (byte)TileFlags.InActive) tile.InActive = true; }
public static Color GetTileColor(Tile tile, Color background, bool showWall = true, bool showTile = true, bool showLiquid = true, bool showRedWire = true, bool showBlueWire = true, bool showGreenWire = true, bool showYellowWire = true) { var c = new Color(0, 0, 0, 0); if (tile.Wall > 0 && showWall) { if (tile.WallColor > 0 && (!showTile || tile.TileColor == 0)) c = c.AlphaBlend(World.PaintProperties[tile.WallColor].Color); else if (World.WallProperties.Count > tile.Wall) { if (World.WallProperties[tile.Wall].Color.A != 0) c = c.AlphaBlend(World.WallProperties[tile.Wall].Color); else c = background; } else c = c.AlphaBlend(Color.Magenta); // Add out-of-range colors } else c = background; if (tile.IsActive && showTile) { if (tile.TileColor > 0) c = c.AlphaBlend(World.PaintProperties[tile.TileColor].Color); else if (World.TileProperties.Count > tile.Type) c = c.AlphaBlend(World.TileProperties[tile.Type].Color); else c = c.AlphaBlend(Color.Magenta); // Add out-of-range colors } if (tile.LiquidAmount > 0 && showLiquid) { if (tile.LiquidType == LiquidType.Lava) c = c.AlphaBlend(World.GlobalColors["Lava"]); else if (tile.LiquidType == LiquidType.Honey) c = c.AlphaBlend(World.GlobalColors["Honey"]); else c = c.AlphaBlend(World.GlobalColors["Water"]); } if (tile.WireRed && showRedWire) { c = c.AlphaBlend(World.GlobalColors["Wire"]); } if (tile.WireGreen && showGreenWire) { c = c.AlphaBlend(World.GlobalColors["Wire2"]); } if (tile.WireBlue && showBlueWire) { c = c.AlphaBlend(World.GlobalColors["Wire1"]); } if (tile.WireYellow && showYellowWire) { c = c.AlphaBlend(World.GlobalColors["Wire3"]); } return c; }
public static void AppendTileFlagsFromByte(ref Tile tile, byte flags) { if ((flags & (byte)TileFlags.IsActive) == (byte)TileFlags.IsActive) tile.IsActive = true; if ((flags & (byte)TileFlags.IsLava) == (byte)TileFlags.IsLava) tile.IsLava = true; if ((flags & (byte)TileFlags.HasWire) == (byte)TileFlags.HasWire) tile.HasWire = true; }
public void Add(Vector2Int32 location, Tile tile) { var undoTile = new UndoTile(location, tile); if (undoTile == null) { throw new Exception("Null undo?"); } lock (UndoSaveLock) { UndoTiles.Add(undoTile); LastTile = undoTile; } if (UndoTiles.Count > FlushSize) { Flush(); } }
public void FixChand(int x, int y) { int newPosition = 0; int type = Tiles[x, y].Type; if (Tiles[x, y].IsActive) { if (type == 35) { newPosition = 1; } if (type == 36) { newPosition = 2; } if (type == 170) { newPosition = 3; } if (type == 171) { newPosition = 4; } if (type == 172) { newPosition = 5; } } if (newPosition > 0) { int xShift = x; int yShift = y; xShift = Tiles[x, y].U/18; while (xShift >= 3) { xShift = xShift - 3; } if (xShift >= 3) { xShift = xShift - 3; } xShift = x - xShift; yShift = yShift + Tiles[x, y].V/18*-1; for (int x1 = xShift; x1 < xShift + 3; x1++) { for (int y1 = yShift; y1 < yShift + 3; y1++) { if (Tiles[x1, y1] == null) { Tiles[x1, y1] = new Tile(); } if (Tiles[x1, y1].IsActive && Tiles[x1, y1].Type == type) { Tiles[x1, y1].Type = 34; Tiles[x1, y1].V = (short) (Tiles[x1, y1].V + newPosition*54); } } } } }
/* Heathtech */ //Pretty much overwrote this whole function. The original part is still intact, but much more hidden private void DrawSprites() { Rectangle visibleBounds = GetViewingArea(); TEditXna.Terraria.Objects.BlendRules blendRules = TEditXna.Terraria.Objects.BlendRules.Instance; if (visibleBounds.Height * visibleBounds.Width < 25000) { //Extended the viewing space to give tiles time to cache their UV's for (int y = visibleBounds.Top - 1; y < visibleBounds.Bottom + 2; y++) { for (int x = visibleBounds.Left - 1; x < visibleBounds.Right + 2; x++) { if (x < 0 || y < 0 || x >= _wvm.CurrentWorld.TilesWide || y >= _wvm.CurrentWorld.TilesHigh) { continue; } var curtile = _wvm.CurrentWorld.Tiles[x, y]; var tileprop = World.TileProperties[curtile.Type]; //Neighbor tiles are often used when dynamically determining which UV position to render int e = 0, n = 1, w = 2, s = 3, ne = 4, nw = 5, sw = 6, se = 7; Tile[] neighborTile = new Tile[8]; neighborTile[e] = (x + 1) < _wvm.CurrentWorld.TilesWide ? _wvm.CurrentWorld.Tiles[x + 1, y] : null; neighborTile[n] = (y - 1) > 0 ? _wvm.CurrentWorld.Tiles[x, y - 1] : null; neighborTile[w] = (x - 1) > 0 ? _wvm.CurrentWorld.Tiles[x - 1, y] : null; neighborTile[s] = (y + 1) < _wvm.CurrentWorld.TilesHigh ? _wvm.CurrentWorld.Tiles[x, y + 1] : null; neighborTile[ne] = (x + 1) < _wvm.CurrentWorld.TilesWide && (y - 1) > 0 ? _wvm.CurrentWorld.Tiles[x + 1, y - 1] : null; neighborTile[nw] = (x - 1) > 0 && (y - 1) > 0 ? _wvm.CurrentWorld.Tiles[x - 1, y - 1] : null; neighborTile[sw] = (x - 1) > 0 && (y + 1) < _wvm.CurrentWorld.TilesHigh ? _wvm.CurrentWorld.Tiles[x - 1, y + 1] : null; neighborTile[se] = (x + 1) < _wvm.CurrentWorld.TilesWide && (y + 1) < _wvm.CurrentWorld.TilesHigh ? _wvm.CurrentWorld.Tiles[x + 1, y + 1] : null; if (_wvm.ShowWalls) { if (curtile.Wall > 0) { var wallTex = _textureDictionary.GetWall(curtile.Wall); if (wallTex != null) { if (curtile.uvWallCache == 0xFFFF) { int sameStyle = 0x00000000; sameStyle |= (neighborTile[e] != null && neighborTile[e].Wall == curtile.Wall) ? 0x0001 : 0x0000; sameStyle |= (neighborTile[n] != null && neighborTile[n].Wall == curtile.Wall) ? 0x0010 : 0x0000; sameStyle |= (neighborTile[w] != null && neighborTile[w].Wall == curtile.Wall) ? 0x0100 : 0x0000; sameStyle |= (neighborTile[s] != null && neighborTile[s].Wall == curtile.Wall) ? 0x1000 : 0x0000; Vector2Int32 uvBlend = blendRules.GetUVForMasks((uint)sameStyle, 0x00000000, 0); curtile.uvWallCache = (ushort)((uvBlend.Y << 8) + uvBlend.X); } var texsize = new Vector2Int32(32, 32); var source = new Rectangle((curtile.uvWallCache & 0x00FF) * (texsize.X + 4), (curtile.uvWallCache >> 8) * (texsize.Y + 4), texsize.X, texsize.Y); var dest = new Rectangle(1 + (int)((_scrollPosition.X + x - 0.5) * _zoom), 1 + (int)((_scrollPosition.Y + y - 0.5) * _zoom), (int)_zoom * 2, (int)_zoom * 2); _spriteBatch.Draw(wallTex, dest, source, Color.White, 0f, default(Vector2), SpriteEffects.None, 1); } } } if (_wvm.ShowTiles) { if (curtile.IsActive) { if (tileprop.IsFramed) { Rectangle source = new Rectangle(), dest = new Rectangle(); var tileTex = _textureDictionary.GetTile(curtile.Type); bool isTree = false, isMushroom = false; bool isLeft = false, isBase = false, isRight = false; if (curtile.Type == 5 && curtile.U >= 22 && curtile.V >= 198) { isTree = true; switch (curtile.U) { case 22: isBase = true; break; case 44: isLeft = true; break; case 66: isRight = true; break; } //Abuse uvTileCache to remember what type of tree it is, since potentially scanning a hundred of blocks PER tree tile sounds slow int treeType = (curtile.uvTileCache & 0x000F); if (treeType > 4) //Tree type not yet set { //Check tree type treeType = 0; //Default to normal in case no grass grows beneath the tree int baseX = (isLeft) ? 1 : (isRight) ? -1 : 0; for (int i = 0; i < 100; i++) { Tile checkTile = (y + i) < _wvm.CurrentWorld.TilesHigh ? _wvm.CurrentWorld.Tiles[x + baseX, y + i] : null; bool found = true; if (checkTile != null && checkTile.IsActive) { switch (checkTile.Type) { case 2: treeType = 0; break; //Normal case 23: treeType = 1; break; //Corruption case 60: treeType = 2; break; //Jungle case 109: treeType = 3; break; //Hallow case 147: treeType = 4; break; //Snow case 199: treeType = 5; break; //Crimson default: found = false; break; } if (found == true) { curtile.uvTileCache = (ushort)((0x00 << 8) + 0x01 * treeType); break; } } } } if (isBase) { tileTex = (Texture2D)_textureDictionary.GetTreeTops(treeType); } else { tileTex = (Texture2D)_textureDictionary.GetTreeBranches(treeType); } } if (curtile.Type == 72 && curtile.U >= 36) { isMushroom = true; tileTex = (Texture2D)_textureDictionary.GetShroomTop(0); } if (tileTex != null) { if (!isTree && !isMushroom) { source = new Rectangle(curtile.U, curtile.V, tileprop.TextureGrid.X, tileprop.TextureGrid.Y); if (source.Width <= 0) source.Width = 16; if (source.Height <= 0) source.Height = 16; if (source.Bottom > tileTex.Height) source.Height -= (source.Bottom - tileTex.Height); if (source.Right > tileTex.Width) source.Width -= (source.Right - tileTex.Width); if (source.Width <= 0 || source.Height <= 0) continue; dest = new Rectangle(1 + (int)((_scrollPosition.X + x) * _zoom), 1 + (int)((_scrollPosition.Y + y) * _zoom), (int)_zoom, (int)_zoom); var texsize = tileprop.TextureGrid; if (texsize.X != 16 || texsize.Y != 16) { dest.Width = (int)(texsize.X * (_zoom / 16)); dest.Height = (int)(texsize.Y * (_zoom / 16)); var frame = (tileprop.Frames.FirstOrDefault(f => f.UV == new Vector2Short(curtile.U, curtile.V))); var frameAnchor = FrameAnchor.None; if (frame != null) frameAnchor = frame.Anchor; switch (frameAnchor) { case FrameAnchor.None: dest.X += (int)(((16 - texsize.X) / 2F) * _zoom / 16); dest.Y += (int)(((16 - texsize.Y) / 2F) * _zoom / 16); break; case FrameAnchor.Left: //position.X += (16 - texsize.X) / 2; dest.Y += (int)(((16 - texsize.Y) / 2F) * _zoom / 16); break; case FrameAnchor.Right: dest.X += (int)((16 - texsize.X) * _zoom / 16); dest.Y += (int)(((16 - texsize.Y) / 2F) * _zoom / 16); break; case FrameAnchor.Top: dest.X += (int)(((16 - texsize.X) / 2F) * _zoom / 16); //position.Y += (16 - texsize.Y); break; case FrameAnchor.Bottom: dest.X += (int)(((16 - texsize.X) / 2F) * _zoom / 16); dest.Y += (int)((16 - texsize.Y) * _zoom / 16); break; } } } else if (isTree) { source = new Rectangle(0, 0, 40, 40); dest = new Rectangle(1 + (int)((_scrollPosition.X + x) * _zoom), 1 + (int)((_scrollPosition.Y + y) * _zoom), (int)_zoom, (int)_zoom); FrameAnchor frameAnchor = FrameAnchor.None; int treeType = (curtile.uvTileCache & 0x000F); if (isBase) { switch (treeType) { case 0: case 1: case 4: source.Width = 80; source.Height = 80; break; case 2: source.Width = 114; source.Height = 96; break; case 3: source.X = (x % 3) * (82 * 3); source.Width = 80; source.Height = 140; break; } source.X += ((curtile.V - 198) / 22) * (source.Width + 2); frameAnchor = FrameAnchor.Bottom; } else if (isLeft) { source.X = 0; switch (treeType) { case 3: source.Y = (x % 3) * (42 * 3); break; } frameAnchor = FrameAnchor.Right; source.Y += ((curtile.V - 198) / 22) * (source.Height + 2); } else if (isRight) { source.X = 42; switch (treeType) { case 3: source.Y = (x % 3) * (42 * 3); break; } frameAnchor = FrameAnchor.Left; source.Y += ((curtile.V - 198) / 22) * (source.Height + 2); } dest.Width = (int)(_zoom * source.Width / 16f); dest.Height = (int)(_zoom * source.Height / 16f); switch (frameAnchor) { case FrameAnchor.None: dest.X += (int)(((16 - source.Width) / 2F) * _zoom / 16); dest.Y += (int)(((16 - source.Height) / 2F) * _zoom / 16); break; case FrameAnchor.Left: dest.Y += (int)(((16 - source.Height) / 2F) * _zoom / 16); break; case FrameAnchor.Right: dest.X += (int)((16 - source.Width) * _zoom / 16); dest.Y += (int)(((16 - source.Height) / 2F) * _zoom / 16); break; case FrameAnchor.Top: dest.X += (int)(((16 - source.Width) / 2F) * _zoom / 16); break; case FrameAnchor.Bottom: dest.X += (int)(((16 - source.Width) / 2F) * _zoom / 16); dest.Y += (int)((16 - source.Height) * _zoom / 16); break; } } else if (isMushroom) { source = new Rectangle(0, 0, 60, 42); dest = new Rectangle(1 + (int)((_scrollPosition.X + x) * _zoom), 1 + (int)((_scrollPosition.Y + y) * _zoom), (int)_zoom, (int)_zoom); source.X = (curtile.V / 18) * 62; dest.Width = (int)(_zoom * source.Width / 16f); dest.Height = (int)(_zoom * source.Height / 16f); dest.X += (int)(((16 - source.Width) / 2F) * _zoom / 16); dest.Y += (int)((16 - source.Height) * _zoom / 16); } _spriteBatch.Draw(tileTex, dest, source, Color.White, 0f, default(Vector2), SpriteEffects.None, 0); } } else if (tileprop.IsPlatform) { var tileTex = _textureDictionary.GetTile(curtile.Type); if (tileTex != null) { Vector2Int32 uv; if (curtile.uvTileCache == 0xFFFF) { uv = new Vector2Int32(0, 0); byte state = 0x00; state |= (byte)((neighborTile[w] != null && neighborTile[w].IsActive && neighborTile[w].Type == curtile.Type) ? 0x01 : 0x00); state |= (byte)((neighborTile[w] != null && neighborTile[w].IsActive && World.TileProperties[neighborTile[w].Type].IsSolid && neighborTile[w].Type != curtile.Type) ? 0x02 : 0x00); state |= (byte)((neighborTile[e] != null && neighborTile[e].IsActive && neighborTile[e].Type == curtile.Type) ? 0x04 : 0x00); state |= (byte)((neighborTile[e] != null && neighborTile[e].IsActive && World.TileProperties[neighborTile[e].Type].IsSolid && neighborTile[e].Type != curtile.Type) ? 0x08 : 0x00); switch (state) { case 0x00: case 0x0A: uv.X = 5; break; case 0x01: uv.X = 1; break; case 0x02: uv.X = 6; break; case 0x04: uv.X = 2; break; case 0x05: uv.X = 0; break; case 0x06: uv.X = 3; break; case 0x08: uv.X = 7; break; case 0x09: uv.X = 4; break; } uv.Y = blendRules.randomVariation.Next(3); curtile.uvTileCache = (ushort)((uv.Y << 8) + uv.X); } var texsize = new Vector2Int32(tileprop.TextureGrid.X, tileprop.TextureGrid.Y); if (texsize.X == 0 || texsize.Y == 0) { texsize = new Vector2Int32(16, 16); } var source = new Rectangle((curtile.uvTileCache & 0x00FF) * (texsize.X + 2), (curtile.uvTileCache >> 8) * (texsize.Y + 2), texsize.X, texsize.Y); var dest = new Rectangle(1 + (int)((_scrollPosition.X + x) * _zoom), 1 + (int)((_scrollPosition.Y + y) * _zoom), (int)_zoom, (int)_zoom); _spriteBatch.Draw(tileTex, dest, source, Color.White, 0f, default(Vector2), SpriteEffects.None, 0); } } else if (tileprop.IsCactus) { var tileTex = _textureDictionary.GetTile(curtile.Type); if ((curtile.uvTileCache & 0x00FF) >= 16) { tileTex = (Texture2D)_textureDictionary.GetMisc("Evil_Cactus"); } else if ((curtile.uvTileCache & 0x00FF) >= 8) { tileTex = (Texture2D)_textureDictionary.GetMisc("Good_Cactus"); } if (tileTex != null) { Vector2Int32 uv; if (curtile.uvTileCache == 0xFFFF || curtile.hasLazyChecked == false) { bool isLeft = false, isRight = false, isBase = false; //Has this cactus been base-evaluated yet? int neighborX = (neighborTile[w].uvTileCache & 0x00FF) % 8; //Why % 8? If X >= 8, use hallow, If X >= 16, use corruption if (neighborX == 0 || neighborX == 1 || neighborX == 4 || neighborX == 5) { isRight = true; } neighborX = neighborTile[e].uvTileCache & 0x00FF; if (neighborX == 0 || neighborX == 1 || neighborX == 4 || neighborX == 5) { isLeft = true; } neighborX = curtile.uvTileCache & 0x00FF; if (neighborX == 0 || neighborX == 1 || neighborX == 4 || neighborX == 5) { isBase = true; } //Evaluate Base if (isLeft == false && isRight == false && isBase == false) { int length1 = 0; int length2 = 0; while (true) { Tile checkTile = (y + length1) < _wvm.CurrentWorld.TilesHigh ? _wvm.CurrentWorld.Tiles[x, y + length1] : null; if (checkTile == null || checkTile.IsActive == false || checkTile.Type != curtile.Type) { break; } length1++; } if (x + 1 < _wvm.CurrentWorld.TilesWide) { while (true) { Tile checkTile = (y + length2) < _wvm.CurrentWorld.TilesHigh ? _wvm.CurrentWorld.Tiles[x + 1, y + length2] : null; if (checkTile == null || checkTile.IsActive == false || checkTile.Type != curtile.Type) { break; } length2++; } } int baseX = 0; int baseY = length1; isBase = true; if (length2 >= length1) { baseX = 1; baseY = length2; isBase = false; isLeft = true; } for (int cy = y; cy < y + baseY; cy++) { if (_wvm.CurrentWorld.Tiles[x + baseX, cy].uvTileCache == 0xFFFF) { if (cy == y) { _wvm.CurrentWorld.Tiles[x + baseX, cy].uvTileCache = 0x00 << 8 + 0x00; } else { _wvm.CurrentWorld.Tiles[x + baseX, cy].uvTileCache = 0x01 << 8 + 0x00; } } } } uv = new Vector2Int32(0, 0); byte state = 0x00; state |= (byte)((neighborTile[e] != null && neighborTile[e].IsActive && neighborTile[e].Type == curtile.Type) ? 0x01 : 0x00); state |= (byte)((neighborTile[n] != null && neighborTile[n].IsActive && neighborTile[n].Type == curtile.Type) ? 0x02 : 0x00); state |= (byte)((neighborTile[w] != null && neighborTile[w].IsActive && neighborTile[w].Type == curtile.Type) ? 0x04 : 0x00); state |= (byte)((neighborTile[s] != null && neighborTile[s].IsActive && neighborTile[s].Type == curtile.Type) ? 0x08 : 0x00); //state |= (byte)((neighborTile[ne] != null && neighborTile[ne].IsActive && neighborTile[ne].Type == curtile.Type) ? 0x10 : 0x00); //state |= (byte)((neighborTile[nw] != null && neighborTile[nw].IsActive && neighborTile[nw].Type == curtile.Type) ? 0x20 : 0x00); state |= (byte)((neighborTile[sw] != null && neighborTile[sw].IsActive && neighborTile[sw].Type == curtile.Type) ? 0x40 : 0x00); state |= (byte)((neighborTile[se] != null && neighborTile[se].IsActive && neighborTile[se].Type == curtile.Type) ? 0x80 : 0x00); if (isLeft) { uv.X = 3; if ((state & 0x08) != 0x00) //s { if ((state & 0x02) != 0x00) //n { uv.Y = 1; } else //!n { uv.Y = 0; } } else //!s { if ((state & 0x02) != 0x00) //n { uv.Y = 2; } else //!n { uv.X = 6; uv.Y = 2; } } } if (isRight) { uv.X = 2; if ((state & 0x08) != 0x00) //s { if ((state & 0x02) != 0x00) //n { uv.Y = 1; } else //!n { uv.Y = 0; } } else //!s { if ((state & 0x02) != 0x00) //n { uv.Y = 2; } else //!n { uv.X = 6; uv.Y = 1; } } } if (isBase) { if ((state & 0x02) != 0x00) //n { uv.Y = 2; if ((state & 0x04) != 0x00 && (state & 0x40) == 0x00 && ((state & 0x01) == 0x00 || (state & 0x80) != 0x00)) //w !sw (!e or se) { uv.X = 4; } else if ((state & 0x01) != 0x00 && (state & 0x80) == 0x00 && ((state & 0x04) == 0x00 || (state & 0x40) != 0x00)) //e !se (!w or sw) { uv.X = 1; } else if ((state & 0x04) != 0x00 && (state & 0x40) == 0x00 && (state & 0x01) != 0x00 && (state & 0x80) == 0x00) //w !sw e !se { uv.X = 5; } else { uv.X = 0; uv.Y = 1; } } else //!n { uv.Y = 0; if ((state & 0x04) != 0x00 && (state & 0x40) == 0x00 && ((state & 0x01) == 0x00 || (state & 0x80) != 0x00)) //w !sw (!e or se) { uv.X = 4; } else if ((state & 0x01) != 0x00 && (state & 0x80) == 0x00 && ((state & 0x04) == 0x00 || (state & 0x40) != 0x00)) //e !se (!w or sw) { uv.X = 1; } else if ((state & 0x04) != 0x00 && (state & 0x40) == 0x00 && (state & 0x01) != 0x00 && (state & 0x80) == 0x00) //w !sw e !se { uv.X = 5; } else { uv.X = 0; uv.Y = 0; } } } //Check if cactus is good or evil for (int i = 0; i < 100; i++) { int baseX = (isLeft) ? 1 : (isRight) ? -1 : 0; Tile checkTile = (y + i) < _wvm.CurrentWorld.TilesHigh ? _wvm.CurrentWorld.Tiles[x + baseX, y + i] : null; if (checkTile != null && checkTile.IsActive && checkTile.Type == 112) //Corruption { uv.X += 16; break; } else if (checkTile != null && checkTile.IsActive && checkTile.Type == 116) //Hallow { uv.X += 8; break; } } curtile.hasLazyChecked = true; curtile.uvTileCache = (ushort)((uv.Y << 8) + uv.X); } var texsize = new Vector2Int32(tileprop.TextureGrid.X, tileprop.TextureGrid.Y); if (texsize.X == 0 || texsize.Y == 0) { texsize = new Vector2Int32(16, 16); } var source = new Rectangle(((curtile.uvTileCache & 0x00FF) % 8) * (texsize.X + 2), (curtile.uvTileCache >> 8) * (texsize.Y + 2), texsize.X, texsize.Y); var dest = new Rectangle(1 + (int)((_scrollPosition.X + x) * _zoom), 1 + (int)((_scrollPosition.Y + y) * _zoom), (int)_zoom, (int)_zoom); _spriteBatch.Draw(tileTex, dest, source, Color.White, 0f, default(Vector2), SpriteEffects.None, 0); } } else if (tileprop.CanBlend) { var tileTex = _textureDictionary.GetTile(curtile.Type); if (tileTex != null) { if (curtile.uvTileCache == 0xFFFF || curtile.hasLazyChecked == false) { int sameStyle = 0x00000000; int mergeMask = 0x00000000; int strictness = 0; if (tileprop.MergeWith.HasValue && tileprop.MergeWith.Value == -1) //Basically for cobweb { sameStyle |= (neighborTile[e] != null && neighborTile[e].IsActive) ? 0x0001 : 0x0000; sameStyle |= (neighborTile[n] != null && neighborTile[n].IsActive) ? 0x0010 : 0x0000; sameStyle |= (neighborTile[w] != null && neighborTile[w].IsActive) ? 0x0100 : 0x0000; sameStyle |= (neighborTile[s] != null && neighborTile[s].IsActive) ? 0x1000 : 0x0000; } else if (tileprop.IsStone) //Stone & Gems { sameStyle |= (neighborTile[e] != null && neighborTile[e].IsActive && World.TileProperties[neighborTile[e].Type].IsStone) ? 0x0001 : 0x0000; sameStyle |= (neighborTile[n] != null && neighborTile[n].IsActive && World.TileProperties[neighborTile[n].Type].IsStone) ? 0x0010 : 0x0000; sameStyle |= (neighborTile[w] != null && neighborTile[w].IsActive && World.TileProperties[neighborTile[w].Type].IsStone) ? 0x0100 : 0x0000; sameStyle |= (neighborTile[s] != null && neighborTile[s].IsActive && World.TileProperties[neighborTile[s].Type].IsStone) ? 0x1000 : 0x0000; sameStyle |= (neighborTile[ne] != null && neighborTile[ne].IsActive && World.TileProperties[neighborTile[ne].Type].IsStone) ? 0x00010000 : 0x00000000; sameStyle |= (neighborTile[nw] != null && neighborTile[nw].IsActive && World.TileProperties[neighborTile[nw].Type].IsStone) ? 0x00100000 : 0x00000000; sameStyle |= (neighborTile[sw] != null && neighborTile[sw].IsActive && World.TileProperties[neighborTile[sw].Type].IsStone) ? 0x01000000 : 0x00000000; sameStyle |= (neighborTile[se] != null && neighborTile[se].IsActive && World.TileProperties[neighborTile[se].Type].IsStone) ? 0x10000000 : 0x00000000; } else //Everything else { //Join to nearby tiles if their merge type is this tile's type sameStyle |= (neighborTile[e] != null && neighborTile[e].IsActive && World.TileProperties[neighborTile[e].Type].MergeWith.HasValue && World.TileProperties[neighborTile[e].Type].MergeWith.Value == curtile.Type) ? 0x0001 : 0x0000; sameStyle |= (neighborTile[n] != null && neighborTile[n].IsActive && World.TileProperties[neighborTile[n].Type].MergeWith.HasValue && World.TileProperties[neighborTile[n].Type].MergeWith.Value == curtile.Type) ? 0x0010 : 0x0000; sameStyle |= (neighborTile[w] != null && neighborTile[w].IsActive && World.TileProperties[neighborTile[w].Type].MergeWith.HasValue && World.TileProperties[neighborTile[w].Type].MergeWith.Value == curtile.Type) ? 0x0100 : 0x0000; sameStyle |= (neighborTile[s] != null && neighborTile[s].IsActive && World.TileProperties[neighborTile[s].Type].MergeWith.HasValue && World.TileProperties[neighborTile[s].Type].MergeWith.Value == curtile.Type) ? 0x1000 : 0x0000; sameStyle |= (neighborTile[ne] != null && neighborTile[ne].IsActive && World.TileProperties[neighborTile[ne].Type].MergeWith.HasValue && World.TileProperties[neighborTile[ne].Type].MergeWith.Value == curtile.Type) ? 0x00010000 : 0x00000000; sameStyle |= (neighborTile[nw] != null && neighborTile[nw].IsActive && World.TileProperties[neighborTile[nw].Type].MergeWith.HasValue && World.TileProperties[neighborTile[nw].Type].MergeWith.Value == curtile.Type) ? 0x00100000 : 0x00000000; sameStyle |= (neighborTile[sw] != null && neighborTile[sw].IsActive && World.TileProperties[neighborTile[sw].Type].MergeWith.HasValue && World.TileProperties[neighborTile[sw].Type].MergeWith.Value == curtile.Type) ? 0x01000000 : 0x00000000; sameStyle |= (neighborTile[se] != null && neighborTile[se].IsActive && World.TileProperties[neighborTile[se].Type].MergeWith.HasValue && World.TileProperties[neighborTile[se].Type].MergeWith.Value == curtile.Type) ? 0x10000000 : 0x00000000; //Join if nearby tiles have the same type as this tile's type sameStyle |= (neighborTile[e] != null && neighborTile[e].IsActive && curtile.Type == neighborTile[e].Type) ? 0x0001 : 0x0000; sameStyle |= (neighborTile[n] != null && neighborTile[n].IsActive && curtile.Type == neighborTile[n].Type) ? 0x0010 : 0x0000; sameStyle |= (neighborTile[w] != null && neighborTile[w].IsActive && curtile.Type == neighborTile[w].Type) ? 0x0100 : 0x0000; sameStyle |= (neighborTile[s] != null && neighborTile[s].IsActive && curtile.Type == neighborTile[s].Type) ? 0x1000 : 0x0000; sameStyle |= (neighborTile[ne] != null && neighborTile[ne].IsActive && curtile.Type == neighborTile[ne].Type) ? 0x00010000 : 0x00000000; sameStyle |= (neighborTile[nw] != null && neighborTile[nw].IsActive && curtile.Type == neighborTile[nw].Type) ? 0x00100000 : 0x00000000; sameStyle |= (neighborTile[sw] != null && neighborTile[sw].IsActive && curtile.Type == neighborTile[sw].Type) ? 0x01000000 : 0x00000000; sameStyle |= (neighborTile[se] != null && neighborTile[se].IsActive && curtile.Type == neighborTile[se].Type) ? 0x10000000 : 0x00000000; } if (curtile.hasLazyChecked == false) { bool lazyCheckReady = true; lazyCheckReady &= (neighborTile[e] == null || neighborTile[e].IsActive == false || World.TileProperties[neighborTile[e].Type].MergeWith.HasValue == false || World.TileProperties[neighborTile[e].Type].MergeWith.Value != curtile.Type) ? true : (neighborTile[e].lazyMergeId != 0xFF); lazyCheckReady &= (neighborTile[n] == null || neighborTile[n].IsActive == false || World.TileProperties[neighborTile[n].Type].MergeWith.HasValue == false || World.TileProperties[neighborTile[n].Type].MergeWith.Value != curtile.Type) ? true : (neighborTile[n].lazyMergeId != 0xFF); lazyCheckReady &= (neighborTile[w] == null || neighborTile[w].IsActive == false || World.TileProperties[neighborTile[w].Type].MergeWith.HasValue == false || World.TileProperties[neighborTile[w].Type].MergeWith.Value != curtile.Type) ? true : (neighborTile[w].lazyMergeId != 0xFF); lazyCheckReady &= (neighborTile[s] == null || neighborTile[s].IsActive == false || World.TileProperties[neighborTile[s].Type].MergeWith.HasValue == false || World.TileProperties[neighborTile[s].Type].MergeWith.Value != curtile.Type) ? true : (neighborTile[s].lazyMergeId != 0xFF); if (lazyCheckReady) { sameStyle &= 0x11111110 | ((neighborTile[e] == null || neighborTile[e].IsActive == false || World.TileProperties[neighborTile[e].Type].MergeWith.HasValue == false || World.TileProperties[neighborTile[e].Type].MergeWith.Value != curtile.Type) ? 0x00000001 : ((neighborTile[e].lazyMergeId & 0x04) >> 2)); sameStyle &= 0x11111101 | ((neighborTile[n] == null || neighborTile[n].IsActive == false || World.TileProperties[neighborTile[n].Type].MergeWith.HasValue == false || World.TileProperties[neighborTile[n].Type].MergeWith.Value != curtile.Type) ? 0x00000010 : ((neighborTile[n].lazyMergeId & 0x08) << 1)); sameStyle &= 0x11111011 | ((neighborTile[w] == null || neighborTile[w].IsActive == false || World.TileProperties[neighborTile[w].Type].MergeWith.HasValue == false || World.TileProperties[neighborTile[w].Type].MergeWith.Value != curtile.Type) ? 0x00000100 : ((neighborTile[w].lazyMergeId & 0x01) << 8)); sameStyle &= 0x11110111 | ((neighborTile[s] == null || neighborTile[s].IsActive == false || World.TileProperties[neighborTile[s].Type].MergeWith.HasValue == false || World.TileProperties[neighborTile[s].Type].MergeWith.Value != curtile.Type) ? 0x00001000 : ((neighborTile[s].lazyMergeId & 0x02) << 11)); curtile.hasLazyChecked = true; } } if (tileprop.MergeWith.HasValue && tileprop.MergeWith.Value > -1) //Merges with a specific type { mergeMask |= (neighborTile[e] != null && neighborTile[e].IsActive && neighborTile[e].Type == tileprop.MergeWith.Value) ? 0x0001 : 0x0000; mergeMask |= (neighborTile[n] != null && neighborTile[n].IsActive && neighborTile[n].Type == tileprop.MergeWith.Value) ? 0x0010 : 0x0000; mergeMask |= (neighborTile[w] != null && neighborTile[w].IsActive && neighborTile[w].Type == tileprop.MergeWith.Value) ? 0x0100 : 0x0000; mergeMask |= (neighborTile[s] != null && neighborTile[s].IsActive && neighborTile[s].Type == tileprop.MergeWith.Value) ? 0x1000 : 0x0000; mergeMask |= (neighborTile[ne] != null && neighborTile[ne].IsActive && neighborTile[ne].Type == tileprop.MergeWith.Value) ? 0x00010000 : 0x00000000; mergeMask |= (neighborTile[nw] != null && neighborTile[nw].IsActive && neighborTile[nw].Type == tileprop.MergeWith.Value) ? 0x00100000 : 0x00000000; mergeMask |= (neighborTile[sw] != null && neighborTile[sw].IsActive && neighborTile[sw].Type == tileprop.MergeWith.Value) ? 0x01000000 : 0x00000000; mergeMask |= (neighborTile[se] != null && neighborTile[se].IsActive && neighborTile[se].Type == tileprop.MergeWith.Value) ? 0x10000000 : 0x00000000; strictness = 1; } if (tileprop.IsGrass) { strictness = 2; } Vector2Int32 uvBlend = blendRules.GetUVForMasks((uint)sameStyle, (uint)mergeMask, strictness); curtile.uvTileCache = (ushort)((uvBlend.Y << 8) + uvBlend.X); curtile.lazyMergeId = blendRules.lazyMergeValidation[uvBlend.Y, uvBlend.X]; } var texsize = new Vector2Int32(tileprop.TextureGrid.X, tileprop.TextureGrid.Y); if (texsize.X == 0 || texsize.Y == 0) { texsize = new Vector2Int32(16, 16); } var source = new Rectangle((curtile.uvTileCache & 0x00FF) * (texsize.X + 2), (curtile.uvTileCache >> 8) * (texsize.Y + 2), texsize.X, texsize.Y); var dest = new Rectangle(1 + (int)((_scrollPosition.X + x) * _zoom), 1 + (int)((_scrollPosition.Y + y) * _zoom), (int)_zoom, (int)_zoom); _spriteBatch.Draw(tileTex, dest, source, Color.White, 0f, default(Vector2), SpriteEffects.None, 0); } } } } if (_wvm.ShowWires) { if (curtile.HasWire) { var tileTex = (Texture2D)_textureDictionary.GetMisc("Wires"); if (tileTex != null) { var source = new Rectangle(0, 0, 16, 16); var dest = new Rectangle(1 + (int)((_scrollPosition.X + x) * _zoom), 1 + (int)((_scrollPosition.Y + y) * _zoom), (int)_zoom, (int)_zoom); byte state = 0x00; state |= (byte)((neighborTile[e] != null && neighborTile[e].HasWire == true) ? 0x01 : 0x00); state |= (byte)((neighborTile[n] != null && neighborTile[n].HasWire == true) ? 0x02 : 0x00); state |= (byte)((neighborTile[w] != null && neighborTile[w].HasWire == true) ? 0x04 : 0x00); state |= (byte)((neighborTile[s] != null && neighborTile[s].HasWire == true) ? 0x08 : 0x00); Vector2Int32 uv = new Vector2Int32(0, 0); switch (state) { case 0x00: uv.X = 0; uv.Y = 3; break; case 0x01: uv.X = 4; uv.Y = 2; break; case 0x02: uv.X = 2; uv.Y = 2; break; case 0x03: uv.X = 2; uv.Y = 1; break; case 0x04: uv.X = 3; uv.Y = 2; break; case 0x05: uv.X = 1; uv.Y = 0; break; case 0x06: uv.X = 3; uv.Y = 1; break; case 0x07: uv.X = 0; uv.Y = 1; break; case 0x08: uv.X = 1; uv.Y = 2; break; case 0x09: uv.X = 0; uv.Y = 2; break; case 0x0A: uv.X = 0; uv.Y = 0; break; case 0x0B: uv.X = 2; uv.Y = 0; break; case 0x0C: uv.X = 4; uv.Y = 1; break; case 0x0D: uv.X = 4; uv.Y = 0; break; case 0x0E: uv.X = 3; uv.Y = 0; break; case 0x0F: uv.X = 1; uv.Y = 1; break; } source.X = uv.X * (source.Width + 2); source.Y = uv.Y * (source.Height + 2); _spriteBatch.Draw(tileTex, dest, source, Color.White, 0f, default(Vector2), SpriteEffects.None, 0); } } if (curtile.HasWire2) { var tileTex = (Texture2D)_textureDictionary.GetMisc("Wires2"); if (tileTex != null) { var source = new Rectangle(0, 0, 16, 16); var dest = new Rectangle(1 + (int)((_scrollPosition.X + x) * _zoom), 1 + (int)((_scrollPosition.Y + y) * _zoom), (int)_zoom, (int)_zoom); byte state = 0x00; state |= (byte)((neighborTile[e] != null && neighborTile[e].HasWire2 == true) ? 0x01 : 0x00); state |= (byte)((neighborTile[n] != null && neighborTile[n].HasWire2 == true) ? 0x02 : 0x00); state |= (byte)((neighborTile[w] != null && neighborTile[w].HasWire2 == true) ? 0x04 : 0x00); state |= (byte)((neighborTile[s] != null && neighborTile[s].HasWire2 == true) ? 0x08 : 0x00); Vector2Int32 uv = new Vector2Int32(0, 0); switch (state) { case 0x00: uv.X = 0; uv.Y = 3; break; case 0x01: uv.X = 4; uv.Y = 2; break; case 0x02: uv.X = 2; uv.Y = 2; break; case 0x03: uv.X = 2; uv.Y = 1; break; case 0x04: uv.X = 3; uv.Y = 2; break; case 0x05: uv.X = 1; uv.Y = 0; break; case 0x06: uv.X = 3; uv.Y = 1; break; case 0x07: uv.X = 0; uv.Y = 1; break; case 0x08: uv.X = 1; uv.Y = 2; break; case 0x09: uv.X = 0; uv.Y = 2; break; case 0x0A: uv.X = 0; uv.Y = 0; break; case 0x0B: uv.X = 2; uv.Y = 0; break; case 0x0C: uv.X = 4; uv.Y = 1; break; case 0x0D: uv.X = 4; uv.Y = 0; break; case 0x0E: uv.X = 3; uv.Y = 0; break; case 0x0F: uv.X = 1; uv.Y = 1; break; } source.X = uv.X * (source.Width + 2); source.Y = uv.Y * (source.Height + 2); _spriteBatch.Draw(tileTex, dest, source, Color.White, 0f, default(Vector2), SpriteEffects.None, 0); } } if (curtile.HasWire3) { var tileTex = (Texture2D)_textureDictionary.GetMisc("Wires3"); if (tileTex != null) { var source = new Rectangle(0, 0, 16, 16); var dest = new Rectangle(1 + (int)((_scrollPosition.X + x) * _zoom), 1 + (int)((_scrollPosition.Y + y) * _zoom), (int)_zoom, (int)_zoom); byte state = 0x00; state |= (byte)((neighborTile[e] != null && neighborTile[e].HasWire3 == true) ? 0x01 : 0x00); state |= (byte)((neighborTile[n] != null && neighborTile[n].HasWire3 == true) ? 0x02 : 0x00); state |= (byte)((neighborTile[w] != null && neighborTile[w].HasWire3 == true) ? 0x04 : 0x00); state |= (byte)((neighborTile[s] != null && neighborTile[s].HasWire3 == true) ? 0x08 : 0x00); Vector2Int32 uv = new Vector2Int32(0, 0); switch (state) { case 0x00: uv.X = 0; uv.Y = 3; break; case 0x01: uv.X = 4; uv.Y = 2; break; case 0x02: uv.X = 2; uv.Y = 2; break; case 0x03: uv.X = 2; uv.Y = 1; break; case 0x04: uv.X = 3; uv.Y = 2; break; case 0x05: uv.X = 1; uv.Y = 0; break; case 0x06: uv.X = 3; uv.Y = 1; break; case 0x07: uv.X = 0; uv.Y = 1; break; case 0x08: uv.X = 1; uv.Y = 2; break; case 0x09: uv.X = 0; uv.Y = 2; break; case 0x0A: uv.X = 0; uv.Y = 0; break; case 0x0B: uv.X = 2; uv.Y = 0; break; case 0x0C: uv.X = 4; uv.Y = 1; break; case 0x0D: uv.X = 4; uv.Y = 0; break; case 0x0E: uv.X = 3; uv.Y = 0; break; case 0x0F: uv.X = 1; uv.Y = 1; break; } source.X = uv.X * (source.Width + 2); source.Y = uv.Y * (source.Height + 2); _spriteBatch.Draw(tileTex, dest, source, Color.White, 0f, default(Vector2), SpriteEffects.None, 0); } } } if (_wvm.ShowLiquid) { if (curtile.Liquid > 0) { Texture2D tileTex = null; if (curtile.IsLava) { tileTex = (Texture2D)_textureDictionary.GetLiquid(1); } else if (curtile.IsHoney) { tileTex = (Texture2D)_textureDictionary.GetLiquid(11); // Not sure if yellow Desert water, or Honey, but looks fine. } else { tileTex = (Texture2D)_textureDictionary.GetLiquid(0); } if (tileTex != null) { var source = new Rectangle(0, 0, 16, 16); var dest = new Rectangle(1 + (int)((_scrollPosition.X + x) * _zoom), 1 + (int)((_scrollPosition.Y + y) * _zoom), (int)_zoom, (int)_zoom); float alpha = 1f; if (curtile.IsLava == false) { alpha = 0.5f; } else { alpha = 0.85f; } if (neighborTile[n] != null && neighborTile[n].Liquid > 0) { source.Y = 8; source.Height = 8; } else { source.Height = 4 + ((int)Math.Round(curtile.Liquid * 6f / 255f)) * 2; dest.Height = (int)(source.Height * _zoom / 16f); dest.Y = 1 + (int)((_scrollPosition.Y + y) * _zoom + ((16 - source.Height) * _zoom / 16f)); } _spriteBatch.Draw(tileTex, dest, source, Color.White * alpha, 0f, default(Vector2), SpriteEffects.None, 0); } } } } } } }
/* Heathtech */ //Pretty much overwrote this whole function. The original part is still intact, but much more hidden private void DrawSprites() { Rectangle visibleBounds = GetViewingArea(); TEditXna.Terraria.Objects.BlendRules blendRules = TEditXna.Terraria.Objects.BlendRules.Instance; var width = _wvm.CurrentWorld.TilesWide; var height = _wvm.CurrentWorld.TilesHigh; if (visibleBounds.Height * visibleBounds.Width < 25000) { //Extended the viewing space to give tiles time to cache their UV's for (int y = visibleBounds.Top - 1; y < visibleBounds.Bottom + 2; y++) { for (int x = visibleBounds.Left - 1; x < visibleBounds.Right + 2; x++) { if (x < 0 || y < 0 || x >= _wvm.CurrentWorld.TilesWide || y >= _wvm.CurrentWorld.TilesHigh) { continue; } var curtile = _wvm.CurrentWorld.Tiles[x, y]; var tileprop = World.TileProperties[curtile.Type]; //Neighbor tiles are often used when dynamically determining which UV position to render int e = 0, n = 1, w = 2, s = 3, ne = 4, nw = 5, sw = 6, se = 7; Tile[] neighborTile = new Tile[8]; neighborTile[ e] = (x + 1) < width ? _wvm.CurrentWorld.Tiles[x + 1, y ] : null; neighborTile[ n] = (y - 1) > 0 ? _wvm.CurrentWorld.Tiles[x , y - 1] : null; neighborTile[ w] = (x - 1) > 0 ? _wvm.CurrentWorld.Tiles[x - 1, y ] : null; neighborTile[ s] = (y + 1) < height ? _wvm.CurrentWorld.Tiles[x , y + 1] : null; neighborTile[ne] = (x + 1) < width && (y - 1) > 0 ? _wvm.CurrentWorld.Tiles[x + 1, y - 1] : null; neighborTile[nw] = (x - 1) > 0 && (y - 1) > 0 ? _wvm.CurrentWorld.Tiles[x - 1, y - 1] : null; neighborTile[sw] = (x - 1) > 0 && (y + 1) < height ? _wvm.CurrentWorld.Tiles[x - 1, y + 1] : null; neighborTile[se] = (x + 1) < width && (y + 1) < height ? _wvm.CurrentWorld.Tiles[x + 1, y + 1] : null; //draw background textures if (y >= 80) { int[,] backstyle = { {66, 67, 68, 69, 128, 125, 185}, {70, 71, 68, 72, 128, 125, 185}, {73, 74, 75, 76, 134, 125, 185}, {77, 78, 79, 82, 134, 125, 185}, {83, 84, 85, 86, 137, 125, 185}, {83, 87, 88, 89, 137, 125, 185}, {121, 122, 123, 124, 140, 125, 185}, {153, 147, 148, 149, 150, 125, 185}, {146, 154, 155, 156, 157, 125, 185} }; int hellback = _wvm.CurrentWorld.HellBackStyle; int backX = 0; if (x <= _wvm.CurrentWorld.CaveBackX0) backX = _wvm.CurrentWorld.CaveBackStyle0; else if (x > _wvm.CurrentWorld.CaveBackX0 && x <= _wvm.CurrentWorld.CaveBackX1) backX = _wvm.CurrentWorld.CaveBackStyle1; else if (x > _wvm.CurrentWorld.CaveBackX1 && x <= _wvm.CurrentWorld.CaveBackX2) backX = _wvm.CurrentWorld.CaveBackStyle2; else if (x > _wvm.CurrentWorld.CaveBackX2) backX = _wvm.CurrentWorld.CaveBackStyle3; var source = new Rectangle(0, 0, 16, 16); var backTex = _textureDictionary.GetBackground(0); if (y < _wvm.CurrentWorld.GroundLevel) { backTex = _textureDictionary.GetBackground(0); source.Y += (y - 80) * 16; } else if (y == _wvm.CurrentWorld.GroundLevel) { backTex = _textureDictionary.GetBackground(backstyle[backX, 0]); source.X += (x % 8) * 16; } else if (y > _wvm.CurrentWorld.GroundLevel && y < _wvm.CurrentWorld.RockLevel) { backTex = _textureDictionary.GetBackground(backstyle[backX, 1]); source.X += (x % 8) * 16; source.Y += ((y - 1 - (int)_wvm.CurrentWorld.GroundLevel) % 6) * 16; } else if (y == _wvm.CurrentWorld.RockLevel) { backTex = _textureDictionary.GetBackground(backstyle[backX, 2]); source.X += (x % 8) * 16; } else if (y > _wvm.CurrentWorld.RockLevel && y < (_wvm.CurrentWorld.TilesHigh - 327)) { backTex = _textureDictionary.GetBackground(backstyle[backX, 3]); source.X += (x % 8) * 16; source.Y += ((y - 1 - (int)_wvm.CurrentWorld.RockLevel) % 6) * 16; } else if (y == (_wvm.CurrentWorld.TilesHigh - 327)) { backTex = _textureDictionary.GetBackground(backstyle[backX, 4] + hellback); source.X += (x % 8) * 16; } else if (y > (_wvm.CurrentWorld.TilesHigh - 327) && y < (_wvm.CurrentWorld.TilesHigh - 200)) { backTex = _textureDictionary.GetBackground(backstyle[backX, 5] + hellback); source.X += (x % 8) * 16; source.Y += ((y - 1 - (int)_wvm.CurrentWorld.TilesHigh + 327) % 18) * 16; } else if (y == (_wvm.CurrentWorld.TilesHigh - 200)) { backTex = _textureDictionary.GetBackground(backstyle[backX, 6] + hellback); source.X += (x % 8) * 16; } else { backTex = _textureDictionary.GetUnderworld(4); source.Y += (y - (int)_wvm.CurrentWorld.TilesHigh + 200) * 16; } var dest = new Rectangle(1 + (int)((_scrollPosition.X + x) * _zoom), 1 + (int)((_scrollPosition.Y + y) * _zoom), (int)_zoom, (int)_zoom); _spriteBatch.Draw(backTex, dest, source, Color.White, 0f, default(Vector2), SpriteEffects.None, LayerTileBackgroundTextures); } if (_wvm.ShowWalls) { if (curtile.Wall > 0) { var wallTex = _textureDictionary.GetWall(curtile.Wall); if (wallTex != null) { if (curtile.uvWallCache == 0xFFFF) { int sameStyle = 0x00000000; sameStyle |= (neighborTile[e] != null && neighborTile[e].Wall > 0) ? 0x0001 : 0x0000; sameStyle |= (neighborTile[n] != null && neighborTile[n].Wall > 0) ? 0x0010 : 0x0000; sameStyle |= (neighborTile[w] != null && neighborTile[w].Wall > 0) ? 0x0100 : 0x0000; sameStyle |= (neighborTile[s] != null && neighborTile[s].Wall > 0) ? 0x1000 : 0x0000; Vector2Int32 uvBlend = blendRules.GetUVForMasks((uint)sameStyle, 0x00000000, 0); curtile.uvWallCache = (ushort)((uvBlend.Y << 8) + uvBlend.X); } var texsize = new Vector2Int32(32, 32); var source = new Rectangle((curtile.uvWallCache & 0x00FF) * (texsize.X + 4), (curtile.uvWallCache >> 8) * (texsize.Y + 4), texsize.X, texsize.Y); var dest = new Rectangle(1 + (int)((_scrollPosition.X + x - 0.5) * _zoom), 1 + (int)((_scrollPosition.Y + y - 0.5) * _zoom), (int)_zoom * 2, (int)_zoom * 2); _spriteBatch.Draw(wallTex, dest, source, Color.White, 0f, default(Vector2), SpriteEffects.None, LayerTileWallTextures); } } } if (_wvm.ShowTiles) { if (curtile.IsActive) { if (tileprop.IsFramed) { Rectangle source = new Rectangle(), dest = new Rectangle(); var tileTex = _textureDictionary.GetTile(curtile.Type); bool isTreeSpecial = false, isMushroom = false; bool isLeft = false, isBase = false, isRight = false; if (curtile.Type == (int)TileType.Tree) { int baseX = 0; if (curtile.U == 66 && curtile.V <= 45) ++baseX; if (curtile.U == 88 && curtile.V >= 66 && curtile.V <= 110) --baseX; if (curtile.U == 22 && curtile.V >= 132 && curtile.V < 198) --baseX; if (curtile.U == 44 && curtile.V >= 132 && curtile.V < 198) ++baseX; if (curtile.U >= 22 && curtile.V >= 198) { isTreeSpecial = true; switch (curtile.U) { case 22: isBase = true; break; case 44: isLeft = true; ++baseX; break; case 66: isRight = true; --baseX; break; } } //Check tree type int treeType = -1; //Default to normal in case no grass grows beneath the tree for (int i = 0; i < 100; i++) { Tile checkTile = (y + i) < _wvm.CurrentWorld.TilesHigh ? _wvm.CurrentWorld.Tiles[x + baseX, y + i] : null; if (checkTile != null && checkTile.IsActive) { bool found = true; switch (checkTile.Type) { case 2: treeType = -1; break; //Normal case 23: treeType = 0; break; //Corruption case 60: if (y <= _wvm.CurrentWorld.GroundLevel) { treeType = 1; break; // Jungle } treeType = 5; break; // Underground Jungle case 70: treeType = 6; break; // Surface Mushroom case 109: treeType = 2; break; // Hallow case 147: treeType = 3; break; // Snow case 199: treeType = 4; break; // Crimson default: found = false; break; } if (found) break; } } if (isTreeSpecial) { int treeStyle = 0; // default branches and tops switch (treeType) { case -1: if (x <= _wvm.CurrentWorld.TreeX0) treeStyle = _wvm.CurrentWorld.TreeStyle0; else if (x <= _wvm.CurrentWorld.TreeX1) treeStyle = _wvm.CurrentWorld.TreeStyle1; else if (x <= _wvm.CurrentWorld.TreeX2) treeStyle = _wvm.CurrentWorld.TreeStyle2; else treeStyle = _wvm.CurrentWorld.TreeStyle3; if (treeStyle == 0) { break; } if (treeStyle == 5) { treeStyle = 10; break; } treeStyle = 5 + treeStyle; break; case 0: treeStyle = 1; break; case 1: treeStyle = 2; if (_wvm.CurrentWorld.BgJungle == 1) treeStyle = 11; break; case 2: treeStyle = 3; break; case 3: treeStyle = 4; if (_wvm.CurrentWorld.BgSnow == 0) { treeStyle = 12; if (x % 10 == 0) treeStyle = 18; } if (_wvm.CurrentWorld.BgSnow != 2 && _wvm.CurrentWorld.BgSnow != 3 && _wvm.CurrentWorld.BgSnow != 32 && _wvm.CurrentWorld.BgSnow != 4 && _wvm.CurrentWorld.BgSnow != 42) { break; } if (_wvm.CurrentWorld.BgSnow % 2 == 0) { if (x < _wvm.CurrentWorld.TilesWide / 2) { treeStyle = 16; break; } treeStyle = 17; break; } else { if (x > _wvm.CurrentWorld.TilesWide / 2) { treeStyle = 16; break; } treeStyle = 17; break; } case 4: treeStyle = 5; break; case 5: treeStyle = 13; break; case 6: treeStyle = 14; break; } //Abuse uvTileCache to remember what type of tree it is, since potentially scanning a hundred of blocks PER tree tile sounds slow curtile.uvTileCache = (ushort)((0x00 << 8) + 0x01 * treeStyle); if (isBase) { tileTex = (Texture2D)_textureDictionary.GetTreeTops(treeStyle); } else { tileTex = (Texture2D)_textureDictionary.GetTreeBranches(treeStyle); } } else { tileTex = _textureDictionary.GetTree(treeType); } } if (curtile.Type == (int)TileType.MushroomTree && curtile.U >= 36) { isMushroom = true; tileTex = (Texture2D)_textureDictionary.GetShroomTop(0); } if (curtile.Type == 323) { if (curtile.U >= 88 && curtile.U <= 132) { isTreeSpecial = true; isBase = true; tileTex = (Texture2D)_textureDictionary.GetTreeTops(15); } int treeType = 0; for (int i = 0; i < 100; i++) { Tile checkTile = (y + i) < _wvm.CurrentWorld.TilesHigh ? _wvm.CurrentWorld.Tiles[x, y + i] : null; if (checkTile != null && checkTile.IsActive) { bool found = true; switch (checkTile.Type) { case 53: treeType = 0; break; //Palm case 112: treeType = 3; break; //Ebonsand Palm case 116: treeType = 2; break; //Pearlsand Palm case 234: treeType = 1; break; //Crimsand Palm default: found = false; break; } if (found) break; } } curtile.uvTileCache = (ushort)((0x00 << 8) + 0x01 * treeType); } if (tileTex != null) { if ((curtile.Type == 128 || curtile.Type == 269) && curtile.U >= 100) { int armor = curtile.U / 100; dest = new Rectangle(1 + (int)((_scrollPosition.X + x) * _zoom), 1 + (int)((_scrollPosition.Y + y) * _zoom), (int)_zoom, (int)_zoom); switch (curtile.V / 18) { case 0: tileTex = (Texture2D)_textureDictionary.GetArmorHead(armor); source = new Rectangle (2, 0, 36, 36); dest.Width = (int)(_zoom * source.Width / 16f); dest.Height = (int)(_zoom * source.Height / 16f); dest.Y += (int)(((16 - source.Height - 4) / 2F) * _zoom / 16); dest.X -= (int)((2 * _zoom / 16)); break; case 1: if (curtile.Type == 128) tileTex = (Texture2D)_textureDictionary.GetArmorBody(armor); else tileTex = (Texture2D)_textureDictionary.GetArmorFemale(armor); source = new Rectangle (2, 0, 36, 54); dest.Width = (int)(_zoom * source.Width / 16f); dest.Height = (int)(_zoom * source.Height / 16f); dest.Y += (int)(((16 - source.Height - 18) / 2F) * _zoom / 16); dest.X -= (int)((2 * _zoom / 16)); break; case 2: tileTex = (Texture2D)_textureDictionary.GetArmorLegs(armor); source = new Rectangle (2, 42, 36, 12); dest.Width = (int)(_zoom * source.Width / 16f); dest.Height = (int)(_zoom * source.Height / 16f); dest.Y -= (int)((2 * _zoom / 16)); dest.X -= (int)((2 * _zoom / 16)); break; } if (curtile.U % 100 < 36) _spriteBatch.Draw(tileTex, dest, source, Color.White, 0f, default(Vector2), SpriteEffects.FlipHorizontally, LayerTileTrack); else _spriteBatch.Draw(tileTex, dest, source, Color.White, 0f, default(Vector2), SpriteEffects.None, LayerTileTrack); tileTex = _textureDictionary.GetTile(curtile.Type); source = new Rectangle((curtile.U % 100), curtile.V, tileprop.TextureGrid.X, tileprop.TextureGrid.Y); dest = new Rectangle(1 + (int)((_scrollPosition.X + x) * _zoom), 1 + (int)((_scrollPosition.Y + y) * _zoom), (int)_zoom, (int)_zoom); } else if (curtile.Type == 334 && curtile.U >= 5000) { if (_wvm.CurrentWorld.Tiles[x + 1, y].U >= 5000) { int weapon = (curtile.U % 5000) - 100; tileTex = (Texture2D)_textureDictionary.GetItem(weapon); int flip = curtile.U / 5000; float scale = 1f; if (tileTex.Width > 40 || tileTex.Height > 40) { if (tileTex.Width > tileTex.Height) scale = 40f / (float)tileTex.Width; else scale = 40f / (float)tileTex.Height; } scale *= World.ItemProperties[weapon].Scale; source = new Rectangle(0, 0, tileTex.Width, tileTex.Height); SpriteEffects effect = SpriteEffects.None; if (flip >= 3) { effect = SpriteEffects.FlipHorizontally; } _spriteBatch.Draw(tileTex, new Vector2(1 + (int)((_scrollPosition.X + x + 1.5) * _zoom) , 1 + (int)((_scrollPosition.Y + y + .5) * _zoom)), source, Color.White, 0f, new Vector2((float)(tileTex.Width / 2), (float)(tileTex.Height / 2)), scale * _zoom / 16f, effect, LayerTileTrack); } source = new Rectangle(((curtile.U / 5000) - 1) * 18, curtile.V, tileprop.TextureGrid.X, tileprop.TextureGrid.Y); tileTex = _textureDictionary.GetTile(curtile.Type); dest = new Rectangle(1 + (int)((_scrollPosition.X + x) * _zoom), 1 + (int)((_scrollPosition.Y + y) * _zoom), (int)_zoom, (int)_zoom); } else if (curtile.Type == 395 && curtile.V == 0 && curtile.U % 36 == 0) { TileEntity entity = _wvm.CurrentWorld.GetTileEntityAtTile(x, y); if (entity != null) { int item = entity.NetId; if (item > 0) { tileTex = (Texture2D)_textureDictionary.GetItem(item); float scale = 1f; if (tileTex.Width > 20 || tileTex.Height > 20) { if (tileTex.Width > tileTex.Height) scale = 20f / (float)tileTex.Width; else scale = 20f / (float)tileTex.Height; } scale *= World.ItemProperties[item].Scale; source = new Rectangle(0, 0, tileTex.Width, tileTex.Height); _spriteBatch.Draw(tileTex, new Vector2(1 + (int)((_scrollPosition.X + x + 1) * _zoom) , 1 + (int)((_scrollPosition.Y + y + 1) * _zoom)), source, Color.White, 0f, new Vector2((float)(tileTex.Width / 2), (float)(tileTex.Height / 2)), scale * _zoom / 16f, SpriteEffects.FlipHorizontally, LayerTileTrack); } } source = new Rectangle(curtile.U, curtile.V, tileprop.TextureGrid.X, tileprop.TextureGrid.Y); tileTex = _textureDictionary.GetTile(curtile.Type); dest = new Rectangle(1 + (int)((_scrollPosition.X + x) * _zoom), 1 + (int)((_scrollPosition.Y + y) * _zoom), (int)_zoom, (int)_zoom); } else if (curtile.Type == 171) // Christmas Tree { if (curtile.U >= 10) { int star = curtile.V & 7; int garland = (curtile.V >> 3) & 7; int bulb = (curtile.V >> 6) & 0xf; int light = (curtile.V >> 10) & 0xf; source = new Rectangle(0, 0, 64, 128); dest = new Rectangle(1 + (int)((_scrollPosition.X + x) * _zoom), 1 + (int)((_scrollPosition.Y + y) * _zoom), (int)_zoom * 4, (int)_zoom * 8); if (star > 0) { tileTex = (Texture2D)_textureDictionary.GetMisc("Xmas_3"); source.X = 66 * (star - 1); _spriteBatch.Draw(tileTex, dest, source, Color.White, 0f, default(Vector2), SpriteEffects.None, LayerTileTrack); } if (garland > 0) { tileTex = (Texture2D)_textureDictionary.GetMisc("Xmas_1"); source.X = 66 * (garland - 1); _spriteBatch.Draw(tileTex, dest, source, Color.White, 0f, default(Vector2), SpriteEffects.None, LayerTileTrack); } if (bulb > 0) { tileTex = (Texture2D)_textureDictionary.GetMisc("Xmas_2"); source.X = 66 * (bulb - 1); _spriteBatch.Draw(tileTex, dest, source, Color.White, 0f, default(Vector2), SpriteEffects.None, LayerTileTrack); } if (light > 0) { tileTex = (Texture2D)_textureDictionary.GetMisc("Xmas_4"); source.X = 66 * (light - 1); _spriteBatch.Draw(tileTex, dest, source, Color.White, 0f, default(Vector2), SpriteEffects.None, LayerTileTrack); } source.X = 0; tileTex = (Texture2D)_textureDictionary.GetMisc("Xmas_0"); } } else if (curtile.Type == 314) { source = new Rectangle(0, 0, 16, 16); dest = new Rectangle(1 + (int)((_scrollPosition.X + x) * _zoom), 1 + (int)((_scrollPosition.Y + y) * _zoom), (int)_zoom, (int)_zoom); if (curtile.V >= 0) // Switch Track, Y is back tile if not -1 { Vector2Int32 uvback = TrackUV(curtile.V); source.X = uvback.X * (source.Width + 2); source.Y = uvback.Y * (source.Height + 2); _spriteBatch.Draw(tileTex, dest, source, Color.White, 0f, default(Vector2), SpriteEffects.None, LayerTileTrackBack); } if ((curtile.U >= 2 && curtile.U <= 3) || (curtile.U >= 10 && curtile.U <= 13)) { // Adding regular endcap dest.Y = 1 + (int)((_scrollPosition.Y + y - 1) * _zoom); source.X = 0; source.Y = 126; _spriteBatch.Draw(tileTex, dest, source, Color.White, 0f, default(Vector2), SpriteEffects.None, LayerTileTrack); } if (curtile.U >= 24 && curtile.U <= 29) { // Adding bumper endcap dest.Y = 1 + (int)((_scrollPosition.Y + y - 1) * _zoom); source.X = 18; source.Y = 126; _spriteBatch.Draw(tileTex, dest, source, Color.White, 0f, default(Vector2), SpriteEffects.None, LayerTileTrack); } if (curtile.U == 4 || curtile.U == 9 || curtile.U == 10 || curtile.U == 16 || curtile.U == 26 || curtile.U == 33 || curtile.U == 35 || curtile.V == 4) { // Adding angle track bottom right dest.Y = 1 + (int)((_scrollPosition.Y + y + 1) * _zoom); source.X = 0; source.Y = 108; for (int slice = 0; slice < 6; slice++) { Rectangle? sourceSlice = new Rectangle(source.X + slice * 2, source.Y, 2, 12 - slice * 2); Vector2 destSlice = new Vector2((int)(dest.X + slice * _zoom / 8.0f), dest.Y); _spriteBatch.Draw(tileTex, destSlice, sourceSlice, Color.White, 0f, default(Vector2), _zoom / 16, SpriteEffects.None, LayerTileTrack); } } if (curtile.U == 5 || curtile.U == 8 || curtile.U == 11 || curtile.U == 17 || curtile.U == 27 || curtile.U == 32 || curtile.U == 34 || curtile.V == 5) { // Adding angle track bottom left dest.Y = 1 + (int)((_scrollPosition.Y + y + 1) * _zoom); source.X = 18; source.Y = 108; for (int slice = 2; slice < 8; slice++) { Rectangle? sourceSlice = new Rectangle(source.X + slice * 2, source.Y, 2, slice * 2 - 2); Vector2 destSlice = new Vector2((int)(dest.X + slice * _zoom / 8.0f), dest.Y); _spriteBatch.Draw(tileTex, destSlice, sourceSlice, Color.White, 0f, default(Vector2), _zoom / 16, SpriteEffects.None, LayerTileTrack); } } dest.Y = 1 + (int)((_scrollPosition.Y + y) * _zoom); Vector2Int32 uv = TrackUV(curtile.U); source.X = uv.X * (source.Width + 2); source.Y = uv.Y * (source.Height + 2); } else if (isTreeSpecial) { source = new Rectangle(0, 0, 40, 40); dest = new Rectangle(1 + (int)((_scrollPosition.X + x) * _zoom), 1 + (int)((_scrollPosition.Y + y) * _zoom), (int)_zoom, (int)_zoom); FrameAnchor frameAnchor = FrameAnchor.None; int treeStyle = (curtile.uvTileCache & 0x000F); if (isBase) { source.Width = 80; source.Height = 80; if (curtile.Type == 323) { source.Y = treeStyle * (source.Height + 2); source.X = ((curtile.U - 88) / 22) * (source.Width + 2); dest.X += (int)(curtile.V * _zoom / 16); } else { switch (treeStyle) { case 2: case 11: case 13: source.Width = 114; source.Height = 96; break; case 3: source.X = (x % 3) * (82 * 3); source.Height = 140; break; } source.X += ((curtile.V - 198) / 22) * (source.Width + 2); } frameAnchor = FrameAnchor.Bottom; } else if (isLeft) { source.X = 0; switch (treeStyle) { case 3: source.Y = (x % 3) * (42 * 3); break; } frameAnchor = FrameAnchor.Right; source.Y += ((curtile.V - 198) / 22) * (source.Height + 2); } else if (isRight) { source.X = 42; switch (treeStyle) { case 3: source.Y = (x % 3) * (42 * 3); break; } frameAnchor = FrameAnchor.Left; source.Y += ((curtile.V - 198) / 22) * (source.Height + 2); } dest.Width = (int)(_zoom * source.Width / 16f); dest.Height = (int)(_zoom * source.Height / 16f); switch (frameAnchor) { case FrameAnchor.None: dest.X += (int)(((16 - source.Width) / 2F) * _zoom / 16); dest.Y += (int)(((16 - source.Height) / 2F) * _zoom / 16); break; case FrameAnchor.Left: dest.Y += (int)(((16 - source.Height) / 2F) * _zoom / 16); break; case FrameAnchor.Right: dest.X += (int)((16 - source.Width) * _zoom / 16); dest.Y += (int)(((16 - source.Height) / 2F) * _zoom / 16); break; case FrameAnchor.Top: dest.X += (int)(((16 - source.Width) / 2F) * _zoom / 16); break; case FrameAnchor.Bottom: dest.X += (int)(((16 - source.Width) / 2F) * _zoom / 16); dest.Y += (int)((16 - source.Height) * _zoom / 16); break; } } else if (isMushroom) { source = new Rectangle(0, 0, 60, 42); dest = new Rectangle(1 + (int)((_scrollPosition.X + x) * _zoom), 1 + (int)((_scrollPosition.Y + y) * _zoom), (int)_zoom, (int)_zoom); source.X = (curtile.V / 18) * 62; dest.Width = (int)(_zoom * source.Width / 16f); dest.Height = (int)(_zoom * source.Height / 16f); dest.X += (int)(((16 - source.Width) / 2F) * _zoom / 16); dest.Y += (int)((16 - source.Height) * _zoom / 16); } else if ((curtile.Type >= 373 && curtile.Type <= 375) || curtile.Type == 461) { //skip rendering drips } else { source = new Rectangle(curtile.U, curtile.V, tileprop.TextureGrid.X, tileprop.TextureGrid.Y); if (source.Width <= 0) source.Width = 16; if (source.Height <= 0) source.Height = 16; if (source.Bottom > tileTex.Height) source.Height -= (source.Bottom - tileTex.Height); if (source.Right > tileTex.Width) source.Width -= (source.Right - tileTex.Width); if (source.Width <= 0 || source.Height <= 0) continue; dest = new Rectangle(1 + (int)((_scrollPosition.X + x) * _zoom), 1 + (int)((_scrollPosition.Y + y) * _zoom), (int)_zoom, (int)_zoom); if (curtile.Type == 323) { dest.X += (int)(curtile.V * _zoom / 16); int treeType = (curtile.uvTileCache & 0x000F); source.Y = 22 * treeType; } var texsize = tileprop.TextureGrid; if (texsize.X != 16 || texsize.Y != 16) { dest.Width = (int)(texsize.X * (_zoom / 16)); dest.Height = (int)(texsize.Y * (_zoom / 16)); var frame = (tileprop.Frames.FirstOrDefault(f => f.UV == new Vector2Short(curtile.U, curtile.V))); var frameAnchor = FrameAnchor.None; if (frame != null) frameAnchor = frame.Anchor; switch (frameAnchor) { case FrameAnchor.None: dest.X += (int)(((16 - texsize.X) / 2F) * _zoom / 16); dest.Y += (int)(((16 - texsize.Y) / 2F) * _zoom / 16); break; case FrameAnchor.Left: //position.X += (16 - texsize.X) / 2; dest.Y += (int)(((16 - texsize.Y) / 2F) * _zoom / 16); break; case FrameAnchor.Right: dest.X += (int)((16 - texsize.X) * _zoom / 16); dest.Y += (int)(((16 - texsize.Y) / 2F) * _zoom / 16); break; case FrameAnchor.Top: dest.X += (int)(((16 - texsize.X) / 2F) * _zoom / 16); //position.Y += (16 - texsize.Y); break; case FrameAnchor.Bottom: dest.X += (int)(((16 - texsize.X) / 2F) * _zoom / 16); dest.Y += (int)((16 - texsize.Y) * _zoom / 16); break; } } } _spriteBatch.Draw(tileTex, dest, source, curtile.InActive ? Color.Gray : Color.White, 0f, default(Vector2), SpriteEffects.None, LayerTileTextures); // Actuator Overlay if (curtile.Actuator && _wvm.ShowActuators) _spriteBatch.Draw(_textureDictionary.Actuator, dest, _textureDictionary.ZeroSixteenRectangle, Color.White, 0f, default(Vector2), SpriteEffects.None, LayerTileActuator); } } else if (tileprop.IsPlatform) { var tileTex = _textureDictionary.GetTile(curtile.Type); if (tileTex != null) { Vector2Int32 uv; if (curtile.uvTileCache == 0xFFFF) { uv = new Vector2Int32(0, 0); byte state = 0x00; state |= (byte)((neighborTile[w] != null && neighborTile[w].IsActive && neighborTile[w].Type == curtile.Type) ? 0x01 : 0x00); state |= (byte)((neighborTile[w] != null && neighborTile[w].IsActive && World.TileProperties[neighborTile[w].Type].IsSolid && neighborTile[w].Type != curtile.Type) ? 0x02 : 0x00); state |= (byte)((neighborTile[e] != null && neighborTile[e].IsActive && neighborTile[e].Type == curtile.Type) ? 0x04 : 0x00); state |= (byte)((neighborTile[e] != null && neighborTile[e].IsActive && World.TileProperties[neighborTile[e].Type].IsSolid && neighborTile[e].Type != curtile.Type) ? 0x08 : 0x00); switch (state) { case 0x00: case 0x0A: uv.X = 5; break; case 0x01: uv.X = 1; break; case 0x02: uv.X = 6; break; case 0x04: uv.X = 2; break; case 0x05: uv.X = 0; break; case 0x06: uv.X = 3; break; case 0x08: uv.X = 7; break; case 0x09: uv.X = 4; break; } uv.Y = blendRules.randomVariation.Next(3); curtile.uvTileCache = (ushort)((uv.Y << 8) + uv.X); } var texsize = new Vector2Int32(tileprop.TextureGrid.X, tileprop.TextureGrid.Y); if (texsize.X == 0 || texsize.Y == 0) { texsize = new Vector2Int32(16, 16); } var source = new Rectangle((curtile.uvTileCache & 0x00FF) * (texsize.X + 2), (curtile.uvTileCache >> 8) * (texsize.Y + 2), texsize.X, texsize.Y); var dest = new Rectangle(1 + (int)((_scrollPosition.X + x) * _zoom), 1 + (int)((_scrollPosition.Y + y) * _zoom), (int)_zoom, (int)_zoom); _spriteBatch.Draw(tileTex, dest, source, curtile.InActive ? Color.Gray : Color.White, 0f, default(Vector2), SpriteEffects.None, LayerTileTextures); // Actuator Overlay if (curtile.Actuator && _wvm.ShowActuators) _spriteBatch.Draw(_textureDictionary.Actuator, dest, _textureDictionary.ZeroSixteenRectangle, Color.White, 0f, default(Vector2), SpriteEffects.None, LayerTileActuator); } } else if (tileprop.IsCactus) { var tileTex = _textureDictionary.GetTile(curtile.Type); if ((curtile.uvTileCache & 0x00FF) >= 24) { tileTex = (Texture2D)_textureDictionary.GetMisc("Crimson_Cactus"); } else if ((curtile.uvTileCache & 0x00FF) >= 16) { tileTex = (Texture2D)_textureDictionary.GetMisc("Evil_Cactus"); } else if ((curtile.uvTileCache & 0x00FF) >= 8) { tileTex = (Texture2D)_textureDictionary.GetMisc("Good_Cactus"); } if (tileTex != null) { Vector2Int32 uv; if (curtile.uvTileCache == 0xFFFF || curtile.hasLazyChecked == false) { bool isLeft = false, isRight = false, isBase = false; //Has this cactus been base-evaluated yet? int neighborX = (neighborTile[w].uvTileCache & 0x00FF) % 8; //Why % 8? If X >= 8, use hallow, If X >= 16, use corruption if (neighborX == 0 || neighborX == 1 || neighborX == 4 || neighborX == 5) { isRight = true; } neighborX = neighborTile[e].uvTileCache & 0x00FF; if (neighborX == 0 || neighborX == 1 || neighborX == 4 || neighborX == 5) { isLeft = true; } neighborX = curtile.uvTileCache & 0x00FF; if (neighborX == 0 || neighborX == 1 || neighborX == 4 || neighborX == 5) { isBase = true; } //Evaluate Base if (isLeft == false && isRight == false && isBase == false) { int length1 = 0; int length2 = 0; while (true) { Tile checkTile = (y + length1) < _wvm.CurrentWorld.TilesHigh ? _wvm.CurrentWorld.Tiles[x, y + length1] : null; if (checkTile == null || checkTile.IsActive == false || checkTile.Type != curtile.Type) { break; } length1++; } if (x + 1 < _wvm.CurrentWorld.TilesWide) { while (true) { Tile checkTile = (y + length2) < _wvm.CurrentWorld.TilesHigh ? _wvm.CurrentWorld.Tiles[x + 1, y + length2] : null; if (checkTile == null || checkTile.IsActive == false || checkTile.Type != curtile.Type) { break; } length2++; } } int baseX = 0; int baseY = length1; isBase = true; if (length2 >= length1) { baseX = 1; baseY = length2; isBase = false; isLeft = true; } for (int cy = y; cy < y + baseY; cy++) { if (_wvm.CurrentWorld.Tiles[x + baseX, cy].uvTileCache == 0xFFFF) { if (cy == y) { _wvm.CurrentWorld.Tiles[x + baseX, cy].uvTileCache = 0x00 << 8 + 0x00; } else { _wvm.CurrentWorld.Tiles[x + baseX, cy].uvTileCache = 0x01 << 8 + 0x00; } } } } uv = new Vector2Int32(0, 0); byte state = 0x00; state |= (byte)((neighborTile[e] != null && neighborTile[e].IsActive && neighborTile[e].Type == curtile.Type) ? 0x01 : 0x00); state |= (byte)((neighborTile[n] != null && neighborTile[n].IsActive && neighborTile[n].Type == curtile.Type) ? 0x02 : 0x00); state |= (byte)((neighborTile[w] != null && neighborTile[w].IsActive && neighborTile[w].Type == curtile.Type) ? 0x04 : 0x00); state |= (byte)((neighborTile[s] != null && neighborTile[s].IsActive && neighborTile[s].Type == curtile.Type) ? 0x08 : 0x00); //state |= (byte)((neighborTile[ne] != null && neighborTile[ne].IsActive && neighborTile[ne].Type == curtile.Type) ? 0x10 : 0x00); //state |= (byte)((neighborTile[nw] != null && neighborTile[nw].IsActive && neighborTile[nw].Type == curtile.Type) ? 0x20 : 0x00); state |= (byte)((neighborTile[sw] != null && neighborTile[sw].IsActive && neighborTile[sw].Type == curtile.Type) ? 0x40 : 0x00); state |= (byte)((neighborTile[se] != null && neighborTile[se].IsActive && neighborTile[se].Type == curtile.Type) ? 0x80 : 0x00); if (isLeft) { uv.X = 3; if ((state & 0x08) != 0x00) //s { if ((state & 0x02) != 0x00) //n { uv.Y = 1; } else //!n { uv.Y = 0; } } else //!s { if ((state & 0x02) != 0x00) //n { uv.Y = 2; } else //!n { uv.X = 6; uv.Y = 2; } } } if (isRight) { uv.X = 2; if ((state & 0x08) != 0x00) //s { if ((state & 0x02) != 0x00) //n { uv.Y = 1; } else //!n { uv.Y = 0; } } else //!s { if ((state & 0x02) != 0x00) //n { uv.Y = 2; } else //!n { uv.X = 6; uv.Y = 1; } } } if (isBase) { if ((state & 0x02) != 0x00) //n { uv.Y = 2; if ((state & 0x04) != 0x00 && (state & 0x40) == 0x00 && ((state & 0x01) == 0x00 || (state & 0x80) != 0x00)) //w !sw (!e or se) { uv.X = 4; } else if ((state & 0x01) != 0x00 && (state & 0x80) == 0x00 && ((state & 0x04) == 0x00 || (state & 0x40) != 0x00)) //e !se (!w or sw) { uv.X = 1; } else if ((state & 0x04) != 0x00 && (state & 0x40) == 0x00 && (state & 0x01) != 0x00 && (state & 0x80) == 0x00) //w !sw e !se { uv.X = 5; } else { uv.X = 0; uv.Y = 1; } } else //!n { uv.Y = 0; if ((state & 0x04) != 0x00 && (state & 0x40) == 0x00 && ((state & 0x01) == 0x00 || (state & 0x80) != 0x00)) //w !sw (!e or se) { uv.X = 4; } else if ((state & 0x01) != 0x00 && (state & 0x80) == 0x00 && ((state & 0x04) == 0x00 || (state & 0x40) != 0x00)) //e !se (!w or sw) { uv.X = 1; } else if ((state & 0x04) != 0x00 && (state & 0x40) == 0x00 && (state & 0x01) != 0x00 && (state & 0x80) == 0x00) //w !sw e !se { uv.X = 5; } else { uv.X = 0; uv.Y = 0; } } } //Check if cactus is good or evil for (int i = 0; i < 100; i++) { int baseX = (isLeft) ? 1 : (isRight) ? -1 : 0; Tile checkTile = (y + i) < _wvm.CurrentWorld.TilesHigh ? _wvm.CurrentWorld.Tiles[x + baseX, y + i] : null; if (checkTile != null && checkTile.IsActive && checkTile.Type == (int)TileType.CrimsandBlock) //Crimson { uv.X += 24; break; } if (checkTile != null && checkTile.IsActive && checkTile.Type == (int)TileType.EbonsandBlock) //Corruption { uv.X += 16; break; } else if (checkTile != null && checkTile.IsActive && checkTile.Type == (int)TileType.PearlsandBlock) //Hallow { uv.X += 8; break; } } curtile.hasLazyChecked = true; curtile.uvTileCache = (ushort)((uv.Y << 8) + uv.X); } var texsize = new Vector2Int32(tileprop.TextureGrid.X, tileprop.TextureGrid.Y); if (texsize.X == 0 || texsize.Y == 0) { texsize = new Vector2Int32(16, 16); } var source = new Rectangle(((curtile.uvTileCache & 0x00FF) % 8) * (texsize.X + 2), (curtile.uvTileCache >> 8) * (texsize.Y + 2), texsize.X, texsize.Y); var dest = new Rectangle(1 + (int)((_scrollPosition.X + x) * _zoom), 1 + (int)((_scrollPosition.Y + y) * _zoom), (int)_zoom, (int)_zoom); _spriteBatch.Draw(tileTex, dest, source, Color.White, 0f, default(Vector2), SpriteEffects.None, LayerTileTextures); } } else if (tileprop.CanBlend) { var tileTex = _textureDictionary.GetTile(curtile.Type); if (tileTex != null) { if (curtile.uvTileCache == 0xFFFF || curtile.hasLazyChecked == false) { int sameStyle = 0x00000000; int mergeMask = 0x00000000; int strictness = 0; if (tileprop.MergeWith.HasValue && tileprop.MergeWith.Value == -1) //Basically for cobweb { sameStyle |= (neighborTile[e] != null && neighborTile[e].IsActive) ? 0x0001 : 0x0000; sameStyle |= (neighborTile[n] != null && neighborTile[n].IsActive) ? 0x0010 : 0x0000; sameStyle |= (neighborTile[w] != null && neighborTile[w].IsActive) ? 0x0100 : 0x0000; sameStyle |= (neighborTile[s] != null && neighborTile[s].IsActive) ? 0x1000 : 0x0000; } else if (tileprop.IsStone) //Stone & Gems { sameStyle |= (neighborTile[e] != null && neighborTile[e].IsActive && World.TileProperties[neighborTile[e].Type].IsStone) ? 0x0001 : 0x0000; sameStyle |= (neighborTile[n] != null && neighborTile[n].IsActive && World.TileProperties[neighborTile[n].Type].IsStone) ? 0x0010 : 0x0000; sameStyle |= (neighborTile[w] != null && neighborTile[w].IsActive && World.TileProperties[neighborTile[w].Type].IsStone) ? 0x0100 : 0x0000; sameStyle |= (neighborTile[s] != null && neighborTile[s].IsActive && World.TileProperties[neighborTile[s].Type].IsStone) ? 0x1000 : 0x0000; sameStyle |= (neighborTile[ne] != null && neighborTile[ne].IsActive && World.TileProperties[neighborTile[ne].Type].IsStone) ? 0x00010000 : 0x00000000; sameStyle |= (neighborTile[nw] != null && neighborTile[nw].IsActive && World.TileProperties[neighborTile[nw].Type].IsStone) ? 0x00100000 : 0x00000000; sameStyle |= (neighborTile[sw] != null && neighborTile[sw].IsActive && World.TileProperties[neighborTile[sw].Type].IsStone) ? 0x01000000 : 0x00000000; sameStyle |= (neighborTile[se] != null && neighborTile[se].IsActive && World.TileProperties[neighborTile[se].Type].IsStone) ? 0x10000000 : 0x00000000; } else //Everything else { //Join to nearby tiles if their merge type is this tile's type sameStyle |= (neighborTile[e] != null && neighborTile[e].IsActive && World.TileProperties[neighborTile[e].Type].MergeWith.HasValue && World.TileProperties[neighborTile[e].Type].MergeWith.Value == curtile.Type) ? 0x0001 : 0x0000; sameStyle |= (neighborTile[n] != null && neighborTile[n].IsActive && World.TileProperties[neighborTile[n].Type].MergeWith.HasValue && World.TileProperties[neighborTile[n].Type].MergeWith.Value == curtile.Type) ? 0x0010 : 0x0000; sameStyle |= (neighborTile[w] != null && neighborTile[w].IsActive && World.TileProperties[neighborTile[w].Type].MergeWith.HasValue && World.TileProperties[neighborTile[w].Type].MergeWith.Value == curtile.Type) ? 0x0100 : 0x0000; sameStyle |= (neighborTile[s] != null && neighborTile[s].IsActive && World.TileProperties[neighborTile[s].Type].MergeWith.HasValue && World.TileProperties[neighborTile[s].Type].MergeWith.Value == curtile.Type) ? 0x1000 : 0x0000; sameStyle |= (neighborTile[ne] != null && neighborTile[ne].IsActive && World.TileProperties[neighborTile[ne].Type].MergeWith.HasValue && World.TileProperties[neighborTile[ne].Type].MergeWith.Value == curtile.Type) ? 0x00010000 : 0x00000000; sameStyle |= (neighborTile[nw] != null && neighborTile[nw].IsActive && World.TileProperties[neighborTile[nw].Type].MergeWith.HasValue && World.TileProperties[neighborTile[nw].Type].MergeWith.Value == curtile.Type) ? 0x00100000 : 0x00000000; sameStyle |= (neighborTile[sw] != null && neighborTile[sw].IsActive && World.TileProperties[neighborTile[sw].Type].MergeWith.HasValue && World.TileProperties[neighborTile[sw].Type].MergeWith.Value == curtile.Type) ? 0x01000000 : 0x00000000; sameStyle |= (neighborTile[se] != null && neighborTile[se].IsActive && World.TileProperties[neighborTile[se].Type].MergeWith.HasValue && World.TileProperties[neighborTile[se].Type].MergeWith.Value == curtile.Type) ? 0x10000000 : 0x00000000; //Join if nearby tiles have the same type as this tile's type sameStyle |= (neighborTile[e] != null && neighborTile[e].IsActive && curtile.Type == neighborTile[e].Type) ? 0x0001 : 0x0000; sameStyle |= (neighborTile[n] != null && neighborTile[n].IsActive && curtile.Type == neighborTile[n].Type) ? 0x0010 : 0x0000; sameStyle |= (neighborTile[w] != null && neighborTile[w].IsActive && curtile.Type == neighborTile[w].Type) ? 0x0100 : 0x0000; sameStyle |= (neighborTile[s] != null && neighborTile[s].IsActive && curtile.Type == neighborTile[s].Type) ? 0x1000 : 0x0000; sameStyle |= (neighborTile[ne] != null && neighborTile[ne].IsActive && curtile.Type == neighborTile[ne].Type) ? 0x00010000 : 0x00000000; sameStyle |= (neighborTile[nw] != null && neighborTile[nw].IsActive && curtile.Type == neighborTile[nw].Type) ? 0x00100000 : 0x00000000; sameStyle |= (neighborTile[sw] != null && neighborTile[sw].IsActive && curtile.Type == neighborTile[sw].Type) ? 0x01000000 : 0x00000000; sameStyle |= (neighborTile[se] != null && neighborTile[se].IsActive && curtile.Type == neighborTile[se].Type) ? 0x10000000 : 0x00000000; } if (curtile.hasLazyChecked == false) { bool lazyCheckReady = true; lazyCheckReady &= (neighborTile[e] == null || neighborTile[e].IsActive == false || World.TileProperties[neighborTile[e].Type].MergeWith.HasValue == false || World.TileProperties[neighborTile[e].Type].MergeWith.Value != curtile.Type) ? true : (neighborTile[e].lazyMergeId != 0xFF); lazyCheckReady &= (neighborTile[n] == null || neighborTile[n].IsActive == false || World.TileProperties[neighborTile[n].Type].MergeWith.HasValue == false || World.TileProperties[neighborTile[n].Type].MergeWith.Value != curtile.Type) ? true : (neighborTile[n].lazyMergeId != 0xFF); lazyCheckReady &= (neighborTile[w] == null || neighborTile[w].IsActive == false || World.TileProperties[neighborTile[w].Type].MergeWith.HasValue == false || World.TileProperties[neighborTile[w].Type].MergeWith.Value != curtile.Type) ? true : (neighborTile[w].lazyMergeId != 0xFF); lazyCheckReady &= (neighborTile[s] == null || neighborTile[s].IsActive == false || World.TileProperties[neighborTile[s].Type].MergeWith.HasValue == false || World.TileProperties[neighborTile[s].Type].MergeWith.Value != curtile.Type) ? true : (neighborTile[s].lazyMergeId != 0xFF); if (lazyCheckReady) { sameStyle &= 0x11111110 | ((neighborTile[e] == null || neighborTile[e].IsActive == false || World.TileProperties[neighborTile[e].Type].MergeWith.HasValue == false || World.TileProperties[neighborTile[e].Type].MergeWith.Value != curtile.Type) ? 0x00000001 : ((neighborTile[e].lazyMergeId & 0x04) >> 2)); sameStyle &= 0x11111101 | ((neighborTile[n] == null || neighborTile[n].IsActive == false || World.TileProperties[neighborTile[n].Type].MergeWith.HasValue == false || World.TileProperties[neighborTile[n].Type].MergeWith.Value != curtile.Type) ? 0x00000010 : ((neighborTile[n].lazyMergeId & 0x08) << 1)); sameStyle &= 0x11111011 | ((neighborTile[w] == null || neighborTile[w].IsActive == false || World.TileProperties[neighborTile[w].Type].MergeWith.HasValue == false || World.TileProperties[neighborTile[w].Type].MergeWith.Value != curtile.Type) ? 0x00000100 : ((neighborTile[w].lazyMergeId & 0x01) << 8)); sameStyle &= 0x11110111 | ((neighborTile[s] == null || neighborTile[s].IsActive == false || World.TileProperties[neighborTile[s].Type].MergeWith.HasValue == false || World.TileProperties[neighborTile[s].Type].MergeWith.Value != curtile.Type) ? 0x00001000 : ((neighborTile[s].lazyMergeId & 0x02) << 11)); curtile.hasLazyChecked = true; } } if (tileprop.MergeWith.HasValue && tileprop.MergeWith.Value > -1) //Merges with a specific type { mergeMask |= (neighborTile[e] != null && neighborTile[e].IsActive && neighborTile[e].Type == tileprop.MergeWith.Value) ? 0x0001 : 0x0000; mergeMask |= (neighborTile[n] != null && neighborTile[n].IsActive && neighborTile[n].Type == tileprop.MergeWith.Value) ? 0x0010 : 0x0000; mergeMask |= (neighborTile[w] != null && neighborTile[w].IsActive && neighborTile[w].Type == tileprop.MergeWith.Value) ? 0x0100 : 0x0000; mergeMask |= (neighborTile[s] != null && neighborTile[s].IsActive && neighborTile[s].Type == tileprop.MergeWith.Value) ? 0x1000 : 0x0000; mergeMask |= (neighborTile[ne] != null && neighborTile[ne].IsActive && neighborTile[ne].Type == tileprop.MergeWith.Value) ? 0x00010000 : 0x00000000; mergeMask |= (neighborTile[nw] != null && neighborTile[nw].IsActive && neighborTile[nw].Type == tileprop.MergeWith.Value) ? 0x00100000 : 0x00000000; mergeMask |= (neighborTile[sw] != null && neighborTile[sw].IsActive && neighborTile[sw].Type == tileprop.MergeWith.Value) ? 0x01000000 : 0x00000000; mergeMask |= (neighborTile[se] != null && neighborTile[se].IsActive && neighborTile[se].Type == tileprop.MergeWith.Value) ? 0x10000000 : 0x00000000; strictness = 1; } if (tileprop.IsGrass) { strictness = 2; } Vector2Int32 uvBlend = blendRules.GetUVForMasks((uint)sameStyle, (uint)mergeMask, strictness); curtile.uvTileCache = (ushort)((uvBlend.Y << 8) + uvBlend.X); curtile.lazyMergeId = blendRules.lazyMergeValidation[uvBlend.Y, uvBlend.X]; } var texsize = new Vector2Int32(tileprop.TextureGrid.X, tileprop.TextureGrid.Y); if (texsize.X == 0 || texsize.Y == 0) { texsize = new Vector2Int32(16, 16); } var source = new Rectangle((curtile.uvTileCache & 0x00FF) * (texsize.X + 2), (curtile.uvTileCache >> 8) * (texsize.Y + 2), texsize.X, texsize.Y); var dest = new Rectangle(1 + (int)((_scrollPosition.X + x) * _zoom), 1 + (int)((_scrollPosition.Y + y) * _zoom), (int)_zoom, (int)_zoom); // hack for some slopes switch (curtile.BrickStyle) { case BrickStyle.HalfBrick: source.Height /= 2; dest.Y += (int)(_zoom * 0.5); dest.Height = (int)(_zoom / 2.0f); _spriteBatch.Draw(tileTex, dest, source, curtile.InActive ? Color.Gray : Color.White, 0f, default(Vector2), SpriteEffects.None, LayerTileTextures); break; case BrickStyle.SlopeTopRight: for (int slice = 0; slice < 8; slice++) { Rectangle? sourceSlice = new Rectangle(source.X + slice * 2, source.Y, 2, 16 - slice * 2); Vector2 destSlice = new Vector2((int)(dest.X + slice * _zoom / 8.0f), (int)(dest.Y + slice * _zoom / 8.0f)); _spriteBatch.Draw(tileTex, destSlice, sourceSlice, curtile.InActive ? Color.Gray : Color.White, 0f, default(Vector2), _zoom / 16, SpriteEffects.None, LayerTileTextures); } break; case BrickStyle.SlopeTopLeft: for (int slice = 0; slice < 8; slice++) { Rectangle? sourceSlice = new Rectangle(source.X + slice * 2, source.Y, 2, slice * 2 + 2); Vector2 destSlice = new Vector2((int)(dest.X + slice * _zoom / 8.0f), (int)(dest.Y + (7 - slice) * _zoom / 8.0f)); _spriteBatch.Draw(tileTex, destSlice, sourceSlice, curtile.InActive ? Color.Gray : Color.White, 0f, default(Vector2), _zoom / 16, SpriteEffects.None, LayerTileTextures); } break; case BrickStyle.SlopeBottomRight: for (int slice = 0; slice < 8; slice++) { Rectangle? sourceSlice = new Rectangle(source.X + slice * 2, source.Y + slice * 2, 2, 16 - slice * 2); Vector2 destSlice = new Vector2((int)(dest.X + slice * _zoom / 8.0f), dest.Y); _spriteBatch.Draw(tileTex, destSlice, sourceSlice, curtile.InActive ? Color.Gray : Color.White, 0f, default(Vector2), _zoom / 16, SpriteEffects.None, LayerTileTextures); } break; case BrickStyle.SlopeBottomLeft: for (int slice = 0; slice < 8; slice++) { Rectangle? sourceSlice = new Rectangle(source.X + slice * 2, source.Y, 2, slice * 2 + 2); Vector2 destSlice = new Vector2((int)(dest.X + slice * _zoom / 8.0f), dest.Y); _spriteBatch.Draw(tileTex, destSlice, sourceSlice, curtile.InActive ? Color.Gray : Color.White, 0f, default(Vector2), _zoom / 16, SpriteEffects.None, LayerTileTextures); } break; case BrickStyle.Full: default: _spriteBatch.Draw(tileTex, dest, source, curtile.InActive ? Color.Gray : Color.White, 0f, default(Vector2), SpriteEffects.None, LayerTileTextures); break; } // Actuator Overlay if (curtile.Actuator && _wvm.ShowActuators) _spriteBatch.Draw(_textureDictionary.Actuator, dest, _textureDictionary.ZeroSixteenRectangle, Color.White, 0f, default(Vector2), SpriteEffects.None, LayerTileActuator); } } } } if (_wvm.ShowRedWires || _wvm.ShowBlueWires || _wvm.ShowGreenWires || _wvm.ShowYellowWires) { var tileTex = (Texture2D)_textureDictionary.GetMisc("WiresNew"); if (tileTex != null) { int voffset = 0; if (curtile.Type == 424) voffset = (curtile.U / 18 + 1) * 72; if (curtile.Type == 445) voffset = 72; if (curtile.WireRed && _wvm.ShowRedWires) { var source = new Rectangle(0, 0, 16, 16); var dest = new Rectangle(1 + (int)((_scrollPosition.X + x) * _zoom), 1 + (int)((_scrollPosition.Y + y) * _zoom), (int)_zoom, (int)_zoom); byte state = 0x00; state |= (byte)((neighborTile[n] != null && neighborTile[n].WireRed == true) ? 0x01 : 0x00); state |= (byte)((neighborTile[e] != null && neighborTile[e].WireRed == true) ? 0x02 : 0x00); state |= (byte)((neighborTile[s] != null && neighborTile[s].WireRed == true) ? 0x04 : 0x00); state |= (byte)((neighborTile[w] != null && neighborTile[w].WireRed == true) ? 0x08 : 0x00); source.X = state * 18; source.Y = voffset; _spriteBatch.Draw(tileTex, dest, source, Color.White, 0f, default(Vector2), SpriteEffects.None, LayerRedWires); } if (curtile.WireBlue && _wvm.ShowBlueWires) { var source = new Rectangle(0, 0, 16, 16); var dest = new Rectangle(1 + (int)((_scrollPosition.X + x) * _zoom), 1 + (int)((_scrollPosition.Y + y) * _zoom), (int)_zoom, (int)_zoom); byte state = 0x00; state |= (byte)((neighborTile[n] != null && neighborTile[n].WireBlue == true) ? 0x01 : 0x00); state |= (byte)((neighborTile[e] != null && neighborTile[e].WireBlue == true) ? 0x02 : 0x00); state |= (byte)((neighborTile[s] != null && neighborTile[s].WireBlue == true) ? 0x04 : 0x00); state |= (byte)((neighborTile[w] != null && neighborTile[w].WireBlue == true) ? 0x08 : 0x00); source.X = state * 18; source.Y = 18 + voffset; _spriteBatch.Draw(tileTex, dest, source, Color.White, 0f, default(Vector2), SpriteEffects.None, LayerBlueWires); } if (curtile.WireGreen && _wvm.ShowGreenWires) { var source = new Rectangle(0, 0, 16, 16); var dest = new Rectangle(1 + (int)((_scrollPosition.X + x) * _zoom), 1 + (int)((_scrollPosition.Y + y) * _zoom), (int)_zoom, (int)_zoom); byte state = 0x00; state |= (byte)((neighborTile[n] != null && neighborTile[n].WireGreen == true) ? 0x01 : 0x00); state |= (byte)((neighborTile[e] != null && neighborTile[e].WireGreen == true) ? 0x02 : 0x00); state |= (byte)((neighborTile[s] != null && neighborTile[s].WireGreen == true) ? 0x04 : 0x00); state |= (byte)((neighborTile[w] != null && neighborTile[w].WireGreen == true) ? 0x08 : 0x00); source.X = state * 18; source.Y = 36 + voffset; _spriteBatch.Draw(tileTex, dest, source, Color.White, 0f, default(Vector2), SpriteEffects.None, LayerGreenWires); } if (curtile.WireYellow && _wvm.ShowYellowWires) { var source = new Rectangle(0, 0, 16, 16); var dest = new Rectangle(1 + (int)((_scrollPosition.X + x) * _zoom), 1 + (int)((_scrollPosition.Y + y) * _zoom), (int)_zoom, (int)_zoom); byte state = 0x00; state |= (byte)((neighborTile[n] != null && neighborTile[n].WireYellow == true) ? 0x01 : 0x00); state |= (byte)((neighborTile[e] != null && neighborTile[e].WireYellow == true) ? 0x02 : 0x00); state |= (byte)((neighborTile[s] != null && neighborTile[s].WireYellow == true) ? 0x04 : 0x00); state |= (byte)((neighborTile[w] != null && neighborTile[w].WireYellow == true) ? 0x08 : 0x00); source.X = state * 18; source.Y = 54 + voffset; _spriteBatch.Draw(tileTex, dest, source, Color.White, 0f, default(Vector2), SpriteEffects.None, LayerYellowWires); } } } if (_wvm.ShowLiquid) { if (curtile.LiquidAmount > 0) { Texture2D tileTex = null; if (curtile.LiquidType == LiquidType.Lava) { tileTex = (Texture2D)_textureDictionary.GetLiquid(1); } else if (curtile.LiquidType == LiquidType.Honey) { tileTex = (Texture2D)_textureDictionary.GetLiquid(11); // Not sure if yellow Desert water, or Honey, but looks fine. } else { tileTex = (Texture2D)_textureDictionary.GetLiquid(0); } if (tileTex != null) { var source = new Rectangle(0, 0, 16, 16); var dest = new Rectangle(1 + (int)((_scrollPosition.X + x) * _zoom), 1 + (int)((_scrollPosition.Y + y) * _zoom), (int)_zoom, (int)_zoom); float alpha = 1f; if (curtile.LiquidType != LiquidType.Lava) { alpha = 0.5f; } else { alpha = 0.85f; } if (neighborTile[n] != null && neighborTile[n].LiquidAmount > 0) { source.Y = 8; source.Height = 8; } else { source.Height = 4 + ((int)Math.Round(curtile.LiquidAmount * 6f / 255f)) * 2; dest.Height = (int)(source.Height * _zoom / 16f); dest.Y = 1 + (int)((_scrollPosition.Y + y) * _zoom + ((16 - source.Height) * _zoom / 16f)); } _spriteBatch.Draw(tileTex, dest, source, Color.White * alpha, 0f, default(Vector2), SpriteEffects.None, LayerLiquid); } } } } } } }
private void SetWall(Tile curTile, bool erase) { if (TilePicker.WallMaskMode == MaskMode.Off || (TilePicker.WallMaskMode == MaskMode.Match && curTile.Wall == TilePicker.WallMask) || (TilePicker.WallMaskMode == MaskMode.Empty && curTile.Wall == 0) || (TilePicker.WallMaskMode == MaskMode.NotMatching && curTile.Wall != TilePicker.WallMask)) { if (erase) SetPixelAutomatic(curTile, wall: 0); else SetPixelAutomatic(curTile, wall: TilePicker.Wall); } }
private void SetPixelAutomatic(Tile curTile, int? tile = null, int? wall = null, byte? liquid = null, LiquidType? liquidType = null, bool? wire = null, short? u = null, short? v = null, bool? wire2 = null, bool? wire3 = null, BrickStyle? brickStyle = null, bool? actuator = null, bool? actuatorInActive = null, int? tileColor = null, int? wallColor = null) { // Set Tile Data if (u != null) curTile.U = (short)u; if (v != null) curTile.V = (short)v; if (tile != null) { if (tile == -1) { curTile.Type = 0; curTile.IsActive = false; } else { curTile.Type = (ushort)tile; curTile.IsActive = true; } } if (actuator != null && curTile.IsActive) { curTile.Actuator = (bool)actuator; } if (actuatorInActive != null && curTile.IsActive) { curTile.InActive = (bool)actuatorInActive; } if (brickStyle != null && TilePicker.BrickStyleActive) { curTile.BrickStyle = (BrickStyle)brickStyle; } if (wall != null) curTile.Wall = (byte)wall; if (liquid != null) { curTile.LiquidAmount = (byte)liquid; } if (liquidType != null) { curTile.LiquidType = (LiquidType)liquidType; } if (wire != null) curTile.WireRed = (bool)wire; if (wire2 != null) curTile.WireGreen = (bool)wire2; if (wire3 != null) curTile.WireBlue = (bool)wire3; if (tileColor != null) { if (curTile.IsActive) { curTile.TileColor = (byte)tileColor; } else { curTile.TileColor = (byte)0; } } if (wallColor != null) { if (curTile.Wall != 0) { curTile.WallColor = (byte)wallColor; } else { curTile.WallColor = (byte)0; } } if (curTile.IsActive) if (World.TileProperties[curTile.Type].IsSolid) curTile.LiquidAmount = 0; }
public bool Equals(Tile other) { if (ReferenceEquals(null, other)) return false; if (ReferenceEquals(this, other)) return true; return other.IsActive.Equals(IsActive) && other.Type == Type && other.Wall == Wall && other.Liquid == Liquid && other.IsLava.Equals(IsLava) && other.U == U && other.V == V && other.HasWire.Equals(HasWire); }
private void LinearFloodFill(ref int x, ref int y, ref Tile originTile) { int bitmapWidth = _wvm.CurrentWorld.TilesWide; int bitmapHeight = _wvm.CurrentWorld.TilesHigh; //FIND LEFT EDGE OF COLOR AREA int lFillLoc = x; //the location to check/fill on the left int tileIndex = (bitmapWidth * y) + x; while (true) { if (!_wvm.CheckTiles[tileIndex]) { _wvm.UndoManager.SaveTile(lFillLoc, y); _wvm.SetPixel(lFillLoc, y); _wvm.UpdateRenderPixel(lFillLoc, y); _wvm.CheckTiles[tileIndex] = true; } lFillLoc--; tileIndex--; if (lFillLoc <= 0 || _wvm.CheckTiles[tileIndex] || !CheckTileMatch(ref originTile, ref _wvm.CurrentWorld.Tiles[lFillLoc, y]) || !_wvm.Selection.IsValid(lFillLoc, y)) break; //exit loop if we're at edge of bitmap or color area } /* Heathtech */ BlendRules.ResetUVCache(_wvm, lFillLoc + 1, y, x - lFillLoc, 1); lFillLoc++; if (lFillLoc < _minX) _minX = lFillLoc; //FIND RIGHT EDGE OF COLOR AREA int rFillLoc = x; //the location to check/fill on the left tileIndex = (bitmapWidth * y) + x; while (true) { if (!_wvm.CheckTiles[tileIndex]) { _wvm.UndoManager.SaveTile(rFillLoc, y); _wvm.SetPixel(rFillLoc, y); _wvm.UpdateRenderPixel(rFillLoc, y); _wvm.CheckTiles[tileIndex] = true; BlendRules.ResetUVCache(_wvm, rFillLoc, y, 1, 1); } rFillLoc++; tileIndex++; if (rFillLoc >= bitmapWidth || _wvm.CheckTiles[tileIndex] || !CheckTileMatch(ref originTile, ref _wvm.CurrentWorld.Tiles[rFillLoc, y]) || !_wvm.Selection.IsValid(rFillLoc, y)) break; //exit loop if we're at edge of bitmap or color area } /* Heathtech */ BlendRules.ResetUVCache(_wvm, x, y, rFillLoc - x, 1); rFillLoc--; if (rFillLoc > _maxX) _maxX = rFillLoc; var r = new FloodFillRange(lFillLoc, rFillLoc, y); _ranges.Enqueue(ref r); }
public static ClipboardBuffer Load2(string filename) { using (var stream = new FileStream(filename, FileMode.Open)) { using (var reader = new BinaryReader(stream)) { string name = reader.ReadString(); int version = reader.ReadInt32(); int maxx = reader.ReadInt32(); int maxy = reader.ReadInt32(); var buffer = new ClipboardBuffer(new Vector2Int32(maxx, maxy)); buffer.Name = string.IsNullOrWhiteSpace(name) ? Path.GetFileNameWithoutExtension(filename) : name; try { for (int x = 0; x < maxx; x++) { for (int y = 0; y < maxy; y++) { var curTile = new Tile(); curTile.IsActive = reader.ReadBoolean(); if (curTile.IsActive) { curTile.Type = reader.ReadByte(); if (curTile.Type == 19) // fix for platforms { curTile.U = 0; curTile.V = 0; } else if (World.TileProperties[curTile.Type].IsFramed) { curTile.U = reader.ReadInt16(); curTile.V = reader.ReadInt16(); if (curTile.Type == 144) //timer curTile.V = 0; } else { curTile.U = -1; curTile.V = -1; } } if (reader.ReadBoolean()) curTile.Wall = reader.ReadByte(); if (reader.ReadBoolean()) { curTile.Liquid = reader.ReadByte(); curTile.IsLava = reader.ReadBoolean(); } curTile.HasWire = reader.ReadBoolean(); buffer.Tiles[x, y] = curTile; } } } catch (Exception) { for (int x = 0; x < buffer.Size.X; x++) { for (int y = 0; y < buffer.Size.Y; y++) { if (buffer.Tiles[x, y] == null) buffer.Tiles[x, y] = new Tile(); } } return buffer; } for (int chestIndex = 0; chestIndex < 1000; chestIndex++) { if (reader.ReadBoolean()) { var chest = new Chest(); chest.X = reader.ReadInt32(); chest.Y = reader.ReadInt32(); for (int slot = 0; slot < 20; slot++) { byte stackSize = reader.ReadByte(); if (stackSize > 0) { string itemName = reader.ReadString(); chest.Items[slot].SetFromName(itemName); chest.Items[slot].StackSize = stackSize; } } //Chests[chestIndex] = chest; buffer.Chests.Add(chest); } } for (int signIndex = 0; signIndex < 1000; signIndex++) { if (reader.ReadBoolean()) { string signText = reader.ReadString(); int x = reader.ReadInt32(); int y = reader.ReadInt32(); if (buffer.Tiles[x, y].IsActive && (buffer.Tiles[x, y].Type == 55 || buffer.Tiles[x, y].Type == 85)) // validate tile location { var sign = new Sign(x, y, signText); //Signs[signIndex] = sign; buffer.Signs.Add(sign); } } } string checkName = reader.ReadString(); int checkversion = reader.ReadInt32(); int checkx = reader.ReadInt32(); int checky = reader.ReadInt32(); if (checkName != buffer.Name || checkversion != version || checkx != maxx || checky != maxy) System.Windows.MessageBox.Show("Verification failed. Some schematic data may be missing.", "Legacy Schematic Version"); return buffer; } } #pragma warning disable 162 return null; #pragma warning restore }
public static void WriteTileDataToStream(Tile curTile, BinaryWriter bw) { if (curTile.Type == 127) curTile.IsActive = false; bw.Write(curTile.IsActive); if (curTile.IsActive) { bw.Write(curTile.Type); if (TileProperties[curTile.Type].IsFramed) { bw.Write(curTile.U); bw.Write(curTile.V); } if (curTile.Color > 0) { bw.Write(true); bw.Write(curTile.Color); } else bw.Write(false); } if ((int)curTile.Wall > 0) { bw.Write(true); bw.Write(curTile.Wall); if (curTile.WallColor > 0) { bw.Write(true); bw.Write(curTile.WallColor); } else bw.Write(false); } else bw.Write(false); if ((int)curTile.Liquid > 0) { bw.Write(true); bw.Write(curTile.Liquid); bw.Write(curTile.IsLava); bw.Write(curTile.IsHoney); } else bw.Write(false); bw.Write(curTile.HasWire); bw.Write(curTile.HasWire2); bw.Write(curTile.HasWire3); bw.Write(curTile.HalfBrick); bw.Write(curTile.Slope); bw.Write(curTile.Actuator); bw.Write(curTile.InActive); }
public static ClipboardBuffer Load3(string filename, bool frame19 = false) { bool failed = false; try { using (var stream = new FileStream(filename, FileMode.Open)) { using (var br = new BinaryReader(stream)) { string name = br.ReadString(); int version = br.ReadInt32(); int sizeX = br.ReadInt32(); int sizeY = br.ReadInt32(); var buffer = new ClipboardBuffer(new Vector2Int32(sizeX, sizeY)); buffer.Name = name; for (int x = 0; x < sizeX; x++) { for (int y = 0; y < sizeY; y++) { var curTile = new Tile(); curTile.IsActive = br.ReadBoolean(); if (curTile.IsActive) { curTile.Type = br.ReadByte(); if (curTile.Type == 19) // fix for platforms { curTile.U = 0; curTile.V = 0; if (frame19) { curTile.U = br.ReadInt16(); curTile.V = br.ReadInt16(); } } else if (World.TileProperties[curTile.Type].IsFramed) { curTile.U = br.ReadInt16(); curTile.V = br.ReadInt16(); if (curTile.Type == 144) //timer curTile.V = 0; } else { curTile.U = -1; curTile.V = -1; } } if (br.ReadBoolean()) curTile.Wall = br.ReadByte(); if (br.ReadBoolean()) { curTile.Liquid = br.ReadByte(); curTile.IsLava = br.ReadBoolean(); } curTile.HasWire = br.ReadBoolean(); buffer.Tiles[x, y] = curTile; } } for (int chestIndex = 0; chestIndex < 1000; chestIndex++) { if (br.ReadBoolean()) { var curChest = new Chest(br.ReadInt32(), br.ReadInt32()); for (int j = 0; j < 20; ++j) { curChest.Items[j].StackSize = br.ReadByte(); if (curChest.Items[j].StackSize > 0) { if (version >= 3) curChest.Items[j].NetId = br.ReadInt32(); else curChest.Items[j].SetFromName(br.ReadString()); curChest.Items[j].Prefix = br.ReadByte(); } else { curChest.Items[j].SetFromName("[empty]"); } } buffer.Chests.Add(curChest); } } for (int signIndex = 0; signIndex < 1000; signIndex++) { if (br.ReadBoolean()) { string text = br.ReadString(); int x = br.ReadInt32(); int y = br.ReadInt32(); buffer.Signs.Add(new Sign(x, y, text)); } } if (buffer.Name != br.ReadString() || version != br.ReadInt32() || buffer.Size.X != br.ReadInt32() || buffer.Size.Y != br.ReadInt32()) { if (!frame19) { br.Close(); return Load3(filename, true); } else System.Windows.MessageBox.Show("Verification failed. Some schematic data may be missing.", "Legacy Schematic Version"); } br.Close(); return buffer; } } } catch (Exception) { failed = true; } if (failed && !frame19) { return Load3(filename, true); } return null; }
private bool CheckTileMatch(ref Tile originTile, ref Tile nextTile) { switch (_wvm.TilePicker.PaintMode) { case PaintMode.Tile: if (originTile.Type != nextTile.Type || originTile.IsActive != nextTile.IsActive) return false; break; case PaintMode.Wall: if (originTile.Wall != nextTile.Wall) return false; break; case PaintMode.TileAndWall: if (originTile.Type != nextTile.Type || originTile.IsActive != nextTile.IsActive || originTile.Wall != nextTile.Wall) return false; break; case PaintMode.Wire: return false; case PaintMode.Liquid: if ((originTile.Liquid > 0 != nextTile.Liquid > 0) || originTile.IsLava != nextTile.IsLava || originTile.IsHoney != nextTile.IsHoney || (originTile.IsActive && World.TileProperties[originTile.Type].IsSolid) || (nextTile.IsActive && World.TileProperties[nextTile.Type].IsSolid)) return false; break; } return true; }
public static ClipboardBuffer Load4(string filename) { using (var stream = new FileStream(filename, FileMode.Open)) { using (var b = new BinaryReader(stream)) { string name = b.ReadString(); int version = b.ReadInt32(); int sizeX = b.ReadInt32(); int sizeY = b.ReadInt32(); var buffer = new ClipboardBuffer(new Vector2Int32(sizeX, sizeY)); buffer.Name = name; for (int x = 0; x < sizeX; ++x) { for (int y = 0; y < sizeY; y++) { var tile = new Tile(); tile.IsActive = b.ReadBoolean(); TileProperty tileProperty = null; if (tile.IsActive) { tile.Type = b.ReadByte(); tileProperty = World.TileProperties[tile.Type]; if (tile.Type == 127) tile.IsActive = false; if (tileProperty.IsFramed) { tile.U = b.ReadInt16(); tile.V = b.ReadInt16(); if (tile.Type == 144) //timer tile.V = 0; } else { tile.U = -1; tile.V = -1; } if (b.ReadBoolean()) { tile.Color = b.ReadByte(); } } if (b.ReadBoolean()) { tile.Wall = b.ReadByte(); if (b.ReadBoolean()) tile.WallColor = b.ReadByte(); } if (b.ReadBoolean()) { tile.Liquid = b.ReadByte(); tile.IsLava = b.ReadBoolean(); tile.IsHoney = b.ReadBoolean(); } tile.HasWire = b.ReadBoolean(); tile.HasWire2 = b.ReadBoolean(); tile.HasWire3 = b.ReadBoolean(); tile.HalfBrick = b.ReadBoolean(); if (tileProperty == null || !tileProperty.IsSolid) tile.HalfBrick = false; tile.Slope = b.ReadByte(); if (tileProperty == null || !tileProperty.IsSolid) tile.Slope = 0; tile.Actuator = b.ReadBoolean(); tile.InActive = b.ReadBoolean(); // read complete, start compression buffer.Tiles[x, y] = tile; int rle = b.ReadInt16(); if (rle < 0) throw new ApplicationException("Invalid Tile Data!"); if (rle > 0) { for (int k = y + 1; k < y + rle + 1; k++) { var tcopy = (Tile)tile.Clone(); buffer.Tiles[x, k] = tcopy; } y = y + rle; } } } for (int i = 0; i < 1000; i++) { if (b.ReadBoolean()) { var chest = new Chest(b.ReadInt32(), b.ReadInt32()); for (int slot = 0; slot < Chest.MaxItems; slot++) { if (slot < Chest.MaxItems) { int stackSize = (int)b.ReadInt16(); chest.Items[slot].StackSize = stackSize; if (chest.Items[slot].StackSize > 0) { chest.Items[slot].NetId = b.ReadInt32(); chest.Items[slot].StackSize = stackSize; chest.Items[slot].Prefix = b.ReadByte(); } } } buffer.Chests.Add(chest); } } for (int i = 0; i < 1000; i++) { if (b.ReadBoolean()) { Sign sign = new Sign(); sign.Text = b.ReadString(); sign.X = b.ReadInt32(); sign.Y = b.ReadInt32(); if (buffer.Tiles[sign.X, sign.Y].IsActive && (int)buffer.Tiles[sign.X, sign.Y].Type == 55 && (int)buffer.Tiles[sign.X, sign.Y].Type == 85) buffer.Signs.Add(sign); } } string verifyName = b.ReadString(); int verifyVersion = b.ReadInt32(); int verifyX = b.ReadInt32(); int verifyY = b.ReadInt32(); if (buffer.Name == verifyName && version == verifyVersion && buffer.Size.X == verifyX && buffer.Size.Y == verifyY) { // valid; return buffer; } b.Close(); return null; } } }
public static UndoBuffer Read(string filename) { var buffer = new UndoBuffer(); using (var stream = new FileStream(filename, FileMode.Open)) { using (var br = new BinaryReader(stream)) { var tilecount = br.ReadInt32(); for (int i = 0; i < tilecount; i++) { int x = br.ReadInt32(); int y = br.ReadInt32(); var curTile = new Tile(); curTile.IsActive = br.ReadBoolean(); if (curTile.IsActive) { curTile.Type = br.ReadByte(); if (World.TileProperties[curTile.Type].IsFramed) { curTile.U = br.ReadInt16(); curTile.V = br.ReadInt16(); } } if (br.ReadBoolean()) curTile.Wall = br.ReadByte(); if (br.ReadBoolean()) { curTile.Liquid = br.ReadByte(); curTile.IsLava = br.ReadBoolean(); } curTile.HasWire = br.ReadBoolean(); buffer.Tiles.Add(new UndoTile(new Vector2Int32(x,y), curTile)); } for (int chestIndex = 0; chestIndex < 1000; chestIndex++) { if (br.ReadBoolean()) { var curChest = new Chest(br.ReadInt32(), br.ReadInt32()); for (int j = 0; j < Chest.MaxItems; ++j) { curChest.Items[j].StackSize = br.ReadByte(); if (curChest.Items[j].StackSize > 0) { curChest.Items[j].NetId = br.ReadInt32(); curChest.Items[j].Prefix = br.ReadByte(); } else { curChest.Items[j].NetId = 0; } } buffer.Chests.Add(curChest); } } for (int signIndex = 0; signIndex < 1000; signIndex++) { if (br.ReadBoolean()) { string text = br.ReadString(); int x = br.ReadInt32(); int y = br.ReadInt32(); buffer.Signs.Add(new Sign(x, y, text)); } } } } return buffer; }
public static ClipboardBuffer LoadOld(string filename) { using (var stream = new FileStream(filename, FileMode.Open)) { using (var reader = new BinaryReader(stream)) { string name = reader.ReadString(); int version = reader.ReadInt32(); int maxx = reader.ReadInt32(); int maxy = reader.ReadInt32(); var buffer = new ClipboardBuffer(new Vector2Int32(maxx, maxy)); buffer.Name = string.IsNullOrWhiteSpace(name) ? Path.GetFileNameWithoutExtension(filename) : name; try { for (int x = 0; x < buffer.Size.X; x++) { for (int y = 0; y < buffer.Size.Y; y++) { var tile = new Tile(); tile.IsActive = reader.ReadBoolean(); if (tile.IsActive) { tile.Type = reader.ReadByte(); if (tile.Type == 19) { tile.U = 0; tile.V = 0; } else if (World.TileProperties[tile.Type].IsFramed) { tile.U = reader.ReadInt16(); tile.V = reader.ReadInt16(); } else { tile.U = -1; tile.V = -1; } } // trash old lighted value reader.ReadBoolean(); if (reader.ReadBoolean()) { tile.Wall = reader.ReadByte(); } if (reader.ReadBoolean()) { tile.Liquid = reader.ReadByte(); tile.IsLava = reader.ReadBoolean(); } buffer.Tiles[x, y] = tile; } } } catch (Exception) { for (int x = 0; x < buffer.Size.X; x++) { for (int y = 0; y < buffer.Size.Y; y++) { if (buffer.Tiles[x, y] == null) buffer.Tiles[x, y] = new Tile(); } } return buffer; } for (int chestIndex = 0; chestIndex < 1000; chestIndex++) { if (reader.ReadBoolean()) { var chest = new Chest(); chest.X = reader.ReadInt32(); chest.Y = reader.ReadInt32(); for (int slot = 0; slot < 20; slot++) { byte stackSize = reader.ReadByte(); if (stackSize > 0) { string itemName = reader.ReadString(); chest.Items[slot].SetFromName(itemName); chest.Items[slot].StackSize = stackSize; } } //Chests[chestIndex] = chest; buffer.Chests.Add(chest); } } for (int signIndex = 0; signIndex < 1000; signIndex++) { if (reader.ReadBoolean()) { string signText = reader.ReadString(); int x = reader.ReadInt32(); int y = reader.ReadInt32(); if (buffer.Tiles[x, y].IsActive && (buffer.Tiles[x, y].Type == 55 || buffer.Tiles[x, y].Type == 85)) // validate tile location { var sign = new Sign(x, y, signText); //Signs[signIndex] = sign; buffer.Signs.Add(sign); } } } int checkx = reader.ReadInt32(); int checky = reader.ReadInt32(); if (checkx == maxx && checky == maxy) return buffer; } } return null; }
private void SetTile(Tile curTile, bool erase) { if (TilePicker.TileMaskMode == MaskMode.Off || (TilePicker.TileMaskMode == MaskMode.Match && curTile.Type == TilePicker.TileMask && curTile.IsActive) || (TilePicker.TileMaskMode == MaskMode.Empty && !curTile.IsActive) || (TilePicker.TileMaskMode == MaskMode.NotMatching && (curTile.Type != TilePicker.TileMask || !curTile.IsActive))) { if (erase) SetPixelAutomatic(curTile, tile: -1); else SetPixelAutomatic(curTile, tile: TilePicker.Tile); } }
public byte TileArgsToByte(Tile tile) { byte b = 0; if (tile.IsActive) b |= (byte)TileFlags.IsActive; if (tile.IsLava) b |= (byte)TileFlags.IsLava; if (tile.HasWire) b |= (byte)TileFlags.HasWire; if (tile.IsHoney) b |= (byte)TileFlags.IsHoney; if (tile.HasWire2) b |= (byte)TileFlags.HasWire2; if (tile.HasWire3) b |= (byte)TileFlags.HasWire3; if (tile.Actuator) b |= (byte)TileFlags.Actuator; if (tile.InActive) b |= (byte)TileFlags.InActive; return b; }
protected void ClearTile(Tile tile) { tile.Type = 0; tile.IsActive = false; tile.U = 0; tile.V = 0; }
private static Tile TileFromColor(int color) { byte a = (byte)(color >> 24); byte r = (byte)(color >> 16); byte g = (byte)(color >> 8); byte b = (byte)(color >> 0); var tile = new Tile(); // try and find a matching brick var tileProperty = World.GetBrickFromColor(a, r, g, b); if (tileProperty != null && !tileProperty.IsFramed) { tile.IsActive = true; tile.Type = (byte)tileProperty.Id; } // try and find a matching wall var wallproperty = World.GetWallFromColor(a, r, g, b); if (wallproperty != null && !tile.IsActive) { tile.Wall = (byte)wallproperty.Id; } return tile; }
protected bool Equals(Tile other) { return IsActive.Equals(other.IsActive) && Type == other.Type && TileColor == other.TileColor && U == other.U && V == other.V && LiquidType.Equals(other.LiquidType) && LiquidAmount == other.LiquidAmount && Wall == other.Wall && WallColor == other.WallColor && WireRed.Equals(other.WireRed) && WireGreen.Equals(other.WireGreen) && WireBlue.Equals(other.WireBlue) && BrickStyle.Equals(other.BrickStyle) && BrickStyle == other.BrickStyle && Actuator.Equals(other.Actuator) && InActive.Equals(other.InActive); }
private static Tile TileFromFalseColor(int color) { byte a = (byte)(color >> 24); byte r = (byte)(color >> 16); byte g = (byte)(color >> 8); byte b = (byte)(color >> 0); var tile = new Tile(); AppendTileFlagsFromByte(ref tile, a); // try and find a matching brick var tileProperty = World.TileProperties.FirstOrDefault(t => t.Id == r); if (tileProperty != null && !tileProperty.IsFramed) { tile.Type = (byte)tileProperty.Id; } else { // disable missing and framed tiles tile.IsActive = false; } // try and find a matching wall var wallproperty = World.WallProperties[g]; if (wallproperty != null && !tile.IsActive) { tile.Wall = (byte)wallproperty.Id; } tile.Liquid = b; return tile; }
public UndoTile(Vector2Int32 location, Tile tile) { Location = location; Tile = tile; }
public static Tile ReadTileDataFromStream(BinaryReader b, uint version) { Tile tile = new Tile(); tile.IsActive = b.ReadBoolean(); TileProperty tileProperty = null; if (tile.IsActive) { tile.Type = b.ReadByte(); tileProperty = TileProperties[tile.Type]; if (tile.Type == 127) tile.IsActive = false; if (version < 72 && (tile.Type == 35 || tile.Type == 36 || tile.Type == 170 || tile.Type == 171 || tile.Type == 172)) { tile.U = b.ReadInt16(); tile.V = b.ReadInt16(); } else if (!tileProperty.IsFramed) { tile.U = -1; tile.V = -1; } else if (version < 28 && tile.Type == 4) { // torches didn't have extra in older versions. tile.U = 0; tile.V = 0; } else if (version < 40 && tile.Type == 19) { tile.U = 0; tile.V = 0; } else { tile.U = b.ReadInt16(); tile.V = b.ReadInt16(); if (tile.Type == 144) //timer tile.V = 0; } if (version >= 48 && b.ReadBoolean()) { tile.Color = b.ReadByte(); } } //skip obsolete hasLight if (version <= 25) b.ReadBoolean(); if (b.ReadBoolean()) { tile.Wall = b.ReadByte(); if (version >= 48 && b.ReadBoolean()) tile.WallColor = b.ReadByte(); } if (b.ReadBoolean()) { tile.Liquid = b.ReadByte(); tile.IsLava = b.ReadBoolean(); if (version >= 51) { tile.IsHoney = b.ReadBoolean(); } } if (version >= 33) { tile.HasWire = b.ReadBoolean(); } if (version >= 43) { tile.HasWire2 = b.ReadBoolean(); tile.HasWire3 = b.ReadBoolean(); } if (version >= 41) { tile.HalfBrick = b.ReadBoolean(); if (tileProperty == null || !tileProperty.IsSolid) tile.HalfBrick = false; if (version >= 49) { tile.Slope = b.ReadByte(); if (tileProperty == null || !tileProperty.IsSolid) tile.Slope = 0; } } if (version >= 42) { tile.Actuator = b.ReadBoolean(); tile.InActive = b.ReadBoolean(); } return tile; }
private void NewWorld() { NewWorldView nwDialog = new NewWorldView(); if ((bool)nwDialog.ShowDialog()) { _loadTimer.Reset(); _loadTimer.Start(); _saveTimer.Stop(); Task.Factory.StartNew(() => { var w = nwDialog.NewWorld; w.SpawnX = w.TilesWide / 2; w.SpawnY = (int)Math.Max(0, w.GroundLevel - 10); w.GroundLevel = (int)w.GroundLevel; w.RockLevel = (int)w.RockLevel; w.BottomWorld = w.TilesHigh * 16; w.RightWorld = w.TilesWide * 16; w.Tiles = new Tile[w.TilesWide, w.TilesHigh]; Tile cloneTile = new Tile(); for (int y = 0; y < w.TilesHigh; y++) { OnProgressChanged(w, new ProgressChangedEventArgs(BCCL.Utility.Calc.ProgressPercentage(y, w.TilesHigh), "Generating World...")); if (y == (int)w.GroundLevel - 10) cloneTile = new Tile { HasWire = false, IsActive = true, IsLava = false, Liquid = 0, Type = 2, U = -1, V = -1, Wall = 2 }; if (y == (int)w.GroundLevel - 9) cloneTile = new Tile { HasWire = false, IsActive = true, IsLava = false, Liquid = 0, Type = 0, U = -1, V = -1, Wall = 2 }; else if (y == (int)w.GroundLevel + 1) cloneTile = new Tile { HasWire = false, IsActive = true, IsLava = false, Liquid = 0, Type = 0, U = -1, V = -1, Wall = 0 }; else if (y == (int)w.RockLevel) cloneTile = new Tile { HasWire = false, IsActive = true, IsLava = false, Liquid = 0, Type = 1, U = -1, V = -1, Wall = 0 }; else if (y == w.TilesHigh - 182) cloneTile = new Tile(); for (int x = 0; x < w.TilesWide; x++) { w.Tiles[x, y] = (Tile)cloneTile.Clone(); } } return w; }) .ContinueWith(t => CurrentWorld = t.Result, TaskFactoryHelper.UiTaskScheduler) .ContinueWith(t => RenderEntireWorld()) .ContinueWith(t => { CurrentFile = null; PixelMap = t.Result; UpdateTitle(); Points.Clear(); Points.Add("Spawn"); Points.Add("Dungeon"); foreach (var npc in CurrentWorld.NPCs) { Points.Add(npc.Name); } _loadTimer.Stop(); OnProgressChanged(this, new ProgressChangedEventArgs(0, string.Format("World loaded in {0} seconds.", _loadTimer.Elapsed.TotalSeconds))); _saveTimer.Start(); }, TaskFactoryHelper.UiTaskScheduler); } }
public void Validate() { for (int x = 0; x < TilesWide; x++) { OnProgressChanged(this, new ProgressChangedEventArgs((int) (x/(float) TilesWide*100.0), "Validating World...")); for (int y = 0; y < TilesHigh; y++) { Tile curTile = Tiles[x, y]; if (curTile.Type == 127) curTile.IsActive = false; // TODO: Let Validate handle these //validate chest entry exists if (curTile.Type == 21) { if (GetChestAtTile(x, y) == null) { Chests.Add(new Chest(x, y)); } } //validate sign entry exists else if (curTile.Type == 55 || curTile.Type == 85) { if (GetSignAtTile(x, y) == null) { Signs.Add(new Sign(x, y, string.Empty)); } } } } foreach (Chest chest in Chests.ToArray()) { bool removed = false; for (int x = chest.X; x < chest.X+1; x++) { for (int y = chest.Y; y < chest.Y + 1; y++) { if (!Tiles[x, y].IsActive || Tiles[x, y].Type != 21) { Chests.Remove(chest); removed = true; break; } } if (removed) break; } } foreach (Sign sign in Signs.ToArray()) { if (sign.Text == null) { Signs.Remove(sign); continue; } bool removed = false; for (int x = sign.X; x < sign.X + 1; x++) { for (int y = sign.Y; y < sign.Y + 1; y++) { if (!Tiles[x, y].IsActive || (Tiles[x, y].Type != 55 && Tiles[x, y].Type != 85)) { Signs.Remove(sign); removed = true; break; } } if (removed) break; } } }