Files
MinecraftForge/src/main/java/net/minecraftforge/server/ServerLifecycleHooks.java
T

222 lines
10 KiB
Java
Raw Normal View History

2018-06-21 15:37:32 -04:00
/*
* Copyright (c) Forge Development LLC and contributors
* SPDX-License-Identifier: LGPL-2.1-only
2018-06-21 15:37:32 -04:00
*/
2021-11-26 18:57:41 +00:00
package net.minecraftforge.server;
2018-06-21 15:37:32 -04:00
import static net.minecraftforge.fml.Logging.CORE;
import java.nio.file.Path;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Objects;
import java.util.Set;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.atomic.AtomicBoolean;
2020-06-19 10:58:45 -04:00
import java.util.function.Consumer;
import net.minecraft.core.Registry;
import net.minecraft.gametest.framework.GameTestServer;
2021-07-17 00:08:49 -05:00
import net.minecraft.server.packs.repository.PackSource;
import net.minecraft.server.packs.repository.RepositorySource;
2021-07-17 00:08:49 -05:00
import net.minecraft.world.level.storage.LevelResource;
import net.minecraftforge.fml.DistExecutor;
2021-11-26 18:57:41 +00:00
import net.minecraftforge.common.util.LogicalSidedProvider;
import net.minecraftforge.fml.ModLoader;
import net.minecraftforge.fml.ModLoadingStage;
import net.minecraftforge.fml.ModLoadingWarning;
2021-11-26 18:57:41 +00:00
import net.minecraftforge.network.ConnectionType;
import net.minecraftforge.network.NetworkConstants;
import net.minecraftforge.network.ServerStatusPing;
import net.minecraftforge.network.NetworkHooks;
import net.minecraftforge.network.NetworkRegistry;
2021-07-17 00:08:49 -05:00
import net.minecraftforge.forgespi.locating.IModFile;
import net.minecraftforge.resource.PathResourcePack;
2021-12-20 19:34:57 +01:00
import net.minecraftforge.server.permission.PermissionAPI;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.apache.logging.log4j.Marker;
import org.apache.logging.log4j.MarkerManager;
2021-07-17 00:08:49 -05:00
import net.minecraft.network.Connection;
import net.minecraft.network.ConnectionProtocol;
import net.minecraft.network.protocol.handshake.ClientIntentionPacket;
import net.minecraft.network.protocol.login.ClientboundLoginDisconnectPacket;
import net.minecraft.resources.ResourceKey;
2021-07-17 00:08:49 -05:00
import net.minecraft.server.packs.repository.Pack;
2018-06-21 15:37:32 -04:00
import net.minecraft.server.MinecraftServer;
2021-07-17 00:08:49 -05:00
import net.minecraft.network.chat.TextComponent;
import net.minecraftforge.api.distmarker.Dist;
2018-06-21 15:37:32 -04:00
import net.minecraftforge.common.MinecraftForge;
2019-01-28 22:42:37 -05:00
import net.minecraftforge.fml.config.ConfigTracker;
import net.minecraftforge.fml.config.ModConfig;
2021-11-26 18:57:41 +00:00
import net.minecraftforge.event.server.ServerAboutToStartEvent;
import net.minecraftforge.event.server.ServerStartedEvent;
import net.minecraftforge.event.server.ServerStartingEvent;
import net.minecraftforge.event.server.ServerStoppedEvent;
import net.minecraftforge.event.server.ServerStoppingEvent;
2019-01-28 22:42:37 -05:00
import net.minecraftforge.fml.loading.FileUtils;
import net.minecraftforge.forgespi.language.IModInfo;
import net.minecraftforge.registries.DataPackRegistriesHooks;
import net.minecraftforge.registries.GameData;
2018-06-21 15:37:32 -04:00
public class ServerLifecycleHooks
{
2018-08-27 13:10:07 -04:00
private static final Logger LOGGER = LogManager.getLogger();
2018-06-21 15:37:32 -04:00
private static final Marker SERVERHOOKS = MarkerManager.getMarker("SERVERHOOKS");
2021-07-17 00:08:49 -05:00
private static final LevelResource SERVERCONFIG = new LevelResource("serverconfig");
2018-06-21 15:37:32 -04:00
private static volatile CountDownLatch exitLatch = null;
private static MinecraftServer currentServer;
private static Path getServerConfigPath(final MinecraftServer server)
{
final Path serverConfig = server.getWorldPath(SERVERCONFIG);
FileUtils.getOrCreateDirectory(serverConfig, "serverconfig");
return serverConfig;
}
2018-06-21 15:37:32 -04:00
public static boolean handleServerAboutToStart(final MinecraftServer server)
{
currentServer = server;
2021-11-26 18:57:41 +00:00
currentServer.getStatus().setForgeData(new ServerStatusPing()); //gathers NetworkRegistry data
// on the dedi server we need to force the stuff to setup properly
2018-06-22 22:45:01 -04:00
LogicalSidedProvider.setServer(()->server);
ConfigTracker.INSTANCE.loadConfigs(ModConfig.Type.SERVER, getServerConfigPath(server));
2021-11-26 18:57:41 +00:00
return !MinecraftForge.EVENT_BUS.post(new ServerAboutToStartEvent(server));
2018-06-21 15:37:32 -04:00
}
public static boolean handleServerStarting(final MinecraftServer server)
{
DistExecutor.runWhenOn(Dist.DEDICATED_SERVER, ()->()->{
LanguageHook.loadLanguagesOnServer(server);
// GameTestServer requires the gametests to be registered earlier, so it is done in main and should not be done twice.
if (!(server instanceof GameTestServer))
net.minecraftforge.gametest.ForgeGameTestHooks.registerGametests();
});
2021-12-20 19:34:57 +01:00
PermissionAPI.initializePermissionAPI();
2021-11-26 18:57:41 +00:00
return !MinecraftForge.EVENT_BUS.post(new ServerStartingEvent(server));
2018-06-21 15:37:32 -04:00
}
public static void handleServerStarted(final MinecraftServer server)
2018-06-21 15:37:32 -04:00
{
2021-11-26 18:57:41 +00:00
MinecraftForge.EVENT_BUS.post(new ServerStartedEvent(server));
2018-06-21 15:37:32 -04:00
allowLogins.set(true);
}
public static void handleServerStopping(final MinecraftServer server)
2018-06-21 15:37:32 -04:00
{
allowLogins.set(false);
2021-11-26 18:57:41 +00:00
MinecraftForge.EVENT_BUS.post(new ServerStoppingEvent(server));
2018-06-21 15:37:32 -04:00
}
public static void expectServerStopped()
{
exitLatch = new CountDownLatch(1);
}
public static void handleServerStopped(final MinecraftServer server)
{
if (!server.isDedicatedServer()) GameData.revertToFrozen();
2021-11-26 18:57:41 +00:00
MinecraftForge.EVENT_BUS.post(new ServerStoppedEvent(server));
2018-06-21 15:37:32 -04:00
currentServer = null;
2018-06-22 22:45:01 -04:00
LogicalSidedProvider.setServer(null);
2018-06-21 15:37:32 -04:00
CountDownLatch latch = exitLatch;
if (latch != null)
{
latch.countDown();
exitLatch = null;
}
ConfigTracker.INSTANCE.unloadConfigs(ModConfig.Type.SERVER, getServerConfigPath(server));
2018-06-21 15:37:32 -04:00
}
public static MinecraftServer getCurrentServer()
{
return currentServer;
}
private static AtomicBoolean allowLogins = new AtomicBoolean(false);
2021-07-17 00:08:49 -05:00
public static boolean handleServerLogin(final ClientIntentionPacket packet, final Connection manager) {
2018-06-21 15:37:32 -04:00
if (!allowLogins.get())
{
2021-07-17 00:08:49 -05:00
TextComponent text = new TextComponent("Server is still starting! Please wait before reconnecting.");
LOGGER.info(SERVERHOOKS,"Disconnecting Player (server is still starting): {}", text.getContents());
2021-07-17 00:08:49 -05:00
manager.send(new ClientboundLoginDisconnectPacket(text));
manager.disconnect(text);
2018-06-21 15:37:32 -04:00
return false;
}
2021-07-17 00:08:49 -05:00
if (packet.getIntention() == ConnectionProtocol.LOGIN) {
final ConnectionType connectionType = ConnectionType.forVersionFlag(packet.getFMLVersion());
final int versionNumber = connectionType.getFMLVersionNumber(packet.getFMLVersion());
if (connectionType == ConnectionType.MODDED)
{
// Allow clients with incorrect netcode version to connect to netversion 3 servers,
// if and only if client is netversion 2 and server has no syncable non-vanilla datapack registries.
// TODO 1.19: Remove netcode backwards-compatability in 1.19, as there will be no clients on netversion 2 in 1.19.
Set<ResourceKey<? extends Registry<?>>> customDatapackRegistries = DataPackRegistriesHooks.getSyncedCustomRegistries();
if (versionNumber == 2)
{
if (!customDatapackRegistries.isEmpty())
{
rejectConnection(manager, connectionType, "Missing required datapack registries: " + String.join(", ", customDatapackRegistries.stream().map(key -> key.location().toString()).toList()));
return false;
}
}
else if (versionNumber != NetworkConstants.FMLNETVERSION)
{
rejectConnection(manager, connectionType, "This modded server is not impl compatible with your modded client. Please verify your Forge version closely matches the server. Got net version "+ versionNumber + " this server is net version "+ NetworkConstants.FMLNETVERSION);
return false;
}
}
if (connectionType == ConnectionType.VANILLA && !NetworkRegistry.acceptsVanillaClientConnections()) {
rejectConnection(manager, connectionType, "This server has mods that require Forge to be installed on the client. Contact your server admin for more details.");
return false;
}
2018-06-21 15:37:32 -04:00
}
2021-07-17 00:08:49 -05:00
if (packet.getIntention() == ConnectionProtocol.STATUS) return true;
2018-09-04 20:23:45 -04:00
NetworkHooks.registerServerLoginChannel(manager, packet);
2018-06-21 15:37:32 -04:00
return true;
}
2021-07-17 00:08:49 -05:00
private static void rejectConnection(final Connection manager, ConnectionType type, String message) {
manager.setProtocol(ConnectionProtocol.LOGIN);
2019-06-08 10:45:28 -04:00
LOGGER.info(SERVERHOOKS, "Disconnecting {} connection attempt: {}", type, message);
2021-07-17 00:08:49 -05:00
TextComponent text = new TextComponent(message);
manager.send(new ClientboundLoginDisconnectPacket(text));
manager.disconnect(text);
}
public static void handleExit(int retVal)
2018-06-21 15:37:32 -04:00
{
System.exit(retVal);
}
2020-06-23 20:56:24 -04:00
//INTERNAL MODDERS DO NOT USE
2021-11-26 18:57:41 +00:00
public static RepositorySource buildPackFinder(Map<IModFile, ? extends PathResourcePack> modResourcePacks) {
return (packList, factory) -> serverPackFinder(modResourcePacks, packList, factory);
}
private static void serverPackFinder(Map<IModFile, ? extends PathResourcePack> modResourcePacks, Consumer<Pack> consumer, Pack.PackConstructor factory) {
for (Entry<IModFile, ? extends PathResourcePack> e : modResourcePacks.entrySet())
{
IModInfo mod = e.getKey().getModInfos().get(0);
if (Objects.equals(mod.getModId(), "minecraft")) continue; // skip the minecraft "mod"
final String name = "mod:" + mod.getModId();
2021-07-17 00:08:49 -05:00
final Pack packInfo = Pack.create(name, false, e::getValue, factory, Pack.Position.BOTTOM, PackSource.DEFAULT);
if (packInfo == null) {
// Vanilla only logs an error, instead of propagating, so handle null and warn that something went wrong
ModLoader.get().addWarning(new ModLoadingWarning(mod, ModLoadingStage.ERROR, "fml.modloading.brokenresources", e.getKey()));
continue;
}
LOGGER.debug(CORE, "Generating PackInfo named {} for mod file {}", name, e.getKey().getFilePath());
2020-06-19 10:58:45 -04:00
consumer.accept(packInfo);
}
}
2018-06-21 15:37:32 -04:00
}