mirror of
https://github.com/ClassiCube/MCGalaxy.git
synced 2025-09-25 14:17:29 -04:00
Allow providing sizes to trees.
This commit is contained in:
parent
a40c342079
commit
770a284212
@ -124,7 +124,7 @@ namespace MCGalaxy.Blocks.Physics {
|
||||
Tree tree = Tree.Find(lvl.TreeType);
|
||||
if (tree == null) tree = new NormalTree();
|
||||
|
||||
tree.SetData(rand, tree.DefaultValue(rand));
|
||||
tree.SetData(rand, tree.DefaultSize(rand));
|
||||
tree.Generate(x, y, z, (xT, yT, zT, bT) =>
|
||||
{
|
||||
if (bT == Block.leaf && lvl.GetTile(xT, yT, zT) != Block.air) return;
|
||||
|
@ -30,38 +30,52 @@ namespace MCGalaxy.Commands.Building {
|
||||
|
||||
public override void Use(Player p, string message) {
|
||||
if (Player.IsSuper(p)) { MessageInGameOnly(p); return; }
|
||||
string[] parts = message.SplitSpaces(2);
|
||||
string brushMsg = parts.Length >= 2 ? parts[1] : "";
|
||||
string[] parts = message.SplitSpaces(3);
|
||||
|
||||
DrawArgs dArgs = default(DrawArgs);
|
||||
dArgs.size = -1;
|
||||
|
||||
Tree tree = Tree.Find(parts[0]);
|
||||
if (tree == null) {
|
||||
brushMsg = message;
|
||||
dArgs.brushMsg = message;
|
||||
tree = new NormalTree();
|
||||
}
|
||||
|
||||
DrawArgs dArgs = default(DrawArgs);
|
||||
dArgs.tree = tree;
|
||||
dArgs.brushMsg = brushMsg;
|
||||
dArgs.value = -1;
|
||||
|
||||
if (brushMsg != "") {
|
||||
if (!p.group.CanExecute("brush")) {
|
||||
Player.Message(p, "You cannot use %T/brush%S, so therefore cannot use %T/tree%S with a brush."); return;
|
||||
|
||||
int size;
|
||||
if (parts.Length > 1 && int.TryParse(parts[1], out size)) {
|
||||
if (size < tree.MinSize) {
|
||||
Player.Message(p, "Value must be {0} or above for {1} trees.", tree.MinSize, parts[0]); return;
|
||||
}
|
||||
if (size > tree.MaxSize) {
|
||||
Player.Message(p, "Value must be {0} or below for {1} trees.", tree.MaxSize, parts[0]); return;
|
||||
}
|
||||
|
||||
Brush brush = ParseBrush(dArgs.brushMsg, p, 0, 0);
|
||||
if (brush == null) return;
|
||||
}
|
||||
|
||||
dArgs.size = size;
|
||||
dArgs.brushMsg = parts.Length >= 3 ? parts[2] : ""; // type value brush
|
||||
} else {
|
||||
dArgs.brushMsg = parts.Length >= 2 ? parts[1] : ""; // type brush
|
||||
}
|
||||
|
||||
if (!CheckBrush(p, dArgs.brushMsg)) return;
|
||||
Player.Message(p, "Select where you wish your tree to grow");
|
||||
p.MakeSelection(1, dArgs, DoTree);
|
||||
}
|
||||
|
||||
static bool CheckBrush(Player p, string brushMsg) {
|
||||
if (brushMsg == "") return true;
|
||||
|
||||
if (!p.group.CanExecute("brush")) {
|
||||
Player.Message(p, "You cannot use %T/brush%S, so therefore cannot use %T/tree%S with a brush."); return false;
|
||||
}
|
||||
return ParseBrush(brushMsg, p, 0, 0) != null;
|
||||
}
|
||||
|
||||
bool DoTree(Player p, Vec3S32[] marks, object state, byte type, byte extType) {
|
||||
DrawArgs dArgs = (DrawArgs)state;
|
||||
TreeDrawOp op = new TreeDrawOp();
|
||||
op.Tree = dArgs.tree;
|
||||
op.Value = dArgs.value;
|
||||
op.Size = dArgs.size;
|
||||
|
||||
Brush brush = null;
|
||||
if (dArgs.brushMsg != "") brush = ParseBrush(dArgs.brushMsg, p, type, extType);
|
||||
@ -83,11 +97,13 @@ namespace MCGalaxy.Commands.Building {
|
||||
return brush.Construct(args);
|
||||
}
|
||||
|
||||
struct DrawArgs { public Tree tree; public string brushMsg; public int value; }
|
||||
struct DrawArgs { public Tree tree; public string brushMsg; public int size; }
|
||||
|
||||
public override void Help(Player p) {
|
||||
Player.Message(p, "%T/tree [type] %H- Draws a tree.");
|
||||
Player.Message(p, "%T/tree [type] [size] %H- Draws a tree of given size.");
|
||||
Player.Message(p, "%T/tree [type] [brush name] <brush args>");
|
||||
Player.Message(p, "%T/tree [type] [size] [brush name] <brush args>");
|
||||
Player.Message(p, "%H Types: &f{0}", Tree.TreeTypes.Join(t => t.Key));
|
||||
Player.Message(p, "%H For help about brushes, type %T/help brush%H.");
|
||||
}
|
||||
|
@ -37,9 +37,9 @@ namespace MCGalaxy.Drawing.Ops {
|
||||
public Tree Tree;
|
||||
static Brush defBrush = new SolidBrush(Block.leaf, 0);
|
||||
|
||||
public int Value = -1;
|
||||
public int Size = -1;
|
||||
|
||||
public override long BlocksAffected(Level lvl, Vec3S32[] marks) { return -1; }
|
||||
public override long BlocksAffected(Level lvl, Vec3S32[] marks) { return Tree.EstimateBlocksAffected(); }
|
||||
|
||||
public override void Perform(Vec3S32[] marks, Brush brush, Action<DrawOpBlock> output) {
|
||||
if (brush == null) brush = defBrush;
|
||||
@ -60,7 +60,7 @@ namespace MCGalaxy.Drawing.Ops {
|
||||
|
||||
public override void SetMarks(Vec3S32[] marks) {
|
||||
base.SetMarks(marks);
|
||||
int value = Value != -1 ? Value : Tree.DefaultValue(random);
|
||||
int value = Size != -1 ? Size : Tree.DefaultSize(random);
|
||||
Tree.SetData(random, value);
|
||||
|
||||
Max.Y += Tree.height;
|
||||
|
@ -23,60 +23,62 @@ using MCGalaxy.Drawing.Ops;
|
||||
namespace MCGalaxy.Generator.Foliage {
|
||||
public sealed class AshTree : Tree {
|
||||
|
||||
int branchBaseHeight, branchAmount;
|
||||
const int maxExtent = 5, maxBranchHeight = 10, maxCluster = 3;
|
||||
int branchBaseHeight, branchAmount;
|
||||
const int maxExtent = 5, maxBranchHeight = 10, maxCluster = 3;
|
||||
List<Vec3S32> branch = new List<Vec3S32>();
|
||||
|
||||
public override int DefaultValue(Random rnd) { return rnd.Next(5, 10); }
|
||||
public override int EstimateBlocksAffected() { return height * height * height; }
|
||||
|
||||
public override int DefaultSize(Random rnd) { return rnd.Next(5, 10); }
|
||||
|
||||
public override void SetData(Random rnd, int value) {
|
||||
this.rnd = rnd;
|
||||
height = (byte)value;
|
||||
size = (byte)(maxExtent + maxCluster);
|
||||
|
||||
branchBaseHeight = height / 4;
|
||||
branchAmount = rnd.Next(10, 25);
|
||||
branchBaseHeight = height / 4;
|
||||
branchAmount = rnd.Next(10, 25);
|
||||
}
|
||||
|
||||
public override void Generate(ushort x, ushort y, ushort z, TreeOutput output) {
|
||||
// Do base trunk
|
||||
// Do base trunk
|
||||
Vec3S32 p1 = new Vec3S32(x, y, z);
|
||||
Vec3S32 p2 = new Vec3S32(x, y + height, z);
|
||||
Line(p1, p2, output);
|
||||
|
||||
for (int i = 0; i < branchAmount; i++) {
|
||||
DoBranch(x, y, z, output);
|
||||
}
|
||||
Vec3S32 p2 = new Vec3S32(x, y + height, z);
|
||||
Line(p1, p2, output);
|
||||
|
||||
for (int i = 0; i < branchAmount; i++) {
|
||||
DoBranch(x, y, z, output);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void DoBranch(int x, int y, int z, TreeOutput output) {
|
||||
int dx = rnd.Next(-maxExtent, maxExtent);
|
||||
int dz = rnd.Next(-maxExtent, maxExtent);
|
||||
int clusterSize = rnd.Next(1, maxCluster);
|
||||
int branchStart = rnd.Next(branchBaseHeight, height);
|
||||
int branchMax = branchStart + rnd.Next(3, maxBranchHeight);
|
||||
|
||||
int R = clusterSize;
|
||||
Vec3S32[] marks = new [] {
|
||||
new Vec3S32(x + dx - R, y + branchMax - R, z + dz - R),
|
||||
new Vec3S32(x + dx + R, y + branchMax + R, z + dz + R) };
|
||||
|
||||
DrawOp op = new EllipsoidDrawOp();
|
||||
Brush brush = new RandomBrush(new [] { new ExtBlock(Block.leaf, 0) });
|
||||
op.SetMarks(marks);
|
||||
op.Perform(marks, brush, b => output(b.X, b.Y, b.Z, b.Block));
|
||||
|
||||
Vec3S32 p1 = new Vec3S32(x, branchStart, z);
|
||||
Vec3S32 p2 = new Vec3S32(x + dx, y + branchMax, z + dz);
|
||||
Line(p1, p2, output);
|
||||
}
|
||||
|
||||
void DoBranch(int x, int y, int z, TreeOutput output) {
|
||||
int dx = rnd.Next(-maxExtent, maxExtent);
|
||||
int dz = rnd.Next(-maxExtent, maxExtent);
|
||||
int clusterSize = rnd.Next(1, maxCluster);
|
||||
int branchStart = rnd.Next(branchBaseHeight, height);
|
||||
int branchMax = branchStart + rnd.Next(3, maxBranchHeight);
|
||||
|
||||
int R = clusterSize;
|
||||
Vec3S32[] marks = new [] {
|
||||
new Vec3S32(x + dx - R, y + branchMax - R, z + dz - R),
|
||||
new Vec3S32(x + dx + R, y + branchMax + R, z + dz + R) };
|
||||
|
||||
DrawOp op = new EllipsoidDrawOp();
|
||||
Brush brush = new RandomBrush(new [] { new ExtBlock(Block.leaf, 0) });
|
||||
op.SetMarks(marks);
|
||||
op.Perform(marks, brush, b => output(b.X, b.Y, b.Z, b.Block));
|
||||
|
||||
Vec3S32 p1 = new Vec3S32(x, branchStart, z);
|
||||
Vec3S32 p2 = new Vec3S32(x + dx, y + branchMax, z + dz);
|
||||
Line(p1, p2, output);
|
||||
}
|
||||
|
||||
void Line(Vec3S32 p1, Vec3S32 p2, TreeOutput output) {
|
||||
LineDrawOp.DrawLine(p1.X, p1.Y, p1.Z, 100, p2.X, p2.Y, p2.Z, branch);
|
||||
|
||||
foreach (Vec3S32 P in branch) {
|
||||
output((ushort)P.X, (ushort)P.Y, (ushort)P.Z, Block.trunk);
|
||||
output((ushort)P.X, (ushort)P.Y, (ushort)P.Z, Block.trunk);
|
||||
}
|
||||
branch.Clear();
|
||||
}
|
||||
|
@ -39,7 +39,8 @@ namespace MCGalaxy.Generator.Foliage {
|
||||
protected const float EDGEHEIGHT = 25f;
|
||||
protected const bool ROOTBUTTRESSES = true;
|
||||
|
||||
public override int DefaultValue(Random rnd) { return 40; }
|
||||
public override int EstimateBlocksAffected() { return height * height * height; }
|
||||
|
||||
public override void SetData(Random rnd, int value) { this.rnd = rnd; height = (byte)value; }
|
||||
|
||||
/// <summary> Outputs the blocks generated by this tree at the given coordinates. </summary>
|
||||
@ -332,7 +333,7 @@ namespace MCGalaxy.Generator.Foliage {
|
||||
/// <summary> This kind of tree is designed to resemble a deciduous tree. </summary>
|
||||
public class RoundTree : ProceduralTree {
|
||||
|
||||
public override int DefaultValue(Random rnd) { return rnd.Next(6, 11); }
|
||||
public override int DefaultSize(Random rnd) { return rnd.Next(6, 11); }
|
||||
|
||||
public override void Prepare() {
|
||||
base.Prepare();
|
||||
@ -366,7 +367,7 @@ namespace MCGalaxy.Generator.Foliage {
|
||||
/// <summary> This kind of tree is designed to resemble a conifer tree. </summary>
|
||||
public class ConeTree : ProceduralTree {
|
||||
|
||||
public override int DefaultValue(Random rnd) { return rnd.Next(15, 31); }
|
||||
public override int DefaultSize(Random rnd) { return rnd.Next(15, 31); }
|
||||
|
||||
public override void Prepare() {
|
||||
base.Prepare();
|
||||
@ -390,7 +391,7 @@ namespace MCGalaxy.Generator.Foliage {
|
||||
/// <summary> This kind of tree is designed to resemble a rainforest tree. </summary>
|
||||
public class RainforestTree : ProceduralTree {
|
||||
|
||||
public override int DefaultValue(Random rnd) { return rnd.Next(6, 11); }
|
||||
public override int DefaultSize(Random rnd) { return rnd.Next(6, 11); }
|
||||
|
||||
public override void Prepare() {
|
||||
base.Prepare();
|
||||
@ -421,7 +422,7 @@ namespace MCGalaxy.Generator.Foliage {
|
||||
/// <summary> This kind of tree is designed to resemble a mangrove tree. </summary>
|
||||
public class MangroveTree : RoundTree {
|
||||
|
||||
public override int DefaultValue(Random rnd) { return rnd.Next(10, 21); }
|
||||
public override int DefaultSize(Random rnd) { return rnd.Next(10, 21); }
|
||||
|
||||
public override void Prepare() {
|
||||
base.Prepare();
|
||||
@ -439,7 +440,9 @@ namespace MCGalaxy.Generator.Foliage {
|
||||
|
||||
public sealed class BambooTree : Tree {
|
||||
|
||||
public override int DefaultValue(Random rnd) { return rnd.Next(4, 8); }
|
||||
public override int EstimateBlocksAffected() { return height * 2; }
|
||||
|
||||
public override int DefaultSize(Random rnd) { return rnd.Next(4, 8); }
|
||||
|
||||
public override void SetData(Random rnd, int value) {
|
||||
height = (byte)value;
|
||||
@ -463,7 +466,9 @@ namespace MCGalaxy.Generator.Foliage {
|
||||
|
||||
public sealed class PalmTree : Tree {
|
||||
|
||||
public override int DefaultValue(Random rnd) { return rnd.Next(4, 8); }
|
||||
public override int EstimateBlocksAffected() { return height + 8; }
|
||||
|
||||
public override int DefaultSize(Random rnd) { return rnd.Next(4, 8); }
|
||||
|
||||
public override void SetData(Random rnd, int value) {
|
||||
height = (byte)value;
|
||||
|
@ -25,7 +25,11 @@ namespace MCGalaxy.Generator.Foliage {
|
||||
int numBranches, maxExtent, maxBranchHeight, trunkHeight;
|
||||
List<Vec3S32> branch = new List<Vec3S32>();
|
||||
|
||||
public override int DefaultValue(Random rnd) { return rnd.Next(0, 11); }
|
||||
public override int MinSize { get { return 0; } }
|
||||
|
||||
public override int EstimateBlocksAffected() { return height * height * height; }
|
||||
|
||||
public override int DefaultSize(Random rnd) { return rnd.Next(0, 11); }
|
||||
|
||||
public override void SetData(Random rnd, int value) {
|
||||
numBranches = value;
|
||||
@ -104,7 +108,7 @@ namespace MCGalaxy.Generator.Foliage {
|
||||
LineDrawOp.DrawLine(p1.X, p1.Y, p1.Z, 100, p2.X, p2.Y, p2.Z, branch);
|
||||
|
||||
foreach (Vec3S32 P in branch) {
|
||||
output((ushort)P.X, (ushort)P.Y, (ushort)P.Z, Block.trunk);
|
||||
output((ushort)P.X, (ushort)P.Y, (ushort)P.Z, Block.trunk);
|
||||
}
|
||||
branch.Clear();
|
||||
}
|
||||
|
@ -28,8 +28,10 @@ using System;
|
||||
|
||||
namespace MCGalaxy.Generator.Foliage {
|
||||
public sealed class CactusTree : Tree {
|
||||
|
||||
public override int EstimateBlocksAffected() { return height + 3 * 2; }
|
||||
|
||||
public override int DefaultValue(Random rnd) { return rnd.Next(3, 6); }
|
||||
public override int DefaultSize(Random rnd) { return rnd.Next(3, 6); }
|
||||
|
||||
public override void SetData(Random rnd, int value) {
|
||||
height = (byte)value;
|
||||
@ -57,7 +59,9 @@ namespace MCGalaxy.Generator.Foliage {
|
||||
|
||||
public sealed class NormalTree : Tree {
|
||||
|
||||
public override int DefaultValue(Random rnd) { return rnd.Next(5, 8); }
|
||||
public override int EstimateBlocksAffected() { return height + size * size * size; }
|
||||
|
||||
public override int DefaultSize(Random rnd) { return rnd.Next(5, 8); }
|
||||
|
||||
public override void SetData(Random rnd, int value) {
|
||||
height = (byte)value;
|
||||
@ -86,7 +90,9 @@ namespace MCGalaxy.Generator.Foliage {
|
||||
|
||||
public sealed class ClassicTree : Tree {
|
||||
|
||||
public override int DefaultValue(Random rnd) { return rnd.Next(3, 7); }
|
||||
public override int EstimateBlocksAffected() { return height + 65; }
|
||||
|
||||
public override int DefaultSize(Random rnd) { return rnd.Next(3, 7); }
|
||||
|
||||
public override void SetData(Random rnd, int value) {
|
||||
height = (byte)value;
|
||||
@ -119,7 +125,9 @@ namespace MCGalaxy.Generator.Foliage {
|
||||
|
||||
public sealed class SwampTree : Tree {
|
||||
|
||||
public override int DefaultValue(Random rnd) { return rnd.Next(4, 8); }
|
||||
public override int EstimateBlocksAffected() { return height + 145; }
|
||||
|
||||
public override int DefaultSize(Random rnd) { return rnd.Next(4, 8); }
|
||||
|
||||
public override void SetData(Random rnd, int value) {
|
||||
height = (byte)value;
|
||||
|
@ -24,18 +24,22 @@ namespace MCGalaxy.Generator.Foliage {
|
||||
public delegate void TreeOutput(ushort x, ushort y, ushort z, byte block);
|
||||
|
||||
public abstract class Tree {
|
||||
protected internal byte height, size;
|
||||
protected internal int height, size;
|
||||
protected Random rnd;
|
||||
|
||||
/// <summary> Calculates a random default value (usually used for height) for this tree. </summary>
|
||||
public abstract int DefaultValue(Random rnd);
|
||||
|
||||
/// <summary> Minimum allowed value (usually used for height) for this tree. </summary>
|
||||
public virtual int MinValue { get { return 3; } }
|
||||
|
||||
/// <summary> Maximum allowed value (usually used for height) for this tree. </summary>
|
||||
public virtual int MaxValue { get { return 100; } }
|
||||
/// <summary> Minimum allowed size (usually means height) for this tree. </summary>
|
||||
public virtual int MinSize { get { return 3; } }
|
||||
|
||||
/// <summary> Maximum allowed size (usually means height) for this tree. </summary>
|
||||
public virtual int MaxSize { get { return 100; } }
|
||||
|
||||
/// <summary> Estimated the maximum number of blocks affected by this tree. </summary>
|
||||
public abstract int EstimateBlocksAffected();
|
||||
|
||||
/// <summary> Calculates a random default size (usually means height) for this tree. </summary>
|
||||
public abstract int DefaultSize(Random rnd);
|
||||
|
||||
/// <summary> Initalises data (e.g. height and size) for this tree using the input value. </summary>
|
||||
public abstract void SetData(Random rnd, int value);
|
||||
|
||||
|
@ -140,7 +140,7 @@ namespace MCGalaxy.Generator {
|
||||
if (genParams.UseCactus) tree = new CactusTree();
|
||||
else tree = new NormalTree();
|
||||
|
||||
tree.SetData(rand, tree.DefaultValue(rand));
|
||||
tree.SetData(rand, tree.DefaultSize(rand));
|
||||
tree.Generate(x, (ushort)(y + 1), z, (xT, yT, zT, bT) =>
|
||||
{
|
||||
if (Lvl.GetTile(xT, yT, zT) == Block.air)
|
||||
|
Loading…
x
Reference in New Issue
Block a user