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}