Permalink
Browse files

Many changes, v0.2.0

* Split source into sub-files, see dev\src.
* Separated the hooking stuff out into JavaScript Hooker, now a full
  project on GitHub, included here as a submodule.
* Created a build tool and updated the dev web server.
  • Loading branch information...
1 parent 07cd467 commit 185471ee0b9b8881d78512b2947fd10d994bcc45 @cowboy committed Nov 1, 2011
View
@@ -0,0 +1,3 @@
+[submodule "dev/javascript-hooker"]
+ path = dev/javascript-hooker
+ url = git://github.com/cowboy/javascript-hooker.git
View
@@ -39,16 +39,22 @@ And for what it's worth, I've spent a LOT of time in the WebKit inspector, setti
Running in "development" mode:
-1. Clone the repo (You'll probably need [Git for Windows](http://code.google.com/p/msysgit/) first).
-1. Disable the `battlelog-hacks.user.js` extension in Chrome's "Extensions" manager.
-2. Run `start-webserver.cmd` in the `dev` directory.
-3. Drag `battlelog-hacks-dev.user.js` into the browser and click Ok/Continue/Install as-necessary.
-4. Reload Battlelog.
+1. Install [Git for Windows](http://code.google.com/p/msysgit/) if you don't already have it.
+2. In Git Bash, run `git clone git://github.com/cowboy/battlelog-hacks.git && cd battlelog-hacks && git submodule init && git submodule update`
+3. Disable the `battlelog-hacks.user.js` extension in Chrome's "Extensions" manager.
+4. Drag `battlelog-hacks-dev.user.js` into the browser and click Ok/Continue/Install as-necessary.
+5. Run `start-webserver.cmd` from the `dev` subdirectory.
+6. Edit scripts in the `dev\src` subdirectory.
+7. Reload Battlelog.
+8. Repeat steps 6-7 ad nauseum. Note that if you add or rename files, you'll need to edit `dev\node\files.js` and kill/restart the webserver (step 5).
+9. Once done, run `build.cmd` from the `dev` subdirectory to build `dist\battlelog-hacks.js`.
_Remember that once you're done developing, you'll need to disable `battlelog-hacks-dev.user.js` and re-enable `battlelog-hacks.user.js` in Chrome's "Extensions" manager. Or just leave the webserver running, always._
In lieu of a formal styleguide, take care to maintain the existing coding style. Issue a pull request when done. Found a bug? [File an issue](https://github.com/cowboy/battlelog-hacks/issues).
+_Also, please don't edit files in the "dist" subdirectory as they are generated via `build.cmd`. You'll find source code in the `dev\src` subdirectory!_
+
## Release History
10/30/2011
Initial release. Not even a version number.
@@ -59,6 +65,12 @@ Adding "development" web server and userscript.
Auto-retry join errors are now whitelisted, to avoid auto-retrying in certain situations (like when kicked from a server).
Version number is announced in a little blue box upon start.
+10/31/2011
+v0.2.0
+Split source into sub-files.
+Broke the hooking stuff out into JavaScript Hooker, included as a submodule.
+Created a build tool and updated the dev web server.
+
## License
Copyright (c) 2011 "Cowboy" Ben Alman
Licensed under the MIT license.
View
@@ -0,0 +1,2 @@
+@echo off
+node\node node\build.js
Submodule javascript-hooker added at 6e89f3
File renamed without changes.
View
@@ -0,0 +1,4 @@
+var fs = require("fs");
+var src = require("./files.js").concat();
+
+fs.writeFileSync("../dist/battlelog-hacks.js", src, "UTF8");
View
@@ -0,0 +1,28 @@
+var fs = require("fs");
+
+exports.files = [
+ "src/intro.js",
+ "javascript-hooker/dist/ba-hooker.js",
+ "src/log.js",
+ "src/auto-retry.js",
+ "src/auto-sort.js",
+ "src/suppress-scrolltop.js",
+ "src/outro.js"
+];
+
+exports.concat = function(files) {
+ // Use defaults if files aren't specified.
+ files || (files = exports.files);
+ // Concat files.
+ return files.map(function(filepath, i) {
+ var src = fs.readFileSync(filepath, "UTF8");
+ // Chomp!
+ src = src.replace(/[\s\n]*$/, "");
+ // Remove leading comment from all but the first Battlelog Hacks internal
+ // files when building.
+ if (i > 0) {
+ src = src.replace(/^[\s\n]*\/\* Battlelog Hacks[\s\S]*?\*\/[\s\n]*/, "");
+ }
+ return src;
+ }).join("\n\n");
+};
File renamed without changes.
@@ -1,11 +1,11 @@
var http = require('http');
-var fs = require('fs');
+var files = require("./files.js");
var port = 8000;
console.log("Starting webserver at http://localhost:" + port + "/");
console.log("\n(Close this window to exit)");
http.createServer(function(req, res) {
- res.writeHead(200, {'Content-Type': 'text/javascript'});
- res.end(fs.readFileSync('../dist/battlelog-hacks.js'));
+ res.writeHead(200, {"Content-Type": "text/javascript"});
+ res.end(files.concat());
}).listen(port);
View
@@ -0,0 +1,99 @@
+/* Battlelog Hacks
+ * http://benalman.com/
+ * Copyright (c) 2011 "Cowboy" Ben Alman; Licensed MIT */
+
+cowboy.register("Auto-retry Join Server");
+
+(function() {
+ var join, id;
+
+ // Create an element to contain auto-retry status text.
+ var retryStatus = $("<span/>");
+
+ // Override existing "join" methods.
+ ["joinMpServer", "joinMpFriend"].forEach(function(method) {
+ cowboy.hooker.hook(launcher, method, function() {
+ cowboy.log(method, arguments);
+ // Stop auto-retrying.
+ unretry();
+ // Create a re-callable "join" function with arguments already applied.
+ var orig = cowboy.hooker.orig(launcher, method);
+ join = Function.apply.bind(orig, this, arguments);
+ });
+ });
+
+ // A list of errors that should trigger auto-retry. Painstakingly parsed from
+ // gamemanager.handleErrors.
+ var validErrors = [
+ launcher.ALERT.ERR_LAUNCH_DISABLED,
+ launcher.ALERT.ERR_EMPTY_JOINSTATE,
+ launcher.ALERT.ERR_FAILED_PERSONACALL,
+ launcher.ALERT.ERR_BACKEND_HTTP,
+ launcher.ALERT.ERR_BACKEND_ROUTE,
+ launcher.ALERT.ERR_TOO_MANY_ATTEMPTS,
+ launcher.ALERT.ERR_DISCONNECT_GAME_SERVERFULL,
+ launcher.ALERT.ERR_SERVERCONNECT_FULL,
+ launcher.ALERT.ERR_SERVER_QUEUE_FULL,
+ launcher.ALERT.ERR_SERVERCONNECT,
+ launcher.ALERT.ERR_SERVERCONNECT_WRONGPASSWORD,
+ launcher.ALERT.ERR_CONFIG_MISSMATCH,
+ launcher.ALERT.ERR_GENERIC,
+ launcher.ALERT.ERR_MATCHMAKE.START_MATCHMAKING_FAILED,
+ launcher.ALERT.ERR_DISCONNECT_GAME_NOREPLY,
+ launcher.ALERT.ERR_DISCONNECT_GAME_TIMEDOUT,
+ launcher.ALERT.ERR_INVALID_GAME_STATE_ACTION
+ ];
+
+ // Override existing error handler method.
+ cowboy.hooker.hook(launcher, "_triggerEvent", {
+ post: function(result, type, details) {
+ // Only auto-retry on valid errors.
+ if (type === "error.generic" && validErrors.indexOf(details[2]) !== -1) {
+ cowboy.log("Starting auto-retry countdown.", details);
+ // Start countdown.
+ retry();
+ }
+ }
+ });
+
+ // Start auto-retrying.
+ function retry() {
+ // Stop any currently executing auto-retry loop.
+ unretry(true);
+
+ // 10-seconds seems like a good number.
+ var count = 10;
+
+ // Attach status element to the DOM.
+ retryStatus.appendTo(".gamemanager-launchstate-gameready");
+
+ function update() {
+ // Update status text.
+ retryStatus.html(" (Auto-retry&nbsp;in&nbsp;" + count + ")");
+ // If counter has reached 0, stop auto-retrying and join.
+ if (count-- === 0) {
+ cowboy.log("Retrying now.");
+ unretry(true);
+ join();
+ }
+ }
+ // Start counter.
+ update();
+ id = setInterval(update, 1000);
+ }
+
+ // Stop auto-retrying.
+ function unretry(silent) {
+ if (!id) { return; }
+ cowboy.log("Stopping auto-retry.");
+ // Actually stop the auto-retry.
+ clearInterval(id);
+ id = null;
+ // Detach the status element from the DOM and empty it.
+ retryStatus.detach().empty();
+ }
+
+ // If user clicks "Close" button in "Could not join..." dialog, stop
+ // auto-retrying.
+ $(document).delegate("#gamemanager-state-close", "click", unretry);
+}());
View
@@ -0,0 +1,119 @@
+/* Battlelog Hacks
+ * http://benalman.com/
+ * Copyright (c) 2011 "Cowboy" Ben Alman; Licensed MIT */
+
+cowboy.register("Auto-sort Server List");
+
+(function() {
+ // Watch for sorting element clicks.
+ $(document).delegate(".serverguide-sorter", "click", function(e, triggered) {
+ // Abort if manually triggered.
+ if (triggered) { return false; }
+ // Get current sort mode and direction.
+ var mode = sortMode(this);
+ var dir = sortDir(this);
+ cowboy.log("Storing server sorting mode: %s, dir: %s.", mode, dir);
+ // Store sort mode and direction.
+ localStorage.setItem("cb_sort_mode", mode);
+ localStorage.setItem("cb_sort_dir", dir);
+ });
+
+ // Get sort mode from a given element.
+ function sortMode(elem) {
+ var matches = /serverguide-sorting-(\w+)/.exec(elem.className);
+ return matches && matches[1];
+ }
+
+ // Get sort direction from a given element.
+ function sortDir(elem) {
+ var matches = /serverguide-sort-(\w+)/.exec(elem.className);
+ return matches && matches[1];
+ }
+
+ // Re-sort the server list based on the last stored sort mode + direction.
+ // I couldn't find a non-DOM way to do this. I feel gross.
+ cowboy.reSortServers = function() {
+ // Get stored sort mode.
+ var mode = localStorage.getItem("cb_sort_mode");
+ // If mode has never been stored, abort.
+ if (!mode) { return; }
+ // Find DOM element corresponding to this sort mode.
+ var elem = $(".serverguide-sorting-" + mode);
+ // If element doesn't exist, abort.
+ if (elem.length === 0) { return; }
+ // Get the current sort direction from the element.
+ var dir = sortDir(elem[0]);
+ // If the element has a sort direction, it has already been sorted. Abort.
+ if (dir) { return; }
+
+ // Get stored sort dir.
+ dir = localStorage.getItem("cb_sort_dir");
+ cowboy.log("Re-sorting servers using mode: %s, dir: %s.", mode, dir);
+ // Click the element once to sort up.
+ elem.trigger("click", [true]);
+ // If sorting down, click the element a second time.
+ if (dir === "down") {
+ elem.trigger("click", [true]);
+ }
+
+ // After sorting, the first server should be highlighted. Get a list of
+ // sorted server id strings.
+ var ids = serverguideSort.getAllServerSurfaceIds();
+ // If there aren't any servers, abort.
+ if (ids.length === 0) { return; }
+ // Highlight the first server (its numeric id value must be parsed from
+ // the id string).
+ serverguide.highlightServerIndex(+ids[0].split('-')[2]);
+ };
+
+ var count, id;
+ // Re-sort the server list when all server data has been retrieved.
+ function initCounter() {
+ cowboy.log("Waiting for server data to be retrieved.");
+ // Reset count to the number of servers displayed (the number of times that
+ // serverguide.refreshHighlight will be called).
+ count = serverguideSort.getAllServerSurfaceIds().length;
+ // Hook serverguide.refreshHighlight (which appears to be called every time
+ // a server's details (name, players, ping, etc) are returned)
+ cowboy.hooker.hook(serverguide, "refreshHighlight", function() {
+ // Clear any existing timeout.
+ clearTimeout(id);
+
+ if (--count === 0) {
+ // Unhook and re-sort servers.
+ done();
+ } else {
+ // Auto-done() after a timeout, in case serverguide.refreshHighlight is
+ // called less than the expected number of times.
+ id = setTimeout(done, 1000);
+ }
+ });
+
+ // Unhook and re-sort servers.
+ function done() {
+ cowboy.log("Server data has been retrieved.");
+ // Unhook.
+ cowboy.hooker.unhook(serverguide, "refreshHighlight");
+ // Re-sort servers.
+ cowboy.reSortServers();
+ }
+ }
+
+ // Hook serverguide.updateFriendsPlayingOnServers (which appears to be
+ // called every time the serverguide is refreshed) to init the counter.
+ cowboy.hooker.hook(serverguide, "updateFriendsPlayingOnServers", function() {
+ // Init counter.
+ initCounter();
+ // Not sure why serverguide.refreshHighlight gets called two extra times,
+ // but I don't really care either.
+ count += 2;
+ });
+
+ // The serverguide form is currently visible, so Battlelog was loaded on the
+ // serverguide page. Handle re-sorting servers here (because this userscript
+ // runs after the initial serverguide.onPageShow is called, and can't hook
+ // it the very first time).
+ if ($("#serverguide-filter-form").is(":visible")) {
+ initCounter();
+ }
+}());
View
@@ -0,0 +1,21 @@
+/* Battlelog Hacks
+ * http://benalman.com/
+ * Copyright (c) 2011 "Cowboy" Ben Alman; Licensed MIT */
+
+// Global namespace.
+window.cowboy = {
+ version: "0.2.0",
+ registry: [],
+ register: function(name) {
+ cowboy.registry.push(name);
+ },
+ loaded: function() {
+ cowboy.popup("Battlelog Hacks v" + cowboy.version + " loaded.");
+ cowboy.registry.forEach(function(name) {
+ cowboy.log("Registered: " + name);
+ });
+ }
+};
+
+// Hooker.
+var exports = cowboy.hooker = {};
Oops, something went wrong.

0 comments on commit 185471e

Please sign in to comment.