* 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
* 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 net.runelite.api.events.FocusChanged;
@@ -44,7 +44,7 @@ public class FpsDrawListener implements Runnable
{
private static final int SAMPLE_SIZE = 4;
private final FpsConfig config;
private final PerformanceConfig config;
private long targetDelay = 0;
@@ -58,7 +58,7 @@ public class FpsDrawListener implements Runnable
private long sleepDelay = 0;
@Inject
private FpsDrawListener(FpsConfig config)
private FpsDrawListener(PerformanceConfig config)
{
this.config = config;
reloadConfig();

View File

@@ -22,7 +22,7 @@
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* 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.RequiredArgsConstructor;

View File

@@ -22,14 +22,14 @@
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* 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.ConfigGroup;
import net.runelite.client.config.ConfigItem;
@ConfigGroup(FpsPlugin.CONFIG_GROUP_KEY)
public interface FpsConfig extends Config
@ConfigGroup(PerformancePlugin.CONFIG_GROUP_KEY)
public interface PerformanceConfig extends Config
{
@ConfigItem(
keyName = "limitMode",
@@ -63,4 +63,15 @@ public interface FpsConfig extends Config
{
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
* 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.Dimension;
import java.awt.FontMetrics;
import java.awt.Graphics2D;
import javax.inject.Inject;
import net.runelite.api.Client;
import net.runelite.api.Point;
import net.runelite.api.Varbits;
import net.runelite.api.events.FocusChanged;
import net.runelite.client.ui.overlay.Overlay;
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),
* 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
private final FpsConfig config;
private final PerformanceConfig config;
private final Client client;
private final PerformancePlugin plugin;
// Often changing values
private boolean isFocused = true;
@Inject
private FpsOverlay(FpsConfig config, Client client)
private PerformanceOverlay(PerformancePlugin plugin, PerformanceConfig config, Client client)
{
this.config = config;
this.client = client;
this.plugin = plugin;
setLayer(OverlayLayer.ABOVE_WIDGETS);
setPriority(OverlayPriority.HIGH);
setPosition(OverlayPosition.DYNAMIC);
@@ -84,21 +84,62 @@ public class FpsOverlay extends Overlay
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
public Dimension render(Graphics2D graphics)
{
if (!config.drawFps())
if (!config.drawFps() && !config.drawPing())
{
return null;
}
final String text = client.getFPS() + FPS_STRING;
final int textWidth = graphics.getFontMetrics().stringWidth(text);
final int textHeight = graphics.getFontMetrics().getAscent() - graphics.getFontMetrics().getDescent();
final int offset = calculateOffset();
final int width = (int) client.getRealDimensions().getWidth();
final Point point = new Point(width - textWidth - VALUE_X_OFFSET, textHeight + Y_OFFSET);
OverlayUtil.renderTextLocation(graphics, point, text, getFpsValueColor());
final FontMetrics fontMetrics = graphics.getFontMetrics();
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;
}

View File

@@ -22,10 +22,16 @@
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* 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.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.FocusChanged;
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.ui.DrawManager;
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.
* 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.
* 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.
*
* <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(
name = "FPS Control",
description = "Show current FPS and/or set an FPS limit",
tags = {"frames", "framerate", "limit", "overlay"},
name = "Performance",
description = "Show current Ping and FPS or set an FPS limit",
tags = {"frames", "framerate", "limit", "overlay", "ping"},
enabledByDefault = false
)
public class FpsPlugin extends Plugin
public class PerformancePlugin extends Plugin
{
static final String CONFIG_GROUP_KEY = "fpscontrol";
@Getter
private int ping;
@Inject
private OverlayManager overlayManager;
@Inject
private FpsOverlay overlay;
private PerformanceOverlay overlay;
@Inject
private FpsDrawListener drawListener;
@@ -67,10 +82,18 @@ public class FpsPlugin extends Plugin
@Inject
private DrawManager drawManager;
@Inject
private Client client;
@Inject
private PerformanceConfig performanceConfig;
private final ScheduledExecutorService pingExecutorService = new ExecutorServiceExceptionLogger(Executors.newSingleThreadScheduledExecutor());
@Provides
FpsConfig provideConfig(ConfigManager configManager)
PerformanceConfig provideConfig(ConfigManager configManager)
{
return configManager.getConfig(FpsConfig.class);
return configManager.getConfig(PerformanceConfig.class);
}
@Subscribe
@@ -95,6 +118,7 @@ public class FpsPlugin extends Plugin
overlayManager.add(overlay);
drawManager.registerEveryFrameListener(drawListener);
drawListener.reloadConfig();
pingExecutorService.scheduleAtFixedRate(this::getPingToCurrentWorld, 5, 5, TimeUnit.SECONDS);
}
@Override
@@ -102,5 +126,18 @@ public class FpsPlugin extends Plugin
{
overlayManager.remove(overlay);
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.plugins.Plugin;
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.NavigationButton;
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
* 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.Native;

View File

@@ -22,7 +22,7 @@
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* 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.Structure;

View File

@@ -22,7 +22,7 @@
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* 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.Pointer;
@@ -44,15 +44,20 @@ public class Ping
private static final int PORT = 43594;
public static int ping(World world)
{
return ping(world.getAddress());
}
public static int ping(String address)
{
try
{
switch (OSType.getOSType())
{
case Windows:
return windowsPing(world);
return windowsPing(address);
default:
return tcpPing(world);
return tcpPing(address);
}
}
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;
Pointer ptr = ipHlpAPI.IcmpCreateFile();
InetAddress inetAddress = InetAddress.getByName(world.getAddress());
InetAddress inetAddress = InetAddress.getByName(worldAddress);
byte[] address = inetAddress.getAddress();
String dataStr = RUNELITE_PING;
int dataLength = dataStr.length() + 1;
@@ -88,12 +93,12 @@ public class Ping
return rtt;
}
private static int tcpPing(World world) throws IOException
private static int tcpPing(String worldAddress) throws IOException
{
try (Socket socket = new Socket())
{
socket.setSoTimeout(TIMEOUT);
InetAddress inetAddress = InetAddress.getByName(world.getAddress());
InetAddress inetAddress = InetAddress.getByName(worldAddress);
long start = System.nanoTime();
socket.connect(new InetSocketAddress(inetAddress, PORT));
long end = System.nanoTime();