diff --git a/app/Game/Client/Control/Key.js b/app/Game/Client/Control/Key.js index 2377406..724ea3d 100755 --- a/app/Game/Client/Control/Key.js +++ b/app/Game/Client/Control/Key.js @@ -1,4 +1,9 @@ - define(function () { +define([ +], + +function () { + + "use strict"; function Key () { this._active = false; diff --git a/app/Game/Client/GameController.js b/app/Game/Client/GameController.js index f962892..c239aa0 100755 --- a/app/Game/Client/GameController.js +++ b/app/Game/Client/GameController.js @@ -20,12 +20,6 @@ function (Parent, Box2D, PhysicsEngine, ViewManager, PlayerController, Nc, reque "use strict"; - if (!window.cancelAnimationFrame) { - window.cancelAnimationFrame = function(id) { - clearTimeout(id); - }; - } - function GameController (options) { this.clientIsReady = false; @@ -277,6 +271,12 @@ function (Parent, Box2D, PhysicsEngine, ViewManager, PlayerController, Nc, reque GameController.prototype.destroy = function() { + if (!window.cancelAnimationFrame) { + window.cancelAnimationFrame = function(id) { + clearTimeout(id); + }; + } + cancelAnimationFrame(this.animationRequestId); Parent.prototype.destroy.call(this); diff --git a/app/Game/Client/Me.js b/app/Game/Client/Me.js index cbaaf9e..31436a9 100644 --- a/app/Game/Client/Me.js +++ b/app/Game/Client/Me.js @@ -118,5 +118,4 @@ function (Parent, Settings, Nc) { }; return Me; - -}) \ No newline at end of file +}); \ No newline at end of file diff --git a/app/Game/Client/Physics/Engine.js b/app/Game/Client/Physics/Engine.js index f4f3119..192b078 100755 --- a/app/Game/Client/Physics/Engine.js +++ b/app/Game/Client/Physics/Engine.js @@ -62,4 +62,4 @@ function (Parent, Settings, DomController, Box2D, Nc, DebugDraw, DebugLayer) { } return Engine; -}) \ No newline at end of file +}); \ No newline at end of file diff --git a/app/Game/Client/View/DomController.js b/app/Game/Client/View/DomController.js index 2867704..adfa0b7 100755 --- a/app/Game/Client/View/DomController.js +++ b/app/Game/Client/View/DomController.js @@ -11,13 +11,12 @@ function (Settings, Nc, Screenfull, Graph, PointerLockManager) { "use strict"; function DomController() { - this.canvas = document.getElementById("canvas"); + this.canvas = null; this.stats = null; this.ping = null; this.nickContainer = null; this.fpsContainer = ""; - - this.devToolsContainer = document.getElementById("menuBar"); + this.devToolsContainer = null; this.initDevTools(); } @@ -27,6 +26,9 @@ function (Settings, Nc, Screenfull, Graph, PointerLockManager) { var self = this; var li, button, label; + this.canvas = document.getElementById("canvas"); + this.devToolsContainer = document.getElementById("menuBar"); + // create back to menu button li = document.createElement("li"); li.id = "back-to-menu"; diff --git a/app/Game/Client/View/Pixi/Layer.js b/app/Game/Client/View/Pixi/Layer.js index 7063924..aeb0e87 100644 --- a/app/Game/Client/View/Pixi/Layer.js +++ b/app/Game/Client/View/Pixi/Layer.js @@ -9,13 +9,6 @@ define([ function (Parent, PIXI, ColorRangeReplaceFilter, Settings, ColorConverter) { "use strict"; - - var AVAILABLE_MESH_FILTERS = { - "blur": PIXI.BlurFilter, - "desaturate": PIXI.GrayFilter, - "pixelate": PIXI.PixelateFilter, - "colorRangeReplace": ColorRangeReplaceFilter, - }; function Layer (name, parallaxSpeed) { Parent.call(this, name, parallaxSpeed); @@ -60,6 +53,15 @@ function (Parent, PIXI, ColorRangeReplaceFilter, Settings, ColorConverter) { Layer.prototype = Object.create(Parent.prototype); + Layer.prototype.getAvailableMeshFilters = function() { + return { + "blur": PIXI.BlurFilter, + "desaturate": PIXI.GrayFilter, + "pixelate": PIXI.PixelateFilter, + "colorRangeReplace": ColorRangeReplaceFilter, + }; + }; + Layer.prototype.getContainer = function() { return this.container; }; @@ -135,11 +137,11 @@ function (Parent, PIXI, ColorRangeReplaceFilter, Settings, ColorConverter) { Layer.prototype.addFilter = function(mesh, filterName, options) { - if (!AVAILABLE_MESH_FILTERS.hasOwnProperty(filterName)) { + if (!this.getAvailableMeshFilters().hasOwnProperty(filterName)) { throw new Exception('Filter ' + filterName + ' is not available'); } - var MeshFilter = AVAILABLE_MESH_FILTERS[filterName]; + var MeshFilter = this.getAvailableMeshFilters()[filterName]; var filter = new MeshFilter(); switch (filterName) { @@ -189,7 +191,7 @@ function (Parent, PIXI, ColorRangeReplaceFilter, Settings, ColorConverter) { return; } - var MeshFilter = AVAILABLE_MESH_FILTERS[options.filter]; + var MeshFilter = this.getAvailableMeshFilters()[options.filter]; filters = filters.filter(function(filter){ return !filter instanceof MeshFilter; @@ -271,9 +273,6 @@ function (Parent, PIXI, ColorRangeReplaceFilter, Settings, ColorConverter) { this.container.x += Settings.STAGE_WIDTH / 2; this.container.y += Settings.STAGE_HEIGHT / 2; } - - - }; return Layer; diff --git a/app/Game/Config/ItemSettings.js b/app/Game/Config/ItemSettings.js index 5c95941..aea2aee 100644 --- a/app/Game/Config/ItemSettings.js +++ b/app/Game/Config/ItemSettings.js @@ -1,4 +1,7 @@ -define(function() { +define([ +], + +function () { var ItemSettings = { diff --git a/app/Game/Config/Settings.js b/app/Game/Config/Settings.js index 5fd574b..0309f10 100755 --- a/app/Game/Config/Settings.js +++ b/app/Game/Config/Settings.js @@ -1,4 +1,7 @@ -define(function() { +define([ +], + +function () { var Settings = { STAGE_WIDTH: 600, diff --git a/app/Game/Core/Control/PlayerController.js b/app/Game/Core/Control/PlayerController.js index 97189cb..8915fc3 100755 --- a/app/Game/Core/Control/PlayerController.js +++ b/app/Game/Core/Control/PlayerController.js @@ -1,4 +1,7 @@ -define(function () { +define([ +], + +function () { function PlayerController (player) { diff --git a/app/Game/Core/Loader/Level.js b/app/Game/Core/Loader/Level.js index b94c777..ee029d5 100755 --- a/app/Game/Core/Loader/Level.js +++ b/app/Game/Core/Loader/Level.js @@ -96,4 +96,4 @@ define([ } return Level; -}) \ No newline at end of file +}); \ No newline at end of file diff --git a/app/Game/Core/Loader/TiledLevel.js b/app/Game/Core/Loader/TiledLevel.js index 91f6aa7..b33e0a7 100755 --- a/app/Game/Core/Loader/TiledLevel.js +++ b/app/Game/Core/Loader/TiledLevel.js @@ -213,4 +213,4 @@ define([ } return TiledLevel; -}) \ No newline at end of file +}); \ No newline at end of file diff --git a/app/Game/Core/User.js b/app/Game/Core/User.js index de3264f..e2eda24 100755 --- a/app/Game/Core/User.js +++ b/app/Game/Core/User.js @@ -1,4 +1,7 @@ -define(function () { +define([ +], + +function () { function User (id, options) { this.id = id; diff --git a/app/Lib/Vendor/Box2D.js b/app/Lib/Vendor/Box2D.js index c059918..0e1e7c5 100755 --- a/app/Lib/Vendor/Box2D.js +++ b/app/Lib/Vendor/Box2D.js @@ -1,4 +1,7 @@ -define(function() { +define([ +], + +function () { /* * Copyright (c) 2006-2007 Erin Catto http://www.gphysics.com diff --git a/app/Server/PipeToChannel.js b/app/Server/PipeToChannel.js index 7112783..bf2adcd 100755 --- a/app/Server/PipeToChannel.js +++ b/app/Server/PipeToChannel.js @@ -7,8 +7,6 @@ function (Nc, childProcess) { "use strict"; - var fork = childProcess.fork; - function PipeToChannel (options) { this.fork = null; @@ -16,7 +14,7 @@ function (Nc, childProcess) { this.users = []; try { - this.fork = fork('channel.js' + this.fork = childProcess.fork('channel.js' /*, { execArgv: ['--debug=5859'] }*/ diff --git a/scripts/optimize.js b/scripts/optimize.js new file mode 100644 index 0000000..63d0a76 --- /dev/null +++ b/scripts/optimize.js @@ -0,0 +1,218 @@ +/* + * This is supposed to be a code optimizer. + * + * usage: + * node scripts/optimize.js + * + * based on https://developers.google.com/speed/articles/optimizing-javascript + * I wanted to automatically replace properties as discribed under "Initializing instance variables" + * + * So far it is the only thing this script does, but the potential for more is there. + * Also it does not (yet) write to any files, only outputs the results in the console. + * + * The script fully disasembles the entire codebase (with esprima) and reconstructs (via escodegen) it + * with a few optimisations unfortunately it loses ambiguous new lines and such, so that it might + * not be entirely usable as a code replacing script - it could perhaps be used as a compile script in + * production + * + * But it has also nice things as at will add semicolons everywhere automatically and will + * definately keep a solid indentation style for everything. Since it lacks a lot of extra + * \n newlines it looks quite cluttered though. + * + */ + +var fs = require('fs'); +var util = require('util'); +var esprima = require('esprima'); +var escodegen = require('escodegen'); + +var info = []; + +var generatorOption = { + format: { + indent: { + style: ' ', + base: 0, + adjustMultilineComment: true//false + }, + newline: '\n', + space: ' ', + json: false, + renumber: false, + hexadecimal: false, + quotes: 'single', + escapeless: false, + compact: false, + parentheses: true, + semicolons: true, + safeConcatenation: true + }, + moz: { + starlessGenerator: false, + parenthesizedComprehensionBlock: false, + comprehensionExpressionStartsWithAssignment: false + }, + parse: null, + comment: true, + sourceMap: undefined, + sourceMapRoot: null, + sourceMapWithCode: false, + file: undefined, + directive: false, + verbatim: undefined +}; + +function readdir (path) { + var filesNames = fs.readdirSync(path) + + for (var i = 0; i < filesNames.length; i++) { + + var fileName = filesNames[i]; + var fullPath = path + "/" + fileName; + + if(path == "app/Lib/Vendor"){ + continue; + } + + if(fileName.indexOf(".js") == -1) { + var stats = fs.lstatSync(fullPath); + if (stats.isDirectory()) { + readdir(fullPath); + } + continue; + } + + readFile(path, fileName); + }; +} + +function readFile (path, fileName) { + //console.log("+++++ " + moduleName + " ++++++"); + var contents = fs.readFileSync(path + "/" + fileName); + contents = contents.toString(); + + optimize(path, fileName, contents); +} + +function optimize (path, fileName, contents) { + var fullPath = path + "/" + fileName; + var moduleName = fileName.split(".js").join(""); + var tree = esprima.parse(contents); + + // find moduleId from return statement on module level + var module = tree.body[0].expression.arguments[1].body.body; + var moduleId = findModuleId(module); + + if (!moduleId) { + info.push("could not find moduleId in: " + fullPath); + return; + } + + if (moduleId == "Parent") { + info.push("not optimizing empty module (returning Parent) in: " + fullPath); + return; + } + + // find constructor + var constructorPosition = findConstructorPosition(module, moduleId); + if (constructorPosition === false) { + info.push("could not find constructor in: " + fileName) + return; + } + var constructor = module[constructorPosition]; + transformProps(tree, moduleId, constructor, constructorPosition); + + console.log(escodegen.generate(tree, generatorOption)); +} + +function findModuleId (module) { + var moduleId = false; + for (var j = 0; j < module.length; j++) { + var expression = module[j]; + + //console.log(util.inspect(expression, { showHidden: true, depth: 4 })); + + if (expression.type == "ReturnStatement") { + + if(expression.argument.type == "Identifier") { + + // for return Module; + moduleId = expression.argument.name; + break; + + } else if (expression.argument.type == "NewExpression") { + + // for return new Module; + moduleId = expression.argument.callee.name; + break; + + } else { + info.push("Unexpected return type at module level. " + fullPath) + } + } + } + return moduleId; +}; + +function findConstructorPosition (module, moduleId) { + + for (var j = 0; j < module.length; j++) { + var expression = module[j]; + + if (expression.type == "FunctionDeclaration" && expression.id.name == moduleId) { + return j; + } + } + return false; +} + +function transformProps (tree, moduleId, constructor, constructorPosition) { + var props = []; + for (var k = constructor.body.body.length - 1; k >= 0; k--) { + var line = constructor.body.body[k]; + + if(line.expression + && line.expression.type == "AssignmentExpression" + && line.expression.operator == "=" + && line.expression.left.type == "MemberExpression" + && line.expression.left.object.type == "ThisExpression" + && line.expression.right.type == "Literal") { + + // remove "this" properties with with value type from constructor + constructor.body.body.splice(k, 1); + //console.log(util.inspect(line, { showHidden: true, depth: 4 })); + + props.push({ + name: line.expression.left.property.name, + value: line.expression.right.value, + raw: line.expression.right.raw + }); + } + }; + + // generate prototype properties + for (var l = 0; l < props.length; l++) { + var attributes = props[l]; + + var prop = { type: 'ExpressionStatement', + expression: + { type: 'AssignmentExpression', + operator: '=', + left: + { type: 'MemberExpression', + computed: false, + object: + { type: 'MemberExpression', + computed: false, + object: { type: 'Identifier', name: moduleId }, + property: { type: 'Identifier', name: 'prototype' } }, + property: { type: 'Identifier', name: attributes.name } }, + right: { type: 'Literal', value: attributes.value, raw: attributes.raw } } } + + // place property after constructor + tree.body[0].expression.arguments[1].body.body.splice(constructorPosition+1, 0, prop); + }; +} + +readdir("app"); +console.log(info) diff --git a/scripts/optimize_.js b/scripts/optimize_.js new file mode 100644 index 0000000..4e5883a --- /dev/null +++ b/scripts/optimize_.js @@ -0,0 +1,125 @@ +/* + * First version of the optimizer, relying completely on regular expressions + * + * it grabs the code as text and just executes the outermost function (module level) + * therefore it would not execute any real code, only setup the prototype functinos + * and the constructor + * + * since some modules use "return new Module();" to create a singleton, I added + * a mechanism to remove the "new" keyword and get the same kind of non-executing behaviour + * + * the trial failed because i could not replace the old constructor with the new one + * with simple replace algorithms because of whitespace differences + * + * Spits out some small statistics at the end, which is quite nice + */ + +var fs = require('fs'); + +var successful = []; +var canceled = []; +var noconstruct = []; +var repaired = []; + +function readdir (path) { + var filesNames = fs.readdirSync(path) + + for (var i = 0; i < filesNames.length; i++) { + + var fileName = filesNames[i]; + var newPath = path + "/" + fileName; + + if(path == "app/Lib/Vendor"){ + continue; + } + + if(fileName.indexOf(".js") == -1) { + var stats = fs.lstatSync(newPath); + if (stats.isDirectory()) { + readdir(newPath); + } + continue; + } + + var moduleName = fileName.split(".js").join(""); + + var contents = fs.readFileSync(newPath); + contents = contents.toString(); + + // remove define construct around module, just get the module function + contents = contents.replace(/define\(\[[^\]]*\],\s*([\s\S]*)\);/, '$1'); + + // remove new from last return / disable singletons (eg. return new NotificationCenter;) + var before = contents; + contents = contents.replace(/([\s\S]*)return new ([a-zA-Z0-9]*)\s*\(?.*\);/, '$1return $2;'); + if (contents != before){ + repaired.push(moduleName); + } + + + eval("var module = " + contents); + + try { + // test run, to get possible exceptions + var Parent = function(){}; + var constructor = module(Parent); + + if (typeof constructor == 'object') { + noconstruct.push(newPath); + continue; + } + + //var optimizedModule = optimize(moduleName, module); + //console.log(optimizedModule); + + successful.push(newPath); + + } catch (e) { + //console.log(e) // see whats making it cancel + canceled.push(newPath); + } + }; +} + +function optimize(moduleName, module) { +/* + var better = module.toString(); + + var Parent = function(){}; + var constructor = module(Parent).toString(); + + var regex = /^\s*this\.(.*) = (.*)\n?/mig; + var props = []; + + do { + match = regex.exec(constructor); + if(match) { + props.push(moduleName + ".prototype." + match[1] + " = " + match[2]); + } + + } while (match != null); + + // remove original this.prop + constructor = constructor.replace(regex, ''); + + // add prototype variables at bottom of constructor + if (props.length > 0) { + constructor = constructor + "\n\n" + props.join("\n"); + } + //constructor = constructor.replace("function " + moduleName + "(", "function " + moduleName + " ("); + */ + + return ""; +} + +readdir("app"); + + +console.log("- Successful:", successful.length) +console.log("- Canceled:", canceled.length) +console.log("- No Constructor:", noconstruct.length) +console.log("- Repaired Singletons:", repaired.length) + +console.log("canceled:", canceled) +console.log("no constructor:", noconstruct) +//console.log("successful:", successful) \ No newline at end of file