feat: vanilla style Instance#setWeather method overload, weather api improvements (#2064)

* feat: weather update

* chore: Weather#createIsRainingPacket use isRaining
This commit is contained in:
DeidaraMC 2024-03-29 10:12:45 -04:00 committed by GitHub
parent 9f72bf4c44
commit dc17d171ce
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
4 changed files with 55 additions and 41 deletions

View File

@ -11,19 +11,17 @@ public class WeatherCommand extends Command {
public WeatherCommand() {
super("weather");
var isRaining = ArgumentType.Boolean("isRaining").setDefaultValue(false);
var rainLevel = ArgumentType.Float("rainLevel").setDefaultValue(0.0f);
var thunderLevel = ArgumentType.Float("thunderLevel").setDefaultValue(0.0f);
var transitionTicks = ArgumentType.Integer("transition").setDefaultValue(0);
addSyntax(this::handleWeather, isRaining, rainLevel, thunderLevel, transitionTicks);
addSyntax(this::handleWeather, rainLevel, thunderLevel, transitionTicks);
}
private void handleWeather(CommandSender source, CommandContext context) {
Player player = (Player) source;
boolean isRaining = context.get("isRaining");
float rainLevel = context.get("rainLevel");
float thunderLevel = context.get("thunderLevel");
int transitionTicks = context.get("transition");
player.getInstance().setWeather(new Weather(isRaining, rainLevel, thunderLevel), transitionTicks);
player.getInstance().setWeather(new Weather(rainLevel, thunderLevel), transitionTicks);
}
}

View File

@ -84,9 +84,10 @@ public abstract class Instance implements Block.Getter, Block.Setter,
private long lastTimeUpdate;
// Weather of the instance
private Weather targetWeather = new Weather(false, 0, 0);
private Weather currentWeather = new Weather(false, 0, 0);
private int remainingWeatherTransitionTicks;
private Weather weather = Weather.CLEAR;
private Weather transitioningWeather = Weather.CLEAR;
private int remainingRainTransitionTicks;
private int remainingThunderTransitionTicks;
// Field for tick events
private long lastTickAge = System.currentTimeMillis();
@ -674,11 +675,12 @@ public abstract class Instance implements Block.Getter, Block.Setter,
}
// Weather
if (remainingWeatherTransitionTicks > 0) {
Weather previousWeather = currentWeather;
currentWeather = transitionWeather(remainingWeatherTransitionTicks);
if (remainingRainTransitionTicks > 0 || remainingThunderTransitionTicks > 0) {
Weather previousWeather = transitioningWeather;
transitioningWeather = transitionWeather(remainingRainTransitionTicks, remainingThunderTransitionTicks);
sendWeatherPackets(previousWeather);
remainingWeatherTransitionTicks--;
remainingRainTransitionTicks = Math.max(0, remainingRainTransitionTicks - 1);
remainingThunderTransitionTicks = Math.max(0, remainingThunderTransitionTicks - 1);
}
// Tick event
{
@ -691,12 +693,12 @@ public abstract class Instance implements Block.Getter, Block.Setter,
}
/**
* Gets the current weather on this instance
* Gets the weather of this instance
*
* @return the current weather
* @return the instance weather
*/
public @NotNull Weather getWeather() {
return currentWeather;
return weather;
}
/**
@ -706,27 +708,36 @@ public abstract class Instance implements Block.Getter, Block.Setter,
* @param transitionTicks the ticks to transition to new weather
*/
public void setWeather(@NotNull Weather weather, int transitionTicks) {
Check.stateCondition(transitionTicks < 1, "Transition ticks cannot be lower than 1");
targetWeather = weather;
remainingWeatherTransitionTicks = transitionTicks;
Check.stateCondition(transitionTicks < 1, "Transition ticks cannot be lower than 0");
this.weather = weather;
remainingRainTransitionTicks = transitionTicks;
remainingThunderTransitionTicks = transitionTicks;
}
/**
* Sets the weather of this instance with a fixed transition
*
* @param weather the new weather
*/
public void setWeather(@NotNull Weather weather) {
this.weather = weather;
remainingRainTransitionTicks = (int) Math.max(1, Math.abs((this.weather.rainLevel() - transitioningWeather.rainLevel()) / 0.01));
remainingThunderTransitionTicks = (int) Math.max(1, Math.abs((this.weather.thunderLevel() - transitioningWeather.thunderLevel()) / 0.01));
}
private void sendWeatherPackets(@NotNull Weather previousWeather) {
if (currentWeather.isRaining() != previousWeather.isRaining()) sendGroupedPacket(currentWeather.createIsRainingPacket());
if (currentWeather.rainLevel() != previousWeather.rainLevel()) sendGroupedPacket(currentWeather.createRainLevelPacket());
if (currentWeather.thunderLevel() != previousWeather.thunderLevel()) sendGroupedPacket(currentWeather.createThunderLevelPacket());
boolean toggledRain = (transitioningWeather.isRaining() != previousWeather.isRaining());
if (toggledRain) sendGroupedPacket(transitioningWeather.createIsRainingPacket());
if (transitioningWeather.rainLevel() != previousWeather.rainLevel()) sendGroupedPacket(transitioningWeather.createRainLevelPacket());
if (transitioningWeather.thunderLevel() != previousWeather.thunderLevel()) sendGroupedPacket(transitioningWeather.createThunderLevelPacket());
}
private @NotNull Weather transitionWeather(int remainingTicks) {
Weather target = targetWeather;
Weather current = currentWeather;
if (remainingTicks <= 1) {
return new Weather(target.isRaining(), target.isRaining() ? target.rainLevel() : 0,
target.isRaining() ? target.thunderLevel() : 0);
}
float rainLevel = current.rainLevel() + (target.rainLevel() - current.rainLevel()) * (1 / (float)remainingTicks);
float thunderLevel = current.thunderLevel() + (target.thunderLevel() - current.thunderLevel()) * (1 / (float)remainingTicks);
return new Weather(rainLevel > 0, rainLevel, thunderLevel);
private @NotNull Weather transitionWeather(int remainingRainTransitionTicks, int remainingThunderTransitionTicks) {
Weather target = weather;
Weather current = transitioningWeather;
float rainLevel = current.rainLevel() + (target.rainLevel() - current.rainLevel()) * (1 / (float)Math.max(1, remainingRainTransitionTicks));
float thunderLevel = current.thunderLevel() + (target.thunderLevel() - current.thunderLevel()) * (1 / (float)Math.max(1, remainingThunderTransitionTicks));
return new Weather(rainLevel, thunderLevel);
}
@Override

View File

@ -14,7 +14,6 @@ import java.util.List;
/**
* Represents the possible weather properties of an instance
*
* @param isRaining true if the instance is raining, otherwise false
* @param rainLevel a percentage between 0 and 1
* used to change how heavy the rain is
* higher values darken the sky and increase rain opacity
@ -22,7 +21,11 @@ import java.util.List;
* used to change how heavy the thunder is
* higher values further darken the sky
*/
public record Weather(boolean isRaining, float rainLevel, float thunderLevel) {
public record Weather(float rainLevel, float thunderLevel) {
public static final Weather CLEAR = new Weather(0, 0);
public static final Weather RAIN = new Weather(1, 0);
public static final Weather THUNDER = new Weather(1, 1);
/**
* @throws IllegalArgumentException if {@code rainLevel} is not between 0 and 1
* @throws IllegalArgumentException if {@code thunderLevel} is not between 0 and 1
@ -33,13 +36,15 @@ public record Weather(boolean isRaining, float rainLevel, float thunderLevel) {
}
@Contract(pure = true)
public @NotNull Weather withRain(boolean isRaining) {
return new Weather(isRaining, rainLevel, thunderLevel);
public @NotNull Weather withRainLevel(float rainLevel) {
return new Weather(rainLevel, thunderLevel);
}
@Contract(pure = true)
public @NotNull Weather withRainLevel(float rainLevel) {
return new Weather(isRaining, rainLevel, thunderLevel);
/**
* @return true if {@code rainLevel} is > 0
*/
public boolean isRaining() {
return rainLevel > 0;
}
@Contract(pure = true)
@ -49,7 +54,7 @@ public record Weather(boolean isRaining, float rainLevel, float thunderLevel) {
@Contract(pure = true)
public @NotNull Weather withThunderLevel(float thunderLevel) {
return new Weather(isRaining, rainLevel, thunderLevel);
return new Weather(rainLevel, thunderLevel);
}
@Contract(pure = true)
@ -58,7 +63,7 @@ public record Weather(boolean isRaining, float rainLevel, float thunderLevel) {
}
public ChangeGameStatePacket createIsRainingPacket() {
return new ChangeGameStatePacket(isRaining ? ChangeGameStatePacket.Reason.BEGIN_RAINING : ChangeGameStatePacket.Reason.END_RAINING, 0);
return new ChangeGameStatePacket(isRaining() ? ChangeGameStatePacket.Reason.BEGIN_RAINING : ChangeGameStatePacket.Reason.END_RAINING, 0);
}
public ChangeGameStatePacket createRainLevelPacket() {

View File

@ -23,7 +23,7 @@ public class WeatherTest {
assertEquals(0, weather.rainLevel());
assertEquals(0, weather.thunderLevel());
instance.setWeather(new Weather(true, 1, 0.5f), 1);
instance.setWeather(new Weather(1, 0.5f), 1);
instance.tick(0);
// Weather sent on instance join
@ -45,7 +45,7 @@ public class WeatherTest {
// Weather change while inside instance
var tracker2 = connection.trackIncoming(ChangeGameStatePacket.class);
instance.setWeather(new Weather(false, 0, 0), 2);
instance.setWeather(new Weather(0, 0), 2);
instance.tick(0);
state = tracker2.collect().get(0);
assertEquals(ChangeGameStatePacket.Reason.RAIN_LEVEL_CHANGE, state.reason());