Paper/paper-server/patches/sources/net/minecraft/server/Main.java.patch
Noah van der Aa 5c260c7e51 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.
2022-10-22 14:47:45 +02:00

288 lines
16 KiB
Diff

--- a/net/minecraft/server/Main.java
+++ b/net/minecraft/server/Main.java
@@ -38,6 +38,7 @@
import net.minecraft.server.dedicated.DedicatedServerProperties;
import net.minecraft.server.dedicated.DedicatedServerSettings;
import net.minecraft.server.level.progress.LoggerChunkProgressListener;
+import net.minecraft.server.packs.PackType;
import net.minecraft.server.packs.repository.PackRepository;
import net.minecraft.server.packs.repository.ServerPacksSource;
import net.minecraft.util.Mth;
@@ -55,22 +56,31 @@
import net.minecraft.world.level.levelgen.WorldOptions;
import net.minecraft.world.level.levelgen.presets.WorldPresets;
import net.minecraft.world.level.storage.LevelDataAndDimensions;
+import net.minecraft.world.level.storage.LevelResource;
import net.minecraft.world.level.storage.LevelStorageSource;
import net.minecraft.world.level.storage.LevelSummary;
import net.minecraft.world.level.storage.PrimaryLevelData;
-import net.minecraft.world.level.storage.WorldData;
import org.slf4j.Logger;
+// CraftBukkit start
+import com.google.common.base.Charsets;
+import java.io.InputStreamReader;
+import java.util.concurrent.atomic.AtomicReference;
+import net.minecraft.SharedConstants;
+import org.bukkit.configuration.file.YamlConfiguration;
+// CraftBukkit end
+
public class Main {
private static final Logger LOGGER = LogUtils.getLogger();
public Main() {}
- @SuppressForbidden(a = "System.out needed before bootstrap")
+ @SuppressForbidden(reason = "System.out needed before bootstrap") // CraftBukkit - decompile error
@DontObfuscate
- public static void main(String[] args) {
+ public static void main(final OptionSet optionset) { // CraftBukkit - replaces main(String[] astring)
SharedConstants.tryDetectVersion();
+ /* CraftBukkit start - Replace everything
OptionParser optionparser = new OptionParser();
OptionSpec<Void> optionspec = optionparser.accepts("nogui");
OptionSpec<Void> optionspec1 = optionparser.accepts("initSettings", "Initializes 'server.properties' and 'eula.txt', then quits");
@@ -90,50 +100,104 @@
OptionSpec<String> optionspec15 = optionparser.nonOptions();
try {
- OptionSet optionset = optionparser.parse(args);
+ OptionSet optionset = optionparser.parse(astring);
if (optionset.has(optionspec8)) {
optionparser.printHelpOn(System.err);
return;
}
+ */ // CraftBukkit end
- Path path = (Path) optionset.valueOf(optionspec14);
+ try {
+ Path path = (Path) optionset.valueOf("pidFile"); // CraftBukkit
+
if (path != null) {
Main.writePidFile(path);
}
CrashReport.preload();
- if (optionset.has(optionspec13)) {
+ if (optionset.has("jfrProfile")) { // CraftBukkit
JvmProfiler.INSTANCE.start(Environment.SERVER);
}
+ io.papermc.paper.plugin.PluginInitializerManager.load(optionset); // Paper
Bootstrap.bootStrap();
Bootstrap.validate();
Util.startTimerHackThread();
Path path1 = Paths.get("server.properties");
- DedicatedServerSettings dedicatedserversettings = new DedicatedServerSettings(path1);
+ DedicatedServerSettings dedicatedserversettings = new DedicatedServerSettings(optionset); // CraftBukkit - CLI argument support
dedicatedserversettings.forceSave();
RegionFileVersion.configure(dedicatedserversettings.getProperties().regionFileComression);
Path path2 = Paths.get("eula.txt");
Eula eula = new Eula(path2);
+ // Paper start - load config files early for access below if needed
+ org.bukkit.configuration.file.YamlConfiguration bukkitConfiguration = io.papermc.paper.configuration.PaperConfigurations.loadLegacyConfigFile((File) optionset.valueOf("bukkit-settings"));
+ org.bukkit.configuration.file.YamlConfiguration spigotConfiguration = io.papermc.paper.configuration.PaperConfigurations.loadLegacyConfigFile((File) optionset.valueOf("spigot-settings"));
+ // Paper end - load config files early for access below if needed
- if (optionset.has(optionspec1)) {
+ if (optionset.has("initSettings")) { // CraftBukkit
+ // CraftBukkit start - SPIGOT-5761: Create bukkit.yml and commands.yml if not present
+ File configFile = (File) optionset.valueOf("bukkit-settings");
+ YamlConfiguration configuration = YamlConfiguration.loadConfiguration(configFile);
+ configuration.options().copyDefaults(true);
+ configuration.setDefaults(YamlConfiguration.loadConfiguration(new InputStreamReader(Main.class.getClassLoader().getResourceAsStream("configurations/bukkit.yml"), Charsets.UTF_8)));
+ configuration.save(configFile);
+
+ File commandFile = (File) optionset.valueOf("commands-settings");
+ YamlConfiguration commandsConfiguration = YamlConfiguration.loadConfiguration(commandFile);
+ commandsConfiguration.options().copyDefaults(true);
+ commandsConfiguration.setDefaults(YamlConfiguration.loadConfiguration(new InputStreamReader(Main.class.getClassLoader().getResourceAsStream("configurations/commands.yml"), Charsets.UTF_8)));
+ commandsConfiguration.save(commandFile);
+ // CraftBukkit end
Main.LOGGER.info("Initialized '{}' and '{}'", path1.toAbsolutePath(), path2.toAbsolutePath());
return;
}
- if (!eula.hasAgreedToEULA()) {
+ // Spigot Start
+ boolean eulaAgreed = Boolean.getBoolean( "com.mojang.eula.agree" );
+ if ( eulaAgreed )
+ {
+ System.err.println( "You have used the Spigot command line EULA agreement flag." );
+ System.err.println( "By using this setting you are indicating your agreement to Mojang's EULA (https://account.mojang.com/documents/minecraft_eula)." );
+ System.err.println( "If you do not agree to the above EULA please stop your server and remove this flag immediately." );
+ }
+ // Spigot End
+ if (!eula.hasAgreedToEULA() && !eulaAgreed) { // Spigot
Main.LOGGER.info("You need to agree to the EULA in order to run the server. Go to eula.txt for more info.");
return;
}
- 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;
+ File userCacheFile = new File(Services.USERID_CACHE_FILE);
+ if (optionset.has("universe")) {
+ file = (File) optionset.valueOf("universe"); // CraftBukkit
+ userCacheFile = new File(file, Services.USERID_CACHE_FILE);
+ } else {
+ file = new File(bukkitConfiguration.getString("settings.world-container", "."));
+ }
+ // Paper end - fix SPIGOT-5824
+ Services services = Services.create(new com.destroystokyo.paper.profile.PaperAuthenticationService(Proxy.NO_PROXY), file, userCacheFile, optionset); // Paper - pass OptionSet to load paper config files; override authentication service; fix world-container
+ // CraftBukkit start
+ String s = (String) Optional.ofNullable((String) optionset.valueOf("world")).orElse(dedicatedserversettings.getProperties().levelName);
LevelStorageSource convertable = LevelStorageSource.createDefault(file.toPath());
- LevelStorageSource.LevelStorageAccess convertable_conversionsession = convertable.validateAndCreateAccess(s);
+ LevelStorageSource.LevelStorageAccess convertable_conversionsession = convertable.validateAndCreateAccess(s, LevelStem.OVERWORLD);
+ // CraftBukkit end
Dynamic dynamic;
if (convertable_conversionsession.hasWorldData()) {
@@ -174,13 +238,31 @@
}
Dynamic<?> dynamic1 = dynamic;
- boolean flag = optionset.has(optionspec7);
+ boolean flag = optionset.has("safeMode"); // CraftBukkit
if (flag) {
Main.LOGGER.warn("Safe mode active, only vanilla datapack will be loaded");
}
PackRepository resourcepackrepository = ServerPacksSource.createPackRepository(convertable_conversionsession);
+ // CraftBukkit start
+ File bukkitDataPackFolder = new File(convertable_conversionsession.getLevelPath(LevelResource.DATAPACK_DIR).toFile(), "bukkit");
+ if (!bukkitDataPackFolder.exists()) {
+ bukkitDataPackFolder.mkdirs();
+ }
+ File mcMeta = new File(bukkitDataPackFolder, "pack.mcmeta");
+ try {
+ com.google.common.io.Files.write("{\n"
+ + " \"pack\": {\n"
+ + " \"description\": \"Data pack for resources provided by Bukkit plugins\",\n"
+ + " \"pack_format\": " + SharedConstants.getCurrentVersion().getPackVersion(PackType.SERVER_DATA) + "\n"
+ + " }\n"
+ + "}\n", mcMeta, com.google.common.base.Charsets.UTF_8);
+ } catch (java.io.IOException ex) {
+ throw new RuntimeException("Could not initialize Bukkit datapack", ex);
+ }
+ AtomicReference<WorldLoader.DataLoadContext> worldLoader = new AtomicReference<>();
+ // CraftBukkit end
WorldStem worldstem;
@@ -189,6 +271,7 @@
worldstem = (WorldStem) Util.blockUntilDone((executor) -> {
return WorldLoader.load(worldloader_c, (worldloader_a) -> {
+ worldLoader.set(worldloader_a); // CraftBukkit
Registry<LevelStem> iregistry = worldloader_a.datapackDimensions().lookupOrThrow(Registries.LEVEL_STEM);
if (dynamic1 != null) {
@@ -201,7 +284,7 @@
WorldOptions worldoptions;
WorldDimensions worlddimensions;
- if (optionset.has(optionspec2)) {
+ if (optionset.has("demo")) { // CraftBukkit
worldsettings = MinecraftServer.DEMO_SETTINGS;
worldoptions = WorldOptions.DEMO_OPTIONS;
worlddimensions = WorldPresets.createNormalWorldDimensions(worldloader_a.datapackWorldgen());
@@ -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());
- worldoptions = optionset.has(optionspec3) ? dedicatedserverproperties.worldOptions.withBonusChest(true) : dedicatedserverproperties.worldOptions;
+ worldoptions = optionset.has("bonusChest") ? dedicatedserverproperties.worldOptions.withBonusChest(true) : dedicatedserverproperties.worldOptions; // CraftBukkit
worlddimensions = dedicatedserverproperties.createDimensions(worldloader_a.datapackWorldgen());
}
@@ -225,32 +308,45 @@
return;
}
- RegistryAccess.Frozen iregistrycustom_dimension = worldstem.registries().compositeAccess();
+ /*
+ IRegistryCustom.Dimension iregistrycustom_dimension = worldstem.registries().compositeAccess();
boolean flag1 = optionset.has(optionspec6);
if (optionset.has(optionspec4) || flag1) {
- Main.forceUpgrade(convertable_conversionsession, DataFixers.getDataFixer(), optionset.has(optionspec5), () -> {
+ forceUpgrade(convertable_conversionsession, DataConverterRegistry.getDataFixer(), optionset.has(optionspec5), () -> {
return true;
}, iregistrycustom_dimension, flag1);
}
- WorldData savedata = worldstem.worldData();
+ SaveData savedata = worldstem.worldData();
convertable_conversionsession.saveDataTag(iregistrycustom_dimension, savedata);
+ */
final DedicatedServer dedicatedserver = (DedicatedServer) MinecraftServer.spin((thread) -> {
- DedicatedServer dedicatedserver1 = new DedicatedServer(thread, convertable_conversionsession, resourcepackrepository, worldstem, dedicatedserversettings, DataFixers.getDataFixer(), services, LoggerChunkProgressListener::createFromGameruleRadius);
+ DedicatedServer dedicatedserver1 = new DedicatedServer(optionset, worldLoader.get(), thread, convertable_conversionsession, resourcepackrepository, worldstem, dedicatedserversettings, DataFixers.getDataFixer(), services, LoggerChunkProgressListener::createFromGameruleRadius);
+ /*
dedicatedserver1.setPort((Integer) optionset.valueOf(optionspec11));
dedicatedserver1.setDemo(optionset.has(optionspec2));
dedicatedserver1.setId((String) optionset.valueOf(optionspec12));
- boolean flag2 = !optionset.has(optionspec) && !optionset.valuesOf(optionspec15).contains("nogui");
+ */
+ boolean flag2 = !optionset.has("nogui") && !optionset.nonOptionArguments().contains("nogui");
+ if(!Boolean.parseBoolean(System.getenv().getOrDefault("PAPER_DISABLE_SERVER_GUI", String.valueOf(false)))) // Paper - Add environment variable to disable server gui
if (flag2 && !GraphicsEnvironment.isHeadless()) {
dedicatedserver1.showGui();
}
+ if (optionset.has("port")) {
+ int port = (Integer) optionset.valueOf("port");
+ if (port > 0) {
+ dedicatedserver1.setPort(port);
+ }
+ }
+
return dedicatedserver1;
});
+ /* CraftBukkit start
Thread thread = new Thread("Server Shutdown Thread") {
public void run() {
dedicatedserver.halt(true);
@@ -259,6 +355,7 @@
thread.setUncaughtExceptionHandler(new DefaultUncaughtExceptionHandler(Main.LOGGER));
Runtime.getRuntime().addShutdownHook(thread);
+ */ // CraftBukkit end
} catch (Exception exception1) {
Main.LOGGER.error(LogUtils.FATAL_MARKER, "Failed to start the minecraft server", exception1);
}
@@ -295,7 +392,7 @@
}
public static void forceUpgrade(LevelStorageSource.LevelStorageAccess session, DataFixer dataFixer, boolean eraseCache, BooleanSupplier continueCheck, RegistryAccess dynamicRegistryManager, boolean recreateRegionFiles) {
- Main.LOGGER.info("Forcing world upgrade!");
+ Main.LOGGER.info("Forcing world upgrade! {}", session.getLevelId()); // CraftBukkit
WorldUpgrader worldupgrader = new WorldUpgrader(session, dataFixer, dynamicRegistryManager, eraseCache, recreateRegionFiles);
try {