globald.lua 8.44 KB
local skynet = require "skynet"
local harbor = require "skynet.harbor"
local json = require("shared.json")
local redisproxy = require("shared.redisproxy")

require "shared.init"
require "utils.init"
require "RedisKeys"
require "skynet.manager"
require "GlobalVar"


local ipairs = ipairs
local table_insert = table.insert
local tarr2tab = table.array2Table
local string_format = string.format


local CHECK_MAIL_STATUS_INTERVAL 	= 100 * 60
local CHECK_BATTLE_ACT_CLOSE_INTERVAL = 100 * 1
local function mailQuene()
	local delayEmail = tonum(redisproxy:hget("autoincrement_set", "delay_email"))
	if delayEmail == 0 then
		return
	end
	local begin = math.max(delayEmail - 100, 1)
	local mails = redisproxy:pipelining(function (red)
		for id = begin, delayEmail do
			red:hgetall(string.format("delayEmail:%s", id))
		end
	end)
	if not mails then
		return
	end
	local now = skynet.timex()
	local mailList = {}
	for index, data in ipairs(mails) do
		if next(data) then
			local email = tarr2tab(data)
			if tonum(email.startTime) <= now then
				table_insert(mailList, email)

				if #mailList > 100 then
					break
				end
			end
		end
	end
	if #mailList == 0 then
		return
	end
	redisproxy:pipelining(function (red)
		for _, email in ipairs(mailList) do
			red:del(string_format("delayEmail:%s", email.id))
		end
	end)
	table.sort(mailList, function(a, b)
		return tonum(a.id) < tonum(b.id)
	end)
	for _, email in ipairs(mailList) do
		local gid = redisproxy:hincrby("autoincrement_set", "email", 1)
		if email.mid then
			redisproxy:hmset(string_format("globalEmail:%s", gid), 
				"id", gid,
				"createtime", email.startTime,
				"title", email.title,
				"stitle", email.stitle,
				"content", email.content,
				"attachments", email.attachments,
				"endtime", email.endTime,
				"mid", email.mid,
				"timestamp", now,
				"delayType", email.delayType
			)
		else
			redisproxy:hmset(string_format("globalEmail:%s", gid), 
				"id", gid,
				"createtime", email.startTime,
				"title", email.title,
				"stitle", email.stitle,
				"content", email.content,
				"attachments", email.attachments,
				"endtime", email.endTime,
				"timestamp", now,
				"delayType", email.delayType
			)
		end
	end
	redisproxy:hset("autoincrement_set", "emailTimestamp", now)
end

-- @desc: 定时邮件队列检测
local function check_mail_queue()
	pcall(mailQuene)
	skynet.timeout(CHECK_MAIL_STATUS_INTERVAL, check_mail_queue)
end

-- @desc: 检测关卡活动结束 排行榜奖励发放
local lastCheckBattleActTs = 0
local function check_battle_act_close()
	local csvdb = require "shared.csvdata"
	local act = require "models.Activity"
	local st = 0
	local et = 0
	local actId = 0
	local timeNow = skynet.timex()
	for k, v in pairs(csvdb["activity_ctrlCsv"]) do
		if v.showType == act.ActivityType.ChallengeLevel then
			local openTimes = v.time:toArray(false, "=")
			if openTimes[1] ~= "0" then
				st = toUnixtime(openTimes[1]..string_format("%02x", RESET_TIME))
			end
			if openTimes[2] ~= "0" then
				et = toUnixtime(openTimes[2]..string_format("%02x", RESET_TIME))
			end
			actId = k
			break
		end
	end
	if st ~= 0 and et ~= 0 and actId ~= 0 then
		-- close
		if lastCheckBattleActTs < et and timeNow >= et then
			-- check rank key exist
			local rankKey = RANK_COMMON..RANK_TYPE.ActBattleBoss
			local flag = redisproxy:exists(rankKey)
			if flag then
				local actData = csvdb["activity_groupCsv"][actId]
				local lastRank = actData[#actData].rank

				local ids = redisproxy:zrevrange(rankKey, 0 , lastRank - 1)
				local rankIndex = 0
				for roleId in pairs(ids) do
					rankIndex = rankIndex + 1
					for _, cfg in pairs(actData) do
						if rankIndex <= cfg.rank then
							redisproxy:insertEmail({
								roleId = roleId,
								emailId = cfg.email_1,
								attachments = cfg.reward_1,
								contentPms = {rankIndex},
							})
							break
						end
					end
				end

				redisproxy:del(rankKey..":bak")
				redisproxy:rename(rankKey, rankKey..":bak")
			end
		end
	end
	lastCheckBattleActTs = skynet.timex()
	skynet.timeout(CHECK_BATTLE_ACT_CLOSE_INTERVAL, check_battle_act_close)
end

-- @desc: 检查海港贸易开启、关闭
local function check_trade_seaport_status()
	local nowTime = skynet.timex()
	local nextTime = dayLater(nowTime)
	local interval = 100 * (nextTime - nowTime + 1)

	local curTm = os.date("*t", nowTime)
	if curTm.wday == 7 and curTm.hour >= 4 then -- 周六
		local oldTime = tonumber(redisproxy:hget("autoincrement_set", "seaportTime0")) or 0
		local cur4Time = specTime({hour = 4},nowTime)
		if cur4Time ~= oldTime then
			redisproxy:hset("autoincrement_set", "seaportTime0", cur4Time)
			redisproxy:hset("autoincrement_set", "seaportTime1", 1)
			redisproxy:del(SEAPORT_TRADE_TASK_1)
			redisproxy:del(SEAPORT_TRADE_TASK_2)
		end
	end
	if curTm.wday == 1 and curTm.hour >= 4 then -- 周日
		if (tonumber(redisproxy:hget("autoincrement_set", "seaportTime1")) or 0) == 1 then
			redisproxy:hset("autoincrement_set", "seaportTime2", 1)
		end
	end
	if curTm.wday == 2 and curTm.hour >= 4 then -- 周一
		-- redisproxy:hset("autoincrement_set", "seaportTime0", 0)
		redisproxy:hset("autoincrement_set", "seaportTime1", 0)
		redisproxy:hset("autoincrement_set", "seaportTime2", 0)
	end

	skynet.timeout(interval, check_trade_seaport_status)
end

-- @desc: 海港贸易捐赠作弊
local seaportTimes = {}
local function check_trade_seaport_donate()
	local time1 = tonumber(redisproxy:hget("autoincrement_set", "seaportTime1")) or 0
	local time2 = tonumber(redisproxy:hget("autoincrement_set", "seaportTime2")) or 0
	if time1 == 0 and time2 == 0 then
		seaportTimes = {}
		skynet.timeout(360000, check_trade_seaport_donate)
		return
	end

	local csvdb = require "shared.csvdata"
	local donateCsv = csvdb["seaport_purchaseCsv"]

	local times = {time1, time2}
	for phase, open in ipairs(times) do
		if open == 1 and not seaportTimes[phase] then
			seaportTimes[phase] = {}
			for _, _ in ipairs(donateCsv[phase]) do
				table.insert(seaportTimes[phase],math.randomInt(1800, 3600))
			end
		end
	end

	local interval = 3600
	local phase, id = 0, 0

	for key1, data in ipairs(seaportTimes) do
		for key2, temp in pairs(data) do
			if times[key1] == 1 and temp < interval then
				interval = temp
				phase = key1
				id = key2
			end
		end
	end

	for _, data in ipairs(seaportTimes) do
		for id, temp in pairs(data) do
			data[id] = temp - interval
			if data[id] == 0 then
				data[id] = math.randomInt(1800, 3600)
			end
		end
	end

	if phase ~= 0 and id ~= 0 then
		local redisKeys = {SEAPORT_TRADE_TASK_1,SEAPORT_TRADE_TASK_2}
		local all = donateCsv[phase][id].need_num
		local old = tonumber(redisproxy:hget(redisKeys[phase],id)) or 0
		local add = math.min(math.randomInt(math.floor(all/20),math.floor(all/12)),all - old)
		if add > 0 then
			redisproxy:hincrby(redisKeys[phase],id,add)
		else
			seaportTimes[phase][id] = nil
		end
	end

	skynet.timeout(interval * 100, check_trade_seaport_donate)
end

local function check_work_battle()
	local csvdb = require "shared.csvdata"
	local now = skynet.timex()
	local day = weekday(now)
	local workMainCsv = csvdb["work_mainCsv"][day]
	if workMainCsv and isSpecTime(now - RESET_TIME * 3600, csvdb["time_resetCsv"][TimeReset["WorkBattle1"]].start / 3600, 24) then
		local round = math.floor((now - START_RESET_TIME) / 604800)
		local field = round * 10 + day
		local count = tonum(redisproxy:hget(WORK_BATTLE_COUNT, field))
		if count < workMainCsv.target_num then
			local add = math.floor(workMainCsv.target_num * math.randomInt(3125, 5000) / 100000)
			redisproxy:hincrby(WORK_BATTLE_COUNT, field, add)
		end
	end
	skynet.timeout(math.randomInt(10 * 60, 15 * 60) * 100, check_work_battle)
end

local CMD = {}


-- 服务器缓存50条消息
local cacheWorldMsg = {}
local CACHE_WORLD_MSG_COUNT = 50
function CMD.sendWorldMsg(channel, msg)
	cacheWorldMsg[channel] = cacheWorldMsg[channel] or {}
	table.insert(cacheWorldMsg[channel], msg)
	for i = #cacheWorldMsg[channel] - CACHE_WORLD_MSG_COUNT, 1, -1 do
		table.remove(cacheWorldMsg[channel], i)
	end
end

function CMD.getWorldMsg(channel)
	local msgs = cacheWorldMsg[channel] or {}
	return msgs
end


function CMD.start()
	math.randomInit(skynet.timex())
	check_mail_queue()
	--check_battle_act_close()
	check_trade_seaport_status()
	check_trade_seaport_donate()
	check_work_battle()
end

local function __init__()
	skynet.dispatch("lua", function(_, _, command, ...)
		local f = CMD[command]
		if f then
			if command == "sendWorldMsg" then
				skynet.ignoreret()
				f(...)
			else
				skynet.ret(skynet.pack(f(...)))
			end
		end
	end)
	skynet.register(".globald")

end

skynet.start(__init__)