pokemon-showdown/server/index.js
2019-08-29 19:46:42 -05:00

158 lines
4.8 KiB
JavaScript

/**
* Main file
* Pokemon Showdown - http://pokemonshowdown.com/
*
* This is the main Pokemon Showdown app, and the file you should be
* running to start Pokemon Showdown if you're using it normally.
*
* This file sets up our SockJS server, which handles communication
* between users and your server, and also sets up globals. You can
* see details in their corresponding files, but here's an overview:
*
* Users - from users.js
*
* Most of the communication with users happens in users.js, we just
* forward messages between the sockets.js and users.js.
*
* Rooms - from rooms.js
*
* Every chat room and battle is a room, and what they do is done in
* rooms.js. There's also a global room which every user is in, and
* handles miscellaneous things like welcoming the user.
*
* Dex - from .sim-dist/dex.js
*
* Handles getting data about Pokemon, items, etc.
*
* Ladders - from ladders.js and ladders-remote.js
*
* Handles Elo rating tracking for players.
*
* Chat - from chat.js
*
* Handles chat and parses chat commands like /me and /ban
*
* Sockets - from sockets.js
*
* Used to abstract out network connections. sockets.js handles
* the actual server and connection set-up.
*
* @license MIT
*/
'use strict';
// NOTE: This file intentionally doesn't use too many modern JavaScript
// features, so that it doesn't crash old versions of Node.js, so we
// can successfully print the "We require Node.js 8+" message.
// Check for version and dependencies
try {
// I've gotten enough reports by people who don't use the launch
// script that this is worth repeating here
RegExp("\\p{Emoji}", "u");
} catch (e) {
throw new Error("We require Node.js version 10 or later; you're using " + process.version);
}
try {
require.resolve('../.sim-dist/index');
} catch (e) {
throw new Error("Dependencies are unmet; run `node build` before launching Pokemon Showdown again.");
}
const FS = require('../.lib-dist/fs').FS;
/*********************************************************
* Load configuration
*********************************************************/
const ConfigLoader = require('../.server-dist/config-loader');
global.Config = ConfigLoader.Config;
global.Monitor = require('../.server-dist/monitor').Monitor;
global.__version = {head: ''};
Monitor.version().then(function (hash) {
global.__version.tree = hash;
});
if (Config.watchconfig) {
FS(require.resolve('../config/config')).onModify(() => {
try {
global.Config = ConfigLoader.load(true);
if (global.Users) Users.cacheGroupData();
Monitor.notice('Reloaded ../config/config.js');
} catch (e) {
Monitor.adminlog("Error reloading ../config/config.js: " + e.stack);
}
});
}
/*********************************************************
* Set up most of our globals
*********************************************************/
global.Dex = require('../.sim-dist/dex').Dex;
global.toID = Dex.getId;
global.LoginServer = require('../.server-dist/loginserver').LoginServer;
global.Ladders = require('../.server-dist/ladders').Ladders;
global.Chat = require('../.server-dist/chat').Chat;
global.Users = require('../.server-dist/users').Users;
global.Punishments = require('../.server-dist/punishments').Punishments;
global.Rooms = require('../.server-dist/rooms').Rooms;
global.Verifier = require('../.server-dist/verifier');
Verifier.PM.spawn();
global.Tournaments = require('../.server-dist/tournaments').Tournaments;
global.IPTools = require('../.server-dist/ip-tools').IPTools;
IPTools.loadDatacenters();
if (Config.crashguard) {
// graceful crash - allow current battles to finish before restarting
process.on('uncaughtException', err => {
Monitor.crashlog(err, 'The main process');
});
process.on('unhandledRejection', err => {
Monitor.crashlog(err, 'A main process Promise');
});
}
/*********************************************************
* Start networking processes to be connected to
*********************************************************/
global.Sockets = require('./sockets');
exports.listen = function (port, bindAddress, workerCount) {
Sockets.listen(port, bindAddress, workerCount);
};
if (require.main === module) {
// Launch the server directly when app.js is the main module. Otherwise,
// in the case of app.js being imported as a module (e.g. unit tests),
// postpone launching until app.listen() is called.
let port;
if (process.argv[2]) port = parseInt(process.argv[2]);
Sockets.listen(port);
}
/*********************************************************
* Set up our last global
*********************************************************/
global.TeamValidatorAsync = require('./team-validator-async');
TeamValidatorAsync.PM.spawn();
/*********************************************************
* Start up the REPL server
*********************************************************/
require('../.lib-dist/repl').Repl.start('app', cmd => eval(cmd));