2012-05-04 17:02:12 -04:00
/*
* The FML Forge Mod Loader suite. Copyright (C) 2012 cpw
*
* 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; either version 2.1 of the License, or any later version.
*
* 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
*/
package cpw.mods.fml.client ;
2014-01-18 22:25:35 -05:00
import java.io.File ;
import java.io.FileInputStream ;
2012-05-04 17:02:12 -04:00
import java.util.ArrayList ;
2012-06-01 23:07:32 -04:00
import java.util.Arrays ;
2014-01-06 23:48:53 -05:00
import java.util.Collections ;
2012-05-07 17:44:49 -04:00
import java.util.List ;
2012-05-11 16:23:26 -04:00
import java.util.Map ;
2012-12-12 19:23:40 -05:00
import java.util.Map.Entry ;
2014-01-17 17:47:30 -05:00
import java.util.Set ;
2014-01-13 13:47:18 -05:00
import java.util.concurrent.CountDownLatch ;
import java.util.concurrent.TimeUnit ;
2012-05-04 17:02:12 -04:00
import java.util.logging.Logger ;
import net.minecraft.client.Minecraft ;
2013-12-11 18:46:25 -05:00
import net.minecraft.client.entity.EntityClientPlayerMP ;
2014-01-06 23:48:53 -05:00
import net.minecraft.client.gui.Gui ;
2014-01-01 00:57:24 -05:00
import net.minecraft.client.gui.GuiIngameMenu ;
2014-01-13 13:47:18 -05:00
import net.minecraft.client.gui.GuiMainMenu ;
2012-12-08 20:21:03 -08:00
import net.minecraft.client.gui.GuiScreen ;
2014-01-18 22:25:35 -05:00
import net.minecraft.client.gui.GuiSelectWorld ;
2014-01-06 23:48:53 -05:00
import net.minecraft.client.gui.ServerListEntryNormal ;
2014-01-13 13:47:18 -05:00
import net.minecraft.client.multiplayer.GuiConnecting ;
2014-01-06 23:48:53 -05:00
import net.minecraft.client.multiplayer.ServerData ;
2012-12-08 20:21:03 -08:00
import net.minecraft.client.multiplayer.WorldClient ;
2014-01-16 14:58:28 -05:00
import net.minecraft.client.network.NetHandlerPlayClient ;
2014-01-13 13:47:18 -05:00
import net.minecraft.client.network.OldServerPinger ;
2013-12-11 18:46:25 -05:00
import net.minecraft.client.renderer.entity.Render ;
import net.minecraft.client.renderer.entity.RenderManager ;
2013-12-02 23:46:42 -05:00
import net.minecraft.client.resources.IReloadableResourceManager ;
import net.minecraft.client.resources.IResourcePack ;
2012-12-08 20:21:03 -08:00
import net.minecraft.crash.CrashReport ;
import net.minecraft.entity.Entity ;
import net.minecraft.entity.player.EntityPlayer ;
2013-09-27 10:45:20 -04:00
import net.minecraft.launchwrapper.Launch ;
2014-01-18 22:25:35 -05:00
import net.minecraft.nbt.CompressedStreamTools ;
import net.minecraft.nbt.NBTTagCompound ;
2013-12-31 09:45:26 -05:00
import net.minecraft.network.INetHandler ;
2014-01-16 19:45:42 -05:00
import net.minecraft.network.NetHandlerPlayServer ;
2013-12-06 11:17:40 -05:00
import net.minecraft.network.NetworkManager ;
2014-01-06 23:48:53 -05:00
import net.minecraft.network.ServerStatusResponse ;
2012-08-09 09:21:16 -04:00
import net.minecraft.server.MinecraftServer ;
2014-01-06 23:48:53 -05:00
import net.minecraft.util.ResourceLocation ;
2014-01-18 13:05:18 -08:00
import net.minecraft.world.WorldSettings ;
2013-12-26 12:41:49 -05:00
import org.apache.logging.log4j.Level ;
2014-01-02 11:51:16 -05:00
import com.google.common.base.Strings ;
2012-08-17 09:24:38 -04:00
import com.google.common.base.Throwables ;
2014-01-02 11:51:16 -05:00
import com.google.common.collect.BiMap ;
import com.google.common.collect.HashBiMap ;
2012-11-16 22:39:47 -05:00
import com.google.common.collect.ImmutableList ;
2012-08-17 09:24:38 -04:00
import com.google.common.collect.ImmutableMap ;
2014-01-18 22:25:35 -05:00
import com.google.common.collect.ImmutableMap.Builder ;
2013-07-10 15:47:13 -04:00
import com.google.common.collect.Maps ;
2014-01-18 22:25:35 -05:00
import com.google.gson.JsonArray ;
import com.google.gson.JsonElement ;
2014-01-06 23:48:53 -05:00
import com.google.gson.JsonObject ;
2013-12-11 18:46:25 -05:00
import cpw.mods.fml.client.registry.RenderingRegistry ;
2012-07-23 16:33:17 -02:30
import cpw.mods.fml.common.DummyModContainer ;
2012-10-24 09:41:46 -04:00
import cpw.mods.fml.common.DuplicateModsFoundException ;
2012-05-24 21:06:27 -04:00
import cpw.mods.fml.common.FMLCommonHandler ;
2012-07-23 16:33:17 -02:30
import cpw.mods.fml.common.FMLLog ;
2012-05-24 21:06:27 -04:00
import cpw.mods.fml.common.IFMLSidedHandler ;
import cpw.mods.fml.common.Loader ;
2012-07-05 15:35:38 -04:00
import cpw.mods.fml.common.LoaderException ;
2012-07-23 16:33:17 -02:30
import cpw.mods.fml.common.MetadataCollection ;
2012-08-23 13:43:25 -04:00
import cpw.mods.fml.common.MissingModsException ;
2012-05-24 21:06:27 -04:00
import cpw.mods.fml.common.ModContainer ;
import cpw.mods.fml.common.ModMetadata ;
2012-07-22 11:56:38 -02:30
import cpw.mods.fml.common.ObfuscationReflectionHelper ;
2012-10-02 01:29:46 -04:00
import cpw.mods.fml.common.WrongMinecraftVersionException ;
2014-01-16 19:45:42 -05:00
import cpw.mods.fml.common.eventhandler.EventBus ;
import cpw.mods.fml.common.network.FMLNetworkEvent ;
2013-12-24 00:47:10 -05:00
import cpw.mods.fml.common.registry.GameData ;
2014-01-17 17:47:30 -05:00
import cpw.mods.fml.common.registry.LanguageRegistry ;
2013-05-27 10:28:00 -04:00
import cpw.mods.fml.common.toposort.ModSortingException ;
2012-12-15 23:21:26 -05:00
import cpw.mods.fml.relauncher.Side ;
2012-05-04 17:02:12 -04:00
2012-05-11 15:18:26 -04:00
2012-05-04 17:02:12 -04:00
/**
* Handles primary communication from hooked code into the system
2012-06-26 15:29:34 -04:00
*
2013-07-02 19:39:02 -04:00
* The FML entry point is {@link #beginMinecraftLoading(Minecraft, List)} called from
2012-09-15 18:04:56 -07:00
* {@link Minecraft}
2012-06-26 15:29:34 -04:00
*
2012-05-04 17:02:12 -04:00
* Obfuscated code should focus on this class and other members of the "server"
* (or "client") code
2012-06-26 15:29:34 -04:00
*
2012-05-04 17:02:12 -04:00
* The actual mod loading is handled at arms length by {@link Loader}
2012-06-26 15:29:34 -04:00
*
2012-05-04 17:02:12 -04:00
* It is expected that a similar class will exist for each target environment:
* Bukkit and Client side.
2012-06-26 15:29:34 -04:00
*
2012-05-04 17:02:12 -04:00
* It should not be directly modified.
2012-06-26 15:29:34 -04:00
*
2012-05-04 17:02:12 -04:00
* @author cpw
2012-06-26 15:29:34 -04:00
*
2012-05-04 17:02:12 -04:00
*/
public class FMLClientHandler implements IFMLSidedHandler
{
/**
* The singleton
*/
private static final FMLClientHandler INSTANCE = new FMLClientHandler ();
/**
* A reference to the server itself
*/
private Minecraft client ;
2012-06-26 15:29:34 -04:00
2012-07-23 16:33:17 -02:30
private DummyModContainer optifineContainer ;
2012-06-26 15:29:34 -04:00
2013-11-10 11:49:06 -05:00
@SuppressWarnings ( "unused" )
2012-07-04 00:16:30 -04:00
private boolean guiLoaded ;
2013-11-10 11:49:06 -05:00
@SuppressWarnings ( "unused" )
2012-07-23 16:33:17 -02:30
private boolean serverIsRunning ;
2012-08-23 13:43:25 -04:00
private MissingModsException modsMissing ;
2013-05-27 10:28:00 -04:00
private ModSortingException modSorting ;
2013-07-28 20:52:12 +02:00
private boolean loading = true ;
2012-08-28 22:15:18 -04:00
2012-10-02 01:29:46 -04:00
private WrongMinecraftVersionException wrongMC ;
2012-10-16 12:39:04 -04:00
private CustomModLoadingErrorDisplayException customError ;
2012-10-24 09:41:46 -04:00
private DuplicateModsFoundException dupesFound ;
2012-12-07 01:52:16 -05:00
private boolean serverShouldBeKilledQuietly ;
2013-12-02 23:46:42 -05:00
private List < IResourcePack > resourcePackList ;
2013-07-02 01:39:40 -04:00
2013-11-10 11:49:06 -05:00
@SuppressWarnings ( "unused" )
2013-12-02 23:46:42 -05:00
private IReloadableResourceManager resourceManager ;
2013-07-10 15:47:13 -04:00
2013-12-02 23:46:42 -05:00
private Map < String , IResourcePack > resourcePackMap ;
2013-07-10 15:47:13 -04:00
2014-01-02 11:51:16 -05:00
private BiMap < ModContainer , IModGuiFactory > guiFactories ;
2014-01-06 23:48:53 -05:00
private Map < ServerStatusResponse , JsonObject > extraServerListData ;
private Map < ServerData , ExtendedServerListData > serverDataTag ;
2014-01-17 17:00:55 -05:00
private NetHandlerPlayClient currentPlayClient ;
2012-09-15 18:04:56 -07:00
/**
2012-10-25 16:18:42 -04:00
* Called to start the whole game off
2012-09-15 18:04:56 -07:00
*
2012-10-25 16:18:42 -04:00
* @param minecraft The minecraft instance being launched
2013-07-02 19:39:02 -04:00
* @param resourcePackList The resource pack list we will populate with mods
2013-07-10 15:47:13 -04:00
* @param resourceManager The resource manager
2012-09-15 18:04:56 -07:00
*/
2013-11-10 11:49:06 -05:00
@SuppressWarnings ( "unchecked" )
2013-12-02 23:46:42 -05:00
public void beginMinecraftLoading ( Minecraft minecraft , @SuppressWarnings ( "rawtypes" ) List resourcePackList , IReloadableResourceManager resourceManager )
2012-05-04 17:02:12 -04:00
{
2013-03-10 01:15:16 -05:00
client = minecraft ;
2013-07-02 01:39:40 -04:00
this . resourcePackList = resourcePackList ;
2013-07-10 15:47:13 -04:00
this . resourceManager = resourceManager ;
this . resourcePackMap = Maps . newHashMap ();
2012-07-30 22:31:07 -04:00
if ( minecraft . func_71355_q ())
2012-07-23 22:50:37 -02:30
{
FMLLog . severe ( "DEMO MODE DETECTED, FML will not work. Finishing now." );
haltGame ( "FML will not run in demo mode" , new RuntimeException ());
return ;
}
2012-07-30 22:31:07 -04:00
2012-06-07 19:25:49 -04:00
FMLCommonHandler . instance (). beginLoading ( this );
2012-06-01 14:55:49 -04:00
try
{
Class <?> optifineConfig = Class . forName ( "Config" , false , Loader . instance (). getModClassLoader ());
2012-07-23 16:33:17 -02:30
String optifineVersion = ( String ) optifineConfig . getField ( "VERSION" ). get ( null );
Map < String , Object > dummyOptifineMeta = ImmutableMap . < String , Object > builder (). put ( "name" , "Optifine" ). put ( "version" , optifineVersion ). build ();
2012-08-23 16:43:28 -04:00
ModMetadata optifineMetadata = MetadataCollection . from ( getClass (). getResourceAsStream ( "optifinemod.info" ), "optifine" ). getMetadataForId ( "optifine" , dummyOptifineMeta );
2012-07-23 16:33:17 -02:30
optifineContainer = new DummyModContainer ( optifineMetadata );
FMLLog . info ( "Forge Mod Loader has detected optifine %s, enabling compatibility features" , optifineContainer . getVersion ());
2012-06-01 14:55:49 -04:00
}
catch ( Exception e )
{
2012-06-01 23:07:32 -04:00
optifineContainer = null ;
2012-06-01 14:55:49 -04:00
}
2012-07-03 22:39:35 -04:00
try
{
Loader . instance (). loadMods ();
}
2012-10-02 01:29:46 -04:00
catch ( WrongMinecraftVersionException wrong )
{
wrongMC = wrong ;
}
2012-10-24 09:41:46 -04:00
catch ( DuplicateModsFoundException dupes )
{
dupesFound = dupes ;
}
2012-08-23 13:43:25 -04:00
catch ( MissingModsException missing )
{
modsMissing = missing ;
}
2013-05-27 10:28:00 -04:00
catch ( ModSortingException sorting )
{
modSorting = sorting ;
}
2012-10-16 12:39:04 -04:00
catch ( CustomModLoadingErrorDisplayException custom )
{
2013-12-16 11:47:48 -05:00
FMLLog . log ( Level . ERROR , custom , "A custom exception was thrown by a mod, the game will now halt" );
2012-10-16 12:39:04 -04:00
customError = custom ;
}
2012-07-03 22:39:35 -04:00
catch ( LoaderException le )
{
haltGame ( "There was a severe problem during mod loading that has caused the game to fail" , le );
return ;
}
2013-09-27 10:45:20 -04:00
Map < String , Map < String , String >> sharedModList = ( Map < String , Map < String , String >> ) Launch . blackboard . get ( "modList" );
if ( sharedModList == null )
{
sharedModList = Maps . newHashMap ();
Launch . blackboard . put ( "modList" , sharedModList );
}
for ( ModContainer mc : Loader . instance (). getActiveModList ())
{
Map < String , String > sharedModDescriptor = mc . getSharedModDescriptor ();
if ( sharedModDescriptor != null )
{
String sharedModId = "fml:" + mc . getModId ();
sharedModList . put ( sharedModId , sharedModDescriptor );
}
}
2012-05-04 17:02:12 -04:00
}
2012-07-03 22:39:35 -04:00
@Override
public void haltGame ( String message , Throwable t )
{
2012-07-30 22:31:07 -04:00
client . func_71377_b ( new CrashReport ( message , t ));
2012-07-23 22:50:37 -02:30
throw Throwables . propagate ( t );
2012-07-03 22:39:35 -04:00
}
2012-05-04 17:02:12 -04:00
/**
2012-05-07 17:44:49 -04:00
* Called a bit later on during initialization to finish loading mods
* Also initializes key bindings
2012-06-26 15:29:34 -04:00
*
2012-05-04 17:02:12 -04:00
*/
2013-12-11 18:46:25 -05:00
@SuppressWarnings ({ "deprecation" , "unchecked" })
2012-08-02 02:08:30 -02:30
public void finishMinecraftLoading ()
2012-05-04 17:02:12 -04:00
{
2013-05-27 10:28:00 -04:00
if ( modsMissing != null || wrongMC != null || customError != null || dupesFound != null || modSorting != null )
2012-08-23 13:43:25 -04:00
{
return ;
}
2012-07-03 22:39:35 -04:00
try
{
Loader . instance (). initializeMods ();
}
2012-10-16 12:39:04 -04:00
catch ( CustomModLoadingErrorDisplayException custom )
{
2013-12-16 11:47:48 -05:00
FMLLog . log ( Level . ERROR , custom , "A custom exception was thrown by a mod, the game will now halt" );
2012-10-16 12:39:04 -04:00
customError = custom ;
return ;
}
2012-07-03 22:39:35 -04:00
catch ( LoaderException le )
{
haltGame ( "There was a severe problem during mod loading that has caused the game to fail" , le );
return ;
}
2013-11-10 11:49:06 -05:00
2013-07-03 22:29:10 -07:00
// Reload resources
2013-12-16 11:47:48 -05:00
// client.func_110436_a();
2013-12-11 18:46:25 -05:00
RenderingRegistry . instance (). loadEntityRenderers (( Map < Class <? extends Entity > , Render > ) RenderManager . field_78727_a . field_78729_o );
2014-01-02 11:51:16 -05:00
guiFactories = HashBiMap . create ();
for ( ModContainer mc : Loader . instance (). getActiveModList ())
{
String className = mc . getGuiClassName ();
if ( Strings . isNullOrEmpty ( className ))
{
continue ;
}
try
{
Class <?> clazz = Class . forName ( className , true , Loader . instance (). getModClassLoader ());
Class <? extends IModGuiFactory > guiClassFactory = clazz . asSubclass ( IModGuiFactory . class );
IModGuiFactory guiFactory = guiClassFactory . newInstance ();
guiFactory . initialize ( client );
guiFactories . put ( mc , guiFactory );
} catch ( Exception e )
{
FMLLog . log ( Level . ERROR , e , "A critical error occurred instantiating the gui factory for mod %s" , mc . getModId ());
}
}
2012-08-28 22:15:18 -04:00
loading = false ;
2012-08-13 19:57:40 -04:00
}
2012-07-29 22:54:59 -04:00
2013-11-10 11:49:06 -05:00
@SuppressWarnings ( "unused" )
2013-09-27 10:45:20 -04:00
public void extendModList ()
{
2013-11-10 11:49:06 -05:00
@SuppressWarnings ( "unchecked" )
2013-09-27 10:45:20 -04:00
Map < String , Map < String , String >> modList = ( Map < String , Map < String , String >> ) Launch . blackboard . get ( "modList" );
if ( modList != null )
{
for ( Entry < String , Map < String , String >> modEntry : modList . entrySet ())
{
String sharedModId = modEntry . getKey ();
String system = sharedModId . split ( ":" ) [ 0 ] ;
if ( "fml" . equals ( system ))
{
continue ;
}
Map < String , String > mod = modEntry . getValue ();
String modSystem = mod . get ( "modsystem" ); // the modsystem (FML uses FML or ModLoader)
String modId = mod . get ( "id" ); // unique ID
String modVersion = mod . get ( "version" ); // version
String modName = mod . get ( "name" ); // a human readable name
String modURL = mod . get ( "url" ); // a URL for the mod (can be empty string)
String modAuthors = mod . get ( "authors" ); // a csv of authors (can be empty string)
String modDescription = mod . get ( "description" ); // a (potentially) multiline description (can be empty string)
}
}
}
2012-08-23 13:43:25 -04:00
public void onInitializationComplete ()
2012-08-13 19:57:40 -04:00
{
2012-10-02 01:29:46 -04:00
if ( wrongMC != null )
{
2013-12-02 23:46:42 -05:00
showGuiScreen ( new GuiWrongMinecraft ( wrongMC ));
2012-10-02 01:29:46 -04:00
}
else if ( modsMissing != null )
2012-08-23 13:43:25 -04:00
{
2013-12-02 23:46:42 -05:00
showGuiScreen ( new GuiModsMissing ( modsMissing ));
2012-08-23 13:43:25 -04:00
}
2012-10-24 09:41:46 -04:00
else if ( dupesFound != null )
{
2013-12-02 23:46:42 -05:00
showGuiScreen ( new GuiDupesFound ( dupesFound ));
2012-10-24 09:41:46 -04:00
}
2013-05-27 10:28:00 -04:00
else if ( modSorting != null )
{
2013-12-02 23:46:42 -05:00
showGuiScreen ( new GuiSortingProblem ( modSorting ));
2013-05-27 10:28:00 -04:00
}
else if ( customError != null )
2012-10-16 12:39:04 -04:00
{
2013-12-02 23:46:42 -05:00
showGuiScreen ( new GuiCustomModLoadingErrorScreen ( customError ));
2012-10-16 12:39:04 -04:00
}
2012-08-23 13:43:25 -04:00
else
{
}
2012-05-04 17:02:12 -04:00
}
/**
* Get the server instance
*/
public Minecraft getClient ()
{
return client ;
}
/**
* Get a handle to the client's logger instance
* The client actually doesn't have one- so we return null
*/
public Logger getMinecraftLogger ()
{
return null ;
}
/**
* @return the instance
*/
public static FMLClientHandler instance ()
{
return INSTANCE ;
}
2012-05-07 17:44:49 -04:00
/**
* @param player
* @param gui
*/
public void displayGuiScreen ( EntityPlayer player , GuiScreen gui )
{
2012-07-30 22:31:07 -04:00
if ( client . field_71439_g == player && gui != null ) {
2013-12-02 23:46:42 -05:00
client . func_147108_a ( gui );
2012-05-07 17:44:49 -04:00
}
}
2012-06-01 14:55:49 -04:00
/**
* @param mods
*/
public void addSpecialModEntries ( ArrayList < ModContainer > mods )
{
if ( optifineContainer != null ) {
mods . add ( optifineContainer );
}
}
2012-06-01 23:07:32 -04:00
@Override
public List < String > getAdditionalBrandingInformation ()
{
if ( optifineContainer != null )
{
return Arrays . asList ( String . format ( "Optifine %s" , optifineContainer . getVersion ()));
} else {
2012-11-16 22:39:47 -05:00
return ImmutableList . < String > of ();
2012-06-01 23:07:32 -04:00
}
}
2012-06-02 15:13:55 -04:00
@Override
public Side getSide ()
{
return Side . CLIENT ;
}
2012-07-30 22:31:07 -04:00
public boolean hasOptifine ()
{
return optifineContainer != null ;
2012-07-06 10:29:17 -04:00
}
2012-08-08 00:31:24 -04:00
@Override
public void showGuiScreen ( Object clientGuiElement )
{
GuiScreen gui = ( GuiScreen ) clientGuiElement ;
2013-12-02 23:46:42 -05:00
client . func_147108_a ( gui );
2012-08-08 00:31:24 -04:00
}
2012-08-09 01:58:14 -04:00
2013-12-11 18:46:25 -05:00
public WorldClient getWorldClient ()
2012-08-09 01:58:14 -04:00
{
2013-12-11 18:46:25 -05:00
return client . field_71441_e ;
}
2012-08-09 01:58:14 -04:00
2013-12-11 18:46:25 -05:00
public EntityClientPlayerMP getClientPlayerEntity ()
{
return client . field_71439_g ;
2012-08-09 01:58:14 -04:00
}
2012-08-09 08:40:32 -04:00
2012-08-09 09:21:16 -04:00
@Override
public void beginServerLoading ( MinecraftServer server )
{
2012-12-07 01:52:16 -05:00
serverShouldBeKilledQuietly = false ;
2012-08-09 09:21:16 -04:00
// NOOP
}
@Override
public void finishServerLoading ()
{
// NOOP
}
2012-08-11 11:01:18 -04:00
@Override
public MinecraftServer getServer ()
{
return client . func_71401_C ();
}
2012-08-12 22:45:18 -04:00
2013-12-10 17:29:26 -05:00
public void displayMissingMods ( Object modMissingPacket )
2012-08-26 22:13:43 -04:00
{
2013-12-10 17:29:26 -05:00
// showGuiScreen(new GuiModsMissingForServer(modMissingPacket));
2012-08-26 22:13:43 -04:00
}
2012-08-28 22:15:18 -04:00
/**
* If the client is in the midst of loading, we disable saving so that custom settings aren't wiped out
*/
public boolean isLoading ()
{
return loading ;
}
2012-09-06 10:03:30 -04:00
2012-12-07 01:52:16 -05:00
@Override
public boolean shouldServerShouldBeKilledQuietly ()
{
return serverShouldBeKilledQuietly ;
}
2013-04-20 22:55:56 -04:00
/**
* Is this GUI type open?
*
* @param gui The type of GUI to test for
* @return if a GUI of this type is open
*/
public boolean isGUIOpen ( Class <? extends GuiScreen > gui )
{
return client . field_71462_r != null && client . field_71462_r . getClass (). equals ( gui );
}
2013-07-02 01:39:40 -04:00
@Override
public void addModAsResource ( ModContainer container )
{
2014-01-17 17:47:30 -05:00
LanguageRegistry . instance (). loadLanguagesFor ( container , Side . CLIENT );
2013-07-02 11:11:50 -04:00
Class <?> resourcePackType = container . getCustomResourcePackClass ();
if ( resourcePackType != null )
2013-07-02 01:39:40 -04:00
{
2013-07-02 11:11:50 -04:00
try
{
2013-12-02 23:46:42 -05:00
IResourcePack pack = ( IResourcePack ) resourcePackType . getConstructor ( ModContainer . class ). newInstance ( container );
2013-07-02 11:11:50 -04:00
resourcePackList . add ( pack );
2013-07-10 15:47:13 -04:00
resourcePackMap . put ( container . getModId (), pack );
2013-07-02 11:11:50 -04:00
}
catch ( NoSuchMethodException e )
{
2013-12-16 11:47:48 -05:00
FMLLog . log ( Level . ERROR , "The container %s (type %s) returned an invalid class for it's resource pack." , container . getName (), container . getClass (). getName ());
2013-07-02 11:11:50 -04:00
return ;
}
catch ( Exception e )
{
2013-12-16 11:47:48 -05:00
FMLLog . log ( Level . ERROR , e , "An unexpected exception occurred constructing the custom resource pack for %s" , container . getName ());
2013-07-02 11:11:50 -04:00
throw Throwables . propagate ( e );
}
2013-07-02 01:39:40 -04:00
}
}
2013-07-10 00:42:40 -04:00
@Override
public void updateResourcePackList ()
{
client . func_110436_a ();
}
2013-07-10 15:47:13 -04:00
2013-12-02 23:46:42 -05:00
public IResourcePack getResourcePackFor ( String modId )
2013-07-10 15:47:13 -04:00
{
return resourcePackMap . get ( modId );
}
2013-09-13 19:04:25 -05:00
@Override
public String getCurrentLanguage ()
{
return client . func_135016_M (). func_135041_c (). func_135034_a ();
}
2013-09-20 17:02:56 -04:00
@Override
public void serverStopped ()
{
// If the server crashes during startup, it might hang the client- reset the client so it can abend properly.
2013-09-22 16:56:24 +01:00
MinecraftServer server = getServer ();
if ( server != null && ! server . func_71200_ad ())
2013-09-20 17:02:56 -04:00
{
2013-09-22 16:56:24 +01:00
ObfuscationReflectionHelper . setPrivateValue ( MinecraftServer . class , server , true , "field_71296" + "_Q" , "serverIs" + "Running" );
2013-09-20 17:02:56 -04:00
}
}
2013-12-06 11:17:40 -05:00
2013-12-31 09:45:26 -05:00
@Override
public INetHandler getClientPlayHandler ()
{
2014-01-17 17:00:55 -05:00
return this . currentPlayClient ;
2013-12-31 09:45:26 -05:00
}
2013-12-06 11:17:40 -05:00
@Override
public NetworkManager getClientToServerNetworkManager ()
{
2013-12-06 14:52:33 -05:00
return this . client . func_147114_u () != null ? this . client . func_147114_u (). func_147298_b () : null ;
2013-12-06 11:17:40 -05:00
}
2013-12-24 00:47:10 -05:00
2013-12-26 12:41:49 -05:00
public void handleClientWorldClosing ( WorldClient world )
2013-12-24 00:47:10 -05:00
{
2013-12-26 12:41:49 -05:00
NetworkManager client = getClientToServerNetworkManager ();
// ONLY revert a non-local connection
if ( client != null && ! client . func_150731_c ())
{
GameData . revertToFrozen ();
}
2013-12-24 00:47:10 -05:00
}
2013-12-28 17:51:40 -05:00
2014-01-18 13:05:18 -08:00
public void startIntegratedServer ( String id , String name , WorldSettings settings )
2013-12-28 17:51:40 -05:00
{
2014-01-16 18:15:45 -05:00
playClientBlock = new CountDownLatch ( 1 );
2013-12-28 17:51:40 -05:00
}
2014-01-01 00:57:24 -05:00
2014-01-18 22:25:35 -05:00
public File getSavesDir ()
{
return new File ( client . field_71412_D , "saves" );
}
public void tryLoadExistingWorld ( GuiSelectWorld selectWorldGUI , String dirName , String saveName )
{
File dir = new File ( getSavesDir (), dirName );
NBTTagCompound leveldat ;
try
{
leveldat = CompressedStreamTools . func_74796_a ( new FileInputStream ( new File ( dir , "level.dat" )));
}
catch ( Exception e )
{
try
{
leveldat = CompressedStreamTools . func_74796_a ( new FileInputStream ( new File ( dir , "level.dat_old" )));
}
catch ( Exception e1 )
{
FMLLog . warning ( "There appears to be a problem loading the save %s, both level files are unreadable." , dirName );
return ;
}
}
NBTTagCompound fmlData = leveldat . func_74775_l ( "FML" );
if ( fmlData . func_74764_b ( "ModItemData" ))
{
showGuiScreen ( new GuiOldSaveLoadConfirm ( dirName , saveName , selectWorldGUI ));
}
else
{
launchIntegratedServerCallback ( dirName , saveName );
}
}
public void launchIntegratedServerCallback ( String dirName , String saveName )
{
client . func_71371_a ( dirName , saveName , ( WorldSettings ) null );
}
2014-01-01 00:57:24 -05:00
public void showInGameModOptions ( GuiIngameMenu guiIngameMenu )
{
showGuiScreen ( new GuiIngameModOptions ( guiIngameMenu ));
}
2014-01-02 11:51:16 -05:00
public IModGuiFactory getGuiFactoryFor ( ModContainer selectedMod )
{
return guiFactories . get ( selectedMod );
}
2014-01-06 23:48:53 -05:00
public void setupServerList ()
{
extraServerListData = Collections . synchronizedMap ( Maps . < ServerStatusResponse , JsonObject > newHashMap ());
serverDataTag = Collections . synchronizedMap ( Maps . < ServerData , ExtendedServerListData > newHashMap ());
}
public void captureAdditionalData ( ServerStatusResponse serverstatusresponse , JsonObject jsonobject )
{
if ( jsonobject . has ( "modinfo" ))
{
JsonObject fmlData = jsonobject . get ( "modinfo" ). getAsJsonObject ();
extraServerListData . put ( serverstatusresponse , fmlData );
}
}
public void bindServerListData ( ServerData data , ServerStatusResponse originalResponse )
{
if ( extraServerListData . containsKey ( originalResponse ))
{
JsonObject jsonData = extraServerListData . get ( originalResponse );
String type = jsonData . get ( "type" ). getAsString ();
2014-01-18 22:25:35 -05:00
JsonArray modDataArray = jsonData . get ( "modList" ). getAsJsonArray ();
2014-01-06 23:48:53 -05:00
boolean moddedClientAllowed = jsonData . has ( "clientModsAllowed" ) ? jsonData . get ( "clientModsAllowed" ). getAsBoolean () : true ;
2014-01-18 22:25:35 -05:00
Builder < String , String > modListBldr = ImmutableMap . < String , String > builder ();
for ( JsonElement obj : modDataArray )
{
JsonObject modObj = obj . getAsJsonObject ();
modListBldr . put ( modObj . get ( "modid" ). getAsString (), modObj . get ( "version" ). getAsString ());
}
serverDataTag . put ( data , new ExtendedServerListData ( type , true , modListBldr . build (), ! moddedClientAllowed ));
2014-01-06 23:48:53 -05:00
}
else
{
String serverDescription = data . field_78843_d ;
boolean moddedClientAllowed = true ;
if ( ! Strings . isNullOrEmpty ( serverDescription ))
{
moddedClientAllowed = ! serverDescription . endsWith ( ":NOFML§r" );
}
2014-01-18 22:25:35 -05:00
serverDataTag . put ( data , new ExtendedServerListData ( "VANILLA" , false , ImmutableMap . < String , String > of (), ! moddedClientAllowed ));
2014-01-06 23:48:53 -05:00
}
2014-01-13 13:47:18 -05:00
startupConnectionData . countDown ();
2014-01-06 23:48:53 -05:00
}
private static final ResourceLocation iconSheet = new ResourceLocation ( "fml:textures/gui/icons.png" );
2014-01-13 13:47:18 -05:00
private static final CountDownLatch startupConnectionData = new CountDownLatch ( 1 );
2014-01-06 23:48:53 -05:00
public String enhanceServerListEntry ( ServerListEntryNormal serverListEntry , ServerData serverEntry , int x , int width , int y , int relativeMouseX , int relativeMouseY )
{
String tooltip ;
int idx ;
boolean blocked = false ;
if ( serverDataTag . containsKey ( serverEntry ))
{
ExtendedServerListData extendedData = serverDataTag . get ( serverEntry );
if ( "FML" . equals ( extendedData . type ) && extendedData . isCompatible )
{
idx = 0 ;
2014-01-18 22:25:35 -05:00
tooltip = String . format ( "Compatible FML modded server\n%d mods present" , extendedData . modData . size ());
2014-01-06 23:48:53 -05:00
}
else if ( "FML" . equals ( extendedData . type ) && ! extendedData . isCompatible )
{
idx = 16 ;
2014-01-18 22:25:35 -05:00
tooltip = String . format ( "Incompatible FML modded server\n%d mods present" , extendedData . modData . size ());
2014-01-06 23:48:53 -05:00
}
else if ( "BUKKIT" . equals ( extendedData . type ))
{
idx = 32 ;
tooltip = String . format ( "Bukkit modded server" );
}
else if ( "VANILLA" . equals ( extendedData . type ))
{
idx = 48 ;
tooltip = String . format ( "Vanilla server" );
}
else
{
idx = 64 ;
tooltip = String . format ( "Unknown server data" );
}
blocked = extendedData . isBlocked ;
}
else
{
return null ;
}
this . client . func_110434_K (). func_110577_a ( iconSheet );
Gui . func_146110_a ( x + width - 18 , y + 10 , 0 , ( float ) idx , 16 , 16 , 256 . 0f , 256 . 0f );
if ( blocked )
{
Gui . func_146110_a ( x + width - 18 , y + 10 , 0 , 80 , 16 , 16 , 256 . 0f , 256 . 0f );
}
return relativeMouseX > width - 15 && relativeMouseX < width && relativeMouseY > 10 && relativeMouseY < 26 ? tooltip : null ;
}
public String fixDescription ( String description )
{
return description . endsWith ( ":NOFML§r" ) ? description . substring ( 0 , description . length () - 8 ) + "§r" : description ;
}
2014-01-13 13:47:18 -05:00
public void connectToServerAtStartup ( String host , int port )
{
setupServerList ();
OldServerPinger osp = new OldServerPinger ();
ServerData serverData = new ServerData ( "Command Line" , host + ":" + port );
try
{
osp . func_147224_a ( serverData );
startupConnectionData . await ( 30 , TimeUnit . SECONDS );
}
catch ( Exception e )
{
showGuiScreen ( new GuiConnecting ( new GuiMainMenu (), client , host , port ));
return ;
}
connectToServer ( new GuiMainMenu (), serverData );
}
public void connectToServer ( GuiScreen guiMultiplayer , ServerData serverEntry )
{
ExtendedServerListData extendedData = serverDataTag . get ( serverEntry );
if ( extendedData . isBlocked )
{
showGuiScreen ( new GuiAccessDenied ( guiMultiplayer , serverEntry ));
}
else
{
showGuiScreen ( new GuiConnecting ( guiMultiplayer , client , serverEntry ));
}
2014-01-16 14:58:28 -05:00
playClientBlock = new CountDownLatch ( 1 );
}
private CountDownLatch playClientBlock ;
public void setPlayClient ( NetHandlerPlayClient netHandlerPlayClient )
{
playClientBlock . countDown ();
2014-01-17 17:00:55 -05:00
this . currentPlayClient = netHandlerPlayClient ;
2014-01-16 14:58:28 -05:00
}
@Override
public void waitForPlayClient ()
{
boolean gotIt = false ;
try
{
gotIt = playClientBlock . await ( 1 , TimeUnit . SECONDS );
} catch ( InterruptedException e )
{
}
if ( ! gotIt )
{
throw new RuntimeException ( "Timeout waiting for client thread to catch up!" );
}
2014-01-13 13:47:18 -05:00
}
2014-01-16 19:45:42 -05:00
@Override
public void fireNetRegistrationEvent ( EventBus bus , NetworkManager manager , Set < String > channelSet , String channel , Side side )
{
if ( side == Side . CLIENT )
{
bus . post ( new FMLNetworkEvent . CustomPacketRegistrationEvent < NetHandlerPlayClient > ( manager , channelSet , channel , side , NetHandlerPlayClient . class ));
}
else
{
bus . post ( new FMLNetworkEvent . CustomPacketRegistrationEvent < NetHandlerPlayServer > ( manager , channelSet , channel , side , NetHandlerPlayServer . class ));
}
}
2012-05-04 17:02:12 -04:00
}