-
Notifications
You must be signed in to change notification settings - Fork 274
Expand file tree
/
Copy pathRedwoodTree.java
More file actions
128 lines (114 loc) · 4.47 KB
/
RedwoodTree.java
File metadata and controls
128 lines (114 loc) · 4.47 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
package net.glowstone.generator.objects.trees;
import net.glowstone.util.BlockStateDelegate;
import org.bukkit.Material;
import org.bukkit.World;
import java.util.Random;
import java.util.HashSet;
import java.util.Set;
public class RedwoodTree extends GenericTree {
protected int maxRadius;
protected int leavesHeight;
/**
* Initializes this tree with a random height, preparing it to attempt to generate.
*
* @param random the PRNG
* @param delegate the BlockStateDelegate used to check for space and to fill wood and
*/
public RedwoodTree(Random random, BlockStateDelegate delegate) {
super(random, delegate);
setOverridables(
Material.AIR,
// Leaves
Material.OAK_LEAVES,
Material.SPRUCE_LEAVES,
Material.BIRCH_LEAVES,
Material.JUNGLE_LEAVES,
Material.ACACIA_LEAVES,
Material.DARK_OAK_LEAVES
);
setHeight(random.nextInt(4) + 6);
setLeavesHeight(random.nextInt(2) + 1);
setMaxRadius(random.nextInt(2) + 2);
setTypes(Material.SPRUCE_LOG, Material.SPRUCE_LEAVES);
}
protected final void setMaxRadius(int maxRadius) {
this.maxRadius = maxRadius;
}
protected final void setLeavesHeight(int leavesHeight) {
this.leavesHeight = leavesHeight;
}
@Override
public boolean canPlace(int baseX, int baseY, int baseZ, World world) {
Set<Material> overridableSet = new HashSet<>(overridables);
for (int y = baseY; y <= baseY + 1 + height; y++) {
// Space requirement
int radius; // default radius if above first block
if (y - baseY < leavesHeight) {
radius = 0; // radius is 0 for trunk below leaves
} else {
radius = maxRadius;
}
// check for block collision on horizontal slices
for (int x = baseX - radius; x <= baseX + radius; x++) {
for (int z = baseZ - radius; z <= baseZ + radius; z++) {
if (y >= 0 && y < 256) {
// we can overlap some blocks around
Material type = blockTypeAt(x, y, z, world);
if (!overridableSet.contains(type)) {
return false;
}
} else { // height out of range
return false;
}
}
}
}
return true;
}
@Override
public boolean generate(World world, Random random, int blockX, int blockY, int blockZ) {
if (cannotGenerateAt(blockX, blockY, blockZ, world)) {
return false;
}
// generate the leaves
int radius = random.nextInt(2);
int peakRadius = 1;
int minRadius = 0;
Set<Material> overridableSet = new HashSet<>(overridables);
for (int y = blockY + height; y >= blockY + leavesHeight; y--) {
// leaves are built from top to bottom
for (int x = blockX - radius; x <= blockX + radius; x++) {
for (int z = blockZ - radius; z <= blockZ + radius; z++) {
if ((Math.abs(x - blockX) != radius
|| Math.abs(z - blockZ) != radius || radius <= 0)
&& blockTypeAt(x, y, z, world) == Material.AIR) {
delegate.setType(world, x, y, z, leavesType);
}
}
}
if (radius >= peakRadius) {
radius = minRadius;
minRadius = 1; // after the peak radius is reached once, the min radius increases
peakRadius++; // the peak radius increases each time it's reached
if (peakRadius > maxRadius) {
peakRadius = maxRadius;
}
} else {
radius++;
}
}
// generate the trunk
for (int y = 0; y < height - random.nextInt(3); y++) {
Material type = blockTypeAt(blockX, blockY + y, blockZ, world);
if (overridableSet.contains(type)) {
delegate.setType(world, blockX, blockY + y,
blockZ, logType);
}
}
// block below trunk is always dirt
delegate.setType(world, blockX,
blockY - 1, blockZ,
Material.DIRT);
return true;
}
}