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

AutoMiningScript

【SpaceEngineer】全自动挖矿脚本

公开
关注 0 Fork 0 Star 0
返回提交历史

SpaceEngineersModDev/AutoMiningScript

优化磁吸锁定逻辑与自动命名,完善测试与文档

修复返航、等候、对齐、贴合及接港退避等状态下,连接器报告“可连接”即清除推力与陀螺覆盖并尝试锁定,锁定未完成时显示原因并重试,接错接口时保持连接并报告错误,人工暂停、交还控制和正常离港不自动锁定。新增磁吸锁定相关单元测试,覆盖多场景,确保锁定逻辑正确。主控和矿机等脚本加载配置后自动设置自身名称,主控固定为“XFEAMS系统/ System”,其他类型按编号命名,命名资源加入中英文语言包。更新文档,详细说明自动命名和锁定行为变更,补充验收与测试说明。资源文件增加相关提示文本。结构优化,统一返航等状态判断为 ReturningToDock,减少重复。所有导出脚本字符数合规,SHA-256 校验通过。

8481168
XFE工作室室长 <mail@xfegzs.com>
提交于

代码差异

11 个文件 +116 -26
Modified AutoMiningScript.Tests/DockingNavigationTests.cs +60 -4
@@ -24,7 +24,8 @@ namespace AutoMiningScript.Tests
24 24 public readonly P.DockFrame Dock;
25 25 public MatrixD Orientation=MatrixD.Identity,Mount=MatrixD.CreateWorld(Vector3D.Zero,Vector3D.Backward,Vector3D.Up);
26 26 public Vector3D Velocity,AngularVelocity=Vector3D.Zero;
27 public bool CamerasReady=true,Connected;
27 public bool CamerasReady=true,Connected,Magnetized,LockSucceeds=true;
28 public long PeerId=51;
28 29 public int ConnectCalls,Rays;
29 30 public double Mass=1000,ContactSpacing=1;
30 31 public readonly List<P.FlightState> States=new List<P.FlightState>();
@@ -46,13 +47,13 @@ namespace AutoMiningScript.Tests
46 47 }
47 48 var gyro=(Stub<IMyGyro>)RemotingServices.GetRealProxy(R.Hardware.Gyros[0]);
48 49 gyro.Values.Remove("WorldMatrix");gyro.Method("get_WorldMatrix",a=>Orientation);
49 var peer=new Stub<IMyShipConnector>().Set("EntityId",51L).Set("CubeGrid",new Stub<IMyCubeGrid>().Set("EntityId",50L).Value)
50 var peer=new Stub<IMyShipConnector>().Method("get_EntityId",a=>PeerId).Set("CubeGrid",new Stub<IMyCubeGrid>().Set("EntityId",50L).Value)
50 51 .Method("get_WorldMatrix",a=>MatrixD.CreateWorld(Dock.Position,Dock.Forward,Dock.Up)).Method("GetPosition",a=>Dock.Position);
51 52 R.Connector.Values.Remove("Status");
52 53 R.Connector.Method("GetPosition",a=>PortPosition).Method("get_WorldMatrix",a=>PortPose)
53 .Method("get_Status",a=>Connected?MyShipConnectorStatus.Connected:CanConnect?MyShipConnectorStatus.Connectable:MyShipConnectorStatus.Unconnected)
54 .Method("get_Status",a=>Connected?MyShipConnectorStatus.Connected:Magnetized||CanConnect?MyShipConnectorStatus.Connectable:MyShipConnectorStatus.Unconnected)
54 55 .Method("get_OtherConnector",a=>Connected?peer.Value:null)
55 .Method("Connect",a=>{ConnectCalls++;Connected=CanConnect;return null;});
56 .Method("Connect",a=>{ConnectCalls++;Connected=LockSucceeds&&(Magnetized||CanConnect);return null;});
56 57 MountPort(Mount,new Vector3D(0,0,2),MatrixD.Identity,Vector3D.Zero);
57 58 R.Hardware.Cameras.Clear();
58 59 foreach(Vector3D direction in new[]{Vector3D.Forward,Vector3D.Backward})AddCamera(direction);
@@ -124,6 +125,61 @@ namespace AutoMiningScript.Tests
124 125 r.Finish();Assert.True(r.Gap<start);Assert.Contains(P.FlightState.DockAlign,r.States);Assert.Contains(P.FlightState.DockApproach,r.States);
125 126 }
126 127
128 [Theory]
129 [InlineData(P.FlightState.Returning)]
130 [InlineData(P.FlightState.Holding)]
131 [InlineData(P.FlightState.DockAlign)]
132 [InlineData(P.FlightState.DockApproach)]
133 [InlineData(P.FlightState.DockRetreat)]
134 public void MagneticCaptureLocksBeforeGeometricCorrectionsOrTelemetryWaits(P.FlightState state)
135 {
136 var r=new DockRig();r.R.State(state);r.Magnetized=true;
137 r.R.Position=r.Contact+Vector3D.Right*.4;r.Orientation=MatrixD.CreateFromAxisAngle(Vector3D.Forward,.1);
138 r.Velocity=Vector3D.Right*.4;r.AngularVelocity=Vector3D.Forward*.02;r.Dock.ReceivedAt=r.R.Program.Now-10;
139 r.R.Hardware.Thrusters[0].ThrustOverridePercentage=.5f;r.R.Hardware.Gyros[0].GyroOverride=true;
140 r.R.Miner.Tick(.05);
141 Assert.True(r.Connected);Assert.Equal(1,r.ConnectCalls);Assert.Equal(P.FlightState.Servicing,r.R.StateNow);
142 Assert.All(r.R.Hardware.Thrusters,t=>Assert.Equal(0f,t.ThrustOverridePercentage));
143 Assert.All(r.R.Hardware.Gyros,g=>Assert.False(g.GyroOverride));Assert.False(r.Flight.HasRoute);
144 Assert.Contains(r.R.Sent,p=>p.Kind=="TELEMETRY" && P.Telemetry.FromIni(p.Body).Connected);
145 }
146
147 [Fact]
148 public void PendingMagneticLockStopsCorrectionAndRetriesUntilActuallyConnected()
149 {
150 var r=new DockRig();r.R.State(P.FlightState.DockApproach);r.Magnetized=true;r.LockSucceeds=false;
151 r.Tick();Assert.False(r.Connected);Assert.Equal(1,r.ConnectCalls);
152 Assert.Equal(P.FlightState.DockApproach,r.R.StateNow);Assert.Equal(P.L.MinerDockLockPending,r.Reason);
153 Assert.False(r.Flight.HasRoute);Assert.Equal(0,r.Rays);
154 r.LockSucceeds=true;r.Tick();Assert.True(r.Connected);Assert.Equal(2,r.ConnectCalls);
155 Assert.Equal(P.FlightState.Servicing,r.R.StateNow);
156 }
157
158 [Theory]
159 [InlineData("pause")]
160 [InlineData("release")]
161 public void MagneticCaptureDoesNotOverrideAnOperatorStop(string command)
162 {
163 var r=new DockRig();r.Magnetized=true;r.R.Miner.Command(command);r.R.Miner.Tick(.05);
164 Assert.False(r.Connected);Assert.Equal(0,r.ConnectCalls);
165 }
166
167 [Fact]
168 public void DepartureDoesNotRelockWhileConnectorsAreStillMagneticallyInRange()
169 {
170 var r=new DockRig();r.Magnetized=true;r.R.State(P.FlightState.Departing);Write(r.R.Miner,"laneKind","depart");
171 for(int n=0;n<3;n++)r.R.Miner.Tick(.05);
172 Assert.False(r.Connected);Assert.Equal(0,r.ConnectCalls);Assert.Equal(P.FlightState.Departing,r.R.StateNow);
173 }
174
175 [Fact]
176 public void APhysicallyConnectedUnexpectedPortIsReportedWithoutContinuingThrust()
177 {
178 var r=new DockRig();r.Magnetized=true;r.PeerId=999;r.R.State(P.FlightState.DockApproach);r.R.Miner.Tick(.05);
179 Assert.True(r.Connected);Assert.Equal(P.FlightState.Fault,r.R.StateNow);Assert.Equal(P.L.MinerWrongDock,r.Reason);
180 Assert.False(r.Flight.HasRoute);Assert.All(r.R.Hardware.Thrusters,t=>Assert.Equal(0f,t.ThrustOverridePercentage));
181 }
182
127 183 [Theory]
128 184 [InlineData(5d)]
129 185 [InlineData(20d)]
Modified AutoMiningScript/MinerController.cs +22 -8
@@ -61,6 +61,7 @@ namespace AutoMiningScript
61 61 double DockDistance => Math.Max(P.Config.Number("Dock","ApproachDistance",30,10,300),ship.Radius*2);
62 62 bool InHole => job!=null && job.Kind!=JobKind.Survey && (insideBore || state==FlightState.Drilling || state==FlightState.Retreat);
63 63 bool Idle => state==FlightState.Paused || state==FlightState.Boot || state==FlightState.Docked || state==FlightState.Servicing || state==FlightState.Ready;
64 bool ReturningToDock => state==FlightState.Returning || state==FlightState.Holding || state==FlightState.DockAlign || state==FlightState.DockApproach || state==FlightState.DockRetreat;
64 65 void Set(FlightState next,string text,bool keepRoute=false)
65 66 {
66 67 if(state!=next) {P.Log(L.State(next)+": "+text);state=next;stateSince=P.Now;progressAt=P.Now;lastProgress=0;waitingAligning=false;if(!keepRoute)flight.ResetRoute();if(next==FlightState.Align) {entryProbe=0;entryNearest=double.MaxValue;entryFarthest=double.MinValue;}if(next==FlightState.DockAlign || next==FlightState.DockApproach) {lastProgress=double.MaxValue;stableSince=-1;}}
@@ -109,8 +110,9 @@ namespace AutoMiningScript
109 110 }
110 111 if(Idle)
111 112 {flight.Hold(dt);return;}
113 if(ReturningToDock && TryConnect())return;
112 114 string returnReason;
113 if(state!=FlightState.Returning && state!=FlightState.Holding && state!=FlightState.DockAlign && state!=FlightState.DockApproach && state!=FlightState.DockRetreat && state!=FlightState.Retreat && resources.MustReturn(out returnReason))BeginReturn(returnReason);
115 if(!ReturningToDock && state!=FlightState.Retreat && resources.MustReturn(out returnReason))BeginReturn(returnReason);
114 116 if(home!=null && P.Now-home.ReceivedAt>5)
115 117 {
116 118 if(state==FlightState.DockApproach || state==FlightState.DockAlign || state==FlightState.Departing)AbortDock(L.MinerBaseTimeoutAbortDock);
@@ -362,7 +364,7 @@ namespace AutoMiningScript
362 364 reason=text;pausedAfterRetreat=false;
363 365 if(InHole) {Set(FlightState.Retreat,text);return;}
364 366 if(state==FlightState.Departing) {AbortDock(text);return;}
365 if(state==FlightState.Returning || state==FlightState.Holding || state==FlightState.DockAlign || state==FlightState.DockApproach || state==FlightState.DockRetreat)return;
367 if(ReturningToDock)return;
366 368 retry=0;
367 369 ship.SetDrills(false);ship.SetSampling(false);returnIndex=breadcrumbs.Count-1;Set(FlightState.Returning,text);
368 370 }
@@ -546,6 +548,7 @@ namespace AutoMiningScript
546 548 }
547 549 void DockApproach(double dt)
548 550 {
551 if(TryConnect())return;
549 552 var permit=DockProblem("dock");if(permit.Length>0) {AbortDock(permit);return;}
550 553 Vector3D f,u;var target=DockTarget(0,out f,out u);
551 554 var contact=target;
@@ -579,13 +582,24 @@ namespace AutoMiningScript
579 582 // connector geometry directly. Camera coverage and hits no longer gate it.
580 583 flight.Move(target,dock.PointVelocity(target),f,u,speed,0.1,false,dt,false,false);
581 584 reason=DockNavigationReason(synchronizing?L.MinerDockSyncPose:depth>captureDistance?L.MinerDockFollowAxis:L.MinerSlowRelativeApproach,contact)+" / "+L.F(L.MinerDockPrecision,lateral.Length(),angular);
582 if(ship.Connector.Status==MyShipConnectorStatus.Connectable && aligned && relative.Length()<0.3)
585 if(state==FlightState.DockApproach)CheckDockProgress(contact,L.MinerDockTimeout);
586 }
587 bool TryConnect()
588 {
589 if(ship.Connector==null || ship.Connector.Status!=MyShipConnectorStatus.Connectable)return false;
590 // Magnetic capture is authoritative. Do not fight it with geometric
591 // corrections, or wait for stale approach telemetry before locking.
592 flight.Release();ship.Connector.Connect();reason=L.MinerDockLockPending;
593 if(Connected)
583 594 {
584 ship.Connector.Connect();
585 if(Connected && ship.Connector.OtherConnector!=null && ship.Connector.OtherConnector.EntityId==dock.ConnectorId)
586 {ReleaseLane();flight.ClearDockContact();ship.Release();Set(FlightState.Servicing,L.MinerDockConfirmedService);}
595 ReleaseLane();retry=0;
596 var other=ship.Connector.OtherConnector;
597 if(dock!=null && other!=null && other.EntityId!=dock.ConnectorId)
598 {running=false;Set(FlightState.Fault,L.MinerWrongDock);}
599 else Set(FlightState.Servicing,L.MinerDockConfirmedService);
600 Publish();
587 601 }
588 if(state==FlightState.DockApproach)CheckDockProgress(contact,L.MinerDockTimeout);
602 return true;
589 603 }
590 604 void AbortDock(string why)
591 605 {
@@ -761,7 +775,7 @@ namespace AutoMiningScript
761 775 void ContinueCancelledReturn()
762 776 {
763 777 if(state==FlightState.Departing)AbortDock(L.MinerTaskCancelledReturn);
764 else if(state!=FlightState.DockAlign && state!=FlightState.DockApproach && state!=FlightState.DockRetreat && state!=FlightState.Holding && state!=FlightState.Returning)BeginReturn(L.MinerTaskCancelledReturn);
778 else if(!ReturningToDock)BeginReturn(L.MinerTaskCancelledReturn);
765 779 }
766 780 void CancelThrough(long watermark)
767 781 {
Modified AutoMiningScript/Program.cs +3 -3
@@ -46,7 +46,7 @@ namespace AutoMiningScript
46 46 {
47 47 var defaultRole=CompiledRole();var id=defaultRole=="fleet"?"base":defaultRole+"-"+Me.EntityId;
48 48 if(string.IsNullOrWhiteSpace(Me.CustomData)) {id=Settings.DefaultId(defaultRole,Me.EntityId);Me.CustomData=Settings.Template(defaultRole,id);}
49 Config=new Settings(Me.CustomData,defaultRole,id);dashboard=new Dashboard(this);Bus=new Wire(this);
49 Config=new Settings(Me.CustomData,defaultRole,id);Me.CustomName=Config.BlockName;dashboard=new Dashboard(this);Bus=new Wire(this);
50 50 #if FLEET
51 51 role=new FleetController(this);
52 52 #elif MARKER
@@ -110,7 +110,7 @@ namespace AutoMiningScript
110 110 #endif
111 111 if(!string.IsNullOrWhiteSpace(argument) && argument!="igc")
112 112 {
113 if(argument=="init") {role.Command("rescan");Log(L.CommonConfigReload);}
113 if(argument=="init") {Me.CustomName=Config.BlockName;role.Command("rescan");Log(L.CommonConfigReload);}
114 114 else if(argument=="page" || argument.StartsWith("page ",Data.Ordinal))dashboard.Command(argument);
115 115 else role.Command(argument.Trim());
116 116 }
@@ -165,7 +165,7 @@ namespace AutoMiningScript
165 165 if(Bus!=null)Bus.CancelPending(null);
166 166 var id=string.IsNullOrWhiteSpace(Me.CustomData)?Settings.DefaultId("fleet",Me.EntityId):"base";
167 167 if(string.IsNullOrWhiteSpace(Me.CustomData))Me.CustomData=Settings.Template("fleet",id);
168 Config=new Settings(Me.CustomData,"fleet",id);
168 Config=new Settings(Me.CustomData,"fleet",id);Me.CustomName=Config.BlockName;
169 169 if(Bus==null)Bus=new Wire(this);else Bus.Reset();
170 170 var fleet=new FleetController(this);role=fleet;fleet.BeginRestoreStorage(Storage);dashboard=new Dashboard(this);
171 171 nextDraw=0;nextSave=Now+2;BudgetDeferrals=0;nextBudgetNotice=0;
Modified AutoMiningScript/Settings.cs +1 -0
@@ -12,6 +12,7 @@ namespace AutoMiningScript
12 12 {
13 13 readonly MyIni ini;
14 14 public readonly string Id, FleetId, BaseId, Role;
15 public string BlockName => Role=="fleet"?L.CommonFleetBlockName:L.F(L.CommonNodeBlockName,Id);
15 16 public Settings(string source, string defaultRole, string defaultId)
16 17 {
17 18 ini = new MyIni(); MyIniParseResult result;
Modified Localization/common.en-US.json +2 -0
@@ -1,4 +1,6 @@
1 1 {
2 "CommonFleetBlockName": "XFEAMS System",
3 "CommonNodeBlockName": "XFEAMS-{0}",
2 4 "CommonReady": "{0} {1} / {2}: ready; diagnose first",
3 5 "CommonInitError": "INIT ERROR: {0}",
4 6 "CommonFixConfig": "INIT ERROR: {0}\nFix CustomData, then run init",
Modified Localization/common.zh-CN.json +2 -0
@@ -1,4 +1,6 @@
1 1 {
2 "CommonFleetBlockName": "XFEAMS系统",
3 "CommonNodeBlockName": "XFEAMS-{0}",
2 4 "CommonReady": "{0} {1} / {2} 已就绪;可运行“诊断”查看状态",
3 5 "CommonInitError": "初始化错误:{0}",
4 6 "CommonFixConfig": "初始化错误:{0}\n请修正自定义数据后运行“初始化”",
Modified Localization/docking.en-US.json +1 -0
@@ -1,4 +1,5 @@
1 1 {
2 "MinerDockLockPending": "Magnetic capture; locking connector",
2 3 "MinerDockOuterEntry": "Flying to port entry",
3 4 "MinerDockOuterClearance": "Moving out to entry; holding attitude",
4 5 "MinerDockSyncPose": "Synchronizing at entry",
Modified Localization/docking.zh-CN.json +1 -0
@@ -1,4 +1,5 @@
1 1 {
2 "MinerDockLockPending": "连接器已吸附,正在锁定连接",
2 3 "MinerDockOuterEntry": "前往对接口前方",
3 4 "MinerDockOuterClearance": "保持姿态退至外部入口平面",
4 5 "MinerDockSyncPose": "在引导点同步停靠姿态",
Modified README.md +6 -3
@@ -25,6 +25,8 @@ XFE AMS 是 Space Engineers 原版编程块采矿舰队系统:自主推进器
25 25
26 26 **中文版的自定义数据、运行参数和枚举值均支持中文,以下部署示例以中文版为准。** 新生成模板使用“采矿舰队”“主控”“采矿泊位”“基地货仓”等默认名称;旧英文配置和原英文命令继续兼容,已有 `CustomData` 不会被自动重写。参数及命令完整对照见 [中文参数手册](docs/PARAMETERS.zh-CN.md)。中英文混用时,必须手动统一舰队编号和主控编号;“采矿舰队”与 `mining`、“主控”与 `base` 是不同的真实身份,不会按含义自动合并。旧部署可以继续使用原来的英文 ID 和方块组名,不必为翻译而更名。
27 27
28 编程块加载有效配置后自动设置自身名称,重新编译时会同步更新。中文主控固定为 `XFEAMS系统`,英文主控固定为 `XFEAMS System`;矿机、标点终端及看门狗均使用 `XFEAMS-各自ID`,例如编号“深空工业3号”的矿机编程块叫 `XFEAMS-深空工业3号`。ID 使用配置原文,不翻译、不重复添加“矿机”等前缀。仅修改编程块名称,舰船名称、通信编号、任务和自定义数据保持原值;无需新增命名配置。
29
28 30 ## 硬件与建造要求
29 31
30 32 每台矿机需要:
@@ -207,11 +209,11 @@ XFE AMS 是 Space Engineers 原版编程块采矿舰队系统:自主推进器
207 209
208 210 获得有效进港许可后,矿机直接前往接口前方的引导点,再连续进入对接;已经位于接口前方的矿机就近接入轴线。等待点只在没有可用许可时使用,取得许可后无需先飞到远处等待点、停稳,再返回接口。引导点距离由 `[对接] 接近距离` 控制(默认30米,至少两倍矿机半径),用于从侧面汇入。前往引导点的途中仍扫描避障,沿轴线到达入口时连续转入正式对接;已在入口以内的矿机就近接入,不向外绕行。近港重启返航会核对新许可后就近进港,不先飞回旧采矿航迹的远端。
209 211
210 “进港对接”全程按两个连接器的实际安装关系控制姿态,使开口相向、上方向一致;自动标定保留连接器中心的对接间距,修正人工停靠时的横向和角度偏差。**进入正式对接后关闭摄像机扫描、障碍判断和扫描限速,直接沿预约通道贴合**,并清除上一段的绕行目标与扫描等待。许可、遥测、动力与人工接管检查继续生效。诊断显示“直接对接:扫描与避障已关闭 / 指令速度”,不再把旧扫描净空显示为当前对接条件。
212 “进港对接”全程按两个连接器的实际安装关系控制姿态,使开口相向、上方向一致;自动标定保留连接器中心的对接间距,修正人工停靠时的横向和角度偏差。**进入正式对接后关闭摄像机扫描、障碍判断和扫描限速,直接沿预约通道贴合**,并清除上一段的绕行目标与扫描等待。尚未吸附时继续检查许可、遥测和动力;人工接管始终优先。诊断显示“直接对接:扫描与避障已关闭 / 指令速度”,不再把旧扫描净空显示为当前对接条件。
211 213
212 已标定的正常直线进港随剩余距离逐步减速,最后3米才采用 `最终接近速度`(默认0.2m/s)。首次尚未测得贴合间距时,在距连接器中心至少6米、且不小于两倍矿机半径的范围内先稳定低速,再沿接口轴线接近;游戏报告连接器可连接且姿态、相对速度合格时立即尝试锁定,不等待两个方块中心重合。连接状态由[官方连接器接口](https://keensoftwarehouse.github.io/SpaceEngineersModAPI/api/Sandbox.ModAPI.Ingame.IMyShipConnector.html)提供。
214 已标定的正常直线进港随剩余距离逐步减速,最后3米才采用 `最终接近速度`(默认0.2m/s)。首次尚未测得贴合间距时,在距连接器中心至少6米、且不小于两倍矿机半径的范围内先稳定低速,再沿接口轴线接近。返航、进港等候、对齐、贴合或接港退避时,游戏一旦报告连接器“可连接”,就立即清除推力与陀螺覆盖并尝试锁定;不再等待姿态误差、相对速度、稳定计时或进港遥测门槛,也不等待两个方块中心重合。连接状态由[官方连接器接口](https://keensoftwarehouse.github.io/SpaceEngineersModAPI/api/Sandbox.ModAPI.Ingame.IMyShipConnector.html)提供。
213 215
214 贴合需横向偏移小于0.15m、姿态误差小于1°、横向速度小于0.1m/s、角速度差小于0.1°/s,连续稳定2秒;可在接近途中累计。进入后采用较宽的退出门限(0.25m、2°、0.2m/s、0.2°/s),避免轻微波动反复重置2秒等待;实际连接仍核对严格对齐与相对速度。超过退出门限时暂停轴向接近、修正姿态后重新取得稳定窗口。两段进港状态都以连续60秒无进展触发退避,持续接近不会因为整段超过旧版4分钟限制而退出。
216 尚未进入可连接范围时,末段轴向接近需横向偏移小于0.15m、姿态误差小于1°、横向速度小于0.1m/s、角速度差小于0.1°/s,连续稳定2秒;可在接近途中累计。进入后采用较宽的退出门限(0.25m、2°、0.2m/s、0.2°/s),避免轻微波动反复重置2秒等待。超过退出门限时暂停轴向接近、修正姿态后重新取得稳定窗口;已可连接则直接锁定。真正连接成功后立即上报“卸货补能”并核对实际泊位;连接尚未完成时显示“连接器已吸附,正在锁定连接”,保持停止飞控修正并重试。主动暂停、人工接管及正常离港不会触发这项自动锁定。未吸附的两段进港状态都以连续60秒无进展触发退避,持续接近不会因为整段超过旧版4分钟限制而退出。
215 217
216 218 扫描以待检测区域为单位,按镜头安装位置、朝向、可用距离分配检测工作,把所有镜头的有效结果合并为一轮扫描。某个镜头扫到自身船体时,仅在当前检测点尝试其他镜头,不清空已有的新鲜净空,也不把这个镜头从其他检测点永久排除。例如前方三个镜头中间一个被挡住,左右镜头仍可共同完成扫描;中间镜头在能看见的其他区域仍会被使用。
217 219
@@ -399,6 +401,7 @@ XFE AMS 是 Space Engineers 原版编程块采矿舰队系统:自主推进器
399 401 | 到2.8米附近停住,姿态与偏移接近零 | 更新矿机脚本并从主控运行 `返航 矿机编号`。末端稳定窗口加入退出容差,避免角速度差轻微越过0.1°/s就反复刹停。诊断中的指令速度为0表示仍在调整或同步;指令速度非零而实际速度持续接近0时,应核对推进器实际输出、动力和船体接触情况 |
400 402 | 到接口附近又向外飞,或30多米就以0.1m/s挪动 | 更新矿机脚本并从主控运行 `返航 矿机编号`。新版有效许可下不强制绕回等待点,已在入口以内时就近进港;`最终接近速度` 只用于最后3米。直线航迹连续衔接,正式对接不再受扫描限制;无需重新手动标定 |
401 403 | 对接反复退出 | 母舰加速/旋转、遥测过期、泊位阻塞、连接器几何/钻尖标定错误 |
404 | 已被连接器吸住,仍显示进港对接 | 更新矿机脚本;新版在连接器报告可连接时直接锁定,成功后立即上报卸货补能,不再被姿态、速度或稳定计时拦住 |
402 405 | 自动探索未检出 | 可见表面扫描不代表地下矿床;检查试钻深度、采样有效性与目标矿种配置 |
403 406 | 旧矿机失联后任务不派出 | 保守保留未知占用;先找到失联矿机并安全回收,不能仅等待超时 |
404 407 | 改名后大屏保留旧矿机 | 身份取自 `[系统] 编号`;新身份上线、旧条目显示离线后,在主控运行 `清理离线矿机`。只清名单,旧任务和未知通道占用仍保留 |
Modified docs/PARAMETERS.zh-CN.md +2 -0
@@ -8,6 +8,8 @@
8 8
9 9 编号、舰队编号、主控编号、真实方块名称及方块组名称属于用户数据,保持原文。中英文舰队混用时必须填写完全一致的舰队编号与主控编号;默认“采矿舰队”和 `mining` 不等价,默认“主控”和 `base` 不等价。不要直接改 ID 来迁移旧存档。
10 10
11 编程块初始化时自动命名:中文主控为 `XFEAMS系统`,英文主控为 `XFEAMS System`,其它类型为 `XFEAMS-` 加本节点的“编号”。更改编号并重新编译后,名称随生效配置更新;命名不改变通信身份,也没有额外的名称或角色参数。
12
11 13 硬件参数放在对应角色实际使用的节中;此表是名称对照,不表示每个参数能放入任意节。常用配置及部署步骤见 [README](../README.md)。默认 `[硬件] 自动标定=是`:硬件就绪的待机矿机自动请求接港,用实际连接器安装位置和朝向完成首次对接,真实连接后保存标定。设为 `否` 时,未标定矿机仍需人工接港并执行标定;主动暂停或交还控制不会被自动接港覆盖。`[飞行] 起飞质量=0` 自动测量;`[货物] 起飞载荷上限=0.05`。
12 14
13 15 中文版的两套默认组名互相兼容:找不到“采矿泊位”时查找 `AMS Docks`,找不到“基地货仓”时查找 `AMS Cargo`,反向同样适用。精确匹配的已有组优先,自定义组名不做替换;只收集选定组内的母舰本体方块,配置原文不变。
Modified docs/VALIDATION.md +16 -8
@@ -4,6 +4,12 @@
4 4
5 5 ## 开发机检查
6 6
7 2026-09-14 编程块自动命名:配置解析成功后设置自身名称,重新编译及主控重置同样生效。中文主控使用 `XFEAMS系统`,英文主控使用 `XFEAMS System`,其它类型使用 `XFEAMS-` 加配置编号;命名格式来自两份共用语言资源。只写入本编程块的 `CustomName`,不更改配置编号、舰船名称或存档身份。
8
9 同轮修复吸附后仍校正姿态:返航、等候、对齐、贴合及接港退避时,`Connectable` 优先清除控制覆盖并执行 `Connect()`,不再用姿态、相对速度、稳定计时和进港遥测阻止锁定;真正连接成功才进入服务并立即发布遥测。锁定未完成时显示具体原因并重试,接错接口时保持连接、停止飞控并报告原有泊位错误;人工暂停、交还控制和正常离港不自动锁定。新增10项回归,125项返航、矿机状态及对接定向检查通过,日志为 `obj/magnetic-lock-targeted.log`。模拟连接器状态不等同于游戏内吸力实测,新增实机步骤见 S44。
10
11 最终执行 `./build.ps1 -NoRestore`:中英文各586/586项测试、416对资源及8项生成器检查通过;八份源工程和实际导出均编译0警告、0错误,导出角色检查通过。逐项核对了命名资源、文件字符数及SHA-256,均与 `dist/manifest.json` 一致且不超过100000字符。当前交付日志为 `obj/block-names-magnetic-lock-build.log`;仅命名修改的上一轮记录为 `obj/block-names-final-build.log`,已被本次合并产物替代。游戏内吸附锁定和方块命名验收尚未执行。
12
7 13 2026-09-14 本轮修复配置后自动接港。用户诊断显示主控有6台在线矿机、0个泊位、2台等待,3号“标定=否 / 等待泊位与外部等候点”。只读核对08:51存档:母舰实际组名为 `AMS Docks`、`AMS Cargo`,中文配置引用“采矿泊位”“基地货仓”;3/4号仍处于返航,其余4台已停靠。母舰共8个连接器,采矿组只管理6个,不能用接管全部连接器代替修复组名。原游戏存档未修改。
8 14
9 15 新增21项检查覆盖默认中英文组名兼容、自定义组名精确匹配、母舰网格过滤、缺失泊位原因回传与重扫恢复;主控暂停时为两台空中矿机分配不同泊位;初始自动返航恢复电池供电及储氢罐供气、暂停/人工接管持久化、返航各阶段重新获取许可、孔内沿原轴退出。首次未标定对接以实际控制输出积分,分别测试后置/侧置连接器、20/130米来向及1/2.8/5米实际中心间距;锁定后才测量保存标定。5米间距模型在修正首次低速窗口前两项失败,修复后通过。115项返航、矿机状态与对接定向检查通过,日志为 `obj/auto-home-targeted.log`。模型使用理想姿态、空旷相机和模拟连接器状态,不能替代真实碰撞、吸力、充能与多人联机验证。
@@ -60,14 +66,14 @@
60 66
61 67 | 本次导出产物 | 字符数 | 限额 |
62 68 | --- | ---: | ---: |
63 | `dist/zh-CN/AutoMiningScript/script.cs` | 95,329 | 100,000 |
64 | `dist/zh-CN/AutoMiningFleet/script.cs` | 94,402 | 100,000 |
65 | `dist/zh-CN/AutoMiningMarker/script.cs` | 38,055 | 100,000 |
66 | `dist/zh-CN/AutoMiningWatchdog/script.cs` | 35,368 | 100,000 |
67 | `dist/en-US/AutoMiningScript/script.cs` | 99,194 | 100,000 |
68 | `dist/en-US/AutoMiningFleet/script.cs` | 95,958 | 100,000 |
69 | `dist/en-US/AutoMiningMarker/script.cs` | 38,431 | 100,000 |
70 | `dist/en-US/AutoMiningWatchdog/script.cs` | 35,578 | 100,000 |
69 | `dist/zh-CN/AutoMiningScript/script.cs` | 95,488 | 100,000 |
70 | `dist/zh-CN/AutoMiningFleet/script.cs` | 94,531 | 100,000 |
71 | `dist/zh-CN/AutoMiningMarker/script.cs` | 38,166 | 100,000 |
72 | `dist/zh-CN/AutoMiningWatchdog/script.cs` | 35,480 | 100,000 |
73 | `dist/en-US/AutoMiningScript/script.cs` | 99,380 | 100,000 |
74 | `dist/en-US/AutoMiningFleet/script.cs` | 96,092 | 100,000 |
75 | `dist/en-US/AutoMiningMarker/script.cs` | 38,547 | 100,000 |
76 | `dist/en-US/AutoMiningWatchdog/script.cs` | 35,694 | 100,000 |
71 77
72 78 已核对八份文件的 SHA-256 与 `dist/manifest.json` 一致。中文产物包含中文字串,英文产物没有中文字串;每份脚本只包含对应的一种语言标识。后续修改应以重新执行构建产生的清单和测试报告为准。
73 79
@@ -152,6 +158,7 @@
152 158 | S41 | 在入口前耗尽相机充能超过60s,随后恢复;从旧靠泊故障下达全部返航 | 入口等待不累计三次靠泊失败,只有主控核实停稳后才释放通道;新返航重置旧计数;真实贴合无进展仍退避并保留故障保护 | 未执行 |
153 159 | S42 | 新矿机在空中加载正确配置,分别使用后置/侧置连接器与不同大小接口,主控保持暂停 | 无需单机初始化或手工标定,自动请求泊位、进港及锁定;首次慢速窗口在实际接触前取得,真正连接后才显示已标定并保存测量值 | 未执行 |
154 160 | S43 | 在返航、等候、进港对齐、贴合及退避中重新编译,再对照主动暂停和交还控制 | 原返航自动重新获取母舰遥测和许可,不重复下令;不使用旧目标直接施加推力;暂停/人工接管持续生效;孔内恢复始终先沿原轴退钻 | 未执行 |
161 | S44 | 返航时进入连接器吸附范围,保留轻微姿态/角速度偏差并让泊位遥测过期;再测试锁定延迟、正常离港和人工接管 | 报告可连接即尝试锁定,清除飞控覆盖;真正连接后立即上报卸货补能。延迟不假报成功或继续推挤;正常离港不重新锁定,暂停/人工接管仍由用户控制 | 未执行 |
155 162
156 163 ## 探索与手动采矿验收
157 164
@@ -211,6 +218,7 @@
211 218 | F36 | 多机并行预约中保存恢复,母舰缓慢平移旋转,再恢复原矿机请求 | 各泊位占用都保留,旧token失效;新鲜请求按当前母舰位姿续约,不能从默认世界原点生成旧接近路线 | 未执行 |
212 219 | F37 | 中文默认配置配合原 `AMS Docks`/`AMS Cargo` 组,6台矿机中4台停靠、2台返航,母舰另有其它用途连接器 | 识别采矿组内6个泊位和母舰库存,不接管其它接口或矿机库存;主控暂停仍发接港许可,独立通道可同时接收两台返航矿机 | 未执行 |
213 220 | F38 | 输入不存在的自定义泊位/货仓组名,再修正配置并重新编译;对照只增减组内方块后重扫 | 主控分别说明缺失字段及名称,矿机显示缺失泊位的原因;修复后无需清空存档即可重新请求接港;自定义组不被默认组替换 | 未执行 |
221 | F39 | 分别加载中英文四种脚本,检查编程块名称;保留原编号重新编译,并在主控运行初始化 | 中文主控名为 `XFEAMS系统`、英文主控为 `XFEAMS System`,矿机/标点/看门狗名为 `XFEAMS-各自ID`;配置编号及舰船名称不受命名影响,主控初始化仍按原有规则清档 | 未执行 |
214 222
215 223 ## 双语和编程块自带屏验收
216 224