World hopper data refreshing (#4918)
Update world list on world hop. Schedule a refresh every 10 minutes, and add a refresh option.
This commit is contained in:
@@ -31,11 +31,16 @@ import com.google.common.eventbus.Subscribe;
|
|||||||
import com.google.inject.Provides;
|
import com.google.inject.Provides;
|
||||||
import java.awt.image.BufferedImage;
|
import java.awt.image.BufferedImage;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
import java.time.Duration;
|
||||||
|
import java.time.Instant;
|
||||||
import java.util.Comparator;
|
import java.util.Comparator;
|
||||||
import java.util.EnumSet;
|
import java.util.EnumSet;
|
||||||
|
import java.util.HashMap;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.concurrent.Future;
|
import java.util.Map;
|
||||||
import java.util.concurrent.ScheduledExecutorService;
|
import java.util.concurrent.ScheduledExecutorService;
|
||||||
|
import java.util.concurrent.ScheduledFuture;
|
||||||
|
import java.util.concurrent.TimeUnit;
|
||||||
import javax.imageio.ImageIO;
|
import javax.imageio.ImageIO;
|
||||||
import javax.inject.Inject;
|
import javax.inject.Inject;
|
||||||
import javax.swing.SwingUtilities;
|
import javax.swing.SwingUtilities;
|
||||||
@@ -50,9 +55,11 @@ import net.runelite.api.MenuAction;
|
|||||||
import net.runelite.api.MenuEntry;
|
import net.runelite.api.MenuEntry;
|
||||||
import net.runelite.api.Varbits;
|
import net.runelite.api.Varbits;
|
||||||
import net.runelite.api.events.ConfigChanged;
|
import net.runelite.api.events.ConfigChanged;
|
||||||
|
import net.runelite.api.events.GameStateChanged;
|
||||||
import net.runelite.api.events.MenuEntryAdded;
|
import net.runelite.api.events.MenuEntryAdded;
|
||||||
import net.runelite.api.events.PlayerMenuOptionClicked;
|
import net.runelite.api.events.PlayerMenuOptionClicked;
|
||||||
import net.runelite.api.events.VarbitChanged;
|
import net.runelite.api.events.VarbitChanged;
|
||||||
|
import net.runelite.api.events.WorldListLoad;
|
||||||
import net.runelite.api.widgets.WidgetInfo;
|
import net.runelite.api.widgets.WidgetInfo;
|
||||||
import net.runelite.client.callback.ClientThread;
|
import net.runelite.client.callback.ClientThread;
|
||||||
import net.runelite.client.chat.ChatColorType;
|
import net.runelite.client.chat.ChatColorType;
|
||||||
@@ -81,6 +88,10 @@ import org.apache.commons.lang3.ArrayUtils;
|
|||||||
@Slf4j
|
@Slf4j
|
||||||
public class WorldHopperPlugin extends Plugin
|
public class WorldHopperPlugin extends Plugin
|
||||||
{
|
{
|
||||||
|
private static final int WORLD_FETCH_TIMER = 10;
|
||||||
|
private static final int REFRESH_THROTTLE = 60_000; // ms
|
||||||
|
private static final int TICK_THROTTLE = (int) Duration.ofMinutes(10).toMillis();
|
||||||
|
|
||||||
private static final String HOP_TO = "Hop-to";
|
private static final String HOP_TO = "Hop-to";
|
||||||
private static final String KICK_OPTION = "Kick";
|
private static final String KICK_OPTION = "Kick";
|
||||||
private static final ImmutableList<String> BEFORE_OPTIONS = ImmutableList.of("Add friend", "Remove friend", KICK_OPTION);
|
private static final ImmutableList<String> BEFORE_OPTIONS = ImmutableList.of("Add friend", "Remove friend", KICK_OPTION);
|
||||||
@@ -113,9 +124,14 @@ public class WorldHopperPlugin extends Plugin
|
|||||||
private NavigationButton navButton;
|
private NavigationButton navButton;
|
||||||
private WorldSwitcherPanel panel;
|
private WorldSwitcherPanel panel;
|
||||||
|
|
||||||
|
private int lastWorld;
|
||||||
|
|
||||||
private int favoriteWorld1, favoriteWorld2;
|
private int favoriteWorld1, favoriteWorld2;
|
||||||
private Future<?> worldResultFuture;
|
|
||||||
|
private ScheduledFuture<?> worldResultFuture;
|
||||||
private WorldResult worldResult;
|
private WorldResult worldResult;
|
||||||
|
private Instant lastFetch;
|
||||||
|
|
||||||
private final HotkeyListener previousKeyListener = new HotkeyListener(() -> config.previousKey())
|
private final HotkeyListener previousKeyListener = new HotkeyListener(() -> config.previousKey())
|
||||||
{
|
{
|
||||||
@Override
|
@Override
|
||||||
@@ -145,25 +161,7 @@ public class WorldHopperPlugin extends Plugin
|
|||||||
keyManager.registerKeyListener(previousKeyListener);
|
keyManager.registerKeyListener(previousKeyListener);
|
||||||
keyManager.registerKeyListener(nextKeyListener);
|
keyManager.registerKeyListener(nextKeyListener);
|
||||||
|
|
||||||
worldResultFuture = executorService.submit(() ->
|
worldResultFuture = executorService.scheduleAtFixedRate(this::tick, 0, WORLD_FETCH_TIMER, TimeUnit.MINUTES);
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
WorldResult worldResult = new WorldClient().lookupWorlds();
|
|
||||||
|
|
||||||
if (worldResult != null)
|
|
||||||
{
|
|
||||||
worldResult.getWorlds().sort(Comparator.comparingInt(World::getId));
|
|
||||||
this.worldResult = worldResult;
|
|
||||||
|
|
||||||
SwingUtilities.invokeLater(() -> panel.populate(worldResult.getWorlds()));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
catch (IOException ex)
|
|
||||||
{
|
|
||||||
log.warn("Error looking up worlds", ex);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
panel = new WorldSwitcherPanel(this);
|
panel = new WorldSwitcherPanel(this);
|
||||||
|
|
||||||
@@ -195,6 +193,7 @@ public class WorldHopperPlugin extends Plugin
|
|||||||
worldResultFuture.cancel(true);
|
worldResultFuture.cancel(true);
|
||||||
worldResultFuture = null;
|
worldResultFuture = null;
|
||||||
worldResult = null;
|
worldResult = null;
|
||||||
|
lastFetch = null;
|
||||||
|
|
||||||
clientToolbar.removeNavigation(navButton);
|
clientToolbar.removeNavigation(navButton);
|
||||||
}
|
}
|
||||||
@@ -347,6 +346,94 @@ public class WorldHopperPlugin extends Plugin
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Subscribe
|
||||||
|
public void onGameStateChanged(GameStateChanged gameStateChanged)
|
||||||
|
{
|
||||||
|
// If the player has disabled the side bar plugin panel, do not update the UI
|
||||||
|
if (config.showSidebar() && gameStateChanged.getGameState() == GameState.LOGGED_IN)
|
||||||
|
{
|
||||||
|
if (lastWorld != client.getWorld())
|
||||||
|
{
|
||||||
|
int newWorld = client.getWorld();
|
||||||
|
panel.switchCurrentHighlight(newWorld, lastWorld);
|
||||||
|
lastWorld = newWorld;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Subscribe
|
||||||
|
public void onWorldListLoad(WorldListLoad worldListLoad)
|
||||||
|
{
|
||||||
|
if (!config.showSidebar())
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Map<Integer, Integer> worldData = new HashMap<>();
|
||||||
|
|
||||||
|
for (net.runelite.api.World w : worldListLoad.getWorlds())
|
||||||
|
{
|
||||||
|
worldData.put(w.getId(), w.getPlayerCount());
|
||||||
|
}
|
||||||
|
|
||||||
|
panel.updateListData(worldData);
|
||||||
|
this.lastFetch = Instant.now(); // This counts as a fetch as it updates populations
|
||||||
|
}
|
||||||
|
|
||||||
|
private void tick()
|
||||||
|
{
|
||||||
|
Instant now = Instant.now();
|
||||||
|
if (lastFetch != null && now.toEpochMilli() - lastFetch.toEpochMilli() < TICK_THROTTLE)
|
||||||
|
{
|
||||||
|
log.debug("Throttling world refresh tick");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
fetchWorlds();
|
||||||
|
}
|
||||||
|
|
||||||
|
void refresh()
|
||||||
|
{
|
||||||
|
Instant now = Instant.now();
|
||||||
|
if (lastFetch != null && now.toEpochMilli() - lastFetch.toEpochMilli() < REFRESH_THROTTLE)
|
||||||
|
{
|
||||||
|
log.debug("Throttling world refresh");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
fetchWorlds();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void fetchWorlds()
|
||||||
|
{
|
||||||
|
log.debug("Fetching worlds");
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
WorldResult worldResult = new WorldClient().lookupWorlds();
|
||||||
|
|
||||||
|
if (worldResult != null)
|
||||||
|
{
|
||||||
|
worldResult.getWorlds().sort(Comparator.comparingInt(World::getId));
|
||||||
|
this.worldResult = worldResult;
|
||||||
|
this.lastFetch = Instant.now();
|
||||||
|
updateList();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (IOException ex)
|
||||||
|
{
|
||||||
|
log.warn("Error looking up worlds", ex);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This method ONLY updates the list's UI, not the actual world list and data it displays.
|
||||||
|
*/
|
||||||
|
private void updateList()
|
||||||
|
{
|
||||||
|
SwingUtilities.invokeLater(() -> panel.populate(worldResult.getWorlds()));
|
||||||
|
}
|
||||||
|
|
||||||
private void hop(boolean previous)
|
private void hop(boolean previous)
|
||||||
{
|
{
|
||||||
if (worldResult == null || client.getGameState() != GameState.LOGGED_IN)
|
if (worldResult == null || client.getGameState() != GameState.LOGGED_IN)
|
||||||
|
|||||||
@@ -32,7 +32,9 @@ import java.awt.event.MouseAdapter;
|
|||||||
import java.awt.event.MouseEvent;
|
import java.awt.event.MouseEvent;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
import javax.swing.JPanel;
|
import javax.swing.JPanel;
|
||||||
|
import javax.swing.SwingUtilities;
|
||||||
import javax.swing.border.EmptyBorder;
|
import javax.swing.border.EmptyBorder;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import net.runelite.client.ui.ColorScheme;
|
import net.runelite.client.ui.ColorScheme;
|
||||||
@@ -57,7 +59,7 @@ class WorldSwitcherPanel extends PluginPanel
|
|||||||
private WorldOrder orderIndex = WorldOrder.WORLD;
|
private WorldOrder orderIndex = WorldOrder.WORLD;
|
||||||
private boolean ascendingOrder = true;
|
private boolean ascendingOrder = true;
|
||||||
|
|
||||||
private List<World> worlds;
|
private ArrayList<WorldTableRow> rows = new ArrayList<>();
|
||||||
private WorldHopperPlugin plugin;
|
private WorldHopperPlugin plugin;
|
||||||
|
|
||||||
WorldSwitcherPanel(WorldHopperPlugin plugin)
|
WorldSwitcherPanel(WorldHopperPlugin plugin)
|
||||||
@@ -75,37 +77,73 @@ class WorldSwitcherPanel extends PluginPanel
|
|||||||
add(listContainer);
|
add(listContainer);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void switchCurrentHighlight(int newWorld, int lastWorld)
|
||||||
|
{
|
||||||
|
for (WorldTableRow row : rows)
|
||||||
|
{
|
||||||
|
if (row.getWorld().getId() == newWorld)
|
||||||
|
{
|
||||||
|
row.recolour(true);
|
||||||
|
}
|
||||||
|
else if (row.getWorld().getId() == lastWorld)
|
||||||
|
{
|
||||||
|
row.recolour(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void updateListData(Map<Integer, Integer> worldData)
|
||||||
|
{
|
||||||
|
for (WorldTableRow worldTableRow : rows)
|
||||||
|
{
|
||||||
|
World world = worldTableRow.getWorld();
|
||||||
|
Integer playerCount = worldData.get(world.getId());
|
||||||
|
if (playerCount != null)
|
||||||
|
{
|
||||||
|
worldTableRow.updatePlayerCount(playerCount);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// If the list is being ordered by player count, then it has to be re-painted
|
||||||
|
// to properly display the new data
|
||||||
|
if (orderIndex == WorldOrder.PLAYERS)
|
||||||
|
{
|
||||||
|
updateList();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void updateList()
|
void updateList()
|
||||||
{
|
{
|
||||||
worlds.sort((w1, w2) ->
|
rows.sort((r1, r2) ->
|
||||||
{
|
{
|
||||||
switch (orderIndex)
|
switch (orderIndex)
|
||||||
{
|
{
|
||||||
case WORLD:
|
case WORLD:
|
||||||
return Integer.compare(w1.getId(), w2.getId()) * (ascendingOrder ? 1 : -1);
|
return Integer.compare(r1.getWorld().getId(), r2.getWorld().getId()) * (ascendingOrder ? 1 : -1);
|
||||||
case PLAYERS:
|
case PLAYERS:
|
||||||
return Integer.compare(w1.getPlayers(), w2.getPlayers()) * (ascendingOrder ? 1 : -1);
|
return Integer.compare(r1.getUpdatedPlayerCount(), r2.getUpdatedPlayerCount()) * (ascendingOrder ? 1 : -1);
|
||||||
case ACTIVITY:
|
case ACTIVITY:
|
||||||
return w1.getActivity().compareTo(w2.getActivity()) * (ascendingOrder ? 1 : -1);
|
return r1.getWorld().getActivity().compareTo(r2.getWorld().getActivity()) * (ascendingOrder ? 1 : -1);
|
||||||
default:
|
default:
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
worlds.sort((w1, w2) ->
|
rows.sort((r1, r2) ->
|
||||||
{
|
{
|
||||||
boolean b1 = plugin.isFavorite(w1);
|
boolean b1 = plugin.isFavorite(r1.getWorld());
|
||||||
boolean b2 = plugin.isFavorite(w2);
|
boolean b2 = plugin.isFavorite(r2.getWorld());
|
||||||
return Boolean.compare(b2, b1);
|
return Boolean.compare(b2, b1);
|
||||||
});
|
});
|
||||||
|
|
||||||
listContainer.removeAll();
|
listContainer.removeAll();
|
||||||
|
|
||||||
for (int i = 0; i < worlds.size(); i++)
|
for (int i = 0; i < rows.size(); i++)
|
||||||
{
|
{
|
||||||
World world = worlds.get(i);
|
WorldTableRow row = rows.get(i);
|
||||||
listContainer.add(buildRow(world, i % 2 == 0, world.getId() == plugin.getCurrentWorld(), plugin.isFavorite(world)));
|
row.setBackground(i % 2 == 0 ? ODD_ROW : ColorScheme.DARK_GRAY_COLOR);
|
||||||
|
listContainer.add(row);
|
||||||
}
|
}
|
||||||
|
|
||||||
listContainer.revalidate();
|
listContainer.revalidate();
|
||||||
@@ -114,7 +152,14 @@ class WorldSwitcherPanel extends PluginPanel
|
|||||||
|
|
||||||
void populate(List<World> worlds)
|
void populate(List<World> worlds)
|
||||||
{
|
{
|
||||||
this.worlds = new ArrayList<>(worlds);
|
rows.clear();
|
||||||
|
|
||||||
|
for (int i = 0; i < worlds.size(); i++)
|
||||||
|
{
|
||||||
|
World world = worlds.get(i);
|
||||||
|
rows.add(buildRow(world, i % 2 == 0, world.getId() == plugin.getCurrentWorld(), plugin.isFavorite(world)));
|
||||||
|
}
|
||||||
|
|
||||||
updateList();
|
updateList();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -149,38 +194,49 @@ class WorldSwitcherPanel extends PluginPanel
|
|||||||
JPanel header = new JPanel(new BorderLayout());
|
JPanel header = new JPanel(new BorderLayout());
|
||||||
JPanel leftSide = new JPanel(new BorderLayout());
|
JPanel leftSide = new JPanel(new BorderLayout());
|
||||||
|
|
||||||
worldHeader = new WorldTableHeader("World", orderIndex == WorldOrder.WORLD, ascendingOrder);
|
worldHeader = new WorldTableHeader("World", orderIndex == WorldOrder.WORLD, ascendingOrder, plugin::refresh);
|
||||||
worldHeader.setPreferredSize(new Dimension(WORLD_COLUMN_WIDTH, 0));
|
worldHeader.setPreferredSize(new Dimension(WORLD_COLUMN_WIDTH, 0));
|
||||||
worldHeader.addMouseListener(new MouseAdapter()
|
worldHeader.addMouseListener(new MouseAdapter()
|
||||||
{
|
{
|
||||||
@Override
|
@Override
|
||||||
public void mousePressed(MouseEvent mouseEvent)
|
public void mousePressed(MouseEvent mouseEvent)
|
||||||
{
|
{
|
||||||
|
if (SwingUtilities.isRightMouseButton(mouseEvent))
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
ascendingOrder = orderIndex != WorldOrder.WORLD || !ascendingOrder;
|
ascendingOrder = orderIndex != WorldOrder.WORLD || !ascendingOrder;
|
||||||
orderBy(WorldOrder.WORLD);
|
orderBy(WorldOrder.WORLD);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
playersHeader = new WorldTableHeader("#", orderIndex == WorldOrder.PLAYERS, ascendingOrder);
|
playersHeader = new WorldTableHeader("#", orderIndex == WorldOrder.PLAYERS, ascendingOrder, plugin::refresh);
|
||||||
playersHeader.setPreferredSize(new Dimension(PLAYERS_COLUMN_WIDTH, 0));
|
playersHeader.setPreferredSize(new Dimension(PLAYERS_COLUMN_WIDTH, 0));
|
||||||
playersHeader.addMouseListener(new MouseAdapter()
|
playersHeader.addMouseListener(new MouseAdapter()
|
||||||
{
|
{
|
||||||
@Override
|
@Override
|
||||||
public void mousePressed(MouseEvent mouseEvent)
|
public void mousePressed(MouseEvent mouseEvent)
|
||||||
{
|
{
|
||||||
|
if (SwingUtilities.isRightMouseButton(mouseEvent))
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
ascendingOrder = orderIndex != WorldOrder.PLAYERS || !ascendingOrder;
|
ascendingOrder = orderIndex != WorldOrder.PLAYERS || !ascendingOrder;
|
||||||
orderBy(WorldOrder.PLAYERS);
|
orderBy(WorldOrder.PLAYERS);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
activityHeader = new WorldTableHeader("Activity", orderIndex == WorldOrder.ACTIVITY, ascendingOrder);
|
activityHeader = new WorldTableHeader("Activity", orderIndex == WorldOrder.ACTIVITY, ascendingOrder, plugin::refresh);
|
||||||
activityHeader.setBorder(new EmptyBorder(3, 5, 3, 5));
|
activityHeader.setBorder(new EmptyBorder(3, 5, 3, 5));
|
||||||
activityHeader.addMouseListener(new MouseAdapter()
|
activityHeader.addMouseListener(new MouseAdapter()
|
||||||
{
|
{
|
||||||
@Override
|
@Override
|
||||||
public void mousePressed(MouseEvent mouseEvent)
|
public void mousePressed(MouseEvent mouseEvent)
|
||||||
{
|
{
|
||||||
|
if (SwingUtilities.isRightMouseButton(mouseEvent))
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
ascendingOrder = orderIndex != WorldOrder.ACTIVITY || !ascendingOrder;
|
ascendingOrder = orderIndex != WorldOrder.ACTIVITY || !ascendingOrder;
|
||||||
orderBy(WorldOrder.ACTIVITY);
|
orderBy(WorldOrder.ACTIVITY);
|
||||||
}
|
}
|
||||||
@@ -198,9 +254,9 @@ class WorldSwitcherPanel extends PluginPanel
|
|||||||
/**
|
/**
|
||||||
* Builds a table row, that displays the world's information.
|
* Builds a table row, that displays the world's information.
|
||||||
*/
|
*/
|
||||||
private JPanel buildRow(World world, boolean stripe, boolean current, boolean favorite)
|
private WorldTableRow buildRow(World world, boolean stripe, boolean current, boolean favorite)
|
||||||
{
|
{
|
||||||
JPanel row = new WorldTableRow(world, current, favorite,
|
WorldTableRow row = new WorldTableRow(world, current, favorite,
|
||||||
world1 ->
|
world1 ->
|
||||||
{
|
{
|
||||||
plugin.hopTo(world1);
|
plugin.hopTo(world1);
|
||||||
|
|||||||
@@ -30,10 +30,13 @@ import java.awt.event.MouseAdapter;
|
|||||||
import java.awt.event.MouseEvent;
|
import java.awt.event.MouseEvent;
|
||||||
import java.awt.event.MouseListener;
|
import java.awt.event.MouseListener;
|
||||||
import java.awt.image.BufferedImage;
|
import java.awt.image.BufferedImage;
|
||||||
|
import javax.annotation.Nonnull;
|
||||||
import javax.swing.BorderFactory;
|
import javax.swing.BorderFactory;
|
||||||
import javax.swing.ImageIcon;
|
import javax.swing.ImageIcon;
|
||||||
import javax.swing.JLabel;
|
import javax.swing.JLabel;
|
||||||
|
import javax.swing.JMenuItem;
|
||||||
import javax.swing.JPanel;
|
import javax.swing.JPanel;
|
||||||
|
import javax.swing.JPopupMenu;
|
||||||
import javax.swing.border.CompoundBorder;
|
import javax.swing.border.CompoundBorder;
|
||||||
import javax.swing.border.EmptyBorder;
|
import javax.swing.border.EmptyBorder;
|
||||||
import net.runelite.client.ui.ColorScheme;
|
import net.runelite.client.ui.ColorScheme;
|
||||||
@@ -61,7 +64,7 @@ class WorldTableHeader extends JPanel
|
|||||||
// Determines if this header column is being used to order the list
|
// Determines if this header column is being used to order the list
|
||||||
private boolean ordering = false;
|
private boolean ordering = false;
|
||||||
|
|
||||||
WorldTableHeader(String title, boolean ordered, boolean ascending)
|
WorldTableHeader(String title, boolean ordered, boolean ascending, @Nonnull Runnable onRefresh)
|
||||||
{
|
{
|
||||||
setLayout(new BorderLayout(5, 0));
|
setLayout(new BorderLayout(5, 0));
|
||||||
setBorder(new CompoundBorder(
|
setBorder(new CompoundBorder(
|
||||||
@@ -93,6 +96,19 @@ class WorldTableHeader extends JPanel
|
|||||||
textLabel.setText(title);
|
textLabel.setText(title);
|
||||||
textLabel.setFont(FontManager.getRunescapeSmallFont());
|
textLabel.setFont(FontManager.getRunescapeSmallFont());
|
||||||
|
|
||||||
|
final JMenuItem refresh = new JMenuItem("Refresh worlds");
|
||||||
|
refresh.addActionListener(e ->
|
||||||
|
{
|
||||||
|
onRefresh.run();
|
||||||
|
});
|
||||||
|
|
||||||
|
final JPopupMenu popupMenu = new JPopupMenu();
|
||||||
|
popupMenu.setBorder(new EmptyBorder(5, 5, 5, 5));
|
||||||
|
popupMenu.add(refresh);
|
||||||
|
|
||||||
|
textLabel.setComponentPopupMenu(popupMenu);
|
||||||
|
setComponentPopupMenu(popupMenu);
|
||||||
|
|
||||||
highlight(ordered, ascending);
|
highlight(ordered, ascending);
|
||||||
|
|
||||||
add(textLabel, BorderLayout.WEST);
|
add(textLabel, BorderLayout.WEST);
|
||||||
|
|||||||
@@ -37,6 +37,8 @@ import javax.swing.JMenuItem;
|
|||||||
import javax.swing.JPanel;
|
import javax.swing.JPanel;
|
||||||
import javax.swing.JPopupMenu;
|
import javax.swing.JPopupMenu;
|
||||||
import javax.swing.border.EmptyBorder;
|
import javax.swing.border.EmptyBorder;
|
||||||
|
import lombok.AccessLevel;
|
||||||
|
import lombok.Getter;
|
||||||
import net.runelite.client.ui.FontManager;
|
import net.runelite.client.ui.FontManager;
|
||||||
import net.runelite.client.util.ImageUtil;
|
import net.runelite.client.util.ImageUtil;
|
||||||
import net.runelite.http.api.worlds.World;
|
import net.runelite.http.api.worlds.World;
|
||||||
@@ -67,12 +69,24 @@ class WorldTableRow extends JPanel
|
|||||||
FLAG_GER = new ImageIcon(ImageUtil.getResourceStreamFromClass(WorldHopperPlugin.class, "flag_ger.png"));
|
FLAG_GER = new ImageIcon(ImageUtil.getResourceStreamFromClass(WorldHopperPlugin.class, "flag_ger.png"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private JLabel worldField;
|
||||||
|
private JLabel playerCountField;
|
||||||
|
private JLabel activityField;
|
||||||
|
|
||||||
|
@Getter
|
||||||
|
private final World world;
|
||||||
|
|
||||||
|
@Getter(AccessLevel.PACKAGE)
|
||||||
|
private int updatedPlayerCount;
|
||||||
|
|
||||||
private Color lastBackground;
|
private Color lastBackground;
|
||||||
private boolean current;
|
private boolean current;
|
||||||
|
|
||||||
WorldTableRow(World world, boolean current, boolean favorite, Consumer<World> onSelect, BiConsumer<World, Boolean> onFavorite)
|
WorldTableRow(World world, boolean current, boolean favorite, Consumer<World> onSelect, BiConsumer<World, Boolean> onFavorite)
|
||||||
{
|
{
|
||||||
this.current = current;
|
this.current = current;
|
||||||
|
this.world = world;
|
||||||
|
this.updatedPlayerCount = world.getPlayers();
|
||||||
|
|
||||||
setLayout(new BorderLayout());
|
setLayout(new BorderLayout());
|
||||||
setBorder(new EmptyBorder(2, 0, 2, 0));
|
setBorder(new EmptyBorder(2, 0, 2, 0));
|
||||||
@@ -142,18 +156,20 @@ class WorldTableRow extends JPanel
|
|||||||
JPanel leftSide = new JPanel(new BorderLayout());
|
JPanel leftSide = new JPanel(new BorderLayout());
|
||||||
leftSide.setOpaque(false);
|
leftSide.setOpaque(false);
|
||||||
|
|
||||||
JPanel worldField = buildWorldField(world);
|
JPanel worldField = buildWorldField();
|
||||||
worldField.setPreferredSize(new Dimension(WORLD_COLUMN_WIDTH, 0));
|
worldField.setPreferredSize(new Dimension(WORLD_COLUMN_WIDTH, 0));
|
||||||
worldField.setOpaque(false);
|
worldField.setOpaque(false);
|
||||||
|
|
||||||
JPanel playersField = buildPlayersField(world);
|
JPanel playersField = buildPlayersField();
|
||||||
playersField.setPreferredSize(new Dimension(PLAYERS_COLUMN_WIDTH, 0));
|
playersField.setPreferredSize(new Dimension(PLAYERS_COLUMN_WIDTH, 0));
|
||||||
playersField.setOpaque(false);
|
playersField.setOpaque(false);
|
||||||
|
|
||||||
JPanel activityField = buildActivityField(world);
|
JPanel activityField = buildActivityField();
|
||||||
activityField.setBorder(new EmptyBorder(5, 5, 5, 5));
|
activityField.setBorder(new EmptyBorder(5, 5, 5, 5));
|
||||||
activityField.setOpaque(false);
|
activityField.setOpaque(false);
|
||||||
|
|
||||||
|
recolour(current);
|
||||||
|
|
||||||
leftSide.add(worldField, BorderLayout.WEST);
|
leftSide.add(worldField, BorderLayout.WEST);
|
||||||
leftSide.add(playersField, BorderLayout.EAST);
|
leftSide.add(playersField, BorderLayout.EAST);
|
||||||
|
|
||||||
@@ -161,19 +177,49 @@ class WorldTableRow extends JPanel
|
|||||||
add(activityField, BorderLayout.CENTER);
|
add(activityField, BorderLayout.CENTER);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void updatePlayerCount(int playerCount)
|
||||||
|
{
|
||||||
|
this.updatedPlayerCount = playerCount;
|
||||||
|
playerCountField.setText(String.valueOf(playerCount));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void recolour(boolean current)
|
||||||
|
{
|
||||||
|
playerCountField.setForeground(current ? CURRENT_WORLD : Color.WHITE);
|
||||||
|
|
||||||
|
if (current)
|
||||||
|
{
|
||||||
|
activityField.setForeground(CURRENT_WORLD);
|
||||||
|
worldField.setForeground(CURRENT_WORLD);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
else if (world.getTypes().contains(WorldType.PVP)
|
||||||
|
|| world.getTypes().contains(WorldType.PVP_HIGH_RISK)
|
||||||
|
|| world.getTypes().contains(WorldType.DEADMAN)
|
||||||
|
|| world.getTypes().contains(WorldType.SEASONAL_DEADMAN))
|
||||||
|
{
|
||||||
|
activityField.setForeground(DANGEROUS_WORLD);
|
||||||
|
}
|
||||||
|
else if (world.getTypes().contains(WorldType.TOURNAMENT))
|
||||||
|
{
|
||||||
|
activityField.setForeground(TOURNAMENT_WORLD);
|
||||||
|
}
|
||||||
|
|
||||||
|
worldField.setForeground(world.getTypes().contains(WorldType.MEMBERS) ? MEMBERS_WORLD : FREE_WORLD);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Builds the players list field (containing the amount of players logged in that world).
|
* Builds the players list field (containing the amount of players logged in that world).
|
||||||
*/
|
*/
|
||||||
private JPanel buildPlayersField(World world)
|
private JPanel buildPlayersField()
|
||||||
{
|
{
|
||||||
JPanel column = new JPanel(new BorderLayout());
|
JPanel column = new JPanel(new BorderLayout());
|
||||||
column.setBorder(new EmptyBorder(0, 5, 0, 5));
|
column.setBorder(new EmptyBorder(0, 5, 0, 5));
|
||||||
|
|
||||||
JLabel label = new JLabel(world.getPlayers() + "");
|
playerCountField = new JLabel(world.getPlayers() + "");
|
||||||
label.setFont(FontManager.getRunescapeSmallFont());
|
playerCountField.setFont(FontManager.getRunescapeSmallFont());
|
||||||
label.setForeground(current ? CURRENT_WORLD : Color.WHITE);
|
|
||||||
|
|
||||||
column.add(label, BorderLayout.WEST);
|
column.add(playerCountField, BorderLayout.WEST);
|
||||||
|
|
||||||
return column;
|
return column;
|
||||||
}
|
}
|
||||||
@@ -181,31 +227,15 @@ class WorldTableRow extends JPanel
|
|||||||
/**
|
/**
|
||||||
* Builds the activity list field (containing that world's activity/theme).
|
* Builds the activity list field (containing that world's activity/theme).
|
||||||
*/
|
*/
|
||||||
private JPanel buildActivityField(World world)
|
private JPanel buildActivityField()
|
||||||
{
|
{
|
||||||
JPanel column = new JPanel(new BorderLayout());
|
JPanel column = new JPanel(new BorderLayout());
|
||||||
column.setBorder(new EmptyBorder(0, 5, 0, 5));
|
column.setBorder(new EmptyBorder(0, 5, 0, 5));
|
||||||
|
|
||||||
JLabel label = new JLabel(world.getActivity());
|
activityField = new JLabel(world.getActivity());
|
||||||
label.setFont(FontManager.getRunescapeSmallFont());
|
activityField.setFont(FontManager.getRunescapeSmallFont());
|
||||||
|
|
||||||
if (current)
|
column.add(activityField, BorderLayout.WEST);
|
||||||
{
|
|
||||||
label.setForeground(CURRENT_WORLD);
|
|
||||||
}
|
|
||||||
else if (world.getTypes().contains(WorldType.PVP)
|
|
||||||
|| world.getTypes().contains(WorldType.PVP_HIGH_RISK)
|
|
||||||
|| world.getTypes().contains(WorldType.DEADMAN)
|
|
||||||
|| world.getTypes().contains(WorldType.SEASONAL_DEADMAN))
|
|
||||||
{
|
|
||||||
label.setForeground(DANGEROUS_WORLD);
|
|
||||||
}
|
|
||||||
else if (world.getTypes().contains(WorldType.TOURNAMENT))
|
|
||||||
{
|
|
||||||
label.setForeground(TOURNAMENT_WORLD);
|
|
||||||
}
|
|
||||||
|
|
||||||
column.add(label, BorderLayout.WEST);
|
|
||||||
|
|
||||||
return column;
|
return column;
|
||||||
}
|
}
|
||||||
@@ -213,26 +243,17 @@ class WorldTableRow extends JPanel
|
|||||||
/**
|
/**
|
||||||
* Builds the world list field (containing the country's flag and the world index).
|
* Builds the world list field (containing the country's flag and the world index).
|
||||||
*/
|
*/
|
||||||
private JPanel buildWorldField(World world)
|
private JPanel buildWorldField()
|
||||||
{
|
{
|
||||||
JPanel column = new JPanel(new BorderLayout(7, 0));
|
JPanel column = new JPanel(new BorderLayout(7, 0));
|
||||||
column.setBorder(new EmptyBorder(0, 5, 0, 5));
|
column.setBorder(new EmptyBorder(0, 5, 0, 5));
|
||||||
|
|
||||||
JLabel label = new JLabel(world.getId() + "");
|
worldField = new JLabel(world.getId() + "");
|
||||||
|
|
||||||
if (current)
|
|
||||||
{
|
|
||||||
label.setForeground(CURRENT_WORLD);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
label.setForeground(world.getTypes().contains(WorldType.MEMBERS) ? MEMBERS_WORLD : FREE_WORLD);
|
|
||||||
}
|
|
||||||
|
|
||||||
JLabel flag = new JLabel(getFlag(world.getLocation()));
|
JLabel flag = new JLabel(getFlag(world.getLocation()));
|
||||||
|
|
||||||
column.add(flag, BorderLayout.WEST);
|
column.add(flag, BorderLayout.WEST);
|
||||||
column.add(label, BorderLayout.CENTER);
|
column.add(worldField, BorderLayout.CENTER);
|
||||||
|
|
||||||
return column;
|
return column;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user