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

AutoMiningScript

【SpaceEngineer】全自动挖矿脚本

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

namespace AutoMiningScript.Tests
{
    public class CarouselTests
    {
        static int ConfigurationPageCount { get { return DisplayLocalizationTests.ConfigurationPageCount(4); } }

        sealed class DashboardRole : P.RoleLogic
        {
            public readonly List<P.Telemetry> Fleet = new List<P.Telemetry>();
            public readonly List<P.Job> Jobs = new List<P.Job>();
            public DashboardRole(P program) : base(program) { }
            public override List<P.Telemetry> GetTelemetry() { return Fleet; }
            public override List<P.Job> GetJobs() { return Jobs; }
        }

        // Capture actual frames from each surface. Tests deliberately avoid private carousel
        // fields so they verify what the player sees as telemetry and simulation time change.
        sealed class Rig
        {
            public readonly P Program;
            public readonly P.Dashboard Dashboard;
            public readonly DashboardRole Role;
            public readonly Stub<IMyProgrammableBlock> Block;
            public readonly List<MySprite>[] Frames = { new List<MySprite>(), new List<MySprite>() };

            public Rig(string config = "")
            {
                Program = TestRig.Program(config);
                var main = Surface(0); var auxiliary = Surface(1);
                Block = new Stub<IMyProgrammableBlock>()
                    .Set("EntityId", 20L).Set("CubeGrid", Program.Me.CubeGrid)
                    .Set("CustomName", "Programming block").Set("CustomData", config).Set("SurfaceCount", 2)
                    .Method("GetSurface", args => (int)args[0] == 0 ? main.Value : auxiliary.Value);
                TestRig.SetBase(Program, "Me", Block.Value);
                TestRig.SetBase(Program, "GridTerminalSystem", new Stub<IMyGridTerminalSystem>().Value);
                Dashboard = new P.Dashboard(Program); Role = new DashboardRole(Program);
            }

            Stub<IMyTextSurface> Surface(int index)
            {
                return new Stub<IMyTextSurface>().Set("TextureSize", new Vector2(512, 512))
                    .Set("SurfaceSize", new Vector2(512, 512))
                    .Method("MeasureStringInPixels", args => new Vector2(args[0].ToString().Sum(c => c >= 0x2e80 ? 32 : 16), 32) * (float)args[2])
                    .Method("DrawFrame", args => new MySpriteDrawFrame(frame =>
                    {
                        Frames[index].Clear(); frame.AddToList(Frames[index]);
                    }));
            }

            public void Draw(double now)
            {
                Program.Now = now;
                foreach (var telemetry in Role.Fleet) telemetry.ReceivedAt = now;
                Dashboard.Draw(Role);
            }

            public void Command(double now, string command) { Program.Now = now; Dashboard.Command(command); }
            public string[] Text(int surface = 0) { return Frames[surface].Where(s => s.Type == SpriteType.TEXT).Select(s => s.Data).ToArray(); }
            public void AssertConfig(int page, int surface = 0) { Assert.Contains(P.L.F(P.L.DisplayConfigPages, page, ConfigurationPageCount), Text(surface)); }
            public void Miners(params string[] ids)
            {
                foreach (string id in ids) Role.Fleet.Add(new P.Telemetry { Id = id, State = P.FlightState.Ready });
            }
        }

        [Fact]
        public void ConfigurationStartsAtFirstSlideAndAutomaticallyWrapsEveryEightSeconds()
        {
            var rig = new Rig();
            rig.Draw(0); rig.AssertConfig(1);
            rig.Draw(7.99); rig.AssertConfig(1);
            for (int page = 2; page <= ConfigurationPageCount; page++)
            {
                rig.Draw((page - 1) * 8); rig.AssertConfig(page);
            }
            rig.Draw(ConfigurationPageCount * 8); rig.AssertConfig(1);
        }

        [Fact]
        public void FirstVisibleFrameStartsItsOwnFullDwell()
        {
            var rig = new Rig();
            rig.Draw(100); rig.AssertConfig(1);
            rig.Draw(107.99); rig.AssertConfig(1);
            rig.Draw(108); rig.AssertConfig(2);
        }

        [Fact]
        public void LongRenderingPauseAdvancesOnlyOneSlideAndRestartsDwell()
        {
            var rig = new Rig();
            rig.Draw(0);
            rig.Draw(60); rig.AssertConfig(2);
            rig.Draw(60); rig.AssertConfig(2);
            rig.Draw(67.99); rig.AssertConfig(2);
            rig.Draw(68); rig.AssertConfig(3);
        }

        [Fact]
        public void DisabledCarouselStillAllowsManualPaging()
        {
            var rig = new Rig("[Display]\nAutoPage=false\n");
            rig.Draw(0); rig.Draw(90); rig.AssertConfig(1);
            rig.Command(90, "page +"); rig.Draw(90); rig.AssertConfig(2);
            rig.Draw(200); rig.AssertConfig(2);
        }

        [Theory]
        [InlineData(false, true, 2)]
        [InlineData(true, false, 1)]
        public void ScreenAutoPageSettingOverridesGlobalSetting(bool global, bool screen, int expected)
        {
            var rig = new Rig("[Display]\nAutoPage=" + global + "\n[AMS.Screen]\nAutoPage=" + screen + "\n");
            rig.Draw(0); rig.Draw(8); rig.AssertConfig(expected);
        }

        [Fact]
        public void SurfacesKeepIndependentIntervalsAndSlideCursors()
        {
            var rig = new Rig("[Display]\nPageInterval=10\n[AMS.Screen]\nPageInterval=4\n[AMS.Screen.1]\nEnabled=true\nPage=config\n");
            rig.Draw(0); Assert.Equal(2, rig.Dashboard.ScreenCount);
            rig.AssertConfig(1); rig.AssertConfig(1, 1);
            rig.Draw(4); rig.AssertConfig(2); rig.AssertConfig(1, 1);
            rig.Draw(8); rig.AssertConfig(3); rig.AssertConfig(1, 1);
            rig.Draw(10); rig.AssertConfig(3); rig.AssertConfig(2, 1);
        }

        [Fact]
        public void ManualPagingHoldsThenRestartsACompleteInterval()
        {
            var rig = new Rig();
            rig.Draw(0); rig.Command(5, "page +");
            rig.Draw(5); rig.AssertConfig(2);
            rig.Draw(24.99); rig.AssertConfig(2);
            rig.Draw(25); rig.AssertConfig(2);
            rig.Draw(32.99); rig.AssertConfig(2);
            rig.Draw(33); rig.AssertConfig(3);
        }

        [Fact]
        public void RepeatedManualInputRenewsTheReadingPause()
        {
            var rig = new Rig(); rig.Draw(0);
            rig.Command(5, "page +"); rig.Draw(5);
            rig.Command(20, "page +"); rig.Draw(20); rig.AssertConfig(3);
            rig.Draw(47.99); rig.AssertConfig(3);
            rig.Draw(48); rig.AssertConfig(4);
        }

        [Theory]
        [InlineData(0, 8)]
        [InlineData(4, 12)]
        public void PerSurfaceManualHoldOverridesGlobalDefault(int hold, int nextAdvance)
        {
            var rig = new Rig("[AMS.Screen]\nManualHoldSeconds=" + hold + "\n");
            rig.Draw(0); rig.Command(0, "page +"); rig.Draw(0);
            rig.Draw(nextAdvance - .01); rig.AssertConfig(2);
            rig.Draw(nextAdvance); rig.AssertConfig(3);
        }

        [Fact]
        public void ManualPreviousWrapsAndCommandsBeforeDiscoveryAreRetained()
        {
            var rig = new Rig();
            rig.Command(0, "page -"); rig.Draw(0); rig.AssertConfig(ConfigurationPageCount);
            rig.Command(1, "page +"); rig.Draw(1); rig.AssertConfig(1);
        }

        [Fact]
        public void StopFreezesTheSlideAndPlayResumesWithFreshDwell()
        {
            var rig = new Rig();
            rig.Draw(0); rig.Draw(8); rig.AssertConfig(2);
            rig.Command(9, "page stop"); rig.Draw(80); rig.AssertConfig(2);
            rig.Command(81, "page play"); rig.Draw(81); rig.AssertConfig(2);
            rig.Draw(88.99); rig.AssertConfig(2);
            rig.Draw(89); rig.AssertConfig(3);
        }

        [Fact]
        public void PlayOverridesDisabledConfigurationAndAutoRestoresIt()
        {
            var rig = new Rig("[Display]\nAutoPage=false\n");
            rig.Draw(0); rig.Command(1, "page play");
            rig.Draw(1); rig.Draw(9); rig.AssertConfig(2);
            rig.Command(10, "page auto"); rig.Draw(10); rig.AssertConfig(1);
            rig.Draw(500); rig.AssertConfig(1);
        }

        [Fact]
        public void AutoRestoresScreenBindingAfterManualPageSelection()
        {
            var rig = new Rig();
            rig.Command(0, "page fleet"); rig.Draw(0);
            Assert.Contains(P.L.DisplayFleet, rig.Text());
            rig.Command(1, "page auto"); rig.Draw(1); rig.AssertConfig(1);
            rig.Draw(8.99); rig.AssertConfig(1);
            rig.Draw(9); rig.AssertConfig(2);
        }

        [Theory]
        [InlineData("next", "fleet")]
        [InlineData("prev", "diagnostics")]
        public void NamedPageNavigationIsRelativeToConfiguredPage(string direction, string expected)
        {
            var rig = new Rig();
            rig.Command(0, "page " + direction); rig.Draw(0);
            Assert.Contains(expected == "fleet" ? P.L.DisplayFleet : P.L.DisplayDiagnostics, rig.Text());
            Assert.DoesNotContain(P.L.DisplayConfiguration, rig.Text());
        }

        [Fact]
        public void AutomaticPagingDoesNotChangePageTypeOrExplicitMinerBinding()
        {
            var rig = new Rig("[Display]\nBuiltInPage=miner\n[AMS.Screen]\nMiner=beta\n");
            rig.Miners("alpha", "beta");
            foreach (double now in new[] { 0d, 8d, 16d, 60d })
            {
                rig.Draw(now);
                Assert.Contains("beta", rig.Text()); Assert.DoesNotContain("alpha", rig.Text());
                Assert.Contains(P.L.DisplayMiner, rig.Text());
                Assert.DoesNotContain(P.L.DisplayConfiguration, rig.Text());
            }
        }

        [Fact]
        public void UnboundMinerViewRotatesThroughSortedTelemetry()
        {
            var rig = new Rig("[Display]\nBuiltInPage=miner\n"); rig.Miners("beta", "alpha");
            rig.Draw(0); Assert.Contains("alpha", rig.Text());
            rig.Draw(8); Assert.Contains("beta", rig.Text());
            rig.Draw(16); Assert.Contains("alpha", rig.Text());
        }

        [Fact]
        public void FleetPageRotatesRowsAndClampsWhenTelemetryCountShrinks()
        {
            var rig = new Rig("[Display]\nBuiltInPage=fleet\n");
            rig.Miners(Enumerable.Range(1, 16).Select(n => "miner-" + n.ToString("00")).ToArray());
            rig.Draw(0); Assert.Contains(rig.Text(), text => text.StartsWith("miner-01  "));
            rig.Draw(8); Assert.Contains(rig.Text(), text => text.StartsWith("miner-08  "));
            rig.Draw(16); Assert.Contains(rig.Text(), text => text.StartsWith("miner-15  "));
            rig.Role.Fleet.RemoveRange(7, 9);
            rig.Draw(17); Assert.Contains(rig.Text(), text => text.StartsWith("miner-01  "));
            rig.Draw(40); Assert.Contains(rig.Text(), text => text.StartsWith("miner-01  "));
        }

        [Fact]
        public void MiningMapRotatesDistinctRegionsInsteadOfIndividualJobs()
        {
            var rig = new Rig("[Display]\nBuiltInPage=map\n");
            rig.Role.Jobs.Add(new P.Job { Id = "a1", RegionId = "region-a" });
            rig.Role.Jobs.Add(new P.Job { Id = "a2", RegionId = "region-a" });
            rig.Role.Jobs.Add(new P.Job { Id = "b1", RegionId = "region-b" });
            rig.Draw(0); Assert.Contains(rig.Text(), text => text.StartsWith("region-a  "));
            rig.Draw(8); Assert.Contains(rig.Text(), text => text.StartsWith("region-b  "));
            rig.Draw(16); Assert.Contains(rig.Text(), text => text.StartsWith("region-a  "));
        }

        [Fact]
        public void RediscoveryPreservesCurrentSlideAndItsRemainingDwell()
        {
            var rig = new Rig();
            rig.Draw(0); rig.Draw(8); rig.Draw(16); rig.Draw(24); rig.AssertConfig(4);
            rig.Draw(30); rig.AssertConfig(4);
            rig.Draw(31.99); rig.AssertConfig(4);
            rig.Draw(32); rig.AssertConfig(5);
            rig.Draw(39.99); rig.AssertConfig(5);
            rig.Draw(40); rig.AssertConfig(1);
        }

        [Fact]
        public void RediscoveryAdoptsChangedBindingWithFreshFirstSlide()
        {
            var rig = new Rig("[AMS.Screen]\nPage=fleet\n");
            rig.Draw(0);
            rig.Block.Set("CustomData", "[AMS.Screen]\nPage=config\n");
            rig.Draw(30); rig.AssertConfig(1);
            rig.Draw(37.99); rig.AssertConfig(1);
            rig.Draw(38); rig.AssertConfig(2);
        }

        [Fact]
        public void SinglePageDataRemainsStableWithoutCarouselDots()
        {
            var rig = new Rig("[Display]\nBuiltInPage=miner\n"); rig.Miners("alpha");
            foreach (double now in new[] { 0d, 8d, 80d })
            {
                rig.Draw(now); Assert.Contains("alpha", rig.Text());
                Assert.DoesNotContain(rig.Frames[0], s => s.Type == SpriteType.TEXTURE && s.Data == "Circle");
            }
        }

        [Fact]
        public void MultipleConfigurationSlidesHaveGraphicalCarouselIndicators()
        {
            var rig = new Rig(); rig.Draw(0);
            var dots = rig.Frames[0].Where(s => s.Type == SpriteType.TEXTURE && s.Data == "Circle").ToArray();
            Assert.Equal(ConfigurationPageCount, dots.Length);
            Assert.All(dots, s => Assert.InRange(s.Position.Value.Y, 470, 512));
            var initialColors = dots.Select(s => s.Color).ToArray();
            rig.Draw(8);
            var nextColors = rig.Frames[0].Where(s => s.Type == SpriteType.TEXTURE && s.Data == "Circle").Select(s => s.Color).ToArray();
            Assert.NotEqual(initialColors[0], nextColors[0]);
            Assert.Equal(initialColors[0], nextColors[1]);
        }
    }
}