Skip to content

Commit

Permalink
Program does not have to be run anymore having first loaded the game.
Browse files Browse the repository at this point in the history
  • Loading branch information
nicolasdeory committed Mar 28, 2020
1 parent 5f81587 commit 1528352
Show file tree
Hide file tree
Showing 12 changed files with 293 additions and 33 deletions.
8 changes: 8 additions & 0 deletions LedDashboard/ChromaAppInfo.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
<?xml version="1.0" encoding="utf-8"?>
<application>
<title>League of Legends Chroma Integration</title>
<description>A smart game integration for League of Legends that reacts to game events.</description>
<author name="Nicolas de Ory" contact="https://github.com/nicolasdeory/leagueoflegends-led"/>
<device_supported keyboard="1" mouse="0" headset="0" mousepad="0" keypad="0" chromalink="0"/>
<category game="1"/>
</application>
9 changes: 9 additions & 0 deletions LedDashboard/LedDashboard.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,8 @@
<Compile Include="Modules\LeagueOfLegends\Model\SpellInformation.cs" />
<Compile Include="Modules\LeagueOfLegends\Model\SummonerSpellLoadout.cs" />
<Compile Include="Modules\LeagueOfLegends\WebRequestUtil.cs" />
<Compile Include="MouseUtils.cs" />
<Compile Include="ProcessListenerService.cs" />
<Compile Include="RazerChromaController.cs" />
<Compile Include="SACNController.cs" />
<Compile Include="Utils.cs" />
Expand Down Expand Up @@ -161,6 +163,12 @@
<Reference Include="ScottPlot.WinForms, Version=4.0.1.0, Culture=neutral, processorArchitecture=MSIL">
<HintPath>..\packages\ScottPlot.WinForms.4.0.1\lib\net461\ScottPlot.WinForms.dll</HintPath>
</Reference>
<Reference Include="SharpDX, Version=4.2.0.0, Culture=neutral, PublicKeyToken=b4dcf0f35e5521f1, processorArchitecture=MSIL">
<HintPath>..\packages\SharpDX.4.2.0\lib\net45\SharpDX.dll</HintPath>
</Reference>
<Reference Include="SharpDX.RawInput, Version=4.2.0.0, Culture=neutral, PublicKeyToken=b4dcf0f35e5521f1, processorArchitecture=MSIL">
<HintPath>..\packages\SharpDX.RawInput.4.2.0\lib\net45\SharpDX.RawInput.dll</HintPath>
</Reference>
<Reference Include="System" />
<Reference Include="System.AppContext, Version=4.1.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
<HintPath>..\packages\System.AppContext.4.1.0\lib\net463\System.AppContext.dll</HintPath>
Expand Down Expand Up @@ -310,6 +318,7 @@
<Content Include="Animations\Vel%27Koz\w_close.txt">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</Content>
<Content Include="ChromaAppInfo.xml" />
</ItemGroup>
<ItemGroup>
<Folder Include="Modules\KeyboardListener\" />
Expand Down
22 changes: 19 additions & 3 deletions LedDashboard/LedManager.cs
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ class LedManager
/// Array that contains LED color data for the LED strip.
/// </summary>
private Led[] leds;
private int ledCount;

public delegate void UpdateDisplayHandler(Led[] leds);

Expand All @@ -21,14 +22,15 @@ class LedManager
public event UpdateDisplayHandler UpdateDisplay;

bool reverseOrder;

LightController lightController;

LEDModule currentLEDModule;

/// <param name="ledCount">Number of lights in the LED strip</param>
/// <param name="reverseOrder">Set to true if you want the lights to be reverse in order (i.e. Color for LED 0 will be applied to the last LED in the strip)</param>
public LedManager(int ledCount, bool reverseOrder)
{
this.ledCount = ledCount;
lightController = RazerChromaController.Create();

this.leds = new Led[ledCount];
Expand All @@ -38,14 +40,28 @@ public LedManager(int ledCount, bool reverseOrder)
}
this.reverseOrder = reverseOrder;

LEDModule lolModule = LeagueOfLegendsModule.Create(ledCount);
lolModule.NewFrameReady += UpdateLEDDisplay;
/*LEDModule lolModule = LeagueOfLegendsModule.Create(ledCount);
lolModule.NewFrameReady += UpdateLEDDisplay;*/
/*LEDModule blinkModule = BlinkWhiteModule.Create(leds.Length);
blinkModule.NewFrameReady += UpdateLEDDisplay;*/
KeyboardHookService.Init();
ProcessListenerService.Init();
ProcessListenerService.Register("League of Legends", OnProcessOpened); // Listen when league of legends is opened

UpdateLEDDisplay(this, this.leds);

}

private void OnProcessOpened(string name)
{
if (name == "League of Legends" && !(currentLEDModule is LeagueOfLegendsModule))
{
LEDModule lolModule = LeagueOfLegendsModule.Create(ledCount);
lolModule.NewFrameReady += UpdateLEDDisplay;
currentLEDModule = lolModule;
}
}

/// <summary>
/// Updates the LED display
/// </summary>
Expand Down
21 changes: 17 additions & 4 deletions LedDashboard/Modules/Common/KeyboardHookService.cs
Original file line number Diff line number Diff line change
@@ -1,31 +1,43 @@
using Gma.System.MouseKeyHook;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Runtime.InteropServices;
using System.Text;
using System.Windows.Forms;

namespace LedDashboard.Modules.Common
namespace LedDashboard
{
public class KeyboardHookService
{

private static KeyboardHookService _instance;
public static KeyboardHookService Instance
{
get
{
if (_instance == null) _instance = new KeyboardHookService();
if (_instance == null) _instance = new KeyboardHookService();
return _instance;
}
}

private IKeyboardMouseEvents m_GlobalHook;

/// <summary>
/// Raised when the mouse is clicked.
/// </summary>
public event MouseEventHandler OnMouseClicked; // TODO: Check window in focus. i.e for league of legends make sure it's when the client window is in focus.

/// <summary>
/// Raised when a key is pressed
/// </summary>
public event KeyPressEventHandler OnKeyPressed;

public static void Init()
{
_instance = new KeyboardHookService();
}

private KeyboardHookService()
{
m_GlobalHook = Hook.GlobalEvents();
Expand All @@ -43,5 +55,6 @@ private void OnKeyPress(object sender, KeyPressEventArgs e)
{
OnKeyPressed?.Invoke(sender, e);
}

}
}
}
23 changes: 19 additions & 4 deletions LedDashboard/Modules/LeagueOfLegends/ChampionModule.cs
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,12 @@ public abstract class ChampionModule : LEDModule
/// </summary>
protected event PlayerInfoUpdatedHandle PlayerInfoUpdated;

protected delegate void ChampionInfoLoadedHandler(ChampionAttributes attributes);
/// <summary>
/// Raised when the player info was updated.
/// </summary>
protected event ChampionInfoLoadedHandler ChampionInfoLoaded;

public delegate void OutOfManaHandler();
/// <summary>
/// Raised when the user tried to cast an ability but was out of mana.
Expand All @@ -50,20 +56,29 @@ protected ChampionModule(string champName, ActivePlayer playerInfo)
{
Name = champName;
PlayerInfo = playerInfo;
ChampionInfo = GetChampionInformation(champName);
LoadChampionInformation(champName);
}

private void LoadChampionInformation(string champName)
{
Task.Run(async () =>
{
ChampionInfo = await GetChampionInformation(champName);
ChampionInfoLoaded?.Invoke(ChampionInfo);
});
}

/// <summary>
/// Retrieves the attributes for a given champ (ability cooldowns, mana costs, etc.)
/// </summary>
/// <param name="championName">Internal champion name (i.e. Vel'Koz -> Velkoz)</param>
/// <returns></returns>
private ChampionAttributes GetChampionInformation(string championName)
private async Task<ChampionAttributes> GetChampionInformation(string championName)
{
string latestVersion;
try
{
string versionJSON = WebRequestUtil.GetResponse(VERSION_ENDPOINT);
string versionJSON = await WebRequestUtil.GetResponse(VERSION_ENDPOINT);
List<string> versions = JsonConvert.DeserializeObject<List<string>>(versionJSON);
latestVersion = versions[0];
}
Expand All @@ -75,7 +90,7 @@ private ChampionAttributes GetChampionInformation(string championName)
string championJSON;
try
{
championJSON = WebRequestUtil.GetResponse(String.Format(CHAMPION_INFO_ENDPOINT, latestVersion, championName));
championJSON = await WebRequestUtil.GetResponse(String.Format(CHAMPION_INFO_ENDPOINT, latestVersion, championName));

}
catch (WebException e)
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
using LedDashboard.Modules.BasicAnimation;
using LedDashboard.Modules.Common;
using LedDashboard.Modules.LeagueOfLegends.Model;
using SharpDX.RawInput;
using System.Threading.Tasks;
using System.Windows.Forms;

Expand Down Expand Up @@ -41,7 +42,12 @@ private VelKozModule(int ledCount, ActivePlayer playerInfo, string championName)
animator.PreloadAnimation(@"Animations/Vel'Koz/w_cast.txt");
animator.PreloadAnimation(@"Animations/Vel'Koz/w_close.txt");

animator.NewFrameReady += (_,ls) => DispatchNewFrame(ls);
ChampionInfoLoaded += OnChampionInfoLoaded;
}

private void OnChampionInfoLoaded(ChampionAttributes champInfo)
{
animator.NewFrameReady += (_, ls) => DispatchNewFrame(ls);

KeyboardHookService.Instance.OnMouseClicked += OnMouseClick;
KeyboardHookService.Instance.OnKeyPressed += OnKeyPress;
Expand All @@ -50,7 +56,7 @@ private VelKozModule(int ledCount, ActivePlayer playerInfo, string championName)
/// <summary>
/// Called when the mouse is clicked.
/// </summary>
private void OnMouseClick(object sender, MouseEventArgs m)
private void OnMouseClick(object s, MouseEventArgs m)
{
// TODO: Quick cast support

Expand Down Expand Up @@ -126,7 +132,7 @@ private void OnMouseClick(object sender, MouseEventArgs m)
/// <summary>
/// Called when a key is pressed;
/// </summary>
private void OnKeyPress(object sender, KeyPressEventArgs e)
private void OnKeyPress(object s, KeyPressEventArgs e)
{
if (e.KeyChar == 'q')
{
Expand Down
74 changes: 58 additions & 16 deletions LedDashboard/Modules/LeagueOfLegends/LeagueOfLegendsModule.cs
Original file line number Diff line number Diff line change
Expand Up @@ -60,22 +60,60 @@ public static LeagueOfLegendsModule Create(int ledCount)

private LeagueOfLegendsModule(int ledCount)
{

// League of Legends integration Initialization
Process[] pname = Process.GetProcessesByName("League of Legends");
if (pname.Length == 0) throw new InvalidOperationException("Game client is not open.");

// Queries the game information
QueryPlayerInfo(true);
// League of Legends integration Initialization
/*Process[] pname = Process.GetProcessesByName("League of Legends");
if (pname.Length == 0) throw new InvalidOperationException("Game client is not open.");*/

// LED Initialization
//reverseOrder = reverse;
this.leds = new Led[ledCount];
for (int i = 0; i < ledCount; i++)
leds[i] = new Led();

WaitForGameInitialization();


}

private void WaitForGameInitialization()
{
Task.Run(async () =>
{
while (true)
{
try
{
if (await WebRequestUtil.IsLive("https://127.0.0.1:2999/liveclientdata/allgamedata"))
{
break;
} else
{
await Task.Delay(1000);
continue;
}
}
catch (WebException e)
{
// TODO: Account for League client disconnects, game ended, etc. without crashing the whole program
//throw new InvalidOperationException("Couldn't connect with the game client", e);
await Task.Delay(1000);
continue;
}

}
await InitializeModule();
});

}

private async Task InitializeModule()
{
// Queries the game information
await QueryPlayerInfo(true);


// Load animation module
animationModule = AnimationModule.Create(ledCount);
animationModule = AnimationModule.Create(this.leds.Length);
animationModule.NewFrameReady += OnNewFrameReceived;

// Load champion module. Different modules will be loaded depending on the champion.
Expand All @@ -84,37 +122,37 @@ private LeagueOfLegendsModule(int ledCount)
// TODO: Make this easily extendable when there are many champion modules
if (playerChampion.RawChampionName.ToLower().Contains("velkoz"))
{
championModule = VelKozModule.Create(ledCount, activePlayer);
championModule = VelKozModule.Create(this.leds.Length, activePlayer);
championModule.NewFrameReady += OnNewFrameReceived;
championModule.TriedToCastOutOfMana += OnAbilityCastNoMana;
}
CurrentLEDSource = championModule;

// Sets up a task to always check for updated player info
Task.Run(async () =>
_ = Task.Run(async () =>
{
while (true)
{
QueryPlayerInfo();
await QueryPlayerInfo();
await Task.Delay(150);
}
});

// start frame timer
Task.Run(FrameTimer);
_ = Task.Run(FrameTimer);

}

/// <summary>
/// Queries updated game data from the LoL live client API.
/// </summary>
private void QueryPlayerInfo(bool firstTime = false)
private async Task QueryPlayerInfo(bool firstTime = false)
{

string json;
try
{
json = WebRequestUtil.GetResponse("https://127.0.0.1:2999/liveclientdata/allgamedata");
json = await WebRequestUtil.GetResponse("https://127.0.0.1:2999/liveclientdata/allgamedata");
}
catch (WebException e)
{
Expand Down Expand Up @@ -173,7 +211,11 @@ private void ProcessGameEvents(bool firstTime = false)
{
if (firstTime)
{
currentGameTimestamp = gameEvents[gameEvents.Count - 1].EventTime;
if (gameEvents.Count > 0)
currentGameTimestamp = gameEvents[gameEvents.Count - 1].EventTime;
else
currentGameTimestamp = 0;

return;
}
foreach(Event ev in gameEvents)
Expand Down
Loading

0 comments on commit 1528352

Please sign in to comment.