From ac08fb6514defbac92876dc70e1ba98f7504ae24 Mon Sep 17 00:00:00 2001 From: Aaron <51387595+AzureAaron@users.noreply.github.com> Date: Mon, 12 Aug 2024 19:28:45 -0400 Subject: Crystals Waypoint WebSocket Enhancements (#917) --- .../skyblock/dwarven/CrystalsLocationsManager.java | 4 ++- .../skyblocker/utils/ws/WsMessageHandler.java | 30 +++++++++++++--------- .../hysky/skyblocker/utils/ws/WsStateManager.java | 9 ++++--- .../message/CrystalsWaypointSubscribeMessage.java | 26 +++++++++++++++++++ .../hysky/skyblocker/utils/ws/message/Message.java | 2 +- 5 files changed, 54 insertions(+), 17 deletions(-) create mode 100644 src/main/java/de/hysky/skyblocker/utils/ws/message/CrystalsWaypointSubscribeMessage.java (limited to 'src/main/java') diff --git a/src/main/java/de/hysky/skyblocker/skyblock/dwarven/CrystalsLocationsManager.java b/src/main/java/de/hysky/skyblocker/skyblock/dwarven/CrystalsLocationsManager.java index 8b8a7737..3ce4cfe0 100644 --- a/src/main/java/de/hysky/skyblocker/skyblock/dwarven/CrystalsLocationsManager.java +++ b/src/main/java/de/hysky/skyblocker/skyblock/dwarven/CrystalsLocationsManager.java @@ -18,6 +18,7 @@ import de.hysky.skyblocker.utils.ws.WsMessageHandler; import de.hysky.skyblocker.utils.ws.Service; import de.hysky.skyblocker.utils.ws.WsStateManager; import de.hysky.skyblocker.utils.ws.message.CrystalsWaypointMessage; +import de.hysky.skyblocker.utils.ws.message.CrystalsWaypointSubscribeMessage; import net.fabricmc.fabric.api.client.command.v2.ClientCommandRegistrationCallback; import net.fabricmc.fabric.api.client.command.v2.FabricClientCommandSource; import net.fabricmc.fabric.api.client.message.v1.ClientReceiveMessageEvents; @@ -327,6 +328,7 @@ public class CrystalsLocationsManager { MiningLocationLabel waypoint = new MiningLocationLabel(category, pos); waypointsSent2Socket.add(category); activeWaypoints.put(category.name(), waypoint); + CLIENT.player.sendMessage(Constants.PREFIX.get().append(Text.translatable("skyblocker.webSocket.receivedCrystalsWaypoint", Text.literal(category.getName()).withColor(category.getColor())))); } protected static void addCustomWaypoint(String waypointName, BlockPos pos) { @@ -362,7 +364,7 @@ public class CrystalsLocationsManager { private static void onLocationChange(Location newLocation) { if (newLocation == Location.CRYSTAL_HOLLOWS) { - WsStateManager.subscribe(Service.CRYSTAL_WAYPOINTS); + WsStateManager.subscribe(Service.CRYSTAL_WAYPOINTS, Optional.of(CrystalsWaypointSubscribeMessage.create(CLIENT.world))); } } diff --git a/src/main/java/de/hysky/skyblocker/utils/ws/WsMessageHandler.java b/src/main/java/de/hysky/skyblocker/utils/ws/WsMessageHandler.java index d85ccbb8..f4aadbc4 100644 --- a/src/main/java/de/hysky/skyblocker/utils/ws/WsMessageHandler.java +++ b/src/main/java/de/hysky/skyblocker/utils/ws/WsMessageHandler.java @@ -23,23 +23,15 @@ public class WsMessageHandler { /** * Used for sending messages to the current channel/server */ - @SuppressWarnings("unchecked") public static void sendMessage(Service service, Message> message) { - try { - Codec> codec = (Codec>) message.getCodec(); - Dynamic dynamic = new Dynamic<>(JsonOps.INSTANCE, codec.encodeStart(JsonOps.INSTANCE, message).getOrThrow()); - - send(Type.PUBLISH, service, Utils.getServer(), Optional.of(dynamic)); - } catch (Exception e) { - LOGGER.info("[Skyblocker WebSocket Message Handler] Failed to encode message! Message: {}", message, e); - } + send(Type.PUBLISH, service, Utils.getServer(), Optional.of(encodeMessage(message))); } /** - * Useful for sending simple state updates + * Useful for sending simple state updates with an optional message */ - static void sendSimple(Type type, Service service, String serverId) { - send(type, service, serverId, Optional.empty()); + static void sendSimple(Type type, Service service, String serverId, Optional>> message) { + send(type, service, serverId, message.isPresent() ? Optional.of(encodeMessage(message.get())) : Optional.empty()); } private static void send(Type type, Service service, String serverId, Optional> message) { @@ -53,6 +45,20 @@ public class WsMessageHandler { } } + private static Dynamic encodeMessage(Message> message) { + try { + @SuppressWarnings("unchecked") + Codec> codec = (Codec>) message.getCodec(); + Dynamic dynamic = new Dynamic<>(JsonOps.INSTANCE, codec.encodeStart(JsonOps.INSTANCE, message).getOrThrow()); + + return dynamic; + } catch (Exception e) { + LOGGER.info("[Skyblocker WebSocket Message Handler] Failed to encode message! Message: {}", message, e); + } + + return new Dynamic<>(JsonOps.INSTANCE); + } + static void handleMessage(String message) { try { JsonObject payloadEncoded = JsonParser.parseString(message).getAsJsonObject(); diff --git a/src/main/java/de/hysky/skyblocker/utils/ws/WsStateManager.java b/src/main/java/de/hysky/skyblocker/utils/ws/WsStateManager.java index 6715c1f6..e3d7bec5 100644 --- a/src/main/java/de/hysky/skyblocker/utils/ws/WsStateManager.java +++ b/src/main/java/de/hysky/skyblocker/utils/ws/WsStateManager.java @@ -1,7 +1,10 @@ package de.hysky.skyblocker.utils.ws; +import java.util.Optional; + import de.hysky.skyblocker.events.SkyblockEvents; import de.hysky.skyblocker.utils.Utils; +import de.hysky.skyblocker.utils.ws.message.Message; import it.unimi.dsi.fastutil.objects.ReferenceOpenHashSet; import it.unimi.dsi.fastutil.objects.ReferenceSet; import net.fabricmc.fabric.api.client.networking.v1.ClientPlayConnectionEvents; @@ -18,7 +21,7 @@ public class WsStateManager { private static void reset() { if (!lastServerId.isEmpty()) { for (Service service : SUBSCRIBED_SERVICES) { - WsMessageHandler.sendSimple(Type.UNSUBSCRIBE, service, lastServerId); + WsMessageHandler.sendSimple(Type.UNSUBSCRIBE, service, lastServerId, Optional.empty()); } lastServerId = ""; @@ -29,9 +32,9 @@ public class WsStateManager { * @implNote The service must be registered after the {@link ClientPlayConnectionEvents#JOIN} event fires, one good * place is inside of the {@link SkyblockEvents#LOCATION_CHANGE} event. */ - public static void subscribe(Service service) { + public static void subscribe(Service service, Optional>> message) { SUBSCRIBED_SERVICES.add(service); - WsMessageHandler.sendSimple(Type.SUBSCRIBE, service, Utils.getServer()); + WsMessageHandler.sendSimple(Type.SUBSCRIBE, service, Utils.getServer(), message); //Update tracked server id lastServerId = Utils.getServer(); diff --git a/src/main/java/de/hysky/skyblocker/utils/ws/message/CrystalsWaypointSubscribeMessage.java b/src/main/java/de/hysky/skyblocker/utils/ws/message/CrystalsWaypointSubscribeMessage.java new file mode 100644 index 00000000..ee63eced --- /dev/null +++ b/src/main/java/de/hysky/skyblocker/utils/ws/message/CrystalsWaypointSubscribeMessage.java @@ -0,0 +1,26 @@ +package de.hysky.skyblocker.utils.ws.message; + +import com.mojang.serialization.Codec; +import com.mojang.serialization.codecs.RecordCodecBuilder; + +import net.minecraft.client.world.ClientWorld; + +public record CrystalsWaypointSubscribeMessage(long timestamp) implements Message { + private static final Codec CODEC = RecordCodecBuilder.create(instance -> instance.group( + Codec.LONG.fieldOf("timestamp").forGetter(CrystalsWaypointSubscribeMessage::timestamp)) + .apply(instance, CrystalsWaypointSubscribeMessage::new)); + /** 26 Minecraft days in ticks */ + private static final int TWENTY_SIX_DAYS = 24000 * 26; + + public static CrystalsWaypointSubscribeMessage create(ClientWorld world) { + //Current timestamp as seconds + ((26 mc days - mc time) / ticks per second) + long closeTime = (System.currentTimeMillis() / 1000L) + ((TWENTY_SIX_DAYS - world.getTimeOfDay()) / 20L); + + return new CrystalsWaypointSubscribeMessage(closeTime); + } + + @Override + public Codec getCodec() { + return CODEC; + } +} diff --git a/src/main/java/de/hysky/skyblocker/utils/ws/message/Message.java b/src/main/java/de/hysky/skyblocker/utils/ws/message/Message.java index 2d145ca4..13f1309a 100644 --- a/src/main/java/de/hysky/skyblocker/utils/ws/message/Message.java +++ b/src/main/java/de/hysky/skyblocker/utils/ws/message/Message.java @@ -2,7 +2,7 @@ package de.hysky.skyblocker.utils.ws.message; import com.mojang.serialization.Codec; -public sealed interface Message> permits CrystalsWaypointMessage { +public sealed interface Message> permits CrystalsWaypointMessage, CrystalsWaypointSubscribeMessage { Codec getCodec(); } -- cgit