This is .NET Standard 2.1 library for reading Age of Empires 2: Definitive Edition hotkeys profiles.
This is mostly an outline, many improvements may be made. API is relatively well documented.
Solution contains following projects:
-
AgeOfSharpKeys - main library.
-
AgeKeys - a sandbox console application.
Here are few main classes you would want to use, listed hierarchically:
-
Hotkeys - manages multiple hotkeys profiles either from your OS user profile files or custom directories.
-
HotkeysProfile - represent a named profile that combines hotkey files which together form a single hotkeys configuration - this is the thing you save/load through the game GUI.
-
HotkeysFile - handles reading of a single hotkey file in known formats (.hkp or .hki)
-
Hotkey - tracks data for single hotkey in specific file.
-
HotkeyData - a struct representing binding for a single action/command. Maintains the native memory layout.
using aoe2.hotkeys;
using static System.Console;
WriteLine("Hello, World!");
var pd = Hotkeys.userProfilesFolder
?? throw new Exception(Hotkeys.userProfilesIssue?.ToString());
var hotkeys = new Hotkeys(); //AoE installation needed, otherwise `new Hotkeys(customFolder)`
WriteLine($@"Loaded {hotkeys.profiles.Count} profiles.");
foreach (var profile in hotkeys)
WriteLine(profile); //pritns profile names
WriteLine($@"Encountered {hotkeys.issues.Count / 2} issues."); //currently we only have summary + exception object hence the /2
foreach (var i in hotkeys.issues)
WriteLine(i); //in case the files were corrupted or something
//this is the name of the profile as you see in game (on my PC :).
WriteLine(@"Printing all hotkeys of ""lapek"" profile:");
foreach (var hotkey in hotkeys["lapek"])
WriteLine(hotkey); //For example: "Go to Stable: Alt + E"
//loads both files as a single profile, printing version from the other one.
var singleProfile = new HotkeysProfile(Path.Combine(pd, "HOTKEYS.hkp"));
WriteLine($@"HOTKEYS.hkp version: {singleProfile.hki.version}");
WriteLine($@"HOTKEYS\Base.hkp version: {singleProfile.hkp.version}");
var singleFile = new HKP(Path.Combine(pd, "HOTKEYS.hkp"));
//This will (correctly) print "HKI" - I'm stating to suspect they did this mess on purpose for some reason :P
WriteLine($"HOTKEYS.hkp format: {singleFile.format}");
ReadLine();
Cloning a profile of a local user:
var p = HotkeysProfile.load("myProfile");
p.save("myClone");
Saving a backup in custom directory (not visible for the game):
var p = HotkeysProfile.load("myProfile");
p.save("myProfile", @"C:\users\user\desktop\backup");
Changing game's default ctrl + 0-9 bindings for creating controls group to alt + 0-9 and saving it in the same profile:
var p = HotkeysProfile.load("myClone");
var sel = p.Where(h => h.name.StartsWith("Create Group #") && !h.alt);
foreach (var h in sel) {
h.ctrl = false;
h.alt = true;
}
p.save();
Important: Currently when editing a profile you need to first close the game, save it, then selected "Local copy" in Steam popup.
Note I didn't tested this on any other PC or hotkeys but I hope it works fine.
-
One thing which bug me currently the most is that I have two file in the profile folder called "myKeys.hki" and "myKeys.hkp", both read as HKI and have exactly the same content. I'm not sure how to understand that.
-
I didn't bother to parse the keys so I used build-in
ConsoleKey
enum forHotkeyData.key
. While most keys are covered, some are not printed nicely for example "Oem3", "D1" instead of just "1" and muse buttons have just plain numbers. -
There are some hotkeys with missing names, though they also don't have any bindings and I took the names from this file so I'm not sure what those hotkeys are.
This project was started thanks to The new HKP hotkey file format explained · GitHub
Also thanks to HotkeyEditor.com repo from where I insolently taken some data and analysed the format.