    001    package cpw.mods.fml.common.network;
    002
    003    import static cpw.mods.fml.common.network.FMLPacket.Type.MOD_IDENTIFIERS;
    004    import static cpw.mods.fml.common.network.FMLPacket.Type.MOD_LIST_RESPONSE;
    005    import static cpw.mods.fml.common.network.FMLPacket.Type.MOD_MISSING;
    006    import static cpw.mods.fml.common.network.FMLPacket.Type.MOD_IDMAP;
    007
    008    import java.util.List;
    009    import java.util.Map;
    010    import java.util.Map.Entry;
    011    import java.util.logging.Logger;
    012
    013    import net.minecraft.nbt.NBTTagList;
    014    import net.minecraft.network.*;
    015    import net.minecraft.network.packet.*;
    016
    017    import com.google.common.collect.Lists;
    018    import com.google.common.collect.Maps;
    019    import com.google.common.io.ByteArrayDataInput;
    020    import com.google.common.io.ByteArrayDataOutput;
    021    import com.google.common.io.ByteStreams;
    022
    023    import cpw.mods.fml.common.FMLLog;
    024    import cpw.mods.fml.common.Loader;
    025    import cpw.mods.fml.common.ModContainer;
    026    import cpw.mods.fml.common.registry.GameData;
    027    import cpw.mods.fml.common.registry.GameRegistry;
    028
    029    public 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    }