I am adding the plant growth simulation system. I want it to support offline growth as well. So plants will keep growing even when the player is not in the game. I want to do it by using the “time passed” approach.
The most basic form is to use a GrowthTime component with a start and end time
public class GrowthTime implements PersistentComponent {
private final long startTime;
private final long endTime;
public GrowthTime(long startTime, long endTime) {
this.startTime = startTime;
this.endTime = endTime;
}
public long getStartTime() {
return startTime;
}
public long getEndTime() {
return endTime;
}
}
The PlantGrowthSystem will watch for entities with GrowthTime and call the “OnGrowth” action on the plant object type when the time comes. This should work fine with offline growth as well.
But I want to add another factor and that is the WaterLevel of the field (soil). So I want the plant growth only when the water level is > 0, if the water level becomes 0 then the plant must stop growing.
public class WaterLevel implements PersistentComponent {
private final int level;
private final long reductionInterval; // nano time
private final long lastModifiedTime; // nano time
/**
* @param level The water level in [0, 100]
* @param reductionIntervalSecond The time interval after which the water level will be reduced by one. This will be
* continued until the water level becomes 0.
*/
public WaterLevel(int level, long reductionIntervalSecond) {
if (level < 0 || level > 100) {
throw new IllegalArgumentException("Level value must be in [0, 100]");
}
this.level = level;
this.reductionInterval = reductionIntervalSecond * 1000000000;
this.lastModifiedTime = System.nanoTime();
}
/**
* @return The water level between [0, 100] at the current time.
*/
public double getLevel() {
return getLevel(System.nanoTime());
}
/**
* @return The water level between [0, 100] at the specified time.
*/
public double getLevel(long time) {
if (reductionInterval > 0) {
double timePassed = (time - lastModifiedTime);
double reduction = timePassed / reductionInterval;
return Math.max(0d, level - reduction);
}
return level;
}
public WaterLevel adjustLevel(int delta) {
int newLevel = (int) (getLevel() + delta);
return new WaterLevel(Math.min(Math.max(0, newLevel), 100), reductionInterval);
}
}
So I need another entity set in PlantGrowthSystem to watch for the WaterLevel of fields and somehow stop the plant from growing and works when offline as well.
My previous implementation of the GrowthTime component (with a start time and end time) is not compatible with this as I need a way to stop the time when the water level is 0.
But I am not sure how should implement this in PlantGrowthSystem while making it compatible with offline growing.
Yeah, these things have a way of chaining together.
It’s easy enough to say "plant will be grown at time x’.
And “water level will be low at time y”.
…and another thing entirely to have plant growth be stunted by water level… which might be consumed by animals… which might get eaten by wolves at a certain rate, etc…
Suddenly, determining what specific time something will happen gets quite tricky.
I will deal with this issue with my AI at some point. I hope to go with the “estimation” route in my case… on average, these x,y,z things will happen every day so if you get there at 2 PM, probably the state will be “this”. and so on.
…but I keep “fast forward the simulation” in my hip pocket. And sometimes they can be combined. Estimate by the hour, catch up to the minute, and so on.