RoleAction.lua 8.23 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), "ignoreMaintain")) ~= 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 lastLoginTime = role:getProperty("lastLoginTime")

	-- 跨天登陆事件
	if not role:onCrossDay(now) then
		role:checkActivityStatus(lastLoginTime, now)
		if role:getProperty("carbonDouble") == "" then
			role:initCarbonDouble()
		end
	end
	-- 登陆回复
	role:onRecoverLogin(now)
	-- 引导是否连续
	role:checkGuide()


	role:setProperty("lastLoginTime", now)
	if msg.device and type(msg.device) == "string" then
		role:setProperty("device", msg.device)
	end

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

	-- 需要加载模块数据
	local modules = {
		"carbons","maps",
	}

	local heroIds = {}
	for heroId, _ in pairs(role.heros) do
		table.insert(heroIds, heroId)
	end
	local heroWave = math.ceil(#heroIds / WAVE_HERO_NUMS)

	local equipIds = {}
	for equipId, _ in pairs(role.equips) do
		table.insert(equipIds, equipId)
	end
	local equipWave = math.ceil(#equipIds / WAVE_EQUIP_NUMS)

	if #heroIds <= 50 then
		heroWave = 0
		table_insert(modules, "heros")
	end
	if #equipIds <= 50 then
		equipWave = 0
		table_insert(modules, "equips")
	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 + equipWave

	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
	local equipIndex = 1
	for index = 2 + heroWave, 1 + heroWave + equipWave  do
		local equipResponse = {equips = {}}
		for i = equipIndex, equipIndex + WAVE_EQUIP_NUMS do
			local equipId = equipIds[i]
			if not equipId then
				break
			end
			local equip = role.equips[equipId]
			table_insert(equipResponse.equips, equip:data())
			equipIndex = equipIndex + 1
		end
		equipResponse.equipWave = index
		SendPacket(actionCodes.Role_loginRpc, MsgPack.pack(equipResponse))
	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
	role.lessmsg = false
	
	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

	-- 给角色自动加载当前副本数据
	newRole:addCarbon({carbonId = 10101, status = 0, starNum = 0})
	-- 给角色自动加载农场信息
	newRole:addFarm()
	-- 给角色自动加载爬塔信息
	newRole:addTower()
	-- 给角色增加pvpInfo
	newRole:addPvpInfo()
	--给新角色增加diner
	newRole:addDiner()
	-- 关闭 锁定新食灵
	local autoStatus = newRole:getProperty("autoStatus")
	newRole:setProperty("autoStatus", autoStatus:setv(3,1))

	for index, hero in ipairs(globalCsv["birthHero"]) do
		hero.notNotify = true
		hero.desc = "birth_award"
		local heroId = newRole:awardHero(hero.type, hero)
		if index == 1 then
			local newHero = newRole.heros[heroId]
			newHero:setProperty("lock", 1)
			newHero:setProperty("formation", 1)
			newRole:setProperty("crown", heroId)
			newRole:setProperty("formationJson", json.encode({["1"] = {list = {["1"] = heroId}, pos = {["1"] = heroId}, lock = {}}}))
		end
	end
	-- 出生道具
	local ucode = getActionCode(newRole)
	for id, num in pairs(globalCsv["birthItem"]:toNumMap()) do
		newRole:awardItemCsv(id, {count = num, desc = "birth_award", notNotify = true, ucode = ucode})
	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