RoleAction.lua 10.1 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_RUNE_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")

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

	-- 跨天登陆事件
	role:onCrossDay(now)
	role:setProperty("ltime", now)


	for _, name in ipairs({"dailyData", "dinerData"}) do
		response[name] = role[name]:data()
	end

	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 <= 50 then
		heroWave = 0
		table_insert(modules, "heros")
	end

	local runeIds = {}
	for id ,_ in pairs(role.runeBag) do
		table.insert(runeIds, id)
	end 
	local runeWave = math.ceil(#runeIds / WAVE_RUNE_NUMS)
	if #runeIds <= 50 then
		runeWave = 0
		table_insert(modules, "runeBag")
	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 + runeWave

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

	local curWave = 1 

	local runeIndex = 1
	for index = curWave + 1, curWave + runeWave do
		local runeResponse = {runeBag = {}}
		for i = runeIndex, runeIndex + WAVE_RUNE_NUMS do
			local runeId = runeIds[i]
			if not runeId then
				break
			end
			local rune = role.runeBag[runeId]
			table.insert(runeResponse.runeBag, rune:data())
			runeIndex = runeIndex + 1
		end
		runeResponse.runeWave = index
		SendPacket(actionCodes.Role_loginRpc, MsgPack.pack(runeResponse))
	end
	curWave = curWave + runeWave

	local heroIndex = 1
	for index = curWave + 1, curWave + 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
	curWave = curWave + heroWave

	-- 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

function _M.saleItemRpc(agent, data)
	local role = agent.role
	local msg = MsgPack.unpack(data)
	local itemId = msg.itemId
	local count = msg.count
	if math.illegalNum(count, 1, role:getItemCount(itemId)) then return end
	local itemData = csvdb["itemCsv"][itemId]
	if itemData.sell_effect == "" then return end
	local sellEffect = itemData.sell_effect:toArray(true, "=")

	role:costItems({[itemId] = count})
	local reward = role:award({[sellEffect[1]] = sellEffect[2] * count})

	SendPacket(actionCodes.Role_saleItemRpc, MsgPack.pack({reward = reward}))
	return true
end

function _M.openItemRpc(agent, data)
	local role = agent.role
	local msg = MsgPack.unpack(data)
	local itemId = msg.itemId
	local count = msg.count
	if math.illegalNum(count, 1, role:getItemCount(itemId)) then return end
	local itemData = csvdb["itemCsv"][itemId]
	if itemData.use_type ~= 2 then return end
	local randomData = csvdb["item_randomCsv"][tonumber(itemData.use_effect)]
	if not randomData then return end

	local reward = randomData.gift:toNumMap()
	for _id, _count in pairs(reward) do
		reward[_id] = _count * count
	end
	if randomData.random_num > 0 and randomData.random_gift ~= "" then
		for i = 1, count do
			local pool = {}
			for _, temp in ipairs(randomData.random_gift:toArray()) do
				table.insert(pool, temp:toArray(true, "="))
			end
			local needCount = math.min(#pool, randomData.random_num)
			for j = 1, needCount do
				local idx = math.randWeight(pool, 3)
				reward[pool[idx][1]] = (reward[pool[idx][1]] or 0) + pool[idx][2]
				table.remove(pool, idx)
			end
		end
	end
	role:costItems({[itemId] = count})
	reward = role:award(reward)

	SendPacket(actionCodes.Role_openItemRpc, MsgPack.pack({reward = reward}))
	return true
end

function _M.storyBookRewardRpc(agent, data)
	local role = agent.role
	local msg = MsgPack.unpack(data)
	local storyId = msg.id
	local storyBookData = csvdb["story_bookCsv"][storyId]
	if not storyBookData then return end
	local storyStatus = role:getProperty("storyB")
	if not storyStatus[storyId] or not storyStatus[storyId].s or storyStatus[storyId].s ~= 1 then 
		return 
	end
	-- 获取奖励
	storyStatus[storyId].s = -1
	role:changeUpdates({{ type = "storyB", field = storyId, value = storyStatus[storyId] }})
	local reward = role:award(storyBookData.gift)
	SendPacket(actionCodes.Role_storyBookRewardRpc, MsgPack.pack({reward = reward}))
	return true
end

function _M.unLockStoryBookRpc(agent, data)
	local role = agent.role
	local msg = MsgPack.unpack(data)

	local storyId = msg.id
	local storyBookData = csvdb["story_bookCsv"][storyId]
	if not storyBookData or storyBookData.lockItem == "" then return end -- 不能解锁

	local storyStatus = role:getProperty("storyB")
	if storyStatus[storyId] and storyStatus[storyId].s then return end  --不需要解锁

	local cost = storyBookData.lockItem:toNumMap()
	if not cost or not next(cost) then return end
	if not role:checkItemEnough(cost) then return end  -- 消耗品不足

	role:costItems(cost)

	-- 解锁
	storyStatus[storyId] = storyStatus[storyId] or {}
	table.clear(storyStatus[storyId])
	storyStatus[storyId].s = 1
	role:changeUpdates({{ type = "storyB", field = storyId, value = storyStatus[storyId] }})
	SendPacket(actionCodes.Role_unLockStoryBookRpc, '')
	return true
end


return _M