示例#1
0
        static void UpdateBlock(Player p, Level lvl, BlockDefinition def, bool global)
        {
            BlockDefinition[] defs  = global ? BlockDefinition.GlobalDefs : lvl.CustomBlockDefs;
            BlockID           block = def.GetBlock();

            string scope = global ? "global" : "level";

            p.Message("Created a new " + scope + " custom block " + def.Name + "(" + def.RawID + ")");

            block = def.GetBlock();
            BlockDefinition.Add(def, defs, lvl);
            ResetProps(global, lvl, block, p);
        }
示例#2
0
        static bool AddBlock(Player p, Level lvl, BlockDefinition def, bool global, string cmd)
        {
            BlockDefinition[] defs  = global ? BlockDefinition.GlobalDefs : lvl.CustomBlockDefs;
            BlockID           block = def.GetBlock();
            BlockDefinition   old   = defs[block];

            if (!global && old == BlockDefinition.GlobalDefs[block])
            {
                old = null;
            }

            // in case the list is modified before we finish the command.
            if (old != null)
            {
                block = GetFreeBlock(p, global, lvl, cmd);
                if (block == Block.Invalid)
                {
                    if (!global)
                    {
                        p.Message("You may also manually specify the same existing id of a global custom block.");
                    }
                    return(false);
                }
                def.SetBlock(block);
            }

            UpdateBlock(p, lvl, def, global);
            return(true);
        }
示例#3
0
        public static int GetBlock(Player p, string msg, out byte extBlock)
        {
            byte block = Block.Byte(msg);

            extBlock = 0;
            if (msg.CaselessEq("skip") || msg.CaselessEq("none"))
            {
                return(Block.Invalid);
            }
            if (block != Block.Invalid)
            {
                return(block);
            }

            // try treat as a block definition id.
            block = BlockDefinition.GetBlock(msg, p);
            if (block == Block.Invalid)
            {
                Player.Message(p, "&cThere is no block \"{0}\".", msg);
                return(-1);
            }

            // custom block overriding a core block
            if (block < Block.CpeCount)
            {
                return(block);
            }

            extBlock = block;
            return(Block.custom_block);
        }
示例#4
0
        static void ListHandler(Player p, Level lvl, string[] parts,
                                bool global, string cmd)
        {
            string modifier = parts.Length > 1 ? parts[1] : "";

            BlockDefinition[]      defs        = global ? BlockDefinition.GlobalDefs : lvl.CustomBlockDefs;
            List <BlockDefinition> defsInScope = new List <BlockDefinition>();

            for (int i = 0; i < defs.Length; i++)
            {
                BlockDefinition def = defs[i];
                if (def == null)
                {
                    continue;
                }
                BlockID block = def.GetBlock();

                if (!ExistsInScope(def, block, global))
                {
                    continue;
                }
                defsInScope.Add(def);
            }
            MultiPageOutput.Output(p, defsInScope, FormatBlock, cmd.Substring(1) + " list",
                                   "custom blocks", modifier, true);
        }
示例#5
0
        static void ParseBlockDefinitions(NbtCompound cpe, Level lvl)
        {
            NbtCompound blocks       = (NbtCompound)cpe["BlockDefinitions"];
            bool        hasBlockDefs = false;

            foreach (NbtTag tag in blocks)
            {
                if (tag.TagType != NbtTagType.Compound)
                {
                    continue;
                }

                NbtCompound     props = (NbtCompound)tag;
                BlockDefinition def   = new BlockDefinition();
                def.RawID       = props["ID"].ByteValue;
                def.Name        = props["Name"].StringValue;
                def.CollideType = props["CollideType"].ByteValue;
                def.Speed       = props["Speed"].FloatValue;

                def.BlocksLight = props["TransmitsLight"].ByteValue == 0;
                def.WalkSound   = props["WalkSound"].ByteValue;
                def.FullBright  = props["FullBright"].ByteValue != 0;
                def.Shape       = props["Shape"].ByteValue;
                def.BlockDraw   = props["BlockDraw"].ByteValue;

                byte[] fog = props["Fog"].ByteArrayValue;
                def.FogDensity = fog[0];
                // Fix for older ClassicalSharp versions which saved wrong value for density = 0
                if (def.FogDensity == 0xFF)
                {
                    def.FogDensity = 0;
                }
                def.FogR = fog[1]; def.FogG = fog[2]; def.FogB = fog[3];

                byte[] tex = props["Textures"].ByteArrayValue;
                def.TopTex   = tex[0]; def.BottomTex = tex[1];
                def.LeftTex  = tex[2]; def.RightTex = tex[3];
                def.FrontTex = tex[4]; def.BackTex = tex[5];

                byte[] coords = props["Coords"].ByteArrayValue;
                def.MinX = coords[0]; def.MinZ = coords[1]; def.MinY = coords[2];
                def.MaxX = coords[3]; def.MaxZ = coords[4]; def.MaxY = coords[5];

                // Don't define level custom block if same as global custom block
                BlockID         block     = def.GetBlock();
                BlockDefinition globalDef = BlockDefinition.GlobalDefs[block];
                if (PropsEquals(def, globalDef))
                {
                    continue;
                }

                lvl.UpdateCustomBlock(block, def);
                hasBlockDefs = true;
            }

            if (hasBlockDefs)
            {
                BlockDefinition.Save(false, lvl);
            }
        }
示例#6
0
        internal static byte GetBlock(Player p, string msg, out byte extType, bool checkPlacePerm = true)
        {
            byte type = Block.Byte(msg);

            extType = 0;
            if (type == Block.Zero)
            {
                // try treat as a block definition id.
                type = BlockDefinition.GetBlock(msg, p);
                if (type == Block.Zero)
                {
                    Player.SendMessage(p, "There is no block \"" + msg + "\".");
                    return(Block.Zero);
                }
                extType = type;
                return(Block.custom_block);
            }

            if (checkPlacePerm && !Block.canPlace(p, type))
            {
                Player.SendMessage(p, "Cannot place the block \"" + msg + "\".");
                return(Block.Zero);
            }
            return(type);
        }
示例#7
0
        /// <summary> Attempts to parse the given argument as either a block name or a block ID. </summary>
        /// <remarks> This does not output any messages to the player. </remarks>
        public static ExtBlock RawGetBlock(Player p, string input)
        {
            BlockDefinition[] defs = p == null ? BlockDefinition.GlobalDefs : p.level.CustomBlockDefs;
            byte id;

            // raw ID is treated specially, before names
            if (byte.TryParse(input, out id) && (id < Block.CpeCount || defs[id] != null))
            {
                return(ExtBlock.FromRaw(id));
            }

            int raw = BlockDefinition.GetBlock(input, defs);

            if (raw != -1)
            {
                return(ExtBlock.FromRaw((byte)raw));
            }

            id = Block.Byte(input);
            if (id != Block.Invalid)
            {
                return(new ExtBlock(id, 0));
            }

            return(ExtBlock.Invalid);
        }
示例#8
0
        byte GetBlock(Player p, string name, out byte extBlock)
        {
            extBlock = 0;
            byte id = Block.Byte(name);

            if (Block.Props[id].IsPortal)
            {
                return(id);
            }
            if (name == "show")
            {
                ShowPortals(p); return(Block.Invalid);
            }

            id = BlockDefinition.GetBlock(name, p);
            if (p.level.CustomBlockProps[id].IsPortal)
            {
                extBlock = id; return(Block.custom_block);
            }

            // Hardcoded aliases for backwards compatibility
            id = Block.Invalid;
            if (name == "")
            {
                id = Block.blue_portal;
            }
            if (name == "blue")
            {
                id = Block.blue_portal;
            }
            if (name == "orange")
            {
                id = Block.orange_portal;
            }
            if (name == "air")
            {
                id = Block.air_portal;
            }
            if (name == "water")
            {
                id = Block.water_portal;
            }
            if (name == "lava")
            {
                id = Block.lava_portal;
            }

            if (!Block.Props[id].IsPortal)
            {
                Help(p); return(Block.Invalid);
            }
            return(id);
        }
示例#9
0
        byte GetBlock(Player p, string name, out byte extBlock,
                      ref bool allMessage)
        {
            extBlock = 0;
            byte id = Block.Byte(name);

            if (Block.Props[id].IsMessageBlock)
            {
                return(id);
            }
            if (name == "show")
            {
                ShowMessageBlocks(p); return(Block.Invalid);
            }

            id = BlockDefinition.GetBlock(name, p);
            if (p.level.CustomBlockProps[id].IsMessageBlock)
            {
                extBlock = id; return(Block.custom_block);
            }

            // Hardcoded aliases for backwards compatibility
            id = Block.MsgWhite;
            if (name == "white")
            {
                id = Block.MsgWhite;
            }
            if (name == "black")
            {
                id = Block.MsgBlack;
            }
            if (name == "air")
            {
                id = Block.MsgAir;
            }
            if (name == "water")
            {
                id = Block.MsgWater;
            }
            if (name == "lava")
            {
                id = Block.MsgLava;
            }

            allMessage = id == Block.MsgWhite && name != "white";
            if (!Block.Props[id].IsMessageBlock)
            {
                Help(p); return(Block.Invalid);
            }
            return(id);
        }
示例#10
0
        static bool AddBlock(Player p, Level lvl, BlockDefinition def,
                             bool global, string cmd, BlockProps props)
        {
            BlockDefinition[] defs  = global ? BlockDefinition.GlobalDefs : lvl.CustomBlockDefs;
            BlockID           block = def.GetBlock();
            BlockDefinition   old   = defs[block];

            if (!global && old == BlockDefinition.GlobalDefs[block])
            {
                old = null;
            }

            // in case the list is modified before we finish the command.
            if (old != null)
            {
                block = GetFreeBlock(global, lvl);
                if (block == Block.Invalid)
                {
                    p.Message("There are no custom block ids left, " +
                              "you must " + cmd + " remove a custom block first.");
                    if (!global)
                    {
                        p.Message("You may also manually specify the same existing id of a global custom block.");
                    }
                    return(false);
                }
                def.SetBlock(block);
            }

            string scope = global ? "global" : "level";

            p.Message("Created a new " + scope + " custom block " + def.Name + "(" + def.RawID + ")");

            block = def.GetBlock();
            BlockDefinition.Add(def, defs, lvl);
            ResetProps(global, lvl, block, p);
            return(true);
        }
示例#11
0
        static BlockID[] Transform(BlockDefinition[] defs, string[] mirrorDirs, string[] rotateDirs)
        {
            BlockID[] transform = new BlockID[Block.ExtendedCount];
            for (int i = 0; i < transform.Length; i++)
            {
                transform[i] = (BlockID)i;
            }
            if (mirrorDirs == null && rotateDirs == null)
            {
                return(transform);
            }

            // Rotate/Mirror directional blocks
            for (int i = 0; i < defs.Length; i++)
            {
                if (defs[i] == null)
                {
                    continue;
                }
                int dirIndex = defs[i].Name.LastIndexOf('-');
                if (dirIndex == -1)
                {
                    continue;
                }

                BlockDefinition transformed = null;
                if (mirrorDirs != null)
                {
                    transformed = MirrorTransform(defs, i, dirIndex, mirrorDirs);
                }
                else
                {
                    transformed = RotateTransform(defs, i, dirIndex, rotateDirs);
                }

                if (transformed == null)
                {
                    continue;
                }
                BlockID src = defs[i].GetBlock();
                transform[src] = transformed.GetBlock();
            }
            return(transform);
        }
示例#12
0
        static ExtBlock GetBlock(Player p, BlockProps[] scope, string input)
        {
            if (scope == Block.Props)
            {
                byte raw;
                if (!byte.TryParse(input, out raw))
                {
                    raw = Block.Byte(input);
                }

                if (Block.Name(raw).CaselessEq("unknown"))
                {
                    Player.Message(p, "&cThere is no block with id or name \"{0}\"", input);
                    return(ExtBlock.Invalid);
                }
                return(new ExtBlock(raw, 0));
            }
            else if (scope == BlockDefinition.GlobalProps)
            {
                int raw = BlockDefinition.GetBlock(input, BlockDefinition.GlobalDefs);
                if (raw == -1)
                {
                    Player.Message(p, "&cThere is no global custom block with id or name \"{0}\"", input);
                    return(ExtBlock.Invalid);
                }
                return(ExtBlock.FromRaw((byte)raw));
            }
            else
            {
                int raw = BlockDefinition.GetBlock(input, p.level.CustomBlockDefs);
                if (raw == -1)
                {
                    Player.Message(p, "&cThere is no level custom block with id or name \"{0}\"", input);
                    return(ExtBlock.Invalid);
                }

                if (p.level.CustomBlockDefs[raw] == BlockDefinition.GlobalDefs[raw])
                {
                    Player.Message(p, "&cUse %T/BlockProps global &cto modify this custom block."); return(ExtBlock.Invalid);
                }
                return(ExtBlock.FromRaw((byte)raw));
            }
        }
示例#13
0
        byte GetBlock(Player p, BlockProps[] scope, string block)
        {
            byte id = 0;

            if (scope == Block.Props)
            {
                if (!byte.TryParse(block, out id))
                {
                    id = Block.Byte(block);
                }

                if (Block.Name(id).CaselessEq("unknown"))
                {
                    Player.Message(p, "&cThere is no block with id or name \"{0}\"", block);
                    id = Block.Invalid;
                }
            }
            else if (scope == BlockDefinition.GlobalProps)
            {
                id = BlockDefinition.GetBlock(block, BlockDefinition.GlobalDefs);
                if (id == Block.Invalid)
                {
                    Player.Message(p, "&cThere is no global custom block with id or name \"{0}\"", block);
                }
            }
            else
            {
                id = BlockDefinition.GetBlock(block, p.level.CustomBlockDefs);
                if (id == Block.Invalid)
                {
                    Player.Message(p, "&cThere is no level custom block with id or name \"{0}\"", block);
                }
                if (p.level.CustomBlockDefs[id] == BlockDefinition.GlobalDefs[id])
                {
                    Player.Message(p, "&cUse %T/blockprops global &cto modify this custom block."); return(Block.Invalid);
                }
            }
            return(id);
        }
示例#14
0
        static bool DoEdit(Player p, Level lvl, BlockID block, string[] parts,
                           bool global, string cmd)
        {
            BlockDefinition[] defs = global ? BlockDefinition.GlobalDefs : lvl.CustomBlockDefs;
            BlockDefinition   def = defs[block], globalDef = BlockDefinition.GlobalDefs[block];

            if (def == null && block < Block.CpeCount)
            {
                def = DefaultSet.MakeCustomBlock(block);
                UpdateBlock(p, lvl, def, global);
            }
            if (def != null && !global && def == globalDef)
            {
                def = globalDef.Copy();
                UpdateBlock(p, lvl, def, global);
            }
            if (!ExistsInScope(def, block, global))
            {
                MessageNoBlock(p, block, global, cmd); return(false);
            }

            string value = parts[3], blockName = def.Name;
            bool   temp = false, changedFallback = false;

            string arg = MapPropertyName(parts[2].ToLower());

            switch (arg)
            {
            case "name":
                def.Name = value; break;

            case "collide":
                if (!EditByte(p, value, "Collide type", ref def.CollideType, arg))
                {
                    return(false);
                }
                break;

            case "speed":
                if (!CommandParser.GetReal(p, value, "Movement speed", ref def.Speed, 0.25f, 3.96f))
                {
                    SendEditHelp(p, arg); return(false);
                }
                break;

            case "toptex":
                if (!EditUShort(p, value, "Top texture", ref def.TopTex, arg))
                {
                    return(false);
                }
                break;

            case "alltex":
                if (!EditUShort(p, value, "All textures", ref def.RightTex, arg))
                {
                    return(false);
                }
                def.SetAllTex(def.RightTex);
                break;

            case "sidetex":
                if (!EditUShort(p, value, "Side texture", ref def.RightTex, arg))
                {
                    return(false);
                }
                def.SetSideTex(def.RightTex);
                break;

            case "lefttex":
                if (!EditUShort(p, value, "Left texture", ref def.LeftTex, arg))
                {
                    return(false);
                }
                break;

            case "righttex":
                if (!EditUShort(p, value, "Right texture", ref def.RightTex, arg))
                {
                    return(false);
                }
                break;

            case "fronttex":
                if (!EditUShort(p, value, "Front texture", ref def.FrontTex, arg))
                {
                    return(false);
                }
                break;

            case "backtex":
                if (!EditUShort(p, value, "Back texture", ref def.BackTex, arg))
                {
                    return(false);
                }
                break;

            case "bottomtex":
                if (!EditUShort(p, value, "Bottom texture", ref def.BottomTex, arg))
                {
                    return(false);
                }
                break;

            case "blockslight":
                if (!CommandParser.GetBool(p, value, ref temp))
                {
                    SendEditHelp(p, arg); return(false);
                }
                def.BlocksLight = temp;
                break;

            case "sound":
                if (!EditByte(p, value, "Walk sound", ref def.WalkSound, arg))
                {
                    return(false);
                }
                break;

            case "fullbright":
                if (!CommandParser.GetBool(p, value, ref temp))
                {
                    SendEditHelp(p, arg); return(false);
                }
                def.FullBright = temp;
                break;

            case "shape":
                if (!CommandParser.GetBool(p, value, ref temp))
                {
                    SendEditHelp(p, arg); return(false);
                }
                def.Shape = temp ? (byte)0 : def.MaxZ;
                break;

            case "blockdraw":
                if (!EditByte(p, value, "Block draw", ref def.BlockDraw, arg))
                {
                    return(false);
                }
                break;

            case "min":
                if (!ParseCoords(p, value, ref def.MinX, ref def.MinY, ref def.MinZ))
                {
                    SendEditHelp(p, arg); return(false);
                }
                break;

            case "max":
                if (!ParseCoords(p, value, ref def.MaxX, ref def.MaxY, ref def.MaxZ))
                {
                    SendEditHelp(p, arg); return(false);
                }
                break;

            case "fogdensity":
                if (!EditByte(p, value, "Fog density", ref def.FogDensity, arg))
                {
                    return(false);
                }
                break;

            case "fogcolor":
                ColorDesc rgb = default(ColorDesc);
                if (!CommandParser.GetHex(p, value, ref rgb))
                {
                    return(false);
                }
                def.FogR = rgb.R; def.FogG = rgb.G; def.FogB = rgb.B;
                break;

            case "fallback":
                byte fallback = GetFallback(p, value);
                if (fallback == Block.Invalid)
                {
                    return(false);
                }
                changedFallback = true;

                value        = Block.GetName(p, fallback);
                def.FallBack = fallback; break;

            case "order":
                int order = 0;
                if (!CommandParser.GetInt(p, value, "Inventory order", ref order, 0, Block.MaxRaw))
                {
                    SendEditHelp(p, arg); return(false);
                }

                // Don't let multiple blocks be assigned to same order
                if (order != def.RawID && order != 0)
                {
                    for (int i = 0; i < defs.Length; i++)
                    {
                        if (defs[i] == null || defs[i].InventoryOrder != order)
                        {
                            continue;
                        }
                        p.Message("Block {0} already had order {1}", defs[i].Name, order);
                        return(false);
                    }
                }

                def.InventoryOrder = order == def.RawID ? -1 : order;
                BlockDefinition.UpdateOrder(def, global, lvl);
                p.Message("Set inventory order for {0} to {1}", blockName,
                          order == def.RawID ? "default" : order.ToString());
                return(true);

            default:
                p.Message("Unrecognised property: " + arg); return(false);
            }

            p.Message("Set {0} for {1} to {2}", arg, blockName, value);
            BlockDefinition.Add(def, defs, lvl);
            if (changedFallback)
            {
                BlockDefinition.UpdateFallback(global, def.GetBlock(), lvl);
            }
            return(true);
        }
示例#15
0
        static void DefineBlockStep(Player p, string value, bool global, string cmd)
        {
            string          opt  = value.ToLower();
            int             step = GetStep(p, global);
            BlockDefinition bd   = GetBD(p, global);
            bool            temp = false;

            if (opt == "revert" && step > 2)
            {
                if (step == 17 && bd.FogDensity == 0)
                {
                    step -= 2;
                }
                else if (step == 9 && bd.Shape == 0)
                {
                    step -= 5;
                }
                else
                {
                    step--;
                }

                SetStep(p, global, step);
                SendStepHelp(p, global);
                return;
            }

            if (step == 2)
            {
                bd.Name = value;
                step++;
            }
            else if (step == 3)
            {
                if (CommandParser.GetBool(p, value, ref temp))
                {
                    bd.Shape = temp ? (byte)0 : (byte)16;
                    step++;
                }
            }
            else if (step == 4)
            {
                if (CommandParser.GetUShort(p, value, "Texture ID", ref bd.TopTex, 0, 255))
                {
                    step += (bd.Shape == 0 ? 5 : 1); // skip other texture steps for sprites
                    if (bd.Shape == 0)
                    {
                        bd.SetAllTex(bd.TopTex);
                    }
                }
            }
            else if (step == 5)
            {
                if (CommandParser.GetUShort(p, value, "Texture ID", ref bd.RightTex, 0, 255))
                {
                    bd.SetSideTex(bd.RightTex);
                    step++;
                }
            }
            else if (step == 6)
            {
                if (CommandParser.GetUShort(p, value, "Texture ID", ref bd.BottomTex, 0, 255))
                {
                    step++;
                }
            }
            else if (step == 7)
            {
                if (ParseCoords(p, value, ref bd.MinX, ref bd.MinY, ref bd.MinZ))
                {
                    step++;
                }
            }
            else if (step == 8)
            {
                if (ParseCoords(p, value, ref bd.MaxX, ref bd.MaxY, ref bd.MaxZ))
                {
                    step++;
                }
                bd.Shape = bd.MaxY;
            }
            else if (step == 9)
            {
                if (CommandParser.GetByte(p, value, "Collide type", ref bd.CollideType, 0, 7))
                {
                    step++;
                }
            }
            else if (step == 10)
            {
                if (CommandParser.GetReal(p, value, "Movement speed", ref bd.Speed, 0.25f, 3.96f))
                {
                    step++;
                }
            }
            else if (step == 11)
            {
                if (CommandParser.GetBool(p, value, ref temp))
                {
                    bd.BlocksLight = temp;
                    step++;
                }
            }
            else if (step == 12)
            {
                if (CommandParser.GetByte(p, value, "Walk sound", ref bd.WalkSound, 0, 11))
                {
                    step++;
                }
            }
            else if (step == 13)
            {
                if (CommandParser.GetBool(p, value, ref bd.FullBright))
                {
                    step++;
                }
            }
            else if (step == 14)
            {
                if (CommandParser.GetByte(p, value, "Block draw", ref bd.BlockDraw, 0, 4))
                {
                    step++;
                }
            }
            else if (step == 15)
            {
                if (CommandParser.GetByte(p, value, "Fog density", ref bd.FogDensity))
                {
                    step += (bd.FogDensity == 0 ? 2 : 1);
                }
            }
            else if (step == 16)
            {
                ColorDesc rgb = default(ColorDesc);
                if (CommandParser.GetHex(p, value, ref rgb))
                {
                    bd.FogR = rgb.R; bd.FogG = rgb.G; bd.FogB = rgb.B;
                    step++;
                }
            }
            else if (step == 17)
            {
                byte fallback = GetFallback(p, value);
                if (fallback == Block.Invalid)
                {
                    SendStepHelp(p, global); return;
                }
                bd.FallBack = fallback;

                BlockID block = bd.GetBlock();
                if (!AddBlock(p, bd, global, cmd, Block.Props[block]))
                {
                    return;
                }

                SetBD(p, global, null);
                SetStep(p, global, 0);
                return;
            }

            SetStep(p, global, step);
            SendStepHelp(p, global);
        }
示例#16
0
        static void ParseBlockDefinitions(NbtCompound cpe, Level lvl)
        {
            NbtCompound blocks       = (NbtCompound)cpe["BlockDefinitions"];
            bool        hasBlockDefs = false;

            foreach (NbtTag tag in blocks)
            {
                if (tag.TagType != NbtTagType.Compound)
                {
                    continue;
                }

                NbtCompound     props = (NbtCompound)tag;
                BlockDefinition def   = new BlockDefinition();
                def.RawID = props["ID"].ByteValue;
                // can't change "ID" to short since backwards compatibility
                if (props.Contains("ID2"))
                {
                    def.RawID = (ushort)props["ID2"].ShortValue;
                }

                def.Name        = props["Name"].StringValue;
                def.CollideType = props["CollideType"].ByteValue;
                def.Speed       = props["Speed"].FloatValue;

                def.BlocksLight = props["TransmitsLight"].ByteValue == 0;
                def.WalkSound   = props["WalkSound"].ByteValue;
                def.FullBright  = props["FullBright"].ByteValue != 0;
                def.Shape       = props["Shape"].ByteValue;
                def.BlockDraw   = props["BlockDraw"].ByteValue;

                byte[] fog = props["Fog"].ByteArrayValue;
                def.FogDensity = fog[0];
                // Fix for older ClassicalSharp versions which saved wrong value for density = 0
                if (def.FogDensity == 0xFF)
                {
                    def.FogDensity = 0;
                }
                def.FogR = fog[1]; def.FogG = fog[2]; def.FogB = fog[3];

                byte[] tex = props["Textures"].ByteArrayValue;
                ImportTexs(def, tex, 0);
                if (tex.Length > 6)
                {
                    ImportTexs(def, tex, 6);
                }

                byte[] coords = props["Coords"].ByteArrayValue;
                def.MinX = coords[0]; def.MinZ = coords[1]; def.MinY = coords[2];
                def.MaxX = coords[3]; def.MaxZ = coords[4]; def.MaxY = coords[5];

                BlockID block = def.GetBlock();
                if (block >= Block.ExtendedCount)
                {
                    Logger.Log(LogType.Warning, "Cannot import custom block {0} (ID {1})",
                               def.Name, def.RawID);
                    continue;
                }

                // Don't define level custom block if same as global custom block
                BlockDefinition globalDef = BlockDefinition.GlobalDefs[block];
                if (PropsEquals(def, globalDef))
                {
                    continue;
                }

                lvl.UpdateCustomBlock(block, def);
                hasBlockDefs = true;
            }

            if (hasBlockDefs)
            {
                BlockDefinition.Save(false, lvl);
            }
        }