mirror of
https://github.com/smogon/pokemon-showdown.git
synced 2026-03-21 17:25:10 -05:00
1644 lines
41 KiB
JavaScript
1644 lines
41 KiB
JavaScript
config = require('./config/config.js');
|
|
serverid = config.serverid;
|
|
servertoken = config.servertoken;
|
|
|
|
require("./node_modules/long-stack-traces");
|
|
|
|
request = require('request');
|
|
|
|
/*
|
|
var app = require('http').createServer()
|
|
, io = require('socket.io').listen(app)
|
|
, fs = require('fs');
|
|
|
|
function handler (req, res) {
|
|
fs.readFile(__dirname + '/index.html',
|
|
function (err, data) {
|
|
if (err) {
|
|
res.writeHead(500);
|
|
return res.end('Error loading index.html');
|
|
}
|
|
|
|
res.writeHead(200);
|
|
res.end(data);
|
|
});
|
|
}
|
|
|
|
app.listen(8000); */
|
|
|
|
var io = require('socket.io').listen(config.port);
|
|
|
|
function getTime()
|
|
{
|
|
return new Date().getTime();
|
|
}
|
|
|
|
function toId(text)
|
|
{
|
|
text = text || '';
|
|
return text.replace(/ /g, '');
|
|
}
|
|
function toUserid(name)
|
|
{
|
|
return name.toLowerCase().replace(/[^a-z0-9]+/g, '');
|
|
}
|
|
|
|
BattlePokedex = require('./pokedex.js').BattlePokedex;
|
|
BattleTiers = require('./tiers.js').BattleTiers;
|
|
BattleMovedex = require('./movedex.js').BattleMovedex;
|
|
BattleStatuses = require('./statuses.js').BattleStatuses;
|
|
BattleTypeChart = require('./typechart.js').BattleTypeChart;
|
|
BattleScripts = require('./scripts.js').BattleScripts;
|
|
BattleItems = require('./items.js').BattleItems;
|
|
BattleAbilities = require('./abilities.js').BattleAbilities;
|
|
BattleFormats = require('./formats.js').BattleFormats;
|
|
BattleLearnsets = require('./learnsets.js').BattleLearnsets;
|
|
|
|
var sim = require('./simulator.js');
|
|
|
|
BattlePokemon = sim.BattlePokemon;
|
|
BattleSide = sim.BattleSide;
|
|
Battle = sim.Battle;
|
|
|
|
BattleTools = require('./tools.js').BattleTools;
|
|
|
|
Tools = new BattleTools();
|
|
|
|
getUser = require('./users.js').getUser;
|
|
|
|
lockdown = false;
|
|
|
|
function reloadEngine()
|
|
{
|
|
for (var i in require.cache)
|
|
{
|
|
delete require.cache[i];
|
|
}
|
|
BattlePokedex = require('./pokedex.js').BattlePokedex;
|
|
BattleTiers = require('./tiers.js').BattleTiers;
|
|
BattleMovedex = require('./movedex.js').BattleMovedex;
|
|
BattleStatuses = require('./statuses.js').BattleStatuses;
|
|
BattleTypeChart = require('./typechart.js').BattleTypeChart;
|
|
BattleScripts = require('./scripts.js').BattleScripts;
|
|
BattleItems = require('./items.js').BattleItems;
|
|
BattleAbilities = require('./abilities.js').BattleAbilities;
|
|
BattleFormats = require('./formats.js').BattleFormats;
|
|
BattleLearnsets = require('./learnsets.js').BattleLearnsets;
|
|
|
|
sim = require('./simulator.js');
|
|
|
|
BattlePokemon = sim.BattlePokemon;
|
|
BattleSide = sim.BattleSide;
|
|
Battle = sim.Battle;
|
|
|
|
BattleTools = require('./tools.js').BattleTools;
|
|
|
|
Tools = new BattleTools();
|
|
}
|
|
|
|
function Room(roomid, format, p1, p2, parentid, ranked)
|
|
{
|
|
var selfR = this;
|
|
|
|
format = ''+(format||'');
|
|
|
|
this.id = roomid;
|
|
this.i = {};
|
|
this.users = {};
|
|
this.format = format;
|
|
console.log("NEW BATTLE");
|
|
|
|
var formatid = toId(format);
|
|
|
|
if (ranked && BattleFormats[formatid] && BattleFormats[formatid].ranked)
|
|
{
|
|
ranked = {
|
|
p1: p1.userid,
|
|
p2: p2.userid,
|
|
format: format
|
|
};
|
|
}
|
|
else
|
|
{
|
|
ranked = false;
|
|
}
|
|
|
|
this.ranked = ranked;
|
|
this.battle = new Battle(selfR.id, format, ranked);
|
|
this.resetTimer = null;
|
|
this.graceTimer = null;
|
|
this.graceUp = false;
|
|
|
|
this.parentid = parentid||'';
|
|
this.p1 = p1 || '';
|
|
this.p2 = p2 || '';
|
|
|
|
this.active = false;
|
|
|
|
this.update = function(excludeUser) {
|
|
update = selfR.battle.getUpdates();
|
|
if (!update) return;
|
|
|
|
if (selfR.battle.ended && selfR.ranked)
|
|
{
|
|
var p1score = 0.5;
|
|
|
|
if (selfR.battle.winner === selfR.ranked.p1)
|
|
{
|
|
p1score = 1;
|
|
}
|
|
else if (selfR.battle.winner === selfR.ranked.p2)
|
|
{
|
|
p1score = 0;
|
|
}
|
|
|
|
var p1 = selfR.ranked.p1;
|
|
if (getUser(selfR.ranked.p1)) p1 = getUser(selfR.ranked.p1).name;
|
|
var p2 = selfR.ranked.p2;
|
|
if (getUser(selfR.ranked.p2)) p2 = getUser(selfR.ranked.p2).name;
|
|
|
|
update.updates.push('[DEBUG] uri: '+config.loginserver+'action.php?act=ladderupdate&serverid='+serverid+'&p1='+encodeURIComponent(p1)+'&p2='+encodeURIComponent(p2)+'&score='+p1score+'&format='+toId(selfR.ranked.format)+'&servertoken=[token]');
|
|
|
|
if (!selfR.ranked.p1 || !selfR.ranked.p2)
|
|
{
|
|
update.updates.push('message ERROR: Ladder not updated: a player does not exist');
|
|
}
|
|
else
|
|
{
|
|
// update rankings
|
|
request({
|
|
uri: config.loginserver+'action.php?act=ladderupdate&serverid='+serverid+'&p1='+encodeURIComponent(p1)+'&p2='+encodeURIComponent(p2)+'&score='+p1score+'&format='+toId(selfR.ranked.format)+'&servertoken='+servertoken+'&nocache='+getTime(),
|
|
}, function(error, response, body) {
|
|
if (body)
|
|
{
|
|
try
|
|
{
|
|
var data = JSON.parse(body);
|
|
// we don't actually do much with this data
|
|
selfR.battle.add("[DEBUG] ladder reply: "+body);
|
|
selfR.battle.add("message Ladder updated.");
|
|
selfR.update();
|
|
}
|
|
catch(e)
|
|
{
|
|
}
|
|
}
|
|
else
|
|
{
|
|
}
|
|
});
|
|
}
|
|
|
|
selfR.ranked = false;
|
|
}
|
|
|
|
update.room = roomid;
|
|
for (var i in selfR.users)
|
|
{
|
|
if (selfR.users[i] === excludeUser) continue;
|
|
selfR.users[i].emit('update', update);
|
|
}
|
|
};
|
|
this.broadcastError = function(message) {
|
|
for (var i in selfR.users)
|
|
{
|
|
selfR.users.emit('connectionError', message);
|
|
}
|
|
};
|
|
this.reset = function(reload)
|
|
{
|
|
clearTimeout(selfR.resetTimer);
|
|
selfR.resetTimer = null;
|
|
|
|
if (lockdown)
|
|
{
|
|
selfR.add('The battle was not restarted because the server is preparing to shut down.');
|
|
return;
|
|
}
|
|
|
|
selfR.battle.add('RESET');
|
|
selfR.update();
|
|
|
|
if (selfR.battle.allySide && selfR.battle.allySide.user) delete selfR.battle.allySide.user.sides[selfR.id];
|
|
if (selfR.battle.foeSide && selfR.battle.foeSide.user) delete selfR.battle.foeSide.user.sides[selfR.id];
|
|
|
|
console.log("NEW BATTLE (reset)");
|
|
selfR.battle = new Battle(selfR.id, selfR.format, false);
|
|
selfR.active = selfR.battle.active;
|
|
if (selfR.parentid)
|
|
{
|
|
getRoom(selfR.parentid).updateRooms();
|
|
}
|
|
};
|
|
this.kickInactive = function()
|
|
{
|
|
clearTimeout(selfR.resetTimer);
|
|
selfR.resetTimer = null;
|
|
if (selfR.ranked)
|
|
{
|
|
if (!selfR.battle.allySide.user && selfR.battle.foeSide.user)
|
|
{
|
|
selfR.battle.add('message '+selfR.battle.allySide.name+' lost because of their inactivity.');
|
|
selfR.battle.win(selfR.battle.foeSide);
|
|
}
|
|
else if (selfR.battle.allySide.user && !selfR.battle.foeSide.user)
|
|
{
|
|
selfR.battle.add('message '+selfR.battle.foeSide.name+' lost because of their inactivity.');
|
|
selfR.battle.win(selfR.battle.allySide);
|
|
}
|
|
else if (!selfR.battle.allySide.decision && selfR.battle.foeSide.decision)
|
|
{
|
|
selfR.battle.add('message '+selfR.battle.allySide.name+' lost because of their inactivity.');
|
|
selfR.battle.win(selfR.battle.foeSide);
|
|
}
|
|
else if (selfR.battle.allySide.decision && !selfR.battle.foeSide.decision)
|
|
{
|
|
selfR.battle.add('message '+selfR.battle.foeSide.name+' lost because of their inactivity.');
|
|
selfR.battle.win(selfR.battle.allySide);
|
|
}
|
|
else
|
|
{
|
|
selfR.battle.add('message Both players are inactive, so neither player was kicked.');
|
|
}
|
|
}
|
|
else
|
|
{
|
|
selfR.battle.add('message Kicking inactive players.');
|
|
if (!selfR.battle.allySide.decision)
|
|
{
|
|
selfR.battle.leave(selfR.battle.allySide.user);
|
|
}
|
|
if (!selfR.battle.foeSide.decision)
|
|
{
|
|
selfR.battle.leave(selfR.battle.foeSide.user);
|
|
}
|
|
}
|
|
selfR.active = selfR.battle.active;
|
|
selfR.update();
|
|
if (selfR.parentid)
|
|
{
|
|
getRoom(selfR.parentid).updateRooms();
|
|
}
|
|
}
|
|
this.requestReset = function(user) {
|
|
if (selfR.resetTimer) return;
|
|
if (!selfR.battle.started) return; // no point
|
|
if (user) attrib = ' (requested by '+user.name+')';
|
|
if (selfR.ranked)
|
|
{
|
|
selfR.battle.add('message The battle cannot be restarted because it is a ranked battle'+attrib+'.');
|
|
return;
|
|
}
|
|
if (!selfR.graceUp)
|
|
{
|
|
selfR.battle.add('message The battle will restart if there is no activity for 90 seconds'+attrib+'.');
|
|
selfR.update();
|
|
selfR.resetTimer = setTimeout(selfR.reset, 90000);
|
|
return;
|
|
}
|
|
selfR.battle.add('message The battle will restart if there is no activity for 30 seconds'+attrib+'.');
|
|
selfR.update();
|
|
selfR.resetTimer = setTimeout(selfR.reset, 30000);
|
|
};
|
|
this.requestKickInactive = function(user) {
|
|
if (selfR.resetTimer) return;
|
|
if (!selfR.battle.active && !selfR.ranked) return; // no point
|
|
if (user) attrib = ' (requested by '+user.name+')';
|
|
var action = 'be kicked';
|
|
if (selfR.ranked)
|
|
{
|
|
action = 'forfeit';
|
|
}
|
|
if (!selfR.graceUp)
|
|
{
|
|
selfR.battle.add('message Inactive players will '+action+' in 90 seconds'+attrib+'.');
|
|
selfR.update();
|
|
selfR.resetTimer = setTimeout(selfR.kickInactive, 90000);
|
|
return;
|
|
}
|
|
selfR.battle.add('message Inactive players will '+action+' in 30 seconds'+attrib+'.');
|
|
selfR.update();
|
|
selfR.resetTimer = setTimeout(selfR.kickInactive, 30000);
|
|
};
|
|
this.cancelReset = function() {
|
|
if (selfR.resetTimer)
|
|
{
|
|
selfR.battle.add('message The restart or kick was interrupted by activity.');
|
|
selfR.update();
|
|
clearTimeout(selfR.resetTimer);
|
|
selfR.resetTimer = null;
|
|
}
|
|
if (selfR.graceTimer)
|
|
{
|
|
clearTimeout(selfR.graceTimer);
|
|
selfR.graceUp = false;
|
|
}
|
|
setTimeout(selfR.graceTimeout, 60000);
|
|
};
|
|
this.graceTimeout = function() {
|
|
clearTimeout(selfR.graceTimer);
|
|
selfR.graceUp = true;
|
|
selfR.graceTimer = null;
|
|
};
|
|
this.decision = function(user, choice, data) {
|
|
selfR.cancelReset();
|
|
selfR.battle.decision(user, choice, data);
|
|
if (selfR.battle.ended)
|
|
{
|
|
selfR.battle.add('callback restart');
|
|
}
|
|
if (selfR.active !== selfR.battle.active)
|
|
{
|
|
selfR.active = selfR.battle.active;
|
|
if (selfR.parentid)
|
|
{
|
|
getRoom(selfR.parentid).updateRooms();
|
|
}
|
|
}
|
|
selfR.update();
|
|
};
|
|
this.battleEndRestart = function() {
|
|
if (selfR.resetTimer) return;
|
|
if (selfR.battle.ended)
|
|
{
|
|
selfR.battle.add('message A new game will start in 5 seconds.');
|
|
// reset in 5 seconds
|
|
selfR.resetTimer = setTimeout(selfR.reset, 5000);
|
|
}
|
|
};
|
|
this.initSocket = function(user, socket) {
|
|
var initdata = {
|
|
name: user.name,
|
|
userid: user.userid,
|
|
named: user.named,
|
|
renamePending: user.renamePending,
|
|
token: user.token,
|
|
room: selfR.id,
|
|
roomType: 'battle',
|
|
battlelog: selfR.battle.log
|
|
};
|
|
socket.emit('init', initdata);
|
|
};
|
|
this.join = function(user) {
|
|
if (!user) return false;
|
|
if (selfR.users[user.userid]) return user;
|
|
|
|
selfR.users[user.userid] = user;
|
|
|
|
if (user.named)
|
|
{
|
|
selfR.battle.add('join '+user.name);
|
|
selfR.update(user);
|
|
}
|
|
|
|
var initdata = {
|
|
name: user.name,
|
|
userid: user.userid,
|
|
named: user.named,
|
|
renamePending: user.renamePending,
|
|
token: user.token,
|
|
room: selfR.id,
|
|
roomType: 'battle',
|
|
battlelog: selfR.battle.log
|
|
};
|
|
user.emit('init', initdata);
|
|
|
|
return user;
|
|
};
|
|
this.rename = function(user, oldid, joining) {
|
|
if (joining)
|
|
{
|
|
selfR.battle.add('join '+user.name);
|
|
}
|
|
if (user.sides[selfR.id])
|
|
{
|
|
selfR.battle.rename(user);
|
|
}
|
|
delete selfR.users[oldid];
|
|
selfR.users[user.userid] = user;
|
|
selfR.update();
|
|
return user;
|
|
};
|
|
this.joinBattle = function(user) {
|
|
var slot = 0;
|
|
if (selfR.ranked)
|
|
{
|
|
if (selfR.ranked.p1 === user.userid)
|
|
{
|
|
slot = 1;
|
|
}
|
|
else if (selfR.ranked.p2 === user.userid)
|
|
{
|
|
slot = 2;
|
|
}
|
|
else
|
|
{
|
|
return;
|
|
}
|
|
}
|
|
|
|
selfR.cancelReset();
|
|
selfR.battle.join(user, slot);
|
|
selfR.active = selfR.battle.active;
|
|
selfR.update();
|
|
|
|
if (selfR.parentid)
|
|
{
|
|
getRoom(selfR.parentid).updateRooms();
|
|
}
|
|
};
|
|
this.leaveBattle = function(user) {
|
|
if (!user) return; // ...
|
|
if (user.sides[selfR.id])
|
|
{
|
|
selfR.battle.leave(user);
|
|
}
|
|
selfR.active = selfR.battle.active;
|
|
selfR.update();
|
|
|
|
if (selfR.parentid)
|
|
{
|
|
getRoom(selfR.parentid).updateRooms();
|
|
}
|
|
};
|
|
this.leave = function(user) {
|
|
if (!user) return; // ...
|
|
if (user.sides[selfR.id])
|
|
{
|
|
selfR.battle.leave(user);
|
|
selfR.active = selfR.battle.active;
|
|
if (selfR.parentid)
|
|
{
|
|
getRoom(selfR.parentid).updateRooms();
|
|
}
|
|
}
|
|
else if (!user.named)
|
|
{
|
|
delete selfR.users[user.userid];
|
|
return;
|
|
}
|
|
delete selfR.users[user.userid];
|
|
selfR.battle.add('leave '+user.name);
|
|
selfR.update();
|
|
};
|
|
this.isEmpty = function() {
|
|
if (selfR.battle.allySide && selfR.battle.allySide.user) return false;
|
|
if (selfR.battle.foeSide && selfR.battle.foeSide.user) return false;
|
|
return true;
|
|
};
|
|
this.isFull = function() {
|
|
if (selfR.battle.allySide && selfR.battle.allySide.user && selfR.battle.foeSide && selfR.battle.foeSide.user) return true;
|
|
return false;
|
|
};
|
|
this.add = function(message) {
|
|
selfR.battle.add('chatmsg '+message);
|
|
};
|
|
this.addRaw = function(message) {
|
|
selfR.battle.add('chatmsg-raw '+message);
|
|
};
|
|
this.chat = function(user, message, socket) {
|
|
var cmd = '', target = '';
|
|
if (message.substr(0,2) === '//')
|
|
{
|
|
message = message.substr(1);
|
|
}
|
|
else if (message.substr(0,1) === '/')
|
|
{
|
|
var spaceIndex = message.indexOf(' ');
|
|
if (spaceIndex > 0)
|
|
{
|
|
cmd = message.substr(1, spaceIndex-1);
|
|
target = message.substr(spaceIndex+1);
|
|
}
|
|
else
|
|
{
|
|
cmd = message.substr(1);
|
|
target = '';
|
|
}
|
|
}
|
|
|
|
if (parseCommand(user, cmd, target, selfR, socket))
|
|
{
|
|
// do nothing
|
|
}
|
|
else if (cmd === 'a')
|
|
{
|
|
if (user.isMod())
|
|
{
|
|
selfR.battle.add(target);
|
|
}
|
|
}
|
|
else if (cmd === 'shutdown')
|
|
{
|
|
selfR.broadcastError('The server is restarting. Please refresh this page.');
|
|
}
|
|
else if (message.substr(0,3) === '>> ')
|
|
{
|
|
var cmd = message.substr(3);
|
|
|
|
var room = selfR;
|
|
var battle = selfR.battle;
|
|
var foeSide;
|
|
var allySide;
|
|
var foePokemon;
|
|
var allyPokemon;
|
|
var me = user;
|
|
if (battle)
|
|
{
|
|
foeSide = battle.foeSide;
|
|
allySide = battle.allySide;
|
|
if (foeSide)
|
|
{
|
|
foePokemon = foeSide.active[0];
|
|
}
|
|
if (allySide)
|
|
{
|
|
allyPokemon = allySide.active[0];
|
|
}
|
|
}
|
|
selfR.battle.add('chat '+toId(user.name)+' >> '+cmd);
|
|
if (user.group === '&')
|
|
{
|
|
try
|
|
{
|
|
selfR.battle.add('chat '+toId(user.name)+' << '+eval(cmd));
|
|
}
|
|
catch (e)
|
|
{
|
|
selfR.battle.add('chat '+toId(user.name)+' << error: '+e.message);
|
|
user.emit('console', '<< error details: '+JSON.stringify(e.stack));
|
|
}
|
|
}
|
|
else
|
|
{
|
|
selfR.battle.add('chat '+toId(user.name)+' << Access denied. To use the developer console, you must be: &');
|
|
}
|
|
}
|
|
else if (cmd === 'forcereset')
|
|
{
|
|
if (user.isMod())
|
|
{
|
|
selfR.reset();
|
|
}
|
|
else
|
|
{
|
|
}
|
|
}
|
|
else if (cmd === 'reset')
|
|
{
|
|
selfR.requestReset(user);
|
|
}
|
|
else if (cmd === 'restart')
|
|
{
|
|
selfR.battleEndRestart(user);
|
|
}
|
|
else if (cmd === 'kickinactive')
|
|
{
|
|
selfR.requestKickInactive(user);
|
|
}
|
|
else if (!user.muted)
|
|
{
|
|
selfR.battle.add('chat '+toId(user.name)+' '+message);
|
|
}
|
|
selfR.update();
|
|
};
|
|
}
|
|
|
|
function parseCommand(user, cmd, target, room, socket)
|
|
{
|
|
if (cmd === 1 || cmd === 'b')
|
|
{
|
|
if (!target) return parseCommand(user, '?', cmd, room, socket);
|
|
if (user.isMod())
|
|
{
|
|
var targetUser = getUser(target);
|
|
if (!targetUser)
|
|
{
|
|
socket.emit('console', 'User '+target+' not found.');
|
|
return true;
|
|
}
|
|
if (!user.canMod(targetUser.group)) return true;
|
|
|
|
room.add(''+targetUser.name+' was banned by '+user.name+'.');
|
|
|
|
bannedIps[targetUser.ip] = targetUser.userid;
|
|
targetUser.destroy();
|
|
return true;
|
|
}
|
|
}
|
|
else if (cmd === 'unban')
|
|
{
|
|
if (!target) return parseCommand(user, '?', cmd, room, socket);
|
|
if (user.isMod())
|
|
{
|
|
var targetid = toUserid(target);
|
|
var success = false;
|
|
|
|
for (var id in bannedIps)
|
|
{
|
|
if (bannedIps[id] === targetid)
|
|
{
|
|
delete bannedIps[id];
|
|
if (!success)
|
|
{
|
|
room.add(''+target+' was unbanned by '+user.name+'.');
|
|
success = true;
|
|
}
|
|
}
|
|
}
|
|
if (!success)
|
|
{
|
|
socket.emit('console', 'User '+target+' is not banned.');
|
|
}
|
|
}
|
|
else
|
|
{
|
|
socket.emit('console', 'Access denied.');
|
|
}
|
|
return true;
|
|
}
|
|
else if (cmd === 'reply' || cmd === 'r')
|
|
{
|
|
if (!target) return parseCommand(user, '?', cmd, room, socket);
|
|
return parseCommand(user, 'msg', ''+(user.lastPM||'')+', '+target, room, socket);
|
|
}
|
|
else if (cmd === 'msg' || cmd === 'pm')
|
|
{
|
|
if (!target) return parseCommand(user, '?', cmd, room, socket);
|
|
var commaIndex = target.indexOf(',');
|
|
if (commaIndex < 0)
|
|
{
|
|
socket.emit('console', 'You forgot the comma.');
|
|
return parseCommand(user, '?', cmd, room, socket);
|
|
}
|
|
var targetUser = getUser(target.substr(0, commaIndex));
|
|
if (!targetUser || !targetUser.connected)
|
|
{
|
|
socket.emit('console', 'User '+target+' not found. Did you forget a comma?');
|
|
return parseCommand(user, '?', cmd, room, socket);
|
|
}
|
|
|
|
target = target.substr(commaIndex+1).trim();
|
|
|
|
var message = {
|
|
name: user.getIdentity(),
|
|
pm: targetUser.getIdentity(),
|
|
message: target
|
|
};
|
|
socket.emit('console', message);
|
|
targetUser.emit('console', message);
|
|
targetUser.lastPM = user.userid;
|
|
user.lastPM = targetUser.userid;
|
|
return true;
|
|
}
|
|
else if (cmd === 'getip' || cmd === 'ip')
|
|
{
|
|
if (!target)
|
|
{
|
|
socket.emit('console', 'Your IP is: '+user.ip);
|
|
return true;
|
|
}
|
|
if (user.group === '&' || user.group === '@')
|
|
{
|
|
var targetUser = getUser(target);
|
|
if (!targetUser)
|
|
{
|
|
socket.emit('console', 'User '+target+' not found.');
|
|
}
|
|
else
|
|
{
|
|
socket.emit('console', 'User '+targetUser.name+' has IP: '+targetUser.ip);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
socket.emit('console', 'Access denied.');
|
|
}
|
|
return true;
|
|
}
|
|
else if (cmd === 'mute' || cmd === 'm')
|
|
{
|
|
if (!target) return parseCommand(user, '?', cmd, room, socket);
|
|
if (user.isMod())
|
|
{
|
|
target = getUser(target);
|
|
if (!target) return true;
|
|
if (!user.canMod(target.group)) return true;
|
|
|
|
room.add(''+target.name+' was muted by '+user.name+'.');
|
|
|
|
target.muted = true;
|
|
rooms.lobby.usersChanged = true;
|
|
return true;
|
|
}
|
|
}
|
|
else if (cmd === 'unmute')
|
|
{
|
|
if (!target) return parseCommand(user, '?', cmd, room, socket);
|
|
if (user.isMod())
|
|
{
|
|
target = getUser(target);
|
|
if (!target) return true;
|
|
if (!user.canMod(target.group)) return true;
|
|
|
|
room.add(''+target.name+' was unmuted by '+user.name+'.');
|
|
|
|
target.muted = false;
|
|
rooms.lobby.usersChanged = true;
|
|
return true;
|
|
}
|
|
}
|
|
else if (cmd === 'voice')
|
|
{
|
|
if (!target) return parseCommand(user, '?', cmd, room, socket);
|
|
if (user.isMod())
|
|
{
|
|
target = getUser(target);
|
|
if (!target) return true;
|
|
if (!user.canMod(target.group) || user.group === '+') return true;
|
|
|
|
room.add(''+target.name+' was voiced by '+user.name+'.');
|
|
|
|
target.group = '+';
|
|
rooms.lobby.usersChanged = true;
|
|
return true;
|
|
}
|
|
}
|
|
else if (cmd === 'devoice')
|
|
{
|
|
if (!target) return parseCommand(user, '?', cmd, room, socket);
|
|
if (user.isMod())
|
|
{
|
|
target = getUser(target);
|
|
if (!target) return true;
|
|
if (!user.canMod(target.group) || user.group === '+') return true;
|
|
|
|
room.add(''+target.name+' was devoiced by '+user.name+'.');
|
|
|
|
target.group = ' ';
|
|
rooms.lobby.usersChanged = true;
|
|
return true;
|
|
}
|
|
}
|
|
else if (cmd === 'potd')
|
|
{
|
|
if (user.group !== '&' && user.group !== '@' && user.group !== '%') return true;
|
|
|
|
BattleFormats.PotD.onPotD = target;
|
|
if (target)
|
|
{
|
|
room.add('The Pokemon of the Day was changed to '+target+' by '+user.name+'.');
|
|
}
|
|
else
|
|
{
|
|
room.add('The Pokemon of the Day was removed by '+user.name+'.');
|
|
}
|
|
|
|
return true;
|
|
}
|
|
else if (cmd === 'mod')
|
|
{
|
|
if (!target) return parseCommand(user, '?', cmd, room, socket);
|
|
if (user.isMod())
|
|
{
|
|
target = getUser(target);
|
|
if (!target) return true;
|
|
if (user.group !== '&' && user.group !== '@') return true;
|
|
if (!user.canMod(target.group)) return true;
|
|
|
|
if (target.group === '@' || target.group === '&')
|
|
{
|
|
room.add(''+target.name+' was demoted to moderator by '+user.name+'.');
|
|
}
|
|
else
|
|
{
|
|
room.add(''+target.name+' was promoted to moderator by '+user.name+'.');
|
|
}
|
|
target.group = '%';
|
|
rooms.lobby.usersChanged = true;
|
|
return true;
|
|
}
|
|
}
|
|
else if (cmd === 'demod')
|
|
{
|
|
if (!target) return parseCommand(user, '?', cmd, room, socket);
|
|
if (user.isMod())
|
|
{
|
|
target = getUser(target);
|
|
if (!target) return true;
|
|
if (user.group !== '&' && user.group !== '@') return true;
|
|
if (!user.canMod(target.group)) return true;
|
|
|
|
room.add(''+target.name+' was demoted to voice by '+user.name+'.');
|
|
|
|
if (target.group === '%')
|
|
{
|
|
target.group = '+';
|
|
rooms.lobby.usersChanged = true;
|
|
}
|
|
return true;
|
|
}
|
|
}
|
|
else if (cmd === 'admin')
|
|
{
|
|
if (!target) return parseCommand(user, '?', cmd, room, socket);
|
|
if (user.isMod())
|
|
{
|
|
target = getUser(target);
|
|
if (!target) return true;
|
|
if (user.group !== '&' && user.group !== '@') return true;
|
|
if (!user.canMod(target.group)) return true;
|
|
|
|
if (target.group === '&')
|
|
{
|
|
room.add(''+target.name+' was demoted to admin by '+user.name+'.');
|
|
}
|
|
else
|
|
{
|
|
room.add(''+target.name+' was promoted to admin by '+user.name+'.');
|
|
}
|
|
target.group = '@';
|
|
rooms.lobby.usersChanged = true;
|
|
return true;
|
|
}
|
|
}
|
|
else if (cmd === 'deadmin')
|
|
{
|
|
if (!target) return parseCommand(user, '?', cmd, room, socket);
|
|
if (user.isMod())
|
|
{
|
|
target = getUser(target);
|
|
if (!target) return true;
|
|
if (user.group !== '&' && user.group !== '@') return true;
|
|
if (!user.canMod(target.group)) return true;
|
|
|
|
room.add(''+target.name+' was demoted to moderator by '+user.name+'.');
|
|
|
|
if (target.group === '@')
|
|
{
|
|
target.group = '%';
|
|
rooms.lobby.usersChanged = true;
|
|
}
|
|
return true;
|
|
}
|
|
}
|
|
else if (cmd === 'hotpatch')
|
|
{
|
|
if (user.group === '&')
|
|
{
|
|
if (target === 'confirm')
|
|
{
|
|
reloadEngine();
|
|
room.add('The game engine has been updated.');
|
|
return true;
|
|
}
|
|
socket.emit('console', 'Hot-patching the game engine allows you to update most of Showdown without interrupting currently-running battles.');
|
|
socket.emit('console', 'WARNING: This uses significantly more memory than restarting Showdown, since currently-running battles will use the old engine, but new battles will use the new engine.');
|
|
socket.emit('console', 'To reload the engine, use /hotpatch confirm.');
|
|
return true;
|
|
}
|
|
}
|
|
else if (cmd === 'rating' || cmd === 'ranking' || cmd === 'rank')
|
|
{
|
|
target = toUserid(target) || user.userid;
|
|
request({
|
|
uri: config.loginserver+'action.php?act=ladderget&serverid='+serverid+'&user='+target,
|
|
}, function(error, response, body) {
|
|
if (body)
|
|
{
|
|
try
|
|
{
|
|
var data = JSON.parse(body);
|
|
|
|
socket.emit('console', 'User: '+target);
|
|
|
|
if (!data.length)
|
|
{
|
|
socket.emit('console', 'has not played a ladder game yet');
|
|
}
|
|
else for (var i=0; i<data.length; i++)
|
|
{
|
|
var row = data[i];
|
|
socket.emit('console', row.formatid+': '+Math.floor(row.rpr)+' (percentile: '+row.pgxe+')');
|
|
}
|
|
}
|
|
catch(e)
|
|
{
|
|
}
|
|
}
|
|
else
|
|
{
|
|
socket.emit('console', 'Error');
|
|
}
|
|
});
|
|
return true;
|
|
}
|
|
else if (cmd === 'nick')
|
|
{
|
|
if (!target) return parseCommand(user, '?', cmd, room, socket);
|
|
user.rename(target);
|
|
return true;
|
|
}
|
|
else if (cmd === 'forcewin')
|
|
{
|
|
if (user.group === '&' && room.battle)
|
|
{
|
|
if (!target)
|
|
{
|
|
room.battle.win('');
|
|
return true;
|
|
}
|
|
target = getUser(target);
|
|
if (target) target = target.userid;
|
|
else target = '';
|
|
|
|
if (target) room.battle.win(target);
|
|
|
|
return true;
|
|
}
|
|
}
|
|
else if (cmd === 'lockdown')
|
|
{
|
|
if (user.group === '&')
|
|
{
|
|
lockdown = true;
|
|
for (var id in rooms)
|
|
{
|
|
rooms[id].addRaw('<strong style="color:red">The server is restarting soon. Please finish your battles quickly. No new battles can be started until the server resets in a few minutes.</strong>');
|
|
}
|
|
}
|
|
return true;
|
|
}
|
|
else if (cmd === 'endlockdown')
|
|
{
|
|
if (user.group === '&')
|
|
{
|
|
lockdown = false;
|
|
for (var id in rooms)
|
|
{
|
|
rooms[id].addRaw('<strong style="color:blue">The server shutdown was canceled.</strong>');
|
|
}
|
|
}
|
|
return true;
|
|
}
|
|
else if (cmd === 'help' || cmd === 'commands' || cmd === 'h' || cmd === '?')
|
|
{
|
|
var matched = false;
|
|
if (target === 'all' || target === 'msg' || target === 'pm')
|
|
{
|
|
matched = true;
|
|
socket.emit('console', '/msg [username], [message] - Send a private message. Can be used by: anyone');
|
|
}
|
|
if (target === 'all' || target === 'r' || target === 'reply')
|
|
{
|
|
matched = true;
|
|
socket.emit('console', '/reply OR /r [message] - Send a private message to the last person you received a message from, or sent a message to. Can be used by: anyone');
|
|
}
|
|
if (target === 'all' || target === 'getip' || target === 'ip')
|
|
{
|
|
matched = true;
|
|
socket.emit('console', '/ip - Get your own IP address. Can be used by: anyone');
|
|
socket.emit('console', '/ip [username] - Get a user\'s IP address. Can be used by: @ &');
|
|
}
|
|
if (target === 'all' || target === 'ranking')
|
|
{
|
|
matched = true;
|
|
socket.emit('console', '/ranking - Get your own ranking.');
|
|
socket.emit('console', '/ranking [username] - Get user\'s ranking.');
|
|
}
|
|
if (target === 'all' || target === 'nick')
|
|
{
|
|
matched = true;
|
|
socket.emit('console', '/nick [username] - Change your username.');
|
|
}
|
|
if (target === 'all' || target === 'ban' || target === 'b')
|
|
{
|
|
matched = true;
|
|
socket.emit('console', '/ban OR /b [username] - Kick user from all rooms and ban user\'s IP address. Can be used by: + % @ &');
|
|
}
|
|
if (target === 'all' || target === 'unban')
|
|
{
|
|
matched = true;
|
|
socket.emit('console', '/unban [username] - Unban a user. Can be used by: + % @ &');
|
|
}
|
|
if (target === 'all' || target === 'unbanall')
|
|
{
|
|
matched = true;
|
|
socket.emit('console', '/unbanall - Unban all IP addresses. Can be used by: + % @ &');
|
|
}
|
|
if (target === 'all' || target === 'mute')
|
|
{
|
|
matched = true;
|
|
socket.emit('console', '/mute OR /m [username] - Mute user. Can be used by: + % @ &');
|
|
}
|
|
if (target === 'all' || target === 'unmute')
|
|
{
|
|
matched = true;
|
|
socket.emit('console', '/unmute [username] - Remove mute from user. Can be used by: + % @ &');
|
|
}
|
|
if (target === 'all' || target === 'voice')
|
|
{
|
|
matched = true;
|
|
socket.emit('console', '/voice [username] - Change user\'s group to +. Can be used by: % @ &');
|
|
}
|
|
if (target === 'all' || target === 'devoice')
|
|
{
|
|
matched = true;
|
|
socket.emit('console', '/devoice [username] - Remove user\'s group. Can be used by: % @ &');
|
|
}
|
|
if (target === 'all' || target === 'mod')
|
|
{
|
|
matched = true;
|
|
socket.emit('console', '/mod [username] - Change user\'s group to %. Can be used by: @ &');
|
|
}
|
|
if (target === 'all' || target === 'demod')
|
|
{
|
|
matched = true;
|
|
socket.emit('console', '/demod [username] - Change user\'s group from % to +. Can be used by: @ &');
|
|
}
|
|
if (target === 'all' || target === 'admin')
|
|
{
|
|
matched = true;
|
|
socket.emit('console', '/admin [username] - Change user\'s group to @. Can be used by: @ &');
|
|
}
|
|
if (target === 'all' || target === 'deadmin')
|
|
{
|
|
matched = true;
|
|
socket.emit('console', '/deadmin [username] - Change user\'s group from @ to %. Can be used by: @ &');
|
|
}
|
|
if (target === 'all' || target === 'help' || target === 'h' || target === '?' || target === 'commands')
|
|
{
|
|
matched = true;
|
|
socket.emit('console', '/help OR /h OR /? - Tells you things.');
|
|
}
|
|
if (!matched)
|
|
{
|
|
socket.emit('console', 'Commands: /msg, /reply, /ip, /ranking, /nick, /help');
|
|
socket.emit('console', 'Moderator commands: /ip, /ban, /unban, /unbanall, /mute, /unmute, /voice, /devoice, /mod, /demod, /admin, /deadmin');
|
|
socket.emit('console', 'For details on all commands, use /help all. For details of a specific command, use something like: /help ban');
|
|
}
|
|
return true;
|
|
}
|
|
else if (cmd === 'unbanall')
|
|
{
|
|
if (user.isMod())
|
|
{
|
|
room.add('All bans have been lifted by '+user.name+'.');
|
|
bannedIps = {};
|
|
mutedIps = {};
|
|
return true;
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
function Lobby(roomid)
|
|
{
|
|
var selfR = this; // a lobby is like a room, selfR makes things simpler
|
|
this.id = roomid;
|
|
this.i = {};
|
|
this.log = [];
|
|
this.lastUpdate = 0;
|
|
this.users = {};
|
|
this.rooms = [];
|
|
this.searchers = [];
|
|
|
|
this.usersChanged = true;
|
|
this.roomsChanged = true;
|
|
|
|
this.getUpdate = function(since, omitUsers, omitRoomList) {
|
|
var update = {room: roomid};
|
|
var i = since;
|
|
if (!i) i = selfR.log.length - 100;
|
|
if (i<0) i = 0;
|
|
update.logStart = i;
|
|
update.logUpdate = [];
|
|
for (;i<selfR.log.length;i++)
|
|
{
|
|
update.logUpdate.push(selfR.log[i]);
|
|
}
|
|
if (!omitRoomList) update.rooms = selfR.getRoomList();
|
|
if (!omitUsers) update.users = selfR.getUserList();
|
|
update.searcher = selfR.searchers.length;
|
|
return update;
|
|
};
|
|
this.getUserList = function()
|
|
{
|
|
var userList = {list: {}, users: 0, guests: 0};
|
|
for (var i in selfR.users)
|
|
{
|
|
if (!selfR.users[i].named)
|
|
{
|
|
userList.guests++;
|
|
continue;
|
|
}
|
|
userList.users++;
|
|
userList.list[selfR.users[i].userid] = selfR.users[i].getIdentity();
|
|
}
|
|
return userList;
|
|
};
|
|
this.getRoomList = function()
|
|
{
|
|
var roomList = {};
|
|
for (i=0; i<selfR.rooms.length; i++)
|
|
{
|
|
var room = selfR.rooms[i];
|
|
if (!room.active) continue;
|
|
var roomData = {};
|
|
if (room.battle && room.battle.sides[0] && room.battle.sides[1])
|
|
{
|
|
if (room.battle.sides[0].user && room.battle.sides[1].user)
|
|
{
|
|
roomData.p1 = room.battle.sides[0].user.getIdentity();
|
|
roomData.p2 = room.battle.sides[1].user.getIdentity();
|
|
}
|
|
else if (room.battle.sides[0].user)
|
|
{
|
|
roomData.p1 = room.battle.sides[0].user.getIdentity();
|
|
}
|
|
else if (room.battle.sides[1].user)
|
|
{
|
|
roomData.p1 = room.battle.sides[1].user.getIdentity();
|
|
}
|
|
}
|
|
roomList[selfR.rooms[i].id] = roomData;
|
|
}
|
|
return roomList;
|
|
};
|
|
this.cancelSearch = function(user, noUpdate) {
|
|
user.cancelChallengeTo();
|
|
for (var i=0; i<selfR.searchers.length; i++)
|
|
{
|
|
var search = selfR.searchers[i];
|
|
if (!search.user.connected)
|
|
{
|
|
selfR.searchers.splice(i,1);
|
|
i--;
|
|
continue;
|
|
}
|
|
if (search.user === user)
|
|
{
|
|
selfR.searchers.splice(i,1);
|
|
search.user.emit('update', {searching: false, room: selfR.id});
|
|
if (!noUpdate)
|
|
{
|
|
selfR.update();
|
|
}
|
|
return true;
|
|
}
|
|
}
|
|
return false;
|
|
};
|
|
this.searchBattle = function(user, format) {
|
|
if (!user.connected) return;
|
|
if (lockdown)
|
|
{
|
|
user.emit('connectionError', 'The server is shutting down. Battles cannot be started at this time.');
|
|
return;
|
|
}
|
|
|
|
var problems = Tools.validateTeam(user.team, format);
|
|
if (problems)
|
|
{
|
|
user.emit('message', "Your team was rejected for the following reasons:\n\n- "+problems.join("\n- "));
|
|
return;
|
|
}
|
|
|
|
for (var i=0; i<selfR.searchers.length; i++)
|
|
{
|
|
var search = selfR.searchers[i];
|
|
if (!search.user.connected)
|
|
{
|
|
selfR.searchers.splice(i,1);
|
|
i--;
|
|
continue;
|
|
}
|
|
if (format === search.format)
|
|
{
|
|
if (search.user === user)
|
|
{
|
|
return;
|
|
}
|
|
selfR.searchers.splice(i,1);
|
|
search.user.emit('update', {searching: false, room: selfR.id});
|
|
search.user.team = search.team;
|
|
selfR.startBattle(search.user, user, format, true);
|
|
return;
|
|
}
|
|
}
|
|
var newSearch = {
|
|
user: user,
|
|
format: format,
|
|
room: selfR.id,
|
|
team: user.team
|
|
};
|
|
var newSearchData = {
|
|
userid: user.userid,
|
|
format: format,
|
|
room: selfR.id
|
|
};
|
|
selfR.searchers.push(newSearch);
|
|
user.emit('update', {searching: newSearchData, room: selfR.id});
|
|
selfR.update();
|
|
};
|
|
this.update = function(excludeUser) {
|
|
var update = selfR.getUpdate(selfR.lastUpdate, !selfR.usersChanged, !selfR.roomsChanged);
|
|
update.room = selfR.id;
|
|
selfR.lastUpdate = selfR.log.length;
|
|
for (var i in selfR.users)
|
|
{
|
|
if (selfR.users[i] === excludeUser) continue;
|
|
selfR.users[i].emit('update', update);
|
|
}
|
|
selfR.usersChanged = false;
|
|
selfR.roomsChanged = false;
|
|
};
|
|
this.updateRooms = function(excludeUser) {
|
|
var update = {
|
|
rooms: selfR.getRoomList()
|
|
};
|
|
update.room = selfR.id;
|
|
for (var i in selfR.users)
|
|
{
|
|
if (selfR.users[i] === excludeUser) continue;
|
|
selfR.users[i].emit('update', update);
|
|
}
|
|
selfR.roomsChanged = false;
|
|
};
|
|
this.add = function(message) {
|
|
selfR.log.push({
|
|
message: message
|
|
});
|
|
selfR.update();
|
|
};
|
|
this.addRaw = function(message) {
|
|
selfR.log.push({
|
|
rawMessage: message
|
|
});
|
|
selfR.update();
|
|
};
|
|
this.initSocket = function(user, socket) {
|
|
var initdata = {
|
|
name: user.name,
|
|
userid: user.userid,
|
|
named: user.named,
|
|
renamePending: user.renamePending,
|
|
token: user.token,
|
|
room: selfR.id,
|
|
rooms: selfR.getRoomList(),
|
|
users: selfR.getUserList(),
|
|
roomType: 'lobby',
|
|
log: selfR.log.slice(-100),
|
|
searcher: selfR.searchers.length,
|
|
}
|
|
socket.emit('init', initdata);
|
|
};
|
|
this.join = function(user) {
|
|
if (!user) return false; // ???
|
|
if (selfR.users[user.userid]) return user;
|
|
|
|
selfR.users[user.userid] = user;
|
|
if (user.named)
|
|
{
|
|
selfR.log.push({name: user.name, action: 'join'});
|
|
selfR.usersChanged = true;
|
|
selfR.update(user);
|
|
}
|
|
|
|
var initdata = {
|
|
name: user.name,
|
|
userid: user.userid,
|
|
named: user.named,
|
|
renamePending: user.renamePending,
|
|
token: user.token,
|
|
room: selfR.id,
|
|
rooms: selfR.getRoomList(),
|
|
users: selfR.getUserList(),
|
|
roomType: 'lobby',
|
|
log: selfR.log.slice(-100),
|
|
searcher: selfR.searchers.length,
|
|
}
|
|
user.emit('init', initdata);
|
|
|
|
return user;
|
|
};
|
|
this.rename = function(user, oldid, joining) {
|
|
if (joining)
|
|
{
|
|
selfR.log.push({name: user.name, action: 'join'});
|
|
}
|
|
delete selfR.users[oldid];
|
|
selfR.users[user.userid] = user;
|
|
selfR.usersChanged = true;
|
|
selfR.update();
|
|
return user;
|
|
};
|
|
this.leave = function(user) {
|
|
if (!user) return; // ...
|
|
delete selfR.users[user.userid];
|
|
selfR.cancelSearch(user, true);
|
|
if (user.named)
|
|
{
|
|
selfR.log.push({name: user.name, action: 'leave'});
|
|
}
|
|
selfR.usersChanged = true;
|
|
selfR.update();
|
|
};
|
|
this.startBattle = function(p1, p2, format, ranked) {
|
|
var newRoom, i=1;
|
|
p1 = getUser(p1);
|
|
p2 = getUser(p2);
|
|
|
|
if (p1 === p2)
|
|
{
|
|
selfR.cancelSearch(p1, true);
|
|
selfR.cancelSearch(p2, true);
|
|
selfR.add('A battle between '+p1.name+' and '+p2.name+' was not started because you can\'t battle your own account. Please use Private Browsing to battle yourself.');
|
|
return;
|
|
}
|
|
|
|
if (lockdown)
|
|
{
|
|
selfR.cancelSearch(p1, true);
|
|
selfR.cancelSearch(p2, true);
|
|
selfR.add('A battle was not started because the server is shutting down.');
|
|
selfR.update();
|
|
return;
|
|
}
|
|
|
|
//console.log('BATTLE START BETWEEN: '+p1.userid+' '+p2.userid);
|
|
while(rooms[selfR.id+'-battle'+i])
|
|
{
|
|
i++;
|
|
}
|
|
newRoom = selfR.addRoom(selfR.id+'-battle'+i, format, p1, p2, selfR.id, ranked);
|
|
p1.joinRoom(newRoom);
|
|
p2.joinRoom(newRoom);
|
|
newRoom.joinBattle(p1);
|
|
newRoom.joinBattle(p2);
|
|
selfR.log.push({
|
|
name: p1.name,
|
|
name2: p2.name,
|
|
room: newRoom.id,
|
|
format: format,
|
|
action: 'battle'
|
|
});
|
|
selfR.cancelSearch(p1, true);
|
|
selfR.cancelSearch(p2, true);
|
|
selfR.roomsChanged = true;
|
|
selfR.update();
|
|
};
|
|
this.addRoom = function(room, format, p1, p2, parent, ranked) {
|
|
room = newRoom(room, format, p1, p2, parent, ranked);
|
|
if (typeof room.i[selfR.id] !== 'undefined') return;
|
|
room.i[selfR.id] = selfR.rooms.length;
|
|
selfR.rooms.push(room);
|
|
return room;
|
|
};
|
|
this.removeRoom = function(room) {
|
|
room = getRoom(room);
|
|
if (typeof room.i[selfR.id] !== 'undefined')
|
|
{
|
|
selfR.rooms = selfR.rooms.splice(room.i[selfR.id],1);
|
|
delete room.i[selfR.id];
|
|
for (var i=0; i<selfR.rooms.length; i++)
|
|
{
|
|
selfR.rooms[i].i[selfR.id] = i;
|
|
}
|
|
}
|
|
};
|
|
this.isEmpty = function() { return false; };
|
|
this.isFull = function() { return false; };
|
|
this.chat = function(user, message, socket) {
|
|
if (!user.named || !message.trim().length) return;
|
|
var cmd = '', target = '';
|
|
if (message.substr(0,2) === '//')
|
|
{
|
|
message = message.substr(1);
|
|
}
|
|
else if (message.substr(0,1) === '/')
|
|
{
|
|
var spaceIndex = message.indexOf(' ');
|
|
if (spaceIndex > 0)
|
|
{
|
|
cmd = message.substr(1, spaceIndex-1);
|
|
target = message.substr(spaceIndex+1);
|
|
}
|
|
else
|
|
{
|
|
cmd = message.substr(1);
|
|
target = '';
|
|
}
|
|
}
|
|
|
|
if (parseCommand(user, cmd, target, selfR, socket))
|
|
{
|
|
// do nothing
|
|
}
|
|
else if (message.substr(0,3) === '>> ')
|
|
{
|
|
var cmd = message.substr(3);
|
|
|
|
var room = selfR;
|
|
var me = user;
|
|
selfR.log.push({
|
|
name: user.getIdentity(),
|
|
message: '>> '+cmd
|
|
});
|
|
if (user.group === '&')
|
|
{
|
|
try
|
|
{
|
|
selfR.log.push({
|
|
name: user.getIdentity(),
|
|
message: '<< '+eval(cmd)
|
|
});
|
|
}
|
|
catch (e)
|
|
{
|
|
selfR.log.push({
|
|
name: user.getIdentity(),
|
|
message: '<< error: '+e.message
|
|
});
|
|
user.emit('console', '<< error details: '+JSON.stringify(e.stack));
|
|
}
|
|
}
|
|
else
|
|
{
|
|
selfR.log.push({
|
|
name: user.getIdentity(),
|
|
message: '<< Access denied. To use the developer console, you must be: &'
|
|
});
|
|
}
|
|
}
|
|
else if (!user.muted)
|
|
{
|
|
selfR.log.push({
|
|
name: user.getIdentity(),
|
|
message: message
|
|
});
|
|
}
|
|
selfR.update();
|
|
};
|
|
}
|
|
|
|
|
|
rooms = {};
|
|
console.log("NEW LOBBY: lobby");
|
|
var lobby = new Lobby('lobby');
|
|
rooms.lobby = lobby;
|
|
|
|
getRoom = function(roomid)
|
|
{
|
|
if (roomid && roomid.id) return roomid;
|
|
if (!roomid) roomid = 'default';
|
|
if (!rooms[roomid])
|
|
{
|
|
return rooms.lobby;
|
|
}
|
|
return rooms[roomid];
|
|
}
|
|
newRoom = function(roomid, format, p1, p2, parent, ranked)
|
|
{
|
|
if (roomid && roomid.id) return roomid;
|
|
if (!roomid) roomid = 'default';
|
|
if (!rooms[roomid])
|
|
{
|
|
console.log("NEW ROOM: "+roomid);
|
|
rooms[roomid] = new Room(roomid, format, p1, p2, parent, ranked);
|
|
}
|
|
return rooms[roomid];
|
|
}
|
|
|
|
mutedIps = {
|
|
};
|
|
bannedIps = {
|
|
};
|
|
|
|
function resolveUser(you, socket)
|
|
{
|
|
if (!you)
|
|
{
|
|
socket.emit('connectionError', 'There has been a connection error. Please refresh the page.');
|
|
return false;
|
|
}
|
|
return you.user;
|
|
}
|
|
|
|
io.sockets.on('connection', function (socket) {
|
|
var you = null;
|
|
console.log('INIT SOCKET: '+socket.id);
|
|
|
|
if (socket.handshake && socket.handshake.address && socket.handshake.address.address)
|
|
{
|
|
if (bannedIps[socket.handshake.address.address])
|
|
{
|
|
console.log('IP BANNED: '+socket.handshake.address.address);
|
|
return;
|
|
}
|
|
}
|
|
|
|
socket.on('join', function(data) {
|
|
if (!you)
|
|
{
|
|
you = getUser(data.name, socket, data.token, data.room);
|
|
console.log('JOIN: '+data.name+' => '+you.name+' ['+data.token+']');
|
|
}
|
|
else
|
|
{
|
|
var youUser = resolveUser(you, socket);
|
|
if (!youUser) return;
|
|
youUser.joinRoom(data.room, socket);
|
|
}
|
|
});
|
|
socket.on('rename', function(data) {
|
|
var youUser = resolveUser(you, socket);
|
|
if (!youUser) return;
|
|
youUser.rename(data.name, data.token);
|
|
});
|
|
socket.on('chat', function(message) {
|
|
var youUser = resolveUser(you, socket);
|
|
if (!youUser) return;
|
|
if (!message) return;
|
|
getRoom(message.room).chat(youUser, message.message, socket);
|
|
});
|
|
socket.on('leave', function(data) {
|
|
var youUser = resolveUser(you, socket);
|
|
if (!youUser) return;
|
|
if (!data) return;
|
|
youUser.leaveRoom(getRoom(data.room), socket);
|
|
});
|
|
socket.on('leaveBattle', function(data) {
|
|
var youUser = resolveUser(you, socket);
|
|
if (!youUser) return;
|
|
if (!data) return;
|
|
getRoom(data.room).leaveBattle(youUser);
|
|
});
|
|
socket.on('joinBattle', function(data) {
|
|
var youUser = resolveUser(you, socket);
|
|
if (!youUser) return;
|
|
getRoom(data.room).joinBattle(youUser);
|
|
});
|
|
|
|
socket.on('disconnect', function() {
|
|
var youUser = resolveUser(you, socket);
|
|
if (!youUser) return;
|
|
youUser.disconnect(socket);
|
|
});
|
|
socket.on('challenge', function(data) {
|
|
var youUser = resolveUser(you, socket);
|
|
if (!youUser) return;
|
|
console.log('CHALLENGE: '+youUser.name+' => '+data.userid+' ('+data.act+')');
|
|
switch (data.act)
|
|
{
|
|
case 'make':
|
|
youUser.makeChallenge(data.userid, data.format);
|
|
break;
|
|
case 'cancel':
|
|
youUser.cancelChallengeTo(data.userid);
|
|
break;
|
|
case 'accept':
|
|
youUser.acceptChallengeFrom(data.userid);
|
|
break;
|
|
case 'reject':
|
|
youUser.rejectChallengeFrom(data.userid);
|
|
break;
|
|
}
|
|
});
|
|
socket.on('decision', function(data) {
|
|
var youUser = resolveUser(you, socket);
|
|
if (!youUser) return;
|
|
var room = getRoom(data.room);
|
|
switch (data.choice)
|
|
{
|
|
case 'move':
|
|
case 'switch':
|
|
case 'undo':
|
|
case 'team':
|
|
if (room.decision) room.decision(youUser,data.choice,data.move);
|
|
break;
|
|
case 'search':
|
|
if (data.search)
|
|
{
|
|
/* if (data.name)
|
|
{
|
|
youUser.rename(data.name, data.token);
|
|
} */
|
|
if (room.searchBattle) room.searchBattle(youUser, data.format);
|
|
}
|
|
else
|
|
{
|
|
if (room.cancelSearch) room.cancelSearch(youUser);
|
|
}
|
|
break;
|
|
}
|
|
});
|
|
socket.on('saveTeam', function(data) {
|
|
var youUser = resolveUser(you, socket);
|
|
if (!youUser) return;
|
|
youUser.team = data.team;
|
|
youUser.emit('update', {team: 'saved', room: 'teambuilder'});
|
|
});
|
|
});
|
|
|