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.Reflection;
using System.Runtime.Remoting.Messaging;
using System.Runtime.Remoting.Proxies;
using System.Runtime.Serialization;
using Sandbox.ModAPI.Ingame;
using VRage.Game.ModAPI.Ingame;
using VRageMath;
using P=AutoMiningScript.Program;

namespace AutoMiningScript.Tests
{
    // Interface proxies exercise the real production code against controlled game observations.
    // These are not physics simulators and are not included in any PB artifact.
    public sealed class Stub<T> : RealProxy where T:class
    {
        public readonly Dictionary<string,object> Values=new Dictionary<string,object>();
        public readonly Dictionary<string,Func<object[],object>> Methods=new Dictionary<string,Func<object[],object>>();
        public readonly T Value;
        public Stub():base(typeof(T)) {Value=(T)GetTransparentProxy();}
        public Stub<T> Set(string name,object value) {Values[name]=value;return this;}
        public Stub<T> Method(string name,Func<object[],object> method) {Methods[name]=method;return this;}
        public override IMessage Invoke(IMessage message)
        {
            var call=(IMethodCallMessage)message;var method=(MethodInfo)call.MethodBase;object result=null;
            try
            {
                if(call.MethodName.StartsWith("set_"))Values[call.MethodName.Substring(4)]=call.Args[0];
                else if(call.MethodName.StartsWith("get_") && Values.ContainsKey(call.MethodName.Substring(4)))result=Values[call.MethodName.Substring(4)];
                else if(Methods.ContainsKey(call.MethodName))result=Methods[call.MethodName](call.Args);
                if(result==null && method.ReturnType!=typeof(void) && method.ReturnType.IsValueType)result=Activator.CreateInstance(method.ReturnType);
                return new ReturnMessage(result,call.Args,call.ArgCount,call.LogicalCallContext,call);
            }
            catch(Exception e) {return new ReturnMessage(e,call);}
        }
    }
    public static class TestRig
    {
        public static P Program(string config="")
        {
            var p=(P)FormatterServices.GetUninitializedObject(typeof(P));
            p.Config=new P.Settings(config,"miner","test");
            typeof(P).GetField("Events").SetValue(p,new Queue<string>());
            var grid=new Stub<IMyCubeGrid>().Set("EntityId",10L).Set("GridSize",2.5f);
            var me=new Stub<IMyProgrammableBlock>().Set("CubeGrid",grid.Value).Set("EntityId",20L).Set("WorldMatrix",MatrixD.Identity).Method("GetPosition",a=>Vector3D.Zero);
            SetBase(p,"Me",me.Value);
            var runtime=new Stub<IMyGridProgramRuntimeInfo>().Set("MaxInstructionCount",100000).Set("CurrentInstructionCount",0);
            SetBase(p,"Runtime",runtime.Value);
            SetBase(p,"Echo",(Action<string>)(s=>{}));
            return p;
        }
        public static void SetBase(P p,string name,object value)
        {
            if(name=="IGC")
            {
                typeof(MyGridProgram).GetField("m_IGC_ContextGetter",BindingFlags.Instance|BindingFlags.NonPublic).SetValue(p,(Func<IMyIntergridCommunicationSystem>)(()=> (IMyIntergridCommunicationSystem)value));return;
            }
            var property=typeof(MyGridProgram).GetProperty(name,BindingFlags.Instance|BindingFlags.Public|BindingFlags.NonPublic);
            if(property!=null && property.GetSetMethod(true)!=null) {property.GetSetMethod(true).Invoke(p,new[]{value});return;}
            var field=typeof(MyGridProgram).GetField("<"+name+">k__BackingField",BindingFlags.Instance|BindingFlags.NonPublic);
            if(field==null)
            {
                throw new Exception("Cannot inject game property "+name);
            }
            field.SetValue(p,value);
        }
        public static Stub<IMyBatteryBlock> Battery(P p,float stored,float capacity)
        {
            return new Stub<IMyBatteryBlock>().Set("CubeGrid",p.Me.CubeGrid).Set("IsFunctional",true).Set("CurrentStoredPower",stored).Set("MaxStoredPower",capacity).Set("CurrentInput",0f).Set("CurrentOutput",0.01f);
        }
        public static Stub<IMyShipConnector> Connector(P p,bool connected)
        {
            return new Stub<IMyShipConnector>().Set("CubeGrid",p.Me.CubeGrid).Set("Status",connected?MyShipConnectorStatus.Connected:MyShipConnectorStatus.Unconnected).Set("IsFunctional",true);
        }
    }
}