public static void CreateGeometry(IMinecraftCommandService commandService, params string[] args)
        {
            var position = commandService.GetLocation();
            var lines    = new CreateCommandHandler(commandService).Handle(args.ToList().Skip(1).ToArray(), position,
                                                                           new List <SavedPosition>());

            if (lines.Any())
            {
                var _commandFormater = commandService.GetFormater();
                var sw = new Stopwatch();
                sw.Start();
                var lastLine = lines.First();
                foreach (var line in lines)
                {
                    if (lastLine.Start.Distance2D(line.Start) > 100)
                    {
                        commandService.Command($"tp @s {line.Start.X} ~ {line.Start.Z}");
                    }
                    var command = _commandFormater.Fill(line.Start.X, line.Start.Y, line.Start.Z, line.End.X, line.End.Y, line.End.Z, line.Block, line.Block.Contains(" ")?"":"0");
                    commandService.Command(command);
                    lastLine = line;
                }
                sw.Stop();
                commandService.Status($"time to queue commands {sw.Elapsed.TotalSeconds}");
                //Console.WriteLine($"time to queue commands {sw.Elapsed.TotalSeconds}");
                sw.Reset();
                sw.Start();
                commandService.Wait();
                sw.Stop();
                commandService.Status($"time to complete import {sw.Elapsed.TotalSeconds}");
                //Console.WriteLine($"time to complete import {sw.Elapsed.TotalSeconds}");
            }
        }
 public void OnConnection()
 {
     _minecraftService.Command(_minecraftService.GetFormater().Title(_serverName + " Started", ""));
     foreach (var subscription in _eventSubscriptions)
     {
         Console.WriteLine($"subscibing to {subscription}");
         _minecraftService.Subscribe((new SubscribeMessage(subscription.ToString())).ToString());
         Thread.Sleep(100);
     }
 }
        public static void CreateGeometry(IMinecraftCommandService commandService, List <SavedPosition> savedPositions, params string[] args)
        {
            var sw = new Stopwatch();

            sw.Start();
            var position = commandService.GetLocation();

            var commandArgs   = args.Skip(1).ToArray();
            var lines         = new List <Line>();
            var createCommand = (commandArgs.ElementAtOrDefault(0) ?? "").ToLower();

            switch (createCommand)
            {
            case "circle":
                lines = CreateCircle(commandService, commandArgs, position, savedPositions);
                break;

            case "ring":
                lines = CreateRing(commandService, commandArgs, position, savedPositions);
                break;

            case "walls":
                lines = CreateWalls(commandService, commandArgs, position, savedPositions);
                break;

            case "outline":
                lines = CreateBox(commandService, commandArgs, position, savedPositions, false);
                break;

            case "box":
                lines = CreateBox(commandService, commandArgs, position, savedPositions, true);
                break;

            case "floor":
                lines = CreateFloor(commandService, commandArgs, position, savedPositions);
                break;

            case "sphere":
                lines = CreateSphere(commandService, commandArgs, position, savedPositions);
                break;

            case "merlon":
                lines = CreateMerlon(commandService, commandArgs, position, savedPositions);
                break;

            case "maze":
                lines = CreateMaze(commandService, commandArgs, position, savedPositions);
                break;

            case "house":
                lines = CreateHouse(commandService, commandArgs, position, savedPositions);
                break;

            case "triangle":
                lines = CreateTriangle(commandService, commandArgs, position, savedPositions);
                break;

            case "poly":
            case "polygon":
                lines = CreatePoly(commandService, commandArgs, position, savedPositions);
                break;

            default:
                commandService.Status("CREATE\n" +
                                      "create circle\n" +
                                      "create ring\n" +
                                      "create walls\n" +
                                      "create outline\n" +
                                      "create box\n" +
                                      "create floor\n" +
                                      "create sphere\n" +
                                      "create merlon\n" +
                                      "create triangle\n" +
                                      "create [poly|polygon]\n" +
                                      "create maze"
                                      );
                return;
            }

            if (!lines.Any())
            {
                return;
            }
            LogTime(commandService, sw, $"CREATE {createCommand.ToUpper()}: time to get lines to render: {sw.Elapsed.TotalSeconds}");

            var commandFormater = commandService.GetFormater();

            var lastLine = lines.First();

            foreach (var line in lines)
            {
                if (lastLine.Start.Distance2D(line.Start) > 100)
                {
                    commandService.Command($"tp @s {line.Start.X} ~ {line.Start.Z}");
                }

                var command = commandFormater.Fill(line.Start.X, line.Start.Y, line.Start.Z, line.End.X, line.End.Y,
                                                   line.End.Z, line.Block, line.Block.Contains(" ") ? "" : "0");
                // TODO: Identify the limitation here and account for it.
                // Should this be executed on a thread so that other commands can be processed at the same time?
                // Is that possible?
                commandService.Command(command);
                lastLine = line;
            }

            LogTime(commandService, sw, $"CREATE {createCommand.ToUpper()}: time to queue commands: {sw.Elapsed.TotalSeconds}");

            commandService.Wait();
            LogTime(commandService, sw, $"CREATE {createCommand.ToUpper()}: time to complete import: {sw.Elapsed.TotalSeconds}");
        }
        private void SendCommandsToCodeConnection(Position target, List <Point> points, Rotate rotation,
                                                  Position clip = null)
        {
            // var service = new MinecraftCodeConnectionCommandService();
            var sw = new Stopwatch();


            _minecraftCommandService.Status("preparing schematic");

            if (clip != null)
            {
                points =
                    points.Where(a => a.X >= clip.X && a.Y >= clip.Y && a.Z >= clip.Z)
                    .Select(a => a.Shift(clip.Muliply(-1)))
                    .ToList();
            }
            if (rotation != Rotate.None)
            {
                sw.Start();
                Console.WriteLine($"rotating points...");
                var rotatedPoints = points.AsParallel().Select(a => a.Rotate(rotation)).ToList();
                Console.WriteLine($"time to rotate {sw.Elapsed}");
                sw.Reset();
                var measures = ModelAnalyzer.Analyze(rotatedPoints);
                sw.Start();
                Console.WriteLine($"shifting points...");
                points = rotatedPoints.AsParallel().Select(a => a.Shift(measures.Minimum.Muliply(-1))).ToList();
                Console.WriteLine($"time to shift {sw.Elapsed}");
                sw.Reset();
            }
            sw.Start();
            Console.WriteLine($"combining points...");
            var exportLines = ConvertFileToCommands(points.Where(a => a.BlockId != 0).ToList());

            Console.WriteLine($"time to combine {sw.Elapsed}");
            sw.Reset();
            sw.Start();
            var shift = exportLines.AsParallel().Select(a => a.Shift(target)).ToList();

            Console.WriteLine($"time to shift {sw.Elapsed}");
            sw.Reset();
            sw.Start();
            var importLines =
                shift.AsParallel()
                .OrderBy(a => a.Start.SortOrder)
                .ThenBy(a => a.Start.Y)
                .ThenBy(a => a.Start.X)
                .ThenBy(a => a.Start.Z)
                .ToList();

            Console.WriteLine($"time to sort {sw.Elapsed}");

            sw.Reset();

            _minecraftCommandService.Status("starting schematic import");

            sw.Start();
            foreach (var line in importLines)
            {
                var command = _minecraftCommandService.GetFormater()
                              .Fill(line.Start.X, line.Start.Y, line.Start.Z, line.End.X, line.End.Y, line.End.Z, line.BlockName,
                                    line.Data.ToString());
                _minecraftCommandService.Command(command);
                //$"fill?from={line.Start.X} {line.Start.Y} {line.Start.Z}&to={line.End.X} {line.End.Y} {line.End.Z}&tileName={line.BlockName}&tileData={line.Data}");
            }
            sw.Stop();
            _minecraftCommandService.Status($"time to queue commands {sw.Elapsed.TotalSeconds}");
            Console.WriteLine($"time to queue commands {sw.Elapsed.TotalSeconds}");
            sw.Reset();
            sw.Start();
            _minecraftCommandService.Wait();
            sw.Stop();
            _minecraftCommandService.Status($"time to complete import {sw.Elapsed.TotalSeconds}");
            Console.WriteLine($"time to complete import {sw.Elapsed.TotalSeconds}");
        }