    001package cpw.mods.fml.common.network;
    002
    003import static cpw.mods.fml.common.network.FMLPacket.Type.MOD_IDENTIFIERS;
    004import static cpw.mods.fml.common.network.FMLPacket.Type.MOD_LIST_RESPONSE;
    005import static cpw.mods.fml.common.network.FMLPacket.Type.MOD_MISSING;
    006import static cpw.mods.fml.common.network.FMLPacket.Type.MOD_IDMAP;
    007
    008import java.util.List;
    009import java.util.Map;
    010import java.util.Map.Entry;
    011import java.util.logging.Logger;
    012
    013import net.minecraft.nbt.NBTTagList;
    014import net.minecraft.network.*;
    015import net.minecraft.network.packet.*;
    016
    017import com.google.common.collect.Lists;
    018import com.google.common.collect.Maps;
    019import com.google.common.io.ByteArrayDataInput;
    020import com.google.common.io.ByteArrayDataOutput;
    021import com.google.common.io.ByteStreams;
    022
    023import cpw.mods.fml.common.FMLLog;
    024import cpw.mods.fml.common.Loader;
    025import cpw.mods.fml.common.ModContainer;
    026import cpw.mods.fml.common.registry.GameData;
    027import cpw.mods.fml.common.registry.GameRegistry;
    028
    029public class ModListResponsePacket extends FMLPacket
    030{
    031    private Map<String,String> modVersions;
    032    private List<String> missingMods;
    033
    034    public ModListResponsePacket()
    035    {
    036        super(MOD_LIST_RESPONSE);
    037    }
    038
    039    @Override
    040    public byte[] generatePacket(Object... data)
    041    {
    042        Map<String,String> modVersions = (Map<String, String>) data[0];
    043        List<String> missingMods = (List<String>) data[1];
    044        ByteArrayDataOutput dat = ByteStreams.newDataOutput();
    045        dat.writeInt(modVersions.size());
    046        for (Entry<String, String> version : modVersions.entrySet())
    047        {
    048            dat.writeUTF(version.getKey());
    049            dat.writeUTF(version.getValue());
    050        }
    051        dat.writeInt(missingMods.size());
    052        for (String missing : missingMods)
    053        {
    054            dat.writeUTF(missing);
    055        }
    056        return dat.toByteArray();
    057    }
    058
    059    @Override
    060    public FMLPacket consumePacket(byte[] data)
    061    {
    062        ByteArrayDataInput dat = ByteStreams.newDataInput(data);
    063        int versionListSize = dat.readInt();
    064        modVersions = Maps.newHashMapWithExpectedSize(versionListSize);
    065        for (int i = 0; i < versionListSize; i++)
    066        {
    067            String modName = dat.readUTF();
    068            String modVersion = dat.readUTF();
    069            modVersions.put(modName, modVersion);
    070        }
    071
    072        int missingModSize = dat.readInt();
    073        missingMods = Lists.newArrayListWithExpectedSize(missingModSize);
    074
    075        for (int i = 0; i < missingModSize; i++)
    076        {
    077            missingMods.add(dat.readUTF());
    078        }
    079        return this;
    080    }
    081
    082    @Override
    083    public void execute(INetworkManager network, FMLNetworkHandler handler, NetHandler netHandler, String userName)
    084    {
    085        Map<String, ModContainer> indexedModList = Maps.newHashMap(Loader.instance().getIndexedModList());
    086        List<String> missingClientMods = Lists.newArrayList();
    087        List<String> versionIncorrectMods = Lists.newArrayList();
    088
    089        for (String m : missingMods)
    090        {
    091            ModContainer mc = indexedModList.get(m);
    092            NetworkModHandler networkMod = handler.findNetworkModHandler(mc);
    093            if (networkMod.requiresClientSide())
    094            {
    095                missingClientMods.add(m);
    096            }
    097        }
    098
    099        for (Entry<String,String> modVersion : modVersions.entrySet())
    100        {
    101            ModContainer mc = indexedModList.get(modVersion.getKey());
    102            NetworkModHandler networkMod = handler.findNetworkModHandler(mc);
    103            if (!networkMod.acceptVersion(modVersion.getValue()))
    104            {
    105                versionIncorrectMods.add(modVersion.getKey());
    106            }
    107        }
    108
    109        Packet250CustomPayload pkt = new Packet250CustomPayload();
    110        pkt.channel = "FML";
    111        if (missingClientMods.size()>0 || versionIncorrectMods.size() > 0)
    112        {
    113            pkt.data = FMLPacket.makePacket(MOD_MISSING, missingClientMods, versionIncorrectMods);
    114            Logger.getLogger("Minecraft").info(String.format("User %s connection failed: missing %s, bad versions %s", userName, missingClientMods, versionIncorrectMods));
    115            FMLLog.info("User %s connection failed: missing %s, bad versions %s", userName, missingClientMods, versionIncorrectMods);
    116            // Mark this as bad
    117            FMLNetworkHandler.setHandlerState((NetLoginHandler) netHandler, FMLNetworkHandler.MISSING_MODS_OR_VERSIONS);
    118            pkt.length = pkt.data.length;
    119            network.addToSendQueue(pkt);
    120        }
    121        else
    122        {
    123            pkt.data = FMLPacket.makePacket(MOD_IDENTIFIERS, netHandler);
    124            Logger.getLogger("Minecraft").info(String.format("User %s connecting with mods %s", userName, modVersions.keySet()));
    125            FMLLog.info("User %s connecting with mods %s", userName, modVersions.keySet());
    126            pkt.length = pkt.data.length;
    127            network.addToSendQueue(pkt);
    128            NBTTagList itemList = new NBTTagList();
    129            GameData.writeItemData(itemList);
    130            byte[][] registryPackets = FMLPacket.makePacketSet(MOD_IDMAP, itemList);
    131            for (int i = 0; i < registryPackets.length; i++)
    132            {
    133                network.addToSendQueue(PacketDispatcher.getPacket("FML", registryPackets[i]));
    134            }
    135        }
    136
    137        // reset the continuation flag - we have completed extra negotiation and the login should complete now
    138        NetLoginHandler.func_72531_a((NetLoginHandler) netHandler, true);
    139    }
    140
    141}