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.INetworkManager;
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(INetworkManager 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, FMLNetworkHandler.MISSING_MODS_OR_VERSIONS);
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 }