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