2018-06-21 19:37:32 +00:00
/ *
* Minecraft Forge
2020-07-02 17:49:11 +00:00
* Copyright ( c ) 2016 - 2020 .
2018-06-21 19:37:32 +00:00
*
* This library is free software ; you can redistribute it and / or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation version 2 . 1
* of the License .
*
* This library is distributed in the hope that it will be useful ,
* but WITHOUT ANY WARRANTY ; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the GNU
* Lesser General Public License for more details .
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library ; if not , write to the Free Software
* Foundation , Inc . , 51 Franklin Street , Fifth Floor , Boston , MA 02110 - 1301 USA
* /
2018-08-27 17:10:07 +00:00
package net.minecraftforge.fml.server ;
2018-06-21 19:37:32 +00:00
2019-10-04 21:16:36 +00: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.concurrent.CountDownLatch ;
import java.util.concurrent.atomic.AtomicBoolean ;
import java.util.function.BiConsumer ;
2020-06-19 14:58:45 +00:00
import java.util.function.Consumer ;
2019-10-04 21:16:36 +00:00
2020-06-19 14:58:45 +00:00
import net.minecraft.resources.IPackNameDecorator ;
2020-06-24 00:56:24 +00:00
import net.minecraft.world.storage.FolderName ;
2020-06-30 02:08:50 +00:00
import net.minecraftforge.fml.DistExecutor ;
import net.minecraftforge.fml.LogicalSidedProvider ;
import net.minecraftforge.fml.ModLoader ;
import net.minecraftforge.fml.ModLoadingStage ;
import net.minecraftforge.fml.ModLoadingWarning ;
import net.minecraftforge.fml.network.ConnectionType ;
import net.minecraftforge.fml.network.FMLNetworkConstants ;
import net.minecraftforge.fml.network.FMLStatusPing ;
import net.minecraftforge.fml.network.NetworkHooks ;
import net.minecraftforge.fml.network.NetworkRegistry ;
2019-10-04 21:16:36 +00:00
import org.apache.logging.log4j.LogManager ;
import org.apache.logging.log4j.Logger ;
import org.apache.logging.log4j.Marker ;
import org.apache.logging.log4j.MarkerManager ;
2018-06-21 19:37:32 +00:00
import net.minecraft.network.NetworkManager ;
2019-10-04 21:16:36 +00:00
import net.minecraft.network.ProtocolType ;
2019-05-23 23:02:15 +00:00
import net.minecraft.network.handshake.client.CHandshakePacket ;
import net.minecraft.network.login.server.SDisconnectLoginPacket ;
2019-10-04 19:24:15 +00:00
import net.minecraft.resources.ResourcePackInfo ;
2018-06-21 19:37:32 +00:00
import net.minecraft.server.MinecraftServer ;
2019-05-23 23:02:15 +00:00
import net.minecraft.util.text.StringTextComponent ;
2018-10-06 01:42:15 +00:00
import net.minecraftforge.api.distmarker.Dist ;
2018-06-21 19:37:32 +00:00
import net.minecraftforge.common.MinecraftForge ;
2019-01-29 03:42:37 +00:00
import net.minecraftforge.fml.config.ConfigTracker ;
import net.minecraftforge.fml.config.ModConfig ;
2019-01-15 03:32:43 +00:00
import net.minecraftforge.fml.event.server.FMLServerAboutToStartEvent ;
import net.minecraftforge.fml.event.server.FMLServerStartedEvent ;
2019-10-04 21:16:36 +00:00
import net.minecraftforge.fml.event.server.FMLServerStartingEvent ;
2019-01-15 03:32:43 +00:00
import net.minecraftforge.fml.event.server.FMLServerStoppedEvent ;
import net.minecraftforge.fml.event.server.FMLServerStoppingEvent ;
2019-01-29 03:42:37 +00:00
import net.minecraftforge.fml.loading.FileUtils ;
2019-10-04 19:24:15 +00:00
import net.minecraftforge.fml.loading.moddiscovery.ModFile ;
import net.minecraftforge.fml.packs.ModFileResourcePack ;
2018-10-06 01:42:15 +00:00
import net.minecraftforge.fml.packs.ResourcePackLoader ;
2019-10-04 19:24:15 +00:00
import net.minecraftforge.forgespi.language.IModInfo ;
2020-09-27 17:09:31 +00:00
import net.minecraftforge.network.VanillaConnectionNetworkFilter ;
2020-02-03 20:21:10 +00:00
import net.minecraftforge.registries.GameData ;
2018-06-21 19:37:32 +00:00
public class ServerLifecycleHooks
{
2018-08-27 17:10:07 +00:00
private static final Logger LOGGER = LogManager . getLogger ( ) ;
2018-06-21 19:37:32 +00:00
private static final Marker SERVERHOOKS = MarkerManager . getMarker ( " SERVERHOOKS " ) ;
2020-06-24 00:56:24 +00:00
private static final FolderName SERVERCONFIG = new FolderName ( " serverconfig " ) ;
2018-06-21 19:37:32 +00:00
private static volatile CountDownLatch exitLatch = null ;
private static MinecraftServer currentServer ;
2020-05-12 22:11:45 +00:00
private static Path getServerConfigPath ( final MinecraftServer server )
{
2020-06-19 14:58:45 +00:00
final Path serverConfig = server . func_240776_a_ ( SERVERCONFIG ) ;
2020-05-12 22:11:45 +00:00
FileUtils . getOrCreateDirectory ( serverConfig , " serverconfig " ) ;
return serverConfig ;
}
2018-06-21 19:37:32 +00:00
public static boolean handleServerAboutToStart ( final MinecraftServer server )
{
currentServer = server ;
2020-06-30 02:08:50 +00:00
currentServer . getServerStatusResponse ( ) . setForgeData ( new FMLStatusPing ( ) ) ; //gathers NetworkRegistry data
// on the dedi server we need to force the stuff to setup properly
2018-06-23 02:45:01 +00:00
LogicalSidedProvider . setServer ( ( ) - > server ) ;
2020-05-12 22:11:45 +00:00
ConfigTracker . INSTANCE . loadConfigs ( ModConfig . Type . SERVER , getServerConfigPath ( server ) ) ;
2018-06-21 19:37:32 +00:00
return ! MinecraftForge . EVENT_BUS . post ( new FMLServerAboutToStartEvent ( server ) ) ;
}
public static boolean handleServerStarting ( final MinecraftServer server )
{
2018-10-06 01:42:15 +00:00
DistExecutor . runWhenOn ( Dist . DEDICATED_SERVER , ( ) - > ( ) - > LanguageHook . loadLanguagesOnServer ( server ) ) ;
2018-06-21 19:37:32 +00:00
return ! MinecraftForge . EVENT_BUS . post ( new FMLServerStartingEvent ( server ) ) ;
}
2018-07-01 20:10:13 +00:00
public static void handleServerStarted ( final MinecraftServer server )
2018-06-21 19:37:32 +00:00
{
2018-07-01 20:10:13 +00:00
MinecraftForge . EVENT_BUS . post ( new FMLServerStartedEvent ( server ) ) ;
2018-06-21 19:37:32 +00:00
allowLogins . set ( true ) ;
}
2018-07-01 20:10:13 +00:00
public static void handleServerStopping ( final MinecraftServer server )
2018-06-21 19:37:32 +00:00
{
allowLogins . set ( false ) ;
2018-07-01 20:10:13 +00:00
MinecraftForge . EVENT_BUS . post ( new FMLServerStoppingEvent ( server ) ) ;
2018-06-21 19:37:32 +00:00
}
public static void expectServerStopped ( )
{
exitLatch = new CountDownLatch ( 1 ) ;
}
public static void handleServerStopped ( final MinecraftServer server )
{
2020-02-03 20:21:10 +00:00
if ( ! server . isDedicatedServer ( ) ) GameData . revertToFrozen ( ) ;
2018-07-01 20:10:13 +00:00
MinecraftForge . EVENT_BUS . post ( new FMLServerStoppedEvent ( server ) ) ;
2018-06-21 19:37:32 +00:00
currentServer = null ;
2018-06-23 02:45:01 +00:00
LogicalSidedProvider . setServer ( null ) ;
2018-06-21 19:37:32 +00:00
CountDownLatch latch = exitLatch ;
if ( latch ! = null )
{
latch . countDown ( ) ;
exitLatch = null ;
}
2020-05-12 22:11:45 +00:00
ConfigTracker . INSTANCE . unloadConfigs ( ModConfig . Type . SERVER , getServerConfigPath ( server ) ) ;
2018-06-21 19:37:32 +00:00
}
public static MinecraftServer getCurrentServer ( )
{
return currentServer ;
}
private static AtomicBoolean allowLogins = new AtomicBoolean ( false ) ;
2019-05-23 23:02:15 +00:00
public static boolean handleServerLogin ( final CHandshakePacket packet , final NetworkManager manager ) {
2018-06-21 19:37:32 +00:00
if ( ! allowLogins . get ( ) )
{
2019-05-23 23:02:15 +00:00
StringTextComponent text = new StringTextComponent ( " Server is still starting! Please wait before reconnecting. " ) ;
2018-08-27 17:10:07 +00:00
LOGGER . info ( SERVERHOOKS , " Disconnecting Player (server is still starting): {} " , text . getUnformattedComponentText ( ) ) ;
2019-05-23 23:02:15 +00:00
manager . sendPacket ( new SDisconnectLoginPacket ( text ) ) ;
2018-06-21 19:37:32 +00:00
manager . closeChannel ( text ) ;
return false ;
}
2019-05-23 23:02:15 +00:00
if ( packet . getRequestedState ( ) = = ProtocolType . LOGIN ) {
2019-02-28 05:59:27 +00:00
final ConnectionType connectionType = ConnectionType . forVersionFlag ( packet . getFMLVersion ( ) ) ;
final int versionNumber = connectionType . getFMLVersionNumber ( packet . getFMLVersion ( ) ) ;
if ( connectionType = = ConnectionType . MODDED & & versionNumber ! = FMLNetworkConstants . FMLNETVERSION ) {
rejectConnection ( manager , connectionType , " This modded server is not network compatible with your modded client. Please verify your Forge version closely matches the server. Got net version " + versionNumber + " this server is net version " + FMLNetworkConstants . 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 19:37:32 +00:00
}
2019-05-23 23:02:15 +00:00
if ( packet . getRequestedState ( ) = = ProtocolType . STATUS ) return true ;
2019-02-16 02:45:28 +00:00
2018-09-05 00:23:45 +00:00
NetworkHooks . registerServerLoginChannel ( manager , packet ) ;
2020-09-27 17:09:31 +00:00
VanillaConnectionNetworkFilter . injectIfNecessary ( manager ) ;
2018-06-21 19:37:32 +00:00
return true ;
}
2019-02-28 05:59:27 +00:00
private static void rejectConnection ( final NetworkManager manager , ConnectionType type , String message ) {
2019-05-23 23:02:15 +00:00
manager . setConnectionState ( ProtocolType . LOGIN ) ;
2019-06-08 14:45:28 +00:00
LOGGER . info ( SERVERHOOKS , " Disconnecting {} connection attempt: {} " , type , message ) ;
2019-05-23 23:02:15 +00:00
StringTextComponent text = new StringTextComponent ( message ) ;
manager . sendPacket ( new SDisconnectLoginPacket ( text ) ) ;
2019-02-28 05:59:27 +00:00
manager . closeChannel ( text ) ;
}
2018-11-29 06:15:05 +00:00
public static void handleExit ( int retVal )
2018-06-21 19:37:32 +00:00
{
System . exit ( retVal ) ;
}
2020-06-24 00:56:24 +00:00
//INTERNAL MODDERS DO NOT USE
@Deprecated
2020-08-13 07:13:48 +00:00
public static ResourcePackLoader . IPackInfoFinder buildPackFinder ( Map < ModFile , ? extends ModFileResourcePack > modResourcePacks , BiConsumer < ? super ModFileResourcePack , ResourcePackInfo > packSetter ) {
2019-10-04 19:24:15 +00:00
return ( packList , factory ) - > serverPackFinder ( modResourcePacks , packSetter , packList , factory ) ;
}
2020-08-13 07:13:48 +00:00
private static void serverPackFinder ( Map < ModFile , ? extends ModFileResourcePack > modResourcePacks , BiConsumer < ? super ModFileResourcePack , ResourcePackInfo > packSetter , Consumer < ResourcePackInfo > consumer , ResourcePackInfo . IFactory factory ) {
2019-10-04 21:16:36 +00:00
for ( Entry < ModFile , ? extends ModFileResourcePack > e : modResourcePacks . entrySet ( ) )
2019-10-04 19:24:15 +00:00
{
IModInfo mod = e . getKey ( ) . getModInfos ( ) . get ( 0 ) ;
if ( Objects . equals ( mod . getModId ( ) , " minecraft " ) ) continue ; // skip the minecraft "mod"
final String name = " mod: " + mod . getModId ( ) ;
2020-12-26 19:38:45 +00:00
final ResourcePackInfo packInfo = ResourcePackInfo . createResourcePack ( name , false , e : : getValue , factory , ResourcePackInfo . Priority . BOTTOM , IPackNameDecorator . PLAIN ) ;
2019-10-04 19:24:15 +00:00
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 ;
}
packSetter . accept ( e . getValue ( ) , packInfo ) ;
LOGGER . debug ( CORE , " Generating PackInfo named {} for mod file {} " , name , e . getKey ( ) . getFilePath ( ) ) ;
2020-06-19 14:58:45 +00:00
consumer . accept ( packInfo ) ;
2019-10-04 19:24:15 +00:00
}
}
2018-06-21 19:37:32 +00:00
}