diff options
Diffstat (limited to 'src')
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();} + } + } +} |