ygopro-server.js 70 KB
Newer Older
mercury233's avatar
mercury233 committed
1
// Generated by CoffeeScript 1.10.0
神楽坂玲奈's avatar
init  
神楽坂玲奈 committed
2
(function() {
mercury233's avatar
mercury233 committed
3
  var Cloud_replay_ids, Graveyard, ROOM_all, ROOM_ban_player, ROOM_find_by_name, ROOM_find_by_port, ROOM_find_or_create_by_name, ROOM_find_or_create_random, ROOM_players_banned, ROOM_players_oppentlist, ROOM_validate, Room, _, ban_user, bunyan, crypto, date, defaultconfig, execFile, fs, get_memory_usage, http, http_server, https, https_server, list, load_dialogues, load_tips, log, moment, nconf, net, options, os, path, pg, redis, redisdb, request, requestListener, roomlist, settings, spawn, spawnSync, tribute, url, users_cache, wait_room_start, 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');

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

mercury233's avatar
mercury233 committed
21 22 23 24
  spawn = require('child_process').spawn;

  spawnSync = require('child_process').spawnSync;

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

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

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

  request = require('request');

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

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

39 40
  moment = require('moment');

mercury233's avatar
mercury233 committed
41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58
  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年'
    }
  });

mercury233's avatar
mercury233 committed
59 60
  nconf = require('nconf');

mercury233's avatar
mercury233 committed
61
  nconf.file('./config.user.json');
mercury233's avatar
mercury233 committed
62 63 64 65 66 67 68 69 70 71

  defaultconfig = require('./config.json');

  nconf.defaults(defaultconfig);

  settings = global.settings = nconf.get();

  nconf.myset = function(settings, path, val) {
    var key, target;
    nconf.set(path, val);
mercury233's avatar
mercury233 committed
72 73 74 75
    nconf.save();
    if (_.isString(val)) {
      log.info("setting changed", path, val);
    }
mercury233's avatar
mercury233 committed
76 77 78 79 80 81 82 83 84 85 86 87 88
    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;
    }
  };
神楽坂玲奈's avatar
11.7  
神楽坂玲奈 committed
89

mercury233's avatar
mercury233 committed
90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109
  ban_user = function(name) {
    var k, l, len, len1, player, ref, room;
    settings.ban.banned_user.push(name);
    nconf.myset(settings, "ban:banned_user", settings.ban.banned_user);
    for (k = 0, len = ROOM_all.length; k < len; k++) {
      room = ROOM_all[k];
      if (room && room.established) {
        ref = room.players;
        for (l = 0, len1 = ref.length; l < len1; l++) {
          player = ref[l];
          if (player && player.name === name) {
            settings.ban.banned_ip.push(player.remoteAddress);
            ygopro.stoc_send_chat_to_room(room, player.name + " 被系统请出了房间", ygopro.constants.COLORS.RED);
            player.end();
            continue;
          }
        }
      }
    }
  };
mercury233's avatar
mercury233 committed
110

mercury233's avatar
mercury233 committed
111
  settings.version = parseInt(fs.readFileSync('ygopro/gframe/game.cpp', 'utf8').match(/PRO_VERSION = ([x\dABCDEF]+)/)[1], '16');
112

神楽坂玲奈's avatar
fix  
神楽坂玲奈 committed
113
  settings.lflist = (function() {
神楽坂玲奈's avatar
神楽坂玲奈 committed
114
    var k, len, ref, results;
神楽坂玲奈's avatar
fix  
神楽坂玲奈 committed
115
    ref = fs.readFileSync('ygopro/lflist.conf', 'utf8').match(/!.*/g);
神楽坂玲奈's avatar
神楽坂玲奈 committed
116 117 118
    results = [];
    for (k = 0, len = ref.length; k < len; k++) {
      list = ref[k];
mercury233's avatar
mercury233 committed
119 120 121 122
      date = list.match(/!([\d\.]+)/);
      if (!date) {
        continue;
      }
神楽坂玲奈's avatar
神楽坂玲奈 committed
123
      results.push({
神楽坂玲奈's avatar
神楽坂玲奈 committed
124
        date: moment(list.match(/!([\d\.]+)/)[1], 'YYYY.MM.DD').utcOffset("-08:00"),
神楽坂玲奈's avatar
fix  
神楽坂玲奈 committed
125
        tcg: list.indexOf('TCG') !== -1
神楽坂玲奈's avatar
神楽坂玲奈 committed
126 127 128 129 130
      });
    }
    return results;
  })();

mercury233's avatar
mercury233 committed
131 132 133 134 135 136 137 138 139
  if (settings.modules.enable_cloud_replay) {
    redis = require('redis');
    zlib = require('zlib');
    redisdb = redis.createClient({
      host: "127.0.0.1",
      port: settings.modules.redis_port
    });
  }

mercury233's avatar
mercury233 committed
140
  if (settings.modules.enable_windbot) {
mercury233's avatar
mercury233 committed
141
    settings.modules.windbots = require('./windbot/bots.json').windbots;
mercury233's avatar
mercury233 committed
142 143
  }

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

mercury233's avatar
mercury233 committed
146 147 148
  if (settings.modules.enable_websocket_roomlist) {
    roomlist = require('./roomlist.js');
  }
神楽坂玲奈's avatar
神楽坂玲奈 committed
149

神楽坂玲奈's avatar
fix  
神楽坂玲奈 committed
150 151
  users_cache = {};

mercury233's avatar
mercury233 committed
152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169
  get_memory_usage = function() {
    var actualFree, buffers, cached, free, line, lines, percentUsed, prc_free, total;
    prc_free = spawnSync("free", []);
    if (prc_free.stdout) {
      lines = prc_free.stdout.toString().split(/\n/g);
      line = lines[1].split(/\s+/);
      total = parseInt(line[1], 10);
      free = parseInt(line[3], 10);
      buffers = parseInt(line[5], 10);
      cached = parseInt(line[6], 10);
      actualFree = free + buffers + cached;
      percentUsed = parseFloat(((1 - (actualFree / total)) * 100).toFixed(2));
    } else {
      percentUsed = 0;
    }
    return percentUsed;
  };

170
  Graveyard = [];
mercury233's avatar
test1  
mercury233 committed
171

172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193
  tribute = function(socket) {
    setTimeout((function(socket) {
      Graveyard.push(socket);
    })(socket), 3000);
  };

  setInterval(function() {
    var fuck, i, j, k, l, len, len1, ref, you;
    for (i = k = 0, len = Graveyard.length; k < len; i = ++k) {
      fuck = Graveyard[i];
      if (Graveyard[i]) {
        Graveyard[i].destroy();
      }
      ref = Graveyard[i];
      for (j = l = 0, len1 = ref.length; l < len1; j = ++l) {
        you = ref[j];
        Graveyard[i][j] = null;
      }
      Graveyard[i] = null;
    }
    Graveyard = [];
  }, 3000);
mercury233's avatar
test1  
mercury233 committed
194

mercury233's avatar
mercury233 committed
195 196
  Cloud_replay_ids = [];

mercury233's avatar
mercury233 committed
197 198 199 200 201 202
  ROOM_all = [];

  ROOM_players_oppentlist = {};

  ROOM_players_banned = [];

mercury233's avatar
mercury233 committed
203
  ROOM_ban_player = function(name, ip, reason, countadd) {
mercury233's avatar
mercury233 committed
204
    var bannedplayer, bantime;
mercury233's avatar
mercury233 committed
205 206 207
    if (countadd == null) {
      countadd = 1;
    }
mercury233's avatar
mercury233 committed
208 209 210 211
    bannedplayer = _.find(ROOM_players_banned, function(bannedplayer) {
      return ip === bannedplayer.ip;
    });
    if (bannedplayer) {
mercury233's avatar
mercury233 committed
212
      bannedplayer.count = bannedplayer.count + countadd;
mercury233's avatar
mercury233 committed
213 214 215 216 217 218 219 220 221 222 223 224
      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
225
        "count": countadd,
mercury233's avatar
mercury233 committed
226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274
        "reasons": [reason],
        "need_tip": true
      };
      ROOM_players_banned.push(bannedplayer);
    }
  };

  ROOM_find_or_create_by_name = function(name, player_ip) {
    var room;
    if (settings.modules.enable_random_duel && (name === '' || name.toUpperCase() === 'S' || name.toUpperCase() === 'M' || name.toUpperCase() === 'T')) {
      return ROOM_find_or_create_random(name.toUpperCase(), player_ip);
    }
    if (room = ROOM_find_by_name(name)) {
      return room;
    } else if (get_memory_usage() >= 90) {
      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 {
          "error": "因为您近期在游戏中多次" + (bannedplayer.reasons.join('')) + ",您已被禁止使用随机对战功能,将在" + (moment(bannedplayer.time).fromNow(true)) + "后解封"
        };
      }
      if (bannedplayer.count > 3 && moment() < bannedplayer.time && bannedplayer.need_tip) {
        bannedplayer.need_tip = false;
        return {
          "error": "因为您近期在游戏中" + (bannedplayer.reasons.join('')) + ",在" + (moment(bannedplayer.time).fromNow(true)) + "内您随机对战时只能遇到其他违规玩家"
        };
      } else if (bannedplayer.need_tip) {
        bannedplayer.need_tip = false;
        return {
          "error": "系统检测到您近期在游戏中" + (bannedplayer.reasons.join('')) + ",若您违规超过3次,将受到惩罚"
        };
      } 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) {
275
      return room && room.random_type !== '' && !room.started && ((type === '' && room.random_type !== 'T') || room.random_type === type) && room.get_playing_player().length < max_player && (room.get_host() === null || room.get_host().remoteAddress !== ROOM_players_oppentlist[player_ip]) && (playerbanned === room.deprecated);
mercury233's avatar
mercury233 committed
276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296
    });
    if (result) {
      result.welcome = '对手已经在等你了,开始决斗吧!';
    } else {
      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;
      result.welcome = '已建立随机对战房间,正在等待对手!';
      result.deprecated = playerbanned;
    }
    if (result.random_type === 'M') {
      result.welcome = result.welcome + '\n您进入了比赛模式的房间,我们推荐使用竞技卡组!';
    }
    return result;
  };

  ROOM_find_by_name = function(name) {
    var result;
    result = _.find(ROOM_all, function(room) {
297
      return room && room.name === name;
mercury233's avatar
mercury233 committed
298 299 300 301 302 303
    });
    return result;
  };

  ROOM_find_by_port = function(port) {
    return _.find(ROOM_all, function(room) {
304
      return room && room.port === port;
mercury233's avatar
mercury233 committed
305 306 307 308 309 310 311 312 313 314 315 316 317
    });
  };

  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;
318 319 320
      if (!room) {
        return false;
      }
mercury233's avatar
mercury233 committed
321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340
      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;
    });
  };

  Room = (function() {
    function Room(name, hostinfo) {
      var draw_count, error1, lflist, param, rule, start_hand, start_lp, time_limit;
      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 = [];
341
      this.cloud_replay_id = Math.floor(Math.random() * 100000000);
mercury233's avatar
mercury233 committed
342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357
      this.watchers = [];
      this.random_type = '';
      this.welcome = '';
      ROOM_all.push(this);
      this.hostinfo || (this.hostinfo = {
        lflist: _.findIndex(settings.lflist, function(list) {
          return !list.tcg && list.date.isBefore();
        }),
        rule: settings.modules.enable_TCG_as_default ? 2 : 0,
        mode: 0,
        enable_priority: false,
        no_check_deck: false,
        no_shuffle_deck: false,
        start_lp: 8000,
        start_hand: 5,
        draw_count: 1,
mercury233's avatar
mercury233 committed
358 359
        time_limit: 180,
        replay_mode: settings.modules.tournament_mode.enabled ? 1 : 0
mercury233's avatar
mercury233 committed
360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530
      });
      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;
      } 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) && ((param[1].length <= 2 && param[1].match(/(S|N|M|T)(0|1|2|T|A)/i)) || (param[1].match(/^(S|N|M|T)(0|1|2|O|T|A)(0|1|O|T)/i)))) {
        rule = param[1].toUpperCase();
        switch (rule.charAt(0)) {
          case "M":
          case "1":
            this.hostinfo.mode = 1;
            break;
          case "T":
          case "2":
            this.hostinfo.mode = 2;
            this.hostinfo.start_lp = 16000;
            break;
          default:
            this.hostinfo.mode = 0;
        }
        switch (rule.charAt(1)) {
          case "0":
          case "O":
            this.hostinfo.rule = 0;
            break;
          case "1":
          case "T":
            this.hostinfo.rule = 1;
            break;
          default:
            this.hostinfo.rule = 2;
        }
        switch (rule.charAt(2)) {
          case "1":
          case "T":
            this.hostinfo.lflist = _.findIndex(settings.lflist, function(list) {
              return list.tcg && list.date.isBefore();
            });
            break;
          default:
            this.hostinfo.lflist = _.findIndex(settings.lflist, function(list) {
              return !list.tcg && list.date.isBefore();
            });
        }
        if ((param = parseInt(rule.charAt(3).match(/\d/))) >= 0) {
          this.hostinfo.time_limit = param * 60;
        }
        switch (rule.charAt(4)) {
          case "T":
          case "1":
            this.hostinfo.enable_priority = true;
            break;
          default:
            this.hostinfo.enable_priority = false;
        }
        switch (rule.charAt(5)) {
          case "T":
          case "1":
            this.hostinfo.no_check_deck = true;
            break;
          default:
            this.hostinfo.no_check_deck = false;
        }
        switch (rule.charAt(6)) {
          case "T":
          case "1":
            this.hostinfo.no_shuffle_deck = true;
            break;
          default:
            this.hostinfo.no_shuffle_deck = false;
        }
        if ((param = parseInt(rule.charAt(7).match(/\d/))) > 0) {
          this.hostinfo.start_lp = param * 4000;
        }
        if ((param = parseInt(rule.charAt(8).match(/\d/))) > 0) {
          this.hostinfo.start_hand = param;
        }
        if ((param = parseInt(rule.charAt(9).match(/\d/))) >= 0) {
          this.hostinfo.draw_count = param;
        }
      } 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;
          this.hostinfo.lflist = _.findIndex(settings.lflist, function(list) {
            return list.tcg && list.date.isBefore();
          });
        }
        if (rule.match(/(^|,|,)(OCGONLY|OO)(,|,|$)/)) {
          this.hostinfo.rule = 0;
        }
        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;
        }
      }
mercury233's avatar
mercury233 committed
531
      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
532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582
      try {
        this.process = spawn('./ygopro', param, {
          cwd: settings.ygopro_path
        });
        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;
            if (!_this["private"] && settings.modules.enable_websocket_roomlist) {
              roomlist.create(_this);
            }
            _this.port = parseInt(data);
            _.each(_this.players, function(player) {
              player.server.connect(_this.port, '127.0.0.1', function() {
                var buffer, k, len, ref;
                ref = player.pre_establish_buffers;
                for (k = 0, len = ref.length; k < len; k++) {
                  buffer = ref[k];
                  player.server.write(buffer);
                }
                player.established = true;
                player.pre_establish_buffers = [];
              });
            });
            if (_this.windbot) {
              _this.ai_process = spawn('mono', ['WindBot.exe'], {
                cwd: 'windbot',
                env: {
                  YGOPRO_VERSION: settings.version,
                  YGOPRO_HOST: '127.0.0.1',
                  YGOPRO_PORT: _this.port,
                  YGOPRO_NAME: _this.windbot.name,
                  YGOPRO_DECK: _this.windbot.deck,
                  YGOPRO_DIALOG: _this.windbot.dialog
                }
              });
              _this.ai_process.stdout.on('data', function(data) {});
              _this.ai_process.stderr.on('data', function(data) {
                log.info("AI stderr: " + data);
              });
            }
          };
        })(this));
mercury233's avatar
mercury233 committed
583 584
        this.process.stderr.on('data', (function(_this) {
          return function(data) {
mercury233's avatar
mercury233 committed
585 586 587 588
            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
589 590 591
            _this.has_ygopro_error = true;
          };
        })(this));
mercury233's avatar
mercury233 committed
592 593 594 595 596 597
      } catch (error1) {
        this.error = "建立房间失败,请重试";
      }
    }

    Room.prototype["delete"] = function() {
598
      var index, log_rep_id, player_ips, player_names, recorder_buffer, replay_id;
mercury233's avatar
mercury233 committed
599 600 601 602
      if (this.deleted) {
        return;
      }
      if (this.player_datas.length && settings.modules.enable_cloud_replay) {
603
        replay_id = this.cloud_replay_id;
mercury233's avatar
mercury233 committed
604 605 606
        if (this.has_ygopro_error) {
          log_rep_id = true;
        }
mercury233's avatar
mercury233 committed
607 608 609 610 611 612 613
        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) {
614
          var date_time, recorded_ip;
mercury233's avatar
mercury233 committed
615 616 617 618 619 620 621 622 623 624 625 626
          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);
          redisdb.expire("replay:" + replay_id, 60 * 60 * 24);
          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
627
          if (log_rep_id) {
mercury233's avatar
mercury233 committed
628 629
            log.info("error replay: R#" + replay_id);
          }
mercury233's avatar
mercury233 committed
630 631 632 633 634 635 636 637 638 639 640
        });
      }
      this.watcher_buffers = [];
      this.recorder_buffers = [];
      this.players = [];
      if (this.watcher) {
        this.watcher.end();
      }
      this.deleted = true;
      index = _.indexOf(ROOM_all, this);
      if (index !== -1) {
641
        ROOM_all[index] = null;
mercury233's avatar
mercury233 committed
642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712
      }
      if (!this["private"] && !this.started && this.established && settings.modules.enable_websocket_roomlist) {
        roomlist["delete"](this.name);
      }
    };

    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;
    };

    Room.prototype.connect = function(client) {
      var host_player;
      this.players.push(client);
      client.ip = client.remoteAddress;
      if (this.random_type) {
        host_player = this.get_host();
        if (host_player && (host_player !== client)) {
          ROOM_players_oppentlist[host_player.remoteAddress] = client.remoteAddress;
          ROOM_players_oppentlist[client.remoteAddress] = host_player.remoteAddress;
        } else {
          ROOM_players_oppentlist[client.remoteAddress] = null;
        }
      }
      if (this.established) {
        if (!this["private"] && !this.started && settings.modules.enable_websocket_roomlist) {
          roomlist.update(this);
        }
        client.server.connect(this.port, '127.0.0.1', function() {
          var buffer, k, len, ref;
          ref = client.pre_establish_buffers;
          for (k = 0, len = ref.length; k < len; k++) {
            buffer = ref[k];
            client.server.write(buffer);
          }
          client.established = true;
          client.pre_establish_buffers = [];
        });
      }
    };

    Room.prototype.disconnect = function(client, error) {
      var index;
      if (client.is_post_watcher) {
        ygopro.stoc_send_chat_to_room(this, (client.name + " 退出了观战") + (error ? ": " + error : ''));
        index = _.indexOf(this.watchers, client);
        if (index !== -1) {
          this.watchers.splice(index, 1);
        }
      } else {
        index = _.indexOf(this.players, client);
        if (index !== -1) {
          this.players.splice(index, 1);
        }
713
        if (this.started && this.disconnector !== 'server' && this.random_type) {
mercury233's avatar
mercury233 committed
714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731
          ROOM_ban_player(client.name, client.ip, "强退");
        }
        if (this.players.length) {
          ygopro.stoc_send_chat_to_room(this, (client.name + " 离开了游戏") + (error ? ": " + error : ''));
          if (!this["private"] && !this.started && settings.modules.enable_websocket_roomlist) {
            roomlist.update(this);
          }
        } else {
          this.process.kill();
          this["delete"]();
        }
      }
    };

    return Room;

  })();

神楽坂玲奈's avatar
神楽坂玲奈 committed
732
  net.createServer(function(client) {
mercury233's avatar
mercury233 committed
733
    var server;
神楽坂玲奈's avatar
神楽坂玲奈 committed
734 735
    server = new net.Socket();
    client.server = server;
736
    client.setTimeout(300000);
737
    client.on('close', function(had_error) {
738 739
      var room;
      room = ROOM_all[client.rid];
740
      tribute(client);
741
      if (!client.closed) {
神楽坂玲奈's avatar
11.7  
神楽坂玲奈 committed
742
        client.closed = true;
743 744
        if (room) {
          room.disconnect(client);
神楽坂玲奈's avatar
init  
神楽坂玲奈 committed
745
        }
mercury233's avatar
mercury233 committed
746
      }
mercury233's avatar
test3  
mercury233 committed
747
      server.end();
mercury233's avatar
mercury233 committed
748
    });
749
    client.on('error', function(error) {
750 751
      var room;
      room = ROOM_all[client.rid];
752
      tribute(client);
753 754
      if (!client.closed) {
        client.closed = error;
755 756
        if (room) {
          room.disconnect(client, error);
757
        }
神楽坂玲奈's avatar
神楽坂玲奈 committed
758
      }
mercury233's avatar
test3  
mercury233 committed
759
      server.end();
神楽坂玲奈's avatar
init  
神楽坂玲奈 committed
760
    });
761
    client.on('timeout', function() {
mercury233's avatar
test3  
mercury233 committed
762
      server.end();
763
    });
764
    server.on('close', function(had_error) {
765 766
      var room;
      room = ROOM_all[client.rid];
767
      tribute(server);
768 769 770
      if (room) {
        room.disconnector = 'server';
      }
771 772
      if (!server.closed) {
        server.closed = true;
mercury233's avatar
mercury233 committed
773
      }
774
      if (!client.closed) {
mercury233's avatar
mercury233 committed
775
        ygopro.stoc_send_chat(client, "服务器关闭了连接", ygopro.constants.COLORS.RED);
mercury233's avatar
test3  
mercury233 committed
776
        client.end();
mercury233's avatar
mercury233 committed
777 778
      }
    });
779
    server.on('error', function(error) {
780 781
      var room;
      room = ROOM_all[client.rid];
782
      tribute(server);
783 784 785
      if (room) {
        room.disconnector = 'server';
      }
786 787
      server.closed = error;
      if (!client.closed) {
mercury233's avatar
mercury233 committed
788
        ygopro.stoc_send_chat(client, "服务器错误: " + error, ygopro.constants.COLORS.RED);
mercury233's avatar
test3  
mercury233 committed
789
        client.end();
mercury233's avatar
mercury233 committed
790 791
      }
    });
mercury233's avatar
mercury233 committed
792 793 794 795
    if (settings.modules.enable_cloud_replay) {
      client.open_cloud_replay = function(err, replay) {
        var buffer;
        if (err || !replay) {
mercury233's avatar
mercury233 committed
796
          ygopro.stoc_die(client, "没有找到录像");
mercury233's avatar
mercury233 committed
797
          return;
mercury233's avatar
mercury233 committed
798
        }
mercury233's avatar
mercury233 committed
799 800
        redisdb.expire("replay:" + replay.replay_id, 60 * 60 * 48);
        buffer = new Buffer(replay.replay_buffer, 'binary');
mercury233's avatar
mercury233 committed
801 802
        zlib.unzip(buffer, function(err, replay_buffer) {
          if (err) {
mercury233's avatar
mercury233 committed
803
            log.info("cloud replay unzip error: " + err);
mercury233's avatar
mercury233 committed
804
            ygopro.stoc_send_chat(client, "播放录像出错", ygopro.constants.COLORS.RED);
mercury233's avatar
mercury233 committed
805
            client.end();
mercury233's avatar
mercury233 committed
806 807 808 809 810 811
            return;
          }
          ygopro.stoc_send_chat(client, "正在观看云录像:R#" + replay.replay_id + " " + replay.player_names + " " + replay.date_time, ygopro.constants.COLORS.BABYBLUE);
          client.write(replay_buffer);
          client.end();
        });
mercury233's avatar
mercury233 committed
812 813
      };
    }
神楽坂玲奈's avatar
神楽坂玲奈 committed
814 815
    client.pre_establish_buffers = new Array();
    client.on('data', function(data) {
816
      var b, buffer, cancel, ctos_buffer, ctos_message_length, ctos_proto, datas, k, l, len, len1, looplimit, room, struct;
817
      if (client.is_post_watcher) {
818 819 820 821
        room = ROOM_all[client.rid];
        if (room) {
          room.watcher.write(data);
        }
神楽坂玲奈's avatar
11.7  
神楽坂玲奈 committed
822
      } else {
mercury233's avatar
mercury233 committed
823 824 825
        ctos_buffer = new Buffer(0);
        ctos_message_length = 0;
        ctos_proto = 0;
826
        ctos_buffer = Buffer.concat([ctos_buffer, data], ctos_buffer.length + data.length);
827
        datas = [];
mercury233's avatar
mercury233 committed
828
        looplimit = 0;
神楽坂玲奈's avatar
11.7  
神楽坂玲奈 committed
829
        while (true) {
830 831
          if (ctos_message_length === 0) {
            if (ctos_buffer.length >= 2) {
mercury233's avatar
test3  
mercury233 committed
832
              ctos_message_length = ctos_buffer.readUInt16LE(0);
神楽坂玲奈's avatar
11.7  
神楽坂玲奈 committed
833 834 835
            } else {
              break;
            }
836 837
          } else if (ctos_proto === 0) {
            if (ctos_buffer.length >= 3) {
mercury233's avatar
test3  
mercury233 committed
838
              ctos_proto = ctos_buffer.readUInt8(2);
神楽坂玲奈's avatar
11.7  
神楽坂玲奈 committed
839 840
            } else {
              break;
神楽坂玲奈's avatar
init  
神楽坂玲奈 committed
841 842
            }
          } else {
843
            if (ctos_buffer.length >= 2 + ctos_message_length) {
844
              cancel = false;
845 846 847
              if (ygopro.ctos_follows[ctos_proto]) {
                b = ctos_buffer.slice(3, ctos_message_length - 1 + 3);
                if (struct = ygopro.structs[ygopro.proto_structs.CTOS[ygopro.constants.CTOS[ctos_proto]]]) {
神楽坂玲奈's avatar
11.7  
神楽坂玲奈 committed
848
                  struct._setBuff(b);
849 850 851 852 853
                  if (ygopro.ctos_follows[ctos_proto].synchronous) {
                    cancel = ygopro.ctos_follows[ctos_proto].callback(b, _.clone(struct.fields), client, server);
                  } else {
                    ygopro.ctos_follows[ctos_proto].callback(b, _.clone(struct.fields), client, server);
                  }
神楽坂玲奈's avatar
11.7  
神楽坂玲奈 committed
854
                } else {
855
                  ygopro.ctos_follows[ctos_proto].callback(b, null, client, server);
神楽坂玲奈's avatar
11.7  
神楽坂玲奈 committed
856 857
                }
              }
858 859 860
              if (!cancel) {
                datas.push(ctos_buffer.slice(0, 2 + ctos_message_length));
              }
861 862
              ctos_buffer = ctos_buffer.slice(2 + ctos_message_length);
              ctos_message_length = 0;
mercury233's avatar
test3  
mercury233 committed
863
              ctos_proto = 0;
神楽坂玲奈's avatar
11.7  
神楽坂玲奈 committed
864 865 866
            } else {
              break;
            }
神楽坂玲奈's avatar
init  
神楽坂玲奈 committed
867
          }
mercury233's avatar
mercury233 committed
868 869
          looplimit++;
          if (looplimit > 800) {
mercury233's avatar
fix  
mercury233 committed
870
            log.info("error ctos", client.name);
mercury233's avatar
mercury233 committed
871 872 873
            server.end();
            break;
          }
神楽坂玲奈's avatar
init  
神楽坂玲奈 committed
874
        }
875 876 877 878 879 880 881 882 883 884 885
        if (client.established) {
          for (k = 0, len = datas.length; k < len; k++) {
            buffer = datas[k];
            server.write(buffer);
          }
        } else {
          for (l = 0, len1 = datas.length; l < len1; l++) {
            buffer = datas[l];
            client.pre_establish_buffers.push(buffer);
          }
        }
神楽坂玲奈's avatar
init  
神楽坂玲奈 committed
886 887
      }
    });
mercury233's avatar
test1  
mercury233 committed
888
    server.on('data', function(data) {
889
      var b, buffer, cancel, datas, k, len, looplimit, stanzas, stoc_buffer, stoc_message_length, stoc_proto, struct;
mercury233's avatar
mercury233 committed
890 891 892
      stoc_buffer = new Buffer(0);
      stoc_message_length = 0;
      stoc_proto = 0;
893
      stoc_buffer = Buffer.concat([stoc_buffer, data], stoc_buffer.length + data.length);
894
      datas = [];
mercury233's avatar
mercury233 committed
895
      looplimit = 0;
神楽坂玲奈's avatar
神楽坂玲奈 committed
896
      while (true) {
897 898
        if (stoc_message_length === 0) {
          if (stoc_buffer.length >= 2) {
mercury233's avatar
test3  
mercury233 committed
899
            stoc_message_length = stoc_buffer.readUInt16LE(0);
神楽坂玲奈's avatar
神楽坂玲奈 committed
900 901 902
          } else {
            break;
          }
903 904
        } else if (stoc_proto === 0) {
          if (stoc_buffer.length >= 3) {
mercury233's avatar
test3  
mercury233 committed
905
            stoc_proto = stoc_buffer.readUInt8(2);
神楽坂玲奈's avatar
神楽坂玲奈 committed
906 907 908 909
          } else {
            break;
          }
        } else {
910
          if (stoc_buffer.length >= 2 + stoc_message_length) {
911
            cancel = false;
912 913 914 915
            stanzas = stoc_proto;
            if (ygopro.stoc_follows[stoc_proto]) {
              b = stoc_buffer.slice(3, stoc_message_length - 1 + 3);
              if (struct = ygopro.structs[ygopro.proto_structs.STOC[ygopro.constants.STOC[stoc_proto]]]) {
神楽坂玲奈's avatar
神楽坂玲奈 committed
916
                struct._setBuff(b);
917 918 919 920 921
                if (ygopro.stoc_follows[stoc_proto].synchronous) {
                  cancel = ygopro.stoc_follows[stoc_proto].callback(b, _.clone(struct.fields), client, server);
                } else {
                  ygopro.stoc_follows[stoc_proto].callback(b, _.clone(struct.fields), client, server);
                }
神楽坂玲奈's avatar
神楽坂玲奈 committed
922
              } else {
923 924 925 926 927
                if (ygopro.stoc_follows[stoc_proto].synchronous) {
                  cancel = ygopro.stoc_follows[stoc_proto].callback(b, null, client, server);
                } else {
                  ygopro.stoc_follows[stoc_proto].callback(b, null, client, server);
                }
神楽坂玲奈's avatar
神楽坂玲奈 committed
928 929
              }
            }
930 931 932
            if (!cancel) {
              datas.push(stoc_buffer.slice(0, 2 + stoc_message_length));
            }
933 934
            stoc_buffer = stoc_buffer.slice(2 + stoc_message_length);
            stoc_message_length = 0;
mercury233's avatar
test3  
mercury233 committed
935
            stoc_proto = 0;
神楽坂玲奈's avatar
神楽坂玲奈 committed
936 937 938 939
          } else {
            break;
          }
        }
mercury233's avatar
mercury233 committed
940 941
        looplimit++;
        if (looplimit > 800) {
mercury233's avatar
fix  
mercury233 committed
942
          log.info("error stoc", client.name);
mercury233's avatar
mercury233 committed
943 944 945
          server.end();
          break;
        }
神楽坂玲奈's avatar
 
神楽坂玲奈 committed
946
      }
947 948 949 950
      for (k = 0, len = datas.length; k < len; k++) {
        buffer = datas[k];
        client.write(buffer);
      }
神楽坂玲奈's avatar
init  
神楽坂玲奈 committed
951
    });
神楽坂玲奈's avatar
神楽坂玲奈 committed
952
  }).listen(settings.port, function() {
mercury233's avatar
mercury233 committed
953
    log.info("server started", settings.port);
神楽坂玲奈's avatar
神楽坂玲奈 committed
954
  });
神楽坂玲奈's avatar
init  
神楽坂玲奈 committed
955

神楽坂玲奈's avatar
神楽坂玲奈 committed
956
  ygopro.ctos_follow('PLAYER_INFO', true, function(buffer, info, client, server) {
957 958 959 960 961 962 963 964
    var name, struct;
    name = info.name.split("$")[0];
    struct = ygopro.structs["CTOS_PlayerInfo"];
    struct._setBuff(buffer);
    struct.set("name", name);
    buffer = struct.buffer;
    client.name = name;
    return false;
神楽坂玲奈's avatar
init  
神楽坂玲奈 committed
965 966
  });

神楽坂玲奈's avatar
神楽坂玲奈 committed
967
  ygopro.ctos_follow('JOIN_GAME', false, function(buffer, info, client, server) {
mercury233's avatar
mercury233 committed
968
    var check, decrypted_buffer, finish, i, id, k, l, len, len1, name, ref, ref1, replay_id, room, secret, struct, windbot;
mercury233's avatar
fix  
mercury233 committed
969
    if (settings.modules.stop) {
mercury233's avatar
mercury233 committed
970
      ygopro.stoc_die(client, settings.modules.stop);
mercury233's avatar
mercury233 committed
971
    } else if (info.pass.toUpperCase() === "R" && settings.modules.enable_cloud_replay) {
mercury233's avatar
mercury233 committed
972
      ygopro.stoc_send_chat(client, "以下是您近期的云录像,密码处输入 R#录像编号 即可观看", ygopro.constants.COLORS.BABYBLUE);
mercury233's avatar
mercury233 committed
973 974 975 976
      redisdb.lrange(client.remoteAddress + ":replays", 0, 2, function(err, result) {
        _.each(result, function(replay_id, id) {
          redisdb.hgetall("replay:" + replay_id, function(err, replay) {
            if (err || !replay) {
mercury233's avatar
mercury233 committed
977 978 979
              if (err) {
                log.info("cloud replay getall error: " + err);
              }
mercury233's avatar
mercury233 committed
980 981 982
              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
983
          });
mercury233's avatar
mercury233 committed
984 985 986 987 988 989 990
        });
      });
      setTimeout((function() {
        ygopro.stoc_send(client, 'ERROR_MSG', {
          msg: 1,
          code: 2
        });
mercury233's avatar
mercury233 committed
991
        client.end();
mercury233's avatar
mercury233 committed
992
      }), 500);
mercury233's avatar
mercury233 committed
993 994
    } else if (info.pass.slice(0, 2).toUpperCase() === "R#" && settings.modules.enable_cloud_replay) {
      replay_id = info.pass.split("#")[1];
mercury233's avatar
fix  
mercury233 committed
995
      if (replay_id > 0 && replay_id <= 9) {
mercury233's avatar
mercury233 committed
996 997
        redisdb.lindex(client.remoteAddress + ":replays", replay_id - 1, function(err, replay_id) {
          if (err || !replay_id) {
mercury233's avatar
mercury233 committed
998 999 1000
            if (err) {
              log.info("cloud replay replayid error: " + err);
            }
mercury233's avatar
mercury233 committed
1001
            ygopro.stoc_die(client, "没有找到录像");
mercury233's avatar
mercury233 committed
1002 1003 1004 1005
            return;
          }
          redisdb.hgetall("replay:" + replay_id, client.open_cloud_replay);
        });
mercury233's avatar
mercury233 committed
1006 1007 1008
      } else if (replay_id) {
        redisdb.hgetall("replay:" + replay_id, client.open_cloud_replay);
      } else {
mercury233's avatar
mercury233 committed
1009
        ygopro.stoc_die(client, "没有找到录像");
mercury233's avatar
mercury233 committed
1010
      }
mercury233's avatar
mercury233 committed
1011 1012 1013
    } else if (info.pass.toUpperCase() === "W" && settings.modules.enable_cloud_replay) {
      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
1014
    } else if (info.version !== settings.version && info.version !== 4921) {
mercury233's avatar
mercury233 committed
1015
      ygopro.stoc_send_chat(client, settings.modules.update, ygopro.constants.COLORS.RED);
mercury233's avatar
fix  
mercury233 committed
1016 1017 1018 1019 1020
      ygopro.stoc_send(client, 'ERROR_MSG', {
        msg: 4,
        code: settings.version
      });
      client.end();
mercury233's avatar
mercury233 committed
1021
    } else if (!info.pass.length && !settings.modules.enable_random_duel) {
mercury233's avatar
mercury233 committed
1022
      ygopro.stoc_die(client, "房间名为空,请填写主机密码");
mercury233's avatar
mercury233 committed
1023
    } else if (settings.modules.enable_windbot && info.pass.slice(0, 2) === 'AI') {
神楽坂玲奈's avatar
神楽坂玲奈 committed
1024
      if (info.pass.length > 3 && info.pass.slice(0, 3) === 'AI#' || info.pass.slice(0, 3) === 'AI_') {
神楽坂玲奈's avatar
神楽坂玲奈 committed
1025
        name = info.pass.slice(3);
mercury233's avatar
mercury233 committed
1026
        windbot = _.sample(_.filter(settings.modules.windbots, function(w) {
神楽坂玲奈's avatar
神楽坂玲奈 committed
1027 1028 1029
          return w.name === name || w.deck === name;
        }));
        if (!windbot) {
mercury233's avatar
mercury233 committed
1030
          ygopro.stoc_die(client, '主机密码不正确 (Invalid Windbot Name)');
神楽坂玲奈's avatar
神楽坂玲奈 committed
1031 1032 1033
          return;
        }
      } else {
mercury233's avatar
mercury233 committed
1034
        windbot = _.sample(settings.modules.windbots);
神楽坂玲奈's avatar
神楽坂玲奈 committed
1035
      }
mercury233's avatar
mercury233 committed
1036 1037 1038 1039 1040 1041 1042 1043
      if (info.version === 4921) {
        info.version = settings.version;
        struct = ygopro.structs["CTOS_JoinGame"];
        struct._setBuff(buffer);
        struct.set("version", info.version);
        buffer = struct.buffer;
        ygopro.stoc_send_chat(client, "您的版本号过低,可能出现未知问题,电脑用户请升级版本,YGOMobile用户请等待作者更新", ygopro.constants.COLORS.BABYBLUE);
      }
mercury233's avatar
mercury233 committed
1044
      room = ROOM_find_or_create_by_name('AI#' + Math.floor(Math.random() * 100000));
mercury233's avatar
mercury233 committed
1045
      if (!room) {
mercury233's avatar
mercury233 committed
1046
        ygopro.stoc_die(client, "服务器已经爆满,请稍候再试");
mercury233's avatar
mercury233 committed
1047
      } else if (room.error) {
mercury233's avatar
mercury233 committed
1048
        ygopro.stoc_die(client, room.error);
mercury233's avatar
mercury233 committed
1049 1050 1051
      } else {
        room.windbot = windbot;
        room["private"] = true;
1052 1053
        client.rid = _.indexOf(ROOM_all, room);
        room.connect(client);
mercury233's avatar
mercury233 committed
1054
      }
1055
    } else if (info.pass.length && settings.modules.mycard_auth) {
mercury233's avatar
mercury233 committed
1056
      ygopro.stoc_send_chat(client, '正在读取用户信息...', ygopro.constants.COLORS.BABYBLUE);
神楽坂玲奈's avatar
fix  
神楽坂玲奈 committed
1057
      if (info.pass.length <= 8) {
mercury233's avatar
mercury233 committed
1058
        ygopro.stoc_die(client, '主机密码不正确 (Invalid Length)');
神楽坂玲奈's avatar
fix  
神楽坂玲奈 committed
1059 1060 1061
        return;
      }
      buffer = new Buffer(info.pass.slice(0, 8), 'base64');
神楽坂玲奈's avatar
fix  
神楽坂玲奈 committed
1062
      if (buffer.length !== 6) {
mercury233's avatar
mercury233 committed
1063
        ygopro.stoc_die(client, '主机密码不正确 (Invalid Payload Length)');
神楽坂玲奈's avatar
fix  
神楽坂玲奈 committed
1064 1065
        return;
      }
神楽坂玲奈's avatar
fix  
神楽坂玲奈 committed
1066 1067 1068 1069 1070
      check = function(buf) {
        var checksum, i, k, ref;
        checksum = 0;
        for (i = k = 0, ref = buf.length; 0 <= ref ? k < ref : k > ref; i = 0 <= ref ? ++k : --k) {
          checksum += buf.readUInt8(i);
1071
        }
神楽坂玲奈's avatar
fix  
神楽坂玲奈 committed
1072 1073 1074
        return (checksum & 0xFF) === 0;
      };
      finish = function(buffer) {
神楽坂玲奈's avatar
神楽坂玲奈 committed
1075
        var action, opt1, opt2, opt3, options;
1076 1077
        action = buffer.readUInt8(1) >> 4;
        if (buffer !== decrypted_buffer && (action === 1 || action === 2 || action === 4)) {
mercury233's avatar
mercury233 committed
1078
          ygopro.stoc_die(client, '主机密码不正确 (Unauthorized)');
1079 1080 1081 1082 1083 1084
          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
1085
            if (ROOM_find_by_name(name)) {
mercury233's avatar
mercury233 committed
1086
              ygopro.stoc_die(client, '主机密码不正确 (Already Existed)');
1087 1088 1089
              return;
            }
            opt1 = buffer.readUInt8(2);
神楽坂玲奈's avatar
fix  
神楽坂玲奈 committed
1090
            opt2 = buffer.readUInt16LE(3);
1091 1092 1093 1094 1095 1096 1097 1098 1099 1100 1101 1102 1103
            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
            };
神楽坂玲奈's avatar
fix  
神楽坂玲奈 committed
1104 1105
            options.lflist = _.findIndex(settings.lflist, function(list) {
              return ((options.rule === 1) === list.tcg) && list.date.isBefore();
神楽坂玲奈's avatar
神楽坂玲奈 committed
1106
            });
1107
            room = new Room(name, options);
神楽坂玲奈's avatar
fix  
神楽坂玲奈 committed
1108
            room.title = info.pass.slice(8).replace(String.fromCharCode(0xFEFF), ' ');
神楽坂玲奈's avatar
神楽坂玲奈 committed
1109
            room["private"] = action === 2;
1110 1111 1112
            break;
          case 3:
            name = info.pass.slice(8);
mercury233's avatar
mercury233 committed
1113
            room = ROOM_find_by_name(name);
1114
            if (!room) {
mercury233's avatar
mercury233 committed
1115
              ygopro.stoc_die(client, '主机密码不正确 (Not Found)');
1116 1117 1118 1119
              return;
            }
            break;
          case 4:
mercury233's avatar
mercury233 committed
1120
            room = ROOM_find_or_create_by_name('M#' + info.pass.slice(8));
神楽坂玲奈's avatar
fix  
神楽坂玲奈 committed
1121
            room["private"] = true;
1122 1123
            break;
          default:
mercury233's avatar
mercury233 committed
1124
            ygopro.stoc_die(client, '主机密码不正确 (Invalid Action)');
1125 1126
            return;
        }
mercury233's avatar
mercury233 committed
1127
        if (!room) {
mercury233's avatar
mercury233 committed
1128
          ygopro.stoc_die(client, "服务器已经爆满,请稍候再试");
mercury233's avatar
mercury233 committed
1129
        } else if (room.error) {
mercury233's avatar
mercury233 committed
1130
          ygopro.stoc_die(client, room.error);
mercury233's avatar
mercury233 committed
1131
        } else {
1132 1133
          client.rid = _.indexOf(ROOM_all, room);
          room.connect(client);
mercury233's avatar
mercury233 committed
1134
        }
神楽坂玲奈's avatar
fix  
神楽坂玲奈 committed
1135 1136 1137 1138 1139 1140 1141 1142 1143 1144 1145 1146 1147 1148 1149 1150 1151 1152 1153 1154 1155 1156 1157 1158 1159 1160 1161 1162 1163 1164 1165 1166 1167 1168 1169 1170 1171
      };
      if (id = users_cache[client.name]) {
        secret = id % 65535 + 1;
        decrypted_buffer = new Buffer(6);
        ref = [0, 2, 4];
        for (k = 0, len = ref.length; k < len; k++) {
          i = ref[k];
          decrypted_buffer.writeUInt16LE(buffer.readUInt16LE(i) ^ secret, i);
        }
        if (check(decrypted_buffer)) {
          return finish(decrypted_buffer);
        }
      }
      request({
        baseUrl: settings.modules.mycard_auth,
        url: '/users/' + encodeURIComponent(client.name) + '.json',
        qs: {
          api_key: 'dc7298a754828b3d26b709f035a0eeceb43e73cbd8c4fa8dec18951f8a95d2bc',
          api_username: client.name,
          skip_track_visit: true
        },
        json: true
      }, function(error, response, body) {
        var l, len1, ref1;
        if (body && body.user) {
          secret = body.user.id % 65535 + 1;
          decrypted_buffer = new Buffer(6);
          ref1 = [0, 2, 4];
          for (l = 0, len1 = ref1.length; l < len1; l++) {
            i = ref1[l];
            decrypted_buffer.writeUInt16LE(buffer.readUInt16LE(i) ^ secret, i);
          }
          if (check(decrypted_buffer)) {
            buffer = decrypted_buffer;
          }
        }
        if (!check(buffer)) {
mercury233's avatar
mercury233 committed
1172
          ygopro.stoc_die(client, '主机密码不正确 (Checksum Failed)');
神楽坂玲奈's avatar
fix  
神楽坂玲奈 committed
1173 1174 1175 1176
          return;
        }
        users_cache[client.name] = body.user.id;
        return finish(buffer);
1177
      });
mercury233's avatar
mercury233 committed
1178
    } else if (info.pass.length && !ROOM_validate(info.pass)) {
mercury233's avatar
mercury233 committed
1179
      ygopro.stoc_die(client, "房间密码不正确");
mercury233's avatar
mercury233 committed
1180 1181
    } else if (_.indexOf(settings.ban.banned_user, client.name) > -1) {
      settings.ban.banned_ip.push(client.remoteAddress);
mercury233's avatar
mercury233 committed
1182
      log.warn("BANNED USER LOGIN", client.name, client.remoteAddress);
mercury233's avatar
mercury233 committed
1183
      ygopro.stoc_die(client, "您的账号已被封禁");
mercury233's avatar
mercury233 committed
1184
    } else if (_.indexOf(settings.ban.banned_ip, client.remoteAddress) > -1) {
mercury233's avatar
mercury233 committed
1185
      log.warn("BANNED IP LOGIN", client.name, client.remoteAddress);
mercury233's avatar
mercury233 committed
1186
      ygopro.stoc_die(client, "您的账号已被封禁");
mercury233's avatar
mercury233 committed
1187 1188
    } else if (_.any(settings.ban.badword_level3, function(badword) {
      var regexp;
mercury233's avatar
fix  
mercury233 committed
1189
      regexp = new RegExp(badword, 'i');
mercury233's avatar
mercury233 committed
1190 1191 1192 1193 1194 1195
      return name.match(regexp);
    }, name = client.name)) {
      log.warn("BAD NAME LEVEL 3", client.name, client.remoteAddress);
      ygopro.stoc_die(client, "您的用户名存在不适当的内容");
    } else if (_.any(settings.ban.badword_level2, function(badword) {
      var regexp;
mercury233's avatar
fix  
mercury233 committed
1196
      regexp = new RegExp(badword, 'i');
mercury233's avatar
mercury233 committed
1197 1198 1199 1200 1201 1202
      return name.match(regexp);
    }, name = client.name)) {
      log.warn("BAD NAME LEVEL 2", client.name, client.remoteAddress);
      ygopro.stoc_die(client, "您的用户名存在不适当的内容");
    } else if (_.any(settings.ban.badword_level1, function(badword) {
      var regexp;
mercury233's avatar
fix  
mercury233 committed
1203
      regexp = new RegExp(badword, 'i');
mercury233's avatar
mercury233 committed
1204 1205 1206 1207
      return name.match(regexp);
    }, name = client.name)) {
      log.warn("BAD NAME LEVEL 1", client.name, client.remoteAddress);
      ygopro.stoc_die(client, "您的用户名存在不适当的内容,请注意更改");
神楽坂玲奈's avatar
init  
神楽坂玲奈 committed
1208
    } else {
mercury233's avatar
mercury233 committed
1209 1210 1211 1212 1213 1214 1215 1216
      if (info.version === 4921) {
        info.version = settings.version;
        struct = ygopro.structs["CTOS_JoinGame"];
        struct._setBuff(buffer);
        struct.set("version", info.version);
        buffer = struct.buffer;
        ygopro.stoc_send_chat(client, "您的版本号过低,可能出现未知问题,电脑用户请升级版本,YGOMobile用户请等待作者更新", ygopro.constants.COLORS.BABYBLUE);
      }
mercury233's avatar
mercury233 committed
1217
      room = ROOM_find_or_create_by_name(info.pass, client.remoteAddress);
mercury233's avatar
mercury233 committed
1218
      if (!room) {
mercury233's avatar
mercury233 committed
1219
        ygopro.stoc_die(client, "服务器已经爆满,请稍候再试");
mercury233's avatar
mercury233 committed
1220
      } else if (room.error) {
mercury233's avatar
mercury233 committed
1221
        ygopro.stoc_die(client, room.error);
mercury233's avatar
mercury233 committed
1222
      } else if (room.started) {
mercury233's avatar
mercury233 committed
1223
        if (settings.modules.enable_halfway_watch) {
1224
          client.rid = _.indexOf(ROOM_all, room);
神楽坂玲奈's avatar
11.7  
神楽坂玲奈 committed
1225
          client.is_post_watcher = true;
1226 1227
          ygopro.stoc_send_chat_to_room(room, client.name + " 加入了观战");
          room.watchers.push(client);
mercury233's avatar
mercury233 committed
1228
          ygopro.stoc_send_chat(client, "观战中", ygopro.constants.COLORS.BABYBLUE);
1229
          ref1 = room.watcher_buffers;
神楽坂玲奈's avatar
fix  
神楽坂玲奈 committed
1230 1231
          for (l = 0, len1 = ref1.length; l < len1; l++) {
            buffer = ref1[l];
神楽坂玲奈's avatar
11.7  
神楽坂玲奈 committed
1232 1233 1234
            client.write(buffer);
          }
        } else {
mercury233's avatar
mercury233 committed
1235
          ygopro.stoc_die(client, "决斗已开始,不允许观战");
神楽坂玲奈's avatar
11.7  
神楽坂玲奈 committed
1236 1237
        }
      } else {
1238 1239
        client.rid = _.indexOf(ROOM_all, room);
        room.connect(client);
神楽坂玲奈's avatar
11.7  
神楽坂玲奈 committed
1240
      }
神楽坂玲奈's avatar
init  
神楽坂玲奈 committed
1241 1242 1243
    }
  });

神楽坂玲奈's avatar
神楽坂玲奈 committed
1244
  ygopro.stoc_follow('JOIN_GAME', false, function(buffer, info, client, server) {
1245 1246 1247
    var recorder, room, watcher;
    room = ROOM_all[client.rid];
    if (!room) {
1248 1249
      return;
    }
神楽坂玲奈's avatar
11.7  
神楽坂玲奈 committed
1250
    if (settings.modules.welcome) {
mercury233's avatar
mercury233 committed
1251
      ygopro.stoc_send_chat(client, settings.modules.welcome, ygopro.constants.COLORS.GREEN);
神楽坂玲奈's avatar
11.7  
神楽坂玲奈 committed
1252
    }
1253 1254
    if (room.welcome) {
      ygopro.stoc_send_chat(client, room.welcome, ygopro.constants.COLORS.BABYBLUE);
mercury233's avatar
add  
mercury233 committed
1255
    }
1256 1257
    if (!room.recorder) {
      room.recorder = recorder = net.connect(room.port, function() {
mercury233's avatar
mercury233 committed
1258 1259 1260 1261 1262 1263 1264 1265 1266 1267 1268 1269
        ygopro.ctos_send(recorder, 'PLAYER_INFO', {
          name: "Marshtomp"
        });
        ygopro.ctos_send(recorder, 'JOIN_GAME', {
          version: settings.version,
          gameid: 2577,
          some_unknown_mysterious_fucking_thing: 0,
          pass: ""
        });
        ygopro.ctos_send(recorder, 'HS_TOOBSERVER');
      });
      recorder.on('data', function(data) {
1270 1271
        room = ROOM_all[client.rid];
        if (!(room && settings.modules.enable_cloud_replay)) {
mercury233's avatar
mercury233 committed
1272 1273
          return;
        }
mercury233's avatar
mercury233 committed
1274
        room.recorder_buffers.push(data);
mercury233's avatar
mercury233 committed
1275 1276 1277
      });
      recorder.on('error', function(error) {});
    }
1278 1279
    if (settings.modules.enable_halfway_watch && !room.watcher) {
      room.watcher = watcher = net.connect(room.port, function() {
神楽坂玲奈's avatar
11.7  
神楽坂玲奈 committed
1280 1281 1282 1283 1284 1285 1286 1287 1288
        ygopro.ctos_send(watcher, 'PLAYER_INFO', {
          name: "the Big Brother"
        });
        ygopro.ctos_send(watcher, 'JOIN_GAME', {
          version: settings.version,
          gameid: 2577,
          some_unknown_mysterious_fucking_thing: 0,
          pass: ""
        });
mercury233's avatar
test3  
mercury233 committed
1289
        ygopro.ctos_send(watcher, 'HS_TOOBSERVER');
神楽坂玲奈's avatar
11.7  
神楽坂玲奈 committed
1290
      });
mercury233's avatar
fix  
mercury233 committed
1291
      watcher.on('data', function(data) {
1292
        var k, len, ref, w;
1293 1294
        room = ROOM_all[client.rid];
        if (!room) {
1295 1296
          return;
        }
1297 1298
        room.watcher_buffers.push(data);
        ref = room.watchers;
1299 1300
        for (k = 0, len = ref.length; k < len; k++) {
          w = ref[k];
神楽坂玲奈's avatar
12.2  
神楽坂玲奈 committed
1301
          if (w) {
mercury233's avatar
test3  
mercury233 committed
1302
            w.write(data);
神楽坂玲奈's avatar
12.2  
神楽坂玲奈 committed
1303
          }
神楽坂玲奈's avatar
11.7  
神楽坂玲奈 committed
1304 1305
        }
      });
mercury233's avatar
test3  
mercury233 committed
1306
      watcher.on('error', function(error) {});
神楽坂玲奈's avatar
神楽坂玲奈 committed
1307
    }
神楽坂玲奈's avatar
tip  
神楽坂玲奈 committed
1308
  });
神楽坂玲奈's avatar
神楽坂玲奈 committed
1309

mercury233's avatar
mercury233 committed
1310
  load_dialogues = function() {
神楽坂玲奈's avatar
11.7  
神楽坂玲奈 committed
1311 1312 1313 1314 1315
    request({
      url: settings.modules.dialogues,
      json: true
    }, function(error, response, body) {
      if (_.isString(body)) {
mercury233's avatar
test3  
mercury233 committed
1316
        log.warn("dialogues bad json", body);
神楽坂玲奈's avatar
12.2  
神楽坂玲奈 committed
1317
      } else if (error || !body) {
mercury233's avatar
test3  
mercury233 committed
1318
        log.warn('dialogues error', error, response);
神楽坂玲奈's avatar
11.7  
神楽坂玲奈 committed
1319
      } else {
mercury233's avatar
mercury233 committed
1320 1321
        nconf.myset(settings, "dialogues", body);
        log.info("dialogues loaded", _.size(body));
神楽坂玲奈's avatar
11.7  
神楽坂玲奈 committed
1322 1323
      }
    });
mercury233's avatar
mercury233 committed
1324 1325 1326 1327
  };

  if (settings.modules.dialogues) {
    load_dialogues();
神楽坂玲奈's avatar
11.7  
神楽坂玲奈 committed
1328 1329
  }

神楽坂玲奈's avatar
神楽坂玲奈 committed
1330
  ygopro.stoc_follow('GAME_MSG', false, function(buffer, info, client, server) {
mercury233's avatar
mercury233 committed
1331
    var card, k, len, line, msg, playertype, pos, reason, ref, ref1, ref2, room, val;
1332 1333 1334 1335
    room = ROOM_all[client.rid];
    if (!room) {
      return;
    }
神楽坂玲奈's avatar
神楽坂玲奈 committed
1336
    msg = buffer.readInt8(0);
1337
    if (msg >= 10 && msg < 30) {
1338 1339
      room.waiting_for_player = client;
      room.last_active_time = moment();
1340
    }
神楽坂玲奈's avatar
11.7  
神楽坂玲奈 committed
1341 1342 1343
    if (ygopro.constants.MSG[msg] === 'START') {
      playertype = buffer.readUInt8(1);
      client.is_first = !(playertype & 0xf);
1344
      client.lp = room.hostinfo.start_lp;
神楽坂玲奈's avatar
11.7  
神楽坂玲奈 committed
1345
    }
mercury233's avatar
mercury233 committed
1346 1347 1348 1349 1350 1351 1352 1353
    if (ygopro.constants.MSG[msg] === 'WIN' && client.is_host) {
      pos = buffer.readUInt8(1);
      if (!(client.is_first || pos === 2)) {
        pos = 1 - pos;
      }
      reason = buffer.readUInt8(2);
      room.winner = pos;
    }
神楽坂玲奈's avatar
12.2  
神楽坂玲奈 committed
1354 1355 1356 1357 1358 1359
    if (ygopro.constants.MSG[msg] === 'DAMAGE' && client.is_host) {
      pos = buffer.readUInt8(1);
      if (!client.is_first) {
        pos = 1 - pos;
      }
      val = buffer.readInt32LE(2);
1360 1361 1362
      room.dueling_players[pos].lp -= val;
      if ((0 < (ref = room.dueling_players[pos].lp) && ref <= 100)) {
        ygopro.stoc_send_chat_to_room(room, "你的生命已经如风中残烛了!", ygopro.constants.COLORS.PINK);
神楽坂玲奈's avatar
12.2  
神楽坂玲奈 committed
1363 1364 1365 1366 1367 1368 1369 1370
      }
    }
    if (ygopro.constants.MSG[msg] === 'RECOVER' && client.is_host) {
      pos = buffer.readUInt8(1);
      if (!client.is_first) {
        pos = 1 - pos;
      }
      val = buffer.readInt32LE(2);
1371
      room.dueling_players[pos].lp += val;
神楽坂玲奈's avatar
12.2  
神楽坂玲奈 committed
1372 1373 1374 1375 1376 1377 1378
    }
    if (ygopro.constants.MSG[msg] === 'LPUPDATE' && client.is_host) {
      pos = buffer.readUInt8(1);
      if (!client.is_first) {
        pos = 1 - pos;
      }
      val = buffer.readInt32LE(2);
1379
      room.dueling_players[pos].lp = val;
神楽坂玲奈's avatar
12.2  
神楽坂玲奈 committed
1380 1381 1382 1383 1384 1385 1386
    }
    if (ygopro.constants.MSG[msg] === 'PAY_LPCOST' && client.is_host) {
      pos = buffer.readUInt8(1);
      if (!client.is_first) {
        pos = 1 - pos;
      }
      val = buffer.readInt32LE(2);
1387 1388 1389
      room.dueling_players[pos].lp -= val;
      if ((0 < (ref1 = room.dueling_players[pos].lp) && ref1 <= 100)) {
        ygopro.stoc_send_chat_to_room(room, "背水一战!", ygopro.constants.COLORS.PINK);
神楽坂玲奈's avatar
12.2  
神楽坂玲奈 committed
1390 1391
      }
    }
神楽坂玲奈's avatar
11.7  
神楽坂玲奈 committed
1392 1393 1394
    if (settings.modules.dialogues) {
      if (ygopro.constants.MSG[msg] === 'SUMMONING' || ygopro.constants.MSG[msg] === 'SPSUMMONING') {
        card = buffer.readUInt32LE(1);
mercury233's avatar
mercury233 committed
1395 1396
        if (settings.dialogues[card]) {
          ref2 = _.lines(settings.dialogues[card][Math.floor(Math.random() * settings.dialogues[card].length)]);
1397 1398
          for (k = 0, len = ref2.length; k < len; k++) {
            line = ref2[k];
mercury233's avatar
mercury233 committed
1399
            ygopro.stoc_send_chat(client, line, ygopro.constants.COLORS.PINK);
神楽坂玲奈's avatar
11.7  
神楽坂玲奈 committed
1400
          }
神楽坂玲奈's avatar
神楽坂玲奈 committed
1401
        }
神楽坂玲奈's avatar
 
神楽坂玲奈 committed
1402 1403 1404 1405
      }
    }
  });

1406
  ygopro.ctos_follow('HS_KICK', true, function(buffer, info, client, server) {
1407 1408 1409
    var k, len, player, ref, room;
    room = ROOM_all[client.rid];
    if (!room) {
1410 1411
      return;
    }
1412
    ref = room.players;
1413 1414
    for (k = 0, len = ref.length; k < len; k++) {
      player = ref[k];
mercury233's avatar
mercury233 committed
1415
      if (player && player.pos === info.pos && player !== client) {
mercury233's avatar
mercury233 committed
1416 1417 1418 1419 1420 1421 1422
        client.kick_count = client.kick_count ? client.kick_count + 1 : 1;
        if (client.kick_count >= 5) {
          ygopro.stoc_send_chat_to_room(room, client.name + " 被系统请出了房间", ygopro.constants.COLORS.RED);
          ROOM_ban_player(player.name, player.ip, "挂房间");
          client.end();
          return true;
        }
1423
        ygopro.stoc_send_chat_to_room(room, player.name + " 被请出了房间", ygopro.constants.COLORS.RED);
1424 1425 1426 1427 1428
      }
    }
    return false;
  });

神楽坂玲奈's avatar
神楽坂玲奈 committed
1429 1430 1431 1432 1433
  ygopro.stoc_follow('TYPE_CHANGE', false, function(buffer, info, client, server) {
    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
1434
    client.pos = selftype;
神楽坂玲奈's avatar
神楽坂玲奈 committed
1435 1436
  });

1437
  ygopro.stoc_follow('HS_PLAYER_CHANGE', false, function(buffer, info, client, server) {
1438 1439 1440
    var is_ready, k, len, player, pos, ref, room;
    room = ROOM_all[client.rid];
    if (!(room && room.max_player && client.is_host)) {
1441 1442 1443 1444
      return;
    }
    pos = info.status >> 4;
    is_ready = (info.status & 0xf) === 9;
1445 1446 1447
    if (pos < room.max_player) {
      room.ready_player_count_without_host = 0;
      ref = room.players;
1448 1449 1450 1451 1452 1453
      for (k = 0, len = ref.length; k < len; k++) {
        player = ref[k];
        if (player.pos === pos) {
          player.is_ready = is_ready;
        }
        if (!player.is_host) {
1454
          room.ready_player_count_without_host += player.is_ready;
1455 1456
        }
      }
1457
      if (room.ready_player_count_without_host >= room.max_player - 1) {
1458
        setTimeout((function() {
1459
          wait_room_start(ROOM_all[client.rid], 20);
1460 1461 1462 1463 1464 1465 1466 1467 1468 1469 1470
        }), 1000);
      }
    }
  });

  wait_room_start = function(room, time) {
    var k, len, player, ref;
    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
1471
          ygopro.stoc_send_chat_to_room(room, "" + (time <= 9 ? ' ' : '') + time + "秒后房主若不开始游戏将被请出房间", time <= 9 ? ygopro.constants.COLORS.RED : ygopro.constants.COLORS.LIGHTBLUE);
1472 1473 1474 1475 1476 1477 1478 1479
        }
        setTimeout((function() {
          wait_room_start(room, time);
        }), 1000);
      } else {
        ref = room.players;
        for (k = 0, len = ref.length; k < len; k++) {
          player = ref[k];
mercury233's avatar
fix  
mercury233 committed
1480
          if (player && player.is_host) {
mercury233's avatar
mercury233 committed
1481
            ROOM_ban_player(player.name, player.ip, "挂房间");
mercury233's avatar
mercury233 committed
1482
            ygopro.stoc_send_chat_to_room(room, player.name + " 被系统请出了房间", ygopro.constants.COLORS.RED);
1483 1484 1485 1486 1487 1488 1489
            player.end();
          }
        }
      }
    }
  };

神楽坂玲奈's avatar
11.7  
神楽坂玲奈 committed
1490
  ygopro.stoc_send_random_tip = function(client) {
mercury233's avatar
mercury233 committed
1491 1492
    if (settings.modules.tips) {
      ygopro.stoc_send_chat(client, "Tip: " + settings.tips[Math.floor(Math.random() * settings.tips.length)]);
神楽坂玲奈's avatar
神楽坂玲奈 committed
1493
    }
神楽坂玲奈's avatar
11.7  
神楽坂玲奈 committed
1494 1495
  };

1496
  ygopro.stoc_send_random_tip_to_room = function(room) {
mercury233's avatar
mercury233 committed
1497 1498
    if (settings.modules.tips) {
      ygopro.stoc_send_chat_to_room(room, "Tip: " + settings.tips[Math.floor(Math.random() * settings.tips.length)]);
1499 1500 1501
    }
  };

mercury233's avatar
mercury233 committed
1502
  load_tips = function() {
神楽坂玲奈's avatar
fix  
神楽坂玲奈 committed
1503 1504 1505 1506
    request({
      url: settings.modules.tips,
      json: true
    }, function(error, response, body) {
mercury233's avatar
mercury233 committed
1507 1508 1509 1510 1511 1512 1513
      if (_.isString(body)) {
        log.warn("tips bad json", body);
      } else if (error || !body) {
        log.warn('tips error', error, response);
      } else {
        nconf.myset(settings, "tips", body);
        log.info("tips loaded", settings.tips.length);
mercury233's avatar
mercury233 committed
1514
      }
神楽坂玲奈's avatar
fix  
神楽坂玲奈 committed
1515
    });
mercury233's avatar
mercury233 committed
1516 1517 1518 1519 1520
  };

  if (settings.modules.tips) {
    load_tips();
    setInterval(function() {
mercury233's avatar
mercury233 committed
1521 1522 1523
      var k, len, room;
      for (k = 0, len = ROOM_all.length; k < len; k++) {
        room = ROOM_all[k];
1524 1525 1526 1527
        if (room && room.established) {
          if (!(room && room.started)) {
            ygopro.stoc_send_random_tip_to_room(room);
          }
mercury233's avatar
mercury233 committed
1528 1529 1530
        }
      }
    }, 30000);
神楽坂玲奈's avatar
fix  
神楽坂玲奈 committed
1531
  }
神楽坂玲奈's avatar
11.7  
神楽坂玲奈 committed
1532

神楽坂玲奈's avatar
fix  
神楽坂玲奈 committed
1533 1534 1535 1536
  if (settings.modules.mycard_auth && process.env.MYCARD_AUTH_DATABASE) {
    pg = require('pg');
    pg.connect(process.env.MYCARD_AUTH_DATABASE, function(error, client, done) {
      if (error) {
神楽坂玲奈's avatar
fix  
神楽坂玲奈 committed
1537
        throw error;
神楽坂玲奈's avatar
fix  
神楽坂玲奈 committed
1538
      }
mercury233's avatar
mercury233 committed
1539
      client.query('SELECT username, id from users', function(error, result) {
神楽坂玲奈's avatar
fix  
神楽坂玲奈 committed
1540
        var k, len, ref, row;
神楽坂玲奈's avatar
fix  
神楽坂玲奈 committed
1541 1542 1543
        if (error) {
          throw error;
        }
神楽坂玲奈's avatar
fix  
神楽坂玲奈 committed
1544 1545 1546 1547 1548 1549
        done();
        ref = result.rows;
        for (k = 0, len = ref.length; k < len; k++) {
          row = ref[k];
          users_cache[row.username] = row.id;
        }
mercury233's avatar
mercury233 committed
1550
        console.log("users loaded", _.keys(users_cache).length);
神楽坂玲奈's avatar
fix  
神楽坂玲奈 committed
1551 1552 1553 1554
      });
    });
  }

神楽坂玲奈's avatar
11.7  
神楽坂玲奈 committed
1555
  ygopro.stoc_follow('DUEL_START', false, function(buffer, info, client, server) {
1556 1557 1558
    var k, len, player, ref, room;
    room = ROOM_all[client.rid];
    if (!room) {
1559 1560
      return;
    }
1561 1562 1563 1564
    if (!room.started) {
      room.started = true;
      if (settings.modules.enable_websocket_roomlist && !room["private"]) {
        roomlist["delete"](room.name);
神楽坂玲奈's avatar
神楽坂玲奈 committed
1565
      }
1566 1567
      room.dueling_players = [];
      ref = room.players;
1568 1569
      for (k = 0, len = ref.length; k < len; k++) {
        player = ref[k];
mercury233's avatar
mercury233 committed
1570 1571
        if (!(player.pos !== 7)) {
          continue;
神楽坂玲奈's avatar
12.2  
神楽坂玲奈 committed
1572
        }
1573 1574
        room.dueling_players[player.pos] = player;
        room.player_datas.push({
mercury233's avatar
mercury233 committed
1575 1576 1577
          ip: player.remoteAddress,
          name: player.name
        });
1578 1579
        if (room.windbot) {
          room.dueling_players[1 - player.pos] = {};
神楽坂玲奈's avatar
神楽坂玲奈 committed
1580
        }
神楽坂玲奈's avatar
11.7  
神楽坂玲奈 committed
1581 1582 1583
      }
    }
    if (settings.modules.tips) {
mercury233's avatar
test3  
mercury233 committed
1584
      ygopro.stoc_send_random_tip(client);
神楽坂玲奈's avatar
11.7  
神楽坂玲奈 committed
1585 1586 1587
    }
  });

1588
  ygopro.ctos_follow('CHAT', true, function(buffer, info, client, server) {
mercury233's avatar
mercury233 committed
1589
    var cancel, msg, oldmsg, room, struct;
1590 1591
    room = ROOM_all[client.rid];
    if (!room) {
mercury233's avatar
mercury233 committed
1592 1593
      return;
    }
mercury233's avatar
mercury233 committed
1594 1595
    msg = _.trim(info.msg);
    cancel = _.startsWith(msg, "/");
1596 1597
    if (!(cancel || !room.random_type)) {
      room.last_active_time = moment();
1598
    }
mercury233's avatar
mercury233 committed
1599
    switch (msg) {
神楽坂玲奈's avatar
11.7  
神楽坂玲奈 committed
1600
      case '/help':
mercury233's avatar
mercury233 committed
1601
        ygopro.stoc_send_chat(client, "YGOSrv233 指令帮助");
神楽坂玲奈's avatar
11.7  
神楽坂玲奈 committed
1602
        ygopro.stoc_send_chat(client, "/help 显示这个帮助信息");
1603
        ygopro.stoc_send_chat(client, "/roomname 显示当前房间的名字");
神楽坂玲奈's avatar
11.7  
神楽坂玲奈 committed
1604
        if (settings.modules.tips) {
mercury233's avatar
test3  
mercury233 committed
1605
          ygopro.stoc_send_chat(client, "/tip 显示一条提示");
神楽坂玲奈's avatar
11.7  
神楽坂玲奈 committed
1606
        }
mercury233's avatar
mercury233 committed
1607
        break;
神楽坂玲奈's avatar
11.7  
神楽坂玲奈 committed
1608 1609
      case '/tip':
        if (settings.modules.tips) {
mercury233's avatar
test3  
mercury233 committed
1610
          ygopro.stoc_send_random_tip(client);
神楽坂玲奈's avatar
11.7  
神楽坂玲奈 committed
1611
        }
mercury233's avatar
mercury233 committed
1612 1613
        break;
      case '/roomname':
1614 1615
        if (room) {
          ygopro.stoc_send_chat(client, "您当前的房间名是 " + room.name, ygopro.constants.COLORS.BABYBLUE);
mercury233's avatar
mercury233 committed
1616
        }
神楽坂玲奈's avatar
神楽坂玲奈 committed
1617
    }
mercury233's avatar
mercury233 committed
1618 1619 1620 1621 1622 1623
    if (!(room && room.random_type)) {
      return cancel;
    }
    oldmsg = msg;
    if (_.any(settings.ban.badword_level3, function(badword) {
      var regexp;
mercury233's avatar
fix  
mercury233 committed
1624
      regexp = new RegExp(badword, 'i');
mercury233's avatar
mercury233 committed
1625 1626
      return msg.match(regexp);
    }, msg)) {
mercury233's avatar
mercury233 committed
1627
      log.warn("BAD WORD LEVEL 3", client.name, client.remoteAddress, oldmsg);
mercury233's avatar
mercury233 committed
1628 1629 1630 1631 1632 1633 1634
      ygopro.stoc_send_chat(client, "您的发言存在不适当的内容,禁止您使用随机对战功能!", ygopro.constants.COLORS.RED);
      ROOM_ban_player(client.name, client.ip, "发言违规");
      ROOM_ban_player(client.name, client.ip, "发言违规", 3);
      client.end();
      cancel = true;
    } else if (_.any(settings.ban.badword_level2, function(badword) {
      var regexp;
mercury233's avatar
fix  
mercury233 committed
1635
      regexp = new RegExp(badword, 'i');
mercury233's avatar
mercury233 committed
1636 1637
      return msg.match(regexp);
    }, msg)) {
mercury233's avatar
mercury233 committed
1638
      log.warn("BAD WORD LEVEL 2", client.name, client.remoteAddress, oldmsg);
mercury233's avatar
mercury233 committed
1639
      ygopro.stoc_send_chat(client, "您的发言存在不适当的内容,发送失败,并记录一次违规!", ygopro.constants.COLORS.RED);
mercury233's avatar
mercury233 committed
1640 1641 1642 1643 1644
      ROOM_ban_player(client.name, client.ip, "发言违规");
      cancel = true;
    } else {
      _.each(settings.ban.badword_level1, function(badword) {
        var regexp;
mercury233's avatar
fix  
mercury233 committed
1645
        regexp = new RegExp(badword, "ig");
mercury233's avatar
mercury233 committed
1646 1647 1648
        msg = msg.replace(regexp, "**");
      }, msg);
      if (oldmsg !== msg) {
mercury233's avatar
mercury233 committed
1649
        log.warn("BAD WORD LEVEL 1", client.name, client.remoteAddress, oldmsg);
mercury233's avatar
mercury233 committed
1650
        ygopro.stoc_send_chat(client, "请使用文明用语");
mercury233's avatar
mercury233 committed
1651 1652 1653 1654 1655 1656 1657 1658 1659 1660
        struct = ygopro.structs["chat"];
        struct._setBuff(buffer);
        struct.set("msg", msg);
        buffer = struct.buffer;
      } else if (_.any(settings.ban.badword_level0, function(badword) {
        var regexp;
        regexp = new RegExp(badword, 'i');
        return msg.match(regexp);
      }, msg)) {
        log.info("BAD WORD LEVEL 0", client.name, client.remoteAddress, oldmsg);
mercury233's avatar
mercury233 committed
1661 1662
      }
    }
1663
    return cancel;
神楽坂玲奈's avatar
11.7  
神楽坂玲奈 committed
1664 1665
  });

mercury233's avatar
mercury233 committed
1666 1667 1668 1669 1670 1671 1672
  ygopro.ctos_follow('UPDATE_DECK', true, function(buffer, info, client, server) {
    var buff_main, buff_side, card, current_deck, deck, deck_array, deck_main, deck_side, deck_text, deckbuf, decks, found_deck, i, k, l, len, len1, line, room, struct;
    room = ROOM_all[client.rid];
    if (!room) {
      return false;
    }
    buff_main = (function() {
1673
      var k, ref, results;
1674
      results = [];
1675
      for (i = k = 0, ref = info.mainc; 0 <= ref ? k < ref : k > ref; i = 0 <= ref ? ++k : --k) {
1676
        results.push(info.deckbuf[i]);
神楽坂玲奈's avatar
11.7  
神楽坂玲奈 committed
1677
      }
1678
      return results;
神楽坂玲奈's avatar
11.7  
神楽坂玲奈 committed
1679
    })();
mercury233's avatar
mercury233 committed
1680
    buff_side = (function() {
1681
      var k, ref, ref1, results;
1682
      results = [];
1683
      for (i = k = ref = info.mainc, ref1 = info.mainc + info.sidec; ref <= ref1 ? k < ref1 : k > ref1; i = ref <= ref1 ? ++k : --k) {
1684
        results.push(info.deckbuf[i]);
神楽坂玲奈's avatar
11.7  
神楽坂玲奈 committed
1685
      }
1686
      return results;
神楽坂玲奈's avatar
11.7  
神楽坂玲奈 committed
1687
    })();
mercury233's avatar
mercury233 committed
1688 1689 1690 1691 1692 1693 1694 1695 1696 1697 1698 1699 1700 1701 1702 1703 1704 1705 1706 1707 1708
    if (room.random_type) {
      if (client.is_host) {
        room.waiting_for_player = room.waiting_for_player2;
      }
      room.last_active_time = moment();
    } else if (!room.started && room.hostinfo.mode === 1 && settings.modules.tournament_mode.enabled) {
      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);
      for (k = 0, len = decks.length; k < len; k++) {
        deck = decks[k];
        if (_.endsWith(deck, client.name + ".ydk")) {
          found_deck = deck;
        }
      }
      if (found_deck) {
mercury233's avatar
mercury233 committed
1709
        deck_text = fs.readFileSync(settings.modules.tournament_mode.deck_path + found_deck, {
mercury233's avatar
mercury233 committed
1710 1711 1712 1713 1714 1715 1716 1717 1718 1719 1720 1721 1722 1723 1724 1725 1726 1727 1728 1729 1730 1731
          encoding: "ASCII"
        });
        deck_array = deck_text.split("\n");
        deck_main = [];
        deck_side = [];
        current_deck = deck_main;
        for (l = 0, len1 = deck_array.length; l < len1; l++) {
          line = deck_array[l];
          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
1732
          ygopro.stoc_send_chat(client, "成功使用卡组 " + found_deck + " 参加比赛。", ygopro.constants.COLORS.BABYBLUE);
mercury233's avatar
mercury233 committed
1733
        } else {
mercury233's avatar
mercury233 committed
1734
          ygopro.stoc_send_chat(client, "您的卡组与报名卡组 " + found_deck + " 不符。注意卡组不能有包括卡片顺序在内的任何修改。", ygopro.constants.COLORS.RED);
mercury233's avatar
mercury233 committed
1735 1736
        }
      } else {
mercury233's avatar
mercury233 committed
1737
        ygopro.stoc_send_chat(client, client.name + ",没有找到您的报名信息,请确定您使用昵称与报名ID一致。", ygopro.constants.COLORS.RED);
mercury233's avatar
mercury233 committed
1738
      }
mercury233's avatar
mercury233 committed
1739
    }
mercury233's avatar
mercury233 committed
1740
    return false;
神楽坂玲奈's avatar
11.7  
神楽坂玲奈 committed
1741 1742
  });

1743
  ygopro.ctos_follow('RESPONSE', false, function(buffer, info, client, server) {
1744 1745 1746
    var room;
    room = ROOM_all[client.rid];
    if (!(room && room.random_type)) {
1747 1748
      return;
    }
1749
    room.last_active_time = moment();
1750 1751 1752
  });

  ygopro.ctos_follow('HAND_RESULT', false, function(buffer, info, client, server) {
1753 1754 1755
    var room;
    room = ROOM_all[client.rid];
    if (!(room && room.random_type)) {
1756 1757 1758
      return;
    }
    if (client.is_host) {
1759
      room.waiting_for_player = room.waiting_for_player2;
1760
    }
1761
    room.last_active_time = moment().subtract(settings.modules.hang_timeout - 19, 's');
1762 1763 1764
  });

  ygopro.ctos_follow('TP_RESULT', false, function(buffer, info, client, server) {
1765 1766 1767
    var room;
    room = ROOM_all[client.rid];
    if (!(room && room.random_type)) {
1768 1769
      return;
    }
1770
    room.last_active_time = moment();
1771 1772 1773
  });

  ygopro.stoc_follow('SELECT_HAND', false, function(buffer, info, client, server) {
1774 1775 1776
    var room;
    room = ROOM_all[client.rid];
    if (!(room && room.random_type)) {
1777 1778 1779
      return;
    }
    if (client.is_host) {
1780
      room.waiting_for_player = client;
1781
    } else {
1782
      room.waiting_for_player2 = client;
1783
    }
1784
    room.last_active_time = moment().subtract(settings.modules.hang_timeout - 19, 's');
1785 1786 1787
  });

  ygopro.stoc_follow('SELECT_TP', false, function(buffer, info, client, server) {
1788 1789 1790
    var room;
    room = ROOM_all[client.rid];
    if (!(room && room.random_type)) {
1791 1792
      return;
    }
1793 1794
    room.waiting_for_player = client;
    room.last_active_time = moment();
1795 1796
  });

mercury233's avatar
mercury233 committed
1797
  ygopro.stoc_follow('CHANGE_SIDE', false, function(buffer, info, client, server) {
1798 1799 1800
    var room;
    room = ROOM_all[client.rid];
    if (!(room && room.random_type)) {
mercury233's avatar
mercury233 committed
1801 1802 1803
      return;
    }
    if (client.is_host) {
1804
      room.waiting_for_player = client;
mercury233's avatar
mercury233 committed
1805
    } else {
1806
      room.waiting_for_player2 = client;
mercury233's avatar
mercury233 committed
1807
    }
1808
    room.last_active_time = moment();
mercury233's avatar
mercury233 committed
1809 1810
  });

1811
  ygopro.stoc_follow('REPLAY', true, function(buffer, info, client, server) {
mercury233's avatar
mercury233 committed
1812
    var player, room;
1813 1814 1815 1816 1817
    room = ROOM_all[client.rid];
    if (!room) {
      return settings.modules.tournament_mode.enabled;
    }
    if (settings.modules.tournament_mode.enabled) {
mercury233's avatar
mercury233 committed
1818 1819 1820 1821 1822 1823 1824 1825 1826 1827 1828 1829 1830 1831 1832 1833 1834 1835 1836 1837 1838 1839 1840
      if (client.is_host) {
        log = {
          time: moment().format('YYYY-MM-DD HH:mm:ss'),
          name: room.name,
          roomid: room.port.toString(),
          cloud_replay_id: "R#" + room.cloud_replay_id,
          players: (function() {
            var k, len, ref, results;
            ref = room.players;
            results = [];
            for (k = 0, len = ref.length; k < len; k++) {
              player = ref[k];
              results.push({
                name: player.name,
                winner: player.pos === room.winner
              });
            }
            return results;
          })()
        };
        settings.modules.tournament_mode.duel_log.push(log);
        nconf.myset(settings, "modules:tournament_mode:duel_log", settings.modules.tournament_mode.duel_log);
      }
mercury233's avatar
mercury233 committed
1841 1842 1843 1844
      if (settings.modules.enable_cloud_replay) {
        ygopro.stoc_send_chat(client, "本场比赛云录像:R#" + room.cloud_replay_id + "。将于MATCH结束后可播放。", ygopro.constants.COLORS.BABYBLUE);
        Cloud_replay_ids.push(room.cloud_replay_id);
      }
1845 1846 1847 1848 1849 1850
      return true;
    } else {
      return false;
    }
  });

1851
  setInterval(function() {
mercury233's avatar
mercury233 committed
1852 1853 1854
    var k, len, room, time_passed;
    for (k = 0, len = ROOM_all.length; k < len; k++) {
      room = ROOM_all[k];
mercury233's avatar
mercury233 committed
1855
      if (!(room && room.started && room.random_type && room.last_active_time && room.waiting_for_player)) {
1856 1857 1858 1859 1860
        continue;
      }
      time_passed = Math.floor((moment() - room.last_active_time) / 1000);
      if (time_passed >= settings.modules.hang_timeout) {
        room.last_active_time = moment();
mercury233's avatar
mercury233 committed
1861
        ROOM_ban_player(room.waiting_for_player.name, room.waiting_for_player.ip, "挂机");
mercury233's avatar
mercury233 committed
1862
        ygopro.stoc_send_chat_to_room(room, room.waiting_for_player.name + " 被系统请出了房间", ygopro.constants.COLORS.RED);
1863 1864
        room.waiting_for_player.server.end();
      } else if (time_passed >= (settings.modules.hang_timeout - 20) && !(time_passed % 10)) {
mercury233's avatar
mercury233 committed
1865
        ygopro.stoc_send_chat_to_room(room, room.waiting_for_player.name + " 已经很久没有操作了,若继续挂机,将于" + (settings.modules.hang_timeout - time_passed) + "秒后被请出房间", ygopro.constants.COLORS.RED);
1866 1867 1868 1869
      }
    }
  }, 1000);

神楽坂玲奈's avatar
11.7  
神楽坂玲奈 committed
1870
  if (settings.modules.http) {
1871
    requestListener = function(request, response) {
mercury233's avatar
mercury233 committed
1872
      var duellog, k, len, parseQueryString, pass_validated, player, room, roomsjson, u;
1873 1874 1875 1876
      parseQueryString = true;
      u = url.parse(request.url, parseQueryString);
      pass_validated = u.query.pass === settings.modules.http.password;
      if (u.pathname === '/api/getrooms') {
1877
        if (!pass_validated) {
1878 1879 1880 1881 1882 1883
          response.writeHead(200);
          response.end(u.query.callback + '( {"rooms":[{"roomid":"0","roomname":"密码错误","needpass":"true"}]} );');
        } else {
          response.writeHead(200);
          roomsjson = JSON.stringify({
            rooms: (function() {
mercury233's avatar
mercury233 committed
1884
              var k, len, results;
1885
              results = [];
mercury233's avatar
mercury233 committed
1886 1887
              for (k = 0, len = ROOM_all.length; k < len; k++) {
                room = ROOM_all[k];
1888
                if (room && room.established) {
1889
                  results.push({
mercury233's avatar
mercury233 committed
1890
                    pid: room.process.pid.toString(),
1891 1892 1893 1894
                    roomid: room.port.toString(),
                    roomname: pass_validated ? room.name : room.name.split('$', 2)[0],
                    needpass: (room.name.indexOf('$') !== -1).toString(),
                    users: (function() {
mercury233's avatar
mercury233 committed
1895 1896
                      var l, len1, ref, results1;
                      ref = room.players;
1897
                      results1 = [];
mercury233's avatar
mercury233 committed
1898 1899
                      for (l = 0, len1 = ref.length; l < len1; l++) {
                        player = ref[l];
1900 1901 1902 1903 1904 1905 1906
                        if (player.pos != null) {
                          results1.push({
                            id: (-1).toString(),
                            name: player.name,
                            pos: player.pos
                          });
                        }
神楽坂玲奈's avatar
11.7  
神楽坂玲奈 committed
1907
                      }
1908 1909 1910 1911 1912
                      return results1;
                    })(),
                    istart: room.started ? 'start' : 'wait'
                  });
                }
神楽坂玲奈's avatar
11.7  
神楽坂玲奈 committed
1913
              }
1914 1915 1916 1917 1918
              return results;
            })()
          });
          response.end(u.query.callback + "( " + roomsjson + " );");
        }
mercury233's avatar
mercury233 committed
1919 1920 1921 1922 1923 1924 1925 1926 1927 1928
      } else if (u.pathname === '/api/duellog' && settings.modules.tournament_mode.enabled) {
        if (!pass_validated) {
          response.writeHead(200);
          response.end("密码错误");
          return;
        } else {
          response.writeHead(200);
          duellog = JSON.stringify(settings.modules.tournament_mode.duel_log);
          response.end(u.query.callback + "( " + duellog + " );");
        }
1929 1930 1931
      } else if (u.pathname === '/api/message') {
        if (!pass_validated) {
          response.writeHead(200);
mercury233's avatar
mercury233 committed
1932
          response.end(u.query.callback + "( ['密码错误', 0] );");
1933 1934 1935
          return;
        }
        if (u.query.shout) {
mercury233's avatar
mercury233 committed
1936 1937
          for (k = 0, len = ROOM_all.length; k < len; k++) {
            room = ROOM_all[k];
1938 1939 1940
            if (room && room.established) {
              ygopro.stoc_send_chat_to_room(room, u.query.shout, ygopro.constants.COLORS.YELLOW);
            }
1941 1942
          }
          response.writeHead(200);
mercury233's avatar
mercury233 committed
1943
          response.end(u.query.callback + "( ['shout ok', '" + u.query.shout + "'] );");
1944 1945 1946 1947 1948 1949
        } else if (u.query.stop) {
          if (u.query.stop === 'false') {
            u.query.stop = false;
          }
          settings.modules.stop = u.query.stop;
          response.writeHead(200);
mercury233's avatar
mercury233 committed
1950
          response.end(u.query.callback + "( ['stop ok', '" + u.query.stop + "'] );");
1951
        } else if (u.query.welcome) {
mercury233's avatar
mercury233 committed
1952 1953 1954 1955
          nconf.myset(settings, 'modules:welcome', u.query.welcome);
          response.writeHead(200);
          response.end(u.query.callback + "( ['welcome ok', '" + u.query.welcome + "'] );");
        } else if (u.query.getwelcome) {
1956
          response.writeHead(200);
mercury233's avatar
mercury233 committed
1957
          response.end(u.query.callback + "( ['get ok', '" + settings.modules.welcome + "'] );");
mercury233's avatar
mercury233 committed
1958 1959 1960 1961 1962 1963 1964 1965
        } else if (u.query.loadtips) {
          load_tips();
          response.writeHead(200);
          response.end(u.query.callback + "( ['loading tip', '" + settings.modules.tips + "'] );");
        } else if (u.query.loaddialogues) {
          load_dialogues();
          response.writeHead(200);
          response.end(u.query.callback + "( ['loading dialogues', '" + settings.modules.dialogues + "'] );");
mercury233's avatar
mercury233 committed
1966
        } else if (u.query.ban) {
mercury233's avatar
mercury233 committed
1967
          ban_user(u.query.ban);
mercury233's avatar
mercury233 committed
1968
          response.writeHead(200);
mercury233's avatar
mercury233 committed
1969
          response.end(u.query.callback + "( ['ban ok', '" + u.query.ban + "'] );");
1970 1971 1972
        } else {
          response.writeHead(404);
          response.end();
1973
        }
神楽坂玲奈's avatar
11.7  
神楽坂玲奈 committed
1974 1975
      } else {
        response.writeHead(404);
mercury233's avatar
test3  
mercury233 committed
1976
        response.end();
神楽坂玲奈's avatar
11.7  
神楽坂玲奈 committed
1977
      }
1978 1979
    };
    http_server = http.createServer(requestListener);
神楽坂玲奈's avatar
神楽坂玲奈 committed
1980
    http_server.listen(settings.modules.http.port);
mercury233's avatar
mercury233 committed
1981
    if (settings.modules.http.ssl.enabled) {
1982 1983 1984 1985 1986 1987
      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);
神楽坂玲奈's avatar
神楽坂玲奈 committed
1988
      roomlist.init(https_server, Room);
1989 1990
      https_server.listen(settings.modules.http.ssl.port);
    }
神楽坂玲奈's avatar
11.7  
神楽坂玲奈 committed
1991
  }
神楽坂玲奈's avatar
神楽坂玲奈 committed
1992

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