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 }