Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ repositories {
mavenCentral()
}

def runeLiteVersion = '1.8.30'
def runeLiteVersion = 'latest.release'

dependencies {
compileOnly group: 'net.runelite', name:'client', version: runeLiteVersion
Expand Down
25 changes: 25 additions & 0 deletions src/main/java/com/infernostats/GodbookConfig.java
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,14 @@ default boolean theatreOnly()

@ConfigItem(
position = 1,
keyName = "lightbearerSupport",
name = "Lightbearer Support",
description = "Additional info displayed based on ring usage"
)
default boolean lightbearerSupport() { return false; }

@ConfigItem(
position = 2,
keyName = "ticks",
name = "Ticks",
description = "How many ticks the counter remains active for"
Expand All @@ -28,4 +36,21 @@ default int maxTicks()
{
return 157;
}

@ConfigItem(
position = 4,
hidden = true,
keyName = "hornAnimId",
name = "[WIP] Extra Animation Id",

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Don't PR things that are still a work in progress

description = "Extra animation ID to treat as a godbook"
)
default int hornAnimId() { return 0; }

@ConfigItem(
position = 3,
keyName = "backwardsCount",
name = "Count Backwards",
description = "Display ticks until full regen, instead of ticks since preach."
)
default boolean backwardsCount() { return false; }
}
14 changes: 9 additions & 5 deletions src/main/java/com/infernostats/GodbookOverlay.java
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ private GodbookOverlay(GodbookPlugin plugin)
public Dimension render(Graphics2D graphics)
{
String title = "Tick:";
HashMap<String, Integer> players = plugin.getPlayers();
HashMap<String, Preach> players = plugin.getPlayers();

panelComponent.getChildren().clear();

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not something you changed, but since we're going to update this: panelComponent.setPreferredSize(new Dimension(getMaxWidth(graphics, players, title) + 10, 0)); should probably be like +12 or +14. It's at the point where it's close enough that the font size will occasionally mess up the formatting of the name.

Expand All @@ -44,15 +44,19 @@ public Dimension render(Graphics2D graphics)
return panelComponent.render(graphics);
}

private int getMaxWidth(Graphics2D graphics, HashMap<String, Integer> players, String title)
private int getMaxWidth(Graphics2D graphics, HashMap<String, Preach> players, String title)
{
String longestKey = Collections.max(players.keySet(), Comparator.comparingInt(String::length));
return graphics.getFontMetrics().stringWidth(longestKey) + graphics.getFontMetrics().stringWidth(title);
return graphics.getFontMetrics().stringWidth(longestKey) + graphics.getFontMetrics().stringWidth(title) + graphics.getFontMetrics().stringWidth("(157)");

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Format this line so it's not as long

}

private void addPlayerToOverlay(String playerName, Integer ticks)
private void addPlayerToOverlay(String playerName, Preach preach)
{
panelComponent.getChildren().add(LineComponent.builder().left(playerName).right(Integer.toString(ticks)).build());
panelComponent.getChildren().add(LineComponent.builder()
.leftColor(preach.preachedWithRing ? Color.YELLOW : Color.WHITE)
.left(playerName)
.right(Integer.toString(preach.tick) + (!preach.preachedWithRing && preach.ringTick != 0 ? " (" + Integer.toString(preach.ringTick) + ")" : ""))

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Extract the logic in the right hand side of this out of the builder

.build());
}
}

128 changes: 122 additions & 6 deletions src/main/java/com/infernostats/GodbookPlugin.java
Original file line number Diff line number Diff line change
Expand Up @@ -9,13 +9,18 @@
import net.runelite.api.*;
import net.runelite.api.events.AnimationChanged;
import net.runelite.api.events.GameTick;
import net.runelite.api.events.VarbitChanged;
import net.runelite.api.gameval.VarbitID;
import net.runelite.client.config.ConfigManager;
import net.runelite.client.eventbus.Subscribe;
import net.runelite.client.party.PartyService;
import net.runelite.client.party.WSClient;
import net.runelite.client.plugins.Plugin;
import net.runelite.client.plugins.PluginDescriptor;
import net.runelite.client.ui.overlay.OverlayManager;

import java.util.LinkedHashMap;
import java.util.*;
import java.util.stream.Collectors;

@Slf4j
@PluginDescriptor(
Expand All @@ -24,7 +29,7 @@
public class GodbookPlugin extends Plugin
{
@Getter(AccessLevel.MODULE)
private LinkedHashMap<String, Integer> players;
private LinkedHashMap<String, Preach> players;

@Inject
private Client client;
Expand All @@ -35,6 +40,12 @@ public class GodbookPlugin extends Plugin
@Inject
private OverlayManager overlayManager;

@Inject
private PartyService partyService;

@Inject
private WSClient wsClient;

@Inject
private GodbookConfig config;

Expand All @@ -48,24 +59,44 @@ GodbookConfig provideConfig(ConfigManager configManager)
protected void startUp() throws Exception
{
players = new LinkedHashMap<>();
wsClient.registerMessage(RingChangeMessage.class);
overlayManager.add(overlay);
}

@Override
protected void shutDown() throws Exception
{
overlayManager.remove(overlay);
wsClient.unregisterMessage(RingChangeMessage.class);
players.clear();
}

@Subscribe
public void onAnimationChanged(final AnimationChanged event)
{
int animId = event.getActor().getAnimation();

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Remove this after creating PreachAnimationID

if (config.theatreOnly() && !isInTheatreOfBlood())
return;

if (GodbookAnimationID.isGodbookAnimation(event.getActor().getAnimation()))
players.put(event.getActor().getName(), 0);
if (GodbookAnimationID.isGodbookAnimation(animId) || isHornAnimation(animId)) {

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Rename GodbookAnimationID to PreachAnimationID and add the horn values

boolean isLightbearerPreach = false;
String name = event.getActor().getName();

if (event.getActor().getName().equalsIgnoreCase(client.getLocalPlayer().getName())) {
if (config.lightbearerSupport()) {
// This is preaching, check our equipment.
try {
Item item = client.getItemContainer(InventoryID.EQUIPMENT)
.getItem(EquipmentInventorySlot.RING.getSlotIdx());
isLightbearerPreach = item.getId() == ItemID.LIGHTBEARER;
} catch (NullPointerException _e) {
isLightbearerPreach = false;
}
}
}

doNewPreach(name, isLightbearerPreach, 0);
}
}

@Subscribe
Expand All @@ -74,11 +105,96 @@ public void onGameTick(GameTick event)
if (players.isEmpty())
return;

// Check if the localPlayer equipped a Lightbearer
if (config.lightbearerSupport() && players.containsKey(client.getLocalPlayer().getName())) {
Preach localPreach = players.get(client.getLocalPlayer().getName());

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

client.getLocalPlayer().getName() can throw an error, do appropriate handling above this branch


Item item;
try {
item = client.getItemContainer(InventoryID.EQUIPMENT).getItem(EquipmentInventorySlot.RING.getSlotIdx());
} catch (NullPointerException _e) {
item = null;
}
Comment on lines +112 to +117

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Make a function for this, it's done more than once

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would also prefer checking for nulls instead of try-catching NPEs

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

InventoryID is also deprecated, use the GameVal form of it


if (item != null && item.getId() == ItemID.LIGHTBEARER) {

if (localPreach.ringTick == 0) {
localPreach.ringTick = findLowestPreach();

if (partyService.isInParty()) {
partyService.send(new RingChangeMessage(client.getLocalPlayer().getName(), 1, localPreach.ringTick));

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Create a new RingChangeMessage (and format it), then call partyService.send(message);

}
}
} else {
if (partyService.isInParty() && localPreach.ringTick != 0) {
partyService.send(new RingChangeMessage(client.getLocalPlayer().getName(), 0, 0));
}

localPreach.ringTick = 0;
}
}

players.entrySet()
.forEach(i -> i.setValue(i.getValue() + 1));
.forEach(i -> i.setValue(i.getValue().advance(config.backwardsCount())));

players.entrySet()
.removeIf(i -> i.getValue() >= config.maxTicks());
.removeIf(this::shouldRemove);
}

public void doNewPreach(String name, boolean isLightbearerPreach, int offset) {
players.put(name,
new Preach(0, isLightbearerPreach, name, startTick() + offset));

// Re-order in descending order so that the lowest preach tick always appears
// at the bottom of the list.
players = players.entrySet()
.stream()
.sorted(Map.Entry.comparingByValue(Comparator.reverseOrder()))
.collect(Collectors.toMap(
Map.Entry::getKey,
Map.Entry::getValue,
(oldValue, newValue) -> newValue, LinkedHashMap::new));
}

@Subscribe
public void onRingChangeMessage(RingChangeMessage e) {
if (!e.n.equalsIgnoreCase(client.getLocalPlayer().getName())) {

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Prefer an early return to avoid nesting

players.entrySet().forEach(p -> {
if (p.getKey().equalsIgnoreCase(e.n)) {
Preach remotePreach = p.getValue();
remotePreach.ringTick = e.r == 1 ? e.t : 0;
p.setValue(remotePreach);
}
});
}
}

private int findLowestPreach() {
// Find the lowest preach
final int[] lowestPreach = {Integer.MAX_VALUE};
players.entrySet().forEach(i -> {
if (lowestPreach[0] > i.getValue().tick) {
lowestPreach[0] = i.getValue().tick;
}
});

return lowestPreach[0];
}
Comment on lines +172 to +182

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This whole function looks weird. It should look something like:

private int findLowestPreach() {
  return players.values().stream()
    .mapToInt(preach -> preach.tick)
    .min().orElse(-1);
}


private boolean shouldRemove(Map.Entry<String, Preach> p) {
if (config.backwardsCount()) {
return p.getValue().tick < 0;
} else {
return p.getValue().tick >= config.maxTicks();
}
}

private boolean isHornAnimation(int animId) {
return config.hornAnimId() != 0 && animId == config.hornAnimId();
}

private int startTick() {
return config.backwardsCount() ? 150 : 0;

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

150 should not be hardcoded here, it should be a config option

}

private boolean isInTheatreOfBlood()
Expand Down
25 changes: 25 additions & 0 deletions src/main/java/com/infernostats/Preach.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
package com.infernostats;

public class Preach implements Comparable<Preach> {

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Needs @AllArgsDataConstructor, set all properties to private, and add @Getter as well

public int tick;
public String name;
public boolean preachedWithRing;
public int ringTick;

public Preach(int ringTick, boolean preachedWithRing, String name, int tick) {
this.ringTick = ringTick;
this.preachedWithRing = preachedWithRing;
this.name = name;
this.tick = tick;
}

@Override
public int compareTo(Preach p) {
return Integer.compare(p.tick, this.tick);
}

public Preach advance(boolean isBackwards) {
this.tick += isBackwards ? -1 : 1;
return this;
}
}
15 changes: 15 additions & 0 deletions src/main/java/com/infernostats/RingChangeMessage.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
package com.infernostats;

import net.runelite.client.party.messages.PartyMessage;

public class RingChangeMessage extends PartyMessage {

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Use Lombok's @AllArgsConstructor to remove your own and give these fields descriptive names. Then, annotate them with @SerializedName to shrink the serialized size of the party message.

String n;
int r;
int t;

public RingChangeMessage(String n, int r, int t) {
this.n = n;
this.r = r;
this.t = t;
}
}
6 changes: 5 additions & 1 deletion src/test/java/com/infernostats/GodbookPluginTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,15 @@
import net.runelite.client.RuneLite;
import net.runelite.client.externalplugins.ExternalPluginManager;

import java.util.Arrays;

public class GodbookPluginTest
{
public static void main(String[] args) throws Exception
{
ExternalPluginManager.loadBuiltin(GodbookPlugin.class);
RuneLite.main(args);
String[] debugArgs = Arrays.copyOf(args, args.length + 1);
debugArgs[args.length] = "--developer-mode";
RuneLite.main(debugArgs);
}
}