diff options
| author | Zoryn <zoryn4163@gmail.com> | 2016-03-03 15:06:25 -0500 |
|---|---|---|
| committer | Zoryn <zoryn4163@gmail.com> | 2016-03-03 15:06:25 -0500 |
| commit | 9a1b910ea32f518b605c88315f192afc6fc40f28 (patch) | |
| tree | fcc475ef046295a06a2358c7f83cb4e97e38ce9c | |
| parent | de3f161a49bf7486290f0e4b3531177f949bc3cd (diff) | |
| download | SMAPI-9a1b910ea32f518b605c88315f192afc6fc40f28.tar.gz SMAPI-9a1b910ea32f518b605c88315f192afc6fc40f28.tar.bz2 SMAPI-9a1b910ea32f518b605c88315f192afc6fc40f28.zip | |
resync for merge conflicts
64 files changed, 12726 insertions, 687 deletions
@@ -1,7 +1,6 @@ StardewModdingAPI/bin/ StardewModdingAPI/obj/ packages/ -StardewInjector/ *.symlink *.lnk diff --git a/Release/Mods/TrainerMod.dll b/Release/Mods/TrainerMod.dll Binary files differindex bcf663ab..d39f4375 100644 --- a/Release/Mods/TrainerMod.dll +++ b/Release/Mods/TrainerMod.dll diff --git a/Release/StardewModdingAPI.exe b/Release/StardewModdingAPI.exe Binary files differindex 5c6d556b..c4813237 100644 --- a/Release/StardewModdingAPI.exe +++ b/Release/StardewModdingAPI.exe diff --git a/StardewInjector/App.config b/StardewInjector/App.config new file mode 100644 index 00000000..f1914205 --- /dev/null +++ b/StardewInjector/App.config @@ -0,0 +1,15 @@ +<?xml version="1.0" encoding="utf-8"?> +<configuration> + <appSettings> + <add key="RunSpeed" value="0"/> + <add key="EnableTweakedDiagonalMovement" value="False"/> + <add key="EnableEasyFishing" value="False"/> + <add key="EnableAlwaysSpawnFishingBubble" value="False"/> + <add key="SecondsPerTenMinutes" value="7"/> + <add key="EnableDebugMode" value="False"/> + + </appSettings> + <startup> + <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.0"/> + </startup> +</configuration> diff --git a/StardewInjector/CecilUtils.cs b/StardewInjector/CecilUtils.cs new file mode 100644 index 00000000..acdf5198 --- /dev/null +++ b/StardewInjector/CecilUtils.cs @@ -0,0 +1,173 @@ +using Mono.Cecil; +using Mono.Cecil.Cil; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace StardewInjector +{ + public struct ScannerState + { + public ILProcessor ILProcessor; + public Instruction Instruction; + + public ScannerState(ILProcessor ilProc, Instruction ins) + { + ILProcessor = ilProc; + Instruction = ins; + } + + public ScannerState Previous(Func<Instruction, bool> until = null) + { + if (until != null) + { + Instruction cur = this.Instruction; + do + { + cur = cur.Previous; + } while (!until(cur)); + return new ScannerState(this.ILProcessor, cur); + } + return new ScannerState(this.ILProcessor, Instruction.Previous); + } + + public ScannerState Next(Func<Instruction, bool> until = null) + { + if (until != null) + { + Instruction cur = this.Instruction; + do + { + cur = cur.Next; + } while (!until(cur)); + return new ScannerState(this.ILProcessor, cur); + } + return new ScannerState(this.ILProcessor, Instruction.Next); + } + + public ScannerState Last() + { + var instructions = this.ILProcessor.Body.Instructions; + return new ScannerState(this.ILProcessor, instructions[instructions.Count - 1]); + } + + public ScannerState First() + { + var instructions = this.ILProcessor.Body.Instructions; + return new ScannerState(this.ILProcessor, instructions[0]); + } + + public ScannerState ReplaceCreate(OpCode opcode) + { + Instruction ins = this.ILProcessor.Create(opcode); + this.ILProcessor.Replace(this.Instruction, ins); + return new ScannerState(this.ILProcessor, ins); + } + + public ScannerState ReplaceCreate(OpCode opcode, object arg) + { + Instruction ins = this.ILProcessor.Create(opcode, arg as dynamic); + this.ILProcessor.Replace(this.Instruction, ins); + return new ScannerState(this.ILProcessor, ins); + } + + public ScannerState CreateBefore(OpCode opcode) + { + Instruction ins = this.ILProcessor.Create(opcode); + this.ILProcessor.InsertBefore(this.Instruction, ins); + return new ScannerState(this.ILProcessor, ins); + } + + public ScannerState CreateBefore(OpCode opcode, object arg) + { + Instruction ins = this.ILProcessor.Create(opcode, arg as dynamic); + this.ILProcessor.InsertBefore(this.Instruction, ins); + return new ScannerState(this.ILProcessor, ins); + } + + public ScannerState CreateAfter(OpCode opcode) + { + Instruction ins = this.ILProcessor.Create(opcode); + this.ILProcessor.InsertAfter(this.Instruction, ins); + return new ScannerState(this.ILProcessor, ins); + } + + public ScannerState CreateAfter(OpCode opcode, object arg) + { + Instruction ins = this.ILProcessor.Create(opcode, arg as dynamic); + this.ILProcessor.InsertAfter(this.Instruction, ins); + return new ScannerState(this.ILProcessor, ins); + } + } + + public static class CecilUtils + { + public static ScannerState Scanner(this MethodDefinition me) + { + return new ScannerState(me.Body.GetILProcessor(), me.Body.Instructions[0]); + } + + public static ScannerState FindSetField(this MethodDefinition me, string fieldName) + { + var instruction = me.Body.Instructions + .FirstOrDefault(i => i.OpCode == OpCodes.Stsfld && (i.Operand as FieldDefinition).Name == fieldName); + return new ScannerState(me.Body.GetILProcessor(), instruction); + } + + public static ScannerState FindLoadField(this MethodDefinition me, string fieldName) + { + var instruction = me.Body.Instructions + .FirstOrDefault(i => { + if (i.OpCode != OpCodes.Ldfld && i.OpCode != OpCodes.Ldsfld) + return false; + if (i.Operand is FieldDefinition && (i.Operand as FieldDefinition).Name == fieldName) + return true; + if (i.Operand is FieldReference && (i.Operand as FieldReference).Name == fieldName) + return true; + return false; + }); + return new ScannerState(me.Body.GetILProcessor(), instruction); + } + + public static ScannerState FindLoadConstant(this MethodDefinition me, int val) + { + var instruction = me.Body.Instructions + .FirstOrDefault(i => i.OpCode == OpCodes.Ldc_I4 && (int)i.Operand == val); + return new ScannerState(me.Body.GetILProcessor(), instruction); + } + + public static ScannerState FindLoadConstant(this MethodDefinition me, float val) + { + var instruction = me.Body.Instructions + .FirstOrDefault(i => i.OpCode == OpCodes.Ldc_R4 && (float)i.Operand == val); + return new ScannerState(me.Body.GetILProcessor(), instruction); + } + + public static MethodDefinition FindMethod(this ModuleDefinition me, string name) + { + var nameSplit = name.Split(new string[] { "::" }, StringSplitOptions.RemoveEmptyEntries); + if (nameSplit.Length < 2) + throw new ArgumentException("Invalid method full name", "name"); + + var currentType = me.Types.FirstOrDefault(t => t.FullName == nameSplit[0]); + if (currentType == null) + return null; + + return currentType.Methods.FirstOrDefault(m => m.Name == nameSplit[1]); + } + + public static FieldDefinition FindField(this ModuleDefinition me, string name) + { + var nameSplit = name.Split(new string[] { "::" }, StringSplitOptions.RemoveEmptyEntries); + if (nameSplit.Length < 2) + throw new ArgumentException("Invalid field full name", "name"); + + var currentType = me.Types.FirstOrDefault(t => t.FullName == nameSplit[0]); + if (currentType == null) + return null; + + return currentType.Fields.FirstOrDefault(m => m.Name == nameSplit[1]); + } + } +} diff --git a/StardewInjector/Config.cs b/StardewInjector/Config.cs new file mode 100644 index 00000000..cea45e98 --- /dev/null +++ b/StardewInjector/Config.cs @@ -0,0 +1,72 @@ +using System; +using System.Collections.Generic; +using System.Configuration; +using System.Linq; +using System.Text; + +namespace StardewInjector +{ + public static class Config + { + public static bool EnableDebugMode + { + get + { + bool val = false; + bool.TryParse(ConfigurationManager.AppSettings["EnableDebugMode"], out val); + return val; + } + } + + public static bool EnableAlwaysSpawnFishingBubble + { + get + { + bool val = false; + bool.TryParse(ConfigurationManager.AppSettings["EnableAlwaysSpawnFishingBubble"], out val); + return val; + } + } + + public static bool EnableEasyFishing + { + get + { + bool val = false; + bool.TryParse(ConfigurationManager.AppSettings["EnableEasyFishing"], out val); + return val; + } + } + + public static int SecondsPerTenMinutes + { + get + { + int val = 7; + int.TryParse(ConfigurationManager.AppSettings["SecondsPerTenMinutes"], out val); + return val; + } + } + + public static float RunSpeed + { + get + { + float val = 1f; + float.TryParse(ConfigurationManager.AppSettings["RunSpeed"], out val); + return val; + } + } + + public static bool EnableTweakedDiagonalMovement + { + get + { + bool val = false; + bool.TryParse(ConfigurationManager.AppSettings["EnableTweakedDiagonalMovement"], out val); + return val; + } + } + + } +} diff --git a/StardewInjector/Program.cs b/StardewInjector/Program.cs new file mode 100644 index 00000000..41c72240 --- /dev/null +++ b/StardewInjector/Program.cs @@ -0,0 +1,30 @@ +/* +using Mono.Cecil; +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Reflection; +using System.Text; +using System.Threading.Tasks; + +namespace Stardew_Injector +{ + class Program + { + + private static Stardew_Hooker hooker = new Stardew_Hooker(); + + static void Main(string[] args) + { + hooker.Initialize(); + hooker.ApplyHooks(); + hooker.Finalize(); + + hooker.Run(); + Console.ReadLine(); + } + + } +} +*/
\ No newline at end of file diff --git a/StardewInjector/Properties/AssemblyInfo.cs b/StardewInjector/Properties/AssemblyInfo.cs new file mode 100644 index 00000000..0ba4aafe --- /dev/null +++ b/StardewInjector/Properties/AssemblyInfo.cs @@ -0,0 +1,36 @@ +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +// General Information about an assembly is controlled through the following +// set of attributes. Change these attribute values to modify the information +// associated with an assembly. +[assembly: AssemblyTitle("StardewInjector")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("")] +[assembly: AssemblyProduct("StardewInjector")] +[assembly: AssemblyCopyright("Copyright © 2016")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +// Setting ComVisible to false makes the types in this assembly not visible +// to COM components. If you need to access a type in this assembly from +// COM, set the ComVisible attribute to true on that type. +[assembly: ComVisible(false)] + +// The following GUID is for the ID of the typelib if this project is exposed to COM +[assembly: Guid("820406dc-ae78-461f-8c7f-6329f34f986c")] + +// Version information for an assembly consists of the following four values: +// +// Major Version +// Minor Version +// Build Number +// Revision +// +// You can specify all the values or you can default the Build and Revision Numbers +// by using the '*' as shown below: +// [assembly: AssemblyVersion("1.0.*")] +[assembly: AssemblyVersion("1.0.0.0")] +[assembly: AssemblyFileVersion("1.0.0.0")] diff --git a/StardewInjector/StardewHooker.cs b/StardewInjector/StardewHooker.cs new file mode 100644 index 00000000..a92b96c1 --- /dev/null +++ b/StardewInjector/StardewHooker.cs @@ -0,0 +1,190 @@ +using Microsoft.Xna.Framework; +using Mono.Cecil; +using Mono.Cecil.Cil; +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Reflection; +using System.Text; +using System.Threading.Tasks; +using StardewModdingAPI; + +namespace StardewInjector +{ + public class Stardew_Hooker + { + private AssemblyDefinition m_vAsmDefinition = null; + private ModuleDefinition m_vModDefinition = null; + private Assembly m_vAssembly = null; + + public bool Initialize() + { + Console.WriteLine("Initiating StarDew_Injector...."); + try + { + this.m_vAsmDefinition = AssemblyDefinition.ReadAssembly(@"Stardew Valley.exe"); + this.m_vModDefinition = this.m_vAsmDefinition.MainModule; + return true; + } + catch (Exception ex) + { + Program.LogError(ex); + return false; + } + } + + public bool Finalize() + { + Console.WriteLine("Finalizing StarDew_Injector...."); + try + { + if (this.m_vAsmDefinition == null) + return false; + + using (MemoryStream mStream = new MemoryStream()) + { + // Write the edited data to the memory stream.. + this.m_vAsmDefinition.Write(mStream); + + // Load the new assembly from the memory stream buffer.. + this.m_vAssembly = Assembly.Load(mStream.GetBuffer()); + + Program.StardewAssembly = m_vAssembly; + + return true; + } + } + catch (Exception ex) + { + Program.LogError(ex); + return false; + } + } + + public bool Run() + { + if (this.m_vAssembly == null) + return false; + + Console.WriteLine("Starting Stardew Valley..."); + + m_vAssembly.EntryPoint.Invoke(null, new object[] {new string[0]}); + + return true; + } + + public void ApplyHooks() + { + Console.WriteLine("Applying StarDew_Injector...."); + try + { + InjectMovementSpeed(); + + if (Config.SecondsPerTenMinutes != 7) + InjectClockScale(); + + if (Config.EnableEasyFishing) + InjectEasyFishing(); + + if (Config.EnableAlwaysSpawnFishingBubble) + InjectMoreBubbles(); + + /* + if (Config.EnableDebugMode) + InjectDebugMode(); + */ + } + catch (Exception ex) + { + Program.LogError(ex); + } + + } + + private void InjectDebugMode() + { + this.m_vModDefinition.FindMethod("StardewValley.Program::.cctor") + .FindSetField("releaseBuild").Previous() + .ReplaceCreate(OpCodes.Ldc_I4_0); + + Console.WriteLine("Enabled debug mode."); + } + + private void InjectMoreBubbles() + { + this.m_vModDefinition.FindMethod("StardewValley.GameLocation::performTenMinuteUpdate") + .FindLoadField("currentLocation").Next(i => i.ToString().Contains("NextDouble")).Next() + .ReplaceCreate(OpCodes.Ldc_R8, 1.1); + + Console.WriteLine("Forced each area to always spawn a fishing bubble."); + } + + private void InjectEasyFishing() + { + this.m_vModDefinition.FindMethod("StardewValley.Menus.BobberBar::update") + .FindLoadConstant(694) + .Next(i => i.OpCode == OpCodes.Ldc_R4) + .ReplaceCreate(OpCodes.Ldc_R4, 0.001f) + .Next(i => i.OpCode == OpCodes.Ldc_R4) + .ReplaceCreate(OpCodes.Ldc_R4, 0.001f); + + Console.WriteLine("Replaced fish escape constants for all bobbers & bobber id 694 with 0.001, slowing it down."); + } + + private void InjectClockScale() + { + int timeScale = Config.SecondsPerTenMinutes; + timeScale *= 1000; + + this.m_vModDefinition.FindMethod("StardewValley.Game1::UpdateGameClock") + .FindLoadConstant(7000f) + .ReplaceCreate(OpCodes.Ldc_R4, timeScale*1.0f) + .Next(i => i.OpCode == OpCodes.Ldc_R4 && (float) i.Operand == 7000f) + .ReplaceCreate(OpCodes.Ldc_R4, timeScale*1.0f) + .Next(i => i.OpCode == OpCodes.Ldc_I4 && (int) i.Operand == 7000) + .ReplaceCreate(OpCodes.Ldc_I4, timeScale); + + Console.WriteLine("Updated lighting for new timescale ({0}).", timeScale); + } + + private void InjectMovementSpeed() + { + + + if (Config.EnableTweakedDiagonalMovement) + { + this.m_vModDefinition.FindMethod("StardewValley.Farmer::getMovementSpeed") + .FindLoadField("movementDirections").Next(i => i.OpCode == OpCodes.Ldc_I4_1) + .ReplaceCreate(OpCodes.Ldc_I4_4); + + Console.WriteLine("Removed diagonal movement check."); + } + + if (Config.RunSpeed > 0) + { + this.m_vModDefinition.FindMethod("StardewValley.Farmer::getMovementSpeed") + .FindLoadField("movementDirections").Last().CreateBefore(OpCodes.Ldc_R4, (float) Config.RunSpeed).CreateAfter(OpCodes.Add); + + Console.WriteLine("Added run speed: " + Config.RunSpeed); + } + + + } + + + + private void DumpInstructionsToFile(MethodDefinition methodDefinition) + { + var fileName = string.Format("{0}.{1}.txt", methodDefinition.DeclaringType.Name, methodDefinition.Name); + + using (var stream = File.OpenWrite(Path.Combine(".", fileName))) + using (var writer = new StreamWriter(stream)) + { + var ilProcessor = methodDefinition.Body.GetILProcessor(); + for (int i = 0; i < ilProcessor.Body.Instructions.Count; i++) + writer.WriteLine((i) + ":" + ilProcessor.Body.Instructions[i]); + } + } + } +}
\ No newline at end of file diff --git a/StardewInjector/StardewInjector.cs b/StardewInjector/StardewInjector.cs new file mode 100644 index 00000000..055a79f9 --- /dev/null +++ b/StardewInjector/StardewInjector.cs @@ -0,0 +1,55 @@ +using StardewModdingAPI; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace StardewInjector +{ + public class StardewInjector : Mod + { + public override string Name + { + get { return "Stardew Injector"; } + } + + public override string Authour + { + get { return "Zoryn Aaron"; } + } + + public override string Version + { + get { return "1.0"; } + } + + public override string Description + { + get { return "Pulled from https://github.com/kevinmurphy678/Stardew_Injector and converted to a mod."; } + } + + public static Stardew_Hooker hooker { get; set; } + public override void Entry(params object[] objects) + { + if (objects.Length <= 0 || (objects.Length > 0 && objects[0].AsBool() == false)) + { + hooker = new Stardew_Hooker(); + hooker.Initialize(); + hooker.ApplyHooks(); + hooker.Finalize(); + + Program.LogInfo("INJECTOR ENTERED"); + } + else if (objects.Length > 0 && objects[0].AsBool() == true) + { + Program.LogInfo("INJECTOR LAUNCHING"); + hooker.Run(); + } + else + { + Program.LogError("INVALID PARAMETERS FOR INJECTOR"); + } + } + } +} diff --git a/StardewInjector/StardewInjector.csproj b/StardewInjector/StardewInjector.csproj new file mode 100644 index 00000000..7987a7bd --- /dev/null< |
