From fa0c77e265ffe9180ba2b8d5c477e38d062c9a6b Mon Sep 17 00:00:00 2001 From: Gregg Tavares Date: Tue, 28 Oct 2014 20:31:52 -0700 Subject: [PATCH] make HFT controllers use HFTSystem to find next game to switch too. This makes it much more responsive make HFT controllers not able to connect if a game is not running. This will prevent people getting stuck on a controller which I've seen. They'd be in a game, we'd switch games, they'd for some reason refresh or whatever and the old controller would start and be waiting for the game. Now the controller will switch go back to "/" which will then redirect it to whatever is running make index.html use HFTSystem to list the games. This makes it much more responsive. --- public/hft/0.x.x/scripts/commonui.js | 65 ++++++++++------------------ public/scripts/showgames.js | 64 +++++++++++++-------------- server/hftgame.js | 56 +++++++++++++++++------- server/relayserver.js | 2 +- todo.md | 13 ++++-- 5 files changed, 103 insertions(+), 97 deletions(-) diff --git a/public/hft/0.x.x/scripts/commonui.js b/public/hft/0.x.x/scripts/commonui.js index 9bf0869c..6346db87 100644 --- a/public/hft/0.x.x/scripts/commonui.js +++ b/public/hft/0.x.x/scripts/commonui.js @@ -38,11 +38,13 @@ define([ './io', './hft-splash', + './hft-system', './misc/misc', './misc/playername', ], function( IO, HFTSplash, + HFTSystem, Misc, PlayerNameHandler) { @@ -125,49 +127,30 @@ define([ options.disconnectFn(); } - // - var checkForGame = function() { - IO.sendJSON(window.location.href, {cmd: 'listRunningGames'}, function (exception, obj) { - if (exception) { - // the server is down. Try again?. I'm not sure what to do here. Currently the display - // will say "restart"/"main menu" but neither have a point if the server is down. - // Maybe there should be no options? - setTimeout(checkForGame, 1000); + var hftSystem = new HFTSystem(); + hftSystem.on('runningGames', function(obj) { + // Is the game running + for (var ii = 0; ii < obj.length; ++ii) { + var game = obj[ii]; + if (game.gameId == client.getGameId()) { + // Yes! Reload + window.location.reload(); return; } - - // Is the game running - for (var ii = 0; ii < obj.length; ++ii) { - var game = obj[ii]; - if (game.gameId == client.getGameId()) { - // Yes! Reload - window.location.reload(); - return; - } - } - - // Are any games running? If 1 game, go to it. - if (obj.length == 1 && obj[0].controllerUrl) { - window.location.href = obj[0].controllerUrl; - return; - } - // If 2+ games, go to the menu. - if (obj.length > 1) { - // Go to main menu - window.location.href = "/"; - return; - } - - // Note: If we knew the path each game and there was only 1 game running - // we could jump directly to that game. Right now gameIds don't correspond - // to their URL. - - setTimeout(checkForGame, 1000); - }); - }; - - // Give the game a moment to restart and connect to happyFunTimes - setTimeout(checkForGame, 1000); + } + + // Are any games running? If 1 game, go to it. + if (obj.length == 1 && obj[0].controllerUrl) { + window.location.href = obj[0].controllerUrl; + return; + } + // If 2+ games, go to the menu. + if (obj.length > 1) { + // Go to main menu + window.location.href = "/"; + return; + } + }); }); client.addEventListener('_hft_redirect_', function(data) { diff --git a/public/scripts/showgames.js b/public/scripts/showgames.js index 7f9a1b4f..124b11ec 100644 --- a/public/scripts/showgames.js +++ b/public/scripts/showgames.js @@ -31,12 +31,11 @@ "use strict"; -// Start the main app logic. requirejs( - [ 'hft/io', + [ 'hft/hft-system', 'hft/misc/strings', ], function( - IO, + HFTSystem, Strings) { var $ = function(id) { @@ -48,41 +47,36 @@ requirejs( var template = $("item-template").text; var oldHtml = ""; - var getGames = function() { - IO.sendJSON(window.location.href, {cmd: 'listRunningGames'}, function (exception, obj) { - if (exception) { - setTimeout(getGames, 1000); - return; - } + var hftSystem = new HFTSystem(); + hftSystem.on('runningGames', function(obj) { +console.log(obj); + // If there's only one game just go to it. + if (obj.length == 1 && obj[0].controllerUrl) { + window.location.href = obj[0].controllerUrl; + return; + } - var items = []; - for (var ii = 0; ii < obj.length; ++ii) { - var game = obj[ii]; + var items = []; + for (var ii = 0; ii < obj.length; ++ii) { + var game = obj[ii]; + var runtimeInfo = game.runtimeInfo; + var hftInfo = runtimeInfo.info.happyFunTimes; + // Not sure how I should figure out the name and screenshot. + var basePath = game.controllerUrl.substring(0, game.controllerUrl.lastIndexOf('/') + 1); + var dev = (runtimeInfo.originalGameId != hftInfo.gameId) ? "(*)" : ""; + game.name = dev + (hftInfo.name || runtimeInfo.originalGameId); + game.screenshotUrl = game.screenshotUrl; + items.push(Strings.replaceParams(template, game)); + } + var html = items.join(""); + if (html != oldHtml) { + oldHtml = html; + gamemenu.innerHTML = html; + } - // Not sure how I should figure out the name and screenshot. - var basePath = game.controllerUrl.substring(0, game.controllerUrl.lastIndexOf('/') + 1); - game.name = game.name || game.gameId; - game.screenshotUrl = game.screenshotUrl || (basePath + game.gameId + "-screenshot.png"); - items.push(Strings.replaceParams(template, game)); - } - var html = items.join(""); - if (html != oldHtml) { - oldHtml = html; - gamemenu.innerHTML = html; - } + nogames.style.display = items.length ? "none" : "block"; - nogames.style.display = items.length ? "none" : "block"; - - // If there's only one game just go to it. - if (obj.length == 1 && obj[0].controllerUrl) { - window.location.href = obj[0].controllerUrl; - return; - } - - setTimeout(getGames, 5000); - }); - }; - getGames(); + }); }); diff --git a/server/hftgame.js b/server/hftgame.js index 61087e4e..ae20a7f8 100644 --- a/server/hftgame.js +++ b/server/hftgame.js @@ -62,19 +62,20 @@ var HFTPlayer = function(netPlayer, game, gameDB, relayServer) { this.game = game; this.gameDB = gameDB; this.relayServer = relayServer; - this.getAvailableGamesSubscribed = false; + this.subscribedGetAvailableGames = false; + this.subscribedGetRunningGames = false; // Remember these must be safe. - netPlayer.addEventListener('disconnect', HFTPlayer.prototype.disconnect.bind(this)); - netPlayer.addEventListener('getGameInfo', HFTPlayer.prototype.handleGetGameInfo.bind(this)); - netPlayer.addEventListener('getAvailableGames', HFTPlayer.prototype.handleGetAvailableGames.bind(this)); - netPlayer.addEventListener('getRunningGames', HFTPlayer.prototype.handleGetRunningGames.bind(this)); - netPlayer.addEventListener('install', HFTPlayer.prototype.handleInstall.bind(this)); - netPlayer.addEventListener('upgrade', HFTPlayer.prototype.handleUpgrade.bind(this)); - netPlayer.addEventListener('launch', HFTPlayer.prototype.handleLaunch.bind(this)); - netPlayer.addEventListener('quit', HFTPlayer.prototype.handleQuit.bind(this)); - netPlayer.addEventListener('quitGame', HFTPlayer.prototype.handleQuitGame.bind(this)); - netPlayer.addEventListener('disconnectGame', HFTPlayer.prototype.handleDisconnectGame.bind(this)); + netPlayer.addEventListener('disconnect', HFTPlayer.prototype.disconnect.bind(this)); + netPlayer.addEventListener('getGameInfo', HFTPlayer.prototype.handleGetGameInfo.bind(this)); + netPlayer.addEventListener('getAvailableGames', HFTPlayer.prototype.handleGetAvailableGames.bind(this)); + netPlayer.addEventListener('getRunningGames', HFTPlayer.prototype.handleGetRunningGames.bind(this)); + netPlayer.addEventListener('install', HFTPlayer.prototype.handleInstall.bind(this)); + netPlayer.addEventListener('upgrade', HFTPlayer.prototype.handleUpgrade.bind(this)); + netPlayer.addEventListener('launch', HFTPlayer.prototype.handleLaunch.bind(this)); + netPlayer.addEventListener('quit', HFTPlayer.prototype.handleQuit.bind(this)); + netPlayer.addEventListener('quitGame', HFTPlayer.prototype.handleQuitGame.bind(this)); + netPlayer.addEventListener('disconnectGame', HFTPlayer.prototype.handleDisconnectGame.bind(this)); this.handleGameExited = HFTPlayer.prototype.handleGameExited.bind(this) relayServer.on('gameExited', this.handleGameExited); @@ -93,8 +94,8 @@ var HFTPlayer = function(netPlayer, game, gameDB, relayServer) { }; HFTPlayer.prototype.disconnect = function() { - if (this.getAvailableGamesSubscribed) { - this.gameDB.removeListener('changed', this.getAvailableGamesSubscribed); + if (this.subscribedGetAvailableGames) { + this.gameDB.removeListener('changed', this.subscribedGetAvailableGames); this.gameAvailableGamesSubscribed = undefined; } this.relayServer.removeListener('gameExited', this.handleGameExited); @@ -142,9 +143,9 @@ HFTPlayer.prototype.handleGetGameInfo = function(data) { }; HFTPlayer.prototype.handleGetAvailableGames = function(data) { - if (!this.getAvailableGamesSubscribed) { - this.getAvailableGamesSubscribed = HFTPlayer.prototype.handleGetAvailableGames.bind(this); - this.gameDB.on('changed', this.getAvailableGamesSubscribed); + if (!this.subscribedGetAvailableGames) { + this.subscribedGetAvailableGames = HFTPlayer.prototype.handleGetAvailableGames.bind(this); + this.gameDB.on('changed', this.subscribedGetAvailableGames); } debug("sending available games"); @@ -152,10 +153,21 @@ HFTPlayer.prototype.handleGetAvailableGames = function(data) { }; HFTPlayer.prototype.handleGetRunningGames = function(data) { + this.subscribedGetRunningGames = true; + this.sendRunningGames(); +}; + +HFTPlayer.prototype.sendRunningGames = function() { debug("sending running games"); this.sendCmd("runningGames", this.relayServer.getGames()); }; +HFTPlayer.prototype.sendRunningGamesIfSubscribed = function() { + if (this.subscribedGetRunningGames) { + this.sendRunningGames(); + } +}; + HFTPlayer.prototype.download = function(gameId, upgrade) { var emitter = download(gameId, undefined, { //verbose: true, @@ -303,6 +315,18 @@ var HFTGame = function(options) { players.push(new HFTPlayer(netPlayer, this, gameDB, relayServer)); }.bind(this)); + relayServer.on('gameStarted', function() { + players.forEach(function(player) { + player.sendRunningGamesIfSubscribed(); + }); + }); + + relayServer.on('gameExited', function() { + players.forEach(function(player) { + player.sendRunningGamesIfSubscribed(); + }); + }); + this.removePlayer = function(player) { var index = players.indexOf(player); if (index >= 0) { diff --git a/server/relayserver.js b/server/relayserver.js index 8b6af5a0..42259028 100644 --- a/server/relayserver.js +++ b/server/relayserver.js @@ -241,9 +241,9 @@ var RelayServer = function(servers, options) { return; } debug("starting game: " + gameId); - eventEmitter.emit('gameStarted', {gameId: gameId}); var gameGroup = getGameGroup(gameId, true); gameGroup.assignClient(client, data); + eventEmitter.emit('gameStarted', {gameId: gameId}); }.bind(this); for (var ii = 0; ii < servers.length; ++ii) { diff --git a/todo.md b/todo.md index 97b592eb..a85cff44 100644 --- a/todo.md +++ b/todo.md @@ -1,15 +1,17 @@ To Do ===== +* make games 'reload' if the server disconnects then reconnects + + can we some how indicate to the game it's a reconnect? For example, set a local cookie. + On load read and clear the cookie. Set a flag on gameserver? + * send audio example * move tiled support to hft-tiled? * add tiled support to jumpjump -* make controllers only work if game is running, otherwise switch to other game -* make games use websockets to switch games instead of polling ajax * Add unity support for multiple games * fix back button on shft game page. Only center is hot. * make hft-publish work for html-example -* Add option to skip name input. hft start --no-ask-name * add optional player timeout? I already have the ping but maybe I should also have an input timeout. @@ -20,7 +22,6 @@ To Do * add "hft remove --missing" and "--broken" to remove missing/broken ones * consider using a fake inmem file system for testing, both reading and writing * publish unity plugin -* figure out why unitycharacterexample is not exiting when hft asks it to. * if hft is not running, have shft save a cookie if you choose a game to install. when hft starts it can open an iframe to shft which will read the cookie and @@ -759,6 +760,10 @@ Runs Repo noid Done ==== +* figure out why unitycharacterexample is not exiting when hft asks it to. +* Add option to skip name input. hft start --no-ask-name +* make controllers only work if game is running, otherwise switch to other game +* make games use websockets to switch games instead of polling ajax * make subId the id. If not subId use a prefixed id like _hft_123 * test broadcast * support multiple games on the same gameId for shared games.