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 java.io.IOException; 016import java.util.BitSet; 017import java.util.Set; 018import java.util.logging.Level; 019 020import net.minecraft.nbt.*; 021import net.minecraft.network.INetworkManager; 022import net.minecraft.network.packet.NetHandler; 023 024import com.google.common.collect.MapDifference; 025import com.google.common.io.ByteArrayDataInput; 026import com.google.common.io.ByteStreams; 027import com.google.common.primitives.Bytes; 028import com.google.common.primitives.Ints; 029import com.google.common.primitives.UnsignedBytes; 030 031import cpw.mods.fml.client.FMLClientHandler; 032import cpw.mods.fml.common.FMLCommonHandler; 033import cpw.mods.fml.common.FMLLog; 034import cpw.mods.fml.common.registry.GameData; 035import cpw.mods.fml.common.registry.GameRegistry; 036import cpw.mods.fml.common.registry.ItemData; 037import static cpw.mods.fml.common.network.FMLPacket.Type.MOD_IDMAP; 038 039public class ModIdMapPacket extends FMLPacket { 040 private byte[][] partials; 041 042 public ModIdMapPacket() 043 { 044 super(MOD_IDMAP); 045 } 046 047 @Override 048 public byte[] generatePacket(Object... data) 049 { 050 NBTTagList completeList = (NBTTagList) data[0]; 051 NBTTagCompound wrap = new NBTTagCompound(); 052 wrap.setTag("List", completeList); 053 try 054 { 055 return CompressedStreamTools.compress(wrap); 056 } 057 catch (Exception e) 058 { 059 FMLLog.log(Level.SEVERE, e, "A critical error writing the id map"); 060 throw new FMLNetworkException(e); 061 } 062 } 063 064 @Override 065 public FMLPacket consumePacket(byte[] data) 066 { 067 ByteArrayDataInput bdi = ByteStreams.newDataInput(data); 068 int chunkIdx = UnsignedBytes.toInt(bdi.readByte()); 069 int chunkTotal = UnsignedBytes.toInt(bdi.readByte()); 070 int chunkLength = bdi.readInt(); 071 if (partials == null) 072 { 073 partials = new byte[chunkTotal][]; 074 } 075 partials[chunkIdx] = new byte[chunkLength]; 076 bdi.readFully(partials[chunkIdx]); 077 for (int i = 0; i < partials.length; i++) 078 { 079 if (partials[i] == null) 080 { 081 return null; 082 } 083 } 084 return this; 085 } 086 087 @Override 088 public void execute(INetworkManager network, FMLNetworkHandler handler, NetHandler netHandler, String userName) 089 { 090 byte[] allData = Bytes.concat(partials); 091 GameData.initializeServerGate(1); 092 try 093 { 094 NBTTagCompound serverList = CompressedStreamTools.decompress(allData); 095 NBTTagList list = serverList.getTagList("List"); 096 Set<ItemData> itemData = GameData.buildWorldItemData(list); 097 GameData.validateWorldSave(itemData); 098 MapDifference<Integer, ItemData> serverDifference = GameData.gateWorldLoadingForValidation(); 099 if (serverDifference!=null) 100 { 101 FMLCommonHandler.instance().disconnectIDMismatch(serverDifference, netHandler, network); 102 103 } 104 } 105 catch (IOException e) 106 { 107 } 108 } 109 110}