mirror of
https://github.com/PaperMC/Paper.git
synced 2024-12-31 00:20:44 +01:00
Make the GUI graph fancier
This commit is contained in:
parent
196c153504
commit
fa7c667a3e
6 changed files with 366 additions and 2 deletions
|
@ -1,10 +1,12 @@
|
||||||
--- a/net/minecraft/server/gui/MinecraftServerGui.java
|
--- a/net/minecraft/server/gui/MinecraftServerGui.java
|
||||||
+++ b/net/minecraft/server/gui/MinecraftServerGui.java
|
+++ b/net/minecraft/server/gui/MinecraftServerGui.java
|
||||||
@@ -96,7 +96,7 @@
|
@@ -95,8 +95,8 @@
|
||||||
|
|
||||||
private JComponent buildInfoPanel() {
|
private JComponent buildInfoPanel() {
|
||||||
JPanel jpanel = new JPanel(new BorderLayout());
|
JPanel jpanel = new JPanel(new BorderLayout());
|
||||||
StatsComponent guistatscomponent = new StatsComponent(this.server);
|
- StatsComponent guistatscomponent = new StatsComponent(this.server);
|
||||||
- Collection collection = this.finalizers;
|
- Collection collection = this.finalizers;
|
||||||
|
+ com.destroystokyo.paper.gui.GuiStatsComponent guistatscomponent = new com.destroystokyo.paper.gui.GuiStatsComponent(this.server); // Paper - Make GUI graph fancier
|
||||||
+ Collection<Runnable> collection = this.finalizers; // CraftBukkit - decompile error
|
+ Collection<Runnable> collection = this.finalizers; // CraftBukkit - decompile error
|
||||||
|
|
||||||
Objects.requireNonNull(guistatscomponent);
|
Objects.requireNonNull(guistatscomponent);
|
||||||
|
|
|
@ -0,0 +1,44 @@
|
||||||
|
package com.destroystokyo.paper.gui;
|
||||||
|
|
||||||
|
import java.awt.Color;
|
||||||
|
|
||||||
|
public class GraphColor {
|
||||||
|
private static final Color[] colorLine = new Color[101];
|
||||||
|
private static final Color[] colorFill = new Color[101];
|
||||||
|
|
||||||
|
static {
|
||||||
|
for (int i = 0; i < 101; i++) {
|
||||||
|
Color color = createColor(i);
|
||||||
|
colorLine[i] = new Color(color.getRed() / 2, color.getGreen() / 2, color.getBlue() / 2, 255);
|
||||||
|
colorFill[i] = new Color(colorLine[i].getRed(), colorLine[i].getGreen(), colorLine[i].getBlue(), 125);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Color getLineColor(int percent) {
|
||||||
|
return colorLine[percent];
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Color getFillColor(int percent) {
|
||||||
|
return colorFill[percent];
|
||||||
|
}
|
||||||
|
|
||||||
|
private static Color createColor(int percent) {
|
||||||
|
if (percent <= 50) {
|
||||||
|
return new Color(0X00FF00);
|
||||||
|
}
|
||||||
|
|
||||||
|
int value = 510 - (int) (Math.min(Math.max(0, ((percent - 50) / 50F)), 1) * 510);
|
||||||
|
|
||||||
|
int red, green;
|
||||||
|
if (value < 255) {
|
||||||
|
red = 255;
|
||||||
|
green = (int) (Math.sqrt(value) * 16);
|
||||||
|
} else {
|
||||||
|
green = 255;
|
||||||
|
value = value - 255;
|
||||||
|
red = 255 - (value * value / 255);
|
||||||
|
}
|
||||||
|
|
||||||
|
return new Color(red, green, 0);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,47 @@
|
||||||
|
package com.destroystokyo.paper.gui;
|
||||||
|
|
||||||
|
import java.awt.Color;
|
||||||
|
|
||||||
|
public class GraphData {
|
||||||
|
private long total;
|
||||||
|
private long free;
|
||||||
|
private long max;
|
||||||
|
private long usedMem;
|
||||||
|
private int usedPercent;
|
||||||
|
|
||||||
|
public GraphData(long total, long free, long max) {
|
||||||
|
this.total = total;
|
||||||
|
this.free = free;
|
||||||
|
this.max = max;
|
||||||
|
this.usedMem = total - free;
|
||||||
|
this.usedPercent = usedMem == 0 ? 0 : (int) (usedMem * 100L / max);
|
||||||
|
}
|
||||||
|
|
||||||
|
public long getTotal() {
|
||||||
|
return total;
|
||||||
|
}
|
||||||
|
|
||||||
|
public long getFree() {
|
||||||
|
return free;
|
||||||
|
}
|
||||||
|
|
||||||
|
public long getMax() {
|
||||||
|
return max;
|
||||||
|
}
|
||||||
|
|
||||||
|
public long getUsedMem() {
|
||||||
|
return usedMem;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getUsedPercent() {
|
||||||
|
return usedPercent;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Color getFillColor() {
|
||||||
|
return GraphColor.getFillColor(usedPercent);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Color getLineColor() {
|
||||||
|
return GraphColor.getLineColor(usedPercent);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,41 @@
|
||||||
|
package com.destroystokyo.paper.gui;
|
||||||
|
|
||||||
|
import net.minecraft.server.MinecraftServer;
|
||||||
|
|
||||||
|
import javax.swing.JPanel;
|
||||||
|
import javax.swing.Timer;
|
||||||
|
import java.awt.BorderLayout;
|
||||||
|
import java.awt.Dimension;
|
||||||
|
|
||||||
|
public class GuiStatsComponent extends JPanel {
|
||||||
|
private final Timer timer;
|
||||||
|
private final RAMGraph ramGraph;
|
||||||
|
|
||||||
|
public GuiStatsComponent(MinecraftServer server) {
|
||||||
|
super(new BorderLayout());
|
||||||
|
|
||||||
|
setOpaque(false);
|
||||||
|
|
||||||
|
ramGraph = new RAMGraph();
|
||||||
|
RAMDetails ramDetails = new RAMDetails(server);
|
||||||
|
|
||||||
|
add(ramGraph, "North");
|
||||||
|
add(ramDetails, "Center");
|
||||||
|
|
||||||
|
timer = new Timer(500, (event) -> {
|
||||||
|
ramGraph.update();
|
||||||
|
ramDetails.update();
|
||||||
|
});
|
||||||
|
timer.start();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Dimension getPreferredSize() {
|
||||||
|
return new Dimension(350, 200);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void close() {
|
||||||
|
timer.stop();
|
||||||
|
ramGraph.stop();
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,74 @@
|
||||||
|
package com.destroystokyo.paper.gui;
|
||||||
|
|
||||||
|
import net.minecraft.Util;
|
||||||
|
import net.minecraft.server.MinecraftServer;
|
||||||
|
import net.minecraft.util.TimeUtil;
|
||||||
|
|
||||||
|
import javax.swing.DefaultListCellRenderer;
|
||||||
|
import javax.swing.DefaultListSelectionModel;
|
||||||
|
import javax.swing.JList;
|
||||||
|
import javax.swing.border.EmptyBorder;
|
||||||
|
import java.awt.Dimension;
|
||||||
|
import java.text.DecimalFormat;
|
||||||
|
import java.text.DecimalFormatSymbols;
|
||||||
|
import java.util.Locale;
|
||||||
|
import java.util.Vector;
|
||||||
|
|
||||||
|
public class RAMDetails extends JList<String> {
|
||||||
|
public static final DecimalFormat DECIMAL_FORMAT = Util.make(new DecimalFormat("########0.000"), (format)
|
||||||
|
-> format.setDecimalFormatSymbols(DecimalFormatSymbols.getInstance(Locale.ROOT)));
|
||||||
|
|
||||||
|
private final MinecraftServer server;
|
||||||
|
|
||||||
|
public RAMDetails(MinecraftServer server) {
|
||||||
|
this.server = server;
|
||||||
|
|
||||||
|
setBorder(new EmptyBorder(0, 10, 0, 0));
|
||||||
|
setFixedCellHeight(20);
|
||||||
|
setOpaque(false);
|
||||||
|
|
||||||
|
DefaultListCellRenderer renderer = new DefaultListCellRenderer();
|
||||||
|
renderer.setOpaque(false);
|
||||||
|
setCellRenderer(renderer);
|
||||||
|
|
||||||
|
setSelectionModel(new DefaultListSelectionModel() {
|
||||||
|
@Override
|
||||||
|
public void setAnchorSelectionIndex(final int anchorIndex) {
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setLeadAnchorNotificationEnabled(final boolean flag) {
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setLeadSelectionIndex(final int leadIndex) {
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setSelectionInterval(final int index0, final int index1) {
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Dimension getPreferredSize() {
|
||||||
|
return new Dimension(350, 100);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void update() {
|
||||||
|
GraphData data = RAMGraph.DATA.peekLast();
|
||||||
|
Vector<String> vector = new Vector<>();
|
||||||
|
vector.add("Memory use: " + (data.getUsedMem() / 1024L / 1024L) + " mb (" + (data.getFree() * 100L / data.getMax()) + "% free)");
|
||||||
|
vector.add("Heap: " + (data.getTotal() / 1024L / 1024L) + " / " + (data.getMax() / 1024L / 1024L) + " mb");
|
||||||
|
vector.add("Avg tick: " + DECIMAL_FORMAT.format((double)this.server.getAverageTickTimeNanos() / (double) TimeUtil.NANOSECONDS_PER_MILLISECOND) + " ms");
|
||||||
|
setListData(vector);
|
||||||
|
}
|
||||||
|
|
||||||
|
public double getAverage(long[] tickTimes) {
|
||||||
|
long total = 0L;
|
||||||
|
for (long value : tickTimes) {
|
||||||
|
total += value * 1000;
|
||||||
|
}
|
||||||
|
return ((double) total / (double) tickTimes.length) * 1.0E-6D;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,156 @@
|
||||||
|
package com.destroystokyo.paper.gui;
|
||||||
|
|
||||||
|
import javax.swing.JComponent;
|
||||||
|
import javax.swing.SwingUtilities;
|
||||||
|
import javax.swing.Timer;
|
||||||
|
import javax.swing.ToolTipManager;
|
||||||
|
import java.awt.Color;
|
||||||
|
import java.awt.Dimension;
|
||||||
|
import java.awt.Graphics;
|
||||||
|
import java.awt.MouseInfo;
|
||||||
|
import java.awt.Point;
|
||||||
|
import java.awt.PointerInfo;
|
||||||
|
import java.awt.event.MouseAdapter;
|
||||||
|
import java.awt.event.MouseEvent;
|
||||||
|
import java.text.SimpleDateFormat;
|
||||||
|
import java.util.Date;
|
||||||
|
import java.util.LinkedList;
|
||||||
|
import java.util.concurrent.TimeUnit;
|
||||||
|
|
||||||
|
public class RAMGraph extends JComponent {
|
||||||
|
public static final LinkedList<GraphData> DATA = new LinkedList<GraphData>() {
|
||||||
|
@Override
|
||||||
|
public boolean add(GraphData data) {
|
||||||
|
if (size() >= 348) {
|
||||||
|
remove();
|
||||||
|
}
|
||||||
|
return super.add(data);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
static {
|
||||||
|
GraphData empty = new GraphData(0, 0, 0);
|
||||||
|
for (int i = 0; i < 350; i++) {
|
||||||
|
DATA.add(empty);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private final Timer timer;
|
||||||
|
private final SimpleDateFormat TIME_FORMAT = new SimpleDateFormat("HH:mm:ss");
|
||||||
|
|
||||||
|
private int currentTick;
|
||||||
|
|
||||||
|
public RAMGraph() {
|
||||||
|
ToolTipManager.sharedInstance().setInitialDelay(0);
|
||||||
|
|
||||||
|
addMouseListener(new MouseAdapter() {
|
||||||
|
final int defaultDismissTimeout = ToolTipManager.sharedInstance().getDismissDelay();
|
||||||
|
final int dismissDelayMinutes = (int) TimeUnit.MINUTES.toMillis(10);
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void mouseEntered(MouseEvent me) {
|
||||||
|
ToolTipManager.sharedInstance().setDismissDelay(dismissDelayMinutes);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void mouseExited(MouseEvent me) {
|
||||||
|
ToolTipManager.sharedInstance().setDismissDelay(defaultDismissTimeout);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
timer = new Timer(50, (event) -> repaint());
|
||||||
|
timer.start();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Dimension getPreferredSize() {
|
||||||
|
return new Dimension(350, 110);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void update() {
|
||||||
|
Runtime jvm = Runtime.getRuntime();
|
||||||
|
DATA.add(new GraphData(jvm.totalMemory(), jvm.freeMemory(), jvm.maxMemory()));
|
||||||
|
|
||||||
|
PointerInfo pointerInfo = null;
|
||||||
|
// I think I recall spotting a bug report where this throwed an exception once
|
||||||
|
// not sure it's of concern here
|
||||||
|
try {
|
||||||
|
pointerInfo = MouseInfo.getPointerInfo();
|
||||||
|
} catch (NullPointerException | ArrayIndexOutOfBoundsException ignored) {
|
||||||
|
// https://bugs.openjdk.org/browse/JDK-6840067
|
||||||
|
}
|
||||||
|
if (pointerInfo != null) {
|
||||||
|
Point point = pointerInfo.getLocation();
|
||||||
|
if (point != null) {
|
||||||
|
Point loc = new Point(point);
|
||||||
|
SwingUtilities.convertPointFromScreen(loc, this);
|
||||||
|
if (this.contains(loc)) {
|
||||||
|
ToolTipManager.sharedInstance().mouseMoved(
|
||||||
|
new MouseEvent(this, -1, System.currentTimeMillis(), 0, loc.x, loc.y,
|
||||||
|
point.x, point.y, 0, false, 0));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
currentTick++;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void paint(Graphics graphics) {
|
||||||
|
graphics.setColor(new Color(0xFFFFFFFF));
|
||||||
|
graphics.fillRect(0, 0, 350, 100);
|
||||||
|
|
||||||
|
graphics.setColor(new Color(0x888888));
|
||||||
|
graphics.drawLine(1, 25, 348, 25);
|
||||||
|
graphics.drawLine(1, 50, 348, 50);
|
||||||
|
graphics.drawLine(1, 75, 348, 75);
|
||||||
|
|
||||||
|
int i = 0;
|
||||||
|
for (GraphData data : DATA) {
|
||||||
|
i++;
|
||||||
|
if ((i + currentTick) % 120 == 0) {
|
||||||
|
graphics.setColor(new Color(0x888888));
|
||||||
|
graphics.drawLine(i, 1, i, 99);
|
||||||
|
}
|
||||||
|
int used = data.getUsedPercent();
|
||||||
|
if (used > 0) {
|
||||||
|
Color color = data.getLineColor();
|
||||||
|
graphics.setColor(data.getFillColor());
|
||||||
|
graphics.fillRect(i, 100 - used, 1, used);
|
||||||
|
graphics.setColor(color);
|
||||||
|
graphics.fillRect(i, 100 - used, 1, 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
graphics.setColor(new Color(0xFF000000));
|
||||||
|
graphics.drawRect(0, 0, 348, 100);
|
||||||
|
|
||||||
|
Point m = null;
|
||||||
|
try {
|
||||||
|
m = getMousePosition();
|
||||||
|
} catch (NullPointerException ignored) {
|
||||||
|
// https://bugs.openjdk.org/browse/JDK-6840067
|
||||||
|
}
|
||||||
|
if (m != null && m.x > 0 && m.x < 348 && m.y > 0 && m.y < 100) {
|
||||||
|
GraphData data = DATA.get(m.x);
|
||||||
|
int used = data.getUsedPercent();
|
||||||
|
graphics.setColor(new Color(0x000000));
|
||||||
|
graphics.drawLine(m.x, 1, m.x, 99);
|
||||||
|
graphics.drawOval(m.x - 2, 100 - used - 2, 5, 5);
|
||||||
|
graphics.setColor(data.getLineColor());
|
||||||
|
graphics.fillOval(m.x - 2, 100 - used - 2, 5, 5);
|
||||||
|
setToolTipText(String.format("<html><body>Used: %s mb (%s%%)<br/>%s</body></html>",
|
||||||
|
Math.round(data.getUsedMem() / 1024F / 1024F),
|
||||||
|
used, getTime(m.x)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getTime(int halfSeconds) {
|
||||||
|
int millis = (348 - halfSeconds) / 2 * 1000;
|
||||||
|
return TIME_FORMAT.format(new Date((System.currentTimeMillis() - millis)));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void stop() {
|
||||||
|
timer.stop();
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in a new issue