You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

441 lines
13 KiB
Lua

local skynet = require "skynet"
local socket = require "skynet.socket"
local cjson = require "cjson"
local datacenter = require "skynet.datacenter"
local config = require "config"
local msgutils = require "msgutils"
local dateutils = require "dateutils"
local mc = require "skynet.multicast"
local netpack = require "websocketnetpack"
local usermodel = require "usermodel"
local bagmodel = require "bagmodel"
local heromodel = require "heromodel"
local coingetmodel = require "coingetmodel"
local dailydealmodel = require "dailydealmodel"
local fundmodel = require "fundmodel"
local fukamodel = require "fukamodel"
local daybuymodel = require "daybuymodel"
local huobamodel = require "huobamodel"
local signinmodel = require "signinmodel"
local limitshopmodel = require "limitshopmodel"
local friendmodel = require "friendmodel"
local achievementmodel = require "achievementmodel"
local baoxiangmodel = require "baoxiangmodel"
local zhaomumodel = require "zhaomumodel"
local duanwumodel = require "duanwumodel"
local clubmodel = require "clubmodel"
local msgmodel = require "msgmodel"
local arenamodel = require "arenamodel"
local mailmodel = require "mailmodel"
local guajimodel = require "guajimodel"
local shoplogic = require "shoplogic"
local fukalogic = require "fukalogic"
local shoplimitlogic = require "shoplimitlogic"
local guajilogic = require "guajilogic"
require "functions"
local myid = ...
DEBUG("agent myid = ", myid)
local WATCHDOG
local gate
local CMD = {}
local uid
local client_fd
local runfork = true
local idletime
local lastcgtime
local counter = 0
local channels = {}
local funcs={}
local func_checker = {}
local handlers = {
"game.cmd.user",
"game.cmd.eqp",
"game.cmd.activity",
"game.cmd.room",
"game.cmd.friend",
"game.cmd.club",
"game.cmd.tower",
"game.cmd.boss",
"game.cmd.shop",
"game.cmd.mail",
"game.cmd.arena",
}
local function send_package(pack)
if not client_fd then
return
end
local data = pack.data or {}
data.errcode = data.errcode or 0
if data and data.errcode and data.errcode>0 and not data.errmsg then
data.errmsg = config.get("errmsg",string.format("e%d",data.errcode))
end
data.curtime = os.time()
data.msec = skynet.time()*1000
local ok, pack = msgutils.encode(pack)
if not ok then
error("agent send_package encode fail")
end
DEBUG("<=========== agent发送消息 to client :", pack)
local ok = socket.write(client_fd,netpack.pack(pack))
-- DEBUG("socket write ok = ", ok)
end
local sendmsgpack = function(pkg)
local box = pkg.box
-- skynet.error("uid ---------->", UID, " box ---------->", cjson.encode(box))
if box ~= nil then
if box.c=="msg" then
if box.m=="clubmsg" then
msgmodel.clubindex = box.data.data.msg.id
send_package(box)
elseif box.m == "mailmsg" then
msgmodel.mailindex = box.data.data.msg.id
mailmodel:newmail(box.data.data.msg)
send_package(box)
elseif box.m == "recruitmsg" then
msgmodel.recruitindex = box.data.data.msg.id
send_package(box)
elseif box.m == "arenamsg" then
msgmodel.arenaindex = box.data.data.msg.id
send_package(box)
elseif box.m == "friendapply" then
send_package(box)
elseif box.m == "applyagree" then
friendmodel:inneraddfriend(box.data.data.user)
send_package(box)
elseif box.m == "givecoin" then
friendmodel:innergivecoin(box.data.data.msg.uid, box.data.data.msg.coin)
send_package(box)
elseif box.m == "friendmsg" then
msgmodel.friendindex = box.data.data.msg.id
send_package(box)
end
end
end
end
local registerHandler = function ()
for _, v in ipairs(handlers) do
local handler = require(v)
if handler then
for k, func in pairs(handler) do
if type(func) == 'function' and not string.startwith(k, "_") then
local splits = string.split(v, ".")
local funname = string.format("on_%s_%s", splits[#splits], k)
funcs[funname] = func
end
end
end
end
end
skynet.register_protocol {
name = "client",
id = skynet.PTYPE_CLIENT,
unpack = function (msg, sz)
local a= skynet.tostring(msg,sz)
-- return funpack(a)
return a
end,
dispatch = function (fd, _, msg)
skynet.ignoreret()
local ok, cmd = msgutils.decode(msg)
skynet.error("agent recv new msg ===>", cjson.encode(cmd))
if ok then
idletime = os.time()
local c = cmd.c
local m = cmd.m
local fname = string.format("on_%s_%s",tostring(c),tostring(m))
local curmsec = skynet.time() * 1000
-- DEBUG("curmsec = ", curmsec)
-- DEBUG("func_checker fname = ", fname, " curmsec ", func_checker[fname], " uid = ", UID)
if func_checker[fname] and curmsec - func_checker[fname] < 200 then
local resp = {}
resp.c = c
resp.m = m
local data = {}
data.errcode = 10000
data.errmsg = "对不起! 太快了~~~"
data.data = {}
resp.data = data
-- WARN(" cmd result = ", cjson.encode(resp))
send_package(resp)
return
end
func_checker[fname] = curmsec
local f = funcs[fname]
if f then
if not cmd.data.curtime or os.time()+1 < cmd.data.curtime then
WARN("Timestamp verification failed")
counter = counter + 1
if counter >= 3 then
local resp = {}
resp.c = "user"
resp.m = "logout"
local data = {}
data.errcode = 10000
data.errmsg = "对不起! 检测到您的数据异常了~~~"
data.data = {}
resp.data = data
send_package(resp)
return
end
local resp = {}
resp.c = c
resp.m = m
local data = {}
data.errcode = 10000
data.errmsg = "对不起! 检测到您的数据异常了~~~"
data.data = {}
resp.data = data
-- WARN(" cmd result = ", cjson.encode(resp))
send_package(resp)
return
end
cmd.data.agent = skynet.self()
local result = f(cmd)
-- WARN(" cmd result = ", cjson.encode(result))
if result then
send_package(result)
end
end
end
end
}
--加入消息中心
local function join_msg_center()
pcall(skynet.call, ".msgd", "lua", "come", UID)
-- 挂接钩子
skynet.fork(function()
while runfork do
local ok, resp = pcall(skynet.call, ".msgd", "lua", "get", UID, msgmodel:serialize(), clubmodel:getclubid() or 0, usermodel:getserverid(), arenamodel:calcurserverid(), usermodel:getBaiFuServer())
if ok then
sendmsgpack(resp)
end
skynet.sleep(100)
end
end)
JOIN_SUCCESS = true
end
local exit_msg_center = function()
if not UID then
return
end
pcall(skynet.call, ".msgd", "lua", "bye", UID)
end
local function init()
local ok = pcall(skynet.call, ".ordermqd", "lua", "online", UID, skynet.self())
end
local function login()
runfork = true
local ok, account_status, first_login = pcall(skynet.call, ".usercenterd", "lua", "login", UID)
assert(ok, "login fail")
assert(checkint(account_status) == 0, "该账号已冻结")
if first_login then
local ok = pcall(skynet.call, ".signind", "lua", "login", UID)
local ok = pcall(skynet.call, ".taskd", "lua", "login", UID)
end
if usermodel._init then
usermodel:login()
end
send_package({ c = "user", m = "login", data = { errcode = 0, data = {} } })
end
--领取每日福利
local function receiverdaywelfare()
local ok = pcall(skynet.call, ".maild", "lua", "newusermail", UID)
-- local ok = pcall(skynet.call, ".maild", "lua", "senddaywelfaremail", UID)
end
local function autokick(t)
skynet.fork(function()
while runfork do
DEBUG("autokick ", t)
if os.time() - idletime > 60 then
pcall(skynet.send,WATCHDOG,"lua","close",client_fd)
break
end
if not lastcgtime or os.time() - lastcgtime > 5*60 then
collectgarbage()
end
skynet.sleep(15*100)
end
end)
end
function CMD.start(conf)
DEBUG("agent start conf = ", cjson.encode(conf))
local fd = conf.client
gate = conf.gate
WATCHDOG = conf.watchdog
client_fd = fd
CLIENT_FD = client_fd
UID = math.floor(conf.uid)
skynet.call(gate, "lua", "forward", fd)
registerHandler()
init()
login()
receiverdaywelfare()
idletime = os.time()
--是否开启心跳检查
autokick("start")
counter = 0
return "ok"
end
--重连
function CMD.reconnect(fd)
-- skynet.error("agent reconnect fd ------>", fd)
client_fd = fd
CLIENT_FD = client_fd
skynet.error("server agent forward")
skynet.call(gate, "lua", "forward", fd)
login()
receiverdaywelfare()
idletime = os.time()
autokick("reconnect")
counter = 0
return "ok"
end
function CMD.join_msg_center()
join_msg_center()
return "ok"
end
function CMD.recharge_callback(order_no)
local ok, order = pcall(skynet.call, ".orderd", "lua", "get", order_no)
-- INFO("recharge_callback ok = ", ok ," order = ", inspect(order))
if order.pay_type == "goldshop" then
local conf = shoplogic.getconf(order.recharge_id)
bagmodel:incrBagA("gold", checkint(conf.gold) + checkint(conf.give_gold))
elseif order.pay_type == "buyguajitime" then ---购买挂机时长
local cfg = guajilogic.getguajishichangconf(order.recharge_id)
guajimodel:setbasetime(cfg.time)
elseif order.pay_type == "firstrecharge" then --首冲
elseif order.pay_type == "buydailydeal" then ---购买特惠礼包
dailydealmodel:buydailydeal(order.recharge_id)
elseif order.pay_type == "buyfund" then ---购买基金
fundmodel:buyfund(order.recharge_id)
elseif order.pay_type == "buyfuka" then ---购买福卡
fukamodel:buyfuka(order.recharge_id)
local cfg = fukalogic.getconfbyid(order.recharge_id)
local rewards = cfg.buy_reward
for i,v in ipairs(rewards) do
bagmodel:incrBagA(v.key, v.value)
end
elseif order.pay_type == "buylimitshop" then ---购买限购商品
local cfg = shoplimitlogic.getconfbyid(checkint(order.recharge_id))
local rewards = cfg.reward
for i,v in ipairs(rewards) do
bagmodel:incrBagA(v.key, v.value)
end
limitshopmodel:buy(order.recharge_id)
elseif order.pay_type == "buybaoxiang" then ---购买宝箱商城
baoxiangmodel:buy(order.recharge_id)
elseif order.pay_type == "buyzhaomu" then ---购买招募商城
zhaomumodel:buy(order.recharge_id)
elseif order.pay_type == "buyduanwu" then ---购买端午限购
if duanwumodel._init then
duanwumodel:buy(order.recharge_id)
duanwumodel:incrscore(checkint(order.payment))
end
end
--TODO: 获取积天好礼 累计充值天数
usermodel:incrrechargetotal(checkint(order.payment)) --vip 充值金额增加
achievementmodel:emit("recharge", achievementmodel)
daybuymodel:add(order.payment)
local ok, ret = pcall(skynet.call, ".orderd", "lua", "complete", order_no)
send_package({ c = "user", m = "recharge_callback", data = { errcode = 0, errmsg = "充值成功", data = {} } })
return "ok"
end
local function logout()
if huobamodel._init then
huobamodel:save()
end
usermodel:logout()
end
function CMD.disconnect()
skynet.error("disconnect close------>")
runfork=false
JOIN_SUCCESS=false
logout()
exit_msg_center()
skynet.call(WATCHDOG, "lua", "close", client_fd)
return "ok"
end
local function exit()
local ok = pcall(skynet.call, ".ordermqd", "lua", "offline", UID)
usermodel:saveall()
heromodel:saveall()
end
function CMD.exit()
skynet.error("agent exit------->")
runfork=false
JOIN_SUCCESS=false
exit()
skynet.exit()
return 'ok'
end
function CMD.nativesend(cmd)
--skynet.error('nativesend--------->', cjson.encode(cmd))
local c = cmd.c
local m = cmd.m
send_package(cmd)
return "ok"
end
skynet.start(function()
skynet.dispatch("lua", function(_,_, command, ...)
-- skynet.trace()
--skynet.error("game agent command = ", command)
local f = CMD[command]
local ret = f(...)
if ret then
skynet.ret(skynet.pack(ret))
end
end)
end)