aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rwxr-xr-xsrc/main/java/kr/syeyoung/dungeonsguide/DungeonsGuide.java9
-rw-r--r--src/main/java/kr/syeyoung/dungeonsguide/RichPresenceManager.java196
-rw-r--r--src/main/java/kr/syeyoung/dungeonsguide/commands/CommandDungeonsGuide.java21
-rw-r--r--src/main/java/kr/syeyoung/dungeonsguide/eventlistener/FeatureListener.java24
-rw-r--r--src/main/java/kr/syeyoung/dungeonsguide/events/DiscordUserJoinRequestEvent.java30
-rw-r--r--src/main/java/kr/syeyoung/dungeonsguide/events/DiscordUserUpdateEvent.java30
-rw-r--r--src/main/java/kr/syeyoung/dungeonsguide/features/FeatureRegistry.java8
-rw-r--r--src/main/java/kr/syeyoung/dungeonsguide/features/impl/discord/inviteViewer/ImageTexture.java120
-rw-r--r--src/main/java/kr/syeyoung/dungeonsguide/features/impl/discord/inviteViewer/PartyInviteViewer.java (renamed from src/main/java/kr/syeyoung/dungeonsguide/party/PartyInviteViewer.java)123
-rw-r--r--src/main/java/kr/syeyoung/dungeonsguide/features/impl/discord/inviteViewer/PartyJoinRequest.java (renamed from src/main/java/kr/syeyoung/dungeonsguide/party/PartyJoinRequest.java)26
-rw-r--r--src/main/java/kr/syeyoung/dungeonsguide/features/impl/discord/onlinealarm/PlayingDGAlarm.java171
-rw-r--r--src/main/java/kr/syeyoung/dungeonsguide/features/listener/DiscordUserJoinRequestListener.java26
-rw-r--r--src/main/java/kr/syeyoung/dungeonsguide/features/listener/DiscordUserUpdateListener.java25
-rw-r--r--src/main/java/kr/syeyoung/dungeonsguide/gamesdk/jna/datastruct/DiscordCreateParams.java25
-rw-r--r--src/main/java/kr/syeyoung/dungeonsguide/gamesdk/jna/interfacestruct/IDiscordRelationshipManager.java2
-rw-r--r--src/main/java/kr/syeyoung/dungeonsguide/party/LoadedImage.java40
-rw-r--r--src/main/java/kr/syeyoung/dungeonsguide/party/PartyManager.java3
-rw-r--r--src/main/java/kr/syeyoung/dungeonsguide/rpc/JDiscordActivity.java72
-rw-r--r--src/main/java/kr/syeyoung/dungeonsguide/rpc/JDiscordRelation.java42
-rw-r--r--src/main/java/kr/syeyoung/dungeonsguide/rpc/JDiscordUser.java40
-rw-r--r--src/main/java/kr/syeyoung/dungeonsguide/rpc/RichPresenceManager.java250
21 files changed, 942 insertions, 341 deletions
diff --git a/src/main/java/kr/syeyoung/dungeonsguide/DungeonsGuide.java b/src/main/java/kr/syeyoung/dungeonsguide/DungeonsGuide.java
index 48c392e0..c8c96940 100755
--- a/src/main/java/kr/syeyoung/dungeonsguide/DungeonsGuide.java
+++ b/src/main/java/kr/syeyoung/dungeonsguide/DungeonsGuide.java
@@ -28,14 +28,14 @@ import kr.syeyoung.dungeonsguide.eventlistener.FeatureListener;
import kr.syeyoung.dungeonsguide.eventlistener.PacketListener;
import kr.syeyoung.dungeonsguide.events.StompConnectedEvent;
import kr.syeyoung.dungeonsguide.features.FeatureRegistry;
-import kr.syeyoung.dungeonsguide.party.PartyInviteViewer;
+import kr.syeyoung.dungeonsguide.features.impl.discord.inviteViewer.PartyInviteViewer;
import kr.syeyoung.dungeonsguide.party.PartyManager;
import kr.syeyoung.dungeonsguide.resources.DGTexturePack;
+import kr.syeyoung.dungeonsguide.rpc.RichPresenceManager;
import kr.syeyoung.dungeonsguide.stomp.CloseListener;
import kr.syeyoung.dungeonsguide.stomp.StompClient;
import kr.syeyoung.dungeonsguide.stomp.StompInterface;
import kr.syeyoung.dungeonsguide.utils.AhUtils;
-import kr.syeyoung.dungeonsguide.utils.cursor.GLCursors;
import kr.syeyoung.dungeonsguide.wsresource.StaticResourceCache;
import lombok.Getter;
import net.minecraft.client.Minecraft;
@@ -44,12 +44,10 @@ import net.minecraft.launchwrapper.LaunchClassLoader;
import net.minecraft.util.IChatComponent;
import net.minecraftforge.client.ClientCommandHandler;
import net.minecraftforge.common.MinecraftForge;
-import net.minecraftforge.common.config.Configuration;
import net.minecraftforge.fml.common.ProgressManager;
import net.minecraftforge.fml.common.event.FMLInitializationEvent;
import net.minecraftforge.fml.common.event.FMLPreInitializationEvent;
import net.minecraftforge.fml.relauncher.ReflectionHelper;
-import org.apache.commons.io.IOUtils;
import javax.crypto.BadPaddingException;
import javax.crypto.IllegalBlockSizeException;
@@ -124,11 +122,10 @@ public class DungeonsGuide implements DGInterface, CloseListener {
MinecraftForge.EVENT_BUS.register(new PacketListener());
MinecraftForge.EVENT_BUS.register(new Keybinds());
- RichPresenceManager.INSTANCE.setup();
+ RichPresenceManager.INSTANCE.getLastSetupCode();
MinecraftForge.EVENT_BUS.register(RichPresenceManager.INSTANCE);
MinecraftForge.EVENT_BUS.register(PartyManager.INSTANCE);
MinecraftForge.EVENT_BUS.register(StaticResourceCache.INSTANCE);
- MinecraftForge.EVENT_BUS.register(PartyInviteViewer.INSTANCE);
AhUtils.registerTimer();
diff --git a/src/main/java/kr/syeyoung/dungeonsguide/RichPresenceManager.java b/src/main/java/kr/syeyoung/dungeonsguide/RichPresenceManager.java
deleted file mode 100644
index 7f02d69a..00000000
--- a/src/main/java/kr/syeyoung/dungeonsguide/RichPresenceManager.java
+++ /dev/null
@@ -1,196 +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 <https://www.gnu.org/licenses/>.
- */
-
-package kr.syeyoung.dungeonsguide;
-
-import com.sun.jna.Pointer;
-import com.sun.jna.ptr.PointerByReference;
-import kr.syeyoung.dungeonsguide.dungeon.DungeonContext;
-import kr.syeyoung.dungeonsguide.events.SkyblockJoinedEvent;
-import kr.syeyoung.dungeonsguide.events.SkyblockLeftEvent;
-import kr.syeyoung.dungeonsguide.features.FeatureRegistry;
-import kr.syeyoung.dungeonsguide.gamesdk.GameSDK;
-import kr.syeyoung.dungeonsguide.gamesdk.jna.NativeGameSDK;
-import kr.syeyoung.dungeonsguide.gamesdk.jna.datastruct.*;
-import kr.syeyoung.dungeonsguide.gamesdk.jna.enumuration.EDiscordActivityActionType;
-import kr.syeyoung.dungeonsguide.gamesdk.jna.enumuration.EDiscordActivityJoinRequestReply;
-import kr.syeyoung.dungeonsguide.gamesdk.jna.enumuration.EDiscordLogLevel;
-import kr.syeyoung.dungeonsguide.gamesdk.jna.enumuration.EDiscordResult;
-import kr.syeyoung.dungeonsguide.gamesdk.jna.interfacestruct.IDiscordActivityEvents;
-import kr.syeyoung.dungeonsguide.gamesdk.jna.interfacestruct.IDiscordActivityManager;
-import kr.syeyoung.dungeonsguide.gamesdk.jna.interfacestruct.IDiscordCore;
-import kr.syeyoung.dungeonsguide.gamesdk.jna.typedef.*;
-import kr.syeyoung.dungeonsguide.party.PartyInviteViewer;
-import kr.syeyoung.dungeonsguide.party.PartyJoinRequest;
-import kr.syeyoung.dungeonsguide.party.PartyManager;
-import kr.syeyoung.dungeonsguide.stomp.StompHeader;
-import kr.syeyoung.dungeonsguide.stomp.StompPayload;
-import lombok.Getter;
-import net.minecraftforge.fml.common.eventhandler.SubscribeEvent;
-import net.minecraftforge.fml.common.gameevent.TickEvent;
-import org.json.JSONObject;
-
-public class RichPresenceManager implements Runnable {
- public static RichPresenceManager INSTANCE = new RichPresenceManager();
- private Thread t = new Thread(this);
-
- public RichPresenceManager() {
- t.start();
- }
- @Getter
- private NativeGameSDK nativeGameSDK;
- @Getter
- private IDiscordCore iDiscordCore;
- private IDiscordActivityManager activityManager;
- private IDiscordActivityEvents.ByReference callbacks;
-
- @Getter
- private boolean setupSuccessful = false;
- public boolean setup() {
- nativeGameSDK = GameSDK.getNativeGameSDK();
- if (nativeGameSDK == null) return false;
- DiscordCreateParams discordCreateParams = new DiscordCreateParams();
- discordCreateParams.client_id = new DiscordClientID(816298079732498473L);
-
- callbacks = new IDiscordActivityEvents.ByReference();
- callbacks.OnActivityInvite = (eventData, type, user, activity) -> {
- PartyJoinRequest partyJoinRequest = new PartyJoinRequest();
- partyJoinRequest.setDiscordUser(user);
- partyJoinRequest.setExpire(System.currentTimeMillis() + 30000);
- partyJoinRequest.setInvite(true);
-
- PartyInviteViewer.INSTANCE.joinRequests.add(partyJoinRequest);
- System.out.println("Received Join Request from "+user.id.longValue()+" ("+partyJoinRequest.getUsername()+"#"+partyJoinRequest.getDiscriminator()+")");
- };
- callbacks.OnActivityJoin = (eventData, secret) -> {DungeonsGuide.getDungeonsGuide().getStompConnection().send(new StompPayload().method(StompHeader.SEND)
- .header("destination", "/app/party.askedtojoin")
- .payload(new JSONObject().put("token", secret).toString()));
- System.out.println("Trying to join with token "+secret);
- };
- callbacks.OnActivityJoinRequest = (eventData, user) -> {
- PartyJoinRequest partyJoinRequest = new PartyJoinRequest();
- partyJoinRequest.setDiscordUser(user);
- partyJoinRequest.setExpire(System.currentTimeMillis() + 30000);
-
- PartyInviteViewer.INSTANCE.joinRequests.add(partyJoinRequest);
- System.out.println("Received Join Request from "+user.id.longValue()+" ("+partyJoinRequest.getUsername()+"#"+partyJoinRequest.getDiscriminator()+")");
- };
- callbacks.OnActivitySpectate = (eventData, secret) -> {
-
- };
- callbacks.write();
- discordCreateParams.activity_events = callbacks;
-
- PointerByReference pointerByReference = new PointerByReference();
- nativeGameSDK.DiscordCreate(new DiscordVersion(NativeGameSDK.DISCORD_VERSION), discordCreateParams, pointerByReference);
- if (pointerByReference.getValue() == Pointer.NULL) return false;
- iDiscordCore = new IDiscordCore(pointerByReference.getValue());
-
- iDiscordCore.SetLogHook.setLogHook(iDiscordCore, EDiscordLogLevel.DiscordLogLevel_Debug, Pointer.NULL, new IDiscordCore.LogHook() {
- @Override
- public void hook(Pointer hookData, EDiscordLogLevel level, String message) {
- System.out.println(message+" - "+level+" - "+hookData);
- }
- });
-
- activityManager = iDiscordCore.GetActivityManager.getActivityManager(iDiscordCore);
- latestDiscordActivity = new DiscordActivity();
- latestDiscordActivity.assets = new DiscordActivityAssets();
- latestDiscordActivity.secrets = new DiscordActivitySecrets();
- latestDiscordActivity.party = new DiscordActivityParty();
- latestDiscordActivity.party.discordActivityParty = new DiscordPartySize();
- latestDiscordActivity.timestamps = new DiscordActivityTimestamps();
- GameSDK.writeString(latestDiscordActivity.assets.large_image, "mort");
- GameSDK.writeString(latestDiscordActivity.assets.large_text, "mort");
-
- return true;
- }
-
- private final SkyblockStatus skyblockStatus = DungeonsGuide.getDungeonsGuide().getSkyblockStatus();
-
- private DiscordActivity latestDiscordActivity;
-
- public void respond(DiscordSnowflake userID, EDiscordActivityJoinRequestReply reply) {
- activityManager.SendRequestReply.sendRequestReply(activityManager, userID, reply, Pointer.NULL, (callbackData, result) -> {
- System.out.println("Discord Returned "+result+" For Replying "+reply+" To "+userID.longValue()+"L");
- });
- }
-
- public void accept(DiscordSnowflake userID) {
- activityManager.AcceptInvite.acceptInvite(activityManager, userID, Pointer.NULL, (callbackData, result) -> {
- System.out.println("Discord Returned "+result+" For Accepting invite from "+userID.longValue()+"L");
- });
- }
- public void updatePresence() {
- if (!skyblockStatus.isOnHypixel() || !FeatureRegistry.ADVANCED_RICHPRESENCE.isEnabled() || (!skyblockStatus.isOnSkyblock() && FeatureRegistry.ADVANCED_RICHPRESENCE.<Boolean>getParameter("disablenotskyblock").getValue())) {
- activityManager.ClearActivity.clearActivity(activityManager, Pointer.NULL, new NativeGameSDK.DiscordCallback() {
- @Override
- public void callback(Pointer callbackData, EDiscordResult result) {
- }
- });
- } else {
- String name = skyblockStatus.getDungeonName();
- if (name.trim().equals("Your Island")) name = "Private Island";
-
- GameSDK.writeString(latestDiscordActivity.state, name);
-
-
- GameSDK.writeString(latestDiscordActivity.party.id, PartyManager.INSTANCE.getPartyID() == null ? "" : PartyManager.INSTANCE.getPartyID());
- latestDiscordActivity.party.discordActivityParty.current_size = new Int32(PartyManager.INSTANCE.getMemberCount());
- latestDiscordActivity.party.discordActivityParty.max_size = new Int32(PartyManager.INSTANCE.getMaxParty());
-
- if (skyblockStatus.getContext() != null) {
- DungeonContext dungeonContext = skyblockStatus.getContext();
- long init = dungeonContext.getInit();
- latestDiscordActivity.timestamps.start = new DiscordTimestamp(init);
-
- if (dungeonContext.getBossfightProcessor() != null) {
- GameSDK.writeString(latestDiscordActivity.details, "Fighting "+dungeonContext.getBossfightProcessor().getBossName()+": "+dungeonContext.getBossfightProcessor().getCurrentPhase());
- } else {
- GameSDK.writeString(latestDiscordActivity.details, "Clearing Rooms");
- }
- } else {
- latestDiscordActivity.timestamps.start = new DiscordTimestamp(0);
- GameSDK.writeString(latestDiscordActivity.details, "Dungeons Guide");
- }
- if (PartyManager.INSTANCE.isAllowAskToJoin()) {
- GameSDK.writeString(latestDiscordActivity.secrets.join, PartyManager.INSTANCE.getAskToJoinSecret());
- } else {
- GameSDK.writeString(latestDiscordActivity.secrets.join, "");
- }
- activityManager.UpdateActivity.updateActivity(activityManager, latestDiscordActivity, Pointer.NULL, new NativeGameSDK.DiscordCallback() {
- @Override
- public void callback(Pointer callbackData, EDiscordResult result) {
- }
- });
- }
- }
-
- @Override
- public void run() {
- setupSuccessful = setup();
- if (!setupSuccessful) return;
- while(!Thread.interrupted()) {
- try {
- iDiscordCore.RunCallbacks.runCallbacks(iDiscordCore);
- updatePresence();
- Thread.sleep(300L);
- } catch (Exception e) {e.printStackTrace();}
- }
- }
-}
diff --git a/src/main/java/kr/syeyoung/dungeonsguide/commands/CommandDungeonsGuide.java b/src/main/java/kr/syeyoung/dungeonsguide/commands/CommandDungeonsGuide.java
index d2960b2a..d7759f92 100644
--- a/src/main/java/kr/syeyoung/dungeonsguide/commands/CommandDungeonsGuide.java
+++ b/src/main/java/kr/syeyoung/dungeonsguide/commands/CommandDungeonsGuide.java
@@ -20,6 +20,8 @@ package kr.syeyoung.dungeonsguide.commands;
import com.google.gson.JsonObject;
import kr.syeyoung.dungeonsguide.DungeonsGuide;
+import kr.syeyoung.dungeonsguide.rpc.JDiscordRelation;
+import kr.syeyoung.dungeonsguide.rpc.RichPresenceManager;
import kr.syeyoung.dungeonsguide.SkyblockStatus;
import kr.syeyoung.dungeonsguide.config.guiconfig.GuiConfigV2;
import kr.syeyoung.dungeonsguide.config.guiconfig.NestedCategory;
@@ -39,7 +41,7 @@ import kr.syeyoung.dungeonsguide.features.AbstractFeature;
import kr.syeyoung.dungeonsguide.features.FeatureRegistry;
import kr.syeyoung.dungeonsguide.features.impl.party.playerpreview.FeatureViewPlayerOnJoin;
import kr.syeyoung.dungeonsguide.features.impl.party.api.ApiFetchur;
-import kr.syeyoung.dungeonsguide.party.PartyInviteViewer;
+import kr.syeyoung.dungeonsguide.features.impl.discord.inviteViewer.PartyInviteViewer;
import kr.syeyoung.dungeonsguide.party.PartyManager;
import kr.syeyoung.dungeonsguide.roomedit.EditingContext;
import kr.syeyoung.dungeonsguide.roomedit.gui.GuiDungeonRoomEdit;
@@ -327,8 +329,11 @@ public class CommandDungeonsGuide extends CommandBase {
sender.addChatMessage(new ChatComponentText("§eDungeons Guide §7:: §fToggled Ask to join to " + (PartyManager.INSTANCE.isAllowAskToJoin() ? "§eon" : "§coff")));
}
- if (!FeatureRegistry.ADVANCED_RICHPRESENCE.isEnabled()) {
- sender.addChatMessage(new ChatComponentText("§eDungeons Guide §7:: §cDiscord Rich Presence is disabled! Enable at /dg -> Advanced "));
+ if (!FeatureRegistry.DISCORD_RICHPRESENCE.isEnabled()) {
+ sender.addChatMessage(new ChatComponentText("§eDungeons Guide §7:: §cDiscord Rich Presence is disabled! Enable at /dg -> Discord "));
+ }
+ if (!FeatureRegistry.DISCORD_ASKTOJOIN.isEnabled()) {
+ sender.addChatMessage(new ChatComponentText("§eDungeons Guide §7:: §cDiscord Invite Viewer is disabled! Enable at /dg -> Discord ")); // how
}
} else if (args[0].equalsIgnoreCase("partymax") || args[0].equalsIgnoreCase("pm")) {
if (args.length == 1) {
@@ -396,8 +401,8 @@ public class CommandDungeonsGuide extends CommandBase {
cosmeticsManager.requestCosmeticsList();
cosmeticsManager.requestActiveCosmetics();
StaticResourceCache.INSTANCE.purgeCache();
- PartyInviteViewer.INSTANCE.imageMap.clear();
- PartyInviteViewer.INSTANCE.futureMap.clear();
+ FeatureRegistry.DISCORD_ASKTOJOIN.imageMap.clear();
+ FeatureRegistry.DISCORD_ASKTOJOIN.futureMap.clear();
sender.addChatMessage(new ChatComponentText("§eDungeons Guide §7:: §fSuccessfully purged API Cache!"));
} else if (args[0].equals("pbroadcast")) {
@@ -533,7 +538,11 @@ public class CommandDungeonsGuide extends CommandBase {
}
System.out.println(stringBuilder.toString());
System.out.println(stringBuilder2.toString());
- } else {
+ } else if (args[0].equals("IDKTEST")) {
+ for (Map.Entry<Long, JDiscordRelation> longJDiscordRelationEntry : RichPresenceManager.INSTANCE.getRelationMap().entrySet()) {
+ System.out.println(longJDiscordRelationEntry.getValue());
+ }
+ } else{
sender.addChatMessage(new ChatComponentText("§eDungeons Guide §7:: §e/dg §7-§fOpens configuration gui"));
sender.addChatMessage(new ChatComponentText("§eDungeons Guide §7:: §e/dg gui §7-§fOpens configuration gui"));
sender.addChatMessage(new ChatComponentText("§eDungeons Guide §7:: §e/dg help §7-§fShows command help"));
diff --git a/src/main/java/kr/syeyoung/dungeonsguide/eventlistener/FeatureListener.java b/src/main/java/kr/syeyoung/dungeonsguide/eventlistener/FeatureListener.java
index ab7eae21..20aeb460 100644
--- a/src/main/java/kr/syeyoung/dungeonsguide/eventlistener/FeatureListener.java
+++ b/src/main/java/kr/syeyoung/dungeonsguide/eventlistener/FeatureListener.java
@@ -92,6 +92,30 @@ public class FeatureListener {
}
}
@SubscribeEvent
+ public void onDiscordUserUpdate(DiscordUserUpdateEvent discordUserUpdateEvent) {
+ try {
+ for (AbstractFeature abstractFeature : FeatureRegistry.getFeatureList()) {
+ if (abstractFeature instanceof DiscordUserUpdateListener) {
+ ((DiscordUserUpdateListener) abstractFeature).onDiscordUserUpdate(discordUserUpdateEvent);
+ }
+ }
+ } catch (Throwable t) {
+ t.printStackTrace();
+ }
+ }
+ @SubscribeEvent
+ public void onDiscordUserUpdate(DiscordUserJoinRequestEvent discordUserUpdateEvent) {
+ try {
+ for (AbstractFeature abstractFeature : FeatureRegistry.getFeatureList()) {
+ if (abstractFeature instanceof DiscordUserJoinRequestListener) {
+ ((DiscordUserJoinRequestListener) abstractFeature).onDiscordUserJoinRequest(discordUserUpdateEvent);
+ }
+ }
+ } catch (Throwable t) {
+ t.printStackTrace();
+ }
+ }
+ @SubscribeEvent
public void onWindowUpdate(WindowUpdateEvent windowUpdateEvent) {
try {
SkyblockStatus skyblockStatus = DungeonsGuide.getDungeonsGuide().getSkyblockStatus();
diff --git a/src/main/java/kr/syeyoung/dungeonsguide/events/DiscordUserJoinRequestEvent.java b/src/main/java/kr/syeyoung/dungeonsguide/events/DiscordUserJoinRequestEvent.java
new file mode 100644
index 00000000..80a9315a
--- /dev/null
+++ b/src/main/java/kr/syeyoung/dungeonsguide/events/DiscordUserJoinRequestEvent.java
@@ -0,0 +1,30 @@
+/*
+ * 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.events;
+
+import kr.syeyoung.dungeonsguide.gamesdk.jna.datastruct.DiscordUser;
+import lombok.AllArgsConstructor;
+import lombok.Data;
+import net.minecraftforge.fml.common.eventhandler.Event;
+
+@Data @AllArgsConstructor
+public class DiscordUserJoinRequestEvent extends Event {
+ private DiscordUser discordUser;
+ private boolean isInvite;
+}
diff --git a/src/main/java/kr/syeyoung/dungeonsguide/events/DiscordUserUpdateEvent.java b/src/main/java/kr/syeyoung/dungeonsguide/events/DiscordUserUpdateEvent.java
new file mode 100644
index 00000000..f737b598
--- /dev/null
+++ b/src/main/java/kr/syeyoung/dungeonsguide/events/DiscordUserUpdateEvent.java
@@ -0,0 +1,30 @@
+/*
+ * 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.events;
+
+import kr.syeyoung.dungeonsguide.rpc.JDiscordRelation;
+import kr.syeyoung.dungeonsguide.rpc.JDiscordUser;
+import lombok.AllArgsConstructor;
+import lombok.Data;
+import net.minecraftforge.fml.common.eventhandler.Event;
+
+@Data @AllArgsConstructor
+public class DiscordUserUpdateEvent extends Event {
+ private JDiscordRelation prev, current;
+}
diff --git a/src/main/java/kr/syeyoung/dungeonsguide/features/FeatureRegistry.java b/src/main/java/kr/syeyoung/dungeonsguide/features/FeatureRegistry.java
index ee81ee2f..55e2753b 100644
--- a/src/main/java/kr/syeyoung/dungeonsguide/features/FeatureRegistry.java
+++ b/src/main/java/kr/syeyoung/dungeonsguide/features/FeatureRegistry.java
@@ -28,6 +28,8 @@ import kr.syeyoung.dungeonsguide.features.impl.boss.terminal.FeatureSimonSaysSol
import kr.syeyoung.dungeonsguide.features.impl.boss.terminal.FeatureTerminalSolvers;
import kr.syeyoung.dungeonsguide.features.impl.cosmetics.FeatureNicknameColor;
import kr.syeyoung.dungeonsguide.features.impl.cosmetics.FeatureNicknamePrefix;
+import kr.syeyoung.dungeonsguide.features.impl.discord.inviteViewer.PartyInviteViewer;
+import kr.syeyoung.dungeonsguide.features.impl.discord.onlinealarm.PlayingDGAlarm;
import kr.syeyoung.dungeonsguide.features.impl.dungeon.*;
import kr.syeyoung.dungeonsguide.features.impl.etc.*;
import kr.syeyoung.dungeonsguide.features.impl.etc.ability.FeatureAbilityCooldown;
@@ -76,11 +78,15 @@ public class FeatureRegistry {
public static final FeatureRoomDebugInfo ADVANCED_DEBUG_ROOM = register(new FeatureRoomDebugInfo());
public static final FeatureDebuggableMap ADVANCED_DEBUGGABLE_MAP = register(new FeatureDebuggableMap());
public static final FeatureRoomCoordDisplay ADVANCED_COORDS = register(new FeatureRoomCoordDisplay());
- public static final SimpleFeature ADVANCED_RICHPRESENCE = register(new SimpleFeature("Misc", "Discord RPC", "Discord rich presence with ASK-TO-JOIN Support!\n\nSimply type /dg asktojoin or /dg atj to toggle whether ask-to-join would be presented as option on discord!", "advanced.richpresence", true) {
+
+ public static final SimpleFeature DISCORD_RICHPRESENCE = register(new SimpleFeature("Discord", "Discord RPC", "Enable Discord rich presence", "advanced.richpresence", true) {
{
parameters.put("disablenotskyblock", new FeatureParameter<Boolean>("disablenotskyblock", "Disable When not on Skyblock", "Disable When not on skyblock", false, "boolean"));
}
});
+ public static final PartyInviteViewer DISCORD_ASKTOJOIN = register(new PartyInviteViewer());
+ public static final PlayingDGAlarm DISCORD_ONLINEALARM = register(new PlayingDGAlarm());
+
public static final SimpleFeature SOLVER_RIDDLE = register(new SimpleFeature("Solver.Any Floor", "Riddle", "Highlights the correct box after clicking on all 3 weirdos", "solver.riddle"));
public static final SimpleFeature SOLVER_KAHOOT = register(new SimpleFeature("Solver.Floor 4+", "Quiz", "Highlights the correct solution for trivia puzzle", "solver.trivia"));
diff --git a/src/main/java/kr/syeyoung/dungeonsguide/features/impl/discord/inviteViewer/ImageTexture.java b/src/main/java/kr/syeyoung/dungeonsguide/features/impl/discord/inviteViewer/ImageTexture.java
new file mode 100644
index 00000000..62ee2913
--- /dev/null
+++ b/src/main/java/kr/syeyoung/dungeonsguide/features/impl/discord/inviteViewer/ImageTexture.java
@@ -0,0 +1,120 @@
+/*
+ * 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.features.impl.discord.inviteViewer;
+
+
+import lombok.Data;
+import lombok.Getter;
+import lombok.Setter;
+import net.minecraft.client.Minecraft;
+import net.minecraft.client.gui.Gui;
+import net.minecraft.client.renderer.GlStateManager;
+import net.minecraft.client.renderer.Tessellator;
+import net.minecraft.client.renderer.WorldRenderer;
+import net.minecraft.client.renderer.texture.DynamicTexture;
+import net.minecraft.client.renderer.texture.TextureManager;
+import net.minecraft.client.renderer.vertex.DefaultVertexFormats;
+import net.minecraft.util.ResourceLocation;
+
+import javax.imageio.ImageIO;
+import javax.imageio.ImageReader;
+import javax.imageio.stream.ImageInputStream;
+import java.awt.*;
+import java.awt.image.BufferedImage;
+import java.io.IOException;
+import java.net.HttpURLConnection;
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.util.Iterator;
+
+@Data
+public class ImageTexture {
+ private String url;
+ private BufferedImage image;
+ private DynamicTexture previewTexture;
+ private ResourceLocation resourceLocation;
+
+ private int width;
+ private int height;
+ private int frames;
+ private int size;
+
+ @Getter @Setter
+ private int lastFrame = 0;
+
+ public void buildGLThings() {
+ previewTexture = new DynamicTexture(image);
+ resourceLocation = Minecraft.getMinecraft().getTextureManager().getDynamicTextureLocation("dgurl/"+url, previewTexture);
+ }
+
+ public ImageTexture(String url) throws IOException {
+ this.url = url;
+
+ URL urlObj = new URL(url);
+ HttpURLConnection huc = (HttpURLConnection) urlObj.openConnection();
+ huc.addRequestProperty("User-Agent", "DungeonsGuideMod (dungeons.guide, 1.0)");
+ ImageInputStream imageInputStream = ImageIO.createImageInputStream(huc.getInputStream());
+ Iterator<ImageReader> readers = ImageIO.getImageReaders(imageInputStream);
+ if(!readers.hasNext()) throw new IOException("No image reader what" + url);
+ ImageReader reader = readers.next();
+ reader.setInput(imageInputStream);
+ frames = reader.getNumImages(true);
+ BufferedImage dummyFrame = reader.read(0);
+ width = dummyFrame.getWidth(); height = dummyFrame.getHeight();
+
+
+ image = new BufferedImage(width, height * frames, dummyFrame.getType());
+ Graphics2D graphics2D = image.createGraphics();
+
+ for (int i = 0; i < frames; i++) {
+ BufferedImage bufferedImage = reader.read(i);
+ graphics2D.drawImage(bufferedImage, 0, i*height, null);
+ }
+ reader.dispose(); imageInputStream.close(); huc.disconnect();
+ }
+
+ public void drawFrame(int frame, int x, int y, int width, int height) {
+ if (getResourceLocation() == null)
+ buildGLThings();
+
+ TextureManager textureManager = Minecraft.getMinecraft().getTextureManager();
+ textureManager.bindTexture(getResourceLocation());
+
+ GlStateManager.color(1, 1, 1, 1.0F);
+
+ Tessellator tessellator = Tessellator.getInstance();
+ WorldRenderer worldrenderer = tessellator.getWorldRenderer();
+ worldrenderer.begin(7, DefaultVertexFormats.POSITION_TEX);
+ worldrenderer.pos((double)x, (double)(y + height), 0.0D)
+ .tex(0,((frame+1) * height)/ ((double)frames * height)).endVertex();
+ worldrenderer.pos((double)(x + width), (double)(y + height), 0.0D)
+ .tex(1, ((frame+1) * height)/ ((double)frames * height)).endVertex();
+ worldrenderer.pos((double)(x + width), (double)y, 0.0D)
+ .tex(1,(frame * height)/ ((double)frames * height)).endVertex();
+ worldrenderer.pos((double)x, (double)y, 0.0D)
+ .tex(0, (frame * height) / ((double)frames * height)).endVertex();
+ tessellator.draw();
+ }
+
+ public void drawFrameAndIncrement(int x, int y, int width, int height) {
+ drawFrame(lastFrame, x,y,width,height);
+ lastFrame++;
+ if (lastFrame >= frames) lastFrame = 0;
+ }
+}
diff --git a/src/main/java/kr/syeyoung/dungeonsguide/party/PartyInviteViewer.java b/src/main/java/kr/syeyoung/dungeonsguide/features/impl/discord/inviteViewer/PartyInviteViewer.java
index 8dbdf2bb..6676eae2 100644
--- a/src/main/java/kr/syeyoung/dungeonsguide/party/PartyInviteViewer.java
+++ b/src/main/java/kr/syeyoung/dungeonsguide/features/impl/discord/inviteViewer/PartyInviteViewer.java
@@ -1,25 +1,28 @@
/*
- * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod
- * Copyright (C) 2021 cyoung06
+ * 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 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.
+ * 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/>.
+ * 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.party;
+package kr.syeyoung.dungeonsguide.features.impl.discord.inviteViewer;
import kr.syeyoung.dungeonsguide.DungeonsGuide;
-import kr.syeyoung.dungeonsguide.RichPresenceManager;
+import kr.syeyoung.dungeonsguide.events.DiscordUserJoinRequestEvent;
+import kr.syeyoung.dungeonsguide.features.SimpleFeature;
+import kr.syeyoung.dungeonsguide.features.listener.*;
+import kr.syeyoung.dungeonsguide.rpc.RichPresenceManager;
import kr.syeyoung.dungeonsguide.gamesdk.jna.enumuration.EDiscordActivityJoinRequestReply;
import kr.syeyoung.dungeonsguide.utils.TextUtils;
import net.minecraft.client.Minecraft;
@@ -27,13 +30,8 @@ import net.minecraft.client.gui.FontRenderer;
import net.minecraft.client.gui.Gui;
import net.minecraft.client.gui.ScaledResolution;
import net.minecraft.client.renderer.GlStateManager;
-import net.minecraft.client.renderer.OpenGlHelper;
import net.minecraft.client.renderer.texture.TextureManager;
import net.minecraftforge.client.event.GuiScreenEvent;
-import net.minecraftforge.client.event.RenderGameOverlayEvent;
-import net.minecraftforge.fml.common.eventhandler.EventPriority;
-import net.minecraftforge.fml.common.eventhandler.SubscribeEvent;
-import net.minecraftforge.fml.common.gameevent.TickEvent;
import org.lwjgl.input.Mouse;
import org.lwjgl.opengl.GL11;
import org.lwjgl.opengl.GL14;
@@ -47,29 +45,32 @@ import java.util.*;
import java.util.List;
import java.util.concurrent.*;
-public class PartyInviteViewer {
- public static final PartyInviteViewer INSTANCE = new PartyInviteViewer();
+public class PartyInviteViewer extends SimpleFeature implements GuiPostRenderListener, ScreenRenderListener, TickListener, GuiClickListener, DiscordUserJoinRequestListener {
+ public PartyInviteViewer() {
+ super("Discord", "Party Invite Viewer","Simply type /dg asktojoin or /dg atj to toggle whether ask-to-join would be presented as option on discord!\n\nRequires Discord RPC to be enabled", "discord.party_invite_viewer");
+ }
- @SubscribeEvent
- public void onRender(RenderGameOverlayEvent.Post postRender) {
- try {
- if (postRender.type == RenderGameOverlayEvent.ElementType.TEXT) {
- renderRequests(false);
- }
- } catch (Throwable t) {
- t.printStackTrace();
- }
+ @Override
+ public boolean isDisyllable() {
+ return false;
}
- @SubscribeEvent
- public void onRender(GuiScreenEvent.DrawScreenEvent.Post postRender) {
+ @Override
+ public void onGuiPostRender(GuiScreenEvent.DrawScreenEvent.Post rendered) {
renderRequests(true);
}
- @SubscribeEvent
- public void onTick(TickEvent.ClientTickEvent clientTickEvent) {
+ @Override
+ public void drawScreen(float partialTicks) {
+ try {
+ renderRequests(false);
+ } catch (Throwable t) {
+ t.printStackTrace();
+ }
+ }
+ @Override
+ public void onTick() {
try {
- if (clientTickEvent.phase != TickEvent.Phase.START) return;
List<PartyJoinRequest> partyJoinRequestList = new ArrayList<>();
boolean isOnHypixel = DungeonsGuide.getDungeonsGuide().getSkyblockStatus().isOnHypixel();
for (PartyJoinRequest joinRequest:joinRequests) {
@@ -90,14 +91,13 @@ public class PartyInviteViewer {
}
-
- @SubscribeEvent(receiveCanceled = true, priority = EventPriority.HIGH)
- public void onRender(GuiScreenEvent.MouseInputEvent.Pre mouseInput) {
+ @Override
+ public void onMouseInput(GuiScreenEvent.MouseInputEvent.Pre mouseInputEvent) {
int mouseX = Mouse.getX();
int mouseY = Minecraft.getMinecraft().displayHeight - Mouse.getY() +3;
for (PartyJoinRequest joinRequest:joinRequests) {
if (joinRequest.getWholeRect() != null && joinRequest.getWholeRect().contains(mouseX, mouseY)) {
- mouseInput.setCanceled(true);
+ mouseInputEvent.setCanceled(true);
if (Mouse.getEventButton() == -1) return;
@@ -148,29 +148,21 @@ public class PartyInviteViewer {
}
+
public CopyOnWriteArrayList<PartyJoinRequest> joinRequests = new CopyOnWriteArrayList<>();
ExecutorService executorService = Executors.newFixedThreadPool(3);
- public Map<String, Future<LoadedImage>> futureMap = new HashMap<>();
- public Map<String, LoadedImage> imageMap = new HashMap<>();
+ public Map<String, Future<ImageTexture>> futureMap = new HashMap<>();
+ public Map<String, ImageTexture> imageMap = new HashMap<>();
- public Future<LoadedImage> loadImage(String url) {
+ public Future<ImageTexture> loadImage(String url) {
if (imageMap.containsKey(url)) return CompletableFuture.completedFuture(imageMap.get(url));
if (futureMap.containsKey(url)) return futureMap.get(url);
- Future<LoadedImage> future = executorService.submit(() -> {
+ Future<ImageTexture> future = executorService.submit(() -> {
try {
- URL urlObj = new URL(url);
- HttpURLConnection huc = (HttpURLConnection) urlObj.openConnection();
- huc.addRequestProperty("User-Agent", "DungeonsGuideMod (dungeons.guide, 1.0)");
- BufferedImage bufferedImage = ImageIO.read(huc.getInputStream());
- BufferedImage newImage = new BufferedImage(128,128, BufferedImage.TYPE_INT_RGB);
- Graphics g = newImage.createGraphics();
- g.drawImage(bufferedImage, 0, 0, 128, 128, null);
- g.dispose();
- LoadedImage loadedImage = new LoadedImage();
- loadedImage.setImage(newImage);
- imageMap.put(url, loadedImage);
- return loadedImage;
+ ImageTexture imageTexture = new ImageTexture(url);
+ imageMap.put(url, imageTexture);
+ return imageTexture;
} catch (Exception e) {
throw e;
}
@@ -217,8 +209,8 @@ public class PartyInviteViewer {
Gui.drawRect(2, 2, width-2, height-2, 0XFF2c2f33);
{
String avatar = "https://cdn.discordapp.com/avatars/"+Long.toUnsignedString(partyJoinRequest.getDiscordUser().id.longValue())+"/"+partyJoinRequest.getAvatar()+"."+(partyJoinRequest.getAvatar().startsWith("a_") ? "gif":"png");
- Future<LoadedImage> loadedImageFuture = loadImage(avatar);
- LoadedImage loadedImage = null;
+ Future<ImageTexture> loadedImageFuture = loadImage(avatar);
+ ImageTexture loadedImage = null;
if (loadedImageFuture.isDone()) {
try {
loadedImage = loadedImageFuture.get();
@@ -227,13 +219,7 @@ public class PartyInviteViewer {
}
}
if (loadedImage != null) {
- if (loadedImage.getResourceLocation() == null) loadedImage.buildGLThings();
- TextureManager textureManager = Minecraft.getMinecraft().getTextureManager();
- textureManager.bindTexture(loadedImage.getResourceLocation());
-
- GlStateManager.color(1, 1, 1, 1.0F);
-
- Gui.drawScaledCustomSizeModalRect(7, 7, 0, 0, loadedImage.getImage().getWidth(),loadedImage.getImage().getHeight(),height-14,height-14, loadedImage.getImage().getWidth(), loadedImage.getImage().getHeight());
+ loadedImage.drawFrameAndIncrement( 7,7,height-14,height-14);
} else {
Gui.drawRect(7, 7, height - 7, height-7, 0xFF4E4E4E);
}
@@ -320,4 +306,13 @@ public class PartyInviteViewer {
}
GlStateManager.popMatrix();
}
+
+ @Override
+ public void onDiscordUserJoinRequest(DiscordUserJoinRequestEvent event) {
+ PartyJoinRequest partyInvite = new PartyJoinRequest();
+ partyInvite.setDiscordUser(event.getDiscordUser());
+ partyInvite.setExpire(System.currentTimeMillis() + 30000L);
+ partyInvite.setInvite(event.isInvite());
+ joinRequests.add(partyInvite);
+ }
}
diff --git a/src/main/java/kr/syeyoung/dungeonsguide/party/PartyJoinRequest.java b/src/main/java/kr/syeyoung/dungeonsguide/features/impl/discord/inviteViewer/PartyJoinRequest.java
index a894ee4e..b95da68a 100644
--- a/src/main/java/kr/syeyoung/dungeonsguide/party/PartyJoinRequest.java
+++ b/src/main/java/kr/syeyoung/dungeonsguide/features/impl/discord/inviteViewer/PartyJoinRequest.java
@@ -1,22 +1,22 @@
/*
- * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod
- * Copyright (C) 2021 cyoung06
+ * 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 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.
+ * 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/>.
+ * 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.party;
+package kr.syeyoung.dungeonsguide.features.impl.discord.inviteViewer;
import kr.syeyoung.dungeonsguide.gamesdk.GameSDK;
import kr.syeyoung.dungeonsguide.gamesdk.jna.datastruct.DiscordUser;
diff --git a/src/main/java/kr/syeyoung/dungeonsguide/features/impl/discord/onlinealarm/PlayingDGAlarm.java b/src/main/java/kr/syeyoung/dungeonsguide/features/impl/discord/onlinealarm/PlayingDGAlarm.java
new file mode 100644
index 00000000..d003b165
--- /dev/null
+++ b/src/main/java/kr/syeyoung/dungeonsguide/features/impl/discord/onlinealarm/PlayingDGAlarm.java
@@ -0,0 +1,171 @@
+/*
+ * 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.features.impl.discord.onlinealarm;
+
+import kr.syeyoung.dungeonsguide.DungeonsGuide;
+import kr.syeyoung.dungeonsguide.events.DiscordUserUpdateEvent;
+import kr.syeyoung.dungeonsguide.features.FeatureRegistry;
+import kr.syeyoung.dungeonsguide.features.SimpleFeature;
+import kr.syeyoung.dungeonsguide.features.impl.discord.inviteViewer.ImageTexture;
+import kr.syeyoung.dungeonsguide.features.listener.DiscordUserUpdateListener;
+import kr.syeyoung.dungeonsguide.features.listener.ScreenRenderListener;
+import kr.syeyoung.dungeonsguide.features.listener.TickListener;
+import kr.syeyoung.dungeonsguide.gamesdk.jna.enumuration.EDiscordRelationshipType;
+import kr.syeyoung.dungeonsguide.rpc.JDiscordActivity;
+import kr.syeyoung.dungeonsguide.rpc.JDiscordRelation;
+import kr.syeyoung.dungeonsguide.utils.TextUtils;
+import lombok.AllArgsConstructor;
+import lombok.Data;
+import net.minecraft.client.Minecraft;
+import net.minecraft.client.gui.FontRenderer;
+import net.minecraft.client.gui.Gui;
+import net.minecraft.client.gui.ScaledResolution;
+import net.minecraft.client.renderer.GlStateManager;
+import net.minecraft.client.renderer.texture.TextureManager;
+import org.lwjgl.opengl.GL11;
+import org.lwjgl.opengl.GL14;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.concurrent.CopyOnWriteArrayList;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.Future;
+
+public class PlayingDGAlarm extends SimpleFeature implements DiscordUserUpdateListener, ScreenRenderListener, TickListener {
+ public PlayingDGAlarm() {
+ super("Discord", "Friend Online Notification","Notifies you in bottom when your discord friend has launched a Minecraft with DG!\n\nRequires the Friend's Discord RPC to be enabled", "discord.playingalarm");
+ }
+ private List<PlayerOnline> notif = new CopyOnWriteArrayList<>();
+
+ @Override
+ public void onTick() {
+ try {
+ List<PlayerOnline> partyJoinRequestList = new ArrayList<>();
+ boolean isOnHypixel = DungeonsGuide.getDungeonsGuide().getSkyblockStatus().isOnHypixel();
+ for (PlayerOnline joinRequest:notif) {
+ if (!isOnHypixel){
+ partyJoinRequestList.add(joinRequest);
+ } else if (joinRequest.getEnd() < System.currentTimeMillis()) {
+ partyJoinRequestList.add(joinRequest);
+ }
+ }
+ notif.removeAll(partyJoinRequestList);
+ } catch (Throwable e) {e.printStackTrace();}
+ }
+
+
+
+ @Override
+ public void drawScreen(float partialTicks) {
+ try {
+ GlStateManager.pushMatrix();
+ GlStateManager.translate(0,0,100);
+ ScaledResolution sr = new ScaledResolution(Minecraft.getMinecraft());
+ GlStateManager.scale(1.0 / sr.getScaleFactor(), 1.0 / sr.getScaleFactor(), 1.0);
+ int height = 90;
+ int gap = 5;
+ int x = Minecraft.getMinecraft().displayWidth-350-gap;
+ int y = Minecraft.getMinecraft().displayHeight-(height+gap)*notif.size();
+ for (PlayerOnline partyJoinRequest : notif) {
+ renderRequest(partyJoinRequest, x, y, 350,height);
+ y += height + gap;
+ }
+ GlStateManager.popMatrix();
+ GlStateManager.enableBlend();
+ } catch (Throwable t) {
+ t.printStackTrace();
+ }
+ }
+
+ public void renderRequest(PlayerOnline online, int x, int y, int width, int height) {
+ GlStateManager.pushMatrix();
+ online.setEnd(System.currentTimeMillis()+600000);
+ GlStateManager.translate(x,y,0);
+
+ Gui.drawRect(0, 0,width,height, 0xFF23272a);
+ Gui.drawRect(2, 2, width-2, height-2, 0XFF2c2f33);
+ {
+ String avatar = "https://cdn.discordapp.com/avatars/"+Long.toUnsignedString(online.getJDiscordRelation().getDiscordUser().getId())+"/"+online.getJDiscordRelation().getDiscordUser().getAvatar()+"."+(online.getJDiscordRelation().getDiscordUser().getAvatar().startsWith("a_") ? "gif":"png");
+ Future<ImageTexture> loadedImageFuture = FeatureRegistry.DISCORD_ASKTOJOIN.loadImage(avatar);
+ ImageTexture loadedImage = null;
+ if (loadedImageFuture.isDone()) {
+ try {
+ loadedImage = loadedImageFuture.get();
+ } catch (InterruptedException | ExecutionException e) {
+ e.printStackTrace();
+ }
+ }
+ if (loadedImage != null) {
+ loadedImage.drawFrameAndIncrement( 7,7,height-14,height-14);
+ } else {
+ Gui.drawRect(7, 7, height - 7, height-7, 0xFF4E4E4E);
+ }
+ }
+
+ GlStateManager.enableBlend();
+ GL14.glBlendFuncSeparate(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA, GL11.GL_ONE, GL11.GL_ONE_MINUS_SRC_ALPHA);
+ GlStateManager.tryBlendFuncSeparate(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA, GL11.GL_ONE, GL11.GL_ONE_MINUS_SRC_ALPHA);
+ FontRenderer fr = Minecraft.getMinecraft().fontRendererObj;
+ GlStateManager.pushMatrix();
+ GlStateManager.translate(height +3,7, 0);
+
+ GlStateManager.pushMatrix();
+ GlStateManager.scale(3.0,3.0,1.0);
+ fr.drawString(online.getJDiscordRelation().getDiscordUser().getUsername()+"", 0,0, 0xFFFFFFFF, true);
+ GlStateManager.popMatrix();
+
+ GlStateManager.pushMatrix();
+ GlStateManager.translate(fr.getStringWidth(online.getJDiscordRelation().getDiscordUser().getUsername()+"") * 3 + 1, (int)(fr.FONT_HEIGHT*1.5), 0);
+ fr.drawString("#"+online.getJDiscordRelation().getDiscordUser().getDiscriminator(), 0,0,0xFFaaaaaa, true);
+ GlStateManager.popMatrix();
+ GlStateManager.pushMatrix();
+ GlStateManager.translate(0, fr.FONT_HEIGHT * 3 + 5, 0);
+ GlStateManager.scale(1.0,1.0,1.0);
+ fr.drawString("Started Playing Skyblock! (Dismissed in "+(TextUtils.formatTime(online.getEnd() - System.currentTimeMillis()))+")", 0,0,0xFFFFFFFF,false);
+ GlStateManager.popMatrix();
+ GlStateManager.popMatrix();
+ GlStateManager.popMatrix();
+ }
+
+
+ @Data @AllArgsConstructor
+ public static class PlayerOnline {
+ private JDiscordRelation jDiscordRelation;
+ private long end;
+ }
+
+ @Override
+ public void onDiscordUserUpdate(DiscordUserUpdateEvent event) {
+ JDiscordRelation prev = event.getPrev(), current = event.getCurrent();
+ if (!isDisplayable(prev) && isDisplayable(current)) {
+ notif.add(new PlayerOnline(current, System.currentTimeMillis()+600000));
+ }
+ }
+
+ public boolean isDisplayable(JDiscordRelation jDiscordRelation) {
+ EDiscordRelationshipType relationshipType = jDiscordRelation.getDiscordRelationshipType();
+ if (relationshipType == EDiscordRelationshipType.DiscordRelationshipType_Blocked) return false;
+ if (relationshipType == EDiscordRelationshipType.DiscordRelationshipType_None) return false;
+ if (relationshipType == EDiscordRelationshipType.DiscordRelationshipType_PendingIncoming) return false;
+ if (relationshipType == EDiscordRelationshipType.DiscordRelationshipType_PendingOutgoing) return false;
+
+ JDiscordActivity jDiscordActivity = jDiscordRelation.getDiscordActivity();
+ return jDiscordActivity.getApplicationId() == 816298079732498473L;
+ }
+}
diff --git a/src/main/java/kr/syeyoung/dungeonsguide/features/listener/DiscordUserJoinRequestListener.java b/src/main/java/kr/syeyoung/dungeonsguide/features/listener/DiscordUserJoinRequestListener.java
new file mode 100644
index 00000000..d48331d5
--- /dev/null
+++ b/src/main/java/kr/syeyoung/dungeonsguide/features/listener/DiscordUserJoinRequestListener.java
@@ -0,0 +1,26 @@
+/*
+ * 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.features.listener;
+
+import kr.syeyoung.dungeonsguide.events.DiscordUserJoinRequestEvent;
+import kr.syeyoung.dungeonsguide.events.DiscordUserUpdateEvent;
+
+public interface DiscordUserJoinRequestListener {
+ void onDiscordUserJoinRequest(DiscordUserJoinRequestEvent event);
+}
diff --git a/src/main/java/kr/syeyoung/dungeonsguide/features/listener/DiscordUserUpdateListener.java b/src/main/java/kr/syeyoung/dungeonsguide/features/listener/DiscordUserUpdateListener.java
new file mode 100644
index 00000000..d376a21d
--- /dev/null
+++ b/src/main/java/kr/syeyoung/dungeonsguide/features/listener/DiscordUserUpdateListener.java
@@ -0,0 +1,25 @@
+/*
+ * 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.features.listener;
+
+import kr.syeyoung.dungeonsguide.events.DiscordUserUpdateEvent;
+
+public interface DiscordUserUpdateListener {
+ void onDiscordUserUpdate(DiscordUserUpdateEvent event);
+}
diff --git a/src/main/java/kr/syeyoung/dungeonsguide/gamesdk/jna/datastruct/DiscordCreateParams.java b/src/main/java/kr/syeyoung/dungeonsguide/gamesdk/jna/datastruct/DiscordCreateParams.java
index 8e230b73..10f1ba3d 100644
--- a/src/main/java/kr/syeyoung/dungeonsguide/gamesdk/jna/datastruct/DiscordCreateParams.java
+++ b/src/main/java/kr/syeyoung/dungeonsguide/gamesdk/jna/datastruct/DiscordCreateParams.java
@@ -20,6 +20,7 @@ package kr.syeyoung.dungeonsguide.gamesdk.jna.datastruct;
import com.sun.jna.Pointer;
import com.sun.jna.Structure;
+import kr.syeyoung.dungeonsguide.gamesdk.jna.NativeGameSDK;
import kr.syeyoung.dungeonsguide.gamesdk.jna.interfacestruct.*;
import kr.syeyoung.dungeonsguide.gamesdk.jna.typedef.DiscordClientID;
import kr.syeyoung.dungeonsguide.gamesdk.jna.typedef.DiscordVersion;
@@ -34,29 +35,29 @@ public class DiscordCreateParams extends DiscordStruct { public DiscordCreatePar
public Pointer events; // void*
public Pointer event_data; // void*
public Pointer application_events;
- public DiscordVersion application_version = new DiscordVersion();
+ public DiscordVersion application_version = new DiscordVersion(NativeGameSDK.DISCORD_APPLICATION_MANAGER_VERSION);
public IDiscordUserEvents.ByReference user_events;
- public DiscordVersion user_version= new DiscordVersion();
+ public DiscordVersion user_version= new DiscordVersion(NativeGameSDK.DISCORD_USER_MANAGER_VERSION);
public Pointer image_events;// void*
- public DiscordVersion image_version= new DiscordVersion();
+ public DiscordVersion image_version= new DiscordVersion(NativeGameSDK.DISCORD_IMAGE_MANAGER_VERSION);
public IDiscordActivityEvents.ByReference activity_events;
- public DiscordVersion activity_version= new DiscordVersion();
+ public DiscordVersion activity_version= new DiscordVersion(NativeGameSDK.DISCORD_ACTIVITY_MANAGER_VERSION);
public IDiscordRelationshipEvents.ByReference relationship_events;
- public DiscordVersion relationship_version= new DiscordVersion();
+ public DiscordVersion relationship_version= new DiscordVersion(NativeGameSDK.DISCORD_RELATIONSHIP_MANAGER_VERSION);
public IDiscordLobbyEvents.ByReference lobby_events;
- public DiscordVersion lobby_version= new DiscordVersion();
+ public DiscordVersion lobby_version= new DiscordVersion(NativeGameSDK.DISCORD_LOBBY_MANAGER_VERSION);
public IDiscordNetworkEvents.ByReference network_events;
- public DiscordVersion network_version= new DiscordVersion();
+ public DiscordVersion network_version= new DiscordVersion(NativeGameSDK.DISCORD_NETWORK_MANAGER_VERSION);
public IDiscordOverlayEvents.ByReference overlay_events;
- public DiscordVersion overlay_version= new DiscordVersion();
+ public DiscordVersion overlay_version= new DiscordVersion(NativeGameSDK.DISCORD_OVERLAY_MANAGER_VERSION);
public Pointer storage_events;// void*
- public DiscordVersion storage_version= new DiscordVersion();
+ public DiscordVersion storage_version= new DiscordVersion(NativeGameSDK.DISCORD_STORAGE_MANAGER_VERSION);
public IDiscordStoreEvents.ByReference store_events;
- public DiscordVersion store_version= new DiscordVersion();
+ public DiscordVersion store_version= new DiscordVersion(NativeGameSDK.DISCORD_STORE_MANAGER_VERSION);
public IDiscordVoiceEvents.ByReference voice_events;
- public DiscordVersion voice_version= new DiscordVersion();
+ public DiscordVersion voice_version= new DiscordVersion(NativeGameSDK.DISCORD_VOICE_MANAGER_VERSION);
public IDiscordAchievementEvents.ByReference achievement_events;
- public DiscordVersion achievement_version= new DiscordVersion();
+ public DiscordVersion achievement_version= new DiscordVersion(NativeGameSDK.DISCORD_ACHIEVEMENT_MANAGER_VERSION);
public static class ByReference extends DiscordCreateParams implements Structure.ByReference { public ByReference() {super();} public ByReference(Pointer pointer) {super(pointer);}}
public static class ByValue extends DiscordCreateParams implements Structure.ByValue { public ByValue() {super();} public ByValue(Pointer pointer) {super(pointer);}}
diff --git a/src/main/java/kr/syeyoung/dungeonsguide/gamesdk/jna/interfacestruct/IDiscordRelationshipManager.java b/src/main/java/kr/syeyoung/dungeonsguide/gamesdk/jna/interfacestruct/IDiscordRelationshipManager.java
index f2db8dd6..1b3ffe16 100644
--- a/src/main/java/kr/syeyoung/dungeonsguide/gamesdk/jna/interfacestruct/IDiscordRelationshipManager.java
+++ b/src/main/java/kr/syeyoung/dungeonsguide/gamesdk/jna/interfacestruct/IDiscordRelationshipManager.java
@@ -33,7 +33,7 @@ import java.util.List;
public class IDiscordRelationshipManager extends DiscordStruct { public IDiscordRelationshipManager() {super();} public IDiscordRelationshipManager(Pointer pointer) {super(pointer);}
public interface FilterCallback extends GameSDKCallback { void filter(IDiscordRelationshipManager manager, Pointer filterData, FilterCallback_Callback filter); }
- public interface FilterCallback_Callback extends GameSDKCallback { boolean filter(Pointer filterData, Structure relationShip);}
+ public interface FilterCallback_Callback extends GameSDKCallback { boolean filter(Pointer filterData, DiscordRelationship relationShip);}
public FilterCallback Filter;
public interface CountCallback extends GameSDKCallback { EDiscordResult count(IDiscordRelationshipManager manager, IntByReference count); }
diff --git a/src/main/java/kr/syeyoung/dungeonsguide/party/LoadedImage.java b/src/main/java/kr/syeyoung/dungeonsguide/party/LoadedImage.java
deleted file mode 100644
index ca3764d9..00000000
--- a/src/main/java/kr/syeyoung/dungeonsguide/party/LoadedImage.java
+++ /dev/null
@@ -1,40 +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 <https://www.gnu.org/licenses/>.
- */
-
-package kr.syeyoung.dungeonsguide.party;
-
-
-import lombok.Data;
-import net.minecraft.client.Minecraft;
-import net.minecraft.client.renderer.texture.DynamicTexture;
-import net.minecraft.util.ResourceLocation;
-
-import java.awt.image.BufferedImage;
-
-@Data
-public class LoadedImage {
- private String url;
- private BufferedImage image;
- private DynamicTexture previewTexture;
- private ResourceLocation resourceLocation;
-
- public void buildGLThings() {
- previewTexture = new DynamicTexture(image);
- resourceLocation = Minecraft.getMinecraft().getTextureManager().getDynamicTextureLocation("dgurl/"+url, previewTexture);
- }
-}
diff --git a/src/main/java/kr/syeyoung/dungeonsguide/party/PartyManager.java b/src/main/java/kr/syeyoung/dungeonsguide/party/PartyManager.java
index eaebc433..7382f203 100644
--- a/src/main/java/kr/syeyoung/dungeonsguide/party/PartyManager.java
+++ b/src/main/java/kr/syeyoung/dungeonsguide/party/PartyManager.java
@@ -18,7 +18,7 @@
package kr.syeyoung.dungeonsguide.party;
-import kr.syeyoung.dungeonsguide.RichPresenceManager;
+import kr.syeyoung.dungeonsguide.rpc.RichPresenceManager;
import kr.syeyoung.dungeonsguide.DungeonsGuide;
import kr.syeyoung.dungeonsguide.events.HypixelJoinedEvent;
import kr.syeyoung.dungeonsguide.events.StompConnectedEvent;
@@ -42,7 +42,6 @@ import org.json.JSONObject;
import java.security.SecureRandom;
import java.util.*;
import java.util.concurrent.ConcurrentLinkedQueue;
-import java.util.concurrent.SynchronousQueue;
import java.util.function.Consumer;
public class PartyManager implements StompMessageHandler {
diff --git a/src/main/java/kr/syeyoung/dungeonsguide/rpc/JDiscordActivity.java b/src/main/java/kr/syeyoung/dungeonsguide/rpc/JDiscordActivity.java
new file mode 100644
index 00000000..f25022f2
--- /dev/null
+++ b/src/main/java/kr/syeyoung/dungeonsguide/rpc/JDiscordActivity.java
@@ -0,0 +1,72 @@
+/*
+ * 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.rpc;
+
+import kr.syeyoung.dungeonsguide.gamesdk.GameSDK;
+import kr.syeyoung.dungeonsguide.gamesdk.jna.datastruct.DiscordActivity;
+import kr.syeyoung.dungeonsguide.gamesdk.jna.enumuration.EDiscordActivityType;
+import lombok.Data;
+
+@Data
+public class JDiscordActivity {
+ private EDiscordActivityType activityType;
+ private long applicationId;
+ private String name, state, details;
+ private long start, end;
+ private String largeImage, largeText, smallImage, smallText;
+ private String partyId;
+ private int partyCurr, partyMax;
+ private String matchSecret, joinSecret, spectateSecret;
+ private boolean instance;
+
+ public static JDiscordActivity fromJNA(DiscordActivity discordActivity) {
+ if (discordActivity == null) return null;
+ JDiscordActivity jDiscordActivity = new JDiscordActivity();
+ jDiscordActivity.activityType = discordActivity.activityType;
+ jDiscordActivity.applicationId = discordActivity.applicationId.longValue();
+ jDiscordActivity.name = GameSDK.readString(discordActivity.name);
+ jDiscordActivity.state = GameSDK.readString(discordActivity.state);
+ jDiscordActivity.details = GameSDK.readString(discordActivity.details);
+ if (discordActivity.assets != null) {
+ jDiscordActivity.largeImage = GameSDK.readString(discordActivity.assets.large_image);
+ jDiscordActivity.largeText = GameSDK.readString(discordActivity.assets.large_text);
+ jDiscordActivity.smallImage = GameSDK.readString(discordActivity.assets.small_image);
+ jDiscordActivity.smallText = GameSDK.readString(discordActivity.assets.small_text);
+ }
+ if (discordActivity.timestamps != null) {
+ jDiscordActivity.start = discordActivity.timestamps.start.longValue();
+ jDiscordActivity.end = discordActivity.timestamps.end.longValue();
+ }
+ if (discordActivity.secrets != null) {
+ jDiscordActivity.matchSecret= GameSDK.readString(discordActivity.secrets.match);
+ jDiscordActivity.joinSecret = GameSDK.readString(discordActivity.secrets.join);
+ jDiscordActivity.spectateSecret = GameSDK.readString(discordActivity.secrets.spectate);
+ }
+ if (discordActivity.party != null) {
+ jDiscordActivity.partyId = GameSDK.readString(discordActivity.party.id);
+ if (discordActivity.party.discordActivityParty != null) {
+ jDiscordActivity.partyCurr = discordActivity.party.discordActivityParty.current_size.intValue();
+ jDiscordActivity.partyMax = discordActivity.party.discordActivityParty.max_size.intValue();
+ }
+ }
+ jDiscordActivity.instance = discordActivity.instance;
+
+ return jDiscordActivity;
+ }
+}
diff --git a/src/main/java/kr/syeyoung/dungeonsguide/rpc/JDiscordRelation.java b/src/main/java/kr/syeyoung/dungeonsguide/rpc/JDiscordRelation.java
new file mode 100644
index 00000000..3086c936
--- /dev/null
+++ b/src/main/java/kr/syeyoung/dungeonsguide/rpc/JDiscordRelation.java
@@ -0,0 +1,42 @@
+/*
+ * 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.rpc;
+
+import kr.syeyoung.dungeonsguide.gamesdk.jna.datastruct.DiscordRelationship;
+import kr.syeyoung.dungeonsguide.gamesdk.jna.enumuration.EDiscordRelationshipType;
+import kr.syeyoung.dungeonsguide.gamesdk.jna.enumuration.EDiscordStatus;
+import lombok.Data;
+
+@Data
+public class JDiscordRelation {
+ private EDiscordRelationshipType discordRelationshipType;
+ private EDiscordStatus status;
+ private JDiscordActivity discordActivity;
+ private JDiscordUser discordUser;
+
+ public static JDiscordRelation fromJNA(DiscordRelationship relationship) {
+ JDiscordRelation jDiscordRelation = new JDiscordRelation();
+ jDiscordRelation.discordUser = JDiscordUser.fromJNA(relationship.user);
+ jDiscordRelation.discordActivity = JDiscordActivity.fromJNA(relationship.presence.activity);
+ jDiscordRelation.status = relationship.presence.status;
+ jDiscordRelation.discordRelationshipType = relationship.type;
+ return jDiscordRelation;
+ }
+
+}
diff --git a/src/main/java/kr/syeyoung/dungeonsguide/rpc/JDiscordUser.java b/src/main/java/kr/syeyoung/dungeonsguide/rpc/JDiscordUser.java
new file mode 100644
index 00000000..635ac405
--- /dev/null
+++ b/src/main/java/kr/syeyoung/dungeonsguide/rpc/JDiscordUser.java
@@ -0,0 +1,40 @@
+/*
+ * 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.rpc;
+
+import kr.syeyoung.dungeonsguide.gamesdk.GameSDK;
+import kr.syeyoung.dungeonsguide.gamesdk.jna.datastruct.DiscordUser;
+import lombok.Data;
+
+@Data
+public class JDiscordUser {
+ private long id;
+ private String username, discriminator, avatar;
+ private boolean bot;
+
+ public static JDiscordUser fromJNA(DiscordUser discordUser) {
+ JDiscordUser jDiscordUser = new JDiscordUser();
+ jDiscordUser.id = discordUser.id.longValue();
+ jDiscordUser.username = GameSDK.readString(discordUser.username);
+ jDiscordUser.discriminator = GameSDK.readString(discordUser.discriminator);
+ jDiscordUser.avatar = GameSDK.readString(discordUser.avatar);
+ jDiscordUser.bot = discordUser.bot;
+ return jDiscordUser;
+ }
+}
diff --git a/src/main/java/kr/syeyoung/dungeonsguide/rpc/RichPresenceManager.java b/src/main/java/kr/syeyoung/dungeonsguide/rpc/RichPresenceManager.java
new file mode 100644
index 00000000..23f8433d
--- /dev/null
+++ b/src/main/java/kr/syeyoung/dungeonsguide/rpc/RichPresenceManager.java
@@ -0,0 +1,250 @@
+/*
+ * 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.rpc;
+
+import com.sun.jna.Pointer;
+import com.sun.jna.ptr.IntByReference;
+import com.sun.jna.ptr.PointerByReference;
+import kr.syeyoung.dungeonsguide.DungeonsGuide;
+import kr.syeyoung.dungeonsguide.SkyblockStatus;
+import kr.syeyoung.dungeonsguide.dungeon.DungeonContext;
+import kr.syeyoung.dungeonsguide.events.DiscordUserJoinRequestEvent;
+import kr.syeyoung.dungeonsguide.events.DiscordUserUpdateEvent;
+import kr.syeyoung.dungeonsguide.features.FeatureRegistry;
+import kr.syeyoung.dungeonsguide.gamesdk.GameSDK;
+import kr.syeyoung.dungeonsguide.gamesdk.jna.NativeGameSDK;
+import kr.syeyoung.dungeonsguide.gamesdk.jna.datastruct.*;
+import kr.syeyoung.dungeonsguide.gamesdk.jna.enumuration.*;
+import kr.syeyoung.dungeonsguide.gamesdk.jna.interfacestruct.*;
+import kr.syeyoung.dungeonsguide.gamesdk.jna.typedef.*;
+import kr.syeyoung.dungeonsguide.party.PartyManager;
+import kr.syeyoung.dungeonsguide.stomp.StompHeader;
+import kr.syeyoung.dungeonsguide.stomp.StompPayload;
+import lombok.Getter;
+import net.minecraftforge.common.MinecraftForge;
+import org.json.JSONObject;
+
+import java.util.HashMap;
+import java.util.Map;
+
+public class RichPresenceManager implements Runnable {
+ public static RichPresenceManager INSTANCE = new RichPresenceManager();
+ private Thread t = new Thread(this);
+
+ public RichPresenceManager() {
+ t.start();
+ }
+ @Getter
+ private NativeGameSDK nativeGameSDK;
+ @Getter
+ private IDiscordCore iDiscordCore;
+ private IDiscordActivityManager activityManager;
+ private IDiscordRelationshipManager relationshipManager;
+ private IDiscordActivityEvents.ByReference callbacks;
+ private IDiscordRelationshipEvents.ByReference relation_callbacks;
+
+ @Getter
+ private Map<Long, JDiscordRelation> relationMap = new HashMap<>();
+
+ @Getter
+ private int lastSetupCode = -99999;
+ public int setup() {
+ System.out.println("SETUP!!! "+ iDiscordCore);
+ if (iDiscordCore != null) {
+ System.out.println("DETROYED");
+ iDiscordCore.Destroy.destroy(iDiscordCore);
+ activityManager = null; callbacks = null; relation_callbacks = null; relationMap.clear();
+ }
+
+ nativeGameSDK = GameSDK.getNativeGameSDK();
+ if (nativeGameSDK == null) return -9999;
+ DiscordCreateParams discordCreateParams = new DiscordCreateParams();
+ discordCreateParams.flags = new UInt64(EDiscordCreateFlags.DiscordCreateFlags_Default.getValue());
+ discordCreateParams.client_id = new DiscordClientID(816298079732498473L);
+
+ callbacks = new IDiscordActivityEvents.ByReference();
+ callbacks.OnActivityInvite = (eventData, type, user, activity) -> {
+ try {
+ MinecraftForge.EVENT_BUS.post(new DiscordUserJoinRequestEvent(user, true));
+ } catch (Throwable t) {
+ t.printStackTrace();
+ }
+ System.out.println("Received Join Request from "+user.id.longValue()+" ("+GameSDK.readString(user.username)+")");
+ };
+ callbacks.OnActivityJoin = (eventData, secret) -> {
+ DungeonsGuide.getDungeonsGuide().getStompConnection().send(new StompPayload().method(StompHeader.SEND)
+ .header("destination", "/app/party.askedtojoin")
+ .payload(new JSONObject().put("token", secret).toString()));
+ System.out.println("Trying to join with token "+secret);
+ };
+ callbacks.OnActivityJoinRequest = (eventData, user) -> {
+ try {
+ MinecraftForge.EVENT_BUS.post(new DiscordUserJoinRequestEvent(user, false));
+ } catch (Throwable t) {
+ t.printStackTrace();
+ }
+ System.out.println("Received Join Request from "+user.id.longValue()+" - "+GameSDK.readString(user.username));
+ };
+ callbacks.OnActivitySpectate = (eventData, secret) -> {
+ };
+ callbacks.write();
+
+ relation_callbacks = new IDiscordRelationshipEvents.ByReference();
+ relation_callbacks.OnRefresh = (p) -> {
+ IDiscordRelationshipManager iDiscordRelationshipManager = iDiscordCore.GetRelationshipManager.getRelationshipManager(iDiscordCore);
+ iDiscordRelationshipManager.Filter.filter(iDiscordRelationshipManager, Pointer.NULL, (d, relation) -> true);
+ IntByReference intByReference = new IntByReference();
+ iDiscordRelationshipManager.Count.count(iDiscordRelationshipManager, intByReference);
+ int count = intByReference.getValue();
+ for (int i = 0; i < count; i++) {
+ DiscordRelationship discordRelationship = new DiscordRelationship();
+ iDiscordRelationshipManager.GetAt.getAt(iDiscordRelationshipManager, new UInt32(i), discordRelationship);
+
+ JDiscordRelation jDiscordRelation = JDiscordRelation.fromJNA(discordRelationship);
+ relationMap.put(jDiscordRelation.getDiscordUser().getId(), jDiscordRelation);
+ }
+ };
+ relation_callbacks.OnRelationshipUpdate = (p, rel) -> {
+ JDiscordRelation jDiscordRelation = JDiscordRelation.fromJNA(rel);
+ JDiscordRelation prev = relationMap.put(jDiscordRelation.getDiscordUser().getId(), jDiscordRelation);
+ System.out.println("Discord relation update!! "+jDiscordRelation);
+ try {
+ MinecraftForge.EVENT_BUS.post(new DiscordUserUpdateEvent(prev, jDiscordRelation));
+ } catch (Throwable t) {
+ t.printStackTrace();
+ }
+ };
+ relation_callbacks.write();
+
+ discordCreateParams.activity_events = callbacks;
+ discordCreateParams.relationship_events = relation_callbacks; // 96
+
+ PointerByReference pointerByReference = new PointerByReference();
+ discordCreateParams.write();
+
+ EDiscordResult eDiscordResult = nativeGameSDK.DiscordCreate(new DiscordVersion(NativeGameSDK.DISCORD_VERSION), discordCreateParams, pointerByReference);
+ if (eDiscordResult != EDiscordResult.DiscordResult_Ok) return eDiscordResult.getValue();
+ if (pointerByReference.getValue() == Pointer.NULL) return -9998;
+ iDiscordCore = new IDiscordCore(pointerByReference.getValue());
+
+ iDiscordCore.SetLogHook.setLogHook(iDiscordCore, EDiscordLogLevel.DiscordLogLevel_Debug, Pointer.NULL, new IDiscordCore.LogHook() {
+ @Override
+ public void hook(Pointer hookData, EDiscordLogLevel level, String message) {
+ System.out.println(message+" - "+level+" - "+hookData);
+ }
+ });
+
+ activityManager = iDiscordCore.GetActivityManager.getActivityManager(iDiscordCore);
+ relationshipManager = iDiscordCore.GetRelationshipManager.getRelationshipManager(iDiscordCore);
+
+ return eDiscordResult.getValue();
+ }
+
+ private final SkyblockStatus skyblockStatus = DungeonsGuide.getDungeonsGuide().getSkyblockStatus();
+
+ public void respond(DiscordSnowflake userID, EDiscordActivityJoinRequestReply reply) {
+ activityManager.SendRequestReply.sendRequestReply(activityManager, userID, reply, Pointer.NULL, (callbackData, result) -> {
+ System.out.println("Discord Returned "+result+" For Replying "+reply+" To "+userID.longValue()+"L");
+ });
+ }
+
+ public void accept(DiscordSnowflake userID) {
+ activityManager.AcceptInvite.acceptInvite(activityManager, userID, Pointer.NULL, (callbackData, result) -> {
+ System.out.println("Discord Returned "+result+" For Accepting invite from "+userID.longValue()+"L");
+ });
+ }
+ public void updatePresence() {
+ if (!skyblockStatus.isOnHypixel() || !FeatureRegistry.DISCORD_RICHPRESENCE.isEnabled() || (!skyblockStatus.isOnSkyblock() && FeatureRegistry.DISCORD_RICHPRESENCE.<Boolean>getParameter("disablenotskyblock").getValue())) {
+ activityManager.ClearActivity.clearActivity(activityManager, Pointer.NULL, new NativeGameSDK.DiscordCallback() {
+ @Override
+ public void callback(Pointer callbackData, EDiscordResult result) {
+ }
+ });
+ } else {
+ String name = skyblockStatus.getDungeonName() == null ? "" : skyblockStatus.getDungeonName();
+ if (!skyblockStatus.isOnSkyblock()) name ="Somewhere on Hypixel";
+ if (name.trim().equals("Your Island")) name = "Private Island";
+
+ DiscordActivity latestDiscordActivity = new DiscordActivity();
+ latestDiscordActivity.assets = new DiscordActivityAssets();
+ latestDiscordActivity.secrets = new DiscordActivitySecrets();
+ latestDiscordActivity.party = new DiscordActivityParty();
+ latestDiscordActivity.party.discordActivityParty = new DiscordPartySize();
+ latestDiscordActivity.timestamps = new DiscordActivityTimestamps();
+ GameSDK.writeString(latestDiscordActivity.assets.large_image, "mort");
+ GameSDK.writeString(latestDiscordActivity.assets.large_text, "mort");
+ GameSDK.writeString(latestDiscordActivity.state, name);
+
+ GameSDK.writeString(latestDiscordActivity.party.id, PartyManager.INSTANCE.getPartyID() == null ? "" : PartyManager.INSTANCE.getPartyID());
+ latestDiscordActivity.party.discordActivityParty.current_size = new Int32(PartyManager.INSTANCE.getMemberCount());
+ latestDiscordActivity.party.discordActivityParty.max_size = new Int32(PartyManager.INSTANCE.getMaxParty());
+
+ if (skyblockStatus.getContext() != null) {
+ DungeonContext dungeonContext = skyblockStatus.getContext();
+ long init = dungeonContext.getInit();
+ latestDiscordActivity.timestamps.start = new DiscordTimestamp(init);
+
+ if (dungeonContext.getBossfightProcessor() != null) {
+ GameSDK.writeString(latestDiscordActivity.details, "Fighting "+dungeonContext.getBossfightProcessor().getBossName()+": "+dungeonContext.getBossfightProcessor().getCurrentPhase());
+ } else {
+ GameSDK.writeString(latestDiscordActivity.details, "Clearing Rooms");
+ }
+ } else {
+ latestDiscordActivity.timestamps.start = new DiscordTimestamp(0);
+ GameSDK.writeString(latestDiscordActivity.details, "Dungeons Guide");
+ }
+ if (PartyManager.INSTANCE.isAllowAskToJoin()) {
+ GameSDK.writeString(latestDiscordActivity.secrets.join, PartyManager.INSTANCE.getAskToJoinSecret());
+ } else {
+ GameSDK.writeString(latestDiscordActivity.secrets.join, "");
+ }
+ activityManager.UpdateActivity.updateActivity(activityManager, latestDiscordActivity, Pointer.NULL, new NativeGameSDK.DiscordCallback() {
+ @Override
+ public void callback(Pointer callbackData, EDiscordResult result) {
+ }
+ });
+ }
+ }
+
+ @Override
+ public void run() {
+ boolean setup = true;
+ int counter = 0;
+ while(!Thread.interrupted()) {
+ try {
+ if (iDiscordCore == null || setup) {
+ lastSetupCode = setup();
+ System.out.println("Discord returned "+lastSetupCode+" for setup "+EDiscordResult.fromValue(lastSetupCode));
+ setup = lastSetupCode != EDiscordResult.DiscordResult_Ok.getValue();
+ counter = 0;
+ } else {
+ EDiscordResult eDiscordResult = iDiscordCore.RunCallbacks.runCallbacks(iDiscordCore);
+ if (eDiscordResult == EDiscordResult.DiscordResult_NotRunning) {
+ setup = true;
+ } else {
+ if (counter == 0)
+ updatePresence();
+ if (++counter == 15) counter = 0;
+ }
+ }
+ Thread.sleep(16L);
+ } catch (Exception e) {e.printStackTrace();}
+ }
+ }
+}