diff --git a/runelite-client/src/main/java/net/runelite/client/events/PartyChanged.java b/runelite-client/src/main/java/net/runelite/client/events/PartyChanged.java index 0cb8a94c3e..be8bd63a9b 100644 --- a/runelite-client/src/main/java/net/runelite/client/events/PartyChanged.java +++ b/runelite-client/src/main/java/net/runelite/client/events/PartyChanged.java @@ -30,5 +30,6 @@ import lombok.Value; @Value public class PartyChanged { + private final String passphrase; private final UUID partyId; } diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/party/PartyPanel.java b/runelite-client/src/main/java/net/runelite/client/plugins/party/PartyPanel.java index 590424eaf8..2affaf1214 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/party/PartyPanel.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/party/PartyPanel.java @@ -41,6 +41,7 @@ import javax.swing.JComponent; import javax.swing.JOptionPane; import javax.swing.JPanel; import javax.swing.border.EmptyBorder; +import net.runelite.client.callback.ClientThread; import net.runelite.client.plugins.party.data.PartyData; import net.runelite.client.ui.ColorScheme; import net.runelite.client.ui.PluginPanel; @@ -51,7 +52,7 @@ import net.runelite.client.ws.PartyService; class PartyPanel extends PluginPanel { private static final String BTN_CREATE_TEXT = "Create party"; - private static final String BTN_LEAVE_TEXT = "Leave party"; + private static final String BTN_LEAVE_TEXT = "Leave"; private final PartyPlugin plugin; private final PartyService party; @@ -69,7 +70,7 @@ class PartyPanel extends PluginPanel private final JComponent memberBoxPanel = new DragAndDropReorderPane(); @Inject - PartyPanel(final PartyPlugin plugin, final PartyConfig config, final PartyService party) + PartyPanel(final ClientThread clientThread, final PartyPlugin plugin, final PartyConfig config, final PartyService party) { this.plugin = plugin; this.party = party; @@ -122,7 +123,7 @@ class PartyPanel extends PluginPanel rejoinPartyButton.setText("Join previous party"); rejoinPartyButton.setFocusable(false); - copyPartyIdButton.setText("Copy party id"); + copyPartyIdButton.setText("Copy passphrase"); copyPartyIdButton.setFocusable(false); startButton.addActionListener(e -> @@ -143,7 +144,7 @@ class PartyPanel extends PluginPanel else { // Create party - party.changeParty(party.getLocalPartyId()); + clientThread.invokeLater(() -> party.changeParty(party.generatePasspharse())); } }); @@ -153,8 +154,8 @@ class PartyPanel extends PluginPanel { String s = (String) JOptionPane.showInputDialog( joinPartyButton, - "Please enter the party id:", - "Party Id", + "Please enter the party passphrase:", + "Party Passphrase", JOptionPane.PLAIN_MESSAGE, null, null, @@ -165,15 +166,7 @@ class PartyPanel extends PluginPanel return; } - try - { - party.changeParty(UUID.fromString(s)); - } - catch (IllegalArgumentException ex) - { - JOptionPane.showMessageDialog(joinPartyButton, "You have entered an invalid party id.", "Invalid Party Id", - JOptionPane.ERROR_MESSAGE); - } + party.changeParty(s); } }); @@ -181,17 +174,7 @@ class PartyPanel extends PluginPanel { if (!party.isInParty()) { - try - { - party.changeParty(UUID.fromString(config.previousPartyId())); - } - catch (IllegalArgumentException ex) - { - JOptionPane.showMessageDialog(rejoinPartyButton, - "Failed to join your previous party, create a new party or join a new one.", - "Failed to Join Party", - JOptionPane.ERROR_MESSAGE); - } + party.changeParty(config.previousPartyId()); } }); @@ -200,12 +183,11 @@ class PartyPanel extends PluginPanel if (party.isInParty()) { Clipboard clipboard = Toolkit.getDefaultToolkit().getSystemClipboard(); - clipboard.setContents(new StringSelection(String.valueOf(party.getPartyId())), null); + clipboard.setContents(new StringSelection(party.getPartyPassphrase()), null); } }); noPartyPanel.setContent("Not in a party", "Create a party to begin."); - partyEmptyPanel.setContent("Party created", "You can now invite friends!"); updateParty(); } @@ -226,6 +208,8 @@ class PartyPanel extends PluginPanel } else if (plugin.getPartyDataMap().size() <= 1) { + partyEmptyPanel.setContent("Party created", "You can now invite friends!
" + + "Your party passphrase is: " + party.getPartyPassphrase() + "."); add(partyEmptyPanel); } } diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/party/PartyPlugin.java b/runelite-client/src/main/java/net/runelite/client/plugins/party/PartyPlugin.java index c833be1e98..38fdba6e23 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/party/PartyPlugin.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/party/PartyPlugin.java @@ -493,7 +493,7 @@ public class PartyPlugin extends Plugin if (event.getPartyId() != null) { - config.setPreviousPartyId(String.valueOf(event.getPartyId())); + config.setPreviousPartyId(event.getPassphrase()); } SwingUtilities.invokeLater(panel::removeAllMembers); @@ -507,8 +507,7 @@ public class PartyPlugin extends Plugin return; } - chatMessageManager.queue(QueuedMessage.builder().type(ChatMessageType.GAMEMESSAGE).value("Party " + party.getPartyId()).build()); - chatMessageManager.queue(QueuedMessage.builder().type(ChatMessageType.GAMEMESSAGE).value("Local Party " + party.getLocalPartyId()).build()); + chatMessageManager.queue(QueuedMessage.builder().type(ChatMessageType.GAMEMESSAGE).value("Party " + party.getPartyPassphrase() + " ID " + party.getPartyId()).build()); chatMessageManager.queue(QueuedMessage.builder().type(ChatMessageType.GAMEMESSAGE).value("Local ID " + party.getLocalMember().getMemberId()).build()); for (PartyMember partyMember : party.getMembers()) { diff --git a/runelite-client/src/main/java/net/runelite/client/ws/PartyService.java b/runelite-client/src/main/java/net/runelite/client/ws/PartyService.java index d9f82836e0..123a172a0b 100644 --- a/runelite-client/src/main/java/net/runelite/client/ws/PartyService.java +++ b/runelite-client/src/main/java/net/runelite/client/ws/PartyService.java @@ -25,10 +25,14 @@ */ package net.runelite.client.ws; +import com.google.common.base.CharMatcher; +import com.google.common.hash.Hashing; import java.awt.image.BufferedImage; +import java.nio.charset.StandardCharsets; import java.util.ArrayList; import java.util.Collections; import java.util.List; +import java.util.Locale; import java.util.Random; import java.util.UUID; import javax.annotation.Nullable; @@ -37,6 +41,9 @@ import javax.inject.Singleton; import lombok.Getter; import lombok.extern.slf4j.Slf4j; import net.runelite.api.ChatMessageType; +import net.runelite.api.Client; +import net.runelite.api.GameState; +import net.runelite.api.ItemComposition; import net.runelite.client.account.AccountSession; import net.runelite.client.account.SessionManager; import net.runelite.client.chat.ChatMessageManager; @@ -61,22 +68,24 @@ public class PartyService private static final int MAX_MESSAGE_LEN = 150; private static final int MAX_USERNAME_LEN = 32; // same as Discord private static final String USERNAME = "rluser-" + new Random().nextInt(Integer.MAX_VALUE); + private static final String ALPHABET = "bcdfghjklmnpqrstvwxyz"; + private final Client client; private final WSClient wsClient; private final SessionManager sessionManager; private final EventBus eventBus; private final ChatMessageManager chat; private final List members = new ArrayList<>(); - @Getter - private UUID localPartyId = UUID.randomUUID(); - @Getter private UUID partyId; // secret party id + @Getter + private String partyPassphrase; @Inject - private PartyService(final WSClient wsClient, final SessionManager sessionManager, final EventBus eventBus, final ChatMessageManager chat) + private PartyService(final Client client, final WSClient wsClient, final SessionManager sessionManager, final EventBus eventBus, final ChatMessageManager chat) { + this.client = client; this.wsClient = wsClient; this.sessionManager = sessionManager; this.eventBus = eventBus; @@ -84,28 +93,89 @@ public class PartyService eventBus.register(this); } - public void changeParty(@Nullable UUID newParty) + public String generatePasspharse() + { + assert client.isClientThread(); + + Random r = new Random(); + StringBuilder sb = new StringBuilder(); + + if (client.getGameState().getState() >= GameState.LOGIN_SCREEN.getState()) + { + int len = 0; + final CharMatcher matcher = CharMatcher.javaLetter(); + do + { + final int itemId = r.nextInt(client.getItemCount()); + final ItemComposition def = client.getItemDefinition(itemId); + final String name = def.getName(); + if (name == null || name.isEmpty() || name.equals("null")) + { + continue; + } + + final String[] split = name.split(" "); + final String token = split[r.nextInt(split.length)]; + if (!matcher.matchesAllOf(token) || token.length() <= 2) + { + continue; + } + + if (sb.length() > 0) + { + sb.append('-'); + } + sb.append(token.toLowerCase(Locale.US)); + ++len; + } + while (len < 4); + } + else + { + int len = 0; + do + { + if (sb.length() > 0) + { + sb.append('-'); + } + for (int i = 0; i < 5; ++i) + { + sb.append(ALPHABET.charAt(r.nextInt(ALPHABET.length()))); + } + ++len; + } + while (len < 4); + } + + String partyPassphrase = sb.toString(); + log.debug("Generated party passpharse {}", partyPassphrase); + return partyPassphrase; + } + + public void changeParty(@Nullable String passphrase) { if (wsClient.sessionExists()) { wsClient.send(new Part()); } - log.debug("Party change to {}", newParty); + UUID id = passphrase != null ? passphraseToId(passphrase) : null; + + log.debug("Party change to {} (id {})", passphrase, id); members.clear(); - partyId = newParty; + partyId = id; + partyPassphrase = passphrase; if (partyId == null) { - localPartyId = UUID.randomUUID(); // cycle local party id so that a new party is created now - // close the websocket if the session id isn't for an account if (sessionManager.getAccountSession() == null) { wsClient.changeSession(null); } - eventBus.post(new PartyChanged(partyId)); + eventBus.post(new PartyChanged(partyPassphrase, partyId)); return; } @@ -118,7 +188,7 @@ public class PartyService wsClient.changeSession(uuid); } - eventBus.post(new PartyChanged(partyId)); + eventBus.post(new PartyChanged(partyPassphrase, partyId)); wsClient.send(new Join(partyId, USERNAME)); } @@ -221,11 +291,6 @@ public class PartyService return partyId != null; } - public boolean isPartyOwner() - { - return localPartyId.equals(partyId); - } - public void setPartyMemberAvatar(UUID memberID, BufferedImage image) { final PartyMember memberById = getMemberById(memberID); @@ -246,4 +311,13 @@ public class PartyService } return s; } + + private static UUID passphraseToId(String passphrase) + { + return UUID.nameUUIDFromBytes( + Hashing.sha256().hashBytes( + passphrase.getBytes(StandardCharsets.UTF_8) + ).asBytes() + ); + } }