diff options
author | syeyoung <cyong06@naver.com> | 2021-04-28 17:35:58 +0900 |
---|---|---|
committer | syeyoung <cyong06@naver.com> | 2021-04-28 17:35:58 +0900 |
commit | 3b4d4a96f7b246ee3d07f82a78c1e9cf5de91300 (patch) | |
tree | 211cec844864c98e37ef1d97bf74fc461230ab16 | |
parent | 31962f3cd061697fe7596102632f471ff01cb6c8 (diff) | |
download | Skyblock-Dungeons-Guide-3b4d4a96f7b246ee3d07f82a78c1e9cf5de91300.tar.gz Skyblock-Dungeons-Guide-3b4d4a96f7b246ee3d07f82a78c1e9cf5de91300.tar.bz2 Skyblock-Dungeons-Guide-3b4d4a96f7b246ee3d07f82a78c1e9cf5de91300.zip |
ok done
8 files changed, 208 insertions, 45 deletions
diff --git a/options.txt b/options.txt index 200b71ef..1b8c369a 100755 --- a/options.txt +++ b/options.txt @@ -24,7 +24,7 @@ chatLinks:true chatLinksPrompt:true chatOpacity:1.0 snooperEnabled:true -fullscreen:true +fullscreen:false enableVsync:false useVbo:true hideServerAddress:false @@ -116,7 +116,7 @@ key_Flip (Hold):0 key_Rotate (Hold):0 key_Flip (Toggle):0 key_Rotate (Toggle):0 -soundCategory_master:1.0 +soundCategory_master:0.0 soundCategory_music:0.0 soundCategory_record:1.0 soundCategory_weather:1.0 diff --git a/src/main/java/kr/syeyoung/dungeonsguide/commands/CommandDungeonsGuide.java b/src/main/java/kr/syeyoung/dungeonsguide/commands/CommandDungeonsGuide.java index 87ff13e2..c4e006bb 100644 --- a/src/main/java/kr/syeyoung/dungeonsguide/commands/CommandDungeonsGuide.java +++ b/src/main/java/kr/syeyoung/dungeonsguide/commands/CommandDungeonsGuide.java @@ -327,24 +327,18 @@ public class CommandDungeonsGuide extends CommandBase { sender.addChatMessage(new ChatComponentText("§eDungeons Guide §7:: §cAn error occured while writing rundata "+e.getMessage())); e.printStackTrace(); } - } else if (args[0].equals("fetch")) { - try { - sender.addChatMessage(new ChatComponentText("§eDungeons Guide §7:: §eProfile Viewer Test: ").appendSibling(new ChatComponentText("§7view").setChatStyle(new ChatStyle().setChatHoverEvent(new FeatureViewPlayerOnJoin.HoverEventRenderPlayer(args[1]))))); - } catch (Exception e) { - e.printStackTrace(); - } - } else if (args[0].equals("fetchbynick")) { + } else if (args[0].equals("pv")) { try { ApiFetchur.fetchUUIDAsync(args[1]) .thenAccept(a -> { - sender.addChatMessage(new ChatComponentText("§eDungeons Guide §7:: §eProfile Viewer Test: ").appendSibling(new ChatComponentText("§7view").setChatStyle(new ChatStyle().setChatHoverEvent(new FeatureViewPlayerOnJoin.HoverEventRenderPlayer(a.orElse(null)))))); + sender.addChatMessage(new ChatComponentText("§eDungeons Guide §7:: §e"+args[1]+"§f's Profile ").appendSibling(new ChatComponentText("§7view").setChatStyle(new ChatStyle().setChatHoverEvent(new FeatureViewPlayerOnJoin.HoverEventRenderPlayer(a.orElse(null)))))); }); - } catch (Exception e) { e.printStackTrace(); } } else if (args[0].equals("purge")) { ApiFetchur.purgeCache(); + sender.addChatMessage(new ChatComponentText("§eDungeons Guide §7:: §fSuccessfully purged API Cache!")); } else { sender.addChatMessage(new ChatComponentText("§eDungeons Guide §7:: §e/dg §7-§fOpens configuration gui")); sender.addChatMessage(new ChatComponentText("§eDungeons Guide §7:: §e/dg gui §7-§fOpens configuration gui")); @@ -357,6 +351,7 @@ public class CommandDungeonsGuide extends CommandBase { sender.addChatMessage(new ChatComponentText("§eDungeons Guide §7:: §e/dg info §7-§f View Current DG User info.")); sender.addChatMessage(new ChatComponentText("§eDungeons Guide §7:: §e/dg asktojoin or /dg atj §7-§f Toggle ask to join §cRequires Discord Rich Presence enabled. (/dg -> Advanced)")); sender.addChatMessage(new ChatComponentText("§eDungeons Guide §7:: §e/dg partymax [number] or /dg pm [number] §7-§f Sets partymax §7(maximum amount people in party, for discord rpc)")); + sender.addChatMessage(new ChatComponentText("§eDungeons Guide §7:: §e/dg pv [ign] §7-§f Profile Viewer")); } } diff --git a/src/main/java/kr/syeyoung/dungeonsguide/features/FeatureRegistry.java b/src/main/java/kr/syeyoung/dungeonsguide/features/FeatureRegistry.java index b62a6764..bf2779d9 100644 --- a/src/main/java/kr/syeyoung/dungeonsguide/features/FeatureRegistry.java +++ b/src/main/java/kr/syeyoung/dungeonsguide/features/FeatureRegistry.java @@ -11,6 +11,7 @@ import kr.syeyoung.dungeonsguide.features.impl.dungeon.*; import kr.syeyoung.dungeonsguide.features.impl.etc.*; import kr.syeyoung.dungeonsguide.features.impl.etc.ability.FeatureAbilityCooldown; import kr.syeyoung.dungeonsguide.features.impl.party.APIKey; +import kr.syeyoung.dungeonsguide.features.impl.party.FeatureGoodParties; import kr.syeyoung.dungeonsguide.features.impl.party.playerpreview.FeatureViewPlayerOnJoin; import kr.syeyoung.dungeonsguide.features.impl.secret.FeatureActions; import kr.syeyoung.dungeonsguide.features.impl.secret.FeatureFreezePathfind; @@ -86,6 +87,7 @@ public class FeatureRegistry { public static final APIKey PARTYKICKER_APIKEY = register(new APIKey()); public static final FeatureViewPlayerOnJoin PARTYKICKER_VIEWPLAYER = register(new FeatureViewPlayerOnJoin()); + public static final FeatureGoodParties PARTYKICKER_GOODPARTIES = register(new FeatureGoodParties()); public static final FeatureWarningOnPortal BOSSFIGHT_WARNING_ON_PORTAL = register(new FeatureWarningOnPortal()); public static final SimpleFeature BOSSFIGHT_CHESTPRICE = register(new FeatureChestPrice()); diff --git a/src/main/java/kr/syeyoung/dungeonsguide/features/impl/party/APIKey.java b/src/main/java/kr/syeyoung/dungeonsguide/features/impl/party/APIKey.java index ed708ec5..8516944e 100644 --- a/src/main/java/kr/syeyoung/dungeonsguide/features/impl/party/APIKey.java +++ b/src/main/java/kr/syeyoung/dungeonsguide/features/impl/party/APIKey.java @@ -1,9 +1,13 @@ package kr.syeyoung.dungeonsguide.features.impl.party; import kr.syeyoung.dungeonsguide.features.FeatureParameter; +import kr.syeyoung.dungeonsguide.features.FeatureRegistry; import kr.syeyoung.dungeonsguide.features.SimpleFeature; import kr.syeyoung.dungeonsguide.features.listener.ChatListener; import kr.syeyoung.dungeonsguide.features.listener.ChatListenerGlobal; +import kr.syeyoung.dungeonsguide.utils.TextUtils; +import net.minecraft.client.Minecraft; +import net.minecraft.util.ChatComponentText; import net.minecraftforge.client.event.ClientChatReceivedEvent; public class APIKey extends SimpleFeature implements ChatListenerGlobal { @@ -20,6 +24,13 @@ public class APIKey extends SimpleFeature implements ChatListenerGlobal { @Override public void onChat(ClientChatReceivedEvent clientChatReceivedEvent) { - // ay set apikey + if (clientChatReceivedEvent.type == 2) return; + String str = clientChatReceivedEvent.message.getFormattedText(); + if (str.startsWith("§aYour new API key is §r§b")) { + String apiKeys = TextUtils.stripColor(str.split(" ")[5]); + Minecraft.getMinecraft().thePlayer.addChatMessage(new ChatComponentText("§eDungeons Guide §7:: §fAutomatically Configured Hypixel API Key")); + this.<String>getParameter("apikey").setValue(apiKeys); + } + } } diff --git a/src/main/java/kr/syeyoung/dungeonsguide/features/impl/party/FeatureGoodParties.java b/src/main/java/kr/syeyoung/dungeonsguide/features/impl/party/FeatureGoodParties.java new file mode 100644 index 00000000..ae7b0b45 --- /dev/null +++ b/src/main/java/kr/syeyoung/dungeonsguide/features/impl/party/FeatureGoodParties.java @@ -0,0 +1,93 @@ +package kr.syeyoung.dungeonsguide.features.impl.party; + +import kr.syeyoung.dungeonsguide.features.FeatureRegistry; +import kr.syeyoung.dungeonsguide.features.SimpleFeature; +import kr.syeyoung.dungeonsguide.features.impl.party.api.ApiFetchur; +import kr.syeyoung.dungeonsguide.features.impl.party.api.DungeonType; +import kr.syeyoung.dungeonsguide.features.impl.party.api.PlayerProfile; +import kr.syeyoung.dungeonsguide.features.listener.GuiPostRenderListener; +import kr.syeyoung.dungeonsguide.features.listener.TickListener; +import kr.syeyoung.dungeonsguide.utils.TextUtils; +import kr.syeyoung.dungeonsguide.utils.XPUtils; +import net.minecraft.client.Minecraft; +import net.minecraft.client.gui.FontRenderer; +import net.minecraft.client.gui.Gui; +import net.minecraft.client.gui.inventory.GuiChest; +import net.minecraft.client.renderer.GlStateManager; +import net.minecraft.init.Items; +import net.minecraft.inventory.Container; +import net.minecraft.inventory.ContainerChest; +import net.minecraft.inventory.Slot; +import net.minecraft.nbt.NBTTagCompound; +import net.minecraft.nbt.NBTTagList; +import net.minecraftforge.client.event.GuiScreenEvent; + +import java.util.Optional; +import java.util.concurrent.CompletableFuture; +import java.util.concurrent.ExecutionException; + +public class FeatureGoodParties extends SimpleFeature implements GuiPostRenderListener { + public FeatureGoodParties() { + super("Party Kicker", "Highlight parties in party viewer", "Highlight parties you can't join with red", "partykicker.goodparty",true); + } + + @Override + public void onGuiPostRender(GuiScreenEvent.DrawScreenEvent.Post rendered) { + if (!isEnabled()) return; + if (!(Minecraft.getMinecraft().currentScreen instanceof GuiChest)) return; + GuiChest chest = (GuiChest) Minecraft.getMinecraft().currentScreen; + ContainerChest cont = (ContainerChest) chest.inventorySlots; + String name = cont.getLowerChestInventory().getName(); + if (!"Party Finder".equals(name)) return; + + + int i = 222; + int j = i - 108; + int ySize = j + (((ContainerChest)(((GuiChest) Minecraft.getMinecraft().currentScreen).inventorySlots)).getLowerChestInventory().getSizeInventory() / 9) * 18; + int left = (rendered.gui.width - 176) / 2; + int top = (rendered.gui.height - ySize ) / 2; + GlStateManager.pushMatrix(); + GlStateManager.disableDepth(); + GlStateManager.disableLighting(); + GlStateManager.colorMask(true, true, true, false); + GlStateManager.translate(left, top, 0); + FontRenderer fr = Minecraft.getMinecraft().fontRendererObj; + try { + + for (int i1 = 0; i1 < Integer.min(54, cont.inventorySlots.size()); i1++) { + Slot s = cont.inventorySlots.get(i1); + if (s.getStack() == null) continue; + if (s.getStack().getItem() != Items.skull) continue; + NBTTagCompound nbt = s.getStack().getTagCompound(); + if (nbt == null || nbt.hasNoTags()) continue; + NBTTagCompound display = nbt.getCompoundTag("display"); + if (display.hasNoTags()) return; + NBTTagList lore = display.getTagList("Lore", 8); + int classLvReq = 0; + int cataLvReq = 0; + boolean Req = false; + for (int n = 0; n < lore.tagCount(); n++) { + String str = lore.getStringTagAt(n); + if (str.startsWith("§7Dungeon Level Required: §b")) cataLvReq = Integer.parseInt(str.substring(28)); + if (str.startsWith("§7Class Level Required: §b")) classLvReq = Integer.parseInt(str.substring(26)); + if (str.startsWith("§cRequires")) Req = true; + } + System.out.println(classLvReq + " / "+cataLvReq); + + if (Req) { + int x = s.xDisplayPosition; + int y = s.yDisplayPosition; + Gui.drawRect(x, y, x + 16, y + 16, 0x77AA0000); + } + + + } + } catch (Throwable e) { + e.printStackTrace(); + } + GlStateManager.colorMask(true, true, true, true); + GlStateManager.popMatrix(); + GlStateManager.enableBlend(); + GlStateManager.enableLighting(); + } +} diff --git a/src/main/java/kr/syeyoung/dungeonsguide/features/impl/party/api/ApiFetchur.java b/src/main/java/kr/syeyoung/dungeonsguide/features/impl/party/api/ApiFetchur.java index 0a80d93c..2c22b94a 100644 --- a/src/main/java/kr/syeyoung/dungeonsguide/features/impl/party/api/ApiFetchur.java +++ b/src/main/java/kr/syeyoung/dungeonsguide/features/impl/party/api/ApiFetchur.java @@ -29,6 +29,7 @@ public class ApiFetchur { private static final ExecutorService ex = Executors.newFixedThreadPool(4); + private static final Set<String> invalidKeys = new HashSet<>(); public static void purgeCache() { playerProfileCache.clear(); nicknameToUID.clear(); @@ -39,6 +40,7 @@ public class ApiFetchur { completableFutureMap2.clear(); completableFutureMap3.clear(); completableFutureMap4.clear(); + invalidKeys.clear(); } public static JsonObject getJson(String url) throws IOException { @@ -106,6 +108,11 @@ public class ApiFetchur { playerProfileCache.remove(uid); } if (completableFutureMap.containsKey(uid)) return completableFutureMap.get(uid); + if (invalidKeys.contains(apiKey)) { + CompletableFuture cf = new CompletableFuture(); + cf.completeExceptionally(new IOException("403 for url")); + return cf; + } CompletableFuture<Optional<PlayerProfile>> completableFuture = new CompletableFuture<>(); ex.submit(() -> { @@ -116,10 +123,16 @@ public class ApiFetchur { completableFutureMap.remove(uid); return; } catch (IOException e) { + if (e.getMessage().contains("403 for URL")) { + completableFuture.completeExceptionally(e); + completableFutureMap.remove(uid); + invalidKeys.add(apiKey); + } else { + completableFuture.complete(Optional.empty()); + completableFutureMap.remove(uid); + } e.printStackTrace(); } - completableFuture.complete(Optional.empty()); - completableFutureMap.remove(uid); }); completableFutureMap.put(uid, completableFuture); return completableFuture; diff --git a/src/main/java/kr/syeyoung/dungeonsguide/features/impl/party/playerpreview/FeatureViewPlayerOnJoin.java b/src/main/java/kr/syeyoung/dungeonsguide/features/impl/party/playerpreview/FeatureViewPlayerOnJoin.java index 0e96d4c4..b2596f63 100644 --- a/src/main/java/kr/syeyoung/dungeonsguide/features/impl/party/playerpreview/FeatureViewPlayerOnJoin.java +++ b/src/main/java/kr/syeyoung/dungeonsguide/features/impl/party/playerpreview/FeatureViewPlayerOnJoin.java @@ -20,6 +20,7 @@ import kr.syeyoung.dungeonsguide.features.listener.GuiPostRenderListener; import kr.syeyoung.dungeonsguide.features.text.PanelTextParameterConfig; import kr.syeyoung.dungeonsguide.features.text.TextHUDFeature; import kr.syeyoung.dungeonsguide.gui.MPanel; +import kr.syeyoung.dungeonsguide.party.PartyManager; import kr.syeyoung.dungeonsguide.utils.TextUtils; import kr.syeyoung.dungeonsguide.utils.XPUtils; import lombok.Getter; @@ -71,40 +72,41 @@ public class FeatureViewPlayerOnJoin extends SimpleFeature implements GuiPostRen @Override public void onGuiPostRender(GuiScreenEvent.DrawScreenEvent.Post rendered) { if (!(Minecraft.getMinecraft().currentScreen instanceof GuiChat)) { - popupRect = null; - profileFuture = null; - gfFuture = null; - skinFuture= null; - fakePlayer= null; + cancelRender(); return; } ScaledResolution scaledResolution = new ScaledResolution(Minecraft.getMinecraft()); - int width = scaledResolution.getScaledWidth(); - int height = scaledResolution.getScaledHeight(); - int mouseX = Mouse.getX() * width / Minecraft.getMinecraft().displayWidth; - int mouseY = height - Mouse.getY() * height / Minecraft.getMinecraft().displayHeight - 1; - IChatComponent ichatcomponent = getHoveredComponent(scaledResolution); String uid = null; if (ichatcomponent != null && ichatcomponent.getChatStyle().getChatHoverEvent() instanceof HoverEventRenderPlayer) { uid = ((HoverEventRenderPlayer) ichatcomponent.getChatStyle().getChatHoverEvent()).getUuid(); } + reqRender(uid); + } + + public void cancelRender() { + popupRect = null; + profileFuture = null; + lastuid = null; + gfFuture = null; + skinFuture= null; + fakePlayer= null; + } + + public void reqRender(String uid) { + ScaledResolution scaledResolution = new ScaledResolution(Minecraft.getMinecraft()); + int width = scaledResolution.getScaledWidth(); + int height = scaledResolution.getScaledHeight(); + int mouseX = Mouse.getX() * width / Minecraft.getMinecraft().displayWidth; + int mouseY = height - Mouse.getY() * height / Minecraft.getMinecraft().displayHeight - 1; + if (!((popupRect != null && popupRect.contains(mouseX, mouseY)) || uid != null && uid.equals(lastuid))) { - popupRect = null; - profileFuture = null; - lastuid = null; - gfFuture = null; - skinFuture= null; - fakePlayer= null; + cancelRender(); } if (uid != null && !uid.equals(lastuid) && (popupRect==null || !popupRect.contains(mouseX, mouseY))) { - popupRect = null; - profileFuture = null; - gfFuture = null; - skinFuture= null; - fakePlayer= null; + cancelRender(); lastuid = uid; } if (lastuid == null) return; @@ -124,24 +126,42 @@ public class FeatureViewPlayerOnJoin extends SimpleFeature implements GuiPostRen if (gfFuture == null) { gfFuture = ApiFetchur.getSkinGameProfileByUUIDAsync(lastuid); } + boolean plsSetAPIKEY = false; if (skinFuture == null && gfFuture.isDone()) { - skinFuture = SkinFetchur.getSkinSet(gfFuture.get().orElse(null)); + try { + skinFuture = SkinFetchur.getSkinSet(gfFuture.get().orElse(null)); + } catch (InterruptedException | ExecutionException e) { + e.printStackTrace(); + } } - if (fakePlayer == null && skinFuture != null && profileFuture != null && skinFuture.isDone() && profileFuture.isDone()) { - fakePlayer = new FakePlayer(gfFuture.get().orElse(null), skinFuture.get(), profileFuture.get().orElse(null)); + try { + if (fakePlayer == null && skinFuture != null && profileFuture != null && skinFuture.isDone() && profileFuture.isDone() && profileFuture.get().isPresent()) { + fakePlayer = new FakePlayer(gfFuture.get().orElse(null), skinFuture.get(), profileFuture.get().orElse(null)); + } + } catch (InterruptedException | ExecutionException e) { + plsSetAPIKEY = true; } - render(popupRect, scaledResolution, mouseX, mouseY, profileFuture.isDone() ? profileFuture.get() : null); + try { + render(popupRect, scaledResolution, mouseX, mouseY, plsSetAPIKEY ? null : (profileFuture.isDone() ? profileFuture.get() : null), plsSetAPIKEY); + } catch (InterruptedException | ExecutionException e) { + } + } - public void render(Rectangle popupRect, ScaledResolution scaledResolution, int mouseX, int mouseY, Optional<PlayerProfile> playerProfile) { + private void render(Rectangle popupRect, ScaledResolution scaledResolution, int mouseX, int mouseY, Optional<PlayerProfile> playerProfile, boolean apiKeyPlsSet) { GlStateManager.pushMatrix(); GlStateManager.translate(popupRect.x, popupRect.y, 0); Gui.drawRect(0,0, popupRect.width, popupRect.height, 0xFF23272a); Gui.drawRect(2,2, popupRect.width-2, popupRect.height-2, 0XFF2c2f33); + if (apiKeyPlsSet) { + Minecraft.getMinecraft().fontRendererObj.drawString("Please set API KEY on /dg -> Party Kicker", 5,5, 0xFFFFFFFF); + GlStateManager.popMatrix(); + return; + } if (playerProfile == null) { Minecraft.getMinecraft().fontRendererObj.drawString("Fetching data...", 5,5, 0xFFFFFFFF); GlStateManager.popMatrix(); @@ -271,7 +291,6 @@ public class FeatureViewPlayerOnJoin extends SimpleFeature implements GuiPostRen } } catch (InterruptedException | ExecutionException e) { - e.printStackTrace(); } @@ -297,6 +316,30 @@ public class FeatureViewPlayerOnJoin extends SimpleFeature implements GuiPostRen @Override public void onChat(ClientChatReceivedEvent clientChatReceivedEvent) { + String str = clientChatReceivedEvent.message.getFormattedText(); + if (str.contains("§r§ejoined the dungeon group! (§r§b")) { + String username = TextUtils.stripColor(str).split(" ")[3]; + if (username.equalsIgnoreCase(Minecraft.getMinecraft().getSession().getUsername())) { + Minecraft.getMinecraft().thePlayer.sendChatMessage("/pl"); + PartyManager.INSTANCE.getRunOnMembersReceived().add((e) -> { + for (String s : e) { + ApiFetchur.fetchUUIDAsync(s) + .thenAccept(a -> { + if (a == null) return; + ApiFetchur.fetchMostRecentProfileAsync(a.get(), FeatureRegistry.PARTYKICKER_APIKEY.getAPIKey()); + Minecraft.getMinecraft().thePlayer.addChatMessage(new ChatComponentText("§eDungeons Guide §7:: §e"+s+"§f's Profile ").appendSibling(new ChatComponentText("§7view").setChatStyle(new ChatStyle().setChatHoverEvent(new FeatureViewPlayerOnJoin.HoverEventRenderPlayer(a.orElse(null)))))); + }); + } + }); + } else { + ApiFetchur.fetchUUIDAsync(username) + .thenAccept(a -> { + if (a == null) return; + ApiFetchur.fetchMostRecentProfileAsync(a.get(), FeatureRegistry.PARTYKICKER_APIKEY.getAPIKey()); + Minecraft.getMinecraft().thePlayer.addChatMessage(new ChatComponentText("§eDungeons Guide §7:: §e"+username+"§f's Profile ").appendSibling(new ChatComponentText("§7view").setChatStyle(new ChatStyle().setChatHoverEvent(new FeatureViewPlayerOnJoin.HoverEventRenderPlayer(a.orElse(null)))))); + }); + } + } } diff --git a/src/main/java/kr/syeyoung/dungeonsguide/party/PartyManager.java b/src/main/java/kr/syeyoung/dungeonsguide/party/PartyManager.java index 2ba47dfc..8f938ca3 100644 --- a/src/main/java/kr/syeyoung/dungeonsguide/party/PartyManager.java +++ b/src/main/java/kr/syeyoung/dungeonsguide/party/PartyManager.java @@ -23,10 +23,8 @@ import org.json.JSONArray; import org.json.JSONObject; import java.security.SecureRandom; -import java.util.HashMap; -import java.util.HashSet; -import java.util.Map; -import java.util.Set; +import java.util.*; +import java.util.function.Consumer; public class PartyManager implements StompMessageHandler { public static final PartyManager INSTANCE = new PartyManager(); @@ -46,6 +44,10 @@ public class PartyManager implements StompMessageHandler { private int invitedDash =0; @Getter + private Queue<Consumer<Set<String>>> runOnMembersReceived = new LinkedList<>(); + + + @Getter @Setter private int maxParty = 5; @@ -141,6 +143,10 @@ public class PartyManager implements StompMessageHandler { if (partyJoin == 2 || partyJoin == 100) { partyJoin = 0; // REQ PARTY JOIN + Consumer<Set<String>> r; + while ((r = runOnMembersReceived.poll()) != null){ + r.accept(members); + } JSONArray jsonArray = new JSONArray(); for (String member : members) { |