    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.INetworkManager;
    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.FMLCommonHandler;
    022    import cpw.mods.fml.common.FMLLog;
    023    import cpw.mods.fml.common.Loader;
    024    import cpw.mods.fml.common.ModContainer;
    025
    026    public class ModListRequestPacket extends FMLPacket
    027    {
    028        private List<String> sentModList;
    029        private byte compatibilityLevel;
    030
    031        public ModListRequestPacket()
    032        {
    033            super(MOD_LIST_REQUEST);
    034        }
    035
    036        @Override
    037        public byte[] generatePacket(Object... data)
    038        {
    039            ByteArrayDataOutput dat = ByteStreams.newDataOutput();
    040            Set<ModContainer> activeMods = FMLNetworkHandler.instance().getNetworkModList();
    041            dat.writeInt(activeMods.size());
    042            for (ModContainer mc : activeMods)
    043            {
    044                dat.writeUTF(mc.getModId());
    045            }
    046            dat.writeByte(FMLNetworkHandler.getCompatibilityLevel());
    047            return dat.toByteArray();
    048        }
    049
    050        @Override
    051        public FMLPacket consumePacket(byte[] data)
    052        {
    053            sentModList = Lists.newArrayList();
    054            ByteArrayDataInput in = ByteStreams.newDataInput(data);
    055            int listSize = in.readInt();
    056            for (int i = 0; i < listSize; i++)
    057            {
    058                sentModList.add(in.readUTF());
    059            }
    060            try
    061            {
    062                compatibilityLevel = in.readByte();
    063            }
    064            catch (IllegalStateException e)
    065            {
    066                FMLLog.fine("No compatibility byte found - the server is too old");
    067            }
    068            return this;
    069        }
    070
    071        /**
    072         *
    073         * This packet is executed on the client to evaluate the server's mod list against
    074         * the client
    075         *
    076         * @see cpw.mods.fml.common.network.FMLPacket#execute(INetworkManager, FMLNetworkHandler, NetHandler, String)
    077         */
    078        @Override
    079        public void execute(INetworkManager mgr, FMLNetworkHandler handler, NetHandler netHandler, String userName)
    080        {
    081            List<String> missingMods = Lists.newArrayList();
    082            Map<String,String> modVersions = Maps.newHashMap();
    083            Map<String, ModContainer> indexedModList = Maps.newHashMap(Loader.instance().getIndexedModList());
    084
    085            for (String m : sentModList)
    086            {
    087                ModContainer mc = indexedModList.get(m);
    088                if (mc == null)
    089                {
    090                    missingMods.add(m);
    091                    continue;
    092                }
    093                indexedModList.remove(m);
    094                modVersions.put(m, mc.getVersion());
    095            }
    096
    097            if (indexedModList.size()>0)
    098            {
    099                for (Entry<String, ModContainer> e : indexedModList.entrySet())
    100                {
    101                    if (e.getValue().isNetworkMod())
    102                    {
    103                        NetworkModHandler missingHandler = FMLNetworkHandler.instance().findNetworkModHandler(e.getValue());
    104                        if (missingHandler.requiresServerSide())
    105                        {
    106                            // TODO : what should we do if a mod is marked "serverSideRequired"? Stop the connection?
    107                            FMLLog.warning("The mod %s was not found on the server you connected to, but requested that the server side be present", e.getKey());
    108                        }
    109                    }
    110                }
    111            }
    112
    113            FMLLog.fine("The server has compatibility level %d", compatibilityLevel);
    114            FMLCommonHandler.instance().getSidedDelegate().setClientCompatibilityLevel(compatibilityLevel);
    115
    116            mgr.addToSendQueue(PacketDispatcher.getPacket("FML", FMLPacket.makePacket(MOD_LIST_RESPONSE, modVersions, missingMods)));
    117        }
    118    }