minecraft-src/net/minecraft/server/gui/MinecraftServerGui.java
2025-07-04 01:41:11 +03:00

178 lines
5.7 KiB
Java

package net.minecraft.server.gui;
import com.google.common.collect.Lists;
import com.mojang.logging.LogQueues;
import com.mojang.logging.LogUtils;
import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.event.FocusAdapter;
import java.awt.event.FocusEvent;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.util.Collection;
import java.util.concurrent.atomic.AtomicBoolean;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JList;
import javax.swing.JPanel;
import javax.swing.JScrollBar;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.JTextField;
import javax.swing.SwingUtilities;
import javax.swing.UIManager;
import javax.swing.border.EtchedBorder;
import javax.swing.border.TitledBorder;
import javax.swing.text.BadLocationException;
import javax.swing.text.Document;
import net.minecraft.DefaultUncaughtExceptionHandler;
import net.minecraft.server.dedicated.DedicatedServer;
import org.slf4j.Logger;
public class MinecraftServerGui extends JComponent {
private static final Font MONOSPACED = new Font("Monospaced", 0, 12);
private static final Logger LOGGER = LogUtils.getLogger();
private static final String TITLE = "Minecraft server";
private static final String SHUTDOWN_TITLE = "Minecraft server - shutting down!";
private final DedicatedServer server;
private Thread logAppenderThread;
private final Collection<Runnable> finalizers = Lists.<Runnable>newArrayList();
final AtomicBoolean isClosing = new AtomicBoolean();
public static MinecraftServerGui showFrameFor(DedicatedServer server) {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (Exception var3) {
}
final JFrame jFrame = new JFrame("Minecraft server");
final MinecraftServerGui minecraftServerGui = new MinecraftServerGui(server);
jFrame.setDefaultCloseOperation(2);
jFrame.add(minecraftServerGui);
jFrame.pack();
jFrame.setLocationRelativeTo(null);
jFrame.setVisible(true);
jFrame.addWindowListener(new WindowAdapter() {
public void windowClosing(WindowEvent windowEvent) {
if (!minecraftServerGui.isClosing.getAndSet(true)) {
jFrame.setTitle("Minecraft server - shutting down!");
server.halt(true);
minecraftServerGui.runFinalizers();
}
}
});
minecraftServerGui.addFinalizer(jFrame::dispose);
minecraftServerGui.start();
return minecraftServerGui;
}
private MinecraftServerGui(DedicatedServer server) {
this.server = server;
this.setPreferredSize(new Dimension(854, 480));
this.setLayout(new BorderLayout());
try {
this.add(this.buildChatPanel(), "Center");
this.add(this.buildInfoPanel(), "West");
} catch (Exception var3) {
LOGGER.error("Couldn't build server GUI", (Throwable)var3);
}
}
public void addFinalizer(Runnable finalizer) {
this.finalizers.add(finalizer);
}
/**
* Generates new StatsComponent and returns it.
*/
private JComponent buildInfoPanel() {
JPanel jPanel = new JPanel(new BorderLayout());
StatsComponent statsComponent = new StatsComponent(this.server);
this.finalizers.add(statsComponent::close);
jPanel.add(statsComponent, "North");
jPanel.add(this.buildPlayerPanel(), "Center");
jPanel.setBorder(new TitledBorder(new EtchedBorder(), "Stats"));
return jPanel;
}
/**
* Generates new PlayerListComponent and returns it.
*/
private JComponent buildPlayerPanel() {
JList<?> jList = new PlayerListComponent(this.server);
JScrollPane jScrollPane = new JScrollPane(jList, 22, 30);
jScrollPane.setBorder(new TitledBorder(new EtchedBorder(), "Players"));
return jScrollPane;
}
private JComponent buildChatPanel() {
JPanel jPanel = new JPanel(new BorderLayout());
JTextArea jTextArea = new JTextArea();
JScrollPane jScrollPane = new JScrollPane(jTextArea, 22, 30);
jTextArea.setEditable(false);
jTextArea.setFont(MONOSPACED);
JTextField jTextField = new JTextField();
jTextField.addActionListener(actionEvent -> {
String string = jTextField.getText().trim();
if (!string.isEmpty()) {
this.server.handleConsoleInput(string, this.server.createCommandSourceStack());
}
jTextField.setText("");
});
jTextArea.addFocusListener(new FocusAdapter() {
public void focusGained(FocusEvent focusEvent) {
}
});
jPanel.add(jScrollPane, "Center");
jPanel.add(jTextField, "South");
jPanel.setBorder(new TitledBorder(new EtchedBorder(), "Log and chat"));
this.logAppenderThread = new Thread(() -> {
String string;
while ((string = LogQueues.getNextLogEvent("ServerGuiConsole")) != null) {
this.print(jTextArea, jScrollPane, string);
}
});
this.logAppenderThread.setUncaughtExceptionHandler(new DefaultUncaughtExceptionHandler(LOGGER));
this.logAppenderThread.setDaemon(true);
return jPanel;
}
public void start() {
this.logAppenderThread.start();
}
public void close() {
if (!this.isClosing.getAndSet(true)) {
this.runFinalizers();
}
}
void runFinalizers() {
this.finalizers.forEach(Runnable::run);
}
public void print(JTextArea textArea, JScrollPane scrollPane, String line) {
if (!SwingUtilities.isEventDispatchThread()) {
SwingUtilities.invokeLater(() -> this.print(textArea, scrollPane, line));
} else {
Document document = textArea.getDocument();
JScrollBar jScrollBar = scrollPane.getVerticalScrollBar();
boolean bl = false;
if (scrollPane.getViewport().getView() == textArea) {
bl = jScrollBar.getValue() + jScrollBar.getSize().getHeight() + MONOSPACED.getSize() * 4 > jScrollBar.getMaximum();
}
try {
document.insertString(document.getLength(), line, null);
} catch (BadLocationException var8) {
}
if (bl) {
jScrollBar.setValue(Integer.MAX_VALUE);
}
}
}
}