From 046fc5171f3d933200cdf010c4db12d4b5b8517b Mon Sep 17 00:00:00 2001 From: leguan Date: Sun, 10 Mar 2024 20:10:41 +0100 Subject: [PATCH] Add onboarding message for initial server start --- .../server/MinecraftServer.java.patch | 108 ++++++++++-------- .../server/gui/MinecraftServerGui.java.patch | 56 ++++++++- .../paper/configuration/Configurations.java | 1 + .../configuration/GlobalConfiguration.java | 1 + 4 files changed, 112 insertions(+), 54 deletions(-) diff --git a/paper-server/patches/sources/net/minecraft/server/MinecraftServer.java.patch b/paper-server/patches/sources/net/minecraft/server/MinecraftServer.java.patch index a79638003a..3c886f0c9e 100644 --- a/paper-server/patches/sources/net/minecraft/server/MinecraftServer.java.patch +++ b/paper-server/patches/sources/net/minecraft/server/MinecraftServer.java.patch @@ -565,12 +565,10 @@ if (!iworlddataserver.isInitialized()) { try { -@@ -425,32 +725,10 @@ - } - +@@ -427,30 +727,8 @@ iworlddataserver.setInitialized(true); -- } -- + } + - this.getPlayerList().addWorldborderListener(worldserver); - if (this.worldData.getCustomBossEvents() != null) { - this.getCustomBossEvents().load(this.worldData.getCustomBossEvents(), this.registryAccess()); @@ -591,8 +589,8 @@ - worldborder.addListener(new BorderChangeListener.DelegateBorderChangeListener(worldserver1.getWorldBorder())); - this.levels.put(resourcekey1, worldserver1); - } - } - +- } +- - worldborder.applySettings(iworlddataserver.getWorldBorder()); } + // CraftBukkit end @@ -853,7 +851,7 @@ protected void runServer() { try { if (!this.initServer()) { -@@ -727,9 +1138,16 @@ +@@ -727,9 +1138,26 @@ } this.nextTickTimeNanos = Util.getNanos(); @@ -868,10 +866,20 @@ + long tickSection = Util.getNanos(); + long currentTime; + // Paper end - further improve server tick loop ++ // Paper start - Add onboarding message for initial server start ++ if (io.papermc.paper.configuration.GlobalConfiguration.isFirstStart) { ++ LOGGER.info("*************************************************************************************"); ++ LOGGER.info("This is the first time you're starting this server."); ++ LOGGER.info("It's recommended you read our 'Getting Started' documentation for guidance."); ++ LOGGER.info("View this and more helpful information here: https://docs.papermc.io/paper/next-steps"); ++ LOGGER.info("*************************************************************************************"); ++ } ++ // Paper end - Add onboarding message for initial server start ++ while (this.running) { long i; -@@ -744,12 +1162,31 @@ +@@ -744,12 +1172,31 @@ if (j > MinecraftServer.OVERLOADED_THRESHOLD_NANOS + 20L * i && this.nextTickTimeNanos - this.lastOverloadWarningNanos >= MinecraftServer.OVERLOADED_WARNING_INTERVAL_NANOS + 100L * i) { long k = j / i; @@ -903,7 +911,7 @@ boolean flag = i == 0L; if (this.debugCommandProfilerDelayStart) { -@@ -757,6 +1194,8 @@ +@@ -757,6 +1204,8 @@ this.debugCommandProfiler = new MinecraftServer.TimeProfiler(Util.getNanos(), this.tickCount); } @@ -912,7 +920,7 @@ this.nextTickTimeNanos += i; try { -@@ -830,6 +1269,14 @@ +@@ -830,6 +1279,14 @@ this.services.profileCache().clearExecutor(); } @@ -927,23 +935,25 @@ this.onServerExit(); } -@@ -889,7 +1336,14 @@ +@@ -889,9 +1346,16 @@ } private boolean haveTime() { - return this.runningTask() || Util.getNanos() < (this.mayHaveDelayedTasks ? this.delayedTasksMaxNextTickTimeNanos : this.nextTickTimeNanos); + // CraftBukkit start + return this.forceTicks || this.runningTask() || Util.getNanos() < (this.mayHaveDelayedTasks ? this.delayedTasksMaxNextTickTimeNanos : this.nextTickTimeNanos); -+ } -+ + } + + private void executeModerately() { + this.runAllTasks(); + java.util.concurrent.locks.LockSupport.parkNanos("executing tasks", 1000L); + // CraftBukkit end - } - ++ } ++ public static boolean throwIfFatalException() { -@@ -903,7 +1357,7 @@ + RuntimeException runtimeexception = (RuntimeException) MinecraftServer.fatalException.get(); + +@@ -903,7 +1367,7 @@ } public static void setFatalException(RuntimeException exception) { @@ -952,7 +962,7 @@ } @Override -@@ -961,6 +1415,7 @@ +@@ -961,6 +1425,7 @@ if (super.pollTask()) { return true; } else { @@ -960,7 +970,7 @@ if (this.tickRateManager.isSprinting() || this.haveTime()) { Iterator iterator = this.getAllLevels().iterator(); -@@ -968,16 +1423,16 @@ +@@ -968,16 +1433,16 @@ ServerLevel worldserver = (ServerLevel) iterator.next(); if (worldserver.getChunkSource().pollTask()) { @@ -980,7 +990,7 @@ Profiler.get().incrementCounter("runTask"); super.doRunTask(ticktask); } -@@ -1025,6 +1480,7 @@ +@@ -1025,6 +1490,7 @@ } public void tickServer(BooleanSupplier shouldKeepTicking) { @@ -988,7 +998,7 @@ long i = Util.getNanos(); int j = this.pauseWhileEmptySeconds() * 20; -@@ -1041,11 +1497,13 @@ +@@ -1041,11 +1507,13 @@ this.autoSave(); } @@ -1002,7 +1012,7 @@ ++this.tickCount; this.tickRateManager.tick(); this.tickChildren(shouldKeepTicking); -@@ -1055,12 +1513,18 @@ +@@ -1055,12 +1523,18 @@ } --this.ticksUntilAutosave; @@ -1022,7 +1032,7 @@ gameprofilerfiller.push("tallying"); long k = Util.getNanos() - i; int l = this.tickCount % 100; -@@ -1069,12 +1533,17 @@ +@@ -1069,12 +1543,17 @@ this.aggregatedTickTimesNanos += k; this.tickTimesNanos[l] = k; this.smoothedTickTimeMillis = this.smoothedTickTimeMillis * 0.8F + (float) k / (float) TimeUtil.NANOSECONDS_PER_MILLISECOND * 0.19999999F; @@ -1041,7 +1051,7 @@ MinecraftServer.LOGGER.debug("Autosave started"); ProfilerFiller gameprofilerfiller = Profiler.get(); -@@ -1123,7 +1592,7 @@ +@@ -1123,7 +1602,7 @@ private ServerStatus buildServerStatus() { ServerStatus.Players serverping_serverpingplayersample = this.buildPlayerStatus(); @@ -1050,7 +1060,7 @@ } private ServerStatus.Players buildPlayerStatus() { -@@ -1133,7 +1602,7 @@ +@@ -1133,7 +1612,7 @@ if (this.hidesOnlinePlayers()) { return new ServerStatus.Players(i, list.size(), List.of()); } else { @@ -1059,7 +1069,7 @@ ObjectArrayList objectarraylist = new ObjectArrayList(j); int k = Mth.nextInt(this.random, 0, list.size() - j); -@@ -1154,24 +1623,72 @@ +@@ -1154,24 +1633,72 @@ this.getPlayerList().getPlayers().forEach((entityplayer) -> { entityplayer.connection.suspendFlushing(); }); @@ -1084,13 +1094,13 @@ gameprofilerfiller.popPush("levels"); - Iterator iterator = this.getAllLevels().iterator(); + //Iterator iterator = this.getAllLevels().iterator(); // Paper - Throw exception on world create while being ticked; moved down - ++ + // CraftBukkit start + // Run tasks that are waiting on processing + while (!this.processQueue.isEmpty()) { + this.processQueue.remove().run(); + } -+ + + // Send time updates to everyone, it will get the right time from the world the player is in. + // Paper start - Perf: Optimize time updates + for (final ServerLevel level : this.getAllLevels()) { @@ -1133,7 +1143,7 @@ gameprofilerfiller.push("tick"); -@@ -1186,7 +1703,9 @@ +@@ -1186,7 +1713,9 @@ gameprofilerfiller.pop(); gameprofilerfiller.pop(); @@ -1143,7 +1153,7 @@ gameprofilerfiller.popPush("connection"); this.tickConnection(); -@@ -1267,6 +1786,22 @@ +@@ -1267,6 +1796,22 @@ return (ServerLevel) this.levels.get(key); } @@ -1166,7 +1176,7 @@ public Set> levelKeys() { return this.levels.keySet(); } -@@ -1296,7 +1831,7 @@ +@@ -1296,7 +1841,7 @@ @DontObfuscate public String getServerModName() { @@ -1175,7 +1185,7 @@ } public SystemReport fillSystemReport(SystemReport details) { -@@ -1347,7 +1882,7 @@ +@@ -1347,7 +1892,7 @@ @Override public void sendSystemMessage(Component message) { @@ -1184,7 +1194,7 @@ } public KeyPair getKeyPair() { -@@ -1385,11 +1920,14 @@ +@@ -1385,11 +1930,14 @@ } } @@ -1204,7 +1214,7 @@ } } -@@ -1403,7 +1941,7 @@ +@@ -1403,7 +1951,7 @@ while (iterator.hasNext()) { ServerLevel worldserver = (ServerLevel) iterator.next(); @@ -1213,7 +1223,7 @@ } } -@@ -1481,10 +2019,20 @@ +@@ -1481,10 +2029,20 @@ @Override public String getMotd() { @@ -1235,7 +1245,7 @@ this.motd = motd; } -@@ -1507,7 +2055,7 @@ +@@ -1507,7 +2065,7 @@ } public ServerConnectionListener getConnection() { @@ -1244,7 +1254,7 @@ } public boolean isReady() { -@@ -1593,7 +2141,7 @@ +@@ -1593,7 +2151,7 @@ @Override public void executeIfPossible(Runnable runnable) { if (this.isStopped()) { @@ -1253,7 +1263,7 @@ } else { super.executeIfPossible(runnable); } -@@ -1632,13 +2180,19 @@ +@@ -1632,13 +2190,19 @@ return this.functionManager; } @@ -1275,7 +1285,7 @@ }, this).thenCompose((immutablelist) -> { MultiPackResourceManager resourcemanager = new MultiPackResourceManager(PackType.SERVER_DATA, immutablelist); List> list = TagLoader.loadTagsForExistingRegistries(resourcemanager, this.registries.compositeAccess()); -@@ -1654,17 +2208,21 @@ +@@ -1654,17 +2218,21 @@ }).thenAcceptAsync((minecraftserver_reloadableresources) -> { this.resources.close(); this.resources = minecraftserver_reloadableresources; @@ -1297,7 +1307,7 @@ }, this); if (this.isSameThread()) { -@@ -1789,14 +2347,15 @@ +@@ -1789,14 +2357,15 @@ if (this.isEnforceWhitelist()) { PlayerList playerlist = source.getServer().getPlayerList(); UserWhiteList whitelist = playerlist.getWhiteList(); @@ -1315,7 +1325,7 @@ } } -@@ -1952,7 +2511,7 @@ +@@ -1952,7 +2521,7 @@ final List list = Lists.newArrayList(); final GameRules gamerules = this.getGameRules(); @@ -1324,7 +1334,7 @@ @Override public > void visit(GameRules.Key key, GameRules.Type type) { list.add(String.format(Locale.ROOT, "%s=%s\n", key.getId(), gamerules.getRule(key))); -@@ -2058,7 +2617,7 @@ +@@ -2058,7 +2627,7 @@ try { label51: { @@ -1333,7 +1343,7 @@ try { arraylist = Lists.newArrayList(NativeModuleLister.listModules()); -@@ -2105,9 +2664,24 @@ +@@ -2105,9 +2674,24 @@ if (bufferedwriter != null) { bufferedwriter.close(); } @@ -1358,7 +1368,7 @@ private ProfilerFiller createProfiler() { if (this.willStartRecordingMetrics) { this.metricsRecorder = ActiveMetricsRecorder.createStarted(new ServerMetricsSamplersProvider(Util.timeSource, this.isDedicatedServer()), Util.timeSource, Util.ioPool(), new MetricsPersister("server"), this.onMetricsRecordingStopped, (path) -> { -@@ -2225,18 +2799,24 @@ +@@ -2225,18 +2809,24 @@ } public void logChatMessage(Component message, ChatType.Bound params, @Nullable String prefix) { @@ -1387,13 +1397,11 @@ } public boolean logIPs() { -@@ -2377,6 +2957,32 @@ - } - +@@ -2379,4 +2969,30 @@ public static record ServerResourcePackInfo(UUID id, String url, String hash, boolean isRequired, @Nullable Component prompt) { -+ -+ } + } ++ + // Paper start - Add tick times API and /mspt command + public static class TickTimes { + private final long[] times; @@ -1417,6 +1425,6 @@ + } + return ((double) total / (double) times.length) * 1.0E-6D; + } - } ++ } + // Paper end - Add tick times API and /mspt command } diff --git a/paper-server/patches/sources/net/minecraft/server/gui/MinecraftServerGui.java.patch b/paper-server/patches/sources/net/minecraft/server/gui/MinecraftServerGui.java.patch index 1da278dd93..84332717d5 100644 --- a/paper-server/patches/sources/net/minecraft/server/gui/MinecraftServerGui.java.patch +++ b/paper-server/patches/sources/net/minecraft/server/gui/MinecraftServerGui.java.patch @@ -16,7 +16,15 @@ jframe.addWindowListener(new WindowAdapter() { public void windowClosing(WindowEvent windowevent) { if (!servergui.isClosing.getAndSet(true)) { -@@ -95,8 +104,8 @@ +@@ -81,6 +90,7 @@ + this.setLayout(new BorderLayout()); + + try { ++ this.add(this.buildOnboardingPanel(), "North"); // Paper - Add onboarding message for initial server start + this.add(this.buildChatPanel(), "Center"); + this.add(this.buildInfoPanel(), "West"); + } catch (Exception exception) { +@@ -95,8 +105,8 @@ private JComponent buildInfoPanel() { JPanel jpanel = new JPanel(new BorderLayout()); @@ -27,7 +35,47 @@ Objects.requireNonNull(guistatscomponent); collection.add(guistatscomponent::close); -@@ -132,7 +141,7 @@ +@@ -106,6 +116,39 @@ + return jpanel; + } + ++ // Paper start - Add onboarding message for initial server start ++ private JComponent buildOnboardingPanel() { ++ String onboardingLink = "https://docs.papermc.io/paper/next-steps"; ++ JPanel jPanel = new JPanel(); ++ ++ javax.swing.JLabel jLabel = new javax.swing.JLabel("If you need help setting up your server you can visit:"); ++ jLabel.setFont(MinecraftServerGui.MONOSPACED); ++ ++ javax.swing.JLabel link = new javax.swing.JLabel(" " + onboardingLink + ""); ++ link.setFont(MinecraftServerGui.MONOSPACED); ++ link.setCursor(new java.awt.Cursor(java.awt.Cursor.HAND_CURSOR)); ++ link.addMouseListener(new java.awt.event.MouseAdapter() { ++ @Override ++ public void mouseClicked(final java.awt.event.MouseEvent e) { ++ try { ++ java.awt.Desktop.getDesktop().browse(java.net.URI.create(onboardingLink)); ++ } catch (java.io.IOException exception) { ++ LOGGER.error("Unable to find a default browser. Please manually visit the website: " + onboardingLink, exception); ++ } catch (UnsupportedOperationException exception) { ++ LOGGER.error("This platform does not support the BROWSE action. Please manually visit the website: " + onboardingLink, exception); ++ } catch (SecurityException exception) { ++ LOGGER.error("This action has been denied by the security manager. Please manually visit the website: " + onboardingLink, exception); ++ } ++ } ++ }); ++ ++ jPanel.add(jLabel); ++ jPanel.add(link); ++ ++ return jPanel; ++ } ++ // Paper end - Add onboarding message for initial server start ++ + private JComponent buildPlayerPanel() { + JList jlist = new PlayerListComponent(this.server); + JScrollPane jscrollpane = new JScrollPane(jlist, 22, 30); +@@ -132,7 +175,7 @@ jtextfield.setText(""); }); @@ -36,7 +84,7 @@ public void focusGained(FocusEvent focusevent) {} }); jpanel.add(jscrollpane, "Center"); -@@ -166,6 +175,7 @@ +@@ -166,6 +209,7 @@ this.finalizers.forEach(Runnable::run); } @@ -44,7 +92,7 @@ public void print(JTextArea textArea, JScrollPane scrollPane, String message) { if (!SwingUtilities.isEventDispatchThread()) { SwingUtilities.invokeLater(() -> { -@@ -181,7 +191,7 @@ +@@ -181,7 +225,7 @@ } try { diff --git a/paper-server/src/main/java/io/papermc/paper/configuration/Configurations.java b/paper-server/src/main/java/io/papermc/paper/configuration/Configurations.java index 007e01d329..8cf720f085 100644 --- a/paper-server/src/main/java/io/papermc/paper/configuration/Configurations.java +++ b/paper-server/src/main/java/io/papermc/paper/configuration/Configurations.java @@ -127,6 +127,7 @@ public abstract class Configurations { if (Files.notExists(configFile)) { node = CommentedConfigurationNode.root(loader.defaultOptions()); node.node(Configuration.VERSION_FIELD).raw(this.globalConfigVersion()); + GlobalConfiguration.isFirstStart = true; } else { node = loader.load(); this.verifyGlobalConfigVersion(node); diff --git a/paper-server/src/main/java/io/papermc/paper/configuration/GlobalConfiguration.java b/paper-server/src/main/java/io/papermc/paper/configuration/GlobalConfiguration.java index d8db428f06..2d2ff82635 100644 --- a/paper-server/src/main/java/io/papermc/paper/configuration/GlobalConfiguration.java +++ b/paper-server/src/main/java/io/papermc/paper/configuration/GlobalConfiguration.java @@ -25,6 +25,7 @@ public class GlobalConfiguration extends ConfigurationPart { private static final Logger LOGGER = LogUtils.getLogger(); static final int CURRENT_VERSION = 29; // (when you change the version, change the comment, so it conflicts on rebases): private static GlobalConfiguration instance; + public static boolean isFirstStart = false; public static GlobalConfiguration get() { return instance; }