mirror of
https://github.com/PaperMC/Paper.git
synced 2024-12-30 16:19:03 +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
|
||||
+++ b/net/minecraft/server/gui/MinecraftServerGui.java
|
||||
@@ -96,7 +96,7 @@
|
||||
@@ -95,8 +95,8 @@
|
||||
|
||||
private JComponent buildInfoPanel() {
|
||||
JPanel jpanel = new JPanel(new BorderLayout());
|
||||
StatsComponent guistatscomponent = new StatsComponent(this.server);
|
||||
- StatsComponent guistatscomponent = new StatsComponent(this.server);
|
||||
- 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
|
||||
|
||||
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