This commit is contained in:
Felix 2016-08-06 13:56:54 +02:00
parent 2899d78469
commit 9cdbe5686c
13 changed files with 289 additions and 85 deletions

2
.gitattributes vendored
View File

@ -13,4 +13,4 @@
# Explicitly specify language for non-standard extensions used under
# ide/web/lib/templates to make GitHub correctly count their language stats.
#
*.js_ linguist-language=JavaScript
*.js_ linguist-language=JavaScript

View File

@ -13,4 +13,5 @@ TODO:
- [ ] Database
- [ ] Player objects
- [ ] Map server
- [ ] Receive GPS data
- [ ] Receive GPS data# POGOServer
Pokemon GO server emulation

4
cfg.js
View File

@ -1,9 +1,11 @@
export const SERVER_PORT = 3000;
export const SERVER_HOST_IP = "127.0.0.1";
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_DEFAULT_CONSOLE_COLOR = 32;
export const ASSET_DIGEST_PATH = "../../asset_digest";
export const ASSET_DIGEST_PATH = "asset_digest";

View File

@ -29,7 +29,7 @@ export function cycle() {
}
export function updateTimers() {
let local = new Date();
let local = Date.now();
this.passedTicks = local - this.time;
this.tick += this.passedTicks;
this.time = local;
@ -43,11 +43,31 @@ export function resetTimers() {
this.fullTick = 0;
}
this.tick = 0;
// Player timeout tick, not precise
this.playerTimeoutTick();
}
this.saveTick++;
// Save interval
if (this.saveTick >= CFG.SERVER_SAVE_INTERVAL) {
this.savePlayers();
this.saveTick = 0;
}
return void 0;
}
export function playerTimeoutTick() {
let client = null;
let maxTimeout = CFG.SERVER_PLAYER_CONNECTION_TIMEOUT;
let ii = 0, length = this.clients.length;
for (; ii < length; ++ii) {
client = this.clients[ii];
if (this.time - client.timeout >= maxTimeout) {
this.print(`${client.remoteAddress} timed out!`, 36);
this.killPlayer(client);
}
};
}

View File

@ -6,10 +6,11 @@ import querystring from "querystring";
import { inherit } from "./utils";
import * as CFG from "../cfg";
import { REQUEST } from "../requests";
import * as _setup from "./setup";
import * as _cycle from "./cycle";
import * as _player from "./player";
import * as _request from "./request";
import * as _process from "./process";
import * as _database from "./database";
@ -38,45 +39,55 @@ class GameServer {
this.time = 0;
this.fullTick = 0;
this.saveTick = 0;
this.timeoutTick = 0;
this.passedTicks = 0;
this.clients = [];
this.setup();
}
clientAlreadyConnected(client) {
let remoteAddress = client.connection.remoteAddress;
let ii = 0, length = this.clients.length;
for (; ii < length; ++ii) {
if (this.clients[ii].remoteAddress === remoteAddress) {
return (true);
}
};
return (false);
}
createHTTPServer() {
this.socket = http.createServer((req) => {
let server = http.createServer((req, res) => {
if (!this.clientAlreadyConnected(req)) {
this.print(`${req.connection.remoteAddress} connected!`, 36);
this.addPlayer(req.connection);
}
let chunks = [];
req.on("data", (chunk) => {
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);
this.onRequest(buffer);
req.body = buffer;
this.onRequest(req, res);
});
}).listen(CFG.SERVER_PORT);
}
});
server.listen(CFG.SERVER_PORT, CFG.SERVER_HOST_IP, () => {
/**
* @param {Buffer} body
*/
onRequest(body) {
let request = proto.Networking.Envelopes.RequestEnvelope.decode(body);
console.log("Got request");
console.log("Received:", request.requests.map((request) => {
return request.request_type;
}).join(","));
}
/**
* @param {Request} req
* @return {Boolean}
*/
validRequest(req) {
return (true);
});
return (server);
}
/**
@ -88,59 +99,12 @@ class GameServer {
console.log(`\x1b[${color};1m${msg}\x1b[0m`);
}
/**
* @param {Request} req
*/
answer(req) {
switch (req.request_type) {
// #LOGIN START
case REQUEST.GET_PLAYER:
break;
case REQUEST.GET_HATCHED_EGGS:
break;
case REQUEST.GET_INVENTORY:
break;
case REQUEST.CHECK_AWARDED_BADGES:
break;
case REQUEST.DOWNLOAD_SETTINGS:
break;
case REQUEST.DOWNLOAD_ITEM_TEMPLATES:
break;
// #LOGIN END
case REQUEST.GET_PLAYER_PROFILE:
break;
case REQUEST.GET_MAP_OBJECTS:
break;
case REQUEST.GET_GYM_DETAILS:
break;
};
}
updatePlayers() {
//this.print("Updating players");
return void 0;
}
savePlayers() {
this.print("Saving players into database");
return void 0;
}
}
inherit(GameServer, _setup);
inherit(GameServer, _cycle);
inherit(GameServer, _player);
inherit(GameServer, _request);
inherit(GameServer, _process);
inherit(GameServer, _database);

View File

@ -0,0 +1,23 @@
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,
response_data: new proto.Networking.Envelopes.Unknown6Response.Unknown2({
unknown1: 1
})
}),
request_id: obj.id,
returns: obj.res
})
);
}

View File

@ -9,7 +9,7 @@ export default function DownloadRemoteConfigVersion(obj) {
return (
new proto.Networking.Responses.DownloadSettingsResponse({
hash: "54b359c97e46900f87211ef6e6dd0b7f2a3ea1f5"
}).encode();
}).encode()
);
}

View File

@ -8,8 +8,8 @@ export default function DownloadSettings(obj) {
return (
new proto.Networking.Responses.DownloadSettingsResponse({
hash: "54b359c97e46900f87211ef6e6dd0b7f2a3ea1f5"
}).encode();
hash: "b1f2bf509a025b7cd76e1c484e2a24411c50f0612"
}).encode()
);
}

View File

@ -1,4 +1,4 @@
import * as CFG from "../cfg";
import * as CFG from "../../cfg";
import proto from "../proto";
@ -9,7 +9,7 @@ import proto from "../proto";
export default function GetAssetDigest(obj) {
return (
fs.readFileSync(CFG.ASSET_DIGEST_PATH)
fs.readFileSync("../../" + CFG.ASSET_DIGEST_PATH)
);
}

View File

@ -4,4 +4,7 @@ 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 GetPlayer from "./Responses.GetPlayer";
export AuthTicket from "./Envelopes.AuthTicket";
export ResponseEnvelope from "./Envelopes.ResponseEnvelope";

74
src/player.js Normal file
View File

@ -0,0 +1,74 @@
import * as CFG from "../cfg";
export function killPlayer(player) {
let index = this.getPlayerIndex(player);
if (index >= 0) {
this.clients.splice(index, 1);
}
else {
this.print("Failed at killing player", 33);
}
}
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);
}
export function getPlayerByRequest(req) {
return (
this.getPlayerByIP(req.connection.remoteAddress)
);
}
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);
}
export function addPlayer(connection) {
this.clients.push({
name: "rofl",
timeout: this.time,
remotePort: connection.remotePort,
remoteAddress: connection.remoteAddress,
connection: connection
});
}
export function updatePlayers() {
//this.print("Updating players");
return void 0;
}
export function savePlayers() {
this.print("Saving players into database");
return void 0;
}

117
src/request.js Normal file
View File

@ -0,0 +1,117 @@
import proto from "./proto";
import * as CFG from "../cfg";
import { REQUEST } from "../requests";
import { ResponseEnvelope, AuthTicket, GetPlayer } from "./packets";
/**
* @param {Buffer} body
*/
export function decodeRequestBody(body) {
return (
proto.Networking.Envelopes.RequestEnvelope.decode(body)
);
}
/**
* @param {Request} req
* @param {Response} res
*/
export function onRequest(req, res) {
let request = this.decodeRequestBody(req.body);
console.log("Got request");
console.log("Received:", request.requests.map((request) => {
return request.request_type;
}).join(","));
let answer = this.processRequests(request);
//res.send(answer);
}
/**
* @param {Request} req
* @return {Array}
*/
export function processRequests(req) {
let ii = 0;
let length = req.requests.length;
let body = [];
for (; ii < length; ++ii) {
body.push(this.processRequest(req.requests[ii]));
};
return (body);
}
export function decodeBuffer(buffer) {
let auth = proto.Networking.Envelopes.RequestEnvelope.decode(buffer);
//console.log(auth);
}
/**
* @param {Request} req
* @return {Object}
*/
export function processRequest(req) {
switch (req.request_type) {
// #LOGIN START
case REQUEST.GET_PLAYER:
this.decodeBuffer(req.request_message.buffer);
return (
GetPlayer({
username: "Felix",
team: 2,
pokecoins: 500,
stardust: 32500
})
);
break;
case REQUEST.GET_HATCHED_EGGS:
break;
case REQUEST.GET_INVENTORY:
break;
case REQUEST.CHECK_AWARDED_BADGES:
break;
case REQUEST.DOWNLOAD_SETTINGS:
break;
case REQUEST.DOWNLOAD_ITEM_TEMPLATES:
break;
// #LOGIN END
case REQUEST.GET_PLAYER_PROFILE:
break;
case REQUEST.GET_MAP_OBJECTS:
break;
case REQUEST.GET_GYM_DETAILS:
break;
};
}
/**
* @param {Request} req
* @return {Boolean}
*/
export function validRequest(req) {
return (true);
}

View File

@ -15,6 +15,6 @@ export function setup() {
setTimeout(this::this.cycle, 1);
this.print("Server listening on port " + CFG.SERVER_PORT);
this.print(`Server running at ${CFG.SERVER_HOST_IP}:${CFG.SERVER_PORT}`);
}