- Passed login phase
- Extend player object
- Fixed stdin bug
- Decode auth_info on authentication, to get email and generate uid
- Hash code generator for uid
This commit is contained in:
Felix 2016-08-08 00:57:16 +02:00
parent 42d62a6b31
commit 83fa228615
19 changed files with 471 additions and 56 deletions

6
.greet Normal file
View File

@ -0,0 +1,6 @@
______ _____ _____ _____
| ___ \ _ | __ \ _ |
| |_/ / | | | | \/ | | | ___ ___ _ ____ _____ _ __
| __/| | | | | __| | | |/ __|/ _ \ '__\ \ / / _ \ '__|
| | \ \_/ / |_\ \ \_/ /\__ \ __/ | \ V / __/ |
\_| \___/ \____/\___/ |___/\___|_| \_/ \___|_|

Binary file not shown.

6
cfg.js
View File

@ -4,8 +4,10 @@ export const SERVER_GAME_MODE = 0;
export const SERVER_TICK_INTERVAL = 1; // better dont change
export const SERVER_SAVE_INTERVAL = 120000; // all 120s
export const SERVER_MAX_CONNECTIONS = 64;
export const SERVER_PLAYER_CONNECTION_TIMEOUT = 30000; // 1min
export const SERVER_PLAYER_CONNECTION_TIMEOUT = 60000; // 1min
export const SERVER_DEFAULT_CONSOLE_COLOR = 32;
export const ASSET_DIGEST_PATH = "asset_digest";
export const ASSET_DIGEST_PATH = "asset_digest";
export const MINIMUM_CLIENT_VERSION = "0.31.0";

View File

@ -65,8 +65,9 @@ export function playerTimeoutTick() {
for (; ii < length; ++ii) {
client = this.clients[ii];
if (this.time - client.timeout >= maxTimeout) {
this.print(`${client.remoteAddress} timed out!`, 36);
this.killPlayer(client);
this.print(`${client.remoteAddress} timed out`, 34);
this.savePlayer(client);
this.removePlayer(client);
}
};

View File

@ -14,6 +14,8 @@ import * as _request from "./request";
import * as _process from "./process";
import * as _database from "./database";
const greetMessage = fs.readFileSync(".greet", "utf8");
/**
* @class GameServer
*/
@ -28,10 +30,11 @@ class GameServer {
CRASH: false
};
this.paused = false;
this.proto = null;
this.socket = null;
this.player = null;
this.request = null;
this.response = null;
this.cycleInstance = null;
// Timer things
@ -44,6 +47,7 @@ class GameServer {
this.clients = [];
this.greet();
this.setup();
}
@ -64,10 +68,13 @@ class GameServer {
}
/**
* @return {HTTP}
*/
createHTTPServer() {
let server = http.createServer((req, res) => {
this.response = res;
if (!this.clientAlreadyConnected(req)) {
this.print(`${req.connection.remoteAddress} connected!`, 36);
this.addPlayer(req.connection);
}
let chunks = [];
@ -75,18 +82,13 @@ class GameServer {
chunks.push(chunk);
});
req.on("end", () => {
// Reset player timeout
let player = this.getPlayerByRequest(req);
if (player !== null) player.timeout = this.time;
// Data
let buffer = Buffer.concat(chunks);
req.body = buffer;
this.request = req;
this.onRequest(req, res);
});
});
server.listen(CFG.SERVER_PORT, CFG.SERVER_HOST_IP, () => {
});
server.listen(CFG.SERVER_PORT);
return (server);
}
@ -99,6 +101,10 @@ class GameServer {
console.log(`\x1b[${color};1m${msg}\x1b[0m`);
}
greet() {
console.log(greetMessage);
}
}
inherit(GameServer, _setup);

View File

@ -0,0 +1,14 @@
import proto from "../proto";
/**
* @return {Object}
*/
export default function AuthTicket() {
return (
new proto.Networking.Envelopes.AuthTicket({
expire_timestamp_ms: 9999999999999,
})
);
}

View File

@ -0,0 +1,22 @@
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()
);
}

View File

@ -16,8 +16,8 @@ export default function ResponseEnvelope(obj) {
})
}),
request_id: obj.id,
returns: obj.res
})
returns: obj.response
}).encode().toBuffer()
);
}

View File

@ -0,0 +1,17 @@
import * as CFG from "../../cfg";
import proto from "../proto";
/**
* @param {Object} obj
* @return {Object}
*/
export default function CheckAwardedBadges(obj) {
return (
new proto.Networking.Responses.CheckAwardedBadgesResponse({
success: true
}).encode()
);
}

View File

@ -7,8 +7,10 @@ import proto from "../proto";
export default function DownloadRemoteConfigVersion(obj) {
return (
new proto.Networking.Responses.DownloadSettingsResponse({
hash: "54b359c97e46900f87211ef6e6dd0b7f2a3ea1f5"
new proto.Networking.Responses.DownloadRemoteConfigVersionResponse({
result: 1,
item_templates_timestamp_ms: 1468540960537,
asset_digest_timestamp_ms: 1467338276561000
}).encode()
);

View File

@ -1,5 +1,7 @@
import proto from "../proto";
import * as CFG from "../../cfg";
/**
* @param {Object} obj
* @return {Object}
@ -8,7 +10,33 @@ export default function DownloadSettings(obj) {
return (
new proto.Networking.Responses.DownloadSettingsResponse({
hash: "b1f2bf509a025b7cd76e1c484e2a24411c50f0612"
hash: "54b359c97e46900f87211ef6e6dd0b7f2a3ea1f5",
settings: new proto.Settings.GlobalSettings({
fort_settings: new proto.Settings.FortSettings({
interaction_range_meters: 40,
max_total_deployed_pokemon: 10,
max_player_deployed_pokemon: 1,
deploy_stamina_multiplier: 500,
far_interaction_range_meters: 1000
}),
map_settings: new proto.Settings.MapSettings({
pokemon_visible_range: 70,
poke_nav_range_meters: 201,
encounter_range_meters: 50,
get_map_objects_min_refresh_seconds: 5,
get_map_objects_max_refresh_seconds: 30,
get_map_objects_min_distance_meters: 10,
google_maps_api_key: "AIzaSyDF9rkP8lhcddBtvH9gVFzjnNo13WtmJIM"
}),
inventory_settings: new proto.Settings.InventorySettings({
max_pokemon: 1000,
max_bag_items: 1000,
base_pokemon: 250,
base_bag_items: 350,
base_eggs: 1000
}),
minimum_client_version: CFG.MINIMUM_CLIENT_VERSION
})
}).encode()
);

View File

@ -1,6 +1,9 @@
import fs from "fs";
import proto from "../proto";
import * as CFG from "../../cfg";
import proto from "../proto";
let asset = fs.readFileSync(CFG.ASSET_DIGEST_PATH);
/**
* @param {Object} obj
@ -8,8 +11,6 @@ import proto from "../proto";
*/
export default function GetAssetDigest(obj) {
return (
fs.readFileSync("../../" + CFG.ASSET_DIGEST_PATH)
);
return (asset);
}

View File

@ -6,22 +6,25 @@ import proto from "../proto";
*/
function getPlayerDataPacket(obj) {
return new proto.Data.PlayerData({
creation_timestamp_ms: 1467936859925,
username: obj.username,
team: obj.team,
tutorial_state: obj.tutorial_state,
avatar: new proto.Data.Player.PlayerAvatar(obj.avatar),
max_pokemon_storage: 250,
max_item_storage: 350,
daily_bonus: new proto.Data.Player.DailyBonus({
next_defender_bonus_collect_timestamp_ms: 1470174535972
}),
contact_settings: new proto.Data.Player.ContactSettings({
send_marketing_emails: true
}),
currencies: obj.currencies
});
return (
new proto.Data.PlayerData({
creation_timestamp_ms: 1467936859925,
username: obj.username,
team: obj.team,
tutorial_state: obj.tutorial_state,
avatar: new proto.Data.Player.PlayerAvatar(obj.avatar),
max_pokemon_storage: 250,
max_item_storage: 350,
daily_bonus: new proto.Data.Player.DailyBonus({
next_defender_bonus_collect_timestamp_ms: 1470174535972
}),
// equipped_badge: new proto.Data.Player.EquippedBadge({}),
contact_settings: new proto.Data.Player.ContactSettings({
send_marketing_emails: true
}),
currencies: obj.currencies
})
);
}

View File

@ -0,0 +1,25 @@
import proto from "../proto";
/**
* @param {Object} obj
* @return {Object}
*/
export default function GetPlayerProfile(obj) {
return (
new proto.Networking.Responses.GetPlayerProfileResponse({
result: proto.Networking.Responses.GetPlayerProfileResponse.Result.SUCCESS,
start_time: new Date().getTime() * 1000,
badges: [
new proto.Data.PlayerBadge({
badge_type: proto.Enums.BadgeType.BADGE_PIKACHU,
rank: 1,
start_value: 0,
end_value: 2000,
current_value: 1337
})
]
}).encode()
);
}

View File

@ -0,0 +1,141 @@
import * as CFG from "../../cfg";
import proto from "../proto";
/**
* @param {Object} obj
* @return {Object}
*/
export default function ItemTemplates(obj) {
return (
new proto.Networking.Responses.DownloadItemTemplatesResponse({
success: true,
item_templates: new proto.Networking.Responses.DownloadItemTemplatesResponse.ItemTemplate({
pokemon_settings: null,
// unused but saved here for later use
item_settings: new proto.Settings.Master.ItemSettings({
"item_id": 702,
"item_type": 6,
"category": 2,
"drop_freq": 0,
"drop_trainer_level": 0,
"pokeball": null,
"potion": null,
"revive": null,
"battle": null,
"food": null,
"inventory_upgrade": null,
"xp_boost": null,
"incense": null,
"egg_incubator": null,
"fort_modifier": null
}),
// unused but saved here for later use
move_settings: new proto.Settings.Master.MoveSettings({
"movement_id": 13,
"animation_id": 5,
"pokemon_type": 1,
"power": 25,
"accuracy_chance": 1,
"critical_chance": 0.05000000074505806,
"heal_scalar": 0,
"stamina_loss_scalar": 0.05999999865889549,
"trainer_level_min": 1,
"trainer_level_max": 100,
"vfx_name": "wrap",
"duration_ms": 4000,
"damage_window_start_ms": 2800,
"damage_window_end_ms": 3400,
"energy_delta": -20
}),
move_sequence_settings: new proto.Settings.Master.MoveSequenceSettings({
"sequence": ["anim attacker atk-move", "f2fvfx attacker acid_fast", "sfx attacker 051-0_acid", "wait 0.15", "vfx defender acid_fast_hit", "anim defender damageS01", "wait 0.35", "sys ui-sync", "sys complete"]
}),
type_effective: new proto.Settings.Master.TypeEffectiveSettings({
"attack_scalar": [1, 0.800000011920929, 0.800000011920929, 0.800000011920929, 1, 1, 1, 0.800000011920929, 0.800000011920929, 0.800000011920929, 1, 1.25, 1, 1.25, 1, 1, 1.25, 0.800000011920929],
"attack_type": 7
}),
badge_settings: new proto.Settings.Master.BadgeSettings({
"badge_type": 13,
"badge_rank": 4,
"targets": [10, 100, 1000]
}),
// unused but saved here for later use
camera: new proto.Settings.Master.CameraSettings({
"next_camera": "",
"interpolation": [1],
"target_type": [12],
"ease_in_speed": [0],
"east_out_speed": [0],
"duration_seconds": [5],
"wait_seconds": [0],
"transition_seconds": [0.5],
"angle_degree": [-20],
"angle_offset_degree": [0],
"pitch_degree": [20],
"pitch_offset_degree": [0],
"roll_degree": [0],
"distance_meters": [4],
"height_percent": [0],
"vert_ctr_ratio": [1]
}),
player_level: new proto.Settings.Master.PlayerLevelSettings({
"rank_num": [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1],
"required_experience": [0, 1000, 3000, 6000, 10000, 15000, 21000, 28000, 36000, 45000, 55000, 65000, 75000, 85000, 100000, 120000, 140000, 160000, 185000, 210000, 260000, 335000, 435000, 560000, 710000, 900000, 1100000, 1350000, 1650000, 2000000, 2500000, 3000000, 3750000, 4750000, 6000000, 7500000, 9500000, 12000000, 15000000, 20000000],
"cp_multiplier": [0.09399999678134918, 0.16639786958694458, 0.21573247015476227, 0.2557200491428375, 0.29024988412857056, 0.3210875988006592, 0.3492126762866974, 0.37523558735847473, 0.39956727623939514, 0.42250001430511475, 0.443107545375824, 0.4627983868122101, 0.48168495297431946, 0.49985843896865845, 0.517393946647644, 0.5343543291091919, 0.5507926940917969, 0.5667545199394226, 0.5822789072990417, 0.5974000096321106, 0.6121572852134705, 0.6265671253204346, 0.6406529545783997, 0.6544356346130371, 0.667934000492096, 0.6811649203300476, 0.6941436529159546, 0.7068842053413391, 0.719399094581604, 0.7317000031471252, 0.7377694845199585, 0.7437894344329834, 0.7497610449790955, 0.7556855082511902, 0.7615638375282288, 0.7673971652984619, 0.7731865048408508, 0.7789327502250671, 0.7846369743347168, 0.7903000116348267],
"max_egg_player_level": 20,
"max_encounter_player_level": 30
}),
gym_level: new proto.Settings.Master.GymLevelSettings({
"required_experience": [0, 2000, 4000, 8000, 12000, 16000, 20000, 30000, 40000, 50000],
"leader_slots": [1, 1, 1, 2, 2, 2, 3, 3, 3, 4],
"trainer_slots": [0, 1, 2, 2, 3, 4, 4, 5, 6, 6],
"search_roll_bonus": []
}),
battle_settings: new proto.Settings.Master.GymBattleSettings({
"energy_per_sec": 0,
"dodge_energy_cost": 0,
"retarget_seconds": 0.5,
"enemy_attack_interval": 1.5,
"attack_server_interval": 5,
"round_duration_seconds": 99,
"bonus_time_per_ally_seconds": 10,
"maximum_attackers_per_battle": 20,
"same_type_attack_bonus_multiplier": 1.25,
"maximum_energy": 100,
"energy_delta_per_health_lost": 0.5,
"dodge_duration_ms": 500,
"minimum_player_level": 5,
"swap_duration_ms": 1000
}),
encounter_settings: new proto.Settings.Master.EncounterSettings({
"spin_bonus_threshold": 0.5,
"excellent_throw_threshold": 1.7000000476837158,
"great_throw_threshold": 1.2999999523162842,
"nice_throw_threshold": 1,
"milestone_threshold": 100
}),
iap_item_display: null, // seems like useless??
iap_settings: new proto.Settings.Master.IapSettings({
"daily_bonus_coins": 0,
"daily_defender_bonus_per_pokemon": [500, 10],
"daily_defender_bonus_max_defenders": 10,
"daily_defender_bonus_currency": ["STARDUST", "POKECOIN"],
"min_time_between_claims_ms": 0,
"daily_bonus_enabled": false,
"daily_defender_bonus_enabled": true
}),
pokemon_upgrades: new proto.Settings.Master.PokemonUpgradeSettings({
"upgrades_per_level": 2,
"allowed_levels_above_player": 2,
"candy_cost": [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 4, 4, 4, 4, 4, 6, 6, 8, 8, 10, 10, 12, 12, 15, 15],
"stardust_cost": [200, 200, 400, 400, 600, 600, 800, 800, 1000, 1000, 1300, 1300, 1600, 1600, 1900, 1900, 2200, 2200, 2500, 2500, 3000, 3000, 3500, 3500, 4000, 4000, 4500, 4500, 5000, 5000, 6000, 6000, 7000, 7000, 8000, 8000, 9000, 9000, 10000, 10000]
}),
equipped_badges: null // seems like unused
}),
timestamp_ms: 1468540960537
}).encode()
);
}

View File

@ -5,6 +5,11 @@ 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 ItemTemplates from "./Responses.ItemTemplates";
export CheckAwardedBadges from "./Responses.CheckAwardedBadges";
export AuthTicket from "./Envelopes.AuthTicket";
export ResponseEnvelope from "./Envelopes.ResponseEnvelope";
export ResponseEnvelope from "./Envelopes.ResponseEnvelope";
export ResponseEnvelopeAuth from "./Envelopes.ResponseEnvelope.Auth";

View File

@ -1,18 +1,98 @@
import proto from "./proto";
import * as CFG from "../cfg";
export function killPlayer(player) {
import {
getHashCodeFrom,
decodeRequestEnvelope
} from "./utils";
let index = this.getPlayerIndex(player);
/**
* @class Player
*/
class Player {
/** @constructor */
constructor(obj) {
this.uid = -1;
this.name = null;
this.email = null;
this.position = {
latitude: 0,
longitude: 0,
altitude: 0
};
this.exp = 0;
this.stardust = 0;
this.pokecoins = 0;
this.avatar = null;
this.badges = null;
this.pokedex = null;
this.inventory = null;
this.response = obj.response;
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;
if (index >= 0) {
this.clients.splice(index, 1);
}
else {
this.print("Failed at killing player", 33);
/**
* @param {String} email
*/
generateUid(email) {
this.uid = getHashCodeFrom(String(email));
}
/**
* @param {Request} req
*/
updatePosition(req) {
let data = decodeRequestEnvelope(req.request_message.buffer);
this.latitude = data.latitude;
this.longitude = data.longitude;
//this.position.altitude = data.altitude;
//console.log(`Updated position: ${data.latitude};${data.longitude}`);
}
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;
}
}
/**
* @param {Player} player
*/
export function getPlayerIndex(player) {
let ip = player.remoteAddress;
@ -31,12 +111,18 @@ export function getPlayerIndex(player) {
}
/**
* @param {Request} req
*/
export function getPlayerByRequest(req) {
return (
this.getPlayerByIP(req.connection.remoteAddress)
);
}
/**
* @param {String} ip
*/
export function getPlayerByIP(ip) {
let ii = 0, length = this.clients.length;
@ -51,15 +137,35 @@ export function getPlayerByIP(ip) {
}
/**
* @param {Request} connection
*/
export function addPlayer(connection) {
this.clients.push({
name: "rofl",
this.clients.push(new Player({
timeout: this.time,
connection: connection,
response: this.response,
remotePort: connection.remotePort,
remoteAddress: connection.remoteAddress,
connection: connection
});
remoteAddress: connection.remoteAddress
}));
}
/**
* @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);
}
else {
this.print("Failed at removing player", 33);
}
}
@ -69,6 +175,14 @@ export function updatePlayers() {
}
export function savePlayers() {
this.print("Saving players into database");
this.print("Saving players into database..");
return void 0;
}
/**
* @param {Player} player
*/
export function savePlayer(player) {
this.print(`${player.remoteAddress} saved into database`, 34);
return void 0;
}

View File

@ -1,10 +1,11 @@
import * as CFG from "../cfg";
function processCommand(cmd, data) {
export function processCommand(cmd, data) {
switch (cmd) {
// How many active connections there are
case "/clients":
this.print("There are many connected players!", 33);
let length = this.clients.length;
this.print(`${length} connected player${length === 1 ? "": "s"}!`, 33);
break;
// Kill the server
case "/exit":
@ -19,7 +20,7 @@ export function stdinInput(data) {
if (data.length < 1) return void 0;
data = data.split(" ");
var cmd = data[0];
processCommand();
this.processCommand(cmd, data);
};
export function uncaughtException(excp) {

View File

@ -1,3 +1,5 @@
import proto from "./proto";
/**
* @param {Object} cls
* @param {Object} prot
@ -13,4 +15,29 @@ 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
* @return {String}
*/
export function getHashCodeFrom(str) {
var hash = 0, i, chr, len;
if (str.length === 0) return hash;
for (i = 0, len = str.length; i < len; i++) {
chr = str.charCodeAt(i);
hash = ((hash << 5) - hash) + chr;
hash |= 0; // Convert to 32bit integer
}
return hash;
};