mirror of
https://github.com/PurpurMC/Purpur.git
synced 2026-02-17 16:37:43 +01:00
Make the GUI better
This commit is contained in:
@@ -1,221 +0,0 @@
|
||||
From dc3dc7f0e53caf7b9e9936243c9f994b87b3d883 Mon Sep 17 00:00:00 2001
|
||||
From: William Blake Galbreath <Blake.Galbreath@GMail.com>
|
||||
Date: Thu, 16 Jan 2020 14:59:16 -0600
|
||||
Subject: [PATCH] Fix layout and add colors to the Server GUI
|
||||
|
||||
---
|
||||
.../java/net/minecraft/server/ServerGUI.java | 6 +-
|
||||
.../java/net/pl3x/purpur/swing/ColorPane.java | 129 ++++++++++++++++++
|
||||
.../java/org/bukkit/craftbukkit/Main.java | 1 +
|
||||
src/main/resources/log4j2.xml | 11 +-
|
||||
4 files changed, 144 insertions(+), 3 deletions(-)
|
||||
create mode 100644 src/main/java/net/pl3x/purpur/swing/ColorPane.java
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/server/ServerGUI.java b/src/main/java/net/minecraft/server/ServerGUI.java
|
||||
index 95561d9db..2ce99770b 100644
|
||||
--- a/src/main/java/net/minecraft/server/ServerGUI.java
|
||||
+++ b/src/main/java/net/minecraft/server/ServerGUI.java
|
||||
@@ -109,7 +109,7 @@ public class ServerGUI extends JComponent {
|
||||
|
||||
private JComponent e() {
|
||||
JPanel jpanel = new JPanel(new BorderLayout());
|
||||
- JTextArea jtextarea = new JTextArea();
|
||||
+ net.pl3x.purpur.swing.ColorPane jtextarea = new net.pl3x.purpur.swing.ColorPane(); // Purpur
|
||||
JScrollPane jscrollpane = new JScrollPane(jtextarea, 22, 30);
|
||||
|
||||
jtextarea.setEditable(false);
|
||||
@@ -160,7 +160,7 @@ public class ServerGUI extends JComponent {
|
||||
}
|
||||
|
||||
private static final java.util.regex.Pattern ANSI = java.util.regex.Pattern.compile("\\x1B\\[([0-9]{1,2}(;[0-9]{1,2})*)?[m|K]"); // CraftBukkit
|
||||
- public void a(JTextArea jtextarea, JScrollPane jscrollpane, String s) {
|
||||
+ public void a(net.pl3x.purpur.swing.ColorPane jtextarea, JScrollPane jscrollpane, String s) { // Purpur
|
||||
if (!SwingUtilities.isEventDispatchThread()) {
|
||||
SwingUtilities.invokeLater(() -> {
|
||||
this.a(jtextarea, jscrollpane, s);
|
||||
@@ -174,11 +174,13 @@ public class ServerGUI extends JComponent {
|
||||
flag = (double) jscrollbar.getValue() + jscrollbar.getSize().getHeight() + (double) (ServerGUI.a.getSize() * 4) > (double) jscrollbar.getMaximum();
|
||||
}
|
||||
|
||||
+ /* // Purpur
|
||||
try {
|
||||
document.insertString(document.getLength(), ANSI.matcher(s).replaceAll(""), (AttributeSet) null); // CraftBukkit
|
||||
} catch (BadLocationException badlocationexception) {
|
||||
;
|
||||
}
|
||||
+ */ jtextarea.appendANSI(s); // Purpur
|
||||
|
||||
if (flag) {
|
||||
jscrollbar.setValue(Integer.MAX_VALUE);
|
||||
diff --git a/src/main/java/net/pl3x/purpur/swing/ColorPane.java b/src/main/java/net/pl3x/purpur/swing/ColorPane.java
|
||||
new file mode 100644
|
||||
index 000000000..6f702ad4d
|
||||
--- /dev/null
|
||||
+++ b/src/main/java/net/pl3x/purpur/swing/ColorPane.java
|
||||
@@ -0,0 +1,129 @@
|
||||
+package net.pl3x.purpur.swing;
|
||||
+
|
||||
+import org.apache.commons.lang.StringEscapeUtils;
|
||||
+
|
||||
+import javax.swing.*;
|
||||
+import javax.swing.text.AttributeSet;
|
||||
+import javax.swing.text.BadLocationException;
|
||||
+import javax.swing.text.SimpleAttributeSet;
|
||||
+import javax.swing.text.StyleConstants;
|
||||
+import javax.swing.text.StyleContext;
|
||||
+import java.awt.*;
|
||||
+
|
||||
+/*
|
||||
+ * Class from: https://stackoverflow.com/a/6899478
|
||||
+ */
|
||||
+
|
||||
+public class ColorPane extends JTextPane {
|
||||
+ static final Color BLACK = Color.BLACK;
|
||||
+ static final Color RED = Color.RED;
|
||||
+ static final Color BLUE = Color.BLUE;
|
||||
+ static final Color MAGENTA = Color.MAGENTA;
|
||||
+ static final Color GREEN = Color.GREEN;
|
||||
+ static final Color YELLOW = Color.getHSBColor(0.15f, 1.0f, 1.0f);
|
||||
+ static final Color CYAN = Color.CYAN;
|
||||
+ static final Color WHITE = Color.LIGHT_GRAY;
|
||||
+
|
||||
+ static Color colorCurrent = BLACK;
|
||||
+ String remaining = "";
|
||||
+
|
||||
+ public void append(Color c, String s) {
|
||||
+ StyleContext sc = StyleContext.getDefaultStyleContext();
|
||||
+ AttributeSet aset = sc.addAttribute(SimpleAttributeSet.EMPTY, StyleConstants.Foreground, c);
|
||||
+ if (c != BLACK) {
|
||||
+ aset = sc.addAttribute(aset, StyleConstants.CharacterConstants.Bold, true);
|
||||
+ }
|
||||
+ int len = getDocument().getLength(); // same value as getText().length();
|
||||
+
|
||||
+ //setCaretPosition(len); // place caret at the end (with no selection)
|
||||
+ //setCharacterAttributes(aset, false);
|
||||
+ //replaceSelection(s); // there is no selection, so inserts at caret
|
||||
+
|
||||
+ try {
|
||||
+ getDocument().insertString(len, s, aset);
|
||||
+ } catch (BadLocationException e) {
|
||||
+ e.printStackTrace();
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ public void appendANSI(String s) { // convert ANSI color codes first
|
||||
+ int aPos = 0; // current char position in addString
|
||||
+ int aIndex = 0; // index of next Escape sequence
|
||||
+ int mIndex = 0; // index of "m" terminating Escape sequence
|
||||
+ String tmpString = "";
|
||||
+ boolean stillSearching = true; // true until no more Escape sequences
|
||||
+ String addString = remaining + s;
|
||||
+ remaining = "";
|
||||
+ colorCurrent = BLACK; // reset the colors
|
||||
+
|
||||
+ if (addString.length() > 0) {
|
||||
+ aIndex = addString.indexOf("\u001B"); // find first escape
|
||||
+ if (aIndex == -1) { // no escape/color change in this string, so just send it with current color
|
||||
+ append(colorCurrent, addString);
|
||||
+ return;
|
||||
+ }
|
||||
+ // otherwise There is an escape character in the string, so we must process it
|
||||
+
|
||||
+ if (aIndex > 0) { // Escape is not first char, so send text up to first escape
|
||||
+ tmpString = addString.substring(0, aIndex);
|
||||
+ append(colorCurrent, tmpString);
|
||||
+ aPos = aIndex;
|
||||
+ }
|
||||
+ // aPos is now at the beginning of the first escape sequence
|
||||
+
|
||||
+ stillSearching = true;
|
||||
+ while (stillSearching) {
|
||||
+ mIndex = addString.indexOf("m", aPos); // find the end of the escape sequence
|
||||
+ if (mIndex < 0) { // the buffer ends halfway through the ansi string!
|
||||
+ remaining = addString.substring(aPos, addString.length());
|
||||
+ stillSearching = false;
|
||||
+ continue;
|
||||
+ } else {
|
||||
+ tmpString = addString.substring(aPos, mIndex + 1);
|
||||
+ colorCurrent = getANSIColor(tmpString);
|
||||
+ }
|
||||
+ aPos = mIndex + 1;
|
||||
+ // now we have the color, send text that is in that color (up to next escape)
|
||||
+
|
||||
+ aIndex = addString.indexOf("\u001B", aPos);
|
||||
+
|
||||
+ if (aIndex == -1) { // if that was the last sequence of the input, send remaining text
|
||||
+ tmpString = addString.substring(aPos, addString.length());
|
||||
+ append(colorCurrent, tmpString);
|
||||
+ stillSearching = false;
|
||||
+ continue; // jump out of loop early, as the whole string has been sent now
|
||||
+ }
|
||||
+
|
||||
+ // there is another escape sequence, so send part of the string and prepare for the next
|
||||
+ tmpString = addString.substring(aPos, aIndex);
|
||||
+ aPos = aIndex;
|
||||
+ append(colorCurrent, tmpString);
|
||||
+
|
||||
+ } // while there's text in the input buffer
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ public Color getANSIColor(String ANSIColor) {
|
||||
+ if (ANSIColor.isEmpty()) {
|
||||
+ return BLACK;
|
||||
+ } else if (ANSIColor.contains("30")) {
|
||||
+ return BLACK;
|
||||
+ } else if (ANSIColor.contains("31")) {
|
||||
+ return RED;
|
||||
+ } else if (ANSIColor.contains("32")) {
|
||||
+ return GREEN;
|
||||
+ } else if (ANSIColor.contains("33")) {
|
||||
+ return YELLOW;
|
||||
+ } else if (ANSIColor.contains("34")) {
|
||||
+ return BLUE;
|
||||
+ } else if (ANSIColor.contains("35")) {
|
||||
+ return MAGENTA;
|
||||
+ } else if (ANSIColor.contains("36")) {
|
||||
+ return CYAN;
|
||||
+ } else if (ANSIColor.contains("37")) {
|
||||
+ return WHITE;
|
||||
+ } else {
|
||||
+ return BLACK;
|
||||
+ }
|
||||
+ }
|
||||
+}
|
||||
diff --git a/src/main/java/org/bukkit/craftbukkit/Main.java b/src/main/java/org/bukkit/craftbukkit/Main.java
|
||||
index 7e8b6cab7..f30bcbd48 100644
|
||||
--- a/src/main/java/org/bukkit/craftbukkit/Main.java
|
||||
+++ b/src/main/java/org/bukkit/craftbukkit/Main.java
|
||||
@@ -144,6 +144,7 @@ public class Main {
|
||||
.ofType(File.class)
|
||||
.defaultsTo(new File("purpur.yml"))
|
||||
.describedAs("Yml file");
|
||||
+ accepts("nogui", "Disables the graphical window");
|
||||
// Purpur end
|
||||
|
||||
// Paper start
|
||||
diff --git a/src/main/resources/log4j2.xml b/src/main/resources/log4j2.xml
|
||||
index 869bff4af..2a3e57c2f 100644
|
||||
--- a/src/main/resources/log4j2.xml
|
||||
+++ b/src/main/resources/log4j2.xml
|
||||
@@ -2,7 +2,16 @@
|
||||
<Configuration status="WARN" packages="com.mojang.util">
|
||||
<Appenders>
|
||||
<Queue name="ServerGuiConsole">
|
||||
- <PatternLayout pattern="[%d{HH:mm:ss} %level]: %msg%n" />
|
||||
+ <!-- Purpur start -->
|
||||
+ <PatternLayout>
|
||||
+ <LoggerNamePatternSelector defaultPattern="%highlightError{[%d{HH:mm:ss} %level]: [%logger] %minecraftFormatting{%msg}%n%xEx}">
|
||||
+ <!-- Log root, Minecraft, Mojang and Bukkit loggers without prefix -->
|
||||
+ <!-- Disable prefix for various plugins that bypass the plugin logger -->
|
||||
+ <PatternMatch key=",net.minecraft.,Minecraft,com.mojang.,com.sk89q.,ru.tehkode.,Minecraft.AWE"
|
||||
+ pattern="%highlightError{[%d{HH:mm:ss} %level]: %minecraftFormatting{%msg}%n%xEx}" />
|
||||
+ </LoggerNamePatternSelector>
|
||||
+ </PatternLayout>
|
||||
+ <!-- Purpur end -->
|
||||
</Queue>
|
||||
<Queue name="TerminalConsole">
|
||||
<PatternLayout pattern="[%d{HH:mm:ss}] [%t/%level]: %msg%n" />
|
||||
--
|
||||
2.24.0
|
||||
|
||||
819
patches/server/0087-Make-the-GUI-better.patch
Normal file
819
patches/server/0087-Make-the-GUI-better.patch
Normal file
@@ -0,0 +1,819 @@
|
||||
From ccac65fb797842f093e4f04c6750152a193afeaf Mon Sep 17 00:00:00 2001
|
||||
From: William Blake Galbreath <Blake.Galbreath@GMail.com>
|
||||
Date: Thu, 16 Jan 2020 14:59:16 -0600
|
||||
Subject: [PATCH] Make the GUI better
|
||||
|
||||
---
|
||||
.../net/minecraft/server/DedicatedServer.java | 6 +-
|
||||
.../net/minecraft/server/MinecraftServer.java | 3 +-
|
||||
.../java/net/pl3x/purpur/gui/ColorPane.java | 126 ++++++++++++
|
||||
.../net/pl3x/purpur/gui/ConsolePanel.java | 128 +++++++++++++
|
||||
.../pl3x/purpur/gui/PlayerListComponent.java | 27 +++
|
||||
.../java/net/pl3x/purpur/gui/ServerGUI.java | 121 ++++++++++++
|
||||
.../net/pl3x/purpur/gui/info/RAMDetails.java | 52 +++++
|
||||
.../net/pl3x/purpur/gui/info/RAMGraph.java | 179 ++++++++++++++++++
|
||||
.../pl3x/purpur/gui/info/ServerInfoPanel.java | 42 ++++
|
||||
src/main/resources/log4j2.xml | 11 +-
|
||||
10 files changed, 690 insertions(+), 5 deletions(-)
|
||||
create mode 100644 src/main/java/net/pl3x/purpur/gui/ColorPane.java
|
||||
create mode 100644 src/main/java/net/pl3x/purpur/gui/ConsolePanel.java
|
||||
create mode 100644 src/main/java/net/pl3x/purpur/gui/PlayerListComponent.java
|
||||
create mode 100644 src/main/java/net/pl3x/purpur/gui/ServerGUI.java
|
||||
create mode 100644 src/main/java/net/pl3x/purpur/gui/info/RAMDetails.java
|
||||
create mode 100644 src/main/java/net/pl3x/purpur/gui/info/RAMGraph.java
|
||||
create mode 100644 src/main/java/net/pl3x/purpur/gui/info/ServerInfoPanel.java
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/server/DedicatedServer.java b/src/main/java/net/minecraft/server/DedicatedServer.java
|
||||
index 8b5f4cab0..aec6040c8 100644
|
||||
--- a/src/main/java/net/minecraft/server/DedicatedServer.java
|
||||
+++ b/src/main/java/net/minecraft/server/DedicatedServer.java
|
||||
@@ -51,7 +51,7 @@ public class DedicatedServer extends MinecraftServer implements IMinecraftServer
|
||||
public DedicatedServerSettings propertyManager;
|
||||
private EnumGamemode o;
|
||||
@Nullable
|
||||
- private ServerGUI p;
|
||||
+ private net.pl3x.purpur.gui.ServerGUI p; // Purpur
|
||||
|
||||
// CraftBukkit start - Signature changed
|
||||
public DedicatedServer(joptsimple.OptionSet options, DedicatedServerSettings dedicatedserversettings, DataFixer datafixer, YggdrasilAuthenticationService yggdrasilauthenticationservice, MinecraftSessionService minecraftsessionservice, GameProfileRepository gameprofilerepository, UserCache usercache, WorldLoadListenerFactory worldloadlistenerfactory, String s) {
|
||||
@@ -413,7 +413,7 @@ public class DedicatedServer extends MinecraftServer implements IMinecraftServer
|
||||
@Override
|
||||
public void exit() {
|
||||
if (this.p != null) {
|
||||
- this.p.b();
|
||||
+ this.p.close(); // Purpur
|
||||
}
|
||||
|
||||
if (this.remoteControlListener != null) {
|
||||
@@ -512,7 +512,7 @@ public class DedicatedServer extends MinecraftServer implements IMinecraftServer
|
||||
|
||||
public void bc() {
|
||||
if (this.p == null) {
|
||||
- this.p = ServerGUI.a(this);
|
||||
+ this.p = net.pl3x.purpur.gui.ServerGUI.create(this); // Purpur
|
||||
}
|
||||
|
||||
}
|
||||
diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java
|
||||
index 9d5ef40a0..105ac8a04 100644
|
||||
--- a/src/main/java/net/minecraft/server/MinecraftServer.java
|
||||
+++ b/src/main/java/net/minecraft/server/MinecraftServer.java
|
||||
@@ -105,7 +105,7 @@ public abstract class MinecraftServer extends IAsyncTaskHandlerReentrant<TickTas
|
||||
private String motd;
|
||||
private int G;
|
||||
private int H;
|
||||
- public final long[] f = new long[100];
|
||||
+ public final long[] f = new long[100]; public long[] getTickTimes() { return f; } // Purpur
|
||||
@Nullable
|
||||
private KeyPair I;
|
||||
@Nullable
|
||||
@@ -1298,6 +1298,7 @@ public abstract class MinecraftServer extends IAsyncTaskHandlerReentrant<TickTas
|
||||
return true;
|
||||
}
|
||||
|
||||
+ public void addTickable(Runnable tickable) { b(tickable); } // Purpur - OBFHELPER
|
||||
public void b(Runnable runnable) {
|
||||
this.tickables.add(runnable);
|
||||
}
|
||||
diff --git a/src/main/java/net/pl3x/purpur/gui/ColorPane.java b/src/main/java/net/pl3x/purpur/gui/ColorPane.java
|
||||
new file mode 100644
|
||||
index 000000000..d5d5766e1
|
||||
--- /dev/null
|
||||
+++ b/src/main/java/net/pl3x/purpur/gui/ColorPane.java
|
||||
@@ -0,0 +1,126 @@
|
||||
+package net.pl3x.purpur.gui;
|
||||
+
|
||||
+import javax.swing.JTextPane;
|
||||
+import javax.swing.text.AttributeSet;
|
||||
+import javax.swing.text.BadLocationException;
|
||||
+import javax.swing.text.SimpleAttributeSet;
|
||||
+import javax.swing.text.StyleConstants;
|
||||
+import javax.swing.text.StyleContext;
|
||||
+import java.awt.Color;
|
||||
+
|
||||
+/*
|
||||
+ * Class from: https://stackoverflow.com/a/6899478
|
||||
+ */
|
||||
+
|
||||
+public class ColorPane extends JTextPane {
|
||||
+ private static final Color BLACK = Color.BLACK;
|
||||
+ private static final Color RED = Color.RED;
|
||||
+ private static final Color BLUE = Color.BLUE;
|
||||
+ private static final Color MAGENTA = Color.MAGENTA;
|
||||
+ private static final Color GREEN = Color.GREEN;
|
||||
+ private static final Color YELLOW = Color.getHSBColor(0.15f, 1.0f, 1.0f);
|
||||
+ private static final Color CYAN = Color.CYAN;
|
||||
+ private static final Color WHITE = Color.LIGHT_GRAY;
|
||||
+
|
||||
+ private String remaining = "";
|
||||
+
|
||||
+ public void append(Color c, String s) {
|
||||
+ StyleContext sc = StyleContext.getDefaultStyleContext();
|
||||
+ AttributeSet aset = sc.addAttribute(SimpleAttributeSet.EMPTY, StyleConstants.Foreground, c);
|
||||
+ if (c != BLACK) {
|
||||
+ aset = sc.addAttribute(aset, StyleConstants.CharacterConstants.Bold, true);
|
||||
+ }
|
||||
+ int len = getDocument().getLength(); // same value as getText().length();
|
||||
+
|
||||
+ //setCaretPosition(len); // place caret at the end (with no selection)
|
||||
+ //setCharacterAttributes(aset, false);
|
||||
+ //replaceSelection(s); // there is no selection, so inserts at caret
|
||||
+
|
||||
+ try {
|
||||
+ getDocument().insertString(len, s, aset);
|
||||
+ } catch (BadLocationException e) {
|
||||
+ e.printStackTrace();
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ public void appendANSI(String s) { // convert ANSI color codes first
|
||||
+ int aPos = 0; // current char position in addString
|
||||
+ int aIndex; // index of next Escape sequence
|
||||
+ int mIndex; // index of "m" terminating Escape sequence
|
||||
+ String tmpString;
|
||||
+ boolean stillSearching; // true until no more Escape sequences
|
||||
+ String addString = remaining + s;
|
||||
+ remaining = "";
|
||||
+ Color colorCurrent = BLACK; // reset the colors
|
||||
+
|
||||
+ if (addString.length() > 0) {
|
||||
+ aIndex = addString.indexOf("\u001B"); // find first escape
|
||||
+ if (aIndex == -1) { // no escape/color change in this string, so just send it with current color
|
||||
+ append(colorCurrent, addString);
|
||||
+ return;
|
||||
+ }
|
||||
+ // otherwise There is an escape character in the string, so we must process it
|
||||
+
|
||||
+ if (aIndex > 0) { // Escape is not first char, so send text up to first escape
|
||||
+ tmpString = addString.substring(0, aIndex);
|
||||
+ append(colorCurrent, tmpString);
|
||||
+ aPos = aIndex;
|
||||
+ }
|
||||
+ // aPos is now at the beginning of the first escape sequence
|
||||
+
|
||||
+ stillSearching = true;
|
||||
+ while (stillSearching) {
|
||||
+ mIndex = addString.indexOf("m", aPos); // find the end of the escape sequence
|
||||
+ if (mIndex < 0) { // the buffer ends halfway through the ansi string!
|
||||
+ remaining = addString.substring(aPos);
|
||||
+ stillSearching = false;
|
||||
+ continue;
|
||||
+ } else {
|
||||
+ tmpString = addString.substring(aPos, mIndex + 1);
|
||||
+ colorCurrent = getANSIColor(tmpString);
|
||||
+ }
|
||||
+ aPos = mIndex + 1;
|
||||
+ // now we have the color, send text that is in that color (up to next escape)
|
||||
+
|
||||
+ aIndex = addString.indexOf("\u001B", aPos);
|
||||
+
|
||||
+ if (aIndex == -1) { // if that was the last sequence of the input, send remaining text
|
||||
+ tmpString = addString.substring(aPos);
|
||||
+ append(colorCurrent, tmpString);
|
||||
+ stillSearching = false;
|
||||
+ continue; // jump out of loop early, as the whole string has been sent now
|
||||
+ }
|
||||
+
|
||||
+ // there is another escape sequence, so send part of the string and prepare for the next
|
||||
+ tmpString = addString.substring(aPos, aIndex);
|
||||
+ aPos = aIndex;
|
||||
+ append(colorCurrent, tmpString);
|
||||
+
|
||||
+ } // while there's text in the input buffer
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ private Color getANSIColor(String ANSIColor) {
|
||||
+ if (ANSIColor.isEmpty()) {
|
||||
+ return BLACK;
|
||||
+ } else if (ANSIColor.contains("30")) {
|
||||
+ return BLACK;
|
||||
+ } else if (ANSIColor.contains("31")) {
|
||||
+ return RED;
|
||||
+ } else if (ANSIColor.contains("32")) {
|
||||
+ return GREEN;
|
||||
+ } else if (ANSIColor.contains("33")) {
|
||||
+ return YELLOW;
|
||||
+ } else if (ANSIColor.contains("34")) {
|
||||
+ return BLUE;
|
||||
+ } else if (ANSIColor.contains("35")) {
|
||||
+ return MAGENTA;
|
||||
+ } else if (ANSIColor.contains("36")) {
|
||||
+ return CYAN;
|
||||
+ } else if (ANSIColor.contains("37")) {
|
||||
+ return WHITE;
|
||||
+ } else {
|
||||
+ return BLACK;
|
||||
+ }
|
||||
+ }
|
||||
+}
|
||||
diff --git a/src/main/java/net/pl3x/purpur/gui/ConsolePanel.java b/src/main/java/net/pl3x/purpur/gui/ConsolePanel.java
|
||||
new file mode 100644
|
||||
index 000000000..a728f46e6
|
||||
--- /dev/null
|
||||
+++ b/src/main/java/net/pl3x/purpur/gui/ConsolePanel.java
|
||||
@@ -0,0 +1,128 @@
|
||||
+package net.pl3x.purpur.gui;
|
||||
+
|
||||
+import com.mojang.util.QueueLogAppender;
|
||||
+import net.minecraft.server.DedicatedServer;
|
||||
+import net.minecraft.server.DefaultUncaughtExceptionHandler;
|
||||
+import org.apache.logging.log4j.LogManager;
|
||||
+import org.apache.logging.log4j.Logger;
|
||||
+
|
||||
+import javax.swing.AbstractAction;
|
||||
+import javax.swing.JPanel;
|
||||
+import javax.swing.JScrollBar;
|
||||
+import javax.swing.JScrollPane;
|
||||
+import javax.swing.JTextField;
|
||||
+import javax.swing.KeyStroke;
|
||||
+import javax.swing.ScrollPaneConstants;
|
||||
+import javax.swing.SwingUtilities;
|
||||
+import javax.swing.border.EtchedBorder;
|
||||
+import javax.swing.border.TitledBorder;
|
||||
+import java.awt.BorderLayout;
|
||||
+import java.awt.Font;
|
||||
+import java.awt.event.ActionEvent;
|
||||
+import java.util.LinkedList;
|
||||
+
|
||||
+public class ConsolePanel extends JPanel {
|
||||
+ private static final Font MONOSPACED = new Font("Monospaced", Font.PLAIN, 12);
|
||||
+ private static final Logger LOGGER = LogManager.getLogger();
|
||||
+
|
||||
+ private final CommandHistory history = new CommandHistory();
|
||||
+ private String currentCommand = "";
|
||||
+ private int historyIndex = 0;
|
||||
+
|
||||
+ private Thread logAppenderThread;
|
||||
+
|
||||
+ ConsolePanel(DedicatedServer server) {
|
||||
+ super(new BorderLayout());
|
||||
+
|
||||
+ ColorPane console = new ColorPane();
|
||||
+ console.setEditable(false);
|
||||
+ console.setFont(MONOSPACED);
|
||||
+
|
||||
+ JTextField jtextfield = new JTextField();
|
||||
+ jtextfield.addActionListener((actionevent) -> {
|
||||
+ String msg = jtextfield.getText().trim();
|
||||
+ if (!msg.isEmpty()) {
|
||||
+ server.issueCommand(msg, server.getServerCommandListener());
|
||||
+ history.add(msg);
|
||||
+ historyIndex = -1;
|
||||
+ }
|
||||
+ jtextfield.setText("");
|
||||
+ });
|
||||
+ jtextfield.getInputMap().put(KeyStroke.getKeyStroke("UP"), "up");
|
||||
+ jtextfield.getInputMap().put(KeyStroke.getKeyStroke("DOWN"), "down");
|
||||
+ jtextfield.getActionMap().put("up", new AbstractAction() {
|
||||
+ @Override
|
||||
+ public void actionPerformed(ActionEvent actionEvent) {
|
||||
+ if (historyIndex < 0) {
|
||||
+ currentCommand = jtextfield.getText();
|
||||
+ }
|
||||
+ if (historyIndex < history.size() - 1) {
|
||||
+ jtextfield.setText(history.get(++historyIndex));
|
||||
+ }
|
||||
+ }
|
||||
+ });
|
||||
+ jtextfield.getActionMap().put("down", new AbstractAction() {
|
||||
+ @Override
|
||||
+ public void actionPerformed(ActionEvent actionEvent) {
|
||||
+ if (historyIndex >= 0) {
|
||||
+ if (historyIndex == 0) {
|
||||
+ --historyIndex;
|
||||
+ jtextfield.setText(currentCommand);
|
||||
+ } else {
|
||||
+ --historyIndex;
|
||||
+ jtextfield.setText(history.get(historyIndex));
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+ });
|
||||
+
|
||||
+ JScrollPane jscrollpane = new JScrollPane(console, ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS, ScrollPaneConstants.HORIZONTAL_SCROLLBAR_AS_NEEDED);
|
||||
+
|
||||
+ add(jscrollpane, "Center");
|
||||
+ add(jtextfield, "South");
|
||||
+ setBorder(new TitledBorder(new EtchedBorder(), "Console"));
|
||||
+
|
||||
+ logAppenderThread = new Thread(() -> {
|
||||
+ String msg;
|
||||
+ while ((msg = QueueLogAppender.getNextLogEvent("ServerGuiConsole")) != null) {
|
||||
+ this.print(console, jscrollpane, msg);
|
||||
+ }
|
||||
+
|
||||
+ });
|
||||
+ logAppenderThread.setUncaughtExceptionHandler(new DefaultUncaughtExceptionHandler(LOGGER));
|
||||
+ logAppenderThread.setDaemon(true);
|
||||
+ }
|
||||
+
|
||||
+ public void start() {
|
||||
+ logAppenderThread.start();
|
||||
+ }
|
||||
+
|
||||
+ private void print(ColorPane console, JScrollPane jscrollpane, String s) {
|
||||
+ if (!SwingUtilities.isEventDispatchThread()) {
|
||||
+ SwingUtilities.invokeLater(() -> print(console, jscrollpane, s));
|
||||
+ } else {
|
||||
+ JScrollBar jscrollbar = jscrollpane.getVerticalScrollBar();
|
||||
+ boolean scrollToBottom = false;
|
||||
+
|
||||
+ if (jscrollpane.getViewport().getView() == console) {
|
||||
+ scrollToBottom = (double) jscrollbar.getValue() + jscrollbar.getSize().getHeight() + (double) (MONOSPACED.getSize() * 4) > (double) jscrollbar.getMaximum();
|
||||
+ }
|
||||
+
|
||||
+ console.appendANSI(s);
|
||||
+
|
||||
+ if (scrollToBottom) {
|
||||
+ jscrollbar.setValue(Integer.MAX_VALUE);
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ public static class CommandHistory extends LinkedList<String> {
|
||||
+ @Override
|
||||
+ public boolean add(String command) {
|
||||
+ if (size() > 1000) {
|
||||
+ remove();
|
||||
+ }
|
||||
+ return super.offerFirst(command);
|
||||
+ }
|
||||
+ }
|
||||
+}
|
||||
diff --git a/src/main/java/net/pl3x/purpur/gui/PlayerListComponent.java b/src/main/java/net/pl3x/purpur/gui/PlayerListComponent.java
|
||||
new file mode 100644
|
||||
index 000000000..c97a6f7dc
|
||||
--- /dev/null
|
||||
+++ b/src/main/java/net/pl3x/purpur/gui/PlayerListComponent.java
|
||||
@@ -0,0 +1,27 @@
|
||||
+package net.pl3x.purpur.gui;
|
||||
+
|
||||
+import net.minecraft.server.EntityPlayer;
|
||||
+import net.minecraft.server.MinecraftServer;
|
||||
+
|
||||
+import javax.swing.JList;
|
||||
+import java.util.Vector;
|
||||
+
|
||||
+public class PlayerListComponent extends JList<String> {
|
||||
+ private final MinecraftServer server;
|
||||
+ private int tickCount;
|
||||
+
|
||||
+ PlayerListComponent(MinecraftServer server) {
|
||||
+ this.server = server;
|
||||
+ server.addTickable(this::tick);
|
||||
+ }
|
||||
+
|
||||
+ public void tick() {
|
||||
+ if (tickCount++ % 20 == 0) {
|
||||
+ Vector<String> vector = new Vector<>();
|
||||
+ for (EntityPlayer player : server.getPlayerList().getPlayers()) {
|
||||
+ vector.add(player.getProfile().getName());
|
||||
+ }
|
||||
+ setListData(vector);
|
||||
+ }
|
||||
+ }
|
||||
+}
|
||||
diff --git a/src/main/java/net/pl3x/purpur/gui/ServerGUI.java b/src/main/java/net/pl3x/purpur/gui/ServerGUI.java
|
||||
new file mode 100644
|
||||
index 000000000..a779fea68
|
||||
--- /dev/null
|
||||
+++ b/src/main/java/net/pl3x/purpur/gui/ServerGUI.java
|
||||
@@ -0,0 +1,121 @@
|
||||
+package net.pl3x.purpur.gui;
|
||||
+
|
||||
+import com.google.common.collect.Lists;
|
||||
+import net.minecraft.server.DedicatedServer;
|
||||
+import net.pl3x.purpur.gui.info.ServerInfoPanel;
|
||||
+import org.apache.logging.log4j.LogManager;
|
||||
+import org.apache.logging.log4j.Logger;
|
||||
+
|
||||
+import javax.swing.JComponent;
|
||||
+import javax.swing.JFrame;
|
||||
+import javax.swing.JPanel;
|
||||
+import javax.swing.JScrollPane;
|
||||
+import javax.swing.ScrollPaneConstants;
|
||||
+import javax.swing.UIManager;
|
||||
+import javax.swing.WindowConstants;
|
||||
+import javax.swing.border.EtchedBorder;
|
||||
+import javax.swing.border.TitledBorder;
|
||||
+import java.awt.BorderLayout;
|
||||
+import java.awt.Dimension;
|
||||
+import java.awt.event.WindowAdapter;
|
||||
+import java.awt.event.WindowEvent;
|
||||
+import java.util.Collection;
|
||||
+import java.util.concurrent.atomic.AtomicBoolean;
|
||||
+
|
||||
+public class ServerGUI extends JComponent {
|
||||
+ private static final Logger LOGGER = LogManager.getLogger();
|
||||
+
|
||||
+ private final DedicatedServer server;
|
||||
+
|
||||
+ private final Collection<Runnable> finalizers = Lists.newArrayList();
|
||||
+ private final AtomicBoolean isClosing = new AtomicBoolean();
|
||||
+
|
||||
+ private ConsolePanel consolePanel;
|
||||
+
|
||||
+ public static ServerGUI create(final DedicatedServer dedicatedserver) {
|
||||
+ try {
|
||||
+ UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
|
||||
+ } catch (Exception ignore) {
|
||||
+ }
|
||||
+
|
||||
+ JFrame window = new JFrame("Purpur Minecraft Server");
|
||||
+ ServerGUI serverGUI = new ServerGUI(dedicatedserver);
|
||||
+
|
||||
+ window.setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE);
|
||||
+ window.add(serverGUI);
|
||||
+ window.pack();
|
||||
+ window.setLocationRelativeTo(null);
|
||||
+ window.setVisible(true);
|
||||
+
|
||||
+ window.addWindowListener(new WindowAdapter() {
|
||||
+ @Override
|
||||
+ public void windowClosing(WindowEvent windowevent) {
|
||||
+ if (!serverGUI.isClosing.getAndSet(true)) {
|
||||
+ window.setTitle("Purpur Minecraft Server - Shutting Down!");
|
||||
+ dedicatedserver.safeShutdown(true);
|
||||
+ serverGUI.runFinalizers();
|
||||
+ }
|
||||
+
|
||||
+ }
|
||||
+ });
|
||||
+
|
||||
+ serverGUI.addFinalizer(window::dispose);
|
||||
+ serverGUI.start();
|
||||
+
|
||||
+ return serverGUI;
|
||||
+ }
|
||||
+
|
||||
+ private ServerGUI(DedicatedServer dedicatedserver) {
|
||||
+ this.server = dedicatedserver;
|
||||
+
|
||||
+ setPreferredSize(new Dimension(854, 480));
|
||||
+ setLayout(new BorderLayout());
|
||||
+
|
||||
+ consolePanel = new ConsolePanel(server);
|
||||
+
|
||||
+ try {
|
||||
+ add(consolePanel, "Center");
|
||||
+ add(buildInfoPanel(), "West");
|
||||
+ } catch (Exception exception) {
|
||||
+ LOGGER.error("Couldn't build server GUI", exception);
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ private void addFinalizer(Runnable runnable) {
|
||||
+ finalizers.add(runnable);
|
||||
+ }
|
||||
+
|
||||
+ private JComponent buildInfoPanel() {
|
||||
+ JPanel jpanel = new JPanel(new BorderLayout());
|
||||
+
|
||||
+ ServerInfoPanel serverInfo = new ServerInfoPanel(server);
|
||||
+ finalizers.add(serverInfo::stop);
|
||||
+
|
||||
+ jpanel.add(serverInfo, "North");
|
||||
+ jpanel.add(buildPlayerPanel(), "Center");
|
||||
+
|
||||
+ jpanel.setBorder(new TitledBorder(new EtchedBorder(), "Stats"));
|
||||
+ return jpanel;
|
||||
+ }
|
||||
+
|
||||
+ private JComponent buildPlayerPanel() {
|
||||
+ JScrollPane jscrollpane = new JScrollPane(new PlayerListComponent(server), ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS, ScrollPaneConstants.HORIZONTAL_SCROLLBAR_AS_NEEDED);
|
||||
+ jscrollpane.setBorder(new TitledBorder(new EtchedBorder(), "Players"));
|
||||
+ return jscrollpane;
|
||||
+ }
|
||||
+
|
||||
+ public void start() {
|
||||
+ consolePanel.start();
|
||||
+ }
|
||||
+
|
||||
+ public void close() {
|
||||
+ if (!isClosing.getAndSet(true)) {
|
||||
+ runFinalizers();
|
||||
+ }
|
||||
+
|
||||
+ }
|
||||
+
|
||||
+ private void runFinalizers() {
|
||||
+ finalizers.forEach(Runnable::run);
|
||||
+ }
|
||||
+}
|
||||
diff --git a/src/main/java/net/pl3x/purpur/gui/info/RAMDetails.java b/src/main/java/net/pl3x/purpur/gui/info/RAMDetails.java
|
||||
new file mode 100644
|
||||
index 000000000..b1ea91b49
|
||||
--- /dev/null
|
||||
+++ b/src/main/java/net/pl3x/purpur/gui/info/RAMDetails.java
|
||||
@@ -0,0 +1,52 @@
|
||||
+package net.pl3x.purpur.gui.info;
|
||||
+
|
||||
+import net.minecraft.server.MinecraftServer;
|
||||
+import net.minecraft.server.SystemUtils;
|
||||
+
|
||||
+import javax.swing.DefaultListCellRenderer;
|
||||
+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> {
|
||||
+ private static final DecimalFormat DECIMAL_FORMAT = SystemUtils.a(new DecimalFormat("########0.000"), (format)
|
||||
+ -> format.setDecimalFormatSymbols(DecimalFormatSymbols.getInstance(Locale.ROOT)));
|
||||
+ private final MinecraftServer server;
|
||||
+
|
||||
+ 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);
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public Dimension getPreferredSize() {
|
||||
+ return new Dimension(350, 100);
|
||||
+ }
|
||||
+
|
||||
+ public void update(RAMGraph graph) {
|
||||
+ Vector<String> vector = new Vector<>();
|
||||
+ vector.add("Memory use: " + (graph.usedMem / 1024L / 1024L) + " mb (" + (graph.free * 100L / graph.max) + "% free)");
|
||||
+ vector.add("Heap: " + (graph.total / 1024L / 1024L) + " / " + (graph.max / 1024L / 1024L) + " mb");
|
||||
+ vector.add("Avg tick: " + DECIMAL_FORMAT.format(getAverage(server.getTickTimes()) * 1.0E-6D) + " ms");
|
||||
+ setListData(vector);
|
||||
+ }
|
||||
+
|
||||
+ private double getAverage(long[] values) {
|
||||
+ long total = 0L;
|
||||
+ for (long value : values) {
|
||||
+ total += value;
|
||||
+ }
|
||||
+ return (double) total / (double) values.length;
|
||||
+ }
|
||||
+}
|
||||
diff --git a/src/main/java/net/pl3x/purpur/gui/info/RAMGraph.java b/src/main/java/net/pl3x/purpur/gui/info/RAMGraph.java
|
||||
new file mode 100644
|
||||
index 000000000..7623088ba
|
||||
--- /dev/null
|
||||
+++ b/src/main/java/net/pl3x/purpur/gui/info/RAMGraph.java
|
||||
@@ -0,0 +1,179 @@
|
||||
+package net.pl3x.purpur.gui.info;
|
||||
+
|
||||
+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.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 {
|
||||
+ private final Timer timer;
|
||||
+
|
||||
+ private final SimpleDateFormat sdf = new SimpleDateFormat("HH:mm:ss");
|
||||
+
|
||||
+ private final Color[] colors = new Color[101];
|
||||
+ private final Color[] colorsAlpha = new Color[101];
|
||||
+
|
||||
+ private final RAMQueue<Long> usedMemQueue = new RAMQueue<>();
|
||||
+ private final RAMQueue<Integer> usedPercentQueue = new RAMQueue<>();
|
||||
+
|
||||
+ private int currentTick;
|
||||
+
|
||||
+ protected long total;
|
||||
+ protected long free;
|
||||
+ protected long max;
|
||||
+
|
||||
+ long usedMem;
|
||||
+
|
||||
+ RAMGraph() {
|
||||
+ for (int i = 0; i < 350; i++) {
|
||||
+ usedMemQueue.add(0L);
|
||||
+ usedPercentQueue.add(0);
|
||||
+ }
|
||||
+
|
||||
+ for (int i = 0; i < 101; i++) {
|
||||
+ Color color = getColor(i);
|
||||
+ colors[i] = new Color(color.getRed() / 2, color.getGreen() / 2, color.getBlue() / 2, 255);
|
||||
+ colorsAlpha[i] = new Color(colors[i].getRed(), colors[i].getGreen(), colors[i].getBlue(), 125);
|
||||
+ }
|
||||
+
|
||||
+ ToolTipManager.sharedInstance().setInitialDelay(0);
|
||||
+
|
||||
+ addMouseListener(new MouseAdapter() {
|
||||
+ final int defaultDismissTimeout = ToolTipManager.sharedInstance().getDismissDelay();
|
||||
+ final int dismissDelayMinutes = (int) TimeUnit.MINUTES.toMillis(10); // 10 minutes
|
||||
+
|
||||
+ @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);
|
||||
+ }
|
||||
+
|
||||
+ protected void update() {
|
||||
+ total = Runtime.getRuntime().totalMemory();
|
||||
+ free = Runtime.getRuntime().freeMemory();
|
||||
+ max = Runtime.getRuntime().maxMemory();
|
||||
+ usedMem = total - free;
|
||||
+
|
||||
+ usedMemQueue.add(usedMem);
|
||||
+ usedPercentQueue.add((int) (usedMem * 100L / max));
|
||||
+
|
||||
+ Point scr = MouseInfo.getPointerInfo().getLocation();
|
||||
+ Point loc = new Point(scr);
|
||||
+ SwingUtilities.convertPointFromScreen(loc, this);
|
||||
+ if (this.contains(loc)) {
|
||||
+ ToolTipManager.sharedInstance().mouseMoved(
|
||||
+ new MouseEvent(this, -1, System.currentTimeMillis(), 0, loc.x, loc.y,
|
||||
+ scr.x, scr.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 (Integer used : usedPercentQueue) {
|
||||
+ i++;
|
||||
+ if ((i + currentTick) % 120 == 0) {
|
||||
+ graphics.setColor(new Color(0x888888));
|
||||
+ graphics.drawLine(i, 1, i, 99);
|
||||
+ }
|
||||
+
|
||||
+ if (used > 0) {
|
||||
+ Color color = colors[used];
|
||||
+ graphics.setColor(colorsAlpha[used]);
|
||||
+ 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 = getMousePosition();
|
||||
+ if (m != null && m.x > 0 && m.x < 348 && m.y > 0 && m.y < 100) {
|
||||
+ Integer used = usedPercentQueue.get(m.x);
|
||||
+ 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(colors[used]);
|
||||
+ 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(usedMemQueue.get(m.x) / 1024F / 1024F),
|
||||
+ used, getTime(m.x)));
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ protected void stop() {
|
||||
+ timer.stop();
|
||||
+ }
|
||||
+
|
||||
+ private String getTime(int halfSeconds) {
|
||||
+ int millis = (348 - halfSeconds) / 2 * 1000;
|
||||
+ return sdf.format(new Date((System.currentTimeMillis() - millis)));
|
||||
+ }
|
||||
+
|
||||
+ private Color getColor(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);
|
||||
+ }
|
||||
+
|
||||
+ public static class RAMQueue<E> extends LinkedList<E> {
|
||||
+ @Override
|
||||
+ public boolean add(E e) {
|
||||
+ if (size() >= 348) {
|
||||
+ remove();
|
||||
+ }
|
||||
+ return super.add(e);
|
||||
+ }
|
||||
+ }
|
||||
+}
|
||||
diff --git a/src/main/java/net/pl3x/purpur/gui/info/ServerInfoPanel.java b/src/main/java/net/pl3x/purpur/gui/info/ServerInfoPanel.java
|
||||
new file mode 100644
|
||||
index 000000000..c4519794c
|
||||
--- /dev/null
|
||||
+++ b/src/main/java/net/pl3x/purpur/gui/info/ServerInfoPanel.java
|
||||
@@ -0,0 +1,42 @@
|
||||
+package net.pl3x.purpur.gui.info;
|
||||
+
|
||||
+import net.minecraft.server.MinecraftServer;
|
||||
+
|
||||
+import javax.swing.JPanel;
|
||||
+import javax.swing.Timer;
|
||||
+import java.awt.BorderLayout;
|
||||
+import java.awt.Dimension;
|
||||
+
|
||||
+public class ServerInfoPanel extends JPanel {
|
||||
+ private final Timer timer;
|
||||
+ private final RAMGraph ramGraph;
|
||||
+ private final RAMDetails ramDetails;
|
||||
+
|
||||
+ public ServerInfoPanel(MinecraftServer server) {
|
||||
+ super(new BorderLayout());
|
||||
+
|
||||
+ setOpaque(false);
|
||||
+
|
||||
+ ramGraph = new RAMGraph();
|
||||
+ ramDetails = new RAMDetails(server);
|
||||
+
|
||||
+ add(ramGraph, "North");
|
||||
+ add(ramDetails, "Center");
|
||||
+
|
||||
+ timer = new Timer(500, (event) -> {
|
||||
+ ramGraph.update();
|
||||
+ ramDetails.update(ramGraph);
|
||||
+ });
|
||||
+ timer.start();
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public Dimension getPreferredSize() {
|
||||
+ return new Dimension(350, 200);
|
||||
+ }
|
||||
+
|
||||
+ public void stop() {
|
||||
+ timer.stop();
|
||||
+ ramGraph.stop();
|
||||
+ }
|
||||
+}
|
||||
diff --git a/src/main/resources/log4j2.xml b/src/main/resources/log4j2.xml
|
||||
index 869bff4af..2a3e57c2f 100644
|
||||
--- a/src/main/resources/log4j2.xml
|
||||
+++ b/src/main/resources/log4j2.xml
|
||||
@@ -2,7 +2,16 @@
|
||||
<Configuration status="WARN" packages="com.mojang.util">
|
||||
<Appenders>
|
||||
<Queue name="ServerGuiConsole">
|
||||
- <PatternLayout pattern="[%d{HH:mm:ss} %level]: %msg%n" />
|
||||
+ <!-- Purpur start -->
|
||||
+ <PatternLayout>
|
||||
+ <LoggerNamePatternSelector defaultPattern="%highlightError{[%d{HH:mm:ss} %level]: [%logger] %minecraftFormatting{%msg}%n%xEx}">
|
||||
+ <!-- Log root, Minecraft, Mojang and Bukkit loggers without prefix -->
|
||||
+ <!-- Disable prefix for various plugins that bypass the plugin logger -->
|
||||
+ <PatternMatch key=",net.minecraft.,Minecraft,com.mojang.,com.sk89q.,ru.tehkode.,Minecraft.AWE"
|
||||
+ pattern="%highlightError{[%d{HH:mm:ss} %level]: %minecraftFormatting{%msg}%n%xEx}" />
|
||||
+ </LoggerNamePatternSelector>
|
||||
+ </PatternLayout>
|
||||
+ <!-- Purpur end -->
|
||||
</Queue>
|
||||
<Queue name="TerminalConsole">
|
||||
<PatternLayout pattern="[%d{HH:mm:ss}] [%t/%level]: %msg%n" />
|
||||
--
|
||||
2.24.0
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
From fd558eb5594f12ec9911f00566a37a5ffba31977 Mon Sep 17 00:00:00 2001
|
||||
From 575046416748239741024cd3f2ed453860aa17bb Mon Sep 17 00:00:00 2001
|
||||
From: William Blake Galbreath <Blake.Galbreath@GMail.com>
|
||||
Date: Sun, 15 Dec 2019 12:53:59 -0600
|
||||
Subject: [PATCH] Disable outdated build check
|
||||
@@ -8,10 +8,10 @@ Subject: [PATCH] Disable outdated build check
|
||||
1 file changed, 1 insertion(+), 1 deletion(-)
|
||||
|
||||
diff --git a/src/main/java/org/bukkit/craftbukkit/Main.java b/src/main/java/org/bukkit/craftbukkit/Main.java
|
||||
index f30bcbd48..1980256b7 100644
|
||||
index 7e8b6cab7..fd0748582 100644
|
||||
--- a/src/main/java/org/bukkit/craftbukkit/Main.java
|
||||
+++ b/src/main/java/org/bukkit/craftbukkit/Main.java
|
||||
@@ -221,7 +221,7 @@ public class Main {
|
||||
@@ -220,7 +220,7 @@ public class Main {
|
||||
System.setProperty(TerminalConsoleAppender.JLINE_OVERRIDE_PROPERTY, "false"); // Paper
|
||||
}
|
||||
|
||||
|
||||
@@ -1,14 +1,17 @@
|
||||
From 063bb512eb620d23fc41913e95e6405a43dbf699 Mon Sep 17 00:00:00 2001
|
||||
From f57586d123fab52e1a14494b485936afc38994c6 Mon Sep 17 00:00:00 2001
|
||||
From: William Blake Galbreath <Blake.Galbreath@GMail.com>
|
||||
Date: Wed, 22 Jan 2020 20:13:40 -0600
|
||||
Subject: [PATCH] UPnP Port Forwarding Service
|
||||
|
||||
---
|
||||
pom.xml | 10 ++++++++
|
||||
.../net/minecraft/server/DedicatedServer.java | 25 +++++++++++++++++++
|
||||
.../net/minecraft/server/MinecraftServer.java | 11 ++++++++
|
||||
.../java/net/pl3x/purpur/PurpurConfig.java | 5 ++++
|
||||
4 files changed, 51 insertions(+)
|
||||
pom.xml | 10 +++++
|
||||
.../net/minecraft/server/DedicatedServer.java | 25 +++++++++++
|
||||
.../net/minecraft/server/MinecraftServer.java | 11 +++++
|
||||
.../java/net/pl3x/purpur/PurpurConfig.java | 5 +++
|
||||
.../pl3x/purpur/gui/info/ServerInfoPanel.java | 4 ++
|
||||
.../pl3x/purpur/gui/info/UPnPComponent.java | 45 +++++++++++++++++++
|
||||
6 files changed, 100 insertions(+)
|
||||
create mode 100644 src/main/java/net/pl3x/purpur/gui/info/UPnPComponent.java
|
||||
|
||||
diff --git a/pom.xml b/pom.xml
|
||||
index 37ff489db..c886104c5 100644
|
||||
@@ -39,7 +42,7 @@ index 37ff489db..c886104c5 100644
|
||||
|
||||
<pluginRepositories>
|
||||
diff --git a/src/main/java/net/minecraft/server/DedicatedServer.java b/src/main/java/net/minecraft/server/DedicatedServer.java
|
||||
index 8b5f4cab0..3e31b2bb3 100644
|
||||
index aec6040c8..c04940d0a 100644
|
||||
--- a/src/main/java/net/minecraft/server/DedicatedServer.java
|
||||
+++ b/src/main/java/net/minecraft/server/DedicatedServer.java
|
||||
@@ -231,6 +231,31 @@ public class DedicatedServer extends MinecraftServer implements IMinecraftServer
|
||||
@@ -75,14 +78,14 @@ index 8b5f4cab0..3e31b2bb3 100644
|
||||
// this.a((PlayerList) (new DedicatedPlayerList(this))); // Spigot - moved up
|
||||
server.loadPlugins();
|
||||
diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java
|
||||
index 9d5ef40a0..01b5a6b3e 100644
|
||||
index 105ac8a04..d36bac5d7 100644
|
||||
--- a/src/main/java/net/minecraft/server/MinecraftServer.java
|
||||
+++ b/src/main/java/net/minecraft/server/MinecraftServer.java
|
||||
@@ -181,6 +181,7 @@ public abstract class MinecraftServer extends IAsyncTaskHandlerReentrant<TickTas
|
||||
public boolean lagging = false; // Purpur
|
||||
public final SlackActivityAccountant slackActivityAccountant = new SlackActivityAccountant();
|
||||
// Spigot end
|
||||
+ protected boolean upnp = false;
|
||||
+ protected boolean upnp = false; public boolean isUPnPEnabled() { return upnp; }
|
||||
|
||||
public MinecraftServer(OptionSet options, Proxy proxy, DataFixer datafixer, CommandDispatcher commanddispatcher, YggdrasilAuthenticationService yggdrasilauthenticationservice, MinecraftSessionService minecraftsessionservice, GameProfileRepository gameprofilerepository, UserCache usercache, WorldLoadListenerFactory worldloadlistenerfactory, String s) {
|
||||
super("Server");
|
||||
@@ -119,6 +122,86 @@ index 544c68b0d..917f6503d 100644
|
||||
public static double laggingThreshold = 19.0D;
|
||||
private static void tickLoopSettings() {
|
||||
laggingThreshold = getDouble("settings.lagging-threshold", laggingThreshold);
|
||||
diff --git a/src/main/java/net/pl3x/purpur/gui/info/ServerInfoPanel.java b/src/main/java/net/pl3x/purpur/gui/info/ServerInfoPanel.java
|
||||
index c4519794c..2d9d1859d 100644
|
||||
--- a/src/main/java/net/pl3x/purpur/gui/info/ServerInfoPanel.java
|
||||
+++ b/src/main/java/net/pl3x/purpur/gui/info/ServerInfoPanel.java
|
||||
@@ -11,6 +11,7 @@ public class ServerInfoPanel extends JPanel {
|
||||
private final Timer timer;
|
||||
private final RAMGraph ramGraph;
|
||||
private final RAMDetails ramDetails;
|
||||
+ private final UPnPComponent upnpComponent;
|
||||
|
||||
public ServerInfoPanel(MinecraftServer server) {
|
||||
super(new BorderLayout());
|
||||
@@ -19,13 +20,16 @@ public class ServerInfoPanel extends JPanel {
|
||||
|
||||
ramGraph = new RAMGraph();
|
||||
ramDetails = new RAMDetails(server);
|
||||
+ upnpComponent = new UPnPComponent(server);
|
||||
|
||||
add(ramGraph, "North");
|
||||
add(ramDetails, "Center");
|
||||
+ add(upnpComponent, "South");
|
||||
|
||||
timer = new Timer(500, (event) -> {
|
||||
ramGraph.update();
|
||||
ramDetails.update(ramGraph);
|
||||
+ upnpComponent.repaint();
|
||||
});
|
||||
timer.start();
|
||||
}
|
||||
diff --git a/src/main/java/net/pl3x/purpur/gui/info/UPnPComponent.java b/src/main/java/net/pl3x/purpur/gui/info/UPnPComponent.java
|
||||
new file mode 100644
|
||||
index 000000000..af6a7e18f
|
||||
--- /dev/null
|
||||
+++ b/src/main/java/net/pl3x/purpur/gui/info/UPnPComponent.java
|
||||
@@ -0,0 +1,45 @@
|
||||
+package net.pl3x.purpur.gui.info;
|
||||
+
|
||||
+import net.minecraft.server.MinecraftServer;
|
||||
+import net.pl3x.purpur.PurpurConfig;
|
||||
+
|
||||
+import javax.swing.JTextPane;
|
||||
+import javax.swing.border.EmptyBorder;
|
||||
+import java.awt.Color;
|
||||
+import java.awt.Dimension;
|
||||
+import java.awt.Graphics;
|
||||
+
|
||||
+public class UPnPComponent extends JTextPane {
|
||||
+ private final MinecraftServer server;
|
||||
+
|
||||
+ UPnPComponent(MinecraftServer server) {
|
||||
+ this.server = server;
|
||||
+ setBorder(new EmptyBorder(0, 30, 0, 10));
|
||||
+ setText("UPnP Status");
|
||||
+ setOpaque(false);
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public Dimension getPreferredSize() {
|
||||
+ return new Dimension(350, 20);
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public void paint(Graphics graphics) {
|
||||
+ super.paint(graphics);
|
||||
+ graphics.setColor(server.isUPnPEnabled() ? Color.GREEN : Color.RED);
|
||||
+ graphics.fillOval(10, 0, 15, 15);
|
||||
+ setToolTipText(getTooltip());
|
||||
+ }
|
||||
+
|
||||
+ private String getTooltip() {
|
||||
+ if (!PurpurConfig.useUPnP) {
|
||||
+ return "UPnP Disabled";
|
||||
+ }
|
||||
+ if (server.isUPnPEnabled()) {
|
||||
+ return "UPnP Enabled";
|
||||
+ } else {
|
||||
+ return "UPnP Unavailable";
|
||||
+ }
|
||||
+ }
|
||||
+}
|
||||
--
|
||||
2.24.0
|
||||
|
||||
|
||||
Reference in New Issue
Block a user