Isomorphic mysql db, updates

- Isomorphic databases
- Refactored some player->db keys
- Seperated shutdown method
- Nearby pidgey instead of rattata
- Removed some unused arguments
- Player saving is async now
- Prettified used db console print
This commit is contained in:
Felix
2016-08-16 13:40:47 +02:00
parent 5cd04c0018
commit b5cce7e127
10 changed files with 356 additions and 164 deletions

3
cfg.js
View File

@@ -15,7 +15,6 @@ export const SERVER_LOG_REQUESTS = true;
export const SERVER_DEFAULT_CONSOLE_COLOR = 32;
// Either mongo or mysql
// Dont use mysql right now
export const SERVER_USE_DATABASE = "MONGO";
// MONGODB
@@ -23,7 +22,6 @@ export const SERVER_MONGO_PORT = 27017;
export const SERVER_MONGO_HOST_IP = "127.0.0.1";
export const SERVER_MONGO_DB_NAME = "pokemongo";
export const SERVER_MONGO_COLLECTION_USERS = "users";
export const SERVER_MONGO_URL = `mongodb://${SERVER_MONGO_HOST_IP}:${SERVER_MONGO_PORT}/${SERVER_MONGO_DB_NAME}`;
// MYSQL
export const SERVER_MYSQL_PORT = 3306;
@@ -31,6 +29,7 @@ export const SERVER_MYSQL_HOST_IP = "127.0.0.1";
export const SERVER_MYSQL_DB_NAME = "pogosql";
export const SERVER_MYSQL_USERNAME = "USERNAME";
export const SERVER_MYSQL_PASSWORD = "PASSWORD";
export const SERVER_MYSQL_TABLE = "users";
// account used for pogo-asset-downloader lib
export const SERVER_POGO_CLIENT_PROVIDER = "GOOGLE"; // either google or ptc

View File

@@ -2,10 +2,12 @@ import mongodb from "mongodb";
import * as CFG from "../../cfg";
export function setupMongo() {
export function setupConnection() {
let url = `mongodb://${CFG.SERVER_MONGO_HOST_IP}:${CFG.SERVER_MONGO_PORT}/${CFG.SERVER_MONGO_DB_NAME}`;
return new Promise((resolve) => {
mongodb.MongoClient.connect(CFG.SERVER_MONGO_URL, (error, db) => {
mongodb.MongoClient.connect(url, (error, db) => {
if (error) {
this.print(error, 31);
} else {
@@ -19,6 +21,18 @@ export function setupMongo() {
}
/**
* @param {Function} resolve
*/
export function closeConnection(resolve) {
this.db.instance.close(() => {
resolve();
});
}
/**
* @param {String} name
*/
export function loadCollection(name) {
return new Promise((resolve) => {
@@ -34,6 +48,9 @@ export function loadCollection(name) {
}
/**
* @param {String} name
*/
export function createCollection(name) {
return new Promise((resolve) => {
this.db.instance.createCollection(name, {}, (err, coll) => {
@@ -42,11 +59,14 @@ export function createCollection(name) {
});
}
/**
* @param {String} email
*/
export function getUserByEmail(email) {
return new Promise((resolve) => {
let collection = this.getUserCollection();
collection.find({email: email}).toArray((err, docs) => {
resolve(docs[0]);
resolve(docs);
});
});
}
@@ -57,22 +77,14 @@ export function getUserCollection() {
);
}
/**
* @param {Object} obj
*/
export function createUser(obj) {
let collection = this.getUserCollection();
let user = {
username: obj.username,
email: obj.email,
position: obj.position,
exp: obj.exp,
stardust: obj.stardust,
pokecoins: obj.pokecoins,
avatar: obj.avatar,
team: obj.team,
contact_settings: obj.contact_settings,
tutorial_state: obj.tutorial_state
};
let user = this.getUserData(obj);
return new Promise((resolve) => {
collection.insert([user], (error, result) => {
@@ -82,27 +94,51 @@ export function createUser(obj) {
}
/**
* @param {Object} obj
*/
export function updateUser(obj) {
let collection = this.getUserCollection();
let user = {
username: obj.username,
email: obj.email,
position: obj.position,
exp: obj.exp,
stardust: obj.stardust,
pokecoins: obj.pokecoins,
avatar: obj.avatar,
team: obj.team,
contact_settings: obj.contact_settings,
tutorial_state: obj.tutorial_state
};
let user = this.getUserData(obj);
return new Promise((resolve) => {
collection.update({email: obj.email}, user, (error, result) => {
collection.update({email: user.email}, user, (error, result) => {
resolve();
});
});
}
/**
* @param {Object} obj
* @return {Object}
*/
export function getUserData(obj) {
return ({
username: obj.username,
email: obj.email,
exp: obj.exp,
stardust: obj.stardust,
pokecoins: obj.pokecoins,
team: obj.team,
skin: obj.skin,
hair: obj.skin,
shirt: obj.skin,
pants: obj.skin,
hat: obj.skin,
shoes: obj.skin,
eyes: obj.skin,
gender: obj.skin,
backpack: obj.skin,
latitude: obj.latitude,
longitude: obj.latitude,
altitude: obj.latitude,
send_marketing_emails: false,
send_push_notifications: false
});
}

View File

@@ -2,7 +2,7 @@ import mysql from "mysql";
import * as CFG from "../../cfg";
export function setupMySQL() {
export function setupConnection() {
let connection = mysql.createConnection({
host : CFG.SERVER_MYSQL_HOST_IP,
@@ -19,8 +19,178 @@ export function setupMySQL() {
return void 0;
}
this.db.instance = connection;
resolve();
this.createTableIfNoExists().then(() => {
resolve();
});
});
});
}
export function createTableIfNoExists() {
return new Promise((resolve) => {
this.db.instance.query(`SHOW TABLES LIKE '${CFG.SERVER_MYSQL_TABLE}';`, (e, rows, fields) => {
if (e) console.log(e);
else {
// exists
if (rows && rows.length) resolve();
// create user table
else this.createTable(CFG.SERVER_MYSQL_TABLE).then(resolve);
}
});
});
}
/**
* @param {String} name
*/
export function createTable(name) {
this.print(`Creating table ${CFG.SERVER_MYSQL_TABLE}`, 36);
return new Promise((resolve) => {
let query = `
CREATE TABLE IF NOT EXISTS ${name} (
id int(11) NOT NULL,
username longtext NOT NULL,
email longtext NOT NULL,
exp int(255) NOT NULL,
stardust int(255) NOT NULL,
pokecoins int(255) NOT NULL,
team int(11) NOT NULL,
latitude double NOT NULL,
longitude double NOT NULL,
altitude int(255) 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
) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=latin1;
`;
this.db.instance.query(query, (e, rows, fields) => {
if (e) console.log(e);
else resolve();
});
});
}
/**
* @param {Function} resolve
*/
export function closeConnection(resolve) {
this.db.instance.end(() => {
resolve();
});
}
/**
* @param {String} email
*/
export function getUserByEmail(email) {
return new Promise((resolve) => {
this.db.instance.query(`SELECT * FROM ${CFG.SERVER_MYSQL_TABLE} WHERE email=? LIMIT 1`, [email], (e, rows, fields) => {
if (e) console.log(e);
else resolve(rows);
});
});
}
/**
* @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, resolve);
});
}
/**
* @param {Object} obj
*/
export function updateUser(obj) {
let query = this.getUserQuery("UPDATE", "WHERE email=? LIMIT 1");
let data = this.getUserQueryData(obj);
return new Promise((resolve) => {
this.db.instance.query(query, data, resolve);
});
}
/**
* @return {String}
*/
export function getUserQuery(cmd, after) {
return (`
${cmd} ${CFG.SERVER_MYSQL_TABLE}
SET
username=?,
email=?,
exp=?,
stardust=?,
pokecoins=?,
team=?,
latitude=?,
longitude=?,
altitude=?,
send_marketing_emails=?,
send_push_notifications=?,
skin=?,
hair=?,
shirt=?,
pants=?,
hat=?,
shoes=?,
eyes=?,
gender=?,
backpack=?
${after}
`);
}
/**
* @param {Object} obj
* @return {Array}
*/
export function getUserQueryData(obj) {
return ([
obj.username,
obj.email,
obj.exp,
obj.stardust,
obj.pokecoins,
obj.team,
// position
obj.latitude,
obj.longitude,
obj.altitude,
// contact settings
obj.send_marketing_emails,
obj.send_push_notifications,
// avatar
obj.skin,
obj.hair,
obj.shirt,
obj.pants,
obj.hat,
obj.shoes,
obj.eyes,
obj.gender,
obj.backpack,
// where
obj.email
]);
}

View File

@@ -87,6 +87,7 @@ class GameServer {
password: CFG.SERVER_POGO_CLIENT_PASSWORD,
downloadModels: false
}).then(() => {
this.print("Created asset download session");
resolve();
});
});
@@ -134,6 +135,43 @@ class GameServer {
return (server);
}
setupDatabaseConnection() {
return new Promise((resolve) => {
let name = String(CFG.SERVER_USE_DATABASE).toUpperCase();
switch (name) {
case "MONGO":
case "MONGODB":
inherit(GameServer, _mongo);
this.setupConnection().then(resolve);
break;
case "MYSQL":
inherit(GameServer, _mysql);
this.setupConnection().then(resolve);
break;
default:
this.print("Invalid database connection type!", 31);
return void 0;
break;
};
});
}
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);
});
});
}
/**
* @param {String} msg
* @param {Number} color
@@ -155,8 +193,6 @@ inherit(GameServer, _player);
inherit(GameServer, _request);
inherit(GameServer, _response);
inherit(GameServer, _process);
inherit(GameServer, _mongo);
inherit(GameServer, _mysql);
let server = new GameServer();

View File

@@ -76,7 +76,7 @@ export default function GetMapObjects(request) {
new proto.Map.Pokemon.MapPokemon({
spawn_point_id: "87bdd289c69",
encounter_id: 11810991820755313517,
pokemon_id: 19,
pokemon_id: 16,
latitude: 39.19047143172622,
longitude: -96.58502161502839,
expiration_timestamp_ms: (new Date().getTime() + 1e6) * 1e3
@@ -86,7 +86,7 @@ export default function GetMapObjects(request) {
cell.nearby_pokemons = [
new proto.Map.Pokemon.NearbyPokemon({
distance_in_meters: 200.0,
pokemon_id: 19
pokemon_id: 16
})
];

View File

@@ -37,19 +37,22 @@ function buildPlayerData(obj) {
let pokecoins = obj.pokecoins;
let stardust = obj.stardust;
let avatar = obj.avatar || {
skin: 0,
hair: 2,
shirt: 1,
pants: 2,
hat: 0,
shoes: 2,
eyes: 3,
gender: proto.Enums.Gender.MALE,
backpack: 1
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 = obj.contact_settings;
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,

View File

@@ -20,37 +20,31 @@ class Player {
this.uid = -1;
this.email = null;
this._username = "undefined";
this.username = "undefined";
this.position = {
latitude: 0,
longitude: 0,
altitude: 0
};
this.latitude = 0;
this.longitude = 0;
this.altitude = 0;
this.contact_settings = {
send_marketing_emails: false,
send_push_notifications: false
};
this.send_marketing_emails = false;
this.send_push_notifications = false;
this.exp = 0;
this.stardust = 0;
this.pokecoins = 0;
this.team = proto.Enums.TeamColor.BLUE;
this.team = 0;
this.avatar = {
skin: 0,
hair: 0,
shirt: 0,
pants: 0,
hat: 0,
shoes: 0,
eyes: 0,
gender: 0,
backpack: 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.tutorial_state = [32, 1, 3, 4, 7];
@@ -81,13 +75,11 @@ class Player {
}
updateByObject(obj) {
for (let key in obj) {
if (this.hasOwnProperty(key)) {
this[key] = obj[key];
}
};
}
/**
@@ -99,9 +91,7 @@ class Player {
this.latitude = data.latitude;
this.longitude = data.longitude;
//this.position.altitude = data.altitude;
//console.log(`Updated position: ${data.latitude};${data.longitude}`);
this.altitude = data.altitude;
}
@@ -111,17 +101,15 @@ class Player {
if (!data) return void 0;
this.avatar = {
skin: data.skin,
hair: data.hair,
shirt: data.shirt,
pants: data.pants,
hat: data.hat,
shoes: data.shoes,
eyes: data.eyes,
gender: data.gender,
backpack: data.backpack
};
this.skin = data.skin;
this.hair = data.hair;
this.shirt = data.shirt;
this.pants = data.pants;
this.hat = data.hat;
this.shoes = data.shoes;
this.eyes = data.eyes;
this.gender = data.gender;
this.backpack = data.backpack;
}
@@ -131,32 +119,11 @@ class Player {
if (!data) return void 0;
this.contact_settings.send_marketing_emails = data.send_marketing_emails;
this.contact_settings.send_push_notifications = data.send_push_notifications;
this.send_marketing_emails = data.send_marketing_emails;
this.send_push_notifications = data.send_push_notifications;
}
get username() {
return (this._username);
}
set username(name) {
this._username = name;
}
get latitude() {
return (this.position.latitude);
}
set latitude(lat) {
this.position.latitude = lat;
}
get longitude() {
return (this.position.longitude);
}
set longitude(lng) {
this.position.longitude = lng;
}
}
/**
@@ -302,16 +269,14 @@ export function removeAllPlayers() {
* @param {Player} player
*/
export function savePlayer(player) {
if (player.authenticated) {
this.updateUser(player);
}
//this.print(`${player.remoteAddress} saved into database`, 34);
return new Promise((resolve) => {
if (player.authenticated) {
this.updateUser(player).then(resolve);
}
});
}
/**
* @param {Object} doc
*/
export function loginPlayer(doc) {
export function loginPlayer() {
let buffer = null;
let player = this.player;
@@ -319,7 +284,7 @@ export function loginPlayer(doc) {
return new Promise((resolve) => {
this.getUserByEmail(player.email).then((doc) => {
player.updateByObject(doc);
buffer = GetPlayer(doc).encode();
buffer = GetPlayer(player).encode();
resolve(buffer);
});
});
@@ -335,13 +300,13 @@ export function forwardPlayer() {
if (player.email.length) {
this.print(`${player.email.replace("@gmail.com", "")} authenticated!`, 36);
}
if (doc === void 0) {
this.registerPlayer(doc).then((res) => {
if (doc === void 0 || doc && !doc.length) {
this.registerPlayer().then((res) => {
resolve(res);
});
}
else {
this.loginPlayer(doc).then((res) => {
this.loginPlayer().then((res) => {
resolve(res);
});
}
@@ -350,10 +315,7 @@ export function forwardPlayer() {
}
/**
* @param {Object} doc
*/
export function registerPlayer(doc) {
export function registerPlayer() {
let player = this.player;
@@ -361,7 +323,7 @@ export function registerPlayer(doc) {
this.createUser(player).then(() => {
this.print(`${this.player.email.replace("@gmail.com", "")} registered!`, 36);
player.tutorial_state = [];
this.loginPlayer(doc).then((res) => {
this.loginPlayer().then((res) => {
resolve(res);
});
});

View File

@@ -9,14 +9,7 @@ export function processCommand(cmd, data) {
break;
// Exit the server
case "/exit":
this.socket.close(() => {
this.print("Closed http server!", 33);
this.db.instance.close(() => {
this.print("Closed database connection!", 33);
this.print("Killed the server!", 31);
setTimeout(() => process.exit(1), 2e3);
});
});
this.shutdown();
break;
case "/kick":
this.kickPlayer(data[1]);

View File

@@ -74,7 +74,10 @@ export function processResponse(request) {
case REQUEST.GET_MAP_OBJECTS:
this.player.updatePosition(request);
buffer = GetMapObjects(request);
this.savePlayer(player);
this.savePlayer(player).then(() => {
resolve(buffer);
});
return void 0;
break;
case REQUEST.GET_DOWNLOAD_URLS:
GetDownloadUrls(request, this.generateDownloadUrlByAssetId).then((res) => {
@@ -85,18 +88,27 @@ export function processResponse(request) {
case REQUEST.SET_AVATAR:
player.updateAvatar(request);
buffer = SetAvatar(player);
this.savePlayer(player);
this.savePlayer(player).then(() => {
resolve(buffer);
});
return void 0;
break;
case REQUEST.SFIDA_ACTION_LOG:
buffer = SfidaActionLog();
break;
case REQUEST.MARK_TUTORIAL_COMPLETE:
buffer = MarkTutorialComplete(player);
this.savePlayer(player);
this.savePlayer(player).then(() => {
resolve(buffer);
});
return void 0;
break;
case REQUEST.CLAIM_CODENAME:
buffer = ClaimCodeName(request, player);
this.savePlayer(player);
this.savePlayer(player).then(() => {
resolve(buffer);
});
return void 0;
break;
case REQUEST.LEVEL_UP_REWARDS:
buffer = LevelUpRewards();
@@ -110,7 +122,10 @@ export function processResponse(request) {
case REQUEST.SET_CONTACT_SETTINGS:
player.updateContactSettings(request);
buffer = SetContactSettings(player);
this.savePlayer(player);
this.savePlayer(player).then(() => {
resolve(buffer);
});
return void 0;
break;
case REQUEST.ENCOUNTER:
buffer = Encounter(request);

View File

@@ -7,10 +7,12 @@ export function setup() {
this.print("Booting server..", 33);
this.createAssetDownloadSession().then(() => {
this.print("Created asset download session");
this.setupDatabaseConnection().then(() => {
this.print("Database connection established");
let dbType = String(CFG.SERVER_USE_DATABASE).toLowerCase();
let name = dbType === "mongo" ? "MongoDB" : "MySQL";
this.print(`\x1b[36;1m${name}\x1b[0m\x1b[${CFG.SERVER_DEFAULT_CONSOLE_COLOR};1m connection established\x1b[0m`);
if (CFG.SERVER_PORT < 1) {
this.print("Invalid port!", 31);
@@ -26,28 +28,4 @@ export function setup() {
});
});
}
export function setupDatabaseConnection() {
return new Promise((resolve) => {
let name = String(CFG.SERVER_USE_DATABASE).toUpperCase();
switch (name) {
case "MONGO":
case "MONGODB":
this.setupMongo().then(resolve);
break;
case "MYSQL":
this.setupMySQL().then(resolve);
break;
default:
this.print("Invalid database connection type!", 31);
return void 0;
break;
};
});
}