diff options
author | syeyoung <cyoung06@naver.com> | 2023-01-17 21:22:51 +0900 |
---|---|---|
committer | syeyoung <cyoung06@naver.com> | 2023-01-17 21:23:07 +0900 |
commit | 786be9ea22c86820c0f552a3b3a5f20b168f704b (patch) | |
tree | 0c3d675b083c3ceac0232a8ec70f41adae0600bf /mod | |
parent | 33ecb692b2b6d672ff231547a5fed4750034e490 (diff) | |
download | Skyblock-Dungeons-Guide-786be9ea22c86820c0f552a3b3a5f20b168f704b.tar.gz Skyblock-Dungeons-Guide-786be9ea22c86820c0f552a3b3a5f20b168f704b.tar.bz2 Skyblock-Dungeons-Guide-786be9ea22c86820c0f552a3b3a5f20b168f704b.zip |
- Move online alarm to overlay manager
Signed-off-by: syeyoung <cyoung06@naver.com>
Diffstat (limited to 'mod')
42 files changed, 957 insertions, 592 deletions
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<Class<? extends Event>, IEventListener> registeredHandlers = new HashMap<>(); - public static void registerActualListeners() { + public static synchronized void registerActualListeners() { for (Class<? extends Event> aClass : targets.keySet()) { if (registeredHandlers.containsKey(aClass)) continue; try { 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<Integer>("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<PartyJoinRequest> 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<PartyJoinRequest> joinRequests = new CopyOnWriteArrayList<>(); - ExecutorService executorService = Executors.newFixedThreadPool(3, DungeonsGuide.THREAD_FACTORY); - public Map<String, Future<ImageTexture>> futureMap = new HashMap<>(); - public Map<String, ImageTexture> imageMap = new HashMap<>(); - - 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<ImageTexture> 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<ImageTexture> 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 <https://www.gnu.org/licenses/>. - */ - -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 <https://www.gnu.org/licenses/>. + */ + +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 <https://www.gnu.org/licenses/>. + */ + +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 <https://www.gnu.org/licenses/>. + */ + +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<String> username; + @Bind(variableName = "discriminator") + public final BindableAttribute<String> discriminator; + @Bind(variableName = "avatarUrl") + public final BindableAttribute<String> 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.<Integer>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 <https://www.gnu.org/licenses/>. + */ + +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<String> username; + @Bind(variableName = "discriminator") + public final BindableAttribute<String> discriminator; + @Bind(variableName = "avatarUrl") + public final BindableAttribute<String> 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.<Integer>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 <https://www.gnu.org/licenses/>. + */ + +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<Column> columnApi = new BindableAttribute<>(Column.class); + + public WidgetPartyInviteViewer() { + super(new ResourceLocation("dungeonsguide:gui/features/discordParty/partyInviteList.gui")); + } + + private final Set<String> joinReqUid = Collections.synchronizedSet( new HashSet<>()); + private final Set<String> inviteUid = Collections.synchronizedSet( new HashSet<>()); + private final List<Widget> 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<Widget> 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<Long> 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<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( 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<PlayerOnline> notif = new CopyOnWriteArrayList<>(); - @DGEventHandler + @DGEventHandler(triggerOutOfSkyblock = true) public void onTick(DGTickEvent event) { 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); + 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<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().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 <https://www.gnu.org/licenses/>. + */ + +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<String> username; + @Bind(variableName = "discriminator") + public final BindableAttribute<String> discriminator; + @Bind(variableName = "avatarUrl") + public final BindableAttribute<String> 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.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/features/impl/discord/onlinealarm/WidgetOnlinePeopleViewer.java new file mode 100644 index 00000000..bf3ebe2c --- /dev/null +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/features/impl/discord/onlinealarm/WidgetOnlinePeopleViewer.java @@ -0,0 +1,72 @@ +/* + * 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 <https://www.gnu.org/licenses/>. + */ + +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.features.impl.discord.inviteViewer.WidgetJoinRequest; +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 WidgetOnlinePeopleViewer extends AnnotatedWidget { + @Bind(variableName = "listApi") + public final BindableAttribute<Column> columnApi = new BindableAttribute<>(Column.class); + + public WidgetOnlinePeopleViewer() { + super(new ResourceLocation("dungeonsguide:gui/features/discordOnline/discordOnlineList.gui")); + } + + private final Set<String> onlineUid = Collections.synchronizedSet( new HashSet<>()); + private List<Widget> widgetList = new CopyOnWriteArrayList<>(); + public void addUser(JDiscordRelation joinRequest) { + if (onlineUid.contains(joinRequest.getDiscordUser().getId())) return; + onlineUid.add(joinRequest.getDiscordUser().getId()); + WidgetOnline online; + columnApi.getValue().addWidget(online = new WidgetOnline(this, joinRequest)); + widgetList.add(online); + } + + + public void remove(Widget widget) { + columnApi.getValue().removeWidget(widget); + widgetList.remove(widget); + + if (widget instanceof WidgetOnline) + onlineUid.remove(((WidgetOnline) widget).getRelation().getDiscordUser().getId()); + } + + public void tick() { + List<Widget> 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/guiv2/DomElement.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/guiv2/DomElement.java index d49589e3..8e1c847a 100644 --- a/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/guiv2/DomElement.java +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/guiv2/DomElement.java @@ -35,6 +35,7 @@ import lombok.Setter; import java.util.ArrayList; import java.util.LinkedList; import java.util.List; +import java.util.concurrent.CopyOnWriteArrayList; public class DomElement { @Getter @@ -51,7 +52,7 @@ public class DomElement { @Setter private DomElement parent; @Getter - private List<DomElement> children = new ArrayList<>(); + private List<DomElement> children = new CopyOnWriteArrayList<>(); @Getter Context context; diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/guiv2/elements/Clip.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/guiv2/elements/Clip.java index 1eb52bf4..42ff1c7a 100644 --- a/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/guiv2/elements/Clip.java +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/guiv2/elements/Clip.java @@ -36,6 +36,8 @@ public class Clip extends AnnotatedExportOnlyWidget implements Renderer { @Override public void doRender(int absMouseX, int absMouseY, double relMouseX, double relMouseY, float partialTicks, RenderingContext context, DomElement buildContext) { if (buildContext.getChildren().isEmpty()) return; + if (buildContext.getSize().getWidth() <= 0 || buildContext.getSize().getHeight() <= 0) + return; context.pushClip(buildContext.getAbsBounds(), buildContext.getSize(), 0,0, buildContext.getSize().getWidth(), buildContext.getSize().getHeight()); DomElement value = buildContext.getChildren().get(0); diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/guiv2/elements/Column.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/guiv2/elements/Column.java index b310e6cf..dc4155b1 100644 --- a/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/guiv2/elements/Column.java +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/guiv2/elements/Column.java @@ -97,7 +97,7 @@ public class Column extends AnnotatedExportOnlyWidget implements Layouter { if (!(child.getWidget() instanceof Flexible)) { Size requiredSize = child.getLayouter().layout(child, new ConstraintBox( crossAxisAlignment == CrossAxisAlignment.STRETCH - ? constraints.getMaxWidth() : 0, constraints.getMaxWidth(), 0, Integer.MAX_VALUE + ? constraints.getMaxWidth() : 0, constraints.getMaxWidth(), 0, Double.POSITIVE_INFINITY )); saved.put(child, requiredSize); width = Math.max(width, requiredSize.getWidth()); @@ -111,13 +111,13 @@ public class Column extends AnnotatedExportOnlyWidget implements Layouter { int sumFlex = 0; for (DomElement child : buildContext.getChildren()) { if (child.getWidget() instanceof Flexible) { - sumFlex += Math.min(1, ((Flexible) child.getWidget()).flex.getValue()); + sumFlex += Math.max(1, ((Flexible) child.getWidget()).flex.getValue()); flexFound = true; } } - if (flexFound && effheight == Integer.MAX_VALUE) throw new IllegalStateException("Max height can not be infinite with flex elements"); - else if (effheight == Integer.MAX_VALUE) effheight = height; + if (flexFound && effheight == Double.POSITIVE_INFINITY) throw new IllegalStateException("Max height can not be infinite with flex elements"); + else if (effheight == Double.POSITIVE_INFINITY) effheight = height; if (flexFound) { double remainingHeight = effheight - height; @@ -135,7 +135,7 @@ public class Column extends AnnotatedExportOnlyWidget implements Layouter { } } } - width = constraints.getMaxWidth() == Integer.MAX_VALUE ? width : constraints.getMaxWidth(); + width = constraints.getMaxWidth() == Double.POSITIVE_INFINITY ? width : constraints.getMaxWidth(); @@ -198,10 +198,10 @@ public class Column extends AnnotatedExportOnlyWidget implements Layouter { for (DomElement child : buildContext.getChildren()) { if (child.getWidget() instanceof Flexible) { flex += ((Flexible) child.getWidget()).flex.getValue(); - maxPer = Double.max(maxPer, child.getLayouter().getMaxIntrinsicHeight(buildContext, width) / + maxPer = Double.max(maxPer, child.getLayouter().getMaxIntrinsicHeight(child, width) / ((Flexible) child.getWidget()).flex.getValue()); } else { - height += child.getLayouter().getMaxIntrinsicHeight(buildContext, width); + height += child.getLayouter().getMaxIntrinsicHeight(child, width); } } return height + maxPer * flex; @@ -214,8 +214,8 @@ public class Column extends AnnotatedExportOnlyWidget implements Layouter { int sumFlex = 0; for (DomElement child : buildContext.getChildren()) { if (!(child.getWidget() instanceof Flexible)) { - heightTaken += child.getLayouter().getMaxIntrinsicWidth(buildContext, Double.POSITIVE_INFINITY); - maxWidth = Double.max(maxWidth, child.getLayouter().getMaxIntrinsicWidth(buildContext, 0)); + heightTaken += child.getLayouter().getMaxIntrinsicHeight(child, 0); + maxWidth = Double.max(maxWidth, child.getLayouter().getMaxIntrinsicWidth(child, 0)); } else { sumFlex += ((Flexible) child.getWidget()).flex.getValue(); } @@ -223,9 +223,10 @@ public class Column extends AnnotatedExportOnlyWidget implements Layouter { double leftOver = height - heightTaken; if (sumFlex > 0) { double per = leftOver / sumFlex; + if (height == 0) per = 0; for (DomElement child : buildContext.getChildren()) { if (child.getWidget() instanceof Flexible) { - maxWidth = Double.max(maxWidth, child.getLayouter().getMaxIntrinsicWidth(buildContext, per * ((Flexible) child.getWidget()).flex.getValue())); + maxWidth = Double.max(maxWidth, child.getLayouter().getMaxIntrinsicWidth(child, per * ((Flexible) child.getWidget()).flex.getValue())); } } } diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/guiv2/elements/ConstrainedBox.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/guiv2/elements/ConstrainedBox.java new file mode 100644 index 00000000..e26085c5 --- /dev/null +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/guiv2/elements/ConstrainedBox.java @@ -0,0 +1,102 @@ +/* + * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod + * Copyright (C) 2022 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 <https://www.gnu.org/licenses/>. + */ + +package kr.syeyoung.dungeonsguide.mod.guiv2.elements; + +import kr.syeyoung.dungeonsguide.mod.guiv2.*; +import kr.syeyoung.dungeonsguide.mod.guiv2.layouter.Layouter; +import kr.syeyoung.dungeonsguide.mod.guiv2.primitive.ConstraintBox; +import kr.syeyoung.dungeonsguide.mod.guiv2.primitive.Rect; +import kr.syeyoung.dungeonsguide.mod.guiv2.primitive.Size; +import kr.syeyoung.dungeonsguide.mod.guiv2.xml.AnnotatedExportOnlyWidget; +import kr.syeyoung.dungeonsguide.mod.guiv2.xml.annotations.Export; + +import java.util.Collections; +import java.util.List; +import java.util.Objects; + +public class ConstrainedBox extends AnnotatedExportOnlyWidget implements Layouter { + + @Export(attributeName = "minWidth") + public final BindableAttribute<Double> minWidth = new BindableAttribute<>(Double.class, 0.0); + @Export(attributeName = "minHeight") + public final BindableAttribute<Double> minHeight = new BindableAttribute<>(Double.class, 0.0); + @Export(attributeName = "maxWidth") + public final BindableAttribute<Double> maxWidth = new BindableAttribute<>(Double.class, Double.POSITIVE_INFINITY); + @Export(attributeName = "maxHeight") + public final BindableAttribute<Double> maxHeight = new BindableAttribute<>(Double.class, Double.POSITIVE_INFINITY); + + + @Export(attributeName = "$") + public final BindableAttribute<Widget> child = new BindableAttribute<>(Widget.class); + + + @Override + public List<Widget> build(DomElement buildContext) { + return child.getValue() == null ? Collections.EMPTY_LIST : Collections.singletonList(child.getValue()); + } + + public ConstrainedBox() { + minWidth.addOnUpdate((a, b) -> getDomElement().requestRelayout()); + minHeight.addOnUpdate((a, b) -> getDomElement().requestRelayout()); + maxWidth.addOnUpdate((a, b) -> getDomElement().requestRelayout()); + maxHeight.addOnUpdate((a, b) -> getDomElement().requestRelayout()); + } + + @Override + public Size layout(DomElement buildContext, ConstraintBox constraintBox) { + + double minWidth = Layouter.clamp(this.minWidth.getValue(), constraintBox.getMinWidth(), constraintBox.getMaxWidth()); + double minHeight = Layouter.clamp(this.minHeight.getValue(), constraintBox.getMinHeight(), constraintBox.getMaxHeight()); + + double maxWidth = Layouter.clamp(this.maxWidth.getValue(), constraintBox.getMinWidth(), constraintBox.getMaxWidth()); + double maxHeight = Layouter.clamp(this.maxHeight.getValue(), constraintBox.getMinHeight(), constraintBox.getMaxHeight()); + + if (getDomElement().getChildren().isEmpty()) { + return new Size(maxWidth == Double.POSITIVE_INFINITY ? 0 : maxWidth, + maxHeight == Double.POSITIVE_INFINITY ? 0 : maxHeight); + } + + DomElement child = getDomElement().getChildren().get(0); + Size dim = child.getLayouter().layout(child, new ConstraintBox( + minWidth, maxWidth, minHeight, maxHeight + )); // force size heh. + child.setRelativeBound(new Rect(0, 0, dim.getWidth(), dim.getHeight())); + return dim; + } + + @Override + public boolean canCutRequest() { + return Objects.equals(minWidth.getValue(), maxWidth.getValue()) + && Objects.equals(minHeight.getValue(), maxHeight.getValue()); + } + + @Override + public double getMaxIntrinsicHeight(DomElement buildContext, double width) { + DomElement child = buildContext.getChildren().get(0); + return Layouter.clamp(child.getLayouter().getMaxIntrinsicHeight(child, width), + minHeight.getValue() == Double.POSITIVE_INFINITY ? 0 : minHeight.getValue(), maxHeight.getValue()); + } + + @Override + public double getMaxIntrinsicWidth(DomElement buildContext, double height) { + DomElement child = buildContext.getChildren().get(0); + return Layouter.clamp(child.getLayouter().getMaxIntrinsicWidth(child, height), + minWidth.getValue() == Double.POSITIVE_INFINITY ? 0 : minWidth.getValue(), maxWidth.getValue()); + } +} diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/guiv2/elements/Flexible.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/guiv2/elements/Flexible.java index 09c1dcaf..4783b426 100644 --- a/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/guiv2/elements/Flexible.java +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/guiv2/elements/Flexible.java @@ -32,6 +32,7 @@ import kr.syeyoung.dungeonsguide.mod.guiv2.xml.data.WidgetList; import java.awt.*; import java.util.Collections; import java.util.List; +import java.util.Optional; // yes it's that flexible from flutter public class Flexible extends AnnotatedExportOnlyWidget implements Layouter { @@ -50,8 +51,8 @@ public class Flexible extends AnnotatedExportOnlyWidget implements Layouter { } public Flexible() { - flex.addOnUpdate((a,b) -> getDomElement().requestRelayout()); - fit.addOnUpdate((a,b) -> getDomElement().requestRelayout()); + flex.addOnUpdate((a,b) -> Optional.ofNullable(getDomElement().getParent()).ifPresent(DomElement::requestRelayout)); + fit.addOnUpdate((a,b) -> Optional.ofNullable(getDomElement().getParent()).ifPresent(DomElement::requestRelayout)); } @Override @@ -64,8 +65,8 @@ public class Flexible extends AnnotatedExportOnlyWidget implements Layouter { FlexFit fit = this.fit.getValue(); ConstraintBox box = fit == FlexFit.TIGHT ? - new ConstraintBox(constraintBox.getMaxWidth() == Integer.MAX_VALUE ? 0 : constraintBox.getMaxWidth(), constraintBox.getMaxWidth() - , constraintBox.getMaxHeight() == Integer.MAX_VALUE ? 0 : constraintBox.getMaxHeight(), constraintBox.getMaxHeight()) + new ConstraintBox(constraintBox.getMaxWidth() == Double.POSITIVE_INFINITY ? 0 : constraintBox.getMaxWidth(), constraintBox.getMaxWidth() + , constraintBox.getMaxHeight() == Double.POSITIVE_INFINITY ? 0 : constraintBox.getMaxHeight(), constraintBox.getMaxHeight()) : ConstraintBox.loose(constraintBox.getMaxWidth(), constraintBox.getMaxHeight()); DomElement child = buildContext.getChildren().get(0); diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/guiv2/elements/IntrinsicHeight.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/guiv2/elements/IntrinsicHeight.java index 484e46f7..f821de54 100644 --- a/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/guiv2/elements/IntrinsicHeight.java +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/guiv2/elements/IntrinsicHeight.java @@ -44,7 +44,7 @@ public class IntrinsicHeight extends AnnotatedExportOnlyWidget implements Layout public Size layout(DomElement buildContext, ConstraintBox constraintBox) { DomElement elem = buildContext.getChildren().get(0); double height = elem.getLayouter().getMaxIntrinsicHeight(elem, constraintBox.getMaxWidth() == Double.POSITIVE_INFINITY ? 0 : constraintBox.getMaxWidth()); - Size size = elem.getLayouter().layout(buildContext, new ConstraintBox( + Size size = elem.getLayouter().layout(elem, new ConstraintBox( constraintBox.getMinWidth(), constraintBox.getMaxWidth(), height, height )); elem.setRelativeBound(new Rect(0,0,size.getWidth(), size.getHeight())); diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/guiv2/elements/IntrinsicWidth.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/guiv2/elements/IntrinsicWidth.java index 9754ec1c..306d366b 100644 --- a/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/guiv2/elements/IntrinsicWidth.java +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/guiv2/elements/IntrinsicWidth.java @@ -44,7 +44,7 @@ public class IntrinsicWidth extends AnnotatedExportOnlyWidget implements Layoute public Size layout(DomElement buildContext, ConstraintBox constraintBox) { DomElement elem = buildContext.getChildren().get(0); double width = elem.getLayouter().getMaxIntrinsicWidth(elem, constraintBox.getMaxHeight() == Double.POSITIVE_INFINITY ? 0 : constraintBox.getMaxHeight()); - Size size = elem.getLayouter().layout(buildContext, new ConstraintBox( + Size size = elem.getLayouter().layout(elem, new ConstraintBox( width, width, constraintBox.getMinHeight(), constraintBox.getMaxHeight() )); elem.setRelativeBound(new Rect(0,0,size.getWidth(), size.getHeight())); diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/guiv2/elements/Line.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/guiv2/elements/Line.java index 5f0d0395..32bd97e0 100644 --- a/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/guiv2/elements/Line.java +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/guiv2/elements/Line.java @@ -123,6 +123,7 @@ public class Line extends AnnotatedExportOnlyWidget implements Layouter, Rendere GL11.glVertex2d(w/2.0f, h); } GL11.glEnd(); + GlStateManager.enableTexture2D(); if (pattern != null) { GL11.glDisable(GL11.GL_LINE_STIPPLE); diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/guiv2/elements/Row.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/guiv2/elements/Row.java index c3539f7c..9843418e 100644 --- a/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/guiv2/elements/Row.java +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/guiv2/elements/Row.java @@ -98,7 +98,7 @@ public class Row extends AnnotatedExportOnlyWidget implements Layouter { for (DomElement child : buildContext.getChildren()) { if (!(child.getWidget() instanceof Flexible)) { Size requiredSize = child.getLayouter().layout(child, new ConstraintBox( - 0, Integer.MAX_VALUE, + 0, Double.POSITIVE_INFINITY, crossAxisAlignment == CrossAxisAlignment.STRETCH ? constraintBox.getMaxHeight() : 0, constraintBox.getMaxHeight() )); saved.put(child, requiredSize); @@ -112,13 +112,13 @@ public class Row extends AnnotatedExportOnlyWidget implements Layouter { int sumFlex = 0; for (DomElement child : buildContext.getChildren()) { if (child.getWidget() instanceof Flexible) { - sumFlex += Math.min(1, ((Flexible) child.getWidget()).flex.getValue()); + sumFlex += Math.max(1, ((Flexible) child.getWidget()).flex.getValue()); flexFound =true; } } - if (flexFound && effwidth == Integer.MAX_VALUE) throw new IllegalStateException("Max width can not be infinite with flex elements"); - else if (effwidth == Integer.MAX_VALUE) effwidth = width; + if (flexFound && effwidth == Double.POSITIVE_INFINITY) throw new IllegalStateException("Max width can not be infinite with flex elements"); + else if (effwidth == Double.POSITIVE_INFINITY) effwidth = width; if (flexFound) { double remainingWidth = effwidth - width; @@ -138,7 +138,7 @@ public class Row extends AnnotatedExportOnlyWidget implements Layouter { } - height = constraintBox.getMaxHeight() == Integer.MAX_VALUE ? height : constraintBox.getMaxHeight(); + height = constraintBox.getMaxHeight() == Double.POSITIVE_INFINITY ? height : constraintBox.getMaxHeight(); @@ -202,8 +202,8 @@ public class Row extends AnnotatedExportOnlyWidget implements Layouter { int sumFlex = 0; for (DomElement child : buildContext.getChildren()) { if (!(child.getWidget() instanceof Flexible)) { - widthTaken += child.getLayouter().getMaxIntrinsicWidth(buildContext, Double.POSITIVE_INFINITY); - maxHeight = Double.max(maxHeight, child.getLayouter().getMaxIntrinsicHeight(buildContext, 0)); + widthTaken += child.getLayouter().getMaxIntrinsicWidth(child, 0); + maxHeight = Double.max(maxHeight, child.getLayouter().getMaxIntrinsicHeight(child, 0)); } else { sumFlex += ((Flexible) child.getWidget()).flex.getValue(); } @@ -211,9 +211,10 @@ public class Row extends AnnotatedExportOnlyWidget implements Layouter { double leftOver = width - widthTaken; if (sumFlex > 0) { double per = leftOver / sumFlex; + if (width == 0) per = 0; for (DomElement child : buildContext.getChildren()) { if (child.getWidget() instanceof Flexible) { - maxHeight = Double.max(maxHeight, child.getLayouter().getMaxIntrinsicHeight(buildContext, per * ((Flexible) child.getWidget()).flex.getValue())); + maxHeight = Double.max(maxHeight, child.getLayouter().getMaxIntrinsicHeight(child, per * ((Flexible) child.getWidget()).flex.getValue())); } } } @@ -228,10 +229,10 @@ public class Row extends AnnotatedExportOnlyWidget implements Layouter { for (DomElement child : buildContext.getChildren()) { if (child.getWidget() instanceof Flexible) { flex += ((Flexible) child.getWidget()).flex.getValue(); - maxPer = Double.max(maxPer, child.getLayouter().getMaxIntrinsicWidth(buildContext, height) / + maxPer = Double.max(maxPer, child.getLayouter().getMaxIntrinsicWidth(child, height) / ((Flexible) child.getWidget()).flex.getValue()); } else { - width += child.getLayouter().getMaxIntrinsicWidth(buildContext, height); + width += child.getLayouter().getMaxIntrinsicWidth(child, height); } } return width + maxPer * flex; diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/guiv2/elements/SizedBox.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/guiv2/elements/SizedBox.java deleted file mode 100644 index e06cd20e..00000000 --- a/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/guiv2/elements/SizedBox.java +++ /dev/null @@ -1,87 +0,0 @@ -/* - * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod - * Copyright (C) 2022 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 <https://www.gnu.org/licenses/>. - */ - -package kr.syeyoung.dungeonsguide.mod.guiv2.elements; - -import kr.syeyoung.dungeonsguide.mod.guiv2.*; -import kr.syeyoung.dungeonsguide.mod.guiv2.layouter.Layouter; -import kr.syeyoung.dungeonsguide.mod.guiv2.primitive.ConstraintBox; -import kr.syeyoung.dungeonsguide.mod.guiv2.primitive.Rect; -import kr.syeyoung.dungeonsguide.mod.guiv2.primitive.Size; -import kr.syeyoung.dungeonsguide.mod.guiv2.renderer.SingleChildRenderer; -import kr.syeyoung.dungeonsguide.mod.guiv2.xml.AnnotatedExportOnlyWidget; -import kr.syeyoung.dungeonsguide.mod.guiv2.xml.DomElementRegistry; -import kr.syeyoung.dungeonsguide.mod.guiv2.xml.annotations.Export; - -import java.awt.*; -import java.util.Collections; -import java.util.List; - -public class SizedBox extends AnnotatedExportOnlyWidget implements Layouter { - - @Export(attributeName = "width") - public final BindableAttribute<Double> width = new BindableAttribute<>(Double.class, Double.POSITIVE_INFINITY); - @Export(attributeName = "height") - public final BindableAttribute<Double> height = new BindableAttribute<>(Double.class, Double.POSITIVE_INFINITY); - @Export(attributeName = "$") - public final BindableAttribute<Widget> child = new BindableAttribute<>(Widget.class); - - - @Override - public List<Widget> build(DomElement buildContext) { - return child.getValue() == null ? Collections.EMPTY_LIST : Collections.singletonList(child.getValue()); - } - - public SizedBox() { - width.addOnUpdate((a,b) -> getDomElement().requestRelayout()); - height.addOnUpdate((a,b) -> getDomElement().requestRelayout()); - } - - @Override - public Size layout(DomElement buildContext, ConstraintBox constraintBox) { - - double width = Layouter.clamp(this.width.getValue(), constraintBox.getMinWidth(), constraintBox.getMaxWidth()); - double height = Layouter.clamp(this.height.getValue(), constraintBox.getMinHeight(), constraintBox.getMaxHeight()); - - if (getDomElement().getChildren().isEmpty()) { - return new Size(width, height); - } - - DomElement child = getDomElement().getChildren().get(0); - Size dim = child.getLayouter().layout(child, new ConstraintBox( - width, width, height, height - )); // force size heh. - child.setRelativeBound(new Rect(0,0,dim.getWidth(),dim.getHeight())); - return dim; - } - - @Override - public boolean canCutRequest() { - return true; - } - - @Override - public double getMaxIntrinsicHeight(DomElement buildContext, double width) { - return this.height.getValue(); - } - - @Override - public double getMaxIntrinsicWidth(DomElement buildContext, double height) { - return this.width.getValue(); - } -} diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/guiv2/elements/Stack.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/guiv2/elements/Stack.java index e9f04d13..69060878 100644 --- a/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/guiv2/elements/Stack.java +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/guiv2/elements/Stack.java @@ -44,6 +44,7 @@ public class Stack extends AnnotatedExportOnlyWidget implements Renderer { for (int i = buildContext.getChildren().size() - 1; i >= 0; i --) { DomElement value = buildContext.getChildren().get(i); Rect original = value.getRelativeBound(); + if (original == null) return; GlStateManager.pushMatrix(); GlStateManager.translate(original.getX(), original.getY(), 0); diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/guiv2/elements/Text.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/guiv2/elements/Text.java index 3c5b1a2d..ce12d105 100644 --- a/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/guiv2/elements/Text.java +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/guiv2/elements/Text.java @@ -35,6 +35,7 @@ import net.minecraft.client.renderer.GlStateManager; import java.util.ArrayList; import java.util.Collections; import java.util.List; +import java.util.concurrent.CopyOnWriteArrayList; public class Text extends AnnotatedExportOnlyWidget implements Layouter, Renderer { @Export(attributeName = "text") @@ -50,7 +51,7 @@ public class Text extends AnnotatedExportOnlyWidget implements Layouter, Rendere final int width; final String text; } - public List<WrappedTextData> wrappedTexts = new ArrayList(); + public List<WrappedTextData> wrappedTexts = new CopyOnWriteArrayList<>(); @Export(attributeName = "font") public final BindableAttribute<FontRenderer> fontRenderer =new BindableAttribute<>(FontRenderer.class, Minecraft.getMinecraft().fontRendererObj); @@ -108,7 +109,7 @@ public class Text extends AnnotatedExportOnlyWidget implements Layouter, Rendere @Override public Size layout(DomElement buildContext, ConstraintBox constraintBox) { - wrappedTexts.clear(); + List<WrappedTextData> wrappedTexts = new ArrayList<>(); FontRenderer fr = fontRenderer.getValue(); String text = this.text.getValue(); @@ -205,7 +206,7 @@ public class Text extends AnnotatedExportOnlyWidget implements Layouter, Rendere wrappedTexts.add(new WrappedTextData(currentWidth, currentLine.toString())); } - + this.wrappedTexts = wrappedTexts; return new Size(hadToWrap ? constraintBox.getMaxWidth() : Layouter.clamp(maxWidth2, constraintBox.getMinWidth(), constraintBox.getMaxWidth()), @@ -221,6 +222,8 @@ public class Text extends AnnotatedExportOnlyWidget implements Layouter, Rendere return max; } + // TODO: incorporate line breaking into + // TODO: maybe turn into rich text? @Override public double getMaxIntrinsicHeight(DomElement buildContext, double width) { return this.text.getValue().split("\n").length * (fr.FONT_HEIGHT * lineSpacing.getValue()); 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/guiv2/elements/image/ImageTexture.java index df3b4043..0e794cc1 100644 --- a/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/features/impl/discord/inviteViewer/ImageTexture.java +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/guiv2/elements/image/ImageTexture.java @@ -1,6 +1,6 @@ /* * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod - * Copyright (C) 2021 cyoung06 + * 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 @@ -16,13 +16,11 @@ * along with this program. If not, see <https://www.gnu.org/licenses/>. */ -package kr.syeyoung.dungeonsguide.mod.features.impl.discord.inviteViewer; +package kr.syeyoung.dungeonsguide.mod.guiv2.elements.image; 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; @@ -95,8 +93,11 @@ public class ImageTexture { IIOMetadataNode graphicsControlExtensionNode = getNode(root, "GraphicControlExtension"); - delayTime = Integer.parseInt(graphicsControlExtensionNode.getAttribute("delayTime")); - + try { + delayTime = Integer.parseInt(graphicsControlExtensionNode.getAttribute("delayTime")); + } catch (Exception e) { + delayTime = 1000; + } image = new BufferedImage(width, height * frames, dummyFrame.getType()); Graphics2D graphics2D = image.createGraphics(); diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/guiv2/elements/image/URLImage.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/guiv2/elements/image/URLImage.java index 05996853..13bc2bae 100644 --- a/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/guiv2/elements/image/URLImage.java +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/guiv2/elements/image/URLImage.java @@ -18,35 +18,19 @@ package kr.syeyoung.dungeonsguide.mod.guiv2.elements.image; -import kr.syeyoung.dungeonsguide.mod.DungeonsGuide; -import kr.syeyoung.dungeonsguide.mod.features.impl.discord.inviteViewer.ImageTexture; 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.Flexible; import kr.syeyoung.dungeonsguide.mod.guiv2.layouter.Layouter; import kr.syeyoung.dungeonsguide.mod.guiv2.primitive.ConstraintBox; -import kr.syeyoung.dungeonsguide.mod.guiv2.primitive.Rect; import kr.syeyoung.dungeonsguide.mod.guiv2.primitive.Size; import kr.syeyoung.dungeonsguide.mod.guiv2.renderer.Renderer; import kr.syeyoung.dungeonsguide.mod.guiv2.renderer.RenderingContext; import kr.syeyoung.dungeonsguide.mod.guiv2.xml.AnnotatedExportOnlyWidget; import kr.syeyoung.dungeonsguide.mod.guiv2.xml.annotations.Export; -import net.minecraft.client.Minecraft; -import net.minecraft.util.ResourceLocation; -import org.apache.logging.log4j.Level; -import org.apache.logging.log4j.LogManager; -import org.apache.logging.log4j.Logger; import java.util.Collections; -import java.util.HashMap; import java.util.List; -import java.util.Map; -import java.util.concurrent.CompletableFuture; -import java.util.concurrent.ExecutorService; -import java.util.concurrent.Executors; -import java.util.concurrent.Future; -import java.util.function.Consumer; public class URLImage extends AnnotatedExportOnlyWidget implements Renderer, Layouter { @Export(attributeName="url") diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/guiv2/renderer/OnlyChildrenRenderer.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/guiv2/renderer/OnlyChildrenRenderer.java index 42d7e35d..057eeafa 100644 --- a/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/guiv2/renderer/OnlyChildrenRenderer.java +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/guiv2/renderer/OnlyChildrenRenderer.java @@ -28,6 +28,7 @@ public class OnlyChildrenRenderer implements Renderer { public void doRender(int absMouseX, int absMouseY, double relMouseX, double relMouseY, float partialTicks, RenderingContext renderingContext, DomElement buildContext) { for (DomElement value : buildContext.getChildren()) { Rect original = value.getRelativeBound(); + if (original == null) continue; GlStateManager.pushMatrix(); GlStateManager.translate(original.getX(), original.getY(), 0); diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/guiv2/renderer/Renderer.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/guiv2/renderer/Renderer.java index 6f655916..2c715626 100644 --- a/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/guiv2/renderer/Renderer.java +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/guiv2/renderer/Renderer.java @@ -30,5 +30,7 @@ public interface Renderer { * @param pos * @return */ - default Position transformPoint(DomElement element, Position pos) {return new Position(pos.getX() - element.getRelativeBound().getX(), pos.getY() - element.getRelativeBound().getY());} + default Position transformPoint(DomElement element, Position pos) { + if (element.getRelativeBound() == null) return pos; + return new Position(pos.getX() - element.getRelativeBound().getX(), pos.getY() - element.getRelativeBound().getY());} } diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/guiv2/renderer/RenderingContext.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/guiv2/renderer/RenderingContext.java index 7073e7be..efa46046 100644 --- a/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/guiv2/renderer/RenderingContext.java +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/guiv2/renderer/RenderingContext.java @@ -90,7 +90,10 @@ public class RenderingContext { public Stack<Rectangle> clips = new Stack<>(); public void pushClip(Rect absBounds, Size size, double x, double y, double width, double height) { - if (width < 0 || height < 0) throw new IllegalArgumentException("Clip width height less than 0"); + if (width < 0 || height < 0) { + width = 0; + height = 0; + } Rectangle previousClip; if (clips.size() == 0) diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/guiv2/renderer/SingleChildRenderer.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/guiv2/renderer/SingleChildRenderer.java index 48fbde81..11067f01 100644 --- a/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/guiv2/renderer/SingleChildRenderer.java +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/guiv2/renderer/SingleChildRenderer.java @@ -31,6 +31,7 @@ public class SingleChildRenderer implements Renderer { DomElement value = buildContext.getChildren().get(0); Rect original = value.getRelativeBound(); + if (original == null) return; GlStateManager.translate(original.getX(), original.getY(), 0); double absXScale = buildContext.getAbsBounds().getWidth() / buildContext.getSize().getWidth(); diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/guiv2/xml/DomElementRegistry.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/guiv2/xml/DomElementRegistry.java index 6d446f32..1ac6c747 100644 --- a/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/guiv2/xml/DomElementRegistry.java +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/guiv2/xml/DomElementRegistry.java @@ -46,7 +46,6 @@ public class DomElementRegistry { static { register("stack", new ExportedWidgetConverter(Stack::new)); - register("size", new ExportedWidgetConverter(SizedBox::new)); register("scaler", new ExportedWidgetConverter(Scaler::new)); register("row", new ExportedWidgetConverter(Row::new)); register("padding", new ExportedWidgetConverter(Padding::new)); @@ -60,6 +59,7 @@ public class DomElementRegistry { register("slot", new ExportedWidgetConverter(Slot::new)); register("clip", new ExportedWidgetConverter(Clip::new)); register("measure", new ExportedWidgetConverter(Measure::new)); + register("ConstrainedBox", new ExportedWidgetConverter(ConstrainedBox::new)); register("UnconstrainedBox", new ExportedWidgetConverter(UnconstrainedBox::new)); register("absXY", new ExportedWidgetConverter(AbsXY::new)); register("Placeholder", new ExportedWidgetConverter(Placeholder::new)); @@ -73,12 +73,12 @@ public class DomElementRegistry { register("IntrinsicWidth", new ExportedWidgetConverter(IntrinsicWidth::new)); register("IntrinsicHeight", new ExportedWidgetConverter(IntrinsicHeight::new)); register("TestView", new ExportedWidgetConverter(TestView::new)); - + register("ColorButton", new DelegatingWidgetConverter(new ResourceLocation("dungeonsguide:gui/elements/simpleButton.gui"))); register("SimpleHorizontalScrollBar", new DelegatingWidgetConverter(new ResourceLocation("dungeonsguide:gui/elements/simpleHorizontalScrollBar.gui"))); register("SimpleVerticalScrollBar", new DelegatingWidgetConverter(new ResourceLocation("dungeonsguide:gui/elements/simpleVerticalScrollBar.gui"))); register("SlowList", new DelegatingWidgetConverter(new ResourceLocation("dungeonsguide:gui/elements/slowlist.gui"))); - + register("size", new DelegatingWidgetConverter(new ResourceLocation("dungeonsguide:gui/elements/size.gui"))); register("ResourceImage", new DelegatingWidgetConverter(new ResourceLocation("dungeonsguide:gui/elements/ratioResourceImage.gui"))); register("UrlImage", new ExportedWidgetConverter(URLImage::new)); } diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/overlay/OverlayManager.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/overlay/OverlayManager.java index 8e38e2a0..4ce5f3aa 100644 --- a/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/overlay/OverlayManager.java +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/overlay/OverlayManager.java @@ -32,6 +32,7 @@ import net.minecraft.client.gui.ScaledResolution; import net.minecraft.client.renderer.GlStateManager; 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 org.lwjgl.input.Keyboard; import org.lwjgl.input.Mouse; @@ -90,11 +91,11 @@ public class OverlayManager { @SubscribeEvent public void renderGui(GuiScreenEvent.DrawScreenEvent.Post postRender) { -// if (postRender.gui instanceof GuiChat) -// view.getContext().CONTEXT.put(OVERLAY_TYPE_KEY, OverlayType.OVER_CHAT); -// else -// view.getContext().CONTEXT.put(OVERLAY_TYPE_KEY, OverlayType.OVER_ANY); -// drawScreen(postRender.renderPartialTicks); + if (postRender.gui instanceof GuiChat) + view.getContext().CONTEXT.put(OVERLAY_TYPE_KEY, OverlayType.OVER_CHAT); + else + view.getContext().CONTEXT.put(OVERLAY_TYPE_KEY, OverlayType.OVER_ANY); + drawScreen(postRender.renderPartialTicks); } @@ -104,6 +105,7 @@ public class OverlayManager { ScaledResolution scaledResolution = new ScaledResolution(Minecraft.getMinecraft()); GlStateManager.pushMatrix(); + GlStateManager.translate(0,0,50); GlStateManager.disableDepth(); GlStateManager.enableBlend(); GlStateManager.enableAlpha(); @@ -115,6 +117,7 @@ public class OverlayManager { GlStateManager.alphaFunc(GL_GREATER, 0.1f); GlStateManager.popMatrix(); GlStateManager.enableDepth(); + GlStateManager.enableTexture2D(); GL11.glDisable(GL11.GL_SCISSOR_TEST); } @@ -195,7 +198,7 @@ public class OverlayManager { private int lastX, lastY; - @SubscribeEvent + @SubscribeEvent(priority = EventPriority.HIGHEST) public void handleMouseInput(GuiScreenEvent.MouseInputEvent.Pre mouseInputEvent) throws IOException { try { int i = Mouse.getEventX(); @@ -247,7 +250,7 @@ public class OverlayManager { } } - @SubscribeEvent + @SubscribeEvent(priority = EventPriority.HIGHEST) public void handleKeyboardInput(GuiScreenEvent.KeyboardInputEvent.Pre keyboardInputEvent) throws IOException { if (Keyboard.getEventKeyState()) { if (Keyboard.isRepeatEvent()) diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/overlay/OverlayManagerRootWidget.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/overlay/OverlayManagerRootWidget.java index 9d27f0b9..83a8f739 100644 --- a/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/overlay/OverlayManagerRootWidget.java +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/overlay/OverlayManagerRootWidget.java @@ -38,6 +38,8 @@ public class OverlayManagerRootWidget extends Widget implements Layouter { } public void addOverlay(OverlayWidget overlayWidget) { + if (getDomElement().getChildren().contains(overlayWidget.getDomElement())) return; + DomElement domElement = overlayWidget.createDomElement(getDomElement()); getDomElement().addElement(domElement); diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/overlay/OverlayWidget.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/overlay/OverlayWidget.java index 60d36f98..3ca0e3ba 100644 --- a/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/overlay/OverlayWidget.java +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/overlay/OverlayWidget.java @@ -55,6 +55,7 @@ public class OverlayWidget extends Widget implements Renderer, Layouter { DomElement value = buildContext.getChildren().get(0); Rect original = value.getRelativeBound(); + if (original == null) return; GlStateManager.translate(original.getX(), original.getY(), 0); double absXScale = buildContext.getAbsBounds().getWidth() / buildContext.getSize().getWidth(); diff --git a/mod/src/main/resources/assets/dungeonsguide/gui/elements/size.gui b/mod/src/main/resources/assets/dungeonsguide/gui/elements/size.gui new file mode 100644 index 00000000..6f326058 --- /dev/null +++ b/mod/src/main/resources/assets/dungeonsguide/gui/elements/size.gui @@ -0,0 +1,23 @@ +<!-- + ~ 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 <https://www.gnu.org/licenses/>. + --> + +<wrapper width="+Infinity" height="+Infinity"> + <ConstrainedBox bind:minWidth="width" bind:maxWidth="width" bind:minHeight="height" bind:maxHeight="height"> + <slot bind:child="$"/> + </ConstrainedBox> +</wrapper>
\ No newline at end of file diff --git a/mod/src/main/resources/assets/dungeonsguide/gui/features/discordOnline/discordOnline.gui b/mod/src/main/resources/assets/dungeonsguide/gui/features/discordOnline/discordOnline.gui new file mode 100644 index 00000000..1b2bda6b --- /dev/null +++ b/mod/src/main/resources/assets/dungeonsguide/gui/features/discordOnline/discordOnline.gui @@ -0,0 +1,52 @@ +<!-- + ~ 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 <https://www.gnu.org/licenses/>. + --> + + <padding left="5" right="5" top="2.5" bottom="2.5"> + <border> + <line slot="left" dir="VERTICAL" thickness="1.0" color="#FF23272A"/> + <line slot="top" dir="HORIZONTAL" thickness="1.0" color="#FF23272A"/> + <line slot="bottom" dir="HORIZONTAL" thickness="1.0" color="#FF23272A"/> + <line slot="right" dir="VERTICAL" thickness="1.0" color="#FF23272A"/> + <bgcolor slot="content" backgroundColor="#FF2C2F33"> + <padding left="3" right="3" top="3" bottom="3"> + <IntrinsicHeight> + <IntrinsicWidth> + <row> + <UrlImage bind:url="avatarUrl"/> + <size width="5"></size> + <flexible> + <col crossAlign="START"> + <row crossAlign="END"> + <scaler scale="3.0"> + <Text bind:text="username" color="#FFFFFFFF"/> + </scaler> + <Text text="#" color="#FFAAAAAA"/> + <Text bind:text="discriminator" color="#FFAAAAAA"/> + </row> + <size height="5"/> + <Text text="started playing with Dungeons Guide!" color="#FFFFFFFF"/> + <size height="5"/> + </col> + </flexible> + </row> + </IntrinsicWidth> + </IntrinsicHeight> + </padding> + </bgcolor> + </border> + </padding>
\ No newline at end of file diff --git a/mod/src/main/resources/assets/dungeonsguide/gui/features/discordOnline/discordOnlineList.gui b/mod/src/main/resources/assets/dungeonsguide/gui/features/discordOnline/discordOnlineList.gui new file mode 100644 index 00000000..3ab3e7f8 --- /dev/null +++ b/mod/src/main/resources/assets/dungeonsguide/gui/features/discordOnline/discordOnlineList.gui @@ -0,0 +1,22 @@ +<!-- + ~ 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 <https://www.gnu.org/licenses/>. + --> + +<align hAlign="END" vAlign="START"> + <col mainAlign="START" crossAlign="END" bind:api="listApi"> + </col> +</align> diff --git a/mod/src/main/resources/assets/dungeonsguide/gui/features/discordParty/invite.gui b/mod/src/main/resources/assets/dungeonsguide/gui/features/discordParty/invite.gui new file mode 100644 index 00000000..f26c525a --- /dev/null +++ b/mod/src/main/resources/assets/dungeonsguide/gui/features/discordParty/invite.gui @@ -0,0 +1,85 @@ +<!-- + ~ 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 <https://www.gnu.org/licenses/>. + --> + + <padding left="5" right="5" top="2.5" bottom="2.5"> + <border> + <line slot="left" dir="VERTICAL" thickness="1.0" color="#FF23272A"/> + <line slot="top" dir="HORIZONTAL" thickness="1.0" color="#FF23272A"/> + <line slot="bottom" dir="HORIZONTAL" thickness="1.0" color="#FF23272A"/> + <line slot="right" dir="VERTICAL" thickness="1.0" color="#FF23272A"/> + <bgcolor slot="content" backgroundColor="#FF2C2F33"> + <padding left="3" right="3" top="3" bottom="3"> + <IntrinsicHeight> + <IntrinsicWidth> + <row> + <UrlImage bind:url="avatarUrl"/> + <size width="5"></size> + <flexible> + <col crossAlign="START"> + <row crossAlign="END"> + <scaler scale="3.0"> + <Text bind:text="username" color="#FFFFFFFF"/> + </scaler> + <Text text="#" color="#FFAAAAAA"/> + <Text bind:text="discriminator" color="#FFAAAAAA"/> + </row> + <size height="5"/> + <Text text="§ewants you to join their party!" color="#FFFFFFFF"/> + <size height="5"/> + <size height="30"> + <scaler scale="2.0"> + <row crossAlign="START"> + <flexible fit="TIGHT" flex="1"> + <size/> + </flexible> + <flexible fit="TIGHT" flex="3"> + <ColorButton on:click="accept" + backgroundColor="#FF7289DA" textColor="#FFFFFFFF" + hoveredBackgroundColor="#FF859DF0" hoveredTextColor="#FFFFFFFF" + disabledBackgroundColor="0" disabledTextColor="0" + pressedBackgroundColor="#FF9BB0FF" pressedTextColor="#FFFFFFFF" + text="ACCEPT" + /> + </flexible> + <flexible fit="TIGHT" flex="1"> + <size/> + </flexible> + <flexible fit="TIGHT" flex="3"> + <ColorButton on:click="deny" + backgroundColor="#FF99AAB5" textColor="#FFFFFFFF" + hoveredBackgroundColor="#FFAEC0CB" hoveredTextColor="#FFFFFFFF" + disabledBackgroundColor="0" disabledTextColor="0" + pressedBackgroundColor="#FFCADDE8" pressedTextColor="#FFFFFFFF" + text="DENY" + /> + </flexible> + <flexible fit="TIGHT" flex="1"> + <size/> + </flexible> + </row> + </scaler> + </size> + </col> + </flexible> + </row> + </IntrinsicWidth> + </IntrinsicHeight> + </padding> + </bgcolor> + </border> + </padding>
\ No newline at end of file diff --git a/mod/src/main/resources/assets/dungeonsguide/gui/features/discordParty/joinRequest.gui b/mod/src/main/resources/assets/dungeonsguide/gui/features/discordParty/joinRequest.gui new file mode 100644 index 00000000..7737d947 --- /dev/null +++ b/mod/src/main/resources/assets/dungeonsguide/gui/features/discordParty/joinRequest.gui @@ -0,0 +1,97 @@ +<!-- + ~ 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 <https://www.gnu.org/licenses/>. + --> + + <padding left="5" right="5" top="2.5" bottom="2.5"> + <border> + <line slot="left" dir="VERTICAL" thickness="1.0" color="#FF23272A"/> + <line slot="top" dir="HORIZONTAL" thickness="1.0" color="#FF23272A"/> + <line slot="bottom" dir="HORIZONTAL" thickness="1.0" color="#FF23272A"/> + <line slot="right" dir="VERTICAL" thickness="1.0" color="#FF23272A"/> + <bgcolor slot="content" backgroundColor="#FF2C2F33"> + <padding left="3" right="3" top="3" bottom="3"> + <IntrinsicHeight> + <IntrinsicWidth> + <row> + <UrlImage bind:url="avatarUrl"/> + <size width="5"></size> + <flexible> + <col crossAlign="START"> + <row crossAlign="END"> + <scaler scale="3.0"> + <Text bind:text="username" color="#FFFFFFFF"/> + </scaler> + <Text text="#" color="#FFAAAAAA"/> + <Text bind:text="discriminator" color="#FFAAAAAA"/> + </row> + <size height="5"/> + <Text text="wants to join your party!" color="#FFFFFFFF"/> + <size height="5"/> + <size height="30"> + <scaler scale="2.0"> + <row crossAlign="START"> + <flexible fit="TIGHT" flex="1"> + <size/> + </flexible> + <flexible fit="TIGHT" flex="3"> + <ColorButton on:click="accept" + backgroundColor="#FF7289DA" textColor="#FFFFFFFF" + hoveredBackgroundColor="#FF859DF0" hoveredTextColor="#FFFFFFFF" + disabledBackgroundColor="0" disabledTextColor="0" + pressedBackgroundColor="#FF9BB0FF" pressedTextColor="#FFFFFFFF" + text="ACCEPT" + /> + </flexible> + <flexible fit="TIGHT" flex="1"> + <size/> + </flexible> + <flexible fit="TIGHT" flex="3"> + <ColorButton on:click="deny" + backgroundColor="#FF99AAB5" textColor="#FFFFFFFF" + hoveredBackgroundColor="#FFAEC0CB" hoveredTextColor="#FFFFFFFF" + disabledBackgroundColor="0" disabledTextColor="0" + pressedBackgroundColor="#FFCADDE8" pressedTextColor="#FFFFFFFF" + text="DENY" + /> + </flexible> + <flexible fit="TIGHT" flex="1"> + <size/> + </flexible> + <flexible fit="TIGHT" flex="3"> + <ColorButton on:click="ignore" + backgroundColor="#FF99AAB5" textColor="#FFFFFFFF" + hoveredBackgroundColor="#FFAEC0CB" hoveredTextColor="#FFFFFFFF" + disabledBackgroundColor="0" disabledTextColor="0" + pressedBackgroundColor="#FFCADDE8" pressedTextColor="#FFFFFFFF" + text="Ignore" + /> + </flexible> + <flexible fit="TIGHT" flex="1"> + <size/> + </flexible> + </row> + </scaler> + </size> + </col> + </flexible> + </row> + </IntrinsicWidth> + </IntrinsicHeight> + </padding> + </bgcolor> + </border> + </padding>
\ No newline at end of file diff --git a/mod/src/main/resources/assets/dungeonsguide/gui/features/discordParty/partyInviteList.gui b/mod/src/main/resources/assets/dungeonsguide/gui/features/discordParty/partyInviteList.gui new file mode 100644 index 00000000..0d1d2590 --- /dev/null +++ b/mod/src/main/resources/assets/dungeonsguide/gui/features/discordParty/partyInviteList.gui @@ -0,0 +1,22 @@ +<!-- + ~ 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 <https://www.gnu.org/licenses/>. + --> + +<align hAlign="START" vAlign="START"> + <col mainAlign="START" crossAlign="START" bind:api="listApi"> + </col> +</align> |