diff --git a/src/app/js/controllers.js b/src/app/js/controllers.js index 5a79d3c..fd3699f 100644 --- a/src/app/js/controllers.js +++ b/src/app/js/controllers.js @@ -2,18 +2,18 @@ var app = angular.module('app.controllers', []); app.controller('MainController', ['$scope', '$rootScope', '$mdDialog', function($scope, $rootScope, $mdDialog) { - + var ipc = require('ipc'); - - $scope.hasReplay = false; + + $scope.loading = true; + $scope.msg = "Loading..."; $scope.replay = null; - $scope.leagueClientFound = false; - $scope.leagueClientVersion = ""; - $scope.staticDataReady = false; + $scope.lolClientFound = false; + $scope.lolClientVersion = ""; $scope.aofClientInfo = {}; - + $scope.settings = [ { id: 1, name: "Select LoL Client" }, { id: 2, name: "Client info" } ]; - + $scope.showAofClientInfo = function(ev) { var updateText = ""; if ($scope.aofClientInfo.newVersion) { @@ -31,7 +31,7 @@ app.controller('MainController', ['$scope', '$rootScope', '$mdDialog', .targetEvent(ev) ); }; - + $scope.announceClick = function(index) { if (index == 0) { $scope.selectClient(); @@ -54,32 +54,32 @@ app.controller('MainController', ['$scope', '$rootScope', '$mdDialog', ipc.send("play"); }; - ipc.on("clientInfo", function(obj) { + ipc.on("loading", function(obj) { $scope.$apply(function() { - $scope.leagueClientFound = obj.found; - $scope.leagueClientVersion = obj.version; + $scope.loading = obj.loading + $scope.msg = obj.msg; }); }); - - ipc.on("parsedReplayFile", function(arg) { + + ipc.on("aofUpdate", function(obj) { $scope.$apply(function() { - $scope.replay = arg; - $scope.hasReplay = true; + $scope.aofClientInfo = obj; }); }); - - ipc.on("staticData", function(arg) { + + ipc.on("clientInfo", function(obj) { $scope.$apply(function() { - $scope.staticDataReady = arg; + $scope.lolClientFound = obj.found; + $scope.lolClientVersion = obj.version; }); }); - - ipc.on("update", function(arg) { + + ipc.on("parsedReplayFile", function(obj) { $scope.$apply(function() { - $scope.aofClientInfo = arg; + $scope.replay = obj; }); }); - + ipc.send("ready"); } ]); diff --git a/src/app/tpl/header.html b/src/app/tpl/header.html index d09df4e..3e766e8 100644 --- a/src/app/tpl/header.html +++ b/src/app/tpl/header.html @@ -3,7 +3,7 @@ AnalyzeOrFeed Replay Client Update available! - + settings diff --git a/src/app/tpl/main.html b/src/app/tpl/main.html index 4d5b10c..83a3109 100644 --- a/src/app/tpl/main.html +++ b/src/app/tpl/main.html @@ -1,21 +1,21 @@
-
- - Loading static data from server... - +
- +
+ {{ msg }} +
+ - {{leagueClientFound ? 'check_circle' : 'error'}} + {{ lolClientFound ? 'check_circle' : 'error' }} - {{leagueClientFound ? "LoL Client found: " : "No LoL Client found!"}} {{leagueClientVersion}} + {{ lolClientFound ? "LoL Client found: " : "No LoL Client found!" }} {{ lolClientVersion }} Open file...
-
v{{replay.riotVersion}}
-
Game ID: {{replay.gameId}} ({{replay.region}}) +
v{{ replay.riotVersion }}
+
Game ID: {{ replay.gameId }} ({{ replay.region }}) INCOMPLETE @@ -32,7 +32,7 @@   - {{player.summonerName}} + {{ player.summonerName }}
@@ -43,7 +43,7 @@ - {{player.league.name}} {{player.leagueRank != 0 ? player.leagueRank : ""}} + {{ player.league.name }} {{ player.leagueRank != 0 ? player.leagueRank : "" }} @@ -60,7 +60,7 @@ - {{player.league.name}} {{player.leagueRank != 0 ? player.leagueRank : ""}} + {{ player.league.name }} {{ player.leagueRank != 0 ? player.leagueRank : "" }} @@ -69,12 +69,12 @@
- {{player.summonerName}} + {{ player.summonerName }}
- Play replay + Play replay
diff --git a/src/index.js b/src/index.js index 6446b50..ec6dbf1 100644 --- a/src/index.js +++ b/src/index.js @@ -14,8 +14,8 @@ let lolClient = require(__dirname + "/modules/lol-client.js"); let replay = null; let mainWindow = null; +let settings = {}; let staticData = { - checked: false, extended: false, regions: [ {"Id":5,"Name":"Brazil","ShortName":"BR"}, @@ -32,9 +32,11 @@ let staticData = { ] }; + // Log operating system console.log("We are running on " + process.platform); + // Quit when all windows are closed. app.on("window-all-closed", function() { if (process.platform != "darwin") { @@ -42,53 +44,84 @@ app.on("window-all-closed", function() { } }); -// Get static data from api -fs.readFile(app.getPath("userCache") + "/.static", function(err, data) { - if (!err) { - console.log("Reading static data from local cache"); - staticData = JSON.parse(data); - staticData.extended = true; - } - - console.log("Retrieving static data from server"); - request({ url: "http://api.aof.gg/static", json: true }, function(err, response, body) { - if (!err && response && response.statusCode == 200 && !body.err && body.data) { - staticData = body.data; - staticData.extended = true; - fs.writeFileSync(app.getPath("userCache") + "/.static", JSON.stringify(staticData)); - } else { - console.log("Error while retrieving static data: " + err + " " + JSON.stringify(response)); +// User settings +function loadUserSettings(callback) { + console.log("Loading user settings"); + fs.readFile(app.getPath("userCache") + "/settings", function(err, data) { + if (!err) { + settings = JSON.parse(data); } - staticData.checked = true; - if (mainWindow) - mainWindow.webContents.send("staticData", true); + callback(); }); -}); +} +function saveUserSettings() { + console.log("Saving user settings"); + settings.lolClientPath = lolClient.leaguePath(); + fs.writeFileSync(app.getPath("userCache") + "/settings", JSON.stringify(settings, null, 2)); +} + // Check for updates -console.log("Checking for updates"); -let version = { currVersion: JSON.parse(fs.readFileSync(__dirname + "/package.json")).version, newVersion: null, msg: null }; -request({ url: "http://api.aof.gg/version", json: true }, function(err, response, body) { - if (!err && response && response.statusCode == 200) { - if (version.currVersion != body.version) { - version.newVersion = body.version; - version.msg = body.msg; +function checkForUpdates(callback) { + console.log("Checking for application updates"); + let version = { currVersion: JSON.parse(fs.readFileSync(__dirname + "/package.json")).version, newVersion: null, msg: null }; + let timeout = setTimeout(function() { + req.abort(); + console.log("Could not check for updates, request timed out"); + callback(); + }, 10000); + let req = request({ url: "http://api.aof.gg/version", json: true }, function(err, response, body) { + clearTimeout(timeout); + if (!err && response && response.statusCode == 200) { + // Set the new version info if there is one + if (version.currVersion != body.version) { + version.newVersion = body.version; + version.msg = body.msg; + } + mainWindow.webContents.send("aofUpdate", version); + } else { + console.log("Error while retrieving version: " + err + " " + JSON.stringify(response)); } - if (mainWindow) - mainWindow.webContents.send("update", version); - } else { - console.log("Error while retrieving version: " + err + " " + JSON.stringify(response)); - } -}); + + callback(); + }); +} -// Start our replay server -replayServer.startServer(); -// Try and find the league client -lolClient.find(); +// Get static data from api +function getStaticData(callback) { + console.log("Loading static data"); + fs.readFile(app.getPath("userCache") + "/static", function(err, data) { + if (!err) { + console.log("Reading static data from local cache"); + staticData = JSON.parse(data); + staticData.extended = true; + } + + console.log("Retrieving static data from server"); + let timeout = setTimeout(function() { + req.abort(); + console.log("Could not retreive static data, request timed out"); + callback(); + }, 10000) + let req = request({ url: "http://api.aof.gg/static", json: true }, function(err, response, body) { + if (!err && response && response.statusCode == 200 && !body.err && body.data) { + staticData = body.data; + staticData.extended = true; + fs.writeFileSync(app.getPath("userCache") + "/static", JSON.stringify(staticData)); + } else { + console.log("Error while retrieving static data: " + err + " " + JSON.stringify(response)); + } + + callback(); + }); + }); +} -let extendReplayMetadata = function(meta) { + +// Extend the metadata of a replay with additional information +function extendReplayMetadata(meta) { meta.region = _.find(staticData.regions, function(region) { return region.Id == meta.regionId }).ShortName; if (staticData.extended) { @@ -109,16 +142,39 @@ let extendReplayMetadata = function(meta) { } } return meta; -}; +} -// Listen for renderer messages + +// Called when the renderer is ready to display things ipc.on("ready", function(event, args) { - if (staticData.checked) - event.sender.send("staticData", true); - if (version) - event.sender.send("update", version); - event.sender.send("clientInfo", { found: lolClient.isFound(), version: lolClient.version() }); + + mainWindow.webContents.send("loading", { loading: true, msg: "Loading user settings..." }); + loadUserSettings(function() { + + mainWindow.webContents.send("loading", { loading: true, msg: "Checking for updates..." }); + checkForUpdates(function() { + + mainWindow.webContents.send("loading", { loading: true, msg: "Retreiving static data..." }); + getStaticData(function() { + + mainWindow.webContents.send("loading", { loading: true, msg: "Searching for league client..." }); + lolClient.find(settings.lolClientPath, function(found) { + + mainWindow.webContents.send("loading", { loading: true, msg: "Starting local replay server..." }); + replayServer.startServer(); + + mainWindow.webContents.send("clientInfo", { found: lolClient.isFound(), version: lolClient.version() }); + mainWindow.webContents.send("loading", { loading: false, msg: "" }); + + saveUserSettings(); + }); + }); + }); + }); }); + + +// Called when the user wants to select the league client manually ipc.on("selectClient", function(event, args) { var files = dialog.showOpenDialog({ filters: [{ name: 'League of Legends Client', extensions: ['app', 'exe'] }], @@ -126,10 +182,15 @@ ipc.on("selectClient", function(event, args) { }); if (files && files.length == 1) { - lolClient.extractPath(files[0]); - event.sender.send("clientInfo", { found: lolClient.isFound(), version: lolClient.version() }); + lolClient.extractPath(files[0], function() { + event.sender.send("clientInfo", { found: lolClient.isFound(), version: lolClient.version() }); + saveUserSettings(); + }); } }); + + +// Called when the user wants to open a replay ipc.on("openReplay", function(event, args) { let files = dialog.showOpenDialog({ filters: [{ name: 'Replay File', extensions: ['aof'] }], @@ -148,6 +209,9 @@ ipc.on("openReplay", function(event, args) { }); } }); + + +// Called when the user wants to play a replay ipc.on("play", function(event, args) { replayServer.resetReplay(); @@ -162,6 +226,7 @@ ipc.on("play", function(event, args) { } }); + // Setup windows app.on("ready", function() { mainWindow = new BrowserWindow({ diff --git a/src/modules/lol-client.js b/src/modules/lol-client.js index 7602f31..4ea1a5a 100644 --- a/src/modules/lol-client.js +++ b/src/modules/lol-client.js @@ -3,74 +3,130 @@ let fs = require("fs"); let winreg = require("winreg"); let spawn = require("child_process").spawn; +let _ = require("underscore"); let leaguePath = false; +let fullPath = false; let leagueVersion = ""; +let regexLocations = [{ + hive: winreg.HKCU, + keys: [ + "\\Software\\Riot Games\\RADS", + "\\Software\\Wow6432Node\\Riot Games\\RADS", + "\\Software\\Classes\\VirtualStore\\MACHINE\\SOFTWARE\\Wow6432Node\\RIOT GAMES\\RADS", + "\\Software\\Classes\\VirtualStore\\MACHINE\\SOFTWARE\\RIOT GAMES\\RADS" + ] +},{ + hive: winreg.HKLM, + keys: [ + "\\Software\\Wow6432Node\\Riot Games\\RADS", + "\\Software\\RIOT GAMES\\RADS" + ] +}]; // Try and find the league of legends client -let checkPath = function() { - try { - let logPath = leaguePath + "/../Logs/Game - R3d Logs/"; - - let files = fs.readdirSync(logPath); - files.sort(function(a, b) { - return fs.statSync(logPath + b).mtime.getTime() - fs.statSync(logPath + a).mtime.getTime(); - }); - let content = fs.readFileSync(logPath + files[0], "utf8"); - leagueVersion = content.substring(content.indexOf("Build Version:") + 15, content.indexOf("[PUBLIC]") - 1); - console.log("LoL client version is: " + leagueVersion); - - files = fs.readdirSync(leaguePath + "/solutions/lol_game_client_sln/releases/"); - leaguePath += "/solutions/lol_game_client_sln/releases/" + files[0] + "/deploy/"; - console.log("Complete league path is " + leaguePath); - - return true; - } catch (err) { - console.log("Did not recognize " + leaguePath + "/solutions/lol_game_client_sln/releases/ as a LoL client directory: " + err); +function checkPath(callback) { + let logPath = leaguePath + "/../Logs/Game - R3d Logs/"; + + var errorCallback = function(err) { + console.log("Error checking path " + logPath + ": " + err); leaguePath = false; leagueVersion = ""; - return false; - } -}; - -module.exports = { - isFound: function() { - return leaguePath !== false; - }, - version : function() { - return leagueVersion; - }, - find: function() { - if (process.platform == "win32") { - // Try getting the key from the win32 registry - let regKey = new winreg({ - hive: winreg.HKCU, - key: "\\Software\\Riot Games\\RADS" + callback(false); + }; + + fs.readdir(logPath, function(err, files) { + if (err) { + errorCallback(err); + } else { + files.sort(function(a, b) { + return fs.statSync(logPath + b).mtime.getTime() - fs.statSync(logPath + a).mtime.getTime(); }); - regKey.get("LocalRootFolder", function(err, item) { + + fs.readFile(logPath + files[0], "utf8", function(err, content) { if (err) { - console.log("Couldn't find registry key HKCU\\Software\\Riot Games\\RADS"); + errorCallback(err); + } else { + leagueVersion = content.substring(content.indexOf("Build Version:") + 15, content.indexOf("[PUBLIC]") - 1); + console.log("LoL client version is: " + leagueVersion); - // Try getting the key from the win64 registry - regKey = new winreg({ - hive: winreg.HKCU, - key: "\\Software\\Wow6432Node\\Riot Games\\RADS" - }); - regKey.get("LocalRootFolder", function(err, item) { + fs.readdir(leaguePath + "/solutions/lol_game_client_sln/releases/", function(err, files) { if (err) { - console.log("Couldn't find registry key HKCU\\Software\\Wow6432Node\\Riot Games\\RADS"); + errorCallback(err); } else { - leaguePath = item.value; - console.log("Possible LoL client @ " + leaguePath); - checkPath(); + fullPath = leaguePath + "/solutions/lol_game_client_sln/releases/" + files[0] + "/deploy/"; + console.log("Complete league path is " + fullPath); + + callback(true); } }); - } else { - leaguePath = item.value; - console.log("Possible LoL client @ " + leaguePath); - checkPath(); } }); + } + }); +}; + +// Try and find the specified registry key +function findRegKey(hive, key, callback) { + let regKey = new winreg({ + hive: hive, + key: key + }); + regKey.get("LocalRootFolder", function(err, item) { + if (err) { + console.log("Couldn't find registry key " + hive + key); + callback() + } else { + callback(item.value); + } + }); +}; + +// Try and find the league client +function find(hintPath, callback) { + leaguePath = false; + leagueVersion = ""; + + // Try the hint path if we have one + if (hintPath) { + leaguePath = hintPath; + checkPath(function(found) { + if (!found) + find(false, callback); + else + callback(true); + }); + } else { + if (process.platform == "win32") { + // Try finding the key in all the registry locations + let possiblePaths = []; + let c = 0; + let num = _.reduce(regexLocations, function(memo, item) { return memo + item.keys.length; }, 0); + for (let i = 0; i < regexLocations.length; i++) { + for (let j = 0; j < regexLocations[i].keys.length; j++) { + findRegKey(regexLocations[i].hive, regexLocations[i].keys[j], function(path) { + if (path && !_.contains(possiblePaths, path)) { + possiblePaths.push(path); + } + c++; + + if (c == num) { + if (possiblePaths.length == 0) { + callback(false); + } else { + for (let k = 0; k < possiblePaths.length; k++) { + if (leaguePath) + break; + + console.log("Checking possible LoL client @ " + possiblePaths[k]); + leaguePath = possiblePaths[k]; + checkPath(callback); + } + } + } + }); + } + } } else if (process.platform == "darwin") { fs.access("/Applications/League of Legends.app", function(err) { if (err) { @@ -78,11 +134,24 @@ module.exports = { } else { leaguePath = "/Applications/League of Legends.app/Contents/LoL/RADS"; console.log("Possible LoL client @ " + leaguePath); - checkPath(); + checkPath(callback); } }); - } + } + } +} + +module.exports = { + leaguePath: function() { + return leaguePath; + }, + isFound: function() { + return leaguePath !== false; }, + version : function() { + return leagueVersion; + }, + find: find, launch: function(host, port, replayRegionName, replayGameId, replayKey, callback) { // Ask for LoL client path if we didn't find it if (!leaguePath) { @@ -133,20 +202,25 @@ module.exports = { return true; }, - extractPath: function(file) { + extractPath: function(file, callback) { + file = file.replace(/\\/g, "/"); leaguePath = false; leagueVersion = ""; if (process.platform == "win32") { let i = file.indexOf("RADS/solutions/") + 5; - if (i === 4) - i = file.indexOf("RADS\\solutions\\") + 5; - if (i === 4) - return; - leaguePath = file.substring(0, i); + if (i > 4) { + leaguePath = file.substring(0, i); + } else if ((i = file.indexOf("League of Legends/") + 18) > 17) { + leaguePath = file.substring(0, i) + "RADS"; + } } else if (process.platform == "darwin") { leaguePath = file + "/Contents/LoL/RADS"; } console.log("League path set to " + leaguePath); - checkPath(); + + if (leaguePath) + checkPath(callback); + else + callback(false); }, }; diff --git a/src/package.json b/src/package.json index f646abb..7cc6778 100644 --- a/src/package.json +++ b/src/package.json @@ -1,6 +1,6 @@ { "name": "aof-replay-client", - "version": "0.1.0", + "version": "0.1.1", "main": "./index.js", "scripts": { "start": "./node_modules/.bin/electron ."