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