mirror of
https://github.com/GeyserMC/Geyser.git
synced 2024-08-14 23:57:35 +00:00
Feature: Rework startup logic (#4377)
* This makes `geyser reload` work the same across all platforms. For example, it ensures that we reload the config to the greatest extent possible (with the exception of compression/injection settings). Additionally, this clears up issues where Extensions were previously disabled during reloading - instead, the new Pre and Post reload events allow extensions to reload whatever necessary on their own.
This commit is contained in:
parent
19c6648bc2
commit
6a51d8298f
18 changed files with 539 additions and 358 deletions
|
@ -44,14 +44,28 @@ public interface GeyserBootstrap {
|
|||
GeyserWorldManager DEFAULT_CHUNK_MANAGER = new GeyserWorldManager();
|
||||
|
||||
/**
|
||||
* Called when the GeyserBootstrap is enabled
|
||||
* Called when the GeyserBootstrap is initialized.
|
||||
* This will only be called once, when Geyser is loading. Calling this must
|
||||
* happen before {@link #onGeyserEnable()}, since this "sets up" Geyser.
|
||||
*/
|
||||
void onEnable();
|
||||
void onGeyserInitialize();
|
||||
|
||||
/**
|
||||
* Called when the GeyserBootstrap is disabled
|
||||
* Called when the GeyserBootstrap is enabled/reloaded.
|
||||
* This starts Geyser, after which, Geyser is in a player-accepting state.
|
||||
*/
|
||||
void onDisable();
|
||||
void onGeyserEnable();
|
||||
|
||||
/**
|
||||
* Called when the GeyserBootstrap is disabled - either before a reload,
|
||||
* of before fully shutting down.
|
||||
*/
|
||||
void onGeyserDisable();
|
||||
|
||||
/**
|
||||
* Called when the GeyserBootstrap is shutting down.
|
||||
*/
|
||||
void onGeyserShutdown();
|
||||
|
||||
/**
|
||||
* Returns the current GeyserConfiguration
|
||||
|
|
|
@ -58,9 +58,7 @@ import org.geysermc.floodgate.news.NewsItemAction;
|
|||
import org.geysermc.geyser.api.GeyserApi;
|
||||
import org.geysermc.geyser.api.event.EventBus;
|
||||
import org.geysermc.geyser.api.event.EventRegistrar;
|
||||
import org.geysermc.geyser.api.event.lifecycle.GeyserPostInitializeEvent;
|
||||
import org.geysermc.geyser.api.event.lifecycle.GeyserPreInitializeEvent;
|
||||
import org.geysermc.geyser.api.event.lifecycle.GeyserShutdownEvent;
|
||||
import org.geysermc.geyser.api.event.lifecycle.*;
|
||||
import org.geysermc.geyser.api.network.AuthType;
|
||||
import org.geysermc.geyser.api.network.BedrockListener;
|
||||
import org.geysermc.geyser.api.network.RemoteServer;
|
||||
|
@ -145,6 +143,7 @@ public class GeyserImpl implements GeyserApi {
|
|||
|
||||
private UnixSocketClientListener erosionUnixListener;
|
||||
|
||||
@Setter
|
||||
private volatile boolean shuttingDown = false;
|
||||
|
||||
private ScheduledExecutorService scheduledThread;
|
||||
|
@ -162,8 +161,14 @@ public class GeyserImpl implements GeyserApi {
|
|||
@Getter(AccessLevel.NONE)
|
||||
private Map<String, String> savedRefreshTokens;
|
||||
|
||||
@Getter
|
||||
private static GeyserImpl instance;
|
||||
|
||||
/**
|
||||
* Determines if we're currently reloading. Replaces per-bootstrap reload checks
|
||||
*/
|
||||
private volatile boolean isReloading;
|
||||
|
||||
private GeyserImpl(PlatformType platformType, GeyserBootstrap bootstrap) {
|
||||
instance = this;
|
||||
|
||||
|
@ -172,13 +177,16 @@ public class GeyserImpl implements GeyserApi {
|
|||
this.platformType = platformType;
|
||||
this.bootstrap = bootstrap;
|
||||
|
||||
GeyserLocale.finalizeDefaultLocale(this);
|
||||
|
||||
/* Initialize event bus */
|
||||
this.eventBus = new GeyserEventBus();
|
||||
|
||||
/* Load Extensions */
|
||||
/* Create Extension Manager */
|
||||
this.extensionManager = new GeyserExtensionManager();
|
||||
|
||||
/* Finalize locale loading now that we know the default locale from the config */
|
||||
GeyserLocale.finalizeDefaultLocale(this);
|
||||
|
||||
/* Load Extensions */
|
||||
this.extensionManager.init();
|
||||
this.eventBus.fire(new GeyserPreInitializeEvent(this.extensionManager, this.eventBus));
|
||||
}
|
||||
|
@ -236,11 +244,17 @@ public class GeyserImpl implements GeyserApi {
|
|||
} else if (config.getRemote().authType() == AuthType.FLOODGATE) {
|
||||
VersionCheckUtils.checkForOutdatedFloodgate(logger);
|
||||
}
|
||||
|
||||
VersionCheckUtils.checkForOutdatedJava(logger);
|
||||
}
|
||||
|
||||
private void startInstance() {
|
||||
this.scheduledThread = Executors.newSingleThreadScheduledExecutor(new DefaultThreadFactory("Geyser Scheduled Thread"));
|
||||
|
||||
if (isReloading) {
|
||||
// If we're reloading, the default locale in the config might have changed.
|
||||
GeyserLocale.finalizeDefaultLocale(this);
|
||||
}
|
||||
GeyserLogger logger = bootstrap.getGeyserLogger();
|
||||
GeyserConfiguration config = bootstrap.getGeyserConfig();
|
||||
|
||||
|
@ -536,12 +550,15 @@ public class GeyserImpl implements GeyserApi {
|
|||
|
||||
newsHandler.handleNews(null, NewsItemAction.ON_SERVER_STARTED);
|
||||
|
||||
this.eventBus.fire(new GeyserPostInitializeEvent(this.extensionManager, this.eventBus));
|
||||
if (isReloading) {
|
||||
this.eventBus.fire(new GeyserPostReloadEvent(this.extensionManager, this.eventBus));
|
||||
} else {
|
||||
this.eventBus.fire(new GeyserPostInitializeEvent(this.extensionManager, this.eventBus));
|
||||
}
|
||||
|
||||
if (config.isNotifyOnNewBedrockUpdate()) {
|
||||
VersionCheckUtils.checkForGeyserUpdate(this::getLogger);
|
||||
}
|
||||
|
||||
VersionCheckUtils.checkForOutdatedJava(logger);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -600,9 +617,8 @@ public class GeyserImpl implements GeyserApi {
|
|||
return session.transfer(address, port);
|
||||
}
|
||||
|
||||
public void shutdown() {
|
||||
public void disable() {
|
||||
bootstrap.getGeyserLogger().info(GeyserLocale.getLocaleStringLog("geyser.core.shutdown"));
|
||||
shuttingDown = true;
|
||||
|
||||
if (sessionManager.size() >= 1) {
|
||||
bootstrap.getGeyserLogger().info(GeyserLocale.getLocaleStringLog("geyser.core.shutdown.kick.log", sessionManager.size()));
|
||||
|
@ -616,7 +632,6 @@ public class GeyserImpl implements GeyserApi {
|
|||
skinUploader.close();
|
||||
}
|
||||
newsHandler.shutdown();
|
||||
this.commandManager().getCommands().clear();
|
||||
|
||||
if (this.erosionUnixListener != null) {
|
||||
this.erosionUnixListener.close();
|
||||
|
@ -624,16 +639,29 @@ public class GeyserImpl implements GeyserApi {
|
|||
|
||||
Registries.RESOURCE_PACKS.get().clear();
|
||||
|
||||
bootstrap.getGeyserLogger().info(GeyserLocale.getLocaleStringLog("geyser.core.shutdown.done"));
|
||||
}
|
||||
|
||||
public void shutdown() {
|
||||
shuttingDown = true;
|
||||
this.disable();
|
||||
this.commandManager().getCommands().clear();
|
||||
|
||||
// Disable extensions, fire the shutdown event
|
||||
this.eventBus.fire(new GeyserShutdownEvent(this.extensionManager, this.eventBus));
|
||||
this.extensionManager.disableExtensions();
|
||||
|
||||
bootstrap.getGeyserLogger().info(GeyserLocale.getLocaleStringLog("geyser.core.shutdown.done"));
|
||||
}
|
||||
|
||||
public void reload() {
|
||||
shutdown();
|
||||
this.extensionManager.enableExtensions();
|
||||
bootstrap.onEnable();
|
||||
public void reloadGeyser() {
|
||||
isReloading = true;
|
||||
this.eventBus.fire(new GeyserPreReloadEvent(this.extensionManager, this.eventBus));
|
||||
|
||||
bootstrap.onGeyserDisable();
|
||||
bootstrap.onGeyserEnable();
|
||||
|
||||
isReloading = false;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -744,9 +772,7 @@ public class GeyserImpl implements GeyserApi {
|
|||
throw new RuntimeException("Geyser has not been loaded yet!");
|
||||
}
|
||||
|
||||
// We've been reloaded
|
||||
if (instance.isShuttingDown()) {
|
||||
instance.shuttingDown = false;
|
||||
if (getInstance().isReloading()) {
|
||||
instance.startInstance();
|
||||
} else {
|
||||
instance.initialize();
|
||||
|
@ -797,8 +823,4 @@ public class GeyserImpl implements GeyserApi {
|
|||
}
|
||||
});
|
||||
}
|
||||
|
||||
public static GeyserImpl getInstance() {
|
||||
return instance;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -86,7 +86,7 @@ public class GeyserCommandManager {
|
|||
registerBuiltInCommand(new StopCommand(geyser, "stop", "geyser.commands.stop.desc", "geyser.command.stop"));
|
||||
}
|
||||
|
||||
if (this.geyser.extensionManager().extensions().size() > 0) {
|
||||
if (!this.geyser.extensionManager().extensions().isEmpty()) {
|
||||
registerBuiltInCommand(new ExtensionsCommand(this.geyser, "extensions", "geyser.commands.extensions.desc", "geyser.command.extensions"));
|
||||
}
|
||||
|
||||
|
|
|
@ -55,7 +55,7 @@ public class ReloadCommand extends GeyserCommand {
|
|||
|
||||
geyser.getSessionManager().disconnectAll("geyser.commands.reload.kick");
|
||||
//FIXME Without the tiny wait, players do not get kicked - same happens when Geyser tries to disconnect all sessions on shutdown
|
||||
geyser.getScheduledThread().schedule(geyser::reload, 10, TimeUnit.MILLISECONDS);
|
||||
geyser.getScheduledThread().schedule(geyser::reloadGeyser, 10, TimeUnit.MILLISECONDS);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -52,7 +52,7 @@ public class StopCommand extends GeyserCommand {
|
|||
return;
|
||||
}
|
||||
|
||||
geyser.getBootstrap().onDisable();
|
||||
geyser.getBootstrap().onGeyserShutdown();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -166,7 +166,7 @@ public class UpstreamPacketHandler extends LoggingPacketHandler {
|
|||
|
||||
@Override
|
||||
public PacketSignal handle(LoginPacket loginPacket) {
|
||||
if (geyser.isShuttingDown()) {
|
||||
if (geyser.isShuttingDown() || geyser.isReloading()) {
|
||||
// Don't allow new players in if we're no longer operating
|
||||
session.disconnect(GeyserLocale.getLocaleStringLog("geyser.core.shutdown.kick.message"));
|
||||
return PacketSignal.HANDLED;
|
||||
|
|
|
@ -62,7 +62,7 @@ public final class ScoreboardUpdater extends Thread {
|
|||
|
||||
@Override
|
||||
public void run() {
|
||||
while (!geyser.isShuttingDown()) {
|
||||
while (!geyser.isShuttingDown() && !geyser.isReloading()) {
|
||||
try {
|
||||
long timeTillAction = getTimeTillNextAction();
|
||||
if (timeTillAction > 0) {
|
||||
|
|
|
@ -266,6 +266,7 @@ public final class EntityUtils {
|
|||
* Convert Java GameMode to Bedrock GameType
|
||||
* Needed to account for ordinal differences (spectator is 3 in Java, 6 in Bedrock)
|
||||
*/
|
||||
@SuppressWarnings("deprecation") // Must use survival_viewer due to limitations on Bedrock's spectator gamemode
|
||||
public static GameType toBedrockGamemode(GameMode gamemode) {
|
||||
return switch (gamemode) {
|
||||
case CREATIVE -> GameType.CREATIVE;
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue