diff options
| author | Eryk Ruta <70776766+kingstefan26@users.noreply.github.com> | 2022-11-01 15:51:30 +0100 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2022-11-01 23:51:30 +0900 |
| commit | 292fbd05e13271ca3ad99ebe00ae4302e04848f3 (patch) | |
| tree | 2a7aeb12ab95ff688479a4727f76e3e4152c30b5 /src/main/java/kr/syeyoung/dungeonsguide/mod/stomp | |
| parent | dd7a4209752715db544b2fef804da9762c532cdc (diff) | |
| download | Skyblock-Dungeons-Guide-292fbd05e13271ca3ad99ebe00ae4302e04848f3.tar.gz Skyblock-Dungeons-Guide-292fbd05e13271ca3ad99ebe00ae4302e04848f3.tar.bz2 Skyblock-Dungeons-Guide-292fbd05e13271ca3ad99ebe00ae4302e04848f3.zip | |
3rd time is the charm (#70)
* Updated some dependencies, used my crusty skytils forgegradle fork + removed the IRRELEVANT hytils fixes. generally made the thing build
* made the logs less annoying
* temp fix so it doesn't throw an exception
* FAT REFACTOR
General refactor on
Authenticator.java
DungeonsGuide.java
Main.java
removed unnecessary imports where not needed
to be removed DGInterface.java (no real reason to exist)
in DungeonsGuide.java made the retry stomp a singe-thread executor, so it doesn't leak when offline
added an "offline mode" so it doesn't just error when server down
TODO: move auth to DungeonsGuide.java and make it retry when network down on launch
* New auth implementation that should replace the old one:
does all the things the old one did
removed progressBar cuz it would make the impl 3x more complicated in the name of a splash screen
added a token changed event (so now it supports re-logging with a different account)
code is (should) be more readable / extensible
TODO: surgically replace Authenticator.java with new impl AND support re-logging
* Made the chat processor logger name less obnoxious
* implemented my implementation of an implementation of auth
can and is very buggy, essentially the loading of the remote classes but the mod works so idk
TODO: MAKE STOMP NOT DO STUFF TILL STOMPCONNECTED IS EMITTED
* fix for stomp client null bc forge events not going tru on pre-init
TODO: make work and test the web loadable classes, then make all the stuff that relies on stomp not throw exceptions when stomp is not connected
* move the create auth method into AuthProvider interface,
so we don't clutter AuthManager with implementation details
* Decouple AuthProviderUtil and DgAuth,
move some stuff around and make it more readable
* moved AuthUtil to make more sense
* de-clutter the tree a little bit
* Inline StompClientStatus.java / refactor
* inline the useless interface
* refactoringgg
* fix ahUtils exeption spam
* small StompClient refactor
* fix GLCursors exeption spam + logger
* make sure we are authenticated when downloading resources
* new .destination("value") instead of .header("destination", "value")
* StompMessageHandler -> StompMessageSubscription
* Introduced StompManager
* fix dungeon map not showing ppl heads
* ehhh
* wip (commit cuz im chekig out)
* fix player profile not never loading in chat
* remove this specific line
* fix player profile not never loading in chat
* cut out hychat like a cancer
* ApiFetchur now caches whole players not single profiles,
added a switch profile button in gui
* ugh git
* Revert "cut out hychat like a cancer"
This reverts commit 2ee11afa
* ugh git x2
* I tried, good luck maintaining this
* forgot to uncomment hychat fix
* make my new party ready work and look ok
* change the look and add some "somewhere" locations
* make stomp connection "null safe"
* i hate git
* introduce callbacks on parameter change for cleaner code
add one example
* impl new system,
half way done
* now shows which profile is now selected
put button on top
a lil refactor
* fix player profile sometimes not loading
* add players knowing who is using dg (try to)
* announcing that we are a dg user will get reworked in the future
* update deps
* make it not spam logs
* sanity check for premium features so it doesn't 403
* add YoMamaOutdated that checks if you are using outdated dg
* hychat?? anyone
* try catch in FeatureRegistry
* added Ether transmission ability
* chat shredder borken, disabled for now
* party deserves its own folder
* dungeon stuff in dungeon folder
* events folders moved
* fix score data collection hanging forever if stomp is not connected
* fix stomp never connecting
* re-add the removed
* fix wonky rendering
* server side implementation is not ready, canning this for a future release
* attempt to fix heads loading on main thread
* discord
* me when sonar lint
* new consumer based stomp subscriptions
* replace old with new subscriptions
* remove the remains of StompSubscription and replace CloseListener with a forge event
* StompSubscription is now a functional interface
* remove unnecessary event message chains,
feature logic should be in the feature
* fix events being set up wrongly
* Revert "fix events being set up wrongly"
This reverts commit e6ea7efa557a5f5c8a3ea33be998717bc024b8cb.
* Revert "remove unnecessary event message chains,"
This reverts commit 96f508bae85b33cdcef6be19226c00fc52a1439b.
* fix stomp client sending payload object instead of the actual payload
* fix null pointer on empty party
* fix players with cosmetics name being white in tab
* added message when not connected to dg
changed YoMamaOutdated to use CloudFlare workers
added client sided message queue
* the mod doesn't init when outdated
* mcmod.info
* dont busy wait in authmenager
* test pepole crusty tests
* chill out the authmanager
* name the thread pool in auth manager
* clear most compiler warnings
* make outdated check allow to play without the mod initialized
* make first startup VERY noticeable, move config creation to main
* major dungeon package refactor
* refactor checkpoint
* refactor checkpoint #1
* final refactor checkpoint #2
* remove the player if from version check, made the version check not nesssery for playing
Signed-off-by: kingstefan26 <70776766+kingstefan26@users.noreply.github.com>
* remove trap room fix that didnt fix anything
Signed-off-by: kingstefan26 <70776766+kingstefan26@users.noreply.github.com>
* make secret beacons optional
Signed-off-by: kingstefan26 <70776766+kingstefan26@users.noreply.github.com>
* make the checkmarks on map align with the rest of everyone
Signed-off-by: kingstefan26 <70776766+kingstefan26@users.noreply.github.com>
* removed debug function
Signed-off-by: kingstefan26 <70776766+kingstefan26@users.noreply.github.com>
* move the menus to make more sense + make destination text on secrets optional
Signed-off-by: kingstefan26 <70776766+kingstefan26@users.noreply.github.com>
* improve dungeonMap performance by ~90%
temporarly disabled 9 slot map player location due to bugs
fix DungeonContext not getting player from ScoreBoard
Signed-off-by: kingstefan26 <70776766+kingstefan26@users.noreply.github.com>
* add epic countdown on dungeon start (still wip)
Signed-off-by: kingstefan26 <70776766+kingstefan26@users.noreply.github.com>
* added a option to cache blockstaes
Signed-off-by: kingstefan26 <70776766+kingstefan26@users.noreply.github.com>
* added TabListUtil
Signed-off-by: kingstefan26 <70776766+kingstefan26@users.noreply.github.com>
* fixed epic countdown
Signed-off-by: kingstefan26 <70776766+kingstefan26@users.noreply.github.com>
* (i want to sleep) made all the dungeon room detection async
TODO: fix ol the bugs i created by doing that
Signed-off-by: kingstefan26 <70776766+kingstefan26@users.noreply.github.com>
* stuff still broken but almost playable, unlike last commit
Signed-off-by: kingstefan26 <70776766+kingstefan26@users.noreply.github.com>
* upload build jar to discord
Signed-off-by: kingstefan26 <70776766+kingstefan26@users.noreply.github.com>
* cache the deps for the love of god
Signed-off-by: kingstefan26 <70776766+kingstefan26@users.noreply.github.com>
* who needs linux and 32bit windows anyway
Signed-off-by: kingstefan26 <70776766+kingstefan26@users.noreply.github.com>
* only upload to discord on beta branch
Signed-off-by: kingstefan26 <70776766+kingstefan26@users.noreply.github.com>
* added "kick" when a member joins party
Signed-off-by: kingstefan26 <70776766+kingstefan26@users.noreply.github.com>
* move stuff that sends chat to player into a separate class
Signed-off-by: kingstefan26 <70776766+kingstefan26@users.noreply.github.com>
* use our chat queue instead of calling `thePlayer.addChatMessage` to proxy ourselves from 1.8 code
Signed-off-by: kingstefan26 <70776766+kingstefan26@users.noreply.github.com>
* Added and implemented MortDetector2000.java
Signed-off-by: kingstefan26 <70776766+kingstefan26@users.noreply.github.com>
* extract duplicate + make more readable
Signed-off-by: kingstefan26 <70776766+kingstefan26@users.noreply.github.com>
* added dummy support in FeatureDebugTrap
Signed-off-by: kingstefan26 <70776766+kingstefan26@users.noreply.github.com>
* gradle now puts version in mcmod.info
Signed-off-by: kingstefan26 <70776766+kingstefan26@users.noreply.github.com>
* remove side effects from DgAuth.java
Signed-off-by: kingstefan26 <70776766+kingstefan26@users.noreply.github.com>
* move debug commands into debug CommandDgDebug.java
Signed-off-by: kingstefan26 <70776766+kingstefan26@users.noreply.github.com>
* fix key being wrong
Signed-off-by: kingstefan26 <70776766+kingstefan26@users.noreply.github.com>
* move epic countdown to dungeon huds, clean up
Signed-off-by: kingstefan26 <70776766+kingstefan26@users.noreply.github.com>
* Revert "who needs linux and 32bit windows anyway"
This reverts commit 0f3c2d544a70fc799cd3215dad5e997c0c8b6c06.
* make FeatureRegistry not static initialise to get rid of "ClassNotDefined" errors
Signed-off-by: kingstefan26 <70776766+kingstefan26@users.noreply.github.com>
* null check on Exception since it threw NullPointers
Signed-off-by: kingstefan26 <70776766+kingstefan26@users.noreply.github.com>
* finish up progress bar in DungeonsGuide.java
Signed-off-by: kingstefan26 <70776766+kingstefan26@users.noreply.github.com>
* warn about null features
Signed-off-by: kingstefan26 <70776766+kingstefan26@users.noreply.github.com>
* move stuff around in SkyblockStatus, move the stuff that updates status into SkyblockStatus from DungeonListener
Signed-off-by: kingstefan26 <70776766+kingstefan26@users.noreply.github.com>
* rename DungeonGodObject.java to DungeonFacade.java
Signed-off-by: kingstefan26 <70776766+kingstefan26@users.noreply.github.com>
* add cleanChat clause in FeatureEpicCountdown
Signed-off-by: kingstefan26 <70776766+kingstefan26@users.noreply.github.com>
* implement getPreRequisites and isComplete in ActionBreakWithSuperBoom
Signed-off-by: kingstefan26 <70776766+kingstefan26@users.noreply.github.com>
* clean up FeatureParameter
Signed-off-by: kingstefan26 <70776766+kingstefan26@users.noreply.github.com>
* eliminate possible state inconsistency in DungeonListener
Signed-off-by: kingstefan26 <70776766+kingstefan26@users.noreply.github.com>
* move percentage from DungeonFacade to DungeonContext
Signed-off-by: kingstefan26 <70776766+kingstefan26@users.noreply.github.com>
* move `purge` and `partymax` back into CommandDungeonsGuide
Signed-off-by: kingstefan26 <70776766+kingstefan26@users.noreply.github.com>
* stop repeating ReceiveChatQueue in ChatTransmitter
Signed-off-by: kingstefan26 <70776766+kingstefan26@users.noreply.github.com>
* Clean up DungeonsGuide
Signed-off-by: kingstefan26 <70776766+kingstefan26@users.noreply.github.com>
* move `sendDebugChat` to `ChatTransmitter.java`
Signed-off-by: kingstefan26 <70776766+kingstefan26@users.noreply.github.com>
* change CommandDgDebug into a `else if` from an `switch` because some bigot decided its better
Signed-off-by: kingstefan26 <70776766+kingstefan26@users.noreply.github.com>
* duplicate code since it currently doesn't make sense, to be reworked
Signed-off-by: kingstefan26 <70776766+kingstefan26@users.noreply.github.com>
* fix typo
Signed-off-by: kingstefan26 <70776766+kingstefan26@users.noreply.github.com>
* remove the trycatch so we fail fast
Signed-off-by: kingstefan26 <70776766+kingstefan26@users.noreply.github.com>
* fix null pointer when trying to get fontRenderer before minecraft is initialised
Signed-off-by: kingstefan26 <70776766+kingstefan26@users.noreply.github.com>
* broken checkpoint 0
Signed-off-by: kingstefan26 <70776766+kingstefan26@users.noreply.github.com>
* broken checkpoint 1
Signed-off-by: kingstefan26 <70776766+kingstefan26@users.noreply.github.com>
* Revert "broken checkpoint 1"
This reverts commit 64985e6287c7b5650b509668e42b9803e25c419c.
* Revert "broken checkpoint 0"
This reverts commit 5f62e1345d9c8e7f66f1e5792004a05027913d92.
* Revert "fix null pointer when trying to get fontRenderer before minecraft is initialised"
This reverts commit 57d92a78d31c410f699b58c8995c94055d57e2a4.
* Revert "remove the trycatch so we fail fast"
This reverts commit 12772255ed575e411fb99edf37ec16d0e5f42924.
* Revert "fix typo"
This reverts commit aa96cc2436d3ead42d53ead78f3334fac5100713.
* Revert "duplicate code since it currently doesn't make sense, to be reworked"
This reverts commit 6d71b88e3102d23bcfd90d85e8996327776fd52f.
* Revert "change CommandDgDebug into a `else if` from an `switch` because some bigot decided its better"
This reverts commit ffea84d9b5fd4adbe034a88249bc920eafa7c53a.
* Revert "move `sendDebugChat` to `ChatTransmitter.java`"
This reverts commit 5b8b2e22fff33768134a01c15c7650100ebb9257.
* Revert "Clean up DungeonsGuide"
This reverts commit 2069ad3ebc4344eb1e778954dc1d8f6c9303de69.
* fix typo
Signed-off-by: kingstefan26 <70776766+kingstefan26@users.noreply.github.com>
(cherry picked from commit aa96cc2436d3ead42d53ead78f3334fac5100713)
* duplicate code since it currently doesn't make sense, to be reworked
Signed-off-by: kingstefan26 <70776766+kingstefan26@users.noreply.github.com>
(cherry picked from commit 6d71b88e3102d23bcfd90d85e8996327776fd52f)
* change CommandDgDebug into a `else if` from an `switch` because some bigot decided its better
Signed-off-by: kingstefan26 <70776766+kingstefan26@users.noreply.github.com>
(cherry picked from commit ffea84d9b5fd4adbe034a88249bc920eafa7c53a)
* move debug chat into ChatTransmitter
Signed-off-by: kingstefan26 <70776766+kingstefan26@users.noreply.github.com>
* null pointer in SkyblockStatus bc context was not initialised yet
Signed-off-by: kingstefan26 <70776766+kingstefan26@users.noreply.github.com>
* move dungeon starting door detection up the tree since it was a duplicate in both children, inline MortDetector2000
Signed-off-by: kingstefan26 <70776766+kingstefan26@users.noreply.github.com>
* move dungeon name to DungeonContext
Signed-off-by: kingstefan26 <70776766+kingstefan26@users.noreply.github.com>
* clean up Main
Signed-off-by: kingstefan26 <70776766+kingstefan26@users.noreply.github.com>
* separate the "loader" and "mod"
Signed-off-by: kingstefan26 <70776766+kingstefan26@users.noreply.github.com>
* separate DungeonsGuide and Main even more
Signed-off-by: kingstefan26 <70776766+kingstefan26@users.noreply.github.com>
* change singleton implementation of DungeonsGuide
Signed-off-by: kingstefan26 <70776766+kingstefan26@users.noreply.github.com>
* move classes since their paths are hardcoded into roomdatas
Signed-off-by: kingstefan26 <70776766+kingstefan26@users.noreply.github.com>
* create CatacombsDataProvider.java and implement it
Signed-off-by: kingstefan26 <70776766+kingstefan26@users.noreply.github.com>
* remove unnecessary `DungeonsGuide.getDungeonsGuide();` (IntelliJ refactor bug)
Signed-off-by: kingstefan26 <70776766+kingstefan26@users.noreply.github.com>
* move `help` text in commands
Signed-off-by: kingstefan26 <70776766+kingstefan26@users.noreply.github.com>
* a certain someone hates switch statements
Signed-off-by: kingstefan26 <70776766+kingstefan26@users.noreply.github.com>
* remove my version check, since we have to wait for out lord and savior to make his own
Signed-off-by: kingstefan26 <70776766+kingstefan26@users.noreply.github.com>
* make `Main` and `DungeonsGuide` compatible with supported jar classloading
Signed-off-by: kingstefan26 <70776766+kingstefan26@users.noreply.github.com>
* make the beta upload action run on push
since it didnt get the secret on pull request and failed anyway,
TODO: make the jar name not hardcoded
Signed-off-by: kingstefan26 <70776766+kingstefan26@users.noreply.github.com>
* upload all jar
Signed-off-by: kingstefan26 <70776766+kingstefan26@users.noreply.github.com>
Signed-off-by: kingstefan26 <70776766+kingstefan26@users.noreply.github.com>
Co-authored-by: syeyoung <42869671+cyoung06@users.noreply.github.com>
Diffstat (limited to 'src/main/java/kr/syeyoung/dungeonsguide/mod/stomp')
7 files changed, 413 insertions, 0 deletions
diff --git a/src/main/java/kr/syeyoung/dungeonsguide/mod/stomp/FailedWebSocketConnection.java b/src/main/java/kr/syeyoung/dungeonsguide/mod/stomp/FailedWebSocketConnection.java new file mode 100644 index 00000000..15f79dde --- /dev/null +++ b/src/main/java/kr/syeyoung/dungeonsguide/mod/stomp/FailedWebSocketConnection.java @@ -0,0 +1,7 @@ +package kr.syeyoung.dungeonsguide.mod.stomp; + +public class FailedWebSocketConnection extends RuntimeException{ + public FailedWebSocketConnection(String message) { + super(message); + } +} diff --git a/src/main/java/kr/syeyoung/dungeonsguide/mod/stomp/StompClient.java b/src/main/java/kr/syeyoung/dungeonsguide/mod/stomp/StompClient.java new file mode 100644 index 00000000..84705a1d --- /dev/null +++ b/src/main/java/kr/syeyoung/dungeonsguide/mod/stomp/StompClient.java @@ -0,0 +1,192 @@ +/* + * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod + * Copyright (C) 2021 cyoung06 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +package kr.syeyoung.dungeonsguide.mod.stomp; + +import lombok.Getter; +import net.minecraftforge.common.MinecraftForge; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; +import org.java_websocket.client.WebSocketClient; +import org.java_websocket.handshake.ServerHandshake; + +import java.net.URI; +import java.util.HashMap; +import java.util.Map; +import java.util.concurrent.Executors; +import java.util.concurrent.ScheduledExecutorService; +import java.util.concurrent.ScheduledFuture; +import java.util.concurrent.TimeUnit; + +public class StompClient extends WebSocketClient { + + Logger logger = LogManager.getLogger("StompClient"); + public StompClient(URI serverUri, final String token) throws InterruptedException { + super(serverUri); + + + addHeader("Authorization", token); + + logger.info("connecting websocket"); + if (!connectBlocking()) { + throw new FailedWebSocketConnection("Cant connect to ws"); + } + + logger.info("connected, stomp handshake"); + while(this.stompClientStatus == StompClientStatus.CONNECTING); + logger.info("fully connected"); + } + + + @Getter + private volatile StompClientStatus stompClientStatus = StompClientStatus.CONNECTING; + + @Getter + private StompPayload errorPayload; + + private ScheduledFuture heartbeat = null; + + private static final ScheduledExecutorService ex = Executors.newScheduledThreadPool(1); + @Override + public void onOpen(ServerHandshake handshakedata) { + send(new StompPayload().method(StompHeader.CONNECT) + .header("accept-version","1.2") + .header("heart-beat", "30000,30000") + .header("host",uri.getHost()).getBuilt() + ); + } + + @Override + public void onMessage(String message) { + try { + StompPayload payload = StompPayload.parse(message); + + switch (payload.method()){ + case SEND: + case SUBSCRIBE: + case UNSUBSCRIBE: + case BEGIN: + case COMMIT: + case ABORT: + case ACK: + case NACK: + case DISCONNECT: + case STOMP: + break; + case CONNECTED: + stompClientStatus = StompClientStatus.CONNECTED; + + String serverHeartbeat = payload.headers().get("heart-beat"); + if (serverHeartbeat != null) { + int heartbeatMS = 30; + this.heartbeat = ex.scheduleAtFixedRate(() -> send("\n"), heartbeatMS-1, heartbeatMS-1, TimeUnit.SECONDS); + } + + break; + case MESSAGE: + String subscriptionName = payload.headers().get("subscription"); + int subscriptionId = Integer.parseInt(subscriptionName); + StompSubscription listener = stompSubscriptionMap.get(subscriptionId); + + listener.process(this, payload.payload()); + + break; + case RECEIPT: + String receiptId = payload.headers().get("receipt-id"); + StompPayload payload1 = receiptMap.remove(Integer.parseInt(receiptId)); + if (payload1.method() == StompHeader.DISCONNECT) { + stompClientStatus = StompClientStatus.DISCONNECTED; + close(); + } + break; + case ERROR: + errorPayload = payload; + stompClientStatus = StompClientStatus.ERROR; + this.close(); + break; + + } + } catch (Exception e) { + e.printStackTrace(); + } + } + + @Override + public void onClose(int code, String reason, boolean remote) { + if (heartbeat != null) heartbeat.cancel(true); + + MinecraftForge.EVENT_BUS.post(new StompDiedEvent(code, reason, remote)); + + } + + @Override + public void onError(Exception ex) { + if(ex != null){ + ex.printStackTrace(); + } + } + + + private final Map<Integer, StompSubscription> stompSubscriptionMap = new HashMap<>(); + private final Map<Integer, StompPayload> receiptMap = new HashMap<>(); + + private int idIncrement = 0; + + private void makeSureStompIsConnected() { + if (stompClientStatus != StompClientStatus.CONNECTED) throw new IllegalStateException("not connected"); + } + + public void sendfake(StompPayload payload) { + makeSureStompIsConnected(); + payload.method(StompHeader.SEND); + if (payload.headers().get("receipt") != null) + receiptMap.put(Integer.parseInt(payload.headers().get("receipt")), payload); + send(payload.getBuilt()); + } + + public void subscribe(String destination, StompSubscription listener) { + makeSureStompIsConnected(); + int id = ++idIncrement; + + send(new StompPayload() + .method(StompHeader.SUBSCRIBE) + .header("id", String.valueOf(id)) + .destination(destination) + .header("ack", "auto") + .getBuilt() + ); + + stompSubscriptionMap.put(id, listener); + } + + + public void disconnect() { + makeSureStompIsConnected(); + stompClientStatus =StompClientStatus.DISCONNECTING; + + StompPayload stompPayload = new StompPayload().method(StompHeader.DISCONNECT).header("receipt", String.valueOf(++idIncrement)); + + send(stompPayload.getBuilt()); + receiptMap.put(idIncrement, stompPayload); + } + + + public enum StompClientStatus { + CONNECTING, CONNECTED, ERROR, DISCONNECTING, DISCONNECTED + } +} diff --git a/src/main/java/kr/syeyoung/dungeonsguide/mod/stomp/StompDiedEvent.java b/src/main/java/kr/syeyoung/dungeonsguide/mod/stomp/StompDiedEvent.java new file mode 100644 index 00000000..33913424 --- /dev/null +++ b/src/main/java/kr/syeyoung/dungeonsguide/mod/stomp/StompDiedEvent.java @@ -0,0 +1,15 @@ +package kr.syeyoung.dungeonsguide.mod.stomp; + +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.EqualsAndHashCode; +import net.minecraftforge.fml.common.eventhandler.Event; + +@Data +@EqualsAndHashCode(callSuper=false) +@AllArgsConstructor +public class StompDiedEvent extends Event { + int code; + String reason; + boolean remote; +} diff --git a/src/main/java/kr/syeyoung/dungeonsguide/mod/stomp/StompHeader.java b/src/main/java/kr/syeyoung/dungeonsguide/mod/stomp/StompHeader.java new file mode 100644 index 00000000..7755d8a6 --- /dev/null +++ b/src/main/java/kr/syeyoung/dungeonsguide/mod/stomp/StompHeader.java @@ -0,0 +1,24 @@ +/* + * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod + * Copyright (C) 2021 cyoung06 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +package kr.syeyoung.dungeonsguide.mod.stomp; + + +public enum StompHeader { + SEND, SUBSCRIBE, UNSUBSCRIBE, BEGIN, COMMIT, ABORT, ACK, NACK, DISCONNECT, CONNECT, STOMP, CONNECTED, MESSAGE, RECEIPT, ERROR +} diff --git a/src/main/java/kr/syeyoung/dungeonsguide/mod/stomp/StompManager.java b/src/main/java/kr/syeyoung/dungeonsguide/mod/stomp/StompManager.java new file mode 100644 index 00000000..31b3b961 --- /dev/null +++ b/src/main/java/kr/syeyoung/dungeonsguide/mod/stomp/StompManager.java @@ -0,0 +1,73 @@ +package kr.syeyoung.dungeonsguide.mod.stomp; + +import com.google.common.base.Throwables; +import kr.syeyoung.dungeonsguide.auth.AuthManager; +import kr.syeyoung.dungeonsguide.mod.events.impl.StompConnectedEvent; +import net.minecraftforge.common.MinecraftForge; +import net.minecraftforge.fml.common.eventhandler.SubscribeEvent; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; + +import java.net.URI; +import java.util.concurrent.Executors; +import java.util.concurrent.ScheduledExecutorService; +import java.util.concurrent.TimeUnit; + +public class StompManager { + Logger logger = LogManager.getLogger("StompManager"); + public static final String STOMP_URL = "wss://dungeons.guide/ws"; + // private String stompURL = "ws://localhost/ws"; + static StompManager instance; + + public static StompManager getInstance() { + if (instance == null) { + instance = new StompManager(); + MinecraftForge.EVENT_BUS.register(instance); + } + return instance; + } + + public void init() { + connectStomp(); + } + + private StompClient stompConnection; + + + public boolean isStompConnected(){ + if(stompConnection != null && stompConnection.getStompClientStatus() == StompClient.StompClientStatus.CONNECTED) return true; + return false; + } + + public void send(StompPayload payload){ + if(stompConnection != null){ + stompConnection.sendfake(payload); + } else { + logger.error("OOPS STOMP CONNECTION IS NULL AND SOMEONE TRIED TO SEND SOMETHING THIS SHOULD NOT HAPPEN"); + } + } + + ScheduledExecutorService ex = Executors.newSingleThreadScheduledExecutor(); + + @SubscribeEvent + public void onStompDied(StompDiedEvent event) { + logger.info("Stomp Connection closed, trying to reconnect - {} - {}", event.reason, event.code); + connectStomp(); + } + + public void connectStomp() { + ex.schedule(() -> { + if (AuthManager.getInstance().getToken() == null) return; + try { + if (stompConnection != null) { + stompConnection.disconnect(); + } + stompConnection = new StompClient(new URI(StompManager.STOMP_URL), AuthManager.getInstance().getToken()); + MinecraftForge.EVENT_BUS.post(new StompConnectedEvent(stompConnection)); + } catch (Exception e) { + logger.error("Failed to connect to Stomp with message: {}", String.valueOf(Throwables.getRootCause(e))); + } + + }, 5L, TimeUnit.SECONDS); + } +} diff --git a/src/main/java/kr/syeyoung/dungeonsguide/mod/stomp/StompPayload.java b/src/main/java/kr/syeyoung/dungeonsguide/mod/stomp/StompPayload.java new file mode 100644 index 00000000..8bfb8543 --- /dev/null +++ b/src/main/java/kr/syeyoung/dungeonsguide/mod/stomp/StompPayload.java @@ -0,0 +1,96 @@ +/* + * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod + * Copyright (C) 2021 cyoung06 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +package kr.syeyoung.dungeonsguide.mod.stomp; + +import kr.syeyoung.dungeonsguide.mod.features.FeatureRegistry; +import lombok.Data; +import lombok.experimental.Accessors; + +import java.util.*; + +@Data +@Accessors(chain = true, fluent = true) +public class StompPayload { + private StompHeader method; + private Map<String, String> headers = new HashMap<>(); + private String payload; + + public StompPayload header(String key, String value) { + headers.put(key, value); + return this; + } + + + public StompPayload destination(String value){ + headers.put("destination", value); + return this; + } + + public StompPayload id(String value){ + headers.put("id", value); + return this; + } + + public String getBuilt() { + StringBuilder sb = new StringBuilder(); + sb.append(method.name()); + sb.append("\n"); + for (Map.Entry<String, String> stringStringEntry : headers.entrySet()) { + sb.append(stringStringEntry.getKey()); + sb.append(":"); + sb.append(stringStringEntry.getValue()); + sb.append("\n"); + if (stringStringEntry.getKey().contains(":")) throw new IllegalStateException("Illegal Character : inside headers"); + if (stringStringEntry.getValue().contains(":")) throw new IllegalStateException("Illegal Character : inside headers"); + } + sb.append("\n"); + if (payload != null) + sb.append(payload); + sb.append((char) 0); + if (FeatureRegistry.DEBUG.isEnabled()) System.out.println("Sending.. "+ sb); + return sb.toString(); + } + + public static StompPayload parse(String payload) { + if (FeatureRegistry.DEBUG.isEnabled()) System.out.println("Receving.. "+payload); + + Scanner scanner = new Scanner(payload); + StompPayload stompPayload = new StompPayload(); + stompPayload.method = StompHeader.valueOf(scanner.nextLine()); + String line; + while (!(line = scanner.nextLine()).isEmpty()) { + int index = line.indexOf(":"); + if (index == -1) throw new IllegalArgumentException("No : found in headers section"); + String name = line.substring(0, index); + String value; + if (index == line.length() - 1) + value = ""; + else + value = line.substring(index+1); + stompPayload.headers.put(name, value); + } + + List<String> lines = new ArrayList<>(); + while (scanner.hasNextLine() && !(line = scanner.nextLine()).equals("\0")) { + lines.add(line); + } + stompPayload.payload = String.join("\n", lines); + return stompPayload; + } +} diff --git a/src/main/java/kr/syeyoung/dungeonsguide/mod/stomp/StompSubscription.java b/src/main/java/kr/syeyoung/dungeonsguide/mod/stomp/StompSubscription.java new file mode 100644 index 00000000..965eaae9 --- /dev/null +++ b/src/main/java/kr/syeyoung/dungeonsguide/mod/stomp/StompSubscription.java @@ -0,0 +1,6 @@ +package kr.syeyoung.dungeonsguide.mod.stomp; + +@FunctionalInterface +public interface StompSubscription { + void process(StompClient stompInterface, String stompPayload); +} |
