From 5c260c7e51c7bcf4ff15f4a3c1c6b384499a1eac Mon Sep 17 00:00:00 2001 From: Noah van der Aa Date: Sat, 22 Oct 2022 14:47:45 +0200 Subject: [PATCH] Detect headless JREs Crashes caused by the missing AWT dependency come up in the support channels fairly often. This patch detects the missing dependency and stops the server with a clear error message, containing a link to instructions on how to install a non-headless JRE. --- .../net/minecraft/server/Main.java.patch | 28 +++++++++++++------ .../papermc/paper/util/ServerEnvironment.java | 10 +++++++ 2 files changed, 30 insertions(+), 8 deletions(-) diff --git a/paper-server/patches/sources/net/minecraft/server/Main.java.patch b/paper-server/patches/sources/net/minecraft/server/Main.java.patch index a4e6e66dcc..182db91996 100644 --- a/paper-server/patches/sources/net/minecraft/server/Main.java.patch +++ b/paper-server/patches/sources/net/minecraft/server/Main.java.patch @@ -43,7 +43,7 @@ OptionParser optionparser = new OptionParser(); OptionSpec optionspec = optionparser.accepts("nogui"); OptionSpec optionspec1 = optionparser.accepts("initSettings", "Initializes 'server.properties' and 'eula.txt', then quits"); -@@ -90,50 +100,92 @@ +@@ -90,50 +100,104 @@ OptionSpec optionspec15 = optionparser.nonOptions(); try { @@ -125,6 +125,18 @@ - File file = new File((String) optionset.valueOf(optionspec9)); - Services services = Services.create(new YggdrasilAuthenticationService(Proxy.NO_PROXY), file); - String s = (String) Optional.ofNullable((String) optionset.valueOf(optionspec10)).orElse(dedicatedserversettings.getProperties().levelName); ++ // Paper start - Detect headless JRE ++ String awtException = io.papermc.paper.util.ServerEnvironment.awtDependencyCheck(); ++ if (awtException != null) { ++ Main.LOGGER.error("You are using a headless JRE distribution."); ++ Main.LOGGER.error("This distribution is missing certain graphic libraries that the Minecraft server needs to function."); ++ Main.LOGGER.error("For instructions on how to install the non-headless JRE, see https://docs.papermc.io/misc/java-install"); ++ Main.LOGGER.error(""); ++ Main.LOGGER.error(awtException); ++ return; ++ } ++ // Paper end - Detect headless JRE ++ + org.spigotmc.SpigotConfig.disabledAdvancements = spigotConfiguration.getStringList("advancements.disabled"); // Paper - fix SPIGOT-5885, must be set early in init + // Paper start - fix SPIGOT-5824 + File file; @@ -146,7 +158,7 @@ Dynamic dynamic; if (convertable_conversionsession.hasWorldData()) { -@@ -174,13 +226,31 @@ +@@ -174,13 +238,31 @@ } Dynamic dynamic1 = dynamic; @@ -179,7 +191,7 @@ WorldStem worldstem; -@@ -189,6 +259,7 @@ +@@ -189,6 +271,7 @@ worldstem = (WorldStem) Util.blockUntilDone((executor) -> { return WorldLoader.load(worldloader_c, (worldloader_a) -> { @@ -187,7 +199,7 @@ Registry iregistry = worldloader_a.datapackDimensions().lookupOrThrow(Registries.LEVEL_STEM); if (dynamic1 != null) { -@@ -201,7 +272,7 @@ +@@ -201,7 +284,7 @@ WorldOptions worldoptions; WorldDimensions worlddimensions; @@ -196,7 +208,7 @@ worldsettings = MinecraftServer.DEMO_SETTINGS; worldoptions = WorldOptions.DEMO_OPTIONS; worlddimensions = WorldPresets.createNormalWorldDimensions(worldloader_a.datapackWorldgen()); -@@ -209,7 +280,7 @@ +@@ -209,7 +292,7 @@ DedicatedServerProperties dedicatedserverproperties = dedicatedserversettings.getProperties(); worldsettings = new LevelSettings(dedicatedserverproperties.levelName, dedicatedserverproperties.gamemode, dedicatedserverproperties.hardcore, dedicatedserverproperties.difficulty, false, new GameRules(worldloader_a.dataConfiguration().enabledFeatures()), worldloader_a.dataConfiguration()); @@ -205,7 +217,7 @@ worlddimensions = dedicatedserverproperties.createDimensions(worldloader_a.datapackWorldgen()); } -@@ -225,32 +296,45 @@ +@@ -225,32 +308,45 @@ return; } @@ -256,7 +268,7 @@ Thread thread = new Thread("Server Shutdown Thread") { public void run() { dedicatedserver.halt(true); -@@ -259,6 +343,7 @@ +@@ -259,6 +355,7 @@ thread.setUncaughtExceptionHandler(new DefaultUncaughtExceptionHandler(Main.LOGGER)); Runtime.getRuntime().addShutdownHook(thread); @@ -264,7 +276,7 @@ } catch (Exception exception1) { Main.LOGGER.error(LogUtils.FATAL_MARKER, "Failed to start the minecraft server", exception1); } -@@ -295,7 +380,7 @@ +@@ -295,7 +392,7 @@ } public static void forceUpgrade(LevelStorageSource.LevelStorageAccess session, DataFixer dataFixer, boolean eraseCache, BooleanSupplier continueCheck, RegistryAccess dynamicRegistryManager, boolean recreateRegionFiles) { diff --git a/paper-server/src/main/java/io/papermc/paper/util/ServerEnvironment.java b/paper-server/src/main/java/io/papermc/paper/util/ServerEnvironment.java index 68098dfe71..2b7070e0ce 100644 --- a/paper-server/src/main/java/io/papermc/paper/util/ServerEnvironment.java +++ b/paper-server/src/main/java/io/papermc/paper/util/ServerEnvironment.java @@ -20,4 +20,14 @@ public class ServerEnvironment { public static boolean userIsRootOrAdmin() { return RUNNING_AS_ROOT_OR_ADMIN; } + + public static String awtDependencyCheck() { + try { + new java.awt.Color(0); + } catch (UnsatisfiedLinkError e) { + return e.getClass().getName() + ": " + e.getMessage(); + } + + return null; + } }