internal void processBlockUpdates(Vec2i coord, UpdateSnowLayerChunk updateChunk, IBulkBlockAccessor ba)
        {
            int    chunkX    = coord.X;
            int    chunkZ    = coord.Y;
            var    setblocks = updateChunk.SetBlocks;
            double lastSnowAccumUpdateTotalHours = updateChunk.LastSnowAccumUpdateTotalHours;

            IMapChunk mc = sapi.WorldManager.GetMapChunk(chunkX, chunkZ);

            if (mc == null)
            {
                return;             // No longer loaded, we can just ditch it and re-do the thing again next time it gets loaded again
            }
            Vec2i tmpVec = new Vec2i();

            foreach (var sval in setblocks)
            {
                Block newblock  = sval.Value.Block;
                float snowLevel = sval.Value.SnowLevel;

                Block hereblock = ba.GetBlock(sval.Key);

                tmpVec.Set(sval.Key.X, sval.Key.Z);
                if (snowLevel > 0 && !mc.SnowAccum.ContainsKey(tmpVec))
                {
                    continue;                                                     // Must have gotten removed since we last checked in our seperate thread
                }
                hereblock.PerformSnowLevelUpdate(ba, sval.Key, newblock, snowLevel);
            }

            mc.SetData("lastSnowAccumUpdateTotalHours", SerializerUtil.Serialize <double>(lastSnowAccumUpdateTotalHours));
            mc.MarkDirty();
        }
        internal void processBlockUpdates(IMapChunk mc, UpdateSnowLayerChunk updateChunk, IBulkBlockAccessor ba)
        {
            var    setblocks = updateChunk.SetBlocks;
            double lastSnowAccumUpdateTotalHours = updateChunk.LastSnowAccumUpdateTotalHours;

            Vec2i tmpVec = new Vec2i();

            foreach (var sval in setblocks)
            {
                Block newblock  = sval.Value.Block;
                float snowLevel = sval.Value.SnowLevel;

                Block hereblock = ba.GetBlock(sval.Key);

                tmpVec.Set(sval.Key.X, sval.Key.Z);
                if (snowLevel > 0 && !mc.SnowAccum.ContainsKey(tmpVec))
                {
                    continue;                                                     // Must have gotten removed since we last checked in our seperate thread
                }
                hereblock.PerformSnowLevelUpdate(ba, sval.Key, newblock, snowLevel);
            }

            mc.SetModdata("lastSnowAccumUpdateTotalHours", SerializerUtil.Serialize <double>(lastSnowAccumUpdateTotalHours));
            mc.MarkDirty();
        }
        private void onSetChiselEditable(IServerPlayer player, int groupId, CmdArgs args)
        {
            var wmod = api.ModLoader.GetModSystem <WorldEdit.WorldEdit>();

            var workspace = wmod.GetWorkSpace(player.PlayerUID);

            if (workspace == null || workspace.StartMarker == null || workspace.EndMarker == null)
            {
                player.SendMessage(groupId, "Select an area with worldedit first", EnumChatType.CommandError);
                return;
            }

            bool editable  = args.PopBool() == true;
            bool resetName = args.PopBool() == true;

            Block chiselBlock = api.World.GetBlock(new AssetLocation("chiseledblock"));
            Block microblock  = api.World.GetBlock(new AssetLocation("microblock"));

            Block targetBlock = editable ? chiselBlock : microblock;

            int      startx = Math.Min(workspace.StartMarker.X, workspace.EndMarker.X);
            int      endx   = Math.Max(workspace.StartMarker.X, workspace.EndMarker.X);
            int      starty = Math.Min(workspace.StartMarker.Y, workspace.EndMarker.Y);
            int      endy   = Math.Max(workspace.StartMarker.Y, workspace.EndMarker.Y);
            int      startz = Math.Min(workspace.StartMarker.Z, workspace.EndMarker.Z);
            int      endZ   = Math.Max(workspace.StartMarker.Z, workspace.EndMarker.Z);
            BlockPos pos    = new BlockPos();

            IBulkBlockAccessor ba = api.World.BulkBlockAccessor;

            int cnt = 0;

            for (int x = startx; x < endx; x++)
            {
                for (int y = starty; y < endy; y++)
                {
                    for (int z = startz; z < endZ; z++)
                    {
                        pos.Set(x, y, z);

                        Block block = ba.GetBlock(x, y, z);
                        if (block is BlockMicroBlock && block.Id != targetBlock.Id)
                        {
                            cnt++;

                            TreeAttribute         tree = new TreeAttribute();
                            BlockEntityMicroBlock be   = api.World.BlockAccessor.GetBlockEntity(pos) as BlockEntityMicroBlock;
                            be.ToTreeAttributes(tree);

                            api.World.BlockAccessor.SetBlock(targetBlock.Id, pos);

                            be = api.World.BlockAccessor.GetBlockEntity(pos) as BlockEntityMicroBlock;
                            be.FromTreeAttributes(tree, api.World);

                            if (resetName)
                            {
                                be.BlockName = api.World.BlockAccessor.GetBlock(be.MaterialIds[0]).GetPlacedBlockName(api.World, pos);
                            }
                        }
                    }
                }
            }

            player.SendMessage(groupId, string.Format("Ok. {0} Chisel blocks exchanged", cnt), EnumChatType.CommandSuccess);
        }