using System;
using System.Collections.Generic;
using Sandbox.ModAPI.Ingame;
using VRage.Game.ModAPI.Ingame;
using VRage.Game.ModAPI.Ingame.Utilities;
using VRageMath;
namespace AutoMiningScript
{
public partial class Program
{
public static class Marking
{
public static double Number(string text)
{
double n;if(!double.TryParse(text,System.Globalization.NumberStyles.Float,Data.Culture,out n)||!Data.Finite(n)) throw Data.Invalid(L.F(L.FleetNumericArgumentInvalid,text));return n;
}
public static MyIni Parse(Program p,string command)
{
command=Settings.NormalizeCommand(command);
int gps=command.IndexOf("GPS:",Data.Ordinal);
var prefix=gps<0?command:command.Substring(0,gps);
var parts=prefix.Trim().Split(new[]{' '},StringSplitOptions.RemoveEmptyEntries);
if(parts.Length!=4) throw Data.Invalid(L.FleetMarkUsage);
double width=Number(parts[1]),height=Number(parts[2]),depth=Number(parts[3]);
if(width<=0||height<=0||depth<=0||width>1000||height>1000||depth>1000) throw Data.Invalid(L.FleetMarkDimensions);
Vector3D entry,direction,up=p.Me.WorldMatrix.Up;
if(gps>=0)
{
int second=command.IndexOf("GPS:",gps+4,Data.Ordinal);Vector3D inside;
if(second<0||!Data.TryGps(command.Substring(gps,second-gps),out entry)||!Data.TryGps(command.Substring(second),out inside)) throw Data.Invalid(L.FleetTwoGpsRequired);
direction=inside-entry;if(direction.LengthSquared()<0.01) throw Data.Invalid(L.FleetGpsPointsDiffer);
}
else
{
var name=p.Config.Text("Marker","Camera","");var cameras=new List<IMyCameraBlock>();
p.GridTerminalSystem.GetBlocksOfType(cameras,c=>c.CubeGrid==p.Me.CubeGrid&&c.IsFunctional&&(name.Length==0||c.CustomName==name));
if(cameras.Count==0) throw Data.Invalid(L.FleetMarkerCameraMissing);
var camera=cameras[0];camera.EnableRaycast=true;
var distance=p.Config.Number("Marker","ScanDistance",1000,10,10000);
if(!camera.CanScan(distance)) throw Data.Invalid(L.F(L.FleetMarkerCameraCharging,camera.AvailableScanRange));
var hit=camera.Raycast(distance);
if(hit.IsEmpty()||!hit.HitPosition.HasValue||(hit.Type!=MyDetectedEntityType.Asteroid&&hit.Type!=MyDetectedEntityType.Planet)) throw Data.Invalid(L.FleetMarkerSurfaceRequired);
entry=hit.HitPosition.Value;direction=entry-camera.GetPosition();up=camera.WorldMatrix.Up;
}
var i=new MyIni();Data.PutVector(i,"mark","Entry",entry);i.Set("mark","Direction",Data.Vector(Data.Unit(direction,Data.Forward)));i.Set("mark","Up",Data.Vector(Data.Perpendicular(direction,up)));
i.Set("mark","Width",width);i.Set("mark","Height",height);i.Set("mark","Depth",depth);return i;
}
}
public class MarkerController : RoleLogic
{
string last=L.FleetMarkerGuidance;
string lastStatus="Guidance",lastWidth="",lastHeight="",lastDepth="",lastEntry="";
public MarkerController(Program p):base(p) {EnableCameras();}
void EnableCameras()
{
var cameras=new List<IMyCameraBlock>();P.GridTerminalSystem.GetBlocksOfType(cameras,c=>c.CubeGrid==P.Me.CubeGrid);
foreach(var camera in cameras) camera.EnableRaycast=true;
}
public override string Diagnostics => L.F(L.FleetMarkerDiagnostics,P.Config.BaseId,last);
public override void Receive(Packet packet)
{
if(packet.From!=P.Config.BaseId || packet.Epoch<=P.Bus.Epoch)return;
P.Bus.Epoch=packet.Epoch;P.Bus.CancelPending(null,P.Config.BaseId);lastStatus="Guidance";UpdateLast();
}
public override void Command(string command)
{
command=Settings.NormalizeCommand(command);
var parts=command.Trim().Split(new[]{' '},StringSplitOptions.RemoveEmptyEntries);if(parts.Length==0) return;
var verb=parts[0].ToLowerInvariant();
if(verb=="init"||verb=="rescan"||verb=="diagnose") {EnableCameras();P.Log(Diagnostics);return;}
if(verb=="mark")
{
var body=Marking.Parse(P,command);P.Bus.Send("MARK",P.Config.BaseId,body,true);
lastStatus="Manual";lastWidth=Data.Text(body,"mark","Width");lastHeight=Data.Text(body,"mark","Height");lastDepth=Data.Text(body,"mark","Depth");lastEntry=Data.Text(body,"mark","Entry");UpdateLast();P.Log(last);return;
}
if(verb=="survey")
{
var radius=parts.Length>1?Marking.Number(parts[1]):0;if(radius!=0&&(radius<20||radius>20000)) throw Data.Invalid(L.FleetSurveyRadius);
var body=new MyIni();body.Set("survey","Radius",radius);P.Bus.Send("SURVEY_REQUEST",P.Config.BaseId,body,true);lastStatus="Survey";UpdateLast();P.Log(last);return;
}
P.Log(L.FleetMarkerCommands);
}
void UpdateLast()
{
last=lastStatus=="Manual"?L.F(L.FleetMarkerSubmitted,lastWidth,lastHeight,lastDepth,lastEntry):lastStatus=="Survey"?L.FleetMarkerSurveySubmitted:L.FleetMarkerGuidance;
}
public override void Save(MyIni ini)
{
ini.Set("marker","FleetEpoch",P.Bus.Epoch);
ini.Set("marker","Last",last);ini.Set("marker","Status",lastStatus);ini.Set("marker","Width",lastWidth);ini.Set("marker","Height",lastHeight);ini.Set("marker","Depth",lastDepth);ini.Set("marker","Entry",lastEntry);
}
public override void Load(MyIni ini)
{
var epoch=Data.ReadLong(ini,"marker","FleetEpoch");if(epoch<0 || epoch>DateTime.MaxValue.Ticks)throw Data.Invalid("marker.FleetEpoch");P.Bus.Epoch=epoch;
// Persist stable status tokens so replacing the script's language changes the UI immediately.
lastStatus=ini.Get("marker","Status").ToString("Guidance");lastWidth=Data.Text(ini,"marker","Width");lastHeight=Data.Text(ini,"marker","Height");lastDepth=Data.Text(ini,"marker","Depth");lastEntry=Data.Text(ini,"marker","Entry");UpdateLast();
}
}
}
}
using System;
using System.Collections.Generic;
using Sandbox.ModAPI.Ingame;
using VRage.Game.ModAPI.Ingame;
using VRage.Game.ModAPI.Ingame.Utilities;
using VRageMath;
namespace AutoMiningScript
{
public partial class Program
{
public static class Marking
{
public static double Number(string text)
{
double n;if(!double.TryParse(text,System.Globalization.NumberStyles.Float,Data.Culture,out n)||!Data.Finite(n)) throw Data.Invalid(L.F(L.FleetNumericArgumentInvalid,text));return n;
}
public static MyIni Parse(Program p,string command)
{
command=Settings.NormalizeCommand(command);
int gps=command.IndexOf("GPS:",Data.Ordinal);
var prefix=gps<0?command:command.Substring(0,gps);
var parts=prefix.Trim().Split(new[]{' '},StringSplitOptions.RemoveEmptyEntries);
if(parts.Length!=4) throw Data.Invalid(L.FleetMarkUsage);
double width=Number(parts[1]),height=Number(parts[2]),depth=Number(parts[3]);
if(width<=0||height<=0||depth<=0||width>1000||height>1000||depth>1000) throw Data.Invalid(L.FleetMarkDimensions);
Vector3D entry,direction,up=p.Me.WorldMatrix.Up;
if(gps>=0)
{
int second=command.IndexOf("GPS:",gps+4,Data.Ordinal);Vector3D inside;
if(second<0||!Data.TryGps(command.Substring(gps,second-gps),out entry)||!Data.TryGps(command.Substring(second),out inside)) throw Data.Invalid(L.FleetTwoGpsRequired);
direction=inside-entry;if(direction.LengthSquared()<0.01) throw Data.Invalid(L.FleetGpsPointsDiffer);
}
else
{
var name=p.Config.Text("Marker","Camera","");var cameras=new List<IMyCameraBlock>();
p.GridTerminalSystem.GetBlocksOfType(cameras,c=>c.CubeGrid==p.Me.CubeGrid&&c.IsFunctional&&(name.Length==0||c.CustomName==name));
if(cameras.Count==0) throw Data.Invalid(L.FleetMarkerCameraMissing);
var camera=cameras[0];camera.EnableRaycast=true;
var distance=p.Config.Number("Marker","ScanDistance",1000,10,10000);
if(!camera.CanScan(distance)) throw Data.Invalid(L.F(L.FleetMarkerCameraCharging,camera.AvailableScanRange));
var hit=camera.Raycast(distance);
if(hit.IsEmpty()||!hit.HitPosition.HasValue||(hit.Type!=MyDetectedEntityType.Asteroid&&hit.Type!=MyDetectedEntityType.Planet)) throw Data.Invalid(L.FleetMarkerSurfaceRequired);
entry=hit.HitPosition.Value;direction=entry-camera.GetPosition();up=camera.WorldMatrix.Up;
}
var i=new MyIni();Data.PutVector(i,"mark","Entry",entry);i.Set("mark","Direction",Data.Vector(Data.Unit(direction,Data.Forward)));i.Set("mark","Up",Data.Vector(Data.Perpendicular(direction,up)));
i.Set("mark","Width",width);i.Set("mark","Height",height);i.Set("mark","Depth",depth);return i;
}
}
public class MarkerController : RoleLogic
{
string last=L.FleetMarkerGuidance;
string lastStatus="Guidance",lastWidth="",lastHeight="",lastDepth="",lastEntry="";
public MarkerController(Program p):base(p) {EnableCameras();}
void EnableCameras()
{
var cameras=new List<IMyCameraBlock>();P.GridTerminalSystem.GetBlocksOfType(cameras,c=>c.CubeGrid==P.Me.CubeGrid);
foreach(var camera in cameras) camera.EnableRaycast=true;
}
public override string Diagnostics => L.F(L.FleetMarkerDiagnostics,P.Config.BaseId,last);
public override void Receive(Packet packet)
{
if(packet.From!=P.Config.BaseId || packet.Epoch<=P.Bus.Epoch)return;
P.Bus.Epoch=packet.Epoch;P.Bus.CancelPending(null,P.Config.BaseId);lastStatus="Guidance";UpdateLast();
}
public override void Command(string command)
{
command=Settings.NormalizeCommand(command);
var parts=command.Trim().Split(new[]{' '},StringSplitOptions.RemoveEmptyEntries);if(parts.Length==0) return;
var verb=parts[0].ToLowerInvariant();
if(verb=="init"||verb=="rescan"||verb=="diagnose") {EnableCameras();P.Log(Diagnostics);return;}
if(verb=="mark")
{
var body=Marking.Parse(P,command);P.Bus.Send("MARK",P.Config.BaseId,body,true);
lastStatus="Manual";lastWidth=Data.Text(body,"mark","Width");lastHeight=Data.Text(body,"mark","Height");lastDepth=Data.Text(body,"mark","Depth");lastEntry=Data.Text(body,"mark","Entry");UpdateLast();P.Log(last);return;
}
if(verb=="survey")
{
var radius=parts.Length>1?Marking.Number(parts[1]):0;if(radius!=0&&(radius<20||radius>20000)) throw Data.Invalid(L.FleetSurveyRadius);
var body=new MyIni();body.Set("survey","Radius",radius);P.Bus.Send("SURVEY_REQUEST",P.Config.BaseId,body,true);lastStatus="Survey";UpdateLast();P.Log(last);return;
}
P.Log(L.FleetMarkerCommands);
}
void UpdateLast()
{
last=lastStatus=="Manual"?L.F(L.FleetMarkerSubmitted,lastWidth,lastHeight,lastDepth,lastEntry):lastStatus=="Survey"?L.FleetMarkerSurveySubmitted:L.FleetMarkerGuidance;
}
public override void Save(MyIni ini)
{
ini.Set("marker","FleetEpoch",P.Bus.Epoch);
ini.Set("marker","Last",last);ini.Set("marker","Status",lastStatus);ini.Set("marker","Width",lastWidth);ini.Set("marker","Height",lastHeight);ini.Set("marker","Depth",lastDepth);ini.Set("marker","Entry",lastEntry);
}
public override void Load(MyIni ini)
{
var epoch=Data.ReadLong(ini,"marker","FleetEpoch");if(epoch<0 || epoch>DateTime.MaxValue.Ticks)throw Data.Invalid("marker.FleetEpoch");P.Bus.Epoch=epoch;
// Persist stable status tokens so replacing the script's language changes the UI immediately.
lastStatus=ini.Get("marker","Status").ToString("Guidance");lastWidth=Data.Text(ini,"marker","Width");lastHeight=Data.Text(ini,"marker","Height");lastDepth=Data.Text(ini,"marker","Depth");lastEntry=Data.Text(ini,"marker","Entry");UpdateLast();
}
}
}
}