mirror of
https://github.com/smogon/pokemon-showdown.git
synced 2026-03-22 01:35:31 -05:00
Move IPC from battle-engine.js to simulator.js (#2666)
This commit is contained in:
parent
5d74cfff90
commit
f6a7c4bd30
107
battle-engine.js
107
battle-engine.js
|
|
@ -12,98 +12,8 @@
|
|||
|
||||
'use strict';
|
||||
|
||||
global.Config = require('./config/config.js');
|
||||
|
||||
if (Config.crashguard) {
|
||||
// graceful crash - allow current battles to finish before restarting
|
||||
process.on('uncaughtException', err => {
|
||||
require('./crashlogger.js')(err, 'A simulator process');
|
||||
});
|
||||
}
|
||||
|
||||
global.Tools = require('./tools.js').includeMods();
|
||||
global.toId = Tools.getId;
|
||||
|
||||
let Battle, BattleSide, BattlePokemon;
|
||||
|
||||
let Battles = Object.create(null);
|
||||
|
||||
require('./repl.js').start('battle-engine-', process.pid, cmd => eval(cmd));
|
||||
|
||||
// Receive and process a message sent using Simulator.prototype.send in
|
||||
// another process.
|
||||
process.on('message', message => {
|
||||
//console.log('CHILD MESSAGE RECV: "' + message + '"');
|
||||
let nlIndex = message.indexOf("\n");
|
||||
let more = '';
|
||||
if (nlIndex > 0) {
|
||||
more = message.substr(nlIndex + 1);
|
||||
message = message.substr(0, nlIndex);
|
||||
}
|
||||
let data = message.split('|');
|
||||
if (data[1] === 'init') {
|
||||
if (!Battles[data[0]]) {
|
||||
try {
|
||||
Battles[data[0]] = Battle.construct(data[0], data[2], data[3]);
|
||||
} catch (err) {
|
||||
if (require('./crashlogger.js')(err, 'A battle', {
|
||||
message: message,
|
||||
}) === 'lockdown') {
|
||||
let ministack = Tools.escapeHTML(err.stack).split("\n").slice(0, 2).join("<br />");
|
||||
process.send(data[0] + '\nupdate\n|html|<div class="broadcast-red"><b>A BATTLE PROCESS HAS CRASHED:</b> ' + ministack + '</div>');
|
||||
} else {
|
||||
process.send(data[0] + '\nupdate\n|html|<div class="broadcast-red"><b>The battle crashed!</b><br />Don\'t worry, we\'re working on fixing it.</div>');
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if (data[1] === 'dealloc') {
|
||||
if (Battles[data[0]] && Battles[data[0]].destroy) {
|
||||
Battles[data[0]].destroy();
|
||||
} else {
|
||||
require('./crashlogger.js')(new Error("Invalid dealloc"), 'A battle', {
|
||||
message: message,
|
||||
});
|
||||
}
|
||||
delete Battles[data[0]];
|
||||
} else {
|
||||
let battle = Battles[data[0]];
|
||||
if (battle) {
|
||||
let prevRequest = battle.currentRequest;
|
||||
let prevRequestDetails = battle.currentRequestDetails || '';
|
||||
try {
|
||||
battle.receive(data, more);
|
||||
} catch (err) {
|
||||
require('./crashlogger.js')(err, 'A battle', {
|
||||
message: message,
|
||||
currentRequest: prevRequest,
|
||||
log: '\n' + battle.log.join('\n').replace(/\n\|split\n[^\n]*\n[^\n]*\n[^\n]*\n/g, '\n'),
|
||||
});
|
||||
|
||||
let logPos = battle.log.length;
|
||||
battle.add('html', '<div class="broadcast-red"><b>The battle crashed</b><br />You can keep playing but it might crash again.</div>');
|
||||
let nestedError;
|
||||
try {
|
||||
battle.makeRequest(prevRequest, prevRequestDetails);
|
||||
} catch (e) {
|
||||
nestedError = e;
|
||||
}
|
||||
battle.sendUpdates(logPos);
|
||||
if (nestedError) {
|
||||
throw nestedError;
|
||||
}
|
||||
}
|
||||
} else if (data[1] === 'eval') {
|
||||
try {
|
||||
eval(data[2]);
|
||||
} catch (e) {}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
process.on('disconnect', () => {
|
||||
process.exit();
|
||||
});
|
||||
|
||||
BattlePokemon = (() => {
|
||||
function BattlePokemon(set, side) {
|
||||
this.side = side;
|
||||
|
|
@ -1996,7 +1906,7 @@ Battle = (() => {
|
|||
|
||||
Battle.construct = (() => {
|
||||
let battleProtoCache = new Map();
|
||||
return (roomid, formatarg, rated) => {
|
||||
return (roomid, formatarg, rated, send) => {
|
||||
let format = Tools.getFormat(formatarg);
|
||||
let mod = format.mod || 'base';
|
||||
if (!battleProtoCache.has(mod)) {
|
||||
|
|
@ -2009,7 +1919,7 @@ Battle = (() => {
|
|||
battleProtoCache.set(mod, battle);
|
||||
}
|
||||
let battle = Object.create(battleProtoCache.get(mod));
|
||||
Battle.prototype.init.call(battle, roomid, format, rated);
|
||||
Battle.prototype.init.call(battle, roomid, format, rated, send);
|
||||
return battle;
|
||||
};
|
||||
})();
|
||||
|
|
@ -2021,7 +1931,7 @@ Battle = (() => {
|
|||
|
||||
Battle.prototype = {};
|
||||
|
||||
Battle.prototype.init = function (roomid, format, rated) {
|
||||
Battle.prototype.init = function (roomid, format, rated, send) {
|
||||
this.log = [];
|
||||
this.sides = [null, null];
|
||||
this.roomid = roomid;
|
||||
|
|
@ -2045,6 +1955,10 @@ Battle = (() => {
|
|||
this.messageLog = [];
|
||||
|
||||
this.startingSeed = this.generateSeed();
|
||||
|
||||
if (typeof send === 'function') {
|
||||
this.send = send;
|
||||
}
|
||||
};
|
||||
|
||||
Battle.prototype.turn = 0;
|
||||
|
|
@ -5013,12 +4927,12 @@ Battle = (() => {
|
|||
|
||||
// IPC
|
||||
|
||||
// This function is overridden in Battle.construct.
|
||||
// Messages sent by this function are received and handled in
|
||||
// Battle.prototype.receive in simulator.js (in another process).
|
||||
Battle.prototype.send = function (type, data) {
|
||||
if (Array.isArray(data)) data = data.join("\n");
|
||||
process.send(this.id + "\n" + type + "\n" + data);
|
||||
};
|
||||
|
||||
// This function is called by this process's 'message' event.
|
||||
Battle.prototype.receive = function (data, more) {
|
||||
this.messageLog.push(data.join(' '));
|
||||
|
|
@ -5148,9 +5062,6 @@ Battle = (() => {
|
|||
|
||||
// in case the garbage collector really sucks, at least deallocate the log
|
||||
this.log = null;
|
||||
|
||||
// remove from battle list
|
||||
Battles[this.id] = null;
|
||||
};
|
||||
return Battle;
|
||||
})();
|
||||
|
|
|
|||
114
simulator.js
114
simulator.js
|
|
@ -13,11 +13,14 @@
|
|||
|
||||
'use strict';
|
||||
|
||||
global.Config = require('./config/config.js');
|
||||
|
||||
const ProcessManager = require('./process-manager');
|
||||
const BattleEngine = require('./battle-engine').Battle;
|
||||
|
||||
const SimulatorProcess = new ProcessManager({
|
||||
maxProcesses: Config.simulatorprocesses,
|
||||
execFile: 'battle-engine.js',
|
||||
execFile: 'simulator.js',
|
||||
onMessageUpstream: function (message) {
|
||||
let lines = message.split('\n');
|
||||
let battle = this.pendingTasks.get(lines[0]);
|
||||
|
|
@ -30,9 +33,6 @@ const SimulatorProcess = new ProcessManager({
|
|||
},
|
||||
});
|
||||
|
||||
// Create the initial set of simulator processes.
|
||||
SimulatorProcess.spawn();
|
||||
|
||||
let slice = Array.prototype.slice;
|
||||
|
||||
class BattlePlayer {
|
||||
|
|
@ -442,3 +442,109 @@ exports.SimulatorProcess = SimulatorProcess;
|
|||
exports.create = function (id, format, rated, room) {
|
||||
return new Battle(room, format, rated);
|
||||
};
|
||||
|
||||
if (process.send && module === process.mainModule) {
|
||||
// This is a child process!
|
||||
|
||||
global.Tools = require('./tools.js').includeMods();
|
||||
global.toId = Tools.getId;
|
||||
|
||||
if (Config.crashguard) {
|
||||
// graceful crash - allow current battles to finish before restarting
|
||||
process.on('uncaughtException', err => {
|
||||
require('./crashlogger.js')(err, 'A simulator process');
|
||||
});
|
||||
}
|
||||
|
||||
require('./repl.js').start('battle-engine-', process.pid, cmd => eval(cmd));
|
||||
|
||||
let Battles = Object.create(null);
|
||||
|
||||
// Receive and process a message sent using Simulator.prototype.send in
|
||||
// another process.
|
||||
process.on('message', message => {
|
||||
//console.log('CHILD MESSAGE RECV: "' + message + '"');
|
||||
let nlIndex = message.indexOf("\n");
|
||||
let more = '';
|
||||
if (nlIndex > 0) {
|
||||
more = message.substr(nlIndex + 1);
|
||||
message = message.substr(0, nlIndex);
|
||||
}
|
||||
let data = message.split('|');
|
||||
if (data[1] === 'init') {
|
||||
if (!Battles[data[0]]) {
|
||||
try {
|
||||
Battles[data[0]] = BattleEngine.construct(data[0], data[2], data[3], sendBattleMessage);
|
||||
} catch (err) {
|
||||
if (require('./crashlogger.js')(err, 'A battle', {
|
||||
message: message,
|
||||
}) === 'lockdown') {
|
||||
let ministack = Tools.escapeHTML(err.stack).split("\n").slice(0, 2).join("<br />");
|
||||
process.send(data[0] + '\nupdate\n|html|<div class="broadcast-red"><b>A BATTLE PROCESS HAS CRASHED:</b> ' + ministack + '</div>');
|
||||
} else {
|
||||
process.send(data[0] + '\nupdate\n|html|<div class="broadcast-red"><b>The battle crashed!</b><br />Don\'t worry, we\'re working on fixing it.</div>');
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if (data[1] === 'dealloc') {
|
||||
if (Battles[data[0]] && Battles[data[0]].destroy) {
|
||||
const id = data[0];
|
||||
Battles[id].destroy();
|
||||
|
||||
// remove from battle list
|
||||
Battles[id] = null;
|
||||
} else {
|
||||
require('./crashlogger.js')(new Error("Invalid dealloc"), 'A battle', {
|
||||
message: message,
|
||||
});
|
||||
}
|
||||
delete Battles[data[0]];
|
||||
} else {
|
||||
let battle = Battles[data[0]];
|
||||
if (battle) {
|
||||
let prevRequest = battle.currentRequest;
|
||||
let prevRequestDetails = battle.currentRequestDetails || '';
|
||||
try {
|
||||
battle.receive(data, more);
|
||||
} catch (err) {
|
||||
require('./crashlogger.js')(err, 'A battle', {
|
||||
message: message,
|
||||
currentRequest: prevRequest,
|
||||
log: '\n' + battle.log.join('\n').replace(/\n\|split\n[^\n]*\n[^\n]*\n[^\n]*\n/g, '\n'),
|
||||
});
|
||||
|
||||
let logPos = battle.log.length;
|
||||
battle.add('html', '<div class="broadcast-red"><b>The battle crashed</b><br />You can keep playing but it might crash again.</div>');
|
||||
let nestedError;
|
||||
try {
|
||||
battle.makeRequest(prevRequest, prevRequestDetails);
|
||||
} catch (e) {
|
||||
nestedError = e;
|
||||
}
|
||||
battle.sendUpdates(logPos);
|
||||
if (nestedError) {
|
||||
throw nestedError;
|
||||
}
|
||||
}
|
||||
} else if (data[1] === 'eval') {
|
||||
try {
|
||||
eval(data[2]);
|
||||
} catch (e) {}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
process.on('disconnect', () => {
|
||||
process.exit();
|
||||
});
|
||||
} else {
|
||||
// Create the initial set of simulator processes.
|
||||
SimulatorProcess.spawn();
|
||||
}
|
||||
|
||||
// Messages sent by this function are received and handled in
|
||||
// Battle.prototype.receive in simulator.js (in another process).
|
||||
function sendBattleMessage(type, data) {
|
||||
if (Array.isArray(data)) data = data.join("\n");
|
||||
process.send(this.id + "\n" + type + "\n" + data);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -28,7 +28,6 @@ function init(callback) {
|
|||
}
|
||||
|
||||
// Turn IPC methods into no-op
|
||||
BattleEngine.Battle.prototype.send = noop;
|
||||
BattleEngine.Battle.prototype.receive = noop;
|
||||
|
||||
let Simulator = global.Simulator;
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user