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