Further work on getting MSIL Injection in. Next step is to overwrite the constructor for Game1 and redirect it to SGame
This commit is contained in:
parent
608a5cb257
commit
792cfcd796
|
@ -48,13 +48,12 @@ namespace StardewModdingAPI.Helpers
|
||||||
public CecilContext(CecilContextType contextType)
|
public CecilContext(CecilContextType contextType)
|
||||||
{
|
{
|
||||||
ContextType = contextType;
|
ContextType = contextType;
|
||||||
|
|
||||||
if (ContextType == CecilContextType.SMAPI)
|
if (ContextType == CecilContextType.SMAPI)
|
||||||
_assemblyDefinition = AssemblyDefinition.ReadAssembly(Assembly.GetExecutingAssembly().Location);
|
_assemblyDefinition = AssemblyDefinition.ReadAssembly(Assembly.GetExecutingAssembly().Location);
|
||||||
else
|
else
|
||||||
_assemblyDefinition = AssemblyDefinition.ReadAssembly(Constants.StardewExePath);
|
_assemblyDefinition = AssemblyDefinition.ReadAssembly(Constants.StardewExePath);
|
||||||
}
|
}
|
||||||
|
|
||||||
public ILProcessor GetMethodILProcessor(string type, string method)
|
public ILProcessor GetMethodILProcessor(string type, string method)
|
||||||
{
|
{
|
||||||
if (_assemblyDefinition == null)
|
if (_assemblyDefinition == null)
|
||||||
|
@ -64,7 +63,7 @@ namespace StardewModdingAPI.Helpers
|
||||||
throw new ArgumentNullException("Both type and method must be set");
|
throw new ArgumentNullException("Both type and method must be set");
|
||||||
|
|
||||||
Mono.Cecil.Cil.ILProcessor ilProcessor = null;
|
Mono.Cecil.Cil.ILProcessor ilProcessor = null;
|
||||||
TypeDefinition typeDef = _assemblyDefinition.MainModule.Types.FirstOrDefault(n => n.FullName == type);
|
TypeDefinition typeDef = GetTypeDefinition(type);
|
||||||
if (typeDef != null)
|
if (typeDef != null)
|
||||||
{
|
{
|
||||||
MethodDefinition methodDef = typeDef.Methods.FirstOrDefault(m => m.Name == method);
|
MethodDefinition methodDef = typeDef.Methods.FirstOrDefault(m => m.Name == method);
|
||||||
|
@ -77,6 +76,31 @@ namespace StardewModdingAPI.Helpers
|
||||||
return ilProcessor;
|
return ilProcessor;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public TypeDefinition GetTypeDefinition(string type)
|
||||||
|
{
|
||||||
|
if (_assemblyDefinition == null)
|
||||||
|
throw new Exception("ERROR Assembly not properly read. Cannot parse");
|
||||||
|
|
||||||
|
if (string.IsNullOrWhiteSpace(type))
|
||||||
|
throw new ArgumentNullException("Both type and method must be set");
|
||||||
|
|
||||||
|
TypeDefinition typeDef = _assemblyDefinition.MainModule.Types.FirstOrDefault(n => n.FullName == type);
|
||||||
|
return typeDef;
|
||||||
|
}
|
||||||
|
|
||||||
|
public MethodDefinition GetMethodDefinition(string type, string method)
|
||||||
|
{
|
||||||
|
MethodDefinition methodDef = null;
|
||||||
|
TypeDefinition typeDef = GetTypeDefinition(type);
|
||||||
|
|
||||||
|
if (typeDef != null)
|
||||||
|
{
|
||||||
|
methodDef = typeDef.Methods.FirstOrDefault(m => m.Name == method);
|
||||||
|
}
|
||||||
|
|
||||||
|
return methodDef;
|
||||||
|
}
|
||||||
|
|
||||||
public MethodInfo GetSMAPIMethodReference(string type, string method)
|
public MethodInfo GetSMAPIMethodReference(string type, string method)
|
||||||
{
|
{
|
||||||
if (_assemblyDefinition == null)
|
if (_assemblyDefinition == null)
|
||||||
|
|
|
@ -11,7 +11,8 @@ namespace StardewModdingAPI.Helpers
|
||||||
{
|
{
|
||||||
public static class CecilHelper
|
public static class CecilHelper
|
||||||
{
|
{
|
||||||
|
//System.Void StardewValley.Game1::.ctor()
|
||||||
|
|
||||||
private static void InjectMethod(ILProcessor ilProcessor, Instruction target, MethodReference method)
|
private static void InjectMethod(ILProcessor ilProcessor, Instruction target, MethodReference method)
|
||||||
{
|
{
|
||||||
Instruction callEnterInstruction = ilProcessor.Create(OpCodes.Call, method);
|
Instruction callEnterInstruction = ilProcessor.Create(OpCodes.Call, method);
|
||||||
|
@ -26,6 +27,13 @@ namespace StardewModdingAPI.Helpers
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// public void ReplaceInstruction(ILProcessor processor, OpCode opcode, string oldOperand, string newOperand)
|
||||||
|
//{
|
||||||
|
//var instructions = processor.Body.Instructions.Where(i => i.OpCode == opcode && i.Operand == oldOperand);
|
||||||
|
// processor.Create()
|
||||||
|
//}
|
||||||
|
|
||||||
public static void InjectEntryMethod(CecilContext stardewContext, CecilContext smapiContext, string injecteeType, string injecteeMethod,
|
public static void InjectEntryMethod(CecilContext stardewContext, CecilContext smapiContext, string injecteeType, string injecteeMethod,
|
||||||
string injectedType, string injectedMethod)
|
string injectedType, string injectedMethod)
|
||||||
{
|
{
|
||||||
|
|
|
@ -0,0 +1,13 @@
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace StardewModdingAPI.Helpers
|
||||||
|
{
|
||||||
|
public static class ReflectionHelper
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
|
@ -72,7 +72,11 @@ namespace StardewModdingAPI
|
||||||
private static void ConfigureMethodInjection()
|
private static void ConfigureMethodInjection()
|
||||||
{
|
{
|
||||||
StardewContext = new CecilContext(CecilContextType.Stardew);
|
StardewContext = new CecilContext(CecilContextType.Stardew);
|
||||||
//SmapiContext = new CecilContext(CecilContextType.SMAPI);
|
SmapiContext = new CecilContext(CecilContextType.SMAPI);
|
||||||
|
|
||||||
|
//StardewContext.ReplaceMethodInstruction(OpCodes.Newobj, "System.Void StardewValley.Game1::.ctor()")
|
||||||
|
var test = StardewContext.GetMethodILProcessor("StardewValley.Program", "Main");
|
||||||
|
StardewContext.GetTypeDefinition("StardewValley.Game1");
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void WeaveOnEnterMethod(Mono.Cecil.Cil.ILProcessor ilProcessor, Instruction target, MethodReference callback)
|
private static void WeaveOnEnterMethod(Mono.Cecil.Cil.ILProcessor ilProcessor, Instruction target, MethodReference callback)
|
||||||
|
@ -143,11 +147,11 @@ namespace StardewModdingAPI
|
||||||
StardewModdingAPI.Log.Info("Initializing SDV Assembly...");
|
StardewModdingAPI.Log.Info("Initializing SDV Assembly...");
|
||||||
|
|
||||||
// Load in the assembly - ignores security
|
// Load in the assembly - ignores security
|
||||||
//StardewAssembly = Assembly.UnsafeLoadFrom(Constants.ExecutionPath + "\\Stardew Valley.exe");
|
StardewAssembly = Assembly.UnsafeLoadFrom(Constants.ExecutionPath + "\\Stardew Valley.exe");
|
||||||
StardewAssembly = Assembly.Load(StardewContext.ModifiedAssembly.GetBuffer());
|
//StardewAssembly = Assembly.Load(StardewContext.ModifiedAssembly.GetBuffer());
|
||||||
StardewProgramType = StardewAssembly.GetType("StardewValley.Program", true);
|
StardewProgramType = StardewAssembly.GetType("StardewValley.Program", true);
|
||||||
StardewGameInfo = StardewProgramType.GetField("gamePtr");
|
StardewGameInfo = StardewProgramType.GetField("gamePtr");
|
||||||
|
|
||||||
// Change the game's version
|
// Change the game's version
|
||||||
StardewModdingAPI.Log.Verbose("Injecting New SDV Version...");
|
StardewModdingAPI.Log.Verbose("Injecting New SDV Version...");
|
||||||
Game1.version += string.Format("-Z_MODDED | SMAPI {0}", Constants.VersionString);
|
Game1.version += string.Format("-Z_MODDED | SMAPI {0}", Constants.VersionString);
|
||||||
|
@ -252,26 +256,11 @@ namespace StardewModdingAPI
|
||||||
StardewForm = Control.FromHandle(Program.gamePtr.Window.Handle).FindForm();
|
StardewForm = Control.FromHandle(Program.gamePtr.Window.Handle).FindForm();
|
||||||
StardewForm.Closing += StardewForm_Closing;
|
StardewForm.Closing += StardewForm_Closing;
|
||||||
|
|
||||||
ready = true;
|
ready = true;
|
||||||
|
|
||||||
StardewGameInfo.SetValue(StardewProgramType, gamePtr);
|
StardewAssembly.EntryPoint.Invoke(null, new object[] { new string[] { } });
|
||||||
gamePtr.Run();
|
//StardewGameInfo.SetValue(StardewProgramType, gamePtr);
|
||||||
|
gamePtr.Run();
|
||||||
#region deprecated
|
|
||||||
if (false)
|
|
||||||
{
|
|
||||||
//Nope, I can't get it to work. I depend on Game1 being an SGame, and can't cast a parent to a child
|
|
||||||
//I'm leaving this here in case the community is interested
|
|
||||||
//StardewInjectorMod.Entry(true);
|
|
||||||
Type gt = StardewAssembly.GetType("StardewValley.Game1", true);
|
|
||||||
gamePtr = (SGame)Activator.CreateInstance(gt);
|
|
||||||
|
|
||||||
ready = true;
|
|
||||||
|
|
||||||
StardewGameInfo.SetValue(StardewProgramType, gamePtr);
|
|
||||||
gamePtr.Run();
|
|
||||||
}
|
|
||||||
#endregion
|
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
|
|
|
@ -145,6 +145,7 @@
|
||||||
<Compile Include="Extensions.cs" />
|
<Compile Include="Extensions.cs" />
|
||||||
<Compile Include="Helpers\CecilContext.cs" />
|
<Compile Include="Helpers\CecilContext.cs" />
|
||||||
<Compile Include="Helpers\CecilHelper.cs" />
|
<Compile Include="Helpers\CecilHelper.cs" />
|
||||||
|
<Compile Include="Helpers\ReflectionHelper.cs" />
|
||||||
<Compile Include="Inheritance\ItemStackChange.cs" />
|
<Compile Include="Inheritance\ItemStackChange.cs" />
|
||||||
<Compile Include="Inheritance\Menus\SBobberBar.cs" />
|
<Compile Include="Inheritance\Menus\SBobberBar.cs" />
|
||||||
<Compile Include="Inheritance\Menus\SGameMenu.cs" />
|
<Compile Include="Inheritance\Menus\SGameMenu.cs" />
|
||||||
|
|
Loading…
Reference in New Issue