package cpw.mods.fml.common.network;
import static cpw.mods.fml.common.network.FMLPacket.Type.MOD_LIST_REQUEST;
import static cpw.mods.fml.common.network.FMLPacket.Type.MOD_LIST_RESPONSE;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
import net.minecraft.network.INetworkManager;
import net.minecraft.network.packet.NetHandler;
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.FMLCommonHandler;
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;
private byte compatibilityLevel;
public ModListRequestPacket()
{
super(MOD_LIST_REQUEST);
}
@Override
public byte[] generatePacket(Object... data)
{
ByteArrayDataOutput dat = ByteStreams.newDataOutput();
Set<ModContainer> activeMods = FMLNetworkHandler.instance().getNetworkModList();
dat.writeInt(activeMods.size());
for (ModContainer mc : activeMods)
{
dat.writeUTF(mc.getModId());
}
dat.writeByte(FMLNetworkHandler.getCompatibilityLevel());
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());
}
try
{
compatibilityLevel = in.readByte();
}
catch (IllegalStateException e)
{
FMLLog.fine("No compatibility byte found - the server is too old");
}
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(INetworkManager, FMLNetworkHandler, NetHandler, String)
*/
@Override
public void execute(INetworkManager mgr, FMLNetworkHandler handler, NetHandler netHandler, String userName)
{
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)
{
for (Entry<String, ModContainer> e : indexedModList.entrySet())
{
if (e.getValue().isNetworkMod())
{
NetworkModHandler missingHandler = FMLNetworkHandler.instance().findNetworkModHandler(e.getValue());
if (missingHandler.requiresServerSide())
{
// TODO : what should we do if a mod is marked "serverSideRequired"? Stop the connection?
FMLLog.warning("The mod %s was not found on the server you connected to, but requested that the server side be present", e.getKey());
}
}
}
}
FMLLog.fine("The server has compatibility level %d", compatibilityLevel);
FMLCommonHandler.instance().getSidedDelegate().setClientCompatibilityLevel(compatibilityLevel);
mgr.addToSendQueue(PacketDispatcher.getPacket("FML", FMLPacket.makePacket(MOD_LIST_RESPONSE, modVersions, missingMods)));
}
}