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)
|
||||
{
|
||||
ContextType = contextType;
|
||||
|
||||
if (ContextType == CecilContextType.SMAPI)
|
||||
_assemblyDefinition = AssemblyDefinition.ReadAssembly(Assembly.GetExecutingAssembly().Location);
|
||||
else
|
||||
_assemblyDefinition = AssemblyDefinition.ReadAssembly(Constants.StardewExePath);
|
||||
}
|
||||
|
||||
|
||||
public ILProcessor GetMethodILProcessor(string type, string method)
|
||||
{
|
||||
if (_assemblyDefinition == null)
|
||||
|
@ -64,7 +63,7 @@ namespace StardewModdingAPI.Helpers
|
|||
throw new ArgumentNullException("Both type and method must be set");
|
||||
|
||||
Mono.Cecil.Cil.ILProcessor ilProcessor = null;
|
||||
TypeDefinition typeDef = _assemblyDefinition.MainModule.Types.FirstOrDefault(n => n.FullName == type);
|
||||
TypeDefinition typeDef = GetTypeDefinition(type);
|
||||
if (typeDef != null)
|
||||
{
|
||||
MethodDefinition methodDef = typeDef.Methods.FirstOrDefault(m => m.Name == method);
|
||||
|
@ -77,6 +76,31 @@ namespace StardewModdingAPI.Helpers
|
|||
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)
|
||||
{
|
||||
if (_assemblyDefinition == null)
|
||||
|
|
|
@ -11,7 +11,8 @@ namespace StardewModdingAPI.Helpers
|
|||
{
|
||||
public static class CecilHelper
|
||||
{
|
||||
|
||||
//System.Void StardewValley.Game1::.ctor()
|
||||
|
||||
private static void InjectMethod(ILProcessor ilProcessor, Instruction target, MethodReference 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,
|
||||
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()
|
||||
{
|
||||
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)
|
||||
|
@ -143,11 +147,11 @@ namespace StardewModdingAPI
|
|||
StardewModdingAPI.Log.Info("Initializing SDV Assembly...");
|
||||
|
||||
// Load in the assembly - ignores security
|
||||
//StardewAssembly = Assembly.UnsafeLoadFrom(Constants.ExecutionPath + "\\Stardew Valley.exe");
|
||||
StardewAssembly = Assembly.Load(StardewContext.ModifiedAssembly.GetBuffer());
|
||||
StardewAssembly = Assembly.UnsafeLoadFrom(Constants.ExecutionPath + "\\Stardew Valley.exe");
|
||||
//StardewAssembly = Assembly.Load(StardewContext.ModifiedAssembly.GetBuffer());
|
||||
StardewProgramType = StardewAssembly.GetType("StardewValley.Program", true);
|
||||
StardewGameInfo = StardewProgramType.GetField("gamePtr");
|
||||
|
||||
|
||||
// Change the game's version
|
||||
StardewModdingAPI.Log.Verbose("Injecting New SDV Version...");
|
||||
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.Closing += StardewForm_Closing;
|
||||
|
||||
ready = true;
|
||||
|
||||
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
|
||||
ready = true;
|
||||
|
||||
StardewAssembly.EntryPoint.Invoke(null, new object[] { new string[] { } });
|
||||
//StardewGameInfo.SetValue(StardewProgramType, gamePtr);
|
||||
gamePtr.Run();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
|
|
|
@ -145,6 +145,7 @@
|
|||
<Compile Include="Extensions.cs" />
|
||||
<Compile Include="Helpers\CecilContext.cs" />
|
||||
<Compile Include="Helpers\CecilHelper.cs" />
|
||||
<Compile Include="Helpers\ReflectionHelper.cs" />
|
||||
<Compile Include="Inheritance\ItemStackChange.cs" />
|
||||
<Compile Include="Inheritance\Menus\SBobberBar.cs" />
|
||||
<Compile Include="Inheritance\Menus\SGameMenu.cs" />
|
||||
|
|
Loading…
Reference in New Issue