ygopro-server.js 173 KB
Newer Older
mercury233's avatar
mercury233 committed
1
// Generated by CoffeeScript 1.12.7
神楽坂玲奈's avatar
init  
神楽坂玲奈 committed
2
(function() {
nanahira's avatar
nanahira committed
3
  var CLIENT_get_authorize_key, CLIENT_get_kick_reconnect_target, CLIENT_heartbeat_register, CLIENT_heartbeat_unregister, CLIENT_import_data, CLIENT_is_able_to_kick_reconnect, CLIENT_is_able_to_reconnect, CLIENT_is_banned_by_mc, CLIENT_is_player, CLIENT_kick, CLIENT_kick_reconnect, CLIENT_pre_reconnect, CLIENT_reconnect, CLIENT_reconnect_register, CLIENT_reconnect_unregister, CLIENT_send_pre_reconnect_info, CLIENT_send_reconnect_info, CLIENT_send_replays, Cloud_replay_ids, ROOM_all, ROOM_bad_ip, ROOM_ban_player, ROOM_clear_disconnect, ROOM_connected_ip, ROOM_find_by_name, ROOM_find_by_port, ROOM_find_by_title, ROOM_find_or_create_ai, ROOM_find_or_create_by_name, ROOM_find_or_create_random, ROOM_player_flee, ROOM_player_get_score, ROOM_player_lose, ROOM_player_win, ROOM_players_banned, ROOM_players_oppentlist, ROOM_players_scores, ROOM_unwelcome, ROOM_validate, Room, SERVER_clear_disconnect, SOCKET_flush_data, _, addCallback, auth, badwords, ban_user, bunyan, challonge, challonge_cache, challonge_module_name, challonge_queue_callbacks, chat_color, config, cppversion, crypto, date, default_config, default_data, dialogues, disconnect_list, duel_log, e, exec, execFile, fs, geoip, get_callback, get_memory_usage, http, http_server, https, https_server, import_datas, imported, is_requesting, j, l, len, len1, lflists, list, loadJSON, load_dialogues, load_tips, log, long_resolve_cards, memory_usage, merge, moment, net, oldbadwords, oldconfig, olddialogues, oldduellog, oldtips, options, os, path, pgClient, pg_client, pg_query, redis, redisdb, ref, ref1, refresh_challonge_cache, release_disconnect, report_to_big_brother, request, requestListener, roomlist, setting_change, setting_save, settings, spawn, spawnSync, spawn_windbot, tips, url, users_cache, wait_room_start, wait_room_start_arena, windbot_looplimit, windbots, ygopro, zlib;
神楽坂玲奈's avatar
init  
神楽坂玲奈 committed
4

神楽坂玲奈's avatar
神楽坂玲奈 committed
5
  net = require('net');
神楽坂玲奈's avatar
init  
神楽坂玲奈 committed
6

神楽坂玲奈's avatar
神楽坂玲奈 committed
7 8 9
  http = require('http');

  url = require('url');
神楽坂玲奈's avatar
init  
神楽坂玲奈 committed
10

神楽坂玲奈's avatar
神楽坂玲奈 committed
11 12 13 14
  path = require('path');

  fs = require('fs');

mercury233's avatar
mercury233 committed
15 16
  os = require('os');

17 18
  crypto = require('crypto');

mercury233's avatar
mercury233 committed
19 20
  exec = require('child_process').exec;

神楽坂玲奈's avatar
11.7  
神楽坂玲奈 committed
21 22
  execFile = require('child_process').execFile;

mercury233's avatar
mercury233 committed
23 24 25 26
  spawn = require('child_process').spawn;

  spawnSync = require('child_process').spawnSync;

神楽坂玲奈's avatar
神楽坂玲奈 committed
27 28
  _ = require('underscore');

神楽坂玲奈's avatar
tip  
神楽坂玲奈 committed
29 30 31 32 33 34
  _.str = require('underscore.string');

  _.mixin(_.str.exports());

  request = require('request');

神楽坂玲奈's avatar
11.7  
神楽坂玲奈 committed
35 36
  bunyan = require('bunyan');

mercury233's avatar
mercury233 committed
37 38 39 40
  log = bunyan.createLogger({
    name: "mycard"
  });

41 42
  moment = require('moment');

mercury233's avatar
mercury233 committed
43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60
  moment.locale('zh-cn', {
    relativeTime: {
      future: '%s内',
      past: '%s前',
      s: '%d秒',
      m: '1分钟',
      mm: '%d分钟',
      h: '1小时',
      hh: '%d小时',
      d: '1天',
      dd: '%d天',
      M: '1个月',
      MM: '%d个月',
      y: '1年',
      yy: '%d年'
    }
  });

nanahira's avatar
nanahira committed
61
  import_datas = ["abuse_count", "ban_mc", "vpass", "rag", "rid", "is_post_watcher", "retry_count", "name", "pass", "name_vpass", "is_first", "lp", "card_count", "is_host", "pos", "surrend_confirm", "kick_count", "deck_saved", "main", "side", "side_interval", "side_tcount", "selected_preduel", "last_game_msg", "last_game_msg_title", "last_hint_msg", "start_deckbuf", "challonge_info", "ready_trap", "join_time", "arena_quit_free", "replays_sent"];
nanahira's avatar
nanahira committed
62

mercury233's avatar
mercury233 committed
63 64
  merge = require('deepmerge');

mercury233's avatar
mercury233 committed
65 66
  loadJSON = require('load-json-file').sync;

mercury233's avatar
mercury233 committed
67 68 69 70
  if (!fs.existsSync('./config')) {
    fs.mkdirSync('./config');
  }

mercury233's avatar
mercury233 committed
71
  try {
mercury233's avatar
mercury233 committed
72
    oldconfig = loadJSON('./config.user.json');
mercury233's avatar
mercury233 committed
73 74 75 76 77 78 79 80 81 82 83 84 85 86
    if (oldconfig.tips) {
      oldtips = {};
      oldtips.file = './config/tips.json';
      oldtips.tips = oldconfig.tips;
      fs.writeFileSync(oldtips.file, JSON.stringify(oldtips, null, 2));
      delete oldconfig.tips;
    }
    if (oldconfig.dialogues) {
      olddialogues = {};
      olddialogues.file = './config/dialogues.json';
      olddialogues.dialogues = oldconfig.dialogues;
      fs.writeFileSync(olddialogues.file, JSON.stringify(olddialogues, null, 2));
      delete oldconfig.dialogues;
    }
mercury233's avatar
fix  
mercury233 committed
87 88 89 90 91 92 93 94
    if (oldconfig.modules) {
      if (oldconfig.modules.tournament_mode && oldconfig.modules.tournament_mode.duel_log) {
        oldduellog = {};
        oldduellog.file = './config/duel_log.json';
        oldduellog.duel_log = oldconfig.modules.tournament_mode.duel_log;
        fs.writeFileSync(oldduellog.file, JSON.stringify(oldduellog, null, 2));
        delete oldconfig.oldduellog;
      }
95
    }
mercury233's avatar
mercury233 committed
96
    oldbadwords = {};
mercury233's avatar
fix  
mercury233 committed
97 98 99 100 101 102 103 104 105 106 107 108 109
    if (oldconfig.ban) {
      if (oldconfig.ban.badword_level0) {
        oldbadwords.level0 = oldconfig.ban.badword_level0;
      }
      if (oldconfig.ban.badword_level1) {
        oldbadwords.level1 = oldconfig.ban.badword_level1;
      }
      if (oldconfig.ban.badword_level2) {
        oldbadwords.level2 = oldconfig.ban.badword_level2;
      }
      if (oldconfig.ban.badword_level3) {
        oldbadwords.level3 = oldconfig.ban.badword_level3;
      }
mercury233's avatar
mercury233 committed
110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125
    }
    if (!_.isEmpty(oldbadwords)) {
      oldbadwords.file = './config/badwords.json';
      fs.writeFileSync(oldbadwords.file, JSON.stringify(oldbadwords, null, 2));
      delete oldconfig.ban.badword_level0;
      delete oldconfig.ban.badword_level1;
      delete oldconfig.ban.badword_level2;
      delete oldconfig.ban.badword_level3;
    }
    if (!_.isEmpty(oldconfig)) {
      fs.writeFileSync('./config/config.json', JSON.stringify(oldconfig, null, 2));
      log.info('imported old config from config.user.json');
    }
    fs.renameSync('./config.user.json', './config.user.bak');
  } catch (error1) {
    e = error1;
mercury233's avatar
mercury233 committed
126
    if (e.code !== 'ENOENT') {
mercury233's avatar
mercury233 committed
127 128 129
      log.info(e);
    }
  }
mercury233's avatar
mercury233 committed
130

mercury233's avatar
mercury233 committed
131 132 133
  setting_save = function(settings) {
    fs.writeFileSync(settings.file, JSON.stringify(settings, null, 2));
  };
mercury233's avatar
mercury233 committed
134

mercury233's avatar
mercury233 committed
135
  setting_change = function(settings, path, val) {
mercury233's avatar
mercury233 committed
136
    var key, target;
mercury233's avatar
mercury233 committed
137 138 139
    if (_.isString(val)) {
      log.info("setting changed", path, val);
    }
mercury233's avatar
mercury233 committed
140 141 142 143 144 145 146 147 148 149 150 151
    path = path.split(':');
    if (path.length === 0) {
      settings[path[0]] = val;
    } else {
      target = settings;
      while (path.length > 1) {
        key = path.shift();
        target = target[key];
      }
      key = path.shift();
      target[key] = val;
    }
mercury233's avatar
mercury233 committed
152
    setting_save(settings);
mercury233's avatar
mercury233 committed
153
  };
神楽坂玲奈's avatar
11.7  
神楽坂玲奈 committed
154

mercury233's avatar
mercury233 committed
155
  default_config = loadJSON('./data/default_config.json');
mercury233's avatar
mercury233 committed
156 157

  try {
mercury233's avatar
mercury233 committed
158
    config = loadJSON('./config/config.json');
mercury233's avatar
mercury233 committed
159 160 161 162 163 164 165 166 167 168
  } catch (error1) {
    config = {};
  }

  settings = global.settings = merge(default_config, config, {
    arrayMerge: function(destination, source) {
      return source;
    }
  });

nanahira's avatar
nanahira committed
169 170
  auth = require('./ygopro-auth.js');

nanahira's avatar
nanahira committed
171 172
  imported = false;

nanahira's avatar
nanahira committed
173 174
  if (settings.modules.http.quick_death_rule === true) {
    settings.modules.http.quick_death_rule = 1;
nanahira's avatar
nanahira committed
175 176 177 178 179 180 181 182 183
    imported = true;
  }

  if (settings.modules.cloud_replay.redis_port) {
    settings.modules.cloud_replay.redis.port = settings.modules.cloud_replay.redis_port;
    delete settings.modules.cloud_replay.redis_port;
    imported = true;
  }

nanahira's avatar
nanahira committed
184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202
  if (settings.modules.http.password) {
    auth.add_user("olduser", settings.modules.http.password, true, {
      "get_rooms": true,
      "shout": true,
      "stop": true,
      "change_settings": true,
      "ban_user": true,
      "kick_user": true,
      "start_death": true
    });
    delete settings.modules.http.password;
    imported = true;
  }

  if (settings.modules.tournament_mode.password) {
    auth.add_user("tournament", settings.modules.tournament_mode.password, true, {
      "duel_log": true,
      "download_replay": true,
      "clear_duel_log": true,
nanahira's avatar
fix  
nanahira committed
203
      "deck_dashboard_read": true,
nanahira's avatar
nanahira committed
204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225
      "deck_dashboard_write": true
    });
    delete settings.modules.tournament_mode.password;
    imported = true;
  }

  if (settings.modules.pre_util.password) {
    auth.add_user("pre", settings.modules.pre_util.password, true, {
      "pre_dashboard": true
    });
    delete settings.modules.pre_util.password;
    imported = true;
  }

  if (settings.modules.update_util.password) {
    auth.add_user("update", settings.modules.update_util.password, true, {
      "update_dashboard": true
    });
    delete settings.modules.update_util.password;
    imported = true;
  }

nanahira's avatar
nanahira committed
226
  if (imported) {
nanahira's avatar
nanahira committed
227 228 229
    setting_save(settings);
  }

mercury233's avatar
mercury233 committed
230
  default_data = loadJSON('./data/default_data.json');
mercury233's avatar
mercury233 committed
231 232

  try {
mercury233's avatar
mercury233 committed
233
    tips = loadJSON('./config/tips.json');
mercury233's avatar
mercury233 committed
234 235 236 237 238 239
  } catch (error1) {
    tips = default_data.tips;
    setting_save(tips);
  }

  try {
mercury233's avatar
mercury233 committed
240
    dialogues = loadJSON('./config/dialogues.json');
mercury233's avatar
mercury233 committed
241 242 243 244 245 246
  } catch (error1) {
    dialogues = default_data.dialogues;
    setting_save(dialogues);
  }

  try {
mercury233's avatar
mercury233 committed
247
    badwords = loadJSON('./config/badwords.json');
mercury233's avatar
mercury233 committed
248 249 250 251 252
  } catch (error1) {
    badwords = default_data.badwords;
    setting_save(badwords);
  }

253
  try {
mercury233's avatar
mercury233 committed
254
    duel_log = loadJSON('./config/duel_log.json');
255 256 257 258 259
  } catch (error1) {
    duel_log = default_data.duel_log;
    setting_save(duel_log);
  }

nanahira's avatar
nanahira committed
260
  try {
mercury233's avatar
mercury233 committed
261
    chat_color = loadJSON('./config/chat_color.json');
nanahira's avatar
nanahira committed
262 263 264 265 266
  } catch (error1) {
    chat_color = default_data.chat_color;
    setting_save(chat_color);
  }

267
  try {
mercury233's avatar
mercury233 committed
268
    cppversion = parseInt(fs.readFileSync('ygopro/gframe/game.cpp', 'utf8').match(/PRO_VERSION = ([x\dABCDEF]+)/)[1], '16');
mercury233's avatar
mercury233 committed
269
    setting_change(settings, "version", cppversion);
mercury233's avatar
fix  
mercury233 committed
270
    log.info("ygopro version 0x" + settings.version.toString(16), "(from source code)");
271
  } catch (error1) {
mercury233's avatar
fix  
mercury233 committed
272
    log.info("ygopro version 0x" + settings.version.toString(16), "(from config)");
273
  }
274

nanahira's avatar
nanahira committed
275 276 277 278
  lflists = [];

  try {
    ref = fs.readFileSync('ygopro/expansions/lflist.conf', 'utf8').match(/!.*/g);
mercury233's avatar
mercury233 committed
279 280
    for (j = 0, len = ref.length; j < len; j++) {
      list = ref[j];
mercury233's avatar
mercury233 committed
281 282 283 284
      date = list.match(/!([\d\.]+)/);
      if (!date) {
        continue;
      }
nanahira's avatar
nanahira committed
285
      lflists.push({
神楽坂玲奈's avatar
神楽坂玲奈 committed
286
        date: moment(list.match(/!([\d\.]+)/)[1], 'YYYY.MM.DD').utcOffset("-08:00"),
神楽坂玲奈's avatar
fix  
神楽坂玲奈 committed
287
        tcg: list.indexOf('TCG') !== -1
神楽坂玲奈's avatar
神楽坂玲奈 committed
288 289
      });
    }
nanahira's avatar
nanahira committed
290 291 292 293 294 295
  } catch (error1) {

  }

  try {
    ref1 = fs.readFileSync('ygopro/lflist.conf', 'utf8').match(/!.*/g);
nanahira's avatar
nanahira committed
296 297
    for (l = 0, len1 = ref1.length; l < len1; l++) {
      list = ref1[l];
nanahira's avatar
nanahira committed
298 299 300 301 302 303 304 305 306 307 308 309
      date = list.match(/!([\d\.]+)/);
      if (!date) {
        continue;
      }
      lflists.push({
        date: moment(list.match(/!([\d\.]+)/)[1], 'YYYY.MM.DD').utcOffset("-08:00"),
        tcg: list.indexOf('TCG') !== -1
      });
    }
  } catch (error1) {

  }
神楽坂玲奈's avatar
神楽坂玲奈 committed
310

mercury233's avatar
mercury233 committed
311
  if (settings.modules.cloud_replay.enabled) {
mercury233's avatar
mercury233 committed
312 313
    redis = require('redis');
    zlib = require('zlib');
nanahira's avatar
nanahira committed
314
    redisdb = redis.createClient(settings.modules.cloud_replay.redis);
mercury233's avatar
mercury233 committed
315 316 317
    redisdb.on('error', function(err) {
      log.warn(err);
    });
mercury233's avatar
mercury233 committed
318 319
  }

mercury233's avatar
mercury233 committed
320
  if (settings.modules.windbot.enabled) {
mercury233's avatar
mercury233 committed
321
    windbots = loadJSON(settings.modules.windbot.botlist).windbots;
mercury233's avatar
mercury233 committed
322 323
  }

nanahira's avatar
nanahira committed
324 325 326 327
  if (settings.modules.heartbeat_detection.enabled) {
    long_resolve_cards = loadJSON('./data/long_resolve_cards.json');
  }

神楽坂玲奈's avatar
神楽坂玲奈 committed
328
  ygopro = require('./ygopro.js');
神楽坂玲奈's avatar
init  
神楽坂玲奈 committed
329

mercury233's avatar
mercury233 committed
330
  if (settings.modules.http.websocket_roomlist) {
mercury233's avatar
mercury233 committed
331 332
    roomlist = require('./roomlist.js');
  }
神楽坂玲奈's avatar
神楽坂玲奈 committed
333

mercury233's avatar
mercury233 committed
334 335 336 337
  if (settings.modules.i18n.auto_pick) {
    geoip = require('geoip-country-lite');
  }

神楽坂玲奈's avatar
fix  
神楽坂玲奈 committed
338 339
  users_cache = {};

mercury233's avatar
mercury233 committed
340
  if (settings.modules.mycard.enabled) {
mercury233's avatar
merge  
mercury233 committed
341
    pgClient = require('pg').Client;
mercury233's avatar
mercury233 committed
342
    pg_client = new pgClient(settings.modules.mycard.auth_database);
mercury233's avatar
fix  
mercury233 committed
343 344 345
    pg_client.on('error', function(err) {
      log.warn("PostgreSQL ERROR: ", err);
    });
mercury233's avatar
merge  
mercury233 committed
346
    pg_query = pg_client.query('SELECT username, id from users');
mercury233's avatar
fix  
mercury233 committed
347 348 349
    pg_query.on('error', function(err) {
      log.warn("PostgreSQL Query ERROR: ", err);
    });
mercury233's avatar
merge  
mercury233 committed
350 351 352 353 354 355 356 357 358
    pg_query.on('row', function(row) {
      users_cache[row.username] = row.id;
    });
    pg_query.on('end', function(result) {
      log.info("users loaded", result.rowCount);
    });
    pg_client.on('drain', pg_client.end.bind(pg_client));
    log.info("loading mycard user...");
    pg_client.connect();
nanahira's avatar
nanahira committed
359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377
    if (settings.modules.arena_mode.enabled && settings.modules.arena_mode.init_post.enabled) {
      request.post({
        url: settings.modules.arena_mode.init_post.url,
        qs: {
          ak: settings.modules.arena_mode.init_post.accesskey,
          arena: settings.modules.arena_mode.mode
        }
      }, (function(_this) {
        return function(error, response, body) {
          if (error) {
            log.warn('ARENA INIT POST ERROR', error);
          } else {
            if (response.statusCode >= 400) {
              log.warn('ARENA INIT POST FAIL', response.statusCode, response.statusMessage, body);
            }
          }
        };
      })(this));
    }
mercury233's avatar
merge  
mercury233 committed
378 379
  }

nanahira's avatar
nanahira committed
380
  if (settings.modules.challonge.enabled) {
381 382 383 384 385
    challonge_module_name = 'challonge';
    if (settings.modules.challonge.use_custom_module) {
      challonge_module_name = settings.modules.challonge.use_custom_module;
    }
    challonge = require(challonge_module_name).createClient({
nanahira's avatar
nanahira committed
386 387
      apiKey: settings.modules.challonge.api_key
    });
nanahira's avatar
nanahira committed
388 389 390
    if (settings.modules.challonge.cache_ttl) {
      challonge_cache = [];
    }
nanahira's avatar
nanahira committed
391
    challonge_queue_callbacks = [[], []];
nanahira's avatar
nanahira committed
392
    is_requesting = [null, null];
nanahira's avatar
nanahira committed
393 394 395
    get_callback = function(challonge_type, _callback) {
      return (function(err, data) {
        var cur_callback;
nanahira's avatar
nanahira committed
396
        if (settings.modules.challonge.cache_ttl && !err && data) {
nanahira's avatar
nanahira committed
397 398
          challonge_cache[challonge_type] = data;
        }
nanahira's avatar
nanahira committed
399
        is_requesting[challonge_type] = null;
nanahira's avatar
nanahira committed
400 401
        _callback(err, data);
        while (challonge_queue_callbacks[challonge_type].length) {
nanahira's avatar
fix  
nanahira committed
402
          cur_callback = challonge_queue_callbacks[challonge_type].splice(0, 1)[0];
nanahira's avatar
nanahira committed
403 404 405 406 407
          cur_callback(err, data);
        }
      });
    };
    challonge.participants._index = function(_data) {
nanahira's avatar
js  
nanahira committed
408
      var err;
nanahira's avatar
nanahira committed
409
      if (settings.modules.challonge.cache_ttl && challonge_cache[0]) {
nanahira's avatar
nanahira committed
410
        _data.callback(null, challonge_cache[0]);
nanahira's avatar
nanahira committed
411
      } else if (is_requesting[0] && moment() - is_requesting[0] <= 5000) {
nanahira's avatar
nanahira committed
412 413 414
        challonge_queue_callbacks[0].push(_data.callback);
      } else {
        _data.callback = get_callback(0, _data.callback);
nanahira's avatar
nanahira committed
415
        is_requesting[0] = moment();
nanahira's avatar
js  
nanahira committed
416 417 418 419 420 421
        try {
          challonge.participants.index(_data);
        } catch (error1) {
          err = error1;
          _data.callback(err, null);
        }
nanahira's avatar
nanahira committed
422 423 424
      }
    };
    challonge.matches._index = function(_data) {
nanahira's avatar
js  
nanahira committed
425
      var err;
nanahira's avatar
nanahira committed
426
      if (settings.modules.challonge.cache_ttl && challonge_cache[1]) {
nanahira's avatar
nanahira committed
427
        _data.callback(null, challonge_cache[1]);
nanahira's avatar
nanahira committed
428
      } else if (is_requesting[1] && moment() - is_requesting[1] <= 5000) {
nanahira's avatar
nanahira committed
429 430 431
        challonge_queue_callbacks[1].push(_data.callback);
      } else {
        _data.callback = get_callback(1, _data.callback);
nanahira's avatar
nanahira committed
432
        is_requesting[1] = moment();
nanahira's avatar
js  
nanahira committed
433 434 435 436 437 438
        try {
          challonge.matches.index(_data);
        } catch (error1) {
          err = error1;
          _data.callback(err, null);
        }
nanahira's avatar
nanahira committed
439 440
      }
    };
nanahira's avatar
nanahira committed
441 442 443 444 445 446 447 448 449
    challonge.matches._update = function(_data) {
      var err;
      try {
        challonge.matches.update(_data);
      } catch (error1) {
        err = error1;
        log.warn("Errored pushing scores to Challonge.", err);
      }
    };
nanahira's avatar
nanahira committed
450
    refresh_challonge_cache = function() {
nanahira's avatar
nanahira committed
451 452 453 454
      if (settings.modules.challonge.cache_ttl) {
        challonge_cache[0] = null;
        challonge_cache[1] = null;
      }
nanahira's avatar
nanahira committed
455 456
    };
    refresh_challonge_cache();
nanahira's avatar
nanahira committed
457 458 459
    if (settings.modules.challonge.cache_ttl) {
      setInterval(refresh_challonge_cache, settings.modules.challonge.cache_ttl);
    }
nanahira's avatar
nanahira committed
460 461
  }

mercury233's avatar
mercury233 committed
462 463
  memory_usage = 0;

mercury233's avatar
mercury233 committed
464
  get_memory_usage = function() {
mercury233's avatar
mercury233 committed
465 466
    var prc_free;
    prc_free = exec("free");
mercury233's avatar
fix  
mercury233 committed
467
    prc_free.stdout.on('data', function(data) {
mercury233's avatar
mercury233 committed
468 469 470 471
      var actualFree, buffers, cached, free, line, lines, new_free, percentUsed, total;
      lines = data.toString().split(/\n/g);
      line = lines[0].split(/\s+/);
      new_free = line[6] === 'available' ? true : false;
mercury233's avatar
mercury233 committed
472 473 474 475
      line = lines[1].split(/\s+/);
      total = parseInt(line[1], 10);
      free = parseInt(line[3], 10);
      buffers = parseInt(line[5], 10);
mercury233's avatar
mercury233 committed
476 477 478 479 480 481
      if (new_free) {
        actualFree = parseInt(line[6], 10);
      } else {
        cached = parseInt(line[6], 10);
        actualFree = free + buffers + cached;
      }
mercury233's avatar
mercury233 committed
482
      percentUsed = parseFloat(((1 - (actualFree / total)) * 100).toFixed(2));
mercury233's avatar
fix  
mercury233 committed
483
      memory_usage = percentUsed;
mercury233's avatar
mercury233 committed
484
    });
mercury233's avatar
mercury233 committed
485 486
  };

mercury233's avatar
mercury233 committed
487 488 489 490
  get_memory_usage();

  setInterval(get_memory_usage, 3000);

mercury233's avatar
mercury233 committed
491 492
  Cloud_replay_ids = [];

mercury233's avatar
mercury233 committed
493 494 495 496 497 498
  ROOM_all = [];

  ROOM_players_oppentlist = {};

  ROOM_players_banned = [];

499 500
  ROOM_players_scores = {};

mercury233's avatar
mercury233 committed
501 502 503 504
  ROOM_connected_ip = {};

  ROOM_bad_ip = {};

mercury233's avatar
mercury233 committed
505
  ban_user = function(name) {
nanahira's avatar
nanahira committed
506
    var bad_ip, len2, len3, m, n, player, ref2, room;
mercury233's avatar
mercury233 committed
507
    settings.ban.banned_user.push(name);
mercury233's avatar
mercury233 committed
508
    setting_save(settings);
mercury233's avatar
mercury233 committed
509
    bad_ip = 0;
nanahira's avatar
nanahira committed
510 511
    for (m = 0, len2 = ROOM_all.length; m < len2; m++) {
      room = ROOM_all[m];
mercury233's avatar
mercury233 committed
512
      if (room && room.established) {
nanahira's avatar
nanahira committed
513
        ref2 = room.players;
nanahira's avatar
nanahira committed
514 515
        for (n = 0, len3 = ref2.length; n < len3; n++) {
          player = ref2[n];
mercury233's avatar
mercury233 committed
516 517 518 519 520
          if (player && (player.name === name || player.ip === bad_ip)) {
            bad_ip = player.ip;
            ROOM_bad_ip[bad_ip] = 99;
            settings.ban.banned_ip.push(player.ip);
            ygopro.stoc_send_chat_to_room(room, player.name + " ${kicked_by_system}", ygopro.constants.COLORS.RED);
nanahira's avatar
nanahira committed
521
            CLIENT_send_replays(player, room);
nanahira's avatar
nanahira committed
522
            CLIENT_kick(player);
mercury233's avatar
mercury233 committed
523 524 525 526 527 528 529
            continue;
          }
        }
      }
    }
  };

mercury233's avatar
mercury233 committed
530
  ROOM_ban_player = function(name, ip, reason, countadd) {
mercury233's avatar
mercury233 committed
531
    var bannedplayer, bantime;
mercury233's avatar
mercury233 committed
532 533 534
    if (countadd == null) {
      countadd = 1;
    }
535 536 537
    if (settings.modules.test_mode.no_ban_player) {
      return;
    }
mercury233's avatar
mercury233 committed
538 539 540 541
    bannedplayer = _.find(ROOM_players_banned, function(bannedplayer) {
      return ip === bannedplayer.ip;
    });
    if (bannedplayer) {
mercury233's avatar
mercury233 committed
542
      bannedplayer.count = bannedplayer.count + countadd;
mercury233's avatar
mercury233 committed
543 544 545 546 547 548 549 550 551 552 553 554
      bantime = bannedplayer.count > 3 ? Math.pow(2, bannedplayer.count - 3) * 2 : 0;
      bannedplayer.time = moment() < bannedplayer.time ? moment(bannedplayer.time).add(bantime, 'm') : moment().add(bantime, 'm');
      if (!_.find(bannedplayer.reasons, function(bannedreason) {
        return bannedreason === reason;
      })) {
        bannedplayer.reasons.push(reason);
      }
      bannedplayer.need_tip = true;
    } else {
      bannedplayer = {
        "ip": ip,
        "time": moment(),
mercury233's avatar
mercury233 committed
555
        "count": countadd,
mercury233's avatar
mercury233 committed
556 557 558 559 560 561 562
        "reasons": [reason],
        "need_tip": true
      };
      ROOM_players_banned.push(bannedplayer);
    }
  };

563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608
  ROOM_player_win = function(name) {
    if (!ROOM_players_scores[name]) {
      ROOM_players_scores[name] = {
        win: 0,
        lose: 0,
        flee: 0,
        combo: 0
      };
    }
    ROOM_players_scores[name].win = ROOM_players_scores[name].win + 1;
    ROOM_players_scores[name].combo = ROOM_players_scores[name].combo + 1;
  };

  ROOM_player_lose = function(name) {
    if (!ROOM_players_scores[name]) {
      ROOM_players_scores[name] = {
        win: 0,
        lose: 0,
        flee: 0,
        combo: 0
      };
    }
    ROOM_players_scores[name].lose = ROOM_players_scores[name].lose + 1;
    ROOM_players_scores[name].combo = 0;
  };

  ROOM_player_flee = function(name) {
    if (!ROOM_players_scores[name]) {
      ROOM_players_scores[name] = {
        win: 0,
        lose: 0,
        flee: 0,
        combo: 0
      };
    }
    ROOM_players_scores[name].flee = ROOM_players_scores[name].flee + 1;
    ROOM_players_scores[name].combo = 0;
  };

  ROOM_player_get_score = function(player) {
    var name, score, total;
    name = player.name_vpass;
    score = ROOM_players_scores[name];
    if (!score) {
      return player.name + " ${random_score_blank}";
    }
mercury233's avatar
mercury233 committed
609
    total = score.win + score.lose;
610 611 612 613 614 615 616 617 618 619
    if (score.win < 2 && total < 3) {
      return player.name + " ${random_score_not_enough}";
    }
    if (score.combo >= 2) {
      return "${random_score_part1}" + player.name + " ${random_score_part2} " + (Math.ceil(score.win / total * 100)) + "${random_score_part3} " + (Math.ceil(score.flee / total * 100)) + "${random_score_part4_combo}" + score.combo + "${random_score_part5_combo}";
    } else {
      return "${random_score_part1}" + player.name + " ${random_score_part2} " + (Math.ceil(score.win / total * 100)) + "${random_score_part3} " + (Math.ceil(score.flee / total * 100)) + "${random_score_part4}";
    }
  };

mercury233's avatar
mercury233 committed
620 621
  if (settings.modules.random_duel.post_match_scores) {
    setInterval(function() {
mercury233's avatar
mercury233 committed
622 623 624 625 626 627
      var scores, scores_by_lose, scores_by_win, scores_pair;
      scores_pair = _.pairs(ROOM_players_scores);
      scores_by_lose = _.sortBy(scores_pair, function(score) {
        return score[1].lose;
      }).reverse();
      scores_by_win = _.sortBy(scores_by_lose, function(score) {
mercury233's avatar
mercury233 committed
628
        return score[1].win;
mercury233's avatar
mercury233 committed
629 630
      }).reverse();
      scores = _.first(scores_by_win, 10);
mercury233's avatar
mercury233 committed
631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650
      request.post({
        url: settings.modules.random_duel.post_match_scores,
        form: {
          accesskey: settings.modules.random_duel.post_match_accesskey,
          rank: JSON.stringify(scores)
        }
      }, (function(_this) {
        return function(error, response, body) {
          if (error) {
            log.warn('RANDOM SCORE POST ERROR', error);
          } else {
            if (response.statusCode !== 204 && response.statusCode !== 200) {
              log.warn('RANDOM SCORE POST FAIL', response.statusCode, response.statusMessage, body);
            }
          }
        };
      })(this));
    }, 60000);
  }

mercury233's avatar
mercury233 committed
651
  ROOM_find_or_create_by_name = function(name, player_ip) {
mercury233's avatar
mercury233 committed
652 653
    var room, uname;
    uname = name.toUpperCase();
mercury233's avatar
mercury233 committed
654
    if (settings.modules.windbot.enabled && (uname.slice(0, 2) === 'AI' || (!settings.modules.random_duel.enabled && uname === ''))) {
mercury233's avatar
mercury233 committed
655 656
      return ROOM_find_or_create_ai(name);
    }
mercury233's avatar
mercury233 committed
657
    if (settings.modules.random_duel.enabled && (uname === '' || uname === 'S' || uname === 'M' || uname === 'T')) {
mercury233's avatar
mercury233 committed
658
      return ROOM_find_or_create_random(uname, player_ip);
mercury233's avatar
mercury233 committed
659 660 661
    }
    if (room = ROOM_find_by_name(name)) {
      return room;
mercury233's avatar
mercury233 committed
662
    } else if (memory_usage >= 90) {
mercury233's avatar
mercury233 committed
663 664 665 666 667 668 669 670 671 672 673 674 675 676
      return null;
    } else {
      return new Room(name);
    }
  };

  ROOM_find_or_create_random = function(type, player_ip) {
    var bannedplayer, max_player, name, playerbanned, result;
    bannedplayer = _.find(ROOM_players_banned, function(bannedplayer) {
      return player_ip === bannedplayer.ip;
    });
    if (bannedplayer) {
      if (bannedplayer.count > 6 && moment() < bannedplayer.time) {
        return {
mercury233's avatar
mercury233 committed
677
          "error": "${random_banned_part1}" + (bannedplayer.reasons.join('${random_ban_reason_separator}')) + "${random_banned_part2}" + (moment(bannedplayer.time).fromNow(true)) + "${random_banned_part3}"
mercury233's avatar
mercury233 committed
678 679
        };
      }
mercury233's avatar
mercury233 committed
680
      if (bannedplayer.count > 3 && moment() < bannedplayer.time && bannedplayer.need_tip && type !== 'T') {
mercury233's avatar
mercury233 committed
681 682
        bannedplayer.need_tip = false;
        return {
mercury233's avatar
mercury233 committed
683
          "error": "${random_deprecated_part1}" + (bannedplayer.reasons.join('${random_ban_reason_separator}')) + "${random_deprecated_part2}" + (moment(bannedplayer.time).fromNow(true)) + "${random_deprecated_part3}"
mercury233's avatar
mercury233 committed
684 685 686 687
        };
      } else if (bannedplayer.need_tip) {
        bannedplayer.need_tip = false;
        return {
mercury233's avatar
mercury233 committed
688
          "error": "${random_warn_part1}" + (bannedplayer.reasons.join('${random_ban_reason_separator}')) + "${random_warn_part2}"
mercury233's avatar
mercury233 committed
689 690 691 692 693 694 695 696
        };
      } else if (bannedplayer.count > 2) {
        bannedplayer.need_tip = true;
      }
    }
    max_player = type === 'T' ? 4 : 2;
    playerbanned = bannedplayer && bannedplayer.count > 3 && moment() < bannedplayer.time;
    result = _.find(ROOM_all, function(room) {
697
      return room && room.random_type !== '' && !room.started && ((type === '' && (room.random_type === 'S' || (settings.modules.random_duel.blank_pass_match && room.random_type !== 'T'))) || room.random_type === type) && room.get_playing_player().length < max_player && (settings.modules.random_duel.no_rematch_check || room.get_host() === null || room.get_host().ip !== ROOM_players_oppentlist[player_ip]) && (playerbanned === room.deprecated || type === 'T');
mercury233's avatar
mercury233 committed
698 699
    });
    if (result) {
mercury233's avatar
mercury233 committed
700
      result.welcome = '${random_duel_enter_room_waiting}';
mercury233's avatar
mercury233 committed
701
    } else if (memory_usage < 90) {
mercury233's avatar
mercury233 committed
702 703 704 705 706
      type = type ? type : 'S';
      name = type + ',RANDOM#' + Math.floor(Math.random() * 100000);
      result = new Room(name);
      result.random_type = type;
      result.max_player = max_player;
mercury233's avatar
mercury233 committed
707
      result.welcome = '${random_duel_enter_room_new}';
mercury233's avatar
mercury233 committed
708
      result.deprecated = playerbanned;
mercury233's avatar
mercury233 committed
709 710
    } else {
      return null;
mercury233's avatar
mercury233 committed
711 712
    }
    if (result.random_type === 'M') {
mercury233's avatar
mercury233 committed
713
      result.welcome = result.welcome + '\n${random_duel_enter_room_match}';
mercury233's avatar
mercury233 committed
714 715 716 717
    }
    return result;
  };

mercury233's avatar
mercury233 committed
718
  ROOM_find_or_create_ai = function(name) {
719
    var ainame, namea, result, room, uname, windbot;
mercury233's avatar
mercury233 committed
720 721 722
    if (name === '') {
      name = 'AI';
    }
mercury233's avatar
mercury233 committed
723
    namea = name.split('#');
724
    uname = name.toUpperCase();
mercury233's avatar
mercury233 committed
725 726
    if (room = ROOM_find_by_name(name)) {
      return room;
727
    } else if (uname === 'AI') {
mercury233's avatar
mercury233 committed
728
      windbot = _.sample(windbots);
mercury233's avatar
mercury233 committed
729
      name = 'AI#' + Math.floor(Math.random() * 100000);
mercury233's avatar
mercury233 committed
730 731
    } else if (namea.length > 1) {
      ainame = namea[namea.length - 1];
mercury233's avatar
mercury233 committed
732
      windbot = _.sample(_.filter(windbots, function(w) {
mercury233's avatar
mercury233 committed
733 734 735 736
        return w.name === ainame || w.deck === ainame;
      }));
      if (!windbot) {
        return {
mercury233's avatar
mercury233 committed
737
          "error": "${windbot_deck_not_found}"
mercury233's avatar
mercury233 committed
738 739 740 741
        };
      }
      name = name + ',' + Math.floor(Math.random() * 100000);
    } else {
mercury233's avatar
mercury233 committed
742
      windbot = _.sample(windbots);
mercury233's avatar
mercury233 committed
743 744
      name = name + '#' + Math.floor(Math.random() * 100000);
    }
mercury233's avatar
mercury233 committed
745 746 747
    if (name.replace(/[^\x00-\xff]/g, "00").length > 20) {
      log.info("long ai name", name);
      return {
mercury233's avatar
mercury233 committed
748
        "error": "${windbot_name_too_long}"
mercury233's avatar
mercury233 committed
749 750
      };
    }
mercury233's avatar
mercury233 committed
751 752
    result = new Room(name);
    result.windbot = windbot;
mercury233's avatar
merge  
mercury233 committed
753
    result["private"] = true;
mercury233's avatar
mercury233 committed
754 755 756
    return result;
  };

mercury233's avatar
mercury233 committed
757 758 759
  ROOM_find_by_name = function(name) {
    var result;
    result = _.find(ROOM_all, function(room) {
760
      return room && room.name === name;
mercury233's avatar
mercury233 committed
761 762 763 764
    });
    return result;
  };

mercury233's avatar
mercury233 committed
765 766 767 768 769 770 771 772
  ROOM_find_by_title = function(title) {
    var result;
    result = _.find(ROOM_all, function(room) {
      return room && room.title === title;
    });
    return result;
  };

mercury233's avatar
mercury233 committed
773 774
  ROOM_find_by_port = function(port) {
    return _.find(ROOM_all, function(room) {
775
      return room && room.port === port;
mercury233's avatar
mercury233 committed
776 777 778 779 780 781 782 783 784 785 786 787 788
    });
  };

  ROOM_validate = function(name) {
    var client_name, client_name_and_pass, client_pass;
    client_name_and_pass = name.split('$', 2);
    client_name = client_name_and_pass[0];
    client_pass = client_name_and_pass[1];
    if (!client_pass) {
      return true;
    }
    return !_.find(ROOM_all, function(room) {
      var room_name, room_name_and_pass, room_pass;
789 790 791
      if (!room) {
        return false;
      }
mercury233's avatar
mercury233 committed
792 793 794 795 796 797 798
      room_name_and_pass = room.name.split('$', 2);
      room_name = room_name_and_pass[0];
      room_pass = room_name_and_pass[1];
      return client_name === room_name && client_pass !== room_pass;
    });
  };

mercury233's avatar
mercury233 committed
799
  ROOM_unwelcome = function(room, bad_player, reason) {
nanahira's avatar
nanahira committed
800
    var len2, m, player, ref2;
mercury233's avatar
mercury233 committed
801 802 803
    if (!room) {
      return;
    }
nanahira's avatar
nanahira committed
804
    ref2 = room.players;
nanahira's avatar
nanahira committed
805 806
    for (m = 0, len2 = ref2.length; m < len2; m++) {
      player = ref2[m];
mercury233's avatar
mercury233 committed
807 808 809 810 811 812 813 814 815
      if (player && player === bad_player) {
        ygopro.stoc_send_chat(player, "${unwelcome_warn_part1}" + reason + "${unwelcome_warn_part2}", ygopro.constants.COLORS.RED);
      } else if (player && player.pos !== 7 && player !== bad_player) {
        player.flee_free = true;
        ygopro.stoc_send_chat(player, "${unwelcome_tip_part1}" + reason + "${unwelcome_tip_part2}", ygopro.constants.COLORS.BABYBLUE);
      }
    }
  };

nanahira's avatar
nanahira committed
816
  CLIENT_kick = function(client) {
nanahira's avatar
nanahira committed
817 818 819
    if (!client) {
      return false;
    }
nanahira's avatar
nanahira committed
820
    client.system_kicked = true;
nanahira's avatar
typo  
nanahira committed
821
    if (settings.modules.reconnect.enabled && client.closed) {
nanahira's avatar
fix  
nanahira committed
822 823 824
      if (client.server && !client.had_new_reconnection) {
        client.server.destroy();
      }
nanahira's avatar
nanahira committed
825 826 827
    } else {
      client.destroy();
    }
nanahira's avatar
nanahira committed
828
    return true;
nanahira's avatar
nanahira committed
829 830 831 832 833 834 835 836 837 838 839 840 841
  };

  release_disconnect = function(dinfo, reconnected) {
    if (dinfo.old_client && !reconnected) {
      dinfo.old_client.destroy();
    }
    if (dinfo.old_server && !reconnected) {
      dinfo.old_server.destroy();
    }
    clearTimeout(dinfo.timeout);
  };

  CLIENT_get_authorize_key = function(client) {
nanahira's avatar
js  
nanahira committed
842
    if (!settings.modules.mycard.enabled && client.vpass) {
843
      return client.name_vpass;
nanahira's avatar
js  
nanahira committed
844 845
    } else if (settings.modules.mycard.enabled || settings.modules.tournament_mode.enabled || settings.modules.challonge.enabled || client.is_local) {
      return client.name;
nanahira's avatar
nanahira committed
846
    } else {
847
      return client.ip + ":" + client.name;
nanahira's avatar
nanahira committed
848 849 850
    }
  };

nanahira's avatar
nanahira committed
851
  CLIENT_reconnect_unregister = function(client, reconnected, exact) {
nanahira's avatar
nanahira committed
852 853 854 855
    if (!settings.modules.reconnect.enabled) {
      return false;
    }
    if (disconnect_list[CLIENT_get_authorize_key(client)]) {
nanahira's avatar
nanahira committed
856 857 858
      if (exact && disconnect_list[CLIENT_get_authorize_key(client)].old_client !== client) {
        return false;
      }
nanahira's avatar
nanahira committed
859 860 861 862 863 864 865
      release_disconnect(disconnect_list[CLIENT_get_authorize_key(client)], reconnected);
      delete disconnect_list[CLIENT_get_authorize_key(client)];
      return true;
    }
    return false;
  };

nanahira's avatar
nanahira committed
866
  CLIENT_reconnect_register = function(client, room_id, error) {
nanahira's avatar
nanahira committed
867
    var dinfo, room, tmot;
nanahira's avatar
nanahira committed
868
    room = ROOM_all[room_id];
nanahira's avatar
nanahira committed
869 870 871
    if (client.had_new_reconnection) {
      return false;
    }
nanahira's avatar
js  
nanahira committed
872
    if (!settings.modules.reconnect.enabled || !room || client.system_kicked || client.flee_free || disconnect_list[CLIENT_get_authorize_key(client)] || client.is_post_watcher || !CLIENT_is_player(client, room) || !room.started || room.windbot || (settings.modules.reconnect.auto_surrender_after_disconnect && room.hostinfo.mode !== 1) || (room.random_type && room.get_disconnected_count() > 1)) {
nanahira's avatar
nanahira committed
873 874 875
      return false;
    }
    dinfo = {
nanahira's avatar
nanahira committed
876
      room_id: room_id,
nanahira's avatar
nanahira committed
877 878 879 880 881 882 883 884 885 886
      old_client: client,
      old_server: client.server,
      deckbuf: client.start_deckbuf
    };
    tmot = setTimeout(function() {
      room.disconnect(client, error);
      dinfo.old_server.destroy();
    }, settings.modules.reconnect.wait_time);
    dinfo.timeout = tmot;
    disconnect_list[CLIENT_get_authorize_key(client)] = dinfo;
nanahira's avatar
js  
nanahira committed
887
    ygopro.stoc_send_chat_to_room(room, (client.name + " ${disconnect_from_game}") + (error ? ": " + error : ''));
nanahira's avatar
nanahira committed
888 889 890 891
    if (client.time_confirm_required) {
      client.time_confirm_required = false;
      ygopro.ctos_send(client.server, 'TIME_CONFIRM');
    }
892 893 894
    if (settings.modules.reconnect.auto_surrender_after_disconnect && room.turn && room.turn > 0) {
      ygopro.ctos_send(client.server, 'SURRENDER');
    }
nanahira's avatar
nanahira committed
895 896 897 898
    return true;
  };

  CLIENT_import_data = function(client, old_client, room) {
nanahira's avatar
nanahira committed
899
    var index, key, len2, len3, m, n, player, ref2;
nanahira's avatar
nanahira committed
900 901 902 903 904 905 906 907 908
    ref2 = room.players;
    for (index = m = 0, len2 = ref2.length; m < len2; index = ++m) {
      player = ref2[index];
      if (player === old_client) {
        room.players[index] = client;
        break;
      }
    }
    room.dueling_players[old_client.pos] = client;
nanahira's avatar
nanahira committed
909
    if (room.waiting_for_player === old_client) {
nanahira's avatar
nanahira committed
910 911
      room.waiting_for_player = client;
    }
nanahira's avatar
nanahira committed
912
    if (room.waiting_for_player2 === old_client) {
nanahira's avatar
nanahira committed
913 914
      room.waiting_for_player2 = client;
    }
nanahira's avatar
nanahira committed
915
    if (room.selecting_tp === old_client) {
nanahira's avatar
nanahira committed
916 917
      room.selecting_tp = client;
    }
nanahira's avatar
nanahira committed
918 919 920 921
    for (n = 0, len3 = import_datas.length; n < len3; n++) {
      key = import_datas[n];
      client[key] = old_client[key];
    }
nanahira's avatar
nanahira committed
922 923 924 925 926 927
    old_client.had_new_reconnection = true;
  };

  SERVER_clear_disconnect = function(server) {
    var k, v;
    if (!settings.modules.reconnect.enabled) {
nanahira's avatar
nanahira committed
928
      return false;
nanahira's avatar
nanahira committed
929 930 931 932 933 934
    }
    for (k in disconnect_list) {
      v = disconnect_list[k];
      if (v && server === v.old_server) {
        release_disconnect(v);
        delete disconnect_list[k];
nanahira's avatar
nanahira committed
935
        return true;
nanahira's avatar
nanahira committed
936 937
      }
    }
nanahira's avatar
nanahira committed
938 939 940 941 942 943 944 945 946 947 948 949 950 951 952 953 954
    return false;
  };

  ROOM_clear_disconnect = function(room_id) {
    var k, v;
    if (!settings.modules.reconnect.enabled) {
      return false;
    }
    for (k in disconnect_list) {
      v = disconnect_list[k];
      if (v && room_id === v.room_id) {
        release_disconnect(v);
        delete disconnect_list[k];
        return true;
      }
    }
    return false;
nanahira's avatar
nanahira committed
955 956 957 958 959 960 961 962 963 964 965 966 967
  };

  CLIENT_is_player = function(client, room) {
    var is_player, len2, m, player, ref2;
    is_player = false;
    ref2 = room.players;
    for (m = 0, len2 = ref2.length; m < len2; m++) {
      player = ref2[m];
      if (client === player) {
        is_player = true;
        break;
      }
    }
nanahira's avatar
fix  
nanahira committed
968
    return is_player && client.pos <= 3;
nanahira's avatar
nanahira committed
969 970
  };

nanahira's avatar
nanahira committed
971
  CLIENT_is_able_to_reconnect = function(client, deckbuf) {
nanahira's avatar
nanahira committed
972
    var disconnect_info, room;
nanahira's avatar
nanahira committed
973 974 975 976 977 978 979 980 981 982
    if (!settings.modules.reconnect.enabled) {
      return false;
    }
    if (client.system_kicked) {
      return false;
    }
    disconnect_info = disconnect_list[CLIENT_get_authorize_key(client)];
    if (!disconnect_info) {
      return false;
    }
nanahira's avatar
nanahira committed
983 984 985 986 987
    room = ROOM_all[disconnect_info.room_id];
    if (!room) {
      CLIENT_reconnect_unregister(client);
      return false;
    }
nanahira's avatar
nanahira committed
988 989 990 991 992 993 994 995 996 997
    if (deckbuf && !_.isEqual(deckbuf, disconnect_info.deckbuf)) {
      return false;
    }
    return true;
  };

  CLIENT_get_kick_reconnect_target = function(client, deckbuf) {
    var len2, len3, m, n, player, ref2, room;
    for (m = 0, len2 = ROOM_all.length; m < len2; m++) {
      room = ROOM_all[m];
nanahira's avatar
fix  
nanahira committed
998
      if (room && room.started && !room.windbot) {
nanahira's avatar
nanahira committed
999 1000 1001
        ref2 = room.get_playing_player();
        for (n = 0, len3 = ref2.length; n < len3; n++) {
          player = ref2[n];
1002
          if (!player.closed && player.name === client.name && (settings.modules.challonge.enabled || player.pass === client.pass) && (settings.modules.mycard.enabled || settings.modules.tournament_mode.enabled || player.ip === client.ip || (client.vpass && client.vpass === player.vpass)) && (!deckbuf || _.isEqual(player.start_deckbuf, deckbuf))) {
nanahira's avatar
nanahira committed
1003 1004 1005 1006 1007 1008 1009 1010 1011 1012 1013 1014 1015 1016 1017
            return player;
          }
        }
      }
    }
    return null;
  };

  CLIENT_is_able_to_kick_reconnect = function(client, deckbuf) {
    if (!(settings.modules.reconnect.enabled && settings.modules.reconnect.allow_kick_reconnect)) {
      return false;
    }
    if (!CLIENT_get_kick_reconnect_target(client, deckbuf)) {
      return false;
    }
nanahira's avatar
nanahira committed
1018 1019 1020 1021
    return true;
  };

  CLIENT_send_pre_reconnect_info = function(client, room, old_client) {
nanahira's avatar
nanahira committed
1022
    var len2, m, player, ref2, req_pos;
nanahira's avatar
nanahira committed
1023
    ygopro.stoc_send_chat(client, "${pre_reconnecting_to_room}", ygopro.constants.COLORS.BABYBLUE);
1024
    ygopro.stoc_send(client, 'JOIN_GAME', room.join_game_buffer);
nanahira's avatar
nanahira committed
1025 1026 1027 1028 1029 1030 1031 1032 1033 1034
    req_pos = old_client.pos;
    if (old_client.is_host) {
      req_pos += 0x10;
    }
    ygopro.stoc_send(client, 'TYPE_CHANGE', {
      type: req_pos
    });
    ref2 = room.players;
    for (m = 0, len2 = ref2.length; m < len2; m++) {
      player = ref2[m];
nanahira's avatar
nanahira committed
1035
      ygopro.stoc_send(client, 'HS_PLAYER_ENTER', {
nanahira's avatar
nanahira committed
1036 1037
        name: player.name,
        pos: player.pos
nanahira's avatar
nanahira committed
1038
      });
nanahira's avatar
nanahira committed
1039 1040 1041 1042 1043 1044 1045 1046 1047 1048 1049 1050 1051 1052 1053 1054 1055 1056 1057 1058 1059 1060
    }
  };

  CLIENT_send_reconnect_info = function(client, server, room) {
    client.reconnecting = true;
    ygopro.stoc_send_chat(client, "${reconnecting_to_room}", ygopro.constants.COLORS.BABYBLUE);
    if (room.turn && room.turn > 0) {
      ygopro.ctos_send(server, 'REQUEST_FIELD');
    } else if (room.changing_side) {
      ygopro.stoc_send(client, 'DUEL_START');
      if (!client.selected_preduel) {
        ygopro.stoc_send(client, 'CHANGE_SIDE');
      }
      client.reconnecting = false;
    } else if (room.selecting_hand) {
      ygopro.stoc_send(client, 'DUEL_START');
      if ((room.hostinfo.mode !== 2 || client.pos === 0 || client.pos === 2) && !client.selected_preduel) {
        ygopro.stoc_send(client, 'SELECT_HAND');
      }
      client.reconnecting = false;
    } else if (room.selecting_tp) {
      ygopro.stoc_send(client, 'DUEL_START');
nanahira's avatar
js  
nanahira committed
1061
      if (client === room.selecting_tp) {
nanahira's avatar
nanahira committed
1062 1063 1064 1065 1066 1067 1068 1069 1070
        ygopro.stoc_send(client, 'SELECT_TP');
      }
      client.reconnecting = false;
    } else {
      ygopro.ctos_send(server, 'REQUEST_FIELD');
    }
  };

  CLIENT_pre_reconnect = function(client) {
nanahira's avatar
nanahira committed
1071 1072 1073 1074 1075 1076 1077 1078 1079 1080 1081 1082 1083
    var dinfo, player;
    if (CLIENT_is_able_to_reconnect(client)) {
      dinfo = disconnect_list[CLIENT_get_authorize_key(client)];
      client.pre_reconnecting = true;
      client.pos = dinfo.old_client.pos;
      client.setTimeout(300000);
      CLIENT_send_pre_reconnect_info(client, ROOM_all[dinfo.room_id], dinfo.old_client);
    } else if (CLIENT_is_able_to_kick_reconnect(client)) {
      player = CLIENT_get_kick_reconnect_target(client);
      client.pre_reconnecting = true;
      client.pos = player.pos;
      client.setTimeout(300000);
      CLIENT_send_pre_reconnect_info(client, ROOM_all[player.rid], player);
nanahira's avatar
nanahira committed
1084 1085 1086 1087
    }
  };

  CLIENT_reconnect = function(client) {
nanahira's avatar
nanahira committed
1088
    var current_old_server, dinfo, room;
nanahira's avatar
nanahira committed
1089 1090 1091 1092 1093 1094 1095
    if (!CLIENT_is_able_to_reconnect(client)) {
      ygopro.stoc_send_chat(client, "${reconnect_failed}", ygopro.constants.COLORS.RED);
      CLIENT_kick(client);
      return;
    }
    client.pre_reconnecting = false;
    dinfo = disconnect_list[CLIENT_get_authorize_key(client)];
nanahira's avatar
nanahira committed
1096
    room = ROOM_all[dinfo.room_id];
nanahira's avatar
nanahira committed
1097 1098 1099 1100 1101 1102 1103 1104 1105
    current_old_server = client.server;
    client.server = dinfo.old_server;
    client.server.client = client;
    dinfo.old_client.server = null;
    current_old_server.client = null;
    current_old_server.had_new_reconnection = true;
    current_old_server.destroy();
    client.established = true;
    client.pre_establish_buffers = [];
nanahira's avatar
nanahira committed
1106 1107 1108
    if (room.random_type || room.arena) {
      room.last_active_time = moment();
    }
nanahira's avatar
nanahira committed
1109 1110
    CLIENT_import_data(client, dinfo.old_client, room);
    CLIENT_send_reconnect_info(client, client.server, room);
nanahira's avatar
js  
nanahira committed
1111
    ygopro.stoc_send_chat_to_room(room, client.name + " ${reconnect_to_game}");
nanahira's avatar
nanahira committed
1112 1113 1114
    CLIENT_reconnect_unregister(client, true);
  };

nanahira's avatar
nanahira committed
1115 1116 1117 1118 1119 1120 1121 1122 1123 1124 1125 1126 1127 1128 1129 1130 1131 1132 1133 1134 1135 1136 1137 1138 1139 1140 1141 1142 1143 1144 1145
  CLIENT_kick_reconnect = function(client, deckbuf) {
    var current_old_server, player, room;
    if (!CLIENT_is_able_to_kick_reconnect(client)) {
      ygopro.stoc_send_chat(client, "${reconnect_failed}", ygopro.constants.COLORS.RED);
      CLIENT_kick(client);
      return;
    }
    client.pre_reconnecting = false;
    player = CLIENT_get_kick_reconnect_target(client, deckbuf);
    room = ROOM_all[player.rid];
    current_old_server = client.server;
    client.server = player.server;
    client.server.client = client;
    ygopro.stoc_send_chat(player, "${reconnect_kicked}", ygopro.constants.COLORS.RED);
    player.server = null;
    player.had_new_reconnection = true;
    CLIENT_kick(player);
    current_old_server.client = null;
    current_old_server.had_new_reconnection = true;
    current_old_server.destroy();
    client.established = true;
    client.pre_establish_buffers = [];
    if (room.random_type || room.arena) {
      room.last_active_time = moment();
    }
    CLIENT_import_data(client, player, room);
    CLIENT_send_reconnect_info(client, client.server, room);
    ygopro.stoc_send_chat_to_room(room, client.name + " ${reconnect_to_game}");
    CLIENT_reconnect_unregister(client, true);
  };

nanahira's avatar
nanahira committed
1146 1147 1148 1149
  if (settings.modules.reconnect.enabled) {
    disconnect_list = {};
  }

nanahira's avatar
nanahira committed
1150 1151 1152 1153 1154 1155 1156 1157 1158
  CLIENT_heartbeat_unregister = function(client) {
    if (!settings.modules.heartbeat_detection.enabled || !client.heartbeat_timeout) {
      return false;
    }
    clearTimeout(client.heartbeat_timeout);
    delete client.heartbeat_timeout;
    return true;
  };

1159
  CLIENT_heartbeat_register = function(client, send) {
1160
    if (!settings.modules.heartbeat_detection.enabled || client.closed || client.is_post_watcher || client.pre_reconnecting || client.reconnecting || client.waiting_for_last || client.pos > 3 || client.heartbeat_protected) {
nanahira's avatar
nanahira committed
1161 1162 1163 1164 1165 1166 1167 1168
      return false;
    }
    if (client.heartbeat_timeout) {
      CLIENT_heartbeat_unregister(client);
    }
    client.heartbeat_responsed = false;
    if (send) {
      ygopro.stoc_send(client, "TIME_LIMIT", {
nanahira's avatar
nanahira committed
1169 1170 1171 1172 1173
        player: 0,
        left_time: 0
      });
      ygopro.stoc_send(client, "TIME_LIMIT", {
        player: 1,
nanahira's avatar
nanahira committed
1174 1175 1176 1177 1178 1179 1180 1181
        left_time: 0
      });
    }
    client.heartbeat_timeout = setTimeout(function() {
      CLIENT_heartbeat_unregister(client);
      if (!(client.closed || client.heartbeat_responsed)) {
        client.destroy();
      }
1182
    }, settings.modules.heartbeat_detection.wait_time);
nanahira's avatar
nanahira committed
1183 1184 1185
    return true;
  };

nanahira's avatar
nanahira committed
1186 1187 1188 1189
  CLIENT_is_banned_by_mc = function(client) {
    return client.ban_mc && client.ban_mc.banned && moment().isBefore(client.ban_mc.until);
  };

nanahira's avatar
nanahira committed
1190 1191
  CLIENT_send_replays = function(client, room) {
    var buffer, i, len2, m, ref2;
nanahira's avatar
nanahira committed
1192
    if (!(settings.modules.replay_delay && room.replays.length && room.hostinfo.mode === 1 && !client.replays_sent && !client.closed)) {
nanahira's avatar
nanahira committed
1193 1194
      return false;
    }
nanahira's avatar
nanahira committed
1195
    client.replays_sent = true;
nanahira's avatar
nanahira committed
1196 1197 1198 1199 1200
    i = 0;
    ref2 = room.replays;
    for (m = 0, len2 = ref2.length; m < len2; m++) {
      buffer = ref2[m];
      ++i;
nanahira's avatar
fix  
nanahira committed
1201 1202 1203 1204
      if (buffer) {
        ygopro.stoc_send_chat(client, "${replay_hint_part1}" + i + "${replay_hint_part2}", ygopro.constants.COLORS.BABYBLUE);
        ygopro.stoc_send(client, "REPLAY", buffer);
      }
nanahira's avatar
nanahira committed
1205 1206 1207 1208
    }
    return true;
  };

1209 1210
  SOCKET_flush_data = function(sk, datas) {
    var buffer, len2, m;
nanahira's avatar
js  
nanahira committed
1211 1212 1213
    if (!sk || sk.closed) {
      return false;
    }
1214 1215 1216 1217 1218
    for (m = 0, len2 = datas.length; m < len2; m++) {
      buffer = datas[m];
      sk.write(buffer);
    }
    datas.splice(0, datas.length);
nanahira's avatar
js  
nanahira committed
1219
    return true;
1220 1221
  };

mercury233's avatar
mercury233 committed
1222 1223
  Room = (function() {
    function Room(name, hostinfo) {
mercury233's avatar
mercury233 committed
1224
      var draw_count, lflist, param, rule, start_hand, start_lp, time_limit;
mercury233's avatar
mercury233 committed
1225 1226 1227 1228 1229 1230 1231 1232 1233 1234
      this.hostinfo = hostinfo;
      this.name = name;
      this.alive = true;
      this.players = [];
      this.player_datas = [];
      this.status = 'starting';
      this.started = false;
      this.established = false;
      this.watcher_buffers = [];
      this.recorder_buffers = [];
1235
      this.cloud_replay_id = Math.floor(Math.random() * 100000000);
mercury233's avatar
mercury233 committed
1236 1237 1238
      this.watchers = [];
      this.random_type = '';
      this.welcome = '';
mercury233's avatar
mercury233 committed
1239
      this.scores = {};
nanahira's avatar
nanahira committed
1240
      this.decks = {};
1241
      this.duel_count = 0;
nanahira's avatar
nanahira committed
1242
      this.death = 0;
nanahira's avatar
nanahira committed
1243
      this.turn = 0;
nanahira's avatar
nanahira committed
1244 1245 1246
      if (settings.modules.replay_delay) {
        this.replays = [];
      }
mercury233's avatar
mercury233 committed
1247
      ROOM_all.push(this);
mercury233's avatar
fix  
mercury233 committed
1248
      this.hostinfo || (this.hostinfo = JSON.parse(JSON.stringify(settings.hostinfo)));
nanahira's avatar
nanahira committed
1249
      delete this.hostinfo.comment;
mercury233's avatar
mercury233 committed
1250
      if (lflists.length) {
1251
        if (this.hostinfo.rule === 1 && this.hostinfo.lflist === 0) {
mercury233's avatar
mercury233 committed
1252
          this.hostinfo.lflist = _.findIndex(lflists, function(list) {
1253 1254 1255 1256 1257 1258
            return list.tcg;
          });
        }
      } else {
        this.hostinfo.lflist = -1;
      }
mercury233's avatar
mercury233 committed
1259 1260 1261 1262 1263
      if (name.slice(0, 2) === 'M#') {
        this.hostinfo.mode = 1;
      } else if (name.slice(0, 2) === 'T#') {
        this.hostinfo.mode = 2;
        this.hostinfo.start_lp = 16000;
mercury233's avatar
mercury233 committed
1264 1265 1266
      } else if (name.slice(0, 3) === 'AI#') {
        this.hostinfo.rule = 2;
        this.hostinfo.lflist = -1;
mercury233's avatar
mercury233 committed
1267
        this.hostinfo.time_limit = 999;
mercury233's avatar
mercury233 committed
1268 1269 1270 1271 1272 1273 1274 1275 1276 1277 1278 1279 1280 1281 1282 1283 1284 1285 1286 1287
      } else if ((param = name.match(/^(\d)(\d)(T|F)(T|F)(T|F)(\d+),(\d+),(\d+)/i))) {
        this.hostinfo.rule = parseInt(param[1]);
        this.hostinfo.mode = parseInt(param[2]);
        this.hostinfo.enable_priority = param[3] === 'T';
        this.hostinfo.no_check_deck = param[4] === 'T';
        this.hostinfo.no_shuffle_deck = param[5] === 'T';
        this.hostinfo.start_lp = parseInt(param[6]);
        this.hostinfo.start_hand = parseInt(param[7]);
        this.hostinfo.draw_count = parseInt(param[8]);
      } else if ((param = name.match(/(.+)#/)) !== null) {
        rule = param[1].toUpperCase();
        if (rule.match(/(^|,|,)(M|MATCH)(,|,|$)/)) {
          this.hostinfo.mode = 1;
        }
        if (rule.match(/(^|,|,)(T|TAG)(,|,|$)/)) {
          this.hostinfo.mode = 2;
          this.hostinfo.start_lp = 16000;
        }
        if (rule.match(/(^|,|,)(TCGONLY|TO)(,|,|$)/)) {
          this.hostinfo.rule = 1;
mercury233's avatar
mercury233 committed
1288
          this.hostinfo.lflist = _.findIndex(lflists, function(list) {
mercury233's avatar
mercury233 committed
1289
            return list.tcg;
mercury233's avatar
mercury233 committed
1290 1291 1292 1293
          });
        }
        if (rule.match(/(^|,|,)(OCGONLY|OO)(,|,|$)/)) {
          this.hostinfo.rule = 0;
1294
          this.hostinfo.lflist = 0;
mercury233's avatar
mercury233 committed
1295 1296 1297 1298 1299 1300 1301 1302 1303 1304 1305 1306 1307 1308 1309 1310 1311 1312 1313 1314 1315 1316 1317 1318 1319 1320 1321 1322 1323 1324 1325 1326 1327 1328 1329 1330 1331 1332 1333 1334 1335 1336 1337 1338 1339 1340 1341 1342 1343 1344 1345 1346 1347 1348 1349 1350 1351 1352 1353 1354 1355 1356 1357
        }
        if (rule.match(/(^|,|,)(OT|TCG)(,|,|$)/)) {
          this.hostinfo.rule = 2;
        }
        if ((param = rule.match(/(^|,|,)LP(\d+)(,|,|$)/))) {
          start_lp = parseInt(param[2]);
          if (start_lp <= 0) {
            start_lp = 1;
          }
          if (start_lp >= 99999) {
            start_lp = 99999;
          }
          this.hostinfo.start_lp = start_lp;
        }
        if ((param = rule.match(/(^|,|,)(TIME|TM|TI)(\d+)(,|,|$)/))) {
          time_limit = parseInt(param[3]);
          if (time_limit < 0) {
            time_limit = 180;
          }
          if (time_limit >= 1 && time_limit <= 60) {
            time_limit = time_limit * 60;
          }
          if (time_limit >= 999) {
            time_limit = 999;
          }
          this.hostinfo.time_limit = time_limit;
        }
        if ((param = rule.match(/(^|,|,)(START|ST)(\d+)(,|,|$)/))) {
          start_hand = parseInt(param[3]);
          if (start_hand <= 0) {
            start_hand = 1;
          }
          if (start_hand >= 40) {
            start_hand = 40;
          }
          this.hostinfo.start_hand = start_hand;
        }
        if ((param = rule.match(/(^|,|,)(DRAW|DR)(\d+)(,|,|$)/))) {
          draw_count = parseInt(param[3]);
          if (draw_count >= 35) {
            draw_count = 35;
          }
          this.hostinfo.draw_count = draw_count;
        }
        if ((param = rule.match(/(^|,|,)(LFLIST|LF)(\d+)(,|,|$)/))) {
          lflist = parseInt(param[3]) - 1;
          this.hostinfo.lflist = lflist;
        }
        if (rule.match(/(^|,|,)(NOLFLIST|NF)(,|,|$)/)) {
          this.hostinfo.lflist = -1;
        }
        if (rule.match(/(^|,|,)(NOUNIQUE|NU)(,|,|$)/)) {
          this.hostinfo.rule = 3;
        }
        if (rule.match(/(^|,|,)(NOCHECK|NC)(,|,|$)/)) {
          this.hostinfo.no_check_deck = true;
        }
        if (rule.match(/(^|,|,)(NOSHUFFLE|NS)(,|,|$)/)) {
          this.hostinfo.no_shuffle_deck = true;
        }
        if (rule.match(/(^|,|,)(IGPRIORITY|PR)(,|,|$)/)) {
          this.hostinfo.enable_priority = true;
        }
nanahira's avatar
nanahira committed
1358
        if (rule.match(/(^|,|,)(NOWATCH|NW)(,|,|$)/)) {
nanahira's avatar
nanahira committed
1359
          this.hostinfo.no_watch = true;
nanahira's avatar
nanahira committed
1360
        }
mercury233's avatar
mercury233 committed
1361
      }
nanahira's avatar
nanahira committed
1362
      this.hostinfo.replay_mode = settings.modules.tournament_mode.enabled && settings.modules.tournament_mode.replay_safe || this.hostinfo.mode === 1 && settings.modules.replay_delay ? 1 : 0;
mercury233's avatar
mercury233 committed
1363
      param = [0, this.hostinfo.lflist, this.hostinfo.rule, this.hostinfo.mode, (this.hostinfo.enable_priority ? 'T' : 'F'), (this.hostinfo.no_check_deck ? 'T' : 'F'), (this.hostinfo.no_shuffle_deck ? 'T' : 'F'), this.hostinfo.start_lp, this.hostinfo.start_hand, this.hostinfo.draw_count, this.hostinfo.time_limit, this.hostinfo.replay_mode];
mercury233's avatar
mercury233 committed
1364 1365
      try {
        this.process = spawn('./ygopro', param, {
mercury233's avatar
mercury233 committed
1366
          cwd: 'ygopro'
mercury233's avatar
mercury233 committed
1367
        });
nanahira's avatar
nanahira committed
1368
        this.process_pid = this.process.pid;
mercury233's avatar
fix  
mercury233 committed
1369 1370 1371
        this.process.on('error', (function(_this) {
          return function(err) {
            _.each(_this.players, function(player) {
mercury233's avatar
mercury233 committed
1372
              return ygopro.stoc_die(player, "${create_room_failed}");
mercury233's avatar
fix  
mercury233 committed
1373 1374 1375 1376
            });
            _this["delete"]();
          };
        })(this));
mercury233's avatar
mercury233 committed
1377 1378 1379 1380 1381 1382 1383 1384 1385 1386 1387 1388
        this.process.on('exit', (function(_this) {
          return function(code) {
            if (!_this.disconnector) {
              _this.disconnector = 'server';
            }
            _this["delete"]();
          };
        })(this));
        this.process.stdout.setEncoding('utf8');
        this.process.stdout.once('data', (function(_this) {
          return function(data) {
            _this.established = true;
mercury233's avatar
mercury233 committed
1389
            if (!_this.windbot && settings.modules.http.websocket_roomlist) {
mercury233's avatar
mercury233 committed
1390 1391 1392 1393 1394
              roomlist.create(_this);
            }
            _this.port = parseInt(data);
            _.each(_this.players, function(player) {
              player.server.connect(_this.port, '127.0.0.1', function() {
nanahira's avatar
nanahira committed
1395
                var buffer, len2, m, ref2;
nanahira's avatar
nanahira committed
1396
                ref2 = player.pre_establish_buffers;
nanahira's avatar
nanahira committed
1397 1398
                for (m = 0, len2 = ref2.length; m < len2; m++) {
                  buffer = ref2[m];
mercury233's avatar
mercury233 committed
1399 1400 1401 1402 1403 1404 1405
                  player.server.write(buffer);
                }
                player.established = true;
                player.pre_establish_buffers = [];
              });
            });
            if (_this.windbot) {
mercury233's avatar
mercury233 committed
1406 1407 1408
              setTimeout(function() {
                return _this.add_windbot(_this.windbot);
              }, 200);
mercury233's avatar
mercury233 committed
1409 1410 1411
            }
          };
        })(this));
mercury233's avatar
mercury233 committed
1412 1413
        this.process.stderr.on('data', (function(_this) {
          return function(data) {
mercury233's avatar
mercury233 committed
1414 1415 1416 1417
            data = "Debug: " + data;
            data = data.replace(/\n$/, "");
            log.info("YGOPRO " + data);
            ygopro.stoc_send_chat_to_room(_this, data, ygopro.constants.COLORS.RED);
mercury233's avatar
mercury233 committed
1418
            _this.has_ygopro_error = true;
1419 1420
            _this.ygopro_error_length = _this.ygopro_error_length ? _this.ygopro_error_length + data.length : data.length;
            if (_this.ygopro_error_length > 10000) {
nanahira's avatar
nanahira committed
1421
              _this.send_replays();
1422 1423
              _this.process.kill();
            }
mercury233's avatar
mercury233 committed
1424 1425
          };
        })(this));
mercury233's avatar
mercury233 committed
1426
      } catch (error1) {
mercury233's avatar
mercury233 committed
1427
        this.error = "${create_room_failed}";
mercury233's avatar
mercury233 committed
1428 1429 1430 1431
      }
    }

    Room.prototype["delete"] = function() {
nanahira's avatar
js  
nanahira committed
1432
      var end_time, index, log_rep_id, name, player_ips, player_names, recorder_buffer, ref2, replay_id, room_name, score, score_array, score_form;
mercury233's avatar
mercury233 committed
1433 1434 1435
      if (this.deleted) {
        return;
      }
1436
      score_array = [];
nanahira's avatar
nanahira committed
1437 1438 1439
      ref2 = this.scores;
      for (name in ref2) {
        score = ref2[name];
nanahira's avatar
nanahira committed
1440
        score_form = {
1441
          name: name.split('$')[0],
nanahira's avatar
nanahira committed
1442
          score: score,
1443 1444
          deck: null,
          name_vpass: name
nanahira's avatar
nanahira committed
1445 1446 1447 1448 1449
        };
        if (this.decks[name]) {
          score_form.deck = this.decks[name];
        }
        score_array.push(score_form);
1450
      }
1451 1452 1453 1454 1455 1456 1457 1458 1459 1460 1461 1462 1463 1464 1465 1466 1467
      if (settings.modules.random_duel.record_match_scores && this.random_type === 'M') {
        if (score_array.length === 2) {
          if (score_array[0].score !== score_array[1].score) {
            if (score_array[0].score > score_array[1].score) {
              ROOM_player_win(score_array[0].name_vpass);
              ROOM_player_lose(score_array[1].name_vpass);
            } else {
              ROOM_player_win(score_array[1].name_vpass);
              ROOM_player_lose(score_array[0].name_vpass);
            }
          }
        }
        if (score_array.length === 1) {
          ROOM_player_win(score_array[0].name_vpass);
          ROOM_player_lose(score_array[0].name_vpass);
        }
      }
nanahira's avatar
-5  
nanahira committed
1468 1469 1470 1471 1472 1473 1474 1475
      if (settings.modules.arena_mode.enabled && this.arena) {
        end_time = moment().format();
        if (!this.start_time) {
          this.start_time = end_time;
        }
        if (score_array.length !== 2) {
          if (!score_array[0]) {
            score_array[0] = {
nanahira's avatar
nanahira committed
1476
              name: null,
nanahira's avatar
nanahira committed
1477 1478
              score: -5,
              deck: null
nanahira's avatar
-5  
nanahira committed
1479
            };
1480
          }
nanahira's avatar
-5  
nanahira committed
1481 1482
          if (!score_array[1]) {
            score_array[1] = {
nanahira's avatar
nanahira committed
1483
              name: null,
nanahira's avatar
nanahira committed
1484 1485
              score: -5,
              deck: null
mercury233's avatar
merge  
mercury233 committed
1486
            };
nanahira's avatar
-5  
nanahira committed
1487 1488 1489
          }
          score_array[0].score = -5;
          score_array[1].score = -5;
mercury233's avatar
merge  
mercury233 committed
1490
        }
nanahira's avatar
-5  
nanahira committed
1491 1492 1493 1494 1495 1496 1497 1498
        request.post({
          url: settings.modules.arena_mode.post_score,
          form: {
            accesskey: settings.modules.arena_mode.accesskey,
            usernameA: score_array[0].name,
            usernameB: score_array[1].name,
            userscoreA: score_array[0].score,
            userscoreB: score_array[1].score,
nanahira's avatar
nanahira committed
1499 1500
            userdeckA: score_array[0].deck,
            userdeckB: score_array[1].deck,
nanahira's avatar
-5  
nanahira committed
1501 1502 1503 1504 1505 1506 1507 1508 1509 1510 1511 1512 1513 1514 1515
            start: this.start_time,
            end: end_time,
            arena: this.arena
          }
        }, (function(_this) {
          return function(error, response, body) {
            if (error) {
              log.warn('SCORE POST ERROR', error);
            } else {
              if (response.statusCode !== 204 && response.statusCode !== 200) {
                log.warn('SCORE POST FAIL', response.statusCode, response.statusMessage, _this.name, body);
              }
            }
          };
        })(this));
mercury233's avatar
mercury233 committed
1516
      }
nanahira's avatar
js  
nanahira committed
1517
      if (settings.modules.challonge.enabled && this.started && this.hostinfo.mode !== 2 && !this.kicked) {
nanahira's avatar
js  
nanahira committed
1518
        room_name = this.name;
nanahira's avatar
nanahira committed
1519
        challonge.matches._update({
1520
          id: settings.modules.challonge.tournament_id,
nanahira's avatar
nanahira committed
1521
          matchId: this.challonge_info.id,
nanahira's avatar
nanahira committed
1522
          match: this.get_challonge_score(),
nanahira's avatar
nanahira committed
1523 1524
          callback: function(err, data) {
            if (err) {
nanahira's avatar
js  
nanahira committed
1525
              log.warn("Errored pushing scores to Challonge.", room_name, err);
nanahira's avatar
nanahira committed
1526 1527
            } else {
              refresh_challonge_cache();
nanahira's avatar
nanahira committed
1528 1529 1530 1531
            }
          }
        });
      }
mercury233's avatar
mercury233 committed
1532
      if (this.player_datas.length && settings.modules.cloud_replay.enabled) {
1533
        replay_id = this.cloud_replay_id;
mercury233's avatar
mercury233 committed
1534 1535 1536
        if (this.has_ygopro_error) {
          log_rep_id = true;
        }
mercury233's avatar
mercury233 committed
1537 1538 1539 1540 1541 1542 1543
        player_names = this.player_datas[0].name + (this.player_datas[2] ? "+" + this.player_datas[2].name : "") + " VS " + (this.player_datas[1] ? this.player_datas[1].name : "AI") + (this.player_datas[3] ? "+" + this.player_datas[3].name : "");
        player_ips = [];
        _.each(this.player_datas, function(player) {
          player_ips.push(player.ip);
        });
        recorder_buffer = Buffer.concat(this.recorder_buffers);
        zlib.deflate(recorder_buffer, function(err, replay_buffer) {
1544
          var date_time, recorded_ip;
mercury233's avatar
mercury233 committed
1545 1546 1547
          replay_buffer = replay_buffer.toString('binary');
          date_time = moment().format('YYYY-MM-DD HH:mm:ss');
          redisdb.hmset("replay:" + replay_id, "replay_id", replay_id, "replay_buffer", replay_buffer, "player_names", player_names, "date_time", date_time);
mercury233's avatar
mercury233 committed
1548 1549 1550
          if (!log_rep_id) {
            redisdb.expire("replay:" + replay_id, 60 * 60 * 24);
          }
mercury233's avatar
mercury233 committed
1551 1552 1553 1554 1555 1556 1557 1558
          recorded_ip = [];
          _.each(player_ips, function(player_ip) {
            if (_.contains(recorded_ip, player_ip)) {
              return;
            }
            recorded_ip.push(player_ip);
            redisdb.lpush(player_ip + ":replays", replay_id);
          });
mercury233's avatar
mercury233 committed
1559
          if (log_rep_id) {
mercury233's avatar
mercury233 committed
1560 1561
            log.info("error replay: R#" + replay_id);
          }
mercury233's avatar
mercury233 committed
1562 1563 1564 1565 1566 1567
        });
      }
      this.watcher_buffers = [];
      this.recorder_buffers = [];
      this.players = [];
      if (this.watcher) {
mercury233's avatar
mercury233 committed
1568
        this.watcher.destroy();
mercury233's avatar
mercury233 committed
1569
      }
mercury233's avatar
fix  
mercury233 committed
1570 1571 1572
      if (this.recorder) {
        this.recorder.destroy();
      }
mercury233's avatar
mercury233 committed
1573 1574
      this.deleted = true;
      index = _.indexOf(ROOM_all, this);
nanahira's avatar
nanahira committed
1575
      if (settings.modules.reconnect.enabled) {
nanahira's avatar
nanahira committed
1576
        ROOM_clear_disconnect(index);
nanahira's avatar
nanahira committed
1577
      }
mercury233's avatar
mercury233 committed
1578
      if (index !== -1) {
1579
        ROOM_all[index] = null;
mercury233's avatar
mercury233 committed
1580
      }
mercury233's avatar
mercury233 committed
1581
      if (!this.windbot && this.established && settings.modules.http.websocket_roomlist) {
mercury233's avatar
mercury233 committed
1582
        roomlist["delete"](this);
mercury233's avatar
mercury233 committed
1583 1584 1585 1586 1587 1588 1589 1590 1591 1592 1593 1594 1595 1596 1597 1598 1599 1600 1601 1602 1603 1604 1605 1606 1607
      }
    };

    Room.prototype.get_playing_player = function() {
      var playing_player;
      playing_player = [];
      _.each(this.players, function(player) {
        if (player.pos < 4) {
          playing_player.push(player);
        }
      });
      return playing_player;
    };

    Room.prototype.get_host = function() {
      var host_player;
      host_player = null;
      _.each(this.players, function(player) {
        if (player.is_host) {
          host_player = player;
        }
      });
      return host_player;
    };

1608
    Room.prototype.get_disconnected_count = function() {
1609 1610
      var found, len2, m, player, ref2;
      if (!settings.modules.reconnect.enabled) {
1611
        return 0;
1612
      }
1613
      found = 0;
1614 1615 1616
      ref2 = this.get_playing_player();
      for (m = 0, len2 = ref2.length; m < len2; m++) {
        player = ref2[m];
1617 1618
        if (player.closed) {
          found++;
1619 1620 1621 1622 1623
        }
      }
      return found;
    };

nanahira's avatar
nanahira committed
1624 1625
    Room.prototype.get_challonge_score = function() {
      var challonge_duel_log;
nanahira's avatar
js  
nanahira committed
1626
      if (!settings.modules.challonge.enabled || !this.started || this.hostinfo.mode === 2) {
nanahira's avatar
nanahira committed
1627 1628 1629
        return null;
      }
      challonge_duel_log = {};
1630
      if (this.scores[this.dueling_players[0].name_vpass] > this.scores[this.dueling_players[1].name_vpass]) {
nanahira's avatar
nanahira committed
1631
        challonge_duel_log.winnerId = this.dueling_players[0].challonge_info.id;
1632
      } else if (this.scores[this.dueling_players[0].name_vpass] < this.scores[this.dueling_players[1].name_vpass]) {
nanahira's avatar
nanahira committed
1633 1634 1635 1636 1637 1638
        challonge_duel_log.winnerId = this.dueling_players[1].challonge_info.id;
      } else {
        challonge_duel_log.winnerId = "tie";
      }
      if (settings.modules.challonge.post_detailed_score) {
        if (this.dueling_players[0].challonge_info.id === this.challonge_info.player1Id && this.dueling_players[1].challonge_info.id === this.challonge_info.player2Id) {
1639
          challonge_duel_log.scoresCsv = this.scores[this.dueling_players[0].name_vpass] + "-" + this.scores[this.dueling_players[1].name_vpass];
nanahira's avatar
nanahira committed
1640
        } else if (this.dueling_players[1].challonge_info.id === this.challonge_info.player1Id && this.dueling_players[0].challonge_info.id === this.challonge_info.player2Id) {
1641
          challonge_duel_log.scoresCsv = this.scores[this.dueling_players[1].name_vpass] + "-" + this.scores[this.dueling_players[0].name_vpass];
nanahira's avatar
nanahira committed
1642 1643 1644 1645 1646 1647 1648 1649 1650 1651 1652 1653 1654 1655 1656 1657
        } else {
          challonge_duel_log.scoresCsv = "0-0";
          log.warn("Score mismatch.", this.name);
        }
      } else {
        if (challonge_duel_log.winnerId === this.challonge_info.player1Id) {
          challonge_duel_log.scoresCsv = "1-0";
        } else if (challonge_duel_log.winnerId === this.challonge_info.player2Id) {
          challonge_duel_log.scoresCsv = "0-1";
        } else {
          challonge_duel_log.scoresCsv = "0-0";
        }
      }
      return challonge_duel_log;
    };

nanahira's avatar
nanahira committed
1658 1659 1660 1661 1662 1663 1664 1665 1666 1667 1668 1669 1670 1671 1672 1673 1674 1675
    Room.prototype.send_replays = function() {
      var len2, len3, m, n, player, ref2, ref3;
      if (!(settings.modules.replay_delay && this.replays.length && this.hostinfo.mode === 1)) {
        return false;
      }
      ref2 = this.players;
      for (m = 0, len2 = ref2.length; m < len2; m++) {
        player = ref2[m];
        CLIENT_send_replays(player, this);
      }
      ref3 = this.watchers;
      for (n = 0, len3 = ref3.length; n < len3; n++) {
        player = ref3[n];
        CLIENT_send_replays(player, this);
      }
      return true;
    };

mercury233's avatar
mercury233 committed
1676 1677 1678
    Room.prototype.add_windbot = function(botdata) {
      this.windbot = botdata;
      request({
1679
        url: "http://" + settings.modules.windbot.server_ip + ":" + settings.modules.windbot.port + "/?name=" + (encodeURIComponent(botdata.name)) + "&deck=" + (encodeURIComponent(botdata.deck)) + "&host=" + settings.modules.windbot.my_ip + "&port=" + settings.port + "&dialog=" + (encodeURIComponent(botdata.dialog)) + "&version=" + settings.version + "&password=" + (encodeURIComponent(this.name))
mercury233's avatar
mercury233 committed
1680 1681 1682
      }, (function(_this) {
        return function(error, response, body) {
          if (error) {
mercury233's avatar
merge  
mercury233 committed
1683
            log.warn('windbot add error', error, _this.name);
mercury233's avatar
mercury233 committed
1684
            ygopro.stoc_send_chat_to_room(_this, "${add_windbot_failed}", ygopro.constants.COLORS.RED);
mercury233's avatar
mercury233 committed
1685 1686 1687 1688 1689
          }
        };
      })(this));
    };

mercury233's avatar
mercury233 committed
1690
    Room.prototype.connect = function(client) {
mercury233's avatar
mercury233 committed
1691
      var host_player;
mercury233's avatar
mercury233 committed
1692
      this.players.push(client);
nanahira's avatar
nanahira committed
1693
      client.join_time = moment();
mercury233's avatar
mercury233 committed
1694
      if (this.random_type) {
mercury233's avatar
mercury233 committed
1695
        client.abuse_count = 0;
mercury233's avatar
mercury233 committed
1696 1697
        host_player = this.get_host();
        if (host_player && (host_player !== client)) {
mercury233's avatar
mercury233 committed
1698 1699
          ROOM_players_oppentlist[host_player.ip] = client.ip;
          ROOM_players_oppentlist[client.ip] = host_player.ip;
mercury233's avatar
mercury233 committed
1700
        } else {
mercury233's avatar
mercury233 committed
1701
          ROOM_players_oppentlist[client.ip] = null;
mercury233's avatar
mercury233 committed
1702 1703 1704
        }
      }
      if (this.established) {
mercury233's avatar
mercury233 committed
1705
        if (!this.windbot && !this.started && settings.modules.http.websocket_roomlist) {
mercury233's avatar
mercury233 committed
1706 1707 1708
          roomlist.update(this);
        }
        client.server.connect(this.port, '127.0.0.1', function() {
nanahira's avatar
nanahira committed
1709
          var buffer, len2, m, ref2;
nanahira's avatar
nanahira committed
1710
          ref2 = client.pre_establish_buffers;
nanahira's avatar
nanahira committed
1711 1712
          for (m = 0, len2 = ref2.length; m < len2; m++) {
            buffer = ref2[m];
mercury233's avatar
mercury233 committed
1713 1714 1715 1716 1717 1718 1719 1720 1721
            client.server.write(buffer);
          }
          client.established = true;
          client.pre_establish_buffers = [];
        });
      }
    };

    Room.prototype.disconnect = function(client, error) {
nanahira's avatar
fix  
nanahira committed
1722
      var index, left_name, len2, m, player, ref2;
nanahira's avatar
nanahira committed
1723 1724 1725
      if (client.had_new_reconnection) {
        return;
      }
mercury233's avatar
mercury233 committed
1726
      if (client.is_post_watcher) {
mercury233's avatar
mercury233 committed
1727
        ygopro.stoc_send_chat_to_room(this, (client.name + " ${quit_watch}") + (error ? ": " + error : ''));
mercury233's avatar
mercury233 committed
1728 1729 1730 1731
        index = _.indexOf(this.watchers, client);
        if (index !== -1) {
          this.watchers.splice(index, 1);
        }
nanahira's avatar
nanahira committed
1732
        client.server.destroy();
mercury233's avatar
mercury233 committed
1733
      } else {
nanahira's avatar
fix  
nanahira committed
1734
        if (this.arena && !this.started && this.disconnector !== 'server' && !this.arena_score_handled) {
nanahira's avatar
nanahira committed
1735
          ref2 = this.players;
nanahira's avatar
nanahira committed
1736 1737
          for (m = 0, len2 = ref2.length; m < len2; m++) {
            player = ref2[m];
1738
            if (player.pos !== 7) {
1739
              this.scores[player.name_vpass] = 0;
1740 1741
            }
          }
nanahira's avatar
fix  
nanahira committed
1742
          if (this.players.length === 2 && !client.arena_quit_free) {
1743
            this.scores[client.name_vpass] = -9;
nanahira's avatar
-5  
nanahira committed
1744
          }
nanahira's avatar
nanahira committed
1745
          this.arena_score_handled = true;
1746
        }
mercury233's avatar
mercury233 committed
1747 1748 1749 1750
        index = _.indexOf(this.players, client);
        if (index !== -1) {
          this.players.splice(index, 1);
        }
1751
        if (this.started && this.disconnector !== 'server' && client.pos < 4) {
mercury233's avatar
mercury233 committed
1752
          this.finished = true;
nanahira's avatar
nanahira committed
1753
          if (!this.finished_by_death) {
1754
            this.scores[client.name_vpass] = -9;
nanahira's avatar
fix  
nanahira committed
1755
            if (this.random_type && !client.flee_free && (!settings.modules.reconnect.enabled || this.get_disconnected_count() === 0)) {
nanahira's avatar
nanahira committed
1756
              ROOM_ban_player(client.name, client.ip, "${random_ban_reason_flee}");
mercury233's avatar
mercury233 committed
1757 1758 1759
              if (settings.modules.random_duel.record_match_scores && this.random_type === 'M') {
                ROOM_player_flee(client.name_vpass);
              }
nanahira's avatar
nanahira committed
1760
            }
mercury233's avatar
mercury233 committed
1761
          }
mercury233's avatar
mercury233 committed
1762
        }
nanahira's avatar
-5  
nanahira committed
1763
        if (this.players.length && !(this.windbot && client.is_host) && !(this.arena && !this.started && client.pos <= 3)) {
nanahira's avatar
fix  
nanahira committed
1764 1765
          left_name = (settings.modules.hide_name && !this.started ? "********" : client.name);
          ygopro.stoc_send_chat_to_room(this, (left_name + " ${left_game}") + (error ? ": " + error : ''));
mercury233's avatar
mercury233 committed
1766
          if (!this.windbot && !this.started && settings.modules.http.websocket_roomlist) {
mercury233's avatar
mercury233 committed
1767 1768 1769
            roomlist.update(this);
          }
        } else {
nanahira's avatar
nanahira committed
1770
          this.send_replays();
mercury233's avatar
mercury233 committed
1771 1772 1773
          this.process.kill();
          this["delete"]();
        }
nanahira's avatar
nanahira committed
1774
        if (!CLIENT_reconnect_unregister(client, false, true)) {
nanahira's avatar
nanahira committed
1775 1776
          client.server.destroy();
        }
mercury233's avatar
mercury233 committed
1777 1778 1779
      }
    };

nanahira's avatar
nanahira committed
1780 1781 1782 1783 1784 1785 1786 1787 1788 1789 1790 1791 1792 1793 1794 1795 1796 1797 1798 1799 1800 1801 1802 1803 1804 1805 1806 1807 1808 1809 1810 1811 1812 1813 1814 1815 1816 1817 1818 1819 1820 1821 1822 1823 1824 1825 1826 1827 1828 1829 1830 1831 1832 1833 1834 1835 1836 1837 1838 1839 1840 1841 1842 1843 1844 1845 1846
    Room.prototype.start_death = function() {
      var oppo_pos, win_pos;
      if (!(this.established && this.started && !this.death)) {
        return false;
      }
      oppo_pos = this.hostinfo.mode === 2 ? 2 : 1;
      if (!this.changing_side && (!this.duel_count || this.turn)) {
        switch (settings.modules.http.quick_death_rule) {
          case 3:
            this.death = -2;
            ygopro.stoc_send_chat_to_room(this, "${death_start_phase}", ygopro.constants.COLORS.BABYBLUE);
            break;
          default:
            this.death = (this.turn ? this.turn + 4 : 5);
            ygopro.stoc_send_chat_to_room(this, "${death_start}", ygopro.constants.COLORS.BABYBLUE);
        }
      } else {
        switch (settings.modules.http.quick_death_rule) {
          case 2:
          case 3:
            if (this.scores[this.dueling_players[0].name_vpass] === this.scores[this.dueling_players[oppo_pos].name_vpass]) {
              if (settings.modules.http.quick_death_rule === 3) {
                this.death = -1;
                ygopro.stoc_send_chat_to_room(this, "${death_start_quick}", ygopro.constants.COLORS.BABYBLUE);
              } else {
                this.death = 5;
                ygopro.stoc_send_chat_to_room(this, "${death_start_siding}", ygopro.constants.COLORS.BABYBLUE);
              }
            } else {
              win_pos = this.scores[this.dueling_players[0].name_vpass] > this.scores[this.dueling_players[oppo_pos].name_vpass] ? 0 : oppo_pos;
              this.finished_by_death = true;
              ygopro.stoc_send_chat_to_room(this, "${death2_finish_part1}" + this.dueling_players[win_pos].name + "${death2_finish_part2}", ygopro.constants.COLORS.BABYBLUE);
              if (this.hostinfo.mode === 1) {
                CLIENT_send_replays(this.dueling_players[oppo_pos - win_pos], this);
              }
              ygopro.stoc_send(this.dueling_players[oppo_pos - win_pos], 'DUEL_END');
              if (this.hostinfo.mode === 2) {
                ygopro.stoc_send(this.dueling_players[oppo_pos - win_pos + 1], 'DUEL_END');
              }
              this.scores[this.dueling_players[oppo_pos - win_pos].name_vpass] = -1;
              CLIENT_kick(this.dueling_players[oppo_pos - win_pos]);
              if (this.hostinfo.mode === 2) {
                CLIENT_kick(this.dueling_players[oppo_pos - win_pos + 1]);
              }
            }
            break;
          case 1:
            this.death = -1;
            ygopro.stoc_send_chat_to_room(this, "${death_start_quick}", ygopro.constants.COLORS.BABYBLUE);
            break;
          default:
            this.death = 5;
            ygopro.stoc_send_chat_to_room(this, "${death_start_siding}", ygopro.constants.COLORS.BABYBLUE);
        }
      }
      return true;
    };

    Room.prototype.cancel_death = function() {
      if (!(this.established && this.started && this.death)) {
        return false;
      }
      this.death = 0;
      ygopro.stoc_send_chat_to_room(this, "${death_cancel}", ygopro.constants.COLORS.BABYBLUE);
      return true;
    };

mercury233's avatar
mercury233 committed
1847 1848 1849 1850
    return Room;

  })();

神楽坂玲奈's avatar
神楽坂玲奈 committed
1851
  net.createServer(function(client) {
mercury233's avatar
mercury233 committed
1852 1853
    var connect_count, server;
    client.ip = client.remoteAddress;
mercury233's avatar
mercury233 committed
1854
    client.is_local = client.ip && (client.ip.includes('127.0.0.1') || client.ip.includes(settings.modules.windbot.server_ip));
mercury233's avatar
mercury233 committed
1855
    connect_count = ROOM_connected_ip[client.ip] || 0;
1856
    if (!settings.modules.test_mode.no_connect_count_limit && !client.is_local) {
mercury233's avatar
mercury233 committed
1857 1858 1859
      connect_count++;
    }
    ROOM_connected_ip[client.ip] = connect_count;
神楽坂玲奈's avatar
神楽坂玲奈 committed
1860 1861
    server = new net.Socket();
    client.server = server;
nanahira's avatar
nanahira committed
1862
    server.client = client;
mercury233's avatar
mercury233 committed
1863
    client.setTimeout(2000);
1864
    client.on('close', function(had_error) {
mercury233's avatar
mercury233 committed
1865
      var room;
1866
      room = ROOM_all[client.rid];
mercury233's avatar
mercury233 committed
1867 1868 1869 1870 1871
      connect_count = ROOM_connected_ip[client.ip];
      if (connect_count > 0) {
        connect_count--;
      }
      ROOM_connected_ip[client.ip] = connect_count;
1872
      if (!client.closed) {
神楽坂玲奈's avatar
11.7  
神楽坂玲奈 committed
1873
        client.closed = true;
nanahira's avatar
nanahira committed
1874 1875 1876
        if (settings.modules.heartbeat_detection.enabled) {
          CLIENT_heartbeat_unregister(client);
        }
1877
        if (room) {
nanahira's avatar
nanahira committed
1878
          if (!CLIENT_reconnect_register(client, client.rid)) {
nanahira's avatar
nanahira committed
1879 1880 1881 1882
            room.disconnect(client);
          }
        } else if (!client.had_new_reconnection) {
          client.server.destroy();
神楽坂玲奈's avatar
init  
神楽坂玲奈 committed
1883
        }
mercury233's avatar
mercury233 committed
1884 1885
      }
    });
1886
    client.on('error', function(error) {
mercury233's avatar
mercury233 committed
1887
      var room;
1888
      room = ROOM_all[client.rid];
mercury233's avatar
mercury233 committed
1889 1890 1891 1892 1893
      connect_count = ROOM_connected_ip[client.ip];
      if (connect_count > 0) {
        connect_count--;
      }
      ROOM_connected_ip[client.ip] = connect_count;
1894
      if (!client.closed) {
nanahira's avatar
nanahira committed
1895
        client.closed = true;
1896
        if (room) {
nanahira's avatar
nanahira committed
1897
          if (!CLIENT_reconnect_register(client, client.rid, error)) {
nanahira's avatar
nanahira committed
1898 1899 1900 1901
            room.disconnect(client, error);
          }
        } else if (!client.had_new_reconnection) {
          client.server.destroy();
1902
        }
神楽坂玲奈's avatar
神楽坂玲奈 committed
1903
      }
神楽坂玲奈's avatar
init  
神楽坂玲奈 committed
1904
    });
1905
    client.on('timeout', function() {
nanahira's avatar
nanahira committed
1906
      if (!(settings.modules.reconnect.enabled && (disconnect_list[CLIENT_get_authorize_key(client)] || client.had_new_reconnection))) {
nanahira's avatar
nanahira committed
1907
        client.destroy();
nanahira's avatar
nanahira committed
1908
      }
1909
    });
1910
    server.on('close', function(had_error) {
1911
      var room;
nanahira's avatar
nanahira committed
1912
      room = ROOM_all[server.client.rid];
1913 1914 1915
      if (room) {
        room.disconnector = 'server';
      }
1916 1917
      if (!server.closed) {
        server.closed = true;
mercury233's avatar
mercury233 committed
1918
      }
nanahira's avatar
nanahira committed
1919 1920 1921 1922 1923 1924 1925
      if (!server.client) {
        return;
      }
      if (!server.client.closed) {
        ygopro.stoc_send_chat(server.client, "${server_closed}", ygopro.constants.COLORS.RED);
        CLIENT_kick(server.client);
        SERVER_clear_disconnect(server);
mercury233's avatar
mercury233 committed
1926 1927
      }
    });
1928
    server.on('error', function(error) {
1929
      var room;
nanahira's avatar
nanahira committed
1930
      room = ROOM_all[server.client.rid];
1931 1932 1933
      if (room) {
        room.disconnector = 'server';
      }
1934
      server.closed = error;
nanahira's avatar
nanahira committed
1935 1936 1937 1938 1939 1940 1941
      if (!server.client) {
        return;
      }
      if (!server.client.closed) {
        ygopro.stoc_send_chat(server.client, "${server_error}: " + error, ygopro.constants.COLORS.RED);
        CLIENT_kick(server.client);
        SERVER_clear_disconnect(server);
mercury233's avatar
mercury233 committed
1942 1943
      }
    });
mercury233's avatar
mercury233 committed
1944
    if (ROOM_bad_ip[client.ip] > 5 || ROOM_connected_ip[client.ip] > 10) {
mercury233's avatar
mercury233 committed
1945
      log.info('BAD IP', client.ip);
nanahira's avatar
nanahira committed
1946
      CLIENT_kick(client);
mercury233's avatar
mercury233 committed
1947 1948
      return;
    }
mercury233's avatar
mercury233 committed
1949
    if (settings.modules.cloud_replay.enabled) {
mercury233's avatar
mercury233 committed
1950 1951 1952
      client.open_cloud_replay = function(err, replay) {
        var buffer;
        if (err || !replay) {
mercury233's avatar
mercury233 committed
1953
          ygopro.stoc_die(client, "${cloud_replay_no}");
mercury233's avatar
mercury233 committed
1954
          return;
mercury233's avatar
mercury233 committed
1955
        }
mercury233's avatar
mercury233 committed
1956
        redisdb.expire("replay:" + replay.replay_id, 60 * 60 * 48);
nanahira's avatar
nanahira committed
1957
        buffer = Buffer.from(replay.replay_buffer, 'binary');
mercury233's avatar
mercury233 committed
1958 1959
        zlib.unzip(buffer, function(err, replay_buffer) {
          if (err) {
mercury233's avatar
mercury233 committed
1960
            log.info("cloud replay unzip error: " + err);
mercury233's avatar
mercury233 committed
1961
            ygopro.stoc_send_chat(client, "${cloud_replay_error}", ygopro.constants.COLORS.RED);
nanahira's avatar
nanahira committed
1962
            CLIENT_kick(client);
mercury233's avatar
mercury233 committed
1963 1964
            return;
          }
mercury233's avatar
mercury233 committed
1965
          ygopro.stoc_send_chat(client, "${cloud_replay_playing} R#" + replay.replay_id + " " + replay.player_names + " " + replay.date_time, ygopro.constants.COLORS.BABYBLUE);
mercury233's avatar
mercury233 committed
1966
          client.write(replay_buffer, function() {
nanahira's avatar
nanahira committed
1967
            CLIENT_kick(client);
mercury233's avatar
mercury233 committed
1968
          });
mercury233's avatar
mercury233 committed
1969
        });
mercury233's avatar
mercury233 committed
1970 1971
      };
    }
神楽坂玲奈's avatar
神楽坂玲奈 committed
1972
    client.pre_establish_buffers = new Array();
mercury233's avatar
mercury233 committed
1973
    client.on('data', function(ctos_buffer) {
nanahira's avatar
nanahira committed
1974
      var b, bad_ip_count, buffer, cancel, ctos_message_length, ctos_proto, datas, info, len2, len3, looplimit, m, n, room, struct;
1975
      if (client.is_post_watcher) {
1976
        room = ROOM_all[client.rid];
nanahira's avatar
nanahira committed
1977
        if (room && !CLIENT_is_banned_by_mc(client)) {
mercury233's avatar
mercury233 committed
1978
          room.watcher.write(ctos_buffer);
1979
        }
神楽坂玲奈's avatar
11.7  
神楽坂玲奈 committed
1980
      } else {
mercury233's avatar
mercury233 committed
1981 1982
        ctos_message_length = 0;
        ctos_proto = 0;
1983
        datas = [];
mercury233's avatar
mercury233 committed
1984
        looplimit = 0;
神楽坂玲奈's avatar
11.7  
神楽坂玲奈 committed
1985
        while (true) {
1986 1987
          if (ctos_message_length === 0) {
            if (ctos_buffer.length >= 2) {
mercury233's avatar
test3  
mercury233 committed
1988
              ctos_message_length = ctos_buffer.readUInt16LE(0);
神楽坂玲奈's avatar
11.7  
神楽坂玲奈 committed
1989
            } else {
mercury233's avatar
mercury233 committed
1990 1991 1992
              if (ctos_buffer.length !== 0) {
                log.warn("bad ctos_buffer length", client.ip);
              }
神楽坂玲奈's avatar
11.7  
神楽坂玲奈 committed
1993 1994
              break;
            }
1995 1996
          } else if (ctos_proto === 0) {
            if (ctos_buffer.length >= 3) {
mercury233's avatar
test3  
mercury233 committed
1997
              ctos_proto = ctos_buffer.readUInt8(2);
神楽坂玲奈's avatar
11.7  
神楽坂玲奈 committed
1998
            } else {
mercury233's avatar
mercury233 committed
1999
              log.warn("bad ctos_proto length", client.ip);
神楽坂玲奈's avatar
11.7  
神楽坂玲奈 committed
2000
              break;
神楽坂玲奈's avatar
init  
神楽坂玲奈 committed
2001 2002
            }
          } else {
2003
            if (ctos_buffer.length >= 2 + ctos_message_length) {
2004
              cancel = false;
nanahira's avatar
nanahira committed
2005 2006 2007 2008
              if (settings.modules.reconnect.enabled && client.pre_reconnecting && ygopro.constants.CTOS[ctos_proto] !== 'UPDATE_DECK') {
                cancel = true;
              }
              if (ygopro.ctos_follows[ctos_proto] && !cancel) {
2009
                b = ctos_buffer.slice(3, ctos_message_length - 1 + 3);
2010
                info = null;
2011
                if (struct = ygopro.structs[ygopro.proto_structs.CTOS[ygopro.constants.CTOS[ctos_proto]]]) {
神楽坂玲奈's avatar
11.7  
神楽坂玲奈 committed
2012
                  struct._setBuff(b);
2013 2014 2015
                  info = _.clone(struct.fields);
                }
                if (ygopro.ctos_follows[ctos_proto].synchronous) {
2016
                  cancel = ygopro.ctos_follows[ctos_proto].callback(b, info, client, client.server, datas);
神楽坂玲奈's avatar
11.7  
神楽坂玲奈 committed
2017
                } else {
2018
                  ygopro.ctos_follows[ctos_proto].callback(b, info, client, client.server, datas);
神楽坂玲奈's avatar
11.7  
神楽坂玲奈 committed
2019 2020
                }
              }
2021 2022 2023
              if (!cancel) {
                datas.push(ctos_buffer.slice(0, 2 + ctos_message_length));
              }
2024 2025
              ctos_buffer = ctos_buffer.slice(2 + ctos_message_length);
              ctos_message_length = 0;
mercury233's avatar
test3  
mercury233 committed
2026
              ctos_proto = 0;
mercury233's avatar
fix  
mercury233 committed
2027 2028 2029 2030
            } else {
              if (ctos_message_length !== 17735) {
                log.warn("bad ctos_message length", client.ip, ctos_buffer.length, ctos_message_length, ctos_proto);
              }
神楽坂玲奈's avatar
11.7  
神楽坂玲奈 committed
2031 2032
              break;
            }
神楽坂玲奈's avatar
init  
神楽坂玲奈 committed
2033
          }
mercury233's avatar
mercury233 committed
2034
          looplimit++;
mercury233's avatar
mercury233 committed
2035 2036 2037
          if (looplimit > 800 || ROOM_bad_ip[client.ip] > 5) {
            log.info("error ctos", client.name, client.ip);
            bad_ip_count = ROOM_bad_ip[client.ip];
mercury233's avatar
mercury233 committed
2038
            if (bad_ip_count) {
mercury233's avatar
mercury233 committed
2039
              ROOM_bad_ip[client.ip] = bad_ip_count + 1;
mercury233's avatar
mercury233 committed
2040
            } else {
mercury233's avatar
mercury233 committed
2041
              ROOM_bad_ip[client.ip] = 1;
mercury233's avatar
mercury233 committed
2042
            }
nanahira's avatar
nanahira committed
2043
            CLIENT_kick(client);
mercury233's avatar
mercury233 committed
2044 2045
            break;
          }
神楽坂玲奈's avatar
init  
神楽坂玲奈 committed
2046
        }
nanahira's avatar
nanahira committed
2047 2048 2049
        if (!client.server) {
          return;
        }
2050
        if (client.established) {
nanahira's avatar
nanahira committed
2051 2052 2053
          for (m = 0, len2 = datas.length; m < len2; m++) {
            buffer = datas[m];
            client.server.write(buffer);
2054 2055
          }
        } else {
nanahira's avatar
nanahira committed
2056 2057
          for (n = 0, len3 = datas.length; n < len3; n++) {
            buffer = datas[n];
2058 2059 2060
            client.pre_establish_buffers.push(buffer);
          }
        }
神楽坂玲奈's avatar
init  
神楽坂玲奈 committed
2061 2062
      }
    });
mercury233's avatar
mercury233 committed
2063
    server.on('data', function(stoc_buffer) {
nanahira's avatar
nanahira committed
2064
      var b, buffer, cancel, datas, info, len2, looplimit, m, stanzas, stoc_message_length, stoc_proto, struct;
mercury233's avatar
mercury233 committed
2065 2066
      stoc_message_length = 0;
      stoc_proto = 0;
2067
      datas = [];
mercury233's avatar
mercury233 committed
2068
      looplimit = 0;
神楽坂玲奈's avatar
神楽坂玲奈 committed
2069
      while (true) {
2070 2071
        if (stoc_message_length === 0) {
          if (stoc_buffer.length >= 2) {
mercury233's avatar
test3  
mercury233 committed
2072
            stoc_message_length = stoc_buffer.readUInt16LE(0);
神楽坂玲奈's avatar
神楽坂玲奈 committed
2073
          } else {
mercury233's avatar
mercury233 committed
2074
            if (stoc_buffer.length !== 0) {
nanahira's avatar
nanahira committed
2075
              log.warn("bad stoc_buffer length", server.client.ip);
mercury233's avatar
mercury233 committed
2076
            }
神楽坂玲奈's avatar
神楽坂玲奈 committed
2077 2078
            break;
          }
2079 2080
        } else if (stoc_proto === 0) {
          if (stoc_buffer.length >= 3) {
mercury233's avatar
test3  
mercury233 committed
2081
            stoc_proto = stoc_buffer.readUInt8(2);
神楽坂玲奈's avatar
神楽坂玲奈 committed
2082
          } else {
nanahira's avatar
nanahira committed
2083
            log.warn("bad stoc_proto length", server.client.ip);
神楽坂玲奈's avatar
神楽坂玲奈 committed
2084 2085 2086
            break;
          }
        } else {
2087
          if (stoc_buffer.length >= 2 + stoc_message_length) {
2088
            cancel = false;
2089 2090 2091
            stanzas = stoc_proto;
            if (ygopro.stoc_follows[stoc_proto]) {
              b = stoc_buffer.slice(3, stoc_message_length - 1 + 3);
2092
              info = null;
2093
              if (struct = ygopro.structs[ygopro.proto_structs.STOC[ygopro.constants.STOC[stoc_proto]]]) {
神楽坂玲奈's avatar
神楽坂玲奈 committed
2094
                struct._setBuff(b);
2095 2096 2097
                info = _.clone(struct.fields);
              }
              if (ygopro.stoc_follows[stoc_proto].synchronous) {
2098
                cancel = ygopro.stoc_follows[stoc_proto].callback(b, info, server.client, server, datas);
神楽坂玲奈's avatar
神楽坂玲奈 committed
2099
              } else {
2100
                ygopro.stoc_follows[stoc_proto].callback(b, info, server.client, server, datas);
神楽坂玲奈's avatar
神楽坂玲奈 committed
2101 2102
              }
            }
2103 2104 2105
            if (!cancel) {
              datas.push(stoc_buffer.slice(0, 2 + stoc_message_length));
            }
2106 2107
            stoc_buffer = stoc_buffer.slice(2 + stoc_message_length);
            stoc_message_length = 0;
mercury233's avatar
test3  
mercury233 committed
2108
            stoc_proto = 0;
神楽坂玲奈's avatar
神楽坂玲奈 committed
2109
          } else {
nanahira's avatar
nanahira committed
2110
            log.warn("bad stoc_message length", server.client.ip);
神楽坂玲奈's avatar
神楽坂玲奈 committed
2111 2112 2113
            break;
          }
        }
mercury233's avatar
mercury233 committed
2114 2115
        looplimit++;
        if (looplimit > 800) {
nanahira's avatar
nanahira committed
2116
          log.info("error stoc", server.client.name);
mercury233's avatar
mercury233 committed
2117
          server.destroy();
mercury233's avatar
mercury233 committed
2118 2119
          break;
        }
神楽坂玲奈's avatar
 
神楽坂玲奈 committed
2120
      }
nanahira's avatar
nanahira committed
2121 2122 2123 2124 2125
      if (server.client && !server.client.closed) {
        for (m = 0, len2 = datas.length; m < len2; m++) {
          buffer = datas[m];
          server.client.write(buffer);
        }
2126
      }
神楽坂玲奈's avatar
init  
神楽坂玲奈 committed
2127
    });
神楽坂玲奈's avatar
神楽坂玲奈 committed
2128
  }).listen(settings.port, function() {
mercury233's avatar
mercury233 committed
2129
    log.info("server started", settings.port);
神楽坂玲奈's avatar
神楽坂玲奈 committed
2130
  });
神楽坂玲奈's avatar
init  
神楽坂玲奈 committed
2131

mercury233's avatar
mercury233 committed
2132 2133 2134 2135
  if (settings.modules.stop) {
    log.info("NOTE: server not open due to config, ", settings.modules.stop);
  }

nanahira's avatar
nanahira committed
2136
  ygopro.ctos_follow('PLAYER_INFO', true, function(buffer, info, client, server, datas) {
nanahira's avatar
nanahira committed
2137 2138 2139 2140 2141 2142 2143
    var geo, lang, name, name_full, struct, vpass;
    name_full = info.name.split("$");
    name = name_full[0];
    vpass = name_full[1];
    if (vpass && !vpass.length) {
      vpass = null;
    }
mercury233's avatar
mercury233 committed
2144 2145 2146 2147 2148 2149 2150 2151 2152 2153 2154 2155
    if (_.any(settings.ban.illegal_id, function(badid) {
      var matchs, regexp;
      regexp = new RegExp(badid, 'i');
      matchs = name.match(regexp);
      if (matchs) {
        name = matchs[1];
        return true;
      }
      return false;
    }, name)) {
      client.rag = true;
    }
nanahira's avatar
typo  
nanahira committed
2156
    if (settings.modules.mycard.enabled) {
nanahira's avatar
nanahira committed
2157 2158 2159 2160 2161 2162 2163 2164 2165 2166 2167 2168 2169 2170 2171 2172
      request({
        url: settings.modules.mycard.ban_get,
        json: true,
        qs: {
          user: name
        }
      }, function(error, response, body) {
        if (_.isString(body)) {
          log.warn("ban get bad json", body);
        } else if (error || !body) {
          log.warn('ban get error', error, response);
        } else {
          client.ban_mc = body;
        }
      });
    }
2173 2174 2175 2176 2177
    struct = ygopro.structs["CTOS_PlayerInfo"];
    struct._setBuff(buffer);
    struct.set("name", name);
    buffer = struct.buffer;
    client.name = name;
nanahira's avatar
nanahira committed
2178
    client.vpass = vpass;
2179
    client.name_vpass = vpass ? name + "$" + vpass : name;
2180
    if (!settings.modules.i18n.auto_pick || client.is_local) {
mercury233's avatar
mercury233 committed
2181 2182 2183 2184
      client.lang = settings.modules.i18n["default"];
    } else {
      geo = geoip.lookup(client.ip);
      if (!geo) {
mercury233's avatar
mercury233 committed
2185
        log.warn("fail to locate ip", client.name, client.ip);
mercury233's avatar
mercury233 committed
2186 2187 2188 2189 2190 2191 2192 2193
        client.lang = settings.modules.i18n.fallback;
      } else {
        if (lang = settings.modules.i18n.map[geo.country]) {
          client.lang = lang;
        } else {
          client.lang = settings.modules.i18n.fallback;
        }
      }
mercury233's avatar
mercury233 committed
2194
    }
2195
    return false;
神楽坂玲奈's avatar
init  
神楽坂玲奈 committed
2196 2197
  });

nanahira's avatar
nanahira committed
2198
  ygopro.ctos_follow('JOIN_GAME', false, function(buffer, info, client, server, datas) {
nanahira's avatar
nanahira committed
2199
    var buffer_handle_callback, check_buffer_indentity, len2, len3, m, match_permit_callback, n, name, pre_room, ref2, ref3, replay_id, room;
mercury233's avatar
mercury233 committed
2200
    info.pass = info.pass.trim();
nanahira's avatar
nanahira committed
2201 2202
    client.pass = info.pass;
    if (CLIENT_is_able_to_reconnect(client) || CLIENT_is_able_to_kick_reconnect(client)) {
nanahira's avatar
nanahira committed
2203 2204 2205
      CLIENT_pre_reconnect(client);
      return;
    } else if (settings.modules.stop) {
mercury233's avatar
mercury233 committed
2206
      ygopro.stoc_die(client, settings.modules.stop);
nanahira's avatar
nanahira committed
2207 2208
    } else if (info.pass === "Marshtomp" || info.pass === "the Big Brother") {
      ygopro.stoc_die(client, "${bad_user_name}");
mercury233's avatar
mercury233 committed
2209
    } else if (info.pass.toUpperCase() === "R" && settings.modules.cloud_replay.enabled) {
mercury233's avatar
mercury233 committed
2210
      ygopro.stoc_send_chat(client, "${cloud_replay_hint}", ygopro.constants.COLORS.BABYBLUE);
mercury233's avatar
mercury233 committed
2211
      redisdb.lrange(client.ip + ":replays", 0, 2, function(err, result) {
mercury233's avatar
mercury233 committed
2212 2213 2214
        _.each(result, function(replay_id, id) {
          redisdb.hgetall("replay:" + replay_id, function(err, replay) {
            if (err || !replay) {
mercury233's avatar
mercury233 committed
2215 2216 2217
              if (err) {
                log.info("cloud replay getall error: " + err);
              }
mercury233's avatar
mercury233 committed
2218 2219 2220
              return;
            }
            ygopro.stoc_send_chat(client, "<" + (id - 0 + 1) + "> R#" + replay_id + " " + replay.player_names + " " + replay.date_time, ygopro.constants.COLORS.BABYBLUE);
mercury233's avatar
mercury233 committed
2221
          });
mercury233's avatar
mercury233 committed
2222 2223 2224 2225 2226
        });
      });
      setTimeout((function() {
        ygopro.stoc_send(client, 'ERROR_MSG', {
          msg: 1,
mercury233's avatar
mercury233 committed
2227
          code: 9
mercury233's avatar
mercury233 committed
2228
        });
nanahira's avatar
nanahira committed
2229
        CLIENT_kick(client);
mercury233's avatar
mercury233 committed
2230
      }), 500);
mercury233's avatar
mercury233 committed
2231
    } else if (info.pass.slice(0, 2).toUpperCase() === "R#" && settings.modules.cloud_replay.enabled) {
mercury233's avatar
mercury233 committed
2232
      replay_id = info.pass.split("#")[1];
mercury233's avatar
fix  
mercury233 committed
2233
      if (replay_id > 0 && replay_id <= 9) {
mercury233's avatar
mercury233 committed
2234
        redisdb.lindex(client.ip + ":replays", replay_id - 1, function(err, replay_id) {
mercury233's avatar
mercury233 committed
2235
          if (err || !replay_id) {
mercury233's avatar
mercury233 committed
2236 2237 2238
            if (err) {
              log.info("cloud replay replayid error: " + err);
            }
mercury233's avatar
mercury233 committed
2239
            ygopro.stoc_die(client, "${cloud_replay_no}");
mercury233's avatar
mercury233 committed
2240 2241 2242 2243
            return;
          }
          redisdb.hgetall("replay:" + replay_id, client.open_cloud_replay);
        });
mercury233's avatar
mercury233 committed
2244 2245 2246
      } else if (replay_id) {
        redisdb.hgetall("replay:" + replay_id, client.open_cloud_replay);
      } else {
mercury233's avatar
mercury233 committed
2247
        ygopro.stoc_die(client, "${cloud_replay_no}");
mercury233's avatar
mercury233 committed
2248
      }
mercury233's avatar
mercury233 committed
2249
    } else if (info.pass.toUpperCase() === "W" && settings.modules.cloud_replay.enabled) {
mercury233's avatar
mercury233 committed
2250 2251
      replay_id = Cloud_replay_ids[Math.floor(Math.random() * Cloud_replay_ids.length)];
      redisdb.hgetall("replay:" + replay_id, client.open_cloud_replay);
mercury233's avatar
mercury233 committed
2252
    } else if (info.version !== settings.version) {
mercury233's avatar
mercury233 committed
2253
      ygopro.stoc_send_chat(client, settings.modules.update, ygopro.constants.COLORS.RED);
mercury233's avatar
fix  
mercury233 committed
2254 2255 2256 2257
      ygopro.stoc_send(client, 'ERROR_MSG', {
        msg: 4,
        code: settings.version
      });
nanahira's avatar
nanahira committed
2258
      CLIENT_kick(client);
nanahira's avatar
nanahira committed
2259
    } else if (!info.pass.length && !settings.modules.random_duel.enabled && !settings.modules.windbot.enabled && !settings.modules.challonge.enabled) {
mercury233's avatar
mercury233 committed
2260
      ygopro.stoc_die(client, "${blank_room_name}");
mercury233's avatar
fix  
mercury233 committed
2261
    } else if (info.pass.length && settings.modules.mycard.enabled && info.pass.slice(0, 3) !== 'AI#') {
mercury233's avatar
mercury233 committed
2262
      ygopro.stoc_send_chat(client, '${loading_user_info}', ygopro.constants.COLORS.BABYBLUE);
神楽坂玲奈's avatar
fix  
神楽坂玲奈 committed
2263
      if (info.pass.length <= 8) {
mercury233's avatar
mercury233 committed
2264
        ygopro.stoc_die(client, '${invalid_password_length}');
神楽坂玲奈's avatar
fix  
神楽坂玲奈 committed
2265 2266
        return;
      }
nanahira's avatar
nanahira committed
2267
      buffer = Buffer.from(info.pass.slice(0, 8), 'base64');
神楽坂玲奈's avatar
fix  
神楽坂玲奈 committed
2268
      if (buffer.length !== 6) {
mercury233's avatar
mercury233 committed
2269
        ygopro.stoc_die(client, '${invalid_password_payload}');
神楽坂玲奈's avatar
fix  
神楽坂玲奈 committed
2270 2271
        return;
      }
nanahira's avatar
nanahira committed
2272
      check_buffer_indentity = function(buf) {
nanahira's avatar
nanahira committed
2273
        var checksum, i, m, ref2;
神楽坂玲奈's avatar
fix  
神楽坂玲奈 committed
2274
        checksum = 0;
nanahira's avatar
nanahira committed
2275
        for (i = m = 0, ref2 = buf.length; 0 <= ref2 ? m < ref2 : m > ref2; i = 0 <= ref2 ? ++m : --m) {
神楽坂玲奈's avatar
fix  
神楽坂玲奈 committed
2276
          checksum += buf.readUInt8(i);
2277
        }
神楽坂玲奈's avatar
fix  
神楽坂玲奈 committed
2278 2279
        return (checksum & 0xFF) === 0;
      };
nanahira's avatar
fix  
nanahira committed
2280
      buffer_handle_callback = function(buffer, decrypted_buffer, match_permit) {
nanahira's avatar
nanahira committed
2281
        var action, len2, len3, m, n, name, opt1, opt2, opt3, options, player, ref2, ref3, room, title;
nanahira's avatar
nanahira committed
2282 2283 2284
        if (client.closed) {
          return;
        }
2285 2286
        action = buffer.readUInt8(1) >> 4;
        if (buffer !== decrypted_buffer && (action === 1 || action === 2 || action === 4)) {
mercury233's avatar
mercury233 committed
2287
          ygopro.stoc_die(client, '${invalid_password_unauthorized}');
2288 2289 2290 2291 2292 2293
          return;
        }
        switch (action) {
          case 1:
          case 2:
            name = crypto.createHash('md5').update(info.pass + client.name).digest('base64').slice(0, 10).replace('+', '-').replace('/', '_');
mercury233's avatar
mercury233 committed
2294
            if (ROOM_find_by_name(name)) {
mercury233's avatar
mercury233 committed
2295
              ygopro.stoc_die(client, '${invalid_password_existed}');
2296 2297 2298
              return;
            }
            opt1 = buffer.readUInt8(2);
神楽坂玲奈's avatar
fix  
神楽坂玲奈 committed
2299
            opt2 = buffer.readUInt16LE(3);
2300 2301 2302 2303 2304 2305 2306 2307 2308 2309 2310 2311 2312
            opt3 = buffer.readUInt8(5);
            options = {
              lflist: 0,
              time_limit: 180,
              rule: (opt1 >> 5) & 3,
              mode: (opt1 >> 3) & 3,
              enable_priority: !!((opt1 >> 2) & 1),
              no_check_deck: !!((opt1 >> 1) & 1),
              no_shuffle_deck: !!(opt1 & 1),
              start_lp: opt2,
              start_hand: opt3 >> 4,
              draw_count: opt3 & 0xF
            };
mercury233's avatar
mercury233 committed
2313
            options.lflist = _.findIndex(lflists, function(list) {
神楽坂玲奈's avatar
fix  
神楽坂玲奈 committed
2314
              return ((options.rule === 1) === list.tcg) && list.date.isBefore();
神楽坂玲奈's avatar
神楽坂玲奈 committed
2315
            });
2316
            room = new Room(name, options);
nanahira's avatar
nanahira committed
2317 2318 2319 2320
            if (room) {
              room.title = info.pass.slice(8).replace(String.fromCharCode(0xFEFF), ' ');
              room["private"] = action === 2;
            }
2321 2322 2323
            break;
          case 3:
            name = info.pass.slice(8);
mercury233's avatar
mercury233 committed
2324
            room = ROOM_find_by_name(name);
2325
            if (!room) {
mercury233's avatar
mercury233 committed
2326
              ygopro.stoc_die(client, '${invalid_password_not_found}');
2327 2328 2329 2330
              return;
            }
            break;
          case 4:
nanahira's avatar
move  
nanahira committed
2331 2332 2333 2334
            if (match_permit && !match_permit.permit) {
              ygopro.stoc_die(client, '${invalid_password_unauthorized}');
              return;
            }
mercury233's avatar
mercury233 committed
2335
            room = ROOM_find_or_create_by_name('M#' + info.pass.slice(8));
nanahira's avatar
nanahira committed
2336
            if (room) {
nanahira's avatar
nanahira committed
2337 2338 2339 2340 2341 2342 2343 2344 2345
              ref2 = room.get_playing_player();
              for (m = 0, len2 = ref2.length; m < len2; m++) {
                player = ref2[m];
                if (!(player && player.name === client.name)) {
                  continue;
                }
                ygopro.stoc_die(client, '${invalid_password_unauthorized}');
                return;
              }
nanahira's avatar
nanahira committed
2346 2347 2348 2349 2350 2351
              room["private"] = true;
              room.arena = settings.modules.arena_mode.mode;
              if (room.arena === "athletic") {
                room.max_player = 2;
                room.welcome = "${athletic_arena_tip}";
              }
2352
            }
2353
            break;
mercury233's avatar
mercury233 committed
2354 2355 2356 2357 2358 2359 2360 2361
          case 5:
            title = info.pass.slice(8).replace(String.fromCharCode(0xFEFF), ' ');
            room = ROOM_find_by_title(title);
            if (!room) {
              ygopro.stoc_die(client, '${invalid_password_not_found}');
              return;
            }
            break;
2362
          default:
mercury233's avatar
mercury233 committed
2363
            ygopro.stoc_die(client, '${invalid_password_action}');
2364 2365
            return;
        }
mercury233's avatar
mercury233 committed
2366
        if (!room) {
mercury233's avatar
mercury233 committed
2367
          ygopro.stoc_die(client, "${server_full}");
mercury233's avatar
mercury233 committed
2368
        } else if (room.error) {
mercury233's avatar
mercury233 committed
2369
          ygopro.stoc_die(client, room.error);
mercury233's avatar
mercury233 committed
2370
        } else if (room.started) {
nanahira's avatar
nanahira committed
2371
          if (settings.modules.cloud_replay.enable_halfway_watch && !room.hostinfo.no_watch) {
mercury233's avatar
mercury233 committed
2372 2373 2374 2375 2376 2377
            client.setTimeout(300000);
            client.rid = _.indexOf(ROOM_all, room);
            client.is_post_watcher = true;
            ygopro.stoc_send_chat_to_room(room, client.name + " ${watch_join}");
            room.watchers.push(client);
            ygopro.stoc_send_chat(client, "${watch_watching}", ygopro.constants.COLORS.BABYBLUE);
nanahira's avatar
nanahira committed
2378 2379 2380
            ref3 = room.watcher_buffers;
            for (n = 0, len3 = ref3.length; n < len3; n++) {
              buffer = ref3[n];
mercury233's avatar
mercury233 committed
2381 2382 2383 2384 2385
              client.write(buffer);
            }
          } else {
            ygopro.stoc_die(client, "${watch_denied}");
          }
nanahira's avatar
nanahira committed
2386
        } else if (room.hostinfo.no_watch && room.players.length >= (room.hostinfo.mode === 2 ? 4 : 2)) {
nanahira's avatar
fix  
nanahira committed
2387
          ygopro.stoc_die(client, "${watch_denied_room}");
mercury233's avatar
mercury233 committed
2388
        } else {
mercury233's avatar
mercury233 committed
2389
          client.setTimeout(300000);
2390 2391
          client.rid = _.indexOf(ROOM_all, room);
          room.connect(client);
mercury233's avatar
mercury233 committed
2392
        }
神楽坂玲奈's avatar
fix  
神楽坂玲奈 committed
2393
      };
nanahira's avatar
nanahira committed
2394 2395 2396 2397
      match_permit_callback = function(buffer, match_permit) {
        var decrypted_buffer, i, id, len2, m, ref2, secret;
        if (client.closed) {
          return;
神楽坂玲奈's avatar
fix  
神楽坂玲奈 committed
2398
        }
nanahira's avatar
nanahira committed
2399 2400
        if (id = users_cache[client.name]) {
          secret = id % 65535 + 1;
nanahira's avatar
nanahira committed
2401
          decrypted_buffer = Buffer.allocUnsafe(6);
nanahira's avatar
nanahira committed
2402 2403 2404
          ref2 = [0, 2, 4];
          for (m = 0, len2 = ref2.length; m < len2; m++) {
            i = ref2[m];
神楽坂玲奈's avatar
fix  
神楽坂玲奈 committed
2405 2406
            decrypted_buffer.writeUInt16LE(buffer.readUInt16LE(i) ^ secret, i);
          }
nanahira's avatar
nanahira committed
2407
          if (check_buffer_indentity(decrypted_buffer)) {
nanahira's avatar
fix  
nanahira committed
2408
            return buffer_handle_callback(decrypted_buffer, decrypted_buffer, match_permit);
神楽坂玲奈's avatar
fix  
神楽坂玲奈 committed
2409 2410
          }
        }
nanahira's avatar
nanahira committed
2411 2412 2413 2414 2415 2416 2417 2418 2419 2420 2421 2422 2423 2424 2425 2426 2427 2428 2429 2430 2431 2432 2433 2434 2435 2436 2437 2438
        request({
          baseUrl: settings.modules.mycard.auth_base_url,
          url: '/users/' + encodeURIComponent(client.name) + '.json',
          qs: {
            api_key: settings.modules.mycard.auth_key,
            api_username: client.name,
            skip_track_visit: true
          },
          json: true
        }, function(error, response, body) {
          var len3, n, ref3;
          if (body && body.user) {
            users_cache[client.name] = body.user.id;
            secret = body.user.id % 65535 + 1;
            decrypted_buffer = Buffer.allocUnsafe(6);
            ref3 = [0, 2, 4];
            for (n = 0, len3 = ref3.length; n < len3; n++) {
              i = ref3[n];
              decrypted_buffer.writeUInt16LE(buffer.readUInt16LE(i) ^ secret, i);
            }
            if (check_buffer_indentity(decrypted_buffer)) {
              buffer = decrypted_buffer;
            }
          }
          if (!check_buffer_indentity(buffer)) {
            ygopro.stoc_die(client, '${invalid_password_checksum}');
            return;
          }
nanahira's avatar
fix  
nanahira committed
2439
          return buffer_handle_callback(buffer, decrypted_buffer, match_permit);
nanahira's avatar
nanahira committed
2440 2441 2442 2443 2444 2445 2446 2447
        });
      };
      if (settings.modules.arena_mode.check_permit) {
        request({
          url: settings.modules.arena_mode.check_permit,
          json: true,
          qs: {
            username: client.name,
2448 2449
            password: info.pass,
            arena: settings.modules.arena_mode.mode
nanahira's avatar
nanahira committed
2450 2451 2452 2453 2454 2455 2456 2457
          }
        }, function(error, response, body) {
          if (client.closed) {
            return;
          }
          if (!error && body) {
            match_permit_callback(buffer, body);
          } else {
nanahira's avatar
log  
nanahira committed
2458
            log.warn("Match permit request error", error);
nanahira's avatar
nanahira committed
2459 2460 2461 2462 2463 2464
            match_permit_callback(buffer, null);
          }
        });
      } else {
        match_permit_callback(buffer, null);
      }
nanahira's avatar
nanahira committed
2465 2466
    } else if (settings.modules.challonge.enabled) {
      pre_room = ROOM_find_by_name(info.pass);
nanahira's avatar
nanahira committed
2467
      if (pre_room && pre_room.started && settings.modules.cloud_replay.enable_halfway_watch && !pre_room.hostinfo.no_watch) {
nanahira's avatar
nanahira committed
2468 2469 2470 2471 2472 2473 2474
        room = pre_room;
        client.setTimeout(300000);
        client.rid = _.indexOf(ROOM_all, room);
        client.is_post_watcher = true;
        ygopro.stoc_send_chat_to_room(room, client.name + " ${watch_join}");
        room.watchers.push(client);
        ygopro.stoc_send_chat(client, "${watch_watching}", ygopro.constants.COLORS.BABYBLUE);
nanahira's avatar
nanahira committed
2475 2476 2477
        ref2 = room.watcher_buffers;
        for (m = 0, len2 = ref2.length; m < len2; m++) {
          buffer = ref2[m];
nanahira's avatar
nanahira committed
2478 2479 2480 2481
          client.write(buffer);
        }
      } else {
        ygopro.stoc_send_chat(client, '${loading_user_info}', ygopro.constants.COLORS.BABYBLUE);
nanahira's avatar
fix  
nanahira committed
2482
        client.setTimeout(300000);
nanahira's avatar
nanahira committed
2483
        challonge.participants._index({
2484
          id: settings.modules.challonge.tournament_id,
nanahira's avatar
nanahira committed
2485 2486
          callback: function(err, data) {
            var found, k, user;
nanahira's avatar
nanahira committed
2487 2488 2489
            if (client.closed) {
              return;
            }
nanahira's avatar
nanahira committed
2490 2491 2492 2493 2494 2495 2496 2497 2498 2499
            if (err || !data) {
              if (err) {
                log.warn("Failed loading Challonge user info", err);
              }
              ygopro.stoc_die(client, '${challonge_match_load_failed}');
              return;
            }
            found = false;
            for (k in data) {
              user = data[k];
nanahira's avatar
nanahira committed
2500
              if (user.participant && user.participant.name && _.endsWith(user.participant.name, client.name)) {
nanahira's avatar
nanahira committed
2501 2502 2503 2504 2505 2506 2507 2508 2509
                found = user.participant;
                break;
              }
            }
            if (!found) {
              ygopro.stoc_die(client, '${challonge_user_not_found}');
              return;
            }
            client.challonge_info = found;
nanahira's avatar
nanahira committed
2510
            challonge.matches._index({
2511
              id: settings.modules.challonge.tournament_id,
nanahira's avatar
nanahira committed
2512
              callback: function(err, data) {
nanahira's avatar
nanahira committed
2513
                var len3, len4, match, n, o, player, ref3, ref4;
nanahira's avatar
nanahira committed
2514 2515 2516
                if (client.closed) {
                  return;
                }
nanahira's avatar
nanahira committed
2517 2518 2519 2520 2521 2522 2523 2524 2525 2526
                if (err || !data) {
                  if (err) {
                    log.warn("Failed loading Challonge match info", err);
                  }
                  ygopro.stoc_die(client, '${challonge_match_load_failed}');
                  return;
                }
                found = false;
                for (k in data) {
                  match = data[k];
nanahira's avatar
nanahira committed
2527
                  if (match && match.match && !match.match.winnerId && match.match.state !== "complete" && match.match.player1Id && match.match.player2Id && (match.match.player1Id === client.challonge_info.id || match.match.player2Id === client.challonge_info.id)) {
nanahira's avatar
nanahira committed
2528 2529 2530 2531 2532 2533 2534 2535 2536 2537 2538 2539 2540 2541 2542 2543 2544 2545
                    found = match.match;
                    break;
                  }
                }
                if (!found) {
                  ygopro.stoc_die(client, '${challonge_match_not_found}');
                  return;
                }
                room = ROOM_find_or_create_by_name('M#' + found.id);
                if (room) {
                  room.challonge_info = found;
                  room.welcome = "${challonge_match_created}";
                }
                if (!room) {
                  ygopro.stoc_die(client, "${server_full}");
                } else if (room.error) {
                  ygopro.stoc_die(client, room.error);
                } else if (room.started) {
nanahira's avatar
nanahira committed
2546
                  if (settings.modules.cloud_replay.enable_halfway_watch && !room.hostinfo.no_watch) {
nanahira's avatar
nanahira committed
2547 2548 2549 2550 2551
                    client.rid = _.indexOf(ROOM_all, room);
                    client.is_post_watcher = true;
                    ygopro.stoc_send_chat_to_room(room, client.name + " ${watch_join}");
                    room.watchers.push(client);
                    ygopro.stoc_send_chat(client, "${watch_watching}", ygopro.constants.COLORS.BABYBLUE);
nanahira's avatar
nanahira committed
2552 2553 2554
                    ref3 = room.watcher_buffers;
                    for (n = 0, len3 = ref3.length; n < len3; n++) {
                      buffer = ref3[n];
nanahira's avatar
nanahira committed
2555 2556 2557 2558 2559
                      client.write(buffer);
                    }
                  } else {
                    ygopro.stoc_die(client, "${watch_denied}");
                  }
nanahira's avatar
nanahira committed
2560
                } else if (room.hostinfo.no_watch && room.players.length >= (room.hostinfo.mode === 2 ? 4 : 2)) {
nanahira's avatar
fix  
nanahira committed
2561
                  ygopro.stoc_die(client, "${watch_denied_room}");
nanahira's avatar
nanahira committed
2562
                } else {
nanahira's avatar
nanahira committed
2563 2564 2565
                  ref4 = room.get_playing_player();
                  for (o = 0, len4 = ref4.length; o < len4; o++) {
                    player = ref4[o];
nanahira's avatar
nanahira committed
2566
                    if (!(player && player !== client && player.challonge_info.id === client.challonge_info.id)) {
nanahira's avatar
nanahira committed
2567 2568 2569 2570 2571 2572 2573 2574 2575 2576 2577 2578 2579
                      continue;
                    }
                    ygopro.stoc_die(client, "${challonge_player_already_in}");
                    return;
                  }
                  client.rid = _.indexOf(ROOM_all, room);
                  room.connect(client);
                }
              }
            });
          }
        });
      }
mercury233's avatar
mercury233 committed
2580
    } else if (!client.name || client.name === "") {
mercury233's avatar
mercury233 committed
2581
      ygopro.stoc_die(client, "${bad_user_name}");
mercury233's avatar
mercury233 committed
2582 2583
    } else if (ROOM_connected_ip[client.ip] > 5) {
      log.warn("MULTI LOGIN", client.name, client.ip);
mercury233's avatar
mercury233 committed
2584
      ygopro.stoc_die(client, "${too_much_connection}" + client.ip);
mercury233's avatar
mercury233 committed
2585
    } else if (_.indexOf(settings.ban.banned_user, client.name) > -1) {
mercury233's avatar
mercury233 committed
2586
      settings.ban.banned_ip.push(client.ip);
mercury233's avatar
mercury233 committed
2587
      setting_save(settings);
mercury233's avatar
mercury233 committed
2588
      log.warn("BANNED USER LOGIN", client.name, client.ip);
mercury233's avatar
mercury233 committed
2589
      ygopro.stoc_die(client, "${banned_user_login}");
mercury233's avatar
mercury233 committed
2590 2591
    } else if (_.indexOf(settings.ban.banned_ip, client.ip) > -1) {
      log.warn("BANNED IP LOGIN", client.name, client.ip);
mercury233's avatar
mercury233 committed
2592
      ygopro.stoc_die(client, "${banned_ip_login}");
mercury233's avatar
mercury233 committed
2593
    } else if (_.any(badwords.level3, function(badword) {
mercury233's avatar
mercury233 committed
2594
      var regexp;
mercury233's avatar
fix  
mercury233 committed
2595
      regexp = new RegExp(badword, 'i');
mercury233's avatar
mercury233 committed
2596 2597
      return name.match(regexp);
    }, name = client.name)) {
mercury233's avatar
mercury233 committed
2598
      log.warn("BAD NAME LEVEL 3", client.name, client.ip);
mercury233's avatar
mercury233 committed
2599
      ygopro.stoc_die(client, "${bad_name_level3}");
mercury233's avatar
mercury233 committed
2600
    } else if (_.any(badwords.level2, function(badword) {
mercury233's avatar
mercury233 committed
2601
      var regexp;
mercury233's avatar
fix  
mercury233 committed
2602
      regexp = new RegExp(badword, 'i');
mercury233's avatar
mercury233 committed
2603 2604
      return name.match(regexp);
    }, name = client.name)) {
mercury233's avatar
mercury233 committed
2605
      log.warn("BAD NAME LEVEL 2", client.name, client.ip);
mercury233's avatar
mercury233 committed
2606
      ygopro.stoc_die(client, "${bad_name_level2}");
mercury233's avatar
mercury233 committed
2607
    } else if (_.any(badwords.level1, function(badword) {
mercury233's avatar
mercury233 committed
2608
      var regexp;
mercury233's avatar
fix  
mercury233 committed
2609
      regexp = new RegExp(badword, 'i');
mercury233's avatar
mercury233 committed
2610 2611
      return name.match(regexp);
    }, name = client.name)) {
mercury233's avatar
mercury233 committed
2612
      log.warn("BAD NAME LEVEL 1", client.name, client.ip);
mercury233's avatar
mercury233 committed
2613
      ygopro.stoc_die(client, "${bad_name_level1}");
mercury233's avatar
mercury233 committed
2614
    } else if (info.pass.length && !ROOM_validate(info.pass)) {
mercury233's avatar
mercury233 committed
2615
      ygopro.stoc_die(client, "${invalid_password_room}");
神楽坂玲奈's avatar
init  
神楽坂玲奈 committed
2616
    } else {
mercury233's avatar
mercury233 committed
2617
      room = ROOM_find_or_create_by_name(info.pass, client.ip);
mercury233's avatar
mercury233 committed
2618
      if (!room) {
mercury233's avatar
mercury233 committed
2619
        ygopro.stoc_die(client, "${server_full}");
mercury233's avatar
mercury233 committed
2620
      } else if (room.error) {
mercury233's avatar
mercury233 committed
2621
        ygopro.stoc_die(client, room.error);
mercury233's avatar
mercury233 committed
2622
      } else if (room.started) {
nanahira's avatar
nanahira committed
2623
        if (settings.modules.cloud_replay.enable_halfway_watch && !room.hostinfo.no_watch) {
mercury233's avatar
mercury233 committed
2624
          client.setTimeout(300000);
2625
          client.rid = _.indexOf(ROOM_all, room);
神楽坂玲奈's avatar
11.7  
神楽坂玲奈 committed
2626
          client.is_post_watcher = true;
mercury233's avatar
mercury233 committed
2627
          ygopro.stoc_send_chat_to_room(room, client.name + " ${watch_join}");
2628
          room.watchers.push(client);
mercury233's avatar
mercury233 committed
2629
          ygopro.stoc_send_chat(client, "${watch_watching}", ygopro.constants.COLORS.BABYBLUE);
nanahira's avatar
nanahira committed
2630 2631 2632
          ref3 = room.watcher_buffers;
          for (n = 0, len3 = ref3.length; n < len3; n++) {
            buffer = ref3[n];
神楽坂玲奈's avatar
11.7  
神楽坂玲奈 committed
2633 2634 2635
            client.write(buffer);
          }
        } else {
mercury233's avatar
mercury233 committed
2636
          ygopro.stoc_die(client, "${watch_denied}");
神楽坂玲奈's avatar
11.7  
神楽坂玲奈 committed
2637
        }
nanahira's avatar
nanahira committed
2638
      } else if (room.hostinfo.no_watch && room.players.length >= (room.hostinfo.mode === 2 ? 4 : 2)) {
nanahira's avatar
nanahira committed
2639
        ygopro.stoc_die(client, "${watch_denied_room}");
神楽坂玲奈's avatar
11.7  
神楽坂玲奈 committed
2640
      } else {
mercury233's avatar
mercury233 committed
2641
        client.setTimeout(300000);
2642 2643
        client.rid = _.indexOf(ROOM_all, room);
        room.connect(client);
神楽坂玲奈's avatar
11.7  
神楽坂玲奈 committed
2644
      }
神楽坂玲奈's avatar
init  
神楽坂玲奈 committed
2645 2646 2647
    }
  });

nanahira's avatar
nanahira committed
2648
  ygopro.stoc_follow('JOIN_GAME', false, function(buffer, info, client, server, datas) {
2649
    var len2, m, player, recorder, ref2, room, watcher;
2650
    room = ROOM_all[client.rid];
nanahira's avatar
nanahira committed
2651
    if (!(room && !client.reconnecting)) {
2652 2653
      return;
    }
2654 2655 2656
    if (!room.join_game_buffer) {
      room.join_game_buffer = buffer;
    }
神楽坂玲奈's avatar
11.7  
神楽坂玲奈 committed
2657
    if (settings.modules.welcome) {
mercury233's avatar
mercury233 committed
2658
      ygopro.stoc_send_chat(client, settings.modules.welcome, ygopro.constants.COLORS.GREEN);
神楽坂玲奈's avatar
11.7  
神楽坂玲奈 committed
2659
    }
2660 2661
    if (room.welcome) {
      ygopro.stoc_send_chat(client, room.welcome, ygopro.constants.COLORS.BABYBLUE);
mercury233's avatar
add  
mercury233 committed
2662
    }
2663
    if (settings.modules.arena_mode.enabled && !client.is_local) {
mercury233's avatar
mercury233 committed
2664 2665 2666 2667
      request({
        url: settings.modules.arena_mode.get_score + encodeURIComponent(client.name),
        json: true
      }, function(error, response, body) {
mercury233's avatar
merge  
mercury233 committed
2668
        var rank_txt;
mercury233's avatar
merge  
mercury233 committed
2669 2670 2671 2672
        if (error) {
          log.warn('LOAD SCORE ERROR', client.name, error);
        } else if (!body || _.isString(body)) {
          log.warn('LOAD SCORE FAIL', client.name, response.statusCode, response.statusMessage, body);
mercury233's avatar
mercury233 committed
2673
        } else {
mercury233's avatar
mercury233 committed
2674 2675
          rank_txt = body.arena_rank > 0 ? "${rank_arena}" + body.arena_rank : "${rank_blank}";
          ygopro.stoc_send_chat(client, client.name + "${exp_value_part1}" + body.exp + "${exp_value_part2}${exp_value_part3}" + (Math.round(body.pt)) + rank_txt + "${exp_value_part4}", ygopro.constants.COLORS.BABYBLUE);
mercury233's avatar
mercury233 committed
2676 2677 2678
        }
      });
    }
2679 2680 2681 2682 2683 2684 2685 2686 2687 2688
    if (settings.modules.random_duel.record_match_scores && room.random_type === 'M') {
      ygopro.stoc_send_chat_to_room(room, ROOM_player_get_score(client), ygopro.constants.COLORS.GREEN);
      ref2 = room.players;
      for (m = 0, len2 = ref2.length; m < len2; m++) {
        player = ref2[m];
        if (player.pos !== 7 && player !== client) {
          ygopro.stoc_send_chat(client, ROOM_player_get_score(player), ygopro.constants.COLORS.GREEN);
        }
      }
    }
2689 2690
    if (!room.recorder) {
      room.recorder = recorder = net.connect(room.port, function() {
mercury233's avatar
mercury233 committed
2691 2692 2693 2694 2695
        ygopro.ctos_send(recorder, 'PLAYER_INFO', {
          name: "Marshtomp"
        });
        ygopro.ctos_send(recorder, 'JOIN_GAME', {
          version: settings.version,
mercury233's avatar
mercury233 committed
2696
          pass: "Marshtomp"
mercury233's avatar
mercury233 committed
2697
        });
mercury233's avatar
mercury233 committed
2698
        ygopro.ctos_send(recorder, 'HS_TOOBSERVER');
mercury233's avatar
mercury233 committed
2699 2700
      });
      recorder.on('data', function(data) {
2701
        room = ROOM_all[client.rid];
mercury233's avatar
mercury233 committed
2702
        if (!(room && settings.modules.cloud_replay.enabled)) {
mercury233's avatar
mercury233 committed
2703 2704
          return;
        }
mercury233's avatar
mercury233 committed
2705
        room.recorder_buffers.push(data);
mercury233's avatar
mercury233 committed
2706 2707 2708
      });
      recorder.on('error', function(error) {});
    }
nanahira's avatar
nanahira committed
2709
    if (settings.modules.cloud_replay.enable_halfway_watch && !room.watcher && !room.hostinfo.no_watch) {
2710
      room.watcher = watcher = settings.modules.test_mode.watch_public_hand ? room.recorder : net.connect(room.port, function() {
神楽坂玲奈's avatar
11.7  
神楽坂玲奈 committed
2711 2712 2713 2714 2715
        ygopro.ctos_send(watcher, 'PLAYER_INFO', {
          name: "the Big Brother"
        });
        ygopro.ctos_send(watcher, 'JOIN_GAME', {
          version: settings.version,
mercury233's avatar
mercury233 committed
2716
          pass: "the Big Brother"
神楽坂玲奈's avatar
11.7  
神楽坂玲奈 committed
2717
        });
mercury233's avatar
mercury233 committed
2718
        ygopro.ctos_send(watcher, 'HS_TOOBSERVER');
神楽坂玲奈's avatar
11.7  
神楽坂玲奈 committed
2719
      });
mercury233's avatar
fix  
mercury233 committed
2720
      watcher.on('data', function(data) {
2721
        var len3, n, ref3, w;
2722 2723
        room = ROOM_all[client.rid];
        if (!room) {
2724 2725
          return;
        }
2726
        room.watcher_buffers.push(data);
2727 2728 2729
        ref3 = room.watchers;
        for (n = 0, len3 = ref3.length; n < len3; n++) {
          w = ref3[n];
神楽坂玲奈's avatar
12.2  
神楽坂玲奈 committed
2730
          if (w) {
mercury233's avatar
test3  
mercury233 committed
2731
            w.write(data);
神楽坂玲奈's avatar
12.2  
神楽坂玲奈 committed
2732
          }
神楽坂玲奈's avatar
11.7  
神楽坂玲奈 committed
2733 2734
        }
      });
mercury233's avatar
test3  
mercury233 committed
2735
      watcher.on('error', function(error) {});
神楽坂玲奈's avatar
神楽坂玲奈 committed
2736
    }
神楽坂玲奈's avatar
tip  
神楽坂玲奈 committed
2737
  });
神楽坂玲奈's avatar
神楽坂玲奈 committed
2738

mercury233's avatar
mercury233 committed
2739
  load_dialogues = function() {
神楽坂玲奈's avatar
11.7  
神楽坂玲奈 committed
2740
    request({
mercury233's avatar
mercury233 committed
2741
      url: settings.modules.dialogues.get,
神楽坂玲奈's avatar
11.7  
神楽坂玲奈 committed
2742 2743 2744
      json: true
    }, function(error, response, body) {
      if (_.isString(body)) {
mercury233's avatar
test3  
mercury233 committed
2745
        log.warn("dialogues bad json", body);
神楽坂玲奈's avatar
12.2  
神楽坂玲奈 committed
2746
      } else if (error || !body) {
mercury233's avatar
test3  
mercury233 committed
2747
        log.warn('dialogues error', error, response);
神楽坂玲奈's avatar
11.7  
神楽坂玲奈 committed
2748
      } else {
mercury233's avatar
mercury233 committed
2749 2750
        setting_change(dialogues, "dialogues", body);
        log.info("dialogues loaded", _.size(dialogues.dialogues));
神楽坂玲奈's avatar
11.7  
神楽坂玲奈 committed
2751 2752
      }
    });
mercury233's avatar
mercury233 committed
2753 2754
  };

mercury233's avatar
mercury233 committed
2755
  if (settings.modules.dialogues.get) {
mercury233's avatar
mercury233 committed
2756
    load_dialogues();
神楽坂玲奈's avatar
11.7  
神楽坂玲奈 committed
2757 2758
  }

nanahira's avatar
nanahira committed
2759
  ygopro.stoc_follow('GAME_MSG', true, function(buffer, info, client, server, datas) {
nanahira's avatar
nanahira committed
2760
    var card, chain, check, count, cpos, deck_found, found, hint_type, i, id, len2, len3, len4, len5, limbo_found, line, loc, m, max_loop, msg, n, o, oppo_pos, p, phase, player, playertype, pos, ppos, q, reason, ref2, ref3, ref4, ref5, ref6, ref7, room, trigger_location, val, win_pos;
2761
    room = ROOM_all[client.rid];
nanahira's avatar
nanahira committed
2762
    if (!(room && !client.reconnecting)) {
2763 2764
      return;
    }
神楽坂玲奈's avatar
神楽坂玲奈 committed
2765
    msg = buffer.readInt8(0);
nanahira's avatar
nanahira committed
2766 2767 2768 2769 2770 2771 2772 2773 2774 2775
    if (settings.modules.retry_handle.enabled) {
      if (ygopro.constants.MSG[msg] === 'RETRY') {
        if (client.retry_count == null) {
          client.retry_count = 0;
        }
        client.retry_count++;
        log.warn("MSG_RETRY detected", client.name, client.ip, msg, client.retry_count);
        if (settings.modules.retry_handle.max_retry_count && client.retry_count >= settings.modules.retry_handle.max_retry_count) {
          ygopro.stoc_send_chat_to_room(room, client.name + "${retry_too_much_room_part1}" + settings.modules.retry_handle.max_retry_count + "${retry_too_much_room_part2}", ygopro.constants.COLORS.BABYBLUE);
          ygopro.stoc_send_chat(client, "${retry_too_much_part1}" + settings.modules.retry_handle.max_retry_count + "${retry_too_much_part2}", ygopro.constants.COLORS.RED);
nanahira's avatar
nanahira committed
2776
          CLIENT_send_replays(client, room);
nanahira's avatar
nanahira committed
2777
          CLIENT_kick(client);
nanahira's avatar
nanahira committed
2778 2779 2780 2781 2782 2783 2784 2785
          return true;
        }
        if (client.last_game_msg) {
          if (settings.modules.retry_handle.max_retry_count) {
            ygopro.stoc_send_chat(client, "${retry_part1}" + client.retry_count + "${retry_part2}" + settings.modules.retry_handle.max_retry_count + "${retry_part3}", ygopro.constants.COLORS.RED);
          } else {
            ygopro.stoc_send_chat(client, "${retry_not_counted}", ygopro.constants.COLORS.BABYBLUE);
          }
nanahira's avatar
nanahira committed
2786 2787 2788
          if (client.last_hint_msg) {
            ygopro.stoc_send(client, 'GAME_MSG', client.last_hint_msg);
          }
nanahira's avatar
nanahira committed
2789 2790 2791 2792 2793
          ygopro.stoc_send(client, 'GAME_MSG', client.last_game_msg);
          return true;
        }
      } else {
        client.last_game_msg = buffer;
nanahira's avatar
nanahira committed
2794
        client.last_game_msg_title = ygopro.constants.MSG[msg];
nanahira's avatar
nanahira committed
2795
      }
nanahira's avatar
nanahira committed
2796 2797 2798
    } else if (ygopro.constants.MSG[msg] !== 'RETRY') {
      client.last_game_msg = buffer;
      client.last_game_msg_title = ygopro.constants.MSG[msg];
nanahira's avatar
nanahira committed
2799
    }
nanahira's avatar
fix  
nanahira committed
2800
    if ((msg >= 10 && msg < 30) || msg === 132 || (msg >= 140 && msg <= 144)) {
2801 2802
      room.waiting_for_player = client;
      room.last_active_time = moment();
2803
    }
神楽坂玲奈's avatar
11.7  
神楽坂玲奈 committed
2804 2805 2806
    if (ygopro.constants.MSG[msg] === 'START') {
      playertype = buffer.readUInt8(1);
      client.is_first = !(playertype & 0xf);
2807
      client.lp = room.hostinfo.start_lp;
nanahira's avatar
nanahira committed
2808 2809 2810
      if (room.hostinfo.mode !== 2) {
        client.card_count = 0;
      }
nanahira's avatar
nanahira committed
2811
      room.selecting_tp = false;
nanahira's avatar
nanahira committed
2812
      if (client.pos === 0) {
2813
        room.turn = 0;
2814
        room.duel_count = room.duel_count + 1;
nanahira's avatar
nanahira committed
2815 2816 2817 2818 2819 2820 2821
        if (room.death && room.duel_count > 1) {
          if (room.death === -1) {
            ygopro.stoc_send_chat_to_room(room, "${death_start_final}", ygopro.constants.COLORS.BABYBLUE);
          } else {
            ygopro.stoc_send_chat_to_room(room, "${death_start_extra}", ygopro.constants.COLORS.BABYBLUE);
          }
        }
nanahira's avatar
fix  
nanahira committed
2822
      }
nanahira's avatar
nanahira committed
2823 2824 2825 2826
      if (settings.modules.retry_handle.enabled) {
        client.retry_count = 0;
        client.last_game_msg = null;
      }
神楽坂玲奈's avatar
11.7  
神楽坂玲奈 committed
2827
    }
nanahira's avatar
nanahira committed
2828 2829
    if (ygopro.constants.MSG[msg] === 'HINT') {
      hint_type = buffer.readUInt8(1);
nanahira's avatar
typo  
nanahira committed
2830
      if (hint_type === 3) {
nanahira's avatar
nanahira committed
2831 2832 2833
        client.last_hint_msg = buffer;
      }
    }
2834
    if (ygopro.constants.MSG[msg] === 'NEW_TURN') {
nanahira's avatar
nanahira committed
2835
      if (client.pos === 0) {
2836
        room.turn = room.turn + 1;
nanahira's avatar
nanahira committed
2837
        if (room.death && room.death !== -2) {
nanahira's avatar
nanahira committed
2838
          if (room.turn >= room.death) {
nanahira's avatar
nanahira committed
2839 2840 2841
            oppo_pos = room.hostinfo.mode === 2 ? 2 : 1;
            if (room.dueling_players[0].lp !== room.dueling_players[oppo_pos].lp && room.turn > 1) {
              win_pos = room.dueling_players[0].lp > room.dueling_players[oppo_pos].lp ? 0 : oppo_pos;
nanahira's avatar
nanahira committed
2842
              ygopro.stoc_send_chat_to_room(room, "${death_finish_part1}" + room.dueling_players[win_pos].name + "${death_finish_part2}", ygopro.constants.COLORS.BABYBLUE);
nanahira's avatar
nanahira committed
2843
              if (room.hostinfo.mode === 2) {
nanahira's avatar
nanahira committed
2844
                room.finished_by_death = true;
nanahira's avatar
nanahira committed
2845 2846
                ygopro.stoc_send(room.dueling_players[oppo_pos - win_pos], 'DUEL_END');
                ygopro.stoc_send(room.dueling_players[oppo_pos - win_pos + 1], 'DUEL_END');
2847
                room.scores[room.dueling_players[oppo_pos - win_pos].name_vpass] = -1;
nanahira's avatar
nanahira committed
2848 2849
                CLIENT_kick(room.dueling_players[oppo_pos - win_pos]);
                CLIENT_kick(room.dueling_players[oppo_pos - win_pos + 1]);
nanahira's avatar
nanahira committed
2850 2851 2852
              } else {
                ygopro.ctos_send(room.dueling_players[oppo_pos - win_pos].server, 'SURRENDER');
              }
nanahira's avatar
nanahira committed
2853
            } else {
nanahira's avatar
nanahira committed
2854
              room.death = -1;
nanahira's avatar
nanahira committed
2855 2856 2857 2858 2859 2860
              ygopro.stoc_send_chat_to_room(room, "${death_remain_final}", ygopro.constants.COLORS.BABYBLUE);
            }
          } else {
            ygopro.stoc_send_chat_to_room(room, "${death_remain_part1}" + (room.death - room.turn) + "${death_remain_part2}", ygopro.constants.COLORS.BABYBLUE);
          }
        }
2861 2862 2863 2864 2865
      }
      if (client.surrend_confirm) {
        client.surrend_confirm = false;
        ygopro.stoc_send_chat(client, "${surrender_canceled}", ygopro.constants.COLORS.BABYBLUE);
      }
mercury233's avatar
mercury233 committed
2866
    }
nanahira's avatar
nanahira committed
2867 2868 2869
    if (ygopro.constants.MSG[msg] === 'NEW_PHASE') {
      phase = buffer.readInt16LE(1);
      oppo_pos = room.hostinfo.mode === 2 ? 2 : 1;
nanahira's avatar
fix  
nanahira committed
2870 2871 2872 2873 2874
      if (client.pos === 0 && room.death === -2 && !(phase === 0x1 && room.turn < 2)) {
        if (room.dueling_players[0].lp !== room.dueling_players[oppo_pos].lp) {
          win_pos = room.dueling_players[0].lp > room.dueling_players[oppo_pos].lp ? 0 : oppo_pos;
          ygopro.stoc_send_chat_to_room(room, "${death_finish_part1}" + room.dueling_players[win_pos].name + "${death_finish_part2}", ygopro.constants.COLORS.BABYBLUE);
          if (room.hostinfo.mode === 2) {
nanahira's avatar
nanahira committed
2875
            room.finished_by_death = true;
nanahira's avatar
fix  
nanahira committed
2876 2877
            ygopro.stoc_send(room.dueling_players[oppo_pos - win_pos], 'DUEL_END');
            ygopro.stoc_send(room.dueling_players[oppo_pos - win_pos + 1], 'DUEL_END');
2878
            room.scores[room.dueling_players[oppo_pos - win_pos].name_vpass] = -1;
nanahira's avatar
nanahira committed
2879 2880
            CLIENT_kick(room.dueling_players[oppo_pos - win_pos]);
            CLIENT_kick(room.dueling_players[oppo_pos - win_pos + 1]);
nanahira's avatar
fix  
nanahira committed
2881 2882 2883
          } else {
            ygopro.ctos_send(room.dueling_players[oppo_pos - win_pos].server, 'SURRENDER');
          }
nanahira's avatar
nanahira committed
2884
        } else {
nanahira's avatar
fix  
nanahira committed
2885 2886
          room.death = -1;
          ygopro.stoc_send_chat_to_room(room, "${death_remain_final}", ygopro.constants.COLORS.BABYBLUE);
nanahira's avatar
nanahira committed
2887 2888 2889
        }
      }
    }
nanahira's avatar
nanahira committed
2890
    if (ygopro.constants.MSG[msg] === 'WIN' && client.pos === 0) {
mercury233's avatar
mercury233 committed
2891
      pos = buffer.readUInt8(1);
nanahira's avatar
nanahira committed
2892
      if (!(client.is_first || pos === 2 || room.turn <= 0 || !room.turn)) {
mercury233's avatar
mercury233 committed
2893 2894
        pos = 1 - pos;
      }
nanahira's avatar
nanahira committed
2895 2896 2897
      if (pos >= 0 && room.hostinfo.mode === 2) {
        pos = pos * 2;
      }
mercury233's avatar
mercury233 committed
2898 2899
      reason = buffer.readUInt8(2);
      room.winner = pos;
nanahira's avatar
nanahira committed
2900
      room.turn = 0;
nanahira's avatar
nanahira committed
2901 2902 2903 2904
      if (settings.modules.heartbeat_detection.enabled) {
        ref2 = room.players;
        for (m = 0, len2 = ref2.length; m < len2; m++) {
          player = ref2[m];
2905
          player.heartbeat_protected = false;
nanahira's avatar
nanahira committed
2906
        }
nanahira's avatar
nanahira committed
2907 2908
        delete room.long_resolve_card;
        delete room.long_resolve_chain;
nanahira's avatar
nanahira committed
2909
      }
mercury233's avatar
fix  
mercury233 committed
2910
      if (room && !room.finished && room.dueling_players[pos]) {
2911
        room.winner_name = room.dueling_players[pos].name_vpass;
mercury233's avatar
mercury233 committed
2912 2913
        room.scores[room.winner_name] = room.scores[room.winner_name] + 1;
      }
nanahira's avatar
fix  
nanahira committed
2914
      if (room.death) {
nanahira's avatar
nanahira committed
2915
        if (settings.modules.http.quick_death_rule === 1 || settings.modules.http.quick_death_rule === 3) {
nanahira's avatar
fix  
nanahira committed
2916 2917 2918 2919 2920
          room.death = -1;
        } else {
          room.death = 5;
        }
      }
mercury233's avatar
mercury233 committed
2921
    }
nanahira's avatar
nanahira committed
2922
    if (ygopro.constants.MSG[msg] === 'DAMAGE' && client.pos === 0) {
神楽坂玲奈's avatar
12.2  
神楽坂玲奈 committed
2923 2924 2925 2926
      pos = buffer.readUInt8(1);
      if (!client.is_first) {
        pos = 1 - pos;
      }
nanahira's avatar
nanahira committed
2927 2928 2929
      if (pos >= 0 && room.hostinfo.mode === 2) {
        pos = pos * 2;
      }
神楽坂玲奈's avatar
12.2  
神楽坂玲奈 committed
2930
      val = buffer.readInt32LE(2);
2931
      room.dueling_players[pos].lp -= val;
nanahira's avatar
fix  
nanahira committed
2932 2933 2934
      if (room.dueling_players[pos].lp < 0) {
        room.dueling_players[pos].lp = 0;
      }
nanahira's avatar
nanahira committed
2935
      if ((0 < (ref3 = room.dueling_players[pos].lp) && ref3 <= 100)) {
mercury233's avatar
mercury233 committed
2936
        ygopro.stoc_send_chat_to_room(room, "${lp_low_opponent}", ygopro.constants.COLORS.PINK);
神楽坂玲奈's avatar
12.2  
神楽坂玲奈 committed
2937 2938
      }
    }
nanahira's avatar
nanahira committed
2939
    if (ygopro.constants.MSG[msg] === 'RECOVER' && client.pos === 0) {
神楽坂玲奈's avatar
12.2  
神楽坂玲奈 committed
2940 2941 2942 2943
      pos = buffer.readUInt8(1);
      if (!client.is_first) {
        pos = 1 - pos;
      }
nanahira's avatar
nanahira committed
2944 2945 2946
      if (pos >= 0 && room.hostinfo.mode === 2) {
        pos = pos * 2;
      }
神楽坂玲奈's avatar
12.2  
神楽坂玲奈 committed
2947
      val = buffer.readInt32LE(2);
2948
      room.dueling_players[pos].lp += val;
神楽坂玲奈's avatar
12.2  
神楽坂玲奈 committed
2949
    }
nanahira's avatar
nanahira committed
2950
    if (ygopro.constants.MSG[msg] === 'LPUPDATE' && client.pos === 0) {
神楽坂玲奈's avatar
12.2  
神楽坂玲奈 committed
2951 2952 2953 2954
      pos = buffer.readUInt8(1);
      if (!client.is_first) {
        pos = 1 - pos;
      }
nanahira's avatar
nanahira committed
2955 2956 2957
      if (pos >= 0 && room.hostinfo.mode === 2) {
        pos = pos * 2;
      }
神楽坂玲奈's avatar
12.2  
神楽坂玲奈 committed
2958
      val = buffer.readInt32LE(2);
2959
      room.dueling_players[pos].lp = val;
神楽坂玲奈's avatar
12.2  
神楽坂玲奈 committed
2960
    }
nanahira's avatar
nanahira committed
2961
    if (ygopro.constants.MSG[msg] === 'PAY_LPCOST' && client.pos === 0) {
神楽坂玲奈's avatar
12.2  
神楽坂玲奈 committed
2962 2963 2964 2965
      pos = buffer.readUInt8(1);
      if (!client.is_first) {
        pos = 1 - pos;
      }
nanahira's avatar
nanahira committed
2966 2967 2968
      if (pos >= 0 && room.hostinfo.mode === 2) {
        pos = pos * 2;
      }
神楽坂玲奈's avatar
12.2  
神楽坂玲奈 committed
2969
      val = buffer.readInt32LE(2);
2970
      room.dueling_players[pos].lp -= val;
nanahira's avatar
fix  
nanahira committed
2971 2972 2973
      if (room.dueling_players[pos].lp < 0) {
        room.dueling_players[pos].lp = 0;
      }
nanahira's avatar
nanahira committed
2974
      if ((0 < (ref4 = room.dueling_players[pos].lp) && ref4 <= 100)) {
mercury233's avatar
mercury233 committed
2975
        ygopro.stoc_send_chat_to_room(room, "${lp_low_self}", ygopro.constants.COLORS.PINK);
神楽坂玲奈's avatar
12.2  
神楽坂玲奈 committed
2976 2977
      }
    }
nanahira's avatar
nanahira committed
2978
    if (ygopro.constants.MSG[msg] === 'MOVE' && room.hostinfo.mode !== 2) {
nanahira's avatar
nanahira committed
2979 2980 2981 2982 2983
      pos = buffer.readUInt8(5);
      if (!client.is_first) {
        pos = 1 - pos;
      }
      loc = buffer.readUInt8(6);
nanahira's avatar
nanahira committed
2984 2985
      if ((loc & 0xe) && pos === 0) {
        client.card_count--;
nanahira's avatar
nanahira committed
2986 2987 2988 2989 2990 2991
      }
      pos = buffer.readUInt8(9);
      if (!client.is_first) {
        pos = 1 - pos;
      }
      loc = buffer.readUInt8(10);
nanahira's avatar
nanahira committed
2992 2993
      if ((loc & 0xe) && pos === 0) {
        client.card_count++;
nanahira's avatar
nanahira committed
2994 2995 2996 2997 2998 2999 3000 3001 3002 3003 3004 3005
      }
    }
    if (ygopro.constants.MSG[msg] === 'DRAW' && room.hostinfo.mode !== 2) {
      pos = buffer.readUInt8(1);
      if (!client.is_first) {
        pos = 1 - pos;
      }
      if (pos === 0) {
        count = buffer.readInt8(2);
        client.card_count += count;
      }
    }
nanahira's avatar
nanahira committed
3006 3007 3008 3009 3010 3011 3012 3013 3014 3015 3016 3017 3018 3019 3020 3021 3022 3023 3024
    if (settings.modules.heartbeat_detection.enabled && ygopro.constants.MSG[msg] === 'CONFIRM_CARDS') {
      check = false;
      count = buffer.readInt8(2);
      max_loop = 3 + (count - 1) * 7;
      deck_found = 0;
      limbo_found = 0;
      for (i = n = 3, ref5 = max_loop; n <= ref5; i = n += 7) {
        loc = buffer.readInt8(i + 5);
        if ((loc & 0x41) > 0) {
          deck_found++;
        } else if (loc === 0) {
          limbo_found++;
        }
        if ((deck_found > 0 && count > 1) || limbo_found > 0) {
          check = true;
          break;
        }
      }
      if (check) {
3025
        client.heartbeat_protected = true;
nanahira's avatar
nanahira committed
3026 3027
      }
    }
nanahira's avatar
nanahira committed
3028 3029 3030 3031 3032 3033 3034 3035 3036 3037 3038 3039 3040 3041 3042 3043 3044 3045 3046 3047 3048 3049 3050 3051 3052 3053 3054 3055 3056 3057 3058 3059 3060 3061 3062 3063 3064 3065 3066 3067 3068
    if (settings.modules.heartbeat_detection.enabled && client.pos === 0) {
      if (ygopro.constants.MSG[msg] === 'CHAINING') {
        card = buffer.readUInt32LE(1);
        found = false;
        for (o = 0, len3 = long_resolve_cards.length; o < len3; o++) {
          id = long_resolve_cards[o];
          if (!(id === card)) {
            continue;
          }
          found = true;
          break;
        }
        if (found) {
          room.long_resolve_card = card;
        } else {
          delete room.long_resolve_card;
        }
      } else if (ygopro.constants.MSG[msg] === 'CHAINED' && room.long_resolve_card) {
        chain = buffer.readInt8(1);
        if (!room.long_resolve_chain) {
          room.long_resolve_chain = [];
        }
        room.long_resolve_chain[chain] = true;
        delete room.long_resolve_card;
      } else if (ygopro.constants.MSG[msg] === 'CHAIN_SOLVING' && room.long_resolve_chain) {
        chain = buffer.readInt8(1);
        if (room.long_resolve_chain[chain]) {
          ref6 = room.get_playing_player();
          for (p = 0, len4 = ref6.length; p < len4; p++) {
            player = ref6[p];
            player.heartbeat_protected = true;
          }
        }
      } else if ((ygopro.constants.MSG[msg] === 'CHAIN_NEGATED' || ygopro.constants.MSG[msg] === 'CHAIN_DISABLED') && room.long_resolve_chain) {
        chain = buffer.readInt8(1);
        delete room.long_resolve_chain[chain];
      } else if (ygopro.constants.MSG[msg] === 'CHAIN_END') {
        delete room.long_resolve_card;
        delete room.long_resolve_chain;
      }
    }
mercury233's avatar
mercury233 committed
3069
    if (settings.modules.dialogues.enabled) {
nanahira's avatar
nanahira committed
3070
      if (ygopro.constants.MSG[msg] === 'SUMMONING' || ygopro.constants.MSG[msg] === 'SPSUMMONING' || ygopro.constants.MSG[msg] === 'CHAINING') {
神楽坂玲奈's avatar
11.7  
神楽坂玲奈 committed
3071
        card = buffer.readUInt32LE(1);
nanahira's avatar
fix  
nanahira committed
3072
        trigger_location = buffer.readUInt8(6);
nanahira's avatar
nanahira committed
3073
        if (dialogues.dialogues[card] && (ygopro.constants.MSG[msg] !== 'CHAINING' || (trigger_location & 0x8) && client.ready_trap)) {
nanahira's avatar
nanahira committed
3074 3075 3076
          ref7 = _.lines(dialogues.dialogues[card][Math.floor(Math.random() * dialogues.dialogues[card].length)]);
          for (q = 0, len5 = ref7.length; q < len5; q++) {
            line = ref7[q];
mercury233's avatar
mercury233 committed
3077
            ygopro.stoc_send_chat(client, line, ygopro.constants.COLORS.PINK);
神楽坂玲奈's avatar
11.7  
神楽坂玲奈 committed
3078
          }
神楽坂玲奈's avatar
神楽坂玲奈 committed
3079
        }
神楽坂玲奈's avatar
 
神楽坂玲奈 committed
3080
      }
nanahira's avatar
nanahira committed
3081 3082 3083 3084 3085 3086 3087 3088
      if (ygopro.constants.MSG[msg] === 'POS_CHANGE') {
        loc = buffer.readUInt8(6);
        ppos = buffer.readUInt8(8);
        cpos = buffer.readUInt8(9);
        client.ready_trap = !!(loc & 0x8) && !!(ppos & 0xa) && !!(cpos & 0x5);
      } else if (ygopro.constants.MSG[msg] !== 'UPDATE_CARD' && ygopro.constants.MSG[msg] !== 'WAITING') {
        client.ready_trap = false;
      }
神楽坂玲奈's avatar
 
神楽坂玲奈 committed
3089
    }
nanahira's avatar
nanahira committed
3090
    return false;
神楽坂玲奈's avatar
 
神楽坂玲奈 committed
3091 3092
  });

nanahira's avatar
nanahira committed
3093
  ygopro.ctos_follow('HS_TOOBSERVER', true, function(buffer, info, client, server, datas) {
nanahira's avatar
nanahira committed
3094
    var len2, m, player, ref2, room;
3095 3096 3097 3098
    room = ROOM_all[client.rid];
    if (!room) {
      return;
    }
nanahira's avatar
nanahira committed
3099
    if (room.hostinfo.no_watch) {
nanahira's avatar
nanahira committed
3100 3101 3102
      ygopro.stoc_send_chat(client, "${watch_denied_room}", ygopro.constants.COLORS.RED);
      return true;
    }
nanahira's avatar
nanahira committed
3103
    if ((!room.arena && !settings.modules.challonge.enabled) || client.is_local) {
3104 3105
      return false;
    }
nanahira's avatar
nanahira committed
3106
    ref2 = room.players;
nanahira's avatar
nanahira committed
3107 3108
    for (m = 0, len2 = ref2.length; m < len2; m++) {
      player = ref2[m];
3109 3110 3111 3112 3113 3114 3115
      if (player === client) {
        ygopro.stoc_send_chat(client, "${cannot_to_observer}", ygopro.constants.COLORS.BABYBLUE);
        return true;
      }
    }
    return false;
  });
nanahira's avatar
js  
nanahira committed
3116

nanahira's avatar
nanahira committed
3117
  ygopro.ctos_follow('HS_KICK', true, function(buffer, info, client, server, datas) {
nanahira's avatar
nanahira committed
3118
    var len2, m, player, ref2, room;
3119 3120
    room = ROOM_all[client.rid];
    if (!room) {
3121 3122
      return;
    }
nanahira's avatar
nanahira committed
3123
    ref2 = room.players;
nanahira's avatar
nanahira committed
3124 3125
    for (m = 0, len2 = ref2.length; m < len2; m++) {
      player = ref2[m];
mercury233's avatar
mercury233 committed
3126
      if (player && player.pos === info.pos && player !== client) {
nanahira's avatar
nanahira committed
3127
        if (room.arena === "athletic" || settings.modules.challonge.enabled) {
3128
          ygopro.stoc_send_chat_to_room(room, client.name + " ${kicked_by_system}", ygopro.constants.COLORS.RED);
nanahira's avatar
nanahira committed
3129
          CLIENT_kick(client);
3130 3131
          return true;
        }
mercury233's avatar
mercury233 committed
3132
        client.kick_count = client.kick_count ? client.kick_count + 1 : 1;
mercury233's avatar
fix  
mercury233 committed
3133
        if (client.kick_count >= 5 && room.random_type) {
mercury233's avatar
mercury233 committed
3134
          ygopro.stoc_send_chat_to_room(room, client.name + " ${kicked_by_system}", ygopro.constants.COLORS.RED);
mercury233's avatar
mercury233 committed
3135
          ROOM_ban_player(player.name, player.ip, "${random_ban_reason_zombie}");
nanahira's avatar
nanahira committed
3136
          CLIENT_kick(client);
mercury233's avatar
mercury233 committed
3137 3138
          return true;
        }
mercury233's avatar
mercury233 committed
3139
        ygopro.stoc_send_chat_to_room(room, player.name + " ${kicked_by_player}", ygopro.constants.COLORS.RED);
3140 3141 3142 3143 3144
      }
    }
    return false;
  });

nanahira's avatar
nanahira committed
3145
  ygopro.stoc_follow('TYPE_CHANGE', true, function(buffer, info, client, server, datas) {
神楽坂玲奈's avatar
神楽坂玲奈 committed
3146 3147 3148 3149
    var is_host, selftype;
    selftype = info.type & 0xf;
    is_host = ((info.type >> 4) & 0xf) !== 0;
    client.is_host = is_host;
mercury233's avatar
test3  
mercury233 committed
3150
    client.pos = selftype;
nanahira's avatar
nanahira committed
3151
    return false;
神楽坂玲奈's avatar
神楽坂玲奈 committed
3152 3153
  });

3154 3155 3156 3157 3158 3159 3160 3161 3162 3163 3164 3165 3166 3167 3168 3169
  ygopro.stoc_follow('HS_PLAYER_ENTER', true, function(buffer, info, client, server, datas) {
    var pos, room, struct;
    room = ROOM_all[client.rid];
    if (!(room && settings.modules.hide_name && !room.started)) {
      return false;
    }
    pos = info.pos;
    if (pos < 4 && pos !== client.pos) {
      struct = ygopro.structs["STOC_HS_PlayerEnter"];
      struct._setBuff(buffer);
      struct.set("name", "********");
      buffer = struct.buffer;
    }
    return false;
  });

nanahira's avatar
nanahira committed
3170
  ygopro.stoc_follow('HS_PLAYER_CHANGE', false, function(buffer, info, client, server, datas) {
nanahira's avatar
nanahira committed
3171
    var is_ready, len2, len3, m, n, p1, p2, player, pos, ref2, ref3, room;
3172 3173
    room = ROOM_all[client.rid];
    if (!(room && room.max_player && client.is_host)) {
3174 3175 3176 3177
      return;
    }
    pos = info.status >> 4;
    is_ready = (info.status & 0xf) === 9;
3178
    if (pos < room.max_player) {
3179 3180
      if (room.arena) {
        room.ready_player_count = 0;
nanahira's avatar
nanahira committed
3181
        ref2 = room.players;
nanahira's avatar
nanahira committed
3182 3183
        for (m = 0, len2 = ref2.length; m < len2; m++) {
          player = ref2[m];
3184 3185 3186
          if (player.pos === pos) {
            player.is_ready = is_ready;
          }
3187
        }
3188 3189 3190 3191 3192 3193 3194 3195 3196 3197 3198 3199 3200 3201 3202 3203 3204 3205 3206 3207 3208 3209
        p1 = room.players[0];
        p2 = room.players[1];
        if (!p1 || !p2) {
          if (room.waiting_for_player_interval) {
            clearInterval(room.waiting_for_player_interval);
            room.waiting_for_player_interval = null;
          }
          return;
        }
        room.waiting_for_player2 = room.waiting_for_player;
        room.waiting_for_player = null;
        if (p1.is_ready && p2.is_ready) {
          room.waiting_for_player = p1.is_host ? p1 : p2;
        }
        if (!p1.is_ready && p2.is_ready) {
          room.waiting_for_player = p1;
        }
        if (!p2.is_ready && p1.is_ready) {
          room.waiting_for_player = p2;
        }
        if (room.waiting_for_player !== room.waiting_for_player2) {
          room.waiting_for_player2 = room.waiting_for_player;
nanahira's avatar
nanahira committed
3210
          room.waiting_for_player_time = settings.modules.arena_mode.ready_time;
3211 3212 3213 3214 3215 3216
          room.waiting_for_player_interval = setInterval((function() {
            wait_room_start_arena(ROOM_all[client.rid]);
          }), 1000);
        } else if (!room.waiting_for_player && room.waiting_for_player_interval) {
          clearInterval(room.waiting_for_player_interval);
          room.waiting_for_player_interval = null;
nanahira's avatar
nanahira committed
3217
          room.waiting_for_player_time = settings.modules.arena_mode.ready_time;
3218 3219 3220
        }
      } else {
        room.ready_player_count_without_host = 0;
nanahira's avatar
nanahira committed
3221
        ref3 = room.players;
nanahira's avatar
nanahira committed
3222 3223
        for (n = 0, len3 = ref3.length; n < len3; n++) {
          player = ref3[n];
3224 3225 3226 3227 3228 3229 3230 3231 3232
          if (player.pos === pos) {
            player.is_ready = is_ready;
          }
          if (!player.is_host) {
            room.ready_player_count_without_host += player.is_ready;
          }
        }
        if (room.ready_player_count_without_host >= room.max_player - 1) {
          setTimeout((function() {
nanahira's avatar
nanahira committed
3233
            wait_room_start(ROOM_all[client.rid], settings.modules.random_duel.ready_time);
3234
          }), 1000);
3235 3236 3237 3238 3239
        }
      }
    }
  });

nanahira's avatar
nanahira committed
3240
  ygopro.ctos_follow('REQUEST_FIELD', true, function(buffer, info, client, server, datas) {
3241 3242 3243
    return true;
  });

nanahira's avatar
nanahira committed
3244
  ygopro.stoc_follow('FIELD_FINISH', true, function(buffer, info, client, server, datas) {
nanahira's avatar
nanahira committed
3245 3246
    var room;
    room = ROOM_all[client.rid];
3247
    if (!(room && settings.modules.reconnect.enabled)) {
nanahira's avatar
nanahira committed
3248 3249
      return true;
    }
3250
    client.reconnecting = false;
3251 3252 3253
    if (client.time_confirm_required) {
      client.waiting_for_last = true;
    } else if (client.last_game_msg && client.last_game_msg_title !== 'WAITING') {
3254 3255 3256 3257
      if (client.last_hint_msg) {
        ygopro.stoc_send(client, 'GAME_MSG', client.last_hint_msg);
      }
      ygopro.stoc_send(client, 'GAME_MSG', client.last_game_msg);
nanahira's avatar
nanahira committed
3258 3259 3260 3261
    }
    return true;
  });

3262
  ygopro.stoc_follow('DUEL_END', false, function(buffer, info, client, server, datas) {
nanahira's avatar
js  
nanahira committed
3263
    var len2, len3, m, n, player, ref2, ref3, results, room;
nanahira's avatar
move  
nanahira committed
3264 3265 3266 3267
    room = ROOM_all[client.rid];
    if (!(room && settings.modules.replay_delay && room.hostinfo.mode === 1)) {
      return;
    }
3268
    SOCKET_flush_data(client, datas);
nanahira's avatar
move  
nanahira committed
3269
    CLIENT_send_replays(client, room);
nanahira's avatar
nanahira committed
3270
    if (!room.replays_sent_to_watchers) {
nanahira's avatar
move  
nanahira committed
3271
      room.replays_sent_to_watchers = true;
nanahira's avatar
js  
nanahira committed
3272
      ref2 = room.players;
nanahira's avatar
move  
nanahira committed
3273 3274
      for (m = 0, len2 = ref2.length; m < len2; m++) {
        player = ref2[m];
nanahira's avatar
js  
nanahira committed
3275 3276 3277 3278 3279 3280 3281 3282
        if (player && player.pos > 3) {
          CLIENT_send_replays(player, room);
        }
      }
      ref3 = room.watchers;
      results = [];
      for (n = 0, len3 = ref3.length; n < len3; n++) {
        player = ref3[n];
nanahira's avatar
move  
nanahira committed
3283 3284 3285 3286 3287 3288 3289 3290
        if (player) {
          results.push(CLIENT_send_replays(player, room));
        }
      }
      return results;
    }
  });

3291
  wait_room_start = function(room, time) {
nanahira's avatar
nanahira committed
3292
    var len2, m, player, ref2;
3293 3294 3295 3296
    if (!(!room || room.started || room.ready_player_count_without_host < room.max_player - 1)) {
      time -= 1;
      if (time) {
        if (!(time % 5)) {
mercury233's avatar
mercury233 committed
3297
          ygopro.stoc_send_chat_to_room(room, "" + (time <= 9 ? ' ' : '') + time + "${kick_count_down}", time <= 9 ? ygopro.constants.COLORS.RED : ygopro.constants.COLORS.LIGHTBLUE);
3298 3299 3300 3301 3302
        }
        setTimeout((function() {
          wait_room_start(room, time);
        }), 1000);
      } else {
nanahira's avatar
nanahira committed
3303
        ref2 = room.players;
nanahira's avatar
nanahira committed
3304 3305
        for (m = 0, len2 = ref2.length; m < len2; m++) {
          player = ref2[m];
mercury233's avatar
fix  
mercury233 committed
3306
          if (player && player.is_host) {
mercury233's avatar
mercury233 committed
3307
            ROOM_ban_player(player.name, player.ip, "${random_ban_reason_zombie}");
mercury233's avatar
mercury233 committed
3308
            ygopro.stoc_send_chat_to_room(room, player.name + " ${kicked_by_system}", ygopro.constants.COLORS.RED);
nanahira's avatar
nanahira committed
3309
            CLIENT_kick(player);
3310 3311 3312 3313 3314 3315
          }
        }
      }
    }
  };

3316
  wait_room_start_arena = function(room) {
nanahira's avatar
fix  
nanahira committed
3317
    var display_name, len2, m, player, ref2;
3318 3319 3320 3321
    if (!(!room || room.started || !room.waiting_for_player)) {
      room.waiting_for_player_time = room.waiting_for_player_time - 1;
      if (room.waiting_for_player_time > 0) {
        if (!(room.waiting_for_player_time % 5)) {
nanahira's avatar
fix  
nanahira committed
3322 3323 3324 3325 3326 3327 3328 3329 3330
          ref2 = room.players;
          for (m = 0, len2 = ref2.length; m < len2; m++) {
            player = ref2[m];
            if (!(player)) {
              continue;
            }
            display_name = (settings.modules.hide_name && player !== room.waiting_for_player ? "********" : room.waiting_for_player.name);
            ygopro.stoc_send_chat(player, "" + (room.waiting_for_player_time <= 9 ? ' ' : '') + room.waiting_for_player_time + "${kick_count_down_arena_part1} " + display_name + " ${kick_count_down_arena_part2}", room.waiting_for_player_time <= 9 ? ygopro.constants.COLORS.RED : ygopro.constants.COLORS.LIGHTBLUE);
          }
3331 3332 3333
        }
      } else {
        ygopro.stoc_send_chat_to_room(room, room.waiting_for_player.name + " ${kicked_by_system}", ygopro.constants.COLORS.RED);
nanahira's avatar
nanahira committed
3334
        CLIENT_kick(room.waiting_for_player);
3335 3336 3337 3338 3339 3340 3341 3342
        if (room.waiting_for_player_interval) {
          clearInterval(room.waiting_for_player_interval);
          room.waiting_for_player_interval = null;
        }
      }
    }
  };

神楽坂玲奈's avatar
11.7  
神楽坂玲奈 committed
3343
  ygopro.stoc_send_random_tip = function(client) {
mercury233's avatar
mercury233 committed
3344 3345
    if (settings.modules.tips.enabled && tips.tips.length) {
      ygopro.stoc_send_chat(client, "Tip: " + tips.tips[Math.floor(Math.random() * tips.tips.length)]);
神楽坂玲奈's avatar
神楽坂玲奈 committed
3346
    }
神楽坂玲奈's avatar
11.7  
神楽坂玲奈 committed
3347 3348
  };

3349
  ygopro.stoc_send_random_tip_to_room = function(room) {
mercury233's avatar
mercury233 committed
3350 3351
    if (settings.modules.tips.enabled && tips.tips.length) {
      ygopro.stoc_send_chat_to_room(room, "Tip: " + tips.tips[Math.floor(Math.random() * tips.tips.length)]);
3352 3353 3354
    }
  };

mercury233's avatar
mercury233 committed
3355
  load_tips = function() {
神楽坂玲奈's avatar
fix  
神楽坂玲奈 committed
3356
    request({
mercury233's avatar
mercury233 committed
3357
      url: settings.modules.tips.get,
神楽坂玲奈's avatar
fix  
神楽坂玲奈 committed
3358 3359
      json: true
    }, function(error, response, body) {
mercury233's avatar
mercury233 committed
3360 3361 3362 3363 3364
      if (_.isString(body)) {
        log.warn("tips bad json", body);
      } else if (error || !body) {
        log.warn('tips error', error, response);
      } else {
mercury233's avatar
mercury233 committed
3365 3366
        setting_change(tips, "tips", body);
        log.info("tips loaded", tips.tips.length);
mercury233's avatar
mercury233 committed
3367
      }
神楽坂玲奈's avatar
fix  
神楽坂玲奈 committed
3368
    });
mercury233's avatar
mercury233 committed
3369 3370
  };

mercury233's avatar
mercury233 committed
3371
  if (settings.modules.tips.get) {
mercury233's avatar
mercury233 committed
3372 3373
    load_tips();
    setInterval(function() {
nanahira's avatar
nanahira committed
3374 3375 3376
      var len2, m, room;
      for (m = 0, len2 = ROOM_all.length; m < len2; m++) {
        room = ROOM_all[m];
3377
        if (room && room.established) {
3378
          if (!room.started || room.changing_side) {
3379 3380
            ygopro.stoc_send_random_tip_to_room(room);
          }
mercury233's avatar
mercury233 committed
3381 3382 3383
        }
      }
    }, 30000);
神楽坂玲奈's avatar
fix  
神楽坂玲奈 committed
3384
  }
神楽坂玲奈's avatar
11.7  
神楽坂玲奈 committed
3385

nanahira's avatar
nanahira committed
3386
  ygopro.stoc_follow('DUEL_START', false, function(buffer, info, client, server, datas) {
3387
    var deck_arena, deck_name, deck_text, len2, len3, m, n, player, ref2, ref3, room;
3388
    room = ROOM_all[client.rid];
nanahira's avatar
nanahira committed
3389
    if (!(room && !client.reconnecting)) {
3390 3391
      return;
    }
3392 3393
    if (!room.started) {
      room.started = true;
mercury233's avatar
mercury233 committed
3394
      room.start_time = moment().format();
nanahira's avatar
nanahira committed
3395
      room.turn = 0;
mercury233's avatar
mercury233 committed
3396
      if (!room.windbot && settings.modules.http.websocket_roomlist) {
mercury233's avatar
mercury233 committed
3397
        roomlist.start(room);
神楽坂玲奈's avatar
神楽坂玲奈 committed
3398
      }
3399
      room.dueling_players = [];
nanahira's avatar
nanahira committed
3400
      ref2 = room.players;
nanahira's avatar
nanahira committed
3401 3402
      for (m = 0, len2 = ref2.length; m < len2; m++) {
        player = ref2[m];
mercury233's avatar
mercury233 committed
3403 3404
        if (!(player.pos !== 7)) {
          continue;
神楽坂玲奈's avatar
12.2  
神楽坂玲奈 committed
3405
        }
3406
        room.dueling_players[player.pos] = player;
3407
        room.scores[player.name_vpass] = 0;
3408
        room.player_datas.push({
mercury233's avatar
mercury233 committed
3409
          ip: player.ip,
mercury233's avatar
mercury233 committed
3410 3411
          name: player.name
        });
mercury233's avatar
mercury233 committed
3412 3413 3414
        if (room.random_type === 'T') {
          ROOM_players_oppentlist[player.ip] = null;
        }
神楽坂玲奈's avatar
11.7  
神楽坂玲奈 committed
3415 3416
      }
    }
3417 3418 3419 3420 3421 3422 3423 3424 3425 3426 3427 3428
    if (settings.modules.hide_name && room.duel_count === 0) {
      ref3 = room.get_playing_player();
      for (n = 0, len3 = ref3.length; n < len3; n++) {
        player = ref3[n];
        if (player !== client) {
          ygopro.stoc_send(client, 'HS_PLAYER_ENTER', {
            name: player.name,
            pos: player.pos
          });
        }
      }
    }
mercury233's avatar
mercury233 committed
3429
    if (settings.modules.tips.enabled) {
mercury233's avatar
test3  
mercury233 committed
3430
      ygopro.stoc_send_random_tip(client);
神楽坂玲奈's avatar
11.7  
神楽坂玲奈 committed
3431
    }
nanahira's avatar
nanahira committed
3432 3433
    deck_text = null;
    if (client.main && client.main.length) {
mercury233's avatar
mercury233 committed
3434
      deck_text = '#ygopro-server deck log\n#main\n' + client.main.join('\n') + '\n!side\n' + client.side.join('\n') + '\n';
nanahira's avatar
nanahira committed
3435 3436 3437
      room.decks[client.name] = deck_text;
    }
    if (settings.modules.deck_log.enabled && deck_text && !client.deck_saved && !room.windbot) {
mercury233's avatar
mercury233 committed
3438 3439 3440 3441 3442 3443 3444 3445
      deck_arena = settings.modules.deck_log.arena + '-';
      if (room.arena) {
        deck_arena = deck_arena + room.arena;
      } else if (room.hostinfo.mode === 2) {
        deck_arena = deck_arena + 'tag';
      } else if (room.random_type === 'S') {
        deck_arena = deck_arena + 'entertain';
      } else if (room.random_type === 'M') {
mercury233's avatar
mercury233 committed
3446
        deck_arena = deck_arena + 'athletic';
mercury233's avatar
mercury233 committed
3447 3448 3449
      } else {
        deck_arena = deck_arena + 'custom';
      }
mercury233's avatar
mercury233 committed
3450
      if (settings.modules.deck_log.local) {
nanahira's avatar
nanahira committed
3451
        deck_name = moment().format('YYYY-MM-DD HH-mm-ss') + ' ' + room.process_pid + ' ' + client.pos + ' ' + client.ip.slice(7) + ' ' + client.name.replace(/[\/\\\?\*]/g, '_');
mercury233's avatar
mercury233 committed
3452
        fs.writeFile(settings.modules.deck_log.local + deck_name + '.ydk', deck_text, 'utf-8', function(err) {
mercury233's avatar
mercury233 committed
3453 3454 3455 3456 3457
          if (err) {
            return log.warn('DECK SAVE ERROR', err);
          }
        });
      }
mercury233's avatar
mercury233 committed
3458
      if (settings.modules.deck_log.post) {
mercury233's avatar
mercury233 committed
3459
        request.post({
mercury233's avatar
mercury233 committed
3460
          url: settings.modules.deck_log.post,
mercury233's avatar
mercury233 committed
3461
          form: {
mercury233's avatar
mercury233 committed
3462
            accesskey: settings.modules.deck_log.accesskey,
mercury233's avatar
mercury233 committed
3463 3464
            deck: deck_text,
            playername: client.name,
mercury233's avatar
mercury233 committed
3465
            arena: deck_arena
mercury233's avatar
mercury233 committed
3466 3467 3468
          }
        }, function(error, response, body) {
          if (error) {
mercury233's avatar
merge  
mercury233 committed
3469
            log.warn('DECK POST ERROR', error);
mercury233's avatar
mercury233 committed
3470 3471
          } else {
            if (response.statusCode !== 200) {
mercury233's avatar
merge  
mercury233 committed
3472
              log.warn('DECK POST FAIL', response.statusCode, client.name, body);
mercury233's avatar
mercury233 committed
3473 3474 3475 3476
            }
          }
        });
      }
mercury233's avatar
mercury233 committed
3477 3478
      client.deck_saved = true;
    }
神楽坂玲奈's avatar
11.7  
神楽坂玲奈 committed
3479 3480
  });

nanahira's avatar
nanahira committed
3481
  ygopro.ctos_follow('SURRENDER', true, function(buffer, info, client, server, datas) {
3482 3483 3484 3485 3486 3487 3488 3489
    var room;
    room = ROOM_all[client.rid];
    if (!room) {
      return;
    }
    if (!room.started || room.hostinfo.mode === 2) {
      return true;
    }
3490
    if (room.random_type && room.turn < 3 && !client.flee_free && !settings.modules.test_mode.surrender_anytime && !(room.random_type === 'M' && settings.modules.random_duel.record_match_scores)) {
3491 3492 3493 3494 3495 3496
      ygopro.stoc_send_chat(client, "${surrender_denied}", ygopro.constants.COLORS.BABYBLUE);
      return true;
    }
    return false;
  });

mercury233's avatar
mercury233 committed
3497 3498 3499 3500 3501 3502 3503 3504 3505 3506 3507 3508 3509 3510 3511 3512 3513 3514 3515 3516 3517 3518 3519 3520 3521 3522
  report_to_big_brother = function(roomname, sender, ip, level, content, match) {
    if (!settings.modules.big_brother.enabled) {
      return;
    }
    request.post({
      url: settings.modules.big_brother.post,
      form: {
        accesskey: settings.modules.big_brother.accesskey,
        roomname: roomname,
        sender: sender,
        ip: ip,
        level: level,
        content: content,
        match: match
      }
    }, function(error, response, body) {
      if (error) {
        log.warn('BIG BROTHER ERROR', error);
      } else {
        if (response.statusCode !== 200) {
          log.warn('BIG BROTHER FAIL', response.statusCode, roomname, body);
        }
      }
    });
  };

nanahira's avatar
nanahira committed
3523
  ygopro.ctos_follow('CHAT', true, function(buffer, info, client, server, datas) {
nanahira's avatar
nanahira committed
3524
    var cancel, ccolor, cip, cmd, cmsg, cname, color, cvalue, msg, name, oldmsg, ref2, room, struct, windbot;
3525 3526
    room = ROOM_all[client.rid];
    if (!room) {
mercury233's avatar
mercury233 committed
3527 3528
      return;
    }
mercury233's avatar
mercury233 committed
3529 3530
    msg = _.trim(info.msg);
    cancel = _.startsWith(msg, "/");
mercury233's avatar
fix  
mercury233 committed
3531
    if (!(cancel || !(room.random_type || room.arena))) {
3532
      room.last_active_time = moment();
3533
    }
mercury233's avatar
mercury233 committed
3534 3535
    cmd = msg.split(' ');
    switch (cmd[0]) {
mercury233's avatar
mercury233 committed
3536 3537 3538 3539 3540
      case '/投降':
      case '/surrender':
        if (!room.started || room.hostinfo.mode === 2) {
          return cancel;
        }
3541
        if (room.random_type && room.turn < 3) {
mercury233's avatar
mercury233 committed
3542 3543 3544 3545 3546 3547 3548 3549 3550 3551
          ygopro.stoc_send_chat(client, "${surrender_denied}", ygopro.constants.COLORS.BABYBLUE);
          return cancel;
        }
        if (client.surrend_confirm) {
          ygopro.ctos_send(client.server, 'SURRENDER');
        } else {
          ygopro.stoc_send_chat(client, "${surrender_confirm}", ygopro.constants.COLORS.BABYBLUE);
          client.surrend_confirm = true;
        }
        break;
神楽坂玲奈's avatar
11.7  
神楽坂玲奈 committed
3552
      case '/help':
mercury233's avatar
mercury233 committed
3553 3554
        ygopro.stoc_send_chat(client, "${chat_order_main}");
        ygopro.stoc_send_chat(client, "${chat_order_help}");
mercury233's avatar
mercury233 committed
3555
        if (!settings.modules.mycard.enabled) {
mercury233's avatar
mercury233 committed
3556
          ygopro.stoc_send_chat(client, "${chat_order_roomname}");
mercury233's avatar
merge  
mercury233 committed
3557
        }
mercury233's avatar
mercury233 committed
3558
        if (settings.modules.windbot.enabled) {
mercury233's avatar
mercury233 committed
3559
          ygopro.stoc_send_chat(client, "${chat_order_windbot}");
mercury233's avatar
mercury233 committed
3560
        }
mercury233's avatar
mercury233 committed
3561
        if (settings.modules.tips.enabled) {
mercury233's avatar
mercury233 committed
3562
          ygopro.stoc_send_chat(client, "${chat_order_tip}");
神楽坂玲奈's avatar
11.7  
神楽坂玲奈 committed
3563
        }
nanahira's avatar
nanahira committed
3564 3565 3566 3567 3568 3569
        if (settings.modules.chat_color.enabled) {
          ygopro.stoc_send_chat(client, "${chat_order_chatcolor_1}");
        }
        if (settings.modules.chat_color.enabled) {
          ygopro.stoc_send_chat(client, "${chat_order_chatcolor_2}");
        }
mercury233's avatar
mercury233 committed
3570
        break;
神楽坂玲奈's avatar
11.7  
神楽坂玲奈 committed
3571
      case '/tip':
mercury233's avatar
mercury233 committed
3572
        if (settings.modules.tips.enabled) {
mercury233's avatar
test3  
mercury233 committed
3573
          ygopro.stoc_send_random_tip(client);
神楽坂玲奈's avatar
11.7  
神楽坂玲奈 committed
3574
        }
mercury233's avatar
mercury233 committed
3575
        break;
mercury233's avatar
mercury233 committed
3576
      case '/ai':
3577
        if (settings.modules.windbot.enabled && client.is_host && !settings.modules.challonge.enabled && !room.arena && room.random_type !== 'M') {
mercury233's avatar
mercury233 committed
3578
          if (name = cmd[1]) {
mercury233's avatar
mercury233 committed
3579
            windbot = _.sample(_.filter(windbots, function(w) {
mercury233's avatar
mercury233 committed
3580 3581 3582
              return w.name === name || w.deck === name;
            }));
            if (!windbot) {
mercury233's avatar
mercury233 committed
3583
              ygopro.stoc_send_chat(client, "${windbot_deck_not_found}", ygopro.constants.COLORS.RED);
mercury233's avatar
mercury233 committed
3584 3585 3586
              return;
            }
          } else {
mercury233's avatar
mercury233 committed
3587
            windbot = _.sample(windbots);
mercury233's avatar
mercury233 committed
3588
          }
mercury233's avatar
mercury233 committed
3589 3590 3591
          room.add_windbot(windbot);
        }
        break;
mercury233's avatar
mercury233 committed
3592
      case '/roomname':
3593
        if (room) {
mercury233's avatar
mercury233 committed
3594
          ygopro.stoc_send_chat(client, "${room_name} " + room.name, ygopro.constants.COLORS.BABYBLUE);
mercury233's avatar
mercury233 committed
3595
        }
nanahira's avatar
nanahira committed
3596 3597 3598
        break;
      case '/color':
        if (settings.modules.chat_color.enabled) {
nanahira's avatar
nanahira committed
3599
          cip = CLIENT_get_authorize_key(client);
nanahira's avatar
nanahira committed
3600 3601 3602
          if (cmsg = cmd[1]) {
            if (cmsg.toLowerCase() === "help") {
              ygopro.stoc_send_chat(client, "${show_color_list}", ygopro.constants.COLORS.BABYBLUE);
nanahira's avatar
nanahira committed
3603 3604 3605
              ref2 = ygopro.constants.COLORS;
              for (cname in ref2) {
                cvalue = ref2[cname];
nanahira's avatar
nanahira committed
3606 3607 3608 3609 3610
                if (cvalue > 10) {
                  ygopro.stoc_send_chat(client, cname, cvalue);
                }
              }
            } else if (cmsg.toLowerCase() === "default") {
nanahira's avatar
fix  
nanahira committed
3611 3612
              chat_color.save_list[cip] = false;
              setting_save(chat_color);
nanahira's avatar
nanahira committed
3613 3614 3615
              ygopro.stoc_send_chat(client, "${set_chat_color_default}", ygopro.constants.COLORS.BABYBLUE);
            } else {
              ccolor = cmsg.toUpperCase();
nanahira's avatar
fix  
nanahira committed
3616 3617 3618
              if (ygopro.constants.COLORS[ccolor] && ygopro.constants.COLORS[ccolor] > 10 && ygopro.constants.COLORS[ccolor] < 20) {
                chat_color.save_list[cip] = ccolor;
                setting_save(chat_color);
nanahira's avatar
nanahira committed
3619 3620 3621 3622 3623 3624
                ygopro.stoc_send_chat(client, "${set_chat_color_part1}" + ccolor + "${set_chat_color_part2}", ygopro.constants.COLORS.BABYBLUE);
              } else {
                ygopro.stoc_send_chat(client, "${color_not_found_part1}" + ccolor + "${color_not_found_part2}", ygopro.constants.COLORS.RED);
              }
            }
          } else {
nanahira's avatar
fix  
nanahira committed
3625
            if (color = chat_color.save_list[cip]) {
nanahira's avatar
nanahira committed
3626 3627 3628 3629 3630 3631
              ygopro.stoc_send_chat(client, "${get_chat_color_part1}" + color + "${get_chat_color_part2}", ygopro.constants.COLORS.BABYBLUE);
            } else {
              ygopro.stoc_send_chat(client, "${get_chat_color_default}", ygopro.constants.COLORS.BABYBLUE);
            }
          }
        }
神楽坂玲奈's avatar
神楽坂玲奈 committed
3632
    }
mercury233's avatar
mercury233 committed
3633 3634 3635 3636 3637 3638 3639 3640
    if (msg.length > 100) {
      log.warn("SPAM WORD", client.name, client.ip, msg);
      if (client.abuse_count) {
        client.abuse_count = client.abuse_count + 2;
      }
      ygopro.stoc_send_chat(client, "${chat_warn_level0}", ygopro.constants.COLORS.RED);
      cancel = true;
    }
mercury233's avatar
mercury233 committed
3641
    if (!(room && (room.random_type || room.arena))) {
mercury233's avatar
mercury233 committed
3642 3643
      return cancel;
    }
nanahira's avatar
nanahira committed
3644
    if (client.abuse_count >= 5 || CLIENT_is_banned_by_mc(client)) {
mercury233's avatar
mercury233 committed
3645
      log.warn("BANNED CHAT", client.name, client.ip, msg);
mercury233's avatar
mercury233 committed
3646
      ygopro.stoc_send_chat(client, "${banned_chat_tip}", ygopro.constants.COLORS.RED);
mercury233's avatar
mercury233 committed
3647 3648
      return true;
    }
mercury233's avatar
mercury233 committed
3649
    oldmsg = msg;
mercury233's avatar
mercury233 committed
3650
    if (_.any(badwords.level3, function(badword) {
mercury233's avatar
mercury233 committed
3651
      var regexp;
mercury233's avatar
fix  
mercury233 committed
3652
      regexp = new RegExp(badword, 'i');
mercury233's avatar
mercury233 committed
3653 3654
      return msg.match(regexp);
    }, msg)) {
mercury233's avatar
mercury233 committed
3655 3656
      log.warn("BAD WORD LEVEL 3", client.name, client.ip, oldmsg, RegExp.$1);
      report_to_big_brother(room.name, client.name, client.ip, 3, oldmsg, RegExp.$1);
mercury233's avatar
mercury233 committed
3657
      cancel = true;
mercury233's avatar
mercury233 committed
3658
      if (client.abuse_count > 0) {
mercury233's avatar
mercury233 committed
3659 3660 3661
        ygopro.stoc_send_chat(client, "${banned_duel_tip}", ygopro.constants.COLORS.RED);
        ROOM_ban_player(client.name, client.ip, "${random_ban_reason_abuse}");
        ROOM_ban_player(client.name, client.ip, "${random_ban_reason_abuse}", 3);
nanahira's avatar
nanahira committed
3662
        CLIENT_send_replays(client, room);
nanahira's avatar
nanahira committed
3663
        CLIENT_kick(client);
mercury233's avatar
mercury233 committed
3664 3665 3666
        return true;
      } else {
        client.abuse_count = client.abuse_count + 4;
mercury233's avatar
mercury233 committed
3667
        ygopro.stoc_send_chat(client, "${chat_warn_level2}", ygopro.constants.COLORS.RED);
mercury233's avatar
mercury233 committed
3668
      }
mercury233's avatar
mercury233 committed
3669 3670 3671 3672 3673 3674 3675 3676 3677
    } else if (client.rag && room.started) {
      client.rag = false;
      cancel = true;
    } else if (_.any(settings.ban.spam_word, function(badword) {
      var regexp;
      regexp = new RegExp(badword, 'i');
      return msg.match(regexp);
    }, msg)) {
      client.abuse_count = client.abuse_count + 2;
mercury233's avatar
mercury233 committed
3678
      ygopro.stoc_send_chat(client, "${chat_warn_level0}", ygopro.constants.COLORS.RED);
mercury233's avatar
mercury233 committed
3679
      cancel = true;
mercury233's avatar
mercury233 committed
3680
    } else if (_.any(badwords.level2, function(badword) {
mercury233's avatar
mercury233 committed
3681
      var regexp;
mercury233's avatar
fix  
mercury233 committed
3682
      regexp = new RegExp(badword, 'i');
mercury233's avatar
mercury233 committed
3683 3684
      return msg.match(regexp);
    }, msg)) {
mercury233's avatar
mercury233 committed
3685 3686
      log.warn("BAD WORD LEVEL 2", client.name, client.ip, oldmsg, RegExp.$1);
      report_to_big_brother(room.name, client.name, client.ip, 2, oldmsg, RegExp.$1);
mercury233's avatar
mercury233 committed
3687
      client.abuse_count = client.abuse_count + 3;
mercury233's avatar
mercury233 committed
3688
      ygopro.stoc_send_chat(client, "${chat_warn_level2}", ygopro.constants.COLORS.RED);
mercury233's avatar
mercury233 committed
3689 3690
      cancel = true;
    } else {
mercury233's avatar
mercury233 committed
3691
      _.each(badwords.level1, function(badword) {
mercury233's avatar
mercury233 committed
3692
        var regexp;
mercury233's avatar
fix  
mercury233 committed
3693
        regexp = new RegExp(badword, "ig");
mercury233's avatar
mercury233 committed
3694 3695 3696
        msg = msg.replace(regexp, "**");
      }, msg);
      if (oldmsg !== msg) {
mercury233's avatar
mercury233 committed
3697 3698
        log.warn("BAD WORD LEVEL 1", client.name, client.ip, oldmsg, RegExp.$1);
        report_to_big_brother(room.name, client.name, client.ip, 1, oldmsg, RegExp.$1);
mercury233's avatar
mercury233 committed
3699
        client.abuse_count = client.abuse_count + 1;
mercury233's avatar
mercury233 committed
3700
        ygopro.stoc_send_chat(client, "${chat_warn_level1}");
mercury233's avatar
mercury233 committed
3701 3702 3703 3704
        struct = ygopro.structs["chat"];
        struct._setBuff(buffer);
        struct.set("msg", msg);
        buffer = struct.buffer;
mercury233's avatar
mercury233 committed
3705
      } else if (_.any(badwords.level0, function(badword) {
mercury233's avatar
mercury233 committed
3706 3707 3708 3709
        var regexp;
        regexp = new RegExp(badword, 'i');
        return msg.match(regexp);
      }, msg)) {
mercury233's avatar
mercury233 committed
3710 3711
        log.info("BAD WORD LEVEL 0", client.name, client.ip, oldmsg, RegExp.$1);
        report_to_big_brother(room.name, client.name, client.ip, 0, oldmsg, RegExp.$1);
mercury233's avatar
mercury233 committed
3712 3713
      }
    }
mercury233's avatar
mercury233 committed
3714 3715 3716
    if (client.abuse_count >= 2) {
      ROOM_unwelcome(room, client, "${random_ban_reason_abuse}");
    }
mercury233's avatar
mercury233 committed
3717
    if (client.abuse_count >= 5) {
mercury233's avatar
mercury233 committed
3718 3719
      ygopro.stoc_send_chat_to_room(room, client.name + " ${chat_banned}", ygopro.constants.COLORS.RED);
      ROOM_ban_player(client.name, client.ip, "${random_ban_reason_abuse}");
mercury233's avatar
mercury233 committed
3720
    }
3721
    return cancel;
神楽坂玲奈's avatar
11.7  
神楽坂玲奈 committed
3722 3723
  });

nanahira's avatar
nanahira committed
3724
  ygopro.ctos_follow('UPDATE_DECK', true, function(buffer, info, client, server, datas) {
3725
    var buff_main, buff_side, card, code, current_deck, deck, deck_array, deck_main, deck_side, deck_text, deckbuf, decks, found_deck, i, len2, len3, len4, line, m, n, o, oppo_pos, ref2, room, struct, win_pos;
nanahira's avatar
nanahira committed
3726
    if (settings.modules.reconnect.enabled && client.pre_reconnecting) {
nanahira's avatar
nanahira committed
3727 3728 3729 3730
      if (!CLIENT_is_able_to_reconnect(client) && !CLIENT_is_able_to_kick_reconnect(client)) {
        ygopro.stoc_send_chat(client, "${reconnect_failed}", ygopro.constants.COLORS.RED);
        CLIENT_kick(client);
      } else if (CLIENT_is_able_to_reconnect(client, buffer)) {
nanahira's avatar
nanahira committed
3731
        CLIENT_reconnect(client);
nanahira's avatar
nanahira committed
3732 3733
      } else if (CLIENT_is_able_to_kick_reconnect(client, buffer)) {
        CLIENT_kick_reconnect(client, buffer);
nanahira's avatar
nanahira committed
3734 3735 3736 3737 3738 3739 3740 3741 3742 3743 3744 3745
      } else {
        ygopro.stoc_send_chat(client, "${deck_incorrect_reconnect}", ygopro.constants.COLORS.RED);
        ygopro.stoc_send(client, 'ERROR_MSG', {
          msg: 2,
          code: 0
        });
        ygopro.stoc_send(client, 'HS_PLAYER_CHANGE', {
          status: (client.pos << 4) | 0xa
        });
      }
      return true;
    }
mercury233's avatar
mercury233 committed
3746 3747 3748 3749
    room = ROOM_all[client.rid];
    if (!room) {
      return false;
    }
nanahira's avatar
nanahira committed
3750 3751 3752 3753
    if (info.mainc > 256 || info.sidec > 256) {
      CLIENT_kick(client);
      return true;
    }
mercury233's avatar
mercury233 committed
3754
    buff_main = (function() {
nanahira's avatar
nanahira committed
3755
      var m, ref2, results;
3756
      results = [];
nanahira's avatar
nanahira committed
3757
      for (i = m = 0, ref2 = info.mainc; 0 <= ref2 ? m < ref2 : m > ref2; i = 0 <= ref2 ? ++m : --m) {
3758
        results.push(info.deckbuf[i]);
神楽坂玲奈's avatar
11.7  
神楽坂玲奈 committed
3759
      }
3760
      return results;
神楽坂玲奈's avatar
11.7  
神楽坂玲奈 committed
3761
    })();
mercury233's avatar
mercury233 committed
3762
    buff_side = (function() {
nanahira's avatar
nanahira committed
3763
      var m, ref2, ref3, results;
3764
      results = [];
nanahira's avatar
nanahira committed
3765
      for (i = m = ref2 = info.mainc, ref3 = info.mainc + info.sidec; ref2 <= ref3 ? m < ref3 : m > ref3; i = ref2 <= ref3 ? ++m : --m) {
3766
        results.push(info.deckbuf[i]);
神楽坂玲奈's avatar
11.7  
神楽坂玲奈 committed
3767
      }
3768
      return results;
神楽坂玲奈's avatar
11.7  
神楽坂玲奈 committed
3769
    })();
mercury233's avatar
mercury233 committed
3770 3771
    client.main = buff_main;
    client.side = buff_side;
nanahira's avatar
nanahira committed
3772 3773 3774 3775 3776 3777 3778 3779
    if (room.started) {
      client.selected_preduel = true;
      if (client.side_tcount) {
        clearInterval(client.side_interval);
        client.side_interval = null;
        client.side_tcount = null;
      }
    } else {
nanahira's avatar
fix  
nanahira committed
3780
      client.start_deckbuf = Buffer.from(buffer);
nanahira's avatar
nanahira committed
3781
    }
nanahira's avatar
nanahira committed
3782
    oppo_pos = room.hostinfo.mode === 2 ? 2 : 1;
3783 3784
    if (settings.modules.http.quick_death_rule >= 2 && room.started && room.death && room.scores[room.dueling_players[0].name_vpass] !== room.scores[room.dueling_players[oppo_pos].name_vpass]) {
      win_pos = room.scores[room.dueling_players[0].name_vpass] > room.scores[room.dueling_players[oppo_pos].name_vpass] ? 0 : oppo_pos;
nanahira's avatar
nanahira committed
3785
      room.finished_by_death = true;
nanahira's avatar
nanahira committed
3786
      ygopro.stoc_send_chat_to_room(room, "${death2_finish_part1}" + room.dueling_players[win_pos].name + "${death2_finish_part2}", ygopro.constants.COLORS.BABYBLUE);
nanahira's avatar
nanahira committed
3787 3788 3789
      if (room.hostinfo.mode === 1) {
        CLIENT_send_replays(room.dueling_players[oppo_pos - win_pos], room);
      }
nanahira's avatar
nanahira committed
3790 3791 3792 3793
      ygopro.stoc_send(room.dueling_players[oppo_pos - win_pos], 'DUEL_END');
      if (room.hostinfo.mode === 2) {
        ygopro.stoc_send(room.dueling_players[oppo_pos - win_pos + 1], 'DUEL_END');
      }
3794
      room.scores[room.dueling_players[oppo_pos - win_pos].name_vpass] = -1;
nanahira's avatar
nanahira committed
3795
      CLIENT_kick(room.dueling_players[oppo_pos - win_pos]);
nanahira's avatar
nanahira committed
3796
      if (room.hostinfo.mode === 2) {
nanahira's avatar
nanahira committed
3797
        CLIENT_kick(room.dueling_players[oppo_pos - win_pos + 1]);
nanahira's avatar
nanahira committed
3798
      }
nanahira's avatar
nanahira committed
3799 3800
      return true;
    }
3801 3802 3803 3804 3805 3806 3807 3808 3809 3810 3811 3812 3813 3814
    if (settings.modules.side_restrict.enabled && room.started) {
      ref2 = settings.modules.side_restrict.restrict_cards;
      for (m = 0, len2 = ref2.length; m < len2; m++) {
        code = ref2[m];
        if (_.indexOf(buff_side, code) > -1) {
          ygopro.stoc_send_chat_to_room(room, "${invalid_side_rule}", ygopro.constants.COLORS.RED);
          ygopro.stoc_send(client, 'ERROR_MSG', {
            msg: 3,
            code: 0
          });
          return true;
        }
      }
    }
3815
    if (room.random_type || room.arena) {
nanahira's avatar
nanahira committed
3816
      if (client.pos === 0) {
mercury233's avatar
mercury233 committed
3817 3818 3819
        room.waiting_for_player = room.waiting_for_player2;
      }
      room.last_active_time = moment();
nanahira's avatar
nanahira committed
3820
    } else if (!room.started && room.hostinfo.mode === 1 && settings.modules.tournament_mode.enabled && settings.modules.tournament_mode.deck_check && fs.readdirSync(settings.modules.tournament_mode.deck_path).length) {
mercury233's avatar
mercury233 committed
3821 3822 3823 3824 3825 3826 3827 3828
      struct = ygopro.structs["deck"];
      struct._setBuff(buffer);
      struct.set("mainc", 1);
      struct.set("sidec", 1);
      struct.set("deckbuf", [4392470, 4392470]);
      buffer = struct.buffer;
      found_deck = false;
      decks = fs.readdirSync(settings.modules.tournament_mode.deck_path);
3829 3830
      for (n = 0, len3 = decks.length; n < len3; n++) {
        deck = decks[n];
mercury233's avatar
mercury233 committed
3831 3832 3833
        if (_.endsWith(deck, client.name + ".ydk")) {
          found_deck = deck;
        }
mercury233's avatar
fix  
mercury233 committed
3834 3835 3836
        if (_.endsWith(deck, client.name + ".ydk.ydk")) {
          found_deck = deck;
        }
mercury233's avatar
mercury233 committed
3837 3838
      }
      if (found_deck) {
mercury233's avatar
mercury233 committed
3839
        deck_text = fs.readFileSync(settings.modules.tournament_mode.deck_path + found_deck, {
mercury233's avatar
mercury233 committed
3840 3841 3842 3843 3844 3845
          encoding: "ASCII"
        });
        deck_array = deck_text.split("\n");
        deck_main = [];
        deck_side = [];
        current_deck = deck_main;
3846 3847
        for (o = 0, len4 = deck_array.length; o < len4; o++) {
          line = deck_array[o];
mercury233's avatar
mercury233 committed
3848 3849 3850 3851 3852 3853 3854 3855 3856 3857 3858 3859 3860 3861
          if (line.indexOf("!side") >= 0) {
            current_deck = deck_side;
          }
          card = parseInt(line);
          if (!isNaN(card)) {
            current_deck.push(card);
          }
        }
        if (_.isEqual(buff_main, deck_main) && _.isEqual(buff_side, deck_side)) {
          deckbuf = deck_main.concat(deck_side);
          struct.set("mainc", deck_main.length);
          struct.set("sidec", deck_side.length);
          struct.set("deckbuf", deckbuf);
          buffer = struct.buffer;
mercury233's avatar
mercury233 committed
3862
          ygopro.stoc_send_chat(client, "${deck_correct_part1} " + found_deck + " ${deck_correct_part2}", ygopro.constants.COLORS.BABYBLUE);
mercury233's avatar
mercury233 committed
3863
        } else {
mercury233's avatar
mercury233 committed
3864
          ygopro.stoc_send_chat(client, "${deck_incorrect_part1} " + found_deck + " ${deck_incorrect_part2}", ygopro.constants.COLORS.RED);
mercury233's avatar
mercury233 committed
3865 3866
        }
      } else {
mercury233's avatar
mercury233 committed
3867
        ygopro.stoc_send_chat(client, client.name + "${deck_not_found}", ygopro.constants.COLORS.RED);
mercury233's avatar
mercury233 committed
3868
      }
mercury233's avatar
mercury233 committed
3869
    }
mercury233's avatar
mercury233 committed
3870
    return false;
神楽坂玲奈's avatar
11.7  
神楽坂玲奈 committed
3871 3872
  });

nanahira's avatar
nanahira committed
3873
  ygopro.ctos_follow('RESPONSE', false, function(buffer, info, client, server, datas) {
3874 3875
    var room;
    room = ROOM_all[client.rid];
3876
    if (!(room && (room.random_type || room.arena))) {
3877 3878
      return;
    }
3879
    room.last_active_time = moment();
3880 3881
  });

nanahira's avatar
nanahira committed
3882
  ygopro.stoc_follow('TIME_LIMIT', true, function(buffer, info, client, server, datas) {
3883
    var check, cur_players, room;
nanahira's avatar
nanahira committed
3884
    room = ROOM_all[client.rid];
nanahira's avatar
js  
nanahira committed
3885 3886 3887
    if (!room) {
      return;
    }
nanahira's avatar
nanahira committed
3888 3889 3890 3891 3892 3893 3894
    if (settings.modules.reconnect.enabled) {
      if (client.closed) {
        ygopro.ctos_send(server, 'TIME_CONFIRM');
        return true;
      } else {
        client.time_confirm_required = true;
      }
nanahira's avatar
js  
nanahira committed
3895 3896
    }
    if (!(settings.modules.heartbeat_detection.enabled && room.turn && room.turn > 0 && !room.windbot)) {
nanahira's avatar
nanahira committed
3897 3898 3899 3900 3901 3902 3903 3904 3905 3906 3907 3908 3909 3910 3911 3912 3913 3914 3915 3916 3917 3918 3919 3920 3921 3922 3923 3924 3925 3926 3927
      return;
    }
    check = false;
    if (room.hostinfo.mode !== 2) {
      check = (client.is_first && info.player === 0) || (!client.is_first && info.player === 1);
    } else {
      cur_players = [];
      switch (room.turn % 4) {
        case 1:
          cur_players[0] = 0;
          cur_players[1] = 3;
          break;
        case 2:
          cur_players[0] = 0;
          cur_players[1] = 2;
          break;
        case 3:
          cur_players[0] = 1;
          cur_players[1] = 2;
          break;
        case 0:
          cur_players[0] = 1;
          cur_players[1] = 3;
      }
      if (!room.dueling_players[0].is_first) {
        cur_players[0] = cur_players[0] + 2;
        cur_players[1] = cur_players[1] - 2;
      }
      check = client.pos === cur_players[info.player];
    }
    if (check) {
3928
      CLIENT_heartbeat_register(client, false);
nanahira's avatar
nanahira committed
3929
    }
nanahira's avatar
js  
nanahira committed
3930
    return false;
nanahira's avatar
nanahira committed
3931 3932
  });

nanahira's avatar
nanahira committed
3933
  ygopro.ctos_follow('TIME_CONFIRM', false, function(buffer, info, client, server, datas) {
nanahira's avatar
nanahira committed
3934 3935
    var room;
    room = ROOM_all[client.rid];
nanahira's avatar
nanahira committed
3936
    if (!room) {
nanahira's avatar
nanahira committed
3937 3938
      return;
    }
nanahira's avatar
nanahira committed
3939
    if (settings.modules.reconnect.enabled) {
3940 3941 3942 3943 3944 3945 3946 3947 3948
      if (client.waiting_for_last) {
        client.waiting_for_last = false;
        if (client.last_game_msg && client.last_game_msg_title !== 'WAITING') {
          if (client.last_hint_msg) {
            ygopro.stoc_send(client, 'GAME_MSG', client.last_hint_msg);
          }
          ygopro.stoc_send(client, 'GAME_MSG', client.last_game_msg);
        }
      }
nanahira's avatar
nanahira committed
3949 3950
      client.time_confirm_required = false;
    }
3951 3952 3953 3954
    if (settings.modules.heartbeat_detection.enabled) {
      client.heartbeat_protected = false;
      client.heartbeat_responsed = true;
      CLIENT_heartbeat_unregister(client);
nanahira's avatar
typo  
nanahira committed
3955
    }
nanahira's avatar
nanahira committed
3956 3957
  });

nanahira's avatar
nanahira committed
3958
  ygopro.ctos_follow('HAND_RESULT', false, function(buffer, info, client, server, datas) {
3959 3960
    var room;
    room = ROOM_all[client.rid];
nanahira's avatar
nanahira committed
3961 3962 3963 3964 3965
    if (!room) {
      return;
    }
    client.selected_preduel = true;
    if (!(room.random_type || room.arena)) {
3966 3967
      return;
    }
nanahira's avatar
nanahira committed
3968
    if (client.pos === 0) {
3969
      room.waiting_for_player = room.waiting_for_player2;
3970
    }
mercury233's avatar
mercury233 committed
3971
    room.last_active_time = moment().subtract(settings.modules.random_duel.hang_timeout - 19, 's');
3972 3973
  });

nanahira's avatar
nanahira committed
3974
  ygopro.ctos_follow('TP_RESULT', false, function(buffer, info, client, server, datas) {
3975 3976
    var room;
    room = ROOM_all[client.rid];
nanahira's avatar
nanahira committed
3977 3978 3979 3980 3981
    if (!room) {
      return;
    }
    client.selected_preduel = true;
    if (!(room.random_type || room.arena)) {
3982 3983
      return;
    }
3984
    room.last_active_time = moment();
3985 3986
  });

nanahira's avatar
nanahira committed
3987
  ygopro.stoc_follow('CHAT', true, function(buffer, info, client, server, datas) {
nanahira's avatar
nanahira committed
3988
    var len2, m, pid, player, ref2, room, tcolor, tplayer;
nanahira's avatar
nanahira committed
3989 3990
    room = ROOM_all[client.rid];
    pid = info.player;
nanahira's avatar
fix  
nanahira committed
3991
    if (!(room && pid < 4 && settings.modules.chat_color.enabled && (!settings.modules.hide_name || room.started))) {
nanahira's avatar
nanahira committed
3992 3993
      return;
    }
nanahira's avatar
fix  
nanahira committed
3994 3995
    if (room.started && room.turn > 0 && !room.dueling_players[0].is_first) {
      if (room.hostinfo.mode === 2) {
nanahira's avatar
fix  
nanahira committed
3996 3997 3998 3999 4000 4001
        pid = {
          0: 2,
          1: 3,
          2: 0,
          3: 1
        }[pid];
nanahira's avatar
fix  
nanahira committed
4002 4003 4004 4005
      } else {
        pid = 1 - pid;
      }
    }
nanahira's avatar
nanahira committed
4006
    ref2 = room.players;
nanahira's avatar
nanahira committed
4007 4008
    for (m = 0, len2 = ref2.length; m < len2; m++) {
      player = ref2[m];
nanahira's avatar
nanahira committed
4009 4010 4011 4012 4013 4014 4015
      if (player && player.pos === pid) {
        tplayer = player;
      }
    }
    if (!tplayer) {
      return;
    }
nanahira's avatar
fi  
nanahira committed
4016
    tcolor = chat_color.save_list[CLIENT_get_authorize_key(tplayer)];
nanahira's avatar
nanahira committed
4017 4018 4019 4020 4021 4022 4023 4024 4025
    if (tcolor) {
      ygopro.stoc_send(client, 'CHAT', {
        player: ygopro.constants.COLORS[tcolor],
        msg: tplayer.name + ": " + info.msg
      });
      return true;
    }
  });

nanahira's avatar
nanahira committed
4026
  ygopro.stoc_follow('SELECT_HAND', false, function(buffer, info, client, server, datas) {
4027 4028
    var room;
    room = ROOM_all[client.rid];
nanahira's avatar
nanahira committed
4029 4030 4031 4032 4033 4034 4035 4036 4037
    if (!room) {
      return;
    }
    client.selected_preduel = false;
    if (client.pos === 0) {
      room.selecting_hand = true;
      room.changing_side = false;
    }
    if (!(room.random_type || room.arena)) {
4038 4039
      return;
    }
nanahira's avatar
nanahira committed
4040
    if (client.pos === 0) {
4041
      room.waiting_for_player = client;
4042
    } else {
4043
      room.waiting_for_player2 = client;
4044
    }
mercury233's avatar
mercury233 committed
4045
    room.last_active_time = moment().subtract(settings.modules.random_duel.hang_timeout - 19, 's');
4046 4047
  });

nanahira's avatar
nanahira committed
4048
  ygopro.stoc_follow('SELECT_TP', false, function(buffer, info, client, server, datas) {
4049 4050
    var room;
    room = ROOM_all[client.rid];
4051
    if (!room) {
4052 4053
      return;
    }
nanahira's avatar
nanahira committed
4054
    client.selected_preduel = false;
4055
    room.changing_side = false;
nanahira's avatar
nanahira committed
4056 4057
    room.selecting_hand = false;
    room.selecting_tp = client;
mercury233's avatar
fix  
mercury233 committed
4058
    if (room.random_type || room.arena) {
4059 4060 4061
      room.waiting_for_player = client;
      room.last_active_time = moment();
    }
4062 4063
  });

nanahira's avatar
nanahira committed
4064
  ygopro.stoc_follow('CHANGE_SIDE', false, function(buffer, info, client, server, datas) {
nanahira's avatar
js  
nanahira committed
4065
    var room, room_name, sinterval, temp_log;
4066
    room = ROOM_all[client.rid];
4067
    if (!room) {
mercury233's avatar
mercury233 committed
4068 4069
      return;
    }
4070
    room.changing_side = true;
nanahira's avatar
nanahira committed
4071
    client.selected_preduel = false;
nanahira's avatar
nanahira committed
4072 4073 4074 4075 4076 4077 4078 4079 4080
    if (settings.modules.side_timeout) {
      client.side_tcount = settings.modules.side_timeout;
      ygopro.stoc_send_chat(client, "${side_timeout_part1}" + settings.modules.side_timeout + "${side_timeout_part2}", ygopro.constants.COLORS.BABYBLUE);
      sinterval = setInterval(function() {
        if (!(room && room.started && client && client.side_tcount && room.changing_side)) {
          clearInterval(sinterval);
          return;
        }
        if (client.side_tcount === 1) {
nanahira's avatar
fix  
nanahira committed
4081
          ygopro.stoc_send_chat_to_room(room, client.name + "${side_overtime_room}", ygopro.constants.COLORS.BABYBLUE);
nanahira's avatar
nanahira committed
4082
          ygopro.stoc_send_chat(client, "${side_overtime}", ygopro.constants.COLORS.RED);
nanahira's avatar
nanahira committed
4083
          CLIENT_send_replays(client, room);
nanahira's avatar
nanahira committed
4084
          CLIENT_kick(client);
nanahira's avatar
nanahira committed
4085 4086 4087
          return clearInterval(sinterval);
        } else {
          client.side_tcount = client.side_tcount - 1;
nanahira's avatar
js  
nanahira committed
4088
          return ygopro.stoc_send_chat(client, "${side_remain_part1}" + client.side_tcount + "${side_remain_part2}", ygopro.constants.COLORS.BABYBLUE);
nanahira's avatar
nanahira committed
4089 4090 4091 4092
        }
      }, 60000);
      client.side_interval = sinterval;
    }
nanahira's avatar
js  
nanahira committed
4093
    if (settings.modules.challonge.enabled && settings.modules.challonge.post_score_midduel && room.hostinfo.mode !== 2 && client.pos === 0) {
nanahira's avatar
nanahira committed
4094
      temp_log = JSON.parse(JSON.stringify(room.get_challonge_score()));
nanahira's avatar
nanahira committed
4095
      delete temp_log.winnerId;
nanahira's avatar
js  
nanahira committed
4096
      room_name = room.name;
nanahira's avatar
nanahira committed
4097
      challonge.matches._update({
4098
        id: settings.modules.challonge.tournament_id,
nanahira's avatar
nanahira committed
4099 4100 4101 4102
        matchId: room.challonge_info.id,
        match: temp_log,
        callback: function(err, data) {
          if (err) {
nanahira's avatar
js  
nanahira committed
4103
            log.warn("Errored pushing scores to Challonge.", room_name, err);
nanahira's avatar
nanahira committed
4104 4105
          } else {
            refresh_challonge_cache();
nanahira's avatar
nanahira committed
4106 4107 4108 4109
          }
        }
      });
    }
4110
    if (room.random_type || room.arena) {
nanahira's avatar
nanahira committed
4111
      if (client.pos === 0) {
4112 4113 4114 4115 4116
        room.waiting_for_player = client;
      } else {
        room.waiting_for_player2 = client;
      }
      room.last_active_time = moment();
mercury233's avatar
mercury233 committed
4117 4118 4119
    }
  });

nanahira's avatar
nanahira committed
4120
  ygopro.stoc_follow('REPLAY', true, function(buffer, info, client, server, datas) {
nanahira's avatar
nanahira committed
4121
    var duellog, dueltime, i, len2, len3, m, n, player, ref2, ref3, replay_filename, room;
4122 4123
    room = ROOM_all[client.rid];
    if (!room) {
mercury233's avatar
fix  
mercury233 committed
4124
      return settings.modules.tournament_mode.enabled && settings.modules.tournament_mode.replay_safe && settings.modules.tournament_mode.block_replay_to_player || settings.modules.replay_delay;
4125
    }
mercury233's avatar
mercury233 committed
4126
    if (settings.modules.cloud_replay.enabled && room.random_type) {
mercury233's avatar
fix  
mercury233 committed
4127 4128
      Cloud_replay_ids.push(room.cloud_replay_id);
    }
nanahira's avatar
nanahira committed
4129
    if (settings.modules.replay_delay && room.hostinfo.mode === 1 && !(settings.modules.tournament_mode.enabled && settings.modules.tournament_mode.replay_safe && settings.modules.tournament_mode.block_replay_to_player) && !room.replays[room.duel_count - 1]) {
4130
      room.replays[room.duel_count - 1] = buffer;
nanahira's avatar
nanahira committed
4131
    }
mercury233's avatar
mercury233 committed
4132
    if (settings.modules.tournament_mode.enabled && settings.modules.tournament_mode.replay_safe) {
nanahira's avatar
nanahira committed
4133
      if (client.pos === 0) {
nanahira's avatar
nanahira committed
4134
        dueltime = moment().format('YYYY-MM-DD HH-mm-ss');
mercury233's avatar
mercury233 committed
4135
        replay_filename = dueltime;
nanahira's avatar
fix  
nanahira committed
4136
        if (room.hostinfo.mode !== 2) {
nanahira's avatar
nanahira committed
4137
          ref2 = room.dueling_players;
nanahira's avatar
nanahira committed
4138
          for (i = m = 0, len2 = ref2.length; m < len2; i = ++m) {
nanahira's avatar
nanahira committed
4139
            player = ref2[i];
nanahira's avatar
nanahira committed
4140 4141 4142
            replay_filename = replay_filename + (i > 0 ? " VS " : " ") + player.name;
          }
        } else {
nanahira's avatar
nanahira committed
4143
          ref3 = room.dueling_players;
nanahira's avatar
nanahira committed
4144
          for (i = n = 0, len3 = ref3.length; n < len3; i = ++n) {
nanahira's avatar
nanahira committed
4145
            player = ref3[i];
nanahira's avatar
nanahira committed
4146 4147
            replay_filename = replay_filename + (i > 0 ? (i === 2 ? " VS " : " & ") : " ") + player.name;
          }
mercury233's avatar
mercury233 committed
4148 4149
        }
        replay_filename = replay_filename.replace(/[\/\\\?\*]/g, '_') + ".yrp";
mercury233's avatar
mercury233 committed
4150
        duellog = {
mercury233's avatar
mercury233 committed
4151
          time: dueltime,
4152
          name: room.name + (settings.modules.tournament_mode.show_info ? " (Duel:" + room.duel_count + ")" : ""),
nanahira's avatar
nanahira committed
4153
          roomid: room.process_pid.toString(),
mercury233's avatar
mercury233 committed
4154
          cloud_replay_id: "R#" + room.cloud_replay_id,
mercury233's avatar
mercury233 committed
4155
          replay_filename: replay_filename,
nanahira's avatar
nanahira committed
4156
          roommode: room.hostinfo.mode,
mercury233's avatar
mercury233 committed
4157
          players: (function() {
nanahira's avatar
nanahira committed
4158
            var len4, o, ref4, results;
nanahira's avatar
nanahira committed
4159
            ref4 = room.dueling_players;
mercury233's avatar
mercury233 committed
4160
            results = [];
nanahira's avatar
nanahira committed
4161 4162
            for (o = 0, len4 = ref4.length; o < len4; o++) {
              player = ref4[o];
mercury233's avatar
mercury233 committed
4163
              results.push({
4164
                name: player.name + (settings.modules.tournament_mode.show_ip && !player.is_local ? " (IP: " + player.ip.slice(7) + ")" : "") + (settings.modules.tournament_mode.show_info && !(room.hostinfo.mode === 2 && player.pos % 2 > 0) ? " (Score:" + room.scores[player.name_vpass] + " LP:" + (player.lp != null ? player.lp : room.hostinfo.start_lp) + (room.hostinfo.mode !== 2 ? " Cards:" + (player.card_count != null ? player.card_count : room.hostinfo.start_hand) : "") + ")" : ""),
mercury233's avatar
mercury233 committed
4165 4166 4167 4168 4169 4170
                winner: player.pos === room.winner
              });
            }
            return results;
          })()
        };
mercury233's avatar
mercury233 committed
4171 4172
        duel_log.duel_log.unshift(duellog);
        setting_save(duel_log);
mercury233's avatar
mercury233 committed
4173 4174 4175 4176 4177
        fs.writeFile(settings.modules.tournament_mode.replay_path + replay_filename, buffer, function(err) {
          if (err) {
            return log.warn("SAVE REPLAY ERROR", replay_filename, err);
          }
        });
mercury233's avatar
mercury233 committed
4178
      }
mercury233's avatar
mercury233 committed
4179
      if (settings.modules.cloud_replay.enabled) {
mercury233's avatar
mercury233 committed
4180
        ygopro.stoc_send_chat(client, "${cloud_replay_delay_part1}R#" + room.cloud_replay_id + "${cloud_replay_delay_part2}", ygopro.constants.COLORS.BABYBLUE);
mercury233's avatar
mercury233 committed
4181
      }
nanahira's avatar
nanahira committed
4182
      return settings.modules.tournament_mode.block_replay_to_player || settings.modules.replay_delay && room.hostinfo.mode === 1;
4183
    } else {
nanahira's avatar
nanahira committed
4184
      return settings.modules.replay_delay && room.hostinfo.mode === 1;
4185 4186 4187
    }
  });

mercury233's avatar
mercury233 committed
4188
  if (settings.modules.random_duel.enabled) {
mercury233's avatar
mercury233 committed
4189
    setInterval(function() {
nanahira's avatar
nanahira committed
4190 4191 4192
      var len2, m, room, time_passed;
      for (m = 0, len2 = ROOM_all.length; m < len2; m++) {
        room = ROOM_all[m];
4193
        if (!(room && room.started && room.random_type && room.last_active_time && room.waiting_for_player && room.get_disconnected_count() === 0)) {
mercury233's avatar
mercury233 committed
4194 4195 4196
          continue;
        }
        time_passed = Math.floor((moment() - room.last_active_time) / 1000);
4197
        if (time_passed >= settings.modules.random_duel.hang_timeout) {
mercury233's avatar
mercury233 committed
4198
          room.last_active_time = moment();
mercury233's avatar
mercury233 committed
4199
          ROOM_ban_player(room.waiting_for_player.name, room.waiting_for_player.ip, "${random_ban_reason_AFK}");
4200
          room.scores[room.waiting_for_player.name_vpass] = -9;
mercury233's avatar
mercury233 committed
4201
          ygopro.stoc_send_chat_to_room(room, room.waiting_for_player.name + " ${kicked_by_system}", ygopro.constants.COLORS.RED);
nanahira's avatar
nanahira committed
4202
          CLIENT_send_replays(room.waiting_for_player, room);
nanahira's avatar
js  
nanahira committed
4203
          CLIENT_kick(room.waiting_for_player);
4204
        } else if (time_passed >= (settings.modules.random_duel.hang_timeout - 20) && !(time_passed % 10)) {
mercury233's avatar
mercury233 committed
4205
          ygopro.stoc_send_chat_to_room(room, room.waiting_for_player.name + " ${afk_warn_part1}" + (settings.modules.random_duel.hang_timeout - time_passed) + "${afk_warn_part2}", ygopro.constants.COLORS.RED);
mercury233's avatar
mercury233 committed
4206
          ROOM_unwelcome(room, room.waiting_for_player, "${random_ban_reason_AFK}");
mercury233's avatar
mercury233 committed
4207
        }
4208
      }
mercury233's avatar
mercury233 committed
4209 4210 4211
    }, 1000);
  }

4212 4213
  if (settings.modules.mycard.enabled) {
    setInterval(function() {
nanahira's avatar
nanahira committed
4214
      var len2, len3, m, n, player, room, time_passed, waited_time;
nanahira's avatar
nanahira committed
4215 4216
      for (m = 0, len2 = ROOM_all.length; m < len2; m++) {
        room = ROOM_all[m];
4217
        if (!(room && room.started && room.arena && room.last_active_time && room.waiting_for_player && room.get_disconnected_count() === 0)) {
4218 4219 4220
          continue;
        }
        time_passed = Math.floor((moment() - room.last_active_time) / 1000);
4221
        if (time_passed >= settings.modules.random_duel.hang_timeout) {
4222 4223
          room.last_active_time = moment();
          ygopro.stoc_send_chat_to_room(room, room.waiting_for_player.name + " ${kicked_by_system}", ygopro.constants.COLORS.RED);
4224
          room.scores[room.waiting_for_player.name_vpass] = -9;
nanahira's avatar
nanahira committed
4225
          CLIENT_send_replays(room.waiting_for_player, room);
nanahira's avatar
js  
nanahira committed
4226
          CLIENT_kick(room.waiting_for_player);
4227
        } else if (time_passed >= (settings.modules.random_duel.hang_timeout - 20) && !(time_passed % 10)) {
4228 4229 4230
          ygopro.stoc_send_chat_to_room(room, room.waiting_for_player.name + " ${afk_warn_part1}" + (settings.modules.random_duel.hang_timeout - time_passed) + "${afk_warn_part2}", ygopro.constants.COLORS.RED);
        }
      }
nanahira's avatar
nanahira committed
4231 4232 4233 4234 4235 4236
      for (n = 0, len3 = ROOM_all.length; n < len3; n++) {
        room = ROOM_all[n];
        if (!(room && room.arena && !room.started && room.get_playing_player().length < 2)) {
          continue;
        }
        player = room.get_playing_player()[0];
nanahira's avatar
fix  
nanahira committed
4237
        if (player && player.join_time && !player.arena_quit_free) {
nanahira's avatar
nanahira committed
4238 4239 4240 4241 4242 4243 4244 4245 4246
          waited_time = moment() - player.join_time;
          if (waited_time >= 30000) {
            ygopro.stoc_send_chat(player, "${arena_wait_timeout}", ygopro.constants.COLORS.BABYBLUE);
            player.arena_quit_free = true;
          } else if (waited_time >= 5000 && waited_time < 6000) {
            ygopro.stoc_send_chat(player, "${arena_wait_hint}", ygopro.constants.COLORS.BABYBLUE);
          }
        }
      }
4247 4248 4249
    }, 1000);
  }

nanahira's avatar
nanahira committed
4250 4251 4252 4253 4254
  if (settings.modules.heartbeat_detection.enabled) {
    setInterval(function() {
      var len2, len3, m, n, player, ref2, room;
      for (m = 0, len2 = ROOM_all.length; m < len2; m++) {
        room = ROOM_all[m];
nanahira's avatar
js  
nanahira committed
4255
        if (room && room.started && (room.hostinfo.time_limit === 0 || !room.turn || room.turn <= 0) && !room.windbot) {
nanahira's avatar
fix  
nanahira committed
4256
          ref2 = room.get_playing_player();
nanahira's avatar
nanahira committed
4257 4258
          for (n = 0, len3 = ref2.length; n < len3; n++) {
            player = ref2[n];
nanahira's avatar
fix  
nanahira committed
4259
            if (player && (!room.changing_side || player.selected_preduel)) {
nanahira's avatar
nanahira committed
4260 4261 4262 4263 4264 4265 4266 4267
              CLIENT_heartbeat_register(player, true);
            }
          }
        }
      }
    }, settings.modules.heartbeat_detection.interval);
  }

nanahira's avatar
nanahira committed
4268 4269 4270 4271
  windbot_looplimit = 0;

  spawn_windbot = function() {
    var windbot_bin, windbot_parameters, windbot_process;
mercury233's avatar
mercury233 committed
4272 4273 4274 4275 4276 4277 4278 4279 4280 4281
    if (/^win/.test(process.platform)) {
      windbot_bin = 'WindBot.exe';
      windbot_parameters = [];
    } else {
      windbot_bin = 'mono';
      windbot_parameters = ['WindBot.exe'];
    }
    windbot_parameters.push('ServerMode=true');
    windbot_parameters.push('ServerPort=' + settings.modules.windbot.port);
    windbot_process = spawn(windbot_bin, windbot_parameters, {
mercury233's avatar
mercury233 committed
4282 4283 4284 4285
      cwd: 'windbot'
    });
    windbot_process.on('error', function(err) {
      log.warn('WindBot ERROR', err);
nanahira's avatar
nanahira committed
4286 4287 4288 4289
      if (windbot_looplimit < 1000) {
        windbot_looplimit++;
        spawn_windbot();
      }
mercury233's avatar
mercury233 committed
4290 4291 4292
    });
    windbot_process.on('exit', function(code) {
      log.warn('WindBot EXIT', code);
nanahira's avatar
nanahira committed
4293 4294 4295 4296
      if (windbot_looplimit < 1000) {
        windbot_looplimit++;
        spawn_windbot();
      }
mercury233's avatar
mercury233 committed
4297 4298 4299 4300 4301
    });
    windbot_process.stdout.setEncoding('utf8');
    windbot_process.stdout.on('data', function(data) {
      log.info('WindBot:', data);
    });
mercury233's avatar
fix  
mercury233 committed
4302
    windbot_process.stderr.setEncoding('utf8');
nanahira's avatar
nanahira committed
4303
    windbot_process.stderr.on('data', function(data) {
mercury233's avatar
mercury233 committed
4304 4305
      log.warn('WindBot Error:', data);
    });
nanahira's avatar
nanahira committed
4306 4307 4308 4309
  };

  if (settings.modules.windbot.enabled && settings.modules.windbot.spawn) {
    spawn_windbot();
mercury233's avatar
mercury233 committed
4310
  }
4311

神楽坂玲奈's avatar
11.7  
神楽坂玲奈 committed
4312
  if (settings.modules.http) {
mercury233's avatar
mercury233 committed
4313 4314 4315 4316 4317 4318
    addCallback = function(callback, text) {
      if (!callback) {
        return text;
      }
      return callback + "( " + text + " );";
    };
4319
    requestListener = function(request, response) {
nanahira's avatar
nanahira committed
4320
      var archive_args, archive_name, archive_process, check, death_room_found, duellog, error, filename, getpath, kick_room_found, len2, len3, len4, len5, len6, m, n, o, p, parseQueryString, pass_validated, player, q, ref2, replay, room, roomsjson, u;
4321 4322 4323
      parseQueryString = true;
      u = url.parse(request.url, parseQueryString);
      if (u.pathname === '/api/getrooms') {
nanahira's avatar
fix  
nanahira committed
4324 4325
        pass_validated = auth.auth(u.query.username, u.query.pass, "get_rooms", "get_rooms");
        if (!settings.modules.http.public_roomlist && !pass_validated) {
4326
          response.writeHead(200);
mercury233's avatar
mercury233 committed
4327
          response.end(addCallback(u.query.callback, '{"rooms":[{"roomid":"0","roomname":"密码错误","needpass":"true"}]}'));
4328 4329 4330 4331
        } else {
          response.writeHead(200);
          roomsjson = JSON.stringify({
            rooms: (function() {
nanahira's avatar
nanahira committed
4332
              var len2, m, results;
4333
              results = [];
nanahira's avatar
nanahira committed
4334 4335
              for (m = 0, len2 = ROOM_all.length; m < len2; m++) {
                room = ROOM_all[m];
4336
                if (room && room.established) {
4337
                  results.push({
nanahira's avatar
nanahira committed
4338
                    roomid: room.process_pid.toString(),
4339
                    roomname: pass_validated ? room.name : room.name.split('$', 2)[0],
nanahira's avatar
fix  
nanahira committed
4340
                    roommode: room.hostinfo.mode,
4341
                    needpass: (room.name.indexOf('$') !== -1).toString(),
mercury233's avatar
mercury233 committed
4342
                    users: _.sortBy((function() {
nanahira's avatar
nanahira committed
4343
                      var len3, n, ref2, results1;
nanahira's avatar
nanahira committed
4344
                      ref2 = room.players;
4345
                      results1 = [];
nanahira's avatar
nanahira committed
4346 4347
                      for (n = 0, len3 = ref2.length; n < len3; n++) {
                        player = ref2[n];
4348 4349 4350
                        if (player.pos != null) {
                          results1.push({
                            id: (-1).toString(),
mercury233's avatar
mercury233 committed
4351 4352 4353 4354 4355 4356 4357
                            name: player.name,
                            ip: settings.modules.http.show_ip && pass_validated && !player.is_local ? player.ip.slice(7) : null,
                            status: settings.modules.http.show_info && room.started && player.pos !== 7 ? {
                              score: room.scores[player.name_vpass],
                              lp: player.lp != null ? player.lp : room.hostinfo.start_lp,
                              cards: room.hostinfo.mode !== 2 ? (player.card_count != null ? player.card_count : room.hostinfo.start_hand) : null
                            } : null,
4358 4359 4360
                            pos: player.pos
                          });
                        }
神楽坂玲奈's avatar
11.7  
神楽坂玲奈 committed
4361
                      }
4362
                      return results1;
mercury233's avatar
mercury233 committed
4363
                    })(), "pos"),
nanahira's avatar
nanahira committed
4364
                    istart: room.started ? (settings.modules.http.show_info ? "Duel:" + room.duel_count + " " + (room.changing_side ? "Siding" : "Turn:" + (room.turn != null ? room.turn : 0) + (room.death ? "/" + (room.death > 0 ? room.death - 1 : "Death") : "")) : 'start') : 'wait'
4365 4366
                  });
                }
神楽坂玲奈's avatar
11.7  
神楽坂玲奈 committed
4367
              }
4368 4369
              return results;
            })()
mercury233's avatar
mercury233 committed
4370 4371
          }, null, 2);
          response.end(addCallback(u.query.callback, roomsjson));
4372
        }
mercury233's avatar
mercury233 committed
4373
      } else if (u.pathname === '/api/duellog' && settings.modules.tournament_mode.enabled) {
nanahira's avatar
nanahira committed
4374
        if (!auth.auth(u.query.username, u.query.pass, "duel_log", "duel_log")) {
mercury233's avatar
mercury233 committed
4375
          response.writeHead(200);
mercury233's avatar
mercury233 committed
4376
          response.end(addCallback(u.query.callback, "[{name:'密码错误'}]"));
mercury233's avatar
mercury233 committed
4377 4378 4379
          return;
        } else {
          response.writeHead(200);
mercury233's avatar
mercury233 committed
4380
          duellog = JSON.stringify(duel_log.duel_log, null, 2);
mercury233's avatar
mercury233 committed
4381
          response.end(addCallback(u.query.callback, duellog));
mercury233's avatar
mercury233 committed
4382
        }
nanahira's avatar
nanahira committed
4383
      } else if (u.pathname === '/api/archive.zip' && settings.modules.tournament_mode.enabled) {
nanahira's avatar
nanahira committed
4384
        if (!auth.auth(u.query.username, u.query.pass, "download_replay", "download_replay_archive")) {
nanahira's avatar
nanahira committed
4385 4386 4387 4388 4389
          response.writeHead(403);
          response.end("Invalid password.");
          return;
        } else {
          try {
nanahira's avatar
nanahira committed
4390
            archive_name = moment().format('YYYY-MM-DD HH-mm-ss') + ".zip";
nanahira's avatar
nanahira committed
4391
            archive_args = ["a", "-mx0", "-y", archive_name];
nanahira's avatar
fix  
nanahira committed
4392
            check = false;
nanahira's avatar
nanahira committed
4393
            ref2 = duel_log.duel_log;
nanahira's avatar
nanahira committed
4394 4395
            for (m = 0, len2 = ref2.length; m < len2; m++) {
              replay = ref2[m];
nanahira's avatar
fix  
nanahira committed
4396
              check = true;
nanahira's avatar
nanahira committed
4397 4398
              archive_args.push(replay.replay_filename);
            }
nanahira's avatar
fix  
nanahira committed
4399 4400 4401 4402 4403
            if (!check) {
              response.writeHead(403);
              response.end("Duel logs not found.");
              return;
            }
nanahira's avatar
nanahira committed
4404 4405 4406
            archive_process = spawn(settings.modules.tournament_mode.replay_archive_tool, archive_args, {
              cwd: settings.modules.tournament_mode.replay_path
            });
nanahira's avatar
js  
nanahira committed
4407 4408 4409 4410 4411 4412 4413 4414 4415 4416 4417 4418 4419 4420 4421 4422 4423 4424 4425 4426 4427 4428
            archive_process.on('error', (function(_this) {
              return function(err) {
                response.writeHead(403);
                response.end("Failed packing replays. " + err);
              };
            })(this));
            archive_process.on('exit', (function(_this) {
              return function(code) {
                return fs.readFile(settings.modules.tournament_mode.replay_path + archive_name, function(error, buffer) {
                  if (error) {
                    response.writeHead(403);
                    response.end("Failed sending replays. " + error);
                  } else {
                    response.writeHead(200, {
                      "Content-Type": "application/octet-stream",
                      "Content-Disposition": "attachment"
                    });
                    response.end(buffer);
                  }
                });
              };
            })(this));
nanahira's avatar
nanahira committed
4429
            archive_process.stdout.setEncoding('utf8');
nanahira's avatar
js  
nanahira committed
4430 4431 4432 4433 4434
            archive_process.stdout.on('data', (function(_this) {
              return function(data) {
                return log.info("archive process: " + data);
              };
            })(this));
nanahira's avatar
nanahira committed
4435
            archive_process.stderr.setEncoding('utf8');
nanahira's avatar
js  
nanahira committed
4436 4437 4438 4439 4440
            archive_process.stderr.on('data', (function(_this) {
              return function(data) {
                return log.warn("archive error: " + data);
              };
            })(this));
nanahira's avatar
nanahira committed
4441 4442 4443 4444 4445 4446
          } catch (error1) {
            error = error1;
            response.writeHead(403);
            response.end("Failed reading replays. " + error);
          }
        }
nanahira's avatar
nanahira committed
4447
      } else if (u.pathname === '/api/clearlog' && settings.modules.tournament_mode.enabled) {
nanahira's avatar
nanahira committed
4448
        if (!auth.auth(u.query.username, u.query.pass, "clear_duel_log", "clear_duel_log")) {
nanahira's avatar
nanahira committed
4449 4450 4451 4452 4453
          response.writeHead(200);
          response.end(addCallback(u.query.callback, "[{name:'密码错误'}]"));
          return;
        } else {
          response.writeHead(200);
4454 4455 4456 4457 4458 4459 4460
          if (settings.modules.tournament_mode.log_save_path) {
            fs.writeFile(settings.modules.tournament_mode.log_save_path + 'duel_log.' + moment().format('YYYY-MM-DD HH-mm-ss') + '.json', JSON.stringify(duel_log, null, 2), function(err) {
              if (err) {
                return log.warn('DUEL LOG SAVE ERROR', err);
              }
            });
          }
4461 4462
          duel_log.duel_log = [];
          setting_save(duel_log);
nanahira's avatar
nanahira committed
4463 4464
          response.end(addCallback(u.query.callback, "[{name:'Success'}]"));
        }
mercury233's avatar
mercury233 committed
4465
      } else if (_.startsWith(u.pathname, '/api/replay') && settings.modules.tournament_mode.enabled) {
nanahira's avatar
nanahira committed
4466
        if (!auth.auth(u.query.username, u.query.pass, "download_replay", "download_replay")) {
mercury233's avatar
mercury233 committed
4467 4468 4469 4470 4471 4472 4473 4474 4475
          response.writeHead(403);
          response.end("密码错误");
          return;
        } else {
          getpath = u.pathname.split("/");
          filename = decodeURIComponent(getpath.pop());
          fs.readFile(settings.modules.tournament_mode.replay_path + filename, function(error, buffer) {
            if (error) {
              response.writeHead(404);
mercury233's avatar
fix  
mercury233 committed
4476
              response.end("未找到文件 " + filename);
mercury233's avatar
mercury233 committed
4477 4478 4479 4480 4481
            } else {
              response.writeHead(200, {
                "Content-Type": "application/octet-stream",
                "Content-Disposition": "attachment"
              });
mercury233's avatar
fix  
mercury233 committed
4482
              response.end(buffer);
mercury233's avatar
mercury233 committed
4483 4484 4485
            }
          });
        }
4486 4487
      } else if (u.pathname === '/api/message') {
        if (u.query.shout) {
nanahira's avatar
nanahira committed
4488 4489 4490 4491 4492
          if (!auth.auth(u.query.username, u.query.pass, "shout", "shout")) {
            response.writeHead(200);
            response.end(addCallback(u.query.callback, "['密码错误', 0]"));
            return;
          }
nanahira's avatar
nanahira committed
4493 4494
          for (n = 0, len3 = ROOM_all.length; n < len3; n++) {
            room = ROOM_all[n];
4495 4496 4497
            if (room && room.established) {
              ygopro.stoc_send_chat_to_room(room, u.query.shout, ygopro.constants.COLORS.YELLOW);
            }
4498 4499
          }
          response.writeHead(200);
mercury233's avatar
mercury233 committed
4500
          response.end(addCallback(u.query.callback, "['shout ok', '" + u.query.shout + "']"));
4501
        } else if (u.query.stop) {
nanahira's avatar
nanahira committed
4502 4503 4504 4505 4506
          if (!auth.auth(u.query.username, u.query.pass, "stop", "stop")) {
            response.writeHead(200);
            response.end(addCallback(u.query.callback, "['密码错误', 0]"));
            return;
          }
4507 4508 4509
          if (u.query.stop === 'false') {
            u.query.stop = false;
          }
mercury233's avatar
mercury233 committed
4510
          setting_change(settings, 'modules:stop', u.query.stop);
4511
          response.writeHead(200);
mercury233's avatar
mercury233 committed
4512
          response.end(addCallback(u.query.callback, "['stop ok', '" + u.query.stop + "']"));
4513
        } else if (u.query.welcome) {
nanahira's avatar
nanahira committed
4514 4515 4516 4517 4518
          if (!auth.auth(u.query.username, u.query.pass, "change_settings", "change_welcome")) {
            response.writeHead(200);
            response.end(addCallback(u.query.callback, "['密码错误', 0]"));
            return;
          }
mercury233's avatar
mercury233 committed
4519
          setting_change(settings, 'modules:welcome', u.query.welcome);
mercury233's avatar
mercury233 committed
4520
          response.writeHead(200);
mercury233's avatar
mercury233 committed
4521
          response.end(addCallback(u.query.callback, "['welcome ok', '" + u.query.welcome + "']"));
mercury233's avatar
mercury233 committed
4522
        } else if (u.query.getwelcome) {
nanahira's avatar
nanahira committed
4523 4524 4525 4526 4527
          if (!auth.auth(u.query.username, u.query.pass, "change_settings", "get_welcome")) {
            response.writeHead(200);
            response.end(addCallback(u.query.callback, "['密码错误', 0]"));
            return;
          }
4528
          response.writeHead(200);
mercury233's avatar
mercury233 committed
4529
          response.end(addCallback(u.query.callback, "['get ok', '" + settings.modules.welcome + "']"));
mercury233's avatar
mercury233 committed
4530
        } else if (u.query.loadtips) {
nanahira's avatar
nanahira committed
4531 4532 4533 4534 4535
          if (!auth.auth(u.query.username, u.query.pass, "change_settings", "change_tips")) {
            response.writeHead(200);
            response.end(addCallback(u.query.callback, "['密码错误', 0]"));
            return;
          }
mercury233's avatar
mercury233 committed
4536 4537
          load_tips();
          response.writeHead(200);
mercury233's avatar
mercury233 committed
4538
          response.end(addCallback(u.query.callback, "['loading tip', '" + settings.modules.tips.get + "']"));
mercury233's avatar
mercury233 committed
4539
        } else if (u.query.loaddialogues) {
nanahira's avatar
nanahira committed
4540 4541 4542 4543 4544
          if (!auth.auth(u.query.username, u.query.pass, "change_settings", "change_dialogues")) {
            response.writeHead(200);
            response.end(addCallback(u.query.callback, "['密码错误', 0]"));
            return;
          }
mercury233's avatar
mercury233 committed
4545 4546
          load_dialogues();
          response.writeHead(200);
mercury233's avatar
mercury233 committed
4547
          response.end(addCallback(u.query.callback, "['loading dialogues', '" + settings.modules.dialogues.get + "']"));
mercury233's avatar
mercury233 committed
4548
        } else if (u.query.ban) {
nanahira's avatar
nanahira committed
4549 4550 4551 4552 4553
          if (!auth.auth(u.query.username, u.query.pass, "ban_user", "ban_user")) {
            response.writeHead(200);
            response.end(addCallback(u.query.callback, "['密码错误', 0]"));
            return;
          }
mercury233's avatar
mercury233 committed
4554
          ban_user(u.query.ban);
mercury233's avatar
mercury233 committed
4555
          response.writeHead(200);
mercury233's avatar
mercury233 committed
4556
          response.end(addCallback(u.query.callback, "['ban ok', '" + u.query.ban + "']"));
nanahira's avatar
nanahira committed
4557
        } else if (u.query.kick) {
nanahira's avatar
nanahira committed
4558 4559 4560 4561 4562
          if (!auth.auth(u.query.username, u.query.pass, "kick_user", "kick_user")) {
            response.writeHead(200);
            response.end(addCallback(u.query.callback, "['密码错误', 0]"));
            return;
          }
nanahira's avatar
nanahira committed
4563
          kick_room_found = false;
nanahira's avatar
nanahira committed
4564 4565
          for (o = 0, len4 = ROOM_all.length; o < len4; o++) {
            room = ROOM_all[o];
nanahira's avatar
nanahira committed
4566
            if (!(room && room.established && (u.query.kick === "all" || u.query.kick === room.process_pid.toString() || u.query.kick === room.name))) {
nanahira's avatar
nanahira committed
4567 4568 4569 4570
              continue;
            }
            kick_room_found = true;
            if (room.started) {
4571 4572
              room.scores[room.dueling_players[0].name_vpass] = 0;
              room.scores[room.dueling_players[1].name_vpass] = 0;
nanahira's avatar
nanahira committed
4573
            }
nanahira's avatar
fix  
nanahira committed
4574
            room.kicked = true;
nanahira's avatar
js  
nanahira committed
4575
            room.send_replays();
nanahira's avatar
nanahira committed
4576 4577 4578 4579 4580 4581 4582 4583 4584 4585
            room.process.kill();
            room["delete"]();
          }
          response.writeHead(200);
          if (kick_room_found) {
            response.end(addCallback(u.query.callback, "['kick ok', '" + u.query.kick + "']"));
          } else {
            response.end(addCallback(u.query.callback, "['room not found', '" + u.query.kick + "']"));
          }
        } else if (u.query.death) {
nanahira's avatar
nanahira committed
4586 4587 4588 4589 4590
          if (!auth.auth(u.query.username, u.query.pass, "start_death", "start_death")) {
            response.writeHead(200);
            response.end(addCallback(u.query.callback, "['密码错误', 0]"));
            return;
          }
nanahira's avatar
nanahira committed
4591 4592 4593
          death_room_found = false;
          for (p = 0, len5 = ROOM_all.length; p < len5; p++) {
            room = ROOM_all[p];
nanahira's avatar
nanahira committed
4594 4595 4596
            if (room && (u.query.death === "all" || u.query.death === room.process_pid.toString() || u.query.death === room.name)) {
              if (room.start_death()) {
                death_room_found = true;
nanahira's avatar
nanahira committed
4597
              }
nanahira's avatar
nanahira committed
4598 4599 4600 4601 4602 4603 4604 4605 4606
            }
          }
          response.writeHead(200);
          if (death_room_found) {
            response.end(addCallback(u.query.callback, "['death ok', '" + u.query.death + "']"));
          } else {
            response.end(addCallback(u.query.callback, "['room not found', '" + u.query.death + "']"));
          }
        } else if (u.query.deathcancel) {
nanahira's avatar
nanahira committed
4607 4608 4609 4610 4611
          if (!auth.auth(u.query.username, u.query.pass, "start_death", "cancel_death")) {
            response.writeHead(200);
            response.end(addCallback(u.query.callback, "['密码错误', 0]"));
            return;
          }
nanahira's avatar
nanahira committed
4612
          death_room_found = false;
nanahira's avatar
nanahira committed
4613 4614
          for (q = 0, len6 = ROOM_all.length; q < len6; q++) {
            room = ROOM_all[q];
nanahira's avatar
nanahira committed
4615 4616 4617 4618
            if (room && (u.query.death === "all" || u.query.death === room.process_pid.toString() || u.query.death === room.name)) {
              if (room.cancel_death()) {
                death_room_found = true;
              }
nanahira's avatar
nanahira committed
4619 4620 4621 4622 4623 4624 4625 4626
            }
          }
          response.writeHead(200);
          if (death_room_found) {
            response.end(addCallback(u.query.callback, "['death cancel ok', '" + u.query.deathcancel + "']"));
          } else {
            response.end(addCallback(u.query.callback, "['room not found', '" + u.query.deathcancel + "']"));
          }
4627
        } else {
mercury233's avatar
mercury233 committed
4628
          response.writeHead(400);
4629
          response.end();
4630
        }
神楽坂玲奈's avatar
11.7  
神楽坂玲奈 committed
4631
      } else {
mercury233's avatar
mercury233 committed
4632
        response.writeHead(400);
mercury233's avatar
test3  
mercury233 committed
4633
        response.end();
神楽坂玲奈's avatar
11.7  
神楽坂玲奈 committed
4634
      }
4635 4636
    };
    http_server = http.createServer(requestListener);
神楽坂玲奈's avatar
神楽坂玲奈 committed
4637
    http_server.listen(settings.modules.http.port);
mercury233's avatar
mercury233 committed
4638
    if (settings.modules.http.ssl.enabled) {
4639 4640 4641 4642 4643 4644
      https = require('https');
      options = {
        cert: fs.readFileSync(settings.modules.http.ssl.cert),
        key: fs.readFileSync(settings.modules.http.ssl.key)
      };
      https_server = https.createServer(options, requestListener);
nanahira's avatar
fix  
nanahira committed
4645 4646 4647
      if (settings.modules.http.websocket_roomlist && roomlist) {
        roomlist.init(https_server, ROOM_all);
      }
4648 4649
      https_server.listen(settings.modules.http.ssl.port);
    }
神楽坂玲奈's avatar
11.7  
神楽坂玲奈 committed
4650
  }
神楽坂玲奈's avatar
神楽坂玲奈 committed
4651

神楽坂玲奈's avatar
init  
神楽坂玲奈 committed
4652
}).call(this);