5e6af9d6
 
  zhouhaihai
 
排队功能
 | 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20 
 | 
  -- 排队系统
  
  require "ProtocolCode"
  require "shared.init"
  require "utils.init"
  require "GlobalVar"
  require "RedisKeys"
  require "skynet.manager"
  
  local queue = require "skynet.queue"
  local netpack = require "skynet.netpack"
  local socket = require "skynet.socket"
  local xxtea = require "xxtea"
  
  skynet = require "skynet"
  
  local MAX_COUNT = tonumber(skynet.getenv("max_queue"))
  -- 心跳定时间隔
  local HEART_TIMER_INTERVAL 		= 30
  local HEART_TIMEOUT_COUNT_MAX 	= 3
 
 | 
5e6af9d6
 
  zhouhaihai
 
排队功能
 | 
21
22
23
24
25
26
27
28
29 
 | 
  
  local CMD = {}
  local f2u = {}
  local u2i = {}	-- {idx, fd, {lastHeart, timeOutCount, nextCheck}}
  local idx2u = {}
  local curIdx = 0  -- 下一个即将进入游戏的玩家索引
  local nextIdx = 0  -- 新加的位置
  
  
 
 | 
5e6af9d6
 
  zhouhaihai
 
排队功能
 | 
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63 
 | 
  local function getRank(uid)
  	local info = u2i[uid]
  	if not info then return -1 end
  	return (info[1] + MAX_COUNT - curIdx) % MAX_COUNT + 1
  end
  
  
  function SendPacket(actionCode, bin, client_fd)
  	if #bin > 0 then bin = xxtea.encrypt(bin, XXTEA_KEY) end
  	local head = string.pack("H", actionCode)
  	return socket.write(client_fd, netpack.pack(head .. bin))
  end
  
  local function checkQueue(fd)
  	if not f2u[fd] then return end
  	local info = u2i[f2u[fd]]
  	if info then
  		info[3][1] = skynet.timex()
  	end
  	local rank = getRank(f2u[fd])
  	SendPacket(actionCodes.Sys_checkQueue, MsgPack.pack({rank = rank}), fd)
  end
  
  
  skynet.register_protocol {
  	name = "client",
  	id = skynet.PTYPE_CLIENT,
  	unpack = function (msg, sz)
  		local data = skynet.tostring(msg, sz)
  		local cmd = string.unpack("H", string.sub(data, 1, 2))
  		return cmd, string.sub(data, 3)
  	end,
  	dispatch = function(session, address, cmd, data)
  		skynet.ignoreret()
 
 | 
e24d1abd
 
  zhouhaihai
 
修改 排队
 | 
64
65
66 
 | 
  		if cmd == actionCodes.Sys_checkQueue then
  			checkQueue(session)
  		end
 
 | 
5e6af9d6
 
  zhouhaihai
 
排队功能
 | 
67
68
69 
 | 
  	end
  }
  
 
 | 
5e6af9d6
 
  zhouhaihai
 
排队功能
 | 
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123 
 | 
  function CMD.push(uid, fd)
  	uid = tostring(uid)
  	if u2i[uid] then -- 存在]
  		local oldfd = u2i[uid][2]
  		if  oldfd and oldfd ~= fd then 
  			-- 踢掉老的
  			SendPacket(actionCodes.Sys_maintainNotice, MsgPack.pack({body = "server_accountOccupied", iskey = true}), oldfd)
  			skynet.timeout(10, function ()
  				skynet.call(gate_serv, "lua", "kick", oldfd)
  			end)
  			f2u[oldfd] = nil
  		end
  		u2i[uid][2] = fd
  		f2u[fd] = uid
  		u2i[uid][3] = {skynet.timex(), 0, skynet.timex() + HEART_TIMER_INTERVAL}
  	else -- 新排队的用户
  		if nextIdx == curIdx and next(idx2u) then -- 满了
  			return 
  		end
  		u2i[uid] = {nextIdx, fd, {skynet.timex(), 0, skynet.timex() + HEART_TIMER_INTERVAL}}
  		f2u[fd] = uid
  		idx2u[nextIdx] = uid
  		nextIdx = (nextIdx + 1) % MAX_COUNT
  	end
  	skynet.call(gate_serv, "lua", "forward", fd, 0, skynet.self())
  
  	return getRank(uid)
  end
  
  function CMD.pop()
  	while true do
  		local uid = idx2u[curIdx]
  		if not uid then return end  -- 空的
  		local info = u2i[uid]
  		if not info then
  			idx2u[curIdx] = nil
  		else
  			if info[2] then
  				-- 找到合适的了
  				u2i[uid] = nil
  				idx2u[curIdx] = nil
  				f2u[info[2]] = nil
  
  				curIdx = (curIdx + 1) % MAX_COUNT
  				return uid, info[2]
  			else
  				idx2u[curIdx] = nil
  				u2i[uid] = nil
  			end
  		end
  		curIdx = (curIdx + 1) % MAX_COUNT
  	end
  end
  
 
 | 
e24d1abd
 
  zhouhaihai
 
修改 排队
 | 
124 
 | 
  
 
 | 
5e6af9d6
 
  zhouhaihai
 
排队功能
 | 
125
126
127
128
129
130
131
132
133 
 | 
  -- 下线了
  function CMD.socket_close(fd)
  	local uid = f2u[fd]
  	if not uid then return end
  	f2u[fd] = nil
  	local info = u2i[uid]
  	info[2] = nil
  end
  
 
 | 
e24d1abd
 
  zhouhaihai
 
修改 排队
 | 
134 
 | 
  function CMD.handle_timeout()
 
 | 
5e6af9d6
 
  zhouhaihai
 
排队功能
 | 
135
136
137
138
139
140
141
142
143
144
145
146
147 
 | 
  	local now = skynet.timex()
  	for uid, info in pairs(u2i) do
  		if info[2] and info[3] and now >= info[3][3] then --存在fd 检查心跳
  			if info[3][1] -  now > HEART_TIMER_INTERVAL or now - info[3][1] > HEART_TIMER_INTERVAL then
  				info[3][2] = info[3][2] + 1
  				info[3][3] = now + HEART_TIMER_INTERVAL
  				if info[3][2] >= HEART_TIMEOUT_COUNT_MAX then
  					skynet.error("timeout! then queued will closed", info[2], uid)
  					skynet.call(gate_serv, "lua", "kick", info[2])
  				end
  			end
  		end
  	end
 
 | 
5e6af9d6
 
  zhouhaihai
 
排队功能
 | 
148
149 
 | 
  end
  
 
 | 
e24d1abd
 
  zhouhaihai
 
修改 排队
 | 
150
151
152 
 | 
  function CMD.count()
  	return (nextIdx + MAX_COUNT - curIdx) % MAX_COUNT
  end
 
 | 
5e6af9d6
 
  zhouhaihai
 
排队功能
 | 
153 
 | 
  
 
 | 
e24d1abd
 
  zhouhaihai
 
修改 排队
 | 
154 
 | 
  return CMD
 
 |