* Add option to draw ping underneath the fps

* Move the ping package from the world hopper plugin to utils
This commit is contained in:
sdburns1998
2019-04-24 02:34:28 +02:00
committed by Kyleeld
parent 6062416090
commit bb088dd57f
9 changed files with 135 additions and 41 deletions

View File

@@ -22,7 +22,7 @@
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/ */
package net.runelite.client.plugins.fps; package net.runelite.client.plugins.performance;
import javax.inject.Inject; import javax.inject.Inject;
import net.runelite.api.events.FocusChanged; import net.runelite.api.events.FocusChanged;
@@ -44,7 +44,7 @@ public class FpsDrawListener implements Runnable
{ {
private static final int SAMPLE_SIZE = 4; private static final int SAMPLE_SIZE = 4;
private final FpsConfig config; private final PerformanceConfig config;
private long targetDelay = 0; private long targetDelay = 0;
@@ -58,7 +58,7 @@ public class FpsDrawListener implements Runnable
private long sleepDelay = 0; private long sleepDelay = 0;
@Inject @Inject
private FpsDrawListener(FpsConfig config) private FpsDrawListener(PerformanceConfig config)
{ {
this.config = config; this.config = config;
reloadConfig(); reloadConfig();

View File

@@ -22,7 +22,7 @@
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/ */
package net.runelite.client.plugins.fps; package net.runelite.client.plugins.performance;
import lombok.Getter; import lombok.Getter;
import lombok.RequiredArgsConstructor; import lombok.RequiredArgsConstructor;

View File

@@ -22,14 +22,14 @@
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/ */
package net.runelite.client.plugins.fps; package net.runelite.client.plugins.performance;
import net.runelite.client.config.Config; import net.runelite.client.config.Config;
import net.runelite.client.config.ConfigGroup; import net.runelite.client.config.ConfigGroup;
import net.runelite.client.config.ConfigItem; import net.runelite.client.config.ConfigItem;
@ConfigGroup(FpsPlugin.CONFIG_GROUP_KEY) @ConfigGroup(PerformancePlugin.CONFIG_GROUP_KEY)
public interface FpsConfig extends Config public interface PerformanceConfig extends Config
{ {
@ConfigItem( @ConfigItem(
keyName = "limitMode", keyName = "limitMode",
@@ -63,4 +63,15 @@ public interface FpsConfig extends Config
{ {
return true; return true;
} }
@ConfigItem(
keyName = "drawPing",
name = "Draw ping indicator",
description = "Show a number in the corner for the current ping",
position = 3
)
default boolean drawPing()
{
return false;
}
} }

View File

@@ -22,14 +22,16 @@
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/ */
package net.runelite.client.plugins.fps; package net.runelite.client.plugins.performance;
import java.awt.Color; import java.awt.Color;
import java.awt.Dimension; import java.awt.Dimension;
import java.awt.FontMetrics;
import java.awt.Graphics2D; import java.awt.Graphics2D;
import javax.inject.Inject; import javax.inject.Inject;
import net.runelite.api.Client; import net.runelite.api.Client;
import net.runelite.api.Point; import net.runelite.api.Point;
import net.runelite.api.Varbits;
import net.runelite.api.events.FocusChanged; import net.runelite.api.events.FocusChanged;
import net.runelite.client.ui.overlay.Overlay; import net.runelite.client.ui.overlay.Overlay;
import net.runelite.client.ui.overlay.OverlayLayer; import net.runelite.client.ui.overlay.OverlayLayer;
@@ -45,24 +47,22 @@ import net.runelite.client.ui.overlay.OverlayUtil;
* This locks "FPS:" into one position (the far top right corner of the canvas), * This locks "FPS:" into one position (the far top right corner of the canvas),
* along with a locked position for the FPS value. * along with a locked position for the FPS value.
*/ */
public class FpsOverlay extends Overlay public class PerformanceOverlay extends Overlay
{ {
private static final int Y_OFFSET = 1;
private static final int VALUE_X_OFFSET = 1;
private static final String FPS_STRING = " FPS";
// Local dependencies // Local dependencies
private final FpsConfig config; private final PerformanceConfig config;
private final Client client; private final Client client;
private final PerformancePlugin plugin;
// Often changing values // Often changing values
private boolean isFocused = true; private boolean isFocused = true;
@Inject @Inject
private FpsOverlay(FpsConfig config, Client client) private PerformanceOverlay(PerformancePlugin plugin, PerformanceConfig config, Client client)
{ {
this.config = config; this.config = config;
this.client = client; this.client = client;
this.plugin = plugin;
setLayer(OverlayLayer.ABOVE_WIDGETS); setLayer(OverlayLayer.ABOVE_WIDGETS);
setPriority(OverlayPriority.HIGH); setPriority(OverlayPriority.HIGH);
setPosition(OverlayPosition.DYNAMIC); setPosition(OverlayPosition.DYNAMIC);
@@ -84,21 +84,62 @@ public class FpsOverlay extends Overlay
return isEnforced() ? Color.red : Color.yellow; return isEnforced() ? Color.red : Color.yellow;
} }
private static Color getPingColor(int ping)
{
if (ping >= 100 || ping < 0)
{
return Color.red;
}
else if (ping >= 50)
{
return Color.yellow;
}
return Color.green;
}
private int calculateOffset()
{
if ((client.getVar(Varbits.SIDE_PANELS) == 1) && client.isResized())
{
return 27;
}
return 2;
}
@Override @Override
public Dimension render(Graphics2D graphics) public Dimension render(Graphics2D graphics)
{ {
if (!config.drawFps()) if (!config.drawFps() && !config.drawPing())
{ {
return null; return null;
} }
final String text = client.getFPS() + FPS_STRING; final int offset = calculateOffset();
final int textWidth = graphics.getFontMetrics().stringWidth(text);
final int textHeight = graphics.getFontMetrics().getAscent() - graphics.getFontMetrics().getDescent();
final int width = (int) client.getRealDimensions().getWidth(); final int width = (int) client.getRealDimensions().getWidth();
final Point point = new Point(width - textWidth - VALUE_X_OFFSET, textHeight + Y_OFFSET); final FontMetrics fontMetrics = graphics.getFontMetrics();
OverlayUtil.renderTextLocation(graphics, point, text, getFpsValueColor());
int baseYOffset = (fontMetrics.getAscent() - fontMetrics.getDescent()) + 1;
if (config.drawFps())
{
final String fpsText = String.format("%d FPS", client.getFPS());
final int textWidth = fontMetrics.stringWidth(fpsText);
final Point point = new Point(width - textWidth - offset, baseYOffset);
OverlayUtil.renderTextLocation(graphics, point, fpsText, getFpsValueColor());
baseYOffset += 11;
}
if (config.drawPing())
{
final String pingText = String.format("%dms", plugin.getPing());
final int textWidth = fontMetrics.stringWidth(pingText);
final Point point = new Point(width - textWidth - offset, baseYOffset);
OverlayUtil.renderTextLocation(graphics, point, pingText, getPingColor(plugin.getPing()));
}
return null; return null;
} }

View File

@@ -22,10 +22,16 @@
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/ */
package net.runelite.client.plugins.fps; package net.runelite.client.plugins.performance;
import com.google.inject.Inject; import com.google.inject.Inject;
import com.google.inject.Provides; import com.google.inject.Provides;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
import lombok.Getter;
import net.runelite.api.Client;
import net.runelite.api.GameState;
import net.runelite.api.events.ConfigChanged; import net.runelite.api.events.ConfigChanged;
import net.runelite.api.events.FocusChanged; import net.runelite.api.events.FocusChanged;
import net.runelite.client.config.ConfigManager; import net.runelite.client.config.ConfigManager;
@@ -34,9 +40,11 @@ import net.runelite.client.plugins.Plugin;
import net.runelite.client.plugins.PluginDescriptor; import net.runelite.client.plugins.PluginDescriptor;
import net.runelite.client.ui.DrawManager; import net.runelite.client.ui.DrawManager;
import net.runelite.client.ui.overlay.OverlayManager; import net.runelite.client.ui.overlay.OverlayManager;
import net.runelite.client.util.ExecutorServiceExceptionLogger;
import net.runelite.client.util.ping.Ping;
/** /**
* FPS Control has two primary areas, this plugin class just keeps those areas up to date and handles setup / teardown. * Performance has two primary areas, this plugin class just keeps those areas up to date and handles setup / teardown.
* *
* <p>Overlay paints the current FPS, the color depends on whether or not FPS is being enforced. * <p>Overlay paints the current FPS, the color depends on whether or not FPS is being enforced.
* The overlay is lightweight and is merely and indicator. * The overlay is lightweight and is merely and indicator.
@@ -44,22 +52,29 @@ import net.runelite.client.ui.overlay.OverlayManager;
* <p>Draw Listener, sleeps a calculated amount after each canvas paint operation. * <p>Draw Listener, sleeps a calculated amount after each canvas paint operation.
* This is the heart of the plugin, the amount of sleep taken is regularly adjusted to account varying * This is the heart of the plugin, the amount of sleep taken is regularly adjusted to account varying
* game and system load, it usually finds the sweet spot in about two seconds. * game and system load, it usually finds the sweet spot in about two seconds.
*
* <p>Pinging the world, when logged in and ping display is enabled, every 5 seconds the remote server
* for the current world is pinged. A scheduled method in this class is responsible for that. When ping fails
* or those conditions are not met, ping will have the value of -1.
*/ */
@PluginDescriptor( @PluginDescriptor(
name = "FPS Control", name = "Performance",
description = "Show current FPS and/or set an FPS limit", description = "Show current Ping and FPS or set an FPS limit",
tags = {"frames", "framerate", "limit", "overlay"}, tags = {"frames", "framerate", "limit", "overlay", "ping"},
enabledByDefault = false enabledByDefault = false
) )
public class FpsPlugin extends Plugin public class PerformancePlugin extends Plugin
{ {
static final String CONFIG_GROUP_KEY = "fpscontrol"; static final String CONFIG_GROUP_KEY = "fpscontrol";
@Getter
private int ping;
@Inject @Inject
private OverlayManager overlayManager; private OverlayManager overlayManager;
@Inject @Inject
private FpsOverlay overlay; private PerformanceOverlay overlay;
@Inject @Inject
private FpsDrawListener drawListener; private FpsDrawListener drawListener;
@@ -67,10 +82,18 @@ public class FpsPlugin extends Plugin
@Inject @Inject
private DrawManager drawManager; private DrawManager drawManager;
@Inject
private Client client;
@Inject
private PerformanceConfig performanceConfig;
private final ScheduledExecutorService pingExecutorService = new ExecutorServiceExceptionLogger(Executors.newSingleThreadScheduledExecutor());
@Provides @Provides
FpsConfig provideConfig(ConfigManager configManager) PerformanceConfig provideConfig(ConfigManager configManager)
{ {
return configManager.getConfig(FpsConfig.class); return configManager.getConfig(PerformanceConfig.class);
} }
@Subscribe @Subscribe
@@ -95,6 +118,7 @@ public class FpsPlugin extends Plugin
overlayManager.add(overlay); overlayManager.add(overlay);
drawManager.registerEveryFrameListener(drawListener); drawManager.registerEveryFrameListener(drawListener);
drawListener.reloadConfig(); drawListener.reloadConfig();
pingExecutorService.scheduleAtFixedRate(this::getPingToCurrentWorld, 5, 5, TimeUnit.SECONDS);
} }
@Override @Override
@@ -102,5 +126,18 @@ public class FpsPlugin extends Plugin
{ {
overlayManager.remove(overlay); overlayManager.remove(overlay);
drawManager.unregisterEveryFrameListener(drawListener); drawManager.unregisterEveryFrameListener(drawListener);
pingExecutorService.shutdown();
}
private void getPingToCurrentWorld()
{
if (client.getGameState().equals(GameState.LOGGED_IN) && performanceConfig.drawPing())
{
ping = Ping.ping(String.format("oldschool%d.runescape.com", client.getWorld() - 300));
}
else
{
ping = -1;
}
} }
} }

View File

@@ -75,7 +75,7 @@ import net.runelite.client.eventbus.Subscribe;
import net.runelite.client.input.KeyManager; import net.runelite.client.input.KeyManager;
import net.runelite.client.plugins.Plugin; import net.runelite.client.plugins.Plugin;
import net.runelite.client.plugins.PluginDescriptor; import net.runelite.client.plugins.PluginDescriptor;
import net.runelite.client.plugins.worldhopper.ping.Ping; import net.runelite.client.util.ping.Ping;
import net.runelite.client.ui.ClientToolbar; import net.runelite.client.ui.ClientToolbar;
import net.runelite.client.ui.NavigationButton; import net.runelite.client.ui.NavigationButton;
import net.runelite.client.util.ExecutorServiceExceptionLogger; import net.runelite.client.util.ExecutorServiceExceptionLogger;

View File

@@ -22,7 +22,7 @@
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/ */
package net.runelite.client.plugins.worldhopper.ping; package net.runelite.client.util.ping;
import com.sun.jna.Library; import com.sun.jna.Library;
import com.sun.jna.Native; import com.sun.jna.Native;

View File

@@ -22,7 +22,7 @@
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/ */
package net.runelite.client.plugins.worldhopper.ping; package net.runelite.client.util.ping;
import com.sun.jna.Pointer; import com.sun.jna.Pointer;
import com.sun.jna.Structure; import com.sun.jna.Structure;

View File

@@ -22,7 +22,7 @@
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/ */
package net.runelite.client.plugins.worldhopper.ping; package net.runelite.client.util.ping;
import com.sun.jna.Memory; import com.sun.jna.Memory;
import com.sun.jna.Pointer; import com.sun.jna.Pointer;
@@ -44,15 +44,20 @@ public class Ping
private static final int PORT = 43594; private static final int PORT = 43594;
public static int ping(World world) public static int ping(World world)
{
return ping(world.getAddress());
}
public static int ping(String address)
{ {
try try
{ {
switch (OSType.getOSType()) switch (OSType.getOSType())
{ {
case Windows: case Windows:
return windowsPing(world); return windowsPing(address);
default: default:
return tcpPing(world); return tcpPing(address);
} }
} }
catch (IOException ex) catch (IOException ex)
@@ -62,11 +67,11 @@ public class Ping
} }
} }
private static int windowsPing(World world) throws UnknownHostException private static int windowsPing(String worldAddress) throws UnknownHostException
{ {
IPHlpAPI ipHlpAPI = IPHlpAPI.INSTANCE; IPHlpAPI ipHlpAPI = IPHlpAPI.INSTANCE;
Pointer ptr = ipHlpAPI.IcmpCreateFile(); Pointer ptr = ipHlpAPI.IcmpCreateFile();
InetAddress inetAddress = InetAddress.getByName(world.getAddress()); InetAddress inetAddress = InetAddress.getByName(worldAddress);
byte[] address = inetAddress.getAddress(); byte[] address = inetAddress.getAddress();
String dataStr = RUNELITE_PING; String dataStr = RUNELITE_PING;
int dataLength = dataStr.length() + 1; int dataLength = dataStr.length() + 1;
@@ -88,12 +93,12 @@ public class Ping
return rtt; return rtt;
} }
private static int tcpPing(World world) throws IOException private static int tcpPing(String worldAddress) throws IOException
{ {
try (Socket socket = new Socket()) try (Socket socket = new Socket())
{ {
socket.setSoTimeout(TIMEOUT); socket.setSoTimeout(TIMEOUT);
InetAddress inetAddress = InetAddress.getByName(world.getAddress()); InetAddress inetAddress = InetAddress.getByName(worldAddress);
long start = System.nanoTime(); long start = System.nanoTime();
socket.connect(new InetSocketAddress(inetAddress, PORT)); socket.connect(new InetSocketAddress(inetAddress, PORT));
long end = System.nanoTime(); long end = System.nanoTime();