XFE Git
XFE Studio Git
Git 首页 全局搜索
XFE 主站 文档 NuGet

AutoMiningScript

【SpaceEngineer】全自动挖矿脚本

公开
关注 0 Fork 0 Star 0
UTF-8
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using Sandbox.ModAPI.Ingame;
using VRage.Game.ModAPI.Ingame;
using VRage.Game.ModAPI.Ingame.Utilities;
using VRageMath;
using Xunit;
using P=AutoMiningScript.Program;

namespace AutoMiningScript.Tests
{
    public class AutomaticHomeTests
    {
        const BindingFlags Private=BindingFlags.Instance|BindingFlags.NonPublic;
        static T Read<T>(object o,string key) {return (T)o.GetType().GetField(key,Private).GetValue(o);}
        static void Write(object o,string key,object value) {o.GetType().GetField(key,Private).SetValue(o,value);}
        static object Fill(object[] args,IEnumerable<IMyTerminalBlock> blocks)
        {
            var list=(IList)args[0];var type=list.GetType().GetGenericArguments()[0];var filter=args.Length>1?args[1] as Delegate:null;
            foreach(var block in blocks)if(type.IsInstanceOfType(block)&&(filter==null||(bool)filter.DynamicInvoke(block)))list.Add(block);
            return null;
        }
        sealed class HardwareRig
        {
            public readonly FleetStateTests.Rig Base=new FleetStateTests.Rig(0,false);
            public readonly Dictionary<string,IMyBlockGroup> Groups=new Dictionary<string,IMyBlockGroup>();
            public readonly List<IMyTerminalBlock> Blocks=new List<IMyTerminalBlock>();
            public readonly IMyShipConnector Port,ForeignPort;
            public readonly IMyCargoContainer Cargo;
            public P.FleetController Fleet;
            public HardwareRig(string dockGroup,string cargoGroup,string actualDock,string actualCargo)
            {
                var p=Base.Program;p.Config=new P.Settings("[Fleet]\nDockGroup="+dockGroup+"\nCargoGroup="+cargoGroup,"fleet","base");
                Port=new Stub<IMyShipConnector>().Set("CubeGrid",p.Me.CubeGrid).Set("IsFunctional",true).Set("EntityId",100L).Set("WorldMatrix",MatrixD.Identity).Value;
                ForeignPort=new Stub<IMyShipConnector>().Set("CubeGrid",new Stub<IMyCubeGrid>().Value).Set("EntityId",999L).Value;
                Cargo=new Stub<IMyCargoContainer>().Set("CubeGrid",p.Me.CubeGrid).Set("HasInventory",true).Value;
                var foreignCargo=new Stub<IMyCargoContainer>().Set("CubeGrid",ForeignPort.CubeGrid).Set("HasInventory",true).Value;
                Blocks.Add(new Stub<IMyShipController>().Set("CubeGrid",p.Me.CubeGrid).Set("IsFunctional",true).Set("WorldMatrix",MatrixD.Identity).Value);
                Blocks.Add(Port);Blocks.Add(Cargo);Blocks.Add(ForeignPort);Blocks.Add(foreignCargo);
                if(actualDock!=null)Groups[actualDock]=Group(actualDock,new IMyTerminalBlock[]{Port,ForeignPort});
                if(actualCargo!=null)Groups[actualCargo]=Group(actualCargo,new IMyTerminalBlock[]{Cargo,foreignCargo});
                TestRig.SetBase(p,"GridTerminalSystem",new Stub<IMyGridTerminalSystem>()
                    .Method("GetBlockGroupWithName",a=>{IMyBlockGroup group;return Groups.TryGetValue((string)a[0],out group)?group:null;})
                    .Method("GetBlocksOfType",a=>Fill(a,Blocks)).Value);
                Fleet=new P.FleetController(p);
            }
            public IMyBlockGroup Group(string name,IMyTerminalBlock[] blocks)
            {return new Stub<IMyBlockGroup>().Set("Name",name).Method("GetBlocksOfType",a=>Fill(a,blocks)).Method("GetBlocks",a=>Fill(a,blocks)).Value;}
        }

        [Theory]
        [InlineData(false)]
        [InlineData(true)]
        public void DefaultLocalizedAndOriginalGroupsResolveWithoutIncludingDockedMinerHardware(bool reverse)
        {
            var d=P.Settings.DefaultName("AMS Docks");var c=P.Settings.DefaultName("AMS Cargo");
            var r=new HardwareRig(reverse?"AMS Docks":d,reverse?"AMS Cargo":c,reverse?d:"AMS Docks",reverse?c:"AMS Cargo");
            Assert.Same(r.Port,Assert.Single(Read<List<IMyShipConnector>>(r.Fleet,"docks")));
            Assert.Same(r.Cargo,Assert.Single(Read<List<IMyTerminalBlock>>(r.Fleet,"cargo")));
            Assert.DoesNotContain(P.L.FleetCargoMissing,r.Fleet.Diagnostics);Assert.DoesNotContain(P.L.FleetBerthsMissing,r.Fleet.Diagnostics);
        }

        [Fact]
        public void CustomGroupNamesAreNotSilentlyReplacedByUnrelatedDefaults()
        {
            var r=new HardwareRig("Reserved Mining Ports","Selected Cargo","AMS Docks","AMS Cargo");
            Assert.Empty(Read<List<IMyShipConnector>>(r.Fleet,"docks"));Assert.Empty(Read<List<IMyTerminalBlock>>(r.Fleet,"cargo"));
            Assert.Contains("Reserved Mining Ports",r.Fleet.Diagnostics);Assert.Contains("Selected Cargo",r.Fleet.Diagnostics);
            r.Groups["Reserved Mining Ports"]=r.Group("Reserved Mining Ports",new IMyTerminalBlock[]{r.Port});
            r.Groups["Selected Cargo"]=r.Group("Selected Cargo",new IMyTerminalBlock[]{r.Cargo});
            r.Fleet.Command("rescan");Assert.Single(Read<List<IMyShipConnector>>(r.Fleet,"docks"));Assert.Single(Read<List<IMyTerminalBlock>>(r.Fleet,"cargo"));
        }

        [Fact]
        public void AnExistingExplicitGroupTakesPrecedenceOverDefaultAlias()
        {
            var name=P.Settings.DefaultName("AMS Docks");if(name=="AMS Docks")return;
            var r=new HardwareRig(name,P.Settings.DefaultName("AMS Cargo"),"AMS Docks","AMS Cargo");
            r.Groups[name]=r.Group(name,new IMyTerminalBlock[]{r.ForeignPort});r.Fleet.Command("rescan");
            Assert.Empty(Read<List<IMyShipConnector>>(r.Fleet,"docks"));
        }

        [Fact]
        public void MissingPortConfigurationIsDeliveredToTheWaitingMinerAndRecoversOnRescan()
        {
            var r=new HardwareRig("Selected Ports","Selected Cargo",null,null);var miner=new MinerStateTests.MinerRig();miner.State(P.FlightState.Returning);
            for(int i=0;i<12;i++){r.Base.Program.Now+=.1;r.Fleet.Tick(.1);}
            var broadcast=r.Base.Sent.Last(p=>p.Kind=="BASE");miner.Miner.Receive(broadcast);miner.Miner.Tick(.1);
            Assert.Contains("Selected Ports",Read<string>(miner.Miner,"reason"));Assert.Contains("Selected Ports",miner.Miner.Diagnostics);
            Assert.Equal(P.FlightState.Returning,miner.StateNow);
            Assert.All(miner.Hardware.Thrusters,t=>Assert.Equal(0f,t.ThrustOverridePercentage));
            Assert.False(Read<P.FlightController>(miner.Miner,"flight").HasRoute);
            r.Groups["Selected Ports"]=r.Group("Selected Ports",new IMyTerminalBlock[]{r.Port});r.Fleet.Command("rescan");
            for(int i=0;i<12;i++){r.Base.Program.Now+=.1;r.Fleet.Tick(.1);}
            Assert.Equal("",P.DockFrame.FromIni(r.Base.Sent.Last(p=>p.Kind=="BASE").Body).Problem);
        }

        [Fact]
        public void SixPortLocalizedDeploymentGrantsBothAirborneMinersWhileFleetIsPaused()
        {
            var r=new FleetStateTests.Rig(6,true,"[Fleet]\nDockGroup="+P.Settings.DefaultName("AMS Docks"));
            foreach(int n in new[]{2,3}) {r.SetConnected(n,false);r.Miners[n].State=P.FlightState.Returning;r.Miners[n].Position+=new Vector3D(0,0,-100);}
            r.RegisterAll();r.Tick(30);
            foreach(int n in new[]{2,3})r.Receive("DOCK_REQUEST",r.Miners[n]);
            r.Tick(25);var grants=r.Sent.Where(p=>p.Kind=="DOCK_GRANT").ToList();
            Assert.Equal(2,grants.Count);Assert.Equal(2,grants.Select(p=>P.DockFrame.FromIni(p.Body).ConnectorId).Distinct().Count());
        }

        [Fact]
        public void AConfiguredIdleMinerStartsReturnAndRestoresFlightPowerWithoutAUserCommand()
        {
            var r=new MinerStateTests.MinerRig();r.State(P.FlightState.Paused);Write(r.Miner,"running",false);
            r.Hardware.Batteries[0].ChargeMode=ChargeMode.Recharge;
            var tank=new Stub<IMyGasTank>().Set("CubeGrid",r.Program.Me.CubeGrid).Set("Stockpile",true);r.Hardware.Tanks.Add(tank.Value);
            r.Miner.Tick(.1);
            Assert.Equal(P.FlightState.Returning,r.StateNow);Assert.Contains(r.Sent,p=>p.Kind=="DOCK_REQUEST");
            Assert.Equal(ChargeMode.Auto,r.Hardware.Batteries[0].ChargeMode);Assert.False(tank.Value.Stockpile);
            Assert.False(Read<bool>(r.Miner,"calibrated"));Assert.False(Read<bool>(r.Miner,"running"));
        }

        [Theory]
        [InlineData("pause")]
        [InlineData("release")]
        public void AutomaticReturnNeverOverridesExplicitStopOrManualControl(string command)
        {
            var r=new MinerStateTests.MinerRig();r.Miner.Command(command);var state=r.StateNow;r.Sent.Clear();r.Miner.Tick(.1);
            Assert.Equal(state,r.StateNow);Assert.DoesNotContain(r.Sent,p=>p.Kind=="DOCK_REQUEST");
            var saved=new MyIni();r.Miner.Save(saved);var restart=new MinerStateTests.MinerRig();restart.Miner.Load(saved);restart.Miner.Tick(.1);
            Assert.DoesNotContain(restart.Sent,p=>p.Kind=="DOCK_REQUEST");
        }

        [Theory]
        [InlineData(P.FlightState.Returning)]
        [InlineData(P.FlightState.Holding)]
        [InlineData(P.FlightState.DockAlign)]
        [InlineData(P.FlightState.DockApproach)]
        [InlineData(P.FlightState.DockRetreat)]
        public void ReloadOfReturnNavigationReacquiresBerthWithoutRequiringResume(P.FlightState phase)
        {
            var r=new MinerStateTests.MinerRig();r.State(phase);Write(r.Miner,"manualStop",true);
            var saved=new MyIni();r.Miner.Save(saved);var restart=new MinerStateTests.MinerRig();restart.Miner.Load(saved);
            Assert.False(Read<bool>(restart.Miner,"leaseConfirmed"));Assert.Equal("",Read<string>(restart.Miner,"lane"));
            restart.Miner.Tick(.1);Assert.Equal(P.FlightState.Returning,restart.StateNow);Assert.Contains(restart.Sent,p=>p.Kind=="DOCK_REQUEST");
        }

        [Fact]
        public void RecoveryInsideBoreStartsAlongTheSavedExitInsteadOfTurningTowardBase()
        {
            var r=new MinerStateTests.MinerRig();r.Task(9);r.State(P.FlightState.Retreat);Write(r.Miner,"insideBore",true);
            var saved=new MyIni();r.Miner.Save(saved);var restart=new MinerStateTests.MinerRig();restart.Miner.Load(saved);
            restart.Miner.Tick(.1);Assert.Equal(P.FlightState.Retreat,restart.StateNow);
            Assert.Equal(Vector3D.Forward,Assert.Single(restart.Miner.GetJobs()).Direction);Assert.False(restart.Drill.Value.Enabled);
        }
    }
}