forked from mgrandi/RealisticBiomes
-
Notifications
You must be signed in to change notification settings - Fork 4
Expand file tree
/
Copy pathGrowthConfig.java
More file actions
289 lines (228 loc) · 9.53 KB
/
Copy pathGrowthConfig.java
File metadata and controls
289 lines (228 loc) · 9.53 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
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
package com.untamedears.realisticbiomes;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Random;
import java.util.logging.Logger;
import org.bukkit.Material;
import org.bukkit.block.Biome;
import org.bukkit.block.Block;
import org.bukkit.configuration.ConfigurationSection;
import org.bukkit.util.Vector;
public class GrowthConfig extends BaseConfig {
// a rate of growth between 0 and 1
// this usually represents a chance,
// for a crop, it would be the chance to grow per tick
// for an animal, it would be the chance to spawn after mating
// this rate overrides all other settings if the plant is under artificial light (adjacent to glowstone)
private double greenhouseRate;
private boolean isGreenhouseEnabled;
private boolean greenhouseIgnoreBiome;
// flag that denotes if this crop's growth is persisted
private boolean isPersistent;
private double persistentRate;
// a crop's growth rate can be modulated by the amount of sunlight, not just light in general
// the crop's growth rate may also get a bonus if it is directly open to the sky, or underneath glowstone (not yet)
private boolean needsSunlight;
// multiplier that is applied if the crop is not at light level = 15
private double notFullSunlightMultiplier;
// multiplier that is applied if the crop is not near "fresh water(river biome)"
private double notIrrigatedMultiplier;
// some crops get a boost from layers of materials beneath the block the plant has been planted on
private Material soilMaterial;
private int soilMaxLayers;
private double soilBonusPerLevel;
// the z levels below the actual growth event location in which to start looking for the correct soil
private int soilLayerOffset;
private double pestProbability;
// conversion used for persistence calculations
private static final int SEC_PER_HOUR = 60 * 60;
// maximum light level on a block
private static final double MAX_LIGHT_INTENSITY = 15.0;
// ------------------------------------------------------------------------
public static Logger LOG = Logger.getLogger("RealisticBiomes");
// ========================================================================
// Initialization
// relative locations of visible adjacent blocks
@SuppressWarnings("serial")
private static List<Vector> adjacentBlocks = new ArrayList<Vector>(){{
this.add(new Vector(0,1,0)); // up
this.add(new Vector(-1,0,0)); // west
this.add(new Vector(1,0,0)); // east
this.add(new Vector(0,0,-1)); // north
this.add(new Vector(0,0,1)); // south
}};
private static List<Vector> waterCheckBlocks = new ArrayList<Vector>(){{
this.add(new Vector(-5,-1,0)); // west
this.add(new Vector(5,-1,0)); // east
this.add(new Vector(0,-1,-5)); // north
this.add(new Vector(0,-1,5)); // south
}};
public static GrowthConfig get(ConfigurationSection conf, GrowthConfig parent, Map<String, Biome[]>biomeAliases) {
GrowthConfig growth = new GrowthConfig(parent);
return growth;
}
// create a new default configuration
GrowthConfig() {
super();
greenhouseRate = 1.0;
isGreenhouseEnabled = false;
greenhouseIgnoreBiome = false;
isPersistent = false;
needsSunlight = false;
notFullSunlightMultiplier = 1.0;
notIrrigatedMultiplier = 1.0;
soilMaterial = null; /* none */
soilMaxLayers = 0;
soilBonusPerLevel = 0.0;
soilLayerOffset = 1;
pestProbability = 0.0;
}
// make a copy of the given configuration
GrowthConfig(GrowthConfig parent) {
super();
copy(parent);
}
// make a copy of the given configuration and modify it by loading in a YML config section
GrowthConfig(GrowthConfig parent, ConfigurationSection config, HashMap<String, List<Biome>> biomeAliases) {
copy(parent);
if (config.isSet("base_rate"))
baseRate = config.getDouble("base_rate");
if (config.isSet("greenhouse_rate")) {
isGreenhouseEnabled = true;
greenhouseRate = config.getDouble("greenhouse_rate");
}
if (config.isSet("greenhouse_ignore_biome")) {
greenhouseIgnoreBiome = config.getBoolean("greenhouse_ignore_biome");
}
isPersistent = false;
if (config.isSet("persistent_growth_period")) {
isPersistent = true;
persistentRate = config.getDouble("persistent_growth_period");
}
if (config.isSet("needs_sunlight"))
needsSunlight = config.getBoolean("needs_sunlight");
if (config.isSet("not_full_sunlight_multiplier"))
notFullSunlightMultiplier = config.getDouble("not_full_sunlight_multiplier");
if (config.isSet("not_irrigated_multiplier"))
notIrrigatedMultiplier = config.getDouble("not_irrigated_multiplier");
if (config.isSet("soil_material")) {
String materialName = config.getString("soil_material");
Material material = Material.getMaterial(materialName);
if (material == null)
LOG.warning("loading configs: \""+ config.getName() +"\" soil_material: \"" + materialName +"\" is not a valid material name.");
else
soilMaterial = material;
}
if (config.isSet("soil_max_layers"))
soilMaxLayers = config.getInt("soil_max_layers");
if (config.isSet("soil_bonus_per_layer"))
soilBonusPerLevel = config.getDouble("soil_bonus_per_layer");
if (config.isSet("soil_layer_offset"))
soilLayerOffset = config.getInt("soil_layer_offset");
if (config.isSet("pest_probability"))
pestProbability = config.getDouble("pest_probability");
if (config.isSet("biomes"))
loadBiomes(config.getConfigurationSection("biomes"), biomeAliases);
}
public void copy(GrowthConfig other) {
super.copy(other);
greenhouseRate = other.greenhouseRate;
isGreenhouseEnabled = other.isGreenhouseEnabled;
greenhouseIgnoreBiome = other.greenhouseIgnoreBiome;
needsSunlight = other.needsSunlight;
notFullSunlightMultiplier = other.notFullSunlightMultiplier;
notIrrigatedMultiplier = other.notIrrigatedMultiplier;
soilMaterial = other.soilMaterial;
soilMaxLayers = other.soilMaxLayers;
soilBonusPerLevel = other.soilBonusPerLevel;
soilLayerOffset = other.soilLayerOffset;
}
/* ================================================================================ */
// Public Methods
public boolean isPersistent() {
return isPersistent;
}
// given a block (a location), find the growth rate using these rules
@Override
public double getRate(Block block) {
// rate = baseRate * sunlightLevel * biome * (1.0 + soilBonus)
double rate = baseRate;
// if persistent, the growth rate is measured in growth/second
if (isPersistent) {
rate = 1.0 / (persistentRate * SEC_PER_HOUR);
}
double environmentMultiplier = 1.0;
// biome multiplier
Double biomeMultiplier = biomeMultipliers.get(block.getBiome());
if (biomeMultiplier != null) {
environmentMultiplier *= biomeMultiplier.floatValue();
} else {
return 0.0; // if the biome cannot be found, assume zero
}
// if the greenhouse effect does not ignore biome, fold the biome rate into the main rate directly
if (!greenhouseIgnoreBiome) {
rate *= environmentMultiplier;
environmentMultiplier = 1.0;
}
// modulate the rate by the amount of sunlight recieved by this plant
int sunlightIntensity = block.getLightFromSky();
if (needsSunlight) {
environmentMultiplier *= Math.pow((sunlightIntensity / MAX_LIGHT_INTENSITY), 3.0);
}
// apply multiplier if the sunlight is not at maximum
if (sunlightIntensity < MAX_LIGHT_INTENSITY) {
environmentMultiplier *= notFullSunlightMultiplier;
}
// if the crop block if fully lit, and the greenhouse rate would be an improvement
// over the current environment multiplier, then use the green house rate as the
// environment multiplier.
if(isGreenhouseEnabled && ( environmentMultiplier < greenhouseRate ) && ( block.getLightFromBlocks() == (MAX_LIGHT_INTENSITY - 1) ) ) {
// make sure it's a glowstone/lamp
for( Vector vec : adjacentBlocks ) {
Material mat = block.getLocation().add(vec).getBlock().getType();
if( mat == Material.GLOWSTONE || mat == Material.REDSTONE_LAMP_ON ) {
environmentMultiplier = greenhouseRate;
break;
}
}
}
rate *= environmentMultiplier;
// if the plant will be effected by irrigation, check if the block is at the correct level and
// check if nearby blocks are water blocks in river biomes
if (notIrrigatedMultiplier != 1.0) {
// determine if the block is near a water block in a river biome
boolean irrigated = false;
for( Vector vec : waterCheckBlocks ) {
Block waterBlock = block.getLocation().add(vec).getBlock();
Material mat = waterBlock.getType();
Biome biome = waterBlock.getBiome();
if((biome == Biome.RIVER || biome == Biome.FROZEN_RIVER) && (mat == Material.STATIONARY_WATER || mat == Material.WATER)) {
irrigated = true;
break;
}
}
if (!irrigated)
rate *= notIrrigatedMultiplier;
}
// check the depth of the required 'soil' and add a bonus
float soilBonus = 0.0f;
Block newBlock = block.getRelative(0,-soilLayerOffset,0);
int soilCount = 0;
while (soilCount < soilMaxLayers) {
if (newBlock == null || !newBlock.getType().equals(soilMaterial)) {
break;
}
soilBonus += soilBonusPerLevel;
newBlock = newBlock.getRelative(0, -1, 0);
soilCount++;
}
rate *= (1.0 + soilBonus);
return rate;
}
public boolean testPest() {
Random gen = new Random();
return gen.nextDouble() < pestProbability;
}
}