mirror of
https://github.com/maierfelix/POGOserver.git
synced 2026-03-23 10:24:21 -05:00
Initial commit
This commit is contained in:
parent
59c2bc0767
commit
00e2ed3fa7
16
.gitattributes
vendored
16
.gitattributes
vendored
|
|
@ -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
|
||||
3
.gitignore
vendored
3
.gitignore
vendored
|
|
@ -1,3 +0,0 @@
|
|||
node_modules/
|
||||
scripts/
|
||||
data/
|
||||
6
.greet
6
.greet
|
|
@ -1,6 +0,0 @@
|
|||
______ _____ _____ _____
|
||||
| ___ \ _ | __ \ _ |
|
||||
| |_/ / | | | | \/ | | | ___ ___ _ ____ _____ _ __
|
||||
| __/| | | | | __| | | |/ __|/ _ \ '__\ \ / / _ \ '__|
|
||||
| | \ \_/ / |_\ \ \_/ /\__ \ __/ | \ V / __/ |
|
||||
\_| \___/ \____/\___/ |___/\___|_| \_/ \___|_|
|
||||
8
.help
8
.help
|
|
@ -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
|
||||
|
|
@ -1,7 +0,0 @@
|
|||
sudo: false
|
||||
language: node_js
|
||||
script: "npm run test"
|
||||
node_js:
|
||||
- "4"
|
||||
- "5"
|
||||
- "6"
|
||||
60
README.md
60
README.md
|
|
@ -1,60 +0,0 @@
|
|||
````
|
||||
______ _____ _____ _____
|
||||
| ___ \ _ | __ \ _ |
|
||||
| |_/ / | | | | \/ | | | ___ ___ _ ____ _____ _ __
|
||||
| __/| | | | | __| | | |/ __|/ _ \ '__\ \ / / _ \ '__|
|
||||
| | \ \_/ / |_\ \ \_/ /\__ \ __/ | \ V / __/ |
|
||||
\_| \___/ \____/\___/ |___/\___|_| \_/ \___|_|
|
||||
````
|
||||
<div align="center">
|
||||
<a href="#">
|
||||
<img src="https://img.shields.io/badge/Pokemon%20GO-0.35.0-blue.svg?style=flat-square" />
|
||||
</a>
|
||||
<a href="https://discord.gg/gu8ZUJp">
|
||||
<img src="https://img.shields.io/badge/Discord-Join%20Chat%20%E2%86%92-738bd7.svg?style=flat-square" />
|
||||
</a>
|
||||
<a href="https://nodejs.org/api/documentation.html#documentation_stability_index">
|
||||
<img src="https://img.shields.io/badge/stability-experimental-orange.svg?style=flat-square" alt="Stability" />
|
||||
</a>
|
||||
</div>
|
||||
|
||||
<img width="25%" src="http://image.prntscr.com/image/55fb47b99164465abefb2698a7bb142d.png" />
|
||||
<img width="24%" src="http://image.prntscr.com/image/0ab416fa479f427180476cad8a238f04.png" />
|
||||
<img width="24%" src="http://image.prntscr.com/image/918383bb5cde453ab2572461084b4601.png" />
|
||||
<img width="25%" src="http://i.imgur.com/iZypeny.png" />
|
||||
|
||||
# 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.
|
||||
22
ajax.js
Normal file
22
ajax.js
Normal file
|
|
@ -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));
|
||||
}
|
||||
|
|
@ -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/"
|
||||
|
||||
}
|
||||
240
css/main.css
Normal file
240
css/main.css
Normal file
|
|
@ -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;}
|
||||
}
|
||||
23
css/pure.min.css
vendored
Normal file
23
css/pure.min.css
vendored
Normal file
File diff suppressed because one or more lines are too long
39
index.html
Normal file
39
index.html
Normal file
|
|
@ -0,0 +1,39 @@
|
|||
<html>
|
||||
<head>
|
||||
<meta charset='utf-8'>
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
||||
<meta http-equiv="Content-Language" content="en">
|
||||
<meta name="viewport" content="width=device-width">
|
||||
<meta content="origin-when-cross-origin" name="referrer" />
|
||||
<title>POGOserver api</title>
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<link rel="stylesheet" type="text/css" href="css/main.css">
|
||||
<link rel="stylesheet" type="text/css" href="css/pure.min.css">
|
||||
</head>
|
||||
<body class="body">
|
||||
|
||||
<div class="area">
|
||||
<p>POGOserver</p>
|
||||
<p id="version" class="version"> </p>
|
||||
<p><button class="btn color-1 view login_input" id="connection_status" href="#" style="color:yellow;">Connecting..</button></p>
|
||||
</div>
|
||||
|
||||
<div id="login_area" class="area">
|
||||
<p class="login_area">Login</p>
|
||||
<p><input class="btn color-1 view input login_input" id="login_username" style="margin:-20px;" autocomplete="new-password" value="root"></input></p>
|
||||
<p><input class="btn color-1 view input login_input" id="login_password" type="password" autocomplete="new-password"></input></p>
|
||||
<p><button class="btn color-1 view login_input" id="login_attempt">Login</button></p>
|
||||
</div>
|
||||
|
||||
<div id="world_manager" class="area" style="display:none;">
|
||||
<p class="info" id="server_version">Server version: v0.1.0</p>
|
||||
<p class="info" id="connected_players">Connected players: 0</p>
|
||||
<p class="login_area" style="padding-bottom: 15px;">World Manager</p>
|
||||
<p><button class="btn color-1 view cmd_label label">Spawn</button><input class="btn color-1 view input login_input with_label" id="spawn_user" placeholder="Username" autocomplete="new-password"></input><input class="btn color-1 view input login_input with_label" autocomplete="new-password" id="spawn_pkmn" placeholder="Pokemon"></input><button id="submit_spawn" class="btn color-1 view login_input with_label submit">Submit</button></p>
|
||||
</div>
|
||||
|
||||
<script language="javascript" src="ajax.js"></script>
|
||||
<script language="javascript" src="main.js"></script>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
|
|
@ -1,2 +0,0 @@
|
|||
set LIBPROTOBUF=%CD%\protobuf
|
||||
npm install node-protobuf && npm install
|
||||
72
main.js
Normal file
72
main.js
Normal file
|
|
@ -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;
|
||||
});
|
||||
}
|
||||
32
package.json
32
package.json
|
|
@ -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": {}
|
||||
}
|
||||
10
run-linux.sh
10
run-linux.sh
|
|
@ -1,10 +0,0 @@
|
|||
#!/bin/bash
|
||||
|
||||
pause() {
|
||||
read -p "Press [Enter] key to exit"
|
||||
}
|
||||
|
||||
cd $(dirname $0)
|
||||
|
||||
npm install
|
||||
npm run start
|
||||
|
|
@ -1,2 +0,0 @@
|
|||
npm run start
|
||||
pause
|
||||
44
src/api.js
44
src/api.js
|
|
@ -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 + "!");
|
||||
}
|
||||
75
src/cycle.js
75
src/cycle.js
|
|
@ -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);
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
|
|
@ -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();
|
||||
});
|
||||
});
|
||||
|
||||
}
|
||||
|
|
@ -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);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
|
@ -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();
|
||||
});
|
||||
}
|
||||
227
src/db/query.js
227
src/db/query.js
|
|
@ -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
|
||||
]);
|
||||
|
||||
}
|
||||
|
|
@ -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)
|
||||
|
|
@ -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)
|
||||
75
src/dump.js
75
src/dump.js
|
|
@ -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);
|
||||
}
|
||||
|
||||
}
|
||||
39
src/http.js
39
src/http.js
|
|
@ -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);
|
||||
});
|
||||
});
|
||||
}
|
||||
190
src/index.js
190
src/index.js
|
|
@ -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);
|
||||
});
|
||||
|
||||
})();
|
||||
|
|
@ -1,6 +0,0 @@
|
|||
/**
|
||||
* Global shared parsed
|
||||
* game master file
|
||||
* @type {GameMaster}
|
||||
*/
|
||||
export let GAME_MASTER = 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
|
||||
);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -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);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -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);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -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
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -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);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -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);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -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);
|
||||
|
||||
}
|
||||
|
|
@ -1,7 +0,0 @@
|
|||
import POGOProtos from "pokemongo-protobuf";
|
||||
|
||||
export function GetPlayer() {
|
||||
|
||||
return (POGOProtos.serialize(buffer, "POGOProtos.Networking.Responses.GetPlayerResponse"));
|
||||
|
||||
}
|
||||
|
|
@ -1,7 +0,0 @@
|
|||
import POGOProtos from "pokemongo-protobuf";
|
||||
|
||||
export function GetPlayerProfile() {
|
||||
|
||||
return (POGOProtos.serialize(buffer, "POGOProtos.Networking.Responses.GetPlayerProfileResponse"));
|
||||
|
||||
}
|
||||
|
|
@ -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;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -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
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -1,17 +0,0 @@
|
|||
/**
|
||||
* @class MapObject
|
||||
*/
|
||||
export default class MapObject {
|
||||
|
||||
/** @constructor */
|
||||
constructor() {
|
||||
|
||||
this.uid = 0;
|
||||
|
||||
this.altitude = 0;
|
||||
this.latitude = 0;
|
||||
this.longitude = 0;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -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() {
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -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
|
||||
//
|
||||
});
|
||||
|
||||
}
|
||||
|
|
@ -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);
|
||||
};
|
||||
157
src/request.js
157
src/request.js
|
|
@ -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);
|
||||
|
||||
});
|
||||
|
||||
}
|
||||
|
|
@ -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);
|
||||
|
||||
});
|
||||
|
||||
}
|
||||
238
src/setup.js
238
src/setup.js
|
|
@ -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);
|
||||
|
||||
}
|
||||
82
src/utils.js
82
src/utils.js
|
|
@ -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))
|
||||
);
|
||||
}
|
||||
Loading…
Reference in New Issue
Block a user