- Basic upgrade pkmn
- Basic pokedex
- Player consumes fort rewards
- Only refresh player position on GET_MAP_OBJECTS req
- Fixed pkmn inventory related bugs
- Updated to v 0.5.8
This commit is contained in:
Felix 2016-09-12 15:34:47 +02:00
parent 683e36154f
commit 6a983bc8be
21 changed files with 251 additions and 66 deletions

View File

@ -8,8 +8,11 @@ export default {
// show greeting
GREET: true,
// allow api calls
ENABLE_API: true,
// Api things
API_ENABLE: true,
API_USERNAME: "root",
API_PASSWORD: "",
// Server settings
MAX_CONNECTIONS: 64,
@ -24,6 +27,7 @@ export default {
// Timeouts
BOOT_TIMEOUT: 1e4,
PLAYER_CONNECTION_TIMEOUT: 1e3 * 60 * 30,
CELL_TIMEOUT: 1e3 * 60,
MINIMUM_CLIENT_VERSION: "0.35.0",
DEFAULT_CONSOLE_COLOR: 32,
TRANSFER_ACCOUNTS: false,

View File

@ -1,6 +1,6 @@
{
"name": "POGOServer",
"version": "0.5.6",
"version": "0.5.8",
"description": "",
"repository": {
"type": "git",

View File

@ -6,7 +6,7 @@ import CFG from "../../cfg";
export function createTableIfNotExists(name) {
return new Promise((resolve) => {
this.db.query(`SHOW TABLES LIKE '${name}';`, (e, rows, fields) => {
if (e) console.log(e);
if (e) print(e, 31);
else {
// exists
if (rows && rows.length) resolve();
@ -48,7 +48,7 @@ export function createTable(name) {
return new Promise((resolve) => {
this.db.query(query, (e, rows) => {
if (e) console.log(e);
if (e) print(e, 31);
else resolve();
});
});

View File

@ -1,3 +1,4 @@
import print from "../print";
import CFG from "../../cfg";
/**
@ -8,7 +9,7 @@ import CFG from "../../cfg";
export function getQueryByColumnFromTable(column, value, table) {
return new Promise((resolve) => {
this.db.query(`SELECT * FROM ${table} WHERE ${column}=?`, [value], (e, rows) => {
if (e) console.log(e);
if (e) print(e, 31);
if (rows && rows.length) resolve(rows);
else resolve(void 0);
});
@ -23,7 +24,7 @@ export function getQueryByColumnFromTable(column, value, table) {
export function deleteQueryByColumnFromTable(column, value, table) {
return new Promise((resolve) => {
this.db.query(`DELETE FROM ${table} WHERE ${column}=?`, [value], (e, rows) => {
if (e) console.log(e);
if (e) print(e, 31);
else resolve(void 0);
});
});

View File

@ -28,6 +28,7 @@ export default class Party {
this.player.world.db.query(query, [this.player.uid], (e, rows) => {
if (e) return print(e, 31);
rows.map((row) => {
row.isOwned = true;
this.addPkmn(row);
});
resolve();
@ -40,7 +41,7 @@ export default class Party {
* @return {Pokemon}
*/
addPkmn(obj) {
if (!obj.owner) obj.owner = this.player;
obj.owner = this.player;
let pkmn = new Pokemon(obj);
this.party.push(pkmn);
return (pkmn);

View File

@ -0,0 +1,67 @@
import { GAME_MASTER } from "../../../shared";
import ENUM from "../../../enum";
/**
* @class PokeDex
*/
export default class PokeDex {
/**
* @param {Player} player
* @constructor
*/
constructor(player) {
this.player = player;
this.pkmns = {};
}
/**
* @param {Number} dex
*/
addEntry(dex) {
}
/**
* @param {Number} dex
*/
removeEntry(dex) {
}
/**
* @return {Array}
*/
serialize() {
let out = [];
for (let key in this.pkmns) {
let pkmn = this.pkmns[key];
out.push({
modified_timestamp_ms: +new Date() - 1e3,
inventory_item_data: {
pokedex_entry: {
pokemon_id: key,
times_encountered: 1,
times_captured: 1
}
}
});
};
return (out);
}
/**
* @param {String} str
*/
parseJSON(str) {
let pkmns = JSON.parse(str);
for (let pkmn in pkmns) {
this.addEntry(pkmn);
};
}
}

View File

@ -4,8 +4,9 @@ import Bag from "./Bag";
import Info from "./Info";
import Party from "./Party";
import Avatar from "./Avatar";
import CandyBag from "./CandyBag";
import Pokedex from "./Pokedex";
import Contact from "./Contact";
import CandyBag from "./CandyBag";
import Tutorial from "./Tutorial";
import Currency from "./Currency";
@ -21,6 +22,8 @@ import {
parseSignature
} from "../../utils";
import ENUM from "../../enum";
import { GAME_MASTER } from "../../shared";
/**
@ -64,17 +67,16 @@ export default class Player extends MapObject {
this.currentEncounter = null;
this.bag = new Bag(this);
this.candyBag = new CandyBag(this);
this.info = new Info(this);
this.party = new Party(this);
this.avatar = new Avatar(this);
this.pokeDex = new Pokedex(this);
this.contact = new Contact(this);
this.candyBag = new CandyBag(this);
this.tutorial = new Tutorial(this);
this.currency = new Currency(this);
/*
this.pokedex = new Pokedex(this);
*/
this.refreshSocket(obj.request, obj.response);
}
@ -94,6 +96,19 @@ export default class Player extends MapObject {
this.response.end(buffer);
}
/**
* @param {Request} req
* @param {String} type
* @return {Boolean}
*/
requestContains(req, type) {
let requests = req.requests;
for (let request of requests) {
if (request.request_type === type) return (true);
};
return (false);
}
/**
* @param {Request} req
* @param {Response} res
@ -105,6 +120,20 @@ export default class Player extends MapObject {
this.refreshPosition();
}
refreshPosition() {
let req = this.request;
if (
req.latitude !== void 0 &&
req.longitude !== void 0
) {
this.latitude = req.latitude;
this.longitude = req.longitude;
}
if (this.requestContains(req, "GET_MAP_OBJECTS")) {
this.world.triggerSpawnAt(this.latitude, this.longitude);
}
}
getDevicePlatform() {
let request = this.request;
if (request.unknown6 && request.unknown6[0]) {
@ -137,6 +166,9 @@ export default class Player extends MapObject {
resolve(result);
});
break;
case "UPGRADE_POKEMON":
resolve(this.UpgradePokemon(msg));
break;
case "GET_PLAYER_PROFILE":
resolve(this.GetPlayerProfile(msg));
break;
@ -254,16 +286,17 @@ export default class Player extends MapObject {
});
}
refreshPosition() {
let req = this.request;
if (
req.latitude !== void 0 &&
req.longitude !== void 0
) {
this.latitude = req.latitude;
this.longitude = req.longitude;
}
this.world.triggerSpawnAt(this.latitude, this.longitude);
/**
* @param {Fort} fort
*/
consumeFortRewards(fort) {
let rewards = fort.rewards;
for (let key in rewards) {
let name = ENUM.getNameById(ENUM.ITEMS, key << 0).replace("ITEM_", "").toLowerCase();
if (this.bag.hasOwnProperty(name)) {
this.bag[name] += rewards[key] << 0;
}
};
}
/**
@ -279,10 +312,11 @@ export default class Player extends MapObject {
pkmn.pokeball = ball;
return new Promise((resolve) => {
pkmn.owner = this;
pkmn.calcStats();
pkmn.insertIntoDatabase().then((insertId) => {
let cp = pkmn.getSeenCp(this);
pkmn.isOwned = false;
pkmn = this.party.addPkmn(pkmn);
pkmn.owner = this;
pkmn.cp = cp;
pkmn.uid = insertId;
pkmn.addCandies(3);
print(`${this.username} caught a wild ${pkmn.getPkmnName()}!`);

View File

@ -0,0 +1,28 @@
import POGOProtos from "pokemongo-protobuf";
/**
* @param {Object} msg
* @return {Buffer}
*/
export default function UpgradePokemon(msg) {
let buffer = null;
let pkmn = this.party.getPkmnById(msg.pokemon_id);
if (pkmn) {
if (pkmn.powerUp()) {
buffer = { result: "SUCCESS" };
} else {
buffer = { result: "ERROR_INSUFFICIENT_RESOURCES" };
}
buffer.upgraded_pokemon = pkmn.serialize();
}
else {
buffer = { result: "ERROR_POKEMON_NOT_FOUND" };
}
return (
POGOProtos.serialize(buffer, "POGOProtos.Networking.Responses.UpgradePokemonResponse")
);
}

View File

@ -3,6 +3,7 @@ export GetPlayer from "./GetPlayer";
export GetInventory from "./GetInventory";
export GetAuthTicket from "./GetAuthTicket";
export ReleasePokemon from "./ReleasePokemon";
export UpgradePokemon from "./UpgradePokemon";
export LevelUpRewards from "./LevelUpRewards";
export GetHatchedEggs from "./GetHatchedEggs";
export GetAssetDigest from "./GetAssetDigest";

View File

@ -32,6 +32,9 @@ export default class WildPokemon extends Pokemon {
// players who already caught this pkmn
this.hasCatched = [];
// players who already have seen this pkmn (to store cp)
this.hasSeen = [];
}
/**
@ -54,6 +57,42 @@ export default class WildPokemon extends Pokemon {
);
}
/**
* @param {Player} player
* @return {Number}
*/
getSeenCp(player) {
for (let item of this.hasSeen) {
if (item.uid === player.uid) return (item.cp);
};
return (-1);
}
/**
* @param {Player} player
* @return {Boolean}
*/
seenBy(player) {
if (!this.alreadySeenBy(player)) {
this.calcStats(player);
this.hasSeen.push({
cp: this.cp,
uid: player.uid
});
}
}
/**
* @param {Player} player
* @return {Boolean}
*/
alreadySeenBy(player) {
for (let item of this.hasSeen) {
if (item.uid === player.uid) return (true);
};
return (false);
}
/**
* @return {Boolean}
*/
@ -91,7 +130,7 @@ export default class WildPokemon extends Pokemon {
spawn_point_id: this.spawnPointId,
pokemon_data: {
pokemon_id: this.getPkmnId(),
cp: 66,
cp: this.cp,
stamina: 10,
stamina_max: 10,
move_1: "BUG_BITE_FAST",

View File

@ -17,11 +17,11 @@ export function powerUp() {
let pkmnTmpl = this.getPkmnTemplate(this.dexNumber);
let ownerStardust = this.owner.info.stardust;
let ownerPkmnCandies = this.owner.candyBag.getCandy(this.dexNumber);
let requiredCandies = this.candiesToPowerUp();
print(`${this.getPkmnName()} requires ${requiredCandies} to power up!`);
let requiredCandies = 1;
print(`${this.getPkmnName()} requires ${requiredCandies} candies to power up!`);
if (ownerPkmnCandies >= requiredCandies) {
this.level += 1;
this.owner.candyBag.removeCandy(this.dexNumber, pkmnTmpl.candy_to_evolve);
this.owner.candyBag.removeCandy(this.dexNumber, requiredCandies);
return (true);
}
return (false);

View File

@ -1,6 +1,9 @@
import Settings from "../../modes";
export function calcStats() {
/**
* @param {Player} owner
*/
export function calcStats(owner) {
let pkmnTmpl = this.getPkmnTemplate(this.dexNumber);
let stats = pkmnTmpl.stats;
@ -20,7 +23,9 @@ export function calcStats() {
this.height = pkmnTmpl.pokedex_height_m + ((Math.random() * pkmnTmpl.height_std_dev) + .1);
this.weight = pkmnTmpl.pokedex_weight_kg + ((Math.random() * pkmnTmpl.weight_std_dev) + .1);
this.cp = Math.floor(Math.random() * this.calcCP()) + 16;
if (owner !== null) {
this.cp = Math.floor(Math.random() * this.calcCP(owner)) + 16;
}
this.calcMoves();
@ -39,11 +44,13 @@ export function calcMoves() {
}
/**
* @param {Player} owner
* @return {Number}
*/
export function calcCP() {
export function calcCP(owner) {
let ecpm = this.getCPMultipliers()[this.owner.info.level - 1];
let levelSettings = owner.info.getLevelSettings();
let ecpm = levelSettings.cp_multiplier[owner.info.level - 1];
let atk = (this.attack + this.ivAttack) * ecpm;
let def = (this.defense + this.ivDefense) * ecpm;
@ -55,15 +62,6 @@ export function calcCP() {
}
/**
* @return {Array}
*/
export function getCPMultipliers() {
return (
this.owner.info.getLevelSettings().cp_multiplier
);
}
/**
* @param {Number} lvl
* @return {Number}

View File

@ -66,6 +66,7 @@ export default class Pokemon extends MapObject {
this.pokeball = null;
this.isWild = false;
this.isOwned = false;
this.spawnPoint = null;
@ -78,7 +79,6 @@ export default class Pokemon extends MapObject {
}
set level(value) {
this._level = parseFloat(value);
this.calcStats();
}
/**
@ -102,10 +102,23 @@ export default class Pokemon extends MapObject {
else if (key === "move_2") {
this.move2 = obj[key];
}
else if (key === "height_m") {
this.height = obj[key];
}
else if (key === "weight_kg") {
this.weight = obj[key];
}
else if (key === "individual_attack") {
this.ivAttack = obj[key];
}
else if (key === "individual_defense") {
this.ivDefense = obj[key];
}
else if (key === "individual_stamina") {
this.ivStamina = obj[key];
}
};
if (!obj.isWild) {
this.calcStats();
}
if (!obj.isWild && !obj.isOwned) this.calcStats(this.owner);
}
/**
@ -189,13 +202,6 @@ export default class Pokemon extends MapObject {
return (pkmnTmpl.candy_to_evolve << 0);
}
/**
* @return {Number}
*/
candiesToPowerUp() {
return (1337);
}
/**
* @return {Boolean}
*/

View File

@ -192,7 +192,6 @@ export default class Cell extends MapObject {
* @return {Number}
*/
getFortIndexById(id) {
id = parseInt(id);
let index = 0;
for (let fort of this.forts) {
if (fort.uid === id) return (index);

View File

@ -5,8 +5,10 @@ import POGOProtos from "pokemongo-protobuf";
*/
export default function Encounter(msg) {
let player = msg.player;
// Try to use cached encounter
let encounter = msg.player.currentEncounter;
let encounter = player.currentEncounter;
// Dont use cached encounter
if (
@ -26,17 +28,19 @@ export default function Encounter(msg) {
// Invalid pkmn
if (!encounter) {
msg.player.currentEncounter = null;
player.currentEncounter = null;
buffer.status = "ENCOUNTER_NOT_FOUND";
}
// Already encountered
else if (encounter.alreadyCatchedBy(msg.player)) {
else if (encounter.alreadyCatchedBy(player)) {
buffer.status = "ENCOUNTER_ALREADY_HAPPENED";
}
// Encounter success
else {
msg.player.currentEncounter = encounter;
player.currentEncounter = encounter;
encounter.seenBy(player);
buffer.wild_pokemon = encounter.serializeWild();
buffer.wild_pokemon.pokemon_data.cp = encounter.getSeenCp(player);
}
return (

View File

@ -12,7 +12,6 @@ export default function FortDetails(msg) {
return new Promise((resolve) => {
this.getFortDataById(msg.fort_id).then((fort) => {
if (!fort) return void 0;
let ts = +new Date();
let url = fort.image_url;
let buffer = {
fort_id: msg.fort_id,

View File

@ -14,6 +14,8 @@ export default function FortSearch(msg) {
return new Promise((resolve) => {
this.getFortDataById(msg.fort_id).then((fort) => {
if (!fort) return void 0;
player.consumeFortRewards(fort);
// TODO: disable rewarding when on cooldown
let buffer = ({
result: "SUCCESS",
items_awarded: fort.serializeRewards(),

View File

@ -122,5 +122,5 @@ export function addPlayer(req, res) {
* @param {Player} player
*/
export function removePlayer(player) {
console.log("Remove:", player.email);
print(`Removed ${player.email}`, 36);
}

View File

@ -61,8 +61,8 @@ export function stdinInput(data) {
this.processCommand(cmds[0], cmds.splice(0, 1));
};
export function uncaughtException(excp) {
switch (excp.errno) {
export function uncaughtException(e) {
switch (e.errno) {
case "EADDRINUSE":
print(`Port ${CFG.PORT} is already in use!`, 31);
break;
@ -70,8 +70,9 @@ export function uncaughtException(excp) {
print("No root privileges!", 31);
break;
default:
console.log("Unhandled exception occurred: ", excp.code);
console.log(excp.stack);
print("Unhandled exception occurred: ", 31);
print(e, 31);
print(e.stack, 31);
break;
};
print("The server has crashed!", 31);

View File

@ -40,7 +40,7 @@ export function routeRequest(req, res) {
}
break;
default:
console.log(`Unknown request url: https://${host}${req.url}`);
print(`Unknown request url: https://${host}${req.url}`, 31);
break;
};
@ -125,7 +125,7 @@ export function onRequest(player) {
request.requests.map((request) => {
let reqSize = Buffer.byteLength(request.request_message, "utf8");
let resSize = Buffer.byteLength(returns[index], "utf8");
console.log(`[Packet]: ${request.request_type}`, `${reqSize} => ${resSize}`);
print(`${request.request_type} ${reqSize} => ${resSize}`, 37);
index++;
});
}

View File

@ -43,6 +43,7 @@ export function processResponse(player, req) {
case "GET_PLAYER":
case "GET_INVENTORY":
case "RELEASE_POKEMON":
case "UPGRADE_POKEMON":
case "GET_ASSET_DIGEST":
case "NICKNAME_POKEMON":
case "GET_HATCHED_EGGS":