001/* 002 * Forge Mod Loader 003 * Copyright (c) 2012-2013 cpw. 004 * All rights reserved. This program and the accompanying materials 005 * are made available under the terms of the GNU Lesser Public License v2.1 006 * which accompanies this distribution, and is available at 007 * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html 008 * 009 * Contributors: 010 * cpw - implementation 011 */ 012 013package cpw.mods.fml.common.network; 014 015import static cpw.mods.fml.common.network.FMLPacket.Type.MOD_IDENTIFIERS; 016import static cpw.mods.fml.common.network.FMLPacket.Type.MOD_LIST_RESPONSE; 017import static cpw.mods.fml.common.network.FMLPacket.Type.MOD_MISSING; 018import static cpw.mods.fml.common.network.FMLPacket.Type.MOD_IDMAP; 019 020import java.util.List; 021import java.util.Map; 022import java.util.Map.Entry; 023import java.util.logging.Logger; 024 025import net.minecraft.nbt.NBTTagList; 026import net.minecraft.network.*; 027import net.minecraft.network.packet.*; 028 029import com.google.common.collect.Lists; 030import com.google.common.collect.Maps; 031import com.google.common.io.ByteArrayDataInput; 032import com.google.common.io.ByteArrayDataOutput; 033import com.google.common.io.ByteStreams; 034 035import cpw.mods.fml.common.FMLLog; 036import cpw.mods.fml.common.Loader; 037import cpw.mods.fml.common.ModContainer; 038import cpw.mods.fml.common.registry.GameData; 039import cpw.mods.fml.common.registry.GameRegistry; 040 041public class ModListResponsePacket extends FMLPacket 042{ 043 private Map<String,String> modVersions; 044 private List<String> missingMods; 045 046 public ModListResponsePacket() 047 { 048 super(MOD_LIST_RESPONSE); 049 } 050 051 @Override 052 public byte[] generatePacket(Object... data) 053 { 054 Map<String,String> modVersions = (Map<String, String>) data[0]; 055 List<String> missingMods = (List<String>) data[1]; 056 ByteArrayDataOutput dat = ByteStreams.newDataOutput(); 057 dat.writeInt(modVersions.size()); 058 for (Entry<String, String> version : modVersions.entrySet()) 059 { 060 dat.writeUTF(version.getKey()); 061 dat.writeUTF(version.getValue()); 062 } 063 dat.writeInt(missingMods.size()); 064 for (String missing : missingMods) 065 { 066 dat.writeUTF(missing); 067 } 068 return dat.toByteArray(); 069 } 070 071 @Override 072 public FMLPacket consumePacket(byte[] data) 073 { 074 ByteArrayDataInput dat = ByteStreams.newDataInput(data); 075 int versionListSize = dat.readInt(); 076 modVersions = Maps.newHashMapWithExpectedSize(versionListSize); 077 for (int i = 0; i < versionListSize; i++) 078 { 079 String modName = dat.readUTF(); 080 String modVersion = dat.readUTF(); 081 modVersions.put(modName, modVersion); 082 } 083 084 int missingModSize = dat.readInt(); 085 missingMods = Lists.newArrayListWithExpectedSize(missingModSize); 086 087 for (int i = 0; i < missingModSize; i++) 088 { 089 missingMods.add(dat.readUTF()); 090 } 091 return this; 092 } 093 094 @Override 095 public void execute(INetworkManager network, FMLNetworkHandler handler, NetHandler netHandler, String userName) 096 { 097 Map<String, ModContainer> indexedModList = Maps.newHashMap(Loader.instance().getIndexedModList()); 098 List<String> missingClientMods = Lists.newArrayList(); 099 List<String> versionIncorrectMods = Lists.newArrayList(); 100 101 for (String m : missingMods) 102 { 103 ModContainer mc = indexedModList.get(m); 104 NetworkModHandler networkMod = handler.findNetworkModHandler(mc); 105 if (networkMod.requiresClientSide()) 106 { 107 missingClientMods.add(m); 108 } 109 } 110 111 for (Entry<String,String> modVersion : modVersions.entrySet()) 112 { 113 ModContainer mc = indexedModList.get(modVersion.getKey()); 114 NetworkModHandler networkMod = handler.findNetworkModHandler(mc); 115 if (!networkMod.acceptVersion(modVersion.getValue())) 116 { 117 versionIncorrectMods.add(modVersion.getKey()); 118 } 119 } 120 121 Packet250CustomPayload pkt = new Packet250CustomPayload(); 122 pkt.channel = "FML"; 123 if (missingClientMods.size()>0 || versionIncorrectMods.size() > 0) 124 { 125 pkt.data = FMLPacket.makePacket(MOD_MISSING, missingClientMods, versionIncorrectMods); 126 Logger.getLogger("Minecraft").info(String.format("User %s connection failed: missing %s, bad versions %s", userName, missingClientMods, versionIncorrectMods)); 127 FMLLog.info("User %s connection failed: missing %s, bad versions %s", userName, missingClientMods, versionIncorrectMods); 128 // Mark this as bad 129 FMLNetworkHandler.setHandlerState((NetLoginHandler) netHandler, FMLNetworkHandler.MISSING_MODS_OR_VERSIONS); 130 pkt.length = pkt.data.length; 131 network.addToSendQueue(pkt); 132 } 133 else 134 { 135 pkt.data = FMLPacket.makePacket(MOD_IDENTIFIERS, netHandler); 136 Logger.getLogger("Minecraft").info(String.format("User %s connecting with mods %s", userName, modVersions.keySet())); 137 FMLLog.info("User %s connecting with mods %s", userName, modVersions.keySet()); 138 pkt.length = pkt.data.length; 139 network.addToSendQueue(pkt); 140 NBTTagList itemList = new NBTTagList(); 141 GameData.writeItemData(itemList); 142 byte[][] registryPackets = FMLPacket.makePacketSet(MOD_IDMAP, itemList); 143 for (int i = 0; i < registryPackets.length; i++) 144 { 145 network.addToSendQueue(PacketDispatcher.getPacket("FML", registryPackets[i])); 146 } 147 } 148 149 // reset the continuation flag - we have completed extra negotiation and the login should complete now 150 NetLoginHandler.func_72531_a((NetLoginHandler) netHandler, true); 151 } 152 153}