mirror of
https://github.com/maierfelix/POGOserver.git
synced 2026-09-08 18:46:26 -05:00
5
.gitignore
vendored
5
.gitignore
vendored
@@ -1,6 +1,3 @@
|
||||
node_modules/
|
||||
scripts/
|
||||
logs/
|
||||
data/
|
||||
cfg.js
|
||||
npm-debug.*
|
||||
data/
|
||||
16
.help
16
.help
@@ -1,8 +1,8 @@
|
||||
clients : How many players are connected
|
||||
exit : Exit the server
|
||||
update : Update the server
|
||||
kick [PlayerName] : Kick player by username
|
||||
kickall : Kick all players
|
||||
clear : Clear the server console
|
||||
save : Save all players into database
|
||||
spawn [PlayerName] [PokemonName] [Amount] : Spawn pokemons at specific player
|
||||
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
.save
Normal file
1
.save
Normal file
@@ -0,0 +1 @@
|
||||
{"isFirstRun":false,"allowedApiHosts":["localhost"],"loginDetails":{"username":"root","password":"13377"}}
|
||||
@@ -6,8 +6,8 @@ export default {
|
||||
|
||||
// show greeting
|
||||
GREET: true,
|
||||
// emit api calls
|
||||
ENABLE_API: false,
|
||||
// allow api calls
|
||||
ENABLE_API: true,
|
||||
|
||||
// Server settings
|
||||
MAX_CONNECTIONS: 64,
|
||||
|
||||
2
install-windows.bat
vendored
Normal file
2
install-windows.bat
vendored
Normal file
@@ -0,0 +1,2 @@
|
||||
set LIBPROTOBUF=%CD%\protobuf
|
||||
npm install node-protobuf && npm install
|
||||
15
package.json
15
package.json
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "POGOServer",
|
||||
"version": "0.4.9",
|
||||
"version": "0.5.0",
|
||||
"description": "",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
@@ -9,7 +9,7 @@
|
||||
"scripts": {
|
||||
"test": "echo \"Error: no test specified\"",
|
||||
"babel-node": "babel-node --presets=es2015",
|
||||
"start": "nodemon --ignore tmp/ --ignore data/ --ignore logs/ --exec npm run babel-node -- ./src/index.js"
|
||||
"start": "npm run babel-node -- ./src/index.js"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 6.x",
|
||||
@@ -21,17 +21,12 @@
|
||||
"babel-cli": "^6.11.4",
|
||||
"babel-preset-es2015": "^6.13.1",
|
||||
"babel-preset-stage-0": "^6.5.0",
|
||||
"nodemon": "^1.7.1",
|
||||
"mongodb": "^2.2.5",
|
||||
"url": "^0.11.0",
|
||||
"prompt": "^1.0.0",
|
||||
"fs-extra": "^0.30.0",
|
||||
"mysql": "^2.11.1",
|
||||
"jwt-decode": "^2.1.0",
|
||||
"long": "^3.2.0",
|
||||
"pogo-asset-downloader": "^0.3.1",
|
||||
"node-pogo-protos": "^1.3.0",
|
||||
"path": "^0.12.7",
|
||||
"directory-tree": "^1.1.0",
|
||||
"nodegit": "^0.14.1",
|
||||
"fs-extra": "^0.30.0",
|
||||
"pokemongo-protobuf": "^1.11.0",
|
||||
"pcrypt": "git+https://github.com/laverdet/pcrypt.git"
|
||||
},
|
||||
|
||||
2
run-windows.bat
vendored
2
run-windows.bat
vendored
@@ -1,2 +1,2 @@
|
||||
npm install && npm run start
|
||||
npm run start
|
||||
pause
|
||||
245
src/api.js
245
src/api.js
@@ -1,44 +1,227 @@
|
||||
import fs from "fs";
|
||||
import url from "url";
|
||||
import s2 from "s2-geometry";
|
||||
import prompt from "prompt";
|
||||
|
||||
import print from "./print";
|
||||
import CFG from "../cfg";
|
||||
|
||||
export function ready(e) {
|
||||
if (e) console.log(e);
|
||||
else console.log("Ready!");
|
||||
import {
|
||||
getHashCodeFrom
|
||||
} from "./utils";
|
||||
|
||||
const S2Geo = s2.S2;
|
||||
|
||||
prompt.start({
|
||||
message: " ",
|
||||
delimiter: " "
|
||||
});
|
||||
|
||||
export function processApiCall(req, res, route) {
|
||||
|
||||
let save = JSON.parse(fs.readFileSync(".save", "utf8"));
|
||||
let allowedHosts = save.allowedApiHosts;
|
||||
|
||||
let hoster = url.parse(req.headers.referer).host;
|
||||
|
||||
if (!(allowedHosts.indexOf(hoster) > -1)) {
|
||||
this.grantApiAccess(req, res, route);
|
||||
return void 0;
|
||||
}
|
||||
|
||||
let raw = req.body.toString();
|
||||
let json = null;
|
||||
|
||||
try {
|
||||
json = JSON.parse(raw);
|
||||
} catch (e) {
|
||||
print(e, 31);
|
||||
this.answerApiCall(res, "");
|
||||
return void 0;
|
||||
}
|
||||
|
||||
if (this.isApiCall(json)) {
|
||||
json.host = hoster;
|
||||
if (json.action === "login") {
|
||||
this["api_login"](json).then((result) => {
|
||||
this.answerApiCall(res, JSON.stringify(result));
|
||||
});
|
||||
}
|
||||
else {
|
||||
if (this.apiClients[hoster]) {
|
||||
this["api_" + json.action](json).then((result) => {
|
||||
this.answerApiCall(res, JSON.stringify(result));
|
||||
});
|
||||
}
|
||||
else {
|
||||
print(`${hoster} isnt logged in! Kicking..`, 31);
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (json.action === "init") {
|
||||
this.answerApiCall(res, JSON.stringify({ success: true }));
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @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" : ""}`);
|
||||
export function grantApiAccess(req, res, route) {
|
||||
|
||||
let save = JSON.parse(fs.readFileSync(".save", "utf8"));
|
||||
|
||||
let hoster = url.parse(req.headers.referer).host;
|
||||
|
||||
let msg = `[Console] \x1b[33mGrant API access to ${hoster}?\x1b[0m`;
|
||||
|
||||
prompt.get([{ name: "grant", required: true, description: msg }], (e, result) => {
|
||||
if (result.grant === "y" || result.grant === "yes") {
|
||||
save.allowedApiHosts.push(hoster);
|
||||
fs.writeFileSync(".save", JSON.stringify(save), "utf8");
|
||||
print(`Successfully added ${hoster} to allowed API hosts!`);
|
||||
this.processApiCall(req, res, route);
|
||||
}
|
||||
else {
|
||||
print(`Denied API access for ${hoster}`, 31);
|
||||
this.answerApiCall(res, "");
|
||||
}
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {Player} player
|
||||
*/
|
||||
export function registerPlayer(player) {
|
||||
console.log(player.username + " registered!");
|
||||
export function answerApiCall(res, data) {
|
||||
res.setHeader("Access-Control-Allow-Origin", "*");
|
||||
res.setHeader("Access-Control-Allow-Methods", "GET, POST, OPTIONS, PUT, PATCH, DELETE");
|
||||
res.setHeader("Access-Control-Allow-Headers", "X-Requested-With,content-type");
|
||||
res.setHeader("Access-Control-Allow-Credentials", true);
|
||||
res.end(data);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {Player} player
|
||||
*/
|
||||
export function loginPlayer(player) {
|
||||
console.log(player.username + " logged in!");
|
||||
export function api_login(data) {
|
||||
|
||||
if (typeof data !== "object") return void 0;
|
||||
|
||||
let save = JSON.parse(fs.readFileSync(".save", "utf8"));
|
||||
|
||||
let success = false;
|
||||
|
||||
let username = save.loginDetails.username;
|
||||
let password = save.loginDetails.password;
|
||||
|
||||
if (
|
||||
username === data.username &&
|
||||
password === data.password
|
||||
) {
|
||||
success = true;
|
||||
if (!this.apiClients[data.host]) {
|
||||
print(`API access for ${data.host} granted!`);
|
||||
}
|
||||
print(`${data.host} logged in!`, 36);
|
||||
this.apiClients[data.host] = {
|
||||
timestamp: +new Date()
|
||||
};
|
||||
}
|
||||
|
||||
return new Promise((resolve) => {
|
||||
resolve({
|
||||
success: success
|
||||
});
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {Player} player
|
||||
*/
|
||||
export function killPlayer(player) {
|
||||
console.log(player.username + " killed!");
|
||||
export function api_heartBeat() {
|
||||
return new Promise((resolve) => {
|
||||
resolve({
|
||||
timestamp: +new Date()
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {Player} player
|
||||
*/
|
||||
export function updatePlayerAvatar(player) {
|
||||
console.log("Updated avatar of " + player.username + "!");
|
||||
export function api_getConnectedPlayers() {
|
||||
return new Promise((resolve) => {
|
||||
resolve({
|
||||
connected_players: this.world.connectedPlayers
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
export function api_getServerVersion() {
|
||||
return new Promise((resolve) => {
|
||||
resolve({
|
||||
version: CFG.VERSION
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
export function api_spawnPkmnToPlayer(data) {
|
||||
let name = String(data.player);
|
||||
let pkmn = String(data.pkmn).toUpperCase();
|
||||
print(`Spawned 1x ${pkmn}'s to ${name}!`);
|
||||
return new Promise((resolve) => {
|
||||
resolve({
|
||||
success: true
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
export function api_addFortToPosition(data) {
|
||||
return new Promise((resolve) => {
|
||||
this.world.insertFort(data).then((fort) => {
|
||||
resolve({
|
||||
success: true
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
export function api_deleteFortById(data) {
|
||||
let cellId = data.cell_id;
|
||||
let uid = data.cell_uid;
|
||||
return new Promise((resolve) => {
|
||||
this.world.getFortById(cellId, uid).then((fort) => {
|
||||
fort.deleted = true;
|
||||
this.world.processDeletedFort(fort);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
export function getNeighbors(lvl, lat, lng) {
|
||||
let origin = S2Geo.latLngToKey(lat, lng, lvl);
|
||||
let walk = [S2Geo.keyToId(origin)];
|
||||
let next = S2Geo.nextKey(origin);
|
||||
let prev = S2Geo.prevKey(origin);
|
||||
let ii = 0;
|
||||
let length = 20;
|
||||
for (; ii < length; ++ii) {
|
||||
walk.push(S2Geo.toId(prev));
|
||||
walk.push(S2Geo.toId(next));
|
||||
next = S2Geo.nextKey(next);
|
||||
prev = S2Geo.prevKey(prev);
|
||||
};
|
||||
return (walk);
|
||||
}
|
||||
|
||||
export function getNeighboredForts(cells, out, index) {
|
||||
return new Promise((resolve) => {
|
||||
let id = cells[index];
|
||||
this.world.getFortsByCell(id).then((res) => {
|
||||
out = out.concat(res.forts);
|
||||
if (++index >= cells.length) resolve(out);
|
||||
else resolve(this.getNeighboredForts(cells, out, index));
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
export function api_getFortsByPosition(data) {
|
||||
return new Promise((resolve) => {
|
||||
let lat = data.lat;
|
||||
let lng = data.lng;
|
||||
this.getNeighboredForts(this.getNeighbors(15, lat, lng), [], 0).then((res) => {
|
||||
resolve({
|
||||
forts: res,
|
||||
success: true
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
22
src/cycle.js
22
src/cycle.js
@@ -1,3 +1,4 @@
|
||||
import print from "./print";
|
||||
import CFG from "../cfg";
|
||||
|
||||
export function startCycle() {
|
||||
@@ -20,8 +21,6 @@ export function cycle() {
|
||||
|
||||
if (this.passedTicks <= 0) return void 0;
|
||||
|
||||
this.updatePlayers();
|
||||
|
||||
this.resetTimers();
|
||||
|
||||
return void 0;
|
||||
@@ -49,7 +48,7 @@ export function resetTimers() {
|
||||
this.saveTick++;
|
||||
// Save interval
|
||||
if (this.saveTick >= CFG.SAVE_INTERVAL) {
|
||||
this.saveAllPlayers();
|
||||
//this.saveAllPlayers();
|
||||
this.saveTick = 0;
|
||||
}
|
||||
return void 0;
|
||||
@@ -57,17 +56,20 @@ export function resetTimers() {
|
||||
|
||||
export function playerTimeoutTick() {
|
||||
|
||||
let client = null;
|
||||
let player = null;
|
||||
let maxTimeout = CFG.PLAYER_CONNECTION_TIMEOUT;
|
||||
|
||||
let ii = 0, length = this.clients.length;
|
||||
let players = this.world.players;
|
||||
|
||||
let ii = 0;
|
||||
let length = this.world.connectedPlayers;
|
||||
|
||||
for (; ii < length; ++ii) {
|
||||
client = this.clients[ii];
|
||||
if (this.time - client.timeout >= maxTimeout) {
|
||||
this.print(`${client.remoteAddress} timed out`, 34);
|
||||
this.savePlayer(client);
|
||||
this.removePlayer(client);
|
||||
player = players[ii];
|
||||
if (this.time - player.timeout >= maxTimeout) {
|
||||
print(`${player.remoteAddress} timed out`, 34);
|
||||
this.savePlayer(player);
|
||||
this.removePlayer(player);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -1,9 +1,11 @@
|
||||
import fs from "fs";
|
||||
|
||||
import print from "../print";
|
||||
import CFG from "../../cfg";
|
||||
|
||||
export function createTableIfNoExists(name) {
|
||||
export function createTableIfNotExists(name) {
|
||||
return new Promise((resolve) => {
|
||||
this.db.instance.query(`SHOW TABLES LIKE '${name}';`, (e, rows, fields) => {
|
||||
this.db.query(`SHOW TABLES LIKE '${name}';`, (e, rows, fields) => {
|
||||
if (e) console.log(e);
|
||||
else {
|
||||
// exists
|
||||
@@ -30,16 +32,16 @@ export function createTables() {
|
||||
|
||||
export function createTable(name) {
|
||||
|
||||
this.print(`Creating table ${name}`, 36);
|
||||
print(`Creating table ${name}`, 36);
|
||||
|
||||
let query = `
|
||||
CREATE TABLE ${name} (
|
||||
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) => {
|
||||
this.db.query(query, (e, rows) => {
|
||||
if (e) console.log(e);
|
||||
else resolve();
|
||||
});
|
||||
|
||||
@@ -7,7 +7,7 @@ import CFG from "../../cfg";
|
||||
*/
|
||||
export function getQueryByColumnFromTable(column, value, table) {
|
||||
return new Promise((resolve) => {
|
||||
this.db.instance.query(`SELECT * FROM ${table} WHERE ${column}=?`, [value], (e, rows) => {
|
||||
this.db.query(`SELECT * FROM ${table} WHERE ${column}=?`, [value], (e, rows) => {
|
||||
if (e) console.log(e);
|
||||
if (rows && rows.length) resolve(rows);
|
||||
else resolve(void 0);
|
||||
@@ -22,44 +22,9 @@ export function getQueryByColumnFromTable(column, value, table) {
|
||||
*/
|
||||
export function deleteQueryByColumnFromTable(column, value, table) {
|
||||
return new Promise((resolve) => {
|
||||
this.db.instance.query(`DELETE FROM ${table} WHERE ${column}=?`, [value], (e, rows) => {
|
||||
this.db.query(`DELETE FROM ${table} WHERE ${column}=?`, [value], (e, rows) => {
|
||||
if (e) console.log(e);
|
||||
else resolve(void 0);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {String} column
|
||||
* @param {String} value
|
||||
*/
|
||||
export function getPkmnByColumn(column, value) {
|
||||
return new Promise((resolve) => {
|
||||
this.getQueryByColumnFromTable(column, value, CFG.MYSQL_OWNED_PKMN_TABLE).then((query) => {
|
||||
resolve(query || []);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {String} column
|
||||
* @param {String} value
|
||||
*/
|
||||
export function getUserByColumn(column, value) {
|
||||
return new Promise((resolve) => {
|
||||
this.getQueryByColumnFromTable(column, value, CFG.MYSQL_USERS_TABLE).then((query) => {
|
||||
resolve(query);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {String} email
|
||||
*/
|
||||
export function getUserByEmail(email) {
|
||||
return new Promise((resolve) => {
|
||||
this.getQueryByColumnFromTable("email", email, CFG.MYSQL_USERS_TABLE).then((query) => {
|
||||
resolve(query);
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
121
src/db/index.js
121
src/db/index.js
@@ -1,9 +1,9 @@
|
||||
import fs from "fs";
|
||||
import mysql from "mysql";
|
||||
|
||||
import print from "../print";
|
||||
import CFG from "../../cfg";
|
||||
|
||||
export function setupConnection() {
|
||||
export function setupDatabaseConnection() {
|
||||
|
||||
let connection = mysql.createConnection({
|
||||
host : CFG.MYSQL_HOST_IP,
|
||||
@@ -16,21 +16,21 @@ export function setupConnection() {
|
||||
return new Promise((resolve) => {
|
||||
connection.connect((error) => {
|
||||
if (error) {
|
||||
this.print("MySQL " + error, 31);
|
||||
this.retry("Retrying again in ", () => this.setupConnection().then(resolve), 5);
|
||||
print("MySQL " + error, 31);
|
||||
this.retry("Retrying again in ", () => this.setupDatabaseConnection().then(resolve), 5);
|
||||
return void 0;
|
||||
}
|
||||
this.db.instance = connection;
|
||||
this.createTableIfNoExists(CFG.MYSQL_USERS_TABLE).then(() => {
|
||||
this.createTableIfNoExists(CFG.MYSQL_OWNED_PKMN_TABLE).then(() => {
|
||||
this.print(`\x1b[36;1mMySQL\x1b[0m\x1b[32;1m connection established\x1b[0m`);
|
||||
this.db = connection;
|
||||
this.createTableIfNotExists(CFG.MYSQL_USERS_TABLE).then(() => {
|
||||
this.createTableIfNotExists(CFG.MYSQL_OWNED_PKMN_TABLE).then(() => {
|
||||
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.setupConnection().then(resolve), 5);
|
||||
print("MySQL " + error, 31);
|
||||
this.retry("Trying to reconnect in ", () => this.setupDatabaseConnection().then(resolve), 5);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -40,106 +40,7 @@ export function setupConnection() {
|
||||
* @param {Function} resolve
|
||||
*/
|
||||
export function closeConnection(resolve) {
|
||||
this.db.instance.end(() => {
|
||||
this.db.end(() => {
|
||||
resolve();
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {Object} obj
|
||||
*/
|
||||
export function createUser(obj) {
|
||||
|
||||
let query = this.getUserQuery("INSERT INTO", "");
|
||||
let data = this.getUserQueryData(obj);
|
||||
|
||||
return new Promise((resolve) => {
|
||||
this.db.instance.query(query, data, (e) => {
|
||||
if (e) this.print(e, 31);
|
||||
else resolve();
|
||||
});
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {Object} obj
|
||||
*/
|
||||
export function createOwnedPokemon(obj) {
|
||||
|
||||
let query = this.getOwnedPkmnQuery("INSERT INTO", "");
|
||||
let data = this.getOwnedPkmnQueryData(obj);
|
||||
|
||||
return new Promise((resolve) => {
|
||||
this.db.instance.query(query, data, resolve);
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {Object} obj
|
||||
*/
|
||||
export function deleteOwnedPokemon(id) {
|
||||
|
||||
return new Promise((resolve) => {
|
||||
this.deleteQueryByColumnFromTable("id", id, CFG.MYSQL_OWNED_PKMN_TABLE).then(() => {
|
||||
resolve();
|
||||
});
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {Player} player
|
||||
*/
|
||||
export function updateUser(player) {
|
||||
|
||||
let query = this.getUserQuery("UPDATE", "WHERE email=? LIMIT 1");
|
||||
let data = this.getUserQueryData(player);
|
||||
|
||||
return new Promise((resolve) => {
|
||||
this.db.instance.query(query, data, resolve);
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {Player} player
|
||||
*/
|
||||
export function updateUserItems(player) {
|
||||
|
||||
let query = this.getUserItemQuery("UPDATE", "WHERE email=? LIMIT 1");
|
||||
let data = this.getUserItemQueryData(player);
|
||||
|
||||
return new Promise((resolve) => {
|
||||
this.db.instance.query(query, data, resolve);
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {Player} player
|
||||
*/
|
||||
export function updateUserParty(player) {
|
||||
|
||||
let pkmn = null;
|
||||
let data = null;
|
||||
let query = this.getOwnedPkmnQuery("UPDATE", "WHERE id=? AND owner_id=? LIMIT 1");
|
||||
|
||||
return new Promise((resolve) => {
|
||||
let ii = 0;
|
||||
let index = 0;
|
||||
let length = player.party.length;
|
||||
// dont go on if party empty
|
||||
if (!length) return resolve();
|
||||
for (; ii < length; ++ii) {
|
||||
pkmn = player.party[ii];
|
||||
data = this.getOwnedPkmnQueryData(pkmn);
|
||||
data.push(pkmn.id, player.owner_id);
|
||||
this.db.instance.query(query, data, () => {
|
||||
if (++index >= length) resolve();
|
||||
});
|
||||
};
|
||||
});
|
||||
|
||||
}
|
||||
@@ -1,8 +0,0 @@
|
||||
id int(15) NOT NULL AUTO_INCREMENT,
|
||||
fort_id varchar(42) NOT NULL,
|
||||
latitude double NOT NULL,
|
||||
longitude double NOT NULL,
|
||||
enabled tinyint(1) NOT NULL,
|
||||
items_awarded varchar(42) NOT NULL,
|
||||
experience_awarded int(10) NOT NULL
|
||||
PRIMARY KEY (id)
|
||||
@@ -1,8 +0,0 @@
|
||||
id int(15) NOT NULL AUTO_INCREMENT,
|
||||
fort_id varchar(42) NOT NULL,
|
||||
latitude double NOT NULL,
|
||||
longitude double NOT NULL,
|
||||
enabled tinyint(1) NOT NULL,
|
||||
items_awarded varchar(42) NOT NULL,
|
||||
experience_awarded int(10) NOT NULL
|
||||
PRIMARY KEY (id)
|
||||
@@ -1,25 +1,25 @@
|
||||
id int(11) NOT NULL AUTO_INCREMENT,
|
||||
username longtext NOT NULL,
|
||||
email longtext NOT NULL,
|
||||
exp int(255) NOT NULL,
|
||||
level int(11) NOT NULL,
|
||||
stardust int(255) NOT NULL,
|
||||
pokecoins int(255) NOT NULL,
|
||||
team int(11) NOT NULL,
|
||||
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 int(255) NOT NULL,
|
||||
altitude double NOT NULL,
|
||||
send_marketing_emails tinyint(1) NOT NULL,
|
||||
send_push_notifications tinyint(1) NOT NULL,
|
||||
skin int(11) NOT NULL,
|
||||
hair int(11) NOT NULL,
|
||||
shirt int(11) NOT NULL,
|
||||
pants int(11) NOT NULL,
|
||||
hat int(11) NOT NULL,
|
||||
shoes int(11) NOT NULL,
|
||||
eyes int(11) NOT NULL,
|
||||
gender int(11) NOT NULL,
|
||||
backpack int(11) 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,
|
||||
@@ -45,4 +45,10 @@ 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 NOT NULL,
|
||||
PRIMARY KEY (id)
|
||||
78
src/dump.js
Normal file
78
src/dump.js
Normal file
@@ -0,0 +1,78 @@
|
||||
import fse from "fs-extra";
|
||||
import POGOProtos from "pokemongo-protobuf";
|
||||
|
||||
import print from "./print";
|
||||
import CFG from "../cfg";
|
||||
|
||||
import { _toCC } from "./utils";
|
||||
|
||||
/**
|
||||
* @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) {
|
||||
print("Dump traffic: " + e, 31);
|
||||
}
|
||||
|
||||
}
|
||||
38
src/http.js
Normal file
38
src/http.js
Normal file
@@ -0,0 +1,38 @@
|
||||
import http from "http";
|
||||
|
||||
import print from "./print";
|
||||
import CFG from "../cfg";
|
||||
|
||||
/**
|
||||
* @return {HTTP}
|
||||
*/
|
||||
export function createHTTPServer() {
|
||||
let server = http.createServer((req, res) => {
|
||||
if (this.world.isFull()) {
|
||||
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.routeRequest(req, res);
|
||||
});
|
||||
});
|
||||
server.listen(CFG.PORT);
|
||||
return (server);
|
||||
}
|
||||
|
||||
export function shutdown() {
|
||||
this.socket.close(() => {
|
||||
print("Closed http server!", 33);
|
||||
this.closeConnection(() => {
|
||||
print("Closed database connection!", 33);
|
||||
print("Server shutdown!", 31);
|
||||
setTimeout(() => process.exit(1), 2e3);
|
||||
});
|
||||
});
|
||||
}
|
||||
261
src/index.js
261
src/index.js
@@ -1,21 +1,23 @@
|
||||
import fs from "fs";
|
||||
import os from "os";
|
||||
import fse from "fs-extra";
|
||||
import http from "http";
|
||||
import proto from "./proto";
|
||||
import EventEmitter from "events";
|
||||
import request from "request";
|
||||
import POGOProtos from "pokemongo-protobuf";
|
||||
|
||||
import {
|
||||
inherit,
|
||||
_toCC
|
||||
} from "./utils";
|
||||
|
||||
import print from "./print";
|
||||
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 _player from "./player";
|
||||
import * as _request from "./request";
|
||||
import * as _response from "./response";
|
||||
import * as _process from "./process";
|
||||
@@ -29,26 +31,21 @@ const greetMessage = fs.readFileSync(".greet", "utf8");
|
||||
/**
|
||||
* @class GameServer
|
||||
*/
|
||||
export default class GameServer extends EventEmitter {
|
||||
export default class GameServer {
|
||||
|
||||
/** @constructor */
|
||||
constructor() {
|
||||
|
||||
super(null);
|
||||
|
||||
this.STATES = {
|
||||
PAUSE: false,
|
||||
DEBUG: false,
|
||||
CRASH: false
|
||||
};
|
||||
|
||||
this.db = {
|
||||
instance: null,
|
||||
collections: {}
|
||||
};
|
||||
this.db = null;
|
||||
|
||||
this.apiClients = {};
|
||||
|
||||
this.assets = {};
|
||||
this.master = null;
|
||||
this.socket = null;
|
||||
this.cycleInstance = null;
|
||||
|
||||
@@ -60,201 +57,81 @@ export default class GameServer extends EventEmitter {
|
||||
this.timeoutTick = 0;
|
||||
this.passedTicks = 0;
|
||||
|
||||
this.clients = [];
|
||||
this.wild_pokemons = [];
|
||||
|
||||
this.initAPI();
|
||||
|
||||
if (CFG.GREET) this.greet();
|
||||
|
||||
this.print(`Booting Server v${require("../package.json").version}...`, 33);
|
||||
|
||||
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"]);
|
||||
}
|
||||
}
|
||||
|
||||
clientAlreadyConnected(client) {
|
||||
|
||||
let remoteAddress = client.headers.host;
|
||||
|
||||
let ii = 0, length = this.clients.length;
|
||||
|
||||
for (; ii < length; ++ii) {
|
||||
if (this.clients[ii].remoteAddress === remoteAddress) {
|
||||
return (true);
|
||||
this.getLatestVersion().then((latest) => {
|
||||
let current = require("../package.json").version;
|
||||
print(`Booting Server v${current}`, 33);
|
||||
if (current < latest) {
|
||||
print(`WARNING: Please update to the latest build v${latest}!`, 33);
|
||||
}
|
||||
};
|
||||
|
||||
return (false);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @return {HTTP}
|
||||
*/
|
||||
createHTTPServer() {
|
||||
let server = http.createServer((req, res) => {
|
||||
if (this.clients.length >= CFG.MAX_CONNECTIONS) {
|
||||
this.print(`Server is full! Refused ${req.headers.host}`, 31);
|
||||
return void 0;
|
||||
}
|
||||
|
||||
let player = null;
|
||||
|
||||
if (this.clientAlreadyConnected(req)) player = this.getPlayerByRequest(req);
|
||||
else player = this.addPlayer(req, res);
|
||||
|
||||
let chunks = [];
|
||||
req.on("data", (chunk) => {
|
||||
chunks.push(chunk);
|
||||
});
|
||||
req.on("end", () => {
|
||||
let buffer = Buffer.concat(chunks);
|
||||
req.body = buffer;
|
||||
player.updateResponse(res);
|
||||
this.routeRequest(req, res);
|
||||
});
|
||||
this.world = new World(this);
|
||||
this.setup();
|
||||
});
|
||||
server.listen(CFG.PORT);
|
||||
return (server);
|
||||
|
||||
}
|
||||
|
||||
setupDatabaseConnection() {
|
||||
|
||||
fetchVersioningUrl() {
|
||||
return new Promise((resolve) => {
|
||||
|
||||
let name = String(CFG.DATABASE_TYPE).toUpperCase();
|
||||
|
||||
switch (name) {
|
||||
case "MYSQL":
|
||||
inherit(GameServer, _mysql);
|
||||
this.setupConnection().then(resolve);
|
||||
break;
|
||||
default:
|
||||
this.print("Invalid database connection type!", 31);
|
||||
return void 0;
|
||||
break;
|
||||
};
|
||||
|
||||
let url = "";
|
||||
let branch = "dev";
|
||||
let base = "https://raw.githubusercontent.com";
|
||||
url = require("../package.json").repository.url;
|
||||
url = url.replace("git://", "");
|
||||
url = url.replace(".git", "");
|
||||
url = url.replace("github.com/", "");
|
||||
url = `${base}/${url}/${branch}/package.json`;
|
||||
resolve(url);
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
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);
|
||||
getLatestVersion() {
|
||||
return new Promise((resolve) => {
|
||||
this.fetchVersioningUrl().then((url) => {
|
||||
request({url: url}, (error, response, body) => {
|
||||
let json = null;
|
||||
try {
|
||||
json = JSON.parse(body);
|
||||
} catch (e) {
|
||||
json = {};
|
||||
print(e, 31);
|
||||
}
|
||||
resolve(json.version);
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {String} msg
|
||||
* @param {Number} color
|
||||
* @param {Boolean} nl
|
||||
* @param {Object} obj
|
||||
* @return {Boolean}
|
||||
*/
|
||||
print(msg, color, nl) {
|
||||
this.emit("print", msg, color, nl);
|
||||
isApiCall(call) {
|
||||
let action = String(call.action);
|
||||
return (
|
||||
"api_" + action in _api
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {String} msg
|
||||
* @param {Function} func
|
||||
* @param {Function} fn
|
||||
* @param {Number} timer
|
||||
*/
|
||||
retry(msg, func, 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, func, --timer), 1e3);
|
||||
print(`${msg}${timer}s`, 33, true);
|
||||
if (timer >= 1) setTimeout(() => this.retry(msg, fn, --timer), 1e3);
|
||||
else {
|
||||
process.stdout.write("\n");
|
||||
func();
|
||||
fn();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {Request} req
|
||||
* @param {Array} res
|
||||
* @return {Object}
|
||||
* @return {String}
|
||||
*/
|
||||
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
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
getLocalIPv4() {
|
||||
let address = null;
|
||||
let interfaces = os.networkInterfaces();
|
||||
@@ -264,15 +141,22 @@ export default class GameServer extends EventEmitter {
|
||||
return (address);
|
||||
}
|
||||
|
||||
directoryExists(directory) {
|
||||
/**
|
||||
* @param {Buffer} buffer
|
||||
* @param {String} schema
|
||||
*/
|
||||
parseProtobuf(buffer, schema) {
|
||||
try {
|
||||
fs.statSync(directory);
|
||||
return true;
|
||||
} catch(e) {
|
||||
return false;
|
||||
return POGOProtos.parseWithUnknown(buffer, schema);
|
||||
} catch (e) {
|
||||
print(e, 31);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {String} path
|
||||
* @return {Boolean}
|
||||
*/
|
||||
fileExists(path) {
|
||||
try {
|
||||
fs.statSync(path);
|
||||
@@ -288,9 +172,11 @@ export default class GameServer extends EventEmitter {
|
||||
|
||||
}
|
||||
|
||||
inherit(GameServer, _api);
|
||||
inherit(GameServer, _dump);
|
||||
inherit(GameServer, _http);
|
||||
inherit(GameServer, _setup);
|
||||
inherit(GameServer, _cycle);
|
||||
inherit(GameServer, _player);
|
||||
inherit(GameServer, _request);
|
||||
inherit(GameServer, _response);
|
||||
inherit(GameServer, _process);
|
||||
@@ -299,10 +185,9 @@ inherit(GameServer, _mysql_get);
|
||||
inherit(GameServer, _mysql_query);
|
||||
inherit(GameServer, _mysql_create);
|
||||
|
||||
(() => {
|
||||
|
||||
((Server) => {
|
||||
|
||||
const server = new Server();
|
||||
const server = new GameServer();
|
||||
|
||||
process.openStdin().addListener("data", (data) => {
|
||||
server.stdinInput(data);
|
||||
@@ -312,4 +197,4 @@ inherit(GameServer, _mysql_create);
|
||||
server.uncaughtException(data);
|
||||
});
|
||||
|
||||
})(GameServer);
|
||||
})();
|
||||
84
src/models/GameMaster/index.js
Normal file
84
src/models/GameMaster/index.js
Normal file
@@ -0,0 +1,84 @@
|
||||
import POGOProtos from "pokemongo-protobuf";
|
||||
|
||||
/**
|
||||
* @class GameMaster
|
||||
*/
|
||||
export default class GameMaster {
|
||||
|
||||
/**
|
||||
* @param {Object} decode
|
||||
* @constructor
|
||||
*/
|
||||
constructor(decode) {
|
||||
|
||||
this.settings = this.buildSettings();
|
||||
|
||||
this.decode = decode;
|
||||
this.buffer = this.encode();
|
||||
|
||||
this.parse();
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @return {Buffer}
|
||||
*/
|
||||
encode() {
|
||||
return (
|
||||
POGOProtos.serialize(this.decode, "POGOProtos.Networking.Responses.DownloadItemTemplatesResponse")
|
||||
);
|
||||
}
|
||||
|
||||
parse() {
|
||||
|
||||
let ii = 0;
|
||||
let length = 0;
|
||||
|
||||
let item = null;
|
||||
let items = this.decode.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
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return {Buffer}
|
||||
*/
|
||||
serialize() {
|
||||
return (
|
||||
this.buffer
|
||||
);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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
|
||||
//
|
||||
});
|
||||
|
||||
}
|
||||
137
src/models/Player/Avatar/index.js
Normal file
137
src/models/Player/Avatar/index.js
Normal file
@@ -0,0 +1,137 @@
|
||||
/**
|
||||
* @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;
|
||||
}
|
||||
}
|
||||
|
||||
serialize() {
|
||||
return ({
|
||||
skin: this.skin,
|
||||
hair: this.hair,
|
||||
shirt: this.shirt,
|
||||
pants: this.pants,
|
||||
hat: this.hat,
|
||||
shoes: this.shoes,
|
||||
eyes: this.eyes,
|
||||
gender: this.gender,
|
||||
backpack: this.backpack
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
71
src/models/Player/Bag/CandyBag/index.js
Normal file
71
src/models/Player/Bag/CandyBag/index.js
Normal file
@@ -0,0 +1,71 @@
|
||||
/**
|
||||
* @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}
|
||||
*/
|
||||
serialize() {
|
||||
|
||||
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);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
70
src/models/Player/Bag/index.js
Normal file
70
src/models/Player/Bag/index.js
Normal file
@@ -0,0 +1,70 @@
|
||||
/**
|
||||
* @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);
|
||||
}
|
||||
|
||||
}
|
||||
24
src/models/Player/Contact/index.js
Normal file
24
src/models/Player/Contact/index.js
Normal file
@@ -0,0 +1,24 @@
|
||||
/**
|
||||
* @class Contact
|
||||
*/
|
||||
export default class Contact {
|
||||
|
||||
/** @constructor */
|
||||
constructor() {
|
||||
|
||||
this.sendMarketingEmails = false;
|
||||
this.sendPushNotifications = false;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @return {Object}
|
||||
*/
|
||||
serialize() {
|
||||
return ({
|
||||
send_marketing_emails: this.sendMarketingEmails,
|
||||
send_push_notifications: this.sendPushNotifications
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
30
src/models/Player/Currency/index.js
Normal file
30
src/models/Player/Currency/index.js
Normal file
@@ -0,0 +1,30 @@
|
||||
/**
|
||||
* @class Currency
|
||||
*/
|
||||
export default class Currency {
|
||||
|
||||
/** @constructor */
|
||||
constructor() {
|
||||
|
||||
this.currencies = {
|
||||
"POKECOINS": 0,
|
||||
"STARDUST": 0
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @return {Array}
|
||||
*/
|
||||
serialize() {
|
||||
let out = [];
|
||||
for (let key in this.currencies) {
|
||||
out.push({
|
||||
name: key,
|
||||
amount: this.currencies[key]
|
||||
});
|
||||
};
|
||||
return (out);
|
||||
}
|
||||
|
||||
}
|
||||
94
src/models/Player/Info/index.js
Normal file
94
src/models/Player/Info/index.js
Normal file
@@ -0,0 +1,94 @@
|
||||
/**
|
||||
* @class Info
|
||||
*/
|
||||
export default class Info {
|
||||
|
||||
/** @constructor */
|
||||
constructor() {
|
||||
|
||||
this.lvl = 0;
|
||||
|
||||
this.team = 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;
|
||||
|
||||
this.maxPkmnStorage = 250;
|
||||
this.maxItemStorage = 350;
|
||||
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
serialize() {
|
||||
return ({
|
||||
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
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
68
src/models/Player/Party/index.js
Normal file
68
src/models/Player/Party/index.js
Normal file
@@ -0,0 +1,68 @@
|
||||
import Pokemon from "../../Pokemon";
|
||||
|
||||
/**
|
||||
* @class Party
|
||||
*/
|
||||
export default 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
|
||||
* @return {Pokemon}
|
||||
*/
|
||||
deletePkmn(id) {
|
||||
let index = this.getPkmnIndexById(id);
|
||||
let pkmn = this.party[index];
|
||||
if (pkmn) this.party.splice(index, 1)[0];
|
||||
}
|
||||
|
||||
/**
|
||||
* @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);
|
||||
}
|
||||
|
||||
}
|
||||
31
src/models/Player/Tutorial/index.js
Normal file
31
src/models/Player/Tutorial/index.js
Normal file
@@ -0,0 +1,31 @@
|
||||
/**
|
||||
* @class Tutorial
|
||||
*/
|
||||
export default class Tutorial {
|
||||
|
||||
/** @constructor */
|
||||
constructor() {
|
||||
this.states = [];
|
||||
}
|
||||
|
||||
skipTutorial() {
|
||||
this.states = [
|
||||
"LEGAL_SCREEN",
|
||||
"AVATAR_SELECTION",
|
||||
"POKEMON_CAPTURE",
|
||||
"NAME_SELECTION",
|
||||
"FIRST_TIME_EXPERIENCE_COMPLETE"
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @return {Array}
|
||||
*/
|
||||
serialize() {
|
||||
this.skipTutorial();
|
||||
return (
|
||||
this.states
|
||||
);
|
||||
}
|
||||
|
||||
}
|
||||
143
src/models/Player/index.js
Normal file
143
src/models/Player/index.js
Normal file
@@ -0,0 +1,143 @@
|
||||
import POGOProtos from "pokemongo-protobuf";
|
||||
|
||||
import Bag from "./Bag";
|
||||
import Info from "./Info";
|
||||
import Party from "./Party";
|
||||
import Avatar from "./Avatar";
|
||||
import Contact from "./Contact";
|
||||
import Tutorial from "./Tutorial";
|
||||
import Currency from "./Currency";
|
||||
|
||||
import MapObject from "../World/MapObject";
|
||||
|
||||
import print from "../../print";
|
||||
import CFG from "../../../cfg";
|
||||
|
||||
import * as _packets from "./packets";
|
||||
|
||||
import {
|
||||
inherit,
|
||||
parseSignature
|
||||
} from "../../utils";
|
||||
|
||||
import { GAME_MASTER } from "../../shared";
|
||||
|
||||
/**
|
||||
* @class Player
|
||||
*/
|
||||
export default class Player extends MapObject {
|
||||
|
||||
/**
|
||||
* @param {Object} obj
|
||||
* @constructor
|
||||
*/
|
||||
constructor(obj) {
|
||||
|
||||
super(null);
|
||||
|
||||
this.world = obj.world;
|
||||
|
||||
this._email = null;
|
||||
|
||||
this.username = "unknown";
|
||||
|
||||
this.email_verified = false;
|
||||
|
||||
this.platform = null;
|
||||
|
||||
this.isPTCAccount = false;
|
||||
this.isGoogleAccount = false;
|
||||
|
||||
this.isIOS = false;
|
||||
this.isAndroid = false;
|
||||
|
||||
this.hasSignature = false;
|
||||
|
||||
this.authenticated = false;
|
||||
|
||||
this.request = null;
|
||||
this.response = null;
|
||||
|
||||
this.remoteAddress = null;
|
||||
|
||||
this.bag = new Bag(this);
|
||||
this.info = new Info(this);
|
||||
this.party = new Party(this);
|
||||
this.avatar = new Avatar(this);
|
||||
this.contact = new Contact(this);
|
||||
this.tutorial = new Tutorial(this);
|
||||
this.currency = new Currency(this);
|
||||
/*
|
||||
this.pokedex = new Pokedex(this);
|
||||
*/
|
||||
this.refreshSocket(obj.request, obj.response);
|
||||
|
||||
}
|
||||
|
||||
get email() {
|
||||
return (this._email);
|
||||
}
|
||||
set email(value) {
|
||||
this._email = value;
|
||||
this.username = value.replace("@gmail.com", "");
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {Buffer} buffer
|
||||
*/
|
||||
sendResponse(buffer) {
|
||||
this.response.end(buffer);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {Request} req
|
||||
* @param {Response} res
|
||||
*/
|
||||
refreshSocket(req, res) {
|
||||
this.request = POGOProtos.parseWithUnknown(req.body, "POGOProtos.Networking.Envelopes.RequestEnvelope");
|
||||
this.response = res;
|
||||
}
|
||||
|
||||
getDevicePlatform() {
|
||||
let request = this.request;
|
||||
if (request.unknown6 && request.unknown6[0]) {
|
||||
let sig = parseSignature(request);
|
||||
if (sig.device_info !== void 0) {
|
||||
this.hasSignature = true;
|
||||
this.isIOS = sig.device_info.device_brand === "Apple";
|
||||
this.isAndroid = !this.isIOS;
|
||||
this.platform = this.isIOS ? "ios" : "android";
|
||||
print(`${this.email} is playing with an ${this.isIOS ? "Apple" : "Android"} device!`, 36);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {String} type
|
||||
* @param {Object} msg
|
||||
*/
|
||||
getPacket(type, msg) {
|
||||
return new Promise((resolve) => {
|
||||
switch (type) {
|
||||
case "GET_PLAYER":
|
||||
resolve(this.GetPlayer(msg));
|
||||
break;
|
||||
case "GET_INVENTORY":
|
||||
resolve(this.GetInventory(msg));
|
||||
break;
|
||||
case "GET_ASSET_DIGEST":
|
||||
resolve(this.GetAssetDigest(msg));
|
||||
break;
|
||||
case "GET_HATCHED_EGGS":
|
||||
resolve(this.GetHatchedEggs(msg));
|
||||
break;
|
||||
case "CHECK_AWARDED_BADGES":
|
||||
resolve(this.CheckAwardedBadges(msg));
|
||||
break;
|
||||
};
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
inherit(Player, _packets);
|
||||
19
src/models/Player/packets/CheckAwardedBadges.js
Normal file
19
src/models/Player/packets/CheckAwardedBadges.js
Normal file
@@ -0,0 +1,19 @@
|
||||
import POGOProtos from "pokemongo-protobuf";
|
||||
|
||||
/**
|
||||
* @param {Object} msg
|
||||
* @return {Buffer}
|
||||
*/
|
||||
export default function CheckAwardedBadges(msg) {
|
||||
|
||||
let buffer = {
|
||||
success: true,
|
||||
awarded_badges: [],
|
||||
awarded_badge_levels: []
|
||||
};
|
||||
|
||||
return (
|
||||
POGOProtos.serialize(buffer, "POGOProtos.Networking.Responses.CheckAwardedBadgesResponse")
|
||||
);
|
||||
|
||||
}
|
||||
13
src/models/Player/packets/GetAssetDigest.js
Normal file
13
src/models/Player/packets/GetAssetDigest.js
Normal file
@@ -0,0 +1,13 @@
|
||||
import POGOProtos from "pokemongo-protobuf";
|
||||
|
||||
import * as shared from "../../../shared";
|
||||
|
||||
/**
|
||||
* @param {Object} msg
|
||||
* @return {Buffer}
|
||||
*/
|
||||
export default function GetAssetDigest(msg) {
|
||||
return (
|
||||
shared.GAME_ASSETS[this.platform].buffer
|
||||
);
|
||||
}
|
||||
20
src/models/Player/packets/GetAuthTicket.js
Normal file
20
src/models/Player/packets/GetAuthTicket.js
Normal file
@@ -0,0 +1,20 @@
|
||||
import POGOProtos from "pokemongo-protobuf";
|
||||
|
||||
export default function GetAuthTicket(id) {
|
||||
|
||||
let buffer = ({
|
||||
status_code: 53,
|
||||
request_id: id,
|
||||
api_url: "pgorelease.nianticlabs.com/custom",
|
||||
auth_ticket: {
|
||||
start: new Buffer(""),
|
||||
expire_timestamp_ms: 9999999999999,
|
||||
end: new Buffer("")
|
||||
}
|
||||
});
|
||||
|
||||
return (
|
||||
POGOProtos.serialize(buffer, "POGOProtos.Networking.Envelopes.ResponseEnvelope")
|
||||
);
|
||||
|
||||
}
|
||||
21
src/models/Player/packets/GetHatchedEggs.js
Normal file
21
src/models/Player/packets/GetHatchedEggs.js
Normal file
@@ -0,0 +1,21 @@
|
||||
import POGOProtos from "pokemongo-protobuf";
|
||||
|
||||
/**
|
||||
* @param {Object} msg
|
||||
* @return {Buffer}
|
||||
*/
|
||||
export default function GetHatchedEggs(msg) {
|
||||
|
||||
let buffer = {
|
||||
success: true,
|
||||
pokemon_id: [],
|
||||
experience_awarded: [],
|
||||
candy_awarded: [],
|
||||
stardust_awarded: []
|
||||
};
|
||||
|
||||
return (
|
||||
POGOProtos.serialize(buffer, "POGOProtos.Networking.Responses.GetHatchedEggsResponse")
|
||||
);
|
||||
|
||||
}
|
||||
@@ -1,47 +1,33 @@
|
||||
import POGOProtos from "pokemongo-protobuf";
|
||||
|
||||
export function GetInventory() {
|
||||
|
||||
let stats = this.GetInventoryPlayer();
|
||||
/**
|
||||
* @param {Object} msg
|
||||
* @return {Buffer}
|
||||
*/
|
||||
export default function GetInventory(msg) {
|
||||
/*
|
||||
let items = this.GetInventoryItems();
|
||||
let party = this.GetInventoryParty();
|
||||
*/
|
||||
|
||||
let buffer = ({
|
||||
let stats = {
|
||||
modified_timestamp_ms: +new Date(),
|
||||
inventory_item_data: {
|
||||
player_stats: this.info.serialize()
|
||||
}
|
||||
};
|
||||
|
||||
let buffer = {
|
||||
success: true,
|
||||
inventory_delta: {
|
||||
new_timestamp_ms: new Date().getTime(),
|
||||
inventory_items: stats.concat(items).concat(party)
|
||||
inventory_items: [stats]
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
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
|
||||
}
|
||||
}
|
||||
});
|
||||
return (
|
||||
POGOProtos.serialize(buffer, "POGOProtos.Networking.Responses.GetInventoryResponse")
|
||||
);
|
||||
|
||||
}
|
||||
|
||||
28
src/models/Player/packets/GetPlayer.js
Normal file
28
src/models/Player/packets/GetPlayer.js
Normal file
@@ -0,0 +1,28 @@
|
||||
import POGOProtos from "pokemongo-protobuf";
|
||||
|
||||
/**
|
||||
* @param {Object} msg
|
||||
* @return {Buffer}
|
||||
*/
|
||||
export default function GetPlayer(msg) {
|
||||
|
||||
let buffer = {
|
||||
creation_timestamp_ms: new Date().getTime(),
|
||||
username: this.username,
|
||||
team: this.team,
|
||||
tutorial_state: this.tutorial.serialize(),
|
||||
avatar: this.avatar.serialize(),
|
||||
max_pokemon_storage: this.maxPkmnStorage,
|
||||
max_item_storage: this.maxItemStorage,
|
||||
daily_bonus: {
|
||||
next_defender_bonus_collect_timestamp_ms: +new Date()
|
||||
},
|
||||
contact_settings: this.contact.serialize(),
|
||||
currencies: this.currency.serialize()
|
||||
};
|
||||
|
||||
return (
|
||||
POGOProtos.serialize({ success: true, player_data: buffer }, "POGOProtos.Networking.Responses.GetPlayerResponse")
|
||||
);
|
||||
|
||||
}
|
||||
9
src/models/Player/packets/GetPlayerProfile.js
Normal file
9
src/models/Player/packets/GetPlayerProfile.js
Normal file
@@ -0,0 +1,9 @@
|
||||
import POGOProtos from "pokemongo-protobuf";
|
||||
|
||||
export default function GetPlayerProfile() {
|
||||
|
||||
return (
|
||||
POGOProtos.serialize(buffer, "POGOProtos.Networking.Responses.GetPlayerProfileResponse")
|
||||
);
|
||||
|
||||
}
|
||||
7
src/models/Player/packets/index.js
Normal file
7
src/models/Player/packets/index.js
Normal file
@@ -0,0 +1,7 @@
|
||||
export GetPlayer from "./GetPlayer";
|
||||
export GetInventory from "./GetInventory";
|
||||
export GetAuthTicket from "./GetAuthTicket";
|
||||
export GetHatchedEggs from "./GetHatchedEggs";
|
||||
export GetAssetDigest from "./GetAssetDigest";
|
||||
export GetPlayerProfile from "./GetPlayerProfile";
|
||||
export CheckAwardedBadges from "./CheckAwardedBadges";
|
||||
28
src/models/Pokemon/WildPokemon.js
Normal file
28
src/models/Pokemon/WildPokemon.js
Normal file
@@ -0,0 +1,28 @@
|
||||
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;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
129
src/models/Pokemon/index.js
Normal file
129
src/models/Pokemon/index.js
Normal file
@@ -0,0 +1,129 @@
|
||||
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) {
|
||||
|
||||
super(null);
|
||||
|
||||
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}
|
||||
*/
|
||||
serialize() {
|
||||
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
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
107
src/models/World/Fort/index.js
Normal file
107
src/models/World/Fort/index.js
Normal file
@@ -0,0 +1,107 @@
|
||||
import MapObject from "../MapObject";
|
||||
|
||||
import print from "../../../print";
|
||||
import CFG from "../../../../cfg";
|
||||
|
||||
import {
|
||||
validName
|
||||
} from "../../../utils";
|
||||
|
||||
/**
|
||||
* @class Fort
|
||||
*/
|
||||
export default class Fort extends MapObject {
|
||||
|
||||
/**
|
||||
* @param {Object} obj
|
||||
* @constructor
|
||||
*/
|
||||
constructor(obj) {
|
||||
|
||||
super(obj);
|
||||
|
||||
this.enabled = true;
|
||||
this.deleted = false;
|
||||
|
||||
this.name = null;
|
||||
this.description = null;
|
||||
|
||||
this.image_url = null;
|
||||
|
||||
this.cooldown = 5e3;
|
||||
|
||||
this.experience = 0;
|
||||
|
||||
this.rewards = this.parseRewards(obj.rewards);
|
||||
|
||||
this.init(obj);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {Object} obj
|
||||
*/
|
||||
init(obj) {
|
||||
obj = obj || {};
|
||||
for (let key in obj) {
|
||||
if (this.hasOwnProperty(key)) {
|
||||
this[key] = obj[key];
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* @return {Object}
|
||||
*/
|
||||
parseRewards(rewards) {
|
||||
rewards = rewards || "{}";
|
||||
let json = null;
|
||||
try {
|
||||
json = JSON.parse(rewards);
|
||||
} catch (e) {
|
||||
json = {};
|
||||
print(e, 31);
|
||||
}
|
||||
return (json);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return {Array}
|
||||
*/
|
||||
serializeRewards() {
|
||||
let out = [];
|
||||
for (let key in this.rewards) {
|
||||
let amount = this.rewards[key] << 0;
|
||||
for (let ii = 0; ii < amount; ++ii) {
|
||||
out.push({
|
||||
item_id: key
|
||||
});
|
||||
};
|
||||
};
|
||||
return (out);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return {String}
|
||||
*/
|
||||
getId() {
|
||||
return (
|
||||
this.cellId + "." + this.uid
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return {Object}
|
||||
*/
|
||||
serialize() {
|
||||
return ({
|
||||
id: this.getId(),
|
||||
last_modified_timestamp_ms: +new Date(),
|
||||
latitude: this.latitude,
|
||||
longitude: this.longitude,
|
||||
enabled: this.enabled,
|
||||
type: "CHECKPOINT"
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
42
src/models/World/MapObject/index.js
Normal file
42
src/models/World/MapObject/index.js
Normal file
@@ -0,0 +1,42 @@
|
||||
/**
|
||||
* @class MapObject
|
||||
*/
|
||||
export default class MapObject {
|
||||
|
||||
/**
|
||||
* @param {Object} obj
|
||||
* @constructor
|
||||
*/
|
||||
constructor(obj) {
|
||||
|
||||
this.uid = 0;
|
||||
|
||||
this.cellId = null;
|
||||
|
||||
this.altitude = 0;
|
||||
this.latitude = 0;
|
||||
this.longitude = 0;
|
||||
|
||||
this._init(obj);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {Object} obj
|
||||
*/
|
||||
_init(obj) {
|
||||
obj = obj || {};
|
||||
for (let key in obj) {
|
||||
if (this.hasOwnProperty(key)) {
|
||||
this[key] = obj[key];
|
||||
}
|
||||
else if (key === "cell_id") {
|
||||
this.cellId = obj[key];
|
||||
}
|
||||
else if (key === "cell_uid") {
|
||||
this.uid = obj[key];
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
}
|
||||
366
src/models/World/index.js
Normal file
366
src/models/World/index.js
Normal file
@@ -0,0 +1,366 @@
|
||||
import s2 from "s2-geometry";
|
||||
import Fort from "./Fort";
|
||||
import Player from "../Player";
|
||||
|
||||
import Settings from "../../modes";
|
||||
|
||||
import CFG from "../../../cfg";
|
||||
|
||||
import print from "../../print";
|
||||
|
||||
import * as _packets from "./packets";
|
||||
|
||||
import { inherit } from "../../utils";
|
||||
|
||||
const S2Geo = s2.S2;
|
||||
|
||||
const MAP_REFRESH_RATE = Settings.GAME_SETTINGS.map_settings.get_map_objects_max_refresh_seconds;
|
||||
|
||||
/**
|
||||
* @class World
|
||||
*/
|
||||
export default class World {
|
||||
|
||||
/** @constructor */
|
||||
constructor(instance) {
|
||||
|
||||
this.instance = instance;
|
||||
|
||||
this.db = this.instance.db;
|
||||
|
||||
this.players = [];
|
||||
|
||||
this.cells = {};
|
||||
|
||||
}
|
||||
|
||||
get connectedPlayers() {
|
||||
return (this.players.length);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return {Boolean}
|
||||
*/
|
||||
isFull() {
|
||||
return (
|
||||
this.connectedPlayers >= CFG.MAX_CONNECTIONS
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {Request} req
|
||||
* @param {Response} res
|
||||
*/
|
||||
getPlayerByRequest(req, res) {
|
||||
|
||||
let player = null;
|
||||
|
||||
if (this.playerAlreadyConnected(req)) {
|
||||
player = this.getPlayerByIP(req.headers.host);
|
||||
return (player);
|
||||
}
|
||||
else {
|
||||
player = this.addPlayer(req, res);
|
||||
return (player);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {Request} req
|
||||
* @return {Boolean}
|
||||
*/
|
||||
playerAlreadyConnected(req) {
|
||||
|
||||
let ii = 0;
|
||||
let length = this.connectedPlayers;
|
||||
|
||||
let remoteAddress = req.headers.host;
|
||||
|
||||
for (; ii < length; ++ii) {
|
||||
if (this.players[ii].remoteAddress === remoteAddress) {
|
||||
return (true);
|
||||
}
|
||||
};
|
||||
|
||||
return (false);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {String} ip
|
||||
*/
|
||||
getPlayerByIP(ip) {
|
||||
|
||||
let players = this.players;
|
||||
|
||||
let ii = 0;
|
||||
let length = this.connectedPlayers;
|
||||
|
||||
for (; ii < length; ++ii) {
|
||||
if (players[ii].remoteAddress === ip) {
|
||||
return (players[ii]);
|
||||
}
|
||||
};
|
||||
|
||||
return (null);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {Request} req
|
||||
* @param {Response} res
|
||||
* @return {Player}
|
||||
*/
|
||||
addPlayer(req, res) {
|
||||
|
||||
let player = new Player({
|
||||
world: this,
|
||||
request: req,
|
||||
response: res
|
||||
});
|
||||
|
||||
player.remoteAddress = req.headers.host;
|
||||
|
||||
this.players.push(player);
|
||||
|
||||
return (player);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {Player} player
|
||||
*/
|
||||
removePlayer(player) {
|
||||
console.log("Remove:", player.email);
|
||||
}
|
||||
|
||||
spawnFort() {
|
||||
|
||||
}
|
||||
|
||||
spawnGym() {
|
||||
|
||||
}
|
||||
|
||||
spawnEncounter() {
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {String} id
|
||||
* @return {Object}
|
||||
*/
|
||||
getCellById(id) {
|
||||
if (!this.cells[id]) {
|
||||
this.cells[id] = {
|
||||
id: id,
|
||||
forts: [],
|
||||
synced: false
|
||||
};
|
||||
}
|
||||
return (this.cells[id]);
|
||||
}
|
||||
|
||||
getFortsByCells(cells, out, index) {
|
||||
return new Promise((resolve) => {
|
||||
this.getFortsByCell(cells[index]).then((result) => {
|
||||
out.push(result);
|
||||
if (++index >= cells.length) {
|
||||
print(`Syncing forts with database!`, 33);
|
||||
resolve(out);
|
||||
}
|
||||
else resolve(this.getFortsByCells(cells, out, index));
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Dirty hack to display disappearing forts
|
||||
* @param {Fort} fort
|
||||
*/
|
||||
processDeletedFort(fort) {
|
||||
if (fort.deleted) {
|
||||
fort.latitude = 0;
|
||||
fort.longitude = 0;
|
||||
this.instance.db.query("DELETE FROM forts WHERE cell_id=? AND cell_uid=? LIMIT 1", [fort.cellId, fort.uid], (e, res) => {
|
||||
setTimeout(() => {
|
||||
this.deleteFortById(fort.cellId, fort.uid);
|
||||
}, MAP_REFRESH_RATE + 2e3);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {String} id
|
||||
* @param {Number} uid
|
||||
* @return {Number}
|
||||
*/
|
||||
getFortIndexById(id, uid) {
|
||||
let cell = this.getCellById(id);
|
||||
let index = 0;
|
||||
if (!cell) return (-1);
|
||||
for (let fort of cell.forts) {
|
||||
if (fort.uid === uid) return (index);
|
||||
++index;
|
||||
};
|
||||
return (-1);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {String} id
|
||||
* @param {Number} uid
|
||||
* @return {Fort}
|
||||
*/
|
||||
getFortById(id, uid) {
|
||||
let cell = this.getCellById(id);
|
||||
let index = this.getFortIndexById(id, uid);
|
||||
return new Promise((resolve) => {
|
||||
if (!cell.forts[index]) {
|
||||
this.getFortsByCell(id).then((forts) => {
|
||||
resolve(this.getFortById(id, uid));
|
||||
});
|
||||
}
|
||||
else {
|
||||
resolve(cell.forts[index]);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {String} id
|
||||
* @param {Number} uid
|
||||
* @return {Fort}
|
||||
*/
|
||||
deleteFortById(id, uid) {
|
||||
let cell = this.getCellById(id);
|
||||
let index = this.getFortIndexById(id, uid);
|
||||
if (index < 0) return (null);
|
||||
return (cell.forts.splice(index, 1));
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {Object} obj
|
||||
*/
|
||||
insertFort(obj) {
|
||||
|
||||
let lat = obj.latitude;
|
||||
let lng = obj.longitude;
|
||||
|
||||
let id = S2Geo.keyToId(S2Geo.latLngToKey(lat, lng, obj.zoom));
|
||||
|
||||
let name = obj.name || "";
|
||||
let desc = obj.description || "";
|
||||
|
||||
let img = "http://thecatapi.com/api/images/get?format=src&type=png&d=" + +new Date();
|
||||
|
||||
let query = "INSERT INTO forts SET cell_id=?, cell_uid=?, latitude=?, longitude=?, name=?, description=?, image_url=?, rewards=?";
|
||||
|
||||
obj.cell_id = id;
|
||||
|
||||
return new Promise((resolve) => {
|
||||
this.instance.db.query(query, [id, 0, lat, lng, name, desc, img, ""], (e, res) => {
|
||||
let insertId = res.insertId;
|
||||
this.instance.db.query("SELECT * from forts WHERE cell_id=? ORDER BY cell_uid DESC", [id], (e, res) => {
|
||||
let index = res instanceof Array ? res[0].cell_uid + 1 : 0;
|
||||
this.instance.db.query("UPDATE forts SET cell_uid=? WHERE id=?", [index, insertId], (e, res) => {
|
||||
obj.cell_uid = index;
|
||||
resolve(this.addFort(obj));
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {Object} obj
|
||||
* @return {Fort}
|
||||
*/
|
||||
addFort(obj) {
|
||||
let cell = this.getCellById(obj.cell_id);
|
||||
let fort = new Fort(obj);
|
||||
cell.forts.push(fort);
|
||||
return (fort);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {String} cell
|
||||
* @return {Array}
|
||||
*/
|
||||
getFortsByCell(cellId) {
|
||||
return new Promise((resolve) => {
|
||||
let cell = this.getCellById(cellId);
|
||||
// cached
|
||||
if (cell && cell.synced) {
|
||||
cell.forts.map((fort) => {
|
||||
this.processDeletedFort(fort);
|
||||
});
|
||||
resolve(cell);
|
||||
}
|
||||
// load from db
|
||||
else this.loadFortsFromDbByCell(cellId).then((forts) => {
|
||||
let result = this.getCellById(cellId);
|
||||
forts.map((fort) => {
|
||||
let index = result.forts.push(new Fort(fort)) - 1;
|
||||
this.processDeletedFort(result.forts[index]);
|
||||
});
|
||||
cell.synced = true;
|
||||
resolve(result);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {String} cell
|
||||
*/
|
||||
loadFortsFromDbByCell(cell) {
|
||||
return new Promise((resolve) => {
|
||||
this.instance.getQueryByColumnFromTable("cell_id", cell, "forts").then((forts) => {
|
||||
forts = forts || [];
|
||||
resolve(forts);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {String} type
|
||||
* @param {Object} msg
|
||||
*/
|
||||
getPacket(type, msg) {
|
||||
return new Promise((resolve) => {
|
||||
switch (type) {
|
||||
case "FORT_SEARCH":
|
||||
this.FortSearch(msg).then((result) => {
|
||||
resolve(result);
|
||||
});
|
||||
break;
|
||||
case "FORT_DETAILS":
|
||||
this.FortDetails(msg).then((result) => {
|
||||
resolve(result);
|
||||
});
|
||||
break;
|
||||
case "GET_MAP_OBJECTS":
|
||||
this.GetMapObjects(msg).then((result) => {
|
||||
resolve(result);
|
||||
});
|
||||
break;
|
||||
case "CHECK_CHALLENGE":
|
||||
resolve(this.CheckChallenge(msg));
|
||||
break;
|
||||
case "DOWNLOAD_SETTINGS":
|
||||
resolve(this.DownloadSettings(msg));
|
||||
break;
|
||||
case "DOWNLOAD_REMOTE_CONFIG_VERSION":
|
||||
resolve(this.DownloadRemoteConfigVersion(msg));
|
||||
break;
|
||||
case "DOWNLOAD_ITEM_TEMPLATES":
|
||||
resolve(this.DownloadItemTemplates(msg));
|
||||
break;
|
||||
};
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
inherit(World, _packets);
|
||||
16
src/models/World/packets/CheckChallenge.js
Normal file
16
src/models/World/packets/CheckChallenge.js
Normal file
@@ -0,0 +1,16 @@
|
||||
import POGOProtos from "pokemongo-protobuf";
|
||||
|
||||
/**
|
||||
* @param {Object} msg
|
||||
*/
|
||||
export default function CheckChallenge(msg) {
|
||||
|
||||
let buffer = {
|
||||
challenge_url: " "
|
||||
};
|
||||
|
||||
return (
|
||||
POGOProtos.serialize(buffer, "POGOProtos.Networking.Responses.CheckChallengeResponse")
|
||||
);
|
||||
|
||||
}
|
||||
13
src/models/World/packets/DownloadItemTemplates.js
Normal file
13
src/models/World/packets/DownloadItemTemplates.js
Normal file
@@ -0,0 +1,13 @@
|
||||
import POGOProtos from "pokemongo-protobuf";
|
||||
|
||||
import * as shared from "../../../shared";
|
||||
|
||||
/**
|
||||
* @param {Object} msg
|
||||
* @return {Buffer}
|
||||
*/
|
||||
export default function DownloadItemTemplates(msg) {
|
||||
return (
|
||||
shared.GAME_MASTER.serialize()
|
||||
);
|
||||
}
|
||||
19
src/models/World/packets/DownloadRemoteConfigVersion.js
Normal file
19
src/models/World/packets/DownloadRemoteConfigVersion.js
Normal file
@@ -0,0 +1,19 @@
|
||||
import POGOProtos from "pokemongo-protobuf";
|
||||
|
||||
/**
|
||||
* @param {Object} msg
|
||||
*/
|
||||
export default function DownloadRemoteConfigVersion(msg) {
|
||||
|
||||
let buffer = {
|
||||
"result": "SUCCESS",
|
||||
"item_templates_timestamp_ms": "1471650700946",
|
||||
"asset_digest_timestamp_ms": "1467338276561000",
|
||||
"$unknownFields": []
|
||||
}
|
||||
|
||||
return (
|
||||
POGOProtos.serialize(buffer, "POGOProtos.Networking.Responses.DownloadRemoteConfigVersionResponse")
|
||||
);
|
||||
|
||||
}
|
||||
20
src/models/World/packets/DownloadSettings.js
Normal file
20
src/models/World/packets/DownloadSettings.js
Normal file
@@ -0,0 +1,20 @@
|
||||
import POGOProtos from "pokemongo-protobuf";
|
||||
|
||||
import Settings from "../../../modes";
|
||||
|
||||
/**
|
||||
* @param {Object} msg
|
||||
* @return {Buffer}
|
||||
*/
|
||||
export default function DownloadSettings(msg) {
|
||||
|
||||
let buffer = {
|
||||
hash: "2788184af4004004d6ab0740f7632983332106f6",
|
||||
settings: Settings.GAME_SETTINGS
|
||||
};
|
||||
|
||||
return (
|
||||
POGOProtos.serialize(buffer, "POGOProtos.Networking.Responses.DownloadSettingsResponse")
|
||||
);
|
||||
|
||||
}
|
||||
35
src/models/World/packets/FortDetails.js
Normal file
35
src/models/World/packets/FortDetails.js
Normal file
@@ -0,0 +1,35 @@
|
||||
import POGOProtos from "pokemongo-protobuf";
|
||||
|
||||
import print from "../../../print";
|
||||
|
||||
/**
|
||||
* @param {Object} msg
|
||||
* @return {Buffer}
|
||||
*/
|
||||
export default function FortDetails(msg) {
|
||||
|
||||
let id = msg.fort_id.split(".");
|
||||
|
||||
return new Promise((resolve) => {
|
||||
this.instance.db.query("SELECT * from forts WHERE cell_id=? AND cell_uid=?", [id[0], id[1]], (e, forts) => {
|
||||
let fort = forts[0];
|
||||
if (!fort) return void 0;
|
||||
let buffer = {
|
||||
fort_id: msg.fort_id,
|
||||
name: fort.name,
|
||||
description: fort.description,
|
||||
image_urls: [
|
||||
fort.image_url
|
||||
],
|
||||
type: "CHECKPOINT",
|
||||
latitude: fort.latitude,
|
||||
longitude: fort.longitude,
|
||||
modifiers: []
|
||||
};
|
||||
resolve(
|
||||
POGOProtos.serialize(buffer, "POGOProtos.Networking.Responses.FortDetailsResponse")
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
}
|
||||
33
src/models/World/packets/FortSearch.js
Normal file
33
src/models/World/packets/FortSearch.js
Normal file
@@ -0,0 +1,33 @@
|
||||
import POGOProtos from "pokemongo-protobuf";
|
||||
|
||||
import print from "../../../print";
|
||||
|
||||
/**
|
||||
* @param {Object} msg
|
||||
* @return {Buffer}
|
||||
*/
|
||||
export default function FortSearch(msg) {
|
||||
|
||||
let id = msg.fort_id.split(".");
|
||||
|
||||
return new Promise((resolve) => {
|
||||
this.instance.db.query("SELECT * from forts WHERE cell_id=? AND cell_uid=?", [id[0], id[1]], (e, forts) => {
|
||||
let fort = forts[0];
|
||||
if (!fort) return void 0;
|
||||
let buffer = ({
|
||||
result: "SUCCESS",
|
||||
items_awarded: [
|
||||
{ item_id: 3 },
|
||||
{ item_id: 4 }
|
||||
],
|
||||
experience_awarded: 1337,
|
||||
cooldown_complete_timestamp_ms: +new Date() + 5e3,
|
||||
chain_hack_sequence_number: 2
|
||||
});
|
||||
resolve(
|
||||
POGOProtos.serialize(buffer, "POGOProtos.Networking.Responses.FortSearchResponse")
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
}
|
||||
51
src/models/World/packets/GetMapObjects.js
Normal file
51
src/models/World/packets/GetMapObjects.js
Normal file
@@ -0,0 +1,51 @@
|
||||
import POGOProtos from "pokemongo-protobuf";
|
||||
|
||||
import s2 from "s2-geometry";
|
||||
|
||||
import print from "../../../print";
|
||||
|
||||
const S2Geo = s2.S2;
|
||||
|
||||
/**
|
||||
* @param {Object} msg
|
||||
* @return {Buffer}
|
||||
*/
|
||||
export default function GetMapObjects(msg) {
|
||||
|
||||
let latitude = msg.latitude;
|
||||
let longitude = msg.longitude;
|
||||
|
||||
let mapCells = [];
|
||||
|
||||
let buffer = {
|
||||
status: "SUCCESS",
|
||||
map_cells: mapCells
|
||||
};
|
||||
|
||||
let limit = msg.cell_id.length;
|
||||
|
||||
// TODO: oop, forts are world objects!
|
||||
|
||||
return new Promise((resolve) => {
|
||||
this.getFortsByCells(msg.cell_id, [], 0).then((cells) => {
|
||||
cells.map((cell) => {
|
||||
mapCells.push({
|
||||
s2_cell_id: cell.id,
|
||||
current_timestamp_ms: +new Date(),
|
||||
forts: cell.forts.map((fort) => { return fort.serialize() }),
|
||||
spawn_points: [],
|
||||
deleted_objects: [],
|
||||
fort_summaries: [],
|
||||
decimated_spawn_points: [],
|
||||
wild_pokemons: [],
|
||||
catchable_pokemons: [],
|
||||
nearby_pokemons: []
|
||||
});
|
||||
});
|
||||
resolve(
|
||||
POGOProtos.serialize(buffer, "POGOProtos.Networking.Responses.GetMapObjectsResponse")
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
}
|
||||
7
src/models/World/packets/index.js
Normal file
7
src/models/World/packets/index.js
Normal file
@@ -0,0 +1,7 @@
|
||||
export FortSearch from "./FortSearch";
|
||||
export FortDetails from "./FortDetails";
|
||||
export GetMapObjects from "./GetMapObjects";
|
||||
export CheckChallenge from "./CheckChallenge";
|
||||
export DownloadSettings from "./DownloadSettings";
|
||||
export DownloadItemTemplates from "./DownloadItemTemplates";
|
||||
export DownloadRemoteConfigVersion from "./DownloadRemoteConfigVersion";
|
||||
@@ -1,14 +0,0 @@
|
||||
/**
|
||||
* @class GameServer
|
||||
*/
|
||||
class PacketModel {
|
||||
|
||||
/**
|
||||
* @param {Player} player
|
||||
* @constructor
|
||||
*/
|
||||
constructor(player) {
|
||||
this.player = player;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,9 +0,0 @@
|
||||
{
|
||||
"exp": 0,
|
||||
"level": 5,
|
||||
"stardust": 1000,
|
||||
"pokecoins": 0,
|
||||
"team": 0,
|
||||
"items": [],
|
||||
"pokemons": []
|
||||
}
|
||||
@@ -1,28 +0,0 @@
|
||||
{
|
||||
"fort_settings": {
|
||||
"interaction_range_meters": 40,
|
||||
"max_total_deployed_pokemon": 10,
|
||||
"max_player_deployed_pokemon": 1,
|
||||
"deploy_stamina_multiplier": 8,
|
||||
"deploy_attack_multiplier": 0,
|
||||
"far_interaction_range_meters": 1000
|
||||
},
|
||||
"map_settings": {
|
||||
"pokemon_visible_range": 70,
|
||||
"poke_nav_range_meters": 751,
|
||||
"encounter_range_meters": 50,
|
||||
"get_map_objects_min_refresh_seconds": 10,
|
||||
"get_map_objects_max_refresh_seconds": 30,
|
||||
"get_map_objects_min_distance_meters": 10
|
||||
},
|
||||
"inventory_settings": {
|
||||
"max_pokemon": 1000,
|
||||
"max_bag_items": 1000,
|
||||
"base_pokemon": 250,
|
||||
"base_bag_items": 350,
|
||||
"base_eggs": 9
|
||||
},
|
||||
"pokemon_settings": {
|
||||
|
||||
}
|
||||
}
|
||||
31
src/modes/index.js
Normal file
31
src/modes/index.js
Normal file
@@ -0,0 +1,31 @@
|
||||
import CFG from "../../cfg";
|
||||
|
||||
export default {
|
||||
GAME_SETTINGS: {
|
||||
fort_settings: {
|
||||
interaction_range_meters: 40.25098039215686,
|
||||
max_total_deployed_pokemon: 10,
|
||||
max_player_deployed_pokemon: 1,
|
||||
deploy_stamina_multiplier: 8.062745098039215,
|
||||
deploy_attack_multiplier: 0,
|
||||
far_interaction_range_meters: 1000.0156862745098
|
||||
},
|
||||
map_settings: {
|
||||
pokemon_visible_range: 70.00196078431372,
|
||||
poke_nav_range_meters: 751.0156862745098,
|
||||
encounter_range_meters: 50.25098039215686,
|
||||
get_map_objects_min_refresh_seconds: 0,
|
||||
get_map_objects_max_refresh_seconds: 0,
|
||||
get_map_objects_min_distance_meters: 10.007843017578125,
|
||||
google_maps_api_key: CFG.GMAPS_KEY
|
||||
},
|
||||
inventory_settings: {
|
||||
max_pokemon: 1000,
|
||||
max_bag_items: 1000,
|
||||
base_pokemon: 250,
|
||||
base_bag_items: 350,
|
||||
base_eggs: 9
|
||||
},
|
||||
minimum_client_version: CFG.MINIMUM_CLIENT_VERSION
|
||||
}
|
||||
}
|
||||
@@ -1,18 +0,0 @@
|
||||
import proto from "../proto";
|
||||
|
||||
/**
|
||||
* @param {Object}
|
||||
* @return {Object}
|
||||
*/
|
||||
export default function DownloadUrlEntry(obj) {
|
||||
|
||||
return (
|
||||
new proto.Data.DownloadUrlEntry({
|
||||
url: obj.url,
|
||||
asset_id: obj.id,
|
||||
size: obj.size,
|
||||
checksum: obj.checksum
|
||||
})
|
||||
);
|
||||
|
||||
}
|
||||
@@ -1,19 +0,0 @@
|
||||
import proto from "../proto";
|
||||
import POGOProtos from "pokemongo-protobuf";
|
||||
|
||||
import CFG from "../../cfg";
|
||||
|
||||
/**
|
||||
* @return {Object}
|
||||
*/
|
||||
export default function AuthTicket() {
|
||||
|
||||
let buffer = ({
|
||||
start: new Buffer(""),
|
||||
"expire_timestamp_ms": new Date().getTime() + CFG.PLAYER_CONNECTION_TIMEOUT,
|
||||
end: new Buffer("")
|
||||
});
|
||||
|
||||
return (POGOProtos.serialize(buffer, "POGOProtos.Networking.Envelopes.AuthTicket"));
|
||||
|
||||
}
|
||||
@@ -1,22 +0,0 @@
|
||||
import proto from "../proto";
|
||||
|
||||
/**
|
||||
* @param {Object} obj
|
||||
* @return {Object}
|
||||
*/
|
||||
export default function ResponseEnvelope(obj) {
|
||||
|
||||
return (
|
||||
new proto.Networking.Envelopes.ResponseEnvelope({
|
||||
status_code: 53,
|
||||
request_id: obj.id,
|
||||
api_url: "pgorelease.nianticlabs.com/custom",
|
||||
auth_ticket: new proto.Networking.Envelopes.AuthTicket({
|
||||
start: new Buffer(""),
|
||||
expire_timestamp_ms: 9999999999999,
|
||||
end: new Buffer("")
|
||||
})
|
||||
}).encode().toBuffer()
|
||||
);
|
||||
|
||||
}
|
||||
@@ -1,23 +0,0 @@
|
||||
import proto from "../proto";
|
||||
|
||||
/**
|
||||
* @param {Object} obj
|
||||
* @return {Object}
|
||||
*/
|
||||
export default function ResponseEnvelope(obj) {
|
||||
|
||||
return (
|
||||
new proto.Networking.Envelopes.ResponseEnvelope({
|
||||
status_code: obj.status,
|
||||
unknown6: new proto.Networking.Envelopes.Unknown6Response({
|
||||
response_type: 6,
|
||||
unknown2: new proto.Networking.Envelopes.Unknown6Response.Unknown2({
|
||||
unknown1: 1
|
||||
})
|
||||
}),
|
||||
request_id: obj.id,
|
||||
returns: obj.response
|
||||
}).encode().toBuffer()
|
||||
);
|
||||
|
||||
}
|
||||
@@ -1,52 +0,0 @@
|
||||
import CFG from "../../cfg";
|
||||
|
||||
import POGOProtos from "pokemongo-protobuf";
|
||||
|
||||
/**
|
||||
* @param {Request} req
|
||||
* @return {Object}
|
||||
*/
|
||||
export default function CatchPokemon(encounter, player, req) {
|
||||
|
||||
let obj = {
|
||||
"owner_id": -1,
|
||||
"encounter_id": encounter.encounter_id,
|
||||
"spawn_point_id": "87bdcd88cb5",
|
||||
"captured_cell_id": "9781199952939057152",
|
||||
pokemon_id: encounter.pokemon_id,
|
||||
cp: encounter.cp,
|
||||
"move_1": "BUG_BITE_FAST",
|
||||
"move_2": "STRUGGLE",
|
||||
"stamina": 10,
|
||||
"stamina_max": 10,
|
||||
height_m: 0.30962005257606506,
|
||||
weight_kg: 3.3212273120880127,
|
||||
"pokeball": "ITEM_POKE_BALL",
|
||||
"creation_time_ms": new Date().getTime(),
|
||||
"cp_multiplier": 0.16639786958694458,
|
||||
individual_attack: 7,
|
||||
individual_defense: 13,
|
||||
individual_stamina: 3
|
||||
};
|
||||
|
||||
if (!req.hit_pokemon) {
|
||||
return ({
|
||||
status: 'CATCH_MISSED'
|
||||
});
|
||||
} else {
|
||||
return ({
|
||||
pkmn: obj,
|
||||
buffer: {
|
||||
status: 'CATCH_SUCCESS',
|
||||
captured_pokemon_id: encounter.encounter_id,
|
||||
capture_award: {
|
||||
activity_type: ['ACTIVITY_CATCH_POKEMON'],
|
||||
xp: [100],
|
||||
candy: [3],
|
||||
stardust: [100]
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,21 +0,0 @@
|
||||
import CFG from "../../cfg";
|
||||
|
||||
import proto from "../proto";
|
||||
import POGOProtos from "pokemongo-protobuf";
|
||||
|
||||
/**
|
||||
* @param {Object} obj
|
||||
* @return {Object}
|
||||
*/
|
||||
export default function CheckAwardedBadges(obj) {
|
||||
|
||||
let buffer = {
|
||||
"success": true,
|
||||
"awarded_badges": [],
|
||||
"awarded_badge_levels": [],
|
||||
"$unknownFields": []
|
||||
}
|
||||
|
||||
return POGOProtos.serialize(buffer, "POGOProtos.Networking.Responses.CheckAwardedBadgesResponse");
|
||||
|
||||
}
|
||||
@@ -1,17 +0,0 @@
|
||||
import CFG from "../../cfg";
|
||||
|
||||
import POGOProtos from "pokemongo-protobuf";
|
||||
|
||||
/**
|
||||
* @param {Request} req
|
||||
* @return {Object}
|
||||
*/
|
||||
export default function CheckChallenge(req) {
|
||||
|
||||
let buffer = ({
|
||||
challenge_url: " "
|
||||
});
|
||||
|
||||
return POGOProtos.serialize(buffer, "POGOProtos.Networking.Responses.CheckChallengeResponse");
|
||||
|
||||
}
|
||||
@@ -1,25 +0,0 @@
|
||||
import proto from "../proto";
|
||||
|
||||
import { GetPlayer } from "./";
|
||||
|
||||
/**
|
||||
* @param {Request} req
|
||||
* @param {Player} player
|
||||
* @return {Object}
|
||||
*/
|
||||
export default function ClaimCodeName(req, player) {
|
||||
|
||||
let data = proto.Networking.Requests.Messages.ClaimCodenameMessage.decode(req.request_message.toBuffer());
|
||||
|
||||
player.username = data.codename;
|
||||
|
||||
return (
|
||||
new proto.Networking.Responses.ClaimCodenameResponse({
|
||||
codename: data.codename,
|
||||
user_message: data.codename,
|
||||
is_assignable: true,
|
||||
status: 1
|
||||
}).encode()
|
||||
);
|
||||
|
||||
}
|
||||
@@ -1,19 +0,0 @@
|
||||
import proto from "../proto";
|
||||
import POGOProtos from "pokemongo-protobuf";
|
||||
|
||||
/**
|
||||
* @param {Object} obj
|
||||
* @return {Object}
|
||||
*/
|
||||
export default function DownloadRemoteConfigVersion(obj) {
|
||||
|
||||
let buffer = {
|
||||
"result": "SUCCESS",
|
||||
"item_templates_timestamp_ms": "1471650700946",
|
||||
"asset_digest_timestamp_ms": "1467338276561000",
|
||||
"$unknownFields": []
|
||||
}
|
||||
|
||||
return POGOProtos.serialize(buffer, "POGOProtos.Networking.Responses.DownloadRemoteConfigVersionResponse");
|
||||
|
||||
}
|
||||
@@ -1,44 +0,0 @@
|
||||
import proto from "../proto";
|
||||
import POGOProtos from "pokemongo-protobuf";
|
||||
|
||||
import CFG from "../../cfg";
|
||||
|
||||
/**
|
||||
* @return {Buffer}
|
||||
*/
|
||||
export default function DownloadSettings() {
|
||||
|
||||
let buffer = ({
|
||||
hash: "2788184af4004004d6ab0740f7632983332106f6",
|
||||
settings: {
|
||||
fort_settings: {
|
||||
"interaction_range_meters": 40.25098039215686,
|
||||
"max_total_deployed_pokemon": 10,
|
||||
"max_player_deployed_pokemon": 1,
|
||||
"deploy_stamina_multiplier": 8.062745098039215,
|
||||
"deploy_attack_multiplier": 0,
|
||||
"far_interaction_range_meters": 1000.0156862745098
|
||||
},
|
||||
map_settings: {
|
||||
"pokemon_visible_range": 70.00196078431372,
|
||||
"poke_nav_range_meters": 751.0156862745098,
|
||||
"encounter_range_meters": 50.25098039215686,
|
||||
"get_map_objects_min_refresh_seconds": 10.007843017578125,
|
||||
"get_map_objects_max_refresh_seconds": 11.01568603515625,
|
||||
"get_map_objects_min_distance_meters": 10.007843017578125,
|
||||
"google_maps_api_key": CFG.GMAPS_KEY
|
||||
},
|
||||
inventory_settings: {
|
||||
"max_pokemon": 1000,
|
||||
"max_bag_items": 1000,
|
||||
"base_pokemon": 250,
|
||||
"base_bag_items": 350,
|
||||
"base_eggs": 9
|
||||
},
|
||||
minimum_client_version: CFG.MINIMUM_CLIENT_VERSION
|
||||
}
|
||||
})
|
||||
|
||||
return POGOProtos.serialize(buffer, "POGOProtos.Networking.Responses.DownloadSettingsResponse");
|
||||
|
||||
}
|
||||
@@ -1,46 +0,0 @@
|
||||
import CFG from "../../cfg";
|
||||
|
||||
import proto from "../proto";
|
||||
import POGOProtos from "pokemongo-protobuf";
|
||||
|
||||
import { decodeLong } from "../utils";
|
||||
|
||||
/**
|
||||
* @param {Request} req
|
||||
* @return {Object}
|
||||
*/
|
||||
export default function Encounter(encounter, req) {
|
||||
|
||||
let buffer = ({
|
||||
wild_pokemon: {
|
||||
encounter_id: encounter.encounter_id,
|
||||
last_modified_timestamp_ms: '1471852141657',
|
||||
latitude: encounter.latitude,
|
||||
longitude: encounter.longitude,
|
||||
spawn_point_id: '87bdcd8f2e9',
|
||||
pokemon_data: {
|
||||
pokemon_id: encounter.pokemon_id,
|
||||
cp: encounter.cp,
|
||||
stamina: 10,
|
||||
stamina_max: 10,
|
||||
move_1: "BUG_BITE_FAST",
|
||||
move_2: "STRUGGLE",
|
||||
height_m: 0.30962005257606506,
|
||||
weight_kg: 3.3212273120880127,
|
||||
individual_attack: 7,
|
||||
individual_defense: 13,
|
||||
individual_stamina: 3,
|
||||
cp_multiplier: 0.16639786958694458
|
||||
},
|
||||
time_till_hidden_ms: 860075
|
||||
},
|
||||
status: 'ENCOUNTER_SUCCESS',
|
||||
capture_probability: {
|
||||
pokeball_type: ['ITEM_POKE_BALL', 'ITEM_GREAT_BALL', 'ITEM_ULTRA_BALL'],
|
||||
capture_probability: [1, 1, 1]
|
||||
}
|
||||
});
|
||||
|
||||
return POGOProtos.serialize(buffer, "POGOProtos.Networking.Responses.EncounterResponse");
|
||||
|
||||
}
|
||||
@@ -1,22 +0,0 @@
|
||||
import CFG from "../../cfg";
|
||||
|
||||
import proto from "../proto";
|
||||
|
||||
/**
|
||||
* @param {Request} req
|
||||
* @return {Object}
|
||||
*/
|
||||
export default function EvolvePokemon(req) {
|
||||
|
||||
let data = proto.Networking.Requests.Messages.EvolvePokemonMessage.decode(req.request_message.toBuffer());
|
||||
|
||||
return (
|
||||
new proto.Networking.Responses.EvolvePokemonResponse({
|
||||
result: proto.Networking.Responses.EvolvePokemonResponse.Result.FAILED_POKEMON_CANNOT_EVOLVE,
|
||||
evolved_pokemon_data: null,
|
||||
experience_awarded: 0,
|
||||
candy_awarded: 0
|
||||
}).encode()
|
||||
);
|
||||
|
||||
}
|
||||
@@ -1,27 +0,0 @@
|
||||
import CFG from "../../cfg";
|
||||
|
||||
import proto from "../proto";
|
||||
import POGOProtos from "pokemongo-protobuf";
|
||||
|
||||
/**
|
||||
* @param {Request} req
|
||||
* @return {Object}
|
||||
*/
|
||||
export default function FortDetails(req) {
|
||||
|
||||
let buffer = ({
|
||||
"fort_id": req.fort_id,
|
||||
"name": `POGOserver v${CFG.VERSION}`,
|
||||
"image_urls": [
|
||||
"http://thecatapi.com/api/images/get?format=src&type=png"
|
||||
],
|
||||
"type": "CHECKPOINT",
|
||||
"latitude": req.latitude,
|
||||
"longitude": req.longitude,
|
||||
"modifiers": [],
|
||||
"$unknownFields": []
|
||||
});
|
||||
|
||||
return (POGOProtos.serialize(buffer, "POGOProtos.Networking.Responses.FortDetailsResponse"));
|
||||
|
||||
}
|
||||
@@ -1,42 +0,0 @@
|
||||
import CFG from "../../cfg";
|
||||
|
||||
import proto from "../proto";
|
||||
import POGOProtos from "pokemongo-protobuf";
|
||||
|
||||
/**
|
||||
* @param {Player} player
|
||||
* @return {Buffer}
|
||||
*/
|
||||
export default function FortSearch(player) {
|
||||
|
||||
let ii = 0;
|
||||
let items = [];
|
||||
|
||||
let name = "ultra_ball";
|
||||
let amount = 5;
|
||||
let exp = 50;
|
||||
|
||||
while (++ii < amount) {
|
||||
items.push({
|
||||
"item_id": "ITEM_" + name.toUpperCase(),
|
||||
"item_count": 1
|
||||
});
|
||||
};
|
||||
|
||||
player.items[name] += amount;
|
||||
player.exp += exp;
|
||||
|
||||
console.log(player.items[name]);
|
||||
|
||||
let buffer = ({
|
||||
"result": "SUCCESS",
|
||||
"items_awarded": items,
|
||||
"experience_awarded": exp,
|
||||
"cooldown_complete_timestamp_ms": "1471780158665",
|
||||
"chain_hack_sequence_number": 2,
|
||||
"$unknownFields": []
|
||||
});
|
||||
|
||||
return (POGOProtos.serialize(buffer, "POGOProtos.Networking.Responses.FortSearchResponse"));
|
||||
|
||||
}
|
||||
@@ -1,12 +0,0 @@
|
||||
import fs from "fs";
|
||||
import proto from "../proto";
|
||||
|
||||
import CFG from "../../cfg";
|
||||
|
||||
/**
|
||||
* @param {Player} player
|
||||
* @return {Object}
|
||||
*/
|
||||
export default function GetAssetDigest(player) {
|
||||
return (player.asset_digest.buffer);
|
||||
}
|
||||
@@ -1,42 +0,0 @@
|
||||
import proto from "../proto";
|
||||
import POGOProtos from "pokemongo-protobuf";
|
||||
|
||||
import CFG from "../../cfg";
|
||||
|
||||
import {
|
||||
getDownloadUrlByAssetId
|
||||
} from "../utils.js";
|
||||
|
||||
/**
|
||||
* @return {Object}
|
||||
*/
|
||||
export default function GetDownloadUrls(asset, ip, req) {
|
||||
|
||||
let key = req.asset_id[0];
|
||||
|
||||
let download_urls = [];
|
||||
|
||||
let node = null;
|
||||
|
||||
for (node of asset.digest) {
|
||||
if (node.asset_id === key) {
|
||||
break;
|
||||
}
|
||||
};
|
||||
|
||||
return new Promise((resolve) => {
|
||||
download_urls.push(
|
||||
{
|
||||
asset_id: key,
|
||||
url: `http://${ip}:${CFG.PORT}/model/${node.bundle_name}`,
|
||||
size: node.size,
|
||||
checksum: node.checksum
|
||||
}
|
||||
);
|
||||
let buffer = ({
|
||||
download_urls: download_urls
|
||||
});
|
||||
resolve(POGOProtos.serialize(buffer, "POGOProtos.Networking.Responses.GetDownloadUrlsResponse"));
|
||||
});
|
||||
|
||||
}
|
||||
@@ -1,21 +0,0 @@
|
||||
import proto from "../proto";
|
||||
import POGOProtos from "pokemongo-protobuf";
|
||||
|
||||
/**
|
||||
* @param {Object} obj
|
||||
* @return {Object}
|
||||
*/
|
||||
export default function GetHatchedEggs(obj) {
|
||||
|
||||
let buffer = {
|
||||
"success": true,
|
||||
"pokemon_id": [],
|
||||
"experience_awarded": [],
|
||||
"candy_awarded": [],
|
||||
"stardust_awarded": [],
|
||||
"$unknownFields": []
|
||||
};
|
||||
|
||||
return POGOProtos.serialize(buffer, "POGOProtos.Networking.Responses.GetHatchedEggsResponse");
|
||||
|
||||
}
|
||||
@@ -1,112 +0,0 @@
|
||||
import proto from "../proto";
|
||||
import POGOProtos from "pokemongo-protobuf";
|
||||
|
||||
let isFirst = false;
|
||||
|
||||
/**
|
||||
* @param {Object} data
|
||||
* @return {Object}
|
||||
*/
|
||||
export default function GetInventoryData(player) {
|
||||
|
||||
let entries = [];
|
||||
|
||||
entries.push({
|
||||
"modified_timestamp_ms": new Date().getTime() - 1e3,
|
||||
"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,
|
||||
"pokemon_caught_by_type": {
|
||||
"type": "Buffer",
|
||||
"data": [
|
||||
0,
|
||||
24,
|
||||
0,
|
||||
26,
|
||||
20,
|
||||
1,
|
||||
0,
|
||||
14,
|
||||
0,
|
||||
0,
|
||||
1,
|
||||
14,
|
||||
3,
|
||||
0,
|
||||
1,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
3
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
for (let key in player.items) {
|
||||
let amount = parseInt(player.items[key]);
|
||||
if (amount > 0) {
|
||||
entries.push({
|
||||
"modified_timestamp_ms": new Date().getTime() - 1e3,
|
||||
"inventory_item_data": {
|
||||
"item": {
|
||||
"item_id": "ITEM_" + key.toUpperCase(),
|
||||
"count": amount
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
let party = player.party;
|
||||
|
||||
for (let pkmn of party) {
|
||||
entries.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,
|
||||
"favorite": pkmn.favorite
|
||||
}
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
let buffer = ({
|
||||
"success": true,
|
||||
"inventory_delta": {
|
||||
"new_timestamp_ms": new Date().getTime() - 1e3,
|
||||
"inventory_items": entries
|
||||
}
|
||||
});
|
||||
|
||||
return (POGOProtos.serialize(buffer, "POGOProtos.Networking.Responses.GetInventoryResponse"));
|
||||
|
||||
}
|
||||
@@ -1,195 +0,0 @@
|
||||
import proto from "../proto";
|
||||
import POGOProtos from "pokemongo-protobuf";
|
||||
|
||||
/**
|
||||
* @param {Player} player
|
||||
* @param {Request} request
|
||||
* @return {Object}
|
||||
*/
|
||||
export default function GetMapObjects(player, wild_pkmns, request) {
|
||||
|
||||
let cells = request.cell_id;
|
||||
let cellsRes = [];
|
||||
|
||||
let pokemon_id = 121;
|
||||
|
||||
cells.forEach((cell) => {
|
||||
cellsRes.push({
|
||||
s2_cell_id: cell,
|
||||
current_timestamp_ms: new Date().getTime() * 1e3,
|
||||
forts: [],
|
||||
spawn_points: [],
|
||||
deleted_objects: [],
|
||||
is_truncated_list: false,
|
||||
fort_summaries: [],
|
||||
decimated_spawn_points: [],
|
||||
wild_pokemons: [],
|
||||
catchable_pokemons: [],
|
||||
nearby_pokemons: []
|
||||
});
|
||||
});
|
||||
|
||||
let latitude = player.latitude;
|
||||
let longitude = player.longitude;
|
||||
|
||||
let cell = cellsRes[0];
|
||||
|
||||
cell.forts = [
|
||||
{
|
||||
"id": "108dc9c703a94b619a53a3c29b5c676f.11",
|
||||
"last_modified_timestamp_ms": "1471621873766",
|
||||
"latitude": latitude + 0.0002,
|
||||
"longitude": longitude - 0.0001,
|
||||
"enabled": true,
|
||||
"type": "CHECKPOINT"
|
||||
},
|
||||
{
|
||||
"id": "1391315b489f421abd52ce10b6da7dd3.16",
|
||||
"last_modified_timestamp_ms": "1471776325164",
|
||||
"latitude": 39.188351,
|
||||
"longitude": -96.582561,
|
||||
"enabled": true,
|
||||
"type": "CHECKPOINT"
|
||||
},
|
||||
{
|
||||
"id": "33ad17c71fff4797b7f25dcfcdca48df.16",
|
||||
"last_modified_timestamp_ms": "1470755536809",
|
||||
"latitude": 39.189386,
|
||||
"longitude": -96.581113,
|
||||
"enabled": true,
|
||||
"type": "CHECKPOINT"
|
||||
},
|
||||
{
|
||||
"id": "40f86138ca6f49cc9e98e18b77d6067a.16",
|
||||
"last_modified_timestamp_ms": "1471748353301",
|
||||
"latitude": 39.188351,
|
||||
"longitude": -96.582209,
|
||||
"enabled": true,
|
||||
"type": "CHECKPOINT"
|
||||
},
|
||||
{
|
||||
"id": "560ef7ed6cb5469db29b543cce7677ae.16",
|
||||
"last_modified_timestamp_ms": "1469923654520",
|
||||
"latitude": 39.186848,
|
||||
"longitude": -96.581267,
|
||||
"enabled": true,
|
||||
"type": "CHECKPOINT"
|
||||
},
|
||||
{
|
||||
"id": "60d2ffcfe9cf4003b4d94bcc9ee0c318.16",
|
||||
"last_modified_timestamp_ms": "1471811998365",
|
||||
"latitude": 39.188008,
|
||||
"longitude": -96.582409,
|
||||
"enabled": true,
|
||||
"type": "CHECKPOINT"
|
||||
},
|
||||
{
|
||||
"id": "637941f1f2494276884ede4fc538c2b2.16",
|
||||
"last_modified_timestamp_ms": "1471816829142",
|
||||
"latitude": 39.186868,
|
||||
"longitude": -96.583295,
|
||||
"enabled": true,
|
||||
"type": "CHECKPOINT"
|
||||
},
|
||||
{
|
||||
"id": "7c0154d02e4f4d91b9b74214eda75abc.16",
|
||||
"last_modified_timestamp_ms": "1471483788730",
|
||||
"latitude": 39.187991,
|
||||
"longitude": -96.581251,
|
||||
"enabled": true,
|
||||
"type": "CHECKPOINT"
|
||||
},
|
||||
{
|
||||
"id": "8a94bf6cd17b43be8b5b42655d23e2f6.16",
|
||||
"last_modified_timestamp_ms": "1471751252546",
|
||||
"latitude": 39.187684,
|
||||
"longitude": -96.583537,
|
||||
"enabled": true,
|
||||
"type": "CHECKPOINT"
|
||||
},
|
||||
{
|
||||
"id": "9b469dbd550f43b5a8e94f941d66bc43.16",
|
||||
"last_modified_timestamp_ms": "1471243641146",
|
||||
"latitude": 39.189051,
|
||||
"longitude": -96.581804,
|
||||
"enabled": true,
|
||||
"type": "CHECKPOINT"
|
||||
},
|
||||
{
|
||||
"id": "bb0e515e3f554b398f1fa9c58435dc78.16",
|
||||
"last_modified_timestamp_ms": "1471748285036",
|
||||
"latitude": 39.188823,
|
||||
"longitude": -96.582742,
|
||||
"enabled": true,
|
||||
"type": "CHECKPOINT"
|
||||
}
|
||||
];
|
||||
|
||||
cell.spawn_points = [
|
||||
{
|
||||
"latitude": 39.188870250798956,
|
||||
"longitude": -96.58196728549451
|
||||
},
|
||||
{
|
||||
"latitude": 39.1889464335866,
|
||||
"longitude": -96.58205070456887
|
||||
},
|
||||
{
|
||||
"latitude": 39.18887496474473,
|
||||
"longitude": -96.58188386652927
|
||||
},
|
||||
{
|
||||
"latitude": 39.18879406783625,
|
||||
"longitude": -96.58188386652927
|
||||
},
|
||||
{
|
||||
"latitude": 39.189284161630674,
|
||||
"longitude": -96.58180044767312
|
||||
}
|
||||
];
|
||||
|
||||
for (let pkmn of wild_pkmns) {
|
||||
cell.wild_pokemons.push({
|
||||
encounter_id: pkmn.encounter_id,
|
||||
last_modified_timestamp_ms: new Date().getTime(),
|
||||
latitude: pkmn.latitude,
|
||||
longitude: pkmn.longitude,
|
||||
spawn_point_id: "87bdd289c69",
|
||||
pokemon_data: {
|
||||
pokemon_id: pkmn.pokemon_id,
|
||||
cp: pkmn.cp,
|
||||
stamina: 41,
|
||||
stamina_max: 41,
|
||||
move_1: 221,
|
||||
move_2: 26,
|
||||
height_m: 0.22802678267819977,
|
||||
weight_kg: 1.3452539511871338,
|
||||
individual_attack: 9,
|
||||
individual_defense: 13,
|
||||
individual_stamina: 14,
|
||||
cp_multiplier: 0.5663545199394226
|
||||
},
|
||||
time_till_hidden_ms: 730176
|
||||
});
|
||||
cell.catchable_pokemons.push({
|
||||
spawn_point_id: "87bdd289c69",
|
||||
encounter_id: pkmn.encounter_id,
|
||||
pokemon_id: pkmn.pokemon_id,
|
||||
latitude: latitude,
|
||||
longitude: longitude,
|
||||
expiration_timestamp_ms: (new Date().getTime() + 1e6) * 1e3
|
||||
});
|
||||
cell.nearby_pokemons.push({
|
||||
distance_in_meters: 200.0,
|
||||
pokemon_id: pkmn.pokemon_id
|
||||
});
|
||||
};
|
||||
|
||||
let buffer = ({
|
||||
status: "SUCCESS",
|
||||
map_cells: cellsRes
|
||||
});
|
||||
|
||||
return (POGOProtos.serialize(buffer, "POGOProtos.Networking.Responses.GetMapObjectsResponse"));
|
||||
|
||||
}
|
||||
@@ -1,101 +0,0 @@
|
||||
import proto from "../proto";
|
||||
import POGOProtos from "pokemongo-protobuf";
|
||||
|
||||
/**
|
||||
* @param {Object} obj
|
||||
* @return {Object}
|
||||
*/
|
||||
function getPlayerDataPacket(obj) {
|
||||
|
||||
return (
|
||||
{
|
||||
creation_timestamp_ms: 1467936859925,
|
||||
username: obj.username,
|
||||
team: proto.Enums.TeamColor.YELLOW,
|
||||
tutorial_state: obj.tutorial_state,
|
||||
avatar: obj.avatar,
|
||||
max_pokemon_storage: 250,
|
||||
max_item_storage: 350,
|
||||
daily_bonus: {
|
||||
next_defender_bonus_collect_timestamp_ms: 1470174535972
|
||||
},
|
||||
contact_settings: obj.contact_settings,
|
||||
currencies: obj.currencies
|
||||
}
|
||||
);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {Object} obj
|
||||
* @return {Object}
|
||||
*/
|
||||
function buildPlayerData(obj) {
|
||||
|
||||
let team = obj.team;
|
||||
let username = obj.username;
|
||||
|
||||
let pokecoins = obj.pokecoins;
|
||||
let stardust = obj.stardust;
|
||||
|
||||
let avatar = {
|
||||
skin: obj.skin,
|
||||
hair: obj.hair,
|
||||
shirt: obj.shirt,
|
||||
pants: obj.pants,
|
||||
hat: obj.hat,
|
||||
shoes: obj.shoes,
|
||||
eyes: obj.eyes,
|
||||
gender: obj.gender,
|
||||
backpack: obj.backpack
|
||||
};
|
||||
|
||||
let contact_settings = {
|
||||
send_marketing_emails: obj.send_marketing_emails,
|
||||
send_push_notifications: obj.send_push_notifications
|
||||
};
|
||||
|
||||
let tutorial_state = [
|
||||
proto.Enums.TutorialState.LEGAL_SCREEN,
|
||||
proto.Enums.TutorialState.AVATAR_SELECTION,
|
||||
proto.Enums.TutorialState.POKEMON_CAPTURE,
|
||||
proto.Enums.TutorialState.NAME_SELECTION,
|
||||
proto.Enums.TutorialState.FIRST_TIME_EXPERIENCE_COMPLETE
|
||||
];
|
||||
|
||||
let currencies = [
|
||||
{
|
||||
name: "POKECOIN",
|
||||
amount: pokecoins
|
||||
},
|
||||
{
|
||||
name: "STARDUST",
|
||||
amount: stardust
|
||||
}
|
||||
];
|
||||
|
||||
return ({
|
||||
username: username,
|
||||
team: team,
|
||||
tutorial_state: tutorial_state,
|
||||
contact_settings: contact_settings,
|
||||
avatar: avatar,
|
||||
currencies: currencies
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
export default function GetPlayer(obj) {
|
||||
|
||||
let data = buildPlayerData(obj);
|
||||
|
||||
let packet = getPlayerDataPacket(data);
|
||||
|
||||
let buffer = {
|
||||
success: true,
|
||||
player_data: packet
|
||||
};
|
||||
|
||||
return (POGOProtos.serialize(buffer, "POGOProtos.Networking.Responses.GetPlayerResponse"));
|
||||
|
||||
}
|
||||
@@ -1,168 +0,0 @@
|
||||
import proto from "../proto";
|
||||
import POGOProtos from "pokemongo-protobuf";
|
||||
|
||||
/**
|
||||
* @param {Object} obj
|
||||
* @return {Object}
|
||||
*/
|
||||
export default function GetPlayerProfile(obj) {
|
||||
|
||||
let buffer = ({
|
||||
"result": "SUCCESS",
|
||||
"start_time": "1471096437979",
|
||||
"badges": [
|
||||
{
|
||||
"badge_type": "BADGE_TRAVEL_KM",
|
||||
"end_value": 10,
|
||||
"current_value": 3.921541213989258
|
||||
},
|
||||
{
|
||||
"badge_type": "BADGE_POKEDEX_ENTRIES",
|
||||
"rank": 1,
|
||||
"start_value": 5,
|
||||
"end_value": 50,
|
||||
"current_value": 25
|
||||
},
|
||||
{
|
||||
"badge_type": "BADGE_CAPTURE_TOTAL",
|
||||
"rank": 1,
|
||||
"start_value": 30,
|
||||
"end_value": 500,
|
||||
"current_value": 71
|
||||
},
|
||||
{
|
||||
"badge_type": "BADGE_EVOLVED_TOTAL",
|
||||
"end_value": 3
|
||||
},
|
||||
{
|
||||
"badge_type": "BADGE_HATCHED_TOTAL",
|
||||
"end_value": 10,
|
||||
"current_value": 1
|
||||
},
|
||||
{
|
||||
"badge_type": "BADGE_POKESTOPS_VISITED",
|
||||
"rank": 1,
|
||||
"start_value": 100,
|
||||
"end_value": 1000,
|
||||
"current_value": 123
|
||||
},
|
||||
{
|
||||
"badge_type": "BADGE_BIG_MAGIKARP",
|
||||
"end_value": 3,
|
||||
"current_value": 1
|
||||
},
|
||||
{
|
||||
"badge_type": "BADGE_BATTLE_ATTACK_WON",
|
||||
"end_value": 10
|
||||
},
|
||||
{
|
||||
"badge_type": "BADGE_BATTLE_TRAINING_WON",
|
||||
"end_value": 10
|
||||
},
|
||||
{
|
||||
"badge_type": "BADGE_TYPE_NORMAL",
|
||||
"rank": 1,
|
||||
"start_value": 10,
|
||||
"end_value": 50,
|
||||
"current_value": 24
|
||||
},
|
||||
{
|
||||
"badge_type": "BADGE_TYPE_FIGHTING",
|
||||
"end_value": 10
|
||||
},
|
||||
{
|
||||
"badge_type": "BADGE_TYPE_FLYING",
|
||||
"rank": 1,
|
||||
"start_value": 10,
|
||||
"end_value": 50,
|
||||
"current_value": 26
|
||||
},
|
||||
{
|
||||
"badge_type": "BADGE_TYPE_POISON",
|
||||
"rank": 1,
|
||||
"start_value": 10,
|
||||
"end_value": 50,
|
||||
"current_value": 20
|
||||
},
|
||||
{
|
||||
"badge_type": "BADGE_TYPE_GROUND",
|
||||
"end_value": 10,
|
||||
"current_value": 1
|
||||
},
|
||||
{
|
||||
"badge_type": "BADGE_TYPE_ROCK",
|
||||
"end_value": 10
|
||||
},
|
||||
{
|
||||
"badge_type": "BADGE_TYPE_BUG",
|
||||
"rank": 1,
|
||||
"start_value": 10,
|
||||
"end_value": 50,
|
||||
"current_value": 14
|
||||
},
|
||||
{
|
||||
"badge_type": "BADGE_TYPE_GHOST",
|
||||
"end_value": 10
|
||||
},
|
||||
{
|
||||
"badge_type": "BADGE_TYPE_STEEL",
|
||||
"end_value": 10
|
||||
},
|
||||
{
|
||||
"badge_type": "BADGE_TYPE_FIRE",
|
||||
"end_value": 10,
|
||||
"current_value": 1
|
||||
},
|
||||
{
|
||||
"badge_type": "BADGE_TYPE_WATER",
|
||||
"rank": 1,
|
||||
"start_value": 10,
|
||||
"end_value": 50,
|
||||
"current_value": 14
|
||||
},
|
||||
{
|
||||
"badge_type": "BADGE_TYPE_GRASS",
|
||||
"end_value": 10,
|
||||
"current_value": 3
|
||||
},
|
||||
{
|
||||
"badge_type": "BADGE_TYPE_ELECTRIC",
|
||||
"end_value": 10
|
||||
},
|
||||
{
|
||||
"badge_type": "BADGE_TYPE_PSYCHIC",
|
||||
"end_value": 10,
|
||||
"current_value": 1
|
||||
},
|
||||
{
|
||||
"badge_type": "BADGE_TYPE_ICE",
|
||||
"end_value": 10
|
||||
},
|
||||
{
|
||||
"badge_type": "BADGE_TYPE_DRAGON",
|
||||
"end_value": 10
|
||||
},
|
||||
{
|
||||
"badge_type": "BADGE_TYPE_DARK",
|
||||
"end_value": 10
|
||||
},
|
||||
{
|
||||
"badge_type": "BADGE_TYPE_FAIRY",
|
||||
"end_value": 10,
|
||||
"current_value": 3
|
||||
},
|
||||
{
|
||||
"badge_type": "BADGE_SMALL_RATTATA",
|
||||
"end_value": 3
|
||||
},
|
||||
{
|
||||
"badge_type": "BADGE_PIKACHU",
|
||||
"end_value": 3
|
||||
}
|
||||
],
|
||||
"$unknownFields": []
|
||||
});
|
||||
|
||||
return (POGOProtos.serialize(buffer, "POGOProtos.Networking.Responses.GetPlayerProfileResponse"));
|
||||
|
||||
}
|
||||
@@ -1,13 +0,0 @@
|
||||
import CFG from "../../cfg";
|
||||
|
||||
import fs from "fs";
|
||||
import proto from "../proto";
|
||||
import POGOProtos from "pokemongo-protobuf";
|
||||
|
||||
/**
|
||||
* @param {Buffer} master
|
||||
* @return {Object}
|
||||
*/
|
||||
export default function ItemTemplates(master) {
|
||||
return (master);
|
||||
}
|
||||
@@ -1,21 +0,0 @@
|
||||
import proto from "../proto";
|
||||
import POGOProtos from "pokemongo-protobuf";
|
||||
|
||||
import { GetPlayer } from "./";
|
||||
|
||||
/**
|
||||
* @param {Object} obj
|
||||
* @return {Object}
|
||||
*/
|
||||
export default function LevelUpRewards(obj) {
|
||||
|
||||
let buffer = {
|
||||
"result": "AWARDED_ALREADY",
|
||||
"items_awarded": [],
|
||||
"items_unlocked": [],
|
||||
"$unknownFields": []
|
||||
}
|
||||
|
||||
return POGOProtos.serialize(buffer, "POGOProtos.Networking.Responses.LevelUpRewardsResponse");
|
||||
|
||||
}
|
||||
@@ -1,25 +0,0 @@
|
||||
import proto from "../proto";
|
||||
import POGOProtos from "pokemongo-protobuf";
|
||||
|
||||
import { GetPlayer } from "./";
|
||||
|
||||
/**
|
||||
* @param {Player} player
|
||||
* @param {Object} req
|
||||
* @return {Object}
|
||||
*/
|
||||
export default function MarkTutorialComplete(player, req) {
|
||||
|
||||
if (req.tutorials_completed[0] === "LEGAL_SCREEN") {
|
||||
player.tutorial_state.push("LEGAL_SCREEN");
|
||||
player.send_marketing_emails = !!req.send_marketing_emails;
|
||||
}
|
||||
|
||||
let buffer = ({
|
||||
success: true,
|
||||
player_data: GetPlayer(player).player_data
|
||||
});
|
||||
|
||||
return POGOProtos.serialize(buffer, "POGOProtos.Networking.Responses.GetHatchedEggsResponse");
|
||||
|
||||
}
|
||||
@@ -1,21 +0,0 @@
|
||||
import CFG from "../../cfg";
|
||||
|
||||
import proto from "../proto";
|
||||
|
||||
/**
|
||||
* @param {Request} req
|
||||
* @return {Object}
|
||||
*/
|
||||
export default function NicknamePokemon(req) {
|
||||
|
||||
let data = proto.Networking.Requests.Messages.NicknamePokemonMessage.decode(req.request_message.toBuffer());
|
||||
|
||||
// TODO: Save nickname into db
|
||||
|
||||
return (
|
||||
new proto.Networking.Responses.NicknamePokemonResponse({
|
||||
result: proto.Networking.Responses.NicknamePokemonResponse.Result.ERROR_INVALID_NICKNAME
|
||||
}).encode()
|
||||
);
|
||||
|
||||
}
|
||||
@@ -1,23 +0,0 @@
|
||||
import proto from "../proto";
|
||||
import POGOProtos from "pokemongo-protobuf";
|
||||
|
||||
import { GetPlayer } from "./";
|
||||
|
||||
/**
|
||||
* @param {Player} player
|
||||
* @return {Object}
|
||||
*/
|
||||
export default function SetAvatar(player) {
|
||||
|
||||
let buffer = ({
|
||||
status: proto.Networking.Responses.SetAvatarResponse.Status.SUCCESS,
|
||||
player_data: GetPlayer(player)
|
||||
});
|
||||
|
||||
if (player.tutorial_state.indexOf("AVATAR_SELECTION") === -1) {
|
||||
player.tutorial_state.push("AVATAR_SELECTION");
|
||||
}
|
||||
|
||||
return (POGOProtos.serialize(buffer, "POGOProtos.Networking.Responses.SetAvatarResponse"));
|
||||
|
||||
}
|
||||
@@ -1,20 +0,0 @@
|
||||
import CFG from "../../cfg";
|
||||
|
||||
import proto from "../proto";
|
||||
|
||||
import { GetPlayer } from "./";
|
||||
|
||||
/**
|
||||
* @param {Player} player
|
||||
* @return {Object}
|
||||
*/
|
||||
export default function SetContactSettings(player) {
|
||||
|
||||
return (
|
||||
new proto.Networking.Responses.SetContactSettingsResponse({
|
||||
status: proto.Networking.Responses.SetContactSettingsResponse.Status.SUCCESS,
|
||||
player_data: GetPlayer(player).player_data
|
||||
}).encode()
|
||||
);
|
||||
|
||||
}
|
||||
@@ -1,22 +0,0 @@
|
||||
import CFG from "../../cfg";
|
||||
|
||||
import proto from "../proto";
|
||||
import POGOProtos from "pokemongo-protobuf";
|
||||
|
||||
/**
|
||||
* @param {Request} req
|
||||
* @return {Object}
|
||||
*/
|
||||
export default function SetFavoritePokemon(player, req) {
|
||||
|
||||
let buffer = {
|
||||
"result": "SUCCESS",
|
||||
};
|
||||
|
||||
player.setFavoritePkmn(req.pokemon_id << 0, req.is_favorite);
|
||||
|
||||
return (
|
||||
POGOProtos.serialize(buffer, "POGOProtos.Networking.Responses.SetFavoritePokemonResponse")
|
||||
);
|
||||
|
||||
}
|
||||
@@ -1,650 +0,0 @@
|
||||
import proto from "../proto";
|
||||
import POGOProtos from "pokemongo-protobuf";
|
||||
|
||||
import CFG from "../../cfg";
|
||||
|
||||
/**
|
||||
* @param {Object} obj
|
||||
* @return {Object}
|
||||
*/
|
||||
export default function SfidaActionLog(obj) {
|
||||
|
||||
let buffer = ({
|
||||
"result": "SUCCESS",
|
||||
"log_entries": [
|
||||
{
|
||||
"timestamp_ms": "1471694560585",
|
||||
"catch_pokemon": {
|
||||
"result": "POKEMON_CAPTURED",
|
||||
"pokemon_id": "HORSEA",
|
||||
"combat_points": 110
|
||||
}
|
||||
},
|
||||
{
|
||||
"timestamp_ms": "1471694566830",
|
||||
"catch_pokemon": {
|
||||
"result": "POKEMON_CAPTURED",
|
||||
"pokemon_id": "HORSEA",
|
||||
"combat_points": 73
|
||||
}
|
||||
},
|
||||
{
|
||||
"timestamp_ms": "1471694573468",
|
||||
"fort_search": {
|
||||
"result": "SUCCESS",
|
||||
"items": [
|
||||
{
|
||||
"item_id": "ITEM_POKE_BALL",
|
||||
"count": 2
|
||||
},
|
||||
{
|
||||
"item_id": "ITEM_POTION",
|
||||
"count": 1
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"timestamp_ms": "1471694597662",
|
||||
"catch_pokemon": {
|
||||
"result": "POKEMON_CAPTURED",
|
||||
"pokemon_id": "HORSEA",
|
||||
"combat_points": 102
|
||||
}
|
||||
},
|
||||
{
|
||||
"timestamp_ms": "1471694603880",
|
||||
"catch_pokemon": {
|
||||
"result": "POKEMON_CAPTURED",
|
||||
"pokemon_id": "CATERPIE",
|
||||
"combat_points": 36
|
||||
}
|
||||
},
|
||||
{
|
||||
"timestamp_ms": "1471694610259",
|
||||
"catch_pokemon": {
|
||||
"result": "POKEMON_CAPTURED",
|
||||
"pokemon_id": "WEEDLE",
|
||||
"combat_points": 15
|
||||
}
|
||||
},
|
||||
{
|
||||
"timestamp_ms": "1471694616586",
|
||||
"catch_pokemon": {
|
||||
"result": "POKEMON_CAPTURED",
|
||||
"pokemon_id": "PIDGEY",
|
||||
"combat_points": 26
|
||||
}
|
||||
},
|
||||
{
|
||||
"timestamp_ms": "1471694632969",
|
||||
"fort_search": {
|
||||
"result": "SUCCESS",
|
||||
"items": [
|
||||
{
|
||||
"item_id": "ITEM_RAZZ_BERRY",
|
||||
"count": 1
|
||||
},
|
||||
{
|
||||
"item_id": "ITEM_POKE_BALL",
|
||||
"count": 1
|
||||
},
|
||||
{
|
||||
"item_id": "ITEM_POTION",
|
||||
"count": 1
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"timestamp_ms": "1471694739319",
|
||||
"fort_search": {
|
||||
"result": "SUCCESS",
|
||||
"items": [
|
||||
{
|
||||
"item_id": "ITEM_POKE_BALL",
|
||||
"count": 2
|
||||
},
|
||||
{
|
||||
"item_id": "ITEM_POTION",
|
||||
"count": 2
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"timestamp_ms": "1471694741772",
|
||||
"fort_search": {
|
||||
"result": "SUCCESS",
|
||||
"items": [
|
||||
{
|
||||
"item_id": "ITEM_POKE_BALL",
|
||||
"count": 4
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"timestamp_ms": "1471694904167",
|
||||
"catch_pokemon": {
|
||||
"result": "POKEMON_CAPTURED",
|
||||
"pokemon_id": "KRABBY",
|
||||
"combat_points": 100
|
||||
}
|
||||
},
|
||||
{
|
||||
"timestamp_ms": "1471694925722",
|
||||
"fort_search": {
|
||||
"result": "SUCCESS",
|
||||
"items": [
|
||||
{
|
||||
"item_id": "ITEM_RAZZ_BERRY",
|
||||
"count": 2
|
||||
},
|
||||
{
|
||||
"item_id": "ITEM_POKE_BALL",
|
||||
"count": 4
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"timestamp_ms": "1471695030964",
|
||||
"fort_search": {
|
||||
"result": "SUCCESS",
|
||||
"items": [
|
||||
{
|
||||
"item_id": "ITEM_RAZZ_BERRY",
|
||||
"count": 1
|
||||
},
|
||||
{
|
||||
"item_id": "ITEM_POKE_BALL",
|
||||
"count": 3
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"timestamp_ms": "1471695071016",
|
||||
"fort_search": {
|
||||
"result": "SUCCESS",
|
||||
"items": [
|
||||
{
|
||||
"item_id": "ITEM_POKE_BALL",
|
||||
"count": 2
|
||||
},
|
||||
{
|
||||
"item_id": "ITEM_POTION",
|
||||
"count": 1
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"timestamp_ms": "1471695089887",
|
||||
"catch_pokemon": {
|
||||
"result": "POKEMON_CAPTURED",
|
||||
"pokemon_id": "SPEAROW",
|
||||
"combat_points": 80
|
||||
}
|
||||
},
|
||||
{
|
||||
"timestamp_ms": "1471695096341",
|
||||
"fort_search": {
|
||||
"result": "SUCCESS",
|
||||
"items": [
|
||||
{
|
||||
"item_id": "ITEM_POKE_BALL",
|
||||
"count": 3
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"timestamp_ms": "1471695139926",
|
||||
"catch_pokemon": {
|
||||
"result": "POKEMON_CAPTURED",
|
||||
"pokemon_id": "EKANS",
|
||||
"combat_points": 72
|
||||
}
|
||||
},
|
||||
{
|
||||
"timestamp_ms": "1471695148440",
|
||||
"fort_search": {
|
||||
"result": "SUCCESS",
|
||||
"items": [
|
||||
{
|
||||
"item_id": "ITEM_POKE_BALL",
|
||||
"count": 2
|
||||
},
|
||||
{
|
||||
"item_id": "ITEM_POTION",
|
||||
"count": 1
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"timestamp_ms": "1471695195481",
|
||||
"catch_pokemon": {
|
||||
"result": "UNKNOWN_ENUM_VALUE_Result_3",
|
||||
"pokemon_id": "MAGIKARP",
|
||||
"combat_points": 26
|
||||
}
|
||||
},
|
||||
{
|
||||
"timestamp_ms": "1471695197676",
|
||||
"catch_pokemon": {
|
||||
"result": "POKEMON_CAPTURED",
|
||||
"pokemon_id": "ZUBAT",
|
||||
"combat_points": 41
|
||||
}
|
||||
},
|
||||
{
|
||||
"timestamp_ms": "1471695203917",
|
||||
"catch_pokemon": {
|
||||
"result": "POKEMON_CAPTURED",
|
||||
"pokemon_id": "MAGIKARP",
|
||||
"combat_points": 46
|
||||
}
|
||||
},
|
||||
{
|
||||
"timestamp_ms": "1471695211919",
|
||||
"fort_search": {
|
||||
"result": "SUCCESS",
|
||||
"items": [
|
||||
{
|
||||
"item_id": "ITEM_RAZZ_BERRY",
|
||||
"count": 1
|
||||
},
|
||||
{
|
||||
"item_id": "ITEM_POKE_BALL",
|
||||
"count": 2
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"timestamp_ms": "1471695316895",
|
||||
"catch_pokemon": {
|
||||
"result": "POKEMON_CAPTURED",
|
||||
"pokemon_id": "ZUBAT",
|
||||
"combat_points": 43
|
||||
}
|
||||
},
|
||||
{
|
||||
"timestamp_ms": "1471695323589",
|
||||
"fort_search": {
|
||||
"result": "SUCCESS",
|
||||
"items": [
|
||||
{
|
||||
"item_id": "ITEM_POKE_BALL",
|
||||
"count": 3
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"timestamp_ms": "1471695429795",
|
||||
"fort_search": {
|
||||
"result": "SUCCESS",
|
||||
"items": [
|
||||
{
|
||||
"item_id": "ITEM_RAZZ_BERRY",
|
||||
"count": 1
|
||||
},
|
||||
{
|
||||
"item_id": "ITEM_POKE_BALL",
|
||||
"count": 1
|
||||
},
|
||||
{
|
||||
"item_id": "ITEM_POTION",
|
||||
"count": 1
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"timestamp_ms": "1471695487237",
|
||||
"fort_search": {
|
||||
"result": "SUCCESS",
|
||||
"items": [
|
||||
{
|
||||
"item_id": "ITEM_RAZZ_BERRY",
|
||||
"count": 1
|
||||
},
|
||||
{
|
||||
"item_id": "ITEM_POKE_BALL",
|
||||
"count": 2
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"timestamp_ms": "1471695522740",
|
||||
"fort_search": {
|
||||
"result": "SUCCESS",
|
||||
"items": [
|
||||
{
|
||||
"item_id": "ITEM_RAZZ_BERRY",
|
||||
"count": 1
|
||||
},
|
||||
{
|
||||
"item_id": "ITEM_POKE_BALL",
|
||||
"count": 2
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"timestamp_ms": "1471695577816",
|
||||
"fort_search": {
|
||||
"result": "SUCCESS",
|
||||
"items": [
|
||||
{
|
||||
"item_id": "ITEM_POKE_BALL",
|
||||
"count": 1
|
||||
},
|
||||
{
|
||||
"item_id": "ITEM_POTION",
|
||||
"count": 2
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"timestamp_ms": "1471695633092",
|
||||
"fort_search": {
|
||||
"result": "SUCCESS",
|
||||
"items": [
|
||||
{
|
||||
"item_id": "ITEM_POKE_BALL",
|
||||
"count": 1
|
||||
},
|
||||
{
|
||||
"item_id": "ITEM_POTION",
|
||||
"count": 2
|
||||
}
|
||||
],
|
||||
"eggs": 1
|
||||
}
|
||||
},
|
||||
{
|
||||
"timestamp_ms": "1471695738726",
|
||||
"fort_search": {
|
||||
"result": "SUCCESS",
|
||||
"items": [
|
||||
{
|
||||
"item_id": "ITEM_RAZZ_BERRY",
|
||||
"count": 1
|
||||
},
|
||||
{
|
||||
"item_id": "ITEM_POKE_BALL",
|
||||
"count": 2
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"timestamp_ms": "1471695776746",
|
||||
"fort_search": {
|
||||
"result": "SUCCESS",
|
||||
"items": [
|
||||
{
|
||||
"item_id": "ITEM_RAZZ_BERRY",
|
||||
"count": 1
|
||||
},
|
||||
{
|
||||
"item_id": "ITEM_REVIVE",
|
||||
"count": 1
|
||||
},
|
||||
{
|
||||
"item_id": "ITEM_POKE_BALL",
|
||||
"count": 1
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"timestamp_ms": "1471695790415",
|
||||
"fort_search": {
|
||||
"result": "SUCCESS",
|
||||
"items": [
|
||||
{
|
||||
"item_id": "ITEM_REVIVE",
|
||||
"count": 1
|
||||
},
|
||||
{
|
||||
"item_id": "ITEM_POKE_BALL",
|
||||
"count": 4
|
||||
},
|
||||
{
|
||||
"item_id": "ITEM_POTION",
|
||||
"count": 1
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"timestamp_ms": "1471695829422",
|
||||
"catch_pokemon": {
|
||||
"result": "POKEMON_CAPTURED",
|
||||
"pokemon_id": "MAGIKARP",
|
||||
"combat_points": 40
|
||||
}
|
||||
},
|
||||
{
|
||||
"timestamp_ms": "1471695836445",
|
||||
"fort_search": {
|
||||
"result": "SUCCESS",
|
||||
"items": [
|
||||
{
|
||||
"item_id": "ITEM_POKE_BALL",
|
||||
"count": 2
|
||||
},
|
||||
{
|
||||
"item_id": "ITEM_POTION",
|
||||
"count": 1
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"timestamp_ms": "1471695838748",
|
||||
"fort_search": {
|
||||
"result": "SUCCESS",
|
||||
"items": [
|
||||
{
|
||||
"item_id": "ITEM_POKE_BALL",
|
||||
"count": 2
|
||||
},
|
||||
{
|
||||
"item_id": "ITEM_POTION",
|
||||
"count": 1
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"timestamp_ms": "1471695860629",
|
||||
"catch_pokemon": {
|
||||
"result": "POKEMON_FLED",
|
||||
"pokemon_id": "VENONAT",
|
||||
"combat_points": 174
|
||||
}
|
||||
},
|
||||
{
|
||||
"timestamp_ms": "1471695866223",
|
||||
"fort_search": {
|
||||
"result": "SUCCESS",
|
||||
"items": [
|
||||
{
|
||||
"item_id": "ITEM_POKE_BALL",
|
||||
"count": 2
|
||||
},
|
||||
{
|
||||
"item_id": "ITEM_POTION",
|
||||
"count": 1
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"timestamp_ms": "1471695884419",
|
||||
"catch_pokemon": {
|
||||
"result": "POKEMON_CAPTURED",
|
||||
"pokemon_id": "STARYU",
|
||||
"combat_points": 11
|
||||
}
|
||||
},
|
||||
{
|
||||
"timestamp_ms": "1471695889856",
|
||||
"fort_search": {
|
||||
"result": "SUCCESS",
|
||||
"items": [
|
||||
{
|
||||
"item_id": "ITEM_POKE_BALL",
|
||||
"count": 3
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"timestamp_ms": "1471695906137",
|
||||
"catch_pokemon": {
|
||||
"result": "POKEMON_CAPTURED",
|
||||
"pokemon_id": "PINSIR",
|
||||
"combat_points": 28
|
||||
}
|
||||
},
|
||||
{
|
||||
"timestamp_ms": "1471695914356",
|
||||
"fort_search": {
|
||||
"result": "SUCCESS",
|
||||
"items": [
|
||||
{
|
||||
"item_id": "ITEM_POKE_BALL",
|
||||
"count": 3
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"timestamp_ms": "1471696008778",
|
||||
"fort_search": {
|
||||
"result": "SUCCESS",
|
||||
"items": [
|
||||
{
|
||||
"item_id": "ITEM_POKE_BALL",
|
||||
"count": 3
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"timestamp_ms": "1471696010713",
|
||||
"catch_pokemon": {
|
||||
"result": "POKEMON_CAPTURED",
|
||||
"pokemon_id": "CATERPIE",
|
||||
"combat_points": 74
|
||||
}
|
||||
},
|
||||
{
|
||||
"timestamp_ms": "1471696050313",
|
||||
"fort_search": {
|
||||
"result": "SUCCESS",
|
||||
"items": [
|
||||
{
|
||||
"item_id": "ITEM_POKE_BALL",
|
||||
"count": 3
|
||||
},
|
||||
{
|
||||
"item_id": "ITEM_POTION",
|
||||
"count": 1
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"timestamp_ms": "1471696052566",
|
||||
"fort_search": {
|
||||
"result": "SUCCESS",
|
||||
"items": [
|
||||
{
|
||||
"item_id": "ITEM_POKE_BALL",
|
||||
"count": 3
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"timestamp_ms": "1471696072147",
|
||||
"fort_search": {
|
||||
"result": "SUCCESS",
|
||||
"items": [
|
||||
{
|
||||
"item_id": "ITEM_POKE_BALL",
|
||||
"count": 1
|
||||
},
|
||||
{
|
||||
"item_id": "ITEM_POTION",
|
||||
"count": 2
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"timestamp_ms": "1471696074058",
|
||||
"catch_pokemon": {
|
||||
"result": "POKEMON_CAPTURED",
|
||||
"pokemon_id": "ZUBAT",
|
||||
"combat_points": 40
|
||||
}
|
||||
},
|
||||
{
|
||||
"timestamp_ms": "1471696079308",
|
||||
"fort_search": {
|
||||
"result": "SUCCESS",
|
||||
"items": [
|
||||
{
|
||||
"item_id": "ITEM_RAZZ_BERRY",
|
||||
"count": 1
|
||||
},
|
||||
{
|
||||
"item_id": "ITEM_POKE_BALL",
|
||||
"count": 2
|
||||
},
|
||||
{
|
||||
"item_id": "ITEM_POTION",
|
||||
"count": 1
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"timestamp_ms": "1471696081215",
|
||||
"catch_pokemon": {
|
||||
"result": "POKEMON_CAPTURED",
|
||||
"pokemon_id": "ZUBAT",
|
||||
"combat_points": 73
|
||||
}
|
||||
},
|
||||
{
|
||||
"timestamp_ms": "1471696235352",
|
||||
"fort_search": {
|
||||
"result": "SUCCESS",
|
||||
"items": [
|
||||
{
|
||||
"item_id": "ITEM_POKE_BALL",
|
||||
"count": 3
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
],
|
||||
"$unknownFields": []
|
||||
});
|
||||
|
||||
return (POGOProtos.serialize(buffer, "POGOProtos.Networking.Responses.SfidaActionLogResponse"));
|
||||
|
||||
}
|
||||
@@ -1,71 +0,0 @@
|
||||
import proto from "../proto";
|
||||
import POGOProtos from "pokemongo-protobuf";
|
||||
|
||||
import CFG from "../../cfg";
|
||||
|
||||
/**
|
||||
* @return {Object}
|
||||
*/
|
||||
export default function ShopData() {
|
||||
|
||||
let buffer = ({
|
||||
"response_type": 5,
|
||||
"unknown2": {
|
||||
"unknown1": "1",
|
||||
"items": [
|
||||
{
|
||||
"item_id": "pgorelease.pokeball.100",
|
||||
"currency_to_buy": {
|
||||
"name": "POKECOIN",
|
||||
"amount": 460
|
||||
},
|
||||
"yields_item": {
|
||||
"count": 100
|
||||
},
|
||||
"tags": [
|
||||
{
|
||||
"key": "CATEGORY",
|
||||
"value": "ITEMS"
|
||||
},
|
||||
{
|
||||
"key": "SORT",
|
||||
"value": "2"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"item_id": "pgorelease.pokecoin.100",
|
||||
"is_iap": true,
|
||||
"yields_currency": {
|
||||
"name": "POKECOIN",
|
||||
"amount": 100
|
||||
},
|
||||
"tags": [
|
||||
{
|
||||
"key": "CATEGORY",
|
||||
"value": "POKECOINS"
|
||||
},
|
||||
{
|
||||
"key": "SORT",
|
||||
"value": "1"
|
||||
}
|
||||
],
|
||||
"unknown7": 1
|
||||
}
|
||||
],
|
||||
"player_currencies": [
|
||||
{
|
||||
"name": "POKECOIN"
|
||||
},
|
||||
{
|
||||
"name": "STARDUST",
|
||||
"amount": 7681
|
||||
}
|
||||
],
|
||||
"unknown4": "ZCgldzCNR+0pbImyvzykby/6+iA="
|
||||
}
|
||||
});
|
||||
|
||||
return (buffer);
|
||||
|
||||
}
|
||||
@@ -1,20 +0,0 @@
|
||||
import CFG from "../../cfg";
|
||||
|
||||
import proto from "../proto";
|
||||
|
||||
/**
|
||||
* @param {Request} req
|
||||
* @return {Object}
|
||||
*/
|
||||
export default function UpgradePokemon(req) {
|
||||
|
||||
let data = proto.Networking.Requests.Messages.UpgradePokemonMessage.decode(req.request_message.toBuffer());
|
||||
|
||||
return (
|
||||
new proto.Networking.Responses.UpgradePokemonResponse({
|
||||
result: proto.Networking.Responses.UpgradePokemonResponse.Result.ERROR_UPGRADE_NOT_AVAILABLE,
|
||||
upgraded_pokemon: null
|
||||
}).encode()
|
||||
);
|
||||
|
||||
}
|
||||
@@ -1,42 +0,0 @@
|
||||
export DownloadRemoteConfigVersion from "./Responses.DownloadRemoteConfigVersion";
|
||||
export DownloadSettings from "./Responses.DownloadSettings";
|
||||
|
||||
export GetAssetDigest from "./Responses.GetAssetDigest";
|
||||
export GetHatchedEggs from "./Responses.GetHatchedEggs";
|
||||
export GetInventory from "./Responses.GetInventory";
|
||||
export GetPlayer from "./Responses.GetPlayer";
|
||||
export GetPlayerProfile from "./Responses.GetPlayerProfile";
|
||||
|
||||
export FortDetails from "./Responses.FortDetails";
|
||||
export FortSearch from "./Responses.FortSearch";
|
||||
export GetMapObjects from "./Responses.GetMapObjects";
|
||||
|
||||
export SetContactSettings from "./Responses.SetContactSettings";
|
||||
|
||||
export ItemTemplates from "./Responses.ItemTemplates";
|
||||
export CheckAwardedBadges from "./Responses.CheckAwardedBadges";
|
||||
export GetDownloadUrls from "./Responses.GetDownloadUrls";
|
||||
|
||||
export MarkTutorialComplete from "./Responses.MarkTutorialComplete";
|
||||
export ClaimCodeName from "./Responses.ClaimCodeName";
|
||||
|
||||
export LevelUpRewards from "./Responses.LevelUpRewards";
|
||||
|
||||
export SetAvatar from "./Responses.SetAvatar";
|
||||
|
||||
export SfidaActionLog from "./Responses.SfidaActionLog";
|
||||
|
||||
export CheckChallenge from "./Responses.CheckChallenge";
|
||||
|
||||
export Encounter from "./Responses.Encounter";
|
||||
export CatchPokemon from "./Responses.CatchPokemon";
|
||||
export NicknamePokemon from "./Responses.NicknamePokemon";
|
||||
export UpgradePokemon from "./Responses.UpgradePokemon";
|
||||
export EvolvePokemon from "./Responses.EvolvePokemon";
|
||||
export SetFavoritePokemon from "./Responses.SetFavoritePokemon";
|
||||
|
||||
export ShopData from "./Responses.ShopData";
|
||||
|
||||
export AuthTicket from "./Envelopes.AuthTicket";
|
||||
export ResponseEnvelope from "./Envelopes.ResponseEnvelope";
|
||||
export ResponseEnvelopeAuth from "./Envelopes.ResponseEnvelope.Auth";
|
||||
556
src/player.js
556
src/player.js
@@ -1,556 +0,0 @@
|
||||
import proto from "./proto";
|
||||
|
||||
import CFG from "../cfg";
|
||||
|
||||
import {
|
||||
getHashCodeFrom,
|
||||
decodeRequestEnvelope
|
||||
} from "./utils";
|
||||
|
||||
import {
|
||||
ResponseEnvelope,
|
||||
ResponseEnvelopeAuth
|
||||
} from "./packets";
|
||||
|
||||
import jwtDecode from "jwt-decode";
|
||||
|
||||
import { GetPlayer } from "./packets";
|
||||
|
||||
/**
|
||||
* @class Player
|
||||
*/
|
||||
class Player {
|
||||
|
||||
/** @constructor */
|
||||
constructor(obj) {
|
||||
|
||||
this.uid = -1;
|
||||
this.owner_id = -1;
|
||||
|
||||
this._email = null;
|
||||
this.username = "unknown";
|
||||
|
||||
this.latitude = 0;
|
||||
this.longitude = 0;
|
||||
this.altitude = 0;
|
||||
|
||||
this.send_marketing_emails = false;
|
||||
this.send_push_notifications = false;
|
||||
|
||||
this.exp = 0;
|
||||
this.level = 1;
|
||||
|
||||
this.stardust = 0;
|
||||
this.pokecoins = 0;
|
||||
|
||||
this.team = 0;
|
||||
|
||||
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;
|
||||
|
||||
this.items = {
|
||||
poke_ball: 0,
|
||||
great_ball: 0,
|
||||
ultra_ball: 0,
|
||||
master_ball: 0,
|
||||
potion: 0,
|
||||
super_potion: 0,
|
||||
hyper_potion: 0,
|
||||
max_potion: 0,
|
||||
revive: 0,
|
||||
max_revive: 0,
|
||||
lucky_egg: 0,
|
||||
incense_ordinary: 0,
|
||||
incense_spicy: 0,
|
||||
incense_cool: 0,
|
||||
incense_floral: 0,
|
||||
troy_disk: 0,
|
||||
razz_berry: 0,
|
||||
bluk_berry: 0,
|
||||
nanab_berry: 0,
|
||||
wepar_berry: 0,
|
||||
pinap_berry: 0,
|
||||
incubator_basic: 0,
|
||||
incubator_basic_unlimited: 0,
|
||||
pokemon_storage_upgrade: 0,
|
||||
storage_upgrade: 0
|
||||
};
|
||||
|
||||
this.party = [];
|
||||
|
||||
this.tutorial_state = [];
|
||||
|
||||
this.badges = null;
|
||||
this.pokedex = null;
|
||||
this.inventory = null;
|
||||
|
||||
this.asset_digest = null;
|
||||
|
||||
this.hasSignature = false;
|
||||
|
||||
this.isIOS = false;
|
||||
this.isAndroid = false;
|
||||
|
||||
this.isPTCAccount = false;
|
||||
this.isGoogleAccount = false;
|
||||
|
||||
this.request = obj.request;
|
||||
this.response = null;
|
||||
this.connection = obj.connection;
|
||||
|
||||
this.timeout = obj.timeout;
|
||||
|
||||
this.remotePort = obj.remotePort;
|
||||
this.remoteAddress = obj.remoteAddress;
|
||||
|
||||
this.currentEncounter = null;
|
||||
|
||||
this.loggedIn = obj.loggedIn || false;
|
||||
this.authenticated = false;
|
||||
|
||||
this.authentications = 0;
|
||||
|
||||
}
|
||||
|
||||
get email() {
|
||||
return (this._email);
|
||||
}
|
||||
set email(value) {
|
||||
this._email = value.replace("@gmail.com", "");
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {String} email
|
||||
*/
|
||||
generateUid(email) {
|
||||
this.uid = getHashCodeFrom(String(email));
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {Buffer} buffer
|
||||
*/
|
||||
sendResponse(buffer) {
|
||||
this.response.end(buffer);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {Response} res
|
||||
*/
|
||||
updateResponse(res) {
|
||||
this.response = res;
|
||||
}
|
||||
|
||||
updateByObject(obj) {
|
||||
for (let key in obj) {
|
||||
if (this.hasOwnProperty(key)) {
|
||||
if (key === "send_marketing_emails" || key === "send_push_notifications") {
|
||||
this[key] = !!obj[key];
|
||||
}
|
||||
else {
|
||||
this[key] = obj[key];
|
||||
}
|
||||
}
|
||||
else if (key.substring(0, 5) === "item_") {
|
||||
let name = key.substring(5, key.length);
|
||||
this.items[name] = obj[key];
|
||||
}
|
||||
else if (key === "id") {
|
||||
this.owner_id = obj[key];
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {Object} obj
|
||||
*/
|
||||
updatePosition(obj) {
|
||||
this.latitude = obj.latitude;
|
||||
this.longitude = obj.longitude;
|
||||
}
|
||||
|
||||
updateAvatar(req) {
|
||||
|
||||
let node = null;
|
||||
|
||||
for (let key in req.player_avatar) {
|
||||
node = req.player_avatar[key];
|
||||
if (key === "gender") {
|
||||
this.gender = node === "FEMALE" ? 1 : 0;
|
||||
}
|
||||
else {
|
||||
if (this.hasOwnProperty(key)) {
|
||||
this[key] = node;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
updateContactSettings(req) {
|
||||
|
||||
let data = proto.Networking.Requests.Messages.SetContactSettingsMessage.decode(req.request_message.toBuffer()).contact_settings;
|
||||
|
||||
if (!data) return void 0;
|
||||
|
||||
this.send_marketing_emails = data.send_marketing_emails;
|
||||
this.send_push_notifications = data.send_push_notifications;
|
||||
|
||||
}
|
||||
|
||||
getPkmnIndexFromPartyById(id) {
|
||||
for (let ii = 0; ii < this.party.length; ++ii) {
|
||||
if (this.party[ii].id === id) return (ii);
|
||||
};
|
||||
return (-1);
|
||||
}
|
||||
|
||||
getPkmnFromPartyById(id) {
|
||||
let index = this.getPkmnIndexFromPartyById(id);
|
||||
return (this.party[index]);
|
||||
}
|
||||
|
||||
deletePkmnFromParty(id) {
|
||||
let index = this.getPkmnIndexFromPartyById(id);
|
||||
let pkmn = this.party[index];
|
||||
if (pkmn) this.party.splice(index, 1);
|
||||
}
|
||||
|
||||
setFavoritePkmn(id, favorite) {
|
||||
let pkmn = this.getPkmnFromPartyById(id);
|
||||
if (pkmn) pkmn.favorite = favorite;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {String} name
|
||||
* @return {Boolean}
|
||||
*/
|
||||
export function validPlayerName(name) {
|
||||
return !(
|
||||
name === null ||
|
||||
name === void 0 ||
|
||||
typeof name === "string" &&
|
||||
name.length <= 1
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {Player} player
|
||||
*/
|
||||
export function getPlayerIndex(player) {
|
||||
|
||||
let ip = player.remoteAddress;
|
||||
let index = -1;
|
||||
|
||||
let ii = 0, length = this.clients.length;
|
||||
|
||||
for (; ii < length; ++ii) {
|
||||
if (this.clients[ii].remoteAddress === ip) {
|
||||
index = ii;
|
||||
break;
|
||||
}
|
||||
};
|
||||
|
||||
return (index);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {Request} req
|
||||
*/
|
||||
export function getPlayerByRequest(req) {
|
||||
return (
|
||||
this.getPlayerByIP(req.headers.host)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {String} ip
|
||||
*/
|
||||
export function getPlayerByIP(ip) {
|
||||
|
||||
let ii = 0, length = this.clients.length;
|
||||
|
||||
for (; ii < length; ++ii) {
|
||||
if (this.clients[ii].remoteAddress === ip) {
|
||||
return (this.clients[ii]);
|
||||
}
|
||||
};
|
||||
|
||||
return (null);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {String} name
|
||||
*/
|
||||
export function getPlayerByName(name) {
|
||||
|
||||
let ii = 0, length = this.clients.length;
|
||||
|
||||
for (; ii < length; ++ii) {
|
||||
if (this.clients[ii].username === name) {
|
||||
return (this.clients[ii]);
|
||||
}
|
||||
};
|
||||
|
||||
return (null);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {Request} req
|
||||
* @return {Player}
|
||||
*/
|
||||
export function addPlayer(req) {
|
||||
|
||||
let connection = req.connection;
|
||||
|
||||
let player = new Player({
|
||||
timeout: this.time,
|
||||
connection: connection,
|
||||
request: req,
|
||||
remotePort: connection.remotePort,
|
||||
remoteAddress: req.headers.host
|
||||
});
|
||||
|
||||
this.clients.push(player);
|
||||
|
||||
return (player);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {Player} player
|
||||
*/
|
||||
export function removePlayer(player) {
|
||||
|
||||
let index = this.getPlayerIndex(player);
|
||||
|
||||
if (index >= 0) {
|
||||
this.clients.splice(index, 1);
|
||||
this.print(`${player.remoteAddress} disconnected!`, 36);
|
||||
this.emit("killPlayer", player);
|
||||
}
|
||||
else {
|
||||
this.print("Failed at removing player", 33);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {String} name
|
||||
* @param {String} pkmn
|
||||
*/
|
||||
export function spawnPkmnAtPlayer(name, pkmn, amount) {
|
||||
|
||||
if (!this.validPlayerName(name)) {
|
||||
this.print(`Invalid player name!`, 31);
|
||||
return void 0;
|
||||
}
|
||||
|
||||
let spawn = null;
|
||||
let player = this.getPlayerByName(name);
|
||||
|
||||
if (player !== null) {
|
||||
let index = 0;
|
||||
while (++index <= amount) {
|
||||
spawn = {
|
||||
pokemon_id: pkmn.toUpperCase(),
|
||||
cp: Math.random() * 1e3 << 0,
|
||||
encounter_id: Math.random() * 1e5 << 0,
|
||||
latitude: player.latitude + parseFloat((Math.random() / 1e3).toFixed(5)),
|
||||
longitude: player.longitude + parseFloat((Math.random() / 1e3).toFixed(5))
|
||||
};
|
||||
this.wild_pokemons.push(spawn);
|
||||
};
|
||||
this.print(`Spawned ${amount}x ${pkmn}'s to ${name} at ${spawn.latitude.toFixed(7)}:${spawn.longitude.toFixed(7)}!`);
|
||||
}
|
||||
else this.print(`Failed to spawn ${pkmn} to player ${name}!`, 31);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {String} name
|
||||
*/
|
||||
export function kickPlayer(name) {
|
||||
|
||||
if (!this.validPlayerName(name)) {
|
||||
this.print(`Invalid player name!`, 31);
|
||||
return void 0;
|
||||
}
|
||||
|
||||
let player = this.getPlayerByName(name);
|
||||
|
||||
if (player !== null) {
|
||||
this.removePlayer(player);
|
||||
this.print(`Kicked ${name} from the server!`);
|
||||
}
|
||||
else this.print(`Failed to kick ${name} from the server!`, 31);
|
||||
|
||||
}
|
||||
|
||||
export function updatePlayers() {
|
||||
//this.print("Updating players");
|
||||
}
|
||||
|
||||
export function saveAllPlayers() {
|
||||
for (let client of this.clients) {
|
||||
this.savePlayer(client);
|
||||
};
|
||||
}
|
||||
|
||||
export function removeAllPlayers() {
|
||||
for (let client of this.clients) {
|
||||
this.removePlayer(client);
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {Player} player
|
||||
*/
|
||||
export function savePlayer(player) {
|
||||
return new Promise((resolve) => {
|
||||
if (player.authenticated) {
|
||||
this.updateUser(player).then(() => {
|
||||
this.updateUserItems(player).then(() => {
|
||||
this.updateUserParty(player).then(() => {
|
||||
// refresh player data by database
|
||||
this.loginPlayer(player).then(resolve);
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {Player} player
|
||||
*/
|
||||
export function forwardPlayer(player) {
|
||||
|
||||
return new Promise((resolve) => {
|
||||
this.getUserByEmail(player.email).then((doc) => {
|
||||
if (player.email.length) {
|
||||
let provider = player.isGoogleAccount ? "Google" : "PTC";
|
||||
this.print(`${player.email} authenticated via ${provider}!`, 36);
|
||||
}
|
||||
if (doc) {
|
||||
this.loginPlayer(player).then((res) => {
|
||||
this.emit("loginPlayer", player);
|
||||
resolve(res);
|
||||
});
|
||||
}
|
||||
else {
|
||||
this.registerPlayer(player).then((res) => {
|
||||
this.emit("registerPlayer", player);
|
||||
resolve(res);
|
||||
});
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {Player} player
|
||||
*/
|
||||
export function loginPlayer(player) {
|
||||
|
||||
return new Promise((resolve) => {
|
||||
this.getUserByEmail(player.email).then((user) => {
|
||||
user = user[0];
|
||||
this.getPkmnByColumn("owner_id", user.id).then((party) => {
|
||||
player.updateByObject(user);
|
||||
player.party = party;
|
||||
let buffer = GetPlayer(player);
|
||||
resolve(buffer);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {Player} player
|
||||
*/
|
||||
export function registerPlayer(player) {
|
||||
|
||||
return new Promise((resolve) => {
|
||||
this.createUser(player).then(() => {
|
||||
this.print(`${player.email} registered!`, 36);
|
||||
this.loginPlayer(player).then((res) => {
|
||||
resolve(res);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {Player} player
|
||||
* @return {Buffer}
|
||||
*/
|
||||
export function authenticatePlayer(player) {
|
||||
|
||||
let request = decodeRequestEnvelope(player.request.body);
|
||||
|
||||
let msg = ResponseEnvelopeAuth({
|
||||
id: request.request_id
|
||||
});
|
||||
|
||||
let token = request.auth_info;
|
||||
|
||||
// TODO: Support PTC server authentification
|
||||
|
||||
if (!token || !token.provider) {
|
||||
this.print("Invalid authentication token! Kicking..", 31);
|
||||
this.removePlayer(player);
|
||||
return void 0;
|
||||
}
|
||||
|
||||
if (token.provider === "google") {
|
||||
if (token.token !== null) {
|
||||
let decoded = jwtDecode(token.token.contents);
|
||||
player.generateUid(decoded.email);
|
||||
player.email = decoded.email;
|
||||
player.email_verified = decoded.email_verified;
|
||||
player.isGoogleAccount = true;
|
||||
this.print(`${player.email} connected!`, 36);
|
||||
}
|
||||
else {
|
||||
this.print("Invalid authentication token! Kicking..", 31);
|
||||
this.removePlayer(player);
|
||||
return void 0;
|
||||
}
|
||||
}
|
||||
else if (token.provider === "ptc") {
|
||||
let decoded = token.token.contents;
|
||||
player.isPTCAccount = true;
|
||||
player.email = decoded.split("-")[1];
|
||||
player.email_verified = true;
|
||||
player.isPTCAccount = true;
|
||||
//console.log(decoded);
|
||||
this.print("PTC auth isnt supported yet! Your progress wont get saved!", 33);
|
||||
//this.removePlayer(player);
|
||||
//return void 0;
|
||||
}
|
||||
else {
|
||||
this.print("Invalid provider! Kicking..", 31);
|
||||
this.removePlayer(player);
|
||||
return void 0;
|
||||
}
|
||||
|
||||
player.authenticated = true;
|
||||
|
||||
return (msg);
|
||||
|
||||
}
|
||||
11
src/print.js
Normal file
11
src/print.js
Normal file
@@ -0,0 +1,11 @@
|
||||
import CFG from "../cfg";
|
||||
|
||||
/**
|
||||
* @param {String} msg
|
||||
* @param {Number} color
|
||||
* @param {Boolean} nl
|
||||
*/
|
||||
export default 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" : ""}`);
|
||||
}
|
||||
@@ -1,15 +1,17 @@
|
||||
import fs from "fs";
|
||||
|
||||
import print from "./print";
|
||||
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 "/clients":
|
||||
var length = this.clients.length;
|
||||
this.print(`${length}:${CFG.MAX_CONNECTIONS} connected players!`, 33);
|
||||
case "/players":
|
||||
var length = players.length;
|
||||
print(`${length}:${CFG.MAX_CONNECTIONS} connected players!`, 33);
|
||||
break;
|
||||
// Exit the server
|
||||
case "/exit":
|
||||
@@ -19,10 +21,10 @@ export function processCommand(cmd, data) {
|
||||
this.kickPlayer(data[1]);
|
||||
break;
|
||||
case "/killall":
|
||||
var length = this.clients.length;
|
||||
var length = players.length;
|
||||
this.removeAllPlayers();
|
||||
var result = length - this.clients.length;
|
||||
this.print(`Removed ${result} player${result === 1 ? "": "s"}!`);
|
||||
var result = length - players.length;
|
||||
print(`Removed ${result} player${result === 1 ? "": "s"}!`);
|
||||
break;
|
||||
case "/clear":
|
||||
process.stdout.write("\x1Bc");
|
||||
@@ -35,8 +37,8 @@ export function processCommand(cmd, data) {
|
||||
break;
|
||||
case "/save":
|
||||
this.saveAllPlayers();
|
||||
var length = this.clients.length;
|
||||
this.print(`Saved ${length} player${length === 1 ? "": "s"} into database!`);
|
||||
var length = players.length;
|
||||
print(`Saved ${length} player${length === 1 ? "": "s"} into database!`);
|
||||
break;
|
||||
case "/spawn":
|
||||
this.spawnPkmnAtPlayer(data[1], data[2], data[3] || 1);
|
||||
@@ -45,7 +47,7 @@ export function processCommand(cmd, data) {
|
||||
eval(fs.readFileSync("update.js", "utf8"));
|
||||
break;
|
||||
default:
|
||||
this.print(`${cmd} is not a valid command!`, 31);
|
||||
print(`${cmd} is not a valid command!`, 31);
|
||||
break;
|
||||
};
|
||||
};
|
||||
@@ -61,15 +63,15 @@ export function stdinInput(data) {
|
||||
export function uncaughtException(excp) {
|
||||
switch (excp.errno) {
|
||||
case "EADDRINUSE":
|
||||
this.print(`Port ${CFG.PORT} is already in use!`, 31);
|
||||
print(`Port ${CFG.PORT} is already in use!`, 31);
|
||||
break;
|
||||
case "EACCES":
|
||||
this.print("No root privileges!", 31);
|
||||
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);
|
||||
print("The server has crashed!", 31);
|
||||
};
|
||||
@@ -1,3 +0,0 @@
|
||||
import pogo from "node-pogo-protos";
|
||||
|
||||
export default pogo;
|
||||
205
src/request.js
205
src/request.js
@@ -1,25 +1,17 @@
|
||||
import fs from "fs";
|
||||
import url from "url";
|
||||
import proto from "./proto";
|
||||
import pcrypt from "pcrypt";
|
||||
import jwtDecode from "jwt-decode";
|
||||
import POGOProtos from "pokemongo-protobuf";
|
||||
|
||||
import print from "./print";
|
||||
import CFG from "../cfg";
|
||||
|
||||
import {
|
||||
ResponseEnvelope,
|
||||
AuthTicket,
|
||||
ShopData
|
||||
} from "./packets";
|
||||
|
||||
/**
|
||||
* @param {Request} req
|
||||
* @param {Response} res
|
||||
*/
|
||||
export function routeRequest(req, res) {
|
||||
|
||||
let player = this.getPlayerByRequest(req);
|
||||
|
||||
let parsed = url.parse(req.url).pathname;
|
||||
let route = parsed.split("/");
|
||||
let host = req.headers.host;
|
||||
@@ -27,145 +19,162 @@ export function routeRequest(req, res) {
|
||||
switch (route[1]) {
|
||||
case "plfe":
|
||||
case "custom":
|
||||
if (route[2] === "rpc") this.onRequest(req);
|
||||
this.processRpcRequest(req, res, route);
|
||||
break;
|
||||
case "model":
|
||||
// make sure no random dudes can access download
|
||||
if (!player.authenticated || !player.email_verified) 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);
|
||||
});
|
||||
}
|
||||
this.processModelRequest(req, res, route);
|
||||
break;
|
||||
case "om":
|
||||
if (
|
||||
route[2] === "glm" &&
|
||||
route[3] === "mmap"
|
||||
) {
|
||||
this.print(`Received gmaps request!`, 33);
|
||||
case "api":
|
||||
if (!CFG.ENABLE_API) return void 0;
|
||||
if (req.method === "POST") {
|
||||
this.processApiCall(req, res, route);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
console.log(`Unknown request url: https://${req.headers.host}${req.url}`);
|
||||
console.log(`Unknown request url: https://${host}${req.url}`);
|
||||
break;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
export function parseProtobuf(buffer, path) {
|
||||
try {
|
||||
return POGOProtos.parseWithUnknown(buffer, path);
|
||||
} catch (e) {
|
||||
this.print(e, 31);
|
||||
/**
|
||||
* @param {Request} req
|
||||
* @param {Response} res
|
||||
* @param {Array} route
|
||||
*/
|
||||
export function processModelRequest(req, res, route) {
|
||||
|
||||
let player = this.world.getPlayerByRequest(req, res);
|
||||
|
||||
// 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) {
|
||||
print(`Error file resolving model ${name}:` + error, 31);
|
||||
return void 0;
|
||||
}
|
||||
print(`Sent ${name} to ${player.email}`, 36);
|
||||
res.end(data);
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {Request} req
|
||||
* @param {Response} res
|
||||
* @param {Array} route
|
||||
*/
|
||||
export function parseSignature(req) {
|
||||
let key = pcrypt.decrypt(req.unknown6.unknown2.encrypted_signature);
|
||||
return (
|
||||
POGOProtos.parseWithUnknown(key, "POGOProtos.Networking.Envelopes.Signature")
|
||||
);
|
||||
export function processRpcRequest(req, res, route) {
|
||||
let player = this.world.getPlayerByRequest(req, res);
|
||||
if (route[2] === "rpc") {
|
||||
player.refreshSocket(req, res);
|
||||
this.onRequest(player);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {Request} req
|
||||
* @param {Player} player
|
||||
*/
|
||||
export function onRequest(req) {
|
||||
export function onRequest(player) {
|
||||
|
||||
let player = this.getPlayerByRequest(req);
|
||||
|
||||
// Validate email verification
|
||||
if (player.authenticated) {
|
||||
if (!player.email_verified) {
|
||||
this.print(`${player.email}'s email isnt verified, kicking..`, 31);
|
||||
this.removePlayer(player);
|
||||
return void 0;
|
||||
}
|
||||
}
|
||||
|
||||
let request = this.parseProtobuf(req.body, "POGOProtos.Networking.Envelopes.RequestEnvelope");
|
||||
|
||||
request.requests = request.requests || [];
|
||||
let request = player.request;
|
||||
request.requests = request.requests || [];
|
||||
|
||||
if (CFG.DEBUG_LOG_REQUESTS) {
|
||||
console.log("#####");
|
||||
print("#####");
|
||||
request.requests.map((request) => {
|
||||
console.log("Got request:", request.request_type);
|
||||
print(request.request_type, 35);
|
||||
}).join(",");
|
||||
}
|
||||
|
||||
if (!player.authenticated) {
|
||||
player.sendResponse(this.authenticatePlayer(player));
|
||||
this.authenticatePlayer(player);
|
||||
return void 0;
|
||||
}
|
||||
|
||||
if (player.hasSignature === false) {
|
||||
player.getDevicePlatform();
|
||||
}
|
||||
|
||||
if (!request.requests.length) {
|
||||
// send shop data
|
||||
if (request.unknown6 && request.unknown6.request_type === 6) {
|
||||
let msg = this.envelopResponse(1, [], request, !!request.auth_ticket, true);
|
||||
player.sendResponse(msg);
|
||||
}
|
||||
// otherwise invalid
|
||||
else {
|
||||
this.print("Received invalid request!", 31);
|
||||
return void 0;
|
||||
}
|
||||
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, false);
|
||||
let msg = this.envelopResponse(returns, request, player);
|
||||
player.sendResponse(msg);
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {Number} status
|
||||
* @param {Player} player
|
||||
*/
|
||||
export function authenticatePlayer(player) {
|
||||
|
||||
let request = player.request;
|
||||
let token = request.auth_info;
|
||||
let msg = player.GetAuthTicket(request.request_id);
|
||||
|
||||
if (!token || !token.provider) {
|
||||
print("Invalid authentication token! Kicking..", 31);
|
||||
player.world.removePlayer(player);
|
||||
return void 0;
|
||||
}
|
||||
|
||||
if (token.provider === "google") {
|
||||
if (token.token !== null) {
|
||||
let decoded = jwtDecode(token.token.contents);
|
||||
player.email = decoded.email;
|
||||
player.email_verified = decoded.email_verified;
|
||||
player.isGoogleAccount = true;
|
||||
print(`${player.email} connected!`, 36);
|
||||
}
|
||||
else {
|
||||
print("Invalid authentication token! Kicking..", 31);
|
||||
player.world.removePlayer(player);
|
||||
return void 0;
|
||||
}
|
||||
}
|
||||
else {
|
||||
print("Invalid provider! Kicking..", 31);
|
||||
player.world.removePlayer(player);
|
||||
return void 0;
|
||||
}
|
||||
|
||||
player.authenticated = true;
|
||||
player.sendResponse(msg);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {Array} returns
|
||||
* @param {Request} req
|
||||
* @param {Request} request
|
||||
* @param {Player} player
|
||||
* @param {Boolean} auth
|
||||
* @param {Boolean} shop
|
||||
* @return {Buffer}
|
||||
*/
|
||||
export function envelopResponse(status, returns, req, player, auth, shop) {
|
||||
export function envelopResponse(returns, request, player) {
|
||||
|
||||
let buffer = req;
|
||||
let buffer = request;
|
||||
|
||||
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 (request.auth_ticket) {
|
||||
print("Authenticate!", 31);
|
||||
buffer.auth_ticket = AuthTicket();
|
||||
}
|
||||
|
||||
if (auth) buffer.auth_ticket = AuthTicket();
|
||||
if (shop) buffer.unknown6 = [ShopData()];
|
||||
|
||||
if (buffer.unknown6 && !shop) {
|
||||
if (buffer.unknown6) {
|
||||
buffer.unknown6 = [{
|
||||
"response_type": 6,
|
||||
"unknown2": {
|
||||
@@ -176,7 +185,7 @@ export function envelopResponse(status, returns, req, player, auth, shop) {
|
||||
}];
|
||||
}
|
||||
|
||||
buffer.status_code = status;
|
||||
buffer.status_code = 1;
|
||||
|
||||
return (
|
||||
POGOProtos.serialize(buffer, "POGOProtos.Networking.Envelopes.ResponseEnvelope")
|
||||
@@ -197,7 +206,7 @@ export function processRequests(player, requests) {
|
||||
let length = requests.length;
|
||||
let body = [];
|
||||
|
||||
let loop = (index) => {
|
||||
const loop = (index) => {
|
||||
this.processResponse(player, requests[index]).then((request) => {
|
||||
body.push(request);
|
||||
if (++index >= length) resolve(body);
|
||||
@@ -209,12 +218,4 @@ export function processRequests(player, requests) {
|
||||
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {Request} req
|
||||
* @return {Boolean}
|
||||
*/
|
||||
export function validRequest(req) {
|
||||
return (true);
|
||||
}
|
||||
273
src/response.js
273
src/response.js
@@ -1,40 +1,29 @@
|
||||
import proto from "./proto";
|
||||
import POGOProtos from "pokemongo-protobuf";
|
||||
|
||||
import print from "./print";
|
||||
import CFG from "../cfg";
|
||||
|
||||
import {
|
||||
GetInventory,
|
||||
GetHatchedEggs,
|
||||
CheckAwardedBadges,
|
||||
DownloadSettings,
|
||||
DownloadRemoteConfigVersion,
|
||||
GetPlayerProfile,
|
||||
ItemTemplates,
|
||||
GetPlayer,
|
||||
GetAssetDigest,
|
||||
GetDownloadUrls,
|
||||
GetMapObjects,
|
||||
SfidaActionLog,
|
||||
FortDetails,
|
||||
FortSearch,
|
||||
SetContactSettings,
|
||||
SetAvatar,
|
||||
MarkTutorialComplete,
|
||||
LevelUpRewards,
|
||||
Encounter,
|
||||
CatchPokemon,
|
||||
NicknamePokemon,
|
||||
UpgradePokemon,
|
||||
EvolvePokemon,
|
||||
SetFavoritePokemon,
|
||||
ClaimCodeName,
|
||||
CheckChallenge
|
||||
} from "./packets";
|
||||
_toCC,
|
||||
validUsername
|
||||
} from "./utils";
|
||||
|
||||
import { _toCC } from "./utils";
|
||||
|
||||
const REQUEST = proto.Networking.Requests.RequestType;
|
||||
/**
|
||||
* @param {Request} req
|
||||
* @param {String} type
|
||||
* @return {Buffer}
|
||||
*/
|
||||
export function parseMessage(req, type) {
|
||||
let proto = `POGOProtos.Networking.Requests.Messages.${type}Message`;
|
||||
if (req.request_message) {
|
||||
try {
|
||||
return (this.parseProtobuf(req.request_message, proto));
|
||||
} catch (e) {
|
||||
print(`Failed to parse ${type}: ${e}`, 31);
|
||||
}
|
||||
}
|
||||
return void 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {Player} player
|
||||
@@ -43,230 +32,48 @@ const REQUEST = proto.Networking.Requests.RequestType;
|
||||
*/
|
||||
export function processResponse(player, req) {
|
||||
|
||||
let buffer = null;
|
||||
|
||||
let cc = _toCC(req.request_type);
|
||||
let msg = null;
|
||||
let proto = `POGOProtos.Networking.Requests.Messages.${cc}Message`;
|
||||
|
||||
if (req.request_message) {
|
||||
try {
|
||||
msg = this.parseProtobuf(req.request_message, proto);
|
||||
} catch (e) {
|
||||
this.print(`Failed to parse ${cc}: ${e}`, 31);
|
||||
}
|
||||
}
|
||||
let msg = this.parseMessage(req, cc) || {};
|
||||
|
||||
return new Promise((resolve) => {
|
||||
|
||||
try {
|
||||
switch (req.request_type) {
|
||||
// Player
|
||||
case "GET_PLAYER":
|
||||
player.authentications++;
|
||||
if (player.authentications >= 2) {
|
||||
buffer = GetPlayer(player);
|
||||
resolve(buffer);
|
||||
return void 0;
|
||||
}
|
||||
this.forwardPlayer(player).then((res) => resolve(res));
|
||||
return void 0;
|
||||
break;
|
||||
case "CHECK_CHALLENGE":
|
||||
buffer = CheckChallenge();
|
||||
break;
|
||||
case "GET_HATCHED_EGGS":
|
||||
buffer = GetHatchedEggs();
|
||||
break;
|
||||
case "GET_INVENTORY":
|
||||
buffer = GetInventory(player);
|
||||
break;
|
||||
case "CHECK_AWARDED_BADGES":
|
||||
buffer = CheckAwardedBadges();
|
||||
break;
|
||||
case "DOWNLOAD_SETTINGS":
|
||||
buffer = DownloadSettings();
|
||||
break;
|
||||
case "DOWNLOAD_ITEM_TEMPLATES":
|
||||
buffer = ItemTemplates(this.master);
|
||||
break;
|
||||
case "DOWNLOAD_REMOTE_CONFIG_VERSION":
|
||||
buffer = DownloadRemoteConfigVersion(msg);
|
||||
break;
|
||||
case "GET_ASSET_DIGEST":
|
||||
buffer = GetAssetDigest(player);
|
||||
break;
|
||||
case "GET_PLAYER_PROFILE":
|
||||
buffer = GetPlayerProfile();
|
||||
break;
|
||||
case "GET_MAP_OBJECTS":
|
||||
player.updatePosition(msg);
|
||||
buffer = GetMapObjects(player, this.wild_pokemons, msg);
|
||||
this.savePlayer(player).then(() => {
|
||||
resolve(buffer);
|
||||
case "GET_HATCHED_EGGS":
|
||||
case "CHECK_AWARDED_BADGES":
|
||||
player.getPacket(req.request_type, msg).then((result) => {
|
||||
print(`Success: ${req.request_type} => ${result.toString().length}`);
|
||||
resolve(result);
|
||||
});
|
||||
return void 0;
|
||||
break;
|
||||
case "GET_DOWNLOAD_URLS":
|
||||
GetDownloadUrls(player.asset_digest.decode, CFG.LOCAL_IP || this.getLocalIPv4(), msg).then((res) => {
|
||||
resolve(res);
|
||||
});
|
||||
return void 0;
|
||||
break;
|
||||
case "SET_AVATAR":
|
||||
player.updateAvatar(msg);
|
||||
this.emit("updatePlayerAvatar", player);
|
||||
buffer = SetAvatar(player);
|
||||
this.savePlayer(player).then(() => {
|
||||
resolve(buffer);
|
||||
});
|
||||
return void 0;
|
||||
break;
|
||||
case "SFIDA_ACTION_LOG":
|
||||
buffer = SfidaActionLog();
|
||||
break;
|
||||
case "MARK_TUTORIAL_COMPLETE":
|
||||
buffer = MarkTutorialComplete(player, msg);
|
||||
this.savePlayer(player).then(() => {
|
||||
resolve(buffer);
|
||||
});
|
||||
return void 0;
|
||||
break;
|
||||
case "ENCOUNTER_TUTORIAL_COMPLETE":
|
||||
let starters = ["BULBASAUR", "CHARMANDER", "SQUIRTLE"];
|
||||
// Make sure the catched pokemon is valid
|
||||
if (starters.indexOf(msg.pokemon_id) === -1) {
|
||||
if (player.tutorial_state.indexOf("POKEMON_CAPTURE") === -1) {
|
||||
player.tutorial_state.push("POKEMON_CAPTURE");
|
||||
}
|
||||
let pkmn = {
|
||||
pokemon_id: msg.pokemon_id,
|
||||
cp: 15,
|
||||
stamina: 10,
|
||||
stamina_max: 10,
|
||||
move_1: "TACKLE",
|
||||
move_2: "TACKLE",
|
||||
height_m: 0.20962005257606506,
|
||||
weight_kg: 0.3212273120880127,
|
||||
individual_attack: 7,
|
||||
individual_defense: 7,
|
||||
individual_stamina: 3,
|
||||
cp_multiplier: 0.16639786958694458
|
||||
};
|
||||
player.party.push(pkmn);
|
||||
buffer = POGOProtos.serialize(buffer, "POGOProtos.Networking.Responses.EncounterTutorialCompleteResponse");
|
||||
}
|
||||
break;
|
||||
case "CLAIM_CODENAME":
|
||||
buffer = ClaimCodeName(msg, player);
|
||||
this.savePlayer(player).then(() => {
|
||||
resolve(buffer);
|
||||
});
|
||||
return void 0;
|
||||
break;
|
||||
case "LEVEL_UP_REWARDS":
|
||||
buffer = LevelUpRewards();
|
||||
break;
|
||||
case "FORT_DETAILS":
|
||||
buffer = FortDetails(msg);
|
||||
break;
|
||||
// Global
|
||||
case "FORT_SEARCH":
|
||||
buffer = FortSearch(player);
|
||||
this.updateUserItems(player).then(() => {
|
||||
resolve(buffer);
|
||||
});
|
||||
return void 0;
|
||||
break;
|
||||
case "SET_CONTACT_SETTINGS":
|
||||
player.updateContactSettings(msg);
|
||||
buffer = SetContactSettings(player);
|
||||
this.savePlayer(player).then(() => {
|
||||
resolve(buffer);
|
||||
});
|
||||
return void 0;
|
||||
break;
|
||||
case "ENCOUNTER":
|
||||
buffer = Encounter(this.getEncounterPkmn(msg).pkmn, msg);
|
||||
break;
|
||||
case "CATCH_POKEMON":
|
||||
let encounter = this.getEncounterPkmn(msg);
|
||||
let result = CatchPokemon(encounter.pkmn, player, msg);
|
||||
// save pkmn into player party
|
||||
if (result.status !== "CATCH_MISSED") {
|
||||
result.pkmn.owner_id = player.owner_id;
|
||||
player.exp += 100;
|
||||
player.stardust += 100;
|
||||
this.wild_pokemons.splice(encounter.index, 1);
|
||||
this.createOwnedPokemon(result.pkmn).then(() => {
|
||||
// make sure it got saved, also get db id
|
||||
this.getQueryByColumnFromTable("creation_time_ms", result.pkmn.creation_time_ms, CFG.MYSQL_OWNED_PKMN_TABLE).then((query) => {
|
||||
player.party.push(query[0]);
|
||||
result.buffer.captured_pokemon_id = query[0].id;
|
||||
result = POGOProtos.serialize(result.buffer, "POGOProtos.Networking.Responses.CatchPokemonResponse");
|
||||
resolve(result);
|
||||
});
|
||||
});
|
||||
}
|
||||
else {
|
||||
resolve(POGOProtos.serialize(result, "POGOProtos.Networking.Responses.CatchPokemonResponse"));
|
||||
}
|
||||
return void 0;
|
||||
break;
|
||||
case "NICKNAME_POKEMON":
|
||||
buffer = NicknamePokemon(msg);
|
||||
break;
|
||||
case "UPGRADE_POKEMON":
|
||||
buffer = UpgradePokemon(msg);
|
||||
break;
|
||||
case "EVOLVE_POKEMON":
|
||||
buffer = EvolvePokemon(msg);
|
||||
break;
|
||||
case "SET_FAVORITE_POKEMON":
|
||||
buffer = SetFavoritePokemon(player, msg);
|
||||
break;
|
||||
case "RELEASE_POKEMON":
|
||||
buffer = {
|
||||
result: "SUCCESS",
|
||||
candy_awarded: 5
|
||||
};
|
||||
let id = msg.pokemon_id << 0;
|
||||
this.deleteOwnedPokemon(id).then(() => {
|
||||
player.deletePkmnFromParty(id);
|
||||
buffer = POGOProtos.serialize(buffer, "POGOProtos.Networking.Responses.ReleasePokemonResponse");
|
||||
resolve(buffer);
|
||||
case "FORT_DETAILS":
|
||||
case "GET_MAP_OBJECTS":
|
||||
case "CHECK_CHALLENGE":
|
||||
case "DOWNLOAD_SETTINGS":
|
||||
case "DOWNLOAD_REMOTE_CONFIG_VERSION":
|
||||
case "DOWNLOAD_ITEM_TEMPLATES":
|
||||
msg.player = player;
|
||||
player.world.getPacket(req.request_type, msg).then((result) => {
|
||||
print(`Success: ${req.request_type} => ${result.toString().length}`);
|
||||
resolve(result);
|
||||
});
|
||||
return void 0;
|
||||
break;
|
||||
default:
|
||||
this.print(`Unknown request: ${req.request_type}`, 31);
|
||||
print(`Unknown request: ${req.request_type}`, 31);
|
||||
break;
|
||||
};
|
||||
} catch (e) {
|
||||
this.print(`Response error: ${e}`, 31);
|
||||
print(`Response error: ${e}`, 31);
|
||||
};
|
||||
|
||||
resolve(buffer);
|
||||
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
export function getEncounterPkmn(req) {
|
||||
|
||||
let ii = 0;
|
||||
let length = this.wild_pokemons.length;
|
||||
|
||||
let pkmn = null;
|
||||
|
||||
for (; ii < length; ++ii) {
|
||||
pkmn = this.wild_pokemons[ii];
|
||||
if (pkmn.encounter_id === parseInt(req.encounter_id)) {
|
||||
break;
|
||||
}
|
||||
};
|
||||
|
||||
return ({
|
||||
pkmn: pkmn,
|
||||
index: ii
|
||||
});
|
||||
|
||||
}
|
||||
47
src/setup.js
47
src/setup.js
@@ -1,11 +1,15 @@
|
||||
import fs from "fs";
|
||||
import fse from "fs-extra";
|
||||
import pogo from "pogo-asset-downloader";
|
||||
import proto from "./proto";
|
||||
import POGOProtos from "pokemongo-protobuf";
|
||||
|
||||
import print from "./print";
|
||||
import CFG from "../cfg";
|
||||
|
||||
import * as shared from "./shared";
|
||||
|
||||
import GameMaster from "./models/GameMaster";
|
||||
|
||||
import {
|
||||
capitalize,
|
||||
idToPkmnBundleName
|
||||
@@ -13,12 +17,14 @@ import {
|
||||
|
||||
export function setup() {
|
||||
|
||||
let isFirstRun = !this.directoryExists(CFG.DUMP_ASSET_PATH);
|
||||
let save = JSON.parse(fs.readFileSync(".save", "utf8"));
|
||||
|
||||
if (isFirstRun) {
|
||||
this.print("Required assets are missing! Preparing dump session..", 31);
|
||||
if (save.isFirstRun) {
|
||||
print("Required assets are missing! Preparing dump session..", 33);
|
||||
setTimeout(() => {
|
||||
this.onFirstRun(() => {
|
||||
save.isFirstRun = false;
|
||||
fs.writeFileSync(".save", JSON.stringify(save), "utf8");
|
||||
this.setup();
|
||||
});
|
||||
}, 1e3);
|
||||
@@ -28,26 +34,25 @@ export function setup() {
|
||||
// make sure all assets got loaded properly
|
||||
this.validateAssets().then(() => {
|
||||
|
||||
this.print(`Downloaded assets are valid! Proceeding..`);
|
||||
print(`Downloaded assets are valid! Proceeding..`);
|
||||
|
||||
this.master = POGOProtos.serialize(this.parseGameMaster(), "POGOProtos.Networking.Responses.DownloadItemTemplatesResponse");
|
||||
let parsedMaster = this.parseGameMaster();
|
||||
shared.GAME_MASTER = new GameMaster(parsedMaster);
|
||||
|
||||
this.setupDatabaseConnection().then(() => {
|
||||
if (CFG.PORT < 1) {
|
||||
this.print("Invalid port!", 31);
|
||||
print("Invalid port!", 31);
|
||||
return void 0;
|
||||
}
|
||||
this.socket = this.createHTTPServer();
|
||||
setTimeout(this::this.cycle, 1);
|
||||
let localIPv4 = this.getLocalIPv4();
|
||||
this.print(`Server running at ${localIPv4}:${CFG.PORT}`);
|
||||
this.emit("ready", void 0);
|
||||
print(`Server listening at ${localIPv4}:${CFG.PORT}`, 33);
|
||||
});
|
||||
|
||||
}).catch((e) => {
|
||||
//fse.removeSync(CFG.DUMP_ASSET_PATH);
|
||||
this.print("Error: " + e + " was not found!", 31);
|
||||
this.emit("ready", e);
|
||||
print("Error: " + e + " was not found!", 31);
|
||||
});
|
||||
|
||||
}
|
||||
@@ -92,10 +97,10 @@ export function validateModels() {
|
||||
}
|
||||
else {
|
||||
let buffer = fs.readFileSync(path + "asset_digest");
|
||||
this.assets[name] = {
|
||||
shared.GAME_ASSETS[name] = {
|
||||
buffer: buffer,
|
||||
decode: this.parseProtobuf(buffer, "POGOProtos.Networking.Responses.GetAssetDigestResponse")
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
// validate models inside folder
|
||||
@@ -125,7 +130,7 @@ export function parseGameMaster() {
|
||||
let data = fs.readFileSync(CFG.DUMP_ASSET_PATH + "game_master");
|
||||
master = this.parseProtobuf(data, "POGOProtos.Networking.Responses.DownloadItemTemplatesResponse");
|
||||
} catch (e) {
|
||||
this.print(e, 31);
|
||||
print(e, 31);
|
||||
}
|
||||
return (master);
|
||||
}
|
||||
@@ -141,7 +146,7 @@ export function onFirstRun(resolve) {
|
||||
this.downloadAssets().then(resolve);
|
||||
});
|
||||
}).catch((e) => {
|
||||
this.print(e, 31);
|
||||
print(e, 31);
|
||||
});
|
||||
}
|
||||
|
||||
@@ -183,11 +188,11 @@ export function downloadModels() {
|
||||
let caps = capitalize(name);
|
||||
caps = name === "ios" ? "iOS" : caps;
|
||||
pogo.setPlatform(name);
|
||||
this.print(`Preparing to dump ${caps} assets..`, 36);
|
||||
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!`);
|
||||
print(`Dumped ${CFG.MAX_POKEMON_NATIONAL_ID} ${caps} assets successfully!`);
|
||||
if (++index >= limit) {
|
||||
this.print("Dumped all assets successfully!");
|
||||
print("Dumped all assets successfully!");
|
||||
resolve();
|
||||
return void 0;
|
||||
}
|
||||
@@ -210,16 +215,16 @@ export function dumpPkmnModels(path, resolve) {
|
||||
if (++index <= limit) ids.push(index);
|
||||
pogo.getAssetByPokemonId(ids).then((downloads) => {
|
||||
downloads.map((item) => {
|
||||
this.print(`Dumping model ${item.name}..`, 35);
|
||||
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);
|
||||
print(`Error while dumping model ${item.name}:` + e, 31);
|
||||
}
|
||||
});
|
||||
if (index >= limit) {
|
||||
//this.print(`Dumped ${limit} assets successfully!`);
|
||||
//print(`Dumped ${limit} assets successfully!`);
|
||||
resolve();
|
||||
return void 0;
|
||||
}
|
||||
|
||||
6
src/shared.js
Normal file
6
src/shared.js
Normal file
@@ -0,0 +1,6 @@
|
||||
/**
|
||||
* Global shared assets
|
||||
*/
|
||||
|
||||
export let GAME_ASSETS = {};
|
||||
export let GAME_MASTER = null;
|
||||
42
src/utils.js
42
src/utils.js
@@ -1,5 +1,5 @@
|
||||
import Long from "long";
|
||||
import proto from "./proto";
|
||||
import POGOProtos from "pokemongo-protobuf";
|
||||
import pcrypt from "pcrypt";
|
||||
|
||||
import CFG from "../cfg";
|
||||
|
||||
@@ -20,15 +20,6 @@ export function inherit(cls, prot) {
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {Buffer} body
|
||||
*/
|
||||
export function decodeRequestEnvelope(body) {
|
||||
return (
|
||||
proto.Networking.Envelopes.RequestEnvelope.decode(body)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* http://stackoverflow.com/a/7616484/3367904
|
||||
* @param {String} str
|
||||
@@ -45,18 +36,6 @@ export function getHashCodeFrom(str) {
|
||||
return hash;
|
||||
};
|
||||
|
||||
/**
|
||||
* @param {Long} long
|
||||
* @return {Number}
|
||||
*/
|
||||
export function decodeLong(long) {
|
||||
|
||||
let value = Long.fromBits(long.high, long.low, !!long.unsigned);
|
||||
|
||||
return (parseInt(value.toString()));
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @return {Number}
|
||||
*/
|
||||
@@ -96,4 +75,21 @@ 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))
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {Request} req
|
||||
*/
|
||||
export function parseSignature(req) {
|
||||
let key = pcrypt.decrypt(req.unknown6[0].unknown2.encrypted_signature);
|
||||
return (
|
||||
POGOProtos.parseWithUnknown(key, "POGOProtos.Networking.Envelopes.Signature")
|
||||
);
|
||||
}
|
||||
84
update.js
84
update.js
@@ -1,84 +0,0 @@
|
||||
"use strict";
|
||||
|
||||
var fs = require("fs");
|
||||
var fse = require("fs-extra");
|
||||
var git = require("nodegit");
|
||||
var dirTree = require("directory-tree");
|
||||
|
||||
let tmpDir = "./tmp";
|
||||
let cloneDir = JSON.parse(fs.readFileSync("./package.json")).repository.url;
|
||||
|
||||
let ignore = [".git", "cfg.js", "updater.js"];
|
||||
|
||||
function skip() {
|
||||
return new Promise((resolve) => {
|
||||
fse.removeSync(tmpDir);
|
||||
console.log(`Skipped update to version ${newVersion}`);
|
||||
resolve();
|
||||
});
|
||||
}
|
||||
|
||||
function updateProject() {
|
||||
return new Promise((resolve) => {
|
||||
let newFiles = dirTree("./tmp");
|
||||
recurse(newFiles.children);
|
||||
resolve();
|
||||
});
|
||||
}
|
||||
|
||||
function recurse(parent) {
|
||||
for (let key in parent) {
|
||||
let name = parent[key].name;
|
||||
if (ignore.indexOf(name) > -1) continue;
|
||||
let isDir = parent[key].hasOwnProperty("children");
|
||||
try {
|
||||
if (!isDir) {
|
||||
fse.outputFileSync(parent[key].path.substring(4), fs.readFileSync(parent[key].path));
|
||||
}
|
||||
else {
|
||||
recurse(parent[key].children);
|
||||
}
|
||||
} catch (e) { console.log(e); }
|
||||
};
|
||||
}
|
||||
|
||||
(function() {
|
||||
return new Promise((resolve) => {
|
||||
console.log("Preparing to update..");
|
||||
setTimeout(() => {
|
||||
fse.removeSync(tmpDir);
|
||||
let currentVersion = JSON.parse(fs.readFileSync("./package.json")).version;
|
||||
console.log(`Your current version is ${currentVersion}!`);
|
||||
setTimeout(() => {
|
||||
console.log("Fetching latest version..");
|
||||
git.Clone(cloneDir, tmpDir).then((res, rofl) => {
|
||||
let newVersion = null;
|
||||
try {
|
||||
newVersion = JSON.parse(fs.readFileSync(`${tmpDir}/package.json`)).version;
|
||||
} catch (e) {
|
||||
console.log("Version check failed!");
|
||||
return resolve();
|
||||
}
|
||||
if (currentVersion === newVersion) {
|
||||
console.log(`You are already running the latest version ${currentVersion}!`);
|
||||
skip().then(resolve);
|
||||
return void 0;
|
||||
}
|
||||
else if (currentVersion > newVersion) {
|
||||
console.log(`Your version ${currentVersion} is newer than ${newVersion}!`);
|
||||
skip().then(resolve);
|
||||
return void 0;
|
||||
}
|
||||
console.log(`Latest version is ${newVersion}`);
|
||||
console.log(`Updating to version ${newVersion}`);
|
||||
updateProject().then(() => {
|
||||
fse.removeSync(tmpDir);
|
||||
console.log("Update successfully completed, please restart!");
|
||||
resolve();
|
||||
});
|
||||
});
|
||||
}, 2e3);
|
||||
|
||||
}, 1e3);
|
||||
});
|
||||
})();
|
||||
Reference in New Issue
Block a user