Initial commit
This commit is contained in:
@@ -0,0 +1,325 @@
|
||||
"use strict";
|
||||
|
||||
// console.info = () => null;
|
||||
// console.trace = () => null;
|
||||
console.log = () => null;
|
||||
|
||||
global.socket = require("uWebSockets.js");
|
||||
global.app = socket.App();
|
||||
global.playerBehaviourContext = [];
|
||||
socket.sockets = {};
|
||||
|
||||
const { register } = require("./metrics");
|
||||
|
||||
require("./Routes/Routes");
|
||||
require("./Utility/setTimer");
|
||||
require("./Miscellaneous/mysql");
|
||||
|
||||
const MainLoop = require("./Core");
|
||||
const LeaderboardLoop = require("./Timers/Leaderboard");
|
||||
const BehaviourLoop = require("./Timers/Behaviour");
|
||||
const ResourceLoop = require("./Timers/Resource");
|
||||
|
||||
const { Worker } = require("worker_threads");
|
||||
global.PlayerWorker = new Worker("./Worker/Player.js");
|
||||
global.NPCWorker = new Worker("./Worker/NPC.js");
|
||||
global.StatisticsWorker = new Worker("./Worker/Statistics.js");
|
||||
|
||||
const messageHandler = require("./Events/message");
|
||||
const closeHandler = require("./Events/close");
|
||||
const openHandler = require("./Events/open");
|
||||
const drainHandler = require("./Events/drain");
|
||||
const upgradeHandler = require("./Events/upgrade");
|
||||
|
||||
const Game = require("./Game/Game");
|
||||
const Guild = require("./Game/Guild");
|
||||
const GuildIsland = require("./Game/GuildIsland");
|
||||
|
||||
const leaderboards = require("./Data/leaderboard");
|
||||
const queries = require("./Data/queries");
|
||||
const BASE_SHOP = require("./Data/shop");
|
||||
|
||||
const { SHOP } = BASE_SHOP;
|
||||
|
||||
const formatMemoryUsage = data => `${Math.round(data / 1024 / 1024 * 100) / 100} MB`;
|
||||
|
||||
function log(level, message) {
|
||||
const LOG_LEVELS = {
|
||||
"OK": "32",
|
||||
"FATAL": "31"
|
||||
};
|
||||
|
||||
console.info(`[\x1b[33m%s\x1b[0m] \x1b[${LOG_LEVELS[level]}m%s\x1b[0m`, level, message);
|
||||
};
|
||||
|
||||
function scheduleGc() {
|
||||
setTimeout(() => {
|
||||
let pn = performance.now();
|
||||
global.gc();
|
||||
console.info(performance.now() - pn);
|
||||
/*
|
||||
const memoryData = process.memoryUsage();
|
||||
const memoryUsage = {
|
||||
rss: `${formatMemoryUsage(memoryData.rss)} -> Resident Set Size - total memory allocated for the process execution`,
|
||||
heapTotal: `${formatMemoryUsage(memoryData.heapTotal)} -> total size of the allocated heap`,
|
||||
heapUsed: `${formatMemoryUsage(memoryData.heapUsed)} -> actual memory used during the execution`,
|
||||
external: `${formatMemoryUsage(memoryData.external)} -> V8 external memory`,
|
||||
arrayBuffers: `${formatMemoryUsage(memoryData.arrayBuffers)} -> arraybuffers`,
|
||||
};*/
|
||||
|
||||
// process.exit(1);
|
||||
scheduleGc();
|
||||
}, 600000);
|
||||
};
|
||||
|
||||
scheduleGc();
|
||||
|
||||
const promise = new Promise(async (resolve, reject) => {
|
||||
leaderboards.forEach(async (leaderboard, i) => {
|
||||
const databaseName = `leaderboard_${i + 1}`;
|
||||
const leaderboardSizeFromDB = await execute(`SELECT COUNT(*) AS count FROM ${databaseName}`);
|
||||
if (!leaderboardSizeFromDB.data) return reject(leaderboardSizeFromDB.message);
|
||||
// I don't think this is good
|
||||
leaderboard.size = leaderboardSizeFromDB.data[0].count;
|
||||
});
|
||||
|
||||
const shopEntries = await execute(queries.QUERY_FETCH_SHOP_ENTRIES);
|
||||
if (!shopEntries.data) return reject(shopEntries.error);
|
||||
|
||||
shopEntries.data.forEach(entry => {
|
||||
const shopEntry = {
|
||||
id: entry.id,
|
||||
itemID: entry.itemID,
|
||||
categoryID: entry.categoryID,
|
||||
currencyType: entry.currencyType,
|
||||
currencyAmount: entry.currencyAmount,
|
||||
unit: entry.unit,
|
||||
shopCategoryID: 2,
|
||||
isAvailable: () => true
|
||||
};
|
||||
|
||||
SHOP.push(shopEntry);
|
||||
});
|
||||
|
||||
console.info(SHOP)
|
||||
|
||||
const guildResources = await execute(queries.QUERY_FETCH_GUILD_RESOURCES);
|
||||
if (!guildResources.data) return reject(guildResources.error);
|
||||
|
||||
const guildDiplomacies = await execute(queries.QUERY_FETCH_GUILD_DIPLOMACIES);
|
||||
if (!guildDiplomacies.data) return reject(guildDiplomacies.error);
|
||||
|
||||
const guildRequests = await execute(queries.QUERY_FETCH_GUILD_REQUESTS);
|
||||
if (!guildRequests.data) return reject(guildRequests.error);
|
||||
|
||||
const guildMembers = await execute(queries.QUERY_FETCH_GUILD_MEMBERS);
|
||||
if (!guildMembers.data) return reject(guildMembers.error);
|
||||
|
||||
const guildIslandsFromDB = await execute(queries.QUERY_FETCH_GUILD_ISLANDS);
|
||||
if (!guildIslandsFromDB.data) return reject(guildIslandsFromDB.error);
|
||||
|
||||
const guildIslandDamagesFromDB = await execute(queries.QUERY_FETCH_GUILD_ISLAND_DAMAGES);
|
||||
if (!guildIslandDamagesFromDB.data) return reject(guildIslandDamagesFromDB.error);
|
||||
|
||||
const islands = guildIslandsFromDB.data.reduce((acc, cur) => {
|
||||
if (acc[cur.guildID]) acc[cur.guildID].push(cur);
|
||||
else acc[cur.guildID] = [cur];
|
||||
|
||||
return acc;
|
||||
}, {})
|
||||
|
||||
guildMembers.data.forEach(entry => {
|
||||
let guild = Game.guilds[entry.id];
|
||||
if (!guild) {
|
||||
console.info("Guild", entry.id, entry.name, entry.tag)
|
||||
guild = Game.guilds[entry.id] = new Guild({
|
||||
id: entry.id,
|
||||
name: entry.name,
|
||||
tag: entry.tag,
|
||||
description: entry.description,
|
||||
ownerID: entry.createdBy,
|
||||
experiencePoints: entry.experiencePoints,
|
||||
taxRates: [entry.taxRateGold, entry.taxRateEmerald],
|
||||
timestamps: {
|
||||
taxRatesEditedAt: new Date(entry.taxRatesEditedAt).getTime() / 1000,
|
||||
tagEditedAt: new Date(entry.tagEditedAt).getTime() / 1000,
|
||||
nameEditedAt: new Date(entry.nameEditedAt).getTime() / 1000,
|
||||
descriptionEditedAt: new Date(entry.descriptionEditedAt).getTime() / 1000
|
||||
}
|
||||
});
|
||||
|
||||
const currentGuildIslands = islands[entry.id];
|
||||
if (currentGuildIslands) {
|
||||
for (let i = 0, length = currentGuildIslands.length; i < length; i++) {
|
||||
const currentIsland = currentGuildIslands[i];
|
||||
|
||||
const island = new GuildIsland({
|
||||
id: currentIsland.id,
|
||||
locationMapID: currentIsland.mapID,
|
||||
index: currentIsland.gindex,
|
||||
position: {
|
||||
x: currentIsland.positionX,
|
||||
y: currentIsland.positionY
|
||||
},
|
||||
guild
|
||||
});
|
||||
|
||||
Game.guildIslands.push(island);
|
||||
|
||||
const islandCaptureProgress = guildIslandDamagesFromDB.data.find(e => e.guildIslandID === currentIsland.id);
|
||||
if (islandCaptureProgress) island.updateReceivedDamage(islandCaptureProgress.guildID, islandCaptureProgress.damage);
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
const member = {
|
||||
id: entry.playerID,
|
||||
permission: entry.permission
|
||||
};
|
||||
|
||||
guild.addMember(member);
|
||||
});
|
||||
|
||||
guildResources.data.forEach(entry => {
|
||||
const guild = Game.guilds[entry.guildID];
|
||||
switch (entry.categoryID) {
|
||||
case 1:
|
||||
console.info("guild resource startup", entry)
|
||||
guild.bank.depositTax(entry);
|
||||
break;
|
||||
|
||||
case 6:
|
||||
if (entry.id === 1) {
|
||||
guild.levelUpdate(entry.amount);
|
||||
console.info("LEVEL UPDATE", entry, guild.level, guild.experiencePoints)
|
||||
};
|
||||
break;
|
||||
};
|
||||
});
|
||||
|
||||
guildDiplomacies.data.forEach(entry => {
|
||||
// console.info(entry, Game.guilds[entry.guildID])
|
||||
const guild = Game.guilds[entry.guildID];
|
||||
guild.diplomacy[entry.targetGuildID] = entry.color;
|
||||
});
|
||||
|
||||
guildRequests.data.forEach(entry => {
|
||||
const guild = Game.guilds[entry.id];
|
||||
const arrayBufferMessage = new ArrayBuffer(entry.message.length);
|
||||
const convertedMessage = new Uint8Array(arrayBufferMessage);
|
||||
|
||||
for (let i = 0, strLen = entry.message.length; i < strLen; i++) {
|
||||
arrayBufferMessage[i] = entry.message.charCodeAt(i);
|
||||
};
|
||||
|
||||
guild.addRequest(entry.playerID, arrayBufferMessage);
|
||||
});
|
||||
|
||||
resolve();
|
||||
});
|
||||
|
||||
promise.then(() => {
|
||||
app.ws("/ws", {
|
||||
idleTimeout: 50,
|
||||
maxBackpressure: 1024,
|
||||
maxPayloadLength: 512,
|
||||
compression: socket.DISABLED,
|
||||
upgrade: upgradeHandler,
|
||||
close: closeHandler,
|
||||
open: openHandler,
|
||||
drain: drainHandler,
|
||||
message: messageHandler
|
||||
});
|
||||
|
||||
app.get("/selection/:playerID", async (res, req) => {
|
||||
const playerID = req.getParameter(0);
|
||||
|
||||
res.onAborted(() => {
|
||||
console.info("ABORTED!!!");
|
||||
});
|
||||
|
||||
const playerQuery = await execute("SELECT designID, globalRank, levelRank, mapID FROM playerdata WHERE playerID = ?", [playerID])
|
||||
console.info(playerQuery)
|
||||
if (!playerQuery.success) {
|
||||
console.info("t", playerQuery)
|
||||
res.cork(() => res.end(JSON.stringify({ ok: false })));
|
||||
|
||||
return;
|
||||
};
|
||||
|
||||
if (!playerQuery.data[0])
|
||||
playerQuery.data[0] = {
|
||||
server: process.env.GAME_SERVER
|
||||
};
|
||||
else playerQuery.data[0].server = process.env.GAME_SERVER;
|
||||
|
||||
res.cork(() => res.end(JSON.stringify(playerQuery.data[0])));
|
||||
});
|
||||
|
||||
app.get("/metrics", async (res, req) => {
|
||||
res.writeHeader("Content-Type", register.contentType);
|
||||
|
||||
const metrics = await register.metrics();
|
||||
res.end(metrics);
|
||||
});
|
||||
|
||||
app.listen("0.0.0.0", 9001, listenSocket => {
|
||||
if (!listenSocket) {
|
||||
log("FATAL", "Coudln't initialize listening to connections!");
|
||||
|
||||
process.exit();
|
||||
};
|
||||
|
||||
require("./Handlers/Map");
|
||||
|
||||
MainLoop();
|
||||
LeaderboardLoop();
|
||||
BehaviourLoop();
|
||||
ResourceLoop();
|
||||
|
||||
Game.listeningServer = listenSocket;
|
||||
|
||||
log("OK", "Server is successfully initialized and is listening on *:9001!");
|
||||
if (Game.state === 0) log("OK", `Game is running in restricted mode. To let players in, set game state to be 1.`);
|
||||
});
|
||||
}).catch(e => {
|
||||
log("FATAL", "Couldn't initialize server, application error!", e);
|
||||
console.info(e);
|
||||
|
||||
process.exit();
|
||||
});
|
||||
|
||||
|
||||
/*
|
||||
process.on("exit", function (code) {
|
||||
console.log("exit", code)
|
||||
});
|
||||
|
||||
["beforeExit", "uncaughtException", "unhandledRejection", "SIGHUP", "SIGINT", "SIGQUIT", "SIGILL", "SIGTRAP", "SIGABRT" ,"SIGBUS", "SIGFPE", "SIGUSR1", "SIGSEGV", "SIGUSR2", "SIGTERM"]
|
||||
.forEach(sig => {
|
||||
process.on(sig, function (reason) {
|
||||
if (sig === "uncaughtException" || sig === "unhandledRejection") console.log(reason);
|
||||
|
||||
terminator(sig);
|
||||
console.log("signal: " + sig);
|
||||
});
|
||||
});
|
||||
|
||||
function terminator(sig) {
|
||||
if (typeof sig === "string") {
|
||||
socket.us_listen_socket_close(listeningServer);
|
||||
listeningServer = null;
|
||||
|
||||
Game.disconnectAll();
|
||||
|
||||
setTimeout(() => {
|
||||
console.log(process.argv[0], process.argv.slice(1))
|
||||
|
||||
process.exit(1);
|
||||
}, 5000);
|
||||
};
|
||||
|
||||
console.log("Server has been stopped!");
|
||||
};*/
|
||||
|
||||
|
||||
Reference in New Issue
Block a user