From 2100e8c4abf9662b99b1aaada3469fb6e4cdcc6d Mon Sep 17 00:00:00 2001 From: Daniel Vidmar Date: Sun, 1 Mar 2015 00:24:29 -0500 Subject: [PATCH] Terrain Decorations & some fixes - Decorations are terrain features such as trees & dungeons - cleaned up the code for chunk decorators, and tree & dungeon generation - monster spawner blocks now have no drop - when a block is set to air its metadata value is now reset to 0x0 --- TrueCraft.API/TrueCraft.API.csproj | 1 + TrueCraft.API/World/IDecoration.cs | 13 + .../Logic/Blocks/MonsterSpawnerBlock.cs | 6 + .../TerrainGen/Decorations/BalloonOakTree.cs | 36 +++ .../TerrainGen/Decorations/BirchTree.cs | 36 +++ .../TerrainGen/Decorations/ConiferTree.cs | 31 +++ .../TerrainGen/Decorations/Decoration.cs | 195 +++++++++++++++ .../TerrainGen/Decorations/Dungeon.cs | 105 ++++++++ .../TerrainGen/Decorations/OakTree.cs | 36 +++ .../TerrainGen/Decorations/PineTree.cs | 63 +++++ .../TerrainGen/Decorators/CactusDecorator.cs | 6 +- .../TerrainGen/Decorators/DungeonDecorator.cs | 119 +-------- .../Decorators/SugarCaneDecorator.cs | 55 +---- .../TerrainGen/Decorators/TreeDecorator.cs | 230 +++--------------- TrueCraft.Core/TerrainGen/NewGenerator.cs | 1 + TrueCraft.Core/TrueCraft.Core.csproj | 7 + TrueCraft.Core/World/Chunk.cs | 5 +- 17 files changed, 590 insertions(+), 355 deletions(-) create mode 100644 TrueCraft.API/World/IDecoration.cs create mode 100644 TrueCraft.Core/TerrainGen/Decorations/BalloonOakTree.cs create mode 100644 TrueCraft.Core/TerrainGen/Decorations/BirchTree.cs create mode 100644 TrueCraft.Core/TerrainGen/Decorations/ConiferTree.cs create mode 100644 TrueCraft.Core/TerrainGen/Decorations/Decoration.cs create mode 100644 TrueCraft.Core/TerrainGen/Decorations/Dungeon.cs create mode 100644 TrueCraft.Core/TerrainGen/Decorations/OakTree.cs create mode 100644 TrueCraft.Core/TerrainGen/Decorations/PineTree.cs diff --git a/TrueCraft.API/TrueCraft.API.csproj b/TrueCraft.API/TrueCraft.API.csproj index 56e7b11..35c79c0 100644 --- a/TrueCraft.API/TrueCraft.API.csproj +++ b/TrueCraft.API/TrueCraft.API.csproj @@ -65,6 +65,7 @@ + diff --git a/TrueCraft.API/World/IDecoration.cs b/TrueCraft.API/World/IDecoration.cs new file mode 100644 index 0000000..bd87e45 --- /dev/null +++ b/TrueCraft.API/World/IDecoration.cs @@ -0,0 +1,13 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace TrueCraft.API.World +{ + public interface IDecoration + { + bool ValidLocation(Coordinates3D location); + bool GenerateAt(IWorld world, IChunk chunk, Coordinates3D location); + } +} \ No newline at end of file diff --git a/TrueCraft.Core/Logic/Blocks/MonsterSpawnerBlock.cs b/TrueCraft.Core/Logic/Blocks/MonsterSpawnerBlock.cs index 6f35932..cf1906a 100644 --- a/TrueCraft.Core/Logic/Blocks/MonsterSpawnerBlock.cs +++ b/TrueCraft.Core/Logic/Blocks/MonsterSpawnerBlock.cs @@ -1,5 +1,6 @@ using System; using TrueCraft.API.Logic; +using TrueCraft.API; namespace TrueCraft.Core.Logic.Blocks { @@ -23,5 +24,10 @@ namespace TrueCraft.Core.Logic.Blocks { return new Tuple(1, 4); } + + protected override ItemStack[] GetDrop(BlockDescriptor descriptor) + { + return new ItemStack[0]; + } } } \ No newline at end of file diff --git a/TrueCraft.Core/TerrainGen/Decorations/BalloonOakTree.cs b/TrueCraft.Core/TerrainGen/Decorations/BalloonOakTree.cs new file mode 100644 index 0000000..74cf8f6 --- /dev/null +++ b/TrueCraft.Core/TerrainGen/Decorations/BalloonOakTree.cs @@ -0,0 +1,36 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using TrueCraft.API.World; +using TrueCraft.API; +using TrueCraft.Core.Logic.Blocks; +using TrueCraft.Core.World; + +namespace TrueCraft.Core.TerrainGen.Decorations +{ + public class BalloonOakTree : Decoration + { + int LeafRadius = 2; + + public override bool ValidLocation(Coordinates3D location) + { + if (location.X - LeafRadius < 0 || location.X + LeafRadius >= Chunk.Width || location.Z - LeafRadius < 0 || location.Z + LeafRadius >= Chunk.Depth || location.Y + LeafRadius >= Chunk.Height) + return false; + return true; + } + + public override bool GenerateAt(IWorld world, IChunk chunk, Coordinates3D location) + { + if (!ValidLocation(location)) + return false; + + Random R = new Random(world.Seed); + int Height = R.Next(4, 5); + GenerateColumn(chunk, location, Height, WoodBlock.BlockID, 0x0); + Coordinates3D LeafLocation = location + new Coordinates3D(0, Height, 0); + GenerateSphere(chunk, LeafLocation, LeafRadius, LeavesBlock.BlockID, 0x0); + return true; + } + } +} \ No newline at end of file diff --git a/TrueCraft.Core/TerrainGen/Decorations/BirchTree.cs b/TrueCraft.Core/TerrainGen/Decorations/BirchTree.cs new file mode 100644 index 0000000..69696e6 --- /dev/null +++ b/TrueCraft.Core/TerrainGen/Decorations/BirchTree.cs @@ -0,0 +1,36 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using TrueCraft.API.World; +using TrueCraft.API; +using TrueCraft.Core.Logic.Blocks; +using TrueCraft.Core.World; + +namespace TrueCraft.Core.TerrainGen.Decorations +{ + public class BirchTree : Decoration + { + int LeafRadius = 2; + + public override bool ValidLocation(Coordinates3D location) + { + if (location.X - LeafRadius < 0 || location.X + LeafRadius >= Chunk.Width || location.Z - LeafRadius < 0 || location.Z + LeafRadius >= Chunk.Depth) + return false; + return true; + } + + public override bool GenerateAt(IWorld world, IChunk chunk, Coordinates3D location) + { + if (!ValidLocation(location)) + return false; + + Random R = new Random(world.Seed); + int Height = R.Next(4, 5); + GenerateColumn(chunk, location, Height, WoodBlock.BlockID, 0x2); + Coordinates3D LeafLocation = location + new Coordinates3D(0, Height, 0); + GenerateVanillaLeaves(chunk, LeafLocation, LeafRadius, LeavesBlock.BlockID, 0x2); + return true; + } + } +} \ No newline at end of file diff --git a/TrueCraft.Core/TerrainGen/Decorations/ConiferTree.cs b/TrueCraft.Core/TerrainGen/Decorations/ConiferTree.cs new file mode 100644 index 0000000..a8155d5 --- /dev/null +++ b/TrueCraft.Core/TerrainGen/Decorations/ConiferTree.cs @@ -0,0 +1,31 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using TrueCraft.API; +using TrueCraft.API.World; +using TrueCraft.Core.Logic.Blocks; +using TrueCraft.Core.World; + +namespace TrueCraft.Core.TerrainGen.Decorations +{ + public class ConiferTree : PineTree + { + int LeafRadius = 2; + int LeafOffset = 3; + public override bool GenerateAt(IWorld world, IChunk chunk, Coordinates3D location) + { + if (!ValidLocation(location)) + return false; + + Random R = new Random(world.Seed); + int Height = R.Next(7, 8); + GenerateColumn(chunk, location, Height, WoodBlock.BlockID, 0x1); + GenerateCircle(chunk, location + new Coordinates3D(0, Height - 2, 0), LeafRadius - 1, LeavesBlock.BlockID, 0x1); + GenerateCircle(chunk, location + new Coordinates3D(0, Height - 1, 0), LeafRadius, LeavesBlock.BlockID, 0x1); + GenerateCircle(chunk, location + new Coordinates3D(0, Height, 0), LeafRadius, LeavesBlock.BlockID, 0x1); + GenerateTopper(chunk, (location + new Coordinates3D(0, Height + 1, 0)), 0x0); + return true; + } + } +} diff --git a/TrueCraft.Core/TerrainGen/Decorations/Decoration.cs b/TrueCraft.Core/TerrainGen/Decorations/Decoration.cs new file mode 100644 index 0000000..55662df --- /dev/null +++ b/TrueCraft.Core/TerrainGen/Decorations/Decoration.cs @@ -0,0 +1,195 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using TrueCraft.API.World; +using TrueCraft.API; +using TrueCraft.Core.World; + +namespace TrueCraft.Core.TerrainGen.Decorations +{ + public abstract class Decoration : IDecoration + { + public virtual bool ValidLocation(Coordinates3D location) { return true; } + + public abstract bool GenerateAt(IWorld world, IChunk chunk, Coordinates3D location); + + public static bool IsCuboidWall(Coordinates2D location, Coordinates3D start, Vector3 size) + { + return location.X.Equals(start.X) || location.Z.Equals(start.Z) || location.X.Equals(start.X + (int)size.X - 1) || location.Z.Equals(start.Z + (int)size.Z - 1); + } + + public static bool IsCuboidCorner(Coordinates2D location, Coordinates3D start, Vector3 size) + { + return location.X.Equals(start.X) && location.Z.Equals(start.Z) || location.X.Equals(start.X) && location.Z.Equals(start.Z + (int)size.Z - 1) || location.X.Equals(start.X + (int)size.X - 1) && location.Z.Equals(start.Z) || location.X.Equals(start.X + (int)size.X - 1) && location.Z.Equals(start.Z + (int)size.Z - 1); + } + + public static bool NeighboursBlock(IChunk chunk, Coordinates3D location, byte block, byte meta = 0x0) + { + var Surrounding = new[] { + location + Coordinates3D.Left, + location + Coordinates3D.Right, + location + Coordinates3D.Forwards, + location + Coordinates3D.Backwards, + }; + for (int I = 0; I < Surrounding.Length; I++) + { + Coordinates3D Check = Surrounding[I]; + if (Check.X < 0 || Check.X >= Chunk.Width || Check.Z < 0 || Check.Z >= Chunk.Depth || Check.Y < 0 || Check.Y >= Chunk.Height) + return false; + if (chunk.GetBlockID(Check).Equals(block)) + { + if (meta != 0x0 && chunk.GetMetadata(Check) != meta) + return false; + return true; + } + } + return false; + } + + public static void GenerateColumn(IChunk chunk, Coordinates3D location, int height, byte block, byte meta = 0x0) + { + for (int offset = 0; offset < height; offset++) + { + Coordinates3D blockLocation = location + new Coordinates3D(0, offset, 0); + if (blockLocation.Y >= Chunk.Height) + return; + chunk.SetBlockID(blockLocation, block); + chunk.SetMetadata(blockLocation, meta); + } + } + + /* + * Cuboid Modes + * 0x0 - Solid cuboid of the specified block + * 0x1 - Hollow cuboid of the specified block + * 0x2 - Outlines the area of the cuboid using the specified block + */ + public static void GenerateCuboid(IChunk chunk, Coordinates3D location, Vector3 size, byte block, byte meta = 0x0, byte mode = 0x0) + { + //If mode is 0x2 offset the size by 2 and change mode to 0x1 + if (mode.Equals(0x2)) + { + size += new Vector3(2, 2, 2); + mode = 0x1; + } + + for (int W = location.X; W < location.X + size.X; W++) + { + for (int L = location.Z; L < location.Z + size.Z; L++) + { + for (int H = location.Y; H < location.Y + size.Y; H++) + { + + if (W < 0 || W >= Chunk.Width || L < 0 || L >= Chunk.Depth || H < 0 || H >= Chunk.Height) + continue; + Coordinates3D BlockLocation = new Coordinates3D(W, H, L); + if (!H.Equals(location.Y) && !H.Equals(location.Y + (int)size.Y - 1) && !IsCuboidWall(new Coordinates2D(W, L), location, size) && !IsCuboidCorner(new Coordinates2D(W, L), location, size)) + continue; + + chunk.SetBlockID(BlockLocation, block); + if (meta != 0x0) + chunk.SetMetadata(BlockLocation, meta); + } + } + } + } + + protected void GenerateVanillaLeaves(IChunk chunk, Coordinates3D location, int radius, byte block, byte meta = 0x0) + { + int RadiusOffset = radius; + for (int YOffset = -radius; YOffset <= radius; YOffset = (YOffset + 1)) + { + int Y = location.Y + YOffset; + if (Y > Chunk.Height) + continue; + GenerateVanillaCircle(chunk, new Coordinates3D(location.X, Y, location.Z), RadiusOffset, block, meta); + if (YOffset != -radius && YOffset % 2 == 0) + RadiusOffset--; + } + } + + protected void GenerateVanillaCircle(IChunk chunk, Coordinates3D location, int radius, byte block, byte meta = 0x0, double corner = 0) + { + for (int I = -radius; I <= radius; I = (I + 1)) + { + for (int J = -radius; J <= radius; J = (J + 1)) + { + int Max = (int)Math.Sqrt((I * I) + (J * J)); + if (Max <= radius) + { + if (I.Equals(-radius) && J.Equals(-radius) || I.Equals(-radius) && J.Equals(radius) || I.Equals(radius) && J.Equals(-radius) || I.Equals(radius) && J.Equals(radius)) + { + if (corner + radius * 0.2 < 0.4 || corner + radius * 0.2 > 0.7 || corner.Equals(0)) + continue; + } + int X = location.X + I; + int Z = location.Z + J; + Coordinates3D CurrentBlock = new Coordinates3D(X, location.Y, Z); + if (chunk.GetBlockID(CurrentBlock).Equals(0)) + { + chunk.SetBlockID(CurrentBlock, block); + chunk.SetMetadata(CurrentBlock, meta); + } + } + } + } + } + + protected void GenerateCircle(IChunk chunk, Coordinates3D location, int radius, byte block, byte meta = 0x0) + { + for (int I = -radius; I <= radius; I = (I + 1)) + { + for (int J = -radius; J <= radius; J = (J + 1)) + { + int Max = (int)Math.Sqrt((I * I) + (J * J)); + if (Max <= radius) + { + int X = location.X + I; + int Z = location.Z + J; + + if (X < 0 || X >= Chunk.Width || Z < 0 || Z >= Chunk.Depth) + continue; + + Coordinates3D CurrentBlock = new Coordinates3D(X, location.Y, Z); + if (chunk.GetBlockID(CurrentBlock).Equals(0)) + { + chunk.SetBlockID(CurrentBlock, block); + chunk.SetMetadata(CurrentBlock, meta); + } + } + } + } + } + + protected static void GenerateSphere(IChunk chunk, Coordinates3D location, int radius, byte block, byte meta = 0x0) + { + for (int I = -radius; I <= radius; I = (I + 1)) + { + for (int J = -radius; J <= radius; J = (J + 1)) + { + for (int K = -radius; K <= radius; K = (K + 1)) + { + int Max = (int)Math.Sqrt((I * I) + (J * J) + (K * K)); + if (Max <= radius) + { + int X = location.X + I; + int Y = location.Y + K; + int Z = location.Z + J; + + if (X < 0 || X >= Chunk.Width || Z < 0 || Z >= Chunk.Depth || Y < 0 || Y >= Chunk.Height) + continue; + + Coordinates3D CurrentBlock = new Coordinates3D(X, Y, Z); + if (chunk.GetBlockID(CurrentBlock).Equals(0)) + { + chunk.SetBlockID(CurrentBlock, block); + chunk.SetMetadata(CurrentBlock, meta); + } + } + } + } + } + } + } +} \ No newline at end of file diff --git a/TrueCraft.Core/TerrainGen/Decorations/Dungeon.cs b/TrueCraft.Core/TerrainGen/Decorations/Dungeon.cs new file mode 100644 index 0000000..6bfa3a6 --- /dev/null +++ b/TrueCraft.Core/TerrainGen/Decorations/Dungeon.cs @@ -0,0 +1,105 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using TrueCraft.API; +using TrueCraft.API.World; +using TrueCraft.Core.Logic.Blocks; +using TrueCraft.Core.World; +using TrueCraft.Core.TerrainGen.Noise; + +namespace TrueCraft.Core.TerrainGen.Decorations +{ + public class Dungeon : Decoration + { + Vector3 Size = new Vector3(7, 5, 7); + int MaxEntrances = 5; + + public override bool ValidLocation(Coordinates3D location) + { + var OffsetSize = Size + new Vector3(1, 1, 1); + if (location.X + (int)OffsetSize.X >= Chunk.Width || location.Z + (int)OffsetSize.Z >= Chunk.Depth || location.Y + (int)OffsetSize.Y >= Chunk.Height) + return false; + return true; + } + + public override bool GenerateAt(IWorld world, IChunk chunk, Coordinates3D location) + { + if (!ValidLocation(location)) + return false; + Random R = new Random(world.Seed); + + //Generate room + GenerateCuboid(chunk, location, Size, CobblestoneBlock.BlockID, 0x0, 0x2); + + //Randomly add mossy cobblestone to floor + MossFloor(chunk, location, R); + + //Place Spawner + chunk.SetBlockID(new Coordinates3D((int)(location.X + ((Size.X + 1) / 2)), (int)((location + Coordinates3D.Up).Y), (int)(location.Z + ((Size.Z + 1) / 2))), MonsterSpawnerBlock.BlockID); + + //Create entrances + CreateEntraces(chunk, location, R); + + //Place Chests + PlaceChests(chunk, location, R); + return true; + } + + private void CreateEntraces(IChunk chunk, Coordinates3D location, Random R) + { + int Entrances = 0; + var Above = location + Coordinates3D.Up; + for (int X = location.X; X < location.X + Size.X; X++) + { + if (Entrances >= MaxEntrances) + break; + for (int Z = location.Z; Z < location.Z + Size.Z; Z++) + { + if (Entrances >= MaxEntrances) + break; + if (R.Next(0, 3) == 0 && IsCuboidWall(new Coordinates2D(X, Z), location, Size) && !IsCuboidCorner(new Coordinates2D(X, Z), location, Size)) + { + var BlockLocation = new Coordinates3D(X, Above.Y, Z); + chunk.SetBlockID(BlockLocation, AirBlock.BlockID); + chunk.SetBlockID(BlockLocation + Coordinates3D.Up, AirBlock.BlockID); + } + } + } + } + + private void MossFloor(IChunk chunk, Coordinates3D location, Random R) + { + for (int X = location.X; X < location.X + Size.X; X++) + { + for (int Z = location.Z; Z < location.Z + Size.Z; Z++) + { + if (R.Next(0, 3) == 0) + chunk.SetBlockID(new Coordinates3D(X, location.Y, Z), MossStoneBlock.BlockID); + } + } + } + + private void PlaceChests(IChunk chunk, Coordinates3D location, Random R) + { + var Above = location + Coordinates3D.Up; + var chests = R.Next(0, 2); + for (int I = 0; I < chests; I++) + { + for (int Attempts = 0; Attempts < 10; Attempts++) + { + var X = R.Next(location.X, location.X + (int)Size.X); + var Z = R.Next(location.Z, location.Z + (int)Size.Z); + if (!IsCuboidWall(new Coordinates2D(X, Z), location, Size) && !IsCuboidCorner(new Coordinates2D(X, Z), location, Size)) + { + if (NeighboursBlock(chunk, new Coordinates3D(X, Above.Y, Z), CobblestoneBlock.BlockID)) + { + chunk.SetBlockID(new Coordinates3D(X, Above.Y, Z), ChestBlock.BlockID); + break; + } + } + } + } + } + } +} \ No newline at end of file diff --git a/TrueCraft.Core/TerrainGen/Decorations/OakTree.cs b/TrueCraft.Core/TerrainGen/Decorations/OakTree.cs new file mode 100644 index 0000000..010d66b --- /dev/null +++ b/TrueCraft.Core/TerrainGen/Decorations/OakTree.cs @@ -0,0 +1,36 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using TrueCraft.API; +using TrueCraft.API.World; +using TrueCraft.Core.Logic.Blocks; +using TrueCraft.Core.World; + +namespace TrueCraft.Core.TerrainGen.Decorations +{ + public class OakTree : Decoration + { + int LeafRadius = 2; + + public override bool ValidLocation(Coordinates3D location) + { + if (location.X - LeafRadius < 0 || location.X + LeafRadius >= Chunk.Width || location.Z - LeafRadius < 0 || location.Z + LeafRadius >= Chunk.Depth) + return false; + return true; + } + + public override bool GenerateAt(IWorld world, IChunk chunk, Coordinates3D location) + { + if (!ValidLocation(location)) + return false; + + Random R = new Random(world.Seed); + int Height = R.Next(4, 5); + GenerateColumn(chunk, location, Height, WoodBlock.BlockID, 0x0); + Coordinates3D LeafLocation = location + new Coordinates3D(0, Height, 0); + GenerateVanillaLeaves(chunk, LeafLocation, LeafRadius, LeavesBlock.BlockID, 0x0); + return true; + } + } +} diff --git a/TrueCraft.Core/TerrainGen/Decorations/PineTree.cs b/TrueCraft.Core/TerrainGen/Decorations/PineTree.cs new file mode 100644 index 0000000..c41d87d --- /dev/null +++ b/TrueCraft.Core/TerrainGen/Decorations/PineTree.cs @@ -0,0 +1,63 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using TrueCraft.API; +using TrueCraft.API.World; +using TrueCraft.Core.Logic.Blocks; +using TrueCraft.Core.World; + +namespace TrueCraft.Core.TerrainGen.Decorations +{ + public class PineTree : Decoration + { + int LeafRadius = 2; + int BottomSpace = 2; + + public override bool ValidLocation(Coordinates3D location) + { + if (location.X - LeafRadius < 0 || location.X + LeafRadius >= Chunk.Width || location.Z - LeafRadius < 0 || location.Z + LeafRadius >= Chunk.Depth) + return false; + return true; + } + + public override bool GenerateAt(IWorld world, IChunk chunk, Coordinates3D location) + { + if (!ValidLocation(location)) + return false; + + Random R = new Random(world.Seed); + int Height = R.Next(7, 8); + GenerateColumn(chunk, location, Height, WoodBlock.BlockID, 0x1); + for (int Y = 1; Y < Height; Y++) + { + if (Y % 2 == 0) + { + GenerateVanillaCircle(chunk, location + new Coordinates3D(0, Y + 1, 0), LeafRadius - 1, LeavesBlock.BlockID, 0x1); + continue; + } + GenerateVanillaCircle(chunk, location + new Coordinates3D(0, Y + 1, 0), LeafRadius, LeavesBlock.BlockID, 0x1); + } + + GenerateTopper(chunk, location + new Coordinates3D(0, Height, 0), 0x1); + return true; + } + + /* + * Generates the top of the pine/conifer trees. + * Type: + * 0x0 - two level topper + * 0x1 - three level topper + */ + protected void GenerateTopper(IChunk chunk, Coordinates3D location, byte type = 0x0) + { + int SectionRadius = 1; + GenerateCircle(chunk, location, SectionRadius, LeavesBlock.BlockID, 0x1); + Coordinates3D top = location + Coordinates3D.Up; + chunk.SetBlockID(top, LeavesBlock.BlockID); + chunk.SetMetadata(top, 0x1); + if (type == 0x1 && (top + Coordinates3D.Up).Y < Chunk.Height) + GenerateVanillaCircle(chunk, top + Coordinates3D.Up, SectionRadius, LeavesBlock.BlockID, 0x1); + } + } +} \ No newline at end of file diff --git a/TrueCraft.Core/TerrainGen/Decorators/CactusDecorator.cs b/TrueCraft.Core/TerrainGen/Decorators/CactusDecorator.cs index 26c6b27..a37d65c 100644 --- a/TrueCraft.Core/TerrainGen/Decorators/CactusDecorator.cs +++ b/TrueCraft.Core/TerrainGen/Decorators/CactusDecorator.cs @@ -7,6 +7,7 @@ using TrueCraft.Core.World; using TrueCraft.Core.TerrainGen.Noise; using TrueCraft.Core.Logic.Blocks; using TrueCraft.API; +using TrueCraft.Core.TerrainGen.Decorations; namespace TrueCraft.Core.TerrainGen.Decorators { @@ -34,10 +35,7 @@ namespace TrueCraft.Core.TerrainGen.Decorators { var HeightChance = ChanceNoise.Value2D(BlockX, BlockZ); var CactusHeight = (HeightChance < 1.4) ? 2 : 3; - for (int Y = CactiPosition.Y; Y < CactiPosition.Y + CactusHeight; Y++) - { - chunk.SetBlockID(new Coordinates3D(CactiPosition.X, Y, CactiPosition.Z), CactusBlock.BlockID); - } + Decoration.GenerateColumn(chunk, CactiPosition, CactusHeight, CactusBlock.BlockID); } } } diff --git a/TrueCraft.Core/TerrainGen/Decorators/DungeonDecorator.cs b/TrueCraft.Core/TerrainGen/Decorators/DungeonDecorator.cs index 0a4cec9..6dab83a 100644 --- a/TrueCraft.Core/TerrainGen/Decorators/DungeonDecorator.cs +++ b/TrueCraft.Core/TerrainGen/Decorators/DungeonDecorator.cs @@ -7,6 +7,7 @@ using TrueCraft.Core.World; using TrueCraft.Core.TerrainGen.Noise; using TrueCraft.API; using TrueCraft.Core.Logic.Blocks; +using TrueCraft.Core.TerrainGen.Decorations; namespace TrueCraft.Core.TerrainGen.Decorators { @@ -32,122 +33,18 @@ namespace TrueCraft.Core.TerrainGen.Decorators Offset += OffsetNoise.Value2D(X, Z); int FinalX = (int)Math.Floor(X + Offset); int FinalZ = (int)Math.Floor(Z + Offset); - IBiomeProvider Biome = biomes.GetBiome(chunk.Biomes[X * Chunk.Width + Z]); var Y = (int)(10 + Offset); - if (FinalX < 6 && FinalZ < 6 && Y < BaseLevel - 10) + + var BlockX = MathHelper.ChunkToBlockX(FinalX, chunk.Coordinates.X); + var BlockZ = MathHelper.ChunkToBlockZ(FinalZ, chunk.Coordinates.Z); + var SpawnValue = OffsetNoise.Value2D(BlockX, BlockZ); + if (SpawnValue > 1.95 && SpawnValue < 2.09) { - var BlockX = MathHelper.ChunkToBlockX(X, chunk.Coordinates.X); - var BlockZ = MathHelper.ChunkToBlockZ(Z, chunk.Coordinates.Z); - var SpawnValue = OffsetNoise.Value2D(BlockX, BlockZ); - if (SpawnValue > 1.95 && SpawnValue < 2.09) - { - GenerateDungeon(world, chunk, new Coordinates3D(FinalX, Y, FinalZ), new Vector3(7, 5, 7), 2); + var Generated = new Dungeon().GenerateAt(world, chunk, new Coordinates3D(BlockX, Y, BlockZ)); + if (Generated) break; - } } } } - - void GenerateDungeon(IWorld world, IChunk chunk, Coordinates3D Corner, Vector3 Size, int Chests = 2) - { - Perlin Noise = new Perlin(); - Noise.Seed = world.Seed - (chunk.Coordinates.X + chunk.Coordinates.Z); - int Openings = 0; - for (int X = Corner.X; X <= Corner.X + Size.X + 1; X++) - { - for (int Z = Corner.Z; Z <= Corner.Z + Size.Z + 1; Z++) - { - for (int Y = Corner.Y; Y <= Corner.Y + Size.Y + 1; Y++) - { - if (Y.Equals(Corner.Y)) - { - if (!IsWall(new Coordinates2D(X, Z), Corner, Size) && !IsCorner(new Coordinates2D(X, Z), Corner, Size)) - { - if (Noise.Value2D(X, Z) > 0.2) - { - chunk.SetBlockID(new Coordinates3D(X, Y, Z), MossStoneBlock.BlockID); - } - else - { - chunk.SetBlockID(new Coordinates3D(X, Y, Z), CobblestoneBlock.BlockID); - } - - } - else - { - chunk.SetBlockID(new Coordinates3D(X, Y, Z), CobblestoneBlock.BlockID); - } - } - else if (Y.Equals((int)(Corner.Y + Size.Y + 1))) - { - chunk.SetBlockID(new Coordinates3D(X, Y, Z), CobblestoneBlock.BlockID); - } - else - { - if (IsWall(new Coordinates2D(X, Z), Corner, Size)) - { - if (Noise.Value2D(X, Z) > 0.5 && Openings < 5 && Y.Equals(Corner.Y + 1) && !IsCorner(new Coordinates2D(X, Z), Corner, Size)) - { - Openings++; - } - else - { - if (!chunk.GetBlockID(new Coordinates3D(X, Y - 1, Z)).Equals(0) && Y <= Corner.Y + 2 || Y > Corner.Y + 2) - { - chunk.SetBlockID(new Coordinates3D(X, Y, Z), CobblestoneBlock.BlockID); - } - } - } - } - } - } - } - chunk.SetBlockID(new Coordinates3D((int)(Corner.X + ((Size.X + 1) / 2)), (int)(Corner.Y + 1), (int)(Corner.Z + ((Size.Z + 1) / 2))), MonsterSpawnerBlock.BlockID); - PlaceChests(Noise, chunk, Corner, Size, Chests); - } - - void PlaceChests(Perlin DungeonNoise, IChunk chunk, Coordinates3D Corner, Vector3 Size, int Chests) - { - ClampNoise ChestNoise = new ClampNoise(DungeonNoise); - for (int I = 0; I < Chests; I++) - { - var X = Corner.X; - var Z = Corner.Z; - double Offset = 0; - for (int Attempts = 0; Attempts < 3; Attempts++) - { - Offset += ChestNoise.Value2D(X, Z); - int ChestX = (int)Math.Floor(X + Offset); - int ChestZ = (int)Math.Floor(Z + Offset); - if (!IsWall(new Coordinates2D(ChestX, ChestZ), Corner, Size)) - { - if (NeighboursBlock(chunk, new Coordinates3D(ChestX, Corner.Y + 1, ChestZ), CobblestoneBlock.BlockID)) - { - chunk.SetBlockID(new Coordinates3D(ChestX, Corner.Y + 1, ChestZ), ChestBlock.BlockID); - break; - } - } - } - } - } - - bool NeighboursBlock(IChunk chunk, Coordinates3D Location, byte Block) - { - Coordinates3D Left = new Coordinates3D(Location.X - 1, Location.Y, Location.Z); - Coordinates3D Right = new Coordinates3D(Location.X + 1, Location.Y, Location.Z); - Coordinates3D Front = new Coordinates3D(Location.X, Location.Y, Location.Z - 1); - Coordinates3D Back = new Coordinates3D(Location.X, Location.Y, Location.Z + 1); - return chunk.GetBlockID(Left).Equals(Block) || chunk.GetBlockID(Right).Equals(Block) || chunk.GetBlockID(Front).Equals(Block) || chunk.GetBlockID(Back).Equals(Block); - } - - bool IsWall(Coordinates2D Location, Coordinates3D Start, Vector3 Size) - { - return Location.X.Equals(Start.X) || Location.Z.Equals(Start.Z) || Location.X.Equals((int)(Start.X + Size.X + 1)) || Location.Z.Equals((int)(Start.Z + Size.Z + 1)); - } - - bool IsCorner(Coordinates2D Location, Coordinates3D Start, Vector3 Size) - { - return Location.X.Equals(Start.X - 1) && Location.Z.Equals(Start.Z - 1) || Location.X.Equals((int)(Start.X + Size.X + 1)) && Location.Z.Equals(Start.Z - 1) || Location.Z.Equals(Start.Z - 1) && Location.Z.Equals((int)(Start.Z + Size.Z + 1)) || Location.X.Equals((int)(Start.X + Size.X + 1)) && Location.Z.Equals((int)(Start.Z + Size.Z + 1)); - } } } \ No newline at end of file diff --git a/TrueCraft.Core/TerrainGen/Decorators/SugarCaneDecorator.cs b/TrueCraft.Core/TerrainGen/Decorators/SugarCaneDecorator.cs index 0d3dde3..9e93a0e 100644 --- a/TrueCraft.Core/TerrainGen/Decorators/SugarCaneDecorator.cs +++ b/TrueCraft.Core/TerrainGen/Decorators/SugarCaneDecorator.cs @@ -7,6 +7,7 @@ using TrueCraft.Core.World; using TrueCraft.Core.TerrainGen.Noise; using TrueCraft.API; using TrueCraft.Core.Logic.Blocks; +using TrueCraft.Core.TerrainGen.Decorations; namespace TrueCraft.Core.TerrainGen.Decorators { @@ -31,55 +32,23 @@ namespace TrueCraft.Core.TerrainGen.Decorators if (Noise.Value2D(BlockX, BlockZ) > 0.65) { Coordinates3D BlockLocation = new Coordinates3D(X, Height, Z); - Coordinates3D StalkStart = BlockLocation + Coordinates3D.Up; - if (chunk.GetBlockID(BlockLocation).Equals(GrassBlock.BlockID) && NeighboursWater(chunk, BlockLocation) || chunk.GetBlockID(BlockLocation).Equals(SandBlock.BlockID) && NeighboursWater(chunk, BlockLocation)) + Coordinates3D SugarCaneLocation = BlockLocation + Coordinates3D.Up; + var NeighboursWater = Decoration.NeighboursBlock(chunk, BlockLocation, WaterBlock.BlockID) || Decoration.NeighboursBlock(chunk, BlockLocation, StationaryWaterBlock.BlockID); + if (chunk.GetBlockID(BlockLocation).Equals(GrassBlock.BlockID) && NeighboursWater || chunk.GetBlockID(BlockLocation).Equals(SandBlock.BlockID) && NeighboursWater) { - PlaceStalk(chunk, StalkStart, world.Seed); + Random R = new Random(world.Seed); + double HeightChance = R.NextDouble(); + int CaneHeight = 3; + if (HeightChance < 0.05) + CaneHeight = 4; + else if (HeightChance > 0.1 && Height < 0.25) + CaneHeight = 2; + Decoration.GenerateColumn(chunk, SugarCaneLocation, CaneHeight, SugarcaneBlock.BlockID); } } } } } } - - void PlaceStalk(IChunk chunk, Coordinates3D location, int seed) - { - Random R = new Random(seed); - double HeightChance = R.NextDouble(); - int Height = 3; - if (HeightChance < 0.05) - { - Height = 4; - } - else if (HeightChance > 0.1 && Height < 0.25) - { - Height = 2; - } - Coordinates3D NewLocation = location; - for (int Y = location.Y; Y < location.Y + Height; Y++) - { - NewLocation.Y = Y; - chunk.SetBlockID(NewLocation, SugarcaneBlock.BlockID); - } - } - - bool NeighboursWater(IChunk chunk, Coordinates3D location) - { - var Surrounding = new[] { - location + Coordinates3D.Left, - location + Coordinates3D.Right, - location + Coordinates3D.Forwards, - location + Coordinates3D.Backwards, - }; - for (int I = 0; I < Surrounding.Length; I++) - { - Coordinates3D Check = Surrounding[I]; - if (Check.X < 0 || Check.X >= Chunk.Width || Check.Z < 0 || Check.Z >= Chunk.Depth || Check.Y < 0 || Check.Y >= Chunk.Height) - return false; - if (chunk.GetBlockID(Check).Equals(WaterBlock.BlockID) || chunk.GetBlockID(Check).Equals(StationaryWaterBlock.BlockID)) - return true; - } - return false; - } } } \ No newline at end of file diff --git a/TrueCraft.Core/TerrainGen/Decorators/TreeDecorator.cs b/TrueCraft.Core/TerrainGen/Decorators/TreeDecorator.cs index b86ee96..fa5c285 100644 --- a/TrueCraft.Core/TerrainGen/Decorators/TreeDecorator.cs +++ b/TrueCraft.Core/TerrainGen/Decorators/TreeDecorator.cs @@ -7,6 +7,7 @@ using TrueCraft.API; using TrueCraft.Core.Logic.Blocks; using TrueCraft.Core.TerrainGen.Noise; using TrueCraft.Core.World; +using TrueCraft.Core.TerrainGen.Decorations; namespace TrueCraft.Core.TerrainGen.Decorators { @@ -28,7 +29,7 @@ namespace TrueCraft.Core.TerrainGen.Decorators IBiomeProvider Biome = biomes.GetBiome(chunk.Biomes[X * Chunk.Width + Z]); var BlockX = MathHelper.ChunkToBlockX(X, chunk.Coordinates.X); var BlockZ = MathHelper.ChunkToBlockZ(Z, chunk.Coordinates.Z); - var Height = chunk.HeightMap[X * Chunk.Width + Z] + 1; + var Height = chunk.HeightMap[X * Chunk.Width + Z]; if (!LastTree.Equals(null) && LastTree.DistanceTo(new Coordinates2D(X, Z)) < Biome.TreeDensity) { @@ -37,215 +38,52 @@ namespace TrueCraft.Core.TerrainGen.Decorators if (Noise.Value2D(BlockX, BlockZ) > 0.3) { - if (chunk.GetBlockID(new Coordinates3D(X, Height - 1, Z)).Equals(GrassBlock.BlockID)) + Coordinates3D location = new Coordinates3D(X, Height, Z); + if (chunk.GetBlockID(location).Equals(GrassBlock.BlockID)) { var Chance = ChanceNoise.Value2D(BlockX, BlockZ); var OakNoise = ChanceNoise.Value2D(BlockX * 0.6, BlockZ * 0.6); var BirchNoise = ChanceNoise.Value2D(BlockX * 0.2, BlockZ * 0.2); var SpruceNoise = ChanceNoise.Value2D(BlockX * 0.35, BlockZ * 0.35); - //We currently have to limit where trees can spawn in the trunk due to not being able to use other chunks during generation. - if (X + 4 > 15 || Z + 4 > 15 || X - 4 < 0 || Z - 4 < 0) - continue; + + Coordinates3D Base = location + Coordinates3D.Up; if (Biome.Trees.Contains(TreeSpecies.Oak) && OakNoise > 1.01 && OakNoise < 1.25) { - GenerateTree(chunk, new Coordinates3D(X, Height, Z), TreeSpecies.Oak); - LastTree = new Coordinates2D(X, Z); - continue; + var Oak = new OakTree().GenerateAt(world, chunk, Base); + if (Oak) + { + LastTree = new Coordinates2D(X, Z); + continue; + } } if (Biome.Trees.Contains(TreeSpecies.Birch) && BirchNoise > 0.3 && BirchNoise < 0.95) { - GenerateTree(chunk, new Coordinates3D(X, Height, Z), TreeSpecies.Birch); - LastTree = new Coordinates2D(X, Z); - continue; + var Birch = new BirchTree().GenerateAt(world, chunk, Base); + if (Birch) + { + LastTree = new Coordinates2D(X, Z); + continue; + } } if (Biome.Trees.Contains(TreeSpecies.Spruce) && SpruceNoise < 0.75) { - if (X + 3 > 15 || Z + 3 > 15 || X - 3 < 0 || Z - 3 < 0) + Random R = new Random(world.Seed); + var type = R.Next(1, 2); + var Generated = false; + if (type.Equals(1)) + { + Generated = new PineTree().GenerateAt(world, chunk, Base); + } + else + { + Generated = new ConiferTree().GenerateAt(world, chunk, Base); + } + + if (Generated) + { + LastTree = new Coordinates2D(X, Z); continue; - GenerateTree(chunk, new Coordinates3D(X, Height, Z), TreeSpecies.Spruce); - LastTree = new Coordinates2D(X, Z); - continue; - } - } - } - } - } - } - - private void GenerateTree(IChunk chunk, Coordinates3D Base, TreeSpecies TreeType) - { - switch (TreeType) - { - case TreeSpecies.Oak: - GenerateOak(chunk, Base, 0x0, 0x0); - break; - case TreeSpecies.Birch: - GenerateOak(chunk, Base, 0x2, 0x2); - break; - case TreeSpecies.Spruce: - GenerateSpruce(chunk, Base, 0x1, 0x1); - break; - default: - GenerateOak(chunk, Base, 0x0, 0x0); - break; - } - } - - private void GenerateOak(IChunk chunk, Coordinates3D Base, byte Logs, byte Leaves, OakType Type = OakType.Normal) - { - var BlockX = MathHelper.ChunkToBlockX(Base.X, chunk.Coordinates.X); - var BlockZ = MathHelper.ChunkToBlockZ(Base.Z, chunk.Coordinates.Z); - var HeightChance = ChanceNoise.Value2D(BlockX, BlockZ); - var TreeHeight = (HeightChance < 1.2) ? 4 : 5; - int Radius = 2; - if (Type.Equals(OakType.Normal)) - { - int OffRadius = Radius; - int Offset = 1; - for (int Y = Base.Y; Y < Base.Y + TreeHeight + 2; Y++) - { - if (Y - Base.Y <= TreeHeight) - { - chunk.SetBlockID(new Coordinates3D(Base.X, Y, Base.Z), WoodBlock.BlockID); - chunk.SetMetadata(new Coordinates3D(Base.X, Y, Base.Z), Logs); - } - if (Y - Base.Y >= TreeHeight - Radius) - { - GenerateCircleLeaves(chunk, new Coordinates3D(Base.X, Y, Base.Z), OffRadius, Leaves, ChanceNoise.Value2D((BlockX / Y) * 0.25, (BlockZ / Y) * 0.25)); - if (Offset % 2 == 0) - OffRadius--; - Offset++; - } - } - } - else if (Type.Equals(OakType.BalloonBlocky)) - { - int OffRadius = 1;//Start at 1 - int Offset = 1; - for (int Y = Base.Y; Y < Base.Y + TreeHeight + 3; Y++) - { - if (Y - Base.Y <= TreeHeight) - { - chunk.SetBlockID(new Coordinates3D(Base.X, Y, Base.Z), WoodBlock.BlockID); - chunk.SetMetadata(new Coordinates3D(Base.X, Y, Base.Z), Logs); - } - if (Y - Base.Y >= TreeHeight - Radius) - { - GenerateCircleLeaves(chunk, new Coordinates3D(Base.X, Y, Base.Z), OffRadius, Leaves); - if ((Offset - 1) % 3 == 0 && OffRadius.Equals(2) || Offset % 1 == 0 && OffRadius.Equals(1)) - { - if (Y - Base.Y >= TreeHeight) - { - OffRadius--; - } - else - { - OffRadius++; - } - } - Offset++; - } - } - } - else if (Type.Equals(OakType.Balloon)) - { - for (int Y = Base.Y; Y < Base.Y + TreeHeight; Y++) - { - if (Y - Base.Y <= TreeHeight) - { - chunk.SetBlockID(new Coordinates3D(Base.X, Y, Base.Z), WoodBlock.BlockID); - chunk.SetMetadata(new Coordinates3D(Base.X, Y, Base.Z), Logs); - } - GenerateSphereLeaves(chunk, new Coordinates3D(Base.X, Base.Y + TreeHeight, Base.Z), Radius, Leaves); - } - } - //TODO: I don't want to implement branched oak trees until we're able to use other chunks during generation - } - - private void GenerateSpruce(IChunk chunk, Coordinates3D Base, byte Logs, byte Leaves) - { - var BlockX = MathHelper.ChunkToBlockX(Base.X, chunk.Coordinates.X); - var BlockZ = MathHelper.ChunkToBlockZ(Base.Z, chunk.Coordinates.Z); - var HeightChance = ChanceNoise.Value2D(BlockX, BlockZ); - var TreeHeight = (HeightChance < 1.4) ? 7 : 8; - var Type = (HeightChance < 1.4 && HeightChance > 0.9) ? 2 : 1; - - int SeperatorRadius = 1; - int Radius = 2; - int Offset = (HeightChance > 0.4 && HeightChance < 0.6) ? 1 : 0; - for (int Y = Base.Y; Y < Base.Y + TreeHeight + 4; Y++) - { - if (Y - Base.Y <= TreeHeight) - { - chunk.SetBlockID(new Coordinates3D(Base.X, Y, Base.Z), WoodBlock.BlockID); - chunk.SetMetadata(new Coordinates3D(Base.X, Y, Base.Z), Logs); - } - if (Y - Base.Y >= TreeHeight - 5) - { - int CurrentRadius = ((Offset % 2).Equals(0)) ? Radius : SeperatorRadius; - if (Offset.Equals(0) && Type.Equals(2)) - CurrentRadius = 3; - if (Y.Equals(Base.Y + TreeHeight + 1) || Y.Equals(Base.Y + TreeHeight + 3)) - CurrentRadius = SeperatorRadius; - if (Y.Equals(Base.Y + TreeHeight + 2)) - { - Coordinates3D Block = new Coordinates3D(Base.X, Y, Base.Z); - chunk.SetBlockID(Block, LeavesBlock.BlockID); - chunk.SetMetadata(Block, Leaves); - continue; - } - GenerateCircleLeaves(chunk, new Coordinates3D(Base.X, Y, Base.Z), CurrentRadius, Leaves); - Offset++; - } - } - } - - private void GenerateCircleLeaves(IChunk chunk, Coordinates3D MiddleBlock, int Radius, byte Leaves, double CornerChance = 0) - { - for (int I = -Radius; I <= Radius; I = (I + 1)) - { - for (int J = -Radius; J <= Radius; J = (J + 1)) - { - int Max = (int)Math.Sqrt((I * I) + (J * J)); - if (Max <= Radius) - { - if (I.Equals(-Radius) && J.Equals(-Radius) || I.Equals(-Radius) && J.Equals(Radius) || I.Equals(Radius) && J.Equals(-Radius) || I.Equals(Radius) && J.Equals(Radius)) - { - if (CornerChance + Radius * 0.2 < 0.4 || CornerChance + Radius * 0.2 > 0.7 || CornerChance.Equals(0)) - continue; - } - int X = MiddleBlock.X + I; - int Z = MiddleBlock.Z + J; - Coordinates3D CurrentBlock = new Coordinates3D(X, MiddleBlock.Y, Z); - if (chunk.GetBlockID(CurrentBlock).Equals(0)) - { - chunk.SetBlockID(CurrentBlock, LeavesBlock.BlockID); - chunk.SetMetadata(CurrentBlock, Leaves); - } - } - } - } - } - - private void GenerateSphereLeaves(IChunk chunk, Coordinates3D MiddleBlock, int Radius, byte Leaves) - { - for (int I = -Radius; I <= Radius; I = (I + 1)) - { - for (int J = -Radius; J <= Radius; J = (J + 1)) - { - for (int K = -Radius; K <= Radius; K = (K + 1)) - { - int Max = (int)Math.Sqrt((I * I) + (J * J) + (K * K)); - if (Max <= Radius) - { - int X = MiddleBlock.X + I; - int Y = MiddleBlock.Y + K; - int Z = MiddleBlock.Z + J; - Coordinates3D CurrentBlock = new Coordinates3D(X, Y, Z); - if (chunk.GetBlockID(CurrentBlock).Equals(0)) - { - chunk.SetBlockID(CurrentBlock, LeavesBlock.BlockID); - chunk.SetMetadata(CurrentBlock, Leaves); + } } } } diff --git a/TrueCraft.Core/TerrainGen/NewGenerator.cs b/TrueCraft.Core/TerrainGen/NewGenerator.cs index 124ec13..df3f7ea 100644 --- a/TrueCraft.Core/TerrainGen/NewGenerator.cs +++ b/TrueCraft.Core/TerrainGen/NewGenerator.cs @@ -9,6 +9,7 @@ using TrueCraft.Core.Logic.Blocks; using TrueCraft.Core.TerrainGen.Noise; using TrueCraft.Core.TerrainGen.Biomes; using TrueCraft.Core.TerrainGen.Decorators; +using TrueCraft.Core.TerrainGen.Decorations; namespace TrueCraft.Core.TerrainGen { diff --git a/TrueCraft.Core/TrueCraft.Core.csproj b/TrueCraft.Core/TrueCraft.Core.csproj index 7d5125c..e602728 100644 --- a/TrueCraft.Core/TrueCraft.Core.csproj +++ b/TrueCraft.Core/TrueCraft.Core.csproj @@ -182,6 +182,13 @@ + + + + + + + diff --git a/TrueCraft.Core/World/Chunk.cs b/TrueCraft.Core/World/Chunk.cs index 0699678..92b60f6 100644 --- a/TrueCraft.Core/World/Chunk.cs +++ b/TrueCraft.Core/World/Chunk.cs @@ -7,6 +7,7 @@ using fNbt; using fNbt.Serialization; using TrueCraft.API.World; using TrueCraft.API; +using TrueCraft.Core.Logic.Blocks; namespace TrueCraft.Core.World { @@ -114,8 +115,10 @@ namespace TrueCraft.Core.World IsModified = true; int index = coordinates.Y + (coordinates.Z * Height) + (coordinates.X * Height * Width); Blocks[index] = value; + if (value == AirBlock.BlockID) + Metadata[index] = 0x0; var oldHeight = GetHeight((byte)coordinates.X, (byte)coordinates.Z); - if (value == 0) // Air + if (value == AirBlock.BlockID) { if (oldHeight <= coordinates.Y) {