HytaleServer class

Пакет: com.hypixel.hytale.server.core

Файл: com/hypixel/hytale/server/core/HytaleServer.java

Поля (63)

МодификаторыТипИмя
final int DEFAULT_PORT
instance
return
return
return
return
return
return
return
return
return
ShutdownReason var1
OptionSet var1
UUID var1
Universe var1
LoadAssetEvent var1
List var1
List var10
float var11
List var11
PluginManifest var12
float var12
Message var12
HashMap var13
String var13
Message var14
HashMap var15
PluginManifest var16
HashMap var17
AssetModule var18
boolean var19
var19
SentryOptions var2
OperatingSystem var2
Throwable var2
var2
String var2
HashMap var20
User var21
HashMap var23
UUID var25
ServerAuthManager var26
SessionServiceClient.GameProfile var27
UUID var3
Throwable var3
String var3
Thread var3
Contexts var4
Thread var4
UpdateModule var4
String var4
double var4
HashMap var5
PluginManifest[] var5
ServerAuthManager var5
ServerManager var6
Universe var7
boolean var7
HashMap var8
List var8
boolean var9
var9
boolean var9

Методы (39)

МодификаторыВозвратСигнатура
private void bootvoid boot()
public void doneSetupvoid doneSetup(PluginBase var1)
public void doneStartvoid doneStart(PluginBase var1)
public void doneStopvoid doneStop(PluginBase var1)
for for(PluginManifest var9 : var5)
static HytaleServer getHytaleServer get()
public long getBootStartlong getBootStart()
public String getServerNameString getServerName()
if if(var3 != null)
if if(var6 != null)
if if(var7 != null)
if if(var18 != null)
if if(var25 != null)
if if(var27 != null)
if if(var1 != null)
if if(Constants.SINGLEPLAYER)
if if(var1 != null)
if if(!Constants.BOOTSTRAP)
if if(var7 || var9)
if if(!Constants.BOOTSTRAP)
if if(Constants.SINGLEPLAYER)
if if(Constants.FRESH_UNIVERSE)
if if(!Constants.BOOTSTRAP)
if if(var4 != null)
if if(var1 != ShutdownReason.SIGINT)
if if(Constants.SINGLEPLAYER)
if if(Constants.SINGLEPLAYER)
if if(Constants.SINGLEPLAYER)
public boolean isBootedboolean isBooted()
public boolean isBootingboolean isBooting()
public boolean isShuttingDownboolean isShuttingDown()
public void reportSaveProgressvoid reportSaveProgress(@Nonnull World var1, int var2, int var3)
public void reportSingleplayerStatusvoid reportSingleplayerStatus(@Nonnull Message var1)
public void reportSingleplayerStatusvoid reportSingleplayerStatus(@Nonnull Message var1, double var2)
public void sendSingleplayerProgressvoid sendSingleplayerProgress()
private void sendSingleplayerSignalvoid sendSingleplayerSignal(String var1)
void shutdown0void shutdown0(@Nonnull ShutdownReason var1)
public void shutdownServervoid shutdownServer()
public void shutdownServervoid shutdownServer(@Nonnull ShutdownReason var1)

Исходный код

Показать/скрыть
class="kw">package com.hypixel.hytale.server.core;

class="kw">import com.hypixel.hytale.assetstore.AssetPack;
class="kw">import com.hypixel.hytale.codec.Codec;
class="kw">import com.hypixel.hytale.codec.EmptyExtraInfo;
class="kw">import com.hypixel.hytale.common.plugin.PluginManifest;
class="kw">import com.hypixel.hytale.common.thread.HytaleForkJoinThreadFactory;
class="kw">import com.hypixel.hytale.common.util.FormatUtil;
class="kw">import com.hypixel.hytale.common.util.GCUtil;
class="kw">import com.hypixel.hytale.common.util.HardwareUtil;
class="kw">import com.hypixel.hytale.common.util.NetworkUtil;
class="kw">import com.hypixel.hytale.common.util.java.ManifestUtil;
class="kw">import com.hypixel.hytale.event.EventBus;
class="kw">import com.hypixel.hytale.logger.HytaleLogger;
class="kw">import com.hypixel.hytale.logger.backend.HytaleLogManager;
class="kw">import com.hypixel.hytale.logger.backend.HytaleLoggerBackend;
class="kw">import com.hypixel.hytale.math.util.MathUtil;
class="kw">import com.hypixel.hytale.math.util.TrigMathUtil;
class="kw">import com.hypixel.hytale.metrics.JVMMetrics;
class="kw">import com.hypixel.hytale.metrics.MetricsRegistry;
class="kw">import com.hypixel.hytale.plugin.early.EarlyPluginLoader;
class="kw">import com.hypixel.hytale.server.core.asset.AssetModule;
class="kw">import com.hypixel.hytale.server.core.asset.AssetRegistryLoader;
class="kw">import com.hypixel.hytale.server.core.asset.LoadAssetEvent;
class="kw">import com.hypixel.hytale.server.core.auth.ServerAuthManager;
class="kw">import com.hypixel.hytale.server.core.auth.SessionServiceClient;
class="kw">import com.hypixel.hytale.server.core.command.system.CommandManager;
class="kw">import com.hypixel.hytale.server.core.console.ConsoleSender;
class="kw">import com.hypixel.hytale.server.core.event.events.BootEvent;
class="kw">import com.hypixel.hytale.server.core.event.events.ShutdownEvent;
class="kw">import com.hypixel.hytale.server.core.io.ServerManager;
class="kw">import com.hypixel.hytale.server.core.io.netty.NettyUtil;
class="kw">import com.hypixel.hytale.server.core.modules.singleplayer.SingleplayerModule;
class="kw">import com.hypixel.hytale.server.core.plugin.JavaPlugin;
class="kw">import com.hypixel.hytale.server.core.plugin.PluginBase;
class="kw">import com.hypixel.hytale.server.core.plugin.PluginClassLoader;
class="kw">import com.hypixel.hytale.server.core.plugin.PluginManager;
class="kw">import com.hypixel.hytale.server.core.plugin.PluginState;
class="kw">import com.hypixel.hytale.server.core.schema.SchemaGenerator;
class="kw">import com.hypixel.hytale.server.core.universe.Universe;
class="kw">import com.hypixel.hytale.server.core.universe.datastore.DataStoreProvider;
class="kw">import com.hypixel.hytale.server.core.universe.datastore.DiskDataStoreProvider;
class="kw">import com.hypixel.hytale.server.core.universe.world.World;
class="kw">import com.hypixel.hytale.server.core.universe.world.WorldConfig;
class="kw">import com.hypixel.hytale.server.core.update.UpdateModule;
class="kw">import com.hypixel.hytale.server.core.util.concurrent.ThreadUtil;
class="kw">import io.netty.handler.codec.quic.Quic;
class="kw">import io.sentry.Sentry;
class="kw">import io.sentry.SentryOptions;
class="kw">import io.sentry.protocol.Contexts;
class="kw">import io.sentry.protocol.OperatingSystem;
class="kw">import io.sentry.protocol.User;
class="kw">import it.unimi.dsi.fastutil.objects.ObjectArrayList;
class="kw">import java.nio.file.Path;
class="kw">import java.time.Instant;
class="kw">import java.util.ArrayDeque;
class="kw">import java.util.HashMap;
class="kw">import java.util.List;
class="kw">import java.util.Map;
class="kw">import java.util.Objects;
class="kw">import java.util.UUID;
class="kw">import java.util.concurrent.Executors;
class="kw">import java.util.concurrent.ScheduledExecutorService;
class="kw">import java.util.concurrent.Semaphore;
class="kw">import java.util.concurrent.TimeUnit;
class="kw">import java.util.concurrent.atomic.AtomicBoolean;
class="kw">import java.util.concurrent.atomic.AtomicReference;
class="kw">import java.util.logging.Level;
class="kw">import javax.annotation.Nonnull;
class="kw">import javax.annotation.Nullable;
class="kw">import joptsimple.OptionSet;

class="kw">public class HytaleServer {
   class="kw">public class="kw">static class="kw">final int DEFAULT_PORT = 5520;
   class="kw">public class="kw">static class="kw">final ScheduledExecutorService SCHEDULED_EXECUTOR = Executors.newSingleThreadScheduledExecutor(ThreadUtil.daemon("Scheduler"));
   @Nonnull
   class="kw">public class="kw">static class="kw">final MetricsRegistry<HytaleServer> METRICS_REGISTRY = new MetricsRegistry<HytaleServer>()
      .register("Time", var0 -> Instant.now(), Codec.INSTANT)
      .register("Boot", var0 -> var0.boot, Codec.INSTANT)
      .register("BootStart", var0 -> var0.bootStart, Codec.LONG)
      .register("Booting", var0 -> var0.booting.get(), Codec.BOOLEAN)
      .register("ShutdownReason", var0 -> {
         ShutdownReason var1 = var0.shutdown.get();
         class="kw">return var1 == null ? null : var1.toString();
      }, Codec.STRING)
      .register("PluginManager", HytaleServer::getPluginManager, PluginManager.METRICS_REGISTRY)
      .register("Config", HytaleServer::getConfig, HytaleServerConfig.CODEC)
      .register("JVM", JVMMetrics.METRICS_REGISTRY);
   class="kw">private class="kw">static class="kw">final HytaleLogger LOGGER = HytaleLogger.forEnclosingClass();
   class="kw">private class="kw">static HytaleServer instance;
   class="kw">private class="kw">final Semaphore aliveLock = new Semaphore(0);
   class="kw">private class="kw">final AtomicBoolean booting = new AtomicBoolean(false);
   class="kw">private class="kw">final AtomicBoolean booted = new AtomicBoolean(false);
   class="kw">private class="kw">final AtomicReference<ShutdownReason> shutdown = new AtomicReference<>();
   class="kw">private class="kw">final EventBus eventBus = new EventBus(Options.getOptionSet().has(Options.EVENT_DEBUG));
   class="kw">private class="kw">final PluginManager pluginManager = new PluginManager();
   class="kw">private class="kw">final CommandManager commandManager = new CommandManager();
   @Nonnull
   class="kw">private class="kw">final HytaleServerConfig hytaleServerConfig;
   class="kw">private class="kw">final Instant boot;
   class="kw">private class="kw">final long bootStart;
   class="kw">private int pluginsProgress;

   class="kw">public HytaleServer() {
      instance = this;
      Quic.ensureAvailability();
      HytaleLoggerBackend.setIndent(25);
      ThreadUtil.forceTimeHighResolution();
      ThreadUtil.createKeepAliveThread(this.aliveLock);
      this.boot = Instant.now();
      this.bootStart = System.nanoTime();
      LOGGER.at(Level.INFO).log("Starting HytaleServer");
      Constants.init();
      DataStoreProvider.CODEC.register("Disk", DiskDataStoreProvider.class, DiskDataStoreProvider.CODEC);
      LOGGER.at(Level.INFO).log("Loading config...");
      this.hytaleServerConfig = HytaleServerConfig.load();
      HytaleLoggerBackend.reloadLogLevels();
      System.setProperty("java.util.concurrent.ForkJoinPool.common.threadFactory", HytaleForkJoinThreadFactory.class.getName());
      OptionSet var1 = Options.getOptionSet();
      LOGGER.at(Level.INFO).log("Authentication mode: %s", var1.valueOf(Options.AUTH_MODE));
      ServerAuthManager.getInstance().initialize();
      if (EarlyPluginLoader.hasTransformers()) {
         LOGGER.at(Level.INFO).log("Early plugins loaded!! Disabling Sentry!!");
      } else if (!ManifestUtil.isJar() || ManifestUtil.getVersion() == null) {
         LOGGER.at(Level.INFO).log("Sentry disabled: development build (no version)");
      } else if (!var1.has(Options.DISABLE_SENTRY)) {
         LOGGER.at(Level.INFO).log("Enabling Sentry");
         SentryOptions var2 = new SentryOptions();
         var2.setDsn("https://6043a13c7b5c45b5c834b6d896fb378e@sentry.hytale.com/4");
         var2.setRelease(ManifestUtil.getImplementationVersion());
         var2.setDist(ManifestUtil.getImplementationRevisionId());
         var2.setEnvironment("release");
         var2.setTag("patchline", ManifestUtil.getPatchline());
         var2.setServerName(NetworkUtil.getHostName());
         UUID var3 = HardwareUtil.getUUID();
         if (var3 != null) {
            var2.setDistinctId(var3.toString());
         }

         var2.setBeforeSend((var1x, var2x) -> {
            Throwable var3 = var1x.getThrowable();
            if (PluginClassLoader.isFromThirdPartyPlugin(var3)) {
               class="kw">return null;
            }

            Contexts var4 = var1x.getContexts();
            HashMap var5 = new HashMap<>();
            var5.put("name", this.getServerName());
            var5.put("max-players", this.getConfig().getMaxPlayers());
            ServerManager var6 = ServerManager.get();
            if (var6 != null) {
               var5.put("listeners", var6.getListeners().stream().map(Object::toString).toList());
            }

            var4.put("server", var5);
            Universe var7 = Universe.get();
            if (var7 != null) {
               HashMap var8 = new HashMap<>();
               var8.put("path", var7.getPath().toString());
               var8.put("player-count", var7.getPlayerCount());
               var8.put("worlds", var7.getWorlds().keySet().stream().toList());
               var4.put("universe", var8);
            }

            HashMap var17 = new HashMap<>();
            boolean var9 = false;

            for (PluginBase var11 : this.pluginManager.getPlugins()) {
               PluginManifest var12 = var11.getManifest();
               HashMap var13 = new HashMap<>();
               var13.put("version", var12.getVersion().toString());
               var13.put("state", var11.getState().name());
               var17.put(var11.getIdentifier().toString(), var13);
               if (var11 class="kw">instanceof JavaPlugin var14 && !var14.getClassLoader().isInServerClassPath()) {
                  var9 = true;
               }
            }

            var4.put("plugins", var17);
            AssetModule var18 = AssetModule.get();
            boolean var19 = false;
            if (var18 != null) {
               HashMap var20 = new HashMap<>();

               for (AssetPack var24 : var18.getAssetPacks()) {
                  HashMap var15 = new HashMap<>();
                  PluginManifest var16 = var24.getManifest();
                  if (var16 != null && var16.getVersion() != null) {
                     var15.put("version", var16.getVersion().toString());
                  }

                  var15.put("immutable", var24.isImmutable());
                  var20.put(var24.getName(), var15);
                  if (!var24.isImmutable()) {
                     var19 = true;
                  }
               }

               var4.put("packs", var20);
            }

            var1x.setTag("has-plugins", String.valueOf(var9));
            var1x.setTag("has-packs", String.valueOf(var19));
            User var21 = new User();
            HashMap var23 = new HashMap<>();
            var21.setUnknown(var23);
            UUID var25 = HardwareUtil.getUUID();
            if (var25 != null) {
               var23.put("hardware-uuid", var25.toString());
            }

            ServerAuthManager var26 = ServerAuthManager.getInstance();
            var23.put("auth-mode", var26.getAuthMode().toString());
            SessionServiceClient.GameProfile var27 = var26.getSelectedProfile();
            if (var27 != null) {
               var21.setUsername(var27.username);
               var21.setId(var27.uuid.toString());
            }

            var21.setIpAddress("{{auto}}");
            var1x.setUser(var21);
            class="kw">return var1x;
         });
         Sentry.init(var2);
         Sentry.startSession();
         Sentry.configureScope(
            var0 -> {
               UUID var1 = HardwareUtil.getUUID();
               if (var1 != null) {
                  var0.setContexts("hardware", Map.of("uuid", var1.toString()));
               }

               OperatingSystem var2 = new OperatingSystem();
               var2.setName(System.getProperty("os.name"));
               var2.setVersion(System.getProperty("os.version"));
               var0.getContexts().setOperatingSystem(var2);
               var0.setContexts(
                  "build",
                  Map.of(
                     "version",
                     String.valueOf(ManifestUtil.getImplementationVersion()),
                     "revision-id",
                     String.valueOf(ManifestUtil.getImplementationRevisionId()),
                     "patchline",
                     String.valueOf(ManifestUtil.getPatchline()),
                     "environment",
                     "release"
                  )
               );
               if (Constants.SINGLEPLAYER) {
                  var0.setContexts(
                     "singleplayer", Map.of("owner-uuid", String.valueOf(SingleplayerModule.getUuid()), "owner-name", SingleplayerModule.getUsername())
                  );
               }
            }
         );
         HytaleLogger.getLogger().setSentryClient(Sentry.getCurrentScopes());
      }

      ServerAuthManager.getInstance().checkPendingFatalError();
      NettyUtil.init();
      float var11 = TrigMathUtil.sin(0.0F);
      float var12 = TrigMathUtil.atan2(0.0F, 0.0F);
      Thread var4 = new Thread(() -> {
         if (this.shutdown.getAndSet(ShutdownReason.SIGINT) == null) {
            this.shutdown0(ShutdownReason.SIGINT);
         }
      }, "ShutdownHook");
      var4.setDaemon(false);
      if (!this.isShuttingDown()) {
         try {
            Runtime.getRuntime().addShutdownHook(var4);
         } catch (IllegalStateException var10) {
            if (!this.isShuttingDown()) {
               throw var10;
            }

            class="kw">return;
         }

         AssetRegistryLoader.init();
         PluginManifest[] var5 = Constants.BOOTSTRAP ? Constants.BOOTSTRAP_PLUGINS : Constants.CORE_PLUGINS;

         for (PluginManifest var9 : var5) {
            this.pluginManager.registerCorePlugin(var9);
         }

         GCUtil.register(var0 -> {
            Universe var1 = Universe.get();
            if (var1 != null) {
               for (World var3 : var1.getWorlds().values()) {
                  var3.markGCHasRun();
               }
            }
         });
         this.boot();
      }
   }

   @Nonnull
   class="kw">public EventBus getEventBus() {
      class="kw">return this.eventBus;
   }

   @Nonnull
   class="kw">public PluginManager getPluginManager() {
      class="kw">return this.pluginManager;
   }

   @Nonnull
   class="kw">public CommandManager getCommandManager() {
      class="kw">return this.commandManager;
   }

   @Nonnull
   class="kw">public HytaleServerConfig getConfig() {
      class="kw">return this.hytaleServerConfig;
   }

   class="kw">private void boot() {
      if (!this.booting.getAndSet(true)) {
         LOGGER.at(Level.INFO)
            .log("Booting up HytaleServer - Version: %s, Revision: %s", ManifestUtil.getImplementationVersion(), ManifestUtil.getImplementationRevisionId());

         try {
            this.pluginsProgress = 0;
            this.sendSingleplayerProgress();
            if (this.isShuttingDown()) {
               class="kw">return;
            }

            LOGGER.at(Level.INFO).log("Setup phase...");
            this.commandManager.registerCommands();
            this.pluginManager.setup();
            ServerAuthManager.getInstance().initializeCredentialStore();
            LOGGER.at(Level.INFO).log("Setup phase completed! Boot time %s", FormatUtil.nanosToString(System.nanoTime() - this.bootStart));
            if (this.isShuttingDown()) {
               class="kw">return;
            }

            if (!Constants.BOOTSTRAP) {
               LoadAssetEvent var1 = get().getEventBus().<Void, LoadAssetEvent>dispatchFor(LoadAssetEvent.class).dispatch(new LoadAssetEvent(this.bootStart));
               if (this.isShuttingDown()) {
                  class="kw">return;
               }

               if (var1.isShouldShutdown()) {
                  List var11 = var1.getReasons();
                  String var13 = String.join("\n", var11);
                  LOGGER.at(Level.SEVERE).log("Asset validation FAILED with %d reason(s):\n%s", var11.size(), var13);
                  Message var14 = Message.translation("client.disconnection.shutdownReason.validateError.detail").param("detail", var13);
                  this.shutdownServer(ShutdownReason.VALIDATE_ERROR.withMessage(var14));
                  class="kw">return;
               }
            }

            if (Options.getOptionSet().has(Options.SHUTDOWN_AFTER_VALIDATE)) {
               LOGGER.at(Level.INFO).log("Asset validation passed");
               this.shutdownServer(ShutdownReason.SHUTDOWN);
               class="kw">return;
            }

            SchemaGenerator.registerConfig("HytaleServerConfig", HytaleServerConfig.CODEC, "Config", List.of("/config.json"));
            SchemaGenerator.registerConfig("WorldConfig", WorldConfig.CODEC, "Config", List.of("/worlds/*/config.json"));
            boolean var7 = Options.getOptionSet().has(Options.GENERATE_ASSET_SCHEMA);
            boolean var9 = Options.getOptionSet().has(Options.GENERATE_CONFIG_SCHEMA);
            if (var7 || var9) {
               SchemaGenerator.generate(
                  var7 ? (Path)Options.getOptionSet().valueOf(Options.GENERATE_ASSET_SCHEMA) : null,
                  var9 ? (Path)Options.getOptionSet().valueOf(Options.GENERATE_CONFIG_SCHEMA) : null
               );
               Message var12 = Message.translation("client.disconnection.shutdownReason.shutdown.schemaGenerated");
               this.shutdownServer(ShutdownReason.SHUTDOWN.withMessage(var12));
               class="kw">return;
            }

            this.pluginsProgress = 0;
            this.sendSingleplayerProgress();
            if (this.isShuttingDown()) {
               class="kw">return;
            }

            LOGGER.at(Level.INFO).log("Starting plugin manager...");
            this.pluginManager.start();
            LOGGER.at(Level.INFO).log("Plugin manager started! Startup time so far: %s", FormatUtil.nanosToString(System.nanoTime() - this.bootStart));
            if (this.isShuttingDown()) {
               class="kw">return;
            }

            this.reportSingleplayerStatus(Message.translation("client.gameLoadingView.status.enabled"));
         } catch (Throwable var6) {
            ((HytaleLogger.Api)LOGGER.at(Level.SEVERE).withCause(var6)).log("Failed to boot HytaleServer!");
            Throwable var2 = var6;

            while (var2.getCause() != null) {
               var2 = var2.getCause();
            }

            this.shutdownServer(
               ShutdownReason.CRASH
                  .withMessage(Message.translation("client.disconnection.shutdownReason.crash.startFailed").param("detail", var2.getMessage()))
            );
         }

         if (this.hytaleServerConfig.consumeHasChanged()) {
            HytaleServerConfig.save(this.hytaleServerConfig).join();
         }

         if (!this.isShuttingDown()) {
            SCHEDULED_EXECUTOR.scheduleWithFixedDelay(() -> {
               try {
                  if (this.hytaleServerConfig.consumeHasChanged()) {
                     HytaleServerConfig.save(this.hytaleServerConfig).join();
                  }
               } catch (Exception var2) {
                  ((HytaleLogger.Api)LOGGER.at(Level.SEVERE).withCause(var2)).log("Failed to save server config!");
               }
            }, 1L, 1L, TimeUnit.MINUTES);
            if (!Constants.BOOTSTRAP) {
               LOGGER.at(Level.INFO).log("Getting Hytale Universe ready...");
               Universe.get().getUniverseReady().join();
               LOGGER.at(Level.INFO).log("Universe ready!");
            }

            List var8 = new ObjectArrayList();
            if (Constants.SINGLEPLAYER) {
               var8.add("Singleplayer");
            } else {
               var8.add("Multiplayer");
            }

            if (Constants.FRESH_UNIVERSE) {
               var8.add("Fresh Universe");
            }

            this.booted.set(true);
            if (!Constants.BOOTSTRAP) {
               ServerManager.get().waitForBindComplete();
            }

            this.eventBus.dispatch(BootEvent.class);
            List var10 = Options.getOptionSet().valuesOf(Options.BOOT_COMMAND);
            if (!var10.isEmpty()) {
               CommandManager.get().handleCommands(ConsoleSender.INSTANCE, new ArrayDeque<>(var10)).join();
            }

            String var3 = "\u001b[0;32m===============================================================================================";
            LOGGER.at(Level.INFO).log("\u001b[0;32m===============================================================================================");
            LOGGER.at(Level.INFO)
               .log(
                  "%s         Hytale Server Booted! [%s] took %s",
                  "\u001b[0;32m",
                  String.join(", ", var8),
                  FormatUtil.nanosToString(System.nanoTime() - this.bootStart)
               );
            LOGGER.at(Level.INFO).log("\u001b[0;32m===============================================================================================");
            UpdateModule var4 = UpdateModule.get();
            if (var4 != null) {
               var4.onServerReady();
            }

            ServerAuthManager var5 = ServerAuthManager.getInstance();
            if (!var5.isSingleplayer() && var5.getAuthMode() == ServerAuthManager.AuthMode.NONE) {
               LOGGER.at(Level.WARNING).log("%sNo server tokens configured. Use /auth login to authenticate.", "\u001b[0;31m");
            }

            this.sendSingleplayerSignal(">> Singleplayer Ready <<");
         }
      }
   }

   class="kw">public void shutdownServer() {
      this.shutdownServer(ShutdownReason.SHUTDOWN);
   }

   class="kw">public void shutdownServer(@Nonnull ShutdownReason var1) {
      Objects.requireNonNull(var1, "Server shutdown reason can't be null!");
      if (this.shutdown.getAndSet(var1) == null) {
         if (var1.getFormattedMessage() != null) {
            String var2 = Message.CODEC.encode(new Message(var1.getFormattedMessage()), EmptyExtraInfo.EMPTY).toString();
            this.sendSingleplayerSignal("-=|Shutdown|" + var2);
         }

         Thread var3 = new Thread(() -> this.shutdown0(var1), "ShutdownThread");
         var3.setDaemon(false);
         var3.start();
      }
   }

   void shutdown0(@Nonnull ShutdownReason var1) {
      LOGGER.at(Level.INFO).log("Shutdown triggered!!!");

      try {
         LOGGER.at(Level.INFO).log("Shutting down... %d  '%s'", var1.getExitCode(), var1.getMessage());
         this.eventBus.dispatch(ShutdownEvent.class);
         this.pluginManager.shutdown();
         this.commandManager.shutdown();
         this.eventBus.shutdown();
         ServerAuthManager.getInstance().shutdown();
         LOGGER.at(Level.INFO).log("Saving config...");
         if (this.hytaleServerConfig.consumeHasChanged()) {
            HytaleServerConfig.save(this.hytaleServerConfig).join();
         }

         LOGGER.at(Level.INFO).log("Shutdown completed!");
      } catch (Throwable var3) {
         ((HytaleLogger.Api)LOGGER.at(Level.SEVERE).withCause(var3)).log("Exception while shutting down:");
      }

      this.aliveLock.release();
      HytaleLogManager.resetFinally();
      Sentry.endSession();
      SCHEDULED_EXECUTOR.schedule(() -> {
         LOGGER.at(Level.SEVERE).log("Forcing shutdown!");
         Runtime.getRuntime().halt(var1.getExitCode());
      }, 3L, TimeUnit.SECONDS);
      if (var1 != ShutdownReason.SIGINT) {
         System.exit(var1.getExitCode());
      }
   }

   class="kw">public void doneSetup(PluginBase var1) {
      this.pluginsProgress++;
      this.sendSingleplayerProgress();
   }

   class="kw">public void doneStart(PluginBase var1) {
      this.pluginsProgress++;
      this.sendSingleplayerProgress();
   }

   class="kw">public void doneStop(PluginBase var1) {
      this.pluginsProgress--;
      this.sendSingleplayerProgress();
   }

   class="kw">public void sendSingleplayerProgress() {
      List var1 = this.pluginManager.getPlugins();
      if (this.shutdown.get() != null) {
         this.reportSingleplayerStatus(
            Message.translation("client.gameLoadingView.status.shuttingDownModules"),
            var1.isEmpty() ? 100.0 : MathUtil.round((double)(var1.size() - this.pluginsProgress) / var1.size(), 2) * 100.0
         );
      } else if (this.pluginManager.getState() == PluginState.SETUP) {
         this.reportSingleplayerStatus(
            Message.translation("client.gameLoadingView.status.settingUp"), MathUtil.round((double)this.pluginsProgress / var1.size(), 2) * 100.0
         );
      } else if (this.pluginManager.getState() == PluginState.START) {
         this.reportSingleplayerStatus(
            Message.translation("client.gameLoadingView.status.starting"), MathUtil.round((double)this.pluginsProgress / var1.size(), 2) * 100.0
         );
      }
   }

   class="kw">public String getServerName() {
      class="kw">return this.getConfig().getServerName();
   }

   class="kw">public boolean isBooting() {
      class="kw">return this.booting.get();
   }

   class="kw">public boolean isBooted() {
      class="kw">return this.booted.get();
   }

   class="kw">public boolean isShuttingDown() {
      class="kw">return this.shutdown.get() != null;
   }

   @Nonnull
   class="kw">public Instant getBoot() {
      class="kw">return this.boot;
   }

   class="kw">public long getBootStart() {
      class="kw">return this.bootStart;
   }

   @Nullable
   class="kw">public ShutdownReason getShutdownReason() {
      class="kw">return this.shutdown.get();
   }

   class="kw">private void sendSingleplayerSignal(String var1) {
      if (Constants.SINGLEPLAYER) {
         HytaleLoggerBackend.rawLog(var1);
      }
   }

   class="kw">public void reportSingleplayerStatus(@Nonnull Message var1) {
      this.reportSingleplayerStatus(var1, 0.0);
   }

   class="kw">public void reportSingleplayerStatus(@Nonnull Message var1, double var2) {
      if (Constants.SINGLEPLAYER) {
         String var4 = Message.CODEC.encode(var1, EmptyExtraInfo.EMPTY).toString();
         HytaleLoggerBackend.rawLog("-=|" + var4 + "|" + var2);
      }
   }

   class="kw">public void reportSaveProgress(@Nonnull World var1, int var2, int var3) {
      if (this.isShuttingDown()) {
         double var4 = MathUtil.round((double)var2 / var3, 2) * 100.0;
         if (Constants.SINGLEPLAYER) {
            this.reportSingleplayerStatus(Message.translation("client.gameLoadingView.status.savingChunks").param("name", var1.getName()), var4);
         } else if (var3 < 10 || var2 % (var3 / 10) == 0) {
            var1.getLogger().at(Level.INFO).log("Saving chunks: %.0f%%", var4);
         }
      }
   }

   class="kw">public class="kw">static HytaleServer get() {
      class="kw">return instance;
   }
}