diff --git a/.babelrc b/.babelrc deleted file mode 100644 index bcb6ee8..0000000 --- a/.babelrc +++ /dev/null @@ -1,3 +0,0 @@ -{ - "presets": ["es2015", "stage-0"] -} \ No newline at end of file diff --git a/.gitattributes b/.gitattributes deleted file mode 100644 index 50e1b6e..0000000 --- a/.gitattributes +++ /dev/null @@ -1,16 +0,0 @@ -# Line endings: enforce LF in GitHub, convert to native on checkout. - -* text=auto -*.js text - -# Make GitHub ignore vendor libraries while computing language stats. -# See https://github.com/github/linguist#overrides. - -*.proto linguist-vendored=true -*.sh linguist-vendored=true -*.bat linguist-vendored=true - -# Explicitly specify language for non-standard extensions used under -# ide/web/lib/templates to make GitHub correctly count their language stats. -# -*.js_ linguist-language=JavaScript \ No newline at end of file diff --git a/.gitignore b/.gitignore deleted file mode 100644 index e014de4..0000000 --- a/.gitignore +++ /dev/null @@ -1,3 +0,0 @@ -node_modules/ -scripts/ -data/ \ No newline at end of file diff --git a/.greet b/.greet deleted file mode 100644 index e80ceec..0000000 --- a/.greet +++ /dev/null @@ -1,6 +0,0 @@ - ______ _____ _____ _____ - | ___ \ _ | __ \ _ | - | |_/ / | | | | \/ | | | ___ ___ _ ____ _____ _ __ - | __/| | | | | __| | | |/ __|/ _ \ '__\ \ / / _ \ '__| - | | \ \_/ / |_\ \ \_/ /\__ \ __/ | \ V / __/ | - \_| \___/ \____/\___/ |___/\___|_| \_/ \___|_| diff --git a/.help b/.help deleted file mode 100644 index ed5ed37..0000000 --- a/.help +++ /dev/null @@ -1,8 +0,0 @@ -clients : How many players are connected -exit : Exit the server -update : Update the server -kick [Username] : Kick player by username -kickall : Kick all players -clear : Clear the server console -save : Save all players into database -spawn [Username] [Pkmn] [Amount] : Spawn pokemons at users position \ No newline at end of file diff --git a/.travis.yml b/.travis.yml deleted file mode 100644 index a584e00..0000000 --- a/.travis.yml +++ /dev/null @@ -1,7 +0,0 @@ -sudo: false -language: node_js -script: "npm run test" -node_js: - - "4" - - "5" - - "6" \ No newline at end of file diff --git a/README.md b/README.md deleted file mode 100644 index b47a994..0000000 --- a/README.md +++ /dev/null @@ -1,60 +0,0 @@ -```` - ______ _____ _____ _____ - | ___ \ _ | __ \ _ | - | |_/ / | | | | \/ | | | ___ ___ _ ____ _____ _ __ - | __/| | | | | __| | | |/ __|/ _ \ '__\ \ / / _ \ '__| - | | \ \_/ / |_\ \ \_/ /\__ \ __/ | \ V / __/ | - \_| \___/ \____/\___/ |___/\___|_| \_/ \___|_| -```` -
- - - - - - - - Stability - -
- - - - - - -# Getting started - -## Setup - -Copy and rename ``cfg.js.example`` to ``cfg.js``. - -Open ``cfg.js`` and fill the following fields: - -````js -DOWNLOAD_PROVIDER: "GOOGLE"; -DOWNLOAD_USERNAME: "USERNAME"; -DOWNLOAD_PASSWORD: "PASSWORD"; -```` - -## Tunneling setup -The pokemon go app traffic has to get forwarded manually to this custom server. Download [rastapasta](https://github.com/rastapasta)'s [Pokemon Go Xposed](https://github.com/rastapasta/pokemon-go-xposed/releases) app and follow the installation instructions [here](https://github.com/rastapasta/pokemon-go-xposed#how-to-use-it). - -## Database setup - -To setup a database connection, open ``cfg.js`` and change the database login credentials: - -````js -MYSQL_PORT: 3306, -MYSQL_HOST_IP: "127.0.0.1", -MYSQL_DB_NAME: "pogosql", -MYSQL_USERNAME: "root", -MYSQL_PASSWORD: "", -```` - -The required database tables get generated automatically. - -## Server setup - -You need at minimum [Node.js](https://nodejs.org/en/) version 6.x. -Depending on your OS, you need to run either ``run-linux.sh`` or ``run-windows.bat`` from the root folder. diff --git a/ajax.js b/ajax.js new file mode 100644 index 0000000..c6e8f02 --- /dev/null +++ b/ajax.js @@ -0,0 +1,22 @@ +function send(data, resolve) { + var xhr = new XMLHttpRequest(); + var protocol = window.location.protocol; + xhr.open("POST", protocol + "//" + "127.0.0.1:3000/api", true); + xhr.setRequestHeader("Content-type", "application/x-www-form-urlencoded"); + xhr.onreadystatechange = function() { + if (xhr.readyState === 4) { + if (xhr.status === 200) { + if (typeof resolve === "function") { + try { + resolve(JSON.parse(xhr.responseText)); + } catch (e) { + resolve(void 0); + } + } + } else { + resolve(xhr.statusText); + } + } + }; + xhr.send(JSON.stringify(data)); +} \ No newline at end of file diff --git a/cfg.js.example b/cfg.js.example deleted file mode 100644 index d90ab73..0000000 --- a/cfg.js.example +++ /dev/null @@ -1,58 +0,0 @@ -import fs from "fs"; - -export default { - - VERSION: JSON.parse(fs.readFileSync("./package.json")).version, - - // show greeting - GREET: true, - // emit api calls - ENABLE_API: false, - - // Server settings - MAX_CONNECTIONS: 64, - PORT: 3000, - // If using vmware, vps or multiple network adapters, set the related ip here - // otherwise leave it blank - LOCAL_IP: "", - GAME_MODE: 0, - SAVE_INTERVAL: 6e4, - // Better dont touch these - TICK_INTERVAL: 1, - // Timeouts - BOOT_TIMEOUT: 1e4, - PLAYER_CONNECTION_TIMEOUT: 1e3 * 60 * 30, - MINIMUM_CLIENT_VERSION: "0.35.0", - DEFAULT_CONSOLE_COLOR: 32, - TRANSFER_ACCOUNTS: false, - - // Server debug options - DEBUG_DUMP_PATH: "logs/", - DEBUG_DUMP_TRAFFIC: true, - DEBUG_LOG_REQUESTS: true, - - // Choose a database type - DATABASE_TYPE: "MYSQL", - - // MySQL credentials - MYSQL_PORT: 3306, - MYSQL_HOST_IP: "127.0.0.1", - MYSQL_DB_NAME: "pogosql", - MYSQL_USERNAME: "root", - MYSQL_PASSWORD: "", - MYSQL_USERS_TABLE: "users", - MYSQL_OWNED_PKMN_TABLE: "owned_pkmn", - - // Used for asset download session - DOWNLOAD_PROVIDER: "GOOGLE", - DOWNLOAD_USERNAME: "USERNAME", - DOWNLOAD_PASSWORD: "PASSWORD", - - // Google maps api key - GMAPS_KEY: "AIzaSyDF9rkP8lhcddBtvH9gVFzjnNo13WtmJIM", - - // Currently supported pokemon - MAX_POKEMON_NATIONAL_ID: 151, - DUMP_ASSET_PATH: "data/" - -} \ No newline at end of file diff --git a/css/main.css b/css/main.css new file mode 100644 index 0000000..0ebe265 --- /dev/null +++ b/css/main.css @@ -0,0 +1,240 @@ +html { + -webkit-animation: fadein 1s; + -moz-animation: fadein 1s; + -ms-animation: fadein 1s; + -o-animation: fadein 1s; + animation: fadein 1s; +} + +body { + overflow-x: hidden; +} + +.view { + letter-spacing: 0px; + padding: 5px 25px !important; + margin-top: -35px; +} + +.area { + font-family: "Andale Mono", AndaleMono, monospace; + text-align: center; + font-style: normal; + font-variant: normal; + -webkit-font-smoothing: antialiased; + font-size: 75px; + letter-spacing: -5px; + color: #fff; + position: relative; + margin-top: 5px; + text-transform: uppercase; +} + +.Codemirror { + text-align: left; +} + +.version { + font-size: 15px; + letter-spacing: 0px; + margin-top: -75px; + margin-bottom: -25px; + text-transform: none; +} + +.btn { + text-transform: uppercase; +} + +.centered { + text-align: center; + position: relative; + top: 40%; + transform: translateY(-40%); + margin-top: -175px; + -webkit-transform: translateY(-40%); + -moz-transform: translateY(0%); +} + +@-moz-document url-prefix() { + .centered { + margin-top: 0px; + } +} + +.body { + background: #2d2d2d; + background-color: #2d2d2d; +} + +.star { + position: absolute; + width: 2px; + height: 2px; + background: rgba(255, 255, 255, 0.45); + opacity: 1; +} + +.btn { + font-family: "Andale Mono", AndaleMono, monospace; + display: inline-block; + padding: 5px; + border: 1px solid rgba(255, 255, 255, .35); + border-radius: 4px; + color: rgba(255, 255, 255, .75); + text-decoration: none; + transition: border .35s, background .35s; + min-width: 100px; + text-align: center; + font-size: 15px; + font-style: normal; + font-variant: normal; + font-weight: 500; + line-height: 25px; + cursor: pointer; +} + +.input { + background: rgba(0,0,0,0); + cursor: auto; +} + +input:focus { + outline: none; +} + +button:focus { + outline: none; +} + +.label { + background: rgba(255, 255, 255, .05); + border: 1px solid rgba(255, 255, 255, .5); + color: #79a2b7; +} + +.info { + padding-bottom: 45px; + margin-top: -45px; + font-size: 18px; + letter-spacing: 0px; +} + +.cmd_label { + border: none; + background: rgba(255,255,255,0.05); + color: white; + cursor: auto; + text-transform: none; +} + +.submit { + background: rgba(165, 165, 165, 0.15); +} + +.with_label { + margin-left: 25px; + width: 120px; +} + +#connection_status { + text-transform: uppercase; +} + +.login_area { + font-size: 25px; + letter-spacing: 0px; + text-transform: none; + margin: -25px; + padding: 0px; +} + +.login_input { + text-transform: none; + background: rgba(0,0,0,0); +} + +.noselect { + -webkit-touch-callout: none; + -webkit-user-select: none; + -khtml-user-select: none; + -moz-user-select: none; + -ms-user-select: none; + user-select: none; +} + +.btn:hover { + background: rgba(255, 255, 255, .05); + border: 1px solid rgba(255, 255, 255, .5); +} + +.txt { + margin-left: calc(20%); + margin-right: calc(20%); + left: auto; + width: auto; + min-height: 300px; + background: rgba(255, 255, 255, 0.0) !important; + border: 1px solid rgba(255, 255, 255, 0.0) !important; + border-radius: 4px !important; + padding: 10px 15px !important; + color: rgba(255, 255, 255, .75) !important; + resize: none; + transition: color .35s !important; +} + +.txt:focus { + outline: none; + color: rgba(255, 255, 255, .85); +} + +::-moz-selection { + color: rgba(255, 255, 255, .85); + background: rgba(255, 255, 255, .075); +} +::selection { + color: rgba(255, 255, 255, .85); + background: rgba(255, 255, 255, .075); +} + +::-webkit-scrollbar{ + width: 10px; + height: 0px; + background: transparent; +} +::-webkit-scrollbar-thumb{ + background: rgba(255, 255, 255, .15); + border-radius: 5px; +} +::-webkit-scrollbar-corner{ + background: transparent; +} + +@keyframes fadein { + from { opacity: 0; } + to { opacity: 1; } +} +@-webkit-keyframes fadein { + from { opacity: 0; } + to { opacity: 1; } +} +@-moz-keyframes fadein { + from { opacity: 0; } + to { opacity: 1; } +} + +@keyframes pulsate { + 0% {transform: scale(0.1, 0.1); opacity: 0.0;} + 50% {opacity: 1.0;} + 100% {transform: scale(1.2, 1.2); opacity: 0.0;} +} +@-webkit-keyframes pulsate { + 0% {-webkit-transform: scale(0.1, 0.1); opacity: 0.0;} + 50% {opacity: 1.0;} + 100% {-webkit-transform: scale(1.2, 1.2); opacity: 0.0;} +} +@-moz-keyframes pulsate { + 0% {transform: scale(0.1, 0.1); opacity: 0.0;} + 50% {opacity: 1.0;} + 100% {transform: scale(1.2, 1.2); opacity: 0.0;} +} \ No newline at end of file diff --git a/css/pure.min.css b/css/pure.min.css new file mode 100644 index 0000000..9730346 --- /dev/null +++ b/css/pure.min.css @@ -0,0 +1,23 @@ +/*! +Pure v0.6.0 +Copyright 2014 Yahoo! Inc. All rights reserved. +Licensed under the BSD License. +https://github.com/yahoo/pure/blob/master/LICENSE.md +*/ +/*! +normalize.css v^3.0 | MIT License | git.io/normalize +Copyright (c) Nicolas Gallagher and Jonathan Neal +*/ +/*! normalize.css v3.0.2 | MIT License | git.io/normalize */html{font-family:sans-serif;-ms-text-size-adjust:100%;-webkit-text-size-adjust:100%}body{margin:0}article,aside,details,figcaption,figure,footer,header,hgroup,main,menu,nav,section,summary{display:block}audio,canvas,progress,video{display:inline-block;vertical-align:baseline}audio:not([controls]){display:none;height:0}[hidden],template{display:none}a{background-color:transparent}a:active,a:hover{outline:0}abbr[title]{border-bottom:1px dotted}b,strong{font-weight:700}dfn{font-style:italic}h1{font-size:2em;margin:.67em 0}mark{background:#ff0;color:#000}small{font-size:80%}sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}sup{top:-.5em}sub{bottom:-.25em}img{border:0}svg:not(:root){overflow:hidden}figure{margin:1em 40px}hr{-moz-box-sizing:content-box;box-sizing:content-box;height:0}pre{overflow:auto}code,kbd,pre,samp{font-family:monospace,monospace;font-size:1em}button,input,optgroup,select,textarea{color:inherit;font:inherit;margin:0}button{overflow:visible}button,select{text-transform:none}button,html input[type=button],input[type=reset],input[type=submit]{-webkit-appearance:button;cursor:pointer}button[disabled],html input[disabled]{cursor:default}button::-moz-focus-inner,input::-moz-focus-inner{border:0;padding:0}input{line-height:normal}input[type=checkbox],input[type=radio]{box-sizing:border-box;padding:0}input[type=number]::-webkit-inner-spin-button,input[type=number]::-webkit-outer-spin-button{height:auto}input[type=search]{-webkit-appearance:textfield;-moz-box-sizing:content-box;-webkit-box-sizing:content-box;box-sizing:content-box}input[type=search]::-webkit-search-cancel-button,input[type=search]::-webkit-search-decoration{-webkit-appearance:none}fieldset{border:1px solid silver;margin:0 2px;padding:.35em .625em .75em}legend{border:0;padding:0}textarea{overflow:auto}optgroup{font-weight:700}table{border-collapse:collapse;border-spacing:0}td,th{padding:0}.hidden,[hidden]{display:none!important}.pure-img{max-width:100%;height:auto;display:block}/*! +Pure v0.6.0 +Copyright 2014 Yahoo! Inc. All rights reserved. +Licensed under the BSD License. +https://github.com/yahoo/pure/blob/master/LICENSE.md +*/ +.pure-g{letter-spacing:-.31em;*letter-spacing:normal;*word-spacing:-.43em;text-rendering:optimizespeed;font-family:FreeSans,Arimo,"Droid Sans",Helvetica,Arial,sans-serif;display:-webkit-flex;-webkit-flex-flow:row wrap;display:-ms-flexbox;-ms-flex-flow:row wrap;-ms-align-content:flex-start;-webkit-align-content:flex-start;align-content:flex-start}.opera-only :-o-prefocus,.pure-g{word-spacing:-.43em}.pure-u{display:inline-block;*display:inline;zoom:1;letter-spacing:normal;word-spacing:normal;vertical-align:top;text-rendering:auto}.pure-g [class *="pure-u"]{font-family:sans-serif}.pure-u-1,.pure-u-1-1,.pure-u-1-2,.pure-u-1-3,.pure-u-2-3,.pure-u-1-4,.pure-u-3-4,.pure-u-1-5,.pure-u-2-5,.pure-u-3-5,.pure-u-4-5,.pure-u-5-5,.pure-u-1-6,.pure-u-5-6,.pure-u-1-8,.pure-u-3-8,.pure-u-5-8,.pure-u-7-8,.pure-u-1-12,.pure-u-5-12,.pure-u-7-12,.pure-u-11-12,.pure-u-1-24,.pure-u-2-24,.pure-u-3-24,.pure-u-4-24,.pure-u-5-24,.pure-u-6-24,.pure-u-7-24,.pure-u-8-24,.pure-u-9-24,.pure-u-10-24,.pure-u-11-24,.pure-u-12-24,.pure-u-13-24,.pure-u-14-24,.pure-u-15-24,.pure-u-16-24,.pure-u-17-24,.pure-u-18-24,.pure-u-19-24,.pure-u-20-24,.pure-u-21-24,.pure-u-22-24,.pure-u-23-24,.pure-u-24-24{display:inline-block;*display:inline;zoom:1;letter-spacing:normal;word-spacing:normal;vertical-align:top;text-rendering:auto}.pure-u-1-24{width:4.1667%;*width:4.1357%}.pure-u-1-12,.pure-u-2-24{width:8.3333%;*width:8.3023%}.pure-u-1-8,.pure-u-3-24{width:12.5%;*width:12.469%}.pure-u-1-6,.pure-u-4-24{width:16.6667%;*width:16.6357%}.pure-u-1-5{width:20%;*width:19.969%}.pure-u-5-24{width:20.8333%;*width:20.8023%}.pure-u-1-4,.pure-u-6-24{width:25%;*width:24.969%}.pure-u-7-24{width:29.1667%;*width:29.1357%}.pure-u-1-3,.pure-u-8-24{width:33.3333%;*width:33.3023%}.pure-u-3-8,.pure-u-9-24{width:37.5%;*width:37.469%}.pure-u-2-5{width:40%;*width:39.969%}.pure-u-5-12,.pure-u-10-24{width:41.6667%;*width:41.6357%}.pure-u-11-24{width:45.8333%;*width:45.8023%}.pure-u-1-2,.pure-u-12-24{width:50%;*width:49.969%}.pure-u-13-24{width:54.1667%;*width:54.1357%}.pure-u-7-12,.pure-u-14-24{width:58.3333%;*width:58.3023%}.pure-u-3-5{width:60%;*width:59.969%}.pure-u-5-8,.pure-u-15-24{width:62.5%;*width:62.469%}.pure-u-2-3,.pure-u-16-24{width:66.6667%;*width:66.6357%}.pure-u-17-24{width:70.8333%;*width:70.8023%}.pure-u-3-4,.pure-u-18-24{width:75%;*width:74.969%}.pure-u-19-24{width:79.1667%;*width:79.1357%}.pure-u-4-5{width:80%;*width:79.969%}.pure-u-5-6,.pure-u-20-24{width:83.3333%;*width:83.3023%}.pure-u-7-8,.pure-u-21-24{width:87.5%;*width:87.469%}.pure-u-11-12,.pure-u-22-24{width:91.6667%;*width:91.6357%}.pure-u-23-24{width:95.8333%;*width:95.8023%}.pure-u-1,.pure-u-1-1,.pure-u-5-5,.pure-u-24-24{width:100%}/*! +Pure v0.6.0 +Copyright 2014 Yahoo! Inc. All rights reserved. +Licensed under the BSD License. +https://github.com/yahoo/pure/blob/master/LICENSE.md +*/ +@media screen and (min-width:35.5em){.pure-u-sm-1,.pure-u-sm-1-1,.pure-u-sm-1-2,.pure-u-sm-1-3,.pure-u-sm-2-3,.pure-u-sm-1-4,.pure-u-sm-3-4,.pure-u-sm-1-5,.pure-u-sm-2-5,.pure-u-sm-3-5,.pure-u-sm-4-5,.pure-u-sm-5-5,.pure-u-sm-1-6,.pure-u-sm-5-6,.pure-u-sm-1-8,.pure-u-sm-3-8,.pure-u-sm-5-8,.pure-u-sm-7-8,.pure-u-sm-1-12,.pure-u-sm-5-12,.pure-u-sm-7-12,.pure-u-sm-11-12,.pure-u-sm-1-24,.pure-u-sm-2-24,.pure-u-sm-3-24,.pure-u-sm-4-24,.pure-u-sm-5-24,.pure-u-sm-6-24,.pure-u-sm-7-24,.pure-u-sm-8-24,.pure-u-sm-9-24,.pure-u-sm-10-24,.pure-u-sm-11-24,.pure-u-sm-12-24,.pure-u-sm-13-24,.pure-u-sm-14-24,.pure-u-sm-15-24,.pure-u-sm-16-24,.pure-u-sm-17-24,.pure-u-sm-18-24,.pure-u-sm-19-24,.pure-u-sm-20-24,.pure-u-sm-21-24,.pure-u-sm-22-24,.pure-u-sm-23-24,.pure-u-sm-24-24{display:inline-block;*display:inline;zoom:1;letter-spacing:normal;word-spacing:normal;vertical-align:top;text-rendering:auto}.pure-u-sm-1-24{width:4.1667%;*width:4.1357%}.pure-u-sm-1-12,.pure-u-sm-2-24{width:8.3333%;*width:8.3023%}.pure-u-sm-1-8,.pure-u-sm-3-24{width:12.5%;*width:12.469%}.pure-u-sm-1-6,.pure-u-sm-4-24{width:16.6667%;*width:16.6357%}.pure-u-sm-1-5{width:20%;*width:19.969%}.pure-u-sm-5-24{width:20.8333%;*width:20.8023%}.pure-u-sm-1-4,.pure-u-sm-6-24{width:25%;*width:24.969%}.pure-u-sm-7-24{width:29.1667%;*width:29.1357%}.pure-u-sm-1-3,.pure-u-sm-8-24{width:33.3333%;*width:33.3023%}.pure-u-sm-3-8,.pure-u-sm-9-24{width:37.5%;*width:37.469%}.pure-u-sm-2-5{width:40%;*width:39.969%}.pure-u-sm-5-12,.pure-u-sm-10-24{width:41.6667%;*width:41.6357%}.pure-u-sm-11-24{width:45.8333%;*width:45.8023%}.pure-u-sm-1-2,.pure-u-sm-12-24{width:50%;*width:49.969%}.pure-u-sm-13-24{width:54.1667%;*width:54.1357%}.pure-u-sm-7-12,.pure-u-sm-14-24{width:58.3333%;*width:58.3023%}.pure-u-sm-3-5{width:60%;*width:59.969%}.pure-u-sm-5-8,.pure-u-sm-15-24{width:62.5%;*width:62.469%}.pure-u-sm-2-3,.pure-u-sm-16-24{width:66.6667%;*width:66.6357%}.pure-u-sm-17-24{width:70.8333%;*width:70.8023%}.pure-u-sm-3-4,.pure-u-sm-18-24{width:75%;*width:74.969%}.pure-u-sm-19-24{width:79.1667%;*width:79.1357%}.pure-u-sm-4-5{width:80%;*width:79.969%}.pure-u-sm-5-6,.pure-u-sm-20-24{width:83.3333%;*width:83.3023%}.pure-u-sm-7-8,.pure-u-sm-21-24{width:87.5%;*width:87.469%}.pure-u-sm-11-12,.pure-u-sm-22-24{width:91.6667%;*width:91.6357%}.pure-u-sm-23-24{width:95.8333%;*width:95.8023%}.pure-u-sm-1,.pure-u-sm-1-1,.pure-u-sm-5-5,.pure-u-sm-24-24{width:100%}}@media screen and (min-width:48em){.pure-u-md-1,.pure-u-md-1-1,.pure-u-md-1-2,.pure-u-md-1-3,.pure-u-md-2-3,.pure-u-md-1-4,.pure-u-md-3-4,.pure-u-md-1-5,.pure-u-md-2-5,.pure-u-md-3-5,.pure-u-md-4-5,.pure-u-md-5-5,.pure-u-md-1-6,.pure-u-md-5-6,.pure-u-md-1-8,.pure-u-md-3-8,.pure-u-md-5-8,.pure-u-md-7-8,.pure-u-md-1-12,.pure-u-md-5-12,.pure-u-md-7-12,.pure-u-md-11-12,.pure-u-md-1-24,.pure-u-md-2-24,.pure-u-md-3-24,.pure-u-md-4-24,.pure-u-md-5-24,.pure-u-md-6-24,.pure-u-md-7-24,.pure-u-md-8-24,.pure-u-md-9-24,.pure-u-md-10-24,.pure-u-md-11-24,.pure-u-md-12-24,.pure-u-md-13-24,.pure-u-md-14-24,.pure-u-md-15-24,.pure-u-md-16-24,.pure-u-md-17-24,.pure-u-md-18-24,.pure-u-md-19-24,.pure-u-md-20-24,.pure-u-md-21-24,.pure-u-md-22-24,.pure-u-md-23-24,.pure-u-md-24-24{display:inline-block;*display:inline;zoom:1;letter-spacing:normal;word-spacing:normal;vertical-align:top;text-rendering:auto}.pure-u-md-1-24{width:4.1667%;*width:4.1357%}.pure-u-md-1-12,.pure-u-md-2-24{width:8.3333%;*width:8.3023%}.pure-u-md-1-8,.pure-u-md-3-24{width:12.5%;*width:12.469%}.pure-u-md-1-6,.pure-u-md-4-24{width:16.6667%;*width:16.6357%}.pure-u-md-1-5{width:20%;*width:19.969%}.pure-u-md-5-24{width:20.8333%;*width:20.8023%}.pure-u-md-1-4,.pure-u-md-6-24{width:25%;*width:24.969%}.pure-u-md-7-24{width:29.1667%;*width:29.1357%}.pure-u-md-1-3,.pure-u-md-8-24{width:33.3333%;*width:33.3023%}.pure-u-md-3-8,.pure-u-md-9-24{width:37.5%;*width:37.469%}.pure-u-md-2-5{width:40%;*width:39.969%}.pure-u-md-5-12,.pure-u-md-10-24{width:41.6667%;*width:41.6357%}.pure-u-md-11-24{width:45.8333%;*width:45.8023%}.pure-u-md-1-2,.pure-u-md-12-24{width:50%;*width:49.969%}.pure-u-md-13-24{width:54.1667%;*width:54.1357%}.pure-u-md-7-12,.pure-u-md-14-24{width:58.3333%;*width:58.3023%}.pure-u-md-3-5{width:60%;*width:59.969%}.pure-u-md-5-8,.pure-u-md-15-24{width:62.5%;*width:62.469%}.pure-u-md-2-3,.pure-u-md-16-24{width:66.6667%;*width:66.6357%}.pure-u-md-17-24{width:70.8333%;*width:70.8023%}.pure-u-md-3-4,.pure-u-md-18-24{width:75%;*width:74.969%}.pure-u-md-19-24{width:79.1667%;*width:79.1357%}.pure-u-md-4-5{width:80%;*width:79.969%}.pure-u-md-5-6,.pure-u-md-20-24{width:83.3333%;*width:83.3023%}.pure-u-md-7-8,.pure-u-md-21-24{width:87.5%;*width:87.469%}.pure-u-md-11-12,.pure-u-md-22-24{width:91.6667%;*width:91.6357%}.pure-u-md-23-24{width:95.8333%;*width:95.8023%}.pure-u-md-1,.pure-u-md-1-1,.pure-u-md-5-5,.pure-u-md-24-24{width:100%}}@media screen and (min-width:64em){.pure-u-lg-1,.pure-u-lg-1-1,.pure-u-lg-1-2,.pure-u-lg-1-3,.pure-u-lg-2-3,.pure-u-lg-1-4,.pure-u-lg-3-4,.pure-u-lg-1-5,.pure-u-lg-2-5,.pure-u-lg-3-5,.pure-u-lg-4-5,.pure-u-lg-5-5,.pure-u-lg-1-6,.pure-u-lg-5-6,.pure-u-lg-1-8,.pure-u-lg-3-8,.pure-u-lg-5-8,.pure-u-lg-7-8,.pure-u-lg-1-12,.pure-u-lg-5-12,.pure-u-lg-7-12,.pure-u-lg-11-12,.pure-u-lg-1-24,.pure-u-lg-2-24,.pure-u-lg-3-24,.pure-u-lg-4-24,.pure-u-lg-5-24,.pure-u-lg-6-24,.pure-u-lg-7-24,.pure-u-lg-8-24,.pure-u-lg-9-24,.pure-u-lg-10-24,.pure-u-lg-11-24,.pure-u-lg-12-24,.pure-u-lg-13-24,.pure-u-lg-14-24,.pure-u-lg-15-24,.pure-u-lg-16-24,.pure-u-lg-17-24,.pure-u-lg-18-24,.pure-u-lg-19-24,.pure-u-lg-20-24,.pure-u-lg-21-24,.pure-u-lg-22-24,.pure-u-lg-23-24,.pure-u-lg-24-24{display:inline-block;*display:inline;zoom:1;letter-spacing:normal;word-spacing:normal;vertical-align:top;text-rendering:auto}.pure-u-lg-1-24{width:4.1667%;*width:4.1357%}.pure-u-lg-1-12,.pure-u-lg-2-24{width:8.3333%;*width:8.3023%}.pure-u-lg-1-8,.pure-u-lg-3-24{width:12.5%;*width:12.469%}.pure-u-lg-1-6,.pure-u-lg-4-24{width:16.6667%;*width:16.6357%}.pure-u-lg-1-5{width:20%;*width:19.969%}.pure-u-lg-5-24{width:20.8333%;*width:20.8023%}.pure-u-lg-1-4,.pure-u-lg-6-24{width:25%;*width:24.969%}.pure-u-lg-7-24{width:29.1667%;*width:29.1357%}.pure-u-lg-1-3,.pure-u-lg-8-24{width:33.3333%;*width:33.3023%}.pure-u-lg-3-8,.pure-u-lg-9-24{width:37.5%;*width:37.469%}.pure-u-lg-2-5{width:40%;*width:39.969%}.pure-u-lg-5-12,.pure-u-lg-10-24{width:41.6667%;*width:41.6357%}.pure-u-lg-11-24{width:45.8333%;*width:45.8023%}.pure-u-lg-1-2,.pure-u-lg-12-24{width:50%;*width:49.969%}.pure-u-lg-13-24{width:54.1667%;*width:54.1357%}.pure-u-lg-7-12,.pure-u-lg-14-24{width:58.3333%;*width:58.3023%}.pure-u-lg-3-5{width:60%;*width:59.969%}.pure-u-lg-5-8,.pure-u-lg-15-24{width:62.5%;*width:62.469%}.pure-u-lg-2-3,.pure-u-lg-16-24{width:66.6667%;*width:66.6357%}.pure-u-lg-17-24{width:70.8333%;*width:70.8023%}.pure-u-lg-3-4,.pure-u-lg-18-24{width:75%;*width:74.969%}.pure-u-lg-19-24{width:79.1667%;*width:79.1357%}.pure-u-lg-4-5{width:80%;*width:79.969%}.pure-u-lg-5-6,.pure-u-lg-20-24{width:83.3333%;*width:83.3023%}.pure-u-lg-7-8,.pure-u-lg-21-24{width:87.5%;*width:87.469%}.pure-u-lg-11-12,.pure-u-lg-22-24{width:91.6667%;*width:91.6357%}.pure-u-lg-23-24{width:95.8333%;*width:95.8023%}.pure-u-lg-1,.pure-u-lg-1-1,.pure-u-lg-5-5,.pure-u-lg-24-24{width:100%}}@media screen and (min-width:80em){.pure-u-xl-1,.pure-u-xl-1-1,.pure-u-xl-1-2,.pure-u-xl-1-3,.pure-u-xl-2-3,.pure-u-xl-1-4,.pure-u-xl-3-4,.pure-u-xl-1-5,.pure-u-xl-2-5,.pure-u-xl-3-5,.pure-u-xl-4-5,.pure-u-xl-5-5,.pure-u-xl-1-6,.pure-u-xl-5-6,.pure-u-xl-1-8,.pure-u-xl-3-8,.pure-u-xl-5-8,.pure-u-xl-7-8,.pure-u-xl-1-12,.pure-u-xl-5-12,.pure-u-xl-7-12,.pure-u-xl-11-12,.pure-u-xl-1-24,.pure-u-xl-2-24,.pure-u-xl-3-24,.pure-u-xl-4-24,.pure-u-xl-5-24,.pure-u-xl-6-24,.pure-u-xl-7-24,.pure-u-xl-8-24,.pure-u-xl-9-24,.pure-u-xl-10-24,.pure-u-xl-11-24,.pure-u-xl-12-24,.pure-u-xl-13-24,.pure-u-xl-14-24,.pure-u-xl-15-24,.pure-u-xl-16-24,.pure-u-xl-17-24,.pure-u-xl-18-24,.pure-u-xl-19-24,.pure-u-xl-20-24,.pure-u-xl-21-24,.pure-u-xl-22-24,.pure-u-xl-23-24,.pure-u-xl-24-24{display:inline-block;*display:inline;zoom:1;letter-spacing:normal;word-spacing:normal;vertical-align:top;text-rendering:auto}.pure-u-xl-1-24{width:4.1667%;*width:4.1357%}.pure-u-xl-1-12,.pure-u-xl-2-24{width:8.3333%;*width:8.3023%}.pure-u-xl-1-8,.pure-u-xl-3-24{width:12.5%;*width:12.469%}.pure-u-xl-1-6,.pure-u-xl-4-24{width:16.6667%;*width:16.6357%}.pure-u-xl-1-5{width:20%;*width:19.969%}.pure-u-xl-5-24{width:20.8333%;*width:20.8023%}.pure-u-xl-1-4,.pure-u-xl-6-24{width:25%;*width:24.969%}.pure-u-xl-7-24{width:29.1667%;*width:29.1357%}.pure-u-xl-1-3,.pure-u-xl-8-24{width:33.3333%;*width:33.3023%}.pure-u-xl-3-8,.pure-u-xl-9-24{width:37.5%;*width:37.469%}.pure-u-xl-2-5{width:40%;*width:39.969%}.pure-u-xl-5-12,.pure-u-xl-10-24{width:41.6667%;*width:41.6357%}.pure-u-xl-11-24{width:45.8333%;*width:45.8023%}.pure-u-xl-1-2,.pure-u-xl-12-24{width:50%;*width:49.969%}.pure-u-xl-13-24{width:54.1667%;*width:54.1357%}.pure-u-xl-7-12,.pure-u-xl-14-24{width:58.3333%;*width:58.3023%}.pure-u-xl-3-5{width:60%;*width:59.969%}.pure-u-xl-5-8,.pure-u-xl-15-24{width:62.5%;*width:62.469%}.pure-u-xl-2-3,.pure-u-xl-16-24{width:66.6667%;*width:66.6357%}.pure-u-xl-17-24{width:70.8333%;*width:70.8023%}.pure-u-xl-3-4,.pure-u-xl-18-24{width:75%;*width:74.969%}.pure-u-xl-19-24{width:79.1667%;*width:79.1357%}.pure-u-xl-4-5{width:80%;*width:79.969%}.pure-u-xl-5-6,.pure-u-xl-20-24{width:83.3333%;*width:83.3023%}.pure-u-xl-7-8,.pure-u-xl-21-24{width:87.5%;*width:87.469%}.pure-u-xl-11-12,.pure-u-xl-22-24{width:91.6667%;*width:91.6357%}.pure-u-xl-23-24{width:95.8333%;*width:95.8023%}.pure-u-xl-1,.pure-u-xl-1-1,.pure-u-xl-5-5,.pure-u-xl-24-24{width:100%}} \ No newline at end of file diff --git a/index.html b/index.html new file mode 100644 index 0000000..46f92db --- /dev/null +++ b/index.html @@ -0,0 +1,39 @@ + + + + + + + + POGOserver api + + + + + + +
+

POGOserver

+

 

+

+
+ +
+

Login

+

+

+

+
+ + + + + + + + \ No newline at end of file diff --git a/install-windows.bat b/install-windows.bat deleted file mode 100644 index b69e8ac..0000000 --- a/install-windows.bat +++ /dev/null @@ -1,2 +0,0 @@ -set LIBPROTOBUF=%CD%\protobuf -npm install node-protobuf && npm install \ No newline at end of file diff --git a/main.js b/main.js new file mode 100644 index 0000000..9cd6e5c --- /dev/null +++ b/main.js @@ -0,0 +1,72 @@ +var loggedIn = false; +var loginTimeout = null; + +function setStatus(txt, color) { + connection_status.innerHTML = txt; + connection_status.style.color = color; +} + +setStatus("Connecting", "yellow"); + +send({ + action: "init" +}, function(res) { + if (res.success) { + setStatus("Connected!", "green"); + } + else { + setStatus("Connection failed!", "red"); + return void 0; + } +}); + +login_attempt.addEventListener("click", function() { + + var username = login_username.value; + var password = login_password.value; + + send({ + action: "login", + username: username, + password: password + }, function(res) { + if (res.success) { + login(); + } + else { + setStatus("Login failed!", "red"); + clearTimeout(loginTimeout); + loginTimeout = setTimeout(function() { + setStatus("Connected!", "green"); + }, 3e3); + } + }); + +}); + +submit_spawn.addEventListener("click", function() { + send({ + action: "spawnPkmnToPlayer", + player: spawn_user.value, + pkmn: spawn_pkmn.value + }, function(res) { + console.log(res); + }); +}); + +function login() { + loggedIn = true; + login_area.style.display = "none"; + setStatus("Logged in!", "green"); + world_manager.style.display = "block"; + send({ + action: "getConnectedPlayers" + }, function(res) { + connected_players.innerHTML = "Connected players: " + res.connected_players; + }); + send({ + action: "getServerVersion" + }, function(res) { + server_version.innerHTML = "Server version: v" + res.version; + }); +} \ No newline at end of file diff --git a/package.json b/package.json deleted file mode 100644 index d089a87..0000000 --- a/package.json +++ /dev/null @@ -1,32 +0,0 @@ -{ - "name": "POGOServer", - "version": "0.5.0", - "description": "", - "repository": { - "type": "git", - "url": "git://github.com/maierfelix/POGOServer.git" - }, - "scripts": { - "test": "echo \"Error: no test specified\"", - "babel-node": "babel-node --presets=es2015", - "start": "npm run babel-node -- ./src/index.js" - }, - "engines": { - "node": ">= 6.x", - "npm": ">= 3.x" - }, - "author": "Felix Maier", - "license": "MIT", - "dependencies": { - "babel-cli": "^6.11.4", - "babel-preset-es2015": "^6.13.1", - "babel-preset-stage-0": "^6.5.0", - "fs-extra": "^0.30.0", - "mysql": "^2.11.1", - "jwt-decode": "^2.1.0", - "pogo-asset-downloader": "^0.3.1", - "pokemongo-protobuf": "^1.11.0", - "pcrypt": "git+https://github.com/laverdet/pcrypt.git" - }, - "devDependencies": {} -} \ No newline at end of file diff --git a/run-linux.sh b/run-linux.sh deleted file mode 100644 index 93cae92..0000000 --- a/run-linux.sh +++ /dev/null @@ -1,10 +0,0 @@ -#!/bin/bash - -pause() { - read -p "Press [Enter] key to exit" -} - -cd $(dirname $0) - -npm install -npm run start \ No newline at end of file diff --git a/run-windows.bat b/run-windows.bat deleted file mode 100644 index 0c6c316..0000000 --- a/run-windows.bat +++ /dev/null @@ -1,2 +0,0 @@ -npm run start -pause \ No newline at end of file diff --git a/src/api.js b/src/api.js deleted file mode 100644 index 121f8a4..0000000 --- a/src/api.js +++ /dev/null @@ -1,44 +0,0 @@ -import CFG from "../cfg"; - -export function ready(e) { - if (e) console.log(e); - else console.log("Ready!"); -} - -/** - * @param {String} msg - * @param {Number} color - * @param {Boolean} nl - */ -export function print(msg, color, newline) { - color = Number.isInteger(color) ? color : CFG.DEFAULT_CONSOLE_COLOR; - process.stdout.write(`[Console] \x1b[${color};1m${msg}\x1b[0m${newline === void 0 ? "\n" : ""}`); -} - -/** - * @param {Player} player - */ -export function registerPlayer(player) { - console.log(player.username + " registered!"); -} - -/** - * @param {Player} player - */ -export function loginPlayer(player) { - console.log(player.username + " logged in!"); -} - -/** - * @param {Player} player - */ -export function killPlayer(player) { - console.log(player.username + " killed!"); -} - -/** - * @param {Player} player - */ -export function updatePlayerAvatar(player) { - console.log("Updated avatar of " + player.username + "!"); -} \ No newline at end of file diff --git a/src/cycle.js b/src/cycle.js deleted file mode 100644 index abdc078..0000000 --- a/src/cycle.js +++ /dev/null @@ -1,75 +0,0 @@ -import CFG from "../cfg"; - -export function startCycle() { - this.cycleInstance = setTimeout(() => this.cycle(), CFG.TICK_INTERVAL); -} - -export function stopCycle() { - clearTimeout(this.cycleInstance); -} - -export function cycle() { - - this.stopCycle(); - this.startCycle(); - - if (this.STATES.PAUSE === true) return void 0; - if (this.STATES.CRASH === true) return void 0; - - this.updateTimers(); - - if (this.passedTicks <= 0) return void 0; - - this.resetTimers(); - - return void 0; - -} - -export function updateTimers() { - let local = Date.now(); - this.passedTicks = local - this.time; - this.tick += this.passedTicks; - this.time = local; - return void 0; -} - -export function resetTimers() { - if (this.tick >= 25) { - this.fullTick++; - if (this.fullTick >= 2) { - this.fullTick = 0; - } - this.tick = 0; - // Player timeout tick, not precise - this.playerTimeoutTick(); - } - this.saveTick++; - // Save interval - if (this.saveTick >= CFG.SAVE_INTERVAL) { - //this.saveAllPlayers(); - this.saveTick = 0; - } - return void 0; -} - -export function playerTimeoutTick() { - - let player = null; - let maxTimeout = CFG.PLAYER_CONNECTION_TIMEOUT; - - let players = this.world.players; - - let ii = 0; - let length = players.length; - - for (; ii < length; ++ii) { - player = players[ii]; - if (this.time - player.timeout >= maxTimeout) { - this.print(`${player.remoteAddress} timed out`, 34); - this.savePlayer(player); - this.removePlayer(player); - } - }; - -} \ No newline at end of file diff --git a/src/db/create.js b/src/db/create.js deleted file mode 100644 index dd2ae45..0000000 --- a/src/db/create.js +++ /dev/null @@ -1,48 +0,0 @@ -import fs from "fs"; -import CFG from "../../cfg"; - -export function createTableIfNotExists(name) { - return new Promise((resolve) => { - this.db.instance.query(`SHOW TABLES LIKE '${name}';`, (e, rows, fields) => { - if (e) console.log(e); - else { - // exists - if (rows && rows.length) resolve(); - // create user table - else this.createTables().then(resolve); - } - }); - }); -} - -/** - * @param {String} name - */ -export function createTables() { - return new Promise((resolve) => { - this.createTable(CFG.MYSQL_USERS_TABLE).then(() => { - this.createTable(CFG.MYSQL_OWNED_PKMN_TABLE).then(() => { - resolve(); - }); - }); - }); -} - -export function createTable(name) { - - this.print(`Creating table ${name}`, 36); - - let query = ` - CREATE TABLE IF NOT EXISTS ${name} ( - ${fs.readFileSync(__dirname + "/tables/" + name + ".table", "utf8")} - ) ENGINE=InnoDB; - `; - - return new Promise((resolve) => { - this.db.instance.query(query, (e, rows) => { - if (e) console.log(e); - else resolve(); - }); - }); - -} \ No newline at end of file diff --git a/src/db/get.js b/src/db/get.js deleted file mode 100644 index 3d9b9af..0000000 --- a/src/db/get.js +++ /dev/null @@ -1,30 +0,0 @@ -import CFG from "../../cfg"; - -/** - * @param {String} column - * @param {String} value - * @param {String} table - */ -export function getQueryByColumnFromTable(column, value, table) { - return new Promise((resolve) => { - this.db.instance.query(`SELECT * FROM ${table} WHERE ${column}=?`, [value], (e, rows) => { - if (e) console.log(e); - if (rows && rows.length) resolve(rows); - else resolve(void 0); - }); - }); -} - -/** - * @param {String} column - * @param {String} value - * @param {String} table - */ -export function deleteQueryByColumnFromTable(column, value, table) { - return new Promise((resolve) => { - this.db.instance.query(`DELETE FROM ${table} WHERE ${column}=?`, [value], (e, rows) => { - if (e) console.log(e); - else resolve(void 0); - }); - }); -} \ No newline at end of file diff --git a/src/db/index.js b/src/db/index.js deleted file mode 100644 index 2e6f41b..0000000 --- a/src/db/index.js +++ /dev/null @@ -1,45 +0,0 @@ -import mysql from "mysql"; - -import CFG from "../../cfg"; - -export function setupDatabaseConnection() { - - let connection = mysql.createConnection({ - host : CFG.MYSQL_HOST_IP, - port : CFG.MYSQL_PORT, - database : CFG.MYSQL_DB_NAME, - user : CFG.MYSQL_USERNAME, - password : CFG.MYSQL_PASSWORD - }); - - return new Promise((resolve) => { - connection.connect((error) => { - if (error) { - this.print("MySQL " + error, 31); - this.retry("Retrying again in ", () => this.setupDatabaseConnection().then(resolve), 5); - return void 0; - } - this.db.instance = connection; - this.createTableIfNotExists(CFG.MYSQL_USERS_TABLE).then(() => { - this.createTableIfNotExists(CFG.MYSQL_OWNED_PKMN_TABLE).then(() => { - this.print(`\x1b[36;1mMySQL\x1b[0m\x1b[32;1m connection established\x1b[0m`); - resolve(); - }); - }); - }); - connection.on("error", (error) => { - this.print("MySQL " + error, 31); - this.retry("Trying to reconnect in ", () => this.setupDatabaseConnection().then(resolve), 5); - }); - }); - -} - -/** - * @param {Function} resolve - */ -export function closeConnection(resolve) { - this.db.instance.end(() => { - resolve(); - }); -} \ No newline at end of file diff --git a/src/db/query.js b/src/db/query.js deleted file mode 100644 index 336552a..0000000 --- a/src/db/query.js +++ /dev/null @@ -1,227 +0,0 @@ -import CFG from "../../cfg"; - -/** - * @return {String} - */ -export function getUserQuery(cmd, after) { - return (` - ${cmd} ${CFG.MYSQL_USERS_TABLE} - SET - username=?, - email=?, - exp=?, - level=?, - stardust=?, - pokecoins=?, - team=?, - latitude=?, - longitude=?, - altitude=?, - send_marketing_emails=?, - send_push_notifications=?, - skin=?, - hair=?, - shirt=?, - pants=?, - hat=?, - shoes=?, - eyes=?, - gender=?, - backpack=? - ${after} - `); -} - -/** - * @param {Object} obj - * @return {Array} - */ -export function getUserQueryData(obj) { - return ([ - obj.username, - obj.email, - obj.exp, - obj.level, - obj.stardust, - obj.pokecoins, - obj.team, - // position - obj.latitude, - obj.longitude, - obj.altitude, - // contact settings - obj.send_marketing_emails, - obj.send_push_notifications, - // avatar - obj.skin, - obj.hair, - obj.shirt, - obj.pants, - obj.hat, - obj.shoes, - obj.eyes, - obj.gender, - obj.backpack, - // WHERE - obj.email - ]); -} - -/** - * @return {String} - */ -export function getOwnedPkmnQuery(cmd, after) { - return (` - ${cmd} ${CFG.MYSQL_OWNED_PKMN_TABLE} - SET - owner_id=?, - pokemon_id=?, - cp=?, - stamina=?, - stamina_max=?, - move_1=?, - move_2=?, - deployed_fort_id=?, - is_egg=?, - egg_km_walked_target=?, - egg_km_walked_start=?, - origin=?, - height_m=?, - weight_kg=?, - individual_attack=?, - individual_defense=?, - individual_stamina=?, - cp_multiplier=?, - pokeball=?, - captured_cell_id=?, - battles_attacked=?, - battles_defended=?, - egg_incubator_id=?, - creation_time_ms=?, - num_upgrades=?, - additional_cp_multiplier=?, - favorite=?, - nickname=?, - from_fort=? - ${after} - `); -} - -/** - * @param {Object} obj - * @return {Array} - */ -export function getOwnedPkmnQueryData(obj) { - return ([ - obj.owner_id, - obj.pokemon_id, - obj.cp, - obj.stamina, - obj.stamina_max, - obj.move_1, - obj.move_2, - obj.deployed_fort_id || "", - obj.is_egg || 0, - obj.egg_km_walked_target || 0, - obj.egg_km_walked_start || 0, - obj.origin || 0, - obj.height_m, - obj.weight_kg, - obj.individual_attack, - obj.individual_defense, - obj.individual_stamina, - obj.cp_multiplier, - obj.pokeball, - obj.captured_cell_id || 0, - obj.battles_attacked || 0, - obj.battles_defended || 0, - obj.egg_incubator_id || "", - obj.creation_time_ms, - obj.num_upgrades || 0, - obj.additional_cp_multiplier || 0, - obj.favorite || 0, - obj.nickname || "", - obj.from_fort || 0 - ]); -} - -export function getUserItemQuery(cmd, after) { - return (` - ${cmd} ${CFG.MYSQL_USERS_TABLE} - SET - item_poke_ball=?, - item_great_ball=?, - item_ultra_ball=?, - item_master_ball=?, - item_potion=?, - item_super_potion=?, - item_hyper_potion=?, - item_max_potion=?, - item_revive=?, - item_max_revive=?, - item_lucky_egg=?, - item_incense_ordinary=?, - item_incense_spicy=?, - item_incense_cool=?, - item_incense_floral=?, - item_troy_disk=?, - item_razz_berry=?, - item_bluk_berry=?, - item_nanab_berry=?, - item_wepar_berry=?, - item_pinap_berry=?, - item_incubator_basic=?, - item_incubator_basic_unlimited=?, - item_pokemon_storage_upgrade=?, - item_storage_upgrade=? - ${after} - `); -} - -/** - * @param {Object} obj - * @return {Array} - */ -export function getUserItemQueryData(obj) { - - let items = []; - - for (let key in obj.items) { - items.push(obj.items[key]); - }; - - let email = obj.email; - - obj = obj.items; - - return ([ - obj.poke_ball, - obj.great_ball, - obj.ultra_ball, - obj.master_ball, - obj.potion, - obj.super_potion, - obj.hyper_potion, - obj.max_potion, - obj.revive, - obj.max_revive, - obj.lucky_egg, - obj.incense_ordinary, - obj.incense_spicy, - obj.incense_cool, - obj.incense_floral, - obj.troy_disk, - obj.razz_berry, - obj.bluk_berry, - obj.nanab_berry, - obj.wepar_berry, - obj.pinap_berry, - obj.incubator_basic, - obj.incubator_basic_unlimited, - obj.pokemon_storage_upgrade, - obj.storage_upgrade, - // WHERE - email - ]); - -} \ No newline at end of file diff --git a/src/db/tables/owned_pkmn.table b/src/db/tables/owned_pkmn.table deleted file mode 100644 index 9f5437d..0000000 --- a/src/db/tables/owned_pkmn.table +++ /dev/null @@ -1,31 +0,0 @@ -id int(11) NOT NULL AUTO_INCREMENT, -owner_id int(11) NOT NULL, -pokemon_id varchar(32) NOT NULL, -cp int(32) NOT NULL, -stamina int(11) NOT NULL, -stamina_max int(11) NOT NULL, -move_1 varchar(32) NOT NULL, -move_2 varchar(32) NOT NULL, -deployed_fort_id longtext NOT NULL, -is_egg tinyint(1) NOT NULL, -egg_km_walked_target double NOT NULL, -egg_km_walked_start double NOT NULL, -origin int(11) NOT NULL, -height_m double NOT NULL, -weight_kg double NOT NULL, -individual_attack int(11) NOT NULL, -individual_defense int(11) NOT NULL, -individual_stamina int(11) NOT NULL, -cp_multiplier double NOT NULL, -pokeball varchar(32) NOT NULL, -captured_cell_id varchar(32) NOT NULL, -battles_attacked int(11) NOT NULL, -battles_defended int(11) NOT NULL, -egg_incubator_id longtext NOT NULL, -creation_time_ms bigint(20) NOT NULL, -num_upgrades int(11) NOT NULL, -additional_cp_multiplier double NOT NULL, -favorite tinyint(1) NOT NULL, -nickname longtext NOT NULL, -from_fort int(11) NOT NULL, -PRIMARY KEY (id) \ No newline at end of file diff --git a/src/db/tables/users.table b/src/db/tables/users.table deleted file mode 100644 index b777823..0000000 --- a/src/db/tables/users.table +++ /dev/null @@ -1,54 +0,0 @@ -id int(11) NOT NULL AUTO_INCREMENT, -username varchar(16) NOT NULL, -email varchar(32) NOT NULL, -exp int(11) NOT NULL, -level smallint(11) NOT NULL, -stardust int(11) NOT NULL, -pokecoins int(11) NOT NULL, -team tinyint(11) NOT NULL, -latitude double NOT NULL, -longitude double NOT NULL, -altitude double NOT NULL, -send_marketing_emails tinyint(1) NOT NULL, -send_push_notifications tinyint(1) NOT NULL, -avatar_skin tinyint(1) NOT NULL, -avatar_hair tinyint(1) NOT NULL, -avatar_shirt tinyint(1) NOT NULL, -avatar_pants tinyint(1) NOT NULL, -avatar_hat tinyint(1) NOT NULL, -avatar_shoes tinyint(1) NOT NULL, -avatar_eyes tinyint(1) NOT NULL, -avatar_gender tinyint(1) NOT NULL, -avatar_backpack tinyint(1) NOT NULL, -item_poke_ball int(11) NOT NULL, -item_great_ball int(11) NOT NULL, -item_ultra_ball int(11) NOT NULL, -item_master_ball int(11) NOT NULL, -item_potion int(11) NOT NULL, -item_super_potion int(11) NOT NULL, -item_hyper_potion int(11) NOT NULL, -item_max_potion int(11) NOT NULL, -item_revive int(11) NOT NULL, -item_max_revive int(11) NOT NULL, -item_lucky_egg int(11) NOT NULL, -item_incense_ordinary int(11) NOT NULL, -item_incense_spicy int(11) NOT NULL, -item_incense_cool int(11) NOT NULL, -item_incense_floral int(11) NOT NULL, -item_troy_disk int(11) NOT NULL, -item_razz_berry int(11) NOT NULL, -item_bluk_berry int(11) NOT NULL, -item_nanab_berry int(11) NOT NULL, -item_wepar_berry int(11) NOT NULL, -item_pinap_berry int(11) NOT NULL, -item_incubator_basic int(11) NOT NULL, -item_incubator_basic_unlimited int(11) NOT NULL, -item_pokemon_storage_upgrade int(11) NOT NULL, -item_storage_upgrade int(11) NOT NULL, -tutorial_legal_screen tinyint(1) NOT NULL, -tutorial_avatar_selection tinyint(1) NOT NULL, -tutorial_pokemon_capture tinyint(1) NOT NULL, -tutorial_name_selection tinyint(1) NOT NULL, -tutorial_first_time_exp tinyint(1) NOT NULL, -candies text(11) NOT NULL, -PRIMARY KEY (id) \ No newline at end of file diff --git a/src/dump.js b/src/dump.js deleted file mode 100644 index 9f85978..0000000 --- a/src/dump.js +++ /dev/null @@ -1,75 +0,0 @@ -import fse from "fs-extra"; -import POGOProtos from "pokemongo-protobuf"; - -import CFG from "../cfg"; - -/** - * @param {Request} req - * @param {Array} res - * @return {Object} - */ -export function decode(req, res) { - - // clone - req = JSON.parse(JSON.stringify(req)); - res = JSON.parse(JSON.stringify(res)); - - // dont decode unknown6, since it bloats the file size - delete req.unknown6; - - // decode requests - for (let request of req.requests) { - let key = _toCC(request.request_type); - let msg = request.request_message; - if (msg) { - let proto = `POGOProtos.Networking.Requests.Messages.${key}Message`; - request.request_message = this.parseProtobuf(new Buffer(msg.data), proto); - } - }; - - // decode responses - let index = 0; - for (let resp of res) { - let key = _toCC(req.requests[index].request_type); - let msg = new Buffer(resp); - let proto = `POGOProtos.Networking.Responses.${key}Response`; - res[index] = this.parseProtobuf(msg, proto); - index++; - }; - - // clone again to build response out of it - let req2 = JSON.parse(JSON.stringify(req)); - - // build res base out of req - delete req2.requests; - req2.returns = res; - req2.status_code = 1; - - return ({ - req: req, - res: res - }); - -} - -/** - * @param {Request} req - * @param {Response} res - */ -export function dumpTraffic(req, res) { - - let decoded = this.decode(req, res); - - let out = { - Request: decoded.req, - Response: decoded.res - }; - - try { - let decoded = JSON.stringify(out, null, 2); - fse.outputFileSync(CFG.DEBUG_DUMP_PATH + Date.now(), decoded); - } catch (e) { - this.print("Dump traffic: " + e, 31); - } - -} \ No newline at end of file diff --git a/src/http.js b/src/http.js deleted file mode 100644 index 4eede73..0000000 --- a/src/http.js +++ /dev/null @@ -1,39 +0,0 @@ -import http from "http"; - -import CFG from "../cfg"; - -/** - * @return {HTTP} - */ -export function createHTTPServer() { - let server = http.createServer((req, res) => { - if (this.world.isFull()) { - this.print(`Server is full! Refused ${req.headers.host}`, 31); - return void 0; - } - let chunks = []; - req.on("data", (chunk) => { - chunks.push(chunk); - }); - req.on("end", () => { - let buffer = Buffer.concat(chunks); - req.body = buffer; - this.world.getPlayerByRequest(req, res).then((player) => { - this.routeRequest(player, req, res); - }); - }); - }); - server.listen(CFG.PORT); - return (server); -} - -export function shutdown() { - this.socket.close(() => { - this.print("Closed http server!", 33); - this.closeConnection(() => { - this.print("Closed database connection!", 33); - this.print("Server shutdown!", 31); - setTimeout(() => process.exit(1), 2e3); - }); - }); -} \ No newline at end of file diff --git a/src/index.js b/src/index.js deleted file mode 100644 index 4226ca2..0000000 --- a/src/index.js +++ /dev/null @@ -1,190 +0,0 @@ -import fs from "fs"; -import os from "os"; -import EventEmitter from "events"; -import POGOProtos from "pokemongo-protobuf"; - -import { - inherit, - _toCC -} from "./utils"; - -import CFG from "../cfg"; - -import World from "./models/World"; - -import * as _api from "./api"; -import * as _dump from "./dump"; -import * as _http from "./http"; -import * as _setup from "./setup"; -import * as _cycle from "./cycle"; -import * as _request from "./request"; -import * as _response from "./response"; -import * as _process from "./process"; -import * as _mysql from "./db/index"; -import * as _mysql_get from "./db/get"; -import * as _mysql_query from "./db/query"; -import * as _mysql_create from "./db/create"; - -const greetMessage = fs.readFileSync(".greet", "utf8"); - -/** - * @class GameServer - */ -export default class GameServer extends EventEmitter { - - /** @constructor */ - constructor() { - - super(null); - - this.STATES = { - PAUSE: false, - DEBUG: false, - CRASH: false - }; - - this.db = { - instance: null, - collections: {} - }; - - this.assets = {}; - this.master = null; - this.socket = null; - this.cycleInstance = null; - - // Timer things - this.tick = 0; - this.time = 0; - this.fullTick = 0; - this.saveTick = 0; - this.timeoutTick = 0; - this.passedTicks = 0; - - this.initAPI(); - - if (CFG.GREET) this.greet(); - - this.print(`Booting Server v${require("../package.json").version}-dev`, 33); - - this.world = new World(this); - - this.setup(); - - } - - initAPI() { - if (CFG.ENABLE_API) { - for (let key in _api) { - this.on(key, _api[key]); - }; - } - // make sure we still have our print fn - else { - this.on("print", _api["print"]); - } - } - - /** - * @param {String} msg - * @param {Number} color - * @param {Boolean} nl - */ - print(msg, color, nl) { - this.emit("print", msg, color, nl); - } - - /** - * @param {String} msg - * @param {Function} fn - * @param {Number} timer - */ - retry(msg, fn, timer) { - process.stdout.clearLine(); - process.stdout.cursorTo(0); - this.print(`${msg}${timer}s`, 33, true); - if (timer >= 1) setTimeout(() => this.retry(msg, fn, --timer), 1e3); - else { - process.stdout.write("\n"); - fn(); - } - } - - /** - * @return {String} - */ - getLocalIPv4() { - let address = null; - let interfaces = os.networkInterfaces(); - for (var dev in interfaces) { - interfaces[dev].filter((details) => details.family === "IPv4" && details.internal === false ? address = details.address: void 0); - }; - return (address); - } - - /** - * @param {Buffer} buffer - * @param {String} schema - */ - parseProtobuf(buffer, schema) { - try { - return POGOProtos.parseWithUnknown(buffer, schema); - } catch (e) { - this.print(e, 31); - } - } - - /** - * @param {Request} req - */ - parseSignature(req) { - let key = pcrypt.decrypt(req.unknown6.unknown2.encrypted_signature); - return ( - POGOProtos.parseWithUnknown(key, "POGOProtos.Networking.Envelopes.Signature") - ); - } - - /** - * @param {String} path - * @return {Boolean} - */ - fileExists(path) { - try { - fs.statSync(path); - } catch (e) { - return (false); - } - return (true); - } - - greet() { - console.log(greetMessage); - } - -} - -inherit(GameServer, _dump); -inherit(GameServer, _http); -inherit(GameServer, _setup); -inherit(GameServer, _cycle); -inherit(GameServer, _request); -inherit(GameServer, _response); -inherit(GameServer, _process); -inherit(GameServer, _mysql); -inherit(GameServer, _mysql_get); -inherit(GameServer, _mysql_query); -inherit(GameServer, _mysql_create); - -(() => { - - const server = new GameServer(); - - process.openStdin().addListener("data", (data) => { - server.stdinInput(data); - }); - - process.on("uncaughtException", (data) => { - server.uncaughtException(data); - }); - -})(); \ No newline at end of file diff --git a/src/master.js b/src/master.js deleted file mode 100644 index f80580f..0000000 --- a/src/master.js +++ /dev/null @@ -1,6 +0,0 @@ -/** - * Global shared parsed - * game master file - * @type {GameMaster} - */ -export let GAME_MASTER = null; \ No newline at end of file diff --git a/src/models/GameMaster/index.js b/src/models/GameMaster/index.js deleted file mode 100644 index 2229041..0000000 --- a/src/models/GameMaster/index.js +++ /dev/null @@ -1,63 +0,0 @@ -/** - * @class GameMaster - */ -export default class GameMaster { - - /** - * @param {Buffer} buffer - * @constructor - */ - constructor(buffer) { - - this.settings = this.buildSettings(); - - this.buffer = buffer; - - this.parse(); - - } - - parse() { - - let ii = 0; - let length = 0; - - let item = null; - let items = this.buffer.item_templates; - - length = items.length; - - for (; ii < length; ++ii) { - item = items[ii]; - this.parseKey(item, item.template_id); - }; - - } - - /** - * @param {Object} item - * @param {String} key - */ - parseKey(item, key) { - if (key in this.settings) { - this.settings[key] = item; - } - } - - /** - * @return {Object} - */ - buildSettings() { - let settings = { - "PLAYER_LEVEL_SETTINGS": null - }; - return (settings); - } - - getPlayerSettings() { - return ( - this.settings["PLAYER_LEVEL_SETTINGS"].player_level - ); - } - -} \ No newline at end of file diff --git a/src/models/Player/Avatar/index.js b/src/models/Player/Avatar/index.js deleted file mode 100644 index 034b501..0000000 --- a/src/models/Player/Avatar/index.js +++ /dev/null @@ -1,123 +0,0 @@ -/** - * @class Avatar - */ -export default class Avatar { - - /** @constructor */ - constructor() { - - this._skin = 0; - this._hair = 0; - this._shirt = 0; - this._pants = 0; - this._hat = 0; - this._shoes = 0; - this._eyes = 0; - this._gender = 0; - this._backpack = 0; - - } - - /** - * @param {Number} value - * @param {Number} a - * @param {Number} b - * @return {Boolean} - */ - between(value, a, b) { - return ( - value >= a && value <= b - ); - } - - // skin - get skin() { - return (this._skin); - } - set skin(value) { - if (this.between(value, 0, 3)) { - this.skin = value; - } - } - - // hair - get hair() { - return (this._hair); - } - set hair(value) { - if (this.between(value, 0, 5)) { - this._hair = value; - } - } - - // shirt - get shirt() { - return (this._shirt); - } - set shirt(value) { - if (this.between(value, 0, 3)) { - this._shirt = value; - } - } - - // pants - get pants() { - return (this._pants); - } - set pants(value) { - if (this.between(value, 0, 2)) { - this._pants = value; - } - } - - // hat - get hat() { - return (this._hat); - } - set hat(value) { - if (this.between(value, 0, 4)) { - this._hat = value; - } - } - - // shoes - get shoes() { - return (this._shoes); - } - set shoes(value) { - if (this.between(value, 0, 6)) { - this._shoes = value; - } - } - - // eyes - get eyes() { - return (this._eyes); - } - set eyes(value) { - if (this.between(value, 0, 4)) { - this._eyes = value; - } - } - - // gender - get gender() { - return (this._gender); - } - set gender(value) { - if (this.between(value, 0, 1)) { - this._gender = value; - } - } - - // backpack - get backpack() { - return (this._backpack); - } - set backpack(value) { - if (this.between(value, 0, 5)) { - this._backpack = value; - } - } - -} \ No newline at end of file diff --git a/src/models/Player/Bag/CandyBag/index.js b/src/models/Player/Bag/CandyBag/index.js deleted file mode 100644 index 9f095e4..0000000 --- a/src/models/Player/Bag/CandyBag/index.js +++ /dev/null @@ -1,71 +0,0 @@ -/** - * @class CandyBag - */ -export default class CandyBag { - - /** @constructor */ - constructor() { - this.candies = []; - } - - getCandyByDexNumber(dex) { - - let candies = this.candies; - - let ii = 0; - let length = candies.length; - - for (; ii < length; ++ii) { - if (candies[ii].dex === dex) { - return (candies[ii]); - } - }; - - return (null); - - } - - /** - * @param {String} str - */ - parseCandies(str) { - - let result = null; - - let seperator = ":"; - let split = str.split(","); - - let ii = 0; - let length = split.length; - - for (; ii < length; ++ii) { - result = split[ii].split(seperator); - this.candies.push({ - dex: result[0] << 0, - amount: result[1] << 0 - }); - }; - - } - - /** - * @return {String} - */ - serializeCandies() { - - let str = ""; - let candies = this.candies; - - let ii = 0; - let length = candies.length; - - for (; ii < length; ++ii) { - str += candies[ii].dex + ":" + candies[ii].dex; - if (ii + 1 < length) str += ","; - }; - - return (str); - - } - -} \ No newline at end of file diff --git a/src/models/Player/Bag/index.js b/src/models/Player/Bag/index.js deleted file mode 100644 index 128ead3..0000000 --- a/src/models/Player/Bag/index.js +++ /dev/null @@ -1,72 +0,0 @@ -import Candy from "./Candy"; - -/** - * @class Bag - */ -export default class Bag { - - /** @constructor */ - constructor() { - - this.candies = new CandyBag(); - - this.stardust = 0; - this.pokecoins = 0; - - this.pokeBall = 0; - this.greatBall = 0; - this.ultraBall = 0; - this.masterBall = 0; - - this.potion = 0; - this.superPotion = 0; - this.hyperPotion = 0; - this.maxPotion = 0; - - this.revive = 0; - this.maxRevive = 0; - - this.razzBerry = 0; - this.blukBerry = 0; - this.nanabBerry = 0; - this.weparBerry = 0; - this.pinapBerry = 0; - - // premium shit - this.luckyEgg = 0; - this.troyDisk = 0; - - this.incenseOrdinary = 0; - this.incenseSpicy = 0; - this.incenseCool = 0; - this.incenseFloral = 0; - - this.incubatorBasic = 0; - this.incubatorBasicUnlimited = 0; - - this.storageUpgrade = 0; - - this.pkmnStorageUpgrade = 0; - - } - - /** - * @param {Number} dex - * @return {Object} - */ - getCandy(dex) { - return ( - this.candies.getCandyByDexNumber(dex) - ); - } - - /** - * @param {Number} dex - * @param {Number} value - */ - updateCandyAmount(dex, value) { - let candy = this.getCandy(dex); - candy.amount += (value << 0); - } - -} \ No newline at end of file diff --git a/src/models/Player/Info/index.js b/src/models/Player/Info/index.js deleted file mode 100644 index 88ed579..0000000 --- a/src/models/Player/Info/index.js +++ /dev/null @@ -1,91 +0,0 @@ -/** - * @class Info - */ -class Info { - - /** @constructor */ - constructor() { - - this.lvl = 0; - - this.exp = 0; - this.prevLvlExp = 0; - this.nextLvlExp = 0; - - this.kmWalked = 0; - this.pkmnEncountered = 0; - this.uniquePokedexEntries = 0; - this.pkmnCaptured = 0; - this.pokeStopVisits = 0; - this.pokeballsThrown = 0; - this.eggsHatched = 0; - this.bigMagikarpCaught = 0; - this.pkmnDeployed = 0; - - } - - upgradeLevel() { - - } - - getLevelSettings() { - return ( - this.owner.gameMaster("PLAYER_LEVEL_SETTINGS") - ); - } - - getMaximumLevel() { - return ( - Object.keys(this.getLevelSettings().player_level).length - ); - } - - getCurrentLevel() { - let levels = this.getLevelSettings().required_experience; - for (let key in levels) { - if (levels[key] << 0 === this.nextLvlExp) { - return (key << 0); - } - }; - return (1); - } - - /** - * @param {Number} exp - */ - upgradeExp(exp) { - let levels = this.getLevelSettings().required_experience; - let maxLevel = this.getMaximumLevel(); - let currentLevel = this.getCurrentLevel(); - if (currentLevel + 1 <= maxLevel) { - this.lvl += 1; - this.exp += exp; - this.prevLvlExp = levels[this.lvl - 1]; - this.nextLvlExp = levels[this.lvl + 1]; - } - else { - this.exp += exp; - } - } - - getPlayerInfo() { - return ({ - player_stats: { - level: this.lvl, - experience: this.exp, - prev_level_xp: this.prevLvlExp, - next_level_xp: this.nextLvlExp, - km_walked: this.kmWalked, - pokemons_encountered: this.pkmnEncountered, - unique_pokedex_entries: this.uniquePokedexEntries, - pokemons_captured: this.pkmnCaptured, - poke_stop_visits: this.pokeStopVisits, - pokeballs_thrown: this.pokeballsThrown, - eggs_hatched: this.eggsHatched, - big_magikarp_caught: this.bigMagikarpCaught, - pokemon_deployed: this.pkmnDeployed - } - }); - } - -} \ No newline at end of file diff --git a/src/models/Player/Party/index.js b/src/models/Player/Party/index.js deleted file mode 100644 index d2b3276..0000000 --- a/src/models/Player/Party/index.js +++ /dev/null @@ -1,65 +0,0 @@ -/** - * @class Party - */ -class Party { - - /** @constructor */ - constructor() { - - this.party = []; - - } - - addPkmn(obj) { - console.log(obj); - } - - /** - * @param {Number} id - * @return {Number} - */ - getPkmnIndexById(id) { - for (let ii = 0; ii < this.party.length; ++ii) { - if (this.party[ii].id === id) return (ii); - }; - return (-1); - } - - /** - * @param {Number} id - * @return {Pokemon} - */ - getPkmnById(id) { - let index = this.getPkmnIndexById(id); - return (this.party[index]); - } - - /** - * @param {Number} id - */ - deletePkmn(id) { - let index = this.getPkmnIndexById(id); - let pkmn = this.party[index]; - if (pkmn) this.party.splice(index, 1); - } - - /** - * @return {Number} - */ - getUniquePkmnCount() { - let ii = 0; - let dex = 0; - let amount = 0; - let length = this.party.length; - let array = []; - for (; ii < length; ++ii) { - dex = this.party[ii].dexNumber; - if (array.indexOf(dex) === -1) { - array.push(dex); - amount++; - } - }; - return (amount); - } - -} \ No newline at end of file diff --git a/src/models/Player/index.js b/src/models/Player/index.js deleted file mode 100644 index 7a98157..0000000 --- a/src/models/Player/index.js +++ /dev/null @@ -1,33 +0,0 @@ -import Avatar from "./Avatar"; -import MapObject from "../World/MapObject"; - -import { GAME_MASTER } from "../../master"; - -/** - * @class Player - */ -export default class Player extends MapObject { - - /** - * @param {Object} obj - * @constructor - */ - constructor(obj) { - - super(null); - - this.request = obj.request; - this.response = obj.response; - - this.authenticated = 0; - - this.bag = new Bag(this); - this.info = new Info(this); - this.pary = new Party(this); - this.avatar = new Avatar(this); - this.pokedex = new Pokedex(this); - this.tutorial = new Tutorial(this); - - } - -} \ No newline at end of file diff --git a/src/models/Player/packets/GetInventory.js b/src/models/Player/packets/GetInventory.js deleted file mode 100644 index d3f6a64..0000000 --- a/src/models/Player/packets/GetInventory.js +++ /dev/null @@ -1,105 +0,0 @@ -import POGOProtos from "pokemongo-protobuf"; - -export function GetInventory() { - - let stats = this.GetInventoryPlayer(); - let items = this.GetInventoryItems(); - let party = this.GetInventoryParty(); - - let buffer = ({ - success: true, - inventory_delta: { - new_timestamp_ms: new Date().getTime(), - inventory_items: stats.concat(items).concat(party) - } - }); - - return (POGOProtos.serialize(buffer, "POGOProtos.Networking.Responses.GetInventoryResponse")); - -} - -export function GetInventoryPlayer() { - - let player = this.player; - - return ({ - modified_timestamp_ms: new Date().getTime(), - inventory_item_data: { - player_stats: { - level: player.level, - experience: player.exp, - prev_level_xp: "21000", - next_level_xp: "36000", - km_walked: 3.921541213989258, - pokemons_encountered: 75, - unique_pokedex_entries: 25, - pokemons_captured: 71, - poke_stop_visits: 123, - pokeballs_thrown: 74, - eggs_hatched: 1, - big_magikarp_caught: 1, - pokemon_deployed: 1 - } - } - }); - -} - -export function GetInventoryItems() { - - let player = this.player; - - let items = []; - let match = "item_"; - - for (let key in player) { - if (key.substring(0, 5) === match) { - items.push({ - modified_timestamp_ms: new Date().getTime(), - inventory_item_data: { - item: { - item_id: key.toUpperCase(), - count: parseFloat(player[key]) - } - } - }); - } - }; - - return (items); - -} - -export function GetInventoryParty() { - - let player = this.player; - let pkmns = []; - - for (let pkmn of player.party) { - pkmns.push({ - inventory_item_data: { - pokemon_data: { - id: pkmn.id, - pokemon_id: pkmn.pokemon_id, - cp: pkmn.cp, - stamina: pkmn.stamina, - stamina_max: pkmn.stamina_max, - move_1: pkmn.move_1, - move_2: pkmn.move_2, - height_m: pkmn.height_m, - weight_kg: pkmn.weight_kg, - individual_attack: pkmn.individual_attack, - individual_defense: pkmn.individual_defense, - individual_stamina: pkmn.individual_stamina, - cp_multiplier: pkmn.cp_multiplier, - pokeball: pkmn.pokeball, - captured_cell_id: pkmn.captured_cell_id, - creation_time_ms: pkmn.creation_time_ms - } - } - }); - }; - - return (pkmns); - -} \ No newline at end of file diff --git a/src/models/Player/packets/GetPlayer.js b/src/models/Player/packets/GetPlayer.js deleted file mode 100644 index b81b18c..0000000 --- a/src/models/Player/packets/GetPlayer.js +++ /dev/null @@ -1,7 +0,0 @@ -import POGOProtos from "pokemongo-protobuf"; - -export function GetPlayer() { - - return (POGOProtos.serialize(buffer, "POGOProtos.Networking.Responses.GetPlayerResponse")); - -} \ No newline at end of file diff --git a/src/models/Player/packets/GetPlayerProfile.js b/src/models/Player/packets/GetPlayerProfile.js deleted file mode 100644 index a785433..0000000 --- a/src/models/Player/packets/GetPlayerProfile.js +++ /dev/null @@ -1,7 +0,0 @@ -import POGOProtos from "pokemongo-protobuf"; - -export function GetPlayerProfile() { - - return (POGOProtos.serialize(buffer, "POGOProtos.Networking.Responses.GetPlayerProfileResponse")); - -} \ No newline at end of file diff --git a/src/models/Pokemon/WildPokemon.js b/src/models/Pokemon/WildPokemon.js deleted file mode 100644 index 9ac34c4..0000000 --- a/src/models/Pokemon/WildPokemon.js +++ /dev/null @@ -1,28 +0,0 @@ -import Pokemon from "index"; -import CaptureProbability from "CaptureProbability"; - -/** - * @class WildPokemon - */ -class WildPokemon extends Pokemon { - - /** - * @param {Object} obj - * @constructor - */ - constructor(obj) { - - super(obj); - - this.encounterId = 0; - - this.latitude = 0; - this.longitude = 0; - - this.pokeball = 0; - - this.spawnPoint = 0; - - } - -} \ No newline at end of file diff --git a/src/models/Pokemon/index.js b/src/models/Pokemon/index.js deleted file mode 100644 index 9013c2e..0000000 --- a/src/models/Pokemon/index.js +++ /dev/null @@ -1,127 +0,0 @@ -import pokename from "pokename"; - -import MapObject from "../World/MapObject"; - -import { - validName -} from "../../utils"; - -/** - * @class Pokemon - */ -export default class Pokemon extends MapObject { - - /** - * @param {Object} obj - * @constructor - */ - constructor(obj) { - - this.id = 0; - this.dexNumber = 0; - - this.owner = null; - - this.level = 0; - - this.cp = 0; - this.cpMultiplier = 0; - this.addCpMultiplier = 0; - - this.stamina = 0; - this.staminaMax = 0; - - this.move1 = 0; - this.move2 = 0; - - this.attack = 0; - this.defence = 0; - - this.height = 0; - this.weight = 0; - - this.ivAttack = 0; - this.ivDefense = 0; - this.ivStamina = 0; - - this.nickname = null; - - this.favorite = 0; - - this.init(obj); - - } - - /** - * @param {Object} obj - */ - init(obj) { - obj = obj || {}; - for (let key in obj) { - if (this.hasOwnProperty(key)) { - this[key] = obj[key]; - } - }; - } - - /** - * @param {Boolean} truth - */ - setFavorite(truth) { - this.favorite = !!truth; - } - - /** - * @param {String} name - */ - setNickname(name) { - if (!validName(name)) return void 0; - this.nickname = name; - } - - /** - * @param {Number} dex - * @return {Object} - */ - getPkmnTemplate(dex) { - let name = pokename.getPokemonNameById(dex); - return (this.owner.gameMaster.pokemon[name]); - } - - upgradePkmn() { - let pkmnTmpl = this.getPkmnTemplate(this.dexNumber); - let ownerCandies = this.owner.bag.getCandyByDexNumber(this.dexNumber); - if (ownerCandies >= pkmnTmpl.CandyToEvolve) { - this.owner.bag.setCandyByDex(ownerCandies - pkmnTmpl.CandyToEvolve); - this.evolveTo(pkmnTmpl.Evolution); - } - } - - /** - * @param {Number} dex - */ - evolveTo(dex) { - console.log("EVOLVE TO: ", dex); - } - - /** - * @return {Object} - */ - getPokemonData() { - return ({ - pokemon_id: this.dexNumber, - cp: this.cp, - stamina: this.stamina, - stamina_max: this.stamina_max, - move_1: this.move_1, - move_2: this.move_2, - height_m: this.height, - weight_kg: this.weight, - individual_attack: this.ivAttack, - individual_defense: this.ivDefense, - individual_stamina: this.ivStamina, - cp_multiplier: this.cpMultiplier - }); - } - -} \ No newline at end of file diff --git a/src/models/World/MapObject/index.js b/src/models/World/MapObject/index.js deleted file mode 100644 index b616555..0000000 --- a/src/models/World/MapObject/index.js +++ /dev/null @@ -1,17 +0,0 @@ -/** - * @class MapObject - */ -export default class MapObject { - - /** @constructor */ - constructor() { - - this.uid = 0; - - this.altitude = 0; - this.latitude = 0; - this.longitude = 0; - - } - -} \ No newline at end of file diff --git a/src/models/World/index.js b/src/models/World/index.js deleted file mode 100644 index 017a75a..0000000 --- a/src/models/World/index.js +++ /dev/null @@ -1,124 +0,0 @@ -import Player from "../Player"; - -import CFG from "../../../cfg"; - -/** - * @class World - */ -export default class World { - - /** @constructor */ - constructor() { - - this.players = []; - - } - - /** - * @return {Boolean} - */ - isFull() { - return ( - this.players.length >= CFG.MAX_CONNECTIONS - ); - } - - /** - * @param {Request} req - * @param {Response} res - */ - getPlayerByRequest(req, res) { - - let player = null; - - return new Promise((resolve) => { - if (this.playerAlreadyConnected(req)) { - player = this.getPlayerByIP(req.headers.host); - resolve(player); - } - else { - this.addPlayer(req, res); - resolve(player); - } - }); - - } - - /** - * @param {Object} client - * @return {Boolean} - */ - playerAlreadyConnected(client) { - - let players = this.players; - - let ii = 0; - let length = players.length; - - let remoteAddress = client.headers.host; - - for (; ii < length; ++ii) { - if (players[ii].remoteAddress === remoteAddress) { - return (true); - } - }; - - return (false); - - } - - /** - * @param {String} ip - */ - getPlayerByIP(ip) { - - let players = this.players; - - let ii = 0; - let length = players.length; - - for (; ii < length; ++ii) { - if (players[ii].remoteAddress === ip) { - return (players[ii]); - } - }; - - return (null); - - } - - /** - * @param {Request} req - * @param {Response} res - */ - addPlayer(req, res) { - - let player = new Player({ - request: req, - response: res - }); - - this.players.push(player); - - } - - /** - * @param {Player} player - */ - removePlayer(player) { - console.log(player); - } - - spawnFort() { - - } - - spawnGym() { - - } - - spawnEncounter() { - - } - -} \ No newline at end of file diff --git a/src/models/World/packets/GetMapObject.js b/src/models/World/packets/GetMapObject.js deleted file mode 100644 index d9c628a..0000000 --- a/src/models/World/packets/GetMapObject.js +++ /dev/null @@ -1,18 +0,0 @@ -import POGOProtos from "pokemongo-protobuf"; - -/** - * @param {Request} request - */ -export function GetMapObject(request) { - - let player = this.player; - - let latitude = player.latitude; - let longitude = player.longitude; - - return new Promise(() => { - // db call - // - }); - -} \ No newline at end of file diff --git a/src/process.js b/src/process.js deleted file mode 100644 index e437c21..0000000 --- a/src/process.js +++ /dev/null @@ -1,76 +0,0 @@ -import fs from "fs"; - -import CFG from "../cfg"; - -const helpMessage = fs.readFileSync(".help", "utf8"); - -export function processCommand(cmd, data) { - let players = this.world.players; - switch (cmd) { - // How many active connections there are - case "/players": - var length = players.length; - this.print(`${length}:${CFG.MAX_CONNECTIONS} connected players!`, 33); - break; - // Exit the server - case "/exit": - this.shutdown(); - break; - case "/kick": - this.kickPlayer(data[1]); - break; - case "/killall": - var length = players.length; - this.removeAllPlayers(); - var result = length - players.length; - this.print(`Removed ${result} player${result === 1 ? "": "s"}!`); - break; - case "/clear": - process.stdout.write("\x1Bc"); - this.greet(); - break; - case "/help": - console.log("\x1b[36;1m==================================== HELP =====================================\x1b[0m"); - console.log(`\x1b[${CFG.DEFAULT_CONSOLE_COLOR};1m${helpMessage}\x1b[0m`); - console.log("\x1b[36;1m===============================================================================\x1b[0m"); - break; - case "/save": - this.saveAllPlayers(); - var length = players.length; - this.print(`Saved ${length} player${length === 1 ? "": "s"} into database!`); - break; - case "/spawn": - this.spawnPkmnAtPlayer(data[1], data[2], data[3] || 1); - break; - case "/update": - eval(fs.readFileSync("update.js", "utf8")); - break; - default: - this.print(`${cmd} is not a valid command!`, 31); - break; - }; -}; - -export function stdinInput(data) { - data = data.toString().substring(0, data.length - 2); - if (data.length < 1) return void 0; - data = data.split(" "); - var cmd = data[0]; - this.processCommand(cmd, data); -}; - -export function uncaughtException(excp) { - switch (excp.errno) { - case "EADDRINUSE": - this.print(`Port ${CFG.PORT} is already in use!`, 31); - break; - case "EACCES": - this.print("No root privileges!", 31); - break; - default: - console.log("Unhandled exception occurred: ", excp.code); - console.log(excp.stack); - break; - }; - this.print("The server has crashed!", 31); -}; \ No newline at end of file diff --git a/src/request.js b/src/request.js deleted file mode 100644 index 9702deb..0000000 --- a/src/request.js +++ /dev/null @@ -1,157 +0,0 @@ -import fs from "fs"; -import url from "url"; -import pcrypt from "pcrypt"; -import POGOProtos from "pokemongo-protobuf"; - -import CFG from "../cfg"; - -/** - * @param {Player} player - * @param {Request} req - * @param {Response} res - */ -export function routeRequest(player, req, res) { - - let parsed = url.parse(req.url).pathname; - let route = parsed.split("/"); - let host = req.headers.host; - - switch (route[1]) { - case "plfe": - case "custom": - if (route[2] === "rpc") this.onRequest(player, req); - break; - case "model": - // make sure no random dudes can access download - if (!player.authenticated) return void 0; - let name = route[2]; - if (name && name.length > 1) { - let folder = player.isAndroid ? "android/" : "ios/"; - fs.readFile("data/" + folder + name, (error, data) => { - if (error) { - this.print(`Error file resolving model ${name}:` + error, 31); - return void 0; - } - this.print(`Sent ${name} to ${player.email}`, 36); - res.end(data); - }); - } - break; - default: - console.log(`Unknown request url: https://${req.headers.host}${req.url}`); - break; - }; - -} - -/** - * @param {Player} player - * @param {Request} req - */ -export function onRequest(player, req) { - - let request = this.parseProtobuf(req.body, "POGOProtos.Networking.Envelopes.RequestEnvelope"); - request.requests = request.requests || []; - - if (CFG.DEBUG_LOG_REQUESTS) { - console.log("#####"); - request.requests.map((request) => { - console.log("Got request:", request.request_type); - }).join(","); - } - - if (!player.authenticated) { - player.sendResponse(this.authenticatePlayer(player)); - return void 0; - } - - if (!request.requests.length) { - this.print("Received invalid request!", 31); - return void 0; - } - - this.processRequests(player, request.requests).then((returns) => { - if (CFG.DEBUG_DUMP_TRAFFIC) { - this.dumpTraffic(request, returns); - } - let msg = this.envelopResponse(1, returns, request, player, !!request.auth_ticket); - player.sendResponse(msg); - }); - -} - -/** - * @param {Number} status - * @param {Array} returns - * @param {Request} req - * @param {Player} player - * @param {Boolean} auth - * @return {Buffer} - */ -export function envelopResponse(status, returns, req, player, auth) { - - let buffer = req; - - delete buffer.requests; - - buffer.returns = returns; - - // get players device platform one time - if (player.hasSignature === false && buffer.unknown6 && buffer.unknown6.unknown2) { - let sig = this.parseSignature(buffer); - if (sig.device_info !== void 0) { - player.isIOS = sig.device_info.device_brand === "Apple"; - player.isAndroid = !player.isIOS; - player.hasSignature = true; - player.asset_digest = this.assets[player.isAndroid ? "android" : "ios"]; - this.print(`${player.email} is playing with an ${player.isIOS ? "Apple" : "Android"} device!`, 36); - } - } - - if (auth) buffer.auth_ticket = AuthTicket(); - - if (buffer.unknown6) { - buffer.unknown6 = [{ - "response_type": 6, - "unknown2": { - "unknown1": "1", - "items": [], - "player_currencies": [] - } - }]; - } - - buffer.status_code = status; - - return ( - POGOProtos.serialize(buffer, "POGOProtos.Networking.Envelopes.ResponseEnvelope") - ); - -} - -/** - * @param {Player} player - * @param {Array} requests - * @return {Array} - */ -export function processRequests(player, requests) { - - return new Promise((resolve) => { - - let index = 0; - let length = requests.length; - let body = []; - - const loop = (index) => { - this.processResponse(player, requests[index]).then((request) => { - body.push(request); - if (++index >= length) resolve(body); - else return loop(index); - }); - }; - - loop(0); - - }); - -} \ No newline at end of file diff --git a/src/response.js b/src/response.js deleted file mode 100644 index 2a66b78..0000000 --- a/src/response.js +++ /dev/null @@ -1,54 +0,0 @@ -import POGOProtos from "pokemongo-protobuf"; - -import CFG from "../cfg"; - -import { - _toCC, - validUsername -} from "./utils"; - -/** - * @param {Request} req - * @return {Buffer} - */ -export function parseMessage(req) { - let proto = `POGOProtos.Networking.Requests.Messages.${cc}Message`; - if (req.request_message) { - try { - return (this.parseProtobuf(req.request_message, proto)); - } catch (e) { - this.print(`Failed to parse ${cc}: ${e}`, 31); - } - } - return void 0; -} - -/** - * @param {Player} player - * @param {Request} req - * @return {Buffer} - */ -export function processResponse(player, req) { - - let buffer = null; - - let cc = _toCC(req.request_type); - let msg = this.parseMessage(req); - - return new Promise((resolve) => { - - try { - switch (req.request_type) { - default: - this.print(`Unknown request: ${req.request_type}`, 31); - break; - }; - } catch (e) { - this.print(`Response error: ${e}`, 31); - }; - - resolve(buffer); - - }); - -} \ No newline at end of file diff --git a/src/setup.js b/src/setup.js deleted file mode 100644 index 498978a..0000000 --- a/src/setup.js +++ /dev/null @@ -1,238 +0,0 @@ -import fs from "fs"; -import fse from "fs-extra"; -import pogo from "pogo-asset-downloader"; -import POGOProtos from "pokemongo-protobuf"; - -import CFG from "../cfg"; - -import * as master from "./master"; - -import GameMaster from "./models/GameMaster"; - -import { - capitalize, - idToPkmnBundleName -} from "./utils"; - -export function setup() { - - let isFirstRun = !this.fileExists(CFG.DUMP_ASSET_PATH); - - if (isFirstRun) { - this.print("Required assets are missing! Preparing dump session..", 31); - setTimeout(() => { - this.onFirstRun(() => { - this.setup(); - }); - }, 1e3); - return void 0; - } - - // make sure all assets got loaded properly - this.validateAssets().then(() => { - - this.print(`Downloaded assets are valid! Proceeding..`); - - master.GAME_MASTER = this.parseGameMaster(); - - this.master = POGOProtos.serialize(fs.readFileSync(CFG.DUMP_ASSET_PATH + "game_master"), "POGOProtos.Networking.Responses.DownloadItemTemplatesResponse"); - - this.setupDatabaseConnection().then(() => { - if (CFG.PORT < 1) { - this.print("Invalid port!", 31); - return void 0; - } - this.socket = this.createHTTPServer(); - setTimeout(this::this.cycle, 1); - let localIPv4 = this.getLocalIPv4(); - this.print(`Server listening at ${localIPv4}:${CFG.PORT}`, 33); - this.emit("ready", void 0); - }); - - }).catch((e) => { - //fse.removeSync(CFG.DUMP_ASSET_PATH); - this.print("Error: " + e + " was not found!", 31); - this.emit("ready", e); - }); - -} - -/** - * Make sure all required - * assets got loaded properly - */ -export function validateAssets() { - - return new Promise((resolve, reject) => { - - // validate game master - if (!this.fileExists(CFG.DUMP_ASSET_PATH + "game_master")) { - return reject("File game_master"); - } - - this.validateModels().then(() => { - resolve(); - }).catch((e) => { - reject(e); - }); - - }); - -} - -export function validateModels() { - - let max = CFG.MAX_POKEMON_NATIONAL_ID; - let limit = pogo.platforms.length; - - return new Promise((resolve, reject) => { - const validate = (index) => { - let platform = pogo.platforms[index]; - let name = platform.name; - let path = CFG.DUMP_ASSET_PATH + name + "/"; - - // ups, validate asset_digest's too - if (!this.fileExists(path + "asset_digest")) { - return reject(`${path}asset_digest`); - } - else { - let buffer = fs.readFileSync(path + "asset_digest"); - this.assets[name] = { - buffer: buffer, - decode: this.parseProtobuf(buffer, "POGOProtos.Networking.Responses.GetAssetDigestResponse") - } - } - - // validate models inside folder - let ii = 0; - while (++ii <= max) { - let id = idToPkmnBundleName(ii); - if (!this.fileExists(path + id)) { - return reject("Model " + id); - } - }; - - if (++index >= limit) { - resolve(); - return void 0; - } - validate(index); - }; - - validate(0); - }); - -} - -export function parseGameMaster() { - let master = null; - try { - let data = fs.readFileSync(CFG.DUMP_ASSET_PATH + "game_master"); - master = this.parseProtobuf(data, "POGOProtos.Networking.Responses.DownloadItemTemplatesResponse"); - let Master = new GameMaster(master); - } catch (e) { - this.print(e, 31); - } - return (master); -} - -export function onFirstRun(resolve) { - // make sure to login first! - pogo.login({ - provider: CFG.DOWNLOAD_PROVIDER, // google or ptc - username: CFG.DOWNLOAD_USERNAME, - password: CFG.DOWNLOAD_PASSWORD - }).then(() => { - this.downloadAssetDigests().then(() => { - this.downloadAssets().then(resolve); - }); - }).catch((e) => { - this.print(e, 31); - }); -} - -export function downloadAssetDigests(assets) { - return new Promise((resolve, reject) => { - // create data folder for each support platform - // and download each asset digest and related models - let index = 0; - let length = pogo.platforms.length; - for (let platform of pogo.platforms) { - fse.ensureDirSync(CFG.DUMP_ASSET_PATH + platform.name); - pogo.getAssetDigest(platform).then((asset) => { - fs.writeFileSync(CFG.DUMP_ASSET_PATH + platform.name + "/asset_digest", asset.toBuffer()); - if (++index >= length) resolve(); - }); - }; - }); -} - -export function downloadAssets() { - return new Promise((resolve, reject) => { - pogo.getGameMaster().then((master) => { - fs.writeFileSync(CFG.DUMP_ASSET_PATH + "game_master", master.toBuffer()); - this.downloadModels().then(() => { - resolve(); - }); - }); - }); -} - -export function downloadModels() { - - let limit = pogo.platforms.length; - - return new Promise((resolve, reject) => { - const dump = (index) => { - let platform = pogo.platforms[index]; - let name = platform.name; - let caps = capitalize(name); - caps = name === "ios" ? "iOS" : caps; - pogo.setPlatform(name); - this.print(`Preparing to dump ${caps} assets..`, 36); - this.dumpPkmnModels(CFG.DUMP_ASSET_PATH + name + "/", () => { - this.print(`Dumped ${CFG.MAX_POKEMON_NATIONAL_ID} ${caps} assets successfully!`); - if (++index >= limit) { - this.print("Dumped all assets successfully!"); - resolve(); - return void 0; - } - dump(index); - }); - }; - dump(0); - }); - -} - -export function dumpPkmnModels(path, resolve) { - - let limit = CFG.MAX_POKEMON_NATIONAL_ID; - - const dump = (index) => { - let ids = []; - if (++index <= limit) ids.push(index); - if (++index <= limit) ids.push(index); - if (++index <= limit) ids.push(index); - pogo.getAssetByPokemonId(ids).then((downloads) => { - downloads.map((item) => { - this.print(`Dumping model ${item.name}..`, 35); - try { - fs.writeFileSync(path + item.name, item.body); - } - catch (e) { - this.print(`Error while dumping model ${item.name}:` + e, 31); - } - }); - if (index >= limit) { - //this.print(`Dumped ${limit} assets successfully!`); - resolve(); - return void 0; - } - setTimeout(() => dump(index), 1e3); - }); - }; - - dump(0); - -} \ No newline at end of file diff --git a/src/utils.js b/src/utils.js deleted file mode 100644 index 0bfe004..0000000 --- a/src/utils.js +++ /dev/null @@ -1,82 +0,0 @@ -import CFG from "../cfg"; - -/** - * @param {Object} cls - * @param {Object} prot - * @export - */ -export function inherit(cls, prot) { - - let key = null; - - for (key in prot) { - if (prot[key] instanceof Function) { - cls.prototype[key] = prot[key]; - } - }; - -} - -/** - * http://stackoverflow.com/a/7616484/3367904 - * @param {String} str - * @return {String} - */ -export function getHashCodeFrom(str) { - var hash = 0, i, chr, len; - if (str.length === 0) return hash; - for (i = 0, len = str.length; i < len; i++) { - chr = str.charCodeAt(i); - hash = ((hash << 5) - hash) + chr; - hash |= 0; // Convert to 32bit integer - } - return hash; -}; - -/** - * @return {Number} - */ -export function randomRequestId() { - return ( - 1e18 - Math.floor(Math.random() * 1e18) - ); -} - -/** - * @param {String} key - * @return {String} - */ -export function _toCC(key) { - key = key.toLowerCase(); - let res = key[0].toUpperCase() + key.substring(1, key.length).replace(/_\s*([a-z])/g, function(d, e) { - return e.toUpperCase(); - }); - return (res); -} - -/** - * @param {Number} index - * @return {String} - */ -export function idToPkmnBundleName(index) { - return ( - "pm" + (index >= 10 ? index >= 100 ? "0" : "00" : "000") + index - ); -} - -/** - * @param {String} str - * @return {String} - */ -export function capitalize(str) { - return ( - str[0].toUpperCase() + str.slice(1) - ); -} - -let rx_username = /[^a-z\d]/i; -export function validUsername(str) { - return ( - !!(rx_username.test(str)) - ); -} \ No newline at end of file