public void Main(string argumentString)
        {
            _output.Clear();
            var arguments = argumentString.ToUpper().Split(';');

            _output.Add($"Mode: {(_isFast ? "Fast" : "Slow")}");

            switch (arguments[0])
            {
            case "":
                foreach (var entry in _spinners)
                {
                    var spinner         = entry.Value;
                    var cycleStatus     = spinner.CalculateCycleStatus();
                    var maxPosition     = spinner.Pistons.Sum(piston => piston.HighestPosition);
                    var currentPosition = spinner.Pistons.Sum(piston => piston.CurrentPosition);

                    _output.Add($"{entry.Key}:");
                    _output.Add($"  {Math.Round(currentPosition, 2)} m/{Math.Round(maxPosition, 2)} m");
                    _output.Add($"  Change in angle: {Math.Round(cycleStatus.ChangeInAngle)}°");

                    if (!cycleStatus.CycleFinished)
                    {
                        continue;
                    }

                    if (spinner.Pistons.All(piston => piston.CurrentPosition == piston.HighestPosition))
                    {
                        spinner.Rotor.Enabled = false;
                        spinner.Drills.ForEach(drill => drill.Enabled = false);
                    }

                    var extendTotalBy = _isFast ? _pistonExtendFast : _pistonExtendSlow;

                    foreach (var piston in spinner.Pistons)
                    {
                        var extendBy = Math.Min(piston.HighestPosition - piston.CurrentPosition, extendTotalBy);
                        extendTotalBy  -= extendBy;
                        piston.MaxLimit = piston.CurrentPosition + extendBy;
                    }
                }
                ;
                break;

            case "LOWER":
                foreach (var spinner in _spinners.Values)
                {
                    spinner.Rotor.RotorLock = true;
                    spinner.Pistons.ForEach(piston => {
                        piston.MaxLimit = piston.HighestPosition;
                        piston.Velocity = _pistonLowerSpeed / spinner.Pistons.Count();
                    });
                }

                break;

            case "PARSE":
                MyIniParseResult result;
                if (!_ini.TryParse(Me.CustomData, out result))
                {
                    _output.Add($"CustomData parsing error: \nLine {result.LineNo}\nError: {result.Error}");
                    return;
                }

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

                _pistonLowerSpeed = (float)_ini
                                    .Get("general", "PistonLowerSpeed")
                                    .ToDouble(_pistonLowerSpeed);
                _drillSpeedMetersPerSecond = (float)_ini
                                             .Get("general", "DrillSpeedMeterPerSecond")
                                             .ToDouble(_drillSpeedMetersPerSecond);

                var lcdInfoName = _ini.Get("general", "LcdInfo").ToString(_lcdInfoName);
                _lcdInfo = lookup.GetBlockWithName <IMyTextPanel>(lcdInfoName);

                _spinners = new Dictionary <string, SpinnerInfo>();
                var sections = new List <string>();
                _ini.GetSections(sections);
                sections.ForEach(section => {
                    if (section.ToLower() == "general")
                    {
                        return;
                    }

                    var spinnerInfo = SpinnerInfo.FromIni(_ini, section, lookup);
                    _spinners.Add(section, spinnerInfo);
                });

                break;

            case "PERSIST_PISTON_POSITION":
                foreach (var entry in _spinners)
                {
                    entry.Value.Pistons.ForEach(piston => piston.MaxLimit = piston.CurrentPosition);
                }

                break;

            case "RETRACT":
                foreach (var spinner in _spinners.Values)
                {
                    var velocity = -3f / spinner.Pistons.Count;
                    spinner.Pistons.ForEach(piston => piston.Velocity = velocity);
                }

                break;

            case "START":
                foreach (var spinner in _spinners.Values)
                {
                    spinner.Drills.ForEach(drill => drill.Enabled = true);
                    spinner.Pistons.ForEach(piston => {
                        piston.MaxLimit = piston.CurrentPosition;
                        piston.Enabled  = true;
                        piston.Velocity = 0.5f;
                    });
                    spinner.Rotor.RotorLock         = false;
                    spinner.Rotor.Enabled           = true;
                    spinner.Rotor.TargetVelocityRad = spinner.GetTargetVelocityRotorRad(_isFast, _drillSpeedMetersPerSecond);
                }

                Runtime.UpdateFrequency = UpdateFrequency.Update100;

                break;

            case "STOP":
                foreach (var spinner in _spinners.Values)
                {
                    spinner.Rotor.Enabled = false;
                    spinner.Drills.ForEach(drill => drill.Enabled = false);
                }

                Runtime.UpdateFrequency = UpdateFrequency.None;

                break;

            case "STOP_EMERGENCY":
                foreach (var spinner in _spinners.Values)
                {
                    spinner.Rotor.Enabled = false;
                    spinner.Drills.ForEach(drill => drill.Enabled    = false);
                    spinner.Pistons.ForEach(piston => piston.Enabled = false);
                }

                Runtime.UpdateFrequency = UpdateFrequency.None;

                break;

            case "TOGGLE_SPEED":
                _isFast = !_isFast;

                foreach (var spinner in _spinners.Values)
                {
                    spinner.Drills.ForEach(drill => drill.Enabled = !_isFast);
                    spinner.Rotor.TargetVelocityRad = spinner.GetTargetVelocityRotorRad(_isFast, _drillSpeedMetersPerSecond);
                }

                break;
            }

            _output.ForEach(line => Echo(line));
            _lcdInfo?.WriteText(String.Join("\n", _output.ToArray()));
        }
Example #2
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());
        }
        public void Main(string input, UpdateType updateSource)
        {
            input = input == "" ? "OBSERVE" : input;

            if (input == "RESTART" || state == null)
            {
                var config = new Config(Me.CustomData);

                config.Set(ref closeConnectorName, "closeConnectorName");
                config.Set(ref grabberGroupName, "grabberGroupName");
                config.Set(ref grabberVelocity, "grabberVelocity");
                config.Set(ref grinderGroupName, "grinderGroupName");
                config.Set(ref namePrefix, "namePrefix");
                config.Set(ref openConnectorName, "openConnectorName");
                config.Set(ref rotorGroupName, "rotorGroupName");
                config.Set(ref rotorVelocity, "rotorVelocity");
                config.Set(ref welderGroupName, "welderGroupName");

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

                // init
                accessCodes = new List <string>(config.Get("accessCodes", "").Split(','));

                closeConnector         = lookup.GetBlockWithName <IMyShipConnector>(closeConnectorName);
                closeConnector.Enabled = true;

                openConnector         = lookup.GetBlockWithName <IMyShipConnector>(openConnectorName);
                openConnector.Enabled = true;

                grinders = lookup.GetBlocksInGroup <IMyShipGrinder>(grinderGroupName);
                grinders.ForEach(grinder => grinder.Enabled = false);
                welders = lookup.GetBlocksInGroup <IMyShipWelder>(welderGroupName);
                welders.ForEach(welder => welder.Enabled = false);

                rotorController = new RotorController(lookup.GetBlocksInGroup <IMyMotorStator>(rotorGroupName), rotorVelocity);
                rotorController.Stop();
                grabberController = new RotorController(lookup.GetBlocksInGroup <IMyMotorStator>(grabberGroupName), grabberVelocity);
                grabberController.Go("BACKWARD"); // Open grabber

                state = "UNKNOWN";
                Runtime.UpdateFrequency = UpdateFrequency.Update100;
                Observe();
            }

            if (input == "radioCommand" && broadcastListener.HasPendingMessage)
            {
                var message = broadcastListener.AcceptMessage();

                while (broadcastListener.HasPendingMessage)
                {
                    message = broadcastListener.AcceptMessage();
                }

                var data = BlastDoorRadioMessage.Deserialize(message.Data as string);

                if (!accessCodes.Contains(data.AccessCode))
                {
                    return;
                }

                input = data.Command;
            }

            if (input == "OBSERVE")
            {
                Observe();
            }
            else if (input == "CLOSE" && state != "CLOSING" && state != "CLOSED")
            {
                openConnector.Enabled  = false;
                closeConnector.Enabled = true;
                grinders.ForEach(grinder => grinder.Enabled = false);
                welders.ForEach(welder => welder.Enabled    = true);
                rotorController.Go("FORWARD");
                grabberController.Go("FORWARD"); // Grab
                state = "CLOSING";
                Runtime.UpdateFrequency = UpdateFrequency.Update100;
            }
            else if (input == "OPEN" && state != "OPENING" && state != "OPEN")
            {
                openConnector.Enabled  = true;
                closeConnector.Enabled = false;
                welders.ForEach(welder => welder.Enabled    = false);
                grinders.ForEach(grinder => grinder.Enabled = true);
                rotorController.Go("BACKWARD");
                grabberController.Go("FORWARD"); // Grab
                state = "OPENING";
                Runtime.UpdateFrequency = UpdateFrequency.Update100;
            }
        }