001    package cpw.mods.fml.common.network;
002    
003    import static cpw.mods.fml.common.network.FMLPacket.Type.MOD_LIST_REQUEST;
004    import static cpw.mods.fml.common.network.FMLPacket.Type.MOD_LIST_RESPONSE;
005    
006    import java.util.List;
007    import java.util.Map;
008    import java.util.Map.Entry;
009    import java.util.Set;
010    
011    import net.minecraft.src.NetHandler;
012    import net.minecraft.src.NetworkManager;
013    import net.minecraft.src.Packet250CustomPayload;
014    
015    import com.google.common.collect.Lists;
016    import com.google.common.collect.Maps;
017    import com.google.common.io.ByteArrayDataInput;
018    import com.google.common.io.ByteArrayDataOutput;
019    import com.google.common.io.ByteStreams;
020    
021    import cpw.mods.fml.common.FMLLog;
022    import cpw.mods.fml.common.Loader;
023    import cpw.mods.fml.common.ModContainer;
024    
025    public class ModListRequestPacket extends FMLPacket
026    {
027        private List<String> sentModList;
028    
029        public ModListRequestPacket()
030        {
031            super(MOD_LIST_REQUEST);
032        }
033    
034        @Override
035        public byte[] generatePacket(Object... data)
036        {
037            ByteArrayDataOutput dat = ByteStreams.newDataOutput();
038            Set<ModContainer> activeMods = FMLNetworkHandler.instance().getNetworkModList();
039            dat.writeInt(activeMods.size());
040            for (ModContainer mc : activeMods)
041            {
042                dat.writeUTF(mc.getModId());
043            }
044            return dat.toByteArray();
045        }
046    
047        @Override
048        public FMLPacket consumePacket(byte[] data)
049        {
050            sentModList = Lists.newArrayList();
051            ByteArrayDataInput in = ByteStreams.newDataInput(data);
052            int listSize = in.readInt();
053            for (int i = 0; i < listSize; i++)
054            {
055                sentModList.add(in.readUTF());
056            }
057            return this;
058        }
059    
060        /**
061         *
062         * This packet is executed on the client to evaluate the server's mod list against
063         * the client
064         *
065         * @see cpw.mods.fml.common.network.FMLPacket#execute()
066         */
067        @Override
068        public void execute(NetworkManager mgr, FMLNetworkHandler handler, NetHandler netHandler, String userName)
069        {
070            List<String> missingMods = Lists.newArrayList();
071            Map<String,String> modVersions = Maps.newHashMap();
072            Map<String, ModContainer> indexedModList = Maps.newHashMap(Loader.instance().getIndexedModList());
073    
074            for (String m : sentModList)
075            {
076                ModContainer mc = indexedModList.get(m);
077                if (mc == null)
078                {
079                    missingMods.add(m);
080                    continue;
081                }
082                indexedModList.remove(m);
083                modVersions.put(m, mc.getVersion());
084            }
085    
086            if (indexedModList.size()>0)
087            {
088                for (Entry<String, ModContainer> e : indexedModList.entrySet())
089                {
090                    if (e.getValue().isNetworkMod())
091                    {
092                        NetworkModHandler missingHandler = FMLNetworkHandler.instance().findNetworkModHandler(e.getValue());
093                        if (missingHandler.requiresServerSide())
094                        {
095                            // TODO : what should we do if a mod is marked "serverSideRequired"? Stop the connection?
096                            FMLLog.warning("The mod %s was not found on the server you connected to, but requested that the server side be present", e.getKey());
097                        }
098                    }
099                }
100            }
101    
102            Packet250CustomPayload pkt = new Packet250CustomPayload();
103            pkt.channel = "FML";
104            pkt.data = FMLPacket.makePacket(MOD_LIST_RESPONSE, modVersions, missingMods);
105            pkt.length = pkt.data.length;
106    
107            mgr.addToSendQueue(pkt);
108        }
109    }