From 8f0c21c34ab2554b2b32b38c1e4237271aac061c Mon Sep 17 00:00:00 2001 From: Felix Date: Wed, 31 Aug 2016 13:36:02 +0200 Subject: [PATCH] Update - Added item enums - Fort live editing seems stable - Better cell neighbor lookup - ForDetails and FortSearch doesnt use db queries anymore - Setup process resolves now after success --- .save | 2 +- package.json | 2 + src/api.js | 4 +- src/db/tables/forts.table | 6 +- src/dump.js | 16 ++-- src/enum.js | 18 +++++ src/index.js | 5 +- .../{WildPokemon.js => WildPokemon/index.js} | 4 +- src/models/World/Cell/index.js | 20 ++++- src/models/World/Fort/index.js | 8 +- src/models/World/MapObject/index.js | 6 +- src/models/World/forts.js | 73 +++++++++++-------- src/models/World/packets/FortDetails.js | 10 +-- src/models/World/packets/FortSearch.js | 13 +--- src/models/World/packets/GetMapObjects.js | 14 +++- src/modes/index.js | 4 +- src/setup.js | 67 +++++++++-------- 17 files changed, 163 insertions(+), 109 deletions(-) create mode 100644 src/enum.js rename src/models/Pokemon/{WildPokemon.js => WildPokemon/index.js} (76%) diff --git a/.save b/.save index d36709e..b23dc08 100644 --- a/.save +++ b/.save @@ -1 +1 @@ -{"isFirstRun":false,"allowedApiHosts":["localhost"],"loginDetails":{"username":"root","password":"13377"}} \ No newline at end of file +{"isFirstRun":true,"allowedApiHosts":["localhost"],"loginDetails":{"username":"root","password":"1337"}} \ No newline at end of file diff --git a/package.json b/package.json index 15cf40b..895d4d5 100644 --- a/package.json +++ b/package.json @@ -23,10 +23,12 @@ "babel-preset-stage-0": "^6.5.0", "url": "^0.11.0", "prompt": "^1.0.0", + "s2-geometry": "^1.2.9", "fs-extra": "^0.30.0", "mysql": "^2.11.1", "jwt-decode": "^2.1.0", "pogo-asset-downloader": "^0.3.1", + "node-pogo-protos": "^1.4.0", "pokemongo-protobuf": "^1.11.0", "pcrypt": "git+https://github.com/laverdet/pcrypt.git" }, diff --git a/src/api.js b/src/api.js index e36b61c..1c72aa4 100644 --- a/src/api.js +++ b/src/api.js @@ -183,6 +183,7 @@ export function api_deleteFortById(data) { return new Promise((resolve) => { this.world.deleteFort(cellId, uid).then(() => { resolve({ + id: cellId + "." + uid, success: true }); }); @@ -216,13 +217,14 @@ export function getNeighbors(lat, lng, lvl) { let next = S2Geo.nextKey(origin); let prev = S2Geo.prevKey(origin); let ii = 0; - let length = 30; + let length = 10; for (; ii < length; ++ii) { walk.push(S2Geo.toId(prev)); walk.push(S2Geo.toId(next)); next = S2Geo.nextKey(next); prev = S2Geo.prevKey(prev); }; + walk.sort((a, b) => a - b); return (walk); } diff --git a/src/db/tables/forts.table b/src/db/tables/forts.table index be1753a..da68986 100644 --- a/src/db/tables/forts.table +++ b/src/db/tables/forts.table @@ -1,10 +1,10 @@ id int(11) NOT NULL AUTO_INCREMENT, cell_id varchar(64) NOT NULL, -cell_uid int(11) NOT NULL, latitude double NOT NULL, longitude double NOT NULL, name varchar(64) NOT NULL, description varchar(128) NOT NULL, image_url varchar(128) NOT NULL, -rewards varchar(64) NOT NULL, -PRIMARY KEY (id) +experience int(11) NOT NULL DEFAULT '0', +rewards varchar(64) NOT NULL DEFAULT '{}', +PRIMARY KEY (id) \ No newline at end of file diff --git a/src/dump.js b/src/dump.js index e7e0716..5c5b94d 100644 --- a/src/dump.js +++ b/src/dump.js @@ -60,19 +60,15 @@ export function decode(req, res) { * @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); + let decoded = this.decode(req, res); + let out = { + Request: decoded.req, + Response: decoded.res + }; + decoded = JSON.stringify(out, null, 2); fse.outputFileSync(CFG.DEBUG_DUMP_PATH + Date.now(), decoded); } catch (e) { print("Dump traffic: " + e, 31); } - } \ No newline at end of file diff --git a/src/enum.js b/src/enum.js new file mode 100644 index 0000000..b79eca0 --- /dev/null +++ b/src/enum.js @@ -0,0 +1,18 @@ +import proto from "node-pogo-protos"; + +export default { + ITEMS: proto.Inventory.Item.ItemId, + getItemNameById: (emu, id) => { + id <<= 0; + for (let key in emu) { + if (emu[key] === id) return (key); + }; + return (null); + }, + getItemIdByName: (emu, name) => { + for (let key in emu) { + if (key === name) return (emu[key]); + }; + return (null); + } +} \ No newline at end of file diff --git a/src/index.js b/src/index.js index 6165dd8..167352f 100644 --- a/src/index.js +++ b/src/index.js @@ -65,8 +65,9 @@ export default class GameServer { if (current < latest) { print(`WARNING: Please update to the latest build v${latest}!`, 33); } - this.world = new World(this); - this.setup(); + this.setup().then(() => { + this.world = new World(this); + }); }); } diff --git a/src/models/Pokemon/WildPokemon.js b/src/models/Pokemon/WildPokemon/index.js similarity index 76% rename from src/models/Pokemon/WildPokemon.js rename to src/models/Pokemon/WildPokemon/index.js index 9ac34c4..95693cf 100644 --- a/src/models/Pokemon/WildPokemon.js +++ b/src/models/Pokemon/WildPokemon/index.js @@ -1,5 +1,5 @@ -import Pokemon from "index"; -import CaptureProbability from "CaptureProbability"; +import Pokemon from "../index"; +//import CaptureProbability from "CaptureProbability"; /** * @class WildPokemon diff --git a/src/models/World/Cell/index.js b/src/models/World/Cell/index.js index ff4cffd..a314021 100644 --- a/src/models/World/Cell/index.js +++ b/src/models/World/Cell/index.js @@ -50,10 +50,12 @@ export default class Cell extends MapObject { } else { this.getFortsFromDatabase().then((forts) => { + this.forts = []; forts.map((fort) => { this.processDeletedFort(this.addFort(fort)); }); this.synced = true; + print(`Synced ${this.cellId} with database..`, 33); resolve(this.forts); }); } @@ -81,10 +83,24 @@ export default class Cell extends MapObject { // wait for the next map refresh setTimeout(() => { this.deleteFortById(fort.uid); + this.deleteFortFromDatabase(fort).then(() => { + + }); }, (MAP_REFRESH_RATE * 1e3) * 3); } } + /** + * @param {Fort} fort + */ + deleteFortFromDatabase(fort) { + return new Promise((resolve) => { + this.world.instance.db.query(`DELETE FROM ${CFG.MYSQL_FORT_TABLE} WHERE cell_id=? AND id=? LIMIT 1`, [fort.cellId, fort.uid], (e, res) => { + resolve(); + }); + }); + } + /** * @param {Number} id * @return {Number} @@ -92,7 +108,7 @@ export default class Cell extends MapObject { getFortIndexById(id) { let index = 0; for (let fort of this.forts) { - if (fort.uid === id) return (index); + if (fort.uid === id || fort.uid === id << 0) return (index); ++index; }; return (-1); @@ -125,8 +141,6 @@ export default class Cell extends MapObject { addFort(obj) { obj.world = this.world; let fort = new Fort(obj); - fort.parent = this; - fort.cellId = fort.parent.cellId; this.forts.push(fort); return (fort); } diff --git a/src/models/World/Fort/index.js b/src/models/World/Fort/index.js index afba110..4fc11d6 100644 --- a/src/models/World/Fort/index.js +++ b/src/models/World/Fort/index.js @@ -7,6 +7,8 @@ import { validName } from "../../../utils"; +import enum from "../../../enum"; + /** * @class Fort */ @@ -20,8 +22,6 @@ export default class Fort extends MapObject { super(obj); - this.parent = null; - this.enabled = true; this.deleted = false; @@ -46,7 +46,7 @@ export default class Fort extends MapObject { init(obj) { obj = obj || {}; for (let key in obj) { - if (this.hasOwnProperty(key)) { + if (this.hasOwnProperty(key) && key !== "rewards") { this[key] = obj[key]; } }; @@ -76,7 +76,7 @@ export default class Fort extends MapObject { let amount = this.rewards[key] << 0; for (let ii = 0; ii < amount; ++ii) { out.push({ - item_id: key + item_id: enum.getItemNameById(enum.ITEMS, key << 0) }); }; }; diff --git a/src/models/World/MapObject/index.js b/src/models/World/MapObject/index.js index 18d9dc0..c6cc93e 100644 --- a/src/models/World/MapObject/index.js +++ b/src/models/World/MapObject/index.js @@ -32,12 +32,12 @@ export default class MapObject { if (this.hasOwnProperty(key)) { this[key] = obj[key]; } + else if (key === "id") { + this.uid = obj[key]; + } else if (key === "cell_id") { this.cellId = obj[key]; } - else if (key === "cell_uid") { - this.uid = obj[key]; - } }; } diff --git a/src/models/World/forts.js b/src/models/World/forts.js index 17c2560..365996e 100644 --- a/src/models/World/forts.js +++ b/src/models/World/forts.js @@ -4,6 +4,28 @@ import CFG from "../../../cfg"; import print from "../../print"; +/** + * @param {String} id + */ +export function getFortDataById(id) { + + id = id.split(".") || []; + + let uid = id[1]; + let cellId = id[0]; + + let cell = this.getCellById(cellId); + + return new Promise((resolve) => { + if (!cellId || !uid || !cell) return resolve(); + cell.loadForts().then(() => { + let fort = cell.getFortById(uid); + resolve(fort); + }); + }); + +} + /** * @param {Array} cells * @param {Array} out @@ -71,44 +93,31 @@ export function deleteFort(cellId, uid) { let cell = this.getCellById(cellId); let fort = cell.getFortById(uid); return new Promise((resolve) => { - this.deleteFortFromDatabase(fort).then(() => { - fort.delete(); - resolve(); - }); - }); -} - -export function insertFortIntoDatabase(obj) { - return new Promise((resolve) => { - this.addFort(obj).then((fort) => { - let query = `INSERT INTO ${CFG.MYSQL_FORT_TABLE} SET cell_id=?, cell_uid=?, latitude=?, longitude=?, name=?, description=?, image_url=?, rewards=?`; - let id = fort.parent.cellId; - let lat = fort.latitude; - let lng = fort.longitude; - let name = fort.name; - let desc = fort.description; - let img = "http://thecatapi.com/api/images/get?format=src&type=png&d=" + +new Date(); - this.instance.db.query(query, [id, 0, lat, lng, name, desc, img, ""], (e, res) => { - let insertId = res.insertId; - this.instance.db.query(`SELECT * from ${CFG.MYSQL_FORT_TABLE} 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 ${CFG.MYSQL_FORT_TABLE} SET cell_uid=? WHERE id=?`, [index, insertId], (e, res) => { - fort.uid = index; - resolve(fort); - }); - }); - }); - }); + fort.delete(); + resolve(); }); } /** - * @param {Fort} fort + * @param {Object} obj */ -export function deleteFortFromDatabase(fort) { +export function insertFortIntoDatabase(obj) { return new Promise((resolve) => { - this.instance.db.query(`DELETE FROM ${CFG.MYSQL_FORT_TABLE} WHERE cell_id=? AND cell_uid=? LIMIT 1`, [fort.cellId, fort.uid], (e, res) => { - resolve(); + let cellId = Cell.getIdByPosition(obj.latitude, obj.longitude, obj.zoom); + let query = `INSERT INTO ${CFG.MYSQL_FORT_TABLE} SET cell_id=?, latitude=?, longitude=?, name=?, description=?, image_url=?, experience=?, rewards=?`; + let lat = obj.latitude; + let lng = obj.longitude; + let name = obj.name; + let desc = obj.description; + let img = obj.image || ""; + let exp = obj.experience || 500; + this.instance.db.query(query, [cellId, lat, lng, name, desc, img, exp, ""], (e, res) => { + let insertId = res.insertId; + obj.uid = insertId; + obj.cell_id = cellId; + this.addFort(obj).then((fort) => { + resolve(fort); + }); }); }); } \ No newline at end of file diff --git a/src/models/World/packets/FortDetails.js b/src/models/World/packets/FortDetails.js index ee321c0..ec158df 100644 --- a/src/models/World/packets/FortDetails.js +++ b/src/models/World/packets/FortDetails.js @@ -1,5 +1,6 @@ import POGOProtos from "pokemongo-protobuf"; +import CFG from "../../../../CFG"; import print from "../../../print"; /** @@ -8,18 +9,17 @@ import print from "../../../print"; */ export default function FortDetails(msg) { - let id = msg.fort_id.split("."); - return new Promise((resolve) => { - this.instance.db.query(`SELECT * from ${CFG.MYSQL_FORT_TABLE} WHERE cell_id=? AND cell_uid=?`, [id[0], id[1]], (e, forts) => { - let fort = forts[0]; + 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, name: fort.name, description: fort.description, image_urls: [ - fort.image_url + url ], type: "CHECKPOINT", latitude: fort.latitude, diff --git a/src/models/World/packets/FortSearch.js b/src/models/World/packets/FortSearch.js index c24fe21..416d797 100644 --- a/src/models/World/packets/FortSearch.js +++ b/src/models/World/packets/FortSearch.js @@ -1,5 +1,6 @@ import POGOProtos from "pokemongo-protobuf"; +import CFG from "../../../../CFG"; import print from "../../../print"; /** @@ -8,19 +9,13 @@ import print from "../../../print"; */ export default function FortSearch(msg) { - let id = msg.fort_id.split("."); - return new Promise((resolve) => { - this.instance.db.query(`SELECT * from ${CFG.MYSQL_FORT_TABLE} WHERE cell_id=? AND cell_uid=?`, [id[0], id[1]], (e, forts) => { - let fort = forts[0]; + this.getFortDataById(msg.fort_id).then((fort) => { if (!fort) return void 0; let buffer = ({ result: "SUCCESS", - items_awarded: [ - { item_id: 3 }, - { item_id: 4 } - ], - experience_awarded: 1337, + items_awarded: fort.serializeRewards(), + experience_awarded: fort.experience, cooldown_complete_timestamp_ms: +new Date() + fort.cooldown, chain_hack_sequence_number: 2 }); diff --git a/src/models/World/packets/GetMapObjects.js b/src/models/World/packets/GetMapObjects.js index b220095..5246c95 100644 --- a/src/models/World/packets/GetMapObjects.js +++ b/src/models/World/packets/GetMapObjects.js @@ -2,6 +2,7 @@ import POGOProtos from "pokemongo-protobuf"; import s2 from "s2-geometry"; +import CFG from "../../../../CFG"; import print from "../../../print"; const S2Geo = s2.S2; @@ -30,9 +31,20 @@ export default function GetMapObjects(msg) { this.getFortsByCells(msg.cell_id, [], 0).then((cells) => { cells.map((cell) => { if (cell.forts.length) { - console.log("###" + cell.cellId + "###"); + let ids = []; + /*console.log("###" + cell.cellId + "###"); cell.forts.map((fort) => { console.log(fort.uid, fort.latitude, fort.longitude); + });*/ + cell.forts.map((fort) => { + let id = fort.cellId + "." + fort.uid; + if (ids.indexOf(id) > -1) { + print(`Duplicated!!!! => ${id}`, 31); + } + else { + ids.push(id); + } + print(`Active fort: ${fort.cellId}.${fort.uid}`, 35); }); } mapCells.push({ diff --git a/src/modes/index.js b/src/modes/index.js index 07ebfa9..569e660 100644 --- a/src/modes/index.js +++ b/src/modes/index.js @@ -14,8 +14,8 @@ export default { pokemon_visible_range: 70.00196078431372, poke_nav_range_meters: 751.0156862745098, encounter_range_meters: 50.25098039215686, - get_map_objects_min_refresh_seconds: 8, - get_map_objects_max_refresh_seconds: 8, + get_map_objects_min_refresh_seconds: 4, + get_map_objects_max_refresh_seconds: 4, get_map_objects_min_distance_meters: 10.007843017578125, google_maps_api_key: CFG.GMAPS_KEY }, diff --git a/src/setup.js b/src/setup.js index 4de954e..b63b7cb 100644 --- a/src/setup.js +++ b/src/setup.js @@ -17,42 +17,47 @@ import { export function setup() { - let save = JSON.parse(fs.readFileSync(".save", "utf8")); + return new Promise((resolve, reject) => { - 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(); + let save = JSON.parse(fs.readFileSync(".save", "utf8")); + + 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().then(resolve); + }); + }, 1e3); + return void 0; + } + + // make sure all assets got loaded properly + this.validateAssets().then(() => { + + print(`Downloaded assets are valid! Proceeding..`); + + let parsedMaster = this.parseGameMaster(); + shared.GAME_MASTER = new GameMaster(parsedMaster); + + this.setupDatabaseConnection().then(() => { + if (CFG.PORT < 1) { + print("Invalid port!", 31); + return void 0; + } + this.socket = this.createHTTPServer(); + setTimeout(this::this.cycle, 1); + let localIPv4 = this.getLocalIPv4(); + print(`Server listening at ${localIPv4}:${CFG.PORT}`, 33); + resolve(); }); - }, 1e3); - return void 0; - } - // make sure all assets got loaded properly - this.validateAssets().then(() => { - - print(`Downloaded assets are valid! Proceeding..`); - - let parsedMaster = this.parseGameMaster(); - shared.GAME_MASTER = new GameMaster(parsedMaster); - - this.setupDatabaseConnection().then(() => { - if (CFG.PORT < 1) { - print("Invalid port!", 31); - return void 0; - } - this.socket = this.createHTTPServer(); - setTimeout(this::this.cycle, 1); - let localIPv4 = this.getLocalIPv4(); - print(`Server listening at ${localIPv4}:${CFG.PORT}`, 33); + }).catch((e) => { + //fse.removeSync(CFG.DUMP_ASSET_PATH); + print("Error: " + e + " was not found!", 31); }); - }).catch((e) => { - //fse.removeSync(CFG.DUMP_ASSET_PATH); - print("Error: " + e + " was not found!", 31); }); }