private void CheckCommandsChanged()
        {
            string currentText = TextPanel.GetText();

            if (currentText == m_panelText)
            {
                return;
            }

            m_panelText = currentText;
            GetAutopilotActions();
        }
示例#2
0
            public TP(ushort id, SubP p) : base(id, p)
            {
                loopturn       = false;
                NormWhAng      = 35; Tangle = 0;
                switchingsusp  = false;
                SuspensionMode = SuspensionModes.sport; DriveMode = DriveModes.full;
                FirstStr       = ""; SecondStr = "";
                Wheels         = new List <IMyMotorSuspension>();

                if (
                    (DriverLCD = OS.GTS.GetBlockWithName("Screen Driver") as IMyTextPanel) == null ||
                    (WheelLF = OS.GTS.GetBlockWithName("Wheel Suspension 3x3 LF") as IMyMotorSuspension) == null ||
                    (WheelRF = OS.GTS.GetBlockWithName("Wheel Suspension 3x3 RF") as IMyMotorSuspension) == null ||
                    (WheelLB = OS.GTS.GetBlockWithName("Wheel Suspension 3x3 LB") as IMyMotorSuspension) == null ||
                    (WheelRB = OS.GTS.GetBlockWithName("Wheel Suspension 3x3 RB") as IMyMotorSuspension) == null ||
                    (RemoteDriver = OS.GTS.GetBlockWithName("Control car") as IMyRemoteControl) == null ||
                    (RotorRull = OS.GTS.GetBlockWithName("Rotor rull") as IMyMotorStator) == null
                    )
                {
                    Terminate("Kontur blocks not found.");
                    return;
                }
                Wheels = new List <IMyMotorSuspension>()
                {
                    WheelLF, WheelRF, WheelLB, WheelRB
                };

                string saved = DriverLCD.GetText();

                if (string.IsNullOrEmpty(saved))
                {
                    if (saved.Contains("front"))
                    {
                        DriveMode = DriveModes.front;
                    }
                    else if (saved.Contains("rear"))
                    {
                        DriveMode = DriveModes.rear;
                    }
                    if (saved.Contains("off-road"))
                    {
                        SuspensionMode = SuspensionModes.offroad;
                    }
                    if (saved.Contains("looper"))
                    {
                        loopturn = true;
                    }
                }

                ChangeFirst();

                AddAct(ref MA, Main, 1);

                SetCmd(new Dictionary <string, Cmd>
                {
                    { "sdm", new Cmd(CmdSDM, "Switch drive mode Full/Front/Rear.") },
                    { "ssm", new Cmd(CmdSSM, "Switch suspension mode Sport/Off road.") },
                    { "sl", new Cmd(CmdSL, "Switch loopturn mode.") }
                });
            }
示例#3
0
        // TODO: display n to m lines.
        public void UpdatePublic(bool show = true)
        {
            try
            {
                if (FontSize != _panel.FontSize)
                {
                    _panel.FontSize = FontSize;
                }
            }
            catch (Exception ex)
            {
                // The game may generate an exception from the GetValueFloat(GetValue) call.
                // We can safely ignore this if it doesn't work, but it may indicate a game issue.
                EconomyScript.Instance.ServerLogger.WriteException(ex, UpdateCrashMessage);
                EconomyScript.Instance.ClientLogger.WriteException(ex, UpdateCrashMessage);
            }

            LastUpdate = DateTime.Now;

            // no need to update if the text has not changed.
            if (_panel.GetText() != _publicString.ToString())
            {
                _panel.WriteText(_publicString.ToString());

                if (show)
                {
                    _panel.ContentType = ContentType.TEXT_AND_IMAGE;
                }
            }
        }
示例#4
0
        public void Main(string argument, UpdateType updateSource)
        {
            IMyTextPanel LCDWritingScreen = (IMyTextPanel)GridTerminalSystem.GetBlockWithName(lcdName);



            // If setupcomplete is false, run Setup method.
            if (!setupcomplete)
            {
                Echo("Running setup.");
                Setup();
            }
            else
            {
                // Create our message. We first make it a string, and then we "box" it as an object type.
                string messageOut = LCDWritingScreen.GetText();

                // Through the IGC variable we issue the broadcast method. IGC is "pre-made",
                // so we don't have to declare it ourselves, just go ahead and use it.
                IGC.SendBroadcastMessage(broadcastChannel, messageOut, TransmissionDistance.TransmissionDistanceMax);

                // To create a listener, we use IGC to access the relevant method.
                // We pass the same tag argument we used for our message.
                IGC.RegisterBroadcastListener(broadcastChannel);
            }
        }
示例#5
0
        private void SwitchHugeLCD(string subPanelNumber)
        {
            IMyTextPanel mainPanel = (IMyTextPanel)GridTerminalSystem.GetBlockWithName($"{hugeLCDName}");
            IMyTextPanel subPanel  = (IMyTextPanel)GridTerminalSystem.GetBlockWithName($"{hugeLCDName} {subPanelNumber}");

            mainPanel.WriteText(subPanel.GetText());
        }
示例#6
0
        //private stringify()
        //private parse()


        /// <summary>
        /// Zapis do pameti
        /// </summary>
        /// <param name="name">Nazev promenne</param>
        /// <param name="value">Hodnota</param>
        public static void Store(string name, float value)
        {
            //definice
            string data = name + "=" + value + "\n";

            string[] rows = Panel.GetText().Trim().Split('\n');
            //sestaveni dat
            for (int i = 0; i < rows.Length; i++)
            {
                if (!rows[i].Contains(name + "="))
                {
                    data += rows[i] + "\n";
                }
            }
            //zapis
            Panel.WriteText(data, false);
        }
 internal void write(string s)
 {
     if (!isDedicated && block.GetText().Contains(s))
     {
         return;
     }
     block.WriteText(s, true);
     block.WriteText("\n", true);
 }
示例#8
0
 public void SaveData()
 {
     userIpPanel = (IMyTextPanel)GridTerminalSystem.GetBlockWithName(lcdSavePanel);
     string[] ips = userIpPanel.GetText().Split(' ');
     for (int i = 0; i < ips.Length; i++)
     {
         knownIp.Add(ips[i]);
         Echo(ips[i]);
     }
 }
示例#9
0
    public void update()
    {
        var sb    = new StringBuilder();
        var lines = display.GetText().Split('\n');

        for (int i = Math.Max(lines.Length - maxLines, 0); i < lines.Length; i++)
        {
            sb.AppendLine(lines[i]);
        }

        display.WriteText(sb);
    }
示例#10
0
        public void Main(string argument, UpdateType updateSource)
        {
            IMyTextPanel lcdWriteScreen = (IMyTextPanel)GridTerminalSystem.GetBlockWithName(lcdName);


            IMyRemoteControl remoteControl = (IMyRemoteControl)GridTerminalSystem.GetBlockWithName(remoteControllerName);

            List <MyWaypointInfo> mywaypoint = new List <MyWaypointInfo>();

            remoteControl.GetWaypointInfo(mywaypoint);

            foreach (MyWaypointInfo item in mywaypoint)
            {
                Echo(item.Coords.ToString());
            }
            wayPoint = mywaypoint[0];

            Echo(wayPoint.ToString());

            // If setupcomplete is false, run Setup method.
            if (!setupcomplete)
            {
                Echo("Running setup.");
                Setup();
            }
            else
            {
                // Create our message. We first make it a string, and then we "box" it as an object type.
                string sendCords = lcdWriteScreen.GetText();

                // Through the IGC variable we issue the broadcast method. IGC is "pre-made",
                // so we don't have to declare it ourselves, just go ahead and use it.
                if (sendCords.ToLower() == "send" && wayPoint.Coords != null)
                {
                    IGC.SendBroadcastMessage(broadcastChannel, wayPoint.ToString(), TransmissionDistance.TransmissionDistanceMax);
                }
                else
                {
                    Echo("Broadcasting failed.");
                }
                // To create a listener, we use IGC to access the relevant method.
                // We pass the same tag argument we used for our message.
                IGC.RegisterBroadcastListener(broadcastChannel);
            }
        }
示例#11
0
        public void Main(string argument, UpdateType updateSource)
        {
            IMyTextPanel Output = GridTerminalSystem.GetBlockWithName("Output") as IMyTextPanel;
            IMyTextPanel Liste  = GridTerminalSystem.GetBlockWithName("Liste") as IMyTextPanel;

            string startIndex;

            if (argument.Length <= 2)
            {
                startIndex = argument;
            }
            else
            {
                startIndex = argument.Substring(2);
            }

            string test = Liste.GetText();

            if (Output != null)
            {
                Echo("Pannel found");
                if (test.Contains(startIndex) == true)
                {
                    Echo("Argument yes");
                    int    index  = test.IndexOf(startIndex);
                    int    index2 = test.Length - index;
                    string result = test.Substring(index, index2);

                    int    endIndex  = result.IndexOf('e') + 2;
                    string endResult = result.Substring(0, endIndex);

                    Output.WriteText(endResult);
                }
                else
                {
                    Echo("Argument no");
                }
            }
            else
            {
                Echo("pannel not found");
            }
        }
示例#12
0
    //Достаём текст из панели. Значение и наименование в одной строке.
    public string GetTextValueInline(string key, string displayName)
    {
        string       value   = "";
        IMyTextPanel lcd     = GridTerminalSystem.GetBlockWithName(displayName) as IMyTextPanel;
        string       lcdText = lcd.GetText();
        string       pattern = key + @":\s\d+";

        System.Text.RegularExpressions.MatchCollection matches;
        matches = System.Text.RegularExpressions.Regex.Matches(lcdText, pattern);
        System.Text.RegularExpressions.Match match = null;

        if (matches.Count > 0)
        {
            //id0
            match = matches[0];

            for (int i = 0; i < match.Groups.Count; i++)
            {
                value += match.Groups[i].ToString();
            }
        }
        return(value);
    }
示例#13
0
        public void Main(string argument, UpdateType updateSource)
        {
            Runtime.UpdateFrequency = UpdateFrequency.Update10;

            IMyTextPanel codeScreen = (IMyTextPanel)GridTerminalSystem.GetBlockWithName("KodePanel");

            IMyTextPanel acceptScreen = (IMyTextPanel)GridTerminalSystem.GetBlockWithName("AcceptScreen");

            IMyDoor myDoor = (IMyDoor)GridTerminalSystem.GetBlockWithName("CommandDoor");

            IMyButtonPanel buttonPanel = (IMyButtonPanel)GridTerminalSystem.GetBlockWithName("Button");

            string inputPassword = codeScreen.GetText();

            if (inputPassword == passcode)
            {
                myDoor.OpenDoor();
                acceptScreen.WriteText("Code Accepted");
            }
            else
            {
                myDoor.CloseDoor();
            }
        }
示例#14
0
    //ТЕХНИЧЕСКИЕ ФУНКЦИИ
    //Достаём текст из панели. Значение и наименование в разных строках.
    public string GetTextValueMultiline(string displayName, string pattern = @"[\S+]\S+")
    {
        string       value   = "";
        IMyTextPanel lcd     = GridTerminalSystem.GetBlockWithName(displayName) as IMyTextPanel;
        string       lcdText = System.Text.RegularExpressions.Regex.Replace(lcd.GetText(), "\r", "");

        lcdText = System.Text.RegularExpressions.Regex.Replace(lcdText, "\n", "");

        System.Text.RegularExpressions.MatchCollection matches;
        matches = System.Text.RegularExpressions.Regex.Matches(lcdText, pattern);
        System.Text.RegularExpressions.Match match = null;

        if (matches.Count > 0)
        {
            //id0
            match = matches[0];

            for (int i = 0; i < match.Groups.Count; i++)
            {
                value += match.Groups[i].ToString();
            }
        }
        return(value);
    }
        public void PreencherLCDPanelOUEcho(int index, ref IMyTextPanel infoLayoutLCD, string assemblerKey, int qtdAssemblersNotFound, ref List <ControlObject> controlObjectList)
        {
            switch (index)
            {
            case 1: {
                if (infoLayoutLCD != null)
                {
                    infoLayoutLCD.WriteText("----- Produção Automática -----", true);
                    infoLayoutLCD.WriteText("-------------------------------", true);
                    infoLayoutLCD.WriteText("", true);
                    infoLayoutLCD.WriteText("", true);
                    infoLayoutLCD.WriteText("O(s) Container(s) Final(is) não existem, por favor verifique o(s) nome(s) do(s) container(s) e tente novamente!", true);
                }
                else
                {
                    myProgram.Echo("----- Produção Automática -----");
                    myProgram.Echo("-------------------------------");
                    myProgram.Echo("");
                    myProgram.Echo("");
                    myProgram.Echo("O(s) Container(s) Final(is) não existem, por favor verifique o(s) nome(s) do(s) container(s) e tente novamente!");
                }
                break;
            }

            case 2: {
                if (infoLayoutLCD != null)
                {
                    if (qtdAssemblersNotFound == 1)
                    {
                        infoLayoutLCD.WriteText("----- Produção Automática -----", true);
                        infoLayoutLCD.WriteText("-------------------------------", true);
                        infoLayoutLCD.WriteText("", true);
                        infoLayoutLCD.WriteText("", true);
                        infoLayoutLCD.WriteText("O assembler: " + assemblerKey + ", não foi encontrado!", true);
                    }
                    else
                    {
                        infoLayoutLCD.WriteText(infoLayoutLCD.GetText(), true);
                        infoLayoutLCD.WriteText("O assembler: " + assemblerKey + ", não foi encontrado!", true);
                    }
                }
                else
                {
                    if (qtdAssemblersNotFound == 1)
                    {
                        myProgram.Echo("----- Produção Automática -----");
                        myProgram.Echo("-------------------------------");
                        myProgram.Echo("");
                        myProgram.Echo("");
                        myProgram.Echo("O assembler: " + assemblerKey + ", não foi encontrado!");
                    }
                    else
                    {
                        myProgram.Echo("O assembler: " + assemblerKey + ", não foi encontrado!");
                    }
                }
                break;
            }

            case 3: {
                // --------------------------------------------------
                // CRIANDO O CABEÇALHO DA TELA
                // --------------------------------------------------
                infoLayoutLCD.WriteText("----- Produção Automática -----", true);
                infoLayoutLCD.WriteText("-------------------------------", true);
                infoLayoutLCD.WriteText("", true);
                infoLayoutLCD.WriteText("", true);
                infoLayoutLCD.WriteText("Componente - Qtd Produzida/Qtd Produzir/Qtd Manter/Assemblers Informados/Assemblers Encontrados", true);

                // --------------------------------------------------
                // CRIANDO O CORPO DA TELA
                // --------------------------------------------------
                StringBuilder linhaLCD = new StringBuilder();
                foreach (var controlObject in controlObjectList)
                {
                    linhaLCD.AppendLine(controlObject.getAssemblerKey() +
                                        controlObject.getComponentsAmountProduced() +
                                        controlObject.getComponentsAmountToProduce() +
                                        controlObject.getComponetAmountKeepStorage() +
                                        controlObject.getFoundAllAssemblers() +
                                        controlObject.getQtdyOfAssemblersFound());
                    infoLayoutLCD.WriteText(linhaLCD, true);
                }
                break;
            }

            default:
                break;
            }
        }
示例#16
0
        public void Main(string argument, UpdateType updateSource)
        {
            Runtime.UpdateFrequency = UpdateFrequency.Update100 | UpdateFrequency.Update10;
            IMyTextPanel   textPanel     = (IMyTextPanel)GridTerminalSystem.GetBlockWithName("LCD");
            IMySensorBlock mySensorBlock = (IMySensorBlock)GridTerminalSystem.GetBlockWithName("EraserSensor");

            if (mySensorBlock.IsActive)
            {
                allmessage = "";
                textPanel.WriteText("");
            }
            // If setupcomplete is false, run Setup method.
            if (!setupcomplete)
            {
                Echo("Running setup.");
                Setup();
            }
            else
            {
                string tag1 = "Channel-1";

                // To create a listener, we use IGC to access the relevant method.
                // We pass the same tag argument we used for our message.
                IGC.RegisterBroadcastListener(tag1);


                // Create a list for broadcast listeners.
                List <IMyBroadcastListener> listeners = new List <IMyBroadcastListener>();

                // The method argument below is the list we wish IGC to populate with all Listeners we've made.
                // Our Listener will be at index 0, since it's the only one we've made so far.
                IGC.GetBroadcastListeners(listeners);

                if (listeners[0].HasPendingMessage)
                {
                    // Let's create a variable for our new message.
                    // Remember, messages have the type MyIGCMessage.
                    MyIGCMessage message = new MyIGCMessage();

                    // Time to get our message from our Listener (at index 0 of our Listener list).
                    // We do this with the following method:
                    message = listeners[0].AcceptMessage();


                    // A message is a struct of 3 variables. To read the actual data,
                    // we access the Data field, convert it to type string (unboxing),
                    // and store it in the variable messagetext.
                    string messagetext = message.Data.ToString();

                    // We can also access the tag that the message was sent with.
                    string messagetag = message.Tag;

                    //Here we store the "address" to the Programmable Block (our friend's) that sent the message.
                    long sender = message.Source;

                    //Do something with the information!
                    Echo("Message received with tag" + messagetag + "\n\r");
                    Echo("from address " + sender.ToString() + ": \n\r");
                    Echo(messagetext);



                    allmessage += $"\n new message \n {messagetext}";
                    textPanel.WriteText(allmessage);
                }
            }

            int textlength = textPanel.GetText().Length;

            if (textlength > 100)
            {
                allmessage = "";
            }
        }
示例#17
0
        public void Main(string argument, UpdateType updateSource)
        {
            //screen that you write text into and send
            IMyTextPanel lcdWritingScreen = (IMyTextPanel)GridTerminalSystem.GetBlockWithName(lcdTextSender);

            //screen that recives
            IMyTextPanel lcdRecieverScreen = (IMyTextPanel)GridTerminalSystem.GetBlockWithName(MessageReciverScreen);



            // If setupcomplete is false, run Setup method.
            if (!setupcomplete)
            {
                Echo("Running setup.");
                Setup();
            }
            else
            {
                // Create our message. We first make it a string, and then we "box" it as an object type.
                string messageOut = lcdWritingScreen.GetText();

                // Through the IGC variable we issue the broadcast method. IGC is "pre-made",
                // so we don't have to declare it ourselves, just go ahead and use it.
                IGC.SendBroadcastMessage(broadcastChannel, messageOut, TransmissionDistance.TransmissionDistanceMax);

                // To create a listener, we use IGC to access the relevant method.
                // We pass the same tag argument we used for our message.
                IGC.RegisterBroadcastListener(broadcastChannel);

                // Create a list for broadcast listeners.
                List <IMyBroadcastListener> listeners = new List <IMyBroadcastListener>();

                // The method argument below is the list we wish IGC to populate with all Listeners we've made.
                // Our Listener will be at index 0, since it's the only one we've made so far.
                IGC.GetBroadcastListeners(listeners);

                if (listeners[0].HasPendingMessage)
                {
                    // Let's create a variable for our new message.
                    // Remember, messages have the type MyIGCMessage.
                    MyIGCMessage message = new MyIGCMessage();

                    // Time to get our message from our Listener (at index 0 of our Listener list).
                    // We do this with the following method:
                    message = listeners[0].AcceptMessage();


                    // A message is a struct of 3 variables. To read the actual data,
                    // we access the Data field, convert it to type string (unboxing),
                    // and store it in the variable messagetext.
                    string messagetext = message.Data.ToString();

                    // We can also access the tag that the message was sent with.
                    string messagetag = message.Tag;

                    //Here we store the "address" to the Programmable Block (our friend's) that sent the message.
                    long sender = message.Source;

                    //Do something with the information!
                    Echo("Message received with tag" + messagetag + "\n\r");
                    Echo("from address " + sender.ToString() + ": \n\r");
                    Echo(messagetext);



                    allmessage += $"\n new message \n {messagetext}";
                    lcdRecieverScreen.WriteText(allmessage);
                }
            }
        }
示例#18
0
        public void Main(string argument, UpdateType updateSource)
        {
            Runtime.UpdateFrequency = UpdateFrequency.Update100 | UpdateFrequency.Update10;
            IMyTextPanel     textPanel     = (IMyTextPanel)GridTerminalSystem.GetBlockWithName(lcdName);
            IMyRemoteControl remoteControl = (IMyRemoteControl)GridTerminalSystem.GetBlockWithName(remoteControllerName);

            // If setupcomplete is false, run Setup method.
            if (!setupcomplete)
            {
                Echo("Running setup.");
                Setup();
            }
            else
            {
                // To create a listener, we use IGC to access the relevant method.
                // We pass the same tag argument we used for our message.
                IGC.RegisterBroadcastListener(broadcastChannel);


                // Create a list for broadcast listeners.
                List <IMyBroadcastListener> listeners = new List <IMyBroadcastListener>();

                // The method argument below is the list we wish IGC to populate with all Listeners we've made.
                // Our Listener will be at index 0, since it's the only one we've made so far.
                IGC.GetBroadcastListeners(listeners);

                if (listeners[0].HasPendingMessage)
                {
                    // Let's create a variable for our new message.
                    // Remember, messages have the type MyIGCMessage.
                    MyIGCMessage message = new MyIGCMessage();

                    // Time to get our message from our Listener (at index 0 of our Listener list).
                    // We do this with the following method:
                    message = listeners[0].AcceptMessage();


                    // A message is a struct of 3 variables. To read the actual data,
                    // we access the Data field, convert it to type string (unboxing),
                    // and store it in the variable messagetext.
                    string messagetext = message.Data.ToString();



                    // We can also access the tag that the message was sent with.
                    string messagetag = message.Tag;

                    //Here we store the "address" to the Programmable Block (our friend's) that sent the message.
                    long sender = message.Source;

                    //Do something with the information!
                    Echo("Message received with tag" + messagetag + "\n\r");
                    Echo("from address " + sender.ToString() + ": \n\r");
                    Echo(messagetext);



                    allmessage += $"\n new message \n {messagetext}\n{messagetext.Split(':')[2]}";
                    textPanel.WriteText(allmessage);

                    List <MyWaypointInfo> myWaypoints = new List <MyWaypointInfo>();

                    string gpsname = messagetext.Split(':')[1];
                    double x       = 0;
                    double y       = 0;
                    double z       = 0;
                    try
                    {
                        x = Convert.ToDouble(messagetext.Split(':')[2]);
                        y = Convert.ToDouble(messagetext.Split(':')[3]);
                        z = Convert.ToDouble(messagetext.Split(':')[4]);
                    }
                    catch (Exception e)
                    {
                        Echo(e.Message);
                    }



                    Echo(messagetext.Split('1')[0]);

                    myWaypoints.Add(new MyWaypointInfo(gpsname, x, y, z));

                    remoteControl.ClearWaypoints();

                    remoteControl.AddWaypoint(myWaypoints[0]);

                    remoteControl.SetCollisionAvoidance(true);

                    remoteControl.SetAutoPilotEnabled(true);
                }
            }

            int textlength = textPanel.GetText().Length;

            if (textlength > 100)
            {
                allmessage = "";
            }
        }
示例#19
0
        public void Main(string argumentString = "CHECK")
        {
            var arguments = argumentString.Split(' ');
            var argument  = arguments[0] == "" ? "CHECK" : arguments[0];

            Echo((executionCounter++).ToString());

            if (argument != "CHECK" || _state != _previousState)
            {
                // Keep previous output on check
                _output.Clear();
            }
            _previousState = _state;

            if (argument == "PARSE")
            {
                Runtime.UpdateFrequency = UpdateFrequency.None;
                MyIniParseResult result;
                if (!_ini.TryParse(Me.CustomData, out result))
                {
                    Echo($"CustomData parsing error: \nLine {result.LineNo}");
                    return;
                }

                var calculatorAssemblerName = _ini.Get("general", "CalculatorAssembler").ToString(_calculatorAssemblerName);
                var lcdBlueprintInfoName    = _ini.Get("general", "LcdBlueprintInfo").ToString(_lcdBlueprintInfoName);
                var lcdComponentStatusName  = _ini.Get("general", "LcdComponentStatus").ToString(_lcdComponentStatusName);
                var lcdWeldStatusName       = _ini.Get("general", "LcdWeldStatus").ToString(_lcdWeldStatusName);
                var pistonGroupName         = _ini.Get("general", "PistonGroup").ToString(_pistonGroupName);
                var productionAssemblerName = _ini.Get("general", "ProductionAssembler").ToString(_productionAssemblerName);
                var projectors         = _ini.Get("general", "Projectors").ToString("Large:WeldWallLargeProjector");
                var retractVelocity    = _ini.Get("general", "RetractVelocity").ToDouble(_retractVelocity);
                var weldEndedTimerName = _ini.Get("general", "WeldEndedTimer").ToString(_weldEndedTimerName);
                var weldReadyTimerName = _ini.Get("general", "WeldReadyTimer").ToString(_weldReadyTimerName);
                var weldVelocity       = _ini.Get("general", "WeldVelocity").ToDouble(_weldVelocity);
                var welderGroupName    = _ini.Get("general", "WelderGroup").ToString(_welderGroupName);

                var lookup = new LookupHelper {
                    GridTerminalSystem = GridTerminalSystem,
                };

                _calculatorAssembler = lookup.GetBlockWithName <IMyAssembler>(calculatorAssemblerName, true);
                _lcdBlueprintInfo    = lookup.GetBlockWithName <IMyTextPanel>(lcdBlueprintInfoName, true);
                _lcdComponentStatus  = lookup.GetBlockWithName <IMyTextPanel>(lcdComponentStatusName, true);
                _lcdWeldStatus       = lookup.GetBlockWithName <IMyTextPanel>(lcdWeldStatusName);
                _pistons             = lookup.GetBlocksInGroup <IMyExtendedPistonBase>(pistonGroupName, true);
                _productionAssembler = lookup.GetBlockWithName <IMyAssembler>(productionAssemblerName, true);
                _weldEndedTimer      = lookup.GetBlockWithName <IMyTimerBlock>(weldEndedTimerName);
                _weldReadyTimer      = lookup.GetBlockWithName <IMyTimerBlock>(weldReadyTimerName);
                _welders             = lookup.GetBlocksInGroup <IMyShipWelder>(welderGroupName, true);

                _projectors = projectors
                              .Split(' ')
                              .Select(part => part.Split(':'))
                              .ToDictionary(split => split[0], split => lookup.GetBlockWithName <IMyProjector>(split[1], true));

                var firstProjectorEntry = _projectors.FirstOrDefault();
                _projector = firstProjectorEntry.Value;

                if (_projector == null)
                {
                    Echo("No projector found");
                    return;
                }
                else
                {
                    _projector.Enabled = true;
                    _projectorName     = firstProjectorEntry.Key;
                }

                ExtractBlueprints();
                Runtime.UpdateFrequency = UpdateFrequency.Update100;
            }

            if (_projector == null)
            {
                Echo("No projector found");
                return;
            }

            var currentBpId = _state == "Preparing" || _state == "Welding"
                ? _previousBlueprint.ID
                : GetProjectorBlueprintId(_projector);
            var currentBlueprint = _blueprints.GetValueOrDefault(currentBpId);

            if (currentBlueprint != _previousBlueprint && currentBlueprint != null)
            {
                _state = "CheckBlueprint";

                _projector.ProjectionOffset   = currentBlueprint.ProjectionOffset;
                _projector.ProjectionRotation = currentBlueprint.ProjectionRotation;
                _projector.UpdateOffsetAndRotation();

                UpdateComponentList(currentBlueprint);
            }

            _previousBlueprint = currentBlueprint;

            switch (argument)
            {
            case "CHECK":
                if (currentBlueprint == null)
                {
                    break;
                }
                if (_state == "Preparing")
                {
                    if (_lcdComponentStatus.GetText().Trim() == "")
                    {
                        if (_weldReadyTimer == null)
                        {
                            Main("Weld");
                        }
                        else
                        {
                            _weldReadyTimer.ApplyAction("TriggerNow");
                        }
                    }
                }
                else if (_state == "Welding")
                {
                    if (_pistons.TrueForAll(p => p.MaxLimit == p.CurrentPosition))
                    {
                        _welders.ForEach(w => w.Enabled = false);
                        _weldEndedTimer?.ApplyAction("TriggerNow");
                        _state = "CheckBlueprint";
                    }
                }

                var buildProgress = _projector.DetailedInfo.Substring(_projector.DetailedInfo.IndexOf("Build progress"));
                if (_lcdWeldStatus != null)
                {
                    _lcdWeldStatus.CustomData = Utils.ToMmasterLcd(buildProgress);
                }

                break;

            case "PREPARE":
                if (currentBlueprint == null)
                {
                    _output.Add("Can't prepare when no blueprint is loaded");
                    break;
                }

                UpdateComponentList(currentBlueprint);
                AssembleMissing();
                _output.Add("Assembly of missing items in progress");
                _state = "Preparing";

                break;

            case "SAVE_OFFSET":
                if (currentBlueprint == null)
                {
                    currentBlueprint = new BlueprintInfo()
                    {
                        ID   = currentBpId,
                        Name = currentBpId,
                    };
                    UpdateComponentList(currentBlueprint);
                    _blueprints.Add(currentBpId, currentBlueprint);
                }

                currentBlueprint.ProjectionOffset   = _projector.ProjectionOffset;
                currentBlueprint.ProjectionRotation = _projector.ProjectionRotation;
                currentBlueprint.Save(_ini);
                Me.CustomData = _ini.ToString();

                break;

            case "SET_ACTIVE":
                IMyProjector newActiveProjector = _projectors.GetValueOrDefault(arguments[1]);

                if (newActiveProjector == null)
                {
                    _output.Add($"Projector {arguments[1]} not found");
                }
                else
                {
                    _projectors.Values.ToList().ForEach(projector => projector.Enabled = false);
                    _projector         = newActiveProjector;
                    _projectorName     = arguments[1];
                    _projector.Enabled = true;
                }

                break;

            case "STOP":
                Stop();
                break;

            case "RETRACT":
                _pistons.ForEach(p => p.Enabled = true);
                DistributePistonVelocity(-_retractVelocity);
                break;

            case "WELD":
                if (currentBlueprint == null)
                {
                    _output.Add("Can't start welding when no blueprint is loaded");
                    break;
                }

                _welders.ForEach(w => w.Enabled = true);
                _pistons.ForEach(p => p.Enabled = true);
                DistributePistonVelocity(_weldVelocity);

                _state = "Welding";
                break;
            }


            _lcdBlueprintInfo.WriteText($@"
{(currentBlueprint == null ? "Unknown blueprint" : (currentBlueprint.Name ?? "Unnamed blueprint"))}
Blueprint ID: {currentBpId}
State: {_state}
Active projector: {_projectorName}

{String.Join("\n", _output.ToArray())}
".Trim());
        }