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 }