public static void SetBlock(RaycastHit hit, Block block, bool adjacent = false)
    {
        if (!singleton.isConnected)
        {
            Debug.LogError("Cannont set block client is not connected");
            return;
        }
        WorldPos pos = EditTerrain.GetBlockPos(hit, adjacent);
        var      msg = new MessaageTypes.SetBlockMessage();

        msg.pos     = pos;
        msg.blockID = BlockIDManager.GetID(block);
        singleton.client.Send(MessaageTypes.SetBlockID, msg);
    }
    void OnSetBlock(NetworkMessage netMsg)
    {
        var msg = netMsg.ReadMessage <MessaageTypes.SetBlockMessage>();

        Debug.Log("Client Set block");

        //Update block on server
        Chunk    chunk = LoadChunk(msg.pos);
        WorldPos pos   = GetBlockPosInChunk(msg.pos);

        chunk.SetBlock(pos.x, pos.y, pos.z, BlockIDManager.GetBlock(msg.blockID));

        //Send data to all clients to update clients chunk
        var response = new MessaageTypes.ChunkDataMessage();

        response.blocks    = new MessaageTypes.MsgBlock[1];
        response.blocks[0] = new MessaageTypes.MsgBlock((byte)pos.x, (byte)pos.y, (byte)pos.z, msg.blockID);
        response.chunkPos  = chunk.pos;

        //netMsg.conn.Send(MessaageTypes.ChunkDataID, response);

        NetworkServer.SendToAll(MessaageTypes.ChunkDataID, response);
    }
    //Application Handlers
    void OnRequestChunkData(NetworkMessage netMsg)
    {
        int blocksPerResponse = 200;

        var msg = netMsg.ReadMessage <MessaageTypes.RequestChunkDataMessage>();
        //Debug.Log("Client requested block data for chunk: " + msg.pos.x + "," + msg.pos.y + "," + msg.pos.z);

        Chunk chunk = LoadChunk(msg.pos); //Load chunk
        //Find number of messages chunk data needs to be split into (Sending a complete chunk will require about 20 msgs)
        int numMsgs = Mathf.FloorToInt(chunk.modifiedBlocks.Count / 200f);
        List <KeyValuePair <WorldPos, Block> > blocks = chunk.modifiedBlocks.ToList();

        for (int msgNum = 0; msgNum <= numMsgs; msgNum++)
        {
            List <MessaageTypes.MsgBlock> msgBlocks = new List <MessaageTypes.MsgBlock>();
            for (int i = numMsgs * blocksPerResponse; numMsgs < (numMsgs + 1) * blocksPerResponse; i++)
            {
                if (i >= blocks.Count)
                {
                    break;
                }

                msgBlocks.Add(new MessaageTypes.MsgBlock((byte)blocks[i].Key.x, (byte)blocks[i].Key.y, (byte)blocks[i].Key.z, BlockIDManager.GetID(blocks[i].Value)));
            }

            var response = new MessaageTypes.ChunkDataMessage();
            response.blocks   = msgBlocks.ToArray();
            response.chunkPos = msg.pos;
            netMsg.conn.Send(MessaageTypes.ChunkDataID, response);
        }
    }
    void OnReceiveChunkData(NetworkMessage netMsg)
    {
        //Debug.Log("Recevied Chunk Data");
        var msg = netMsg.ReadMessage <MessaageTypes.ChunkDataMessage>();

        Chunk chunk = EditTerrain.GetChunk(msg.chunkPos);

        if (chunk == null)
        {
            Debug.Log("Chunk not loaded");
            return;
        }
        foreach (MessaageTypes.MsgBlock msgBlock in msg.blocks)
        {
            Debug.Log(msg.chunkPos.x + "," + msg.chunkPos.y + "," + msg.chunkPos.z);
            Debug.Log(msgBlock.x + "," + msgBlock.y + "," + msgBlock.y);
            World.singleton.SetBlock(msgBlock.x + msg.chunkPos.x, msgBlock.y + msg.chunkPos.y, msgBlock.z + msg.chunkPos.z, BlockIDManager.GetBlock(msgBlock.blockID));
        }
        //If chunk is already rendered update and rerender it.
        if (chunk.rendered)
        {
            chunk.update = true;
        }
    }