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() { public WeatherCommand() {
super("weather"); super("weather");
var isRaining = ArgumentType.Boolean("isRaining").setDefaultValue(false);
var rainLevel = ArgumentType.Float("rainLevel").setDefaultValue(0.0f); var rainLevel = ArgumentType.Float("rainLevel").setDefaultValue(0.0f);
var thunderLevel = ArgumentType.Float("thunderLevel").setDefaultValue(0.0f); var thunderLevel = ArgumentType.Float("thunderLevel").setDefaultValue(0.0f);
var transitionTicks = ArgumentType.Integer("transition").setDefaultValue(0); 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) { private void handleWeather(CommandSender source, CommandContext context) {
Player player = (Player) source; Player player = (Player) source;
boolean isRaining = context.get("isRaining");
float rainLevel = context.get("rainLevel"); float rainLevel = context.get("rainLevel");
float thunderLevel = context.get("thunderLevel"); float thunderLevel = context.get("thunderLevel");
int transitionTicks = context.get("transition"); 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; private long lastTimeUpdate;
// Weather of the instance // Weather of the instance
private Weather targetWeather = new Weather(false, 0, 0); private Weather weather = Weather.CLEAR;
private Weather currentWeather = new Weather(false, 0, 0); private Weather transitioningWeather = Weather.CLEAR;
private int remainingWeatherTransitionTicks; private int remainingRainTransitionTicks;
private int remainingThunderTransitionTicks;
// Field for tick events // Field for tick events
private long lastTickAge = System.currentTimeMillis(); private long lastTickAge = System.currentTimeMillis();
@ -674,11 +675,12 @@ public abstract class Instance implements Block.Getter, Block.Setter,
} }
// Weather // Weather
if (remainingWeatherTransitionTicks > 0) { if (remainingRainTransitionTicks > 0 || remainingThunderTransitionTicks > 0) {
Weather previousWeather = currentWeather; Weather previousWeather = transitioningWeather;
currentWeather = transitionWeather(remainingWeatherTransitionTicks); transitioningWeather = transitionWeather(remainingRainTransitionTicks, remainingThunderTransitionTicks);
sendWeatherPackets(previousWeather); sendWeatherPackets(previousWeather);
remainingWeatherTransitionTicks--; remainingRainTransitionTicks = Math.max(0, remainingRainTransitionTicks - 1);
remainingThunderTransitionTicks = Math.max(0, remainingThunderTransitionTicks - 1);
} }
// Tick event // 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() { 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 * @param transitionTicks the ticks to transition to new weather
*/ */
public void setWeather(@NotNull Weather weather, int transitionTicks) { public void setWeather(@NotNull Weather weather, int transitionTicks) {
Check.stateCondition(transitionTicks < 1, "Transition ticks cannot be lower than 1"); Check.stateCondition(transitionTicks < 1, "Transition ticks cannot be lower than 0");
targetWeather = weather; this.weather = weather;
remainingWeatherTransitionTicks = transitionTicks; 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) { private void sendWeatherPackets(@NotNull Weather previousWeather) {
if (currentWeather.isRaining() != previousWeather.isRaining()) sendGroupedPacket(currentWeather.createIsRainingPacket()); boolean toggledRain = (transitioningWeather.isRaining() != previousWeather.isRaining());
if (currentWeather.rainLevel() != previousWeather.rainLevel()) sendGroupedPacket(currentWeather.createRainLevelPacket()); if (toggledRain) sendGroupedPacket(transitioningWeather.createIsRainingPacket());
if (currentWeather.thunderLevel() != previousWeather.thunderLevel()) sendGroupedPacket(currentWeather.createThunderLevelPacket()); if (transitioningWeather.rainLevel() != previousWeather.rainLevel()) sendGroupedPacket(transitioningWeather.createRainLevelPacket());
if (transitioningWeather.thunderLevel() != previousWeather.thunderLevel()) sendGroupedPacket(transitioningWeather.createThunderLevelPacket());
} }
private @NotNull Weather transitionWeather(int remainingTicks) { private @NotNull Weather transitionWeather(int remainingRainTransitionTicks, int remainingThunderTransitionTicks) {
Weather target = targetWeather; Weather target = weather;
Weather current = currentWeather; Weather current = transitioningWeather;
if (remainingTicks <= 1) { float rainLevel = current.rainLevel() + (target.rainLevel() - current.rainLevel()) * (1 / (float)Math.max(1, remainingRainTransitionTicks));
return new Weather(target.isRaining(), target.isRaining() ? target.rainLevel() : 0, float thunderLevel = current.thunderLevel() + (target.thunderLevel() - current.thunderLevel()) * (1 / (float)Math.max(1, remainingThunderTransitionTicks));
target.isRaining() ? target.thunderLevel() : 0); return new Weather(rainLevel, thunderLevel);
}
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);
} }
@Override @Override

View File

@ -14,7 +14,6 @@ import java.util.List;
/** /**
* Represents the possible weather properties of an instance * 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 * @param rainLevel a percentage between 0 and 1
* used to change how heavy the rain is * used to change how heavy the rain is
* higher values darken the sky and increase rain opacity * 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 * used to change how heavy the thunder is
* higher values further darken the sky * 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 rainLevel} is not between 0 and 1
* @throws IllegalArgumentException if {@code thunderLevel} 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) @Contract(pure = true)
public @NotNull Weather withRain(boolean isRaining) { public @NotNull Weather withRainLevel(float rainLevel) {
return new Weather(isRaining, rainLevel, thunderLevel); return new Weather(rainLevel, thunderLevel);
} }
@Contract(pure = true) /**
public @NotNull Weather withRainLevel(float rainLevel) { * @return true if {@code rainLevel} is > 0
return new Weather(isRaining, rainLevel, thunderLevel); */
public boolean isRaining() {
return rainLevel > 0;
} }
@Contract(pure = true) @Contract(pure = true)
@ -49,7 +54,7 @@ public record Weather(boolean isRaining, float rainLevel, float thunderLevel) {
@Contract(pure = true) @Contract(pure = true)
public @NotNull Weather withThunderLevel(float thunderLevel) { public @NotNull Weather withThunderLevel(float thunderLevel) {
return new Weather(isRaining, rainLevel, thunderLevel); return new Weather(rainLevel, thunderLevel);
} }
@Contract(pure = true) @Contract(pure = true)
@ -58,7 +63,7 @@ public record Weather(boolean isRaining, float rainLevel, float thunderLevel) {
} }
public ChangeGameStatePacket createIsRainingPacket() { 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() { public ChangeGameStatePacket createRainLevelPacket() {

View File

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