diff --git a/EliteDangerousOdysseyPlugin/EliteDangerousOdysseyPlugin.cs b/EliteDangerousOdysseyPlugin/EliteDangerousOdysseyPlugin.cs new file mode 100644 index 0000000..4c894cc --- /dev/null +++ b/EliteDangerousOdysseyPlugin/EliteDangerousOdysseyPlugin.cs @@ -0,0 +1,299 @@ +using EliteDangerousOdysseyPlugin.Properties; +using Newtonsoft.Json.Linq; +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.ComponentModel.Composition; +using System.Diagnostics; +using System.IO; +using System.Linq; +using System.Reflection; +using System.Runtime.InteropServices; +using System.Threading; +using YawGLAPI; + +namespace YawVR_Game_Engine.Plugin +{ + + + + [Export(typeof(Game))] + [ExportMetadata("Name", "Elite Dangerous Odyssey")] + [ExportMetadata("Version", "1.7")] + class EliteDangerousOdysseyPlugin : Game { + + + public int STEAM_ID => 359320; + public string PROCESS_NAME => "EliteDangerous64"; + public bool PATCH_AVAILABLE => false; + public string AUTHOR => "YawVR"; + + public Stream Logo => GetStream("logo.png"); + public Stream SmallLogo => GetStream("recent.png"); + + public Stream Background => GetStream("wide.png"); + + public string Description => string.Empty; + + private IMainFormDispatcher dispatcher; + private IProfileManager controller; + + + + private bool running = false; + private Thread readThread; + private Process handle; + private IntPtr Base; + + private string[] inputs = new string[0]; + + private IntPtr[][] inputAddrs; + + [DllImport("kernel32.dll")] + static extern uint GetLastError(); + + [DllImport("kernel32.dll")] + public static extern IntPtr ReadProcessMemory(IntPtr hProcess, IntPtr lpBaseAddress, + [In, Out] byte[] buffer, UInt32 size, out IntPtr lpNumberOfBytesRead); + + public List DefaultProfile() { + + + return dispatcher.JsonToComponents(Resources.defProfile); + } + public LedEffect DefaultLED() { + + return dispatcher.JsonToLED(Resources.defProfile); + } + + public void Exit() { + running = false; + } + + public string[] GetInputData() { + return inputs; + } + + + public void SetReferences(IProfileManager controller,IMainFormDispatcher dispatcher) + { + this.controller = controller; + this.dispatcher = dispatcher; + JObject objectFileData; + dispatcher.GetObjectFile("elitedangerous", out objectFileData); + if (objectFileData != null) + { + SetupInputs(objectFileData); + } + + } + + private void SetupInputs(JObject objectFileData) + { + + List inputs = new List(); + + inputAddrs = new IntPtr[objectFileData.Properties().Count()][]; + + int counter = 0; + + + foreach(var obj in objectFileData) + { + inputs.Add($"{obj.Key}"); + + var offsets = obj.Value["Offsets"].ToArray(); + inputAddrs[counter] = new IntPtr[offsets.Length]; + for(int i =0;i< offsets.Length; i++) + { + string v = offsets[i].ToString(); + inputAddrs[counter][i] = (IntPtr)int.Parse(v, System.Globalization.NumberStyles.HexNumber); + } + counter++; + } + this.inputs = inputs.ToArray(); + + + } + public void Init() { + + Console.WriteLine("STARTED ELITE PLUGIN"); + running = true; + + + readThread = new Thread(new ThreadStart(ReadFunction)); + readThread.Start(); + + } + + private void ReadFunction() { + try { + GetBase(PROCESS_NAME); + while (running) { + if (handle != null) + { + if (Base != null) + { + for (int i = 0; i < inputAddrs.Length; i++) + { + controller.SetInput(i, readPtr(inputAddrs[i], false)); + } + } + } else + { + Thread.Sleep(1000); + GetBase(PROCESS_NAME); + } + + // Console.WriteLine(string.Format("Yaw: {0:0.00} \n Pitch: {1:0.00} \n Roll {2:0.00}", Yaw, Pitch, Roll) + Thread.Sleep(20); + + } + + } + catch (Exception) { + dispatcher.ExitGame(); + } + } + + public void PatchGame() + { + return; + } + private bool GetBase(string processName) { + Process[] p = Process.GetProcessesByName(processName); + if (p.Length == 0) { + return false; + } + handle = p[0]; + + Base = getBase(handle); + + return true; + } + + float readPtr(IntPtr[] offsets, bool debug = false, string module = null) { + try { + IntPtr tmpptr = (IntPtr)0; + + for (int i = 0; i <= offsets.Length - 1; i++) { + if (i == 0) { + if (debug) + Console.Write(Base.ToString("X") + "[Base] + " + offsets[i].ToString("X") + "[OFFSET 0]"); + IntPtr ptr = IntPtr.Add(Base, (int)offsets[i]); + tmpptr = (IntPtr)ReadInt64(ptr, 8, handle.Handle); + if (debug) + Console.WriteLine(" is " + tmpptr.ToString("X")); + // Console.WriteLine(GetLastError()); + } + else { + if (debug) + Console.Write(tmpptr.ToString("X") + " + " + offsets[i].ToString("X") + "[OFFSET " + i + "]"); + IntPtr ptr2 = IntPtr.Add(tmpptr, (int)offsets[i]); + + if (i == offsets.Length - 1) { + return (BitConverter.ToSingle(ReadBytes((IntPtr)handle.Handle, ptr2, 8), 0)); + } + else { + tmpptr = (IntPtr)ReadInt64(ptr2, 8, handle.Handle); + } + tmpptr = (IntPtr)ReadInt64(ptr2, 8, handle.Handle); + if (debug) + Console.WriteLine(" is " + tmpptr.ToString("X")); + //Console.WriteLine(GetLastError()); + } + } + + } catch (IndexOutOfRangeException) { + } catch (InvalidOperationException) { } + catch (Win32Exception) { } + return 0; + } + IntPtr getBase(Process handle, string module = null) + { + try + { + ProcessModuleCollection modules = handle.Modules; + if (module != null) + { + for (int i = 0; i <= modules.Count - 1; i++) + { + if (modules[i].ModuleName == module) + { + return (IntPtr)modules[i].BaseAddress; + } + } + Console.WriteLine("Module Not Found"); + + } + else + { + + return (IntPtr)handle.MainModule.BaseAddress; + } + Console.WriteLine("zero error"); + return (IntPtr)0; + + } + catch (Win32Exception e) + { + Console.WriteLine(e); + // Form1.Instance.ErrorHappened(new Exception("Please switch game engine version to 64bit")); + return (IntPtr)null; + } + } + + + public static byte[] ReadBytes(IntPtr Handle, IntPtr Address, uint BytesToRead) { + IntPtr ptrBytesRead; + byte[] buffer = new byte[BytesToRead]; + ReadProcessMemory(Handle, Address, buffer, BytesToRead, out ptrBytesRead); + + //Console.WriteLine(GetLastError()); + return buffer; + } + + + public static Int64 ReadInt64(IntPtr Address, uint length = 8, IntPtr? Handle = null) { + return (BitConverter.ToInt64(ReadBytes((IntPtr)Handle, Address, length), 0)); + } + + + public static float Clamp(float v, float limit) + { + if (limit == -1) return v; + if (v > limit) return limit; + if (v < -limit) return -limit; + return v; + } + + public static float NormalizeAngle(float angle) + { + float newAngle = angle; + while (newAngle <= -180) newAngle += 360; + while (newAngle > 180) newAngle -= 360; + return newAngle; + } + + public Dictionary GetFeatures() + { + return null; + } + + Stream GetStream(string resourceName) + { + var assembly = GetType().Assembly; + var rr = assembly.GetManifestResourceNames(); + string fullResourceName = $"{assembly.GetName().Name}.Resources.{resourceName}"; + return assembly.GetManifestResourceStream(fullResourceName); + } + + public Type GetConfigBody() + { + return null; + } + } + + + +} diff --git a/EliteDangerousOdysseyPlugin/EliteDangerousOdysseyPlugin.csproj b/EliteDangerousOdysseyPlugin/EliteDangerousOdysseyPlugin.csproj new file mode 100644 index 0000000..6dd147b --- /dev/null +++ b/EliteDangerousOdysseyPlugin/EliteDangerousOdysseyPlugin.csproj @@ -0,0 +1,36 @@ + + + net8.0 + Library + false + false + true + All;Debug;Release + + + bin\x64\Debug\ + MinimumRecommendedRules.ruleset + + + bin\x64\Release\ + MinimumRecommendedRules.ruleset + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/EliteDangerousOdysseyPlugin/Properties/Resources.Designer.cs b/EliteDangerousOdysseyPlugin/Properties/Resources.Designer.cs new file mode 100644 index 0000000..48c26f3 --- /dev/null +++ b/EliteDangerousOdysseyPlugin/Properties/Resources.Designer.cs @@ -0,0 +1,81 @@ +//------------------------------------------------------------------------------ +// +// This code was generated by a tool. +// Runtime Version:4.0.30319.42000 +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ + +namespace EliteDangerousOdysseyPlugin.Properties { + using System; + + + /// + /// A strongly-typed resource class, for looking up localized strings, etc. + /// + // This class was auto-generated by the StronglyTypedResourceBuilder + // class via a tool like ResGen or Visual Studio. + // To add or remove a member, edit your .ResX file then rerun ResGen + // with the /str option, or rebuild your VS project. + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "17.0.0.0")] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] + internal class Resources { + + private static global::System.Resources.ResourceManager resourceMan; + + private static global::System.Globalization.CultureInfo resourceCulture; + + [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] + internal Resources() { + } + + /// + /// Returns the cached ResourceManager instance used by this class. + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Resources.ResourceManager ResourceManager { + get { + if (object.ReferenceEquals(resourceMan, null)) { + global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("EliteDangerousOdysseyPlugin.Properties.Resources", typeof(Resources).Assembly); + resourceMan = temp; + } + return resourceMan; + } + } + + /// + /// Overrides the current thread's CurrentUICulture property for all + /// resource lookups using this strongly typed resource class. + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Globalization.CultureInfo Culture { + get { + return resourceCulture; + } + set { + resourceCulture = value; + } + } + + /// + /// Looks up a localized string similar to {"GameName":"Elite Dangerous","Name":"Default","Components":[{"Constant":false,"Input_index":4,"Output_index":1,"MultiplierPos":15.0,"MultiplierNeg":15.0,"Offset":0.0,"Inverse":false,"Limit":-1.0,"Smoothing":0.23251808,"Enabled":true,"Spikeflatter":{"Enabled":false,"Limit":100.0,"Strength":0.5},"Deadzone":0.0,"Type":0,"Condition":[],"Math":[]},{"Constant":false,"Input_index":5,"Output_index":2,"MultiplierPos":15.0,"MultiplierNeg":15.0,"Offset":0.0,"Inverse":false,"Limit":-1.0,"Smoothing":0.23251808,"Enabled [rest of string was truncated]";. + /// + internal static string defProfile { + get { + return ResourceManager.GetString("defProfile", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to . + /// + internal static string description { + get { + return ResourceManager.GetString("description", resourceCulture); + } + } + } +} diff --git a/EliteDangerousOdysseyPlugin/Properties/Resources.resx b/EliteDangerousOdysseyPlugin/Properties/Resources.resx new file mode 100644 index 0000000..a7a4d3a --- /dev/null +++ b/EliteDangerousOdysseyPlugin/Properties/Resources.resx @@ -0,0 +1,126 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + {"GameName":"Elite Dangerous Odyssey","Name":"Default","Components":[{"Constant":false,"Input_index":4,"Output_index":1,"MultiplierPos":15.0,"MultiplierNeg":15.0,"Offset":0.0,"Inverse":false,"Limit":-1.0,"Smoothing":0.23251808,"Enabled":true,"Spikeflatter":{"Enabled":false,"Limit":100.0,"Strength":0.5},"Deadzone":0.0,"Type":0,"Condition":[],"Math":[]},{"Constant":false,"Input_index":5,"Output_index":2,"MultiplierPos":15.0,"MultiplierNeg":15.0,"Offset":0.0,"Inverse":false,"Limit":-1.0,"Smoothing":0.23251808,"Enabled":true,"Spikeflatter":{"Enabled":false,"Limit":100.0,"Strength":0.5},"Deadzone":0.0,"Type":0,"Condition":[],"Math":[]}],"Effects":{"EffectID":4,"InputID":0,"Multiplier":0.005,"Colors":[{"R":255,"G":255,"B":255},{"R":189,"G":255,"B":194},{"R":255,"G":0,"B":27},{"R":0,"G":0,"B":255}]},"Functions":[]} + + + + + \ No newline at end of file diff --git a/EliteDangerousOdysseyPlugin/Resources/logo.png b/EliteDangerousOdysseyPlugin/Resources/logo.png new file mode 100644 index 0000000..0e1e5f8 Binary files /dev/null and b/EliteDangerousOdysseyPlugin/Resources/logo.png differ diff --git a/EliteDangerousOdysseyPlugin/Resources/recent.png b/EliteDangerousOdysseyPlugin/Resources/recent.png new file mode 100644 index 0000000..fe8e08e Binary files /dev/null and b/EliteDangerousOdysseyPlugin/Resources/recent.png differ diff --git a/EliteDangerousOdysseyPlugin/Resources/wide.png b/EliteDangerousOdysseyPlugin/Resources/wide.png new file mode 100644 index 0000000..bd78d0c Binary files /dev/null and b/EliteDangerousOdysseyPlugin/Resources/wide.png differ diff --git a/EliteDangerousOdysseyPlugin/app.config b/EliteDangerousOdysseyPlugin/app.config new file mode 100644 index 0000000..a0cefc2 --- /dev/null +++ b/EliteDangerousOdysseyPlugin/app.config @@ -0,0 +1,11 @@ + + + + + + + + + + + \ No newline at end of file diff --git a/Plugins.sln b/Plugins.sln index 6e3d0d3..c9854b8 100644 --- a/Plugins.sln +++ b/Plugins.sln @@ -27,6 +27,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Dirtrally2Plugin", "Dirtral EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "EliteDangerousPlugin", "EliteDangerousPlugin\EliteDangerousPlugin.csproj", "{92393AB1-1006-4B0B-9E9D-365A03EFB5C7}" EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "EliteDangerousOdysseyPlugin", "EliteDangerousOdysseyPlugin\EliteDangerousOdysseyPlugin.csproj", "{42B251B3-D8C7-4D7F-9B41-F37A80E3EE2E}" +EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "EuroTruckSimulator2Plugin", "EuroTruckSimulator2Plugin\EuroTruckSimulator2Plugin.csproj", "{D2732427-4BB0-4540-AA74-0DB9987EBE46}" EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "FarmingSimulator19Plugin", "FarmingSimulator19Plugin\FarmingSimulator19Plugin.csproj", "{C1411400-48BD-48DC-85B8-D151DCD061EC}" @@ -197,6 +199,10 @@ Global {92393AB1-1006-4B0B-9E9D-365A03EFB5C7}.Debug|Any CPU.Build.0 = Debug|Any CPU {92393AB1-1006-4B0B-9E9D-365A03EFB5C7}.Release|Any CPU.ActiveCfg = Release|Any CPU {92393AB1-1006-4B0B-9E9D-365A03EFB5C7}.Release|Any CPU.Build.0 = Release|Any CPU + {42B251B3-D8C7-4D7F-9B41-F37A80E3EE2E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {42B251B3-D8C7-4D7F-9B41-F37A80E3EE2E}.Debug|Any CPU.Build.0 = Debug|Any CPU + {42B251B3-D8C7-4D7F-9B41-F37A80E3EE2E}.Release|Any CPU.ActiveCfg = Release|Any CPU + {42B251B3-D8C7-4D7F-9B41-F37A80E3EE2E}.Release|Any CPU.Build.0 = Release|Any CPU {D2732427-4BB0-4540-AA74-0DB9987EBE46}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {D2732427-4BB0-4540-AA74-0DB9987EBE46}.Debug|Any CPU.Build.0 = Debug|Any CPU {D2732427-4BB0-4540-AA74-0DB9987EBE46}.Release|Any CPU.ActiveCfg = Release|Any CPU