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 : RealProxy where T:class { public readonly Dictionary Values=new Dictionary(); public readonly Dictionary> Methods=new Dictionary>(); public readonly T Value; public Stub():base(typeof(T)) {Value=(T)GetTransparentProxy();} public Stub Set(string name,object value) {Values[name]=value;return this;} public Stub Method(string name,Func 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()); var grid=new Stub().Set("EntityId",10L).Set("GridSize",2.5f); var me=new Stub().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().Set("MaxInstructionCount",100000).Set("CurrentInstructionCount",0); SetBase(p,"Runtime",runtime.Value); SetBase(p,"Echo",(Action)(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)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 Battery(P p,float stored,float capacity) { return new Stub().Set("CubeGrid",p.Me.CubeGrid).Set("IsFunctional",true).Set("CurrentStoredPower",stored).Set("MaxStoredPower",capacity).Set("CurrentInput",0f).Set("CurrentOutput",0.01f); } public static Stub Connector(P p,bool connected) { return new Stub().Set("CubeGrid",p.Me.CubeGrid).Set("Status",connected?MyShipConnectorStatus.Connected:MyShipConnectorStatus.Unconnected).Set("IsFunctional",true); } } }