public static Schematic LoadFromFile(string FileName)
        {
            var output        = new Schematic();
            var schematicFile = new NbtFile();

            schematicFile.LoadFromFile(FileName);
            output.Height   = schematicFile.RootTag.Get <NbtShort>("Height").Value;
            output.Width    = schematicFile.RootTag.Get <NbtShort>("Width").Value;
            output.Length   = schematicFile.RootTag.Get <NbtShort>("Length").Value;
            output.BlockIds = schematicFile.RootTag.Get <NbtByteArray>("Blocks").Value;
            output.Data     = schematicFile.RootTag.Get <NbtByteArray>("Data").Value;

            output.Materials = schematicFile.RootTag.Get <NbtString>("Materials").Value;

            var nbtByteArray = schematicFile.RootTag.Get <NbtByteArray>("AddBlocks");

            if (nbtByteArray != null)
            {
                output.AddBlock = nbtByteArray.Value;
            }
            else
            {
                output.AddBlock = new byte[0];
            }
            output.Blocks = new short[output.BlockIds.Length]; // Have to later combine IDs

            for (var index = 0; index < output.Blocks.Length; index++)
            {
                if ((index >> 1) >= output.AddBlock.Length)
                {
                    output.Blocks[index] = (short)(output.BlockIds[index] & 0xFF);
                }
                else
                {
                    if ((index & 1) == 0)
                    {
                        output.Blocks[index] =
                            (short)(((output.AddBlock[index >> 1] & 0x0F) << 8) + (output.BlockIds[index] & 0xFF));
                    }
                    else
                    {
                        output.Blocks[index] =
                            (short)(((output.AddBlock[index >> 1] & 0xF0) << 4) + (output.BlockIds[index] & 0xFF));
                    }
                }
            }


            return(output);
        }
        private static List <Point> LoadFile(string FileName)
        {
            var       points = new List <Point>();
            Schematic schematic;

            if (!FileName.EndsWith("schematic"))
            {
                FileName += ".schematic";
            }
            var combine = Path.Combine(ConfigurationManager.AppSettings["data"], FileName);

            if (!File.Exists(FileName) && File.Exists(combine))
            {
                FileName = combine;
            }
            schematic = Schematic.LoadFromFile(FileName);
            points    = schematic.GetPoints();
            //var outputFilename = Path.GetFileNameWithoutExtension(FileName) + ".fill";
            //if (args.Length > 2)
            //{
            //    outputFilename = args[2];
            //}
            return(points);
        }
        private List <Point> LoadFile(string filename)
        {
            var schematicFolder = GetSchematicFolder();

            filename = new Regex($"[{Path.GetInvalidFileNameChars()}]").Replace(filename ?? "", "");

            if (!filename.EndsWith(".schematic"))
            {
                filename += ".schematic";
            }

            // Check for file in folder
            var files = Directory.GetFiles(schematicFolder, filename);

            if (files.Length == 0)
            {
                _commandService.Status("Unable to locate the schematic.");
                return(null);
            }

            var schematic = Schematic.LoadFromFile(Path.GetFullPath(files[0]));

            return(schematic.GetPoints());
        }
        public static void SchematicCommandProcessor(string[] args)
        {
            var s        = new MinecraftCommandService();
            var target   = new Position(0, 0, 0);
            var shift    = new Position(0, 0, 0);
            var rotation = Rotate.None;

            var command = args[0];

            var       FileName = "";
            var       points   = new List <Point>();
            Schematic schematic;

            if (args.Length > 1)
            {
                FileName = args[1];
                if (!FileName.EndsWith("schematic"))
                {
                    FileName += ".schematic";
                }
                var combine = Path.Combine(ConfigurationManager.AppSettings["data"], FileName);
                if (!File.Exists(FileName) && File.Exists(combine))
                {
                    FileName = combine;
                }
                schematic = Schematic.LoadFromFile(FileName);
                points    = schematic.GetPoints();
            }
            var outputFilename = Path.GetFileNameWithoutExtension(FileName) + ".fill";

            if (args.Length > 2)
            {
                outputFilename = args[2];
            }
            if (args.Length == 6)
            {
                target.X = Convert.ToInt32(args[3]);
                target.Y = Convert.ToInt32(args[4]);
                target.Z = Convert.ToInt32(args[5]);
            }

            switch (command)
            {
            case "list":

                var files = Directory.GetFiles(ConfigurationManager.AppSettings["data"], "*.schematic");
                foreach (var file in files)
                {
                    s.Status(Path.GetFileName(file));
                }

                break;

            case "analyze":
                var results          = ModelAnalyzer.Analyze(points);
                var firstGroundLayer =
                    results.Layers.First(a => a.Blocks.Any(b => b.Block.Equals("air") && b.PercentOfLayer >= 0.5)).Y;
                string output = $"{Path.GetFileName(FileName)} Model Size: X:{results.Width} Y:{results.Height} Z:{results.Length} Ground Level:{firstGroundLayer} Total Blocks:{results.Width*results.Height*results.Length}";
                Console.WriteLine(output);
                s.Status(output);
                break;

            case "import":
                if (args.Length >= 5)
                {
                    if (args[2].StartsWith("~") || args[3].StartsWith("~") || args[4].StartsWith("~"))
                    {
                        //get current position
                        //parse and add to current position.
                        s.Status("relative positions are not supported.");
                        return;
                    }
                    else
                    {
                        target.X = Convert.ToInt32(args[2]);
                        target.Y = Convert.ToInt32(args[3]);
                        target.Z = Convert.ToInt32(args[4]);
                    }
                }
                if (args.Length >= 6)
                {
                    rotation = (Rotate)Convert.ToInt32(args?[5]);
                }
                if (args.Length >= 9)
                {
                    shift.X = Convert.ToInt32(args[6]);
                    shift.Y = Convert.ToInt32(args[7]);
                    shift.Z = Convert.ToInt32(args[8]);
                }

                Console.WriteLine($"importing {FileName} to {target}");
                SendCommandsToCodeConnection(target, points, rotation, shift);
                break;

            default:
                break;
            }
            Console.WriteLine($"{FileName}  ${outputFilename} {target.X} {target.Y} {target.Z}");
        }