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    }