Add in a lot of network handler stuff - also, expose the asm harvested data
This commit is contained in:
parent
09098f8a0f
commit
8bda53cb77
|
@ -36,6 +36,8 @@ import cpw.mods.fml.common.FMLLog;
|
||||||
import cpw.mods.fml.common.Loader;
|
import cpw.mods.fml.common.Loader;
|
||||||
import cpw.mods.fml.common.modloader.ModLoaderHelper;
|
import cpw.mods.fml.common.modloader.ModLoaderHelper;
|
||||||
import cpw.mods.fml.common.modloader.ModLoaderModContainer;
|
import cpw.mods.fml.common.modloader.ModLoaderModContainer;
|
||||||
|
import cpw.mods.fml.common.network.NetworkRegistry;
|
||||||
|
import cpw.mods.fml.common.network.Player;
|
||||||
import cpw.mods.fml.common.registry.EntityRegistry;
|
import cpw.mods.fml.common.registry.EntityRegistry;
|
||||||
import cpw.mods.fml.common.registry.GameRegistry;
|
import cpw.mods.fml.common.registry.GameRegistry;
|
||||||
import cpw.mods.fml.common.ObfuscationReflectionHelper;
|
import cpw.mods.fml.common.ObfuscationReflectionHelper;
|
||||||
|
@ -446,7 +448,7 @@ public class ModLoader
|
||||||
*/
|
*/
|
||||||
public static boolean isChannelActive(EntityPlayer player, String channel)
|
public static boolean isChannelActive(EntityPlayer player, String channel)
|
||||||
{
|
{
|
||||||
return FMLCommonHandler.instance().isChannelActive(channel, player);
|
return NetworkRegistry.instance().isChannelActive(channel, (Player)player);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static boolean isGUIOpen(Class<? extends GuiScreen> gui)
|
public static boolean isGUIOpen(Class<? extends GuiScreen> gui)
|
||||||
|
@ -592,7 +594,7 @@ public class ModLoader
|
||||||
*/
|
*/
|
||||||
public static void registerPacketChannel(BaseMod mod, String channel)
|
public static void registerPacketChannel(BaseMod mod, String channel)
|
||||||
{
|
{
|
||||||
FMLCommonHandler.instance().registerChannel(FMLCommonHandler.instance().findContainerFor(mod), channel);
|
NetworkRegistry.instance().registerChannel(FMLCommonHandler.instance().findContainerFor(mod), channel);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -122,4 +122,10 @@ public class DummyModContainer implements ModContainer
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isNetworkMod()
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,20 +16,16 @@ package cpw.mods.fml.common;
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
import java.io.UnsupportedEncodingException;
|
|
||||||
import java.lang.reflect.InvocationTargetException;
|
import java.lang.reflect.InvocationTargetException;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.EnumSet;
|
import java.util.EnumSet;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.HashSet;
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Properties;
|
import java.util.Properties;
|
||||||
import java.util.Random;
|
import java.util.Random;
|
||||||
import java.util.Set;
|
|
||||||
import java.util.logging.Level;
|
|
||||||
import java.util.logging.Logger;
|
import java.util.logging.Logger;
|
||||||
import java.util.regex.Matcher;
|
import java.util.regex.Matcher;
|
||||||
import java.util.regex.Pattern;
|
import java.util.regex.Pattern;
|
||||||
|
@ -69,19 +65,6 @@ public class FMLCommonHandler
|
||||||
* The singleton
|
* The singleton
|
||||||
*/
|
*/
|
||||||
private static final FMLCommonHandler INSTANCE = new FMLCommonHandler();
|
private static final FMLCommonHandler INSTANCE = new FMLCommonHandler();
|
||||||
private static final Pattern metadataFile = Pattern.compile("$/modinfo.json$");;
|
|
||||||
/**
|
|
||||||
* A map of mods to their network channels
|
|
||||||
*/
|
|
||||||
private Map<ModContainer, Set<String>> channelList = new HashMap<ModContainer, Set<String>>();
|
|
||||||
/**
|
|
||||||
* A map of channels to mods
|
|
||||||
*/
|
|
||||||
private Map<String, ModContainer> modChannels = new HashMap<String, ModContainer>();
|
|
||||||
/**
|
|
||||||
* A map of active channels per player
|
|
||||||
*/
|
|
||||||
private Map<Object, Set<String>> activeChannels = new HashMap<Object, Set<String>>();
|
|
||||||
/**
|
/**
|
||||||
* The delegate for side specific data and functions
|
* The delegate for side specific data and functions
|
||||||
*/
|
*/
|
||||||
|
@ -89,8 +72,6 @@ public class FMLCommonHandler
|
||||||
|
|
||||||
private int uniqueEntityListId = 220;
|
private int uniqueEntityListId = 220;
|
||||||
|
|
||||||
private List<ModContainer> auxilliaryContainers = new ArrayList<ModContainer>();
|
|
||||||
|
|
||||||
private Map<String,Properties> modLanguageData=new HashMap<String,Properties>();
|
private Map<String,Properties> modLanguageData=new HashMap<String,Properties>();
|
||||||
|
|
||||||
private List<IScheduledTickHandler> scheduledTicks = new ArrayList<IScheduledTickHandler>();
|
private List<IScheduledTickHandler> scheduledTicks = new ArrayList<IScheduledTickHandler>();
|
||||||
|
@ -174,119 +155,6 @@ public class FMLCommonHandler
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
/**
|
|
||||||
* Lookup the mod for a channel
|
|
||||||
* @param channel
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
public ModContainer getModForChannel(String channel)
|
|
||||||
{
|
|
||||||
return modChannels.get(channel);
|
|
||||||
}
|
|
||||||
/**
|
|
||||||
* Get the channel list for a mod
|
|
||||||
* @param modLoaderModContainer
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
public Set<String> getChannelListFor(ModContainer container)
|
|
||||||
{
|
|
||||||
return channelList.get(container);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* register a channel to a mod
|
|
||||||
* @param container
|
|
||||||
* @param channelName
|
|
||||||
*/
|
|
||||||
public void registerChannel(ModContainer container, String channelName)
|
|
||||||
{
|
|
||||||
if (modChannels.containsKey(channelName))
|
|
||||||
{
|
|
||||||
// NOOP
|
|
||||||
}
|
|
||||||
|
|
||||||
Set<String> list = channelList.get(container);
|
|
||||||
|
|
||||||
if (list == null)
|
|
||||||
{
|
|
||||||
list = new HashSet<String>();
|
|
||||||
channelList.put(container, list);
|
|
||||||
}
|
|
||||||
|
|
||||||
list.add(channelName);
|
|
||||||
modChannels.put(channelName, container);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Activate the channel for the player
|
|
||||||
* @param player
|
|
||||||
*/
|
|
||||||
public void activateChannel(Object player, String channel)
|
|
||||||
{
|
|
||||||
Set<String> active = activeChannels.get(player);
|
|
||||||
|
|
||||||
if (active == null)
|
|
||||||
{
|
|
||||||
active = new HashSet<String>();
|
|
||||||
activeChannels.put(player, active);
|
|
||||||
}
|
|
||||||
|
|
||||||
active.add(channel);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Deactivate the channel for the player
|
|
||||||
* @param player
|
|
||||||
* @param channel
|
|
||||||
*/
|
|
||||||
public void deactivateChannel(Object player, String channel)
|
|
||||||
{
|
|
||||||
Set<String> active = activeChannels.get(player);
|
|
||||||
|
|
||||||
if (active == null)
|
|
||||||
{
|
|
||||||
active = new HashSet<String>();
|
|
||||||
activeChannels.put(player, active);
|
|
||||||
}
|
|
||||||
|
|
||||||
active.remove(channel);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get the packet 250 channel registration string
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
public byte[] getPacketRegistry()
|
|
||||||
{
|
|
||||||
StringBuffer sb = new StringBuffer();
|
|
||||||
|
|
||||||
for (String chan : modChannels.keySet())
|
|
||||||
{
|
|
||||||
sb.append(chan).append("\0");
|
|
||||||
}
|
|
||||||
|
|
||||||
try
|
|
||||||
{
|
|
||||||
return sb.toString().getBytes("UTF8");
|
|
||||||
}
|
|
||||||
catch (UnsupportedEncodingException e)
|
|
||||||
{
|
|
||||||
FMLLog.log(Level.WARNING, e, "Error building registration list");
|
|
||||||
return new byte[0];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Is the specified channel active for the player?
|
|
||||||
* @param channel
|
|
||||||
* @param player
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
public boolean isChannelActive(String channel, Object player)
|
|
||||||
{
|
|
||||||
return activeChannels.get(player).contains(channel);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the forge mod loader logging instance (goes to the forgemodloader log file)
|
* Get the forge mod loader logging instance (goes to the forgemodloader log file)
|
||||||
* @return
|
* @return
|
||||||
|
@ -409,6 +277,7 @@ public class FMLCommonHandler
|
||||||
private Class<?> forge;
|
private Class<?> forge;
|
||||||
private boolean noForge;
|
private boolean noForge;
|
||||||
private List<String> brandings;
|
private List<String> brandings;
|
||||||
|
private List<ModContainer> auxilliaryContainers = new ArrayList<ModContainer>();
|
||||||
|
|
||||||
private Class<?> findMinecraftForge()
|
private Class<?> findMinecraftForge()
|
||||||
{
|
{
|
||||||
|
@ -531,17 +400,17 @@ public class FMLCommonHandler
|
||||||
{
|
{
|
||||||
tickStart(EnumSet.of(TickType.WORLDLOAD));
|
tickStart(EnumSet.of(TickType.WORLDLOAD));
|
||||||
}
|
}
|
||||||
|
|
||||||
public void handleServerStarting(MinecraftServer server)
|
public void handleServerStarting(MinecraftServer server)
|
||||||
{
|
{
|
||||||
Loader.instance().serverStarting(server);
|
Loader.instance().serverStarting(server);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void handleServerStarted()
|
public void handleServerStarted()
|
||||||
{
|
{
|
||||||
Loader.instance().serverStarted();
|
Loader.instance().serverStarted();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void handleServerStopping()
|
public void handleServerStopping()
|
||||||
{
|
{
|
||||||
Loader.instance().serverStopping();
|
Loader.instance().serverStopping();
|
||||||
|
|
|
@ -31,6 +31,7 @@ import com.google.common.collect.ImmutableBiMap.Builder;
|
||||||
import com.google.common.collect.Iterables;
|
import com.google.common.collect.Iterables;
|
||||||
import com.google.common.collect.Lists;
|
import com.google.common.collect.Lists;
|
||||||
import com.google.common.collect.Multimap;
|
import com.google.common.collect.Multimap;
|
||||||
|
import com.google.common.collect.Table;
|
||||||
import com.google.common.eventbus.EventBus;
|
import com.google.common.eventbus.EventBus;
|
||||||
import com.google.common.eventbus.Subscribe;
|
import com.google.common.eventbus.Subscribe;
|
||||||
|
|
||||||
|
@ -38,6 +39,8 @@ import cpw.mods.fml.common.LoaderState.ModState;
|
||||||
import cpw.mods.fml.common.Mod.Block;
|
import cpw.mods.fml.common.Mod.Block;
|
||||||
import cpw.mods.fml.common.Mod.Instance;
|
import cpw.mods.fml.common.Mod.Instance;
|
||||||
import cpw.mods.fml.common.Mod.Metadata;
|
import cpw.mods.fml.common.Mod.Metadata;
|
||||||
|
import cpw.mods.fml.common.discovery.ASMDataTable;
|
||||||
|
import cpw.mods.fml.common.discovery.ASMDataTable.ASMData;
|
||||||
import cpw.mods.fml.common.discovery.ContainerType;
|
import cpw.mods.fml.common.discovery.ContainerType;
|
||||||
import cpw.mods.fml.common.event.FMLConstructionEvent;
|
import cpw.mods.fml.common.event.FMLConstructionEvent;
|
||||||
import cpw.mods.fml.common.event.FMLInitializationEvent;
|
import cpw.mods.fml.common.event.FMLInitializationEvent;
|
||||||
|
@ -68,6 +71,7 @@ public class FMLModContainer implements ModContainer
|
||||||
private LoadController controller;
|
private LoadController controller;
|
||||||
private Multimap<Class<? extends Annotation>, Object> annotations;
|
private Multimap<Class<? extends Annotation>, Object> annotations;
|
||||||
private DefaultArtifactVersion processedVersion;
|
private DefaultArtifactVersion processedVersion;
|
||||||
|
private boolean isNetworkMod;
|
||||||
|
|
||||||
private static final BiMap<Class<? extends FMLStateEvent>, Class<? extends Annotation>> modAnnotationTypes = ImmutableBiMap.<Class<? extends FMLStateEvent>, Class<? extends Annotation>>builder()
|
private static final BiMap<Class<? extends FMLStateEvent>, Class<? extends Annotation>> modAnnotationTypes = ImmutableBiMap.<Class<? extends FMLStateEvent>, Class<? extends Annotation>>builder()
|
||||||
.put(FMLPreInitializationEvent.class, Mod.PreInit.class)
|
.put(FMLPreInitializationEvent.class, Mod.PreInit.class)
|
||||||
|
@ -268,6 +272,8 @@ public class FMLModContainer implements ModContainer
|
||||||
ModClassLoader modClassLoader = event.getModClassLoader();
|
ModClassLoader modClassLoader = event.getModClassLoader();
|
||||||
modClassLoader.addFile(source);
|
modClassLoader.addFile(source);
|
||||||
Class<?> clazz = Class.forName(className, true, modClassLoader);
|
Class<?> clazz = Class.forName(className, true, modClassLoader);
|
||||||
|
ASMDataTable asmHarvestedAnnotations = event.getASMHarvestedData();
|
||||||
|
asmHarvestedAnnotations.getAnnotationsFor(this);
|
||||||
annotations = gatherAnnotations(clazz);
|
annotations = gatherAnnotations(clazz);
|
||||||
modInstance = clazz.newInstance();
|
modInstance = clazz.newInstance();
|
||||||
processFieldAnnotations();
|
processFieldAnnotations();
|
||||||
|
@ -316,4 +322,10 @@ public class FMLModContainer implements ModContainer
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isNetworkMod()
|
||||||
|
{
|
||||||
|
return isNetworkMod;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -97,6 +97,11 @@ public class InjectedModContainer implements ModContainer
|
||||||
return wrappedContainer.findSidedProxy();
|
return wrappedContainer.findSidedProxy();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isNetworkMod()
|
||||||
|
{
|
||||||
|
return wrappedContainer.isNetworkMod();
|
||||||
|
}
|
||||||
@Override
|
@Override
|
||||||
public boolean isImmutable()
|
public boolean isImmutable()
|
||||||
{
|
{
|
||||||
|
|
|
@ -19,6 +19,7 @@ import com.google.common.eventbus.Subscribe;
|
||||||
import cpw.mods.fml.common.LoaderState.ModState;
|
import cpw.mods.fml.common.LoaderState.ModState;
|
||||||
import cpw.mods.fml.common.event.FMLLoadEvent;
|
import cpw.mods.fml.common.event.FMLLoadEvent;
|
||||||
import cpw.mods.fml.common.event.FMLStateEvent;
|
import cpw.mods.fml.common.event.FMLStateEvent;
|
||||||
|
import cpw.mods.fml.common.network.FMLNetworkHandler;
|
||||||
|
|
||||||
public class LoadController
|
public class LoadController
|
||||||
{
|
{
|
||||||
|
@ -67,6 +68,7 @@ public class LoadController
|
||||||
}
|
}
|
||||||
|
|
||||||
eventChannels = eventBus.build();
|
eventChannels = eventBus.build();
|
||||||
|
FMLNetworkHandler.instance().freezeModList(activeModList);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void distributeStateMessage(LoaderState state, Object... eventData)
|
public void distributeStateMessage(LoaderState state, Object... eventData)
|
||||||
|
|
|
@ -251,7 +251,7 @@ public class Loader
|
||||||
* Finally, if they are successfully loaded as classes, they are then added
|
* Finally, if they are successfully loaded as classes, they are then added
|
||||||
* to the available mod list.
|
* to the available mod list.
|
||||||
*/
|
*/
|
||||||
private void identifyMods()
|
private ModDiscoverer identifyMods()
|
||||||
{
|
{
|
||||||
FMLLog.fine("Building injected Mod Containers %s", injectedContainers);
|
FMLLog.fine("Building injected Mod Containers %s", injectedContainers);
|
||||||
for (String cont : injectedContainers)
|
for (String cont : injectedContainers)
|
||||||
|
@ -279,6 +279,7 @@ public class Loader
|
||||||
mods.addAll(discoverer.identifyMods());
|
mods.addAll(discoverer.identifyMods());
|
||||||
namedMods = Maps.uniqueIndex(mods, new ModIdFunction());
|
namedMods = Maps.uniqueIndex(mods, new ModIdFunction());
|
||||||
FMLLog.info("Forge Mod Loader has identified %d mod%s to load", mods.size(), mods.size() != 1 ? "s" : "");
|
FMLLog.info("Forge Mod Loader has identified %d mod%s to load", mods.size(), mods.size() != 1 ? "s" : "");
|
||||||
|
return discoverer;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -360,15 +361,15 @@ public class Loader
|
||||||
namedMods = Maps.newHashMap();
|
namedMods = Maps.newHashMap();
|
||||||
modController = new LoadController(this);
|
modController = new LoadController(this);
|
||||||
modController.transition(LoaderState.LOADING);
|
modController.transition(LoaderState.LOADING);
|
||||||
identifyMods();
|
ModDiscoverer disc = identifyMods();
|
||||||
disableRequestedMods();
|
disableRequestedMods();
|
||||||
sortModList();
|
sortModList();
|
||||||
mods = ImmutableList.copyOf(mods);
|
mods = ImmutableList.copyOf(mods);
|
||||||
modController.distributeStateMessage(FMLLoadEvent.class);
|
modController.distributeStateMessage(FMLLoadEvent.class);
|
||||||
modController.transition(LoaderState.CONSTRUCTING);
|
modController.transition(LoaderState.CONSTRUCTING);
|
||||||
modController.distributeStateMessage(LoaderState.CONSTRUCTING, modClassLoader);
|
modController.distributeStateMessage(LoaderState.CONSTRUCTING, modClassLoader, disc.getASMTable());
|
||||||
modController.transition(LoaderState.PREINITIALIZATION);
|
modController.transition(LoaderState.PREINITIALIZATION);
|
||||||
modController.distributeStateMessage(LoaderState.PREINITIALIZATION);
|
modController.distributeStateMessage(LoaderState.PREINITIALIZATION, disc.getASMTable());
|
||||||
modController.transition(LoaderState.INITIALIZATION);
|
modController.transition(LoaderState.INITIALIZATION);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -150,4 +150,6 @@ public interface ModContainer
|
||||||
ProxyInjector findSidedProxy();
|
ProxyInjector findSidedProxy();
|
||||||
|
|
||||||
boolean isImmutable();
|
boolean isImmutable();
|
||||||
|
|
||||||
|
boolean isNetworkMod();
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,106 @@
|
||||||
|
package cpw.mods.fml.common.discovery;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
|
import com.google.common.base.Predicate;
|
||||||
|
import com.google.common.collect.HashMultimap;
|
||||||
|
import com.google.common.collect.ImmutableMap;
|
||||||
|
import com.google.common.collect.ImmutableSetMultimap;
|
||||||
|
import com.google.common.collect.ListMultimap;
|
||||||
|
import com.google.common.collect.Lists;
|
||||||
|
import com.google.common.collect.Multimap;
|
||||||
|
import com.google.common.collect.Multimaps;
|
||||||
|
import com.google.common.collect.SetMultimap;
|
||||||
|
import com.google.common.collect.ImmutableBiMap.Builder;
|
||||||
|
|
||||||
|
import cpw.mods.fml.common.ModContainer;
|
||||||
|
|
||||||
|
public class ASMDataTable
|
||||||
|
{
|
||||||
|
public static class ASMData
|
||||||
|
{
|
||||||
|
private ModCandidate candidate;
|
||||||
|
private String annotationName;
|
||||||
|
private String className;
|
||||||
|
private String objectName;
|
||||||
|
private Map<String,Object> annotationInfo;
|
||||||
|
public ASMData(ModCandidate candidate, String annotationName, String className, String objectName, Map<String,Object> info)
|
||||||
|
{
|
||||||
|
this.candidate = candidate;
|
||||||
|
this.annotationName = annotationName;
|
||||||
|
this.className = className;
|
||||||
|
this.objectName = objectName;
|
||||||
|
this.annotationInfo = info;
|
||||||
|
}
|
||||||
|
public ModCandidate getCandidate()
|
||||||
|
{
|
||||||
|
return candidate;
|
||||||
|
}
|
||||||
|
public String getAnnotationName()
|
||||||
|
{
|
||||||
|
return annotationName;
|
||||||
|
}
|
||||||
|
public String getClassName()
|
||||||
|
{
|
||||||
|
return className;
|
||||||
|
}
|
||||||
|
public String getObjectName()
|
||||||
|
{
|
||||||
|
return objectName;
|
||||||
|
}
|
||||||
|
public Map<String, Object> getAnnotationInfo()
|
||||||
|
{
|
||||||
|
return annotationInfo;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static class ModContainerPredicate implements Predicate<ASMData>
|
||||||
|
{
|
||||||
|
private ModContainer container;
|
||||||
|
public ModContainerPredicate(ModContainer container)
|
||||||
|
{
|
||||||
|
this.container = container;
|
||||||
|
}
|
||||||
|
public boolean apply(ASMData data)
|
||||||
|
{
|
||||||
|
return container.getSource().equals(data.candidate.getModContainer());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
private SetMultimap<String, ASMData> globalAnnotationData;
|
||||||
|
private Map<ModContainer, SetMultimap<String,ASMData>> containerAnnotationData;
|
||||||
|
|
||||||
|
private List<ModContainer> containers = Lists.newArrayList();
|
||||||
|
|
||||||
|
public SetMultimap<String,ASMData> getAnnotationsFor(ModContainer container)
|
||||||
|
{
|
||||||
|
if (containerAnnotationData == null)
|
||||||
|
{
|
||||||
|
ImmutableMap.Builder<ModContainer, SetMultimap<String, ASMData>> mapBuilder = ImmutableMap.<ModContainer, SetMultimap<String,ASMData>>builder();
|
||||||
|
for (ModContainer cont : containers)
|
||||||
|
{
|
||||||
|
Multimap<String, ASMData> values = Multimaps.filterValues(globalAnnotationData, new ModContainerPredicate(cont));
|
||||||
|
mapBuilder.put(cont, ImmutableSetMultimap.copyOf(values));
|
||||||
|
}
|
||||||
|
containerAnnotationData = mapBuilder.build();
|
||||||
|
}
|
||||||
|
return containerAnnotationData.get(container);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Set<ASMData> getAll(String annotation)
|
||||||
|
{
|
||||||
|
return globalAnnotationData.get(annotation);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void addASMData(ModCandidate candidate, String annotation, String className, String objectName, Map<String,Object> annotationInfo)
|
||||||
|
{
|
||||||
|
globalAnnotationData.put(annotation, new ASMData(candidate, annotation, className, objectName, annotationInfo));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void addContainer(ModContainer container)
|
||||||
|
{
|
||||||
|
this.containers.add(container);
|
||||||
|
}
|
||||||
|
}
|
|
@ -10,7 +10,7 @@ public enum ContainerType
|
||||||
{
|
{
|
||||||
JAR(JarDiscoverer.class),
|
JAR(JarDiscoverer.class),
|
||||||
DIR(DirectoryDiscoverer.class);
|
DIR(DirectoryDiscoverer.class);
|
||||||
|
|
||||||
private ITypeDiscoverer discoverer;
|
private ITypeDiscoverer discoverer;
|
||||||
|
|
||||||
private ContainerType(Class<? extends ITypeDiscoverer> discovererClass)
|
private ContainerType(Class<? extends ITypeDiscoverer> discovererClass)
|
||||||
|
@ -24,9 +24,9 @@ public enum ContainerType
|
||||||
throw Throwables.propagate(e);
|
throw Throwables.propagate(e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public List<ModContainer> findMods(ModCandidate candidate)
|
public List<ModContainer> findMods(ModCandidate candidate, ASMDataTable table)
|
||||||
{
|
{
|
||||||
return discoverer.discover(candidate);
|
return discoverer.discover(candidate, table);
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -30,12 +30,19 @@ public class DirectoryDiscoverer implements ITypeDiscoverer
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private ASMDataTable table;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public List<ModContainer> discover(ModCandidate candidate)
|
public List<ModContainer> discover(ModCandidate candidate, ASMDataTable table)
|
||||||
{
|
{
|
||||||
|
this.table = table;
|
||||||
List<ModContainer> found = Lists.newArrayList();
|
List<ModContainer> found = Lists.newArrayList();
|
||||||
FMLLog.fine("Examining directory %s for potential mods", candidate.getModContainer().getName());
|
FMLLog.fine("Examining directory %s for potential mods", candidate.getModContainer().getName());
|
||||||
exploreFileSystem("", candidate.getModContainer(), found, candidate, null);
|
exploreFileSystem("", candidate.getModContainer(), found, candidate, null);
|
||||||
|
for (ModContainer mc : found)
|
||||||
|
{
|
||||||
|
table.addContainer(mc);
|
||||||
|
}
|
||||||
return found;
|
return found;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -85,6 +92,7 @@ public class DirectoryDiscoverer implements ITypeDiscoverer
|
||||||
}
|
}
|
||||||
|
|
||||||
modParser.validate();
|
modParser.validate();
|
||||||
|
modParser.sendToTable(table, candidate);
|
||||||
ModContainer container = ModContainerFactory.instance().build(modParser, candidate.getModContainer());
|
ModContainer container = ModContainerFactory.instance().build(modParser, candidate.getModContainer());
|
||||||
if (container!=null)
|
if (container!=null)
|
||||||
{
|
{
|
||||||
|
|
|
@ -9,5 +9,5 @@ public interface ITypeDiscoverer
|
||||||
{
|
{
|
||||||
public static Pattern classFile = Pattern.compile("([^\\s$]+).class$");
|
public static Pattern classFile = Pattern.compile("([^\\s$]+).class$");
|
||||||
|
|
||||||
public List<ModContainer> discover(ModCandidate candidate);
|
public List<ModContainer> discover(ModCandidate candidate, ASMDataTable table);
|
||||||
}
|
}
|
||||||
|
|
|
@ -18,7 +18,7 @@ import cpw.mods.fml.common.discovery.asm.ASMModParser;
|
||||||
public class JarDiscoverer implements ITypeDiscoverer
|
public class JarDiscoverer implements ITypeDiscoverer
|
||||||
{
|
{
|
||||||
@Override
|
@Override
|
||||||
public List<ModContainer> discover(ModCandidate candidate)
|
public List<ModContainer> discover(ModCandidate candidate, ASMDataTable table)
|
||||||
{
|
{
|
||||||
List<ModContainer> foundMods = Lists.newArrayList();
|
List<ModContainer> foundMods = Lists.newArrayList();
|
||||||
FMLLog.fine("Examining file %s for potential mods", candidate.getModContainer().getName());
|
FMLLog.fine("Examining file %s for potential mods", candidate.getModContainer().getName());
|
||||||
|
@ -41,9 +41,11 @@ public class JarDiscoverer implements ITypeDiscoverer
|
||||||
{
|
{
|
||||||
ASMModParser modParser = new ASMModParser(jar.getInputStream(ze));
|
ASMModParser modParser = new ASMModParser(jar.getInputStream(ze));
|
||||||
modParser.validate();
|
modParser.validate();
|
||||||
|
modParser.sendToTable(table, candidate);
|
||||||
ModContainer container = ModContainerFactory.instance().build(modParser, candidate.getModContainer());
|
ModContainer container = ModContainerFactory.instance().build(modParser, candidate.getModContainer());
|
||||||
if (container!=null)
|
if (container!=null)
|
||||||
{
|
{
|
||||||
|
table.addContainer(container);
|
||||||
foundMods.add(container);
|
foundMods.add(container);
|
||||||
container.bindMetadata(mc);
|
container.bindMetadata(mc);
|
||||||
}
|
}
|
||||||
|
|
|
@ -39,8 +39,8 @@ public class ModCandidate
|
||||||
{
|
{
|
||||||
return sourceType;
|
return sourceType;
|
||||||
}
|
}
|
||||||
public List<ModContainer> explore()
|
public List<ModContainer> explore(ASMDataTable table)
|
||||||
{
|
{
|
||||||
return sourceType.findMods(this);
|
return sourceType.findMods(this, table);
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -8,7 +8,9 @@ import java.io.IOException;
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
import java.nio.channels.FileChannel;
|
import java.nio.channels.FileChannel;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
|
import java.util.Collection;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
|
import java.util.HashMap;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.logging.Level;
|
import java.util.logging.Level;
|
||||||
|
@ -25,9 +27,18 @@ import org.objectweb.asm.ClassVisitor;
|
||||||
import org.objectweb.asm.FieldVisitor;
|
import org.objectweb.asm.FieldVisitor;
|
||||||
import org.objectweb.asm.Opcodes;
|
import org.objectweb.asm.Opcodes;
|
||||||
|
|
||||||
|
import com.google.common.base.Supplier;
|
||||||
import com.google.common.base.Throwables;
|
import com.google.common.base.Throwables;
|
||||||
|
import com.google.common.collect.HashBasedTable;
|
||||||
|
import com.google.common.collect.HashMultimap;
|
||||||
import com.google.common.collect.ImmutableList;
|
import com.google.common.collect.ImmutableList;
|
||||||
|
import com.google.common.collect.ImmutableTable;
|
||||||
|
import com.google.common.collect.Tables;
|
||||||
|
import com.google.common.collect.ImmutableTable.Builder;
|
||||||
import com.google.common.collect.Lists;
|
import com.google.common.collect.Lists;
|
||||||
|
import com.google.common.collect.Multimap;
|
||||||
|
import com.google.common.collect.Table;
|
||||||
|
import com.google.common.collect.Table.Cell;
|
||||||
|
|
||||||
import cpw.mods.fml.common.FMLLog;
|
import cpw.mods.fml.common.FMLLog;
|
||||||
import cpw.mods.fml.common.LoaderException;
|
import cpw.mods.fml.common.LoaderException;
|
||||||
|
@ -41,6 +52,8 @@ public class ModDiscoverer
|
||||||
|
|
||||||
private List<ModCandidate> candidates = Lists.newArrayList();
|
private List<ModCandidate> candidates = Lists.newArrayList();
|
||||||
|
|
||||||
|
private ASMDataTable dataTable = new ASMDataTable();
|
||||||
|
|
||||||
public void findClasspathMods(ModClassLoader modClassLoader)
|
public void findClasspathMods(ModClassLoader modClassLoader)
|
||||||
{
|
{
|
||||||
List<String> knownLibraries = ImmutableList.<String>builder().addAll(modClassLoader.getDefaultLibraries()).addAll(RelaunchLibraryManager.getLibraries()).build();
|
List<String> knownLibraries = ImmutableList.<String>builder().addAll(modClassLoader.getDefaultLibraries()).addAll(RelaunchLibraryManager.getLibraries()).build();
|
||||||
|
@ -114,7 +127,7 @@ public class ModDiscoverer
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
List<ModContainer> mods = candidate.explore();
|
List<ModContainer> mods = candidate.explore(dataTable);
|
||||||
modList.addAll(mods);
|
modList.addAll(mods);
|
||||||
}
|
}
|
||||||
catch (LoaderException le)
|
catch (LoaderException le)
|
||||||
|
@ -129,4 +142,10 @@ public class ModDiscoverer
|
||||||
|
|
||||||
return modList;
|
return modList;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public ASMDataTable getASMTable()
|
||||||
|
{
|
||||||
|
return dataTable;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -14,6 +14,9 @@ import com.google.common.base.Objects;
|
||||||
import com.google.common.collect.Lists;
|
import com.google.common.collect.Lists;
|
||||||
|
|
||||||
import cpw.mods.fml.common.LoaderException;
|
import cpw.mods.fml.common.LoaderException;
|
||||||
|
import cpw.mods.fml.common.discovery.ASMDataTable;
|
||||||
|
import cpw.mods.fml.common.discovery.ModCandidate;
|
||||||
|
import cpw.mods.fml.common.discovery.ModDiscoverer;
|
||||||
|
|
||||||
public class ASMModParser
|
public class ASMModParser
|
||||||
{
|
{
|
||||||
|
@ -23,18 +26,18 @@ public class ASMModParser
|
||||||
private Type asmSuperType;
|
private Type asmSuperType;
|
||||||
private LinkedList<ModAnnotation> annotations = Lists.newLinkedList();
|
private LinkedList<ModAnnotation> annotations = Lists.newLinkedList();
|
||||||
private String baseModProperties;
|
private String baseModProperties;
|
||||||
|
|
||||||
static enum AnnotationType
|
static enum AnnotationType
|
||||||
{
|
{
|
||||||
CLASS, FIELD, METHOD;
|
CLASS, FIELD, METHOD;
|
||||||
}
|
}
|
||||||
|
|
||||||
public ASMModParser(InputStream stream) throws IOException
|
public ASMModParser(InputStream stream) throws IOException
|
||||||
{
|
{
|
||||||
ClassReader reader = new ClassReader(stream);
|
ClassReader reader = new ClassReader(stream);
|
||||||
reader.accept(new ModClassVisitor(this), 0);
|
reader.accept(new ModClassVisitor(this), 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void beginNewTypeName(String typeQName, int classVersion, String superClassQName)
|
public void beginNewTypeName(String typeQName, int classVersion, String superClassQName)
|
||||||
{
|
{
|
||||||
this.asmType = Type.getObjectType(typeQName);
|
this.asmType = Type.getObjectType(typeQName);
|
||||||
|
@ -58,7 +61,7 @@ public class ASMModParser
|
||||||
ModAnnotation ann = new ModAnnotation(AnnotationType.FIELD, Type.getType(annotationName), fieldName);
|
ModAnnotation ann = new ModAnnotation(AnnotationType.FIELD, Type.getType(annotationName), fieldName);
|
||||||
annotations.addFirst(ann);
|
annotations.addFirst(ann);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String toString()
|
public String toString()
|
||||||
{
|
{
|
||||||
|
@ -91,12 +94,12 @@ public class ASMModParser
|
||||||
{
|
{
|
||||||
return annotations;
|
return annotations;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void validate()
|
public void validate()
|
||||||
{
|
{
|
||||||
// if (classVersion > 50.0)
|
// if (classVersion > 50.0)
|
||||||
// {
|
// {
|
||||||
//
|
//
|
||||||
// throw new LoaderException(new RuntimeException("Mod compiled for Java 7 detected"));
|
// throw new LoaderException(new RuntimeException("Mod compiled for Java 7 detected"));
|
||||||
// }
|
// }
|
||||||
}
|
}
|
||||||
|
@ -115,4 +118,12 @@ public class ASMModParser
|
||||||
{
|
{
|
||||||
return this.baseModProperties;
|
return this.baseModProperties;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void sendToTable(ASMDataTable table, ModCandidate candidate)
|
||||||
|
{
|
||||||
|
for (ModAnnotation ma : annotations)
|
||||||
|
{
|
||||||
|
table.addASMData(candidate, ma.asmType.getClassName(), this.asmType.getClassName(), ma.member, ma.values);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,17 +1,28 @@
|
||||||
package cpw.mods.fml.common.event;
|
package cpw.mods.fml.common.event;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
import com.google.common.collect.Table;
|
||||||
|
|
||||||
import cpw.mods.fml.common.LoaderState.ModState;
|
import cpw.mods.fml.common.LoaderState.ModState;
|
||||||
import cpw.mods.fml.common.ModClassLoader;
|
import cpw.mods.fml.common.ModClassLoader;
|
||||||
|
import cpw.mods.fml.common.ModContainer;
|
||||||
|
import cpw.mods.fml.common.discovery.ASMDataTable;
|
||||||
|
import cpw.mods.fml.common.discovery.ASMDataTable.ASMData;
|
||||||
|
import cpw.mods.fml.common.discovery.ModDiscoverer;
|
||||||
|
|
||||||
public class FMLConstructionEvent extends FMLStateEvent
|
public class FMLConstructionEvent extends FMLStateEvent
|
||||||
{
|
{
|
||||||
private ModClassLoader modClassLoader;
|
private ModClassLoader modClassLoader;
|
||||||
|
private ASMDataTable asmData;
|
||||||
|
|
||||||
public FMLConstructionEvent(Object... eventData)
|
public FMLConstructionEvent(Object... eventData)
|
||||||
{
|
{
|
||||||
this.modClassLoader = (ModClassLoader)eventData[0];
|
this.modClassLoader = (ModClassLoader)eventData[0];
|
||||||
|
this.asmData = (ASMDataTable) eventData[1];
|
||||||
}
|
}
|
||||||
|
|
||||||
public ModClassLoader getModClassLoader()
|
public ModClassLoader getModClassLoader()
|
||||||
{
|
{
|
||||||
return modClassLoader;
|
return modClassLoader;
|
||||||
|
@ -22,4 +33,9 @@ public class FMLConstructionEvent extends FMLStateEvent
|
||||||
{
|
{
|
||||||
return ModState.CONSTRUCTED;
|
return ModState.CONSTRUCTED;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public ASMDataTable getASMHarvestedData()
|
||||||
|
{
|
||||||
|
return asmData;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,7 +1,9 @@
|
||||||
package cpw.mods.fml.common.event;
|
package cpw.mods.fml.common.event;
|
||||||
|
|
||||||
|
import cpw.mods.fml.common.FMLCommonHandler;
|
||||||
import cpw.mods.fml.common.LoaderState.ModState;
|
import cpw.mods.fml.common.LoaderState.ModState;
|
||||||
import cpw.mods.fml.common.ModContainer;
|
import cpw.mods.fml.common.ModContainer;
|
||||||
|
import cpw.mods.fml.common.Side;
|
||||||
|
|
||||||
public abstract class FMLStateEvent extends FMLEvent
|
public abstract class FMLStateEvent extends FMLEvent
|
||||||
{
|
{
|
||||||
|
@ -16,4 +18,9 @@ public abstract class FMLStateEvent extends FMLEvent
|
||||||
{
|
{
|
||||||
// NO OP
|
// NO OP
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Side getSide()
|
||||||
|
{
|
||||||
|
return FMLCommonHandler.instance().getSide();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -59,6 +59,8 @@ import cpw.mods.fml.common.event.FMLConstructionEvent;
|
||||||
import cpw.mods.fml.common.event.FMLInitializationEvent;
|
import cpw.mods.fml.common.event.FMLInitializationEvent;
|
||||||
import cpw.mods.fml.common.event.FMLPostInitializationEvent;
|
import cpw.mods.fml.common.event.FMLPostInitializationEvent;
|
||||||
import cpw.mods.fml.common.event.FMLPreInitializationEvent;
|
import cpw.mods.fml.common.event.FMLPreInitializationEvent;
|
||||||
|
import cpw.mods.fml.common.network.FMLNetworkHandler;
|
||||||
|
import cpw.mods.fml.common.network.NetworkMod;
|
||||||
import cpw.mods.fml.common.registry.TickRegistry;
|
import cpw.mods.fml.common.registry.TickRegistry;
|
||||||
import cpw.mods.fml.common.registry.GameRegistry;
|
import cpw.mods.fml.common.registry.GameRegistry;
|
||||||
import cpw.mods.fml.common.versioning.ArtifactVersion;
|
import cpw.mods.fml.common.versioning.ArtifactVersion;
|
||||||
|
@ -88,6 +90,7 @@ public class ModLoaderModContainer implements ModContainer
|
||||||
private boolean enabled = true;
|
private boolean enabled = true;
|
||||||
private String sortingProperties;
|
private String sortingProperties;
|
||||||
private ArtifactVersion processedVersion;
|
private ArtifactVersion processedVersion;
|
||||||
|
private boolean isNetworkMod;
|
||||||
|
|
||||||
public ModLoaderModContainer(String className, File modSource, String sortingProperties)
|
public ModLoaderModContainer(String className, File modSource, String sortingProperties)
|
||||||
{
|
{
|
||||||
|
@ -490,6 +493,7 @@ public class ModLoaderModContainer implements ModContainer
|
||||||
modClassLoader.addFile(modSource);
|
modClassLoader.addFile(modSource);
|
||||||
Class<? extends BaseMod> modClazz = (Class<? extends BaseMod>) Class.forName(modClazzName, true, modClassLoader);
|
Class<? extends BaseMod> modClazz = (Class<? extends BaseMod>) Class.forName(modClazzName, true, modClassLoader);
|
||||||
configureMod(modClazz);
|
configureMod(modClazz);
|
||||||
|
isNetworkMod = FMLNetworkHandler.instance().registerNetworkMod(this, modClazz, event.getASMHarvestedData());
|
||||||
mod = (BaseMod)modClazz.newInstance();
|
mod = (BaseMod)modClazz.newInstance();
|
||||||
}
|
}
|
||||||
catch (Exception e)
|
catch (Exception e)
|
||||||
|
@ -564,4 +568,10 @@ public class ModLoaderModContainer implements ModContainer
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isNetworkMod()
|
||||||
|
{
|
||||||
|
return this.isNetworkMod;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,10 @@
|
||||||
|
package cpw.mods.fml.common.network;
|
||||||
|
|
||||||
|
public class FMLNetworkException extends RuntimeException
|
||||||
|
{
|
||||||
|
|
||||||
|
public FMLNetworkException(Exception e)
|
||||||
|
{
|
||||||
|
super(e);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,164 @@
|
||||||
|
package cpw.mods.fml.common.network;
|
||||||
|
|
||||||
|
import static cpw.mods.fml.common.network.FMLPacket.Type.*;
|
||||||
|
|
||||||
|
import java.net.SocketAddress;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Set;
|
||||||
|
import java.util.WeakHashMap;
|
||||||
|
|
||||||
|
import com.google.common.collect.ArrayListMultimap;
|
||||||
|
import com.google.common.collect.BiMap;
|
||||||
|
import com.google.common.collect.ListMultimap;
|
||||||
|
import com.google.common.collect.Lists;
|
||||||
|
import com.google.common.collect.Maps;
|
||||||
|
import com.google.common.collect.Multimap;
|
||||||
|
import com.google.common.collect.Sets;
|
||||||
|
import com.google.common.hash.Hashing;
|
||||||
|
import com.google.common.io.ByteStreams;
|
||||||
|
|
||||||
|
import cpw.mods.fml.common.Loader;
|
||||||
|
import cpw.mods.fml.common.ModContainer;
|
||||||
|
import cpw.mods.fml.common.discovery.ASMDataTable;
|
||||||
|
import cpw.mods.fml.common.discovery.ASMDataTable.ASMData;
|
||||||
|
|
||||||
|
import net.minecraft.server.MinecraftServer;
|
||||||
|
import net.minecraft.src.NetHandler;
|
||||||
|
import net.minecraft.src.NetLoginHandler;
|
||||||
|
import net.minecraft.src.NetworkManager;
|
||||||
|
import net.minecraft.src.Packet;
|
||||||
|
import net.minecraft.src.Packet1Login;
|
||||||
|
import net.minecraft.src.Packet250CustomPayload;
|
||||||
|
import net.minecraft.src.ServerConfigurationManager;
|
||||||
|
import net.minecraft.src.TcpConnection;
|
||||||
|
|
||||||
|
public class FMLNetworkHandler
|
||||||
|
{
|
||||||
|
private static final int FML_HASH = Hashing.murmur3_32().hashString("FML").asInt();
|
||||||
|
private static final int PROTOCOL_VERSION = 0x1;
|
||||||
|
private static final FMLNetworkHandler INSTANCE = new FMLNetworkHandler();
|
||||||
|
|
||||||
|
private Map<NetLoginHandler, Integer> loginStates = Maps.newHashMap();
|
||||||
|
private Map<ModContainer, NetworkModHandler> networkModHandlers = Maps.newHashMap();
|
||||||
|
|
||||||
|
private Map<Integer, NetworkModHandler> networkIdLookup = Maps.newHashMap();
|
||||||
|
|
||||||
|
public static void handlePacket250Packet(Packet250CustomPayload packet, NetworkManager network, NetHandler handler)
|
||||||
|
{
|
||||||
|
String target = packet.field_73630_a;
|
||||||
|
|
||||||
|
if (target.startsWith("MC|"))
|
||||||
|
{
|
||||||
|
handler.handleVanilla250Packet(packet);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (target.equals("FML"))
|
||||||
|
{
|
||||||
|
instance().handleFMLPacket(packet, network);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void handleFMLPacket(Packet250CustomPayload packet, NetworkManager network)
|
||||||
|
{
|
||||||
|
FMLPacket pkt = FMLPacket.readPacket(packet.field_73629_c);
|
||||||
|
pkt.execute(network, this);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void onClientConnectToServer(NetLoginHandler netLoginHandler, MinecraftServer server, SocketAddress address, String userName)
|
||||||
|
{
|
||||||
|
instance().handleClientConnection(netLoginHandler, server, address, userName);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void handleClientConnection(NetLoginHandler netLoginHandler, MinecraftServer server, SocketAddress address, String userName)
|
||||||
|
{
|
||||||
|
if (!loginStates.containsKey(netLoginHandler))
|
||||||
|
{
|
||||||
|
// Vanilla reasons first
|
||||||
|
ServerConfigurationManager playerList = server.func_71203_ab();
|
||||||
|
String kickReason = playerList.func_72399_a(address, userName);
|
||||||
|
|
||||||
|
if (kickReason!=null)
|
||||||
|
{
|
||||||
|
netLoginHandler.completeConnection(kickReason);
|
||||||
|
}
|
||||||
|
// No FML on the client
|
||||||
|
netLoginHandler.completeConnection("You don't have FML installed, or your installation is too old");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// Are we ready to negotiate with the client?
|
||||||
|
if (loginStates.get(netLoginHandler) == 1)
|
||||||
|
{
|
||||||
|
// Reset the "connection completed" flag so processing can continue
|
||||||
|
NetLoginHandler.func_72531_a(netLoginHandler, false);
|
||||||
|
// Send the mod list request packet to the client from the server
|
||||||
|
netLoginHandler.field_72538_b.func_74429_a(getModListRequestPacket());
|
||||||
|
loginStates.put(netLoginHandler, 2);
|
||||||
|
}
|
||||||
|
// We must be good to go - the ModIdentifiers packet was sent and the continuation signal was indicated
|
||||||
|
else if (loginStates.get(netLoginHandler) == 2)
|
||||||
|
{
|
||||||
|
netLoginHandler.completeConnection(null);
|
||||||
|
loginStates.remove(netLoginHandler);
|
||||||
|
}
|
||||||
|
// We have to abort this connection - there was a negotiation problem (most likely missing mods)
|
||||||
|
else
|
||||||
|
{
|
||||||
|
netLoginHandler.completeConnection("There was a problem during FML negotiation");
|
||||||
|
loginStates.remove(netLoginHandler);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void handleLoginPacketOnServer(NetLoginHandler handler, Packet1Login login)
|
||||||
|
{
|
||||||
|
if (login.field_73561_a == FML_HASH && login.field_73558_e == PROTOCOL_VERSION)
|
||||||
|
{
|
||||||
|
instance().loginStates.put(handler,1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
public static FMLNetworkHandler instance()
|
||||||
|
{
|
||||||
|
return INSTANCE;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Packet1Login getFMLFakeLoginPacket()
|
||||||
|
{
|
||||||
|
Packet1Login fake = new Packet1Login();
|
||||||
|
// Hash FML using a simple function
|
||||||
|
fake.field_73561_a = FML_HASH;
|
||||||
|
// The FML protocol version
|
||||||
|
fake.field_73558_e = PROTOCOL_VERSION;
|
||||||
|
return fake;
|
||||||
|
}
|
||||||
|
public static Packet250CustomPayload getModListRequestPacket()
|
||||||
|
{
|
||||||
|
Packet250CustomPayload pkt = new Packet250CustomPayload();
|
||||||
|
pkt.field_73630_a = "FML";
|
||||||
|
pkt.field_73629_c = FMLPacket.makePacket(MOD_LIST_REQUEST);
|
||||||
|
pkt.field_73628_b = pkt.field_73629_c.length;
|
||||||
|
return pkt;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean registerNetworkMod(ModContainer container, Class<?> networkModClass, ASMDataTable asmData)
|
||||||
|
{
|
||||||
|
NetworkModHandler handler = new NetworkModHandler(container, networkModClass, asmData);
|
||||||
|
if (handler.isNetworkMod())
|
||||||
|
{
|
||||||
|
networkModHandlers.put(container, handler);
|
||||||
|
networkIdLookup.put(handler.getNetworkId(), handler);
|
||||||
|
}
|
||||||
|
|
||||||
|
return handler.isNetworkMod();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public NetworkModHandler findNetworkModHandler(ModContainer mc)
|
||||||
|
{
|
||||||
|
return networkModHandlers.get(mc);
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<ModContainer> getNetworkModList()
|
||||||
|
{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,90 @@
|
||||||
|
package cpw.mods.fml.common.network;
|
||||||
|
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.logging.Level;
|
||||||
|
|
||||||
|
import net.minecraft.src.NetHandler;
|
||||||
|
import net.minecraft.src.NetworkManager;
|
||||||
|
|
||||||
|
import com.google.common.base.Throwables;
|
||||||
|
import com.google.common.io.ByteStreams;
|
||||||
|
import com.google.common.primitives.Bytes;
|
||||||
|
import com.google.common.primitives.Primitives;
|
||||||
|
import com.google.common.primitives.UnsignedBytes;
|
||||||
|
|
||||||
|
import cpw.mods.fml.common.FMLLog;
|
||||||
|
|
||||||
|
public abstract class FMLPacket
|
||||||
|
{
|
||||||
|
enum Type
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Opening salutation from the server to the client -> request all mods from the client
|
||||||
|
*/
|
||||||
|
MOD_LIST_REQUEST(ModListRequestPacket.class),
|
||||||
|
/**
|
||||||
|
* The client responds with the list of mods and versions it has. This is verified by the server.
|
||||||
|
*/
|
||||||
|
MOD_LIST_RESPONSE(ModListResponsePacket.class),
|
||||||
|
/**
|
||||||
|
* At which point the server tells the client the mod identifiers for this session.
|
||||||
|
*/
|
||||||
|
MOD_IDENTIFIERS(ModIdentifiersPacket.class),
|
||||||
|
/**
|
||||||
|
* Or, if there is missing stuff, the server tells the client what's missing and drops the connection.
|
||||||
|
*/
|
||||||
|
MOD_MISSING(ModMissingPacket.class);
|
||||||
|
|
||||||
|
private Class<? extends FMLPacket> packetType;
|
||||||
|
|
||||||
|
private Type(Class<? extends FMLPacket> clazz)
|
||||||
|
{
|
||||||
|
this.packetType = clazz;
|
||||||
|
}
|
||||||
|
|
||||||
|
FMLPacket make()
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
return this.packetType.newInstance();
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
Throwables.propagateIfPossible(e);
|
||||||
|
FMLLog.log(Level.SEVERE, e, "A bizarre critical error occured during packet encoding");
|
||||||
|
throw new FMLNetworkException(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private Type type;
|
||||||
|
|
||||||
|
public static byte[] makePacket(Type type, Object... data)
|
||||||
|
{
|
||||||
|
byte[] packetData = type.make().generatePacket(data);
|
||||||
|
return Bytes.concat(new byte[] { UnsignedBytes.checkedCast(type.ordinal()) }, packetData );
|
||||||
|
}
|
||||||
|
|
||||||
|
public static FMLPacket readPacket(byte[] payload)
|
||||||
|
{
|
||||||
|
int type = UnsignedBytes.toInt(payload[0]);
|
||||||
|
return Type.values()[type].make().consumePacket(Arrays.copyOfRange(payload, 1, payload.length));
|
||||||
|
}
|
||||||
|
|
||||||
|
public FMLPacket(Type type)
|
||||||
|
{
|
||||||
|
this.type = type;
|
||||||
|
}
|
||||||
|
|
||||||
|
public abstract byte[] generatePacket(Object... data);
|
||||||
|
|
||||||
|
public abstract FMLPacket consumePacket(byte[] data);
|
||||||
|
|
||||||
|
public abstract void execute(NetworkManager network, FMLNetworkHandler handler, NetHandler netHandler);
|
||||||
|
{
|
||||||
|
// TODO Auto-generated method stub
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,35 @@
|
||||||
|
package cpw.mods.fml.common.network;
|
||||||
|
|
||||||
|
import static cpw.mods.fml.common.network.FMLPacket.Type.*;
|
||||||
|
import net.minecraft.src.NetHandler;
|
||||||
|
import net.minecraft.src.NetworkManager;
|
||||||
|
|
||||||
|
public class ModIdentifiersPacket extends FMLPacket
|
||||||
|
{
|
||||||
|
|
||||||
|
public ModIdentifiersPacket()
|
||||||
|
{
|
||||||
|
super(MOD_IDENTIFIERS);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public byte[] generatePacket(Object... data)
|
||||||
|
{
|
||||||
|
// TODO Auto-generated method stub
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public FMLPacket consumePacket(byte[] data)
|
||||||
|
{
|
||||||
|
// TODO Auto-generated method stub
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void execute(NetworkManager network, FMLNetworkHandler handler, NetHandler netHandler)
|
||||||
|
{
|
||||||
|
// TODO Auto-generated method stub
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,96 @@
|
||||||
|
package cpw.mods.fml.common.network;
|
||||||
|
|
||||||
|
import static cpw.mods.fml.common.network.FMLPacket.Type.*;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.logging.Level;
|
||||||
|
|
||||||
|
import net.minecraft.src.NetHandler;
|
||||||
|
import net.minecraft.src.NetworkManager;
|
||||||
|
import net.minecraft.src.Packet250CustomPayload;
|
||||||
|
|
||||||
|
import com.google.common.collect.Lists;
|
||||||
|
import com.google.common.collect.Maps;
|
||||||
|
import com.google.common.io.ByteArrayDataInput;
|
||||||
|
import com.google.common.io.ByteArrayDataOutput;
|
||||||
|
import com.google.common.io.ByteStreams;
|
||||||
|
|
||||||
|
import cpw.mods.fml.common.FMLLog;
|
||||||
|
import cpw.mods.fml.common.Loader;
|
||||||
|
import cpw.mods.fml.common.ModContainer;
|
||||||
|
|
||||||
|
public class ModListRequestPacket extends FMLPacket
|
||||||
|
{
|
||||||
|
private List<String> sentModList;
|
||||||
|
|
||||||
|
public ModListRequestPacket()
|
||||||
|
{
|
||||||
|
super(MOD_LIST_REQUEST);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public byte[] generatePacket(Object... data)
|
||||||
|
{
|
||||||
|
ByteArrayDataOutput dat = ByteStreams.newDataOutput();
|
||||||
|
List<ModContainer> activeMods = FMLNetworkHandler.instance().getNetworkModList();
|
||||||
|
dat.writeInt(activeMods.size());
|
||||||
|
for (ModContainer mc : activeMods)
|
||||||
|
{
|
||||||
|
dat.writeUTF(mc.getModId());
|
||||||
|
}
|
||||||
|
return dat.toByteArray();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public FMLPacket consumePacket(byte[] data)
|
||||||
|
{
|
||||||
|
sentModList = Lists.newArrayList();
|
||||||
|
ByteArrayDataInput in = ByteStreams.newDataInput(data);
|
||||||
|
int listSize = in.readInt();
|
||||||
|
for (int i = 0; i < listSize; i++)
|
||||||
|
{
|
||||||
|
sentModList.add(in.readUTF());
|
||||||
|
}
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* This packet is executed on the client to evaluate the server's mod list against
|
||||||
|
* the client
|
||||||
|
*
|
||||||
|
* @see cpw.mods.fml.common.network.FMLPacket#execute()
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public void execute(NetworkManager mgr, FMLNetworkHandler handler, NetHandler netHandler)
|
||||||
|
{
|
||||||
|
List<String> missingMods = Lists.newArrayList();
|
||||||
|
Map<String,String> modVersions = Maps.newHashMap();
|
||||||
|
Map<String, ModContainer> indexedModList = Maps.newHashMap(Loader.instance().getIndexedModList());
|
||||||
|
|
||||||
|
for (String m : sentModList)
|
||||||
|
{
|
||||||
|
ModContainer mc = indexedModList.get(m);
|
||||||
|
if (mc == null)
|
||||||
|
{
|
||||||
|
missingMods.add(m);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
indexedModList.remove(m);
|
||||||
|
modVersions.put(m, mc.getVersion());
|
||||||
|
}
|
||||||
|
|
||||||
|
if (indexedModList.size()>0)
|
||||||
|
{
|
||||||
|
// TODO : handle client present but server absent mods
|
||||||
|
}
|
||||||
|
|
||||||
|
Packet250CustomPayload pkt = new Packet250CustomPayload();
|
||||||
|
pkt.field_73630_a = "FML";
|
||||||
|
pkt.field_73629_c = FMLPacket.makePacket(MOD_LIST_RESPONSE, modVersions, missingMods);
|
||||||
|
pkt.field_73628_b = pkt.field_73629_c.length;
|
||||||
|
|
||||||
|
mgr.func_74429_a(pkt);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,117 @@
|
||||||
|
package cpw.mods.fml.common.network;
|
||||||
|
|
||||||
|
import static cpw.mods.fml.common.network.FMLPacket.Type.*;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Map.Entry;
|
||||||
|
|
||||||
|
import com.google.common.collect.Lists;
|
||||||
|
import com.google.common.collect.Maps;
|
||||||
|
import com.google.common.io.ByteArrayDataInput;
|
||||||
|
import com.google.common.io.ByteArrayDataOutput;
|
||||||
|
import com.google.common.io.ByteStreams;
|
||||||
|
|
||||||
|
import cpw.mods.fml.common.Loader;
|
||||||
|
import cpw.mods.fml.common.ModContainer;
|
||||||
|
|
||||||
|
import net.minecraft.src.NetHandler;
|
||||||
|
import net.minecraft.src.NetLoginHandler;
|
||||||
|
import net.minecraft.src.NetworkManager;
|
||||||
|
import net.minecraft.src.Packet250CustomPayload;
|
||||||
|
|
||||||
|
public class ModListResponsePacket extends FMLPacket
|
||||||
|
{
|
||||||
|
private Map<String,String> modVersions;
|
||||||
|
private List<String> missingMods;
|
||||||
|
|
||||||
|
public ModListResponsePacket()
|
||||||
|
{
|
||||||
|
super(MOD_LIST_RESPONSE);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public byte[] generatePacket(Object... data)
|
||||||
|
{
|
||||||
|
Map<String,String> modVersions = (Map<String, String>) data[0];
|
||||||
|
List<String> missingMods = (List<String>) data[1];
|
||||||
|
ByteArrayDataOutput dat = ByteStreams.newDataOutput();
|
||||||
|
dat.writeInt(modVersions.size());
|
||||||
|
for (Entry<String, String> version : modVersions.entrySet())
|
||||||
|
{
|
||||||
|
dat.writeUTF(version.getKey());
|
||||||
|
dat.writeUTF(version.getValue());
|
||||||
|
}
|
||||||
|
dat.writeInt(missingMods.size());
|
||||||
|
for (String missing : missingMods)
|
||||||
|
{
|
||||||
|
dat.writeUTF(missing);
|
||||||
|
}
|
||||||
|
return dat.toByteArray();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public FMLPacket consumePacket(byte[] data)
|
||||||
|
{
|
||||||
|
ByteArrayDataInput dat = ByteStreams.newDataInput(data);
|
||||||
|
int versionListSize = dat.readInt();
|
||||||
|
modVersions = Maps.newHashMapWithExpectedSize(versionListSize);
|
||||||
|
for (int i = 0; i < versionListSize; i++)
|
||||||
|
{
|
||||||
|
String modName = dat.readUTF();
|
||||||
|
String modVersion = dat.readUTF();
|
||||||
|
modVersions.put(modName, modVersion);
|
||||||
|
}
|
||||||
|
|
||||||
|
int missingModSize = dat.readInt();
|
||||||
|
missingMods = Lists.newArrayListWithExpectedSize(missingModSize);
|
||||||
|
|
||||||
|
for (int i = 0; i < missingModSize; i++)
|
||||||
|
{
|
||||||
|
missingMods.add(dat.readUTF());
|
||||||
|
}
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void execute(NetworkManager network, FMLNetworkHandler handler, NetHandler netHandler)
|
||||||
|
{
|
||||||
|
Map<String, ModContainer> indexedModList = Maps.newHashMap(Loader.instance().getIndexedModList());
|
||||||
|
List<String> missingClientMods = Lists.newArrayList();
|
||||||
|
List<String> versionIncorrectMods = Lists.newArrayList();
|
||||||
|
|
||||||
|
for (String m : missingMods)
|
||||||
|
{
|
||||||
|
ModContainer mc = indexedModList.get(m);
|
||||||
|
NetworkModHandler networkMod = handler.findNetworkModHandler(mc);
|
||||||
|
if (networkMod.requiresClientSide())
|
||||||
|
{
|
||||||
|
missingClientMods.add(m);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (Entry<String,String> modVersion : modVersions.entrySet())
|
||||||
|
{
|
||||||
|
ModContainer mc = indexedModList.get(modVersion.getKey());
|
||||||
|
NetworkModHandler networkMod = handler.findNetworkModHandler(mc);
|
||||||
|
if (!networkMod.acceptVersion(modVersion.getValue()))
|
||||||
|
{
|
||||||
|
versionIncorrectMods.add(modVersion.getKey());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (missingClientMods.size()>0 || versionIncorrectMods.size() > 0)
|
||||||
|
{
|
||||||
|
Packet250CustomPayload pkt = new Packet250CustomPayload();
|
||||||
|
pkt.field_73630_a = "FML";
|
||||||
|
pkt.field_73629_c = FMLPacket.makePacket(MOD_MISSING, missingClientMods, versionIncorrectMods);
|
||||||
|
pkt.field_73628_b = pkt.field_73629_c.length;
|
||||||
|
network.func_74429_a(pkt);
|
||||||
|
NetLoginHandler.func_72531_a((NetLoginHandler) netHandler, false);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
handler.generateModIdentifierData();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,34 @@
|
||||||
|
package cpw.mods.fml.common.network;
|
||||||
|
|
||||||
|
import net.minecraft.src.NetworkManager;
|
||||||
|
|
||||||
|
public class ModMissingPacket extends FMLPacket
|
||||||
|
{
|
||||||
|
|
||||||
|
public ModMissingPacket()
|
||||||
|
{
|
||||||
|
super(Type.MOD_MISSING);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public byte[] generatePacket(Object... data)
|
||||||
|
{
|
||||||
|
// TODO Auto-generated method stub
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public FMLPacket consumePacket(byte[] data)
|
||||||
|
{
|
||||||
|
// TODO Auto-generated method stub
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void execute(NetworkManager network, FMLNetworkHandler handler)
|
||||||
|
{
|
||||||
|
// TODO Auto-generated method stub
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,47 @@
|
||||||
|
package cpw.mods.fml.common.network;
|
||||||
|
|
||||||
|
import java.lang.annotation.ElementType;
|
||||||
|
import java.lang.annotation.Retention;
|
||||||
|
import java.lang.annotation.RetentionPolicy;
|
||||||
|
import java.lang.annotation.Target;
|
||||||
|
import java.util.EnumSet;
|
||||||
|
|
||||||
|
import cpw.mods.fml.common.Side;
|
||||||
|
|
||||||
|
@Retention(RetentionPolicy.RUNTIME)
|
||||||
|
@Target(ElementType.TYPE)
|
||||||
|
public @interface NetworkMod
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Does this mod require the client side to be present when installed on a server?
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
boolean clientSideRequired() default false;
|
||||||
|
/**
|
||||||
|
* Does this mod require the server side to be present when installed on a client?
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
boolean serverSideRequired() default false;
|
||||||
|
/**
|
||||||
|
* A list of Packet250 network channels to register for this mod
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
String[] channels() default {};
|
||||||
|
/**
|
||||||
|
* An optional range check for client to server communication version compatibility
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
String versionBounds() default "";
|
||||||
|
/**
|
||||||
|
* A marker for a method that will be offered the client's version string
|
||||||
|
* if more sophisticated version rejection handling is required:
|
||||||
|
* The method should accept a "String", a "NetworkManager" and return a boolean true
|
||||||
|
* if the version can be accepted.
|
||||||
|
* @author cpw
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
@Retention(RetentionPolicy.RUNTIME)
|
||||||
|
@Target(ElementType.METHOD)
|
||||||
|
public @interface VersionCheckHandler { }
|
||||||
|
}
|
|
@ -0,0 +1,146 @@
|
||||||
|
package cpw.mods.fml.common.network;
|
||||||
|
|
||||||
|
import java.lang.reflect.InvocationTargetException;
|
||||||
|
import java.lang.reflect.Method;
|
||||||
|
import java.util.Collection;
|
||||||
|
import java.util.Set;
|
||||||
|
import java.util.logging.Level;
|
||||||
|
|
||||||
|
import org.objectweb.asm.Type;
|
||||||
|
|
||||||
|
import com.google.common.base.Strings;
|
||||||
|
|
||||||
|
import cpw.mods.fml.common.FMLLog;
|
||||||
|
import cpw.mods.fml.common.ModContainer;
|
||||||
|
import cpw.mods.fml.common.discovery.ASMDataTable;
|
||||||
|
import cpw.mods.fml.common.discovery.ASMDataTable.ASMData;
|
||||||
|
import cpw.mods.fml.common.versioning.DefaultArtifactVersion;
|
||||||
|
import cpw.mods.fml.common.versioning.InvalidVersionSpecificationException;
|
||||||
|
import cpw.mods.fml.common.versioning.VersionRange;
|
||||||
|
|
||||||
|
public class NetworkModHandler
|
||||||
|
{
|
||||||
|
private static int assignedIds = 1;
|
||||||
|
|
||||||
|
private int localId;
|
||||||
|
private int networkId;
|
||||||
|
|
||||||
|
private ModContainer container;
|
||||||
|
private NetworkMod mod;
|
||||||
|
private Method checkHandler;
|
||||||
|
|
||||||
|
private VersionRange acceptableRange;
|
||||||
|
|
||||||
|
public NetworkModHandler(ModContainer container, Class<?> networkModClass, ASMDataTable table)
|
||||||
|
{
|
||||||
|
this.container = container;
|
||||||
|
this.mod = networkModClass.getAnnotation(NetworkMod.class);
|
||||||
|
if (this.mod == null)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.localId = assignedIds++;
|
||||||
|
this.networkId = this.localId;
|
||||||
|
|
||||||
|
Set<ASMData> versionCheckHandlers = table.getAnnotationsFor(container).get(Type.getDescriptor(NetworkMod.VersionCheckHandler.class));
|
||||||
|
String versionCheckHandlerMethod = null;
|
||||||
|
for (ASMData vch : versionCheckHandlers)
|
||||||
|
{
|
||||||
|
if (vch.getClassName().equals(networkModClass.getName()))
|
||||||
|
{
|
||||||
|
versionCheckHandlerMethod = vch.getObjectName();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (versionCheckHandlerMethod != null)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
Method checkHandlerMethod = networkModClass.getDeclaredMethod(versionCheckHandlerMethod, String.class);
|
||||||
|
if (checkHandlerMethod.isAnnotationPresent(NetworkMod.VersionCheckHandler.class))
|
||||||
|
{
|
||||||
|
this.checkHandler = checkHandlerMethod;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
FMLLog.log(Level.WARNING, e, "The declared version check handler method %s on network mod id %s is not accessible", versionCheckHandlerMethod, container.getModId());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this.checkHandler == null)
|
||||||
|
{
|
||||||
|
String versionBounds = mod.versionBounds();
|
||||||
|
if (!Strings.isNullOrEmpty(versionBounds))
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
this.acceptableRange = VersionRange.createFromVersionSpec(versionBounds);
|
||||||
|
}
|
||||||
|
catch (InvalidVersionSpecificationException e)
|
||||||
|
{
|
||||||
|
FMLLog.log(Level.WARNING, e, "Invalid bounded range %s specified for network mod id %s", versionBounds, container.getModId());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean requiresClientSide()
|
||||||
|
{
|
||||||
|
return mod.clientSideRequired();
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean requiresServerSide()
|
||||||
|
{
|
||||||
|
return mod.serverSideRequired();
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean acceptVersion(String version)
|
||||||
|
{
|
||||||
|
if (checkHandler != null)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
return (Boolean)checkHandler.invoke(container.getMod(), version);
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
FMLLog.log(Level.WARNING, e, "There was a problem invoking the checkhandler method %s for network mod id %s", checkHandler.getName(), container.getModId());
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (acceptableRange!=null)
|
||||||
|
{
|
||||||
|
return acceptableRange.containsVersion(new DefaultArtifactVersion(version));
|
||||||
|
}
|
||||||
|
|
||||||
|
return container.getVersion().equals(version);
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getLocalId()
|
||||||
|
{
|
||||||
|
return localId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getNetworkId()
|
||||||
|
{
|
||||||
|
return networkId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ModContainer getContainer()
|
||||||
|
{
|
||||||
|
return container;
|
||||||
|
}
|
||||||
|
|
||||||
|
public NetworkMod getMod()
|
||||||
|
{
|
||||||
|
return mod;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isNetworkMod()
|
||||||
|
{
|
||||||
|
return mod != null;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,95 @@
|
||||||
|
package cpw.mods.fml.common.network;
|
||||||
|
|
||||||
|
import java.io.UnsupportedEncodingException;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.HashSet;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Set;
|
||||||
|
import java.util.logging.Level;
|
||||||
|
|
||||||
|
import net.minecraft.src.EntityPlayer;
|
||||||
|
|
||||||
|
import com.google.common.base.Charsets;
|
||||||
|
import com.google.common.base.Joiner;
|
||||||
|
import com.google.common.collect.ArrayListMultimap;
|
||||||
|
import com.google.common.collect.LinkedHashMultimap;
|
||||||
|
import com.google.common.collect.Maps;
|
||||||
|
import com.google.common.collect.Multimap;
|
||||||
|
import com.google.common.collect.Multimaps;
|
||||||
|
import com.google.common.collect.SetMultimap;
|
||||||
|
|
||||||
|
import cpw.mods.fml.common.FMLLog;
|
||||||
|
import cpw.mods.fml.common.ModContainer;
|
||||||
|
|
||||||
|
public class NetworkRegistry
|
||||||
|
{
|
||||||
|
|
||||||
|
private static final NetworkRegistry INSTANCE = new NetworkRegistry();
|
||||||
|
/**
|
||||||
|
* A map of active channels per player
|
||||||
|
*/
|
||||||
|
private Multimap<Player, String> activeChannels = ArrayListMultimap.create();
|
||||||
|
/**
|
||||||
|
* A map of mods to their network channels - the list is a set
|
||||||
|
*/
|
||||||
|
private SetMultimap<ModContainer, String> channelList = LinkedHashMultimap.create();
|
||||||
|
|
||||||
|
public static NetworkRegistry instance()
|
||||||
|
{
|
||||||
|
return INSTANCE;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Get the channel list for a mod
|
||||||
|
* @param modLoaderModContainer
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public Set<String> getChannelListFor(ModContainer container)
|
||||||
|
{
|
||||||
|
return channelList.get(container);
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Get the packet 250 channel registration string
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public byte[] getPacketRegistry()
|
||||||
|
{
|
||||||
|
return Joiner.on('\0').join(channelList.values()).getBytes(Charsets.UTF_8);
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Is the specified channel active for the player?
|
||||||
|
* @param channel
|
||||||
|
* @param player
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public boolean isChannelActive(String channel, Player player)
|
||||||
|
{
|
||||||
|
return activeChannels.containsEntry(player,channel);
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* register a channel to a mod
|
||||||
|
* @param container
|
||||||
|
* @param channelName
|
||||||
|
*/
|
||||||
|
public void registerChannel(ModContainer container, String channelName)
|
||||||
|
{
|
||||||
|
channelList.put(container, channelName);
|
||||||
|
// invertedChannelList = Multimaps.invertFrom(channelList, ArrayListMultimap.<String, ModContainer>create());
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Activate the channel for the player
|
||||||
|
* @param player
|
||||||
|
*/
|
||||||
|
public void activateChannel(Player player, String channel)
|
||||||
|
{
|
||||||
|
activeChannels.put(player, channel);
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Deactivate the channel for the player
|
||||||
|
* @param player
|
||||||
|
* @param channel
|
||||||
|
*/
|
||||||
|
public void deactivateChannel(Player player, String channel)
|
||||||
|
{
|
||||||
|
activeChannels.remove(player, channel);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,11 @@
|
||||||
|
package cpw.mods.fml.common.network;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @author cpw
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public interface Player
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
|
@ -175,4 +175,6 @@ public ir.a
|
||||||
#public+f ri.c
|
#public+f ri.c
|
||||||
# StatBase - Make statName public, no server side getter
|
# StatBase - Make statName public, no server side getter
|
||||||
public ho.a
|
public ho.a
|
||||||
|
# NetLoginHandler make the "complete connection" callback public so I can reset it during FML negotiation
|
||||||
|
public gw.a(Lgw;Z)Z
|
||||||
|
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
<?xml version="1.0" encoding="UTF-8"?>
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
<classpath>
|
<classpath>
|
||||||
<classpathentry kind="src" path="src"/>
|
|
||||||
<classpathentry kind="src" path="src-common"/>
|
<classpathentry kind="src" path="src-common"/>
|
||||||
|
<classpathentry kind="src" path="src"/>
|
||||||
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.6"/>
|
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.6"/>
|
||||||
<classpathentry kind="lib" path="jars/bin/jinput.jar">
|
<classpathentry kind="lib" path="jars/bin/jinput.jar">
|
||||||
<attributes>
|
<attributes>
|
||||||
|
|
|
@ -8,4 +8,9 @@ System.out.println(new cpw.mods.fml.common.asm.ASMModParser(fis));
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
org.objectweb.asm.Type.getDescriptor(net.minecraft.src.CraftingManager.class.getDeclaredMethods()[1])
|
org.objectweb.asm.Type.getDescriptor(net.minecraft.src.CraftingManager.class.getDeclaredMethods()[1])
|
||||||
|
|
||||||
|
|
||||||
|
com.google.common.collect.Tables.newCustomTable(new HashMap<String,Map<String,List<String>>(), new com.google.common.base.Supplier() {
|
||||||
|
|
||||||
|
});
|
|
@ -0,0 +1,9 @@
|
||||||
|
--- ../src-base/common/net/minecraft/src/NetHandler.java
|
||||||
|
+++ ../src-work/common/net/minecraft/src/NetHandler.java
|
||||||
|
@@ -345,4 +345,6 @@
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
+
|
||||||
|
+ public abstract void handleVanilla250Packet(Packet250CustomPayload payload);
|
||||||
|
}
|
|
@ -0,0 +1,41 @@
|
||||||
|
--- ../src-base/common/net/minecraft/src/NetLoginHandler.java
|
||||||
|
+++ ../src-work/common/net/minecraft/src/NetLoginHandler.java
|
||||||
|
@@ -9,6 +9,8 @@
|
||||||
|
import java.util.Random;
|
||||||
|
import java.util.logging.Logger;
|
||||||
|
import javax.crypto.SecretKey;
|
||||||
|
+
|
||||||
|
+import cpw.mods.fml.common.network.FMLNetworkHandler;
|
||||||
|
import net.minecraft.server.MinecraftServer;
|
||||||
|
|
||||||
|
public class NetLoginHandler extends NetHandler
|
||||||
|
@@ -129,8 +131,11 @@
|
||||||
|
|
||||||
|
public void func_72529_d()
|
||||||
|
{
|
||||||
|
- String var1 = this.field_72534_f.func_71203_ab().func_72399_a(this.field_72538_b.func_74430_c(), this.field_72543_h);
|
||||||
|
-
|
||||||
|
+ FMLNetworkHandler.onClientConnectToServer(this, this.field_72534_f, this.field_72538_b.func_74430_c(), this.field_72543_h);
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ public void completeConnection(String var1)
|
||||||
|
+ {
|
||||||
|
if (var1 != null)
|
||||||
|
{
|
||||||
|
this.func_72527_a(var1);
|
||||||
|
@@ -221,4 +226,15 @@
|
||||||
|
{
|
||||||
|
return p_72531_0_.field_72544_i = p_72531_1_;
|
||||||
|
}
|
||||||
|
+
|
||||||
|
+ public void func_72501_a(Packet250CustomPayload p_72501_1_)
|
||||||
|
+ {
|
||||||
|
+ FMLNetworkHandler.handlePacket250Packet(p_72501_1_, field_72538_b, this);
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ @Override
|
||||||
|
+ public void handleVanilla250Packet(Packet250CustomPayload payload)
|
||||||
|
+ {
|
||||||
|
+ // NOOP for login
|
||||||
|
+ }
|
||||||
|
}
|
|
@ -0,0 +1,23 @@
|
||||||
|
--- ../src-base/common/net/minecraft/src/NetServerHandler.java
|
||||||
|
+++ ../src-work/common/net/minecraft/src/NetServerHandler.java
|
||||||
|
@@ -7,6 +7,8 @@
|
||||||
|
import java.util.Iterator;
|
||||||
|
import java.util.Random;
|
||||||
|
import java.util.logging.Logger;
|
||||||
|
+
|
||||||
|
+import cpw.mods.fml.common.network.FMLNetworkHandler;
|
||||||
|
import net.minecraft.server.MinecraftServer;
|
||||||
|
|
||||||
|
public class NetServerHandler extends NetHandler
|
||||||
|
@@ -956,6 +958,11 @@
|
||||||
|
|
||||||
|
public void func_72501_a(Packet250CustomPayload p_72501_1_)
|
||||||
|
{
|
||||||
|
+ FMLNetworkHandler.handlePacket250Packet(p_72501_1_, field_72575_b, this);
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ public void handleVanilla250Packet(Packet250CustomPayload p_72501_1_)
|
||||||
|
+ {
|
||||||
|
DataInputStream var2;
|
||||||
|
ItemStack var3;
|
||||||
|
ItemStack var4;
|
|
@ -0,0 +1,32 @@
|
||||||
|
--- ../src-base/minecraft/net/minecraft/src/NetClientHandler.java
|
||||||
|
+++ ../src-work/minecraft/net/minecraft/src/NetClientHandler.java
|
||||||
|
@@ -20,6 +20,9 @@
|
||||||
|
import net.minecraft.client.Minecraft;
|
||||||
|
import org.lwjgl.input.Keyboard;
|
||||||
|
|
||||||
|
+import cpw.mods.fml.common.LoaderException;
|
||||||
|
+import cpw.mods.fml.common.network.FMLNetworkHandler;
|
||||||
|
+
|
||||||
|
public class NetClientHandler extends NetHandler
|
||||||
|
{
|
||||||
|
private boolean field_72554_f = false;
|
||||||
|
@@ -116,6 +119,7 @@
|
||||||
|
|
||||||
|
public void func_72513_a(Packet252SharedKey p_72513_1_)
|
||||||
|
{
|
||||||
|
+ this.func_72552_c(FMLNetworkHandler.getFMLFakeLoginPacket());
|
||||||
|
this.func_72552_c(new Packet205ClientCommand(0));
|
||||||
|
}
|
||||||
|
|
||||||
|
@@ -1164,6 +1168,11 @@
|
||||||
|
|
||||||
|
public void func_72501_a(Packet250CustomPayload p_72501_1_)
|
||||||
|
{
|
||||||
|
+
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ public void handleVanilla250Packet(Packet250CustomPayload p_72501_1_)
|
||||||
|
+ {
|
||||||
|
if ("MC|TPack".equals(p_72501_1_.field_73630_a))
|
||||||
|
{
|
||||||
|
String[] var2 = (new String(p_72501_1_.field_73629_c)).split("\u0000");
|
Loading…
Reference in New Issue