RoleAction.lua 6.05 KB
local ipairs = ipairs
local table = table
local math = math
local next = next
local string = string
local redisproxy = redisproxy
local MsgPack = MsgPack
local getRandomName = getRandomName
local mcast_util = mcast_util
local string_format = string.format
local tonumber = tonumber
local require = require
local table_insert = table.insert
local tconcat = table.concat
local httpc = require("http.httpc")

local WAVE_HERO_NUMS = 150
local WAVE_EQUIP_NUMS = 150

local function validName(name)
	name = string.upper(name)
	local exist = redisproxy:exists(string_format("user:%s", name))
	if exist then return "existed" end

	local SERV = string_format("NAMED%d", math.random(1, 5))
	local legal = skynet.call(SERV, "lua", "check", name)
	return legal and "ok" or "illegal"
end

-- 随机玩家名
local function randomRoleName()
	-- 过滤已经存在的名字
	local name
	repeat
		name = getRandomName()
	until validName(name) == "ok"
	return name
end

local function setRoleName(uid, roleId)
	local result
	local name
	local dbName
	repeat
		name = randomRoleName()
		dbName = string.upper(name)
		result = redisproxy:setnx(string_format("user:%s", dbName), roleId)
	until result == 1
	redisproxy:set(string_format("uid:%s", uid), dbName)
	return name
end

local _M = {}
function _M.loginRpc( agent, data )
	local msg = MsgPack.unpack(data)
	local response = {}

	-- if msg.version ~= globalCsv.version then
	-- 	response.result = "UPDATE_TIP"
	-- 	SendPacket(actionCodes.Role_loginRpc, MsgPack.pack(response))
	-- 	return true
	-- end

	-- 1.
	local roleId = redisproxy:get(string_format("user:%s", string.upper(msg.name)))
	if not roleId then
		response.result = "NOT_EXIST"
		SendPacket(actionCodes.Role_loginRpc, MsgPack.pack(response))
		return true
	end

	roleId = tonumber(roleId)

	--维护不能登录
	local maintain = tonumber(redisproxy:hget("autoincrement_set", "maintain"))
	if maintain and maintain > 0 then
		if tonumber(redisproxy:hget(string_format("role:%d", roleId), "ignoreMt")) ~= 1 then
			response.result = "MAINTAIN_TIP"
			SendPacket(actionCodes.Role_loginRpc, MsgPack.pack(response))
			return true
		end
	end

	local now = skynet.timex()
	local role = agent.role
	-- 2
	if not role then
		local roleKey = string_format("role:%d", roleId)
		if not redisproxy:exists(roleKey) then
			response.result = "DB_ERROR"
			SendPacket(actionCodes.Role_loginRpc, MsgPack.pack(response))
			return true
		end
		-- 2a
		role = require("models.Role").new({key = roleKey})
		role:load()
		role:loadAll()
	else
		role:reloadWhenLogin()
	end
	
	if not msg.isGMlogin then
		local banTime = role:getProperty("banTime")
		if banTime > now then
			response.result = "BAN_TIP"
			response.banTime = banTime
			response.banType = role:getProperty("banType")
			response.roleId = roleId
			SendPacket(actionCodes.Role_loginRpc, MsgPack.pack(response))
			return true
		end
		if banTime ~= 0 then
			-- 清除封号状态
			role:setBan(0)
		end
	end
	SERV_OPEN = redisproxy:hget("autoincrement_set", "server_start")
	local ltime = role:getProperty("ltime")

	role:changeStructVersion() -- 数据结构 版本更新

	-- 跨天登陆事件
	role:onCrossDay(now)

	role:setProperty("ltime", now)
	
	response.role = role:data()
	response.result = "SUCCESS"
	response.serverTime = now

	local modules = {}

	local heroIds = {}
	for heroId, _ in pairs(role.heros) do
		table.insert(heroIds, heroId)
	end
	local heroWave = math.ceil(#heroIds / WAVE_HERO_NUMS)
	if #heroIds <= 0 then
		heroWave = 0
		table_insert(modules, "heros")
	end

	for _, name in ipairs(modules) do
		response[name] = {}
		for id, unit in pairs(role[name]) do
			response[name][id] = unit:data()
		end
	end

	response.wave = 1 + heroWave

	SendPacket(actionCodes.Role_loginRpc, MsgPack.pack(response))

	local heroIndex = 1
	for index = 2, 1 + heroWave do
		local heroResponse = {heros = {}}
		for i = heroIndex, heroIndex + WAVE_HERO_NUMS do
			local heroId = heroIds[i]
			if not heroId then
				break
			end
			local hero = role.heros[heroId]
			table_insert(heroResponse.heros, hero:data())
			heroIndex = heroIndex + 1
		end
		heroResponse.heroWave = index
		SendPacket(actionCodes.Role_loginRpc, MsgPack.pack(heroResponse))
	end

	-- role:log("login", { ip = agent.ip, diamond = role:getProperty("diamond"), reDiamond = role:getProperty("reDiamond")})

	datacenter.set("agent", roleId, {
		serv = skynet.self(),
		fd = agent.client_fd,
		gate_serv = agent.gate_serv,
	})
	agent.role = role
	
	start_agent_timer()
	-- 注册全服广播
	local channel = math.randomInt(1, 1)
	local w_channel = datacenter.get( ("MC_W_CHANNEL" .. channel) )
	if w_channel then
		mcast_util.sub_world(w_channel)
	end
	return true
end

function _M.createRpc(agent, data)
	local msg = MsgPack.unpack(data)
	local response = {}

	-- 再次检查uid
	local uid = tostring(msg.uid)
	local user = redisproxy:get(string_format("uid:%s", uid))
	if user then
		response.result = "SUCCESS"
		response.roleName = user
		SendPacket(actionCodes.Role_createRpc, MsgPack.pack(response))
		return true
	end

	local roleId = getNextRoleId()
	if not roleId then
		response.result = "DB_FULL"
		SendPacket(actionCodes.Role_createRpc, MsgPack.pack(response))
		return true
	end
	local roleName = setRoleName(msg.uid, roleId)
	local newRole = require("models.Role").new({
		key = string_format("role:%d", roleId),
		id = roleId,
		uid = tostring(msg.uid),
		subId = msg.subId or 0,
		name = roleName,
		uname = msg.uname or "",
		device = tostring(msg.device)
	})

	if newRole:create() then
		--更新USER表
		response.result = "SUCCESS"
		response.roleId = roleId
		response.roleName = string.upper(roleName)
	else
		response.result = "DB_ERROR"
		SendPacket(actionCodes.Role_createRpc, MsgPack.pack(response))
		return true
	end

	-- 欢迎邮件
	-- redisproxy:insertEmail({roleId = roleId, emailId = 1})
	-- redisproxy:insertEmail({roleId = roleId, emailId = 2})

	newRole:log("create", { ip = agent.ip, ucode = ucode})

	SendPacket(actionCodes.Role_createRpc, MsgPack.pack(response))
	return true
end

function _M.syncTimeRpc(agent, data)
	SendPacket(actionCodes.Role_syncTimeRpc, MsgPack.pack({nowTime = skynet.timex()}))
	return true
end

return _M