From 60c4875a0ebcda90a93aa22aedaaafec258fdfee Mon Sep 17 00:00:00 2001 From: syeyoung <42869671+cyoung06@users.noreply.github.com> Date: Sun, 15 Jan 2023 22:22:47 +0900 Subject: Skyblock dungeons guide 234 (#271) * Skyblock-Dungeons-Guide-234 M1 Compatibility - fix cursors #234 Signed-off-by: syeyoung * - Latest gamesdk (which apparently has issues) https://discord.pyrrha.dev/#/versions v3.2.1 Signed-off-by: syeyoung * - rename libraries Signed-off-by: syeyoung * - update gamesdk ** Interfaces are not updated ** I only updated Signed-off-by: syeyoung * - get rid of gamesdk because it's pain to work with Signed-off-by: syeyoung * - implement ask to join and stuff Signed-off-by: syeyoung * - update library and stuff Signed-off-by: syeyoung * - - better logging Signed-off-by: syeyoung Signed-off-by: syeyoung --- loader/build.gradle | 4 +- mod/build.gradle | 15 +- mod/lib/DiscordIPC-1.0.jar | Bin 0 -> 508553 bytes mod/lib/README.md | 11 + .../syeyoung/dungeonsguide/mod/DungeonsGuide.java | 14 +- .../mod/commands/CommandDungeonsGuide.java | 8 +- .../mod/discord/DiscordIntegrationManager.java | 280 +++++++++++++++++ .../dungeonsguide/mod/discord/InviteHandle.java | 31 ++ .../mod/discord/JDiscordRelation.java | 79 +++++ .../dungeonsguide/mod/discord/RichPresence.java | 336 +++++++++++++++++++++ .../syeyoung/dungeonsguide/mod/discord/User.java | 207 +++++++++++++ .../dungeonsguide/mod/discord/gamesdk/GameSDK.java | 109 ------- .../mod/discord/gamesdk/jna/GameSDKTypeMapper.java | 47 --- .../mod/discord/gamesdk/jna/NativeGameSDK.java | 50 --- .../gamesdk/jna/datastruct/DiscordActivity.java | 50 --- .../jna/datastruct/DiscordActivityAssets.java | 42 --- .../jna/datastruct/DiscordActivityParty.java | 40 --- .../jna/datastruct/DiscordActivitySecrets.java | 41 --- .../jna/datastruct/DiscordActivityTimestamps.java | 40 --- .../jna/datastruct/DiscordCreateParams.java | 72 ----- .../gamesdk/jna/datastruct/DiscordEntitlement.java | 42 --- .../gamesdk/jna/datastruct/DiscordFileStat.java | 41 --- .../jna/datastruct/DiscordImageDimensions.java | 40 --- .../gamesdk/jna/datastruct/DiscordImageHandle.java | 43 --- .../gamesdk/jna/datastruct/DiscordInputMode.java | 41 --- .../gamesdk/jna/datastruct/DiscordLobby.java | 46 --- .../gamesdk/jna/datastruct/DiscordOAuth2Token.java | 42 --- .../gamesdk/jna/datastruct/DiscordPartySize.java | 40 --- .../gamesdk/jna/datastruct/DiscordPresence.java | 40 --- .../jna/datastruct/DiscordRelationship.java | 41 --- .../discord/gamesdk/jna/datastruct/DiscordSku.java | 44 --- .../gamesdk/jna/datastruct/DiscordSkuPrice.java | 40 --- .../gamesdk/jna/datastruct/DiscordStruct.java | 35 --- .../gamesdk/jna/datastruct/DiscordUser.java | 43 --- .../jna/datastruct/DiscordUserAchievement.java | 43 --- .../enumuration/EDiscordActivityActionType.java | 67 ---- .../EDiscordActivityJoinRequestReply.java | 68 ----- .../jna/enumuration/EDiscordActivityType.java | 69 ----- .../jna/enumuration/EDiscordCreateFlags.java | 67 ---- .../jna/enumuration/EDiscordEntitlementType.java | 72 ----- .../gamesdk/jna/enumuration/EDiscordImageType.java | 66 ---- .../jna/enumuration/EDiscordInputModeType.java | 67 ---- .../jna/enumuration/EDiscordLobbySearchCast.java | 67 ---- .../enumuration/EDiscordLobbySearchComparison.java | 71 ----- .../enumuration/EDiscordLobbySearchDistance.java | 69 ----- .../gamesdk/jna/enumuration/EDiscordLobbyType.java | 67 ---- .../gamesdk/jna/enumuration/EDiscordLogLevel.java | 69 ----- .../jna/enumuration/EDiscordPremiumType.java | 68 ----- .../jna/enumuration/EDiscordRelationshipType.java | 71 ----- .../gamesdk/jna/enumuration/EDiscordResult.java | 109 ------- .../gamesdk/jna/enumuration/EDiscordSkuType.java | 69 ----- .../gamesdk/jna/enumuration/EDiscordStatus.java | 69 ----- .../gamesdk/jna/enumuration/EDiscordUserFlag.java | 70 ----- .../jna/interfacestruct/GameSDKCallback.java | 30 -- .../interfacestruct/IDiscordAchievementEvents.java | 39 --- .../IDiscordAchievementManager.java | 57 ---- .../interfacestruct/IDiscordActivityEvents.java | 50 --- .../interfacestruct/IDiscordActivityManager.java | 63 ---- .../IDiscordApplicationManager.java | 60 ---- .../gamesdk/jna/interfacestruct/IDiscordCore.java | 91 ------ .../jna/interfacestruct/IDiscordImageManager.java | 52 ---- .../jna/interfacestruct/IDiscordLobbyEvents.java | 64 ---- .../jna/interfacestruct/IDiscordLobbyManager.java | 148 --------- .../IDiscordLobbyMemberTransaction.java | 42 --- .../interfacestruct/IDiscordLobbySearchQuery.java | 52 ---- .../interfacestruct/IDiscordLobbyTransaction.java | 57 ---- .../jna/interfacestruct/IDiscordNetworkEvents.java | 45 --- .../interfacestruct/IDiscordNetworkManager.java | 65 ---- .../jna/interfacestruct/IDiscordOverlayEvents.java | 38 --- .../interfacestruct/IDiscordOverlayManager.java | 56 ---- .../IDiscordRelationshipEvents.java | 42 --- .../IDiscordRelationshipManager.java | 53 ---- .../interfacestruct/IDiscordStorageManager.java | 81 ----- .../jna/interfacestruct/IDiscordStoreEvents.java | 43 --- .../jna/interfacestruct/IDiscordStoreManager.java | 73 ----- .../jna/interfacestruct/IDiscordUserEvents.java | 38 --- .../jna/interfacestruct/IDiscordUserManager.java | 53 ---- .../jna/interfacestruct/IDiscordVoiceEvents.java | 39 --- .../jna/interfacestruct/IDiscordVoiceManager.java | 72 ----- .../gamesdk/jna/typedef/DiscordClientID.java | 30 -- .../jna/typedef/DiscordNetworkChannelId.java | 30 -- .../gamesdk/jna/typedef/DiscordNetworkPeerId.java | 30 -- .../gamesdk/jna/typedef/DiscordSnowflake.java | 30 -- .../gamesdk/jna/typedef/DiscordTimestamp.java | 30 -- .../gamesdk/jna/typedef/DiscordVersion.java | 30 -- .../mod/discord/gamesdk/jna/typedef/Int32.java | 31 -- .../mod/discord/gamesdk/jna/typedef/Int64.java | 31 -- .../mod/discord/gamesdk/jna/typedef/UInt32.java | 31 -- .../mod/discord/gamesdk/jna/typedef/UInt64.java | 31 -- .../mod/discord/gamesdk/jna/typedef/UInt8.java | 31 -- .../mod/discord/rpc/JDiscordActivity.java | 72 ----- .../mod/discord/rpc/JDiscordRelation.java | 42 --- .../mod/discord/rpc/JDiscordUser.java | 40 --- .../mod/discord/rpc/RichPresenceManager.java | 250 --------------- .../mod/events/impl/DiscordUserInvitedEvent.java | 34 +++ .../events/impl/DiscordUserJoinRequestEvent.java | 5 +- .../mod/events/impl/DiscordUserUpdateEvent.java | 2 +- .../mod/features/FeatureRegistry.java | 2 - .../discord/inviteViewer/PartyInviteViewer.java | 25 +- .../discord/inviteViewer/PartyJoinRequest.java | 15 +- .../impl/discord/invteTooltip/MTooltipInvite.java | 22 +- .../invteTooltip/MTooltipInviteElement.java | 10 +- .../impl/discord/onlinealarm/PlayingDGAlarm.java | 26 +- .../impl/party/customgui/PanelPartyFinder.java | 4 +- .../dungeonsguide/mod/utils/cursor/GLCursors.java | 7 +- .../gamesdk/aarch64/libdiscord_game_sdk.dylib | Bin 0 -> 3818808 bytes .../gamesdk/darwin/libdiscord_game_sdk.dylib | Bin 4130000 -> 0 bytes .../resources/gamesdk/linux/libdiscord_game_sdk.so | Bin 7122200 -> 0 bytes .../resources/gamesdk/win-x64/discord_game_sdk.dll | Bin 3891512 -> 0 bytes .../resources/gamesdk/win-x86/discord_game_sdk.dll | Bin 3154744 -> 0 bytes .../resources/gamesdk/x86/discord_game_sdk.dll | Bin 0 -> 2937856 bytes .../resources/gamesdk/x86_64/discord_game_sdk.dll | Bin 0 -> 3488768 bytes .../gamesdk/x86_64/libdiscord_game_sdk.dylib | Bin 0 -> 4251528 bytes .../gamesdk/x86_64/libdiscord_game_sdk.so | Bin 0 -> 8469240 bytes 114 files changed, 1054 insertions(+), 4712 deletions(-) create mode 100644 mod/lib/DiscordIPC-1.0.jar create mode 100644 mod/lib/README.md create mode 100644 mod/src/main/java/kr/syeyoung/dungeonsguide/mod/discord/DiscordIntegrationManager.java create mode 100644 mod/src/main/java/kr/syeyoung/dungeonsguide/mod/discord/InviteHandle.java create mode 100644 mod/src/main/java/kr/syeyoung/dungeonsguide/mod/discord/JDiscordRelation.java create mode 100644 mod/src/main/java/kr/syeyoung/dungeonsguide/mod/discord/RichPresence.java create mode 100644 mod/src/main/java/kr/syeyoung/dungeonsguide/mod/discord/User.java delete mode 100644 mod/src/main/java/kr/syeyoung/dungeonsguide/mod/discord/gamesdk/GameSDK.java delete mode 100644 mod/src/main/java/kr/syeyoung/dungeonsguide/mod/discord/gamesdk/jna/GameSDKTypeMapper.java delete mode 100644 mod/src/main/java/kr/syeyoung/dungeonsguide/mod/discord/gamesdk/jna/NativeGameSDK.java delete mode 100644 mod/src/main/java/kr/syeyoung/dungeonsguide/mod/discord/gamesdk/jna/datastruct/DiscordActivity.java delete mode 100644 mod/src/main/java/kr/syeyoung/dungeonsguide/mod/discord/gamesdk/jna/datastruct/DiscordActivityAssets.java delete mode 100644 mod/src/main/java/kr/syeyoung/dungeonsguide/mod/discord/gamesdk/jna/datastruct/DiscordActivityParty.java delete mode 100644 mod/src/main/java/kr/syeyoung/dungeonsguide/mod/discord/gamesdk/jna/datastruct/DiscordActivitySecrets.java delete mode 100644 mod/src/main/java/kr/syeyoung/dungeonsguide/mod/discord/gamesdk/jna/datastruct/DiscordActivityTimestamps.java delete mode 100644 mod/src/main/java/kr/syeyoung/dungeonsguide/mod/discord/gamesdk/jna/datastruct/DiscordCreateParams.java delete mode 100644 mod/src/main/java/kr/syeyoung/dungeonsguide/mod/discord/gamesdk/jna/datastruct/DiscordEntitlement.java delete mode 100644 mod/src/main/java/kr/syeyoung/dungeonsguide/mod/discord/gamesdk/jna/datastruct/DiscordFileStat.java delete mode 100644 mod/src/main/java/kr/syeyoung/dungeonsguide/mod/discord/gamesdk/jna/datastruct/DiscordImageDimensions.java delete mode 100644 mod/src/main/java/kr/syeyoung/dungeonsguide/mod/discord/gamesdk/jna/datastruct/DiscordImageHandle.java delete mode 100644 mod/src/main/java/kr/syeyoung/dungeonsguide/mod/discord/gamesdk/jna/datastruct/DiscordInputMode.java delete mode 100644 mod/src/main/java/kr/syeyoung/dungeonsguide/mod/discord/gamesdk/jna/datastruct/DiscordLobby.java delete mode 100644 mod/src/main/java/kr/syeyoung/dungeonsguide/mod/discord/gamesdk/jna/datastruct/DiscordOAuth2Token.java delete mode 100644 mod/src/main/java/kr/syeyoung/dungeonsguide/mod/discord/gamesdk/jna/datastruct/DiscordPartySize.java delete mode 100644 mod/src/main/java/kr/syeyoung/dungeonsguide/mod/discord/gamesdk/jna/datastruct/DiscordPresence.java delete mode 100644 mod/src/main/java/kr/syeyoung/dungeonsguide/mod/discord/gamesdk/jna/datastruct/DiscordRelationship.java delete mode 100644 mod/src/main/java/kr/syeyoung/dungeonsguide/mod/discord/gamesdk/jna/datastruct/DiscordSku.java delete mode 100644 mod/src/main/java/kr/syeyoung/dungeonsguide/mod/discord/gamesdk/jna/datastruct/DiscordSkuPrice.java delete mode 100644 mod/src/main/java/kr/syeyoung/dungeonsguide/mod/discord/gamesdk/jna/datastruct/DiscordStruct.java delete mode 100644 mod/src/main/java/kr/syeyoung/dungeonsguide/mod/discord/gamesdk/jna/datastruct/DiscordUser.java delete mode 100644 mod/src/main/java/kr/syeyoung/dungeonsguide/mod/discord/gamesdk/jna/datastruct/DiscordUserAchievement.java delete mode 100644 mod/src/main/java/kr/syeyoung/dungeonsguide/mod/discord/gamesdk/jna/enumuration/EDiscordActivityActionType.java delete mode 100644 mod/src/main/java/kr/syeyoung/dungeonsguide/mod/discord/gamesdk/jna/enumuration/EDiscordActivityJoinRequestReply.java delete mode 100644 mod/src/main/java/kr/syeyoung/dungeonsguide/mod/discord/gamesdk/jna/enumuration/EDiscordActivityType.java delete mode 100644 mod/src/main/java/kr/syeyoung/dungeonsguide/mod/discord/gamesdk/jna/enumuration/EDiscordCreateFlags.java delete mode 100644 mod/src/main/java/kr/syeyoung/dungeonsguide/mod/discord/gamesdk/jna/enumuration/EDiscordEntitlementType.java delete mode 100644 mod/src/main/java/kr/syeyoung/dungeonsguide/mod/discord/gamesdk/jna/enumuration/EDiscordImageType.java delete mode 100644 mod/src/main/java/kr/syeyoung/dungeonsguide/mod/discord/gamesdk/jna/enumuration/EDiscordInputModeType.java delete mode 100644 mod/src/main/java/kr/syeyoung/dungeonsguide/mod/discord/gamesdk/jna/enumuration/EDiscordLobbySearchCast.java delete mode 100644 mod/src/main/java/kr/syeyoung/dungeonsguide/mod/discord/gamesdk/jna/enumuration/EDiscordLobbySearchComparison.java delete mode 100644 mod/src/main/java/kr/syeyoung/dungeonsguide/mod/discord/gamesdk/jna/enumuration/EDiscordLobbySearchDistance.java delete mode 100644 mod/src/main/java/kr/syeyoung/dungeonsguide/mod/discord/gamesdk/jna/enumuration/EDiscordLobbyType.java delete mode 100644 mod/src/main/java/kr/syeyoung/dungeonsguide/mod/discord/gamesdk/jna/enumuration/EDiscordLogLevel.java delete mode 100644 mod/src/main/java/kr/syeyoung/dungeonsguide/mod/discord/gamesdk/jna/enumuration/EDiscordPremiumType.java delete mode 100644 mod/src/main/java/kr/syeyoung/dungeonsguide/mod/discord/gamesdk/jna/enumuration/EDiscordRelationshipType.java delete mode 100644 mod/src/main/java/kr/syeyoung/dungeonsguide/mod/discord/gamesdk/jna/enumuration/EDiscordResult.java delete mode 100644 mod/src/main/java/kr/syeyoung/dungeonsguide/mod/discord/gamesdk/jna/enumuration/EDiscordSkuType.java delete mode 100644 mod/src/main/java/kr/syeyoung/dungeonsguide/mod/discord/gamesdk/jna/enumuration/EDiscordStatus.java delete mode 100644 mod/src/main/java/kr/syeyoung/dungeonsguide/mod/discord/gamesdk/jna/enumuration/EDiscordUserFlag.java delete mode 100644 mod/src/main/java/kr/syeyoung/dungeonsguide/mod/discord/gamesdk/jna/interfacestruct/GameSDKCallback.java delete mode 100644 mod/src/main/java/kr/syeyoung/dungeonsguide/mod/discord/gamesdk/jna/interfacestruct/IDiscordAchievementEvents.java delete mode 100644 mod/src/main/java/kr/syeyoung/dungeonsguide/mod/discord/gamesdk/jna/interfacestruct/IDiscordAchievementManager.java delete mode 100644 mod/src/main/java/kr/syeyoung/dungeonsguide/mod/discord/gamesdk/jna/interfacestruct/IDiscordActivityEvents.java delete mode 100644 mod/src/main/java/kr/syeyoung/dungeonsguide/mod/discord/gamesdk/jna/interfacestruct/IDiscordActivityManager.java delete mode 100644 mod/src/main/java/kr/syeyoung/dungeonsguide/mod/discord/gamesdk/jna/interfacestruct/IDiscordApplicationManager.java delete mode 100644 mod/src/main/java/kr/syeyoung/dungeonsguide/mod/discord/gamesdk/jna/interfacestruct/IDiscordCore.java delete mode 100644 mod/src/main/java/kr/syeyoung/dungeonsguide/mod/discord/gamesdk/jna/interfacestruct/IDiscordImageManager.java delete mode 100644 mod/src/main/java/kr/syeyoung/dungeonsguide/mod/discord/gamesdk/jna/interfacestruct/IDiscordLobbyEvents.java delete mode 100644 mod/src/main/java/kr/syeyoung/dungeonsguide/mod/discord/gamesdk/jna/interfacestruct/IDiscordLobbyManager.java delete mode 100644 mod/src/main/java/kr/syeyoung/dungeonsguide/mod/discord/gamesdk/jna/interfacestruct/IDiscordLobbyMemberTransaction.java delete mode 100644 mod/src/main/java/kr/syeyoung/dungeonsguide/mod/discord/gamesdk/jna/interfacestruct/IDiscordLobbySearchQuery.java delete mode 100644 mod/src/main/java/kr/syeyoung/dungeonsguide/mod/discord/gamesdk/jna/interfacestruct/IDiscordLobbyTransaction.java delete mode 100644 mod/src/main/java/kr/syeyoung/dungeonsguide/mod/discord/gamesdk/jna/interfacestruct/IDiscordNetworkEvents.java delete mode 100644 mod/src/main/java/kr/syeyoung/dungeonsguide/mod/discord/gamesdk/jna/interfacestruct/IDiscordNetworkManager.java delete mode 100644 mod/src/main/java/kr/syeyoung/dungeonsguide/mod/discord/gamesdk/jna/interfacestruct/IDiscordOverlayEvents.java delete mode 100644 mod/src/main/java/kr/syeyoung/dungeonsguide/mod/discord/gamesdk/jna/interfacestruct/IDiscordOverlayManager.java delete mode 100644 mod/src/main/java/kr/syeyoung/dungeonsguide/mod/discord/gamesdk/jna/interfacestruct/IDiscordRelationshipEvents.java delete mode 100644 mod/src/main/java/kr/syeyoung/dungeonsguide/mod/discord/gamesdk/jna/interfacestruct/IDiscordRelationshipManager.java delete mode 100644 mod/src/main/java/kr/syeyoung/dungeonsguide/mod/discord/gamesdk/jna/interfacestruct/IDiscordStorageManager.java delete mode 100644 mod/src/main/java/kr/syeyoung/dungeonsguide/mod/discord/gamesdk/jna/interfacestruct/IDiscordStoreEvents.java delete mode 100644 mod/src/main/java/kr/syeyoung/dungeonsguide/mod/discord/gamesdk/jna/interfacestruct/IDiscordStoreManager.java delete mode 100644 mod/src/main/java/kr/syeyoung/dungeonsguide/mod/discord/gamesdk/jna/interfacestruct/IDiscordUserEvents.java delete mode 100644 mod/src/main/java/kr/syeyoung/dungeonsguide/mod/discord/gamesdk/jna/interfacestruct/IDiscordUserManager.java delete mode 100644 mod/src/main/java/kr/syeyoung/dungeonsguide/mod/discord/gamesdk/jna/interfacestruct/IDiscordVoiceEvents.java delete mode 100644 mod/src/main/java/kr/syeyoung/dungeonsguide/mod/discord/gamesdk/jna/interfacestruct/IDiscordVoiceManager.java delete mode 100644 mod/src/main/java/kr/syeyoung/dungeonsguide/mod/discord/gamesdk/jna/typedef/DiscordClientID.java delete mode 100644 mod/src/main/java/kr/syeyoung/dungeonsguide/mod/discord/gamesdk/jna/typedef/DiscordNetworkChannelId.java delete mode 100644 mod/src/main/java/kr/syeyoung/dungeonsguide/mod/discord/gamesdk/jna/typedef/DiscordNetworkPeerId.java delete mode 100644 mod/src/main/java/kr/syeyoung/dungeonsguide/mod/discord/gamesdk/jna/typedef/DiscordSnowflake.java delete mode 100644 mod/src/main/java/kr/syeyoung/dungeonsguide/mod/discord/gamesdk/jna/typedef/DiscordTimestamp.java delete mode 100644 mod/src/main/java/kr/syeyoung/dungeonsguide/mod/discord/gamesdk/jna/typedef/DiscordVersion.java delete mode 100644 mod/src/main/java/kr/syeyoung/dungeonsguide/mod/discord/gamesdk/jna/typedef/Int32.java delete mode 100644 mod/src/main/java/kr/syeyoung/dungeonsguide/mod/discord/gamesdk/jna/typedef/Int64.java delete mode 100644 mod/src/main/java/kr/syeyoung/dungeonsguide/mod/discord/gamesdk/jna/typedef/UInt32.java delete mode 100644 mod/src/main/java/kr/syeyoung/dungeonsguide/mod/discord/gamesdk/jna/typedef/UInt64.java delete mode 100644 mod/src/main/java/kr/syeyoung/dungeonsguide/mod/discord/gamesdk/jna/typedef/UInt8.java delete mode 100644 mod/src/main/java/kr/syeyoung/dungeonsguide/mod/discord/rpc/JDiscordActivity.java delete mode 100644 mod/src/main/java/kr/syeyoung/dungeonsguide/mod/discord/rpc/JDiscordRelation.java delete mode 100644 mod/src/main/java/kr/syeyoung/dungeonsguide/mod/discord/rpc/JDiscordUser.java delete mode 100644 mod/src/main/java/kr/syeyoung/dungeonsguide/mod/discord/rpc/RichPresenceManager.java create mode 100644 mod/src/main/java/kr/syeyoung/dungeonsguide/mod/events/impl/DiscordUserInvitedEvent.java create mode 100644 mod/src/main/resources/gamesdk/aarch64/libdiscord_game_sdk.dylib delete mode 100644 mod/src/main/resources/gamesdk/darwin/libdiscord_game_sdk.dylib delete mode 100644 mod/src/main/resources/gamesdk/linux/libdiscord_game_sdk.so delete mode 100644 mod/src/main/resources/gamesdk/win-x64/discord_game_sdk.dll delete mode 100644 mod/src/main/resources/gamesdk/win-x86/discord_game_sdk.dll create mode 100644 mod/src/main/resources/gamesdk/x86/discord_game_sdk.dll create mode 100644 mod/src/main/resources/gamesdk/x86_64/discord_game_sdk.dll create mode 100644 mod/src/main/resources/gamesdk/x86_64/libdiscord_game_sdk.dylib create mode 100644 mod/src/main/resources/gamesdk/x86_64/libdiscord_game_sdk.so diff --git a/loader/build.gradle b/loader/build.gradle index 362a9bf8..58746677 100644 --- a/loader/build.gradle +++ b/loader/build.gradle @@ -72,7 +72,7 @@ dependencies { forge("net.minecraftforge:forge:1.8.9-11.15.1.2318-1.8.9") implementation "org.jetbrains:annotations-java5:19.0.0" - implementation "org.json:json:20171018" + implementation "org.json:json:20220924" implementation 'io.nayuki:qrcodegen:1.4.0' implementation 'org.bouncycastle:bcpg-jdk15on:1.70' @@ -112,7 +112,7 @@ tasks.shadowJar { exclude "META-INF/versions/**" dependencies { include(dependency("org.slf4j:slf4j-api:1.7.25")) - include(dependency("org.json:json:20171018")) + include(dependency("org.json:json:20220924")) include(dependency("org.bouncycastle:bcpg-jdk15on:1.70")) include(dependency("org.bouncycastle:bcprov-jdk15on:1.70")) } diff --git a/mod/build.gradle b/mod/build.gradle index 7fc200b1..b2e528a7 100644 --- a/mod/build.gradle +++ b/mod/build.gradle @@ -50,9 +50,14 @@ dependencies { implementation "org.jetbrains:annotations-java5:19.0.0" implementation "org.java-websocket:Java-WebSocket:1.5.1" - implementation "org.json:json:20171018" + implementation 'org.json:json:20220924' + implementation files("lib/DiscordIPC-1.0.jar") + implementation "com.twelvemonkeys.imageio:imageio-bmp:3.7.0" + implementation 'net.java.dev.jna:jna:5.12.1' // sorry minecraft. + + compileOnly "org.projectlombok:lombok:1.18.20" compileOnly files("../jars/Hychat-1.12.1-BETA.jar") annotationProcessor "org.projectlombok:lombok:1.18.16" @@ -122,13 +127,17 @@ tasks.shadowJar { archiveFileName = jar.archiveFileName - relocate "org.java_websocket", "kr.syeyoung.org.java_websocket" + relocate 'com.sun.jna', "kr.syeyoung.dungeonsguide.com.sun.jna" + relocate "org.java_websocket", "kr.syeyoung.dungeonsguide.org.java_websocket" + relocate 'com.jagrosh.discordipc', 'kr.syeyoung.dungeonsguide.com.jagrosh.discordipc' dependencies { include(dependency("org.java-websocket:Java-WebSocket:1.5.1")) include(dependency("org.slf4j:slf4j-api:1.7.25")) - include(dependency("org.json:json:20171018")) + include(dependency("org.json:json:20220924")) include(dependency("com.twelvemonkeys..*:.*")) + include(dependency("net.java.dev.jna:jna:5.12.1")) + include(dependency(files("lib/DiscordIPC-1.0.jar"))) } } diff --git a/mod/lib/DiscordIPC-1.0.jar b/mod/lib/DiscordIPC-1.0.jar new file mode 100644 index 00000000..423e3c5a Binary files /dev/null and b/mod/lib/DiscordIPC-1.0.jar differ diff --git a/mod/lib/README.md b/mod/lib/README.md new file mode 100644 index 00000000..4d76d7b1 --- /dev/null +++ b/mod/lib/README.md @@ -0,0 +1,11 @@ +This is modified version of +https://github.com/jagrosh/DiscordIPC +which is on +https://github.com/cyoung06/DiscordIPC +(you can view all the changes on that repo) + +This library is licensed under Apache License 2.0 + + +Since it would be painful to setup maven repository on DG backend, (both to me and other developers due to extremely slow network speed) +I've just put a jar. \ No newline at end of file diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/DungeonsGuide.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/DungeonsGuide.java index d54613b8..cfb85aa9 100755 --- a/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/DungeonsGuide.java +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/DungeonsGuide.java @@ -29,8 +29,7 @@ import kr.syeyoung.dungeonsguide.mod.commands.CommandReparty; import kr.syeyoung.dungeonsguide.mod.config.Config; import kr.syeyoung.dungeonsguide.mod.cosmetics.CosmeticsManager; import kr.syeyoung.dungeonsguide.mod.cosmetics.CustomNetworkPlayerInfo; -import kr.syeyoung.dungeonsguide.mod.discord.gamesdk.GameSDK; -import kr.syeyoung.dungeonsguide.mod.discord.rpc.RichPresenceManager; +import kr.syeyoung.dungeonsguide.mod.discord.DiscordIntegrationManager; import kr.syeyoung.dungeonsguide.mod.dungeon.DungeonFacade; import kr.syeyoung.dungeonsguide.mod.events.annotations.EventHandlerRegistry; import kr.syeyoung.dungeonsguide.mod.events.listener.DungeonListener; @@ -250,12 +249,9 @@ public class DungeonsGuide implements DGInterface { if (FeatureRegistry.ETC_REPARTY.isEnabled()) { registerCommands(commandReparty); } + DiscordIntegrationManager.INSTANCE.isLoaded(); - if (FeatureRegistry.DISCORD_DONOTUSE.isEnabled()) { - System.setProperty("dg.safe", "true"); - } - registerEventsForge(RichPresenceManager.INSTANCE); TimeScoreUtil.init(); ProgressManager.pop(progressbar); @@ -396,6 +392,7 @@ public class DungeonsGuide implements DGInterface { e.printStackTrace(); } + DiscordIntegrationManager.INSTANCE.cleanup(); THREAD_GROUP.interrupt(); THREAD_GROUP.stop(); @@ -404,11 +401,6 @@ public class DungeonsGuide implements DGInterface { } catch (InterruptedException e) { } THREAD_GROUP.destroy(); - try { - GameSDK.cleanup(); - } catch (Exception e) { - e.printStackTrace(); - } } @Override diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/commands/CommandDungeonsGuide.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/commands/CommandDungeonsGuide.java index c414e75a..36a0e955 100644 --- a/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/commands/CommandDungeonsGuide.java +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/commands/CommandDungeonsGuide.java @@ -23,7 +23,7 @@ import kr.syeyoung.dungeonsguide.mod.DungeonsGuide; import kr.syeyoung.dungeonsguide.mod.chat.ChatTransmitter; import kr.syeyoung.dungeonsguide.mod.config.guiconfig.GuiConfigV2; import kr.syeyoung.dungeonsguide.mod.cosmetics.CosmeticsManager; -import kr.syeyoung.dungeonsguide.mod.discord.rpc.RichPresenceManager; +import kr.syeyoung.dungeonsguide.mod.discord.DiscordIntegrationManager; import kr.syeyoung.dungeonsguide.mod.features.FeatureRegistry; import kr.syeyoung.dungeonsguide.mod.features.impl.party.playerpreview.FeatureViewPlayerStatsOnJoin; import kr.syeyoung.dungeonsguide.mod.features.impl.party.playerpreview.api.ApiFetcher; @@ -32,12 +32,8 @@ import kr.syeyoung.dungeonsguide.mod.stomp.StompManager; import kr.syeyoung.dungeonsguide.mod.stomp.StompPayload; import kr.syeyoung.dungeonsguide.mod.wsresource.StaticResourceCache; import net.minecraft.client.Minecraft; -import net.minecraft.client.gui.GuiMainMenu; -import net.minecraft.client.gui.GuiMultiplayer; -import net.minecraft.client.multiplayer.WorldClient; import net.minecraft.command.CommandBase; import net.minecraft.command.ICommandSender; -import net.minecraft.realms.RealmsBridge; import net.minecraft.util.ChatComponentText; import net.minecraft.util.ChatStyle; import net.minecraftforge.fml.common.eventhandler.SubscribeEvent; @@ -76,7 +72,7 @@ public class CommandDungeonsGuide extends CommandBase { FeatureViewPlayerStatsOnJoin.processPartyMembers(context); }); } else if (args[0].equalsIgnoreCase("asktojoin") || args[0].equalsIgnoreCase("atj")) { - if (RichPresenceManager.INSTANCE.getLastSetupCode() == -9999) { + if (!DiscordIntegrationManager.INSTANCE.isLoaded()) { sender.addChatMessage(new ChatComponentText("§eDungeons Guide §7:: §cDiscord GameSDK has been disabled, or it failed to load!")); return; } diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/discord/DiscordIntegrationManager.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/discord/DiscordIntegrationManager.java new file mode 100644 index 00000000..196bdbd9 --- /dev/null +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/discord/DiscordIntegrationManager.java @@ -0,0 +1,280 @@ +/* + * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod + * Copyright (C) 2023 cyoung06 (syeyoung) + * + * 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 . + */ + +package kr.syeyoung.dungeonsguide.mod.discord; + +import com.jagrosh.discordipc.IPCClient; +import com.jagrosh.discordipc.IPCListener; +import com.jagrosh.discordipc.entities.Callback; +import com.jagrosh.discordipc.entities.Packet; +import com.jagrosh.discordipc.entities.RichPresence; +import com.jagrosh.discordipc.entities.User; +import com.jagrosh.discordipc.entities.pipe.PipeStatus; +import kr.syeyoung.dungeonsguide.mod.DungeonsGuide; +import kr.syeyoung.dungeonsguide.mod.SkyblockStatus; +import kr.syeyoung.dungeonsguide.mod.dungeon.DungeonContext; +import kr.syeyoung.dungeonsguide.mod.events.impl.DiscordUserInvitedEvent; +import kr.syeyoung.dungeonsguide.mod.events.impl.DiscordUserJoinRequestEvent; +import kr.syeyoung.dungeonsguide.mod.events.impl.DiscordUserUpdateEvent; +import kr.syeyoung.dungeonsguide.mod.features.FeatureRegistry; +import kr.syeyoung.dungeonsguide.mod.features.impl.discord.inviteViewer.PartyJoinRequest; +import kr.syeyoung.dungeonsguide.mod.party.PartyContext; +import kr.syeyoung.dungeonsguide.mod.party.PartyManager; +import lombok.Getter; +import net.minecraftforge.common.MinecraftForge; +import org.apache.logging.log4j.Level; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; +import org.json.JSONArray; +import org.json.JSONObject; + +import java.lang.management.ManagementFactory; +import java.time.Instant; +import java.time.ZoneId; +import java.util.HashMap; +import java.util.Map; +import java.util.Optional; +import java.util.Set; + +public class DiscordIntegrationManager implements IPCListener { + public static DiscordIntegrationManager INSTANCE = new DiscordIntegrationManager(); + private IPCClient ipcClient; + private final Thread t = new Thread(DungeonsGuide.THREAD_GROUP, this::run); + private Logger logger = LogManager.getLogger("DG-DiscordIntegrationManager"); + + private DiscordIntegrationManager(){ + ipcClient = new IPCClient(816298079732498473L, DungeonsGuide.THREAD_FACTORY); + t.start(); + } + + @Getter + private final Map relationMap = new HashMap<>(); + + public boolean isLoaded() { + return ipcClient.getStatus() == PipeStatus.CONNECTED; + } + + public void sendInvite(String id, String content) { + JSONObject payload = new JSONObject() + .put("cmd", "ACTIVITY_INVITE_USER") + .put("args", new JSONObject() + .put("type", 1) + .put("user_id", id) + .put("content", content) + .put("pid",getPID())); + ipcClient.send(payload, new Callback(success ->{}, fail -> { + logger.log(Level.WARN, "Discord failed send Invite for "+fail+"\n Sent payload: "+payload); + })); + } + + + public void respondToJoinRequest(String userId, PartyJoinRequest.Reply accept) { + JSONObject payload = null; + if (accept == PartyJoinRequest.Reply.ACCEPT) { + payload = new JSONObject() + .put("cmd", "SEND_ACTIVITY_JOIN_INVITE") + .put("args", new JSONObject().put("user_id", userId)); + } else { + payload = new JSONObject() + .put("cmd", "CLOSE_ACTIVITY_JOIN_REQUEST") + .put("args", new JSONObject().put("user_id", userId)); + } + JSONObject finalPayload = payload; + ipcClient.send(payload, new Callback(success ->{}, fail -> { + logger.log(Level.WARN, "Discord failed respond to join request for "+fail+"\n Sent payload: "+ finalPayload); + })); + } + + public void acceptInvite(InviteHandle handle) { + JSONObject payload = new JSONObject() + .put("cmd", "ACCEPT_ACTIVITY_INVITE") + .put("args", new JSONObject() + .put("type", 1) + .put("user_id", handle.getUserId()) + .put("session_id", handle.getSessionId()) + .put("channel_id", handle.getChannelId()) + .put("message_id", handle.getMessageId())); + ipcClient.send(payload, new Callback(success ->{}, fail -> { + logger.log(Level.WARN, "Discord failed accept invite for "+fail+"\n Sent payload: "+ payload); + })); + } + + + + private void setup() { + try { + ipcClient.connect(); + ipcClient.subscribe("ACTIVITY_JOIN", this::onActivityJoin); + ipcClient.subscribe("ACTIVITY_JOIN_REQUEST", this::onActivityJoinRequest); + ipcClient.subscribe("ACTIVITY_INVITE", this::onActivityInvite); + ipcClient.subscribe("RELATIONSHIP_UPDATE", this::onRelationshipUpdate); + ipcClient.send(new JSONObject().put("cmd", "GET_RELATIONSHIPS"), new Callback(this::onRelationshipLoad)); + ipcClient.setListener(this); + } catch (Throwable t) { + t.printStackTrace(); + } + } + + private void onRelationshipUpdate(Packet packet){ + JSONObject data = packet.getJson().getJSONObject("data"); + JDiscordRelation relation = JDiscordRelation.parse(data); + JDiscordRelation old = relationMap.put(relation.getDiscordUser().getIdLong(), relation); + MinecraftForge.EVENT_BUS.post(new DiscordUserUpdateEvent(old, relation)); + } + private void onActivityJoinRequest(Packet packet) { + JSONObject data = packet.getJson().getJSONObject("data"); + User user = new User(data.getJSONObject("user") + .getString("username"), + data.getJSONObject("user") + .getString("discriminator"), + Long.parseUnsignedLong(data.getJSONObject("user") + .getString("id")), + data.getJSONObject("user") + .getString("avatar")); + MinecraftForge.EVENT_BUS.post(new DiscordUserJoinRequestEvent(user)); + } + private void onActivityInvite(Packet packet) { + JSONObject data = packet.getJson().getJSONObject("data"); + if (!data.getJSONObject("activity").getString("application_id").equals("816298079732498473")) + return; + MinecraftForge.EVENT_BUS.post(new DiscordUserInvitedEvent( + new User(data.getJSONObject("user") + .getString("username"), + data.getJSONObject("user") + .getString("discriminator"), + Long.parseUnsignedLong(data.getJSONObject("user") + .getString("id")), + data.getJSONObject("user") + .getString("avatar")), + new InviteHandle( + data.getJSONObject("user").getString("id"), + data.getJSONObject("activity").getString("session_id"), + data.getString("channel_id"), + data.getString("message_id") + ))); + } + + private void onRelationshipLoad(Packet object) { + try { + JSONArray relationship = object.getJson().getJSONObject("data").getJSONArray("relationships"); + for (Object o : relationship) { + JSONObject obj = (JSONObject) o; + JDiscordRelation relation = JDiscordRelation.parse(obj); + relationMap.put(relation.getDiscordUser().getIdLong(), relation); + } + } catch (Throwable e) {e.printStackTrace();} + } + + private final SkyblockStatus skyblockStatus = DungeonsGuide.getDungeonsGuide().getSkyblockStatus(); + + private void sendRichPresence(RichPresence presence) { + ipcClient.send(new JSONObject() + .put("cmd","SET_ACTIVITY") + .put("args", new JSONObject() + .put("pid",getPID()) + .put("activity",presence == null ? null : presence.toJson())), new Callback(success ->{}, fail -> {System.out.println(fail);})); + } + private void updatePresence() { + if (!skyblockStatus.isOnHypixel() || !FeatureRegistry.DISCORD_RICHPRESENCE.isEnabled() || (!skyblockStatus.isOnSkyblock() && FeatureRegistry.DISCORD_RICHPRESENCE.getParameter("disablenotskyblock").getValue())) { + sendRichPresence(null); + } else { + String name = DungeonContext.getDungeonName() == null ? "" : DungeonContext.getDungeonName(); + if (!skyblockStatus.isOnSkyblock()) name ="Somewhere on Hypixel"; + if (name.trim().equals("Your Island")) name = "Private Island"; + + RichPresence.Builder presence = new RichPresence.Builder(); + + presence.setLargeImage("mort", "mort"); + presence.setState(name); + presence.setParty( + Optional.ofNullable( PartyManager.INSTANCE.getPartyContext()).map(PartyContext::getPartyID).orElse(null), + Optional.ofNullable(PartyManager.INSTANCE.getPartyContext()).map(PartyContext::getPartyRawMembers).map(Set::size).orElse(1), + PartyManager.INSTANCE.getMaxParty() + ); + + DungeonContext context = DungeonsGuide.getDungeonsGuide().getDungeonFacade().getContext(); + if (context != null) { + long init = context.getInit(); + presence.setStartTimestamp(Instant.ofEpochMilli(init).atZone(ZoneId.systemDefault()).toOffsetDateTime()); + + if (context.getBossfightProcessor() != null) { + presence.setDetails("Fighting "+context.getBossfightProcessor().getBossName()+": "+context.getBossfightProcessor().getCurrentPhase()); + } else { + presence.setDetails("Clearing Rooms"); + } + } else { + presence.setStartTimestamp(null); + presence.setDetails("Dungeons Guide"); + } + if (PartyManager.INSTANCE.getAskToJoinSecret() != null) { + presence.setJoinSecret(PartyManager.INSTANCE.getAskToJoinSecret()); + } + presence.setInstance(false); + sendRichPresence(presence.build()); + } + } + private void run() { + while(!t.isInterrupted()) { + try{ + if (!isLoaded()) setup(); + else { + updatePresence(); + } + } catch (Throwable t) { + t.printStackTrace(); + } + try { + Thread.sleep(32); + } catch (InterruptedException e) { + break; + } + } + } + + + + public void onActivityJoin(Packet packet) { + String secret = packet.getJson().getJSONObject("data").getString("secret"); + PartyManager.INSTANCE.joinWithToken(secret); + logger.log(Level.DEBUG, "Trying to join with token: "+secret); + } + + @Override + public void onClose(IPCClient client, JSONObject json) { + logger.log(Level.DEBUG, "IPC Client closed with: "+json); + } + + @Override + public void onDisconnect(IPCClient client, Throwable t) { + logger.log(Level.DEBUG, "IPC Client disconnected for: ", t); + } + + + + public void cleanup() { + ipcClient.close(); + this.t.interrupt(); + ipcClient = null; + } + + private static int getPID() + { + String pr = ManagementFactory.getRuntimeMXBean().getName(); + return Integer.parseInt(pr.substring(0,pr.indexOf('@'))); + } +} diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/discord/InviteHandle.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/discord/InviteHandle.java new file mode 100644 index 00000000..fce3ab89 --- /dev/null +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/discord/InviteHandle.java @@ -0,0 +1,31 @@ +/* + * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod + * Copyright (C) 2023 cyoung06 (syeyoung) + * + * 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 . + */ + +package kr.syeyoung.dungeonsguide.mod.discord; + +import lombok.AllArgsConstructor; +import lombok.Data; + +@Data +@AllArgsConstructor +public class InviteHandle { + private String userId; + private String sessionId; + private String channelId; + private String messageId; +} diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/discord/JDiscordRelation.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/discord/JDiscordRelation.java new file mode 100644 index 00000000..154ca597 --- /dev/null +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/discord/JDiscordRelation.java @@ -0,0 +1,79 @@ +/* + * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod + * Copyright (C) 2023 cyoung06 (syeyoung) + * + * 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 . + */ + +package kr.syeyoung.dungeonsguide.mod.discord; + +import com.jagrosh.discordipc.entities.User; +import lombok.Data; +import org.json.JSONObject; + +@Data +public class JDiscordRelation { +// private EDiscordRelationshipType discordRelationshipType; +// private EDiscordStatus status; +// private JDiscordActivity discordActivity; + private Status status; + private String applicationId; + private DiscordRelationType relationType; + private User discordUser; + + public enum Status { + OFFLINE, ONLINE, DO_NOT_DISTURB, IDLE, UNKNOWN; + + public static Status fromString(String str) { + switch(str) { + case "offline": return OFFLINE; + case "online": return ONLINE; + case "idle": return IDLE; + case "dnd": return DO_NOT_DISTURB; + } + return UNKNOWN; + } + } + public enum DiscordRelationType { + + None, + Friend, + Blocked, + PendingIncoming, + PendingOutgoing, + Implicit; + } + + + public static JDiscordRelation parse(JSONObject data) { + JDiscordRelation relation = new JDiscordRelation(); + JDiscordRelation.DiscordRelationType relationType = JDiscordRelation.DiscordRelationType.values()[data.getInt("type")]; + JSONObject userJson = data.getJSONObject("user"); + User user = new User(userJson.getString("username"), userJson.getString("discriminator"), + Long.parseUnsignedLong(userJson.getString("id")), + userJson.isNull("avatar") ? null : userJson.getString("avatar")); + JDiscordRelation.Status status = JDiscordRelation.Status.fromString(data.getJSONObject("presence").getString("status")); + + relation.setRelationType(relationType); + relation.setDiscordUser(user); + relation.setStatus(status); + + if (data.has("activity") && !data.isNull("activity")) { + JSONObject activity = data.getJSONObject("activity"); + String appId = activity.getString("application_id"); + relation.setApplicationId(appId); + } + return relation; + } +} diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/discord/RichPresence.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/discord/RichPresence.java new file mode 100644 index 00000000..6d104b8f --- /dev/null +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/discord/RichPresence.java @@ -0,0 +1,336 @@ +/* + * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod + * Copyright (C) 2023 cyoung06 (syeyoung) + * + * 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 . + */ +package kr.syeyoung.dungeonsguide.mod.discord; + +import org.json.JSONArray; +import org.json.JSONObject; + +import java.time.OffsetDateTime; + +/** + * An encapsulation of all data needed to properly construct a JSON RichPresence payload. + * + *

These can be built using {@link Builder}. + * + * @author John Grosh (john.a.grosh@gmail.com) + */ +public class RichPresence +{ + private final String state; + private final String details; + private final OffsetDateTime startTimestamp; + private final OffsetDateTime endTimestamp; + private final String largeImageKey; + private final String largeImageText; + private final String smallImageKey; + private final String smallImageText; + private final String partyId; + private final int partySize; + private final int partyMax; + private final String matchSecret; + private final String joinSecret; + private final String spectateSecret; + private final boolean instance; + + public RichPresence(String state, String details, OffsetDateTime startTimestamp, OffsetDateTime endTimestamp, + String largeImageKey, String largeImageText, String smallImageKey, String smallImageText, + String partyId, int partySize, int partyMax, String matchSecret, String joinSecret, + String spectateSecret, boolean instance) + { + this.state = state; + this.details = details; + this.startTimestamp = startTimestamp; + this.endTimestamp = endTimestamp; + this.largeImageKey = largeImageKey; + this.largeImageText = largeImageText; + this.smallImageKey = smallImageKey; + this.smallImageText = smallImageText; + this.partyId = partyId; + this.partySize = partySize; + this.partyMax = partyMax; + this.matchSecret = matchSecret; + this.joinSecret = joinSecret; + this.spectateSecret = spectateSecret; + this.instance = instance; + } + + /** + * Constructs a {@link JSONObject} representing a payload to send to discord + * to update a user's Rich Presence. + * + *

This is purely internal, and should not ever need to be called outside of + * the library. + * + * @return A JSONObject payload for updating a user's Rich Presence. + */ + public JSONObject toJson() + { + return new JSONObject() + .put("state", state) + .put("details", details) + .put("timestamps", new JSONObject() + .put("start", startTimestamp==null ? null : startTimestamp.toEpochSecond()) + .put("end", endTimestamp==null ? null : endTimestamp.toEpochSecond())) + .put("assets", new JSONObject() + .put("large_image", largeImageKey) + .put("large_text", largeImageText) + .put("small_image", smallImageKey) + .put("small_text", smallImageText)) + .put("party", partyId==null ? null : new JSONObject() + .put("id", partyId) + .put("size", new JSONArray().put(partySize).put(partyMax))) + .put("secrets", new JSONObject() + .put("join", joinSecret) + .put("spectate", spectateSecret) + .put("match", matchSecret)) + .put("instance", instance); + } + + /** + * A chain builder for a {@link RichPresence} object. + * + *

An accurate description of each field and it's functions can be found + * here + */ + public static class Builder + { + private String state; + private String details; + private OffsetDateTime startTimestamp; + private OffsetDateTime endTimestamp; + private String largeImageKey; + private String largeImageText; + private String smallImageKey; + private String smallImageText; + private String partyId; + private int partySize; + private int partyMax; + private String matchSecret; + private String joinSecret; + private String spectateSecret; + private boolean instance; + + /** + * Builds the {@link RichPresence} from the current state of this builder. + * + * @return The RichPresence built. + */ + public RichPresence build() + { + return new RichPresence(state, details, startTimestamp, endTimestamp, + largeImageKey, largeImageText, smallImageKey, smallImageText, + partyId, partySize, partyMax, matchSecret, joinSecret, + spectateSecret, instance); + } + + /** + * Sets the state of the user's current party. + * + * @param state The state of the user's current party. + * + * @return This Builder. + */ + public Builder setState(String state) + { + this.state = state; + return this; + } + + /** + * Sets details of what the player is currently doing. + * + * @param details The details of what the player is currently doing. + * + * @return This Builder. + */ + public Builder setDetails(String details) + { + this.details = details; + return this; + } + + /** + * Sets the time that the player started a match or activity. + * + * @param startTimestamp The time the player started a match or activity. + * + * @return This Builder. + */ + public Builder setStartTimestamp(OffsetDateTime startTimestamp) + { + this.startTimestamp = startTimestamp; + return this; + } + + /** + * Sets the time that the player's current activity will end. + * + * @param endTimestamp The time the player's activity will end. + * + * @return This Builder. + */ + public Builder setEndTimestamp(OffsetDateTime endTimestamp) + { + this.endTimestamp = endTimestamp; + return this; + } + + /** + * Sets the key of the uploaded image for the large profile artwork, as well as + * the text tooltip shown when a cursor hovers over it. + * + *

These can be configured in the applications + * page on the discord website. + * + * @param largeImageKey A key to an image to display. + * @param largeImageText Text displayed when a cursor hovers over the large image. + * + * @return This Builder. + */ + public Builder setLargeImage(String largeImageKey, String largeImageText) + { + this.largeImageKey = largeImageKey; + this.largeImageText = largeImageText; + return this; + } + + /** + * Sets the key of the uploaded image for the large profile artwork. + * + *

These can be configured in the applications + * page on the discord website. + * + * @param largeImageKey A key to an image to display. + * + * @return This Builder. + */ + public Builder setLargeImage(String largeImageKey) + { + return setLargeImage(largeImageKey, null); + } + + /** + * Sets the key of the uploaded image for the small profile artwork, as well as + * the text tooltip shown when a cursor hovers over it. + * + *

These can be configured in the applications + * page on the discord website. + * + * @param smallImageKey A key to an image to display. + * @param smallImageText Text displayed when a cursor hovers over the small image. + * + * @return This Builder. + */ + public Builder setSmallImage(String smallImageKey, String smallImageText) + { + this.smallImageKey = smallImageKey; + this.smallImageText = smallImageText; + return this; + } + + /** + * Sets the key of the uploaded image for the small profile artwork. + * + *

These can be configured in the applications + * page on the discord website. + * + * @param smallImageKey A key to an image to display. + * + * @return This Builder. + */ + public Builder setSmallImage(String smallImageKey) + { + return setSmallImage(smallImageKey, null); + } + + /** + * Sets party configurations for a team, lobby, or other form of group. + * + *

The {@code partyId} is ID of the player's party. + *
The {@code partySize} is the current size of the player's party. + *
The {@code partyMax} is the maximum number of player's allowed in the party. + * + * @param partyId The ID of the player's party. + * @param partySize The current size of the player's party. + * @param partyMax The maximum number of player's allowed in the party. + * + * @return This Builder. + */ + public Builder setParty(String partyId, int partySize, int partyMax) + { + this.partyId = partyId; + this.partySize = partySize; + this.partyMax = partyMax; + return this; + } + + /** + * Sets the unique hashed string for Spectate and Join. + * + * @param matchSecret The unique hashed string for Spectate and Join. + * + * @return This Builder. + */ + public Builder setMatchSecret(String matchSecret) + { + this.matchSecret = matchSecret; + return this; + } + + /** + * Sets the unique hashed string for chat invitations and Ask to Join. + * + * @param joinSecret The unique hashed string for chat invitations and Ask to Join. + * + * @return This Builder. + */ + public Builder setJoinSecret(String joinSecret) + { + this.joinSecret = joinSecret; + return this; + } + + /** + * Sets the unique hashed string for Spectate button. + * + * @param spectateSecret The unique hashed string for Spectate button. + * + * @return This Builder. + */ + public Builder setSpectateSecret(String spectateSecret) + { + this.spectateSecret = spectateSecret; + return this; + } + + /** + * Marks the {@link #setMatchSecret(String) matchSecret} as a game + * session with a specific beginning and end. + * + * @param instance Whether or not the {@code matchSecret} is a game + * with a specific beginning and end. + * + * @return This Builder. + */ + public Builder setInstance(boolean instance) + { + this.instance = instance; + return this; + } + } +} diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/discord/User.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/discord/User.java new file mode 100644 index 00000000..45231079 --- /dev/null +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/discord/User.java @@ -0,0 +1,207 @@ +/* + * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod + * Copyright (C) 2023 cyoung06 (syeyoung) + * + * 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 . + */ +package kr.syeyoung.dungeonsguide.mod.discord; + + +public class User +{ + private final String name; + private final String discriminator; + private final long id; + private final String avatar; + /** + * Constructs a new {@link User}.
+ * Only implemented internally. + * @param name user's name + * @param discriminator user's discrim + * @param id user's id + * @param avatar user's avatar hash, or {@code null} if they have no avatar + */ + public User(String name, String discriminator, long id, String avatar) + { + this.name = name; + this.discriminator = discriminator; + this.id = id; + this.avatar = avatar; + } + + /** + * Gets the Users account name. + * + * @return The Users account name. + */ + public String getName() + { + return name; + } + + /** + * Gets the Users discriminator. + * + * @return The Users discriminator. + */ + public String getDiscriminator() + { + return discriminator; + } + + /** + * Gets the Users Snowflake ID as a {@code long}. + * + * @return The Users Snowflake ID as a {@code long}. + */ + public long getIdLong() + { + return id; + } + + /** + * Gets the Users Snowflake ID as a {@code String}. + * + * @return The Users Snowflake ID as a {@code String}. + */ + public String getId() + { + return Long.toString(id); + } + + /** + * Gets the Users avatar ID. + * + * @return The Users avatar ID. + */ + public String getAvatarId() + { + return avatar; + } + + /** + * Gets the Users avatar URL. + * + * @return The Users avatar URL. + */ + public String getAvatarUrl() + { + return getAvatarId() == null ? null : "https://cdn.discord.com/avatars/" + getId() + "/" + getAvatarId() + + (getAvatarId().startsWith("a_") ? ".gif" : ".png"); + } + + /** + * Gets the Users {@link DefaultAvatar} avatar ID. + * + * @return The Users {@link DefaultAvatar} avatar ID. + */ + public String getDefaultAvatarId() + { + return DefaultAvatar.values()[Integer.parseInt(getDiscriminator()) % DefaultAvatar.values().length].toString(); + } + + /** + * Gets the Users {@link DefaultAvatar} avatar URL. + * + * @return The Users {@link DefaultAvatar} avatar URL. + */ + public String getDefaultAvatarUrl() + { + return "https://discord.com/assets/" + getDefaultAvatarId() + ".png"; + } + + /** + * Gets the Users avatar URL, or their {@link DefaultAvatar} avatar URL if they + * do not have a custom avatar set on their account. + * + * @return The Users effective avatar URL. + */ + public String getEffectiveAvatarUrl() + { + return getAvatarUrl() == null ? getDefaultAvatarUrl() : getAvatarUrl(); + } + + /** + * Gets whether or not this User is a bot.

+ * + * While, at the time of writing this documentation, bots cannot + * use Rich Presence features, there may be a time in the future + * where they have such an ability. + * + * @return False + */ + public boolean isBot() + { + return false; //bots cannot use RPC + } + + /** + * Gets the User as a discord formatted mention.

+ * + * {@code <@SNOWFLAKE_ID> } + * + * @return A discord formatted mention of this User. + */ + public String getAsMention() + { + return "<@" + id + '>'; + } + + @Override + public boolean equals(Object o) + { + if (!(o instanceof User)) + return false; + User oUser = (User) o; + return this == oUser || this.id == oUser.id; + } + + @Override + public int hashCode() + { + return Long.hashCode(id); + } + + @Override + public String toString() + { + return "U:" + getName() + '(' + id + ')'; + } + + /** + * Constants representing one of five different + * default avatars a {@link User} can have. + */ + public enum DefaultAvatar + { + BLURPLE("6debd47ed13483642cf09e832ed0bc1b"), + GREY("322c936a8c8be1b803cd94861bdfa868"), + GREEN("dd4dbc0016779df1378e7812eabaa04d"), + ORANGE("0e291f67c9274a1abdddeb3fd919cbaa"), + RED("1cbd08c76f8af6dddce02c5138971129"); + + private final String text; + + DefaultAvatar(String text) + { + this.text = text; + } + + @Override + public String toString() + { + return text; + } + } +} diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/discord/gamesdk/GameSDK.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/discord/gamesdk/GameSDK.java deleted file mode 100644 index 0a48ad21..00000000 --- a/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/discord/gamesdk/GameSDK.java +++ /dev/null @@ -1,109 +0,0 @@ -/* - * 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 . - */ - -package kr.syeyoung.dungeonsguide.mod.discord.gamesdk; - -import com.sun.jna.*; -import kr.syeyoung.dungeonsguide.mod.discord.gamesdk.jna.GameSDKTypeMapper; -import kr.syeyoung.dungeonsguide.mod.discord.gamesdk.jna.N