Commit ed52f897 authored by nanahira's avatar nanahira

add reconnect

parent 5c4550cb
......@@ -29,7 +29,8 @@
"34": "HS_READY",
"35": "HS_NOTREADY",
"36": "HS_KICK",
"37": "HS_START"
"37": "HS_START",
"48": "REQUEST_FIELD"
},
"STOC": {
"1": "GAME_MSG",
......@@ -51,7 +52,8 @@
"25": "CHAT",
"32": "HS_PLAYER_ENTER",
"33": "HS_PLAYER_CHANGE",
"34": "HS_WATCH_CHANGE"
"34": "HS_WATCH_CHANGE",
"48": "FIELD_FINISH"
},
"PLAYERCHANGE":{
"8": "OBSERVE",
......
......@@ -86,6 +86,10 @@
"enabled": true,
"max_retry_count": false
},
"reconnect": {
"enabled": true,
"wait_time": 300000
},
"mycard": {
"enabled": false,
"auth_base_url": "https://ygobbs.com",
......
......@@ -131,6 +131,10 @@
"retry_too_much_part2": " times.",
"retry_too_much_room_part1": " was kicked from the room for performing an illegal operation ",
"retry_too_much_room_part2": " times.",
"pre_reconnecting_to_room": "You will be reconnected to your previous game. Please pick your Previous deck.",
"deck_incorrect_reconnect": "Please pick your Previous deck.",
"reconnect_failed": "Reconnect failed.",
"reconnecting_to_room": "Reconnecting to server...",
"athletic_arena_tip": "During an athletic match, a game quit behavior is regarded as a surrender."
},
"es-es": {
......@@ -398,6 +402,10 @@
"retry_too_much_part2": "次,已被请出房间。",
"retry_too_much_room_part1": " 由于在决斗中违规操作",
"retry_too_much_room_part2": "次,已被请出房间。",
"pre_reconnecting_to_room": "你有未完成的对局,即将重新连接,请选择你在本局决斗中使用的卡组并准备。",
"deck_incorrect_reconnect": "请选择你在本局决斗中使用的卡组。",
"reconnect_failed": "重新连接失败。",
"reconnecting_to_room": "正在重新连接到服务器……",
"athletic_arena_tip": "在竞技匹配中,比赛开始前退出游戏也会视为投降。"
},
"ko-kr": {
......
......@@ -3,7 +3,7 @@
{"name": "lflist", "type": "unsigned int"},
{"name": "rule", "type": "unsigned char"},
{"name": "mode", "type": "unsigned char"},
{"name": "enable_priority", "type": "bool"},
{"name": "duel_rule", "type": "unsigned char"},
{"name": "no_check_deck", "type": "bool"},
{"name": "no_shuffle_deck", "type": "bool"},
{"name": "start_lp", "type": "unsigned int"},
......
......@@ -254,7 +254,7 @@ ROOM_players_oppentlist = {}
ROOM_players_banned = []
ROOM_connected_ip = {}
ROOM_bad_ip = {}
# ban a user manually and permanently
ban_user = (name) ->
settings.ban.banned_user.push(name)
......@@ -267,7 +267,7 @@ ban_user = (name) ->
ROOM_bad_ip[bad_ip]=99
settings.ban.banned_ip.push(player.ip)
ygopro.stoc_send_chat_to_room(room, "#{player.name} ${kicked_by_system}", ygopro.constants.COLORS.RED)
player.destroy()
CLIENT_kick(player)
continue
return
......@@ -406,6 +406,204 @@ ROOM_unwelcome = (room, bad_player, reason)->
ygopro.stoc_send_chat(player, "${unwelcome_tip_part1}#{reason}${unwelcome_tip_part2}", ygopro.constants.COLORS.BABYBLUE)
return
CLIENT_kick = (client) ->
client.system_kicked = true
client.destroy()
return
release_disconnect = (dinfo, reconnected) ->
if dinfo.old_client and !reconnected
dinfo.old_client.destroy()
if dinfo.old_server and !reconnected
dinfo.old_server.destroy()
clearTimeout(dinfo.timeout)
return
CLIENT_get_authorize_key = (client) ->
if settings.modules.mycard.enabled or client.is_local
return client.name
else
return client.ip
CLIENT_reconnect_unregister = (client, reconnected) ->
if !settings.modules.reconnect.enabled
return false
if disconnect_list[CLIENT_get_authorize_key(client)]
release_disconnect(disconnect_list[CLIENT_get_authorize_key(client)], reconnected)
delete disconnect_list[CLIENT_get_authorize_key(client)]
return true
return false
CLIENT_reconnect_register = (client, room, error) ->
if client.had_new_reconnection
return false
if !settings.modules.reconnect.enabled or client.system_kicked or client.is_post_watcher or !CLIENT_is_player(client, room) or !room.started or (room.windbot and client.is_local)
return false
old_dinfo = disconnect_list[CLIENT_get_authorize_key(client)]
if old_dinfo
old_dinfo.room.disconnect(old_dinfo.old_client)
dinfo = {
room: room,
old_client: client,
old_server: client.server,
deckbuf: client.start_deckbuf
}
tmot = setTimeout(() ->
room.disconnect(client, error)
dinfo.old_server.destroy()
return
, settings.modules.reconnect.wait_time)
dinfo.timeout = tmot
disconnect_list[CLIENT_get_authorize_key(client)] = dinfo
return true
CLIENT_import_data = (client, old_client, room) ->
for player,index in room.players
if player == old_client
room.players[index] = client
break
room.dueling_players[old_client.pos] = client
if room.waiting_for_player = old_client
room.waiting_for_player = client
if room.waiting_for_player2 = old_client
room.waiting_for_player2 = client
if room.selecting_tp = old_client
room.selecting_tp = client
client.abuse_count = old_client.abuse_count
# client.established = old_client.established
# client.pre_establish_buffers = old_client.pre_establish_buffers
client.rag = old_client.rag
client.rid = old_client.rid
client.is_post_watcher = old_client.is_post_watcher
client.retry_count = old_client.retry_count
client.name = old_client.name
client.is_first = old_client.is_first
client.lp = old_client.lp
client.card_count = old_client.card_count
client.is_host = old_client.is_host
client.pos = old_client.pos
client.surrend_confirm = old_client.surrend_confirm
client.kick_count = old_client.kick_count
client.deck_saved = old_client.deck_saved
client.main = old_client.main
client.side = old_client.side
client.side_interval = old_client.side_interval
client.side_tcount = old_client.side_tcount
client.selected_preduel = old_client.selected_preduel
client.last_game_msg = old_client.last_game_msg
client.last_game_msg_title = old_client.last_game_msg_title
client.start_deckbuf = old_client.start_deckbuf
client.join_game_buffer = old_client.join_game_buffer
old_client.had_new_reconnection = true
return
SERVER_clear_disconnect = (server) ->
return unless settings.modules.reconnect.enabled
for k,v of disconnect_list
if v and server == v.old_server
release_disconnect(v)
delete disconnect_list[k]
return
return
CLIENT_is_player = (client, room) ->
is_player = false
for player in room.players
if client == player
is_player = true
break
return is_player
CLIENT_is_able_to_reconnect = (client) ->
unless settings.modules.reconnect.enabled
return false
if client.system_kicked
return false
disconnect_info = disconnect_list[CLIENT_get_authorize_key(client)]
unless disconnect_info
return false
# if disconnect_info.old_server.closed
# return false
# current_room = disconnect_info.room
# unless current_room and current_room.started
# return false
# if client.is_post_watcher or !CLIENT_is_player(client, current_room) or (room.windbot and client.is_local)
# return false
return true
CLIENT_send_pre_reconnect_info = (client, room, old_client) ->
ygopro.stoc_send_chat(client, "${pre_reconnecting_to_room}", ygopro.constants.COLORS.BABYBLUE)
ygopro.stoc_send(client, 'JOIN_GAME', old_client.join_game_buffer)
req_pos = old_client.pos
if old_client.is_host
req_pos += 0x10
ygopro.stoc_send(client, 'TYPE_CHANGE', {
type: req_pos
})
for player in room.players
ygopro.stoc_send(client, 'HS_PLAYER_ENTER', {
name: player.name,
pos: player.pos,
})
CLIENT_send_reconnect_info = (client, server, room) ->
client.reconnecting = true
ygopro.stoc_send_chat(client, "${reconnecting_to_room}", ygopro.constants.COLORS.BABYBLUE)
if room.turn and room.turn > 0
ygopro.ctos_send(server, 'REQUEST_FIELD')
else if room.changing_side
ygopro.stoc_send(client, 'DUEL_START')
if !client.selected_preduel
ygopro.stoc_send(client, 'CHANGE_SIDE')
client.reconnecting = false
else if room.selecting_hand
ygopro.stoc_send(client, 'DUEL_START')
if (room.hostinfo.mode != 2 or client.pos == 0 or client.pos == 2) and !client.selected_preduel
ygopro.stoc_send(client, 'SELECT_HAND')
client.reconnecting = false
else if room.selecting_tp
ygopro.stoc_send(client, 'DUEL_START')
if client == room.selecting_tp and !client.selected_preduel
ygopro.stoc_send(client, 'SELECT_TP')
client.reconnecting = false
else
ygopro.ctos_send(server, 'REQUEST_FIELD')
return
CLIENT_pre_reconnect = (client) ->
if !CLIENT_is_able_to_reconnect(client)
return
dinfo = disconnect_list[CLIENT_get_authorize_key(client)]
client.pre_deckbuf = dinfo.deckbuf
client.pre_reconnecting = true
client.pos = dinfo.old_client.pos
CLIENT_send_pre_reconnect_info(client, dinfo.room, dinfo.old_client)
CLIENT_reconnect = (client) ->
if !CLIENT_is_able_to_reconnect(client)
ygopro.stoc_send_chat(client, "${reconnect_failed}", ygopro.constants.COLORS.RED)
CLIENT_kick(client)
return
client.pre_reconnecting = false
dinfo = disconnect_list[CLIENT_get_authorize_key(client)]
current_old_server = client.server
client.server = dinfo.old_server
client.server.client = client
dinfo.old_client.server = null
current_old_server.client = null
current_old_server.had_new_reconnection = true
current_old_server.destroy()
client.established = true
client.pre_establish_buffers = []
client.setTimeout(300000)
CLIENT_import_data(client, dinfo.old_client, dinfo.room)
CLIENT_send_reconnect_info(client, client.server, dinfo.room)
CLIENT_reconnect_unregister(client, true)
return
if settings.modules.reconnect.enabled
disconnect_list = {} # {old_client, old_server, room, timeout, deckbuf}
class Room
constructor: (name, @hostinfo) ->
@name = name
......@@ -424,9 +622,11 @@ class Room
@scores = {}
@duel_count = 0
@death = 0
@turn = 0
ROOM_all.push this
@hostinfo ||= JSON.parse(JSON.stringify(settings.hostinfo))
delete @hostinfo.comment
if lflists.length
if @hostinfo.rule == 1 and @hostinfo.lflist == 0
@hostinfo.lflist = _.findIndex lflists, (list)-> list.tcg
......@@ -686,11 +886,14 @@ class Room
return
disconnect: (client, error)->
if client.had_new_reconnection
return
if client.is_post_watcher
ygopro.stoc_send_chat_to_room this, "#{client.name} ${quit_watch}" + if error then ": #{error}" else ''
index = _.indexOf(@watchers, client)
@watchers.splice(index, 1) unless index == -1
#client.room = null
client.server.destroy()
else
#log.info(client.name, @started, @disconnector, @random_type, @players.length)
if @arena == "athletic" and !@started and @players.length == 2
......@@ -712,6 +915,8 @@ class Room
@process.kill()
#client.room = null
this.delete()
if !CLIENT_reconnect_unregister(client)
client.server.destroy()
return
......@@ -729,6 +934,7 @@ net.createServer (client) ->
# server stand for the connection to ygopro server process
server = new net.Socket()
client.server = server
server.client = client
client.setTimeout(2000) #连接前超时2秒
......@@ -743,8 +949,11 @@ net.createServer (client) ->
#log.info "disconnect", client.ip, ROOM_connected_ip[client.ip]
unless client.closed
client.closed = true
room.disconnect(client) if room
server.destroy()
if room
if !CLIENT_reconnect_register(client, room)
room.disconnect(client)
else if !client.had_new_reconnection
client.server.destroy()
return
client.on 'error', (error)->
......@@ -756,40 +965,52 @@ net.createServer (client) ->
ROOM_connected_ip[client.ip] = connect_count
#log.info "err disconnect", client.ip, ROOM_connected_ip[client.ip]
unless client.closed
client.closed = error
room.disconnect(client, error) if room
server.destroy()
client.closed = true
if room
if !CLIENT_reconnect_register(client, room, error)
room.disconnect(client, error)
else if !client.had_new_reconnection
client.server.destroy()
return
client.on 'timeout', ()->
server.destroy()
if !client.server
return
unless settings.modules.reconnect.enabled and (disconnect_list[CLIENT_get_authorize_key(client)] or client.had_new_reconnection)
client.server.destroy()
return
server.on 'close', (had_error) ->
#log.info "server closed", client.name, had_error
room=ROOM_all[client.rid]
#log.info "server close", client.ip, ROOM_connected_ip[client.ip]
#log.info "server closed", server.client.name, had_error
room=ROOM_all[server.client.rid]
#log.info "server close", server.client.ip, ROOM_connected_ip[server.client.ip]
room.disconnector = 'server' if room
server.closed = true unless server.closed
unless client.closed
ygopro.stoc_send_chat(client, "${server_closed}", ygopro.constants.COLORS.RED)
client.destroy()
if !server.client
return
unless server.client.closed
ygopro.stoc_send_chat(server.client, "${server_closed}", ygopro.constants.COLORS.RED)
CLIENT_kick(server.client)
SERVER_clear_disconnect(server)
return
server.on 'error', (error)->
#log.info "server error", client.name, error
room=ROOM_all[client.rid]
room=ROOM_all[server.client.rid]
#log.info "server err close", client.ip, ROOM_connected_ip[client.ip]
room.disconnector = 'server' if room
server.closed = error
unless client.closed
ygopro.stoc_send_chat(client, "${server_error}: #{error}", ygopro.constants.COLORS.RED)
client.destroy()
if !server.client
return
unless server.client.closed
ygopro.stoc_send_chat(server.client, "${server_error}: #{error}", ygopro.constants.COLORS.RED)
CLIENT_kick(server.client)
SERVER_clear_disconnect(server)
return
if ROOM_bad_ip[client.ip] > 5 or ROOM_connected_ip[client.ip] > 10
log.info 'BAD IP', client.ip
client.destroy()
CLIENT_kick(client)
return
if settings.modules.cloud_replay.enabled
......@@ -803,11 +1024,11 @@ net.createServer (client) ->
if err
log.info "cloud replay unzip error: " + err
ygopro.stoc_send_chat(client, "${cloud_replay_error}", ygopro.constants.COLORS.RED)
client.destroy()
CLIENT_kick(client)
return
ygopro.stoc_send_chat(client, "${cloud_replay_playing} R##{replay.replay_id} #{replay.player_names} #{replay.date_time}", ygopro.constants.COLORS.BABYBLUE)
client.write replay_buffer, ()->
client.destroy()
CLIENT_kick(client)
return
return
return
......@@ -848,16 +1069,18 @@ net.createServer (client) ->
if ctos_buffer.length >= 2 + ctos_message_length
#console.log "CTOS", ygopro.constants.CTOS[ctos_proto]
cancel = false
if ygopro.ctos_follows[ctos_proto]
if settings.modules.reconnect.enabled and client.pre_reconnecting and ygopro.constants.CTOS[ctos_proto] != 'UPDATE_DECK'
cancel = true
if ygopro.ctos_follows[ctos_proto] and !cancel
b = ctos_buffer.slice(3, ctos_message_length - 1 + 3)
info = null
if struct = ygopro.structs[ygopro.proto_structs.CTOS[ygopro.constants.CTOS[ctos_proto]]]
struct._setBuff(b)
info = _.clone(struct.fields)
if ygopro.ctos_follows[ctos_proto].synchronous
cancel = ygopro.ctos_follows[ctos_proto].callback b, info, client, server
cancel = ygopro.ctos_follows[ctos_proto].callback b, info, client, client.server
else
ygopro.ctos_follows[ctos_proto].callback b, info, client, server
ygopro.ctos_follows[ctos_proto].callback b, info, client, client.server
datas.push ctos_buffer.slice(0, 2 + ctos_message_length) unless cancel
ctos_buffer = ctos_buffer.slice(2 + ctos_message_length)
ctos_message_length = 0
......@@ -875,11 +1098,12 @@ net.createServer (client) ->
ROOM_bad_ip[client.ip] = bad_ip_count + 1
else
ROOM_bad_ip[client.ip] = 1
client.destroy()
CLIENT_kick(client)
break
if !client.server
return
if client.established
server.write buffer for buffer in datas
client.server.write buffer for buffer in datas
else
client.pre_establish_buffers.push buffer for buffer in datas
......@@ -893,7 +1117,7 @@ net.createServer (client) ->
#stoc_buffer = Buffer.concat([stoc_buffer, data], stoc_buffer.length + data.length) #buffer的错误使用方式,好孩子不要学
#unless ygopro.stoc_follows[stoc_proto] and ygopro.stoc_follows[stoc_proto].synchronous
#client.write data
#server.client.write data
datas = []
looplimit = 0
......@@ -903,13 +1127,13 @@ net.createServer (client) ->
if stoc_buffer.length >= 2
stoc_message_length = stoc_buffer.readUInt16LE(0)
else
log.warn("bad stoc_buffer length", client.ip) unless stoc_buffer.length == 0
log.warn("bad stoc_buffer length", server.client.ip) unless stoc_buffer.length == 0
break
else if stoc_proto == 0
if stoc_buffer.length >= 3
stoc_proto = stoc_buffer.readUInt8(2)
else
log.warn("bad stoc_proto length", client.ip)
log.warn("bad stoc_proto length", server.client.ip)
break
else
if stoc_buffer.length >= 2 + stoc_message_length
......@@ -923,24 +1147,25 @@ net.createServer (client) ->
struct._setBuff(b)
info = _.clone(struct.fields)
if ygopro.stoc_follows[stoc_proto].synchronous
cancel = ygopro.stoc_follows[stoc_proto].callback b, info, client, server
cancel = ygopro.stoc_follows[stoc_proto].callback b, info, server.client, server
else
ygopro.stoc_follows[stoc_proto].callback b, info, client, server
ygopro.stoc_follows[stoc_proto].callback b, info, server.client, server
datas.push stoc_buffer.slice(0, 2 + stoc_message_length) unless cancel
stoc_buffer = stoc_buffer.slice(2 + stoc_message_length)
stoc_message_length = 0
stoc_proto = 0
else
log.warn("bad stoc_message length", client.ip)
log.warn("bad stoc_message length", server.client.ip)
break
looplimit++
#log.info(looplimit)
if looplimit > 800
log.info("error stoc", client.name)
log.info("error stoc", server.client.name)
server.destroy()
break
client.write buffer for buffer in datas
if server.client and !server.client.closed
server.client.write buffer for buffer in datas
return
return
......@@ -991,7 +1216,10 @@ ygopro.ctos_follow 'PLAYER_INFO', true, (buffer, info, client, server)->
ygopro.ctos_follow 'JOIN_GAME', false, (buffer, info, client, server)->
#log.info info
info.pass=info.pass.trim()
if settings.modules.stop
if CLIENT_is_able_to_reconnect(client)
CLIENT_pre_reconnect(client)
return
else if settings.modules.stop
ygopro.stoc_die(client, settings.modules.stop)
else if info.pass.toUpperCase()=="R" and settings.modules.cloud_replay.enabled
......@@ -1012,7 +1240,7 @@ ygopro.ctos_follow 'JOIN_GAME', false, (buffer, info, client, server)->
msg: 1
code: 9
}
client.destroy()
CLIENT_kick(client)
return), 500
else if info.pass[0...2].toUpperCase()=="R#" and settings.modules.cloud_replay.enabled
......@@ -1040,7 +1268,7 @@ ygopro.ctos_follow 'JOIN_GAME', false, (buffer, info, client, server)->
msg: 4
code: settings.version
}
client.destroy()
CLIENT_kick(client)
else if !info.pass.length and !settings.modules.random_duel.enabled and !settings.modules.windbot.enabled
ygopro.stoc_die(client, "${blank_room_name}")
......@@ -1265,7 +1493,8 @@ ygopro.ctos_follow 'JOIN_GAME', false, (buffer, info, client, server)->
ygopro.stoc_follow 'JOIN_GAME', false, (buffer, info, client, server)->
#欢迎信息
room=ROOM_all[client.rid]
return unless room
return unless room and !client.reconnecting
client.join_game_buffer = buffer
if settings.modules.welcome
ygopro.stoc_send_chat(client, settings.modules.welcome, ygopro.constants.COLORS.GREEN)
if room.welcome
......@@ -1353,9 +1582,8 @@ if settings.modules.dialogues.get
ygopro.stoc_follow 'GAME_MSG', true, (buffer, info, client, server)->
room=ROOM_all[client.rid]
return unless room
return unless room and !client.reconnecting
msg = buffer.readInt8(0)
if settings.modules.retry_handle.enabled
if ygopro.constants.MSG[msg] == 'RETRY'
if !client.retry_count?
......@@ -1365,7 +1593,7 @@ ygopro.stoc_follow 'GAME_MSG', true, (buffer, info, client, server)->
if settings.modules.retry_handle.max_retry_count and client.retry_count >= settings.modules.retry_handle.max_retry_count
ygopro.stoc_send_chat_to_room(room, client.name + "${retry_too_much_room_part1}" + settings.modules.retry_handle.max_retry_count + "${retry_too_much_room_part2}", ygopro.constants.COLORS.BABYBLUE)
ygopro.stoc_send_chat(client, "${retry_too_much_part1}" + settings.modules.retry_handle.max_retry_count + "${retry_too_much_part2}", ygopro.constants.COLORS.RED)
client.destroy()
CLIENT_kick(client)
return true
if client.last_game_msg
if settings.modules.retry_handle.max_retry_count
......@@ -1376,6 +1604,10 @@ ygopro.stoc_follow 'GAME_MSG', true, (buffer, info, client, server)->
return true
else
client.last_game_msg = buffer
client.last_game_msg_title = ygopro.constants.MSG[msg]
else if ygopro.constants.MSG[msg] != 'RETRY'
client.last_game_msg = buffer
client.last_game_msg_title = ygopro.constants.MSG[msg]
if (msg >= 10 and msg < 30) or msg == 132 or (msg >= 140 and msg < 144) #SELECT和ANNOUNCE开头的消息
room.waiting_for_player = client
......@@ -1388,6 +1620,7 @@ ygopro.stoc_follow 'GAME_MSG', true, (buffer, info, client, server)->
client.is_first = !(playertype & 0xf)
client.lp = room.hostinfo.start_lp
client.card_count = 0 if room.hostinfo.mode != 2
room.selecting_tp = false
if client.pos == 0
room.turn = 0
room.duel_count = room.duel_count + 1
......@@ -1415,8 +1648,8 @@ ygopro.stoc_follow 'GAME_MSG', true, (buffer, info, client, server)->
ygopro.stoc_send(room.dueling_players[oppo_pos - win_pos], 'DUEL_END')
ygopro.stoc_send(room.dueling_players[oppo_pos - win_pos + 1], 'DUEL_END')
room.scores[room.dueling_players[oppo_pos - win_pos].name] = -1
room.dueling_players[oppo_pos - win_pos].destroy()
room.dueling_players[oppo_pos - win_pos + 1].destroy()
CLIENT_kick(room.dueling_players[oppo_pos - win_pos])
CLIENT_kick(room.dueling_players[oppo_pos - win_pos + 1])
else
ygopro.ctos_send(room.dueling_players[oppo_pos - win_pos].server, 'SURRENDER')
else
......@@ -1439,8 +1672,8 @@ ygopro.stoc_follow 'GAME_MSG', true, (buffer, info, client, server)->
ygopro.stoc_send(room.dueling_players[oppo_pos - win_pos], 'DUEL_END')
ygopro.stoc_send(room.dueling_players[oppo_pos - win_pos + 1], 'DUEL_END')
room.scores[room.dueling_players[oppo_pos - win_pos].name] = -1
room.dueling_players[oppo_pos - win_pos].destroy()
room.dueling_players[oppo_pos - win_pos + 1].destroy()
CLIENT_kick(room.dueling_players[oppo_pos - win_pos])
CLIENT_kick(room.dueling_players[oppo_pos - win_pos + 1])
else
ygopro.ctos_send(room.dueling_players[oppo_pos - win_pos].server, 'SURRENDER')
else
......@@ -1549,13 +1782,13 @@ ygopro.ctos_follow 'HS_KICK', true, (buffer, info, client, server)->
if player and player.pos == info.pos and player != client
if room.arena == "athletic"
ygopro.stoc_send_chat_to_room(room, "#{client.name} ${kicked_by_system}", ygopro.constants.COLORS.RED)
client.destroy()
CLIENT_kick(client)
return true
client.kick_count = if client.kick_count then client.kick_count+1 else 1
if client.kick_count>=5 and room.random_type
ygopro.stoc_send_chat_to_room(room, "#{client.name} ${kicked_by_system}", ygopro.constants.COLORS.RED)
ROOM_ban_player(player.name, player.ip, "${random_ban_reason_zombie}")
client.destroy()
CLIENT_kick(client)
return true
ygopro.stoc_send_chat_to_room(room, "#{player.name} ${kicked_by_player}", ygopro.constants.COLORS.RED)
return false
......@@ -1614,6 +1847,17 @@ ygopro.stoc_follow 'HS_PLAYER_CHANGE', false, (buffer, info, client, server)->
setTimeout (()-> wait_room_start(ROOM_all[client.rid], 20);return), 1000
return
ygopro.stoc_follow 'FIELD_FINISH', true, (buffer, info, client, server)->
room=ROOM_all[client.rid]
return unless room
client.reconnecting = false
if client.last_game_msg and client.last_game_msg_title != 'WAITING'
setTimeout( () ->
ygopro.stoc_send(client, 'GAME_MSG', client.last_game_msg)
return
, 1000)
return true
wait_room_start = (room, time)->
unless !room or room.started or room.ready_player_count_without_host < room.max_player - 1
time -= 1
......@@ -1626,7 +1870,7 @@ wait_room_start = (room, time)->
if player and player.is_host
ROOM_ban_player(player.name, player.ip, "${random_ban_reason_zombie}")
ygopro.stoc_send_chat_to_room(room, "#{player.name} ${kicked_by_system}", ygopro.constants.COLORS.RED)
player.destroy()
CLIENT_kick(player)
return
wait_room_start_arena = (room)->
......@@ -1637,7 +1881,7 @@ wait_room_start_arena = (room)->
ygopro.stoc_send_chat_to_room(room, "#{if room.waiting_for_player_time <= 9 then ' ' else ''}#{room.waiting_for_player_time}${kick_count_down_arena_part1} #{room.waiting_for_player.name} ${kick_count_down_arena_part2}", if room.waiting_for_player_time <= 9 then ygopro.constants.COLORS.RED else ygopro.constants.COLORS.LIGHTBLUE)
else
ygopro.stoc_send_chat_to_room(room, "#{room.waiting_for_player.name} ${kicked_by_system}", ygopro.constants.COLORS.RED)
room.waiting_for_player.destroy()
CLIENT_kick(room.waiting_for_player)
if room.waiting_for_player_interval
clearInterval room.waiting_for_player_interval
room.waiting_for_player_interval = null
......@@ -1678,10 +1922,11 @@ if settings.modules.tips.get
ygopro.stoc_follow 'DUEL_START', false, (buffer, info, client, server)->
room=ROOM_all[client.rid]
return unless room
return unless room and !client.reconnecting
unless room.started #first start
room.started = true
room.start_time = moment().format()
room.turn = 0
roomlist.start room if !room.windbot and settings.modules.http.websocket_roomlist
#room.duels = []
room.dueling_players = []
......@@ -1811,7 +2056,7 @@ ygopro.ctos_follow 'CHAT', true, (buffer, info, client, server)->
when '/color'
if settings.modules.chat_color.enabled
cip = if settings.modules.mycard.enabled then client.name else client.ip
cip = CLIENT_get_authorize_key(client)
if cmsg = cmd[1]
if cmsg.toLowerCase() == "help"
ygopro.stoc_send_chat(client, "${show_color_list}", ygopro.constants.COLORS.BABYBLUE)
......@@ -1860,7 +2105,7 @@ ygopro.ctos_follow 'CHAT', true, (buffer, info, client, server)->
ygopro.stoc_send_chat(client, "${banned_duel_tip}", ygopro.constants.COLORS.RED)
ROOM_ban_player(client.name, client.ip, "${random_ban_reason_abuse}")
ROOM_ban_player(client.name, client.ip, "${random_ban_reason_abuse}", 3)
client.destroy()
CLIENT_kick(client)
return true
else
client.abuse_count=client.abuse_count+4
......@@ -1916,6 +2161,19 @@ ygopro.ctos_follow 'CHAT', true, (buffer, info, client, server)->
return cancel
ygopro.ctos_follow 'UPDATE_DECK', true, (buffer, info, client, server)->
if settings.modules.reconnect.enabled and client.pre_reconnecting
if _.isEqual(buffer, client.pre_deckbuf)
CLIENT_reconnect(client)
else
ygopro.stoc_send_chat(client, "${deck_incorrect_reconnect}", ygopro.constants.COLORS.RED)
ygopro.stoc_send(client, 'ERROR_MSG', {
msg: 2,
code: 0
})
ygopro.stoc_send(client, 'HS_PLAYER_CHANGE', {
status: (client.pos << 4) | 0xa
})
return true
room=ROOM_all[client.rid]
return false unless room
#log.info info
......@@ -1923,10 +2181,14 @@ ygopro.ctos_follow 'UPDATE_DECK', true, (buffer, info, client, server)->
buff_side = (info.deckbuf[i] for i in [info.mainc...info.mainc + info.sidec])
client.main = buff_main
client.side = buff_side
if client.side_tcount
clearInterval client.side_interval
client.side_interval = null
client.side_tcount = null
if room.started
client.selected_preduel = true
if client.side_tcount
clearInterval client.side_interval
client.side_interval = null
client.side_tcount = null
else
client.start_deckbuf = buffer
oppo_pos = if room.hostinfo.mode == 2 then 2 else 1
if settings.modules.http.quick_death_rule >= 2 and room.started and room.death and room.scores[room.dueling_players[0].name] != room.scores[room.dueling_players[oppo_pos].name]
win_pos = if room.scores[room.dueling_players[0].name] > room.scores[room.dueling_players[oppo_pos].name] then 0 else oppo_pos
......@@ -1934,8 +2196,8 @@ ygopro.ctos_follow 'UPDATE_DECK', true, (buffer, info, client, server)->
ygopro.stoc_send(room.dueling_players[oppo_pos - win_pos], 'DUEL_END')
ygopro.stoc_send(room.dueling_players[oppo_pos - win_pos + 1], 'DUEL_END') if room.hostinfo.mode == 2
room.scores[room.dueling_players[oppo_pos - win_pos].name] = -1
room.dueling_players[oppo_pos - win_pos].destroy()
room.dueling_players[oppo_pos - win_pos + 1].destroy() if room.hostinfo.mode == 2
CLIENT_kick(room.dueling_players[oppo_pos - win_pos])
CLIENT_kick(room.dueling_players[oppo_pos - win_pos + 1]) if room.hostinfo.mode == 2
return true
if room.random_type or room.arena
if client.pos == 0
......@@ -1990,7 +2252,9 @@ ygopro.ctos_follow 'RESPONSE', false, (buffer, info, client, server)->
ygopro.ctos_follow 'HAND_RESULT', false, (buffer, info, client, server)->
room=ROOM_all[client.rid]
return unless room and (room.random_type or room.arena)
return unless room
client.selected_preduel = true
return unless room.random_type or room.arena
if client.pos == 0
room.waiting_for_player = room.waiting_for_player2
room.last_active_time = moment().subtract(settings.modules.random_duel.hang_timeout - 19, 's')
......@@ -1998,7 +2262,10 @@ ygopro.ctos_follow 'HAND_RESULT', false, (buffer, info, client, server)->
ygopro.ctos_follow 'TP_RESULT', false, (buffer, info, client, server)->
room=ROOM_all[client.rid]
return unless room and (room.random_type or room.arena)
return unless room
client.selected_preduel = true
room.selecting_tp = false
return unless room.random_type or room.arena
room.last_active_time = moment()
return
......@@ -2030,7 +2297,12 @@ ygopro.stoc_follow 'CHAT', true, (buffer, info, client, server)->
ygopro.stoc_follow 'SELECT_HAND', false, (buffer, info, client, server)->
room=ROOM_all[client.rid]
return unless room and (room.random_type or room.arena)
return unless room
client.selected_preduel = false
if client.pos == 0
room.selecting_hand = true
room.changing_side = false
return unless room.random_type or room.arena
if client.pos == 0
room.waiting_for_player = client
else
......@@ -2041,7 +2313,10 @@ ygopro.stoc_follow 'SELECT_HAND', false, (buffer, info, client, server)->
ygopro.stoc_follow 'SELECT_TP', false, (buffer, info, client, server)->
room=ROOM_all[client.rid]
return unless room
client.selected_preduel = false
room.changing_side = false
room.selecting_hand = false
room.selecting_tp = client
if room.random_type or room.arena
room.waiting_for_player = client
room.last_active_time = moment()
......@@ -2051,6 +2326,7 @@ ygopro.stoc_follow 'CHANGE_SIDE', false, (buffer, info, client, server)->
room=ROOM_all[client.rid]
return unless room
room.changing_side = true
client.selected_preduel = false
if settings.modules.side_timeout
client.side_tcount = settings.modules.side_timeout
ygopro.stoc_send_chat(client, "${side_timeout_part1}#{settings.modules.side_timeout}${side_timeout_part2}", ygopro.constants.COLORS.BABYBLUE)
......@@ -2062,7 +2338,7 @@ ygopro.stoc_follow 'CHANGE_SIDE', false, (buffer, info, client, server)->
ygopro.stoc_send_chat_to_room(room, client.name + "${side_overtime_room}", ygopro.constants.COLORS.BABYBLUE)
ygopro.stoc_send_chat(client, "${side_overtime}", ygopro.constants.COLORS.RED)
room.scores[client.name] = -9
client.destroy()
CLIENT_kick(client)
clearInterval sinterval
else
client.side_tcount = client.side_tcount - 1
......@@ -2366,8 +2642,8 @@ if settings.modules.http
ygopro.stoc_send(room.dueling_players[oppo_pos - win_pos], 'DUEL_END')
ygopro.stoc_send(room.dueling_players[oppo_pos - win_pos + 1], 'DUEL_END') if room.hostinfo.mode == 2
room.scores[room.dueling_players[oppo_pos - win_pos].name] = -1
room.dueling_players[oppo_pos - win_pos].destroy()
room.dueling_players[oppo_pos - win_pos + 1].destroy() if room.hostinfo.mode == 2
CLIENT_kick(room.dueling_players[oppo_pos - win_pos])
CLIENT_kick(room.dueling_players[oppo_pos - win_pos + 1]) if room.hostinfo.mode == 2
when 1
room.death = -1
ygopro.stoc_send_chat_to_room(room, "${death_start_quick}", ygopro.constants.COLORS.BABYBLUE)
......
// Generated by CoffeeScript 1.12.7
(function() {
var Cloud_replay_ids, ROOM_all, ROOM_bad_ip, ROOM_ban_player, ROOM_connected_ip, ROOM_find_by_name, ROOM_find_by_port, ROOM_find_by_title, ROOM_find_or_create_ai, ROOM_find_or_create_by_name, ROOM_find_or_create_random, ROOM_players_banned, ROOM_players_oppentlist, ROOM_unwelcome, ROOM_validate, Room, _, addCallback, badwords, ban_user, bunyan, chat_color, config, cppversion, crypto, date, default_config, default_data, dialogues, duel_log, e, exec, execFile, fs, geoip, get_memory_usage, http, http_server, https, https_server, j, k, len, len1, lflists, list, loadJSON, load_dialogues, load_tips, log, memory_usage, merge, moment, net, oldbadwords, oldconfig, olddialogues, oldduellog, oldtips, options, os, path, pgClient, pg_client, pg_query, redis, redisdb, ref, ref1, report_to_big_brother, request, requestListener, roomlist, setting_change, setting_save, settings, spawn, spawnSync, tips, url, users_cache, wait_room_start, wait_room_start_arena, windbot_bin, windbot_parameters, windbot_process, windbots, ygopro, zlib;
var CLIENT_get_authorize_key, CLIENT_import_data, CLIENT_is_able_to_reconnect, CLIENT_is_player, CLIENT_kick, CLIENT_pre_reconnect, CLIENT_reconnect, CLIENT_reconnect_register, CLIENT_reconnect_unregister, CLIENT_send_pre_reconnect_info, CLIENT_send_reconnect_info, Cloud_replay_ids, ROOM_all, ROOM_bad_ip, ROOM_ban_player, ROOM_connected_ip, ROOM_find_by_name, ROOM_find_by_port, ROOM_find_by_title, ROOM_find_or_create_ai, ROOM_find_or_create_by_name, ROOM_find_or_create_random, ROOM_players_banned, ROOM_players_oppentlist, ROOM_unwelcome, ROOM_validate, Room, SERVER_clear_disconnect, _, addCallback, badwords, ban_user, bunyan, chat_color, config, cppversion, crypto, date, default_config, default_data, dialogues, disconnect_list, duel_log, e, exec, execFile, fs, geoip, get_memory_usage, http, http_server, https, https_server, j, l, len, len1, lflists, list, loadJSON, load_dialogues, load_tips, log, memory_usage, merge, moment, net, oldbadwords, oldconfig, olddialogues, oldduellog, oldtips, options, os, path, pgClient, pg_client, pg_query, redis, redisdb, ref, ref1, release_disconnect, report_to_big_brother, request, requestListener, roomlist, setting_change, setting_save, settings, spawn, spawnSync, tips, url, users_cache, wait_room_start, wait_room_start_arena, windbot_bin, windbot_parameters, windbot_process, windbots, ygopro, zlib;
net = require('net');
......@@ -235,8 +235,8 @@
try {
ref1 = fs.readFileSync('ygopro/lflist.conf', 'utf8').match(/!.*/g);
for (k = 0, len1 = ref1.length; k < len1; k++) {
list = ref1[k];
for (l = 0, len1 = ref1.length; l < len1; l++) {
list = ref1[l];
date = list.match(/!([\d\.]+)/);
if (!date) {
continue;
......@@ -341,22 +341,22 @@
ROOM_bad_ip = {};
ban_user = function(name) {
var bad_ip, l, len2, len3, m, player, ref2, room;
var bad_ip, len2, len3, m, n, player, ref2, room;
settings.ban.banned_user.push(name);
setting_save(settings);
bad_ip = 0;
for (l = 0, len2 = ROOM_all.length; l < len2; l++) {
room = ROOM_all[l];
for (m = 0, len2 = ROOM_all.length; m < len2; m++) {
room = ROOM_all[m];
if (room && room.established) {
ref2 = room.players;
for (m = 0, len3 = ref2.length; m < len3; m++) {
player = ref2[m];
for (n = 0, len3 = ref2.length; n < len3; n++) {
player = ref2[n];
if (player && (player.name === name || player.ip === bad_ip)) {
bad_ip = player.ip;
ROOM_bad_ip[bad_ip] = 99;
settings.ban.banned_ip.push(player.ip);
ygopro.stoc_send_chat_to_room(room, player.name + " ${kicked_by_system}", ygopro.constants.COLORS.RED);
player.destroy();
CLIENT_kick(player);
continue;
}
}
......@@ -546,13 +546,13 @@
};
ROOM_unwelcome = function(room, bad_player, reason) {
var l, len2, player, ref2;
var len2, m, player, ref2;
if (!room) {
return;
}
ref2 = room.players;
for (l = 0, len2 = ref2.length; l < len2; l++) {
player = ref2[l];
for (m = 0, len2 = ref2.length; m < len2; m++) {
player = ref2[m];
if (player && player === bad_player) {
ygopro.stoc_send_chat(player, "${unwelcome_warn_part1}" + reason + "${unwelcome_warn_part2}", ygopro.constants.COLORS.RED);
} else if (player && player.pos !== 7 && player !== bad_player) {
......@@ -562,6 +562,249 @@
}
};
CLIENT_kick = function(client) {
client.system_kicked = true;
client.destroy();
};
release_disconnect = function(dinfo, reconnected) {
if (dinfo.old_client && !reconnected) {
dinfo.old_client.destroy();
}
if (dinfo.old_server && !reconnected) {
dinfo.old_server.destroy();
}
clearTimeout(dinfo.timeout);
};
CLIENT_get_authorize_key = function(client) {
if (settings.modules.mycard.enabled || client.is_local) {
return client.name;
} else {
return client.ip;
}
};
CLIENT_reconnect_unregister = function(client, reconnected) {
if (!settings.modules.reconnect.enabled) {
return false;
}
if (disconnect_list[CLIENT_get_authorize_key(client)]) {
release_disconnect(disconnect_list[CLIENT_get_authorize_key(client)], reconnected);
delete disconnect_list[CLIENT_get_authorize_key(client)];
return true;
}
return false;
};
CLIENT_reconnect_register = function(client, room, error) {
var dinfo, old_dinfo, tmot;
if (client.had_new_reconnection) {
return false;
}
if (!settings.modules.reconnect.enabled || client.system_kicked || client.is_post_watcher || !CLIENT_is_player(client, room) || !room.started || (room.windbot && client.is_local)) {
return false;
}
old_dinfo = disconnect_list[CLIENT_get_authorize_key(client)];
if (old_dinfo) {
old_dinfo.room.disconnect(old_dinfo.old_client);
}
dinfo = {
room: room,
old_client: client,
old_server: client.server,
deckbuf: client.start_deckbuf
};
tmot = setTimeout(function() {
room.disconnect(client, error);
dinfo.old_server.destroy();
}, settings.modules.reconnect.wait_time);
dinfo.timeout = tmot;
disconnect_list[CLIENT_get_authorize_key(client)] = dinfo;
return true;
};
CLIENT_import_data = function(client, old_client, room) {
var index, len2, m, player, ref2;
ref2 = room.players;
for (index = m = 0, len2 = ref2.length; m < len2; index = ++m) {
player = ref2[index];
if (player === old_client) {
room.players[index] = client;
break;
}
}
room.dueling_players[old_client.pos] = client;
if (room.waiting_for_player = old_client) {
room.waiting_for_player = client;
}
if (room.waiting_for_player2 = old_client) {
room.waiting_for_player2 = client;
}
if (room.selecting_tp = old_client) {
room.selecting_tp = client;
}
client.abuse_count = old_client.abuse_count;
client.rag = old_client.rag;
client.rid = old_client.rid;
client.is_post_watcher = old_client.is_post_watcher;
client.retry_count = old_client.retry_count;
client.name = old_client.name;
client.is_first = old_client.is_first;
client.lp = old_client.lp;
client.card_count = old_client.card_count;
client.is_host = old_client.is_host;
client.pos = old_client.pos;
client.surrend_confirm = old_client.surrend_confirm;
client.kick_count = old_client.kick_count;
client.deck_saved = old_client.deck_saved;
client.main = old_client.main;
client.side = old_client.side;
client.side_interval = old_client.side_interval;
client.side_tcount = old_client.side_tcount;
client.selected_preduel = old_client.selected_preduel;
client.last_game_msg = old_client.last_game_msg;
client.last_game_msg_title = old_client.last_game_msg_title;
client.start_deckbuf = old_client.start_deckbuf;
client.join_game_buffer = old_client.join_game_buffer;
old_client.had_new_reconnection = true;
};
SERVER_clear_disconnect = function(server) {
var k, v;
if (!settings.modules.reconnect.enabled) {
return;
}
for (k in disconnect_list) {
v = disconnect_list[k];
if (v && server === v.old_server) {
release_disconnect(v);
delete disconnect_list[k];
return;
}
}
};
CLIENT_is_player = function(client, room) {
var is_player, len2, m, player, ref2;
is_player = false;
ref2 = room.players;
for (m = 0, len2 = ref2.length; m < len2; m++) {
player = ref2[m];
if (client === player) {
is_player = true;
break;
}
}
return is_player;
};
CLIENT_is_able_to_reconnect = function(client) {
var disconnect_info;
if (!settings.modules.reconnect.enabled) {
return false;
}
if (client.system_kicked) {
return false;
}
disconnect_info = disconnect_list[CLIENT_get_authorize_key(client)];
if (!disconnect_info) {
return false;
}
return true;
};
CLIENT_send_pre_reconnect_info = function(client, room, old_client) {
var len2, m, player, ref2, req_pos, results;
ygopro.stoc_send_chat(client, "${pre_reconnecting_to_room}", ygopro.constants.COLORS.BABYBLUE);
ygopro.stoc_send(client, 'JOIN_GAME', old_client.join_game_buffer);
req_pos = old_client.pos;
if (old_client.is_host) {
req_pos += 0x10;
}
ygopro.stoc_send(client, 'TYPE_CHANGE', {
type: req_pos
});
ref2 = room.players;
results = [];
for (m = 0, len2 = ref2.length; m < len2; m++) {
player = ref2[m];
results.push(ygopro.stoc_send(client, 'HS_PLAYER_ENTER', {
name: player.name,
pos: player.pos
}));
}
return results;
};
CLIENT_send_reconnect_info = function(client, server, room) {
client.reconnecting = true;
ygopro.stoc_send_chat(client, "${reconnecting_to_room}", ygopro.constants.COLORS.BABYBLUE);
if (room.turn && room.turn > 0) {
ygopro.ctos_send(server, 'REQUEST_FIELD');
} else if (room.changing_side) {
ygopro.stoc_send(client, 'DUEL_START');
if (!client.selected_preduel) {
ygopro.stoc_send(client, 'CHANGE_SIDE');
}
client.reconnecting = false;
} else if (room.selecting_hand) {
ygopro.stoc_send(client, 'DUEL_START');
if ((room.hostinfo.mode !== 2 || client.pos === 0 || client.pos === 2) && !client.selected_preduel) {
ygopro.stoc_send(client, 'SELECT_HAND');
}
client.reconnecting = false;
} else if (room.selecting_tp) {
ygopro.stoc_send(client, 'DUEL_START');
if (client === room.selecting_tp && !client.selected_preduel) {
ygopro.stoc_send(client, 'SELECT_TP');
}
client.reconnecting = false;
} else {
ygopro.ctos_send(server, 'REQUEST_FIELD');
}
};
CLIENT_pre_reconnect = function(client) {
var dinfo;
if (!CLIENT_is_able_to_reconnect(client)) {
return;
}
dinfo = disconnect_list[CLIENT_get_authorize_key(client)];
client.pre_deckbuf = dinfo.deckbuf;
client.pre_reconnecting = true;
client.pos = dinfo.old_client.pos;
return CLIENT_send_pre_reconnect_info(client, dinfo.room, dinfo.old_client);
};
CLIENT_reconnect = function(client) {
var current_old_server, dinfo;
if (!CLIENT_is_able_to_reconnect(client)) {
ygopro.stoc_send_chat(client, "${reconnect_failed}", ygopro.constants.COLORS.RED);
CLIENT_kick(client);
return;
}
client.pre_reconnecting = false;
dinfo = disconnect_list[CLIENT_get_authorize_key(client)];
current_old_server = client.server;
client.server = dinfo.old_server;
client.server.client = client;
dinfo.old_client.server = null;
current_old_server.client = null;
current_old_server.had_new_reconnection = true;
current_old_server.destroy();
client.established = true;
client.pre_establish_buffers = [];
client.setTimeout(300000);
CLIENT_import_data(client, dinfo.old_client, dinfo.room);
CLIENT_send_reconnect_info(client, client.server, dinfo.room);
CLIENT_reconnect_unregister(client, true);
};
if (settings.modules.reconnect.enabled) {
disconnect_list = {};
}
Room = (function() {
function Room(name, hostinfo) {
var draw_count, lflist, param, rule, start_hand, start_lp, time_limit;
......@@ -582,8 +825,10 @@
this.scores = {};
this.duel_count = 0;
this.death = 0;
this.turn = 0;
ROOM_all.push(this);
this.hostinfo || (this.hostinfo = JSON.parse(JSON.stringify(settings.hostinfo)));
delete this.hostinfo.comment;
if (lflists.length) {
if (this.hostinfo.rule === 1 && this.hostinfo.lflist === 0) {
this.hostinfo.lflist = _.findIndex(lflists, function(list) {
......@@ -723,10 +968,10 @@
_this.port = parseInt(data);
_.each(_this.players, function(player) {
player.server.connect(_this.port, '127.0.0.1', function() {
var buffer, l, len2, ref2;
var buffer, len2, m, ref2;
ref2 = player.pre_establish_buffers;
for (l = 0, len2 = ref2.length; l < len2; l++) {
buffer = ref2[l];
for (m = 0, len2 = ref2.length; m < len2; m++) {
buffer = ref2[m];
player.server.write(buffer);
}
player.established = true;
......@@ -908,10 +1153,10 @@
roomlist.update(this);
}
client.server.connect(this.port, '127.0.0.1', function() {
var buffer, l, len2, ref2;
var buffer, len2, m, ref2;
ref2 = client.pre_establish_buffers;
for (l = 0, len2 = ref2.length; l < len2; l++) {
buffer = ref2[l];
for (m = 0, len2 = ref2.length; m < len2; m++) {
buffer = ref2[m];
client.server.write(buffer);
}
client.established = true;
......@@ -921,18 +1166,22 @@
};
Room.prototype.disconnect = function(client, error) {
var index, l, len2, player, ref2;
var index, len2, m, player, ref2;
if (client.had_new_reconnection) {
return;
}
if (client.is_post_watcher) {
ygopro.stoc_send_chat_to_room(this, (client.name + " ${quit_watch}") + (error ? ": " + error : ''));
index = _.indexOf(this.watchers, client);
if (index !== -1) {
this.watchers.splice(index, 1);
}
client.server.destroy();
} else {
if (this.arena === "athletic" && !this.started && this.players.length === 2) {
ref2 = this.players;
for (l = 0, len2 = ref2.length; l < len2; l++) {
player = ref2[l];
for (m = 0, len2 = ref2.length; m < len2; m++) {
player = ref2[m];
if (player.pos !== 7) {
this.scores[player.name] = 0;
}
......@@ -959,6 +1208,9 @@
this.process.kill();
this["delete"]();
}
if (!CLIENT_reconnect_unregister(client)) {
client.server.destroy();
}
}
};
......@@ -977,6 +1229,7 @@
ROOM_connected_ip[client.ip] = connect_count;
server = new net.Socket();
client.server = server;
server.client = client;
client.setTimeout(2000);
client.on('close', function(had_error) {
var room;
......@@ -989,10 +1242,13 @@
if (!client.closed) {
client.closed = true;
if (room) {
room.disconnect(client);
if (!CLIENT_reconnect_register(client, room)) {
room.disconnect(client);
}
} else if (!client.had_new_reconnection) {
client.server.destroy();
}
}
server.destroy();
});
client.on('error', function(error) {
var room;
......@@ -1003,45 +1259,61 @@
}
ROOM_connected_ip[client.ip] = connect_count;
if (!client.closed) {
client.closed = error;
client.closed = true;
if (room) {
room.disconnect(client, error);
if (!CLIENT_reconnect_register(client, room, error)) {
room.disconnect(client, error);
}
} else if (!client.had_new_reconnection) {
client.server.destroy();
}
}
server.destroy();
});
client.on('timeout', function() {
server.destroy();
if (!client.server) {
return;
}
if (!(settings.modules.reconnect.enabled && (disconnect_list[CLIENT_get_authorize_key(client)] || client.had_new_reconnection))) {
client.server.destroy();
}
});
server.on('close', function(had_error) {
var room;
room = ROOM_all[client.rid];
room = ROOM_all[server.client.rid];
if (room) {
room.disconnector = 'server';
}
if (!server.closed) {
server.closed = true;
}
if (!client.closed) {
ygopro.stoc_send_chat(client, "${server_closed}", ygopro.constants.COLORS.RED);
client.destroy();
if (!server.client) {
return;
}
if (!server.client.closed) {
ygopro.stoc_send_chat(server.client, "${server_closed}", ygopro.constants.COLORS.RED);
CLIENT_kick(server.client);
SERVER_clear_disconnect(server);
}
});
server.on('error', function(error) {
var room;
room = ROOM_all[client.rid];
room = ROOM_all[server.client.rid];
if (room) {
room.disconnector = 'server';
}
server.closed = error;
if (!client.closed) {
ygopro.stoc_send_chat(client, "${server_error}: " + error, ygopro.constants.COLORS.RED);
client.destroy();
if (!server.client) {
return;
}
if (!server.client.closed) {
ygopro.stoc_send_chat(server.client, "${server_error}: " + error, ygopro.constants.COLORS.RED);
CLIENT_kick(server.client);
SERVER_clear_disconnect(server);
}
});
if (ROOM_bad_ip[client.ip] > 5 || ROOM_connected_ip[client.ip] > 10) {
log.info('BAD IP', client.ip);
client.destroy();
CLIENT_kick(client);
return;
}
if (settings.modules.cloud_replay.enabled) {
......@@ -1057,19 +1329,19 @@
if (err) {
log.info("cloud replay unzip error: " + err);
ygopro.stoc_send_chat(client, "${cloud_replay_error}", ygopro.constants.COLORS.RED);
client.destroy();
CLIENT_kick(client);
return;
}
ygopro.stoc_send_chat(client, "${cloud_replay_playing} R#" + replay.replay_id + " " + replay.player_names + " " + replay.date_time, ygopro.constants.COLORS.BABYBLUE);
client.write(replay_buffer, function() {
client.destroy();
CLIENT_kick(client);
});
});
};
}
client.pre_establish_buffers = new Array();
client.on('data', function(ctos_buffer) {
var b, bad_ip_count, buffer, cancel, ctos_message_length, ctos_proto, datas, info, l, len2, len3, looplimit, m, room, struct;
var b, bad_ip_count, buffer, cancel, ctos_message_length, ctos_proto, datas, info, len2, len3, looplimit, m, n, room, struct;
if (client.is_post_watcher) {
room = ROOM_all[client.rid];
if (room) {
......@@ -1100,7 +1372,10 @@
} else {
if (ctos_buffer.length >= 2 + ctos_message_length) {
cancel = false;
if (ygopro.ctos_follows[ctos_proto]) {
if (settings.modules.reconnect.enabled && client.pre_reconnecting && ygopro.constants.CTOS[ctos_proto] !== 'UPDATE_DECK') {
cancel = true;
}
if (ygopro.ctos_follows[ctos_proto] && !cancel) {
b = ctos_buffer.slice(3, ctos_message_length - 1 + 3);
info = null;
if (struct = ygopro.structs[ygopro.proto_structs.CTOS[ygopro.constants.CTOS[ctos_proto]]]) {
......@@ -1108,9 +1383,9 @@
info = _.clone(struct.fields);
}
if (ygopro.ctos_follows[ctos_proto].synchronous) {
cancel = ygopro.ctos_follows[ctos_proto].callback(b, info, client, server);
cancel = ygopro.ctos_follows[ctos_proto].callback(b, info, client, client.server);
} else {
ygopro.ctos_follows[ctos_proto].callback(b, info, client, server);
ygopro.ctos_follows[ctos_proto].callback(b, info, client, client.server);
}
}
if (!cancel) {
......@@ -1135,25 +1410,28 @@
} else {
ROOM_bad_ip[client.ip] = 1;
}
client.destroy();
CLIENT_kick(client);
break;
}
}
if (!client.server) {
return;
}
if (client.established) {
for (l = 0, len2 = datas.length; l < len2; l++) {
buffer = datas[l];
server.write(buffer);
for (m = 0, len2 = datas.length; m < len2; m++) {
buffer = datas[m];
client.server.write(buffer);
}
} else {
for (m = 0, len3 = datas.length; m < len3; m++) {
buffer = datas[m];
for (n = 0, len3 = datas.length; n < len3; n++) {
buffer = datas[n];
client.pre_establish_buffers.push(buffer);
}
}
}
});
server.on('data', function(stoc_buffer) {
var b, buffer, cancel, datas, info, l, len2, looplimit, stanzas, stoc_message_length, stoc_proto, struct;
var b, buffer, cancel, datas, info, len2, looplimit, m, stanzas, stoc_message_length, stoc_proto, struct;
stoc_message_length = 0;
stoc_proto = 0;
datas = [];
......@@ -1164,7 +1442,7 @@
stoc_message_length = stoc_buffer.readUInt16LE(0);
} else {
if (stoc_buffer.length !== 0) {
log.warn("bad stoc_buffer length", client.ip);
log.warn("bad stoc_buffer length", server.client.ip);
}
break;
}
......@@ -1172,7 +1450,7 @@
if (stoc_buffer.length >= 3) {
stoc_proto = stoc_buffer.readUInt8(2);
} else {
log.warn("bad stoc_proto length", client.ip);
log.warn("bad stoc_proto length", server.client.ip);
break;
}
} else {
......@@ -1187,9 +1465,9 @@
info = _.clone(struct.fields);
}
if (ygopro.stoc_follows[stoc_proto].synchronous) {
cancel = ygopro.stoc_follows[stoc_proto].callback(b, info, client, server);
cancel = ygopro.stoc_follows[stoc_proto].callback(b, info, server.client, server);
} else {
ygopro.stoc_follows[stoc_proto].callback(b, info, client, server);
ygopro.stoc_follows[stoc_proto].callback(b, info, server.client, server);
}
}
if (!cancel) {
......@@ -1199,20 +1477,22 @@
stoc_message_length = 0;
stoc_proto = 0;
} else {
log.warn("bad stoc_message length", client.ip);
log.warn("bad stoc_message length", server.client.ip);
break;
}
}
looplimit++;
if (looplimit > 800) {
log.info("error stoc", client.name);
log.info("error stoc", server.client.name);
server.destroy();
break;
}
}
for (l = 0, len2 = datas.length; l < len2; l++) {
buffer = datas[l];
client.write(buffer);
if (server.client && !server.client.closed) {
for (m = 0, len2 = datas.length; m < len2; m++) {
buffer = datas[m];
server.client.write(buffer);
}
}
});
}).listen(settings.port, function() {
......@@ -1262,9 +1542,12 @@
});
ygopro.ctos_follow('JOIN_GAME', false, function(buffer, info, client, server) {
var check, decrypted_buffer, finish, i, id, l, len2, len3, m, name, ref2, ref3, replay_id, room, secret;
var check, decrypted_buffer, finish, i, id, len2, len3, m, n, name, ref2, ref3, replay_id, room, secret;
info.pass = info.pass.trim();
if (settings.modules.stop) {
if (CLIENT_is_able_to_reconnect(client)) {
CLIENT_pre_reconnect(client);
return;
} else if (settings.modules.stop) {
ygopro.stoc_die(client, settings.modules.stop);
} else if (info.pass.toUpperCase() === "R" && settings.modules.cloud_replay.enabled) {
ygopro.stoc_send_chat(client, "${cloud_replay_hint}", ygopro.constants.COLORS.BABYBLUE);
......@@ -1286,7 +1569,7 @@
msg: 1,
code: 9
});
client.destroy();
CLIENT_kick(client);
}), 500);
} else if (info.pass.slice(0, 2).toUpperCase() === "R#" && settings.modules.cloud_replay.enabled) {
replay_id = info.pass.split("#")[1];
......@@ -1315,7 +1598,7 @@
msg: 4,
code: settings.version
});
client.destroy();
CLIENT_kick(client);
} else if (!info.pass.length && !settings.modules.random_duel.enabled && !settings.modules.windbot.enabled) {
ygopro.stoc_die(client, "${blank_room_name}");
} else if (info.pass.length && settings.modules.mycard.enabled && info.pass.slice(0, 3) !== 'AI#') {
......@@ -1330,15 +1613,15 @@
return;
}
check = function(buf) {
var checksum, i, l, ref2;
var checksum, i, m, ref2;
checksum = 0;
for (i = l = 0, ref2 = buf.length; 0 <= ref2 ? l < ref2 : l > ref2; i = 0 <= ref2 ? ++l : --l) {
for (i = m = 0, ref2 = buf.length; 0 <= ref2 ? m < ref2 : m > ref2; i = 0 <= ref2 ? ++m : --m) {
checksum += buf.readUInt8(i);
}
return (checksum & 0xFF) === 0;
};
finish = function(buffer) {
var action, l, len2, name, opt1, opt2, opt3, options, ref2, room, title;
var action, len2, m, name, opt1, opt2, opt3, options, ref2, room, title;
action = buffer.readUInt8(1) >> 4;
if (buffer !== decrypted_buffer && (action === 1 || action === 2 || action === 4)) {
ygopro.stoc_die(client, '${invalid_password_unauthorized}');
......@@ -1416,8 +1699,8 @@
room.watchers.push(client);
ygopro.stoc_send_chat(client, "${watch_watching}", ygopro.constants.COLORS.BABYBLUE);
ref2 = room.watcher_buffers;
for (l = 0, len2 = ref2.length; l < len2; l++) {
buffer = ref2[l];
for (m = 0, len2 = ref2.length; m < len2; m++) {
buffer = ref2[m];
client.write(buffer);
}
} else {
......@@ -1433,8 +1716,8 @@
secret = id % 65535 + 1;
decrypted_buffer = new Buffer(6);
ref2 = [0, 2, 4];
for (l = 0, len2 = ref2.length; l < len2; l++) {
i = ref2[l];
for (m = 0, len2 = ref2.length; m < len2; m++) {
i = ref2[m];
decrypted_buffer.writeUInt16LE(buffer.readUInt16LE(i) ^ secret, i);
}
if (check(decrypted_buffer)) {
......@@ -1451,14 +1734,14 @@
},
json: true
}, function(error, response, body) {
var len3, m, ref3;
var len3, n, ref3;
if (body && body.user) {
users_cache[client.name] = body.user.id;
secret = body.user.id % 65535 + 1;
decrypted_buffer = new Buffer(6);
ref3 = [0, 2, 4];
for (m = 0, len3 = ref3.length; m < len3; m++) {
i = ref3[m];
for (n = 0, len3 = ref3.length; n < len3; n++) {
i = ref3[n];
decrypted_buffer.writeUInt16LE(buffer.readUInt16LE(i) ^ secret, i);
}
if (check(decrypted_buffer)) {
......@@ -1522,8 +1805,8 @@
room.watchers.push(client);
ygopro.stoc_send_chat(client, "${watch_watching}", ygopro.constants.COLORS.BABYBLUE);
ref3 = room.watcher_buffers;
for (m = 0, len3 = ref3.length; m < len3; m++) {
buffer = ref3[m];
for (n = 0, len3 = ref3.length; n < len3; n++) {
buffer = ref3[n];
client.write(buffer);
}
} else {
......@@ -1540,9 +1823,10 @@
ygopro.stoc_follow('JOIN_GAME', false, function(buffer, info, client, server) {
var recorder, room, watcher;
room = ROOM_all[client.rid];
if (!room) {
if (!(room && !client.reconnecting)) {
return;
}
client.join_game_buffer = buffer;
if (settings.modules.welcome) {
ygopro.stoc_send_chat(client, settings.modules.welcome, ygopro.constants.COLORS.GREEN);
}
......@@ -1597,15 +1881,15 @@
ygopro.ctos_send(watcher, 'HS_TOOBSERVER');
});
watcher.on('data', function(data) {
var l, len2, ref2, w;
var len2, m, ref2, w;
room = ROOM_all[client.rid];
if (!room) {
return;
}
room.watcher_buffers.push(data);
ref2 = room.watchers;
for (l = 0, len2 = ref2.length; l < len2; l++) {
w = ref2[l];
for (m = 0, len2 = ref2.length; m < len2; m++) {
w = ref2[m];
if (w) {
w.write(data);
}
......@@ -1636,9 +1920,9 @@
}
ygopro.stoc_follow('GAME_MSG', true, function(buffer, info, client, server) {
var card, count, l, len2, line, loc, msg, oppo_pos, phase, playertype, pos, reason, ref2, ref3, ref4, room, trigger_location, val, win_pos;
var card, count, len2, line, loc, m, msg, oppo_pos, phase, playertype, pos, reason, ref2, ref3, ref4, room, trigger_location, val, win_pos;
room = ROOM_all[client.rid];
if (!room) {
if (!(room && !client.reconnecting)) {
return;
}
msg = buffer.readInt8(0);
......@@ -1652,7 +1936,7 @@
if (settings.modules.retry_handle.max_retry_count && client.retry_count >= settings.modules.retry_handle.max_retry_count) {
ygopro.stoc_send_chat_to_room(room, client.name + "${retry_too_much_room_part1}" + settings.modules.retry_handle.max_retry_count + "${retry_too_much_room_part2}", ygopro.constants.COLORS.BABYBLUE);
ygopro.stoc_send_chat(client, "${retry_too_much_part1}" + settings.modules.retry_handle.max_retry_count + "${retry_too_much_part2}", ygopro.constants.COLORS.RED);
client.destroy();
CLIENT_kick(client);
return true;
}
if (client.last_game_msg) {
......@@ -1666,7 +1950,11 @@
}
} else {
client.last_game_msg = buffer;
client.last_game_msg_title = ygopro.constants.MSG[msg];
}
} else if (ygopro.constants.MSG[msg] !== 'RETRY') {
client.last_game_msg = buffer;
client.last_game_msg_title = ygopro.constants.MSG[msg];
}
if ((msg >= 10 && msg < 30) || msg === 132 || (msg >= 140 && msg < 144)) {
room.waiting_for_player = client;
......@@ -1679,6 +1967,7 @@
if (room.hostinfo.mode !== 2) {
client.card_count = 0;
}
room.selecting_tp = false;
if (client.pos === 0) {
room.turn = 0;
room.duel_count = room.duel_count + 1;
......@@ -1708,8 +1997,8 @@
ygopro.stoc_send(room.dueling_players[oppo_pos - win_pos], 'DUEL_END');
ygopro.stoc_send(room.dueling_players[oppo_pos - win_pos + 1], 'DUEL_END');
room.scores[room.dueling_players[oppo_pos - win_pos].name] = -1;
room.dueling_players[oppo_pos - win_pos].destroy();
room.dueling_players[oppo_pos - win_pos + 1].destroy();
CLIENT_kick(room.dueling_players[oppo_pos - win_pos]);
CLIENT_kick(room.dueling_players[oppo_pos - win_pos + 1]);
} else {
ygopro.ctos_send(room.dueling_players[oppo_pos - win_pos].server, 'SURRENDER');
}
......@@ -1738,8 +2027,8 @@
ygopro.stoc_send(room.dueling_players[oppo_pos - win_pos], 'DUEL_END');
ygopro.stoc_send(room.dueling_players[oppo_pos - win_pos + 1], 'DUEL_END');
room.scores[room.dueling_players[oppo_pos - win_pos].name] = -1;
room.dueling_players[oppo_pos - win_pos].destroy();
room.dueling_players[oppo_pos - win_pos + 1].destroy();
CLIENT_kick(room.dueling_players[oppo_pos - win_pos]);
CLIENT_kick(room.dueling_players[oppo_pos - win_pos + 1]);
} else {
ygopro.ctos_send(room.dueling_players[oppo_pos - win_pos].server, 'SURRENDER');
}
......@@ -1862,8 +2151,8 @@
trigger_location = buffer.readUInt8(6);
if (dialogues.dialogues[card] && (ygopro.constants.MSG[msg] !== 'CHAINING' || (trigger_location & 0x8) && !(trigger_location & 0x200))) {
ref4 = _.lines(dialogues.dialogues[card][Math.floor(Math.random() * dialogues.dialogues[card].length)]);
for (l = 0, len2 = ref4.length; l < len2; l++) {
line = ref4[l];
for (m = 0, len2 = ref4.length; m < len2; m++) {
line = ref4[m];
ygopro.stoc_send_chat(client, line, ygopro.constants.COLORS.PINK);
}
}
......@@ -1873,7 +2162,7 @@
});
ygopro.ctos_follow('HS_TOOBSERVER', true, function(buffer, info, client, server) {
var l, len2, player, ref2, room;
var len2, m, player, ref2, room;
room = ROOM_all[client.rid];
if (!room) {
return;
......@@ -1882,8 +2171,8 @@
return false;
}
ref2 = room.players;
for (l = 0, len2 = ref2.length; l < len2; l++) {
player = ref2[l];
for (m = 0, len2 = ref2.length; m < len2; m++) {
player = ref2[m];
if (player === client) {
ygopro.stoc_send_chat(client, "${cannot_to_observer}", ygopro.constants.COLORS.BABYBLUE);
return true;
......@@ -1893,25 +2182,25 @@
});
ygopro.ctos_follow('HS_KICK', true, function(buffer, info, client, server) {
var l, len2, player, ref2, room;
var len2, m, player, ref2, room;
room = ROOM_all[client.rid];
if (!room) {
return;
}
ref2 = room.players;
for (l = 0, len2 = ref2.length; l < len2; l++) {
player = ref2[l];
for (m = 0, len2 = ref2.length; m < len2; m++) {
player = ref2[m];
if (player && player.pos === info.pos && player !== client) {
if (room.arena === "athletic") {
ygopro.stoc_send_chat_to_room(room, client.name + " ${kicked_by_system}", ygopro.constants.COLORS.RED);
client.destroy();
CLIENT_kick(client);
return true;
}
client.kick_count = client.kick_count ? client.kick_count + 1 : 1;
if (client.kick_count >= 5 && room.random_type) {
ygopro.stoc_send_chat_to_room(room, client.name + " ${kicked_by_system}", ygopro.constants.COLORS.RED);
ROOM_ban_player(player.name, player.ip, "${random_ban_reason_zombie}");
client.destroy();
CLIENT_kick(client);
return true;
}
ygopro.stoc_send_chat_to_room(room, player.name + " ${kicked_by_player}", ygopro.constants.COLORS.RED);
......@@ -1929,7 +2218,7 @@
});
ygopro.stoc_follow('HS_PLAYER_CHANGE', false, function(buffer, info, client, server) {
var is_ready, l, len2, len3, m, p1, p2, player, pos, ref2, ref3, room;
var is_ready, len2, len3, m, n, p1, p2, player, pos, ref2, ref3, room;
room = ROOM_all[client.rid];
if (!(room && room.max_player && client.is_host)) {
return;
......@@ -1940,8 +2229,8 @@
if (room.arena) {
room.ready_player_count = 0;
ref2 = room.players;
for (l = 0, len2 = ref2.length; l < len2; l++) {
player = ref2[l];
for (m = 0, len2 = ref2.length; m < len2; m++) {
player = ref2[m];
if (player.pos === pos) {
player.is_ready = is_ready;
}
......@@ -1980,8 +2269,8 @@
} else {
room.ready_player_count_without_host = 0;
ref3 = room.players;
for (m = 0, len3 = ref3.length; m < len3; m++) {
player = ref3[m];
for (n = 0, len3 = ref3.length; n < len3; n++) {
player = ref3[n];
if (player.pos === pos) {
player.is_ready = is_ready;
}
......@@ -1998,8 +2287,23 @@
}
});
ygopro.stoc_follow('FIELD_FINISH', true, function(buffer, info, client, server) {
var room;
room = ROOM_all[client.rid];
if (!room) {
return;
}
client.reconnecting = false;
if (client.last_game_msg && client.last_game_msg_title !== 'WAITING') {
setTimeout(function() {
ygopro.stoc_send(client, 'GAME_MSG', client.last_game_msg);
}, 1000);
}
return true;
});
wait_room_start = function(room, time) {
var l, len2, player, ref2;
var len2, m, player, ref2;
if (!(!room || room.started || room.ready_player_count_without_host < room.max_player - 1)) {
time -= 1;
if (time) {
......@@ -2011,12 +2315,12 @@
}), 1000);
} else {
ref2 = room.players;
for (l = 0, len2 = ref2.length; l < len2; l++) {
player = ref2[l];
for (m = 0, len2 = ref2.length; m < len2; m++) {
player = ref2[m];
if (player && player.is_host) {
ROOM_ban_player(player.name, player.ip, "${random_ban_reason_zombie}");
ygopro.stoc_send_chat_to_room(room, player.name + " ${kicked_by_system}", ygopro.constants.COLORS.RED);
player.destroy();
CLIENT_kick(player);
}
}
}
......@@ -2032,7 +2336,7 @@
}
} else {
ygopro.stoc_send_chat_to_room(room, room.waiting_for_player.name + " ${kicked_by_system}", ygopro.constants.COLORS.RED);
room.waiting_for_player.destroy();
CLIENT_kick(room.waiting_for_player);
if (room.waiting_for_player_interval) {
clearInterval(room.waiting_for_player_interval);
room.waiting_for_player_interval = null;
......@@ -2072,9 +2376,9 @@
if (settings.modules.tips.get) {
load_tips();
setInterval(function() {
var l, len2, room;
for (l = 0, len2 = ROOM_all.length; l < len2; l++) {
room = ROOM_all[l];
var len2, m, room;
for (m = 0, len2 = ROOM_all.length; m < len2; m++) {
room = ROOM_all[m];
if (room && room.established) {
if (!room.started || room.changing_side) {
ygopro.stoc_send_random_tip_to_room(room);
......@@ -2085,21 +2389,22 @@
}
ygopro.stoc_follow('DUEL_START', false, function(buffer, info, client, server) {
var deck_arena, deck_name, deck_text, l, len2, player, ref2, room;
var deck_arena, deck_name, deck_text, len2, m, player, ref2, room;
room = ROOM_all[client.rid];
if (!room) {
if (!(room && !client.reconnecting)) {
return;
}
if (!room.started) {
room.started = true;
room.start_time = moment().format();
room.turn = 0;
if (!room.windbot && settings.modules.http.websocket_roomlist) {
roomlist.start(room);
}
room.dueling_players = [];
ref2 = room.players;
for (l = 0, len2 = ref2.length; l < len2; l++) {
player = ref2[l];
for (m = 0, len2 = ref2.length; m < len2; m++) {
player = ref2[m];
if (!(player.pos !== 7)) {
continue;
}
......@@ -2280,7 +2585,7 @@
break;
case '/color':
if (settings.modules.chat_color.enabled) {
cip = settings.modules.mycard.enabled ? client.name : client.ip;
cip = CLIENT_get_authorize_key(client);
if (cmsg = cmd[1]) {
if (cmsg.toLowerCase() === "help") {
ygopro.stoc_send_chat(client, "${show_color_list}", ygopro.constants.COLORS.BABYBLUE);
......@@ -2343,7 +2648,7 @@
ygopro.stoc_send_chat(client, "${banned_duel_tip}", ygopro.constants.COLORS.RED);
ROOM_ban_player(client.name, client.ip, "${random_ban_reason_abuse}");
ROOM_ban_player(client.name, client.ip, "${random_ban_reason_abuse}", 3);
client.destroy();
CLIENT_kick(client);
return true;
} else {
client.abuse_count = client.abuse_count + 4;
......@@ -2405,33 +2710,53 @@
});
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, l, len2, len3, line, m, oppo_pos, room, struct, win_pos;
var buff_main, buff_side, card, current_deck, deck, deck_array, deck_main, deck_side, deck_text, deckbuf, decks, found_deck, i, len2, len3, line, m, n, oppo_pos, room, struct, win_pos;
if (settings.modules.reconnect.enabled && client.pre_reconnecting) {
if (_.isEqual(buffer, client.pre_deckbuf)) {
CLIENT_reconnect(client);
} else {
ygopro.stoc_send_chat(client, "${deck_incorrect_reconnect}", ygopro.constants.COLORS.RED);
ygopro.stoc_send(client, 'ERROR_MSG', {
msg: 2,
code: 0
});
ygopro.stoc_send(client, 'HS_PLAYER_CHANGE', {
status: (client.pos << 4) | 0xa
});
}
return true;
}
room = ROOM_all[client.rid];
if (!room) {
return false;
}
buff_main = (function() {
var l, ref2, results;
var m, ref2, results;
results = [];
for (i = l = 0, ref2 = info.mainc; 0 <= ref2 ? l < ref2 : l > ref2; i = 0 <= ref2 ? ++l : --l) {
for (i = m = 0, ref2 = info.mainc; 0 <= ref2 ? m < ref2 : m > ref2; i = 0 <= ref2 ? ++m : --m) {
results.push(info.deckbuf[i]);
}
return results;
})();
buff_side = (function() {
var l, ref2, ref3, results;
var m, ref2, ref3, results;
results = [];
for (i = l = ref2 = info.mainc, ref3 = info.mainc + info.sidec; ref2 <= ref3 ? l < ref3 : l > ref3; i = ref2 <= ref3 ? ++l : --l) {
for (i = m = ref2 = info.mainc, ref3 = info.mainc + info.sidec; ref2 <= ref3 ? m < ref3 : m > ref3; i = ref2 <= ref3 ? ++m : --m) {
results.push(info.deckbuf[i]);
}
return results;
})();
client.main = buff_main;
client.side = buff_side;
if (client.side_tcount) {
clearInterval(client.side_interval);
client.side_interval = null;
client.side_tcount = null;
if (room.started) {
client.selected_preduel = true;
if (client.side_tcount) {
clearInterval(client.side_interval);
client.side_interval = null;
client.side_tcount = null;
}
} else {
client.start_deckbuf = buffer;
}
oppo_pos = room.hostinfo.mode === 2 ? 2 : 1;
if (settings.modules.http.quick_death_rule >= 2 && room.started && room.death && room.scores[room.dueling_players[0].name] !== room.scores[room.dueling_players[oppo_pos].name]) {
......@@ -2442,9 +2767,9 @@
ygopro.stoc_send(room.dueling_players[oppo_pos - win_pos + 1], 'DUEL_END');
}
room.scores[room.dueling_players[oppo_pos - win_pos].name] = -1;
room.dueling_players[oppo_pos - win_pos].destroy();
CLIENT_kick(room.dueling_players[oppo_pos - win_pos]);
if (room.hostinfo.mode === 2) {
room.dueling_players[oppo_pos - win_pos + 1].destroy();
CLIENT_kick(room.dueling_players[oppo_pos - win_pos + 1]);
}
return true;
}
......@@ -2462,8 +2787,8 @@
buffer = struct.buffer;
found_deck = false;
decks = fs.readdirSync(settings.modules.tournament_mode.deck_path);
for (l = 0, len2 = decks.length; l < len2; l++) {
deck = decks[l];
for (m = 0, len2 = decks.length; m < len2; m++) {
deck = decks[m];
if (_.endsWith(deck, client.name + ".ydk")) {
found_deck = deck;
}
......@@ -2479,8 +2804,8 @@
deck_main = [];
deck_side = [];
current_deck = deck_main;
for (m = 0, len3 = deck_array.length; m < len3; m++) {
line = deck_array[m];
for (n = 0, len3 = deck_array.length; n < len3; n++) {
line = deck_array[n];
if (line.indexOf("!side") >= 0) {
current_deck = deck_side;
}
......@@ -2518,7 +2843,11 @@
ygopro.ctos_follow('HAND_RESULT', false, function(buffer, info, client, server) {
var room;
room = ROOM_all[client.rid];
if (!(room && (room.random_type || room.arena))) {
if (!room) {
return;
}
client.selected_preduel = true;
if (!(room.random_type || room.arena)) {
return;
}
if (client.pos === 0) {
......@@ -2530,14 +2859,19 @@
ygopro.ctos_follow('TP_RESULT', false, function(buffer, info, client, server) {
var room;
room = ROOM_all[client.rid];
if (!(room && (room.random_type || room.arena))) {
if (!room) {
return;
}
client.selected_preduel = true;
room.selecting_tp = false;
if (!(room.random_type || room.arena)) {
return;
}
room.last_active_time = moment();
});
ygopro.stoc_follow('CHAT', true, function(buffer, info, client, server) {
var l, len2, pid, player, ref2, room, tcolor, tplayer;
var len2, m, pid, player, ref2, room, tcolor, tplayer;
room = ROOM_all[client.rid];
pid = info.player;
if (!(room && pid < 4 && settings.modules.chat_color.enabled)) {
......@@ -2556,8 +2890,8 @@
}
}
ref2 = room.players;
for (l = 0, len2 = ref2.length; l < len2; l++) {
player = ref2[l];
for (m = 0, len2 = ref2.length; m < len2; m++) {
player = ref2[m];
if (player && player.pos === pid) {
tplayer = player;
}
......@@ -2578,7 +2912,15 @@
ygopro.stoc_follow('SELECT_HAND', false, function(buffer, info, client, server) {
var room;
room = ROOM_all[client.rid];
if (!(room && (room.random_type || room.arena))) {
if (!room) {
return;
}
client.selected_preduel = false;
if (client.pos === 0) {
room.selecting_hand = true;
room.changing_side = false;
}
if (!(room.random_type || room.arena)) {
return;
}
if (client.pos === 0) {
......@@ -2595,7 +2937,10 @@
if (!room) {
return;
}
client.selected_preduel = false;
room.changing_side = false;
room.selecting_hand = false;
room.selecting_tp = client;
if (room.random_type || room.arena) {
room.waiting_for_player = client;
room.last_active_time = moment();
......@@ -2609,6 +2954,7 @@
return;
}
room.changing_side = true;
client.selected_preduel = false;
if (settings.modules.side_timeout) {
client.side_tcount = settings.modules.side_timeout;
ygopro.stoc_send_chat(client, "${side_timeout_part1}" + settings.modules.side_timeout + "${side_timeout_part2}", ygopro.constants.COLORS.BABYBLUE);
......@@ -2621,7 +2967,7 @@
ygopro.stoc_send_chat_to_room(room, client.name + "${side_overtime_room}", ygopro.constants.COLORS.BABYBLUE);
ygopro.stoc_send_chat(client, "${side_overtime}", ygopro.constants.COLORS.RED);
room.scores[client.name] = -9;
client.destroy();
CLIENT_kick(client);
return clearInterval(sinterval);
} else {
client.side_tcount = client.side_tcount - 1;
......@@ -2641,7 +2987,7 @@
});
ygopro.stoc_follow('REPLAY', true, function(buffer, info, client, server) {
var duellog, dueltime, i, l, len2, len3, m, player, ref2, ref3, replay_filename, room;
var duellog, dueltime, i, len2, len3, m, n, player, ref2, ref3, replay_filename, room;
room = ROOM_all[client.rid];
if (!room) {
return settings.modules.tournament_mode.enabled && settings.modules.tournament_mode.replay_safe;
......@@ -2655,13 +3001,13 @@
replay_filename = dueltime;
if (room.hostinfo.mode !== 2) {
ref2 = room.dueling_players;
for (i = l = 0, len2 = ref2.length; l < len2; i = ++l) {
for (i = m = 0, len2 = ref2.length; m < len2; i = ++m) {
player = ref2[i];
replay_filename = replay_filename + (i > 0 ? " VS " : " ") + player.name;
}
} else {
ref3 = room.dueling_players;
for (i = m = 0, len3 = ref3.length; m < len3; i = ++m) {
for (i = n = 0, len3 = ref3.length; n < len3; i = ++n) {
player = ref3[i];
replay_filename = replay_filename + (i > 0 ? (i === 2 ? " VS " : " & ") : " ") + player.name;
}
......@@ -2675,11 +3021,11 @@
replay_filename: replay_filename,
roommode: room.hostinfo.mode,
players: (function() {
var len4, n, ref4, results;
var len4, o, ref4, results;
ref4 = room.dueling_players;
results = [];
for (n = 0, len4 = ref4.length; n < len4; n++) {
player = ref4[n];
for (o = 0, len4 = ref4.length; o < len4; o++) {
player = ref4[o];
results.push({
name: player.name + (settings.modules.tournament_mode.show_ip && !player.is_local ? " (IP: " + player.ip.slice(7) + ")" : "") + (settings.modules.tournament_mode.show_info && !(room.hostinfo.mode === 2 && player.pos % 2 > 0) ? " (Score:" + room.scores[player.name] + " LP:" + (player.lp != null ? player.lp : room.hostinfo.start_lp) + (room.hostinfo.mode !== 2 ? " Cards:" + (player.card_count != null ? player.card_count : room.hostinfo.start_hand) : "") + ")" : ""),
winner: player.pos === room.winner
......@@ -2707,9 +3053,9 @@
if (settings.modules.random_duel.enabled) {
setInterval(function() {
var l, len2, room, time_passed;
for (l = 0, len2 = ROOM_all.length; l < len2; l++) {
room = ROOM_all[l];
var len2, m, room, time_passed;
for (m = 0, len2 = ROOM_all.length; m < len2; m++) {
room = ROOM_all[m];
if (!(room && room.started && room.random_type && room.last_active_time && room.waiting_for_player)) {
continue;
}
......@@ -2729,9 +3075,9 @@
if (settings.modules.mycard.enabled) {
setInterval(function() {
var l, len2, room, time_passed;
for (l = 0, len2 = ROOM_all.length; l < len2; l++) {
room = ROOM_all[l];
var len2, m, room, time_passed;
for (m = 0, len2 = ROOM_all.length; m < len2; m++) {
room = ROOM_all[m];
if (!(room && room.started && room.arena && room.last_active_time && room.waiting_for_player)) {
continue;
}
......@@ -2785,7 +3131,7 @@
return callback + "( " + text + " );";
};
requestListener = function(request, response) {
var archive_args, archive_name, archive_process, check, death_room_found, duellog, error, filename, getpath, l, len2, len3, len4, len5, m, n, o, oppo_pos, parseQueryString, pass_validated, player, ref2, replay, room, roomsjson, u, win_pos;
var archive_args, archive_name, archive_process, check, death_room_found, duellog, error, filename, getpath, len2, len3, len4, len5, m, n, o, oppo_pos, p, parseQueryString, pass_validated, player, ref2, replay, room, roomsjson, u, win_pos;
parseQueryString = true;
u = url.parse(request.url, parseQueryString);
pass_validated = u.query.pass === settings.modules.http.password;
......@@ -2797,10 +3143,10 @@
response.writeHead(200);
roomsjson = JSON.stringify({
rooms: (function() {
var l, len2, results;
var len2, m, results;
results = [];
for (l = 0, len2 = ROOM_all.length; l < len2; l++) {
room = ROOM_all[l];
for (m = 0, len2 = ROOM_all.length; m < len2; m++) {
room = ROOM_all[m];
if (room && room.established) {
results.push({
pid: room.process.pid.toString(),
......@@ -2809,11 +3155,11 @@
roommode: room.hostinfo.mode,
needpass: (room.name.indexOf('$') !== -1).toString(),
users: (function() {
var len3, m, ref2, results1;
var len3, n, ref2, results1;
ref2 = room.players;
results1 = [];
for (m = 0, len3 = ref2.length; m < len3; m++) {
player = ref2[m];
for (n = 0, len3 = ref2.length; n < len3; n++) {
player = ref2[n];
if (player.pos != null) {
results1.push({
id: (-1).toString(),
......@@ -2854,8 +3200,8 @@
archive_args = ["a", "-mx0", "-y", archive_name];
check = false;
ref2 = duel_log.duel_log;
for (l = 0, len2 = ref2.length; l < len2; l++) {
replay = ref2[l];
for (m = 0, len2 = ref2.length; m < len2; m++) {
replay = ref2[m];
check = true;
archive_args.push(replay.replay_filename);
}
......@@ -2953,8 +3299,8 @@
return;
}
if (u.query.shout) {
for (m = 0, len3 = ROOM_all.length; m < len3; m++) {
room = ROOM_all[m];
for (n = 0, len3 = ROOM_all.length; n < len3; n++) {
room = ROOM_all[n];
if (room && room.established) {
ygopro.stoc_send_chat_to_room(room, u.query.shout, ygopro.constants.COLORS.YELLOW);
}
......@@ -2989,8 +3335,8 @@
response.end(addCallback(u.query.callback, "['ban ok', '" + u.query.ban + "']"));
} else if (u.query.death) {
death_room_found = false;
for (n = 0, len4 = ROOM_all.length; n < len4; n++) {
room = ROOM_all[n];
for (o = 0, len4 = ROOM_all.length; o < len4; o++) {
room = ROOM_all[o];
if (!(room && room.established && room.started && !room.death && (u.query.death === "all" || u.query.death === room.port.toString()))) {
continue;
}
......@@ -3026,9 +3372,9 @@
ygopro.stoc_send(room.dueling_players[oppo_pos - win_pos + 1], 'DUEL_END');
}
room.scores[room.dueling_players[oppo_pos - win_pos].name] = -1;
room.dueling_players[oppo_pos - win_pos].destroy();
CLIENT_kick(room.dueling_players[oppo_pos - win_pos]);
if (room.hostinfo.mode === 2) {
room.dueling_players[oppo_pos - win_pos + 1].destroy();
CLIENT_kick(room.dueling_players[oppo_pos - win_pos + 1]);
}
}
break;
......@@ -3050,8 +3396,8 @@
}
} else if (u.query.deathcancel) {
death_room_found = false;
for (o = 0, len5 = ROOM_all.length; o < len5; o++) {
room = ROOM_all[o];
for (p = 0, len5 = ROOM_all.length; p < len5; p++) {
room = ROOM_all[p];
if (!(room && room.established && room.started && room.death && (u.query.deathcancel === "all" || u.query.deathcancel === room.port.toString()))) {
continue;
}
......
......@@ -60,6 +60,8 @@ for name, declaration of structs_declaration
#消息发送函数,至少要把俩合起来....
@stoc_send = (socket, proto, info)->
if socket.closed
return
#console.log proto, proto_structs.STOC[proto], structs[proto_structs.STOC[proto]]
if typeof info == 'undefined'
buffer = ""
......@@ -86,6 +88,8 @@ for name, declaration of structs_declaration
return
@ctos_send = (socket, proto, info)->
if socket.closed
return
#console.log proto, proto_structs.CTOS[proto], structs[proto_structs.CTOS[proto]]
if typeof info == 'undefined'
buffer = ""
......@@ -164,5 +168,7 @@ for name, declaration of structs_declaration
msg: 1
code: 9
} if client
client.destroy() if client
if client
client.system_kicked = true
client.destroy()
return
\ No newline at end of file
......@@ -104,6 +104,9 @@
this.stoc_send = function(socket, proto, info) {
var buffer, header, key, ref, struct, value;
if (socket.closed) {
return;
}
if (typeof info === 'undefined') {
buffer = "";
} else if (Buffer.isBuffer(info)) {
......@@ -138,6 +141,9 @@
this.ctos_send = function(socket, proto, info) {
var buffer, header, key, ref, struct, value;
if (socket.closed) {
return;
}
if (typeof info === 'undefined') {
buffer = "";
} else if (Buffer.isBuffer(info)) {
......@@ -264,6 +270,7 @@
});
}
if (client) {
client.system_kicked = true;
client.destroy();
}
};
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment