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
This commit is contained in:
parent
74a191d00f
commit
2100e8c4ab
@ -65,6 +65,7 @@
|
||||
<Compile Include="World\IBiomeProvider.cs" />
|
||||
<Compile Include="World\IChunkDecorator.cs" />
|
||||
<Compile Include="World\INoise.cs" />
|
||||
<Compile Include="World\IDecoration.cs" />
|
||||
<Compile Include="World\IWorld.cs" />
|
||||
<Compile Include="World\IChunk.cs" />
|
||||
<Compile Include="World\IChunkProvider.cs" />
|
||||
|
13
TrueCraft.API/World/IDecoration.cs
Normal file
13
TrueCraft.API/World/IDecoration.cs
Normal file
@ -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);
|
||||
}
|
||||
}
|
@ -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<int, int>(1, 4);
|
||||
}
|
||||
|
||||
protected override ItemStack[] GetDrop(BlockDescriptor descriptor)
|
||||
{
|
||||
return new ItemStack[0];
|
||||
}
|
||||
}
|
||||
}
|
36
TrueCraft.Core/TerrainGen/Decorations/BalloonOakTree.cs
Normal file
36
TrueCraft.Core/TerrainGen/Decorations/BalloonOakTree.cs
Normal file
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
36
TrueCraft.Core/TerrainGen/Decorations/BirchTree.cs
Normal file
36
TrueCraft.Core/TerrainGen/Decorations/BirchTree.cs
Normal file
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
31
TrueCraft.Core/TerrainGen/Decorations/ConiferTree.cs
Normal file
31
TrueCraft.Core/TerrainGen/Decorations/ConiferTree.cs
Normal file
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
195
TrueCraft.Core/TerrainGen/Decorations/Decoration.cs
Normal file
195
TrueCraft.Core/TerrainGen/Decorations/Decoration.cs
Normal file
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
105
TrueCraft.Core/TerrainGen/Decorations/Dungeon.cs
Normal file
105
TrueCraft.Core/TerrainGen/Decorations/Dungeon.cs
Normal file
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
36
TrueCraft.Core/TerrainGen/Decorations/OakTree.cs
Normal file
36
TrueCraft.Core/TerrainGen/Decorations/OakTree.cs
Normal file
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
63
TrueCraft.Core/TerrainGen/Decorations/PineTree.cs
Normal file
63
TrueCraft.Core/TerrainGen/Decorations/PineTree.cs
Normal file
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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));
|
||||
}
|
||||
}
|
||||
}
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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
|
||||
{
|
||||
|
@ -182,6 +182,13 @@
|
||||
<Compile Include="TerrainGen\Biomes\SwamplandBiome.cs" />
|
||||
<Compile Include="TerrainGen\Biomes\TaigaBiome.cs" />
|
||||
<Compile Include="TerrainGen\Biomes\TundraBiome.cs" />
|
||||
<Compile Include="TerrainGen\Decorations\BalloonOakTree.cs" />
|
||||
<Compile Include="TerrainGen\Decorations\BirchTree.cs" />
|
||||
<Compile Include="TerrainGen\Decorations\ConiferTree.cs" />
|
||||
<Compile Include="TerrainGen\Decorations\Decoration.cs" />
|
||||
<Compile Include="TerrainGen\Decorations\Dungeon.cs" />
|
||||
<Compile Include="TerrainGen\Decorations\OakTree.cs" />
|
||||
<Compile Include="TerrainGen\Decorations\PineTree.cs" />
|
||||
<Compile Include="TerrainGen\Decorators\CactusDecorator.cs" />
|
||||
<Compile Include="TerrainGen\Decorators\DungeonDecorator.cs" />
|
||||
<Compile Include="TerrainGen\Decorators\PlantDecorator.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)
|
||||
{
|
||||
|
Reference in New Issue
Block a user