2022-01-10 12:54:07 +00:00
|
|
|
/*
|
|
|
|
* Entrypoint for main server script
|
|
|
|
*/
|
2020-01-02 16:58:06 +00:00
|
|
|
|
2020-01-14 16:42:18 +00:00
|
|
|
import url from 'url';
|
2020-01-02 16:58:06 +00:00
|
|
|
import compression from 'compression';
|
|
|
|
import express from 'express';
|
|
|
|
import http from 'http';
|
|
|
|
|
|
|
|
import forceGC from './core/forceGC';
|
|
|
|
import logger from './core/logger';
|
2022-09-13 14:09:38 +00:00
|
|
|
import rankings from './core/Ranks';
|
2022-06-19 21:19:10 +00:00
|
|
|
import sequelize from './data/sql/sequelize';
|
|
|
|
import { connect as connectRedis } from './data/redis/client';
|
2022-01-10 12:54:07 +00:00
|
|
|
import routes from './routes';
|
2020-11-03 22:43:51 +00:00
|
|
|
import chatProvider from './core/ChatProvider';
|
2022-06-30 13:06:36 +00:00
|
|
|
import rpgEvent from './core/RpgEvent';
|
2022-04-06 19:50:34 +00:00
|
|
|
import canvasCleaner from './core/CanvasCleaner';
|
2020-01-02 16:58:06 +00:00
|
|
|
|
2022-09-09 22:35:28 +00:00
|
|
|
import socketEvents from './socket/socketEvents';
|
2020-01-14 16:42:18 +00:00
|
|
|
import SocketServer from './socket/SocketServer';
|
|
|
|
import APISocketServer from './socket/APISocketServer';
|
|
|
|
|
2022-09-09 22:35:28 +00:00
|
|
|
import {
|
|
|
|
PORT, HOST, HOURLY_EVENT, SHARD_NAME,
|
|
|
|
} from './core/config';
|
2022-01-10 12:54:07 +00:00
|
|
|
import { SECOND } from './core/constants';
|
2020-01-02 16:58:06 +00:00
|
|
|
|
2022-09-09 22:35:28 +00:00
|
|
|
import startAllCanvasLoops from './core/tileserver';
|
2020-01-02 16:58:06 +00:00
|
|
|
|
|
|
|
const app = express();
|
|
|
|
app.disable('x-powered-by');
|
|
|
|
|
|
|
|
|
|
|
|
// Call Garbage Collector every 30 seconds
|
2022-04-04 20:52:45 +00:00
|
|
|
setInterval(forceGC, 10 * 60 * SECOND);
|
2020-01-02 16:58:06 +00:00
|
|
|
|
2020-01-14 16:42:18 +00:00
|
|
|
// create http server
|
2020-01-02 16:58:06 +00:00
|
|
|
const server = http.createServer(app);
|
2020-01-14 16:42:18 +00:00
|
|
|
|
|
|
|
//
|
|
|
|
// websockets
|
|
|
|
// -----------------------------------------------------------------------------
|
|
|
|
const usersocket = new SocketServer();
|
|
|
|
const apisocket = new APISocketServer();
|
|
|
|
function wsupgrade(request, socket, head) {
|
|
|
|
const { pathname } = url.parse(request.url);
|
|
|
|
|
|
|
|
if (pathname === '/ws') {
|
2022-09-03 21:36:22 +00:00
|
|
|
usersocket.handleUpgrade(request, socket, head);
|
2020-01-14 16:42:18 +00:00
|
|
|
} else if (pathname === '/mcws') {
|
2022-09-03 21:36:22 +00:00
|
|
|
apisocket.handleUpgrade(request, socket, head);
|
2020-01-14 16:42:18 +00:00
|
|
|
} else {
|
|
|
|
socket.destroy();
|
|
|
|
}
|
|
|
|
}
|
2020-01-02 16:58:06 +00:00
|
|
|
server.on('upgrade', wsupgrade);
|
|
|
|
|
|
|
|
/*
|
|
|
|
* use gzip compression for following calls
|
|
|
|
/* level from -1 (default, 6) to 0 (no) from 1 (fastest) to 9 (best)
|
|
|
|
* Set custon filter to make sure that .bmp files get compressed
|
|
|
|
*/
|
2020-01-04 06:00:47 +00:00
|
|
|
app.use(compression({
|
|
|
|
level: 3,
|
2020-01-02 16:58:06 +00:00
|
|
|
filter: (req, res) => {
|
|
|
|
if (res.getHeader('Content-Type') === 'application/octet-stream') {
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
return compression.filter(req, res);
|
2020-01-04 06:00:47 +00:00
|
|
|
},
|
|
|
|
}));
|
2020-01-02 16:58:06 +00:00
|
|
|
|
2022-01-10 12:54:07 +00:00
|
|
|
app.use(routes);
|
2020-01-02 16:58:06 +00:00
|
|
|
|
|
|
|
//
|
|
|
|
// ip config
|
|
|
|
// -----------------------------------------------------------------------------
|
2022-04-06 19:50:34 +00:00
|
|
|
// sync sql models
|
2022-06-19 21:19:10 +00:00
|
|
|
sequelize.sync({ alter: { drop: false } })
|
2022-04-06 19:50:34 +00:00
|
|
|
// connect to redis
|
2022-06-19 21:19:10 +00:00
|
|
|
.then(connectRedis)
|
2022-09-09 22:35:28 +00:00
|
|
|
.then(async () => {
|
2022-04-05 19:37:33 +00:00
|
|
|
chatProvider.initialize();
|
|
|
|
startAllCanvasLoops();
|
|
|
|
usersocket.initialize();
|
|
|
|
apisocket.initialize();
|
2022-04-06 19:50:34 +00:00
|
|
|
canvasCleaner.initialize();
|
|
|
|
// start http server
|
|
|
|
const startServer = () => {
|
|
|
|
server.listen(PORT, HOST, () => {
|
|
|
|
logger.log(
|
|
|
|
'info',
|
|
|
|
`HTTP Server listening on port ${PORT}`,
|
|
|
|
);
|
|
|
|
});
|
|
|
|
};
|
|
|
|
startServer();
|
|
|
|
// catch errors of server
|
|
|
|
server.on('error', (e) => {
|
|
|
|
logger.error(
|
|
|
|
`HTTP Server Error ${e.code} occured, trying again in 5s...`,
|
2022-04-05 19:37:33 +00:00
|
|
|
);
|
2022-04-06 19:50:34 +00:00
|
|
|
setTimeout(() => {
|
|
|
|
server.close();
|
|
|
|
startServer();
|
|
|
|
}, 5000);
|
2022-04-05 19:37:33 +00:00
|
|
|
});
|
2022-09-09 22:35:28 +00:00
|
|
|
})
|
|
|
|
.then(async () => {
|
|
|
|
await socketEvents.initialize();
|
|
|
|
})
|
|
|
|
.then(async () => {
|
|
|
|
/*
|
|
|
|
* initializers that rely on the cluster being fully established
|
|
|
|
* i.e. to know if it is the shard that runs the event
|
|
|
|
*/
|
|
|
|
if (socketEvents.isCluster && socketEvents.amIImportant()) {
|
|
|
|
logger.info('I am the main shard');
|
|
|
|
}
|
|
|
|
rankings.initialize();
|
|
|
|
if (HOURLY_EVENT && !SHARD_NAME) {
|
|
|
|
// TODO make it wok in a cluster
|
|
|
|
logger.info('Initializing RpgEvent');
|
|
|
|
rpgEvent.initialize();
|
|
|
|
}
|
2020-01-02 16:58:06 +00:00
|
|
|
});
|