├── .eslintrc.js ├── .gitignore ├── .travis.yml ├── CHANGELOG ├── LICENSE ├── README.md ├── bin ├── legacy │ ├── build.sh │ ├── install-nodegame-for-module-node5.beta.sh │ ├── install-nodegame-for-module.sh │ ├── install.dev.sh │ ├── install.latest.cmd │ ├── install.latest.sh │ ├── install.stable.cmd │ ├── install.stable.sh │ └── pull-all.sh ├── nodegame-cli-experimental.js ├── nodegame-installer.js └── update │ ├── update-steps.js │ └── update_version.sh ├── conf ├── http.js ├── loggers.js ├── servernode.js └── sio.js ├── games └── README.md ├── games_available └── README.md ├── git-hooks └── pre-commit ├── launcher.js ├── log └── README ├── package.json └── test ├── launcher-autoplay.js └── runtest.exp /.eslintrc.js: -------------------------------------------------------------------------------- 1 | var OFF = 0, WARN = 1, ERROR = 2; 2 | 3 | module.exports = exports = { 4 | "env": { 5 | "es6": true, 6 | "node": true, 7 | "browser": true 8 | }, 9 | 10 | "extends": "eslint:recommended", 11 | 12 | // "ecmaFeatures": { 13 | // // env=es6 doesn't include modules, which we are using 14 | // "modules": true 15 | // }, 16 | // 17 | 18 | "rules": { 19 | "no-console": "off" 20 | }, 21 | 22 | "globals": { 23 | "W": "writable", 24 | "node": "writable", 25 | "J": "writable", 26 | "JSUS": "writable" 27 | } 28 | 29 | // 30 | // "rules": { 31 | // // Possible Errors (overrides from recommended set) 32 | // "no-extra-parens": ERROR, 33 | // "no-unexpected-multiline": ERROR, 34 | // // All JSDoc comments must be valid 35 | // "valid-jsdoc": [ ERROR, { 36 | // "requireReturn": false, 37 | // "requireReturnDescription": false, 38 | // "requireParamDescription": true, 39 | // "prefer": { 40 | // "return": "returns" 41 | // } 42 | // }], 43 | // 44 | // // Best Practices 45 | // 46 | // // Allowed a getter without setter, but all setters require getters 47 | // "accessor-pairs": [ ERROR, { 48 | // "getWithoutSet": false, 49 | // "setWithoutGet": true 50 | // }], 51 | // "block-scoped-var": WARN, 52 | // "consistent-return": ERROR, 53 | // "curly": ERROR, 54 | // "default-case": WARN, 55 | // // the dot goes with the property when doing multiline 56 | // "dot-location": [ WARN, "property" ], 57 | // "dot-notation": WARN, 58 | // "eqeqeq": [ ERROR, "smart" ], 59 | // "guard-for-in": WARN, 60 | // "no-alert": ERROR, 61 | // "no-caller": ERROR, 62 | // "no-case-declarations": WARN, 63 | // "no-div-regex": WARN, 64 | // "no-else-return": WARN, 65 | // "no-empty-label": WARN, 66 | // "no-empty-pattern": WARN, 67 | // "no-eq-null": WARN, 68 | // "no-eval": ERROR, 69 | // "no-extend-native": ERROR, 70 | // "no-extra-bind": WARN, 71 | // "no-floating-decimal": WARN, 72 | // "no-implicit-coercion": [ WARN, { 73 | // "boolean": true, 74 | // "number": true, 75 | // "string": true 76 | // }], 77 | // "no-implied-eval": ERROR, 78 | // "no-invalid-this": ERROR, 79 | // "no-iterator": ERROR, 80 | // "no-labels": WARN, 81 | // "no-lone-blocks": WARN, 82 | // "no-loop-func": ERROR, 83 | // "no-magic-numbers": WARN, 84 | // "no-multi-spaces": ERROR, 85 | // "no-multi-str": WARN, 86 | // "no-native-reassign": ERROR, 87 | // "no-new-func": ERROR, 88 | // "no-new-wrappers": ERROR, 89 | // "no-new": ERROR, 90 | // "no-octal-escape": ERROR, 91 | // "no-param-reassign": ERROR, 92 | // "no-process-env": WARN, 93 | // "no-proto": ERROR, 94 | // "no-redeclare": ERROR, 95 | // "no-return-assign": ERROR, 96 | // "no-script-url": ERROR, 97 | // "no-self-compare": ERROR, 98 | // "no-throw-literal": ERROR, 99 | // "no-unused-expressions": ERROR, 100 | // "no-useless-call": ERROR, 101 | // "no-useless-concat": ERROR, 102 | // "no-void": WARN, 103 | // // Produce warnings when something is commented as TODO or FIXME 104 | // "no-warning-comments": [ WARN, { 105 | // "terms": [ "TODO", "FIXME" ], 106 | // "location": "start" 107 | // }], 108 | // "no-with": WARN, 109 | // "radix": WARN, 110 | // "vars-on-top": ERROR, 111 | // // Enforces the style of wrapped functions 112 | // "wrap-iife": [ ERROR, "outside" ], 113 | // "yoda": ERROR, 114 | // 115 | // // Strict Mode - for ES6, never use strict. 116 | // "strict": [ ERROR, "never" ], 117 | // 118 | // // Variables 119 | // "init-declarations": [ ERROR, "always" ], 120 | // "no-catch-shadow": WARN, 121 | // "no-delete-var": ERROR, 122 | // "no-label-var": ERROR, 123 | // "no-shadow-restricted-names": ERROR, 124 | // "no-shadow": WARN, 125 | // // We require all vars to be initialized (see init-declarations) 126 | // // If we NEED a var to be initialized to undefined, 127 | // // it needs to be explicit 128 | // "no-undef-init": OFF, 129 | // "no-undef": ERROR, 130 | // "no-undefined": OFF, 131 | // "no-unused-vars": WARN, 132 | // // Disallow hoisting - let & const don't allow hoisting anyhow 133 | // "no-use-before-define": ERROR, 134 | // 135 | // // Node.js and CommonJS 136 | // "callback-return": [ WARN, [ "callback", "next" ]], 137 | // "global-require": ERROR, 138 | // "handle-callback-err": WARN, 139 | // "no-mixed-requires": WARN, 140 | // "no-new-require": ERROR, 141 | // // Use path.concat instead 142 | // "no-path-concat": ERROR, 143 | // "no-process-exit": ERROR, 144 | // "no-restricted-modules": OFF, 145 | // "no-sync": WARN, 146 | // 147 | // // ECMAScript 6 support 148 | // "arrow-body-style": [ ERROR, "always" ], 149 | // "arrow-parens": [ ERROR, "always" ], 150 | // "arrow-spacing": [ ERROR, { "before": true, "after": true }], 151 | // "constructor-super": ERROR, 152 | // "generator-star-spacing": [ ERROR, "before" ], 153 | // "no-arrow-condition": ERROR, 154 | // "no-class-assign": ERROR, 155 | // "no-const-assign": ERROR, 156 | // "no-dupe-class-members": ERROR, 157 | // "no-this-before-super": ERROR, 158 | // "no-var": WARN, 159 | // "object-shorthand": [ WARN, "never" ], 160 | // "prefer-arrow-callback": WARN, 161 | // "prefer-spread": WARN, 162 | // "prefer-template": WARN, 163 | // "require-yield": ERROR, 164 | // 165 | // // Stylistic - everything here is a warning because of style. 166 | // "array-bracket-spacing": [ WARN, "always" ], 167 | // "block-spacing": [ WARN, "always" ], 168 | // "brace-style": [ WARN, "1tbs", { "allowSingleLine": false } ], 169 | // "camelcase": WARN, 170 | // "comma-spacing": [ WARN, { "before": false, "after": true } ], 171 | // "comma-style": [ WARN, "last" ], 172 | // "computed-property-spacing": [ WARN, "never" ], 173 | // "consistent-this": [ WARN, "self" ], 174 | // "eol-last": WARN, 175 | // "func-names": WARN, 176 | // "func-style": [ WARN, "declaration" ], 177 | // "id-length": [ WARN, { "min": 2, "max": 32 } ], 178 | // "indent": [ WARN, 4 ], 179 | // "jsx-quotes": [ WARN, "prefer-double" ], 180 | // // "linebreak-style": [ WARN, "unix" ], 181 | // "lines-around-comment": [ WARN, { "beforeBlockComment": true } ], 182 | // "max-depth": [ WARN, 8 ], 183 | // "max-len": [ WARN, 132 ], 184 | // "max-nested-callbacks": [ WARN, 8 ], 185 | // "max-params": [ WARN, 8 ], 186 | // "new-cap": WARN, 187 | // "new-parens": WARN, 188 | // "no-array-constructor": WARN, 189 | // "no-bitwise": OFF, 190 | // "no-continue": OFF, 191 | // "no-inline-comments": OFF, 192 | // "no-lonely-if": WARN, 193 | // "no-mixed-spaces-and-tabs": WARN, 194 | // "no-multiple-empty-lines": WARN, 195 | // "no-negated-condition": OFF, 196 | // "no-nested-ternary": WARN, 197 | // "no-new-object": WARN, 198 | // "no-plusplus": OFF, 199 | // "no-spaced-func": WARN, 200 | // "no-ternary": OFF, 201 | // "no-trailing-spaces": WARN, 202 | // "no-underscore-dangle": WARN, 203 | // "no-unneeded-ternary": WARN, 204 | // "object-curly-spacing": [ WARN, "always" ], 205 | // "one-var": OFF, 206 | // "operator-assignment": [ WARN, "never" ], 207 | // "operator-linebreak": [ WARN, "after" ], 208 | // "padded-blocks": [ WARN, "never" ], 209 | // "quote-props": [ WARN, "consistent-as-needed" ], 210 | // // "quotes": [ WARN, "single" ], 211 | // "require-jsdoc": [ WARN, { 212 | // "require": { 213 | // "FunctionDeclaration": true, 214 | // "MethodDefinition": true, 215 | // "ClassDeclaration": false 216 | // } 217 | // }], 218 | // "semi-spacing": [ WARN, { "before": false, "after": true }], 219 | // "semi": [ ERROR, "always" ], 220 | // "sort-vars": OFF, 221 | // "space-after-keywords": [ WARN, "always" ], 222 | // "space-before-blocks": [ WARN, "always" ], 223 | // "space-before-function-paren": [ WARN, "never" ], 224 | // "space-before-keywords": [ WARN, "always" ], 225 | // "space-in-parens": [ WARN, "never" ], 226 | // "space-infix-ops": [ WARN, { "int32Hint": true } ], 227 | // "space-return-throw-case": ERROR, 228 | // "space-unary-ops": ERROR, 229 | // "spaced-comment": [ WARN, "always" ], 230 | // "wrap-regex": WARN 231 | // } 232 | }; 233 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .project 2 | .settings 3 | .idea 4 | Session.vim 5 | 6 | /tests/ 7 | /examples/test/* 8 | 9 | *.tar.gz 10 | *.tmp* 11 | *.csv 12 | *.swp 13 | .DS_Store 14 | \#*\# 15 | .\#* 16 | *~ 17 | *.nddb 18 | _* 19 | LOG 20 | 21 | npm-debug.log 22 | node_modules/ 23 | node_modules_old 24 | 25 | descil.conf.js 26 | 27 | imgscore 28 | 29 | log/*.log 30 | 31 | 32 | games_available/ultimatum-game 33 | games_available/dictator 34 | games_available/meritocracy 35 | games_available/ultimatum 36 | games_available/stopgo 37 | games_available/artex 38 | games_available/MiniSvo 39 | games_available/car-sharing 40 | games_available/DCL 41 | games_available/rules 42 | games_available/prisonersgame 43 | games_available/testergame 44 | 45 | games/ultimatum-game 46 | games/testergame 47 | games/dictator 48 | games/meritocracy 49 | games/ultimatum 50 | games/stopgo 51 | games/artex 52 | games/MiniSvo 53 | games/car-sharing 54 | games/DCL 55 | games/rules 56 | games/prisonersgame 57 | 58 | games_new/ 59 | start/ 60 | 61 | bin/nodegame 62 | 63 | manifest.yml 64 | 65 | private 66 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | sudo: false 2 | language: node_js 3 | node_js: 4 | - 6 5 | - 7 6 | - 8 7 | - 10 8 | 9 | before_install: 10 | # Get installer script. 11 | - wget https://raw.githubusercontent.com/nodeGame/nodegame/master/bin/nodegame-installer.js 12 | - chmod a+x nodegame-installer.js 13 | 14 | install: 15 | ## Remove package json, otherwise npm does not install nodegame as dependency. 16 | - npm install --only=dev 17 | - rm package.json 18 | # --branch v4 19 | - node nodegame-installer.js @dev --install-dir node_modules --no-spinner --yes 20 | 21 | script: 22 | # Add extra tests here. 23 | 24 | # Test Ultimatum game. 25 | - cd node_modules/nodegame/games/ultimatum-game 26 | - ./bin/run-standalone-test-v4.sh 27 | -------------------------------------------------------------------------------- /CHANGELOG: -------------------------------------------------------------------------------- 1 | # nodeGame Changelog 2 | 3 | # 7.1.0 4 | - New release, updated installer. 5 | 6 | # 7.0.4 7 | - Updated installer. 8 | - Minor fixes. 9 | 10 | # 7.0.3 11 | - Minor, installation fixes. 12 | 13 | # 7.0.0 14 | - Dropped --phantoms option in launcher. 15 | - More robust paths in launcher. 16 | - Added nodeGameRoot path in launcher. 17 | - Installer adapted to support alpha releases. 18 | 19 | # 6.3.0 20 | - Fixed installer getting stuck on versions and help. 21 | - Added installer option --no-games to skip installing default games. 22 | - New release. 23 | 24 | # 6.2.4 (6.2.1-6.2.3 deprecated) 25 | - Fixed "default" option in launcher for Commander v7. 26 | - New release, fixed support for images loaded in mainframe. 27 | 28 | # 6.2.0 29 | - Removed debugger from launcher.js. 30 | - Updated server with more options for WaitingRoom. 31 | 32 | # 6.1.1 33 | - Built widgets. 34 | 35 | # 6.1.0 36 | - Fixed launcher for Commander v7. 37 | - Updated server,client,window,widgets. 38 | 39 | # 6.0.3 40 | - Fixed corrupted build in 6.0.2 (thanks jjensenius3). 41 | 42 | # 6.0.2 43 | - Fixed bug create-game missing private folder in stable version (thanks 44 | jjensenius3). 45 | 46 | # 6.0.1 47 | - Updated server. 48 | 49 | # 6.0.0 50 | - Option --port to specify the port of the server in launcher. 51 | 52 | # 5.11.2 53 | - Fixing version numbers. 54 | 55 | # 5.11.0 56 | - Small update to client and bug fixes. 57 | 58 | # 5.10.1 59 | - Now really updated installer, as claimed in 5.10.0 60 | 61 | # 5.10.0 62 | - New release, updated installer. 63 | 64 | # 5.9.0 65 | - New release, updated installer. 66 | 67 | # 5.8.1 68 | - New release, updated installer. 69 | 70 | # 5.8.0 71 | - Game.stepBack. 72 | 73 | # 5.7.0 74 | - GameRoom.computeBonus handles disconnected players in dump file. 75 | 76 | # 5.6.0-5 77 | - New release, updated installer. 78 | 79 | # 5.4.0 80 | - New release, updated server, widgets, window. 81 | 82 | :# 5.3.1 83 | - Minor fixes to installer. 84 | 85 | # 5.3.0 86 | - Improved servernode.js conf file. 87 | - Improved installer: --dry option. 88 | - Improved installer: better handling of parent node_modules folders. 89 | 90 | # 5.1.0 91 | - Minor update to installer. 92 | - Widgets: CustomInput, and garbage collection. 93 | - Window and Client: check frame height automatically. 94 | 95 | # 5.0.1 96 | - Minor update to installer. 97 | - Fixed VisualTimer.restart bug introduced in v5. 98 | - Server does not scan hidden folders inside the games directory. 99 | - Generator does not allow to create games starting with a dot. 100 | 101 | # 5.0.0 102 | - Updated installer, now installing latest versions of v3, v4, v5. 103 | - Updated installer, checks for node_modules folder above the current folder. 104 | - Updated package.json with stricter version numbers. 105 | 106 | # 4.3.3 107 | - Updated package.json to fix the version numbers of v4 108 | 109 | # 4.3.2 110 | - Re-enabled support for games without treatment description (bug introduced 111 | in 4.3.0) 112 | - Installer checks better for -v and -h options. 113 | 114 | # 4.3.0 115 | - Treatment selection in waiting room. If ALLOW_SELECT_TREATMENT is true in 116 | waitroom.settings.js then a small dropdown menu allows user to select the 117 | treatment for the game. 118 | - Small fixes. 119 | 120 | # 4.2.1 (current, not npm) 121 | - Fixed building client. 122 | 123 | # 4.2.0 124 | - Improved create-game command. 125 | - Cleanup 126 | - Small fixes. 127 | 128 | # 4.1.5 129 | - Fixed installer on Node < 8.x 130 | 131 | # 4.1.3 132 | - Improved installer 133 | - Msg anti-spoofing support 134 | - Fixed bug on Chrome with flickering scrollbar 135 | - More options on Monitor, including display of last error 136 | - Improved nodegame-mturk support 137 | - Fixed tests 138 | - Smaller fixes 139 | 140 | # 4.0.4 141 | - Improved monitor error logging. 142 | - Updated installer version. 143 | 144 | # 4.0.2 145 | - Big release, check CHANGELOG on website. 146 | 147 | # 3.5 148 | - Printing version on startup (launcher). 149 | 150 | # 3.2 151 | - Updated client and server. 152 | - Updated install script. 153 | 154 | # 3.0.0 155 | - 02/10/2016 NodeGame Version Upgrade. 156 | 157 | # 2.1.0 158 | - Fixed launcher. 159 | 160 | # 2.0.2 161 | - Fixed install.stable script. 162 | - Fixing launcher options. 163 | 164 | # 2.0.0 (current) 165 | - Added -s option to launcher. Starts the server in SSL mode. Can be empty (loads nodegame-server/ssl/), or a path to a SSL directory. 166 | - Added -b option to launcher. Builds specified components before starting the server. Available options: JSUS, window, widgets, client, all. 167 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | (The MIT License) 2 | 3 | Copyright (c) 2015 Stefano Balietti 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining 6 | a copy of this software and associated documentation files (the 7 | 'Software'), to deal in the Software without restriction, including 8 | without limitation the rights to use, copy, modify, merge, publish, 9 | distribute, sublicense, and/or sell copies of the Software, and to 10 | permit persons to whom the Software is furnished to do so, subject to 11 | the following conditions: 12 | 13 | The above copyright notice and this permission notice shall be 14 | included in all copies or substantial portions of the Software. 15 | 16 | THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, 17 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 18 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 19 | IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 20 | CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 21 | TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 22 | SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 23 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # nodeGame 2 | 3 | Fast, scalable JavaScript for large-scale, online, multiplayer, real-time games 4 | and experiments. 5 | 6 | --- 7 | 8 | ## The Good parts 9 | 10 | - Open source and open standard (HTML5) 11 | - Modular framework (server / client / window / widgets / games) 12 | - Low / medium level of programming required 13 | - Powerful API 14 | - Integrated 15 | [NDDB](http://nodegame.github.com/NDDB/docs/nddb.js.html) 16 | Javascript database 17 | - Server can run multiple games at the same time 18 | - Powerful and customizible waiting rooms 19 | - Monitor interface 20 | - Works on mobile devices and tablets 21 | - Bots (for playing) and Phantoms (for testing) 22 | - Installation is required only for the server, clients just need their browser windows 23 | - Integrates smoothly with other libraries (e.g. jQuery, D3.js, etc.) 24 | and web services, such as Amazon Mechanical Turk 25 | 26 | ## Quick Start 27 | 28 | nodeGame comes with a default game taken from the academic literature 29 | of game theory. It is called the 30 | [Ultimatum](http://en.wikipedia.org/wiki/Ultimatum_game) game. To play 31 | it follows the steps: 32 | 33 | 34 | 1. Download the latest version of [node.js](http://nodejs.org) for 35 | your platform 36 | 2. Download the latest version of [git](http://www.git-scm.com) for 37 | your platform 38 | 3. Download [installer](http://nodegame.org/nodegame-installer.js), and install nodegame: `node nodegame-installer` 39 | 4. Enter installation directory. 40 | 5. Start the server with the command: `node launcher.js` 41 | 6. Open one tab pointing to `localhost:8080` 42 | 7. Select Ultimatum game 43 | 8. Open more tabs, or start a bot through the waiting room interface 44 | 7. Check the monitor interface at 45 | `localhost:8080/ultimatum/monitor` 46 | 47 | ## Documentation 48 | 49 | Complete documentation is available in the nodeGame 50 | [wiki](https://github.com/nodeGame/nodegame/wiki). 51 | 52 | ## License 53 | 54 | [MIT](LICENSE) 55 | -------------------------------------------------------------------------------- /bin/legacy/build.sh: -------------------------------------------------------------------------------- 1 | #! /bin/bash 2 | # nodegame/bin 3 | 4 | # nodegame/node_modules/nodegame-window 5 | cd ../node_modules/nodegame-window 6 | node bin/make build -a 7 | 8 | # nodegame/node_modules/nodegame-widgets 9 | cd ../nodegame-widgets 10 | node bin/make build -a 11 | 12 | # nodegame/node_modules/nodegame-server 13 | cd ../nodegame-server 14 | node bin/make build-css 15 | node bin/make build-client -a -o nodegame-full 16 | 17 | # nodegame 18 | cd ../.. 19 | node $1 launcher.js 20 | -------------------------------------------------------------------------------- /bin/legacy/install-nodegame-for-module-node5.beta.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # nodeGame install development version from sources script 3 | # Copyright(c) 2015 Stefano Balietti 4 | # MIT Licensed 5 | 6 | 7 | # List of all sub-modules on GitHub to clone. 8 | # The order is important because of dependencies (see installation 9 | # of modules below). 10 | gitmodules="nodegame-window nodegame-widgets JSUS NDDB shelf.js "\ 11 | "nodegame-client nodegame-server descil-mturk nodegame-db nodegame-mongodb "\ 12 | "nodegame-requirements nodegame-monitor" 13 | npmmodules="smoosh ya-csv commander docker" 14 | 15 | # Usage information. 16 | read -r -d '' usage_info <] [-n ] 18 | Defaults: 19 | git-modules: "$gitmodules" 20 | npm-modules: "$npmmodules" 21 | It is recommended to give the git-modules in the same order as defined 22 | in this script. 23 | EOT 24 | 25 | 26 | # Parse arguments. 27 | while getopts "h?g:n:" arg 28 | do case $arg in 29 | g) gitmodules=$OPTARG 30 | ;; 31 | n) npmmodules=$OPTARG 32 | ;; 33 | *) echo "$usage_info" 34 | exit 35 | ;; 36 | esac 37 | done 38 | 39 | 40 | # Check node.js version, must be higher than 0.8. 41 | node_version=$(node --version) # e.g. "v0.10.20" 42 | node_version=${node_version#v} # e.g. "0.10.20" 43 | node_major=$(cut -d. -f1 <<< $node_version) 44 | node_minor=$(cut -d. -f2 <<< $node_version) 45 | if (( node_major <= 0 && node_minor < 10 )) 46 | then 47 | echo "Found node.js version $node_version, but at least 0.10 required." 48 | exit 1 49 | fi 50 | 51 | 52 | # Add symbolic links to given dependencies that are in nodegame/node_modules 53 | # (e.g. JSUS, NDDB). 54 | link_deps() { 55 | mkdir -p node_modules 56 | ( 57 | cd node_modules 58 | for dep in "$@" 59 | do ln -s "../../$dep" . 60 | done 61 | ) 62 | } 63 | 64 | 65 | # Return on failure immediately. 66 | set -e 67 | 68 | # Clone the nodegame repo and enter its directory. 69 | if [ ! -d nodegame ] 70 | then 71 | git clone https://github.com/nodeGame/nodegame.git 72 | cd nodegame 73 | else 74 | # If the nodegame directory already exists and is not empty, git will 75 | # refuse to clone into it. 76 | # Instead, it has to be set up manually. 77 | # http://stackoverflow.com/a/18999726/3347292 78 | cd nodegame 79 | git init 80 | git remote add origin https://github.com/nodeGame/nodegame.git 81 | git fetch 82 | git checkout -t origin/master 83 | fi 84 | 85 | # Install the dependencies. 86 | mkdir -p node_modules 87 | 88 | # NPM dependencies. 89 | for module in $npmmodules 90 | do npm install "$module" 91 | done 92 | 93 | # GitHub dependencies. 94 | cd node_modules 95 | for module in $gitmodules 96 | do git clone "https://github.com/nodeGame/${module}.git" 97 | # Get sub-dependencies, link to tracked dependencies. 98 | cd "$module" 99 | case $module in 100 | JSUS|nodegame-mongodb) 101 | npm install 102 | ;; 103 | descil-mturk) 104 | link_deps JSUS NDDB 105 | npm install 106 | ;; 107 | nodegame-client) 108 | link_deps JSUS NDDB shelf.js 109 | npm install 110 | ;; 111 | nodegame-server) 112 | link_deps JSUS NDDB shelf.js nodegame-widgets 113 | npm install 114 | # Patch express connect. (not needed in express 4). 115 | # patch \ 116 | # node_modules/express/node_modules/connect/lib/middleware/static.js < \ 117 | # bin/ng.connect.static.js.patch 118 | # Rebuild js files. 119 | node bin/make.js build-client -a -o nodegame-full 120 | ;; 121 | esac 122 | cd .. 123 | done 124 | 125 | # Link installed modules into parent directory. 126 | cd .. 127 | mkdir -p ../node_modules 128 | for dir in node_modules/* 129 | do ln -s ../nodegame/$dir ../node_modules/ 130 | done 131 | 132 | echo "Installation of nodeGame for module completed." 133 | -------------------------------------------------------------------------------- /bin/legacy/install-nodegame-for-module.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # nodeGame install development version from sources script 3 | # Copyright(c) 2015 Stefano Balietti 4 | # MIT Licensed 5 | 6 | 7 | # List of all sub-modules on GitHub to clone. 8 | # The order is important because of dependencies (see installation 9 | # of modules below). 10 | gitmodules="nodegame-window nodegame-widgets JSUS NDDB shelf.js "\ 11 | "nodegame-client nodegame-server descil-mturk nodegame-db nodegame-mongodb "\ 12 | "nodegame-requirements nodegame-monitor nodegame-game-template" 13 | 14 | # Usage information. 15 | read -r -d '' usage_info <] [-n ] 17 | Defaults: 18 | git-modules: "$gitmodules" 19 | npm-modules: "$npmmodules" 20 | It is recommended to give the git-modules in the same order as defined 21 | in this script. 22 | EOT 23 | 24 | 25 | # Parse arguments. 26 | while getopts "h?g:n:" arg 27 | do case $arg in 28 | g) gitmodules=$OPTARG 29 | ;; 30 | n) npmmodules=$OPTARG 31 | ;; 32 | *) echo "$usage_info" 33 | exit 34 | ;; 35 | esac 36 | done 37 | 38 | 39 | # Check node.js version, must be higher than 0.8. 40 | node_version=$(node --version) # e.g. "v0.10.20" 41 | node_version=${node_version#v} # e.g. "0.10.20" 42 | node_major=$(cut -d. -f1 <<< $node_version) 43 | node_minor=$(cut -d. -f2 <<< $node_version) 44 | if (( node_major <= 0 && node_minor < 10 )) 45 | then 46 | echo "Found node.js version $node_version, but at least 0.10 required." 47 | exit 1 48 | fi 49 | 50 | 51 | # Add symbolic links to given dependencies that are in nodegame/node_modules 52 | # (e.g. JSUS, NDDB). 53 | link_deps() { 54 | mkdir -p node_modules 55 | ( 56 | cd node_modules 57 | for dep in "$@" 58 | do ln -s "../../$dep" . 59 | done 60 | ) 61 | } 62 | 63 | 64 | # Return on failure immediately. 65 | set -e 66 | 67 | # Clone the nodegame repo and enter its directory. 68 | if [ ! -d nodegame ] 69 | then 70 | git clone https://github.com/nodeGame/nodegame.git 71 | cd nodegame 72 | else 73 | # If the nodegame directory already exists and is not empty, git will 74 | # refuse to clone into it. 75 | # Instead, it has to be set up manually. 76 | # http://stackoverflow.com/a/18999726/3347292 77 | cd nodegame 78 | git init 79 | git remote add origin https://github.com/nodeGame/nodegame.git 80 | git fetch 81 | git checkout -t origin/master 82 | fi 83 | 84 | # Install the dependencies. 85 | 86 | # NPM dependencies. 87 | npm install 88 | 89 | # GitHub dependencies. 90 | cd node_modules 91 | for module in $gitmodules 92 | do git clone "https://github.com/nodeGame/${module}.git" 93 | # Get sub-dependencies, link to tracked dependencies. 94 | cd "$module" 95 | case $module in 96 | JSUS|nodegame-mongodb) 97 | npm install 98 | ;; 99 | descil-mturk) 100 | link_deps JSUS NDDB 101 | npm install 102 | ;; 103 | nodegame-client) 104 | link_deps JSUS NDDB shelf.js 105 | npm install 106 | ;; 107 | nodegame-server) 108 | link_deps JSUS NDDB shelf.js 109 | npm install 110 | # Patch express connect. (not needed in express 4). 111 | # patch \ 112 | # node_modules/express/node_modules/connect/lib/middleware/static.js < \ 113 | # bin/ng.connect.static.js.patch 114 | # Rebuild js files. 115 | node bin/make.js build-client -a -o nodegame-full 116 | ;; 117 | esac 118 | cd .. 119 | done 120 | 121 | echo "Installation of nodeGame for module completed." 122 | -------------------------------------------------------------------------------- /bin/legacy/install.dev.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # nodeGame install development version from sources script 3 | # Copyright(c) 2015 Stefano Balietti 4 | # MIT Licensed 5 | 6 | # Default command paths. 7 | node_path=node 8 | npm_path=npm 9 | 10 | print_usage() { 11 | echo "Usage: install.dev.sh [--node-path=...] [--npm-path=...]" 12 | echo -n " The path options select the location " 13 | echo "of the respective executables." 14 | } 15 | 16 | # Check options. 17 | getopt_tmp=`getopt -o h --long help,node-path:,npm-path: -- "$@"` 18 | if [ $? -ne 0 ] 19 | then 20 | echo 21 | print_usage 22 | exit 1 23 | fi 24 | 25 | eval set -- "$getopt_tmp" 26 | while true ; do 27 | case "$1" in 28 | -h|--help) 29 | print_usage 30 | exit 0 31 | shift ;; 32 | --node-path) 33 | node_path="$2" 34 | shift 2 ;; 35 | --npm-path) 36 | npm_path="$2" 37 | shift 2 ;; 38 | --) shift ; break ;; 39 | *) echo "Error parsing options!" ; exit 1 ;; 40 | esac 41 | done 42 | 43 | # Check existence of executables. 44 | command -v $node_path > /dev/null || { 45 | echo "Invalid node path at '$node_path'." 46 | echo 47 | print_usage 48 | exit 1 49 | } 50 | command -v $npm_path > /dev/null || { 51 | echo "Invalid npm path at '$npm_path'." 52 | echo 53 | print_usage 54 | exit 1 55 | } 56 | 57 | # Check node.js version, must be at least 0.10. 58 | node_version=$($node_path --version) # e.g. "v0.10.20" 59 | node_version=${node_version#v} # e.g. "0.10.20" 60 | node_major=$(cut -d. -f1 <<< $node_version) 61 | node_minor=$(cut -d. -f2 <<< $node_version) 62 | if (( node_major <= 0 && node_minor < 10 )) 63 | then 64 | echo "Found node.js version $node_version, but at least 0.10 required." 65 | exit 1 66 | fi 67 | 68 | # Check npm version, must be at least 1.3. 69 | npm_version=$($npm_path --version) 70 | npm_major=$(cut -d. -f1 <<< $npm_version) 71 | npm_minor=$(cut -d. -f2 <<< $npm_version) 72 | if (( npm_major < 1 || npm_major == 1 && npm_minor < 3 )) 73 | then 74 | echo "npm version >= 1.3 required." 75 | echo 76 | print_usage 77 | exit 1 78 | fi 79 | 80 | 81 | # Add symbolic links to given dependencies that are in nodegame/node_modules 82 | # (e.g. JSUS, NDDB). 83 | link_deps() { 84 | mkdir -p node_modules 85 | ( 86 | cd node_modules 87 | for dep in "$@" 88 | do ln -s "../../$dep" . 89 | done 90 | ) 91 | } 92 | 93 | 94 | # List of all sub-modules on GitHub to clone. 95 | gitmodules="nodegame-client nodegame-server nodegame-window nodegame-widgets "\ 96 | "nodegame-requirements nodegame-monitor JSUS NDDB shelf.js descil-mturk "\ 97 | "nodegame-db nodegame-mongodb nodegame-generator" 98 | 99 | # Return on failure immediately. 100 | set -e 101 | 102 | # Clone the repo, copy Git hooks. 103 | git clone git@github.com:nodeGame/nodegame.git 104 | cd nodegame 105 | cp git-hooks/* .git/hooks/ 106 | 107 | # Install the dependencies. 108 | $npm_path install smoosh 109 | $npm_path install ya-csv 110 | $npm_path install commander 111 | $npm_path install docker 112 | mkdir -p node_modules 113 | cd node_modules 114 | for module in $gitmodules 115 | do git clone "git@github.com:nodeGame/${module}.git" 116 | done 117 | 118 | # Install sub-dependencies, link to tracked dependencies. 119 | ( 120 | cd JSUS 121 | $npm_path install 122 | ) 123 | 124 | ( 125 | cd descil-mturk 126 | link_deps JSUS NDDB 127 | $npm_path install 128 | ) 129 | 130 | ( 131 | cd nodegame-mongodb 132 | $npm_path install 133 | ) 134 | 135 | ( 136 | cd nodegame-client 137 | link_deps JSUS NDDB shelf.js 138 | $npm_path install 139 | ) 140 | 141 | ( 142 | cd nodegame-generator 143 | link_deps JSUS 144 | $npm_path install 145 | # Link to executable from nodegame/bin. 146 | ln -s ../node_modules/nodegame-generator/bin/nodegame ../../bin/ 147 | ) 148 | 149 | ( 150 | cd nodegame-server 151 | link_deps JSUS NDDB shelf.js nodegame-widgets 152 | $npm_path install 153 | 154 | # Patch express connect. (not needed in express 4). 155 | # patch node_modules/express/node_modules/connect/lib/middleware/static.js < \ 156 | # bin/ng.connect.static.js.patch 157 | 158 | # Rebuild js files. 159 | $node_path bin/make.js build-client -a -o nodegame-full 160 | ) 161 | 162 | # Copy Git hooks. 163 | for module in $gitmodules 164 | do cp ../git-hooks/* "${module}/.git/hooks/" 165 | done 166 | 167 | # Install ultimatum game under nodegame/games. 168 | cd .. 169 | git clone git@github.com:nodeGame/ultimatum games/ultimatum 170 | cp git-hooks/* games/ultimatum/.git/hooks/ 171 | cd games/ultimatum 172 | $npm_path install 173 | cd ../.. 174 | 175 | 176 | # Execute the following commands to try out the ultimatum game. 177 | 178 | # Start the server: 179 | # node launcher 180 | 181 | # Open two browser tabs for two players at the address: 182 | # http://localhost:8080/ultimatum/ 183 | # Open the admin interface at: 184 | # http://localhost:8080/ultimatum/monitor/ 185 | # See the wiki documentation to modify settings. 186 | -------------------------------------------------------------------------------- /bin/legacy/install.latest.cmd: -------------------------------------------------------------------------------- 1 | :: nodeGame install from sources script for Windows 2 | :: Copyright(c) 2016 Stefano Balietti 3 | :: MIT Licensed 4 | 5 | :: Enable local extensions (more similar to Bash). 6 | setlocal enableextensions enabledelayedexpansion 7 | 8 | :: Clone the main repo. 9 | git clone https://github.com/nodeGame/nodegame.git || exit /b 10 | 11 | cd nodegame || exit /b 12 | 13 | :: Install the dependencies. 14 | 15 | :: The most recent nodejs installer has a bug, this line fixes it. 16 | :: Solution taken from http://stackoverflow.com/q/25093276 17 | if not exist "%APPDATA%\npm" mkdir "%APPDATA%\npm" || exit /b 18 | 19 | :: Install non-nodeGame dependencies. 20 | call npm install || exit /b 21 | 22 | :: Fetch nodeGame modules. 23 | 24 | cd node_modules || exit /b 25 | git clone https://github.com/nodeGame/nodegame-client.git || exit /b 26 | git clone https://github.com/nodeGame/nodegame-server.git || exit /b 27 | git clone https://github.com/nodeGame/nodegame-window.git || exit /b 28 | git clone https://github.com/nodeGame/nodegame-widgets.git || exit /b 29 | git clone https://github.com/nodeGame/nodegame-game-template.git || exit /b 30 | git clone https://github.com/nodeGame/nodegame-requirements.git || exit /b 31 | git clone https://github.com/nodeGame/nodegame-monitor.git || exit /b 32 | git clone https://github.com/nodeGame/JSUS.git || exit /b 33 | git clone https://github.com/nodeGame/NDDB.git || exit /b 34 | git clone https://github.com/nodeGame/shelf.js.git || exit /b 35 | git clone https://github.com/nodeGame/descil-mturk.git || exit /b 36 | git clone https://github.com/nodeGame/nodegame-db.git || exit /b 37 | git clone https://github.com/nodeGame/nodegame-mongodb.git || exit /b 38 | 39 | :: Install sub-dependencies; link to tracked dependencies. 40 | 41 | cd JSUS || exit /b 42 | call npm install || exit /b 43 | 44 | cd ../descil-mturk || exit /b 45 | call:linkDeps JSUS NDDB || exit /b 46 | call npm install || exit /b 47 | 48 | cd ../nodegame-mongodb || exit /b 49 | call npm install || exit /b 50 | 51 | cd ../nodegame-client || exit /b 52 | call:linkDeps JSUS NDDB shelf.js || exit /b 53 | call npm install || exit /b 54 | 55 | cd ../nodegame-server || exit /b 56 | call:linkDeps JSUS NDDB shelf.js nodegame-widgets nodegame-monitor || exit /b 57 | call npm install || exit /b 58 | 59 | :: Patching express connect (copy + rename). (not needed in express 4). 60 | :: xcopy /Y bin\static.js node_modules\express\node_modules\connect\lib\middleware\static.js || exit /b 61 | 62 | :: Rebuild js files. 63 | cd bin || exit /b 64 | node make build-client -a -o nodegame-full || exit /b 65 | 66 | :: Install ultimatum game. 67 | cd ../../../ || exit /b 68 | 69 | git clone https://github.com/nodeGame/ultimatum.git games/ultimatum || exit /b 70 | 71 | cd games/ultimatum || exit /b 72 | call:linkDeps fs-extra || exit /b 73 | 74 | :: Execute the following commands to try out the ultimatum game. 75 | 76 | :: Start the server. 77 | :: node launcher 78 | 79 | :: Open two browser tabs for two players at the address: 80 | :: http://localhost:8080/ultimatum/ 81 | :: Open the admin console at: 82 | :: http://localhost:8080/ultimatum/monitor/ 83 | :: See the wiki documentation to modify settings. 84 | 85 | exit /b 86 | :: End of script. Following labels used for calls only. 87 | 88 | :: Add symbolic links to given dependencies that are in nodegame/node_modules 89 | :: (e.g. JSUS, NDDB) 90 | :linkDeps 91 | mkdir node_modules || exit /b 92 | cd node_modules || exit /b 93 | 94 | :linkDepsHelper 95 | mklink /J "./%1" "../../%1" || exit /b 96 | shift 97 | if not [%1]==[] GOTO:linkDepsHelper 98 | cd ../ || exit /b 99 | GOTO:EOF 100 | -------------------------------------------------------------------------------- /bin/legacy/install.latest.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # nodeGame install from sources script 3 | # Copyright(c) 2016 Stefano Balietti 4 | # MIT Licensed 5 | 6 | # Current dir. 7 | # install_dir=${PWD##*/} # was. 8 | install_dir=${PWD} 9 | 10 | # Assumes to be executed inside the node_modules dir. 11 | create_generator_conf() { 12 | echo 13 | echo "Saving nodegame-generator configuration" 14 | echo -e "{ 15 | \"author\": \"\", 16 | \"email\": \"\", 17 | \"gamesFolder\": \"$install_dir/nodegame/games/\" 18 | }" > nodegame-generator/conf/generator.conf.json 19 | } 20 | 21 | # Default command paths. 22 | node_path=node 23 | npm_path=npm 24 | 25 | print_usage() { 26 | echo "Usage: install.latest.sh [--node-path=...] [--npm-path=...]" 27 | echo -n " The path options select the location " 28 | echo "of the respective executables." 29 | } 30 | 31 | # Check options. 32 | getopt_tmp=`getopt -o h --long help,node-path:,npm-path: -- "$@"` 33 | if [ $? -ne 0 ] 34 | then 35 | echo 36 | print_usage 37 | exit 1 38 | fi 39 | 40 | eval set -- "$getopt_tmp" 41 | while true ; do 42 | case "$1" in 43 | -h|--help) 44 | print_usage 45 | exit 0 46 | shift ;; 47 | --node-path) 48 | node_path="$2" 49 | shift 2 ;; 50 | --npm-path) 51 | npm_path="$2" 52 | shift 2 ;; 53 | --) shift ; break ;; 54 | *) echo "Error parsing options!" ; exit 1 ;; 55 | esac 56 | done 57 | 58 | # Check existence of executables. 59 | command -v $node_path > /dev/null || { 60 | node_path=nodejs 61 | command -v $node_path > /dev/null 62 | } || { 63 | echo "Invalid node path at '$node_path'." 64 | echo 65 | print_usage 66 | exit 1 67 | } 68 | command -v $npm_path > /dev/null || { 69 | echo "Invalid npm path at '$npm_path'." 70 | echo 71 | print_usage 72 | exit 1 73 | } 74 | 75 | # Check node.js version, must be at least 0.10. 76 | node_version=$($node_path --version) # e.g. "v0.10.20" 77 | node_version=${node_version#v} # e.g. "0.10.20" 78 | node_major=$(cut -d. -f1 <<< $node_version) 79 | node_minor=$(cut -d. -f2 <<< $node_version) 80 | if (( node_major <= 0 && node_minor < 10 )) 81 | then 82 | echo "node.js version >= 0.10 required." 83 | echo 84 | print_usage 85 | exit 1 86 | fi 87 | 88 | # Check npm version, must be at least 1.3. 89 | npm_version=$($npm_path --version) 90 | npm_major=$(cut -d. -f1 <<< $npm_version) 91 | npm_minor=$(cut -d. -f2 <<< $npm_version) 92 | if (( npm_major < 1 || npm_major == 1 && npm_minor < 3 )) 93 | then 94 | echo "npm version >= 1.3 required." 95 | echo 96 | print_usage 97 | exit 1 98 | fi 99 | 100 | # Return on failure immediately. 101 | set -e 102 | 103 | # Clone the main repo. 104 | git clone https://github.com/nodeGame/nodegame.git 105 | cd nodegame 106 | 107 | # Install npm dependencies. 108 | $npm_path install 109 | # Install git dependencies. 110 | cd node_modules 111 | git clone https://github.com/nodeGame/nodegame-client.git 112 | git clone https://github.com/nodeGame/nodegame-server.git 113 | git clone https://github.com/nodeGame/nodegame-window.git 114 | git clone https://github.com/nodeGame/nodegame-widgets.git 115 | git clone https://github.com/nodeGame/nodegame-requirements.git 116 | git clone https://github.com/nodeGame/nodegame-game-template.git 117 | git clone https://github.com/nodeGame/nodegame-monitor.git 118 | git clone https://github.com/nodeGame/JSUS.git 119 | git clone https://github.com/nodeGame/NDDB.git 120 | git clone https://github.com/nodeGame/shelf.js.git 121 | git clone https://github.com/nodeGame/descil-mturk.git 122 | git clone https://github.com/nodeGame/nodegame-db.git 123 | git clone https://github.com/nodeGame/nodegame-mongodb.git 124 | git clone https://github.com/nodeGame/nodegame-generator.git 125 | 126 | # Create conf script in nodegame-generator. 127 | create_generator_conf 128 | 129 | # Add symbolic links to given dependencies that are in nodegame/node_modules 130 | # (e.g. JSUS, NDDB). 131 | function link_deps { 132 | mkdir -p node_modules 133 | ( 134 | cd node_modules 135 | for dep in "$@" 136 | do ln -s "../../$dep" . 137 | done 138 | ) 139 | } 140 | 141 | # Install sub-dependencies, link to tracked dependencies. 142 | cd JSUS 143 | $npm_path install 144 | 145 | cd ../descil-mturk 146 | link_deps JSUS NDDB 147 | $npm_path install 148 | 149 | cd ../nodegame-mongodb 150 | $npm_path install 151 | 152 | cd ../nodegame-client 153 | link_deps JSUS NDDB shelf.js 154 | $npm_path install 155 | # Link to executable from nodegame/bin. 156 | ln -s ../node_modules/nodegame-generator/bin/nodegame ../../bin/ 157 | 158 | cd ../nodegame-generator 159 | link_deps JSUS 160 | $npm_path install 161 | 162 | cd ../nodegame-server 163 | link_deps JSUS NDDB shelf.js nodegame-widgets nodegame-monitor 164 | $npm_path install 165 | 166 | # Patching express connect. (not needed in express 4) 167 | # patch node_modules/express/node_modules/connect/lib/middleware/static.js < \ 168 | # bin/ng.connect.static.js.patch 169 | 170 | # Rebuild js files. 171 | cd bin 172 | $node_path make build-client -a -o nodegame-full 173 | 174 | # Install ultimatum game. 175 | cd ../../.. 176 | git clone https://github.com/nodeGame/ultimatum games/ultimatum 177 | cd games/ultimatum 178 | link_deps fs-extra 179 | 180 | 181 | # Execute the following commands to try out the ultimatum game. 182 | 183 | # Start the server: 184 | # node launcher 185 | 186 | # Open two browser tabs for two players at the address: 187 | # http://localhost:8080/ultimatum/ 188 | # Open the admin interface at: 189 | # http://localhost:8080/ultimatum/monitor/ 190 | # See the wiki documentation to modify settings. 191 | -------------------------------------------------------------------------------- /bin/legacy/install.stable.cmd: -------------------------------------------------------------------------------- 1 | :: nodeGame install from npm script for Windows 2 | :: Copyright(c) 2015 Stefano Balietti 3 | :: MIT Licensed 4 | 5 | :: Enable local extensions (more similar to Bash). 6 | setlocal enableextensions enabledelayedexpansion 7 | 8 | 9 | :: The most recent nodejs installer has a bug, this line fixes it. 10 | :: Solution taken from http://stackoverflow.com/q/25093276 11 | if not exist "%APPDATA%\npm" mkdir "%APPDATA%\npm" || exit /b 12 | 13 | :: Get the stable repo. 14 | call npm install nodegame || exit /b 15 | move node_modules/nodegame . || exit /b 16 | rmdir node_modules || exit /b 17 | 18 | cd nodegame || exit /b 19 | 20 | :: Install the dependencies. 21 | call npm install nodegame-client || exit /b 22 | call npm install nodegame-server || exit /b 23 | call npm install nodegame-window || exit /b 24 | call npm install nodegame-widgets || exit /b 25 | call npm install JSUS || exit /b 26 | call npm install NDDB || exit /b 27 | call npm install shelf.js || exit /b 28 | call npm install descil-mturk || exit /b 29 | call npm install nodegame-db || exit /b 30 | call npm install nodegame-mongodb || exit /b 31 | call npm install nodegame-generator || exit /b 32 | call npm install nodegame-requirements || exit /b 33 | call npm install nodegame-monitor || exit /b 34 | call npm install nodegame-game-template || exit /b 35 | call npm install smoosh || exit /b 36 | call npm install ya-csv || exit /b 37 | call npm install commander || exit /b 38 | call npm install ultimatum-game || exit /b 39 | :: docker not installed 40 | 41 | 42 | :: Entering nodegame-server directory 43 | cd node_modules/nodegame-server/ || exit /b 44 | 45 | :: Patching express connect. (not needed in new version). 46 | :: xcopy /Y bin\static.js node_modules\express\node_modules\connect\lib\middleware\static.js || exit /b 47 | 48 | :: Rebuild js files. 49 | cd bin/ || exit /b 50 | node make build-client -a -o nodegame-full || exit /b 51 | 52 | :: Install ultimatum game. 53 | cd ../../../ || exit /b 54 | move node_modules/ultimatum-game games/ultimatum || exit /b 55 | 56 | 57 | :: Execute the following commands to try out the ultimatum game. 58 | 59 | :: Start the ultimatum game. 60 | :: node start/ultimatum-server 61 | 62 | :: Open two browser tabs for two players at the address: 63 | :: http://localhost:8080/ultimatum/ 64 | :: Open the admin console at: 65 | :: http://localhost:8080/ultimatum/monitor.htm 66 | :: See the wiki documentation to modify settings. 67 | 68 | exit /b 69 | :: End of script. 70 | -------------------------------------------------------------------------------- /bin/legacy/install.stable.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # nodeGame install from sources script 3 | # Copyright(c) 2016 Stefano Balietti 4 | # MIT Licensed 5 | 6 | # Current dir. 7 | #install_dir=${PWD##*/} # was. 8 | install_dir=${PWD} 9 | 10 | # Assumes to be executed inside the node_modules dir. 11 | create_generator_conf() { 12 | echo 13 | echo "Saving nodegame-generator configuration" 14 | echo -e "{ 15 | \"author\": \"\", 16 | \"email\": \"\", 17 | \"gamesFolder\": \"$install_dir/nodegame/games/\" 18 | }" > nodegame-generator/conf/generator.conf.json 19 | } 20 | 21 | # Default command paths. 22 | node_path=node 23 | npm_path=npm 24 | 25 | print_usage() { 26 | echo "Usage: install.stable.sh [--node-path=...] [--npm-path=...]" 27 | echo -n " The path options select the location " 28 | echo "of the respective executables." 29 | } 30 | 31 | # Check options. 32 | getopt_tmp=`getopt -o h --long help,node-path:,npm-path: -- "$@"` 33 | if [ $? -ne 0 ] 34 | then 35 | echo 36 | print_usage 37 | exit 1 38 | fi 39 | 40 | eval set -- "$getopt_tmp" 41 | while true ; do 42 | case "$1" in 43 | -h|--help) 44 | print_usage 45 | exit 0 46 | shift ;; 47 | --node-path) 48 | node_path="$2" 49 | shift 2 ;; 50 | --npm-path) 51 | npm_path="$2" 52 | shift 2 ;; 53 | --) shift ; break ;; 54 | *) echo "Error parsing options!" ; exit 1 ;; 55 | esac 56 | done 57 | 58 | # Check existence of executables. 59 | command -v $node_path > /dev/null || { 60 | node_path=nodejs 61 | command -v $node_path > /dev/null 62 | } || { 63 | echo "Invalid node path at '$node_path'." 64 | echo 65 | print_usage 66 | exit 1 67 | } 68 | command -v $npm_path > /dev/null || { 69 | echo "Invalid npm path at '$npm_path'." 70 | echo 71 | print_usage 72 | exit 1 73 | } 74 | 75 | # Check node.js version, must be at least 0.10. 76 | node_version=$($node_path --version) # e.g. "v0.10.20" 77 | node_version=${node_version#v} # e.g. "0.10.20" 78 | node_major=$(cut -d. -f1 <<< $node_version) 79 | node_minor=$(cut -d. -f2 <<< $node_version) 80 | if (( node_major <= 0 && node_minor < 10 )) 81 | then 82 | echo "node.js version >= 0.10 required." 83 | exit 1 84 | fi 85 | 86 | # Check npm version, must be at least 1.3. 87 | npm_version=$($npm_path --version) 88 | npm_major=$(cut -d. -f1 <<< $npm_version) 89 | npm_minor=$(cut -d. -f2 <<< $npm_version) 90 | if (( npm_major < 1 || npm_major == 1 && npm_minor < 3 )) 91 | then 92 | echo "npm version >= 1.3 required." 93 | echo 94 | print_usage 95 | exit 1 96 | fi 97 | 98 | # Return on failure immediately. 99 | set -e 100 | 101 | # Install the main repo. 102 | npm install nodegame 103 | 104 | # Move nodegame modules outsite node_modules dir. 105 | mv node_modules/nodegame ./ 106 | rm -r node_modules 107 | 108 | cd nodegame 109 | 110 | # Install the dependencies. 111 | $npm_path install nodegame-client 112 | $npm_path install nodegame-server 113 | $npm_path install nodegame-window 114 | $npm_path install nodegame-widgets 115 | $npm_path install JSUS 116 | $npm_path install NDDB 117 | $npm_path install shelf.js 118 | $npm_path install descil-mturk 119 | $npm_path install nodegame-db 120 | $npm_path install nodegame-mongodb 121 | $npm_path install nodegame-generator 122 | $npm_path install nodegame-requirements 123 | $npm_path install nodegame-monitor 124 | $npm_path install nodegame-game-template 125 | $npm_path install ultimatum-game 126 | 127 | 128 | cd node_modules 129 | 130 | # Create conf script in nodegame-generator. 131 | create_generator_conf 132 | 133 | # Link to nodegame-generator executable. 134 | ln -s ../node_modules/nodegame-generator/bin/nodegame ../bin/ 135 | 136 | # Entering nodegame-server directory. 137 | cd nodegame-server 138 | 139 | # Patching express connect. 140 | # patch node_modules/express/node_modules/connect/lib/middleware/static.js < \ 141 | # bin/ng.connect.static.js.patch 142 | 143 | # Rebuild js files. 144 | cd bin 145 | $node_path make build-client -a -o nodegame-full 146 | 147 | # Install ultimatum game. 148 | cd ../../.. 149 | mv node_modules/ultimatum-game games/ultimatum 150 | 151 | 152 | # Execute the following commands to try out the ultimatum game. 153 | 154 | # Start the server: 155 | # node launcher 156 | 157 | # Open two browser tabs for two players at the address: 158 | # http://localhost:8080/ultimatum/ 159 | # Open the admin interface at: 160 | # http://localhost:8080/ultimatum/monitor/ 161 | # See the wiki documentation to modify settings. 162 | -------------------------------------------------------------------------------- /bin/legacy/pull-all.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # 3 | # Pull recent versions of all included Git repos. 4 | 5 | echo_and_pull() { 6 | echo -e "\n* Pulling $1 ..." 7 | git pull || echo ' FAILED!' 8 | } 9 | 10 | GAMES=(ultimatum-game) 11 | MODULES=(nodegame-client nodegame-server nodegame-window nodegame-widgets 12 | nodegame-requirements nodegame-game-template nodegame-monitor JSUS NDDB 13 | nodegame-generator nodegame-mturk) 14 | 15 | ## Removed modules for now. 16 | ## nodegame-db nodegame-mongodb 17 | 18 | # Change the current working directory to the parent directory of the script, 19 | # i.e. the nodegame directory. Using the below command instead of simply 20 | # "cd .." makes sure that it does not matter from where the script is executed 21 | # cd "$(dirname "${BASH_SOURCE[0]}")/.." 22 | 23 | ## Not yet, this fails, we just update the modules. 24 | ## echo_and_pull nodegame 25 | 26 | for GAME in "${GAMES[@]}"; do 27 | ( 28 | cd games/"${GAME}" 29 | echo_and_pull "${GAME}" 30 | ) 31 | done 32 | 33 | for MODULE in "${MODULES[@]}"; do 34 | ( 35 | cd node_modules/"${MODULE}" 36 | echo_and_pull "${MODULE}" 37 | ) 38 | done 39 | 40 | echo -e "\n* Done." 41 | -------------------------------------------------------------------------------- /bin/nodegame-cli-experimental.js: -------------------------------------------------------------------------------- 1 | #!/usr/local/bin/node 2 | /** 3 | * # nodeGame 4 | * Copyright(c) 2017 Stefano Balietti 5 | * MIT Licensed 6 | * 7 | * Commands for nodegame 8 | * 9 | * http://www.nodegame.org 10 | */ 11 | 12 | "use strict"; 13 | 14 | console.log('not ready yet!'); 15 | return; 16 | 17 | // Modules. 18 | const fs = require('fs-extra'); 19 | const path = require('path'); 20 | 21 | // Load commander. 22 | var program = require('commander'); 23 | 24 | const exec = require('child_process').exec; 25 | const execFile = require('child_process').execFile; 26 | const spawn = require('child_process').spawn; 27 | 28 | const J = require('JSUS').JSUS; 29 | 30 | 31 | // nodeGame version. 32 | var version = require('./package.json').version; 33 | 34 | const ROOT_DIR = __dirname + '/'; 35 | const NODE_MODULES_DIR = ROOT_DIR + 'node_modules/'; 36 | const NODEGAME_MODULES = [ 37 | 'nodegame-server', 'nodegame-client', 38 | 'nodegame-window', 'nodegame-widgets', 39 | 'nodegame-monitor', 'nodegame-game-template', 40 | 'nodegame-requirements', 'nodegame-generator', 41 | 'NDDB', 'JSUS' 42 | ]; 43 | const N_MODULES = NODEGAME_MODULES.length; 44 | 45 | const GAMES_AVAILABLE_DIR = ROOT_DIR + 'games_available/'; 46 | const GAMES_ENABLED_DIR = ROOT_DIR + 'games/'; 47 | 48 | 49 | // Helper methods; 50 | const getDirectories = srcPath => { 51 | return fs.readdirSync(srcPath) 52 | .filter(file => { 53 | return fs.statSync(path.join(srcPath, file)) 54 | .isDirectory(); 55 | }); 56 | }; 57 | 58 | const getLinks = srcPath => { 59 | return fs.readdirSync(srcPath) 60 | .filter(file => { 61 | debugger; 62 | return fs.lstatSync(path.join(srcPath, file)) 63 | .isSymbolicLink(); 64 | }); 65 | }; 66 | 67 | const logList = txt => { 68 | console.log(' - ' + txt); 69 | }; 70 | 71 | // START. 72 | 73 | program 74 | .version(version) 75 | 76 | program 77 | .command('checkout [branch]') 78 | .description('Checkouts desired branch on all nodegame modules') 79 | .option('-v, --verbose', 'More verbose output') 80 | .action(function(env, options) { 81 | let gitCheckout = function(repo, branch, verbose = false) { 82 | let mydir = NODE_MODULES_DIR + repo; 83 | let child = execFile( 84 | 'git', 85 | [ 'checkout', branch ], 86 | { cwd: mydir }, 87 | (error, stdout, stderr) => { 88 | if (error) { 89 | logList(repo + ' ' + stderr.trim()); 90 | } 91 | else if (verbose) { 92 | logList('module ' + repo + ': ' + 93 | stdout.trim()); 94 | } 95 | }); 96 | } 97 | for (let i=-1 ; ++i < N_MODULES ;) { 98 | let repo = NODEGAME_MODULES[i]; 99 | gitCheckout(repo, env, options.verbose); 100 | } 101 | }); 102 | 103 | program 104 | .command('list [options]') 105 | .description('Lists all nodegame modules|games|games_available') 106 | .action(function(env, options) { 107 | if (env === "modules") { 108 | console.log('NodeGame modules: '); 109 | for (let i=-1 ; ++i < N_MODULES ;) { 110 | logList(NODEGAME_MODULES[i]); 111 | } 112 | } 113 | else if (env === "games" || env === "games_available") { 114 | let dir = env === "games" ? 115 | GAMES_ENABLED_DIR : GAMES_AVAILABLE_DIR; 116 | let dirs = getDirectories(dir); 117 | dirs.sort(); 118 | for (let i = 0; i < dirs.length; i++) { 119 | logList(dirs[i]); 120 | } 121 | } 122 | else { 123 | console.error(`valid options: 124 | modules|games|games_available`); 125 | } 126 | }); 127 | 128 | 129 | program 130 | .command('enable [game]') 131 | .description('Enables a game by adding a link' + 132 | 'from games_available') 133 | .option('-f, --force', 'if link is existings, ' + 134 | 'deletes and recreates it') 135 | .option('-v, --verbose', 'More verbose output') 136 | .option('-a, --all', 'Enables all games') 137 | .action(function(env, options) { 138 | const enableGame = function(game) { 139 | debugger 140 | let source = GAMES_AVAILABLE_DIR + game; 141 | if (!fs.existsSync(source)) { 142 | console.error('game not found: ' + game); 143 | return; 144 | } 145 | let destination = GAMES_ENABLED_DIR + game; 146 | if (fs.existsSync(destination)) { 147 | if (!options.force) { 148 | console.error(`game ${game} already enabled. 149 | use --force`); 150 | return; 151 | } 152 | fs.removeSync(destination); 153 | } 154 | fs.symlink(source, destination, error => { 155 | if (error) { 156 | console.error(`game ${game} could 157 | not be enabled`); 158 | throw(error); 159 | } 160 | else if (options.verbose) { 161 | console.error(`game ${game} enabled`); 162 | } 163 | }); 164 | }; 165 | if (options.all) { 166 | options.force = true; 167 | let dirs = getDirectories(GAMES_AVAILABLE_DIR); 168 | for (let i = 0; i < dirs.length; i++) { 169 | enableGame(dirs[i]); 170 | } 171 | 172 | } 173 | else { 174 | enableGame(env); 175 | } 176 | }); 177 | 178 | program 179 | .command('disable [game]') 180 | .description('Disables a game') 181 | .option('-f, --force', 'removes the game even if not a link') 182 | .option('-v, --verbose', 'More verbose output') 183 | .option('-a, --all', 'Disables all games') 184 | .action(function(env, options) { 185 | const disableGame = function(game) { 186 | let destination = GAMES_ENABLED_DIR + game; 187 | if (!fs.existsSync(destination)) { 188 | console.warn('game ' + game + ' already disabled'); 189 | return; 190 | } 191 | if (!options.force && 192 | !fs.lstatSync(destination).isSymbolicLink()) { 193 | 194 | console.warn('game ' + game + 195 | ' is not a symbolic link. Use --force'); 196 | return; 197 | } 198 | fs.remove(destination, err => { 199 | if (err) { 200 | return console.error(err) 201 | } 202 | if (options.verbose) { 203 | logList(`game ${game} disabled`) 204 | } 205 | }); 206 | }; 207 | 208 | if (options.all) { 209 | if (env) { 210 | console.error('cannot specify a game ' + 211 | 'with option --all'); 212 | return; 213 | } 214 | let links = getLinks(GAMES_ENABLED_DIR); 215 | if (!links.length && options.verbose) { 216 | console.warn('no games to disable found'); 217 | return; 218 | } 219 | options.force = true; 220 | for (let i = 0; i < links.length; i++) { 221 | disableGame(links[i]); 222 | } 223 | } 224 | else { 225 | disableGame(env); 226 | } 227 | }); 228 | 229 | //Parsing options 230 | program.parse(process.argv); 231 | -------------------------------------------------------------------------------- /bin/nodegame-installer.js: -------------------------------------------------------------------------------- 1 | #!/usr/local/bin/node 2 | /** 3 | * # nodeGame Installer 4 | * Copyright(c) 2011-2023 Stefano Balietti 5 | * MIT Licensed 6 | * 7 | * http://www.nodegame.org 8 | */ 9 | 10 | "use strict"; 11 | 12 | // Modules. 13 | 14 | const isWin = /^win/.test(process.platform); 15 | 16 | const path = require('path'); 17 | const fs = require('fs'); 18 | const execFile = require('child_process').execFile; 19 | const readline = require('readline'); 20 | 21 | const logList = txt => { 22 | console.log(' - ' + txt); 23 | }; 24 | const log = txt => { 25 | if ('undefined' === typeof txt) console.log(); 26 | else console.log(' ' + txt); 27 | }; 28 | const err = txt => { 29 | console.error(' Error: ' + txt); 30 | }; 31 | const warn = txt => { 32 | console.error(' Warning: ' + txt); 33 | }; 34 | 35 | // const MAIN_MODULE = 'nodegame'; 36 | let MAIN_MODULE = 'nodegame'; 37 | 38 | // All stable versions. 39 | // Versions below < 3 are not available. 40 | const STABLE_VERSIONS = { 41 | v3: '3.5.3', 42 | v4: '4.3.3', 43 | v5: '5.11.2', 44 | v6: '6.3.0', 45 | v7: '7.1.0' 46 | // v8: '8.0.0' 47 | }; 48 | 49 | const AVAILABLE_VERSIONS = Object.keys(STABLE_VERSIONS).concat(['dev']); 50 | 51 | // Installer default version. 52 | const INSTALLER_VERSION = 'v7'; 53 | 54 | // If node_modules folders are detected, their paths (without node_modules) 55 | // is stored in here. 56 | var parentNodeModules; 57 | 58 | // The actual version being installed, user can change it. 59 | var version = STABLE_VERSIONS[INSTALLER_VERSION]; 60 | 61 | // Check if it is a help call. 62 | let p = process.argv[2]; 63 | if (p === '--help' || p === '-h') { 64 | printHelp(); 65 | return; 66 | } 67 | else if (p === '--list-versions') { 68 | console.log(' List of stable versions:'); 69 | for (let i in STABLE_VERSIONS) { 70 | if (STABLE_VERSIONS.hasOwnProperty(i)) { 71 | console.log(' @' + i + ': ' + STABLE_VERSIONS[i]); 72 | } 73 | } 74 | return; 75 | } 76 | else if (p === '--version' || p === '-v') { 77 | console.log('nodegame-installer ' + version); 78 | return; 79 | } 80 | 81 | var rl = readline.createInterface({ 82 | input: process.stdin, 83 | output: process.stdout 84 | }); 85 | 86 | var alpha = false; 87 | var verbose = false; 88 | var nodeModulesExisting = false; 89 | var isDev = false; 90 | var doSSH = false; 91 | var noSpinner = false; 92 | var doNotMoveInstall = false; 93 | var yes; 94 | var noParentDirCheck; 95 | var branch; 96 | var warnings; 97 | var dry; 98 | 99 | // Add default games in games/ and games_available/. 100 | var addGames = true; 101 | 102 | // User requested version. 103 | var requestedVersion = '@' + version; 104 | 105 | for (let i = 0; i < process.argv.length; i++) { 106 | let option = process.argv[i]; 107 | 108 | if (option.charAt(0) === '@') { 109 | requestedVersion = process.argv[i].substr(1); 110 | 111 | if (requestedVersion === 'dev') { 112 | isDev = true; 113 | requestedVersion = '@' + version; 114 | 115 | // For testing alpha versions. 116 | // MAIN_MODULE = 'nodegame-test'; 117 | // version = '7.0.4'; 118 | // requestedVersion = '@' + version; 119 | // alpha = true; 120 | } 121 | else if (requestedVersion === 'alpha') { 122 | // For testing alpha versions. 123 | MAIN_MODULE = 'nodegame-test'; 124 | requestedVersion = '@latest'; 125 | alpha = true; 126 | } 127 | else { 128 | version = STABLE_VERSIONS[requestedVersion]; 129 | if (!version) { 130 | err('invalid version: ', version); 131 | log('available version options: ' + AVAILABLE_VERSIONS); 132 | log(); 133 | return; 134 | } 135 | requestedVersion = '@' + version; 136 | } 137 | } 138 | else if (option === '--no-spinner') { 139 | noSpinner = true; 140 | } 141 | else if (option === '--yes') { 142 | yes = true; 143 | } 144 | else if (option === '--no-parent-dir-check') { 145 | noParentDirCheck = true; 146 | } 147 | else if (option === '--branch') { 148 | branch = process.argv[i+1]; 149 | if (!branch) { 150 | err('--branch option found, but no value provided.'); 151 | log(); 152 | return; 153 | } 154 | 155 | } 156 | else if (option === '--ssh') { 157 | doSSH = true; 158 | } 159 | else if (option === '--dry') { 160 | dry = true; 161 | } 162 | else if (option === '--no-games') { 163 | addGames = false; 164 | } 165 | } 166 | 167 | if ((doSSH || branch) && !isDev) { 168 | err('--branch and --doSSH options are available only with @dev'); 169 | return; 170 | } 171 | 172 | // nodeGame version. 173 | const VERSION = isDev ? "v" + version + '-dev' : "v" + version; 174 | 175 | const NODEGAME_AND_VERSION = 'nodegame-' + VERSION + (alpha ? '-alpha' : ''); 176 | 177 | const ROOT_DIR = process.cwd() 178 | const NODE_MODULES_DIR = path.resolve(ROOT_DIR, 'node_modules'); 179 | 180 | let installDir = process.argv.indexOf('--install-dir'); 181 | if (installDir !== -1) { 182 | installDir = process.argv[installDir+1]; 183 | if (!installDir) { 184 | err('--install-dir option found, but no value provided.'); 185 | log(); 186 | return; 187 | } 188 | installDir = path.join(ROOT_DIR, installDir); 189 | if (installDir === NODE_MODULES_DIR) doNotMoveInstall = true; 190 | } 191 | else { 192 | installDir = NODEGAME_AND_VERSION; 193 | } 194 | 195 | const INSTALL_DIR = doNotMoveInstall ? 196 | path.resolve(NODE_MODULES_DIR, MAIN_MODULE) : 197 | path.resolve(ROOT_DIR, installDir); 198 | 199 | const INSTALL_DIR_MODULES = doNotMoveInstall ? 200 | NODE_MODULES_DIR : path.resolve(INSTALL_DIR, 'node_modules'); 201 | 202 | const NODEGAME_MODULES = [ 203 | 'nodegame-server', 'nodegame-client', 204 | 'nodegame-window', 'nodegame-widgets', 205 | 'nodegame-monitor', 'nodegame-game-template', 206 | 'nodegame-requirements', 'nodegame-generator', 207 | 'nodegame-mturk', 208 | // No need to replace these now. 209 | // 'nodegame-db', 'nodegame-mondodb', 210 | 'JSUS', 'NDDB', 211 | 'ultimatum-game' 212 | ]; 213 | 214 | const GAMES_AVAILABLE_DIR = path.resolve(INSTALL_DIR, 215 | 'games_available'); 216 | const GAMES_ENABLED_DIR = path.resolve(INSTALL_DIR, 'games'); 217 | 218 | // Making sure we do not slip out on an exception. 219 | 220 | process.on('uncaughtException', function(err) { 221 | warn('A generic error occurred during the installation:\n'); 222 | log(err.stack) 223 | installationFailed(); 224 | }); 225 | 226 | // Printing Info. 227 | 228 | // Print cool nodegame logo. 229 | printNodeGameInfo(); 230 | 231 | // Print node and nodeGame version (npm too?). 232 | printInstallInfo(); 233 | 234 | 235 | // Check node version is. 236 | var nodeVersion = process.versions.node.split('.'); 237 | if (parseInt(nodeVersion[0], 10) < 10) { 238 | err('node version >= 10.x is required.\n' + 239 | 'Please upgrade your Node.Js installation, ' + 240 | 'visit: http://nodejs.org'); 241 | installationAborted(); 242 | return; 243 | } 244 | 245 | // Check if install dir exists (abort). 246 | if (fs.existsSync(INSTALL_DIR)) { 247 | err('installation directory already existing.'); 248 | installationAborted(); 249 | return; 250 | } 251 | 252 | // Check if node_modules exists (prompt continue?) 253 | if (fs.existsSync(NODE_MODULES_DIR)) { 254 | nodeModulesExisting = true; 255 | warn('A "node_modules" folder was detected in this directory.'); 256 | log(); 257 | log('If you continue, it will become a subfolder of the nodeGame '); 258 | log('installation. This might affect live node processes, as well as '); 259 | log('other Node.JS packages relying on this node_modules folder. If '); 260 | log('unsure, choose No and try to install nodeGame on another path.'); 261 | if (!yes) { 262 | log(); 263 | confirm('Continue? [y/n]', function(ok) { 264 | if (ok) { 265 | log(); 266 | log(); 267 | checkParentNodeModules(); 268 | } 269 | else { 270 | installationAborted(true); 271 | log(); 272 | } 273 | }) 274 | return; 275 | } 276 | else { 277 | log('Continue? [y/n] --yes'); 278 | log(); 279 | } 280 | } 281 | 282 | // Install. 283 | if (isDev) checkGitExists(checkParentNodeModules); 284 | else checkParentNodeModules(); 285 | 286 | 287 | // Helper functions. 288 | /////////////////////////////////////////////////////////////////////////////// 289 | 290 | function checkParentNodeModules() { 291 | parentNodeModules = getParentNodeModules(); 292 | 293 | // Check if a node_modules folder exists in any folder from the one above. 294 | // to top /. 295 | if (!noParentDirCheck && parentNodeModules.length) { 296 | let str; 297 | str = 'A "node_modules" folder was detected in '; 298 | str += parentNodeModules.length === 1 ? 'a parent directory: ' : 299 | 'these parent directories: '; 300 | warn(str); 301 | parentNodeModules.forEach(dir => logList(dir)); 302 | log(); 303 | 304 | str = 'If you continue, ' + (parentNodeModules.length === 1 ? 305 | 'that folder' : 'those folders'); 306 | log(str + ' will be temporarily renamed. This'); 307 | log('might affect only live node processes. If unsure, choose No '); 308 | log('and try to install nodeGame on another path.'); 309 | log(); 310 | if (!yes) { 311 | confirm('Continue? [y/n]', renameParentCb); 312 | } 313 | else { 314 | log('Continue? [y/n] --yes'); 315 | log(); 316 | renameParentCb(true); 317 | } 318 | } 319 | else { 320 | doInstall(); 321 | } 322 | } 323 | 324 | function doInstall() { 325 | var sp; 326 | 327 | // Create spinner. 328 | log('Downloading and installing nodeGame packages.'); 329 | 330 | if (dry) { 331 | log(); 332 | warn('Dry run: aborting.'); 333 | closeRL(2); 334 | return; 335 | } 336 | 337 | if (!noSpinner) { 338 | sp = new Spinner(' This might take a few minutes %s '); 339 | sp.start(); 340 | } 341 | else { 342 | log('This might take a few minutes...'); 343 | } 344 | 345 | let child = execFile( 346 | isWin ? 'npm.cmd' : 'npm', 347 | [ 'install', MAIN_MODULE + requestedVersion ], 348 | { cwd: ROOT_DIR }, 349 | (error, stdout, stderr) => { 350 | // Stop spinner. 351 | if (!noSpinner) sp.stop(); 352 | 353 | if (error) { 354 | log(); 355 | log(); 356 | log('Oops! The following error/s occurred: '); 357 | log(); 358 | logList(stderr.trim()); 359 | log(); 360 | installationFailed(); 361 | return; 362 | } 363 | else { 364 | if (verbose) { 365 | log(); 366 | logList(stdout.trim()); 367 | } 368 | if (!fs.existsSync(path.resolve(NODE_MODULES_DIR))) { 369 | log(); 370 | log(); 371 | log('Doh! It looks like npm has a different default ' + 372 | 'installation folder.'); 373 | log('This can happen if you have a directory called '+ 374 | '"node_modules" in any of '); 375 | log('the parent folders. Please try using a ' + 376 | 'different path.'); 377 | installationFailed(); 378 | return; 379 | } 380 | log(); 381 | log('Done! Now some final magic...'); 382 | try { 383 | someMagic(); 384 | } 385 | catch(e) { 386 | // execFile( 387 | // 'ls', 388 | // [ '-la' ], 389 | // (error, stdout, stderr) => { 390 | // if (error) { 391 | // logList(stderr.trim()); 392 | // log(); 393 | // } 394 | // else { 395 | // logList(stdout.trim()); 396 | // } 397 | // }); 398 | // execFile( 399 | // 'ls', 400 | // [ '../node_modules/', '-la' ], 401 | // (error, stdout, stderr) => { 402 | // if (error) { 403 | // logList(stderr.trim()); 404 | // log(); 405 | // } 406 | // else { 407 | // logList(stdout.trim()); 408 | // } 409 | // }); 410 | log('Oops! The following error/s occurred: '); 411 | log(); 412 | console.error(e); 413 | installationFailed(); 414 | return; 415 | } 416 | } 417 | return; 418 | }); 419 | } 420 | 421 | function checkGitExists(cb) { 422 | let child = execFile( 423 | 'git', 424 | [ '--version' ], 425 | { cwd: ROOT_DIR }, 426 | (error, stdout, stderr) => { 427 | if (error) { 428 | err('git not found, cannot install @dev version.'); 429 | log('Install git from: https://git-scm.com/ and retry.'); 430 | installationFailed(); 431 | } 432 | else { 433 | if (cb) cb(); 434 | } 435 | }); 436 | } 437 | 438 | function printNodeGameInfo() { 439 | log(); 440 | if (alpha) { 441 | log('***************************************************** '); 442 | log('** WELCOME TO NODEGAME INSTALLER v' + version + 443 | (alpha ? '-alpha' : '') + ' ** '); 444 | log('***************************************************** '); 445 | } 446 | else { 447 | log('*********************************************** '); 448 | log('** WELCOME TO NODEGAME INSTALLER v' + version + ' ** '); 449 | log('*********************************************** '); 450 | } 451 | 452 | log(); 453 | log('nodeGame: fast, scalable JavaScript for online, large-scale,'); 454 | log('multiplayer, real-time games and experiments in the browser.'); 455 | 456 | log(); 457 | log('creator: Stefano Balietti'); 458 | log('website: https://nodegame.org'); 459 | log('license: MIT'); 460 | log('mail: info@nodegame.org'); 461 | log('twitter: @nodegameorg'); 462 | log('bugs: https://github.com/nodeGame/nodegame/issues'); 463 | log('forum: https://groups.google.com/' + 464 | 'forum/?fromgroups#!forum/nodegame'); 465 | } 466 | 467 | function printInstallInfo() { 468 | log(); 469 | log('----------------------------------------------'); 470 | log(); 471 | 472 | log('node version: ' + process.version); 473 | let str = 'nodeGame version: ' + VERSION; 474 | if (branch) str += ' (' + branch + ')'; 475 | log(str); 476 | str = 'install directory: ' + INSTALL_DIR; 477 | if (doNotMoveInstall) str += ' (npm structure)'; 478 | log(str); 479 | log(); 480 | log(); 481 | } 482 | 483 | function printFinalInfo() { 484 | log(); 485 | let str = ' Installation complete!'; 486 | if (warnings) str += ' (with warnings)'; 487 | log(str); 488 | log('----------------------------------------------'); 489 | 490 | log('Enter the installation directory and start the server:'); 491 | if (!doNotMoveInstall) { 492 | log(' cd ' + NODEGAME_AND_VERSION); 493 | } 494 | else { 495 | log(' cd ' + path.join('node_modules', MAIN_MODULE)); 496 | } 497 | log(' node launcher.js'); 498 | log(); 499 | 500 | log('Open a browser tab at the address:'); 501 | log(' http://localhost:8080/'); 502 | log(); 503 | 504 | log('Start a bot from the waiting room interface, or open another tab:'); 505 | log(' http://localhost:8080/ultimatum?clientType=autoplay'); 506 | log(); 507 | 508 | log('Check the monitor interface:'); 509 | log(' http://localhost:8080/ultimatum/monitor'); 510 | log(); 511 | 512 | log('Create a new game:'); 513 | log(' bin/nodegame create-game mygame'); 514 | log(); 515 | 516 | log('Please cite as:'); 517 | log('----------------------------------------------'); 518 | log(' Balietti (2017) "nodeGame: Real-Time, Synchronous, ' + 519 | 'Online Experiments '); 520 | log(' in the Browser." Behavior Research Methods ' + 521 | '49(5) pp. 1696–1715'); 522 | log(); 523 | } 524 | 525 | function closeRL(code) { 526 | // rl.clearLine(); 527 | rl.close(); 528 | // if (force) process.stdin.destroy(); 529 | process.exit(code); 530 | } 531 | 532 | function someMagic(cb) { 533 | let mainNgDir = path.resolve(NODE_MODULES_DIR, MAIN_MODULE); 534 | 535 | // Check if log and private directories have been created. 536 | if (!fs.existsSync(path.resolve(mainNgDir, 'log'))) { 537 | fs.mkdirSync(path.resolve(mainNgDir, 'log')); 538 | } 539 | if (!fs.existsSync(path.resolve(mainNgDir, 'private'))) { 540 | fs.mkdirSync(path.resolve(mainNgDir, 'private')); 541 | } 542 | if (!fs.existsSync(path.resolve(mainNgDir, 'export'))) { 543 | fs.mkdirSync(path.resolve(mainNgDir, 'export')); 544 | } 545 | 546 | if (!doNotMoveInstall) { 547 | // Move nodegame folder outside node_modules. 548 | fs.renameSync(mainNgDir, INSTALL_DIR); 549 | 550 | try { 551 | // Old npms put already all modules under nodegame. 552 | if (!fs.existsSync(INSTALL_DIR_MODULES)) { 553 | fs.renameSync(NODE_MODULES_DIR, 554 | INSTALL_DIR_MODULES); 555 | } 556 | else if (!nodeModulesExisting) { 557 | fs.rmdirSync(NODE_MODULES_DIR); 558 | } 559 | } 560 | catch(e) { 561 | let keep = nodeModulesExisting; 562 | moveFolderSync(NODE_MODULES_DIR, INSTALL_DIR_MODULES, keep); 563 | } 564 | } 565 | 566 | if (isDev) { 567 | getAllGitModules(function() { 568 | 569 | if (addGames) { 570 | // Move games from node_modules. 571 | copyGameFromNodeModules('ultimatum-game'); 572 | } 573 | 574 | // Generator. 575 | fixGenerator(); 576 | 577 | // Restore any parent node_modules folder that was renamed. 578 | restoreParentNodeModules(); 579 | 580 | // Print final Information. 581 | printFinalInfo(); 582 | 583 | closeRL(0); 584 | }); 585 | } 586 | else { 587 | 588 | if (addGames) { 589 | // Move games from node_modules. 590 | copyGameFromNodeModules('ultimatum-game'); 591 | } 592 | 593 | // Generator. 594 | fixGenerator(); 595 | 596 | // Restore any parent node_modules folder that was renamed. 597 | restoreParentNodeModules(); 598 | 599 | // Print final Information. 600 | printFinalInfo(); 601 | 602 | closeRL(0); 603 | } 604 | } 605 | 606 | function fixGenerator() { 607 | // nodeGame generator: make link and store conf. 608 | makeLink(path.resolve(INSTALL_DIR_MODULES, 609 | 'nodegame-generator', 610 | 'bin', 'nodegame'), 611 | path.resolve(INSTALL_DIR, 'bin', 'nodegame'), 612 | 'file'); 613 | 614 | fs.writeFileSync(path.resolve(INSTALL_DIR_MODULES, 615 | 'nodegame-generator', 'conf', 'generator.conf.json'), 616 | JSON.stringify({ 617 | author: "", 618 | email: "", 619 | ngDir: INSTALL_DIR 620 | }, 4)); 621 | } 622 | 623 | function getAllGitModules(cb) { 624 | let gitPrecommitHook = path.resolve(INSTALL_DIR, 'git-hooks', 'pre-commit'); 625 | let counter = NODEGAME_MODULES.length; 626 | if (verbose) log('Converting modules into git repos.'); 627 | for (let i = 0; i < NODEGAME_MODULES.length; i++) { 628 | (function(i) { 629 | var nodeModulesCopy; 630 | let module = NODEGAME_MODULES[i]; 631 | let modulePath = path.resolve(INSTALL_DIR_MODULES, module); 632 | let nodeModulesPath = path.resolve(modulePath, 'node_modules'); 633 | 634 | // Keep node_modules, if any. 635 | if (fs.existsSync(nodeModulesPath)) { 636 | 637 | // Remove nodegame modules (if any) will be get by git. 638 | fs.readdirSync(nodeModulesPath).forEach(function(file, index) { 639 | if (inArray(file, NODEGAME_MODULES)) { 640 | let modulePath = path.join(nodeModulesPath, file); 641 | removeDirRecursiveSync(modulePath); 642 | } 643 | }); 644 | 645 | let destDir = doNotMoveInstall ? 646 | NODE_MODULES_DIR : INSTALL_DIR_MODULES; 647 | nodeModulesCopy = path.resolve(destDir, 648 | ('_node_modules-' + module)); 649 | fs.renameSync(nodeModulesPath, nodeModulesCopy); 650 | } 651 | 652 | // Remove npm folder. 653 | removeDirRecursiveSync(modulePath); 654 | 655 | setTimeout(function() { 656 | getGitModule(module, INSTALL_DIR_MODULES, function(err) { 657 | if (err) throw new Error(err); 658 | // Put back node_modules, if it was copied before. 659 | if (nodeModulesCopy) { 660 | fs.renameSync(nodeModulesCopy, nodeModulesPath); 661 | } 662 | // Copy pre-commit hook. 663 | fs.copyFileSync(gitPrecommitHook, 664 | path.resolve(modulePath, '.git', 'hooks', 665 | 'pre-commit')); 666 | counter--; 667 | if (counter == 0 && cb) cb(); 668 | }); 669 | }, 100); 670 | })(i); 671 | } 672 | } 673 | 674 | function getGitModule(module, cwd, cb, noBranch) { 675 | let repo = doSSH ? 'git@github.com:' : 'https://github.com/'; 676 | repo += 'nodeGame/' + module + '.git'; 677 | if (verbose) log('Cloning git module: ' + module); 678 | let params = !noBranch && branch ? 679 | [ 'clone', '-b', branch, repo ] : [ 'clone', repo ]; 680 | let child = execFile( 681 | 'git', 682 | params, 683 | { cwd: cwd }, 684 | (error, stdout, stderr) => { 685 | if (error) { 686 | // If it could not checkout a branch, it could just 687 | // be that the branch does not exists, so just warning. 688 | if (!noBranch && branch && 689 | stderr.indexOf('Remote branch') !== -1 && 690 | stderr.indexOf('not found in upstream') !== -1) { 691 | 692 | error = null; 693 | let warnStr = ' Warning! module ' + module + 694 | ' branch not found: ' + branch; 695 | log(warnStr); 696 | warnings = true; 697 | getGitModule(module, cwd, cb, true); 698 | return; 699 | } 700 | else { 701 | logList('Could not clone: ' + module); 702 | logList(stderr.trim()); 703 | } 704 | log(); 705 | } 706 | else if (verbose) { 707 | logList(stdout.trim()); 708 | } 709 | if (cb) cb(error); 710 | }); 711 | } 712 | 713 | function makeLink(from, to, type) { 714 | if (isWin) { 715 | if (type === 'file') fs.linkSync(from, to, 'file'); 716 | else fs.symlinkSync(from, to, 'junction'); 717 | } 718 | else { 719 | fs.symlinkSync(from, to); 720 | } 721 | } 722 | 723 | function copyGameFromNodeModules(game, enable) { 724 | enable = 'undefined' === typeof enable ? true : enable; 725 | let gameDir = path.resolve(GAMES_AVAILABLE_DIR, game); 726 | 727 | // Move game from node_modules into games_available directory. 728 | fs.renameSync(path.resolve(INSTALL_DIR_MODULES, game), gameDir); 729 | 730 | // Make sure that the test command works. 731 | let tmpPath = path.join(gameDir, 'node_modules'); 732 | if (!fs.existsSync(tmpPath)) fs.mkdirSync(tmpPath); 733 | tmpPath = path.join(tmpPath, '.bin'); 734 | if (!fs.existsSync(tmpPath)) fs.mkdirSync(tmpPath); 735 | tmpPath = path.join(tmpPath, 'mocha'); 736 | if (!fs.existsSync(tmpPath)) { 737 | makeLink(path.join(INSTALL_DIR_MODULES, '.bin/mocha'), tmpPath); 738 | } 739 | 740 | if (!enable) return; 741 | 742 | // Enable it. 743 | makeLink(gameDir, path.resolve(GAMES_ENABLED_DIR, game)); 744 | } 745 | 746 | function confirm(msg, callback, ...params) { 747 | rl.question(' ' + msg + ' ', function(input) { 748 | callback(/^y|yes|ok|true$/i.test(input, ...params)); 749 | }); 750 | } 751 | 752 | function removeDirRecursiveSync(dir) { 753 | if (dir === '/') { 754 | throw new Error(' removeDirRecursiveSync error: cannot remove "/"'); 755 | } 756 | if (dir.indexOf(INSTALL_DIR_MODULES) === -1) { 757 | err('removeDirRecursiveSync error: there seems to be ' + 758 | 'an error with the path to remove: '); 759 | console.error(dir); 760 | } 761 | if (fs.existsSync(dir)) { 762 | fs.readdirSync(dir).forEach(function(file, index){ 763 | let curPath = path.join(dir, file); 764 | // Recurse. 765 | if (fs.lstatSync(curPath).isDirectory()) { 766 | removeDirRecursiveSync(curPath); 767 | } 768 | else { // delete file 769 | fs.unlinkSync(curPath); 770 | } 771 | }); 772 | fs.rmdirSync(dir); 773 | } 774 | } 775 | 776 | function getParentNodeModules() { 777 | let tks = ROOT_DIR.split(path.sep); 778 | let found = []; 779 | let dirPath = tks[0]; 780 | for (let i = 0 ; i < (tks.length - 1) ; i++) { 781 | if (i !== 0) dirPath = path.join(dirPath, tks[i]); 782 | if (fs.existsSync(path.join(dirPath, 'node_modules'))) { 783 | found.push(dirPath); 784 | } 785 | } 786 | return found; 787 | } 788 | 789 | // Need this wrapper because --yes option 790 | function renameParentCb(ok) { 791 | if (ok) { 792 | log(); 793 | let res = renameParentNodeModules(parentNodeModules); 794 | if (res !== true) { 795 | err('Could not rename "node_modules" folder in: ' + res[0]); 796 | installationFailed(); 797 | } 798 | log(); 799 | doInstall(); 800 | } 801 | else { 802 | installationAborted(true); 803 | return; 804 | } 805 | } 806 | 807 | function renameParentNodeModules(parents, restore) { 808 | let out = []; 809 | for (let i = 0; i < parents.length; i++) { 810 | try { 811 | let f1 = path.join(parents[i], 'node_modules'); 812 | let f2 = f1 + '_backup'; 813 | // Add _bak or remove _bak from parent node_modules folders. 814 | if (restore) fs.renameSync(f2, f1); 815 | else fs.renameSync(f1, f2); 816 | } 817 | catch(e) { 818 | out.push(parents[i]); 819 | // If we are not restoring original folders, exit immediately. 820 | if (!restore) return(out); 821 | } 822 | } 823 | return true; 824 | } 825 | 826 | function restoreParentNodeModules() { 827 | if (!parentNodeModules || !parentNodeModules.length) return; 828 | let res = renameParentNodeModules(parentNodeModules, true); 829 | if (res !== true) { 830 | log(); 831 | warn('Could not restore parent "node_modules" folder in: '); 832 | res.forEach(dir => logList(dir)); 833 | } 834 | } 835 | 836 | function installationAborted(byUser) { 837 | let str = 'Installation aborted' + (byUser ? ' by user.' : '.'); 838 | log(); 839 | log(str); 840 | closeRL(1); 841 | return; 842 | } 843 | 844 | function installationFailed() { 845 | log(); 846 | 847 | log('Installation did not complete successfully.'); 848 | log('----------------------------------------------'); 849 | log(); 850 | 851 | log('If you think this might be a bug, please report it. ' + 852 | 'You can either:'); 853 | log(' - open an issue at: ' + 854 | 'https://github.com/nodeGame/nodegame/issues'); 855 | log(' - send an email to info@nodegame.org'); 856 | log(); 857 | 858 | // Restore any parent node_modules folder that was renamed. 859 | restoreParentNodeModules(); 860 | closeRL(1); 861 | } 862 | 863 | 864 | function printHelp() { 865 | log(); 866 | log('@ Installs a specific version (v3, v4, v5, v6)'); 867 | log('@dev Installs latest nodeGame from git repos'); 868 | log('--branch Checkouts this branch on all git repos'); 869 | log('--ssh Uses ssh to get all git repos'); 870 | log('--yes Answers yes to all questions'); 871 | log('--install-dir Sets the name of the installation directory;'); 872 | log(' if equals to node_modules, the npm structure'); 873 | log(' stays unchanged'); 874 | log('--no-spinner Does not start the spinner'); 875 | log('--dry Does not actually install anything'); 876 | log('--list-versions Lists stable versions'); 877 | log('--no-games Does not install default games'); 878 | log('--version Prints installer version'); 879 | log('--help Prints this help'); 880 | log(); 881 | } 882 | 883 | // Kudos: cli-spinner package. 884 | 885 | function Spinner(text) { 886 | 887 | this.spinners = [ 888 | "|/-\\", 889 | "⠂-–—–-", 890 | "◐◓◑◒", 891 | "◴◷◶◵", 892 | "◰◳◲◱", 893 | "▖▘▝▗", 894 | "■□▪▫", 895 | "▌▀▐▄", 896 | "▉▊▋▌▍▎▏▎▍▌▋▊▉", 897 | "▁▃▄▅▆▇█▇▆▅▄▃", 898 | "←↖↑↗→↘↓↙", 899 | "┤┘┴└├┌┬┐", 900 | "◢◣◤◥", 901 | ".oO°Oo.", 902 | ".oO@*", 903 | "🌍🌎🌏", 904 | "◡◡ ⊙⊙ ◠◠", 905 | "☱☲☴", 906 | "⠋⠙⠹⠸⠼⠴⠦⠧⠇⠏", 907 | "⠋⠙⠚⠞⠖⠦⠴⠲⠳⠓", 908 | "⠄⠆⠇⠋⠙⠸⠰⠠⠰⠸⠙⠋⠇⠆", 909 | "⠋⠙⠚⠒⠂⠂⠒⠲⠴⠦⠖⠒⠐⠐⠒⠓⠋", 910 | "⠁⠉⠙⠚⠒⠂⠂⠒⠲⠴⠤⠄⠄⠤⠴⠲⠒⠂⠂⠒⠚⠙⠉⠁", 911 | "⠈⠉⠋⠓⠒⠐⠐⠒⠖⠦⠤⠠⠠⠤⠦⠖⠒⠐⠐⠒⠓⠋⠉⠈", 912 | "⠁⠁⠉⠙⠚⠒⠂⠂⠒⠲⠴⠤⠄⠄⠤⠠⠠⠤⠦⠖⠒⠐⠐⠒⠓⠋⠉⠈⠈", 913 | "⢄⢂⢁⡁⡈⡐⡠", 914 | "⢹⢺⢼⣸⣇⡧⡗⡏", 915 | "⣾⣽⣻⢿⡿⣟⣯⣷", 916 | "⠁⠂⠄⡀⢀⠠⠐⠈" 917 | ]; 918 | 919 | this.text = text || ''; 920 | 921 | this.chars = this.spinners[isWin ? 0 : 4].split(''); 922 | 923 | this.delay = 60; 924 | 925 | this.onTick = function(msg) { 926 | this.clearLine(this.stream); 927 | this.stream.write(msg); 928 | }; 929 | 930 | this.stream = process.stdout; 931 | 932 | this.start = function() { 933 | var current = 0; 934 | var self = this; 935 | this.id = setInterval(function() { 936 | var msg = self.text.indexOf('%s') > -1 937 | ? self.text.replace('%s', self.chars[current]) 938 | : self.chars[current] + ' ' + self.text; 939 | self.onTick(msg); 940 | 941 | current = ++current % self.chars.length; 942 | }, this.delay); 943 | }; 944 | 945 | this.stop = function(clear) { 946 | clearInterval(this.id); 947 | this.id = undefined; 948 | if (clear && this.enabled) this.clearLine(this.stream); 949 | }; 950 | 951 | this.clearLine = function(stream) { 952 | readline.clearLine(stream, 0); 953 | readline.cursorTo(stream, 0); 954 | }; 955 | } 956 | 957 | function inArray(needle, haystack) { 958 | var i, len; 959 | len = haystack.length; 960 | for (i = 0; i < len; i++) { 961 | if (needle === haystack[i]) { 962 | return needle; 963 | } 964 | } 965 | return false; 966 | } 967 | 968 | function moveFolderSync(from, to, copy) { 969 | if (!fs.existsSync(to)) fs.mkdirSync(to); 970 | fs.readdirSync(from).forEach(element => { 971 | 972 | let fileFrom = path.join(from, element); 973 | let fileTo = path.join(to, element); 974 | 975 | let stats = fs.lstatSync(fileFrom); 976 | if (stats.isFile() || stats.isSymbolicLink()) { 977 | if (copy) fs.copyFileSync(fileFrom, fileTo); 978 | else fs.renameSync(fileFrom, fileTo); 979 | } 980 | else { 981 | moveFolderSync(fileFrom, fileTo); 982 | } 983 | }); 984 | // ALl files moved, removed dir. 985 | if (!copy) fs.rmdirSync(from); 986 | 987 | } 988 | -------------------------------------------------------------------------------- /bin/update/update-steps.js: -------------------------------------------------------------------------------- 1 | const readline = require('readline'); 2 | let rl = readline.createInterface({ 3 | input: process.stdin, 4 | output: process.stdout, 5 | terminal: true 6 | }); 7 | 8 | var steps = [ 9 | 'Update version in package.json in nodegame', 10 | 'Update CHANGELOG file in nodegame', 11 | 'Update version in nodegame-installer', 12 | 'Git push nodegame to master', 13 | 'Check tests on Travis', 14 | 'Upload nodegame-installer to website', 15 | 'Update version in index.htm and upload it to website', 16 | 'Update changelog.htm and upload it to website', 17 | 'Commit and push changes to nodegame-website', 18 | 'Update nodegame-heroku package.json version', 19 | 'Tweet about new version :)' 20 | ]; 21 | 22 | var counter = 0; 23 | function step(str) { 24 | return new Promise((resolve) => { 25 | rl.question(' ' + (counter + 1) + '. ' + steps[counter++], () => { 26 | resolve(); 27 | if (counter >= steps.length) { 28 | console.log(); 29 | console.log(' Done!'); 30 | rl.close(); 31 | } 32 | }); 33 | }); 34 | }; 35 | 36 | console.log(); 37 | 38 | step() 39 | .then(() => { return step(); }) 40 | .then(() => { return step(); }) 41 | .then(() => { return step(); }) 42 | .then(() => { return step(); }) 43 | .then(() => { return step(); }) 44 | .then(() => { return step(); }) 45 | .then(() => { return step(); }) 46 | .then(() => { return step(); }); 47 | -------------------------------------------------------------------------------- /bin/update/update_version.sh: -------------------------------------------------------------------------------- 1 | # In progress. Do not use now. 2 | 3 | # Rename files. 4 | rename "s/v2/v3/g" * 5 | 6 | # Rename text in files. 7 | find . -type f -exec sed -i 's/2.x/3.x/g' {} + 8 | find . -type f -exec sed -i 's/v2/v3/g' {} + 9 | 10 | -------------------------------------------------------------------------------- /conf/http.js: -------------------------------------------------------------------------------- 1 | /** 2 | * # http.js 3 | * 4 | * Copyright(c) 2020 Stefano Balietti 5 | * MIT Licensed 6 | * 7 | * Configuration file for ServerNode in nodegame-server. 8 | * --- 9 | */ 10 | module.exports = configure; 11 | 12 | function configure(app, servernode) { 13 | 14 | // Edit this file to modify the default configuration options in: 15 | // node_modules/nodegame-server/conf/http.js 16 | 17 | return true; 18 | }; 19 | -------------------------------------------------------------------------------- /conf/loggers.js: -------------------------------------------------------------------------------- 1 | /** 2 | * # servernode.js 3 | * 4 | * Copyright(c) 2020 Stefano Balietti 5 | * MIT Licensed 6 | * 7 | * Configuration file for ServerNode in nodegame-server. 8 | * --- 9 | */ 10 | module.exports = configure; 11 | 12 | const path = require('path'); 13 | 14 | function configure(loggers) { 15 | 16 | // Edit this file to modify the default configuration options in: 17 | // node_modules/nodegame-server/conf/loggers.js 18 | 19 | // For instance: 20 | 21 | // let config = { 22 | // levels: { 23 | // silly: 0, 24 | // verbose: 1, 25 | // info: 2, 26 | // data: 3, 27 | // warn: 4, 28 | // debug: 5, 29 | // error: 6 30 | // }, 31 | // colors: { 32 | // silly: 'magenta', 33 | // verbose: 'cyan', 34 | // info: 'green', 35 | // data: 'grey', 36 | // warn: 'yellow', 37 | // debug: 'blue', 38 | // error: 'red' 39 | // } 40 | // }; 41 | 42 | // let rootDir = path.resolve(__dirname, '..'); 43 | // let logDir = rootDir + '/log/'; 44 | // 45 | // loggers.add('ultimatumchannel', { 46 | // console: { 47 | // level: 'silly', 48 | // colorize: true, 49 | // }, 50 | // file: { 51 | // level: 'silly', 52 | // timestamp: true, 53 | // filename: logDir + 'channel', 54 | // maxsize: 1000, 55 | // maxFiles: 10, 56 | // }, 57 | // }); 58 | 59 | return true; 60 | } 61 | -------------------------------------------------------------------------------- /conf/servernode.js: -------------------------------------------------------------------------------- 1 | /** 2 | * # servernode.js 3 | * 4 | * Copyright(c) 2020 Stefano Balietti 5 | * MIT Licensed 6 | * 7 | * Configuration file for ServerNode in nodegame-server. 8 | * --- 9 | */ 10 | module.exports = configure; 11 | 12 | function configure(servernode) { 13 | 14 | // Edit this file to modify the default configuration options in: 15 | // node_modules/nodegame-server/conf/servernode.js 16 | 17 | // Extra configuration goes here, e.g.: 18 | // servernode.port = 80; 19 | // servernode.homePage = false; 20 | 21 | return true; 22 | } 23 | -------------------------------------------------------------------------------- /conf/sio.js: -------------------------------------------------------------------------------- 1 | /** 2 | * # sio.js 3 | * 4 | * Copyright(c) 2020 Stefano Balietti 5 | * MIT Licensed 6 | * 7 | * Configuration file for the Socket.io server in nodegame-server. 8 | * --- 9 | */ 10 | module.exports = configure; 11 | 12 | function configure(sio, servernode) { 13 | 14 | // Edit this file to modify the default configuration options in: 15 | // node_modules/nodegame-server/conf/sio.js 16 | 17 | return true; 18 | }; 19 | -------------------------------------------------------------------------------- /games/README.md: -------------------------------------------------------------------------------- 1 | ## Default Games Directory 2 | -------------------------------------------------------------------------------- /games_available/README.md: -------------------------------------------------------------------------------- 1 | ## Games Available Directory 2 | 3 | Games need to be symlinked from games/ folder to be enabled. 4 | -------------------------------------------------------------------------------- /git-hooks/pre-commit: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # 3 | # Hook script to clean up code and build docs. 4 | # Only .js files are checked. 5 | # Called by "git commit" with no arguments. 6 | # The hook should exit with non-zero status if it wants to stop the commit. 7 | 8 | # Loop over staged files and clean them up. 9 | while IFS= read -rd '' file 10 | do 11 | 12 | # Special checks for JavaScript sources: 13 | if [[ $file == *.js && $file != *.min.js && $file != public/* && $file != docs/* && $file != build/* ]] 14 | then 15 | 16 | echo "Checking: '$file'" 17 | 18 | len1=`wc -c < "$file"` 19 | 20 | # Remove trailing whitespace on lines. 21 | sed -i 's/\s\+$//' "$file" 22 | len2=`wc -c < "$file"` 23 | [ $len1 != $len2 ] && echo "Removed trailing whitespace in '$file'." 24 | len1=$len2 25 | 26 | # Remove leading and trailing blank lines, ensure that file ends in newline. 27 | sed -i '/./,$!d;:a;/^\n*$/{$d;N;};/\n$/ba;$a\' "$file" 28 | len2=`wc -c < "$file"` 29 | [ $len1 != $len2 ] && echo "Removed surrounding empty lines in '$file'." 30 | len1=$len2 31 | 32 | # Remove trailing empty lines. 33 | sed -i -e :a -e '/^\n*$/{$d;N;};/\n$/ba' "$file" 34 | len2=`wc -c < "$file"` 35 | [ $len1 != $len2 ] && echo "Removed trailing whitespace in '$file'." 36 | len1=$len2 37 | 38 | 39 | # Check for tabs. 40 | if grep -q $'\t' "$file" 41 | then 42 | echo "ABORT: Found tab character in '$file'!" 43 | exit 1 44 | fi 45 | 46 | # Remove debugger statements which are alone on a line. 47 | sed -i '/^\s*debugger;\{0,1\}$/d' "$file" 48 | len2=`wc -c < "$file"` 49 | [ $len1 != $len2 ] && echo "Removed debugger statements in '$file'." 50 | len1=$len2 51 | 52 | # Check for debugger statements which are not alone on a line. 53 | if grep -q 'debugger' "$file" 54 | then 55 | echo "ABORT: Found complicated debugger statement in '$file'!" 56 | exit 1 57 | fi 58 | 59 | # Check for lines wider than 80 characters. 60 | lines=$(grep -n '.\{81,\}' "$file" | cut -d: -f1 | paste -sd',') 61 | if [ -n "$lines" ] 62 | then 63 | echo "ABORT: More than 80 characters in '$file' on line(s) $lines!" 64 | exit 1 65 | fi 66 | fi 67 | 68 | # Keep these changes. 69 | git add "$file" 70 | done < <(git diff --cached --name-only --diff-filter=ACM -z) 71 | 72 | # Build documentation if possible. 73 | if [ -x bin/make.js -a -d docs ] 74 | then 75 | node bin/make.js doc 76 | git add -u docs/ 77 | fi 78 | -------------------------------------------------------------------------------- /launcher.js: -------------------------------------------------------------------------------- 1 | /** 2 | * # Launcher file for nodeGame Server 3 | * Copyright(c) 2011-2020 Stefano Balietti 4 | * MIT Licensed 5 | * 6 | * Load configuration options and start the server 7 | * 8 | * http://www.nodegame.org 9 | */ 10 | 11 | "use strict"; 12 | 13 | // Modules. 14 | const fs = require('fs'); 15 | const path = require('path'); 16 | const exec = require('child_process').exec; 17 | const J = require('JSUS').JSUS; 18 | 19 | // TODO: refactor, eliminate var; check new Commander options. 20 | 21 | // Load commander. 22 | var program = require('commander'); 23 | 24 | // Load the ServerNode class. 25 | var ServerNode = require('nodegame-server').ServerNode; 26 | 27 | // nodeGame version. 28 | var version = require('./package.json').version; 29 | 30 | // ServerNode object. 31 | var sn; 32 | 33 | // ServerNode options. 34 | var options; 35 | 36 | // Other local options. 37 | var confDir, logDir, gamesDir, debug, infoQuery, runTests; 38 | var nClients, clientType, killServer, auth, wait, port; 39 | var codesDb; 40 | 41 | var cert, key; 42 | 43 | // Warn message. 44 | var ignoredOptions; 45 | 46 | // Helper variables. 47 | 48 | // Split input parameters. 49 | function list(val) { 50 | return val.split(','); 51 | } 52 | 53 | // Go! 54 | 55 | ignoredOptions = []; 56 | 57 | // Defaults. 58 | 59 | confDir = path.resolve(__dirname, 'conf'); 60 | logDir = path.resolve(__dirname, 'log'); 61 | gamesDir = path.resolve(__dirname, 'games'); 62 | debug = undefined; 63 | infoQuery = undefined; 64 | 65 | nClients = 4; 66 | clientType = 'autoplay'; 67 | runTests = false; 68 | killServer = false; 69 | 70 | // Commander. 71 | 72 | program 73 | .version(version) 74 | 75 | // Specify a configuration file (other inline-options will be ignored). 76 | 77 | .option('-C, --config [confFile]', 78 | 'Specifies a configuration file to load') 79 | 80 | // Specify inline options (more limited than a conf file, but practical). 81 | 82 | .option('-c, --confDir ', 83 | 'Sets the configuration directory') 84 | .option('-l, --logDir ', 85 | 'Sets the log directory') 86 | .option('-L, --logLevel ', 87 | 'Sets the log level. Values: error(default)|warn|info|silly') 88 | .option('-g, --gamesDir ', 89 | 'Sets the games directory') 90 | .option('-d, --debug', 91 | 'Enables the debug mode') 92 | .option('-i, --infoQuery [false]', 93 | 'Enables getting information via query-string ?q=') 94 | .option('-b, --build [components]', 95 | 'Rebuilds the specified components', list) 96 | .option('-s, --ssl [path-to-ssl-dir]', 97 | 'Starts the server with SSL encryption') 98 | .option('-f, --default [channel]', 99 | 'Sets the default channel') 100 | .option('-P, --port [port]', 101 | 'Sets the port of the server') 102 | 103 | 104 | 105 | // Connect phantoms. 106 | 107 | .option('-p, --phantoms ', 108 | 'Connect phantoms to the specified channel **DISCONTINUED**') 109 | // .option('-n, --nClients ', 110 | // 'Sets the number of clients phantoms to connect (default: 4)') 111 | // .option('-t, --clientType ', 112 | // 'Sets the client type of connecting phantoms (default: autoplay)') 113 | // .option('-T, --runTests', 114 | // 'Run tests after all phantoms are game-over ' + 115 | // '(overwrites settings.js in test/)') 116 | // .option('-k, --killServer', 117 | // 'Kill server after all phantoms are game-over') 118 | // .option('-a --auth [option]', 119 | // 'Phantoms auth options. Values: new(default)|createNew|' + 120 | // 'nextAvailable|next|code|id:code&pwd:password|file:path/to/file.') 121 | // .option('-w --wait [milliseconds]', 122 | // 'Waits before connecting the next phantom. Default: 1000') 123 | 124 | 125 | .parse(process.argv); 126 | 127 | // User options (Commander >= 7). 128 | let opts = program.opts(); 129 | 130 | if (opts.phantoms) { 131 | console.log('***Err: option --phantoms no longer supported. ' + 132 | 'PhantomJS support discontinued.'); 133 | return false; 134 | } 135 | 136 | if (opts.confFile) { 137 | if (!fs.existsSync(opts.confFile)) { 138 | return printErr('--confFile ' + opts.confFile + ' not found.'); 139 | } 140 | options = require(opts.confFile); 141 | if ('object' !== typeof options) { 142 | return printErr('--confFile ' + opts.confFile + ' did not return ' + 143 | 'a configuration object.'); 144 | } 145 | 146 | if (opts.confDir) ignoredOptions.push('--confDir'); 147 | if (opts.logDir) ignoredOptions.push('--logDir'); 148 | if (opts.gamesDir) ignoredOptions.push('--gamesDir'); 149 | if (opts.debug) ignoredOptions.push('--debug'); 150 | if (opts.infoQuery) ignoredOptions.push('--infoQuery'); 151 | } 152 | else { 153 | 154 | options = { 155 | 156 | // Additional conf directory. 157 | confDir: confDir, 158 | 159 | // Log Dir 160 | logDir: logDir, 161 | 162 | servernode: function(servernode) { 163 | // Special configuration for the ServerNode object. 164 | 165 | // Adds a new game directory (Default is nodegame-server/games). 166 | servernode.gamesDirs.push(gamesDir); 167 | 168 | // Sets the debug mode, exceptions will be thrown, if TRUE. 169 | if ('undefined' !== typeof debug) { 170 | servernode.debug = debug; 171 | } 172 | // Can get information from /?q=, if TRUE 173 | if ('undefined' !== typeof infoQuery) { 174 | servernode.enableInfoQuery = infoQuery; 175 | } 176 | // Basepath (without trailing slash). 177 | // servernode.basepath = '/mybasepath'; 178 | 179 | return true; 180 | }, 181 | // http: function(http) { 182 | // // Special configuration for Express goes here. 183 | // return true; 184 | // }, 185 | // sio: function(sio) { 186 | // // Special configuration for Socket.Io goes here here. 187 | // // Might not work in Socket.IO 1.x (check). 188 | // 189 | // // sio.set('transports', ['xhr-polling']); 190 | // // sio.set('transports', ['jsonp-polling']); 191 | // 192 | // // sio.set('transports', [ 193 | // // 'websocket' 194 | // // , 'flashsocket' 195 | // // , 'htmlfile' 196 | // // , 'xhr-polling' 197 | // // , 'jsonp-polling' 198 | // // ]); 199 | // 200 | // return true; 201 | // } 202 | }; 203 | 204 | // Validate other options. 205 | if (opts.confDir) { 206 | if (!fs.existsSync(opts.confDir)) { 207 | return printErr('--confDir ' + opts.confDir + ' not found.'); 208 | } 209 | confDir = opts.confDir; 210 | } 211 | if (opts.logDir) { 212 | if (!fs.existsSync(opts.logDir)) { 213 | return printErr('--logDir ' + opts.logDir + ' not found.'); 214 | } 215 | logDir = opts.logDir; 216 | } 217 | if (opts.gamesDir) { 218 | if (!fs.existsSync(opts.gamesDir)) { 219 | return printErr('--gamesDir ' + opts.gamesDir + ' not found.'); 220 | } 221 | gamesDir = opts.gamesDir; 222 | } 223 | if (opts.debug) debug = true; 224 | 225 | // Parse infoQuery. 226 | if (opts.infoQuery) { 227 | if ('boolean' === typeof opts.infoQuery) { 228 | infoQuery = opts.infoQuery; 229 | } 230 | else { 231 | let i = opts.infoQuery.toLowerCase(); 232 | infoQuery = i === 'f' || i === 'false' || i === '0' ? false : true; 233 | } 234 | } 235 | } 236 | 237 | // Validate general options. 238 | 239 | if ('boolean' === typeof opts.ssl) { 240 | options.ssl = true; 241 | } 242 | else if ('string' === typeof opts.ssl) { 243 | options.ssl = (function(dir) { 244 | var ssl; 245 | 246 | dir = path.resolve(dir) + '/'; 247 | if (!fs.existsSync(dir)) { 248 | printErr('ssl directory not found: ' + dir); 249 | return; 250 | } 251 | 252 | key = dir + 'private.key'; 253 | if (!fs.existsSync(key)) { 254 | printErr('ssl private key not found: ' + key); 255 | return; 256 | } 257 | cert = dir + 'certificate.pem'; 258 | if (!fs.existsSync(cert)) { 259 | printErr('ssl certificate not found: ' + cert); 260 | return; 261 | } 262 | 263 | ssl = {}; 264 | ssl.key = fs.readFileSync(key, 'utf8'); 265 | ssl.cert = fs.readFileSync(cert, 'utf8'); 266 | 267 | return ssl; 268 | 269 | })(opts.ssl); 270 | if (!options.ssl) return; 271 | } 272 | 273 | if (opts['default']) { 274 | options.defaultChannel = opts['default']; 275 | } 276 | 277 | if (opts.port) { 278 | port = J.isInt(opts.port, 0); 279 | if (!port) { 280 | return printErr('--port ' + opts.port + 281 | ' is not a positive number.'); 282 | } 283 | options.port = port; 284 | } 285 | 286 | if (opts.logLevel) { 287 | options.logLevel = opts.logLevel; 288 | } 289 | 290 | if (opts.nClients) { 291 | if (!opts.phantoms) ignoredOptions.push('--nClients'); 292 | else { 293 | nClients = parseInt(opts.nClients, 10); 294 | if (isNaN(nClients)) { 295 | return printErr('--nClients ' + opts.nClients + 296 | ' is invalid.'); 297 | } 298 | } 299 | } 300 | if (opts.clientType) { 301 | if (!opts.phantoms) ignoredOptions.push('--clientType'); 302 | else clientType = opts.clientType; 303 | } 304 | if (opts.runTests) { 305 | if (!opts.runTests) ignoredOptions.push('--runTests'); 306 | else runTests = opts.runTests; 307 | } 308 | if (opts.killServer) { 309 | if (!opts.phantoms) ignoredOptions.push('--killServer'); 310 | else killServer = true; 311 | } 312 | if (opts.wait) { 313 | if (!opts.phantoms) { 314 | ignoredOptions.push('--wait'); 315 | } 316 | else { 317 | if (true === opts.wait) { 318 | wait = 1000; 319 | } 320 | else { 321 | wait = J.isInt(opts.wait, 0); 322 | if (false === wait) { 323 | printErr('--wait must be a positive number or undefined. ' + 324 | 'Found:' + opts.wait); 325 | process.exit(); 326 | } 327 | } 328 | } 329 | } 330 | if (opts.auth) { 331 | if (!opts.phantoms) { 332 | ignoredOptions.push('--auth'); 333 | } 334 | else if ('string' === typeof opts.auth) { 335 | 336 | auth = (function(idIdx, pwdIdx) { 337 | var auth; 338 | idIdx = opts.auth.indexOf('id:'); 339 | if (idIdx === 0) { 340 | pwdIdx = opts.auth.indexOf('&pwd:'); 341 | if (pwdIdx !== -1) { 342 | auth = { 343 | id: opts.auth.substr(3, (pwdIdx-3)), 344 | pwd: opts.auth.substr(pwdIdx+5) 345 | }; 346 | } 347 | else { 348 | printErr('--auth must be a client id or id and ' + 349 | 'pwd in the form "id:123&pwd:456"'); 350 | process.exit(); 351 | } 352 | } 353 | else if (opts.auth === 'new') { 354 | auth = 'createNew'; 355 | } 356 | else if (opts.auth === 'next') { 357 | auth = 'nextAvailable'; 358 | } 359 | else if (opts.auth.indexOf('file:') === 0) { 360 | const NDDB = require('NDDB').NDDB; 361 | codesDb = new NDDB(); 362 | codesDb.loadSync(opts.auth.substr(5)); 363 | if (!codesDb.size()) { 364 | printErr('--auth no auth codes found: opts.auth'); 365 | process.exit(); 366 | } 367 | codesDb = codesDb.db; 368 | } 369 | else { 370 | auth = opts.auth; 371 | } 372 | return auth; 373 | })(); 374 | } 375 | else if ('boolean' === typeof opts.auth) { 376 | auth = 'createNew'; 377 | } 378 | else if ('number' === typeof opts.auth || 379 | 'object' === typeof opts.auth) { 380 | 381 | auth = opts.auth; 382 | } 383 | } 384 | 385 | // Rebuild server files as needed. 386 | 387 | if (opts.build) { 388 | (function() { 389 | let cssAlso, cssOnly; 390 | 391 | let len = opts.build.length; 392 | if (!len) { 393 | opts.build = [ 'client' ]; 394 | } 395 | else if (len === 1) { 396 | if (opts.build[0] === 'all') { 397 | // Client will be done anyway. 398 | opts.build = [ 'window', 'widgets', 'JSUS', 'NDDB' ]; 399 | } 400 | else if (opts.build[0] === 'css') { 401 | cssOnly = true; 402 | } 403 | } 404 | 405 | let info = J.resolveModuleDir('nodegame-server', __dirname); 406 | info = require(path.resolve(info, 'bin', 'info.js')); 407 | 408 | if (!cssOnly) { 409 | let out = 'nodegame-full.js'; 410 | 411 | let modules = { 412 | window: 'window', 413 | client: 'client', 414 | widgets: 'widgets', 415 | JSUS: 'JSUS', 416 | NDDB: 'NDDB', 417 | css: 'css' 418 | }; 419 | 420 | // Starting build. 421 | let i = -1; 422 | for ( ; ++i < len ; ) { 423 | let module = opts.build[i]; 424 | if (!modules[module]) { 425 | throw new Error('unknown build component: ' + module); 426 | } 427 | // Will be done last anyway. 428 | if (module === 'client') { 429 | continue; 430 | } 431 | else if (module === 'NDDB') { 432 | console.log('NDDB does not require build.'); 433 | continue; 434 | } 435 | else if (module === 'css') { 436 | cssAlso = true; 437 | continue; 438 | } 439 | 440 | info.build[module]({ all: true, clean: true }); 441 | console.log(''); 442 | } 443 | // Do client last. 444 | info.build.client({ 445 | clean: true, 446 | all: true, 447 | output: out 448 | }); 449 | J.copyFile(path.resolve(info.modulesDir.client, 'build', out), 450 | path.resolve(info.serverDir.build, out)); 451 | console.log(info.serverDir.build + out + ' rebuilt.'); 452 | console.log(''); 453 | } 454 | 455 | if (cssAlso || cssOnly) { 456 | info.build.css(info.serverDir.css, function(err) { 457 | if (!err) { 458 | console.log(); 459 | startServer(); 460 | } 461 | }); 462 | } 463 | else { 464 | startServer(); 465 | } 466 | 467 | })(); 468 | } 469 | else { 470 | startServer(); 471 | } 472 | 473 | // ## Helper functions. 474 | 475 | function startServer() { 476 | // Print warnings, if any. 477 | printIgnoredOptions(); 478 | 479 | console.log('nodeGame v.' + version); 480 | // Add nodeGame version (might be higher than server version) to options. 481 | options.nodeGameVersion = version; 482 | 483 | options.nodeGameRoot = __dirname; 484 | 485 | // Start server, options parameter is optional. 486 | sn = new ServerNode(options); 487 | 488 | sn.ready(function() { 489 | var channel; 490 | var i, phantoms; 491 | var startPhantom, handleGameover; 492 | var gameName, gameDir, queryString; 493 | var numFinished; 494 | 495 | // If there are not bots to add returns. 496 | if (!opts.phantoms) return; 497 | 498 | gameName = opts.phantoms; 499 | channel = sn.channels[gameName]; 500 | if (!channel) { 501 | printErr('channel ' + gameName + ' was not found.'); 502 | if (killServer) process.exit(); 503 | return; 504 | } 505 | 506 | if (auth && !channel.gameInfo.auth.enabled) { 507 | printErr('auth option enabled, but channel does not support it.'); 508 | process.exit(); 509 | } 510 | 511 | gameDir = sn.channels[gameName].getGameDir(); 512 | 513 | if (clientType) queryString = '?clientType=' + clientType; 514 | 515 | if (killServer || runTests) { 516 | handleGameover = function() { 517 | var command, testProcess; 518 | 519 | console.log(); 520 | console.log(gameName + ' game has run successfully.'); 521 | console.log(); 522 | 523 | if (runTests) { 524 | command = path.resolve(gameDir, 'node_modules', '.bin', 'mocha'); 525 | if (fs.existsSync(command)) { 526 | 527 | // Write and backup settings file. 528 | writeSettingsFile(gameDir); 529 | 530 | command += ' ' + gameDir + 'test/ --colors'; 531 | testProcess = exec(command, 532 | function(err, stdout, stderr) { 533 | if (stdout) console.log(stdout); 534 | if (stderr) console.log(stderr); 535 | testProcess.kill(); 536 | if (killServer) process.exit(); 537 | }); 538 | } 539 | else { 540 | printErr('Cannot run tests, mocha not found: ', 541 | command); 542 | } 543 | } 544 | else if (killServer) process.exit(); 545 | }; 546 | } 547 | 548 | 549 | startPhantom = function(i) { 550 | var str, config; 551 | str = 'Connecting phantom #' + (i+1) + '/' + nClients; 552 | if (codesDb) { 553 | config = { queryString: queryString, auth: codesDb[i] }; 554 | } 555 | else { 556 | config = { queryString: queryString, auth: auth }; 557 | } 558 | if (config.auth) { 559 | if (config.auth.id) { 560 | str += ' id: ' + config.auth.id; 561 | if (config.auth.pwd) str += ' pwd: ' + config.auth.pwd; 562 | } 563 | else { 564 | str += ' ' + config.auth; 565 | } 566 | } 567 | console.log(str); 568 | phantoms[i] = channel.connectPhantom(config); 569 | if ('undefined' !== typeof handleGameover) { 570 | // Wait for all PhantomJS processes to exit, then stop server. 571 | phantoms[i].on('exit', function(code) { 572 | numFinished ++; 573 | if (numFinished === nClients) { 574 | handleGameover(); 575 | } 576 | }); 577 | } 578 | }; 579 | 580 | phantoms = [], numFinished = 0; 581 | for (i = 0; i < nClients; ++i) { 582 | if (i > 0 && wait) { 583 | (function(i) { 584 | setTimeout(function() { startPhantom(i); }, wait * i); 585 | })(i); 586 | } 587 | else { 588 | startPhantom(i); 589 | } 590 | } 591 | 592 | // TODO: Listen for room creation instead of timeout. 593 | //setTimeout(function() { 594 | // var node; 595 | // node = sn.channels.ultimatum.gameRooms["ultimatum1"].node; 596 | // node.events.ee.ng.on( 597 | // 'GAME_OVER', function() {console.log('The game is over now.');}); 598 | //}, 5000); 599 | 600 | 601 | }); 602 | 603 | return sn; 604 | } 605 | 606 | function printIgnoredOptions() { 607 | if (ignoredOptions.length) { 608 | console.log(' ignored options:', ignoredOptions.join(', ')); 609 | console.log(); 610 | console.log(); 611 | } 612 | } 613 | 614 | function printErr(err) { 615 | console.log(' Check the input parameters.'); 616 | console.log(' Error: ' + err); 617 | } 618 | 619 | function writeSettingsFile(gameDir) { 620 | var settings, settingsFile, bak; 621 | settings = 'module.exports = { numPlayers: ' + nClients + ' };'; 622 | settingsFile = path.resolve(gameDir, 'test', 'settings.js'); 623 | // Make a backup of existing settings file, if found. 624 | if (fs.existsSync(settingsFile)) { 625 | bak = fs.readFileSync(settingsFile).toString(); 626 | fs.writeFileSync(settingsFile + '.bak', bak); 627 | } 628 | // Write updated settings file. 629 | fs.writeFileSync(path.resolve(gameDir, 'test', 'settings.js'), settings); 630 | } 631 | 632 | // Exports the ServerNode instance. 633 | module.exports = sn; 634 | -------------------------------------------------------------------------------- /log/README: -------------------------------------------------------------------------------- 1 | # Log Directory 2 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "nodegame", 3 | "description": "Fast, scalable JavaScript for large-scale, online, multiplayer, real-time games and experiments.", 4 | "version": "7.1.0", 5 | "homepage": "http://nodegame.org", 6 | "author": "Stefano Balietti ", 7 | "contributors": [ 8 | { 9 | "name": "Stefano Balietti", 10 | "email": "futur.dorko@gmail.com" 11 | } 12 | ], 13 | "repository": { 14 | "type": "git", 15 | "url": "https://github.com/nodeGame/nodegame.git" 16 | }, 17 | "engines": { 18 | "node": ">= 10.0.0" 19 | }, 20 | "dependencies": { 21 | "nodegame-client": ">=7.1.0", 22 | "nodegame-server": ">=7.0.3", 23 | "nodegame-window": ">=7.0.0", 24 | "nodegame-widgets": ">=7.0.2", 25 | "nodegame-requirements": ">=7.0.0", 26 | "nodegame-game-template": ">=7.0.0", 27 | "nodegame-monitor": ">=7.0.0", 28 | "nodegame-generator": ">=7.0.0", 29 | "ultimatum-game": ">=7.0.0", 30 | "nodegame-mturk": ">=7.0.0", 31 | "JSUS": ">=1.1.0", 32 | "NDDB": ">=3.0.2", 33 | "nodegame-db": "*", 34 | "nodegame-mongodb": "*", 35 | "commander": "^7.0.0", 36 | "fs-extra": "*", 37 | "smoosh": "0.4.0" 38 | }, 39 | "devDependencies": { 40 | "mocha": ">= 0.3.0", 41 | "should": "4.4.1" 42 | }, 43 | "license": "MIT", 44 | "scripts": { 45 | "start": "node launcher.js" 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /test/launcher-autoplay.js: -------------------------------------------------------------------------------- 1 | /** 2 | * # Launcher file for nodeGame Server 3 | * Copyright(c) 2017 Stefano Balietti 4 | * MIT Licensed 5 | * 6 | * Sets conf, log, and games directory and start the server. 7 | * 8 | * http://www.nodegame.org 9 | */ 10 | 11 | if (process.argv.length < 3) { 12 | console.log("Missing game-name argument! Usage:"); 13 | console.log("$ " + process.argv[0] + " " + process.argv[1] + " "); 14 | process.exit(1); 15 | } 16 | var gameName = process.argv[2]; 17 | var gameFolder = process.argv[3] || gameName; 18 | 19 | // Load the Node.js path object. 20 | var path = require('path'); 21 | 22 | // Load the ServerNode class. 23 | var ServerNode = require('nodegame-server').ServerNode; 24 | 25 | // Load the test settings. 26 | var testSettings = require('../games/' + gameFolder + '/test/settings.js'); 27 | 28 | // Overrides some of the default options for ServerNode. 29 | var options = { 30 | 31 | // Additional conf directory. 32 | confDir: './conf', 33 | 34 | // Log Dir 35 | logDir: './log', 36 | 37 | servernode: function(servernode) { 38 | // Special configuration for the ServerNode object. 39 | 40 | // Adds a new game directory (Default is nodegame-server/games). 41 | servernode.gamesDirs.push('./games'); 42 | // Sets the debug mode, exceptions will be thrown (Default is false). 43 | servernode.debug = true; 44 | 45 | return true; 46 | }, 47 | http: function(http) { 48 | // Special configuration for Express goes here. 49 | return true; 50 | }, 51 | sio: function(sio) { 52 | // Special configuration for Socket.Io goes here here. 53 | if (testSettings.sioTransports) { 54 | sio.set('transports', testSettings.sioTransports); 55 | } 56 | return true; 57 | } 58 | }; 59 | 60 | // Start server, options parameter is optional. 61 | var sn = new ServerNode(options); 62 | sn.ready(function() { 63 | var i, n, phantoms, handleGameover; 64 | var numFinished; 65 | 66 | n = testSettings.numPlayers; 67 | phantoms = []; 68 | for (i = 0; i < n; ++i) { 69 | console.log('Connecting autoplay-bot #', i+1, '/', n); 70 | phantoms[i] = sn.channels[gameName].connectPhantom(); 71 | } 72 | 73 | // TODO: Listen for room creation instead of timeout. 74 | //setTimeout(function() { 75 | // var node; 76 | // node = sn.channels.ultimatum.gameRooms["ultimatum1"].node; 77 | // node.events.ee.ng.on( 78 | // 'GAME_OVER', function() {console.log('The game is over now.');}); 79 | //}, 5000); 80 | 81 | handleGameover = function() { 82 | console.log(gameName + ' game has run successfully.'); 83 | process.exit(); 84 | }; 85 | 86 | // Wait for all PhantomJS processes to exit, then stop the server. 87 | numFinished = 0; 88 | for (i = 0; i < n; ++i) { 89 | phantoms[i].on('exit', function(code) { 90 | numFinished ++; 91 | if (numFinished == n) { 92 | handleGameover(); 93 | } 94 | }); 95 | } 96 | }); 97 | 98 | // Exports the whole ServerNode. 99 | module.exports = sn; 100 | -------------------------------------------------------------------------------- /test/runtest.exp: -------------------------------------------------------------------------------- 1 | #!/usr/bin/expect -f 2 | # 3 | # Expect script for starting the server and running an autoplay session. 4 | 5 | # Start server with autoplay, wait until it's done. 6 | set server_pid [spawn node launcher-autoplay.js] 7 | set server_id $spawn_id 8 | set timeout 600 9 | expect { 10 | timeout { puts "\nERROR: Server is not finishing!"; exit 1 } 11 | 12 | "lgc100> game over.\r" 13 | } 14 | 15 | # Stop server. 16 | exec kill $server_pid 17 | close -i $server_id 18 | wait -i $server_id 19 | 20 | puts "\nThe server ran successfully." 21 | 22 | exit 0 23 | --------------------------------------------------------------------------------