diff --git a/CallLcds/CallLcds.csproj b/CallLcds/CallLcds.csproj index be2b5ca..16c6554 100644 --- a/CallLcds/CallLcds.csproj +++ b/CallLcds/CallLcds.csproj @@ -66,10 +66,6 @@ - - False - ..\lib\rtmp-sharp.dll - @@ -94,6 +90,10 @@ {4516f4a5-7594-402c-b0d8-2dd6f80ec8ea} FinalesFunkeln + + {aa1a4f5d-3bd4-4832-9f5d-90727007727e} + rtmp-sharp + diff --git a/FinalesFunkeln/FinalesFunkeln.csproj b/FinalesFunkeln/FinalesFunkeln.csproj index 138a4f6..ddd8e1a 100644 --- a/FinalesFunkeln/FinalesFunkeln.csproj +++ b/FinalesFunkeln/FinalesFunkeln.csproj @@ -98,6 +98,9 @@ False ..\lib\Xceed.Wpf.AvalonDock.dll + + ..\packages\YamlDotNet.4.2.2\lib\net35\YamlDotNet.dll + @@ -147,6 +150,7 @@ + diff --git a/FinalesFunkeln/IO/YamlFile.cs b/FinalesFunkeln/IO/YamlFile.cs new file mode 100644 index 0000000..99a01ee --- /dev/null +++ b/FinalesFunkeln/IO/YamlFile.cs @@ -0,0 +1,98 @@ +using System; +using System.Collections; +using System.Collections.Generic; +using System.Dynamic; +using System.IO; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using YamlDotNet.Serialization; + +namespace FinalesFunkeln.IO +{ + public class YamlFile : DynamicObject, IDynamicMetaObjectProvider,IEnumerable> + { + Dictionary _backingDict = new Dictionary(); + string _fileName; + bool _readOnly; + public YamlFile(string fileName, bool autoInit = true, bool readOnly = false) + { + if (string.IsNullOrEmpty(fileName)) + throw new ArgumentNullException("fileName"); + _fileName = fileName; + _readOnly = readOnly; + if (autoInit) + Read(); + } + + public void Read() + { + using (var x = new FileStream(_fileName, FileMode.Open)) + { + var des = new Deserializer(); + var dict = des.Deserialize>(new StreamReader(x)); + foreach(var entry in dict) + { + this[entry.Key] = entry.Value; + } + } + + + } + public void Write() + { + throw new NotImplementedException(); + } + + public bool GetBoolean(string key) + { + return Convert.ToBoolean(this[key]); + } + + public Int32 GetInt32(string key) + { + return Convert.ToInt32(this[key]); + } + + public double GetDouble(string key) + { + return Convert.ToDouble(this[key]); + } + + public string GetString(string key) + { + return (string)this[key]; + } + + public object this[string key] + { + get { return _backingDict[key]; } + set { if (_readOnly) throw new InvalidOperationException("Cannot change a value because it's set to read-only"); else _backingDict[key] = value; } + } + + public override IEnumerable GetDynamicMemberNames() + { + return _backingDict.Keys; + } + public override bool TryGetMember(GetMemberBinder binder, out object result) + { + result= this[binder.Name]; + return true; + } + public override bool TrySetMember(SetMemberBinder binder, object value) + { + _backingDict[binder.Name] = value; + return true; + } + + public IEnumerator> GetEnumerator() + { + return _backingDict.GetEnumerator(); + } + + IEnumerator IEnumerable.GetEnumerator() + { + return _backingDict.GetEnumerator(); + } + } +} diff --git a/FinalesFunkeln/Lol/LolClient.cs b/FinalesFunkeln/Lol/LolClient.cs index 54d833f..70a1bf3 100644 --- a/FinalesFunkeln/Lol/LolClient.cs +++ b/FinalesFunkeln/Lol/LolClient.cs @@ -20,19 +20,19 @@ public class LolClient public LolClientGameData GameData { get; private set; } - public PropertiesFile Properties { get; private set; } + public YamlFile Properties { get; private set; } public LolConnection Connection { get; private set; } public ExtensionManager ExtensionManager { get; } - internal LolClient(string directory, PropertiesFile properties, LolProxy proxy, Process process, ExtensionManager extManager) + internal LolClient(string directory, YamlFile properties, LolProxy proxy, Process process, ExtensionManager extManager) { if (proxy == null) throw new ArgumentNullException("proxy"); if(!Directory.Exists(directory)) throw new ArgumentException("directory"); - GameData = new LolClientGameData(Path.Combine(directory, GameDataFile)); - Images = new LolClientImages(directory, GameData); + //GameData = new LolClientGameData(Path.Combine(directory, GameDataFile)); + //Images = new LolClientImages(directory, GameData); Connection=new LolConnection(proxy, extManager); Process = process; Properties = properties; diff --git a/FinalesFunkeln/MainWindow.xaml.cs b/FinalesFunkeln/MainWindow.xaml.cs index 75a3c95..92dc4e8 100644 --- a/FinalesFunkeln/MainWindow.xaml.cs +++ b/FinalesFunkeln/MainWindow.xaml.cs @@ -40,7 +40,9 @@ partial class MainWindow const string InternalConfigDir = "config/internal/"; const string LayoutConfigFilename = "Layout.cbf"; const string DefaultLayoutDefinition = "FinalesFunkeln.Resources.Config.Layout.cbf"; - const string LolPropertiesFilename = "lol.properties"; + const string LolPropertiesFilename = "system.yaml"; + const string LcuSettingsFilename = "LeagueClientSettings.yaml"; + const string LcuSettingsPath = "../../../../../../Config/"; const string CertFileName = "data/certs/{0}.p12"; const int RtmpPort = 2099; @@ -51,7 +53,8 @@ partial class MainWindow string _rtmpAddress; X509Certificate2 _certificate; ExtensionManager _extensionManager; - PropertiesFile _lolProperties; + YamlFile _lolProperties; + YamlFile _lcuSettings; Process _lolClientProcess; LolClient _lolClient; @@ -69,12 +72,13 @@ private void Window_Initialized(object sender, EventArgs e) { CultureInfo.DefaultThreadCurrentCulture = new CultureInfo("en-US"); CultureInfo.DefaultThreadCurrentUICulture = new CultureInfo("en-US"); - if (!Directory.Exists("data") || !File.Exists("sqlite3.dll")) + + if (!Directory.Exists("data")) { MessageBox.Show(Debugger.IsAttached ? @"""data"" folder and/or sqlite3.dll not found. Make sure to copy the data folder and sqlite3.dll to the output directory." : "Some files are missing, please reinstall.", "Error", MessageBoxButton.OK, MessageBoxImage.Error); Environment.Exit(-1); } - + if (!Debugger.IsAttached) AppDomain.CurrentDomain.UnhandledException += CurrentDomain_UnhandledException; _uiManager = new UiManager(); @@ -212,28 +216,12 @@ void ProcessInjector_ProcessFound(object sender, Process e) { ProcessInjector pi = sender as ProcessInjector; if (pi == null) return; - -#if !LCU //The new lol client has a separate process for the UI - //sometimes it takes a while for the main module to be loaded... - while (e.MainWindowHandle == IntPtr.Zero) -#endif + Thread.Sleep(1000); string loldir = null; try { -#if AIRDEBUG && DEBUG - string wmiQuery = string.Format("select CommandLine from Win32_Process where Name='{0}'", "adl.exe"); - ManagementObjectSearcher searcher = new ManagementObjectSearcher(wmiQuery); - ManagementObjectCollection retObjectCollection = searcher.Get(); - foreach (ManagementObject retObject in retObjectCollection) - loldir = ProcessHelper.SplitCommandLineArgs((string)retObject["CommandLine"])[2]; -#elif LCU - loldir = Path.GetDirectoryName(e.MainModule.FileName) ?? string.Empty; - loldir = Path.Combine(loldir, @"../../../../lol_air_client/releases/0.0.4.147/deploy"); - //TODO this directory is just a placeholder -#else loldir = Path.GetDirectoryName(e.MainModule.FileName) ?? string.Empty; -#endif } catch (Win32Exception) { @@ -241,9 +229,11 @@ void ProcessInjector_ProcessFound(object sender, Process e) return; } - _lolProperties = new PropertiesFile(Path.Combine(loldir, LolPropertiesFilename)); - var host = _lolProperties["host"]; - _rtmpAddress = host.Contains(",") ? host.Substring(0, host.IndexOf(',')) : host; + + _lolProperties = new YamlFile(Path.Combine(loldir, LolPropertiesFilename)); + _lcuSettings = new YamlFile(Path.Combine(loldir, LcuSettingsPath, LcuSettingsFilename)); + //string host = ((dynamic)_lolProperties)["region_data"][((dynamic)_lcuSettings)["install"]["globals"]["region"]]["servers"]["lcds"]["lcds_host"]; + _rtmpAddress = ((dynamic)_lolProperties)["region_data"][((dynamic)_lcuSettings)["install"]["globals"]["region"]]["servers"]["lcds"]["lcds_host"]; if (_rtmpAddress == null) return; @@ -296,7 +286,10 @@ void InitProxy() #if !LCU _proxy = new LolProxy(new IPEndPoint(IPAddress.Loopback, RtmpPort), new Uri(string.Format("rtmps://{0}:{1}", _rtmpAddress, RtmpPort)), _serializationContext, _certificate); #else - _proxy = new LolProxy(new IPEndPoint(IPAddress.Loopback, RtmpPort), new Uri(string.Format("rtmps://{0}:{1}", _rtmpAddress, RtmpPort)), _serializationContext,_certificate); + //CEF does not allow self-signed certs so we have to disable TLS for the new client + //(locally only, TLS will still be used to communicate with the actual server) + //TLS can be disabled for the client in /system.yaml + _proxy = new LolProxy(new IPEndPoint(IPAddress.Loopback, RtmpPort), new Uri(string.Format("rtmps://{0}:{1}", _rtmpAddress, RtmpPort)), _serializationContext); #endif _proxy.AcknowledgeMessageReceived += OnAckMessageReceived; @@ -394,7 +387,7 @@ void pi_Injected(object sender, EventArgs e) { Dispatcher.Invoke(DispatcherPriority.Input, new ThreadStart(() => { - Title = "Finales Funkeln - Injected [" + _lolProperties["platformId"] + "]"; + Title = "Finales Funkeln - Injected [" + ((dynamic)_lcuSettings)["install"]["globals"]["region"] + "]"; })); } diff --git a/FinalesFunkeln/RiotObjects/BroadcastNotification.cs b/FinalesFunkeln/RiotObjects/BroadcastNotification.cs index d2021b5..7a8f998 100644 --- a/FinalesFunkeln/RiotObjects/BroadcastNotification.cs +++ b/FinalesFunkeln/RiotObjects/BroadcastNotification.cs @@ -8,7 +8,7 @@ namespace FinalesFunkeln.RiotObjects { [Serializable] - [SerializedName("com.riotgames.platform.broadcast.BroadcastNotification")] + //[SerializedName("com.riotgames.platform.broadcast.BroadcastNotification")] public class BroadcastNotification : ExternalizableJsonObject { public BroadcastNotification():base("com.riotgames.platform.broadcast.BroadcastNotification") { } diff --git a/FinalesFunkeln/RiotObjects/ClientSystemStatesNotification.cs b/FinalesFunkeln/RiotObjects/ClientSystemStatesNotification.cs index b416a73..32ae6e0 100644 --- a/FinalesFunkeln/RiotObjects/ClientSystemStatesNotification.cs +++ b/FinalesFunkeln/RiotObjects/ClientSystemStatesNotification.cs @@ -8,7 +8,7 @@ namespace FinalesFunkeln.RiotObjects { [Serializable] - [SerializedName("com.riotgames.platform.systemstate.ClientSystemStatesNotification")] + //[SerializedName("com.riotgames.platform.systemstate.ClientSystemStatesNotification")] public class ClientSystemStatesNotification : ExternalizableJsonObject { public ClientSystemStatesNotification():base("com.riotgames.platform.systemstate.ClientSystemStatesNotification") { } diff --git a/FinalesFunkeln/Util/ProcessInjector.cs b/FinalesFunkeln/Util/ProcessInjector.cs index 079aaf3..b79bec9 100644 --- a/FinalesFunkeln/Util/ProcessInjector.cs +++ b/FinalesFunkeln/Util/ProcessInjector.cs @@ -13,9 +13,14 @@ namespace FinalesFunkeln.Util { class ProcessInjector:IDisposable { - readonly byte[] _connectCc = - { - 0x55, //PUSH EBP +#if LCU + const string CONNECT_FUNCTION = "WSAConnect"; +#else + const string CONNECT_FUNCTION = "connect"; +#endif + readonly byte[] _connectCc = + { + 0x55, //PUSH EBP 0x8B, 0xEC, //MOV EBP, ESP 0x60, //PUSHAD 0x8B, 0x45, 0x0C, //MOV EAX, [EBP+C] @@ -117,7 +122,7 @@ internal void Inject() int jmpaddrloc = connect.Length - 4; var mod = ProcessMemory.GetModule("ws2_32.dll"); - Int32 reladdr = notemem.GetAddress(mod, "connect"); + Int32 reladdr = notemem.GetAddress(mod, CONNECT_FUNCTION); reladdr -= mod; var lolmod = GetModuleAddress(CurrentProcess, mem, "ws2_32.dll"); diff --git a/FinalesFunkeln/packages.config b/FinalesFunkeln/packages.config index d92eb9d..7bd012e 100644 --- a/FinalesFunkeln/packages.config +++ b/FinalesFunkeln/packages.config @@ -2,4 +2,5 @@ + \ No newline at end of file diff --git a/lib/rtmp-sharp b/lib/rtmp-sharp index 43b8eb1..3720769 160000 --- a/lib/rtmp-sharp +++ b/lib/rtmp-sharp @@ -1 +1 @@ -Subproject commit 43b8eb1dd1073e2d1ce7a7b39aeeef9d3657ef15 +Subproject commit 3720769e1162e91b8865c7cff61cdc1bc87345bf diff --git a/lib/rtmpsharpgit/rtmp-sharp b/lib/rtmpsharpgit/rtmp-sharp new file mode 160000 index 0000000..43b8eb1 --- /dev/null +++ b/lib/rtmpsharpgit/rtmp-sharp @@ -0,0 +1 @@ +Subproject commit 43b8eb1dd1073e2d1ce7a7b39aeeef9d3657ef15