Main.java
net.minecraft.server.Main
信息
- 全限定名:net.minecraft.server.Main
- 类型:public class
- 包:net.minecraft.server
- 源码路径:src/main/java/net/minecraft/server/Main.java
- 起始行号:L62
- 职责:
TODO
字段/常量
LOGGER- 类型:
Logger - 修饰符:
private static final - 源码定位:
L63 - 说明:
TODO
- 类型:
内部类/嵌套类型
- 无
构造器
- 无
方法
下面的方法块按源码顺序生成。
public static void main(String[] args) @ L65
- 方法名:main
- 源码定位:L65
- 返回类型:void
- 修饰符:public static
参数:
- args: String[]
说明:
TODO
private static WorldLoader.DataLoadOutput<LevelDataAndDimensions.WorldDataAndGenSettings> createNewWorldData(DedicatedServerSettings settings, WorldLoader.DataLoadContext context, Registry<LevelStem> datapackDimensions, boolean demoMode, boolean bonusChest) @ L231
- 方法名:createNewWorldData
- 源码定位:L231
- 返回类型:WorldLoader.DataLoadOutput<LevelDataAndDimensions.WorldDataAndGenSettings>
- 修饰符:private static
参数:
- settings: DedicatedServerSettings
- context: WorldLoader.DataLoadContext
- datapackDimensions: Registry
- demoMode: boolean
- bonusChest: boolean
说明:
TODO
private static void writePidFile(Path path) @ L263
- 方法名:writePidFile
- 源码定位:L263
- 返回类型:void
- 修饰符:private static
参数:
- path: Path
说明:
TODO
private static WorldLoader.InitConfig loadOrCreateConfig(DedicatedServerProperties properties, Dynamic<?> levelDataTag, boolean safeModeEnabled, PackRepository packRepository) @ L272
- 方法名:loadOrCreateConfig
- 源码定位:L272
- 返回类型:WorldLoader.InitConfig
- 修饰符:private static
参数:
- properties: DedicatedServerProperties
- levelDataTag: Dynamic<?>
- safeModeEnabled: boolean
- packRepository: PackRepository
说明:
TODO
private static void forceUpgrade(LevelStorageSource.LevelStorageAccess storageSource, DataFixer fixerUpper, boolean eraseCache, BooleanSupplier isRunning, RegistryAccess registryAccess, boolean recreateRegionFiles) @ L290
- 方法名:forceUpgrade
- 源码定位:L290
- 返回类型:void
- 修饰符:private static
参数:
- storageSource: LevelStorageSource.LevelStorageAccess
- fixerUpper: DataFixer
- eraseCache: boolean
- isRunning: BooleanSupplier
- registryAccess: RegistryAccess
- recreateRegionFiles: boolean
说明:
TODO
代码
public class Main {
private static final Logger LOGGER = LogUtils.getLogger();
@SuppressForbidden(reason = "System.out needed before bootstrap")
public static void main(String[] args) {
SharedConstants.tryDetectVersion();
OptionParser parser = new OptionParser();
OptionSpec<Void> nogui = parser.accepts("nogui");
OptionSpec<Void> initSettings = parser.accepts("initSettings", "Initializes 'server.properties' and 'eula.txt', then quits");
OptionSpec<Void> demo = parser.accepts("demo");
OptionSpec<Void> bonusChest = parser.accepts("bonusChest");
OptionSpec<Void> forceUpgrade = parser.accepts("forceUpgrade");
OptionSpec<Void> eraseCache = parser.accepts("eraseCache");
OptionSpec<Void> recreateRegionFiles = parser.accepts("recreateRegionFiles");
OptionSpec<Void> safeMode = parser.accepts("safeMode", "Loads level with vanilla datapack only");
OptionSpec<Void> help = parser.accepts("help").forHelp();
OptionSpec<String> universe = parser.accepts("universe").withRequiredArg().defaultsTo(".");
OptionSpec<String> worldName = parser.accepts("world").withRequiredArg();
OptionSpec<Integer> port = parser.accepts("port").withRequiredArg().ofType(Integer.class).defaultsTo(-1);
OptionSpec<String> serverId = parser.accepts("serverId").withRequiredArg();
OptionSpec<Void> jfrProfilingOption = parser.accepts("jfrProfile");
OptionSpec<Path> pidFile = parser.accepts("pidFile").withRequiredArg().withValuesConvertedBy(new PathConverter());
OptionSpec<String> nonOptions = parser.nonOptions();
try {
OptionSet options = parser.parse(args);
if (options.has(help)) {
parser.printHelpOn(System.err);
return;
}
Path pidFilePath = options.valueOf(pidFile);
if (pidFilePath != null) {
writePidFile(pidFilePath);
}
CrashReport.preload();
if (options.has(jfrProfilingOption)) {
JvmProfiler.INSTANCE.start(Environment.SERVER);
}
Bootstrap.bootStrap();
Bootstrap.validate();
Util.startTimerHackThread();
Path settingsFile = Paths.get("server.properties");
DedicatedServerSettings settings = new DedicatedServerSettings(settingsFile);
settings.forceSave();
RegionFileVersion.configure(settings.getProperties().regionFileComression);
Path eulaFile = Paths.get("eula.txt");
Eula eula = new Eula(eulaFile);
if (options.has(initSettings)) {
LOGGER.info("Initialized '{}' and '{}'", settingsFile.toAbsolutePath(), eulaFile.toAbsolutePath());
return;
}
if (!eula.hasAgreedToEULA()) {
LOGGER.info("You need to agree to the EULA in order to run the server. Go to eula.txt for more info.");
return;
}
File universePath = new File(options.valueOf(universe));
Services services = Services.create(new YggdrasilAuthenticationService(Proxy.NO_PROXY), universePath);
String levelName = Optional.ofNullable(options.valueOf(worldName)).orElse(settings.getProperties().levelName);
LevelStorageSource levelStorageSource = LevelStorageSource.createDefault(universePath.toPath());
LevelStorageSource.LevelStorageAccess access = levelStorageSource.validateAndCreateAccess(levelName);
Dynamic<?> levelDataTag;
if (access.hasWorldData()) {
Dynamic<?> levelDataUnfixed;
try {
levelDataUnfixed = access.getUnfixedDataTagWithFallback();
} catch (NbtException | ReportedNbtException | IOException var39) {
LOGGER.error("Failed to load world data. World files may be corrupted. Shutting down.", (Throwable)var39);
return;
}
LevelSummary summary = access.fixAndGetSummaryFromTag(levelDataUnfixed);
if (summary.requiresManualConversion()) {
LOGGER.info("This world must be opened in an older version (like 1.6.4) to be safely converted");
return;
}
if (!summary.isCompatible()) {
LOGGER.info("This world was created by an incompatible version.");
return;
}
levelDataTag = DataFixers.getFileFixer().fix(access, levelDataUnfixed, new UpgradeProgress());
} else {
levelDataTag = null;
}
boolean safeModeEnabled = options.has(safeMode);
if (safeModeEnabled) {
LOGGER.warn("Safe mode active, only vanilla datapack will be loaded");
}
PackRepository packRepository = ServerPacksSource.createPackRepository(access);
WorldStem worldStem;
try {
WorldLoader.InitConfig worldLoadConfig = loadOrCreateConfig(settings.getProperties(), levelDataTag, safeModeEnabled, packRepository);
worldStem = Util.<WorldStem>blockUntilDone(
executor -> WorldLoader.load(
worldLoadConfig,
context -> {
Registry<LevelStem> datapackDimensions = context.datapackDimensions().lookupOrThrow(Registries.LEVEL_STEM);
if (levelDataTag != null) {
LevelDataAndDimensions worldData = LevelStorageSource.getLevelDataAndDimensions(
access, levelDataTag, context.dataConfiguration(), datapackDimensions, context.datapackWorldgen()
);
return new WorldLoader.DataLoadOutput<>(
worldData.worldDataAndGenSettings(), worldData.dimensions().dimensionsRegistryAccess()
);
} else {
LOGGER.info("No existing world data, creating new world");
return createNewWorldData(settings, context, datapackDimensions, options.has(demo), options.has(bonusChest));
}
},
WorldStem::new,
Util.backgroundExecutor(),
executor
)
)
.get();
} catch (Exception var38) {
LOGGER.warn(
"Failed to load datapacks, can't proceed with server load. You can either fix your datapacks or reset to vanilla with --safeMode",
(Throwable)var38
);
return;
}
RegistryAccess.Frozen registryHolder = worldStem.registries().compositeAccess();
WorldData data = worldStem.worldDataAndGenSettings().data();
boolean recreateRegionFilesValue = options.has(recreateRegionFiles);
if (options.has(forceUpgrade) || recreateRegionFilesValue) {
forceUpgrade(access, DataFixers.getDataFixer(), options.has(eraseCache), () -> true, registryHolder, recreateRegionFilesValue);
}
access.saveDataTag(data);
final DedicatedServer dedicatedServer = MinecraftServer.spin(
thread -> {
DedicatedServer server = new DedicatedServer(
thread, access, packRepository, worldStem, Optional.empty(), settings, DataFixers.getDataFixer(), services
);
server.setPort(options.valueOf(port));
server.setDemo(options.has(demo));
server.setId(options.valueOf(serverId));
boolean gui = !options.has(nogui) && !options.valuesOf(nonOptions).contains("nogui");
if (gui && !GraphicsEnvironment.isHeadless()) {
server.showGui();
}
return server;
}
);
Thread shutdownThread = new Thread("Server Shutdown Thread") {
@Override
public void run() {
dedicatedServer.halt(true);
}
};
shutdownThread.setUncaughtExceptionHandler(new DefaultUncaughtExceptionHandler(LOGGER));
Runtime.getRuntime().addShutdownHook(shutdownThread);
} catch (Throwable var40) {
LOGGER.error(LogUtils.FATAL_MARKER, "Failed to start the minecraft server", var40);
}
}
private static WorldLoader.DataLoadOutput<LevelDataAndDimensions.WorldDataAndGenSettings> createNewWorldData(
DedicatedServerSettings settings, WorldLoader.DataLoadContext context, Registry<LevelStem> datapackDimensions, boolean demoMode, boolean bonusChest
) {
LevelSettings createLevelSettings;
WorldOptions worldOptions;
WorldDimensions dimensions;
if (demoMode) {
createLevelSettings = MinecraftServer.DEMO_SETTINGS;
worldOptions = WorldOptions.DEMO_OPTIONS;
dimensions = WorldPresets.createNormalWorldDimensions(context.datapackWorldgen());
} else {
DedicatedServerProperties properties = settings.getProperties();
createLevelSettings = new LevelSettings(
properties.levelName,
properties.gameMode.get(),
new LevelSettings.DifficultySettings(properties.difficulty.get(), properties.hardcore, false),
false,
context.dataConfiguration()
);
worldOptions = bonusChest ? properties.worldOptions.withBonusChest(true) : properties.worldOptions;
dimensions = properties.createDimensions(context.datapackWorldgen());
}
WorldDimensions.Complete finalDimensions = dimensions.bake(datapackDimensions);
Lifecycle lifecycle = finalDimensions.lifecycle().add(context.datapackWorldgen().allRegistriesLifecycle());
PrimaryLevelData primaryLevelData = new PrimaryLevelData(createLevelSettings, finalDimensions.specialWorldProperty(), lifecycle);
return new WorldLoader.DataLoadOutput<>(
new LevelDataAndDimensions.WorldDataAndGenSettings(primaryLevelData, new WorldGenSettings(worldOptions, dimensions)),
finalDimensions.dimensionsRegistryAccess()
);
}
private static void writePidFile(Path path) {
try {
long pid = ProcessHandle.current().pid();
Files.writeString(path, Long.toString(pid));
} catch (IOException var3) {
throw new UncheckedIOException(var3);
}
}
private static WorldLoader.InitConfig loadOrCreateConfig(
DedicatedServerProperties properties, @Nullable Dynamic<?> levelDataTag, boolean safeModeEnabled, PackRepository packRepository
) {
boolean initMode;
WorldDataConfiguration dataConfigToUse;
if (levelDataTag != null) {
WorldDataConfiguration storedConfiguration = LevelStorageSource.readDataConfig(levelDataTag);
initMode = false;
dataConfigToUse = storedConfiguration;
} else {
initMode = true;
dataConfigToUse = new WorldDataConfiguration(properties.initialDataPackConfiguration, FeatureFlags.DEFAULT_FLAGS);
}
WorldLoader.PackConfig packConfig = new WorldLoader.PackConfig(packRepository, dataConfigToUse, safeModeEnabled, initMode);
return new WorldLoader.InitConfig(packConfig, Commands.CommandSelection.DEDICATED, properties.functionPermissions);
}
private static void forceUpgrade(
LevelStorageSource.LevelStorageAccess storageSource,
DataFixer fixerUpper,
boolean eraseCache,
BooleanSupplier isRunning,
RegistryAccess registryAccess,
boolean recreateRegionFiles
) {
LOGGER.info("Forcing world upgrade!");
try (WorldUpgrader upgrader = new WorldUpgrader(storageSource, fixerUpper, registryAccess, eraseCache, recreateRegionFiles)) {
Component lastStatus = null;
while (!upgrader.isFinished()) {
Component status = upgrader.getStatus();
if (lastStatus != status) {
lastStatus = status;
LOGGER.info(upgrader.getStatus().getString());
}
int totalChunks = upgrader.getTotalChunks();
if (totalChunks > 0) {
int done = upgrader.getConverted() + upgrader.getSkipped();
LOGGER.info("{}% completed ({} / {} chunks)...", Mth.floor((float)done / totalChunks * 100.0F), done, totalChunks);
}
if (!isRunning.getAsBoolean()) {
upgrader.cancel();
} else {
try {
Thread.sleep(1000L);
} catch (InterruptedException var12) {
}
}
}
}
}
}引用的其他类
-
- 引用位置:
方法调用 - 关联成员:
CrashReport.preload()
- 引用位置:
-
DefaultUncaughtExceptionHandler
- 引用位置:
构造调用 - 关联成员:
DefaultUncaughtExceptionHandler()
- 引用位置:
-
- 引用位置:
方法调用 - 关联成员:
SharedConstants.tryDetectVersion()
- 引用位置:
-
- 引用位置:
参数
- 引用位置:
-
- 引用位置:
参数
- 引用位置:
-
- 引用位置:
方法调用 - 关联成员:
Bootstrap.bootStrap(), Bootstrap.validate()
- 引用位置:
-
- 引用位置:
构造调用 - 关联成员:
Eula()
- 引用位置:
-
- 引用位置:
方法调用 - 关联成员:
MinecraftServer.spin()
- 引用位置:
-
- 引用位置:
方法调用 - 关联成员:
Services.create()
- 引用位置:
-
- 引用位置:
参数/方法调用/构造调用/返回值 - 关联成员:
InitConfig(), PackConfig(), WorldLoader.InitConfig(), WorldLoader.PackConfig(), WorldLoader.load()
- 引用位置:
-
- 引用位置:
构造调用 - 关联成员:
DedicatedServer()
- 引用位置:
-
- 引用位置:
参数
- 引用位置:
-
- 引用位置:
参数/构造调用 - 关联成员:
DedicatedServerSettings()
- 引用位置:
-
- 引用位置:
参数
- 引用位置:
-
- 引用位置:
方法调用 - 关联成员:
ServerPacksSource.createPackRepository()
- 引用位置:
-
- 引用位置:
方法调用 - 关联成员:
Mth.floor()
- 引用位置:
-
- 引用位置:
方法调用 - 关联成员:
Util.backgroundExecutor(), Util.startTimerHackThread()
- 引用位置:
-
- 引用位置:
方法调用 - 关联成员:
DataFixers.getDataFixer(), DataFixers.getFileFixer()
- 引用位置:
-
- 引用位置:
构造调用 - 关联成员:
File()
- 引用位置:
-
- 引用位置:
构造调用 - 关联成员:
UpgradeProgress()
- 引用位置:
-
- 引用位置:
构造调用 - 关联成员:
WorldUpgrader()
- 引用位置:
-
- 引用位置:
参数
- 引用位置:
-
- 引用位置:
方法调用/构造调用 - 关联成员:
DifficultySettings(), LevelSettings(), LevelSettings.DifficultySettings()
- 引用位置:
-
- 引用位置:
构造调用 - 关联成员:
WorldDataConfiguration()
- 引用位置:
-
- 引用位置:
方法调用 - 关联成员:
RegionFileVersion.configure()
- 引用位置:
-
- 引用位置:
参数
- 引用位置:
-
- 引用位置:
构造调用 - 关联成员:
WorldGenSettings()
- 引用位置:
-
- 引用位置:
方法调用 - 关联成员:
WorldPresets.createNormalWorldDimensions()
- 引用位置:
-
- 引用位置:
方法调用/构造调用/返回值 - 关联成员:
LevelDataAndDimensions.WorldDataAndGenSettings(), WorldDataAndGenSettings()
- 引用位置:
-
- 引用位置:
参数/方法调用 - 关联成员:
LevelStorageSource.createDefault(), LevelStorageSource.getLevelDataAndDimensions(), LevelStorageSource.readDataConfig()
- 引用位置:
-
- 引用位置:
构造调用 - 关联成员:
PrimaryLevelData()
- 引用位置: