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