diff --git a/api/src/main/java/com/lunarclient/apollo/common/location/HudPosition.java b/api/src/main/java/com/lunarclient/apollo/common/location/HudPosition.java new file mode 100644 index 00000000..c6f7f4fa --- /dev/null +++ b/api/src/main/java/com/lunarclient/apollo/common/location/HudPosition.java @@ -0,0 +1,54 @@ +/* + * This file is part of Apollo, licensed under the MIT License. + * + * Copyright (c) 2026 Moonsworth + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ +package com.lunarclient.apollo.common.location; + +import lombok.Builder; +import lombok.Getter; + +/** + * Represents a HUD element position on the client screen. + * + * @since 1.2.6 + */ +@Getter +@Builder +public final class HudPosition { + + /** + * Returns the {@code float} X coordinate for this HUD position. + * + * @return the x coordinate + * @since 1.2.6 + */ + float x; + + /** + * Returns the {@code float} Y coordinate for this HUD position. + * + * @return the y coordinate + * @since 1.2.6 + */ + float y; + +} diff --git a/api/src/main/java/com/lunarclient/apollo/module/cooldown/CooldownStyle.java b/api/src/main/java/com/lunarclient/apollo/module/cooldown/CooldownStyle.java index 2641e5a3..9886e19f 100644 --- a/api/src/main/java/com/lunarclient/apollo/module/cooldown/CooldownStyle.java +++ b/api/src/main/java/com/lunarclient/apollo/module/cooldown/CooldownStyle.java @@ -29,7 +29,7 @@ import org.jetbrains.annotations.Nullable; /** - * Represents the {@link Cooldown} style, allowing customization of the circle start, end, edge & text color. + * Represents the {@link Cooldown} style, allowing customization of the circle start, end, edge and text color. * * @since 1.2.5 */ diff --git a/api/src/main/java/com/lunarclient/apollo/module/stopwatch/Stopwatch.java b/api/src/main/java/com/lunarclient/apollo/module/stopwatch/Stopwatch.java new file mode 100644 index 00000000..3afd1df2 --- /dev/null +++ b/api/src/main/java/com/lunarclient/apollo/module/stopwatch/Stopwatch.java @@ -0,0 +1,119 @@ +/* + * This file is part of Apollo, licensed under the MIT License. + * + * Copyright (c) 2026 Moonsworth + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ +package com.lunarclient.apollo.module.stopwatch; + +import com.lunarclient.apollo.common.location.HudPosition; +import java.awt.Color; +import lombok.Builder; +import lombok.Getter; +import org.jetbrains.annotations.Nullable; + +/** + * Represents a stopwatch which can be displayed on the client HUD. + * + * @since 1.2.6 + */ +@Getter +@Builder +public final class Stopwatch { + + /** + * Returns the stopwatch {@link String} id. + * + * @return the stopwatch id + * @since 1.2.6 + */ + String id; + + /** + * Returns the stopwatch {@link String} name. + * + * @return the stopwatch name + * @since 1.2.6 + */ + String name; + + /** + * Returns the stopwatch {@code boolean} reset on start. + * + *

If {@code true}, elapsed time is reset on each start.

+ * + * @return whether to reset on start + * @since 1.2.6 + */ + boolean resetOnStart; + + /** + * Returns the stopwatch {@code boolean} prevent modification. + * + *

If {@code true}, the user cannot modify the options for this + * stopwatch on the client side.

+ * + * @return whether modification is prevented + * @since 1.2.6 + */ + boolean preventModification; + + /** + * Returns the stopwatch {@code boolean} hide when stopped. + * + *

If {@code true}, the stopwatch is hidden from the HUD when stopped.

+ * + * @return whether to hide when stopped + * @since 1.2.6 + */ + boolean hideWhenStopped; + + /** + * Returns the stopwatch {@link String} display format. + * + *

A format string (e.g. {@code "mm:ss"}), or {@code null} + * for the default display format.

+ * + * @return the display format string + * @since 1.2.6 + */ + @Nullable String displayFormat; + + /** + * Returns the stopwatch {@link Color} text color. + * + *

If {@code null}, the default color (white) is used.

+ * + * @return the text color + * @since 1.2.6 + */ + @Nullable Color textColor; + + /** + * Returns the stopwatch {@link HudPosition} HUD position. + * + *

If {@code null}, the stopwatch is auto-stacked at the default position.

+ * + * @return the HUD position + * @since 1.2.6 + */ + @Nullable HudPosition hudPosition; + +} diff --git a/api/src/main/java/com/lunarclient/apollo/module/stopwatch/StopwatchModule.java b/api/src/main/java/com/lunarclient/apollo/module/stopwatch/StopwatchModule.java index bec98316..f39af579 100644 --- a/api/src/main/java/com/lunarclient/apollo/module/stopwatch/StopwatchModule.java +++ b/api/src/main/java/com/lunarclient/apollo/module/stopwatch/StopwatchModule.java @@ -45,28 +45,141 @@ public Collection getSupportedPlatforms() { return Arrays.asList(ApolloPlatform.Kind.SERVER, ApolloPlatform.Kind.PROXY); } + /** + * Adds a {@link Stopwatch} to the HUD for the {@link Recipients}. + * + * @param recipients the recipients that are receiving the packet + * @param stopwatch the stopwatch to add + * @since 1.2.6 + */ + public abstract void addStopwatch(Recipients recipients, Stopwatch stopwatch); + + /** + * Removes the {@link Stopwatch} with the given id for the {@link Recipients}. + * + * @param recipients the recipients that are receiving the packet + * @param id the stopwatch id + * @since 1.2.6 + */ + public abstract void removeStopwatch(Recipients recipients, String id); + + /** + * Starts the {@link Stopwatch} with the given id for the {@link Recipients}. + * + * @param recipients the recipients that are receiving the packet + * @param id the stopwatch id + * @since 1.2.6 + */ + public abstract void startStopwatch(Recipients recipients, String id); + + /** + * Stops the {@link Stopwatch} with the given id for the {@link Recipients}. + * + * @param recipients the recipients that are receiving the packet + * @param id the stopwatch id + * @since 1.2.6 + */ + public abstract void stopStopwatch(Recipients recipients, String id); + + /** + * Resets the {@link Stopwatch} with the given id for the {@link Recipients}. + * + * @param recipients the recipients that are receiving the packet + * @param id the stopwatch id + * @since 1.2.6 + */ + public abstract void resetStopwatch(Recipients recipients, String id); + + /** + * Resets all {@link Stopwatch}es for the {@link Recipients}. + * + * @param recipients the recipients that are receiving the packet + * @since 1.2.6 + */ + public abstract void resetStopwatches(Recipients recipients); + + /** + * Adds a {@link Timer} to the HUD for the {@link Recipients}. + * + * @param recipients the recipients that are receiving the packet + * @param timer the timer to add + * @since 1.2.6 + */ + public abstract void addTimer(Recipients recipients, Timer timer); + + /** + * Removes the {@link Timer} with the given id for the {@link Recipients}. + * + * @param recipients the recipients that are receiving the packet + * @param id the timer id + * @since 1.2.6 + */ + public abstract void removeTimer(Recipients recipients, String id); + + /** + * Starts the {@link Timer} with the given id for the {@link Recipients}. + * + * @param recipients the recipients that are receiving the packet + * @param id the timer id + * @since 1.2.6 + */ + public abstract void startTimer(Recipients recipients, String id); + + /** + * Stops the {@link Timer} with the given id for the {@link Recipients}. + * + * @param recipients the recipients that are receiving the packet + * @param id the timer id + * @since 1.2.6 + */ + public abstract void stopTimer(Recipients recipients, String id); + + /** + * Resets the {@link Timer} with the given id for the {@link Recipients}. + * + * @param recipients the recipients that are receiving the packet + * @param id the timer id + * @since 1.2.6 + */ + public abstract void resetTimer(Recipients recipients, String id); + + /** + * Resets all {@link Timer}s for the {@link Recipients}. + * + * @param recipients the recipients that are receiving the packet + * @since 1.2.6 + */ + public abstract void resetTimers(Recipients recipients); + /** * Starts the stopwatch for the {@link Recipients}. * * @param recipients the recipients that are receiving the packet + * @deprecated for removal since 1.2.6, use {@link #addStopwatch(Recipients, Stopwatch)} + * and {@link #startStopwatch(Recipients, String)} instead. * @since 1.0.0 */ + @Deprecated public abstract void startStopwatch(Recipients recipients); /** * Stops the stopwatch for the {@link Recipients}. * * @param recipients the recipients that are receiving the packet + * @deprecated for removal since 1.2.6, use {@link #stopStopwatch(Recipients, String)} instead. * @since 1.0.0 */ + @Deprecated public abstract void stopStopwatch(Recipients recipients); /** * Resets the stopwatch for the {@link Recipients}. * * @param recipients the recipients that are receiving the packet + * @deprecated for removal since 1.2.6, use {@link #resetStopwatch(Recipients, String)} instead. * @since 1.0.0 */ + @Deprecated public abstract void resetStopwatch(Recipients recipients); } diff --git a/api/src/main/java/com/lunarclient/apollo/module/stopwatch/Timer.java b/api/src/main/java/com/lunarclient/apollo/module/stopwatch/Timer.java new file mode 100644 index 00000000..99d71861 --- /dev/null +++ b/api/src/main/java/com/lunarclient/apollo/module/stopwatch/Timer.java @@ -0,0 +1,150 @@ +/* + * This file is part of Apollo, licensed under the MIT License. + * + * Copyright (c) 2026 Moonsworth + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ +package com.lunarclient.apollo.module.stopwatch; + +import com.lunarclient.apollo.common.location.HudPosition; +import java.awt.Color; +import java.time.Duration; +import lombok.Builder; +import lombok.Getter; +import net.kyori.adventure.text.Component; +import org.jetbrains.annotations.Nullable; + +/** + * Represents a timer which can be displayed on the client HUD. + * + * @since 1.2.6 + */ +@Getter +@Builder +public final class Timer { + + /** + * Returns the timer {@link String} id. + * + * @return the timer id + * @since 1.2.6 + */ + String id; + + /** + * Returns the timer {@link String} name. + * + * @return the timer name + * @since 1.2.6 + */ + String name; + + /** + * Returns the timer {@link Duration}. + * + * @return the timer duration + * @since 1.2.6 + */ + Duration duration; + + /** + * Returns the timer {@code boolean} loop. + * + *

If {@code true}, the timer restarts automatically when finished.

+ * + * @return whether the timer loops + * @since 1.2.6 + */ + boolean loop; + + /** + * Returns the timer {@code boolean} prevent modification. + * + *

If {@code true}, the user cannot modify the options for this + * timer on the client side.

+ * + * @return whether modification is prevented + * @since 1.2.6 + */ + boolean preventModification; + + /** + * Returns the timer {@code boolean} hide when stopped. + * + *

If {@code true}, the timer is hidden from the HUD when stopped.

+ * + * @return whether to hide when stopped + * @since 1.2.6 + */ + boolean hideWhenStopped; + + /** + * Returns the timer {@link String} display format. + * + *

A format string (e.g. {@code "mm:ss"}), or {@code null} + * for the default display format.

+ * + * @return the display format string + * @since 1.2.6 + */ + @Nullable String displayFormat; + + /** + * Returns the timer {@link Component} title text. + * + *

The on-screen title shown when the timer finishes, + * or {@code null} to skip.

+ * + * @return the title text component + * @since 1.2.6 + */ + @Nullable Component titleText; + + /** + * Returns the timer {@code boolean} in-game notification. + * + *

If {@code true}, an in-game popup is shown when the timer finishes.

+ * + * @return whether an in-game notification is shown + * @since 1.2.6 + */ + boolean inGameNotification; + + /** + * Returns the timer {@link Color} text color. + * + *

If {@code null}, the default color (white) is used.

+ * + * @return the text color + * @since 1.2.6 + */ + @Nullable Color textColor; + + /** + * Returns the timer {@link HudPosition} HUD position. + * + *

If {@code null}, the timer is auto-stacked at the default position.

+ * + * @return the HUD position + * @since 1.2.6 + */ + @Nullable HudPosition hudPosition; + +} diff --git a/common/src/main/java/com/lunarclient/apollo/module/stopwatch/StopwatchModuleImpl.java b/common/src/main/java/com/lunarclient/apollo/module/stopwatch/StopwatchModuleImpl.java index efba37df..ded30e4b 100644 --- a/common/src/main/java/com/lunarclient/apollo/module/stopwatch/StopwatchModuleImpl.java +++ b/common/src/main/java/com/lunarclient/apollo/module/stopwatch/StopwatchModuleImpl.java @@ -23,12 +23,26 @@ */ package com.lunarclient.apollo.module.stopwatch; +import com.lunarclient.apollo.common.ApolloComponent; +import com.lunarclient.apollo.common.location.HudPosition; +import com.lunarclient.apollo.network.NetworkTypes; import com.lunarclient.apollo.player.AbstractApolloPlayer; import com.lunarclient.apollo.recipients.Recipients; +import com.lunarclient.apollo.stopwatch.v1.AddStopwatchMessage; +import com.lunarclient.apollo.stopwatch.v1.AddTimerMessage; +import com.lunarclient.apollo.stopwatch.v1.RemoveStopwatchMessage; +import com.lunarclient.apollo.stopwatch.v1.RemoveTimerMessage; import com.lunarclient.apollo.stopwatch.v1.ResetStopwatchMessage; +import com.lunarclient.apollo.stopwatch.v1.ResetStopwatchesMessage; +import com.lunarclient.apollo.stopwatch.v1.ResetTimerMessage; +import com.lunarclient.apollo.stopwatch.v1.ResetTimersMessage; import com.lunarclient.apollo.stopwatch.v1.StartStopwatchMessage; +import com.lunarclient.apollo.stopwatch.v1.StartTimerMessage; import com.lunarclient.apollo.stopwatch.v1.StopStopwatchMessage; +import com.lunarclient.apollo.stopwatch.v1.StopTimerMessage; +import java.awt.Color; import lombok.NonNull; +import net.kyori.adventure.text.Component; /** * Provides the stopwatch module. @@ -55,4 +69,151 @@ public void resetStopwatch(@NonNull Recipients recipients) { recipients.forEach(player -> ((AbstractApolloPlayer) player).sendPacket(message)); } + @Override + public void addStopwatch(@NonNull Recipients recipients, @NonNull Stopwatch stopwatch) { + AddStopwatchMessage.Builder builder = AddStopwatchMessage.newBuilder() + .setId(stopwatch.getId()) + .setName(stopwatch.getName()) + .setResetOnStart(stopwatch.isResetOnStart()) + .setPreventModification(stopwatch.isPreventModification()) + .setHideWhenStopped(stopwatch.isHideWhenStopped()); + + String displayFormat = stopwatch.getDisplayFormat(); + if (displayFormat != null) { + builder.setDisplayFormat(displayFormat); + } + + Color textColor = stopwatch.getTextColor(); + if (textColor != null) { + builder.setTextColor(NetworkTypes.toProtobuf(textColor)); + } + + HudPosition hudPosition = stopwatch.getHudPosition(); + if (hudPosition != null) { + builder.setHudPosition(NetworkTypes.toProtobuf(hudPosition)); + } + + AddStopwatchMessage message = builder.build(); + recipients.forEach(player -> ((AbstractApolloPlayer) player).sendPacket(message)); + } + + @Override + public void removeStopwatch(@NonNull Recipients recipients, @NonNull String id) { + RemoveStopwatchMessage message = RemoveStopwatchMessage.newBuilder() + .setId(id) + .build(); + + recipients.forEach(player -> ((AbstractApolloPlayer) player).sendPacket(message)); + } + + @Override + public void startStopwatch(@NonNull Recipients recipients, @NonNull String id) { + StartStopwatchMessage message = StartStopwatchMessage.newBuilder() + .setId(id) + .build(); + + recipients.forEach(player -> ((AbstractApolloPlayer) player).sendPacket(message)); + } + + @Override + public void stopStopwatch(@NonNull Recipients recipients, @NonNull String id) { + StopStopwatchMessage message = StopStopwatchMessage.newBuilder() + .setId(id) + .build(); + + recipients.forEach(player -> ((AbstractApolloPlayer) player).sendPacket(message)); + } + + @Override + public void resetStopwatch(@NonNull Recipients recipients, @NonNull String id) { + ResetStopwatchMessage message = ResetStopwatchMessage.newBuilder() + .setId(id) + .build(); + + recipients.forEach(player -> ((AbstractApolloPlayer) player).sendPacket(message)); + } + + @Override + public void resetStopwatches(@NonNull Recipients recipients) { + ResetStopwatchesMessage message = ResetStopwatchesMessage.getDefaultInstance(); + recipients.forEach(player -> ((AbstractApolloPlayer) player).sendPacket(message)); + } + + @Override + public void addTimer(@NonNull Recipients recipients, @NonNull Timer timer) { + AddTimerMessage.Builder builder = AddTimerMessage.newBuilder() + .setId(timer.getId()) + .setName(timer.getName()) + .setDuration(NetworkTypes.toProtobuf(timer.getDuration())) + .setLoop(timer.isLoop()) + .setPreventModification(timer.isPreventModification()) + .setHideWhenStopped(timer.isHideWhenStopped()) + .setInGameNotification(timer.isInGameNotification()); + + String displayFormat = timer.getDisplayFormat(); + if (displayFormat != null) { + builder.setDisplayFormat(displayFormat); + } + + Component titleText = timer.getTitleText(); + if (titleText != null) { + builder.setTitleTextAdventureJsonLines(ApolloComponent.toJson(titleText)); + } + + Color textColor = timer.getTextColor(); + if (textColor != null) { + builder.setTextColor(NetworkTypes.toProtobuf(textColor)); + } + + HudPosition hudPosition = timer.getHudPosition(); + if (hudPosition != null) { + builder.setHudPosition(NetworkTypes.toProtobuf(hudPosition)); + } + + AddTimerMessage message = builder.build(); + recipients.forEach(player -> ((AbstractApolloPlayer) player).sendPacket(message)); + } + + @Override + public void removeTimer(@NonNull Recipients recipients, @NonNull String id) { + RemoveTimerMessage message = RemoveTimerMessage.newBuilder() + .setId(id) + .build(); + + recipients.forEach(player -> ((AbstractApolloPlayer) player).sendPacket(message)); + } + + @Override + public void startTimer(@NonNull Recipients recipients, @NonNull String id) { + StartTimerMessage message = StartTimerMessage.newBuilder() + .setId(id) + .build(); + + recipients.forEach(player -> ((AbstractApolloPlayer) player).sendPacket(message)); + } + + @Override + public void stopTimer(@NonNull Recipients recipients, @NonNull String id) { + StopTimerMessage message = StopTimerMessage.newBuilder() + .setId(id) + .build(); + + recipients.forEach(player -> ((AbstractApolloPlayer) player).sendPacket(message)); + } + + @Override + public void resetTimer(@NonNull Recipients recipients, @NonNull String id) { + ResetTimerMessage message = ResetTimerMessage.newBuilder() + .setId(id) + .build(); + + recipients.forEach(player -> ((AbstractApolloPlayer) player).sendPacket(message)); + } + + @Override + public void resetTimers(@NonNull Recipients recipients) { + ResetTimersMessage message = ResetTimersMessage.getDefaultInstance(); + recipients.forEach(player -> ((AbstractApolloPlayer) player).sendPacket(message)); + } + } diff --git a/common/src/main/java/com/lunarclient/apollo/network/NetworkTypes.java b/common/src/main/java/com/lunarclient/apollo/network/NetworkTypes.java index df89e825..2a0a40ff 100644 --- a/common/src/main/java/com/lunarclient/apollo/network/NetworkTypes.java +++ b/common/src/main/java/com/lunarclient/apollo/network/NetworkTypes.java @@ -35,6 +35,7 @@ import com.lunarclient.apollo.common.location.ApolloBlockLocation; import com.lunarclient.apollo.common.location.ApolloLocation; import com.lunarclient.apollo.common.location.ApolloPlayerLocation; +import com.lunarclient.apollo.common.location.HudPosition; import com.lunarclient.apollo.common.profile.Profile; import com.lunarclient.apollo.common.v1.EntityId; import com.lunarclient.apollo.common.v1.Uuid; @@ -142,6 +143,36 @@ public static Color fromProtobuf(com.lunarclient.apollo.common.v1.Color message) return new Color(message.getColor()); } + /** + * Converts a {@link HudPosition} object to a + * {@link com.lunarclient.apollo.hud.v1.HudPosition} proto message. + * + * @param object the hud position + * @return the proto hud position message + * @since 1.2.6 + */ + public static com.lunarclient.apollo.hud.v1.HudPosition toProtobuf(HudPosition object) { + return com.lunarclient.apollo.hud.v1.HudPosition.newBuilder() + .setX(object.getX()) + .setY(object.getY()) + .build(); + } + + /** + * Converts a {@link com.lunarclient.apollo.hud.v1.HudPosition} + * proto message to a {@link HudPosition} object. + * + * @param message the hud position message + * @return the hud position object + * @since 1.2.6 + */ + public static HudPosition fromProtobuf(com.lunarclient.apollo.hud.v1.HudPosition message) { + return HudPosition.builder() + .x(message.getX()) + .y(message.getY()) + .build(); + } + /** * Converts an {@link Duration} object to an * {@link com.google.protobuf.Duration} proto message. diff --git a/docs/developers/modules/stopwatch.mdx b/docs/developers/modules/stopwatch.mdx index ade32cf4..7d48472b 100644 --- a/docs/developers/modules/stopwatch.mdx +++ b/docs/developers/modules/stopwatch.mdx @@ -1,15 +1,20 @@ -import { Callout, Tab, Tabs } from 'nextra-theme-docs' +import { Tab, Tabs } from 'nextra-theme-docs' +import { Callout } from 'nextra-theme-docs' # Stopwatch Module ## Overview -The stopwatch module allows you to control the stopwatch mod inside Lunar Client. +The stopwatch module allows you to add custom Stopwatch and Timers directly to player's screens in any HUD position you want. -- Ability to fully control a player's stopwatch mod. - - Start a player's stopwatch - - Stop a player's stopwatch - - Reset a player's stopwatch +- Ability to create unique Stopwatch counters for a player. + - Control when it starts, stops, and when it resets. + - Customize the name, display color, and display format. + - Display the stopwatch anywhere on the player's screen. +- Ability to create and control unique Timers for a player. + - Control when the timer starts, stops, and when it resets. + - Customize the duration, name, looping, display format, and display color of the timer. + - Display the timer HUD in the position you'd like on the player's screen. ![Stopwatch Module Example](/modules/stopwatch/overview.gif#center) @@ -30,64 +35,436 @@ Explore each integration by cycling through each tab, to find the best fit for y **Apollo API examples.** See [General](/apollo/developers/general) for common patterns and helpers. -### Start Stopwatch +### Adding a Stopwatch + +```java +public void addStopwatchExample(Player viewer) { + Optional apolloPlayerOpt = Apollo.getPlayerManager().getPlayer(viewer.getUniqueId()); + + apolloPlayerOpt.ifPresent(apolloPlayer -> { + this.stopwatchModule.addStopwatch(apolloPlayer, Stopwatch.builder() + .id("parkour-stopwatch") + .name("Parkour") + .resetOnStart(true) + .preventModification(true) + .hideWhenStopped(false) + .displayFormat("mm:ss") + .textColor(ApolloColors.DARK_AQUA) + .hudPosition(HudPosition.builder() + .x(-30) + .y(30) + .build() + ) + .build()); + }); +} +``` + +### Removing a Stopwatch + +```java +public void removeStopwatchExample(Player viewer) { + Optional apolloPlayerOpt = Apollo.getPlayerManager().getPlayer(viewer.getUniqueId()); + apolloPlayerOpt.ifPresent(apolloPlayer -> this.stopwatchModule.removeStopwatch(apolloPlayer, "parkour-stopwatch")); +} +``` + +### Starting a Stopwatch ```java public void startStopwatchExample(Player viewer) { Optional apolloPlayerOpt = Apollo.getPlayerManager().getPlayer(viewer.getUniqueId()); - apolloPlayerOpt.ifPresent(this.stopwatchModule::startStopwatch); + apolloPlayerOpt.ifPresent(apolloPlayer -> this.stopwatchModule.startStopwatch(apolloPlayer, "parkour-stopwatch")); } ``` -### Stop Stopwatch +### Stopping a Stopwatch ```java public void stopStopwatchExample(Player viewer) { Optional apolloPlayerOpt = Apollo.getPlayerManager().getPlayer(viewer.getUniqueId()); - apolloPlayerOpt.ifPresent(this.stopwatchModule::stopStopwatch); + apolloPlayerOpt.ifPresent(apolloPlayer -> this.stopwatchModule.stopStopwatch(apolloPlayer, "parkour-stopwatch")); } ``` -### Reset Stopwatch +### Resetting a Stopwatch ```java public void resetStopwatchExample(Player viewer) { Optional apolloPlayerOpt = Apollo.getPlayerManager().getPlayer(viewer.getUniqueId()); - apolloPlayerOpt.ifPresent(this.stopwatchModule::resetStopwatch); + apolloPlayerOpt.ifPresent(apolloPlayer -> this.stopwatchModule.resetStopwatch(apolloPlayer, "parkour-stopwatch")); +} +``` + +### Resetting all Stopwatches + +```java +public void resetStopwatchesExample(Player viewer) { + Optional apolloPlayerOpt = Apollo.getPlayerManager().getPlayer(viewer.getUniqueId()); + apolloPlayerOpt.ifPresent(this.stopwatchModule::resetStopwatches); +} +``` + +### Adding a Timer + +```java +public void addTimerExample(Player viewer) { + Optional apolloPlayerOpt = Apollo.getPlayerManager().getPlayer(viewer.getUniqueId()); + + apolloPlayerOpt.ifPresent(apolloPlayer -> { + this.stopwatchModule.addTimer(apolloPlayer, Timer.builder() + .id("game-timer") + .name("Countdown") + .duration(Duration.ofSeconds(45)) + .loop(false) + .preventModification(true) + .hideWhenStopped(false) + .displayFormat("mm:ss") + .titleText(Component.text("Time's up!", NamedTextColor.RED)) + .inGameNotification(true) + .textColor(ApolloColors.LIGHT_PURPLE) + .hudPosition(HudPosition.builder() + .x(-10) + .y(30) + .build() + ) + .build()); + }); +} +``` + +### Removing a Timer + +```java +public void removeTimerExample(Player viewer) { + Optional apolloPlayerOpt = Apollo.getPlayerManager().getPlayer(viewer.getUniqueId()); + apolloPlayerOpt.ifPresent(apolloPlayer -> this.stopwatchModule.removeTimer(apolloPlayer, "game-timer")); +} +``` + +### Starting a Timer + +```java +public void startTimerExample(Player viewer) { + Optional apolloPlayerOpt = Apollo.getPlayerManager().getPlayer(viewer.getUniqueId()); + apolloPlayerOpt.ifPresent(apolloPlayer -> this.stopwatchModule.startTimer(apolloPlayer, "game-timer")); +} +``` + +### Stopping a Timer + +```java +public void stopTimerExample(Player viewer) { + Optional apolloPlayerOpt = Apollo.getPlayerManager().getPlayer(viewer.getUniqueId()); + apolloPlayerOpt.ifPresent(apolloPlayer -> this.stopwatchModule.stopTimer(apolloPlayer, "game-timer")); +} +``` + +### Resetting a Timer + +```java +public void resetTimerExample(Player viewer) { + Optional apolloPlayerOpt = Apollo.getPlayerManager().getPlayer(viewer.getUniqueId()); + apolloPlayerOpt.ifPresent(apolloPlayer -> this.stopwatchModule.resetTimer(apolloPlayer, "game-timer")); +} +``` + +### Resetting all Timers + +```java +public void resetTimersExample(Player viewer) { + Optional apolloPlayerOpt = Apollo.getPlayerManager().getPlayer(viewer.getUniqueId()); + apolloPlayerOpt.ifPresent(this.stopwatchModule::resetTimers); } ``` +#### `Stopwatch` Options + +`.id(String)` is the unique server-assigned id for the stopwatch. + +```java +.id("parkour-stopwatch") +``` + +`.name(String)` is the HUD display name. + +```java +.name("Parkour") +``` + +`.resetOnStart(boolean)` determines whether to reset elapsed time on each start. + +```java +.resetOnStart(true) +``` + +`.preventModification(boolean)` prevents the user from modifying the options for this stopwatch on the client side. + +```java +.preventModification(true) +``` + +`.hideWhenStopped(boolean)` determines whether the stopwatch is hidden from the HUD when stopped. + +```java +.hideWhenStopped(false) +``` + +`.displayFormat(String)` is a format string (e.g. `"mm:ss"`). Uses the default display format if not provided. + +```java +.displayFormat("mm:ss") +``` + +`.textColor(java.awt.Color)` is the text color. Defaults to white if not provided. See the [colors page](/apollo/developers/utilities/colors) for more. + +```java +.textColor(ApolloColors.DARK_AQUA) +``` + +`.hudPosition(HudPosition)` is the HUD position on the client screen. If not provided, the stopwatch is auto-stacked. + +```java +.hudPosition(HudPosition.builder().x(-30).y(30).build()) +``` + +#### `Timer` Options + +`.id(String)` is the unique server-assigned id for the timer. + +```java +.id("game-timer") +``` + +`.name(String)` is the HUD display name. + +```java +.name("Countdown") +``` + +`.duration(java.time.Duration)` is the countdown duration. + +```java +.duration(Duration.ofSeconds(45)) +``` + +`.loop(boolean)` determines whether the timer restarts automatically when finished. + +```java +.loop(false) +``` + +`.preventModification(boolean)` prevents the user from modifying the options for this timer on the client side. + +```java +.preventModification(true) +``` + +`.hideWhenStopped(boolean)` determines whether the timer is hidden from the HUD when stopped. + +```java +.hideWhenStopped(false) +``` + +`.displayFormat(String)` is a format string. Uses the default display format if not provided. + +```java +.displayFormat("mm:ss") +``` + +`.titleText(Component)` is the on-screen title shown when the timer finishes. Set to `null` or omit to skip. See the [chat components](https://docs.advntr.dev/text.html) page for more. + +```java +.titleText(Component.text("Time's up!", NamedTextColor.RED)) +``` + +`.inGameNotification(boolean)` determines whether to show an in-game popup when the timer finishes. + +```java +.inGameNotification(true) +``` + +`.textColor(java.awt.Color)` is the text color. Defaults to white if not provided. See the [colors page](/apollo/developers/utilities/colors) for more. + +```java +.textColor(ApolloColors.LIGHT_PURPLE) +``` + +`.hudPosition(HudPosition)` is the HUD position on the client screen. If not provided, the timer is auto-stacked. + +```java +.hudPosition(HudPosition.builder().x(-10).y(30).build()) +``` + +### Adding a Stopwatch + **Lightweight Protobuf examples.** See [Lightweight Protobuf](/apollo/developers/lightweight/protobuf) for setup. -**Start Stopwatch** +```java +public void addStopwatchExample(Player viewer) { + AddStopwatchMessage message = AddStopwatchMessage.newBuilder() + .setId("parkour-stopwatch") + .setName("Parkour") + .setResetOnStart(true) + .setPreventModification(true) + .setHideWhenStopped(false) + .setDisplayFormat("mm:ss") + .setTextColor(ProtobufUtil.createColorProto(new Color(0, 170, 170))) + .setHudPosition(HudPosition.newBuilder() + .setX(-30) + .setY(30) + .build() + ) + .build(); + + ProtobufPacketUtil.sendPacket(viewer, message); +} +``` + +### Removing a Stopwatch + +```java +public void removeStopwatchExample(Player viewer) { + RemoveStopwatchMessage message = RemoveStopwatchMessage.newBuilder() + .setId("parkour-stopwatch") + .build(); + + ProtobufPacketUtil.sendPacket(viewer, message); +} +``` + +### Starting a Stopwatch ```java public void startStopwatchExample(Player viewer) { - StartStopwatchMessage message = StartStopwatchMessage.getDefaultInstance(); + StartStopwatchMessage message = StartStopwatchMessage.newBuilder() + .setId("parkour-stopwatch") + .build(); + ProtobufPacketUtil.sendPacket(viewer, message); } ``` -**Stop Stopwatch** +### Stopping a Stopwatch ```java public void stopStopwatchExample(Player viewer) { - StopStopwatchMessage message = StopStopwatchMessage.getDefaultInstance(); + StopStopwatchMessage message = StopStopwatchMessage.newBuilder() + .setId("parkour-stopwatch") + .build(); + ProtobufPacketUtil.sendPacket(viewer, message); } ``` -**Reset Stopwatch** +### Resetting a Stopwatch ```java public void resetStopwatchExample(Player viewer) { - ResetStopwatchMessage message = ResetStopwatchMessage.getDefaultInstance(); + ResetStopwatchMessage message = ResetStopwatchMessage.newBuilder() + .setId("parkour-stopwatch") + .build(); + + ProtobufPacketUtil.sendPacket(viewer, message); +} +``` + +### Resetting all Stopwatches + +```java +public void resetStopwatchesExample(Player viewer) { + ResetStopwatchesMessage message = ResetStopwatchesMessage.getDefaultInstance(); + ProtobufPacketUtil.sendPacket(viewer, message); +} +``` + +### Adding a Timer + +```java +public void addTimerExample(Player viewer) { + AddTimerMessage message = AddTimerMessage.newBuilder() + .setId("game-timer") + .setName("Countdown") + .setDuration(ProtobufUtil.createDurationProto(Duration.ofSeconds(45))) + .setLoop(false) + .setPreventModification(true) + .setHideWhenStopped(false) + .setDisplayFormat("mm:ss") + .setTitleTextAdventureJsonLines(AdventureUtil.toJson( + Component.text("Time's up!", NamedTextColor.RED) + )) + .setInGameNotification(true) + .setTextColor(ProtobufUtil.createColorProto(new Color(255, 85, 255))) + .setHudPosition(HudPosition.newBuilder() + .setX(-10) + .setY(30) + .build() + ) + .build(); + + ProtobufPacketUtil.sendPacket(viewer, message); +} +``` + +### Removing a Timer + +```java +public void removeTimerExample(Player viewer) { + RemoveTimerMessage message = RemoveTimerMessage.newBuilder() + .setId("game-timer") + .build(); + + ProtobufPacketUtil.sendPacket(viewer, message); +} +``` + +### Starting a Timer + +```java +public void startTimerExample(Player viewer) { + StartTimerMessage message = StartTimerMessage.newBuilder() + .setId("game-timer") + .build(); + + ProtobufPacketUtil.sendPacket(viewer, message); +} +``` + +### Stopping a Timer + +```java +public void stopTimerExample(Player viewer) { + StopTimerMessage message = StopTimerMessage.newBuilder() + .setId("game-timer") + .build(); + + ProtobufPacketUtil.sendPacket(viewer, message); +} +``` + +### Resetting a Timer + +```java +public void resetTimerExample(Player viewer) { + ResetTimerMessage message = ResetTimerMessage.newBuilder() + .setId("game-timer") + .build(); + + ProtobufPacketUtil.sendPacket(viewer, message); +} +``` + +### Resetting all Timers + +```java +public void resetTimersExample(Player viewer) { + ResetTimersMessage message = ResetTimersMessage.getDefaultInstance(); ProtobufPacketUtil.sendPacket(viewer, message); } ``` @@ -100,34 +477,170 @@ public void resetStopwatchExample(Player viewer) { **Lightweight JSON examples.** See [Lightweight JSON](/apollo/developers/lightweight/json) for setup. -**Start Stopwatch** +### Adding a Stopwatch + +```java +public void addStopwatchExample(Player viewer) { + JsonObject message = new JsonObject(); + message.addProperty("@type", "type.googleapis.com/lunarclient.apollo.stopwatch.v1.AddStopwatchMessage"); + message.addProperty("id", "parkour-stopwatch"); + message.addProperty("name", "Parkour"); + message.addProperty("reset_on_start", true); + message.addProperty("prevent_modification", true); + message.addProperty("hide_when_stopped", false); + message.addProperty("display_format", "mm:ss"); + message.add("text_color", JsonUtil.createColorObject(new Color(0, 170, 170))); + + JsonObject stopwatchPosition = new JsonObject(); + stopwatchPosition.addProperty("x", -30); + stopwatchPosition.addProperty("y", 30); + message.add("hud_position", stopwatchPosition); + + JsonPacketUtil.sendPacket(viewer, message); +} +``` + +### Removing a Stopwatch + +```java +public void removeStopwatchExample(Player viewer) { + JsonObject message = new JsonObject(); + message.addProperty("@type", "type.googleapis.com/lunarclient.apollo.stopwatch.v1.RemoveStopwatchMessage"); + message.addProperty("id", "parkour-stopwatch"); + + JsonPacketUtil.sendPacket(viewer, message); +} +``` + +### Starting a Stopwatch ```java public void startStopwatchExample(Player viewer) { JsonObject message = new JsonObject(); message.addProperty("@type", "type.googleapis.com/lunarclient.apollo.stopwatch.v1.StartStopwatchMessage"); + message.addProperty("id", "parkour-stopwatch"); JsonPacketUtil.sendPacket(viewer, message); } ``` -**Stop Stopwatch** +### Stopping a Stopwatch ```java public void stopStopwatchExample(Player viewer) { JsonObject message = new JsonObject(); message.addProperty("@type", "type.googleapis.com/lunarclient.apollo.stopwatch.v1.StopStopwatchMessage"); + message.addProperty("id", "parkour-stopwatch"); JsonPacketUtil.sendPacket(viewer, message); } ``` -**Reset Stopwatch** +### Resetting a Stopwatch ```java public void resetStopwatchExample(Player viewer) { JsonObject message = new JsonObject(); message.addProperty("@type", "type.googleapis.com/lunarclient.apollo.stopwatch.v1.ResetStopwatchMessage"); + message.addProperty("id", "parkour-stopwatch"); + + JsonPacketUtil.sendPacket(viewer, message); +} +``` + +### Resetting all Stopwatches + +```java +public void resetStopwatchesExample(Player viewer) { + JsonObject message = new JsonObject(); + message.addProperty("@type", "type.googleapis.com/lunarclient.apollo.stopwatch.v1.ResetStopwatchesMessage"); + + JsonPacketUtil.sendPacket(viewer, message); +} +``` + +### Adding a Timer + +```java +public void addTimerExample(Player viewer) { + JsonObject message = new JsonObject(); + message.addProperty("@type", "type.googleapis.com/lunarclient.apollo.stopwatch.v1.AddTimerMessage"); + message.addProperty("id", "game-timer"); + message.addProperty("name", "Countdown"); + message.addProperty("duration", JsonUtil.createDurationObject(Duration.ofSeconds(45))); + message.addProperty("loop", false); + message.addProperty("prevent_modification", true); + message.addProperty("hide_when_stopped", false); + message.addProperty("display_format", "mm:ss"); + message.addProperty("title_text_adventure_json_lines", AdventureUtil.toJson( + Component.text("Time's up!", NamedTextColor.RED) + )); + message.addProperty("in_game_notification", true); + message.add("text_color", JsonUtil.createColorObject(new Color(255, 85, 255))); + + JsonObject timerPosition = new JsonObject(); + timerPosition.addProperty("x", -10); + timerPosition.addProperty("y", 30); + message.add("hud_position", timerPosition); + + JsonPacketUtil.sendPacket(viewer, message); +} +``` + +### Removing a Timer + +```java +public void removeTimerExample(Player viewer) { + JsonObject message = new JsonObject(); + message.addProperty("@type", "type.googleapis.com/lunarclient.apollo.stopwatch.v1.RemoveTimerMessage"); + message.addProperty("id", "game-timer"); + + JsonPacketUtil.sendPacket(viewer, message); +} +``` + +### Starting a Timer + +```java +public void startTimerExample(Player viewer) { + JsonObject message = new JsonObject(); + message.addProperty("@type", "type.googleapis.com/lunarclient.apollo.stopwatch.v1.StartTimerMessage"); + message.addProperty("id", "game-timer"); + + JsonPacketUtil.sendPacket(viewer, message); +} +``` + +### Stopping a Timer + +```java +public void stopTimerExample(Player viewer) { + JsonObject message = new JsonObject(); + message.addProperty("@type", "type.googleapis.com/lunarclient.apollo.stopwatch.v1.StopTimerMessage"); + message.addProperty("id", "game-timer"); + + JsonPacketUtil.sendPacket(viewer, message); +} +``` + +### Resetting a Timer + +```java +public void resetTimerExample(Player viewer) { + JsonObject message = new JsonObject(); + message.addProperty("@type", "type.googleapis.com/lunarclient.apollo.stopwatch.v1.ResetTimerMessage"); + message.addProperty("id", "game-timer"); + + JsonPacketUtil.sendPacket(viewer, message); +} +``` + +### Resetting all Timers + +```java +public void resetTimersExample(Player viewer) { + JsonObject message = new JsonObject(); + message.addProperty("@type", "type.googleapis.com/lunarclient.apollo.stopwatch.v1.ResetTimersMessage"); JsonPacketUtil.sendPacket(viewer, message); } diff --git a/example/bukkit/api/src/main/java/com/lunarclient/apollo/example/api/module/StopwatchApiExample.java b/example/bukkit/api/src/main/java/com/lunarclient/apollo/example/api/module/StopwatchApiExample.java index 620bb4fb..2ff0d6c4 100644 --- a/example/bukkit/api/src/main/java/com/lunarclient/apollo/example/api/module/StopwatchApiExample.java +++ b/example/bukkit/api/src/main/java/com/lunarclient/apollo/example/api/module/StopwatchApiExample.java @@ -24,32 +24,128 @@ package com.lunarclient.apollo.example.api.module; import com.lunarclient.apollo.Apollo; +import com.lunarclient.apollo.common.ApolloColors; +import com.lunarclient.apollo.common.location.HudPosition; import com.lunarclient.apollo.example.module.impl.StopwatchExample; +import com.lunarclient.apollo.module.stopwatch.Stopwatch; import com.lunarclient.apollo.module.stopwatch.StopwatchModule; +import com.lunarclient.apollo.module.stopwatch.Timer; import com.lunarclient.apollo.player.ApolloPlayer; +import java.time.Duration; import java.util.Optional; +import net.kyori.adventure.text.Component; +import net.kyori.adventure.text.format.NamedTextColor; import org.bukkit.entity.Player; public class StopwatchApiExample extends StopwatchExample { private final StopwatchModule stopwatchModule = Apollo.getModuleManager().getModule(StopwatchModule.class); + @Override + public void addStopwatchExample(Player viewer) { + Optional apolloPlayerOpt = Apollo.getPlayerManager().getPlayer(viewer.getUniqueId()); + + apolloPlayerOpt.ifPresent(apolloPlayer -> { + this.stopwatchModule.addStopwatch(apolloPlayer, Stopwatch.builder() + .id("parkour-stopwatch") + .name("Parkour") + .resetOnStart(true) + .preventModification(true) + .hideWhenStopped(false) + .displayFormat("mm:ss") + .textColor(ApolloColors.DARK_AQUA) + .hudPosition(HudPosition.builder() + .x(-30) + .y(30) + .build() + ) + .build()); + }); + } + + @Override + public void removeStopwatchExample(Player viewer) { + Optional apolloPlayerOpt = Apollo.getPlayerManager().getPlayer(viewer.getUniqueId()); + apolloPlayerOpt.ifPresent(apolloPlayer -> this.stopwatchModule.removeStopwatch(apolloPlayer, "parkour-stopwatch")); + } + @Override public void startStopwatchExample(Player viewer) { Optional apolloPlayerOpt = Apollo.getPlayerManager().getPlayer(viewer.getUniqueId()); - apolloPlayerOpt.ifPresent(this.stopwatchModule::startStopwatch); + apolloPlayerOpt.ifPresent(apolloPlayer -> this.stopwatchModule.startStopwatch(apolloPlayer, "parkour-stopwatch")); } @Override public void stopStopwatchExample(Player viewer) { Optional apolloPlayerOpt = Apollo.getPlayerManager().getPlayer(viewer.getUniqueId()); - apolloPlayerOpt.ifPresent(this.stopwatchModule::stopStopwatch); + apolloPlayerOpt.ifPresent(apolloPlayer -> this.stopwatchModule.stopStopwatch(apolloPlayer, "parkour-stopwatch")); } @Override public void resetStopwatchExample(Player viewer) { Optional apolloPlayerOpt = Apollo.getPlayerManager().getPlayer(viewer.getUniqueId()); - apolloPlayerOpt.ifPresent(this.stopwatchModule::resetStopwatch); + apolloPlayerOpt.ifPresent(apolloPlayer -> this.stopwatchModule.resetStopwatch(apolloPlayer, "parkour-stopwatch")); + } + + @Override + public void resetStopwatchesExample(Player viewer) { + Optional apolloPlayerOpt = Apollo.getPlayerManager().getPlayer(viewer.getUniqueId()); + apolloPlayerOpt.ifPresent(this.stopwatchModule::resetStopwatches); + } + + @Override + public void addTimerExample(Player viewer) { + Optional apolloPlayerOpt = Apollo.getPlayerManager().getPlayer(viewer.getUniqueId()); + + apolloPlayerOpt.ifPresent(apolloPlayer -> { + this.stopwatchModule.addTimer(apolloPlayer, Timer.builder() + .id("game-timer") + .name("Countdown") + .duration(Duration.ofSeconds(45)) + .loop(false) + .preventModification(true) + .hideWhenStopped(false) + .displayFormat("mm:ss") + .titleText(Component.text("Time's up!", NamedTextColor.RED)) + .inGameNotification(true) + .textColor(ApolloColors.LIGHT_PURPLE) + .hudPosition(HudPosition.builder() + .x(-10) + .y(30) + .build() + ) + .build()); + }); + } + + @Override + public void removeTimerExample(Player viewer) { + Optional apolloPlayerOpt = Apollo.getPlayerManager().getPlayer(viewer.getUniqueId()); + apolloPlayerOpt.ifPresent(apolloPlayer -> this.stopwatchModule.removeTimer(apolloPlayer, "game-timer")); + } + + @Override + public void startTimerExample(Player viewer) { + Optional apolloPlayerOpt = Apollo.getPlayerManager().getPlayer(viewer.getUniqueId()); + apolloPlayerOpt.ifPresent(apolloPlayer -> this.stopwatchModule.startTimer(apolloPlayer, "game-timer")); + } + + @Override + public void stopTimerExample(Player viewer) { + Optional apolloPlayerOpt = Apollo.getPlayerManager().getPlayer(viewer.getUniqueId()); + apolloPlayerOpt.ifPresent(apolloPlayer -> this.stopwatchModule.stopTimer(apolloPlayer, "game-timer")); + } + + @Override + public void resetTimerExample(Player viewer) { + Optional apolloPlayerOpt = Apollo.getPlayerManager().getPlayer(viewer.getUniqueId()); + apolloPlayerOpt.ifPresent(apolloPlayer -> this.stopwatchModule.resetTimer(apolloPlayer, "game-timer")); + } + + @Override + public void resetTimersExample(Player viewer) { + Optional apolloPlayerOpt = Apollo.getPlayerManager().getPlayer(viewer.getUniqueId()); + apolloPlayerOpt.ifPresent(this.stopwatchModule::resetTimers); } } diff --git a/example/bukkit/common/src/main/java/com/lunarclient/apollo/example/command/StopwatchCommand.java b/example/bukkit/common/src/main/java/com/lunarclient/apollo/example/command/StopwatchCommand.java index a4f081a1..a4bbbc7e 100644 --- a/example/bukkit/common/src/main/java/com/lunarclient/apollo/example/command/StopwatchCommand.java +++ b/example/bukkit/common/src/main/java/com/lunarclient/apollo/example/command/StopwatchCommand.java @@ -42,38 +42,124 @@ public boolean onCommand(@NotNull CommandSender sender, @NotNull Command command Player player = (Player) sender; - if (args.length != 1) { - player.sendMessage("Usage: /stopwatch "); + if (args.length < 2) { + player.sendMessage("Usage: /stopwatch stopwatch "); + player.sendMessage("Usage: /stopwatch timer "); return true; } StopwatchExample stopwatchExample = ApolloExamplePlugin.getInstance().getStopwatchExample(); + String type = args[0].toLowerCase(); + String action = args[1].toLowerCase(); + + switch (type) { + case "stopwatch": { + this.handleStopwatch(player, stopwatchExample, action); + break; + } + + case "timer": { + this.handleTimer(player, stopwatchExample, action); + break; + } + + default: { + player.sendMessage("Usage: /stopwatch stopwatch "); + player.sendMessage("Usage: /stopwatch timer "); + break; + } + } + + return true; + } + + private void handleStopwatch(Player player, StopwatchExample example, String action) { + switch (action) { + case "add": { + example.addStopwatchExample(player); + player.sendMessage("Adding stopwatch..."); + break; + } + + case "remove": { + example.removeStopwatchExample(player); + player.sendMessage("Removing stopwatch..."); + break; + } - switch (args[0].toLowerCase()) { case "start": { - stopwatchExample.startStopwatchExample(player); - player.sendMessage("Starting stopwatch...."); + example.startStopwatchExample(player); + player.sendMessage("Starting stopwatch..."); break; } case "stop": { - stopwatchExample.stopStopwatchExample(player); - player.sendMessage("Stopping stopwatch...."); + example.stopStopwatchExample(player); + player.sendMessage("Stopping stopwatch..."); break; } case "reset": { - stopwatchExample.resetStopwatchExample(player); - player.sendMessage("Resetting stopwatch...."); + example.resetStopwatchExample(player); + player.sendMessage("Resetting stopwatch..."); + break; + } + + case "resetall": { + example.resetStopwatchesExample(player); + player.sendMessage("Resetting all stopwatches..."); break; } default: { - player.sendMessage("Usage: /stopwatch "); + player.sendMessage("Usage: /stopwatch stopwatch "); break; } } + } - return true; + private void handleTimer(Player player, StopwatchExample example, String action) { + switch (action) { + case "add": { + example.addTimerExample(player); + player.sendMessage("Adding timer..."); + break; + } + + case "remove": { + example.removeTimerExample(player); + player.sendMessage("Removing timer..."); + break; + } + + case "start": { + example.startTimerExample(player); + player.sendMessage("Starting timer..."); + break; + } + + case "stop": { + example.stopTimerExample(player); + player.sendMessage("Stopping timer..."); + break; + } + + case "reset": { + example.resetTimerExample(player); + player.sendMessage("Resetting timer..."); + break; + } + + case "resetall": { + example.resetTimersExample(player); + player.sendMessage("Resetting all timers..."); + break; + } + + default: { + player.sendMessage("Usage: /stopwatch timer "); + break; + } + } } } diff --git a/example/bukkit/common/src/main/java/com/lunarclient/apollo/example/module/impl/StopwatchExample.java b/example/bukkit/common/src/main/java/com/lunarclient/apollo/example/module/impl/StopwatchExample.java index 3994bbd4..57d70710 100644 --- a/example/bukkit/common/src/main/java/com/lunarclient/apollo/example/module/impl/StopwatchExample.java +++ b/example/bukkit/common/src/main/java/com/lunarclient/apollo/example/module/impl/StopwatchExample.java @@ -28,10 +28,28 @@ public abstract class StopwatchExample extends ApolloModuleExample { + public abstract void addStopwatchExample(Player viewer); + + public abstract void removeStopwatchExample(Player viewer); + public abstract void startStopwatchExample(Player viewer); public abstract void stopStopwatchExample(Player viewer); public abstract void resetStopwatchExample(Player viewer); + public abstract void resetStopwatchesExample(Player viewer); + + public abstract void addTimerExample(Player viewer); + + public abstract void removeTimerExample(Player viewer); + + public abstract void startTimerExample(Player viewer); + + public abstract void stopTimerExample(Player viewer); + + public abstract void resetTimerExample(Player viewer); + + public abstract void resetTimersExample(Player viewer); + } diff --git a/example/bukkit/json/src/main/java/com/lunarclient/apollo/example/json/module/StopwatchJsonExample.java b/example/bukkit/json/src/main/java/com/lunarclient/apollo/example/json/module/StopwatchJsonExample.java index 96a972ca..33031f2e 100644 --- a/example/bukkit/json/src/main/java/com/lunarclient/apollo/example/json/module/StopwatchJsonExample.java +++ b/example/bukkit/json/src/main/java/com/lunarclient/apollo/example/json/module/StopwatchJsonExample.java @@ -24,16 +24,52 @@ package com.lunarclient.apollo.example.json.module; import com.google.gson.JsonObject; +import com.lunarclient.apollo.example.json.util.AdventureUtil; import com.lunarclient.apollo.example.json.util.JsonPacketUtil; +import com.lunarclient.apollo.example.json.util.JsonUtil; import com.lunarclient.apollo.example.module.impl.StopwatchExample; +import java.awt.Color; +import java.time.Duration; +import net.kyori.adventure.text.Component; +import net.kyori.adventure.text.format.NamedTextColor; import org.bukkit.entity.Player; public class StopwatchJsonExample extends StopwatchExample { + @Override + public void addStopwatchExample(Player viewer) { + JsonObject message = new JsonObject(); + message.addProperty("@type", "type.googleapis.com/lunarclient.apollo.stopwatch.v1.AddStopwatchMessage"); + message.addProperty("id", "parkour-stopwatch"); + message.addProperty("name", "Parkour"); + message.addProperty("reset_on_start", true); + message.addProperty("prevent_modification", true); + message.addProperty("hide_when_stopped", false); + message.addProperty("display_format", "mm:ss"); + message.add("text_color", JsonUtil.createColorObject(new Color(0, 170, 170))); + + JsonObject stopwatchPosition = new JsonObject(); + stopwatchPosition.addProperty("x", -30); + stopwatchPosition.addProperty("y", 30); + message.add("hud_position", stopwatchPosition); + + JsonPacketUtil.sendPacket(viewer, message); + } + + @Override + public void removeStopwatchExample(Player viewer) { + JsonObject message = new JsonObject(); + message.addProperty("@type", "type.googleapis.com/lunarclient.apollo.stopwatch.v1.RemoveStopwatchMessage"); + message.addProperty("id", "parkour-stopwatch"); + + JsonPacketUtil.sendPacket(viewer, message); + } + @Override public void startStopwatchExample(Player viewer) { JsonObject message = new JsonObject(); message.addProperty("@type", "type.googleapis.com/lunarclient.apollo.stopwatch.v1.StartStopwatchMessage"); + message.addProperty("id", "parkour-stopwatch"); JsonPacketUtil.sendPacket(viewer, message); } @@ -42,6 +78,7 @@ public void startStopwatchExample(Player viewer) { public void stopStopwatchExample(Player viewer) { JsonObject message = new JsonObject(); message.addProperty("@type", "type.googleapis.com/lunarclient.apollo.stopwatch.v1.StopStopwatchMessage"); + message.addProperty("id", "parkour-stopwatch"); JsonPacketUtil.sendPacket(viewer, message); } @@ -50,6 +87,84 @@ public void stopStopwatchExample(Player viewer) { public void resetStopwatchExample(Player viewer) { JsonObject message = new JsonObject(); message.addProperty("@type", "type.googleapis.com/lunarclient.apollo.stopwatch.v1.ResetStopwatchMessage"); + message.addProperty("id", "parkour-stopwatch"); + + JsonPacketUtil.sendPacket(viewer, message); + } + + @Override + public void resetStopwatchesExample(Player viewer) { + JsonObject message = new JsonObject(); + message.addProperty("@type", "type.googleapis.com/lunarclient.apollo.stopwatch.v1.ResetStopwatchesMessage"); + + JsonPacketUtil.sendPacket(viewer, message); + } + + @Override + public void addTimerExample(Player viewer) { + JsonObject message = new JsonObject(); + message.addProperty("@type", "type.googleapis.com/lunarclient.apollo.stopwatch.v1.AddTimerMessage"); + message.addProperty("id", "game-timer"); + message.addProperty("name", "Countdown"); + message.addProperty("duration", JsonUtil.createDurationObject(Duration.ofSeconds(45))); + message.addProperty("loop", false); + message.addProperty("prevent_modification", true); + message.addProperty("hide_when_stopped", false); + message.addProperty("display_format", "mm:ss"); + message.addProperty("title_text_adventure_json_lines", AdventureUtil.toJson( + Component.text("Time's up!", NamedTextColor.RED) + )); + message.addProperty("in_game_notification", true); + message.add("text_color", JsonUtil.createColorObject(new Color(255, 85, 255))); + + JsonObject timerPosition = new JsonObject(); + timerPosition.addProperty("x", -10); + timerPosition.addProperty("y", 30); + message.add("hud_position", timerPosition); + + JsonPacketUtil.sendPacket(viewer, message); + } + + @Override + public void removeTimerExample(Player viewer) { + JsonObject message = new JsonObject(); + message.addProperty("@type", "type.googleapis.com/lunarclient.apollo.stopwatch.v1.RemoveTimerMessage"); + message.addProperty("id", "game-timer"); + + JsonPacketUtil.sendPacket(viewer, message); + } + + @Override + public void startTimerExample(Player viewer) { + JsonObject message = new JsonObject(); + message.addProperty("@type", "type.googleapis.com/lunarclient.apollo.stopwatch.v1.StartTimerMessage"); + message.addProperty("id", "game-timer"); + + JsonPacketUtil.sendPacket(viewer, message); + } + + @Override + public void stopTimerExample(Player viewer) { + JsonObject message = new JsonObject(); + message.addProperty("@type", "type.googleapis.com/lunarclient.apollo.stopwatch.v1.StopTimerMessage"); + message.addProperty("id", "game-timer"); + + JsonPacketUtil.sendPacket(viewer, message); + } + + @Override + public void resetTimerExample(Player viewer) { + JsonObject message = new JsonObject(); + message.addProperty("@type", "type.googleapis.com/lunarclient.apollo.stopwatch.v1.ResetTimerMessage"); + message.addProperty("id", "game-timer"); + + JsonPacketUtil.sendPacket(viewer, message); + } + + @Override + public void resetTimersExample(Player viewer) { + JsonObject message = new JsonObject(); + message.addProperty("@type", "type.googleapis.com/lunarclient.apollo.stopwatch.v1.ResetTimersMessage"); JsonPacketUtil.sendPacket(viewer, message); } diff --git a/example/bukkit/proto/src/main/java/com/lunarclient/apollo/example/proto/module/StopwatchProtoExample.java b/example/bukkit/proto/src/main/java/com/lunarclient/apollo/example/proto/module/StopwatchProtoExample.java index 5f8960b5..9f001529 100644 --- a/example/bukkit/proto/src/main/java/com/lunarclient/apollo/example/proto/module/StopwatchProtoExample.java +++ b/example/bukkit/proto/src/main/java/com/lunarclient/apollo/example/proto/module/StopwatchProtoExample.java @@ -24,29 +24,156 @@ package com.lunarclient.apollo.example.proto.module; import com.lunarclient.apollo.example.module.impl.StopwatchExample; +import com.lunarclient.apollo.example.proto.util.AdventureUtil; import com.lunarclient.apollo.example.proto.util.ProtobufPacketUtil; +import com.lunarclient.apollo.example.proto.util.ProtobufUtil; +import com.lunarclient.apollo.hud.v1.HudPosition; +import com.lunarclient.apollo.stopwatch.v1.AddStopwatchMessage; +import com.lunarclient.apollo.stopwatch.v1.AddTimerMessage; +import com.lunarclient.apollo.stopwatch.v1.RemoveStopwatchMessage; +import com.lunarclient.apollo.stopwatch.v1.RemoveTimerMessage; import com.lunarclient.apollo.stopwatch.v1.ResetStopwatchMessage; +import com.lunarclient.apollo.stopwatch.v1.ResetStopwatchesMessage; +import com.lunarclient.apollo.stopwatch.v1.ResetTimerMessage; +import com.lunarclient.apollo.stopwatch.v1.ResetTimersMessage; import com.lunarclient.apollo.stopwatch.v1.StartStopwatchMessage; +import com.lunarclient.apollo.stopwatch.v1.StartTimerMessage; import com.lunarclient.apollo.stopwatch.v1.StopStopwatchMessage; +import com.lunarclient.apollo.stopwatch.v1.StopTimerMessage; +import java.awt.Color; +import java.time.Duration; +import net.kyori.adventure.text.Component; +import net.kyori.adventure.text.format.NamedTextColor; import org.bukkit.entity.Player; public class StopwatchProtoExample extends StopwatchExample { + @Override + public void addStopwatchExample(Player viewer) { + AddStopwatchMessage message = AddStopwatchMessage.newBuilder() + .setId("parkour-stopwatch") + .setName("Parkour") + .setResetOnStart(true) + .setPreventModification(true) + .setHideWhenStopped(false) + .setDisplayFormat("mm:ss") + .setTextColor(ProtobufUtil.createColorProto(new Color(0, 170, 170))) + .setHudPosition(HudPosition.newBuilder() + .setX(-30) + .setY(30) + .build() + ) + .build(); + + ProtobufPacketUtil.sendPacket(viewer, message); + } + + @Override + public void removeStopwatchExample(Player viewer) { + RemoveStopwatchMessage message = RemoveStopwatchMessage.newBuilder() + .setId("parkour-stopwatch") + .build(); + + ProtobufPacketUtil.sendPacket(viewer, message); + } + @Override public void startStopwatchExample(Player viewer) { - StartStopwatchMessage message = StartStopwatchMessage.getDefaultInstance(); + StartStopwatchMessage message = StartStopwatchMessage.newBuilder() + .setId("parkour-stopwatch") + .build(); + ProtobufPacketUtil.sendPacket(viewer, message); } @Override public void stopStopwatchExample(Player viewer) { - StopStopwatchMessage message = StopStopwatchMessage.getDefaultInstance(); + StopStopwatchMessage message = StopStopwatchMessage.newBuilder() + .setId("parkour-stopwatch") + .build(); + ProtobufPacketUtil.sendPacket(viewer, message); } @Override public void resetStopwatchExample(Player viewer) { - ResetStopwatchMessage message = ResetStopwatchMessage.getDefaultInstance(); + ResetStopwatchMessage message = ResetStopwatchMessage.newBuilder() + .setId("parkour-stopwatch") + .build(); + + ProtobufPacketUtil.sendPacket(viewer, message); + } + + @Override + public void resetStopwatchesExample(Player viewer) { + ResetStopwatchesMessage message = ResetStopwatchesMessage.getDefaultInstance(); + ProtobufPacketUtil.sendPacket(viewer, message); + } + + @Override + public void addTimerExample(Player viewer) { + AddTimerMessage message = AddTimerMessage.newBuilder() + .setId("game-timer") + .setName("Countdown") + .setDuration(ProtobufUtil.createDurationProto(Duration.ofSeconds(45))) + .setLoop(false) + .setPreventModification(true) + .setHideWhenStopped(false) + .setDisplayFormat("mm:ss") + .setTitleTextAdventureJsonLines(AdventureUtil.toJson( + Component.text("Time's up!", NamedTextColor.RED) + )) + .setInGameNotification(true) + .setTextColor(ProtobufUtil.createColorProto(new Color(255, 85, 255))) + .setHudPosition(HudPosition.newBuilder() + .setX(-10) + .setY(30) + .build() + ) + .build(); + + ProtobufPacketUtil.sendPacket(viewer, message); + } + + @Override + public void removeTimerExample(Player viewer) { + RemoveTimerMessage message = RemoveTimerMessage.newBuilder() + .setId("game-timer") + .build(); + + ProtobufPacketUtil.sendPacket(viewer, message); + } + + @Override + public void startTimerExample(Player viewer) { + StartTimerMessage message = StartTimerMessage.newBuilder() + .setId("game-timer") + .build(); + + ProtobufPacketUtil.sendPacket(viewer, message); + } + + @Override + public void stopTimerExample(Player viewer) { + StopTimerMessage message = StopTimerMessage.newBuilder() + .setId("game-timer") + .build(); + + ProtobufPacketUtil.sendPacket(viewer, message); + } + + @Override + public void resetTimerExample(Player viewer) { + ResetTimerMessage message = ResetTimerMessage.newBuilder() + .setId("game-timer") + .build(); + + ProtobufPacketUtil.sendPacket(viewer, message); + } + + @Override + public void resetTimersExample(Player viewer) { + ResetTimersMessage message = ResetTimersMessage.getDefaultInstance(); ProtobufPacketUtil.sendPacket(viewer, message); }