First commit
authorGreg Burri <greg.burri@gmail.com>
Fri, 8 Sep 2023 21:45:14 +0000 (23:45 +0200)
committerGreg Burri <greg.burri@gmail.com>
Fri, 8 Sep 2023 21:45:14 +0000 (23:45 +0200)
24 files changed:
.gitignore [new file with mode: 0644]
AutoPilot/AutoPilot.csproj [new file with mode: 0644]
AutoPilot/MDK/Bootstrapper.cs [new file with mode: 0644]
AutoPilot/MDK/MDK.options.props [new file with mode: 0644]
AutoPilot/MDK/MDK.paths.props [new file with mode: 0644]
AutoPilot/Program.cs [new file with mode: 0644]
AutoPilot/thumb.png [new file with mode: 0644]
BaseMiner/BaseApp.csproj [new file with mode: 0644]
BaseMiner/MDK/Bootstrapper.cs [new file with mode: 0644]
BaseMiner/MDK/MDK.options.props [new file with mode: 0644]
BaseMiner/MDK/MDK.paths.props [new file with mode: 0644]
BaseMiner/Program.cs [new file with mode: 0644]
MiningRover/Instructions.readme [new file with mode: 0644]
MiningRover/MDK/Bootstrapper.cs [new file with mode: 0644]
MiningRover/MDK/MDK.options.props [new file with mode: 0644]
MiningRover/MDK/MDK.paths.props [new file with mode: 0644]
MiningRover/MiningRover.csproj [new file with mode: 0644]
MiningRover/Program.cs [new file with mode: 0644]
MiningRover/thumb.png [new file with mode: 0644]
SECommon/Output.cs [new file with mode: 0644]
SECommon/SECommon.projitems [new file with mode: 0644]
SECommon/SECommon.shproj [new file with mode: 0644]
SEScripts.sln [new file with mode: 0644]
thumb.png [new file with mode: 0644]

diff --git a/.gitignore b/.gitignore
new file mode 100644 (file)
index 0000000..e623aa7
--- /dev/null
@@ -0,0 +1,135 @@
+## Ignore Visual Studio temporary files, build results, and
+## files generated by popular Visual Studio add-ons.
+
+.vs
+
+# User-specific files
+*.suo
+*.user
+*.sln.docstates
+
+# Build results
+
+[Dd]ebug/
+[Rr]elease/
+x64/
+[Bb]in/
+[Oo]bj/
+
+# MSTest test Results
+[Tt]est[Rr]esult*/
+[Bb]uild[Ll]og.*
+
+*_i.c
+*_p.c
+*_i.h
+*.ilk
+*.meta
+*.obj
+*.pch
+*.pdb
+*.pgc
+*.pgd
+*.rsp
+*.sbr
+*.tlb
+*.tli
+*.tlh
+*.tmp
+*.tmp_proj
+*.log
+*.vspscc
+*.vssscc
+.builds
+*.pidb
+*.log
+*.svclog
+*.scc
+
+# Visual C++ cache files
+ipch/
+*.aps
+*.ncb
+*.opensdf
+*.sdf
+*.cachefile
+
+# Visual Studio profiler
+*.psess
+*.vsp
+*.vspx
+
+# Guidance Automation Toolkit
+*.gpState
+
+# ReSharper is a .NET coding add-in
+_ReSharper*/
+*.[Rr]e[Ss]harper
+*.DotSettings.user
+
+# Click-Once directory
+publish/
+
+# Publish Web Output
+*.Publish.xml
+*.pubxml
+*.azurePubxml
+
+# NuGet Packages Directory
+## TODO: If you have NuGet Package Restore enabled, uncomment the next line
+packages/
+## TODO: If the tool you use requires repositories.config, also uncomment the next line
+!packages/repositories.config
+
+# Windows Azure Build Output
+csx/
+*.build.csdef
+
+# Windows Store app package directory
+AppPackages/
+
+# Others
+sql/
+*.Cache
+ClientBin/
+[Ss]tyle[Cc]op.*
+![Ss]tyle[Cc]op.targets
+~$*
+*~
+*.dbmdl
+*.[Pp]ublish.xml
+
+*.publishsettings
+
+# RIA/Silverlight projects
+Generated_Code/
+
+# Backup & report files from converting an old project file to a newer
+# Visual Studio version. Backup files are not needed, because we have git ;-)
+_UpgradeReport_Files/
+Backup*/
+UpgradeLog*.XML
+UpgradeLog*.htm
+
+# SQL Server files
+App_Data/*.mdf
+App_Data/*.ldf
+
+# =========================
+# Windows detritus
+# =========================
+
+# Windows image file caches
+Thumbs.db
+ehthumbs.db
+
+# Folder config file
+Desktop.ini
+
+# Recycle Bin used on file shares
+$RECYCLE.BIN/
+
+# Mac desktop service store files
+.DS_Store
+
+_NCrunch*
diff --git a/AutoPilot/AutoPilot.csproj b/AutoPilot/AutoPilot.csproj
new file mode 100644 (file)
index 0000000..23f7ce1
--- /dev/null
@@ -0,0 +1,59 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
+  <PropertyGroup>
+    <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
+    <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
+    <ProjectGuid>{141E1804-F644-48F8-A3D8-BEFEEE66ECBA}</ProjectGuid>
+    <OutputType>Exe</OutputType>
+    <RootNamespace>IngameScript</RootNamespace>
+    <AssemblyName>AutoPilot</AssemblyName>
+    <TargetFrameworkVersion>v4.8</TargetFrameworkVersion>
+    <FileAlignment>512</FileAlignment>
+    <AutoGenerateBindingRedirects>true</AutoGenerateBindingRedirects>
+    <TargetFrameworkProfile />
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|x64'">
+    <DebugSymbols>true</DebugSymbols>
+    <OutputPath>bin\</OutputPath>
+    <DefineConstants>DEBUG;TRACE</DefineConstants>
+    <DebugType>full</DebugType>
+    <PlatformTarget>x64</PlatformTarget>
+    <ErrorReport>prompt</ErrorReport>
+    <CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
+    <Prefer32Bit>true</Prefer32Bit>
+    <LangVersion>6</LangVersion>
+  </PropertyGroup>
+  <ItemGroup>
+    <Reference Include="netstandard" />
+    <Reference Include="System" />
+    <Reference Include="System.Core" />
+    <Reference Include="System.Xml.Linq" />
+    <Reference Include="System.Data.DataSetExtensions" />
+    <Reference Include="Microsoft.CSharp" />
+    <Reference Include="System.Data" />
+    <Reference Include="System.Net.Http" />
+    <Reference Include="System.Xml" />
+  </ItemGroup>
+  <Import Project="MDK/MDK.options.props" />
+  <Import Project="MDK/MDK.paths.props" Condition="exists('MDK/MDK.paths.props')" />
+  <ItemGroup>
+    <Compile Include="MDK\Bootstrapper.cs" />
+    <AdditionalFiles Include="MDK\MDK.options.props">
+      <CopyToOutputDirectory>Always</CopyToOutputDirectory>
+    </AdditionalFiles>
+    <AdditionalFiles Include="MDK\MDK.paths.props">
+      <CopyToOutputDirectory>Always</CopyToOutputDirectory>
+    </AdditionalFiles>
+    <Compile Include="Program.cs" />
+    <AdditionalFiles Include="Instructions.readme" />
+    <AdditionalFiles Include="thumb.png" />
+    <AdditionalFiles Include="MDK\whitelist.cache" />
+  </ItemGroup>
+  <Import Project="..\SECommon\SECommon.projitems" Label="Shared" />
+  <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
+  <Target Name="AfterBuild">
+    <Copy SourceFiles="MDK\MDK.options.props" DestinationFolder="$(TargetDir)\MDK" />
+    <Copy SourceFiles="MDK\MDK.paths.props" DestinationFolder="$(TargetDir)\MDK" />
+  </Target>
+</Project>
\ No newline at end of file
diff --git a/AutoPilot/MDK/Bootstrapper.cs b/AutoPilot/MDK/Bootstrapper.cs
new file mode 100644 (file)
index 0000000..dd86886
--- /dev/null
@@ -0,0 +1,27 @@
+using Malware.MDKUtilities;
+
+namespace IngameScript.MDK
+{
+    public class TestBootstrapper
+    {
+        // All the files in this folder, as well as all files containing the file ".debug.", will be excluded
+        // from the build process. You can use this to create utilites for testing your scripts directly in 
+        // Visual Studio.
+
+        static TestBootstrapper()
+        {
+            // Initialize the MDK utility framework
+            MDKUtilityFramework.Load();
+        }
+
+        public static void Main()
+        {
+            // In order for your program to actually run, you will need to provide a mockup of all the facilities 
+            // your script uses from the game, since they're not available outside of the game.
+
+            // Create and configure the desired program.
+            var program = MDKFactory.CreateProgram<Program>();
+            MDKFactory.Run(program);
+        }
+    }
+}
\ No newline at end of file
diff --git a/AutoPilot/MDK/MDK.options.props b/AutoPilot/MDK/MDK.options.props
new file mode 100644 (file)
index 0000000..0a291ca
--- /dev/null
@@ -0,0 +1,18 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <PropertyGroup>
+    <!-- 
+    Contains basic settings that should be included in code repositories
+    -->
+    <MDKVersion>1.5.17</MDKVersion>
+    <MDKTrimTypes>
+      <Enabled>no</Enabled>
+    </MDKTrimTypes>
+    <MDKMinify>
+      <Level>None</Level>
+    </MDKMinify>
+    <MDKIgnore>
+      <Folder>mdk</Folder>
+    </MDKIgnore>
+  </PropertyGroup>
+</Project>
\ No newline at end of file
diff --git a/AutoPilot/MDK/MDK.paths.props b/AutoPilot/MDK/MDK.paths.props
new file mode 100644 (file)
index 0000000..a0f8f66
--- /dev/null
@@ -0,0 +1,81 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <PropertyGroup>
+    <!-- 
+    You can safely exclude this file from code repositories and use different 
+    user settings per machine.
+    -->
+    <MDKVersion>1.5.17</MDKVersion>
+    <MDKUseGameBinPath>no</MDKUseGameBinPath>
+    <MDKGameBinPath>G:\SteamLibrary\SteamApps\common\SpaceEngineers\Bin64</MDKGameBinPath>
+    <MDKInstallPath>c:\users\lyssmetal\appdata\local\microsoft\visualstudio\17.0_6c02a30d\extensions\bnnd2422.thc</MDKInstallPath>
+    <MDKOutputPath>C:\Users\LyssMetal\AppData\Roaming\SpaceEngineers\IngameScripts\local</MDKOutputPath>
+  </PropertyGroup>
+  <ItemGroup>
+    <Reference Include="System.Collections.Immutable">
+      <HintPath>$(MDKGameBinPath)\System.Collections.Immutable.dll</HintPath>
+      <Private>false</Private>
+    </Reference>
+    <Reference Include="Sandbox.Common">
+      <HintPath>$(MDKGameBinPath)\Sandbox.Common.dll</HintPath>
+      <Private>False</Private>
+    </Reference>
+    <Reference Include="Sandbox.Game">
+      <HintPath>$(MDKGameBinPath)\Sandbox.Game.dll</HintPath>
+      <Private>False</Private>
+    </Reference>
+    <Reference Include="Sandbox.Graphics">
+      <HintPath>$(MDKGameBinPath)\Sandbox.Graphics.dll</HintPath>
+      <Private>False</Private>
+    </Reference>
+    <Reference Include="SpaceEngineers.Game">
+      <HintPath>$(MDKGameBinPath)\SpaceEngineers.Game.dll</HintPath>
+      <Private>False</Private>
+    </Reference>
+    <Reference Include="SpaceEngineers.ObjectBuilders">
+      <HintPath>$(MDKGameBinPath)\SpaceEngineers.ObjectBuilders.dll</HintPath>
+      <Private>False</Private>
+    </Reference>
+    <Reference Include="VRage">
+      <HintPath>$(MDKGameBinPath)\VRage.dll</HintPath>
+      <Private>False</Private>
+    </Reference>
+    <Reference Include="VRage.Audio">
+      <HintPath>$(MDKGameBinPath)\VRage.Audio.dll</HintPath>
+      <Private>False</Private>
+    </Reference>
+    <Reference Include="VRage.Game">
+      <HintPath>$(MDKGameBinPath)\VRage.Game.dll</HintPath>
+      <Private>False</Private>
+    </Reference>
+    <Reference Include="VRage.Input">
+      <HintPath>$(MDKGameBinPath)\VRage.Input.dll</HintPath>
+      <Private>False</Private>
+    </Reference>
+    <Reference Include="VRage.Library">
+      <HintPath>$(MDKGameBinPath)\VRage.Library.dll</HintPath>
+      <Private>False</Private>
+    </Reference>
+    <Reference Include="VRage.Math">
+      <HintPath>$(MDKGameBinPath)\VRage.Math.dll</HintPath>
+      <Private>False</Private>
+    </Reference>
+    <Reference Include="VRage.Render">
+      <HintPath>$(MDKGameBinPath)\VRage.Render.dll</HintPath>
+      <Private>False</Private>
+    </Reference>
+    <Reference Include="VRage.Render11">
+      <HintPath>$(MDKGameBinPath)\VRage.Render11.dll</HintPath>
+      <Private>False</Private>
+    </Reference>
+    <Reference Include="VRage.Scripting">
+      <HintPath>$(MDKGameBinPath)\VRage.Scripting.dll</HintPath>
+      <Private>False</Private>
+    </Reference>
+    <Reference Include="MDKUtilities">
+      <HintPath>$(MDKInstallPath)\MDKUtilities.dll</HintPath>
+      <Private>True</Private>
+    </Reference>
+    <Analyzer Include="$(MDKInstallPath)\Analyzers\MDKAnalyzer.dll" />
+  </ItemGroup>
+</Project>
\ No newline at end of file
diff --git a/AutoPilot/Program.cs b/AutoPilot/Program.cs
new file mode 100644 (file)
index 0000000..5f5eae9
--- /dev/null
@@ -0,0 +1,283 @@
+/*
+ * API index: https://github.com/malware-dev/MDK-SE/wiki/Api-Index
+ * Vector transformation: https://github.com/malware-dev/MDK-SE/wiki/Vector-Transformations-with-World-Matrices
+ * How to get rotation/position: https://forum.keenswh.com/threads/how-do-i-get-the-world-position-and-rotation-of-a-ship.7363867/
+ * 
+ */
+
+using Sandbox.Game.EntityComponents;
+using Sandbox.ModAPI.Ingame;
+using Sandbox.ModAPI.Interfaces;
+
+using SpaceEngineers.Game.ModAPI.Ingame;
+
+using System;
+using System.Collections;
+using System.Collections.Generic;
+using System.Collections.Immutable;
+using System.Linq;
+using System.Text;
+
+using VRage;
+using VRage.Collections;
+using VRage.Game;
+using VRage.Game.Components;
+using VRage.Game.GUI.TextPanel;
+using VRage.Game.ModAPI.Ingame;
+using VRage.Game.ModAPI.Ingame.Utilities;
+using VRage.Game.ObjectBuilders.Definitions;
+
+using VRageMath;
+using VRageMath.Spatial;
+
+namespace IngameScript
+{
+    partial class Program : MyGridProgram
+    {
+        const int CONSOLE_NB_LINES = 9;
+        const float MAX_SPEED = 0.15f; // In rad per second.
+        const int NB_OF_GYRO = 1000; // To limit the number of gyros set to overdrive.
+
+        enum State
+        {
+            NORMAL, // Normal state: Manual commands.
+            AUTO_STABILIZATION,
+            AUTO_DOCKING,
+        }
+
+        State state = State.NORMAL;
+
+        readonly Output output;
+
+        IMyRemoteControl remoteController;
+        IMyCubeGrid grid;
+        readonly List<IMyGyro> gyros = new List<IMyGyro>();
+
+        IMyBroadcastListener connnectorMinerPositionListener;
+        MatrixD connectorMinerPosition;
+
+        public Program()
+        {
+            this.grid = this.Me.CubeGrid;
+
+            var cockpits = new List<IMyCockpit>();
+            this.GridTerminalSystem.GetBlocksOfType(cockpits);
+            IMyCockpit cockpit = null;
+            foreach (var c in cockpits)
+            {
+                if (c.CubeGrid == this.grid)
+                {
+                    cockpit = c;
+                    break;
+                }
+            }
+
+            if (cockpit == null)
+            {
+                this.Echo("Can't find a cockpit");
+                return;
+            }
+
+            this.output = new Output(cockpit, CONSOLE_NB_LINES);
+
+            this.output.Print("Intializing navigation control...");
+
+            var remoteControls = new List<IMyRemoteControl>();
+            this.GridTerminalSystem.GetBlocksOfType(remoteControls);
+            foreach (var rc in remoteControls)
+            {
+                if (rc.CubeGrid == this.grid)
+                {
+                    this.remoteController = rc;
+                    break;
+                }
+            }
+
+            this.GridTerminalSystem.GetBlocksOfType(
+                this.gyros,
+                (IMyGyro gyro) => gyro.CubeGrid == this.grid
+            );
+
+            if (this.remoteController == null)
+            {
+                this.output.Print("Can't find a remote controller");
+                return;
+            }
+
+
+            this.connnectorMinerPositionListener = this.IGC.RegisterBroadcastListener("POSITION_CONNECTOR_MINER");
+
+            /*
+            var sensor = this.GridTerminalSystem.GetBlockWithName("Sensor") as IMySensorBlock;
+            var entities = new List<MyDetectedEntityInfo>();
+            sensor.DetectedEntities(entities);
+            foreach (var entity in entities)
+            {
+                entity.
+                this.output.Print(entity.Name);
+            }*/
+
+            this.Runtime.UpdateFrequency = UpdateFrequency.Update10;
+
+            this.output.Print("Navigation control initializing complete");
+        }
+
+        public void Save()
+        {
+        }
+
+        void UpdateStateAutoStabilization()
+        {
+            //var pos = this.remoteController.Position;
+            var gravity = this.remoteController.GetNaturalGravity().Normalized();
+
+            if (!Vector3D.IsZero(gravity))
+            {
+                var worldMatrix = this.remoteController.WorldMatrix;
+                var up = worldMatrix.Up;
+                var forward = worldMatrix.Forward;
+                var left = worldMatrix.Left;
+
+                //this.Print(gravity.ToString());
+                //gravity.ToString();
+                this.output.Display(
+                    $"Gravity: {gravity.ToString("f2")}\n" +
+                    $"Up: {up.ToString("f2")}\n" +
+                    $"Foward: {forward.ToString("f2")}\n" +
+                    $"Left: {left.ToString("f2")}\n",
+                    1
+                );
+
+                var alpha = (float)Math.Asin(up.Dot(gravity));
+                var beta = (float)Math.Asin(left.Dot(gravity));
+
+                this.output.Display(
+                    $"Alpha: {alpha}\n" +
+                    $"Beta: {beta}\n" +
+                    $"Is under control: {this.remoteController.IsUnderControl}",
+                    2
+                );
+
+                for (int i = 0; i < NB_OF_GYRO && i < this.gyros.Count; i++)
+                {
+                    var gyro = this.gyros[i];
+                    gyro.Pitch = MathHelper.Clamp(-alpha, -MAX_SPEED, MAX_SPEED);
+                    gyro.Roll = MathHelper.Clamp(beta, -MAX_SPEED, MAX_SPEED);
+                }
+            }
+        }
+
+        void UpdateStateAutoDocking()
+        {
+            if (this.connnectorMinerPositionListener.HasPendingMessage)
+                this.connectorMinerPosition = this.connnectorMinerPositionListener.AcceptMessage().As<MatrixD>();
+
+            if (this.connectorMinerPosition.IsValid())
+            {
+                this.output.Display($"Connector position:\n{this.connectorMinerPosition}", 3);
+            }
+            else
+            {
+                this.output.Display($"NOPE", 3);
+            }
+        }
+
+        void UpdateState()
+        {
+            switch (this.state)
+            {
+                case State.AUTO_STABILIZATION:
+                    this.UpdateStateAutoStabilization();
+                    break;
+                case State.AUTO_DOCKING:
+                    this.UpdateStateAutoDocking();
+                    break;
+                case State.NORMAL:
+                    break; // Nothing.
+            }
+        }
+
+        void UpdateStateMachine(State newState)
+        {
+            if (this.state == newState)
+                return;
+
+            if (newState == State.NORMAL)
+            {
+                switch (this.state)
+                {
+                    case State.AUTO_STABILIZATION:
+                        foreach (var gyro in this.gyros)
+                            gyro.GyroOverride = false;
+                        this.state = State.NORMAL;
+                        this.output.Print("Auto stabilization disabled");
+                        break;
+                    case State.AUTO_DOCKING:
+                        this.state = State.NORMAL;
+                        this.output.Print("Auto docking disabled");
+                        break;
+                    case State.NORMAL:
+                        break; // Nothing.
+
+                }
+            }
+            else
+            {
+                this.UpdateStateMachine(State.NORMAL);
+                switch (newState)
+                {
+                    case State.AUTO_STABILIZATION:
+                        for (int i = 0; i < NB_OF_GYRO && i < this.gyros.Count; i++)
+                        {
+                            var gyro = this.gyros[i];
+                            gyro.GyroOverride = true;
+                            gyro.Yaw = 0f;
+                            gyro.Pitch = 0f;
+                            gyro.Roll = 0f;
+                        }
+
+                        this.state = State.AUTO_STABILIZATION;
+                        this.output.Print("Auto stabilization enabled");
+                        break;
+                    case State.AUTO_DOCKING:
+                        this.state = State.AUTO_DOCKING;
+                        this.output.Print("Auto docking enabled");
+                        break;
+                    case State.NORMAL:
+                        break; // Nothing.
+                }
+            }
+        }
+
+        public void Main(string argument, UpdateType updateSource)
+        {
+            if ((updateSource & UpdateType.Update10) != 0)
+            {
+                this.UpdateState();
+            }
+            else if ((updateSource & (UpdateType.Terminal | UpdateType.Trigger)) != 0)
+            {
+                switch (argument)
+                {
+                    case "SWITCH_AUTO_STABILIZATION":
+                        if (this.state != State.AUTO_STABILIZATION)
+                            this.UpdateStateMachine(State.AUTO_STABILIZATION);
+                        else
+                            this.UpdateStateMachine(State.NORMAL);
+                        break;
+
+                    case "SWITCH_AUTO_DOCKING":
+                        if (this.state != State.AUTO_DOCKING)
+                            this.UpdateStateMachine(State.AUTO_DOCKING);
+                        else
+                            this.UpdateStateMachine(State.NORMAL);
+                        break;
+
+                    default:
+                        this.output.Print($"Uknown command: {argument}");
+                        break;
+                }
+            }
+        }
+    }
+}
diff --git a/AutoPilot/thumb.png b/AutoPilot/thumb.png
new file mode 100644 (file)
index 0000000..5f05800
Binary files /dev/null and b/AutoPilot/thumb.png differ
diff --git a/BaseMiner/BaseApp.csproj b/BaseMiner/BaseApp.csproj
new file mode 100644 (file)
index 0000000..0681571
--- /dev/null
@@ -0,0 +1,57 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
+  <PropertyGroup>
+    <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
+    <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
+    <ProjectGuid>{22A83955-FE9B-4EBA-8980-D9DE01353C4C}</ProjectGuid>
+    <OutputType>Exe</OutputType>
+    <RootNamespace>IngameScript</RootNamespace>
+    <AssemblyName>BaseApp</AssemblyName>
+    <TargetFrameworkVersion>v4.8</TargetFrameworkVersion>
+    <FileAlignment>512</FileAlignment>
+    <AutoGenerateBindingRedirects>true</AutoGenerateBindingRedirects>
+    <TargetFrameworkProfile />
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|x64'">
+    <DebugSymbols>true</DebugSymbols>
+    <OutputPath>bin\</OutputPath>
+    <DefineConstants>DEBUG;TRACE</DefineConstants>
+    <DebugType>full</DebugType>
+    <PlatformTarget>x64</PlatformTarget>
+    <ErrorReport>prompt</ErrorReport>
+    <CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
+    <Prefer32Bit>true</Prefer32Bit>
+    <LangVersion>6</LangVersion>
+  </PropertyGroup>
+  <ItemGroup>
+    <Reference Include="netstandard" />
+    <Reference Include="System" />
+    <Reference Include="System.Core" />
+    <Reference Include="System.Xml.Linq" />
+    <Reference Include="System.Data.DataSetExtensions" />
+    <Reference Include="Microsoft.CSharp" />
+    <Reference Include="System.Data" />
+    <Reference Include="System.Net.Http" />
+    <Reference Include="System.Xml" />
+  </ItemGroup>
+  <Import Project="MDK/MDK.options.props" />
+  <Import Project="MDK/MDK.paths.props" Condition="exists('MDK/MDK.paths.props')" />
+  <ItemGroup>
+    <Compile Include="MDK\Bootstrapper.cs" />
+    <AdditionalFiles Include="MDK\MDK.options.props">
+      <CopyToOutputDirectory>Always</CopyToOutputDirectory>
+    </AdditionalFiles>
+    <AdditionalFiles Include="MDK\MDK.paths.props">
+      <CopyToOutputDirectory>Always</CopyToOutputDirectory>
+    </AdditionalFiles>
+    <Compile Include="Program.cs" />
+    <AdditionalFiles Include="MDK\whitelist.cache" />
+  </ItemGroup>
+  <Import Project="..\SECommon\SECommon.projitems" Label="Shared" />
+  <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
+  <Target Name="AfterBuild">
+    <Copy SourceFiles="MDK\MDK.options.props" DestinationFolder="$(TargetDir)\MDK" />
+    <Copy SourceFiles="MDK\MDK.paths.props" DestinationFolder="$(TargetDir)\MDK" />
+  </Target>
+</Project>
\ No newline at end of file
diff --git a/BaseMiner/MDK/Bootstrapper.cs b/BaseMiner/MDK/Bootstrapper.cs
new file mode 100644 (file)
index 0000000..dd86886
--- /dev/null
@@ -0,0 +1,27 @@
+using Malware.MDKUtilities;
+
+namespace IngameScript.MDK
+{
+    public class TestBootstrapper
+    {
+        // All the files in this folder, as well as all files containing the file ".debug.", will be excluded
+        // from the build process. You can use this to create utilites for testing your scripts directly in 
+        // Visual Studio.
+
+        static TestBootstrapper()
+        {
+            // Initialize the MDK utility framework
+            MDKUtilityFramework.Load();
+        }
+
+        public static void Main()
+        {
+            // In order for your program to actually run, you will need to provide a mockup of all the facilities 
+            // your script uses from the game, since they're not available outside of the game.
+
+            // Create and configure the desired program.
+            var program = MDKFactory.CreateProgram<Program>();
+            MDKFactory.Run(program);
+        }
+    }
+}
\ No newline at end of file
diff --git a/BaseMiner/MDK/MDK.options.props b/BaseMiner/MDK/MDK.options.props
new file mode 100644 (file)
index 0000000..0a291ca
--- /dev/null
@@ -0,0 +1,18 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <PropertyGroup>
+    <!-- 
+    Contains basic settings that should be included in code repositories
+    -->
+    <MDKVersion>1.5.17</MDKVersion>
+    <MDKTrimTypes>
+      <Enabled>no</Enabled>
+    </MDKTrimTypes>
+    <MDKMinify>
+      <Level>None</Level>
+    </MDKMinify>
+    <MDKIgnore>
+      <Folder>mdk</Folder>
+    </MDKIgnore>
+  </PropertyGroup>
+</Project>
\ No newline at end of file
diff --git a/BaseMiner/MDK/MDK.paths.props b/BaseMiner/MDK/MDK.paths.props
new file mode 100644 (file)
index 0000000..a0f8f66
--- /dev/null
@@ -0,0 +1,81 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <PropertyGroup>
+    <!-- 
+    You can safely exclude this file from code repositories and use different 
+    user settings per machine.
+    -->
+    <MDKVersion>1.5.17</MDKVersion>
+    <MDKUseGameBinPath>no</MDKUseGameBinPath>
+    <MDKGameBinPath>G:\SteamLibrary\SteamApps\common\SpaceEngineers\Bin64</MDKGameBinPath>
+    <MDKInstallPath>c:\users\lyssmetal\appdata\local\microsoft\visualstudio\17.0_6c02a30d\extensions\bnnd2422.thc</MDKInstallPath>
+    <MDKOutputPath>C:\Users\LyssMetal\AppData\Roaming\SpaceEngineers\IngameScripts\local</MDKOutputPath>
+  </PropertyGroup>
+  <ItemGroup>
+    <Reference Include="System.Collections.Immutable">
+      <HintPath>$(MDKGameBinPath)\System.Collections.Immutable.dll</HintPath>
+      <Private>false</Private>
+    </Reference>
+    <Reference Include="Sandbox.Common">
+      <HintPath>$(MDKGameBinPath)\Sandbox.Common.dll</HintPath>
+      <Private>False</Private>
+    </Reference>
+    <Reference Include="Sandbox.Game">
+      <HintPath>$(MDKGameBinPath)\Sandbox.Game.dll</HintPath>
+      <Private>False</Private>
+    </Reference>
+    <Reference Include="Sandbox.Graphics">
+      <HintPath>$(MDKGameBinPath)\Sandbox.Graphics.dll</HintPath>
+      <Private>False</Private>
+    </Reference>
+    <Reference Include="SpaceEngineers.Game">
+      <HintPath>$(MDKGameBinPath)\SpaceEngineers.Game.dll</HintPath>
+      <Private>False</Private>
+    </Reference>
+    <Reference Include="SpaceEngineers.ObjectBuilders">
+      <HintPath>$(MDKGameBinPath)\SpaceEngineers.ObjectBuilders.dll</HintPath>
+      <Private>False</Private>
+    </Reference>
+    <Reference Include="VRage">
+      <HintPath>$(MDKGameBinPath)\VRage.dll</HintPath>
+      <Private>False</Private>
+    </Reference>
+    <Reference Include="VRage.Audio">
+      <HintPath>$(MDKGameBinPath)\VRage.Audio.dll</HintPath>
+      <Private>False</Private>
+    </Reference>
+    <Reference Include="VRage.Game">
+      <HintPath>$(MDKGameBinPath)\VRage.Game.dll</HintPath>
+      <Private>False</Private>
+    </Reference>
+    <Reference Include="VRage.Input">
+      <HintPath>$(MDKGameBinPath)\VRage.Input.dll</HintPath>
+      <Private>False</Private>
+    </Reference>
+    <Reference Include="VRage.Library">
+      <HintPath>$(MDKGameBinPath)\VRage.Library.dll</HintPath>
+      <Private>False</Private>
+    </Reference>
+    <Reference Include="VRage.Math">
+      <HintPath>$(MDKGameBinPath)\VRage.Math.dll</HintPath>
+      <Private>False</Private>
+    </Reference>
+    <Reference Include="VRage.Render">
+      <HintPath>$(MDKGameBinPath)\VRage.Render.dll</HintPath>
+      <Private>False</Private>
+    </Reference>
+    <Reference Include="VRage.Render11">
+      <HintPath>$(MDKGameBinPath)\VRage.Render11.dll</HintPath>
+      <Private>False</Private>
+    </Reference>
+    <Reference Include="VRage.Scripting">
+      <HintPath>$(MDKGameBinPath)\VRage.Scripting.dll</HintPath>
+      <Private>False</Private>
+    </Reference>
+    <Reference Include="MDKUtilities">
+      <HintPath>$(MDKInstallPath)\MDKUtilities.dll</HintPath>
+      <Private>True</Private>
+    </Reference>
+    <Analyzer Include="$(MDKInstallPath)\Analyzers\MDKAnalyzer.dll" />
+  </ItemGroup>
+</Project>
\ No newline at end of file
diff --git a/BaseMiner/Program.cs b/BaseMiner/Program.cs
new file mode 100644 (file)
index 0000000..bb89dc5
--- /dev/null
@@ -0,0 +1,198 @@
+using Sandbox.Game.EntityComponents;
+using Sandbox.ModAPI.Ingame;
+using Sandbox.ModAPI.Interfaces;
+
+using SpaceEngineers.Game.ModAPI.Ingame;
+
+using System;
+using System.Collections;
+using System.Collections.Generic;
+using System.Collections.Immutable;
+using System.Linq;
+using System.Text;
+
+using VRage;
+using VRage.Collections;
+using VRage.Game;
+using VRage.Game.Components;
+using VRage.Game.GUI.TextPanel;
+using VRage.Game.ModAPI.Ingame;
+using VRage.Game.ModAPI.Ingame.Utilities;
+using VRage.Game.ObjectBuilders.Definitions;
+
+using VRageMath;
+
+namespace IngameScript
+{
+    partial class Program : MyGridProgram
+    {
+        const int CONSOLE_NB_LINES = 7;
+        const string GRID_PREFIX = "[Base]";
+
+        const float PISTON_SPEED = 0.05f;
+        enum State
+        {
+            NORMAL,
+            MINING,
+            STOPPING_MINING,
+        }
+
+        const float EPSILON = 0.05f;
+
+        State currentState = State.NORMAL;
+
+        readonly Output output;
+
+        List<IMyExtendedPistonBase> pistons = new List<IMyExtendedPistonBase>();
+
+        IMyLandingGear magneticPlate;
+        List<IMyShipDrill> drills = new List<IMyShipDrill>();
+
+        IMySoundBlock soundAlert;
+        List<IMyLightingBlock> rotatingLights = new List<IMyLightingBlock>();
+
+        IMyShipConnector minerConnector;
+
+        public Program()
+        {
+            var output = this.Me.GetSurface(0);
+            this.output = new Output(output, CONSOLE_NB_LINES);
+
+            this.output.Print("Base mining system starting...");
+
+            this.GridTerminalSystem.GetBlocksOfType(
+                this.drills, 
+                (IMyShipDrill drill) => drill.CustomName.StartsWith(GRID_PREFIX)
+            );
+
+            this.output.Print($"Nb of drills: {this.drills.Count}");
+
+            this.GridTerminalSystem.GetBlocksOfType(
+                this.pistons,
+                (IMyExtendedPistonBase piston) => piston.CustomName.StartsWith(GRID_PREFIX) && piston.CustomName.Contains("Miner")
+            );
+
+            this.output.Print($"Nb of pistons: {this.pistons.Count}");
+
+            this.magneticPlate = this.GridTerminalSystem.GetBlockWithName("[Base] Magnetic Plate Miner") as IMyLandingGear;
+
+            this.soundAlert = this.GridTerminalSystem.GetBlockWithName("[Base] Sound Block Miner") as IMySoundBlock;
+            if (this.soundAlert == null)
+                this.output.Print($"Error: sound alert system not found");
+
+            this.GridTerminalSystem.GetBlocksOfType(
+                this.rotatingLights,
+                (IMyLightingBlock light) => light.CustomName.StartsWith(GRID_PREFIX) && light.CustomName.Contains("Miner")
+            );
+
+            this.output.Print($"Nb of rotating lights: {this.rotatingLights.Count}");
+            
+            this.minerConnector = this.GridTerminalSystem.GetBlockWithName("[Base] Connector Miner") as IMyShipConnector;
+            if (this.minerConnector == null)
+                this.output.Print($"Error: miner connector not found");
+
+            this.Runtime.UpdateFrequency = UpdateFrequency.Update100;
+
+            this.output.Print("base Mining system has started");
+        }
+
+        public void Save()
+        {
+        }
+
+        void UpdateState()
+        {
+            if (this.currentState == State.STOPPING_MINING)
+            {
+                bool finished = true;
+
+                foreach (var d in this.drills)
+                {
+                    d.Enabled = false;
+                }
+
+                foreach (var p in this.pistons)
+                {
+                    var distanceDocked = 0.0;
+
+                    if (p.CustomName == "[Base] Piston Miner 02")
+                        distanceDocked = 0.1;
+
+                    if (p.CurrentPosition > distanceDocked + EPSILON)
+                    {
+                        finished = false;
+                        p.Velocity = 5 * -PISTON_SPEED;
+                    }
+                    else
+                    {
+                        p.Velocity = 0.0f;
+                    }
+                }
+
+                if (finished)
+                {
+                    foreach (var p in this.pistons)
+                        p.Enabled = false;
+
+                    foreach (var l in this.rotatingLights)
+                        l.Enabled = false;
+
+                    this.soundAlert.Stop();
+
+                    this.output.Print("Drills parked, operation terminated");
+                    this.currentState = State.NORMAL;
+                }
+            }
+            else if (this.currentState == State.MINING)
+            {
+                this.magneticPlate.Unlock();
+
+                foreach (var p in this.pistons)
+                {
+                    p.Enabled = true;
+                    p.Velocity = PISTON_SPEED;
+                }
+
+                foreach (var d in this.drills)
+                {
+                    d.Enabled = true;
+                }
+            }
+
+            // Send miner connector position.
+            this.IGC.SendBroadcastMessage("POSITION_CONNECTOR_MINER", this.minerConnector.WorldMatrix);
+        }
+
+        public void Main(string argument, UpdateType updateSource)
+        {
+            if ((updateSource & UpdateType.Update100) != 0)
+            {
+                this.UpdateState();
+            }
+            else if ((updateSource & (UpdateType.Terminal | UpdateType.Trigger)) != 0)
+            {
+                switch (argument)
+                {
+                    case "STOP_MINING":
+                        this.output.Print("Stopping mining...");
+                        this.currentState = State.STOPPING_MINING;
+                        break;
+
+                    case "START_MINING":
+                        this.soundAlert.Play();
+                        foreach (var l in this.rotatingLights)
+                            l.Enabled = true;
+
+                        this.output.Print("Mining in progress...");
+                        this.currentState = State.MINING;
+                        break;
+
+                    default:
+                        this.output.Print($"Uknown command: {argument}");
+                        break;
+                }
+            }
+        }
+    }
+}
+
diff --git a/MiningRover/Instructions.readme b/MiningRover/Instructions.readme
new file mode 100644 (file)
index 0000000..ed30ab7
--- /dev/null
@@ -0,0 +1,5 @@
+R e a d m e
+-----------
+
+In this file you can include any instructions or other comments you want to have injected onto the 
+top of your final script. You can safely delete this file if you do not want any such comments.
diff --git a/MiningRover/MDK/Bootstrapper.cs b/MiningRover/MDK/Bootstrapper.cs
new file mode 100644 (file)
index 0000000..dd86886
--- /dev/null
@@ -0,0 +1,27 @@
+using Malware.MDKUtilities;
+
+namespace IngameScript.MDK
+{
+    public class TestBootstrapper
+    {
+        // All the files in this folder, as well as all files containing the file ".debug.", will be excluded
+        // from the build process. You can use this to create utilites for testing your scripts directly in 
+        // Visual Studio.
+
+        static TestBootstrapper()
+        {
+            // Initialize the MDK utility framework
+            MDKUtilityFramework.Load();
+        }
+
+        public static void Main()
+        {
+            // In order for your program to actually run, you will need to provide a mockup of all the facilities 
+            // your script uses from the game, since they're not available outside of the game.
+
+            // Create and configure the desired program.
+            var program = MDKFactory.CreateProgram<Program>();
+            MDKFactory.Run(program);
+        }
+    }
+}
\ No newline at end of file
diff --git a/MiningRover/MDK/MDK.options.props b/MiningRover/MDK/MDK.options.props
new file mode 100644 (file)
index 0000000..0a291ca
--- /dev/null
@@ -0,0 +1,18 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <PropertyGroup>
+    <!-- 
+    Contains basic settings that should be included in code repositories
+    -->
+    <MDKVersion>1.5.17</MDKVersion>
+    <MDKTrimTypes>
+      <Enabled>no</Enabled>
+    </MDKTrimTypes>
+    <MDKMinify>
+      <Level>None</Level>
+    </MDKMinify>
+    <MDKIgnore>
+      <Folder>mdk</Folder>
+    </MDKIgnore>
+  </PropertyGroup>
+</Project>
\ No newline at end of file
diff --git a/MiningRover/MDK/MDK.paths.props b/MiningRover/MDK/MDK.paths.props
new file mode 100644 (file)
index 0000000..a0f8f66
--- /dev/null
@@ -0,0 +1,81 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <PropertyGroup>
+    <!-- 
+    You can safely exclude this file from code repositories and use different 
+    user settings per machine.
+    -->
+    <MDKVersion>1.5.17</MDKVersion>
+    <MDKUseGameBinPath>no</MDKUseGameBinPath>
+    <MDKGameBinPath>G:\SteamLibrary\SteamApps\common\SpaceEngineers\Bin64</MDKGameBinPath>
+    <MDKInstallPath>c:\users\lyssmetal\appdata\local\microsoft\visualstudio\17.0_6c02a30d\extensions\bnnd2422.thc</MDKInstallPath>
+    <MDKOutputPath>C:\Users\LyssMetal\AppData\Roaming\SpaceEngineers\IngameScripts\local</MDKOutputPath>
+  </PropertyGroup>
+  <ItemGroup>
+    <Reference Include="System.Collections.Immutable">
+      <HintPath>$(MDKGameBinPath)\System.Collections.Immutable.dll</HintPath>
+      <Private>false</Private>
+    </Reference>
+    <Reference Include="Sandbox.Common">
+      <HintPath>$(MDKGameBinPath)\Sandbox.Common.dll</HintPath>
+      <Private>False</Private>
+    </Reference>
+    <Reference Include="Sandbox.Game">
+      <HintPath>$(MDKGameBinPath)\Sandbox.Game.dll</HintPath>
+      <Private>False</Private>
+    </Reference>
+    <Reference Include="Sandbox.Graphics">
+      <HintPath>$(MDKGameBinPath)\Sandbox.Graphics.dll</HintPath>
+      <Private>False</Private>
+    </Reference>
+    <Reference Include="SpaceEngineers.Game">
+      <HintPath>$(MDKGameBinPath)\SpaceEngineers.Game.dll</HintPath>
+      <Private>False</Private>
+    </Reference>
+    <Reference Include="SpaceEngineers.ObjectBuilders">
+      <HintPath>$(MDKGameBinPath)\SpaceEngineers.ObjectBuilders.dll</HintPath>
+      <Private>False</Private>
+    </Reference>
+    <Reference Include="VRage">
+      <HintPath>$(MDKGameBinPath)\VRage.dll</HintPath>
+      <Private>False</Private>
+    </Reference>
+    <Reference Include="VRage.Audio">
+      <HintPath>$(MDKGameBinPath)\VRage.Audio.dll</HintPath>
+      <Private>False</Private>
+    </Reference>
+    <Reference Include="VRage.Game">
+      <HintPath>$(MDKGameBinPath)\VRage.Game.dll</HintPath>
+      <Private>False</Private>
+    </Reference>
+    <Reference Include="VRage.Input">
+      <HintPath>$(MDKGameBinPath)\VRage.Input.dll</HintPath>
+      <Private>False</Private>
+    </Reference>
+    <Reference Include="VRage.Library">
+      <HintPath>$(MDKGameBinPath)\VRage.Library.dll</HintPath>
+      <Private>False</Private>
+    </Reference>
+    <Reference Include="VRage.Math">
+      <HintPath>$(MDKGameBinPath)\VRage.Math.dll</HintPath>
+      <Private>False</Private>
+    </Reference>
+    <Reference Include="VRage.Render">
+      <HintPath>$(MDKGameBinPath)\VRage.Render.dll</HintPath>
+      <Private>False</Private>
+    </Reference>
+    <Reference Include="VRage.Render11">
+      <HintPath>$(MDKGameBinPath)\VRage.Render11.dll</HintPath>
+      <Private>False</Private>
+    </Reference>
+    <Reference Include="VRage.Scripting">
+      <HintPath>$(MDKGameBinPath)\VRage.Scripting.dll</HintPath>
+      <Private>False</Private>
+    </Reference>
+    <Reference Include="MDKUtilities">
+      <HintPath>$(MDKInstallPath)\MDKUtilities.dll</HintPath>
+      <Private>True</Private>
+    </Reference>
+    <Analyzer Include="$(MDKInstallPath)\Analyzers\MDKAnalyzer.dll" />
+  </ItemGroup>
+</Project>
\ No newline at end of file
diff --git a/MiningRover/MiningRover.csproj b/MiningRover/MiningRover.csproj
new file mode 100644 (file)
index 0000000..dd8931c
--- /dev/null
@@ -0,0 +1,85 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
+  <PropertyGroup>
+    <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
+    <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
+    <ProjectGuid>{DBCD62FE-F7AA-4A03-9241-0A4BE6952664}</ProjectGuid>
+    <OutputType>Exe</OutputType>
+    <RootNamespace>IngameScript</RootNamespace>
+    <AssemblyName>MiningRover</AssemblyName>
+    <TargetFrameworkVersion>v4.8</TargetFrameworkVersion>
+    <FileAlignment>512</FileAlignment>
+    <AutoGenerateBindingRedirects>true</AutoGenerateBindingRedirects>
+    <TargetFrameworkProfile />
+    <PublishUrl>publish\</PublishUrl>
+    <Install>true</Install>
+    <InstallFrom>Disk</InstallFrom>
+    <UpdateEnabled>false</UpdateEnabled>
+    <UpdateMode>Foreground</UpdateMode>
+    <UpdateInterval>7</UpdateInterval>
+    <UpdateIntervalUnits>Days</UpdateIntervalUnits>
+    <UpdatePeriodically>false</UpdatePeriodically>
+    <UpdateRequired>false</UpdateRequired>
+    <MapFileExtensions>true</MapFileExtensions>
+    <ApplicationRevision>0</ApplicationRevision>
+    <ApplicationVersion>1.0.0.%2a</ApplicationVersion>
+    <IsWebBootstrapper>false</IsWebBootstrapper>
+    <UseApplicationTrust>false</UseApplicationTrust>
+    <BootstrapperEnabled>true</BootstrapperEnabled>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|x64'">
+    <DebugSymbols>true</DebugSymbols>
+    <OutputPath>bin\</OutputPath>
+    <DefineConstants>DEBUG;TRACE</DefineConstants>
+    <DebugType>full</DebugType>
+    <PlatformTarget>x64</PlatformTarget>
+    <ErrorReport>prompt</ErrorReport>
+    <CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
+    <Prefer32Bit>true</Prefer32Bit>
+    <LangVersion>6</LangVersion>
+  </PropertyGroup>
+  <ItemGroup>
+    <Reference Include="netstandard" />
+    <Reference Include="System" />
+    <Reference Include="System.Core" />
+    <Reference Include="System.Xml.Linq" />
+    <Reference Include="System.Data.DataSetExtensions" />
+    <Reference Include="Microsoft.CSharp" />
+    <Reference Include="System.Data" />
+    <Reference Include="System.Net.Http" />
+    <Reference Include="System.Xml" />
+  </ItemGroup>
+  <Import Project="MDK/MDK.options.props" />
+  <Import Project="MDK/MDK.paths.props" Condition="exists('MDK/MDK.paths.props')" />
+  <ItemGroup>
+    <Compile Include="MDK\Bootstrapper.cs" />
+    <AdditionalFiles Include="MDK\MDK.options.props">
+      <CopyToOutputDirectory>Always</CopyToOutputDirectory>
+    </AdditionalFiles>
+    <AdditionalFiles Include="MDK\MDK.paths.props">
+      <CopyToOutputDirectory>Always</CopyToOutputDirectory>
+    </AdditionalFiles>
+    <Compile Include="Program.cs" />
+    <AdditionalFiles Include="Instructions.readme" />
+    <AdditionalFiles Include="thumb.png" />
+    <AdditionalFiles Include="MDK\whitelist.cache" />
+  </ItemGroup>
+  <ItemGroup>
+    <BootstrapperPackage Include=".NETFramework,Version=v4.8">
+      <Visible>False</Visible>
+      <ProductName>Microsoft .NET Framework 4.8 %28x86 and x64%29</ProductName>
+      <Install>true</Install>
+    </BootstrapperPackage>
+    <BootstrapperPackage Include="Microsoft.Net.Framework.3.5.SP1">
+      <Visible>False</Visible>
+      <ProductName>.NET Framework 3.5 SP1</ProductName>
+      <Install>false</Install>
+    </BootstrapperPackage>
+  </ItemGroup>
+  <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
+  <Target Name="AfterBuild">
+    <Copy SourceFiles="MDK\MDK.options.props" DestinationFolder="$(TargetDir)\MDK" />
+    <Copy SourceFiles="MDK\MDK.paths.props" DestinationFolder="$(TargetDir)\MDK" />
+  </Target>
+</Project>
\ No newline at end of file
diff --git a/MiningRover/Program.cs b/MiningRover/Program.cs
new file mode 100644 (file)
index 0000000..1a1d15b
--- /dev/null
@@ -0,0 +1,445 @@
+using Sandbox.Game.EntityComponents;
+using Sandbox.ModAPI.Ingame;
+using Sandbox.ModAPI.Interfaces;
+
+using SpaceEngineers.Game.ModAPI.Ingame;
+
+using System;
+using System.Collections;
+using System.Collections.Generic;
+using System.Collections.Immutable;
+using System.Linq;
+using System.Text;
+
+using VRage;
+using VRage.Collections;
+using VRage.Game;
+using VRage.Game.Components;
+using VRage.Game.GUI.TextPanel;
+using VRage.Game.ModAPI.Ingame;
+using VRage.Game.ModAPI.Ingame.Utilities;
+using VRage.Game.ObjectBuilders.Definitions;
+
+using VRageMath;
+
+namespace IngameScript
+{
+    partial class Program : MyGridProgram
+    {   
+        enum State
+        {
+            DEFAULT,
+            PACKING,
+            UNPACKING,
+        }
+
+        const float EPSILON = 0.05f;
+        const float EPSILON_RAD = (float)(Math.PI / 64);
+
+        State currentState = State.DEFAULT;
+
+        IMyMotorAdvancedStator rotor01;
+        IMyMotorAdvancedStator rotor02;
+        IMyMotorAdvancedStator hinge01;
+        IMyMotorAdvancedStator hinge02;
+        IMyMotorAdvancedStator hinge03;
+        IMyExtendedPistonBase piston01;
+
+        List<IMyExtendedPistonBase> pistons = new List<IMyExtendedPistonBase>();
+        List<string> pistonsNames = new List<string> { "Piston 02", "Piston 03", "Piston 04", "Piston 05", "Piston 06", "Piston 07", };
+
+        IMyLandingGear magneticPlateArm;
+        IMyLandingGear lockPlate;
+        IMyExtendedPistonBase lockPiston;
+
+        IMyTextSurface output;
+
+        public void Print(string text)
+        {
+            this.output.WriteText((this.output.GetText() != "" ? Environment.NewLine : "") + text, true);
+        }
+
+        public void PrintError(string text)
+        {
+            this.Print($"Error: {text}");
+        }
+
+        public Program()
+        {
+            this.output = this.Me.GetSurface(0);
+            this.output.ContentType = ContentType.TEXT_AND_IMAGE;
+            this.output.WriteText("");
+
+            this.Me.CustomData = "Packing";
+
+            this.Print("Mining rover system starting...");
+
+            var stators = new List<IMyMotorAdvancedStator>();
+            GridTerminalSystem.GetBlocksOfType(stators);
+
+            foreach (var s in stators)
+            {
+                if (s.DisplayNameText.Contains("Rotor 01"))
+                    this.rotor01 = s;
+                else if (s.DisplayNameText.Contains("Rotor 02"))
+                    this.rotor02 = s;
+                else if (s.DisplayNameText.Contains("Hinge 01"))
+                    this.hinge01 = s;
+                else if (s.DisplayNameText.Contains("Hinge 02"))
+                    this.hinge02 = s;
+                else if (s.DisplayNameText.Contains("Hinge 03"))
+                    this.hinge03 = s;
+            }
+
+            var pistons = new List<IMyExtendedPistonBase>();
+            GridTerminalSystem.GetBlocksOfType(pistons);
+
+            foreach (var p in pistons)
+            {
+                if (p.DisplayNameText.Contains("Piston 01"))
+                {
+                    this.piston01 = p;
+                }
+                else if (p.DisplayNameText.Contains("Lock Piston"))
+                {
+                    this.lockPiston = p;
+                }
+                else
+                {
+                    foreach (var name in pistonsNames)
+                    {
+                        if (p.DisplayNameText.Contains(name))
+                        {
+                            this.pistons.Add(p);
+                            break;
+                        }
+                    }
+                }
+            }
+
+            var magneticPlates = new List<IMyLandingGear>();
+            GridTerminalSystem.GetBlocksOfType(magneticPlates);
+            foreach (var magneticPlate in magneticPlates)
+            {
+                if (magneticPlate.DisplayNameText.Contains("Magnetic Plate arm"))
+                {
+                    this.magneticPlateArm = magneticPlate;
+                }
+                else if (magneticPlate.DisplayNameText.Contains("Lock Plate"))
+                {                    
+                    this.lockPlate = magneticPlate;
+                }
+            }
+
+            if (this.rotor01 == null)
+            {
+                this.PrintError("Can't find 'Rotor 01'");
+                return;
+            }
+
+            if (this.rotor02 == null)
+            {
+                this.PrintError("Can't find 'Rotor 02'");
+                return;
+            }
+
+            if (this.hinge01 == null)
+            {
+                this.PrintError("Can't find 'Hinge 01'");
+                return;
+            }
+
+            if (this.hinge02 == null)
+            {
+                this.PrintError("Can't find 'Hinge 02'");
+                return;
+            }
+
+            if (this.magneticPlateArm == null)
+            {
+                this.PrintError("Can't find 'Magnetic Plate arm'");
+                return;
+            }
+
+            if (this.lockPlate == null)
+            {
+                this.PrintError("Can't find 'Lock Plate'");
+                return;
+            }
+
+            if (this.piston01 == null)
+            {
+                this.PrintError("Can't find 'Piston 01'");
+                return;
+            }
+
+            if (this.lockPiston == null)
+            {
+                this.PrintError("Can't find 'Lock Piston'");
+                return;
+            }
+
+
+            this.Runtime.UpdateFrequency = UpdateFrequency.Update100;
+
+            this.Print("Mining rover system has started");
+        }
+
+        public void Save()
+        {
+        }
+
+        /// <summary>
+        /// Always returns an angle between 0 and pi/2.
+        /// </summary>
+        /// <param name="a1"></param>
+        /// <param name="a2"></param>
+        /// <returns></returns>
+        float SumAngles(float a1, float a2)
+        {
+            var r = (float)((a1 + a2) % (2 * Math.PI));
+
+            if (r < 0)
+                return (float)(r + 2 * Math.PI);
+            else
+                return r;
+        }
+
+        // Return 'true' if the rotor is in place.
+        bool SetRotorVelocity(float targetAngle, IMyMotorAdvancedStator rotor, float tolerance = (float)(Math.PI / 64))
+        {
+            //if (rotor.Angle)
+            return false;
+        }
+
+        void UpdateState()
+        {
+            if (this.currentState == State.UNPACKING)
+            {
+                if (!this.piston01.Enabled)
+                {
+                    this.piston01.Enabled = true;
+                    foreach (var p in this.pistons)
+                        p.Enabled = true;
+                }
+
+                bool finished = true;
+                //bool roverLocked = false;
+
+                if (this.magneticPlateArm.IsLocked)
+                    this.magneticPlateArm.Unlock();
+
+                this.rotor01.TargetVelocityRPM = 0.0f;
+
+                if (this.lockPiston.CurrentPosition <= EPSILON)
+                {
+                    finished = false;
+                    this.lockPiston.Velocity = 0.5f;
+                } 
+                else if (this.lockPiston.CurrentPosition >= this.lockPiston.MaxLimit - EPSILON)
+                {
+                    //roverLocked = true;
+                    if (!this.lockPlate.IsLocked)
+                        this.lockPlate.Lock();
+                    this.lockPiston.Velocity = 0.0f;
+                }
+
+                if (this.hinge01.Angle <= -Math.PI / 8)
+                {
+                    this.hinge01.TargetVelocityRPM = 0.0f;
+                }
+                else // if (roverLocked)
+                {
+                    this.hinge01.TargetVelocityRPM = -1.5f;
+                    finished = false;
+                }
+
+                if (this.hinge02.Angle <= -Math.PI / 3)
+                {
+                    this.hinge02.TargetVelocityRPM = 0.0f;
+                }
+                else // if (roverLocked)
+                {
+                    this.hinge02.TargetVelocityRPM = -1.5f;
+                    finished = false;
+                }
+
+                if (this.piston01.CurrentPosition <= this.piston01.MaxLimit - EPSILON /*&& roverLocked*/)
+                {
+                    this.piston01.Velocity = 1.0f;
+                    finished = false;
+                }
+                else
+                {
+                    this.piston01.Velocity = 0.0f;
+                }
+
+                if (finished)
+                {
+                    this.rotor01.RotorLock = false;
+                    this.currentState = State.DEFAULT;
+                    this.Print("Unpacking terminated");
+                }
+            }
+            else if (this.currentState == State.PACKING)
+            {
+                bool finished = true;
+
+                var rotor01InPlace = this.rotor01.Angle >= 2 * Math.PI - EPSILON_RAD || this.rotor01.Angle <= EPSILON_RAD;
+                if (rotor01InPlace)
+                {
+                    this.rotor01.RotorLock = true;
+                    this.rotor01.TargetVelocityRPM = 0.0f;
+                }
+                else if (this.rotor01.Angle >= Math.PI)
+                {
+                    this.rotor01.TargetVelocityRPM = 1.0f;
+                    finished = false;
+                }
+                else // if (this.rotor01.Angle <= Math.PI)
+                {
+                    this.rotor01.TargetVelocityRPM = -1.0f;
+                    finished = false;
+                }
+
+                //this.Print($"Hinge 01 angle: {this.hinge01.Angle}");
+                if (this.hinge01.Angle <= Math.PI / 4.0 || rotor01InPlace && this.hinge01.Angle <= Math.PI / 2.0 - Math.PI / 32.0)
+                {
+                    this.hinge01.TargetVelocityRPM = 1.5f;
+                    finished = false;
+                }
+                else
+                {
+                    this.hinge01.TargetVelocityRPM = 0f;
+                }
+
+                if (this.hinge02.Angle <= -Math.PI / 32.0)
+                {
+                    this.hinge02.TargetVelocityRPM = 1.5f;
+                    finished = false;
+                }
+                else
+                {
+                    this.hinge02.TargetVelocityRPM = 0f;
+                }
+
+                if (this.piston01.CurrentPosition >= EPSILON)
+                {
+                    this.piston01.Velocity = -1.0f;
+                    finished = false;
+                }
+                else
+                {
+                    this.piston01.Velocity = 0.0f;
+                }
+
+                //var rotor2TargetAngle = 2 * Math.PI - Math.PI / 4; // 315°.                
+
+                if (finished)
+                {
+                    if (!this.magneticPlateArm.IsLocked)
+                        this.magneticPlateArm.Lock();
+
+                    if (this.lockPlate.IsLocked)
+                    {
+                        this.lockPlate.Unlock();
+                        this.lockPiston.Velocity = -0.5f;
+                    }
+
+                    this.piston01.Enabled = false;
+                    foreach (var p in this.pistons)
+                        p.Enabled = false;
+
+                    this.currentState = State.DEFAULT;
+                    this.Print("Packing terminated");
+                }
+            }
+        }
+
+        /*
+        enum RotateDirection
+        {
+            RIGHT,
+            LEFT,
+        }
+
+        enum ElevationDirection
+        {
+            UP,
+            DOWN,
+        }
+
+        const double SPEED_ROTATION = 1.0;
+        const double SPEED_HINGE = 1.0;
+        const double SPEED_EXTEND_1 = 1.0;
+        const double SPEED_EXTEND_2 = 1.0;
+
+        void Rotate(RotateDirection direction)
+        {
+            //if (this.rotor01.)
+        }
+
+        void ChangeElevation(ElevationDirection direction)
+        {
+
+        }
+
+        void LockUnlock()
+        {
+            if (rotor01.Base)
+        }*/
+
+        public void Main(string argument, UpdateType updateSource)
+        {
+            if ((updateSource & UpdateType.Update100) != 0)
+            {
+                this.UpdateState();
+            }
+            else if ((updateSource & (UpdateType.Terminal | UpdateType.Trigger)) != 0)
+            {
+                switch (argument)
+                {
+                    case "UNPACK":
+                        this.Print("Unpacking...");
+                        this.currentState = State.UNPACKING;
+                        break;
+
+                    case "PACK":
+                        this.Print("Packing...");
+                        this.currentState = State.PACKING;
+                        break;
+
+                    case "STOP":
+                        this.currentState = State.DEFAULT;
+                        break;
+
+                    /*
+                    case "LOCK OR UNLOCK":
+                        LockUnlock();
+                        break;
+
+                    case "DOWN":
+                        ChangeElevation(ElevationDirection.DOWN);
+                        break;
+
+                    case "UP":
+                        ChangeElevation(ElevationDirection.UP);
+                        break;
+
+                    case "LEFT":
+                        Rotate(RotateDirection.LEFT);
+                        break;
+
+                    case "RIGHT":
+                        Rotate(RotateDirection.RIGHT);
+                        break;*/
+
+                    default:
+                        Echo($"Uknown command: {argument}");
+                        break;
+                }
+            }
+        }
+    }
+}
+
diff --git a/MiningRover/thumb.png b/MiningRover/thumb.png
new file mode 100644 (file)
index 0000000..5f05800
Binary files /dev/null and b/MiningRover/thumb.png differ
diff --git a/SECommon/Output.cs b/SECommon/Output.cs
new file mode 100644 (file)
index 0000000..5573c61
--- /dev/null
@@ -0,0 +1,105 @@
+using Sandbox.Game.EntityComponents;
+using Sandbox.ModAPI.Ingame;
+using Sandbox.ModAPI.Interfaces;
+
+using SpaceEngineers.Game.ModAPI.Ingame;
+
+using System;
+using System.Collections;
+using System.Collections.Generic;
+using System.Collections.Immutable;
+using System.Linq;
+using System.Text;
+
+using VRage;
+using VRage.Collections;
+using VRage.Game;
+using VRage.Game.Components;
+using VRage.Game.GUI.TextPanel;
+using VRage.Game.ModAPI.Ingame;
+using VRage.Game.ModAPI.Ingame.Utilities;
+using VRage.Game.ObjectBuilders.Definitions;
+
+using VRageMath;
+
+namespace IngameScript
+{
+    class Output
+    {
+        IList<IMyTextSurface> outputs;
+        int maxNbLines;
+
+        public Output(IList<IMyTextSurface> surfaces, int maxNbLines = 10)
+        {
+            foreach (var s in surfaces)
+            {
+                s.ContentType = ContentType.TEXT_AND_IMAGE;
+                s.WriteText("");
+            }
+
+            this.outputs = surfaces;
+            this.maxNbLines = maxNbLines;
+        }
+
+        public Output(IMyCockpit cockpit, int maxNbLines = 10)
+        {
+            this.outputs = new List<IMyTextSurface>();
+            for (int n = 0; n < cockpit.SurfaceCount; n++)
+            {
+                var surface = cockpit.GetSurface(n);
+                surface.ContentType = ContentType.TEXT_AND_IMAGE;
+                surface.WriteText("");
+                this.outputs.Add(surface);
+            }
+            this.maxNbLines = maxNbLines;
+        }
+
+        public Output(IMyTextSurface surface, int maxNbLines = 10)
+            : this(new List<IMyTextSurface> { surface }, maxNbLines)
+        { }
+
+        public void Print(string text, int outputNumber = 0)
+        {
+            if (this.outputs.Count() <= outputNumber)
+            {
+                throw new Exception($"Output number {outputNumber} doesn't exist (number of output: {this.outputs.Count()}");
+            }
+            else
+            {
+                var output = this.outputs[outputNumber];
+                var currentText = output.GetText();
+                var lines = currentText.Split('\n');
+                if (lines.Count() >= this.maxNbLines)
+                {
+                    output.WriteText(lines.Skip(lines.Count() - this.maxNbLines + 1).Append(text).Aggregate((a, b) => a + Environment.NewLine + b));
+                }
+                else if (lines.Count() == 0)
+                {
+                    output.WriteText(text);
+                }
+                else
+                {
+                    output.WriteText(Environment.NewLine + text, true);
+                }
+            }
+        }
+
+        public void PrintError(string text, int outputNumber = 0)
+        {
+            this.Print($"Error: {text}", outputNumber);
+        }
+
+
+        public void Display(string text, int outputNumber = 0)
+        {
+            if (this.outputs.Count() <= outputNumber)
+            {
+                throw new Exception($"Output number {outputNumber} doesn't exist (number of output: {this.outputs.Count()}");
+            }
+            else
+            {
+                this.outputs[outputNumber].WriteText(text);
+            }
+        }
+    }
+}
\ No newline at end of file
diff --git a/SECommon/SECommon.projitems b/SECommon/SECommon.projitems
new file mode 100644 (file)
index 0000000..ab9ad4d
--- /dev/null
@@ -0,0 +1,14 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <PropertyGroup>
+    <MSBuildAllProjects Condition="'$(MSBuildVersion)' == '' Or '$(MSBuildVersion)' &lt; '16.0'">$(MSBuildAllProjects);$(MSBuildThisFileFullPath)</MSBuildAllProjects>
+    <HasSharedItems>true</HasSharedItems>
+    <SharedGUID>9e97399c-4fe6-495b-aa87-acc2213647cd</SharedGUID>
+  </PropertyGroup>
+  <PropertyGroup Label="Configuration">
+    <Import_RootNamespace>SECommon</Import_RootNamespace>
+  </PropertyGroup>
+  <ItemGroup>
+    <Compile Include="$(MSBuildThisFileDirectory)Output.cs" />
+  </ItemGroup>
+</Project>
\ No newline at end of file
diff --git a/SECommon/SECommon.shproj b/SECommon/SECommon.shproj
new file mode 100644 (file)
index 0000000..45d6524
--- /dev/null
@@ -0,0 +1,13 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <PropertyGroup Label="Globals">
+    <ProjectGuid>9e97399c-4fe6-495b-aa87-acc2213647cd</ProjectGuid>
+    <MinimumVisualStudioVersion>14.0</MinimumVisualStudioVersion>
+  </PropertyGroup>
+  <Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
+  <Import Project="$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)\CodeSharing\Microsoft.CodeSharing.Common.Default.props" />
+  <Import Project="$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)\CodeSharing\Microsoft.CodeSharing.Common.props" />
+  <PropertyGroup />
+  <Import Project="SECommon.projitems" Label="Shared" />
+  <Import Project="$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)\CodeSharing\Microsoft.CodeSharing.CSharp.targets" />
+</Project>
diff --git a/SEScripts.sln b/SEScripts.sln
new file mode 100644 (file)
index 0000000..a4defba
--- /dev/null
@@ -0,0 +1,37 @@
+
+Microsoft Visual Studio Solution File, Format Version 12.00
+# Visual Studio Version 17
+VisualStudioVersion = 17.7.34024.191
+MinimumVisualStudioVersion = 10.0.40219.1
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "BaseApp", "BaseMiner\BaseApp.csproj", "{22A83955-FE9B-4EBA-8980-D9DE01353C4C}"
+EndProject
+Project("{D954291E-2A0B-460D-934E-DC6B0785DB48}") = "SECommon", "SECommon\SECommon.shproj", "{9E97399C-4FE6-495B-AA87-ACC2213647CD}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AutoPilot", "AutoPilot\AutoPilot.csproj", "{141E1804-F644-48F8-A3D8-BEFEEE66ECBA}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MiningRover", "MiningRover\MiningRover.csproj", "{DBCD62FE-F7AA-4A03-9241-0A4BE6952664}"
+EndProject
+Global
+       GlobalSection(SolutionConfigurationPlatforms) = preSolution
+               Debug|x64 = Debug|x64
+       EndGlobalSection
+       GlobalSection(ProjectConfigurationPlatforms) = postSolution
+               {22A83955-FE9B-4EBA-8980-D9DE01353C4C}.Debug|x64.ActiveCfg = Debug|x64
+               {22A83955-FE9B-4EBA-8980-D9DE01353C4C}.Debug|x64.Build.0 = Debug|x64
+               {141E1804-F644-48F8-A3D8-BEFEEE66ECBA}.Debug|x64.ActiveCfg = Debug|x64
+               {141E1804-F644-48F8-A3D8-BEFEEE66ECBA}.Debug|x64.Build.0 = Debug|x64
+               {DBCD62FE-F7AA-4A03-9241-0A4BE6952664}.Debug|x64.ActiveCfg = Debug|x64
+               {DBCD62FE-F7AA-4A03-9241-0A4BE6952664}.Debug|x64.Build.0 = Debug|x64
+       EndGlobalSection
+       GlobalSection(SolutionProperties) = preSolution
+               HideSolutionNode = FALSE
+       EndGlobalSection
+       GlobalSection(ExtensibilityGlobals) = postSolution
+               SolutionGuid = {F4600B8D-80EE-4075-8A61-BE8847A00BD7}
+       EndGlobalSection
+       GlobalSection(SharedMSBuildProjectFiles) = preSolution
+               SECommon\SECommon.projitems*{141e1804-f644-48f8-a3d8-befeee66ecba}*SharedItemsImports = 4
+               SECommon\SECommon.projitems*{22a83955-fe9b-4eba-8980-d9de01353c4c}*SharedItemsImports = 4
+               SECommon\SECommon.projitems*{9e97399c-4fe6-495b-aa87-acc2213647cd}*SharedItemsImports = 13
+       EndGlobalSection
+EndGlobal
diff --git a/thumb.png b/thumb.png
new file mode 100644 (file)
index 0000000..5f05800
Binary files /dev/null and b/thumb.png differ