From dc17d171ce0ca7ce9d8cc48810c4b89057037120 Mon Sep 17 00:00:00 2001 From: DeidaraMC <117625071+DeidaraMC@users.noreply.github.com> Date: Fri, 29 Mar 2024 10:12:45 -0400 Subject: [PATCH] feat: vanilla style Instance#setWeather method overload, weather api improvements (#2064) * feat: weather update * chore: Weather#createIsRainingPacket use isRaining --- .../demo/commands/WeatherCommand.java | 6 +- .../minestom/server/instance/Instance.java | 63 +++++++++++-------- .../net/minestom/server/instance/Weather.java | 23 ++++--- .../minestom/server/instance/WeatherTest.java | 4 +- 4 files changed, 55 insertions(+), 41 deletions(-) diff --git a/demo/src/main/java/net/minestom/demo/commands/WeatherCommand.java b/demo/src/main/java/net/minestom/demo/commands/WeatherCommand.java index 36ace5437..b5bbc6c74 100644 --- a/demo/src/main/java/net/minestom/demo/commands/WeatherCommand.java +++ b/demo/src/main/java/net/minestom/demo/commands/WeatherCommand.java @@ -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); } } diff --git a/src/main/java/net/minestom/server/instance/Instance.java b/src/main/java/net/minestom/server/instance/Instance.java index fa34b1b49..b8cbd45dd 100644 --- a/src/main/java/net/minestom/server/instance/Instance.java +++ b/src/main/java/net/minestom/server/instance/Instance.java @@ -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 diff --git a/src/main/java/net/minestom/server/instance/Weather.java b/src/main/java/net/minestom/server/instance/Weather.java index 0056347a4..efee14c04 100644 --- a/src/main/java/net/minestom/server/instance/Weather.java +++ b/src/main/java/net/minestom/server/instance/Weather.java @@ -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() { diff --git a/src/test/java/net/minestom/server/instance/WeatherTest.java b/src/test/java/net/minestom/server/instance/WeatherTest.java index 17a1c6239..42e4a0371 100644 --- a/src/test/java/net/minestom/server/instance/WeatherTest.java +++ b/src/test/java/net/minestom/server/instance/WeatherTest.java @@ -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());