From 786be9ea22c86820c0f552a3b3a5f20b168f704b Mon Sep 17 00:00:00 2001 From: syeyoung Date: Tue, 17 Jan 2023 21:22:51 +0900 Subject: - Move online alarm to overlay manager Signed-off-by: syeyoung --- .../mod/commands/CommandDungeonsGuide.java | 4 +- .../mod/discord/DiscordIntegrationManager.java | 9 +- .../events/annotations/EventHandlerRegistry.java | 2 +- .../impl/discord/inviteViewer/ImageTexture.java | 170 ------------- .../discord/inviteViewer/PartyInviteViewer.java | 280 ++------------------- .../discord/inviteViewer/PartyJoinRequest.java | 60 ----- .../features/impl/discord/inviteViewer/Reply.java | 30 +++ .../features/impl/discord/inviteViewer/TTL.java | 24 ++ .../impl/discord/inviteViewer/WidgetInvite.java | 75 ++++++ .../discord/inviteViewer/WidgetJoinRequest.java | 80 ++++++ .../inviteViewer/WidgetPartyInviteViewer.java | 81 ++++++ .../invteTooltip/MTooltipInviteElement.java | 27 +- .../impl/discord/onlinealarm/PlayingDGAlarm.java | 116 ++------- .../impl/discord/onlinealarm/WidgetOnline.java | 62 +++++ .../onlinealarm/WidgetOnlinePeopleViewer.java | 72 ++++++ .../dungeonsguide/mod/guiv2/DomElement.java | 3 +- .../dungeonsguide/mod/guiv2/elements/Clip.java | 2 + .../dungeonsguide/mod/guiv2/elements/Column.java | 21 +- .../mod/guiv2/elements/ConstrainedBox.java | 102 ++++++++ .../dungeonsguide/mod/guiv2/elements/Flexible.java | 9 +- .../mod/guiv2/elements/IntrinsicHeight.java | 2 +- .../mod/guiv2/elements/IntrinsicWidth.java | 2 +- .../dungeonsguide/mod/guiv2/elements/Line.java | 1 + .../dungeonsguide/mod/guiv2/elements/Row.java | 21 +- .../dungeonsguide/mod/guiv2/elements/SizedBox.java | 87 ------- .../dungeonsguide/mod/guiv2/elements/Stack.java | 1 + .../dungeonsguide/mod/guiv2/elements/Text.java | 9 +- .../mod/guiv2/elements/image/ImageTexture.java | 171 +++++++++++++ .../mod/guiv2/elements/image/URLImage.java | 16 -- .../mod/guiv2/renderer/OnlyChildrenRenderer.java | 1 + .../dungeonsguide/mod/guiv2/renderer/Renderer.java | 4 +- .../mod/guiv2/renderer/RenderingContext.java | 5 +- .../mod/guiv2/renderer/SingleChildRenderer.java | 1 + .../mod/guiv2/xml/DomElementRegistry.java | 6 +- .../dungeonsguide/mod/overlay/OverlayManager.java | 17 +- .../mod/overlay/OverlayManagerRootWidget.java | 2 + .../dungeonsguide/mod/overlay/OverlayWidget.java | 1 + .../assets/dungeonsguide/gui/elements/size.gui | 23 ++ .../gui/features/discordOnline/discordOnline.gui | 52 ++++ .../features/discordOnline/discordOnlineList.gui | 22 ++ .../gui/features/discordParty/invite.gui | 85 +++++++ .../gui/features/discordParty/joinRequest.gui | 97 +++++++ .../gui/features/discordParty/partyInviteList.gui | 22 ++ 43 files changed, 1121 insertions(+), 756 deletions(-) delete mode 100644 mod/src/main/java/kr/syeyoung/dungeonsguide/mod/features/impl/discord/inviteViewer/ImageTexture.java delete mode 100644 mod/src/main/java/kr/syeyoung/dungeonsguide/mod/features/impl/discord/inviteViewer/PartyJoinRequest.java create mode 100644 mod/src/main/java/kr/syeyoung/dungeonsguide/mod/features/impl/discord/inviteViewer/Reply.java create mode 100644 mod/src/main/java/kr/syeyoung/dungeonsguide/mod/features/impl/discord/inviteViewer/TTL.java create mode 100644 mod/src/main/java/kr/syeyoung/dungeonsguide/mod/features/impl/discord/inviteViewer/WidgetInvite.java create mode 100644 mod/src/main/java/kr/syeyoung/dungeonsguide/mod/features/impl/discord/inviteViewer/WidgetJoinRequest.java create mode 100644 mod/src/main/java/kr/syeyoung/dungeonsguide/mod/features/impl/discord/inviteViewer/WidgetPartyInviteViewer.java create mode 100644 mod/src/main/java/kr/syeyoung/dungeonsguide/mod/features/impl/discord/onlinealarm/WidgetOnline.java create mode 100644 mod/src/main/java/kr/syeyoung/dungeonsguide/mod/features/impl/discord/onlinealarm/WidgetOnlinePeopleViewer.java create mode 100644 mod/src/main/java/kr/syeyoung/dungeonsguide/mod/guiv2/elements/ConstrainedBox.java delete mode 100644 mod/src/main/java/kr/syeyoung/dungeonsguide/mod/guiv2/elements/SizedBox.java create mode 100644 mod/src/main/java/kr/syeyoung/dungeonsguide/mod/guiv2/elements/image/ImageTexture.java create mode 100644 mod/src/main/resources/assets/dungeonsguide/gui/elements/size.gui create mode 100644 mod/src/main/resources/assets/dungeonsguide/gui/features/discordOnline/discordOnline.gui create mode 100644 mod/src/main/resources/assets/dungeonsguide/gui/features/discordOnline/discordOnlineList.gui create mode 100644 mod/src/main/resources/assets/dungeonsguide/gui/features/discordParty/invite.gui create mode 100644 mod/src/main/resources/assets/dungeonsguide/gui/features/discordParty/joinRequest.gui create mode 100644 mod/src/main/resources/assets/dungeonsguide/gui/features/discordParty/partyInviteList.gui diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/commands/CommandDungeonsGuide.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/commands/CommandDungeonsGuide.java index 36a0e955..394f95ca 100644 --- a/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/commands/CommandDungeonsGuide.java +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/commands/CommandDungeonsGuide.java @@ -27,6 +27,7 @@ import kr.syeyoung.dungeonsguide.mod.discord.DiscordIntegrationManager; import kr.syeyoung.dungeonsguide.mod.features.FeatureRegistry; import kr.syeyoung.dungeonsguide.mod.features.impl.party.playerpreview.FeatureViewPlayerStatsOnJoin; import kr.syeyoung.dungeonsguide.mod.features.impl.party.playerpreview.api.ApiFetcher; +import kr.syeyoung.dungeonsguide.mod.guiv2.elements.image.ImageTexture; import kr.syeyoung.dungeonsguide.mod.party.PartyManager; import kr.syeyoung.dungeonsguide.mod.stomp.StompManager; import kr.syeyoung.dungeonsguide.mod.stomp.StompPayload; @@ -105,8 +106,7 @@ public class CommandDungeonsGuide extends CommandBase { cosmeticsManager.requestCosmeticsList(); cosmeticsManager.requestActiveCosmetics(); StaticResourceCache.INSTANCE.purgeCache(); - FeatureRegistry.DISCORD_ASKTOJOIN.imageMap.clear(); - FeatureRegistry.DISCORD_ASKTOJOIN.futureMap.clear(); + ImageTexture.imageMap.clear(); sender.addChatMessage(new ChatComponentText("§eDungeons Guide §7:: §fSuccessfully purged API Cache!")); } else if (args[0].equals("pbroadcast")) { diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/discord/DiscordIntegrationManager.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/discord/DiscordIntegrationManager.java index 196bdbd9..6771fc62 100644 --- a/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/discord/DiscordIntegrationManager.java +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/discord/DiscordIntegrationManager.java @@ -32,7 +32,7 @@ import kr.syeyoung.dungeonsguide.mod.events.impl.DiscordUserInvitedEvent; import kr.syeyoung.dungeonsguide.mod.events.impl.DiscordUserJoinRequestEvent; import kr.syeyoung.dungeonsguide.mod.events.impl.DiscordUserUpdateEvent; import kr.syeyoung.dungeonsguide.mod.features.FeatureRegistry; -import kr.syeyoung.dungeonsguide.mod.features.impl.discord.inviteViewer.PartyJoinRequest; +import kr.syeyoung.dungeonsguide.mod.features.impl.discord.inviteViewer.Reply; import kr.syeyoung.dungeonsguide.mod.party.PartyContext; import kr.syeyoung.dungeonsguide.mod.party.PartyManager; import lombok.Getter; @@ -83,9 +83,9 @@ public class DiscordIntegrationManager implements IPCListener { } - public void respondToJoinRequest(String userId, PartyJoinRequest.Reply accept) { + public void respondToJoinRequest(String userId, Reply accept) { JSONObject payload = null; - if (accept == PartyJoinRequest.Reply.ACCEPT) { + if (accept == Reply.ACCEPT) { payload = new JSONObject() .put("cmd", "SEND_ACTIVITY_JOIN_INVITE") .put("args", new JSONObject().put("user_id", userId)); @@ -125,6 +125,7 @@ public class DiscordIntegrationManager implements IPCListener { ipcClient.subscribe("RELATIONSHIP_UPDATE", this::onRelationshipUpdate); ipcClient.send(new JSONObject().put("cmd", "GET_RELATIONSHIPS"), new Callback(this::onRelationshipLoad)); ipcClient.setListener(this); + System.out.println("Connecting"); } catch (Throwable t) { t.printStackTrace(); } @@ -225,7 +226,7 @@ public class DiscordIntegrationManager implements IPCListener { presence.setJoinSecret(PartyManager.INSTANCE.getAskToJoinSecret()); } presence.setInstance(false); - sendRichPresence(presence.build()); +// sendRichPresence(presence.build()); } } private void run() { diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/events/annotations/EventHandlerRegistry.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/events/annotations/EventHandlerRegistry.java index fecfa2fc..1e5b3c70 100644 --- a/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/events/annotations/EventHandlerRegistry.java +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/events/annotations/EventHandlerRegistry.java @@ -112,7 +112,7 @@ public class EventHandlerRegistry { private static Map, IEventListener> registeredHandlers = new HashMap<>(); - public static void registerActualListeners() { + public static synchronized void registerActualListeners() { for (Class aClass : targets.keySet()) { if (registeredHandlers.containsKey(aClass)) continue; try { diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/features/impl/discord/inviteViewer/ImageTexture.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/features/impl/discord/inviteViewer/ImageTexture.java deleted file mode 100644 index df3b4043..00000000 --- a/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/features/impl/discord/inviteViewer/ImageTexture.java +++ /dev/null @@ -1,170 +0,0 @@ -/* - * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod - * Copyright (C) 2021 cyoung06 - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as published - * by the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see . - */ - -package kr.syeyoung.dungeonsguide.mod.features.impl.discord.inviteViewer; - - -import kr.syeyoung.dungeonsguide.mod.DungeonsGuide; -import lombok.Data; -import lombok.Getter; -import lombok.Setter; -import net.minecraft.client.Minecraft; -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 org.apache.logging.log4j.Level; -import org.apache.logging.log4j.LogManager; -import org.apache.logging.log4j.Logger; - -import javax.imageio.ImageIO; -import javax.imageio.ImageReader; -import javax.imageio.metadata.IIOMetadata; -import javax.imageio.metadata.IIOMetadataNode; -import javax.imageio.stream.ImageInputStream; -import java.awt.*; -import java.awt.image.BufferedImage; -import java.io.IOException; -import java.net.HttpURLConnection; -import java.net.URL; -import java.util.HashMap; -import java.util.Iterator; -import java.util.Map; -import java.util.concurrent.ExecutorService; -import java.util.concurrent.Executors; -import java.util.function.Consumer; - -@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; - - private long startedPlayingAt = -1; - - private int delayTime; - - 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 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(); - - IIOMetadata imageMetaData = reader.getImageMetadata(0); - String metaFormatName = imageMetaData.getNativeMetadataFormatName(); - - IIOMetadataNode root = (IIOMetadataNode)imageMetaData.getAsTree(metaFormatName); - - IIOMetadataNode graphicsControlExtensionNode = getNode(root, "GraphicControlExtension"); - - delayTime = Integer.parseInt(graphicsControlExtensionNode.getAttribute("delayTime")); - - - 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(); - } - - - private static IIOMetadataNode getNode(IIOMetadataNode rootNode, String nodeName) { - int nNodes = rootNode.getLength(); - for (int i = 0; i < nNodes; i++) { - if (rootNode.item(i).getNodeName().compareToIgnoreCase(nodeName)== 0) { - return((IIOMetadataNode) rootNode.item(i)); - } - } - IIOMetadataNode node = new IIOMetadataNode(nodeName); - rootNode.appendChild(node); - return(node); - } - - public void drawFrame(double x, double y, double width, double height) { - if (getResourceLocation() == null) - buildGLThings(); - if (startedPlayingAt == -1) startedPlayingAt = System.currentTimeMillis(); - - int frame = (int) (((System.currentTimeMillis() - startedPlayingAt) / delayTime) % frames); - - 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(x, (y + height), 0.0D) - .tex(0,((frame+1) * height)/ ((double)frames * height)).endVertex(); - worldrenderer.pos((x + width), (y + height), 0.0D) - .tex(1, ((frame+1) * height)/ ((double)frames * height)).endVertex(); - worldrenderer.pos((x + width), y, 0.0D) - .tex(1,(frame * height)/ ((double)frames * height)).endVertex(); - worldrenderer.pos(x, y, 0.0D) - .tex(0, (frame * height) / ((double)frames * height)).endVertex(); - tessellator.draw(); - } - - public static final ExecutorService executorService = Executors.newFixedThreadPool(3, DungeonsGuide.THREAD_FACTORY); - public static final Map imageMap = new HashMap<>(); - public static final Logger logger = LogManager.getLogger("DG-ImageLoader"); - public static void loadImage(String url, Consumer callback) { - if (imageMap.containsKey(url)) { - callback.accept(imageMap.get(url)); - return; - } - if (url.isEmpty()) callback.accept(null); - executorService.submit(() -> { - try { - ImageTexture imageTexture = new ImageTexture(url); - imageMap.put(url, imageTexture); - callback.accept(imageTexture); - } catch (Exception e) { - callback.accept(null); - logger.log(Level.WARN, "An error occured while loading image from: "+url, e); - } - }); - } -} diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/features/impl/discord/inviteViewer/PartyInviteViewer.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/features/impl/discord/inviteViewer/PartyInviteViewer.java index e537c311..9e7cc18a 100644 --- a/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/features/impl/discord/inviteViewer/PartyInviteViewer.java +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/features/impl/discord/inviteViewer/PartyInviteViewer.java @@ -25,7 +25,13 @@ import kr.syeyoung.dungeonsguide.mod.events.annotations.DGEventHandler; import kr.syeyoung.dungeonsguide.mod.events.impl.DGTickEvent; import kr.syeyoung.dungeonsguide.mod.events.impl.DiscordUserInvitedEvent; import kr.syeyoung.dungeonsguide.mod.events.impl.DiscordUserJoinRequestEvent; +import kr.syeyoung.dungeonsguide.mod.features.FeatureParameter; import kr.syeyoung.dungeonsguide.mod.features.SimpleFeature; +import kr.syeyoung.dungeonsguide.mod.guiv2.elements.image.ImageTexture; +import kr.syeyoung.dungeonsguide.mod.guiv2.primitive.Rect; +import kr.syeyoung.dungeonsguide.mod.overlay.OverlayManager; +import kr.syeyoung.dungeonsguide.mod.overlay.OverlayType; +import kr.syeyoung.dungeonsguide.mod.overlay.OverlayWidget; import kr.syeyoung.dungeonsguide.mod.utils.TextUtils; import net.minecraft.client.Minecraft; import net.minecraft.client.gui.FontRenderer; @@ -45,10 +51,18 @@ import java.util.Map; import java.util.concurrent.*; public class PartyInviteViewer extends SimpleFeature { + private WidgetPartyInviteViewer partyInviteViewer; + private OverlayWidget widget; 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"); - + addParameter("ttl", new FeatureParameter("ttl", "Request Duration", "The duration after which the requests will be dismissed automatically. The value is in seconds.", 15, "integer")); + widget = new OverlayWidget( + partyInviteViewer = new WidgetPartyInviteViewer(), + OverlayType.OVER_ANY, + () -> new Rect(0,0,Minecraft.getMinecraft().displayWidth, Minecraft.getMinecraft().displayHeight) + ); + OverlayManager.getInstance().addOverlay(widget); } @Override @@ -56,277 +70,21 @@ public class PartyInviteViewer extends SimpleFeature { return false; } - @DGEventHandler - public void onGuiPostRender(GuiScreenEvent.DrawScreenEvent.Post rendered) { - renderRequests(true); - } - - @DGEventHandler - public void drawScreen(RenderGameOverlayEvent.Post postRender) { - - if (!(postRender.type == RenderGameOverlayEvent.ElementType.EXPERIENCE || postRender.type == RenderGameOverlayEvent.ElementType.JUMPBAR)) return; - - try { - renderRequests(false); - } catch (Throwable t) { - t.printStackTrace(); - } - } - @DGEventHandler + @DGEventHandler(triggerOutOfSkyblock = true) public void onTick(DGTickEvent tickEvent) { try { - List partyJoinRequestList = new ArrayList<>(); - boolean isOnHypixel = DungeonsGuide.getDungeonsGuide().getSkyblockStatus().isOnHypixel(); - for (PartyJoinRequest joinRequest:joinRequests) { - if (joinRequest.getTtl() != -1) { - joinRequest.setTtl(joinRequest.getTtl() - 1); - if (joinRequest.getTtl() == 0 || !isOnHypixel) { - partyJoinRequestList.add(joinRequest); - } - } else if (!isOnHypixel){ -// DiscordRPC.discordRespond(joinRequest.getDiscordUser().userId, DiscordRPC.DiscordReply.NO); - partyJoinRequestList.add(joinRequest); - } else if (joinRequest.getExpire() < System.currentTimeMillis()) { - partyJoinRequestList.add(joinRequest); - } - } - joinRequests.removeAll(partyJoinRequestList); + partyInviteViewer.tick(); } catch (Throwable e) {e.printStackTrace();} } - - @DGEventHandler - 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)) { - mouseInputEvent.setCanceled(true); - - if (Mouse.getEventButton() == -1) return; - - if (joinRequest.getReply() != null) { - joinRequests.remove(joinRequest); - return; - } - - if (!joinRequest.isInvite()) { - if (joinRequest.getAcceptRect().contains(mouseX, mouseY)) { - joinRequest.setReply(PartyJoinRequest.Reply.ACCEPT); - joinRequest.setTtl(60); - DiscordIntegrationManager.INSTANCE.respondToJoinRequest(joinRequest.getDiscordUser().getId(), PartyJoinRequest.Reply.ACCEPT); - return; - } - - if (joinRequest.getDenyRect().contains(mouseX, mouseY)) { - joinRequest.setReply(PartyJoinRequest.Reply.DENY); - joinRequest.setTtl(60); - DiscordIntegrationManager.INSTANCE.respondToJoinRequest(joinRequest.getDiscordUser().getId(), PartyJoinRequest.Reply.DENY); - return; - } - - if (joinRequest.getIgnoreRect().contains(mouseX, mouseY)) { - joinRequest.setReply(PartyJoinRequest.Reply.IGNORE); - joinRequest.setTtl(60); - DiscordIntegrationManager.INSTANCE.respondToJoinRequest(joinRequest.getDiscordUser().getId(), PartyJoinRequest.Reply.IGNORE); - return; - } - } else { - if (joinRequest.getAcceptRect().contains(mouseX, mouseY)) { - joinRequest.setReply(PartyJoinRequest.Reply.ACCEPT); - joinRequest.setTtl(60); - DiscordIntegrationManager.INSTANCE.acceptInvite(joinRequest.getHandle()); - return; - } - - if (joinRequest.getDenyRect().contains(mouseX, mouseY)) { - joinRequest.setReply(PartyJoinRequest.Reply.DENY); - joinRequest.setTtl(60); - return; - } - } - - return; - } - } - } - - - - public CopyOnWriteArrayList joinRequests = new CopyOnWriteArrayList<>(); - ExecutorService executorService = Executors.newFixedThreadPool(3, DungeonsGuide.THREAD_FACTORY); - public Map> futureMap = new HashMap<>(); - public Map imageMap = new HashMap<>(); - - public Future loadImage(String url) { - if (imageMap.containsKey(url)) return CompletableFuture.completedFuture(imageMap.get(url)); - if (futureMap.containsKey(url)) return futureMap.get(url); - Future future = executorService.submit(() -> { - try { - ImageTexture imageTexture = new ImageTexture(url); - imageMap.put(url, imageTexture); - return imageTexture; - } catch (Exception e) { - throw e; - } - }); - futureMap.put(url,future); - return future; - } - - - public void renderRequests(boolean hover) { - try { - GlStateManager.pushMatrix(); - 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 = 5; - int y = 5; - for (PartyJoinRequest partyJoinRequest : joinRequests) { - renderRequest(partyJoinRequest, x, y, 350,height, hover); - y += height + gap; - } - GlStateManager.popMatrix(); - GlStateManager.enableBlend(); - } catch (Throwable t) { - t.printStackTrace(); - } - } - - - public void renderRequest(PartyJoinRequest partyJoinRequest, int x, int y, int width, int height, boolean hover) { - ScaledResolution sr = new ScaledResolution(Minecraft.getMinecraft()); - - int mouseX = Mouse.getX(); - int mouseY = Minecraft.getMinecraft().displayHeight - Mouse.getY() +3; - - partyJoinRequest.getWholeRect().setBounds(x,y,width,height); - - - GlStateManager.pushMatrix(); - 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/"+partyJoinRequest.getDiscordUser().getId()+"/"+partyJoinRequest.getAvatar()+"."+(partyJoinRequest.getAvatar().startsWith("a_") ? "gif":"png"); - Future loadedImageFuture = loadImage(avatar); - ImageTexture loadedImage = null; - if (loadedImageFuture.isDone()) { - try { - loadedImage = loadedImageFuture.get(); - } catch (InterruptedException | ExecutionException e) { - e.printStackTrace(); - } - } - if (loadedImage != null) { - loadedImage.drawFrame( 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(partyJoinRequest.getUsername()+"", 0,0, 0xFFFFFFFF, true); - GlStateManager.popMatrix(); - - GlStateManager.pushMatrix(); - GlStateManager.translate(fr.getStringWidth(partyJoinRequest.getUsername()+"") * 3 + 1, (int)(fr.FONT_HEIGHT*1.5), 0); - fr.drawString("#"+partyJoinRequest.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); - if (partyJoinRequest.isInvite()) - fr.drawString("§ewants to you to join their party! ("+(TextUtils.formatTime(partyJoinRequest.getExpire() - System.currentTimeMillis()))+")", 0,0,0xFFFFFFFF,false); - else - fr.drawString("wants to join your party! ("+(TextUtils.formatTime(partyJoinRequest.getExpire() - System.currentTimeMillis()))+")", 0,0,0xFFFFFFFF,false); - GlStateManager.popMatrix(); - GlStateManager.popMatrix(); - if (partyJoinRequest.getReply() == null) { - GlStateManager.pushMatrix(); - GlStateManager.translate(height + 3, height - 32, 0); - int widthForTheThing = (width - height) / 3; - GlStateManager.pushMatrix(); - String text = "Accept"; - partyJoinRequest.getAcceptRect().setBounds(x + height + 3, y + height - 25, widthForTheThing - 10, 25); - Gui.drawRect(0, 0, widthForTheThing - 10, 25, hover && partyJoinRequest.getAcceptRect().contains(mouseX, mouseY) ? 0xFF859DF0 : 0xFF7289da); - GlStateManager.translate((widthForTheThing - 10 - fr.getStringWidth(text) * 2) / 2, 15 - fr.FONT_HEIGHT, 0); - - GlStateManager.scale(2.0f, 2.0f, 1.0f); - 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); - fr.drawString(text, 0, 0, 0xFFFFFFFF); - GlStateManager.popMatrix(); - GlStateManager.translate(widthForTheThing, 0, 0); - partyJoinRequest.getDenyRect().setBounds(x + height + 3 + widthForTheThing, y + height - 25, widthForTheThing - 10, 25); - Gui.drawRect(0, 0, widthForTheThing - 10, 25, hover && partyJoinRequest.getDenyRect().contains(mouseX, mouseY) ? 0xFFAEC0CB : 0xFF99aab5); - GlStateManager.pushMatrix(); - text = "Deny"; - GlStateManager.translate((widthForTheThing - 10 - fr.getStringWidth(text) * 2) / 2, 15 - fr.FONT_HEIGHT, 0); - GlStateManager.scale(2.0f, 2.0f, 1.0f); - 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); - fr.drawString(text, 0, 0, 0xFFFFFFFF); - GlStateManager.popMatrix(); - if (!partyJoinRequest.isInvite()) { - GlStateManager.translate(widthForTheThing, 0, 0); - partyJoinRequest.getIgnoreRect().setBounds(x + height + 3 + widthForTheThing + widthForTheThing, y + height - 25, widthForTheThing - 10, 25); - Gui.drawRect(0, 0, widthForTheThing - 10, 25, hover && partyJoinRequest.getIgnoreRect().contains(mouseX, mouseY) ? 0xFFAEC0CB : 0xFF99aab5); // AEC0CB - - GlStateManager.pushMatrix(); - text = "Ignore"; - GlStateManager.translate((widthForTheThing - 10 - fr.getStringWidth(text) * 2) / 2, 15 - fr.FONT_HEIGHT, 0); - GlStateManager.scale(2.0f, 2.0f, 1.0f); - 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); - fr.drawString(text, 0, 0, 0xFFFFFFFF); - GlStateManager.popMatrix(); - } - GlStateManager.popMatrix(); - } else { - GlStateManager.pushMatrix(); - GlStateManager.translate(height + 3, height - 28, 0); - GlStateManager.scale(2.0f,2.0f,1.0f); - 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); - fr.drawString(partyJoinRequest.getReply().getPast()+" the invite.",0,0,0xFFFFFFFF); - GlStateManager.popMatrix(); - } - GlStateManager.popMatrix(); - } @DGEventHandler(triggerOutOfSkyblock = true) public void onDiscordUserJoinRequest(DiscordUserJoinRequestEvent event) { - PartyJoinRequest partyInvite = new PartyJoinRequest(); - partyInvite.setDiscordUser(event.getDiscordUser()); - partyInvite.setExpire(System.currentTimeMillis() + 30000L); - partyInvite.setInvite(false); - joinRequests.add(partyInvite); + partyInviteViewer.addJoinRequest(event); } @DGEventHandler(triggerOutOfSkyblock = true) public void onDiscordUserJoinRequest(DiscordUserInvitedEvent event) { - PartyJoinRequest partyInvite = new PartyJoinRequest(); - partyInvite.setDiscordUser(event.getDiscordUser()); - partyInvite.setHandle(event.getHandle()); - partyInvite.setExpire(System.currentTimeMillis() + 30000L); - partyInvite.setInvite(true); - joinRequests.add(partyInvite); + partyInviteViewer.addInvite(event); } } diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/features/impl/discord/inviteViewer/PartyJoinRequest.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/features/impl/discord/inviteViewer/PartyJoinRequest.java deleted file mode 100644 index 98d601b9..00000000 --- a/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/features/impl/discord/inviteViewer/PartyJoinRequest.java +++ /dev/null @@ -1,60 +0,0 @@ -/* - * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod - * Copyright (C) 2021 cyoung06 - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as published - * by the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see . - */ - -package kr.syeyoung.dungeonsguide.mod.features.impl.discord.inviteViewer; - -import com.jagrosh.discordipc.entities.User; -import kr.syeyoung.dungeonsguide.mod.discord.InviteHandle; -import lombok.AllArgsConstructor; -import lombok.Data; -import lombok.Getter; - -import java.awt.*; - -@Data -public class PartyJoinRequest { - private User discordUser; - private InviteHandle handle; - - public void setDiscordUser(User discordUser) { - this.discordUser = discordUser; - username = discordUser.getName(); - discriminator = discordUser.getDiscriminator(); - avatar= discordUser.getEffectiveAvatarUrl(); - } - - private String username, discriminator, avatar; - private long expire; - - private Rectangle wholeRect = new Rectangle(); - private Rectangle acceptRect = new Rectangle(); - private Rectangle denyRect = new Rectangle(); - private Rectangle ignoreRect = new Rectangle(); - - private boolean isInvite; - private int ttl = -1; - private Reply reply; - - @AllArgsConstructor - public enum Reply { - ACCEPT("Accepted"), DENY("Denied"), IGNORE("Ignored"); - - @Getter - private final String past; - } -} diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/features/impl/discord/inviteViewer/Reply.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/features/impl/discord/inviteViewer/Reply.java new file mode 100644 index 00000000..c36c0f04 --- /dev/null +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/features/impl/discord/inviteViewer/Reply.java @@ -0,0 +1,30 @@ +/* + * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod + * Copyright (C) 2023 cyoung06 (syeyoung) + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +package kr.syeyoung.dungeonsguide.mod.features.impl.discord.inviteViewer; + +import lombok.AllArgsConstructor; +import lombok.Getter; + +@AllArgsConstructor +public enum Reply { + ACCEPT("Accepted"), DENY("Denied"), IGNORE("Ignored"); + + @Getter + private final String past; +} diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/features/impl/discord/inviteViewer/TTL.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/features/impl/discord/inviteViewer/TTL.java new file mode 100644 index 00000000..8edc2dd6 --- /dev/null +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/features/impl/discord/inviteViewer/TTL.java @@ -0,0 +1,24 @@ +/* + * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod + * Copyright (C) 2023 cyoung06 (syeyoung) + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +package kr.syeyoung.dungeonsguide.mod.features.impl.discord.inviteViewer; + +public interface TTL { + long startedDisplaying(); + long ttl(); +} diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/features/impl/discord/inviteViewer/WidgetInvite.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/features/impl/discord/inviteViewer/WidgetInvite.java new file mode 100644 index 00000000..ebad7821 --- /dev/null +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/features/impl/discord/inviteViewer/WidgetInvite.java @@ -0,0 +1,75 @@ +/* + * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod + * Copyright (C) 2023 cyoung06 (syeyoung) + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +package kr.syeyoung.dungeonsguide.mod.features.impl.discord.inviteViewer; + +import kr.syeyoung.dungeonsguide.mod.discord.DiscordIntegrationManager; +import kr.syeyoung.dungeonsguide.mod.events.impl.DiscordUserInvitedEvent; +import kr.syeyoung.dungeonsguide.mod.events.impl.DiscordUserJoinRequestEvent; +import kr.syeyoung.dungeonsguide.mod.features.FeatureRegistry; +import kr.syeyoung.dungeonsguide.mod.guiv2.BindableAttribute; +import kr.syeyoung.dungeonsguide.mod.guiv2.xml.AnnotatedWidget; +import kr.syeyoung.dungeonsguide.mod.guiv2.xml.annotations.Bind; +import kr.syeyoung.dungeonsguide.mod.guiv2.xml.annotations.On; +import net.minecraft.util.ResourceLocation; + +public class WidgetInvite extends AnnotatedWidget implements TTL { + + @Bind(variableName = "username") + public final BindableAttribute username; + @Bind(variableName = "discriminator") + public final BindableAttribute discriminator; + @Bind(variableName = "avatarUrl") + public final BindableAttribute avatarURL; + private WidgetPartyInviteViewer inviteViewer; + private DiscordUserInvitedEvent event; + private long start; + public WidgetInvite(WidgetPartyInviteViewer parent, DiscordUserInvitedEvent invitedEvent) { + super(new ResourceLocation("dungeonsguide:gui/features/discordParty/invite.gui")); + this.inviteViewer = parent; + this.event = invitedEvent; + this.start = System.currentTimeMillis(); + username = new BindableAttribute<>(String.class, invitedEvent.getDiscordUser().getName()); + discriminator = new BindableAttribute<>(String.class, invitedEvent.getDiscordUser().getDiscriminator()); + avatarURL = new BindableAttribute<>(String.class, invitedEvent.getDiscordUser().getEffectiveAvatarUrl()); + } + + public DiscordUserInvitedEvent getEvent() { + return event; + } + + @On(functionName = "accept") + public void accept() { + inviteViewer.remove(this); + DiscordIntegrationManager.INSTANCE.acceptInvite(event.getHandle()); + } + @On(functionName = "deny") + public void deny() { + inviteViewer.remove(this); + } + + @Override + public long startedDisplaying() { + return 0; + } + + @Override + public long ttl() { + return FeatureRegistry.DISCORD_ASKTOJOIN.getParameter("ttl").getValue() * 1000; + } +} diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/features/impl/discord/inviteViewer/WidgetJoinRequest.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/features/impl/discord/inviteViewer/WidgetJoinRequest.java new file mode 100644 index 00000000..7c51636b --- /dev/null +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/features/impl/discord/inviteViewer/WidgetJoinRequest.java @@ -0,0 +1,80 @@ +/* + * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod + * Copyright (C) 2023 cyoung06 (syeyoung) + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +package kr.syeyoung.dungeonsguide.mod.features.impl.discord.inviteViewer; + +import kr.syeyoung.dungeonsguide.mod.discord.DiscordIntegrationManager; +import kr.syeyoung.dungeonsguide.mod.events.impl.DiscordUserJoinRequestEvent; +import kr.syeyoung.dungeonsguide.mod.features.FeatureRegistry; +import kr.syeyoung.dungeonsguide.mod.guiv2.BindableAttribute; +import kr.syeyoung.dungeonsguide.mod.guiv2.xml.AnnotatedWidget; +import kr.syeyoung.dungeonsguide.mod.guiv2.xml.annotations.Bind; +import kr.syeyoung.dungeonsguide.mod.guiv2.xml.annotations.On; +import net.minecraft.util.ResourceLocation; + +public class WidgetJoinRequest extends AnnotatedWidget implements TTL{ + + @Bind(variableName = "username") + public final BindableAttribute username; + @Bind(variableName = "discriminator") + public final BindableAttribute discriminator; + @Bind(variableName = "avatarUrl") + public final BindableAttribute avatarURL; + private WidgetPartyInviteViewer inviteViewer; + private DiscordUserJoinRequestEvent event; + private long start; + public WidgetJoinRequest(WidgetPartyInviteViewer parent, DiscordUserJoinRequestEvent joinRequestEvent) { + super(new ResourceLocation("dungeonsguide:gui/features/discordParty/joinRequest.gui")); + this.inviteViewer = parent; + this.event = joinRequestEvent; + start = System.currentTimeMillis(); + username = new BindableAttribute<>(String.class, joinRequestEvent.getDiscordUser().getName()); + discriminator = new BindableAttribute<>(String.class, joinRequestEvent.getDiscordUser().getDiscriminator()); + avatarURL = new BindableAttribute<>(String.class, joinRequestEvent.getDiscordUser().getEffectiveAvatarUrl()); + } + + public DiscordUserJoinRequestEvent getEvent() { + return event; + } + + @On(functionName = "accept") + public void accept() { + inviteViewer.remove(this); + DiscordIntegrationManager.INSTANCE.respondToJoinRequest(event.getDiscordUser().getId(), Reply.ACCEPT); + } + @On(functionName = "deny") + public void deny() { + inviteViewer.remove(this); + DiscordIntegrationManager.INSTANCE.respondToJoinRequest(event.getDiscordUser().getId(), Reply.DENY); + } + @On(functionName = "ignore") + public void ignore() { + inviteViewer.remove(this); + DiscordIntegrationManager.INSTANCE.respondToJoinRequest(event.getDiscordUser().getId(), Reply.IGNORE); + } + + @Override + public long startedDisplaying() { + return start; + } + + @Override + public long ttl() { + return FeatureRegistry.DISCORD_ASKTOJOIN.getParameter("ttl").getValue() * 1000; + } +} diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/features/impl/discord/inviteViewer/WidgetPartyInviteViewer.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/features/impl/discord/inviteViewer/WidgetPartyInviteViewer.java new file mode 100644 index 00000000..969e7f94 --- /dev/null +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/features/impl/discord/inviteViewer/WidgetPartyInviteViewer.java @@ -0,0 +1,81 @@ +/* + * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod + * Copyright (C) 2023 cyoung06 (syeyoung) + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +package kr.syeyoung.dungeonsguide.mod.features.impl.discord.inviteViewer; + +import kr.syeyoung.dungeonsguide.mod.events.impl.DiscordUserInvitedEvent; +import kr.syeyoung.dungeonsguide.mod.events.impl.DiscordUserJoinRequestEvent; +import kr.syeyoung.dungeonsguide.mod.guiv2.BindableAttribute; +import kr.syeyoung.dungeonsguide.mod.guiv2.DomElement; +import kr.syeyoung.dungeonsguide.mod.guiv2.Widget; +import kr.syeyoung.dungeonsguide.mod.guiv2.elements.Column; +import kr.syeyoung.dungeonsguide.mod.guiv2.xml.AnnotatedWidget; +import kr.syeyoung.dungeonsguide.mod.guiv2.xml.annotations.Bind; +import net.minecraft.util.ResourceLocation; + +import java.util.*; +import java.util.concurrent.CopyOnWriteArrayList; + +public class WidgetPartyInviteViewer extends AnnotatedWidget { + @Bind(variableName = "listApi") + public final BindableAttribute columnApi = new BindableAttribute<>(Column.class); + + public WidgetPartyInviteViewer() { + super(new ResourceLocation("dungeonsguide:gui/features/discordParty/partyInviteList.gui")); + } + + private final Set joinReqUid = Collections.synchronizedSet( new HashSet<>()); + private final Set inviteUid = Collections.synchronizedSet( new HashSet<>()); + private final List widgetList = new CopyOnWriteArrayList<>(); + public void addJoinRequest(DiscordUserJoinRequestEvent joinRequest) { + if (joinReqUid.contains(joinRequest.getDiscordUser().getId())) return; + joinReqUid.add(joinRequest.getDiscordUser().getId()); + WidgetJoinRequest request; + columnApi.getValue().addWidget(request = new WidgetJoinRequest(this, joinRequest)); + widgetList.add(request); + } + + public void addInvite(DiscordUserInvitedEvent inviteEvent) { + if (inviteUid.contains(inviteEvent.getDiscordUser().getId())) return; + inviteUid.add(inviteEvent.getDiscordUser().getId()); + WidgetInvite invite; + columnApi.getValue().addWidget(invite = new WidgetInvite(this, inviteEvent)); + widgetList.add(invite); + } + + public void remove(Widget widget) { + columnApi.getValue().removeWidget(widget); + widgetList.remove(widget); + + if (widget instanceof WidgetJoinRequest) + joinReqUid.remove(((WidgetJoinRequest) widget).getEvent().getDiscordUser().getId()); + if (widget instanceof WidgetInvite) + inviteUid.remove(((WidgetInvite) widget).getEvent().getDiscordUser().getId()); + } + + public void tick() { + List toRemove = new ArrayList<>(); + for (Widget widget : widgetList) { + TTL ttl = (TTL) widget; + if (ttl.startedDisplaying() + ttl.ttl() < System.currentTimeMillis()) { + toRemove.add(widget); + } + } + toRemove.forEach(this::remove); + } +} diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/features/impl/discord/invteTooltip/MTooltipInviteElement.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/features/impl/discord/invteTooltip/MTooltipInviteElement.java index f895ad4d..7e0aec9e 100644 --- a/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/features/impl/discord/invteTooltip/MTooltipInviteElement.java +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/features/impl/discord/invteTooltip/MTooltipInviteElement.java @@ -21,7 +21,7 @@ package kr.syeyoung.dungeonsguide.mod.features.impl.discord.invteTooltip; import kr.syeyoung.dungeonsguide.mod.discord.JDiscordRelation; import kr.syeyoung.dungeonsguide.mod.features.FeatureRegistry; -import kr.syeyoung.dungeonsguide.mod.features.impl.discord.inviteViewer.ImageTexture; +import kr.syeyoung.dungeonsguide.mod.guiv2.elements.image.ImageTexture; import kr.syeyoung.dungeonsguide.mod.gui.MPanel; import kr.syeyoung.dungeonsguide.mod.gui.elements.MButton; import kr.syeyoung.dungeonsguide.mod.utils.RenderUtils; @@ -38,6 +38,8 @@ import java.util.function.Consumer; public class MTooltipInviteElement extends MPanel { private JDiscordRelation relation; private MButton invite; + private ImageTexture texture; + public MTooltipInviteElement(JDiscordRelation jDiscordRelation, boolean invited, Consumer inviteCallback) { this.relation = jDiscordRelation; this.invite = new MButton(); @@ -67,6 +69,12 @@ public class MTooltipInviteElement extends MPanel { invite.setForeground(new Color(0xFF02EE67)); } + if (!jDiscordRelation.getDiscordUser().getEffectiveAvatarUrl().isEmpty()) { + ImageTexture.loadImage(jDiscordRelation.getDiscordUser().getEffectiveAvatarUrl(), (cback) -> { + this.texture = cback; + }); + } + add(invite); } @@ -78,23 +86,12 @@ public class MTooltipInviteElement extends MPanel { } FontRenderer fr = Minecraft.getMinecraft().fontRendererObj; - if (!relation.getDiscordUser().getEffectiveAvatarUrl().isEmpty()){ - String avatar = relation.getDiscordUser().getEffectiveAvatarUrl(); - Future 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( 3,3,bounds.height-6,bounds.height-6); + if (texture != null) { + texture.drawFrame( 3,3,bounds.height-6,bounds.height-6); } else { Gui.drawRect(3, 3, bounds.height - 6, bounds.height-6, 0xFF4E4E4E); } - } + fr.drawString(relation.getDiscordUser().getName()+"#"+relation.getDiscordUser().getDiscriminator(), bounds.height,(bounds.height-fr.FONT_HEIGHT)/2, -1); } diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/features/impl/discord/onlinealarm/PlayingDGAlarm.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/features/impl/discord/onlinealarm/PlayingDGAlarm.java index ae799764..892cac52 100644 --- a/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/features/impl/discord/onlinealarm/PlayingDGAlarm.java +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/features/impl/discord/onlinealarm/PlayingDGAlarm.java @@ -26,7 +26,12 @@ import kr.syeyoung.dungeonsguide.mod.events.impl.DGTickEvent; import kr.syeyoung.dungeonsguide.mod.events.impl.DiscordUserUpdateEvent; import kr.syeyoung.dungeonsguide.mod.features.FeatureRegistry; import kr.syeyoung.dungeonsguide.mod.features.SimpleFeature; -import kr.syeyoung.dungeonsguide.mod.features.impl.discord.inviteViewer.ImageTexture; +import kr.syeyoung.dungeonsguide.mod.features.impl.discord.inviteViewer.WidgetPartyInviteViewer; +import kr.syeyoung.dungeonsguide.mod.guiv2.elements.image.ImageTexture; +import kr.syeyoung.dungeonsguide.mod.guiv2.primitive.Rect; +import kr.syeyoung.dungeonsguide.mod.overlay.OverlayManager; +import kr.syeyoung.dungeonsguide.mod.overlay.OverlayType; +import kr.syeyoung.dungeonsguide.mod.overlay.OverlayWidget; import kr.syeyoung.dungeonsguide.mod.utils.TextUtils; import lombok.AllArgsConstructor; import lombok.Data; @@ -46,116 +51,31 @@ import java.util.concurrent.ExecutionException; import java.util.concurrent.Future; public class PlayingDGAlarm extends SimpleFeature { + private WidgetOnlinePeopleViewer onlinePeopleViewer; + private OverlayWidget widget; + 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"); + widget = new OverlayWidget( + onlinePeopleViewer = new WidgetOnlinePeopleViewer(), + OverlayType.OVER_ANY, + () -> new Rect(0,0,Minecraft.getMinecraft().displayWidth, Minecraft.getMinecraft().displayHeight) + ); + OverlayManager.getInstance().addOverlay(widget); } - private List notif = new CopyOnWriteArrayList<>(); - @DGEventHandler + @DGEventHandler(triggerOutOfSkyblock = true) public void onTick(DGTickEvent event) { try { - List 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); + onlinePeopleViewer.tick(); } catch (Throwable e) {e.printStackTrace();} } - - - - @DGEventHandler - public void drawScreen(RenderGameOverlayEvent.Post postRender) { - - if (!(postRender.type == RenderGameOverlayEvent.ElementType.EXPERIENCE || postRender.type == RenderGameOverlayEvent.ElementType.JUMPBAR)) return; - - 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(); - GlStateManager.translate(x,y,0); - - Gui.drawRect(0, 0,width,height, 0xFF23272a); - Gui.drawRect(2, 2, width-2, height-2, 0XFF2c2f33); - { - String avatar = online.jDiscordRelation.getDiscordUser().getEffectiveAvatarUrl(); - Future 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().getName()+"", 0,0, 0xFFFFFFFF, true); - GlStateManager.popMatrix(); - - GlStateManager.pushMatrix(); - GlStateManager.translate(fr.getStringWidth(online.getJDiscordRelation().getDiscordUser().getName()+"") * 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; - } - @DGEventHandler(triggerOutOfSkyblock = true) public void onDiscordUserUpdate(DiscordUserUpdateEvent event) { JDiscordRelation prev = event.getPrev(), current = event.getCurrent(); if (prev == null) return; if (!isDisplayable(prev) && isDisplayable(current)) { - notif.add(new PlayerOnline(current, System.currentTimeMillis()+3000)); + onlinePeopleViewer.addUser(current); } } diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/features/impl/discord/onlinealarm/WidgetOnline.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/features/impl/discord/onlinealarm/WidgetOnline.java new file mode 100644 index 00000000..8cdd3d6f --- /dev/null +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/features/impl/discord/onlinealarm/WidgetOnline.java @@ -0,0 +1,62 @@ +/* + * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod + * Copyright (C) 2023 cyoung06 (syeyoung) + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +package kr.syeyoung.dungeonsguide.mod.features.impl.discord.onlinealarm; + +import kr.syeyoung.dungeonsguide.mod.discord.JDiscordRelation; +import kr.syeyoung.dungeonsguide.mod.features.impl.discord.inviteViewer.TTL; +import kr.syeyoung.dungeonsguide.mod.guiv2.BindableAttribute; +import kr.syeyoung.dungeonsguide.mod.guiv2.xml.AnnotatedWidget; +import kr.syeyoung.dungeonsguide.mod.guiv2.xml.annotations.Bind; +import net.minecraft.util.ResourceLocation; + +public class WidgetOnline extends AnnotatedWidget implements TTL { + + @Bind(variableName = "username") + public final BindableAttribute username; + @Bind(variableName = "discriminator") + public final BindableAttribute discriminator; + @Bind(variableName = "avatarUrl") + public final BindableAttribute avatarURL; + private WidgetOnlinePeopleViewer viewer; + private JDiscordRelation relation; + private long start; + public WidgetOnline(WidgetOnlinePeopleViewer parent, JDiscordRelation relation) { + super(new ResourceLocation("dungeonsguide:gui/features/discordOnline/discordOnline.gui")); + this.viewer = parent; + this.relation = relation; + start = System.currentTimeMillis(); + username = new BindableAttribute<>(String.class, relation.getDiscordUser().getName()); + discriminator = new BindableAttribute<>(String.class, relation.getDiscordUser().getDiscriminator()); + avatarURL = new BindableAttribute<>(String.class, relation.getDiscordUser().getEffectiveAvatarUrl()); + } + + public JDiscordRelation getRelation() { + return relation; + } + + @Override + public long startedDisplaying() { + return start; + } + + @Override + public long ttl() { + return 2000; + } +} diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/features/impl/discord/onlinealarm/WidgetOnlinePeopleViewer