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 }