This repository has been archived on 2024-06-13. You can view files and clone it, but cannot push or open issues or pull requests.
2017-11-08 23:48:19 -08:00

205 lines
8.8 KiB
C#

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(IWorldSeed world, ISpatialBlockInformationProvider 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(ISpatialBlockInformationProvider 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++)
{
var locationToCheck = surrounding[i];
if (locationToCheck.X < 0 || locationToCheck.X >= Chunk.Width || locationToCheck.Z < 0 || locationToCheck.Z >= Chunk.Depth || locationToCheck.Y < 0 || locationToCheck.Y >= Chunk.Height)
return false;
if (chunk.GetBlockID(locationToCheck).Equals(block))
{
if (meta != 0x0 && chunk.GetMetadata(locationToCheck) != meta)
return false;
return true;
}
}
return false;
}
public static void GenerateColumn(ISpatialBlockInformationProvider chunk, Coordinates3D location, int height, byte block, byte meta = 0x0)
{
for (int offset = 0; offset < height; offset++)
{
var 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(ISpatialBlockInformationProvider 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(ISpatialBlockInformationProvider 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(ISpatialBlockInformationProvider 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;
var currentBlock = new Coordinates3D(x, location.Y, z);
if (chunk.GetBlockID(currentBlock).Equals(0))
{
chunk.SetBlockID(currentBlock, block);
chunk.SetMetadata(currentBlock, meta);
}
}
}
}
}
protected void GenerateCircle(ISpatialBlockInformationProvider 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;
var 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(ISpatialBlockInformationProvider 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;
var currentBlock = new Coordinates3D(x, y, z);
if (chunk.GetBlockID(currentBlock).Equals(0))
{
chunk.SetBlockID(currentBlock, block);
chunk.SetMetadata(currentBlock, meta);
}
}
}
}
}
}
}
}