HomeServer/lualib-src/Server-main/Common/Player/PlayerCenter.lua
2024-11-20 15:41:37 +08:00

511 lines
18 KiB
Lua
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

local skynet = require "skynet"
local mysql = require "skynet.db.mysql"
local oo = require "Class"
local cmd = require "GameCmd"
local json =require "json"
local player = require "Player"
local log = require "Log"
local pb = require "pb"
local sqlUrl = require "SqlUrl"
local playerFields = require "PlayerFields"
local redisKeyUrl = require "RedisKeyUrl"
local dyeworkshop = require "DyeWorkShop"
local errorInfo = require "ErrorInfo"
local dataType = require "DataType"
local cluserServer = require "ClusterServer"
local serverId = tonumber(skynet.getenv "serverId")
local PlayerCenter = oo.class()
--[[
大致修改 登陆时检查下是否有新字段然后同步的REDIS中
]]
PlayerCenter.Status_Login = 1 --用户已登陆
PlayerCenter.Status_Playing = 2 --用户游戏中
PlayerCenter.Status_Offline = 3 --用户掉线
function PlayerCenter:Init()
self.playerList = {}
end
--跨天
function PlayerCenter:OnNewDay()
for k, v in pairs(self.playerList) do
--非存档玩家才能走这里
if self.Status_Playing == v.status then
v.player:ResetTodayData()
end
end
end
--每5秒调一次
function PlayerCenter:On5SecTimer()
if not cluserServer:IsGameServer(serverId) then
return
end
end
--关闭SocketId连接
function PlayerCenter:CloseSocket( socketId )
local s2cData,retLen = skynet.call( "TcpSocket", "lua","KickUserOffline", socketId )
if errorInfo.Suc == s2cData.code then
log.info(string.format("关闭socketId %d 成功" , socketId ))
return true
else
log.info(string.format("关闭socketId %d 失败" , socketId ))
return false
end
end
--是否存在游戏玩家查找帐号
function PlayerCenter:IsExistPlayerForAccount( account )
account = tostring(account)
for k, v in pairs( self.playerList ) do
if account == v.account then
return true
end
end
return false
end
--是否存在游戏玩家
function PlayerCenter:IsExistPlayer( platform , account )
for k, v in pairs( self.playerList ) do
if platform == v.platform and account == v.account then
return true
end
end
return false
end
--玩家是否在线
function PlayerCenter:IsPlaying( userId )
if self.playerList[ userId ] and self.Status_Playing == self.playerList[ userId ].status then
return true
end
return false
end
--是否掉线
function PlayerCenter:IsOffline( socketId )
if self.playerList[ socketId ] and self.Status_Offline == self.playerList[ socketId ].status then
return true
end
return false
end
--根据帐号获取SocketId
function PlayerCenter:GetSocketIdForAccount( account )
for k, v in pairs(self.playerList) do
if account == v.account then
return k
end
end
return -1
end
--根据userId获取SocketId
function PlayerCenter:GetSocketIdForUserID( userId )
if self.playerList[ userId ] then
return self.playerList[ userId ].socketId
end
return -1
end
--根据SocketId获取userId
function PlayerCenter:GetUserIDForSocketId( socketId )
for k, v in pairs(self.playerList) do
if socketId == v.socketId then
return v.userId
end
end
return nil
end
--获取人数信息
function PlayerCenter:GetPlayerCount()
local countInfo = {}
countInfo.playing = 0
countInfo.offline = 0
for k, v in pairs(self.playerList) do
if self.Status_Playing == v.status then
countInfo.playing = countInfo.playing + 1
elseif self.Status_Offline == v.status then
countInfo.offline = countInfo.offline + 1
end
end
return countInfo
end
--初始化玩家
function PlayerCenter:InitPlayer( player , c2sData)
local addr = c2sData.addr
local platform = c2sData.data.platform
local curHardwareCode = tostring(c2sData.data.hardwareCode)
--检查房间是否有新的配置
skynet.server.passCheck:CheckNew( player )
skynet.server.house:CheckNew( player )
skynet.server.msgTips:CheckNew( player )
skynet.server.friend:CheckNewMsg( player )
skynet.server.extraRevenue:CalcOffline( player )
skynet.server.mail:CheckNewMail( player)
skynet.server.announcement:CheckNewAnnouncement( player)
skynet.server.flowerpot:RefreshFlowerpot( player )
skynet.server.map:InitData( player )
skynet.server.dyeworkshop:InitData(player)
skynet.server.store:InitData(player)
skynet.server.store:SendIconPackToUser(player)
--是否完成第一步新手引导
local isExistFirstStep = false
for k, v in pairs( player.gameData.finishGuide ) do
if 1 == v then
isExistFirstStep = true
break
end
end
if player.basicInfo.isNewPlayer then
--新玩家
player.basicInfo.isNewPlayer = false
for i = dataType.FirstOpType_Start, dataType.FirstOpType_End, 1 do
if not player.gameData.firstOp[ i ] then
player.gameData.firstOp[ i ] = false
end
end
--解锁
player:CheckUnlockSystem()
--赠送家具到房间
self:InitPlayerData( player )
--新人签到数据初始化
skynet.server.playerLand:InitData(player)
--设置界面关注有礼
skynet.server.msgTips:Add( player , 20 )
skynet.server.msgTips:Add( player , 21 )
skynet.server.msgTips:Add( player , 22 )
elseif not player.basicInfo.isNewPlayer and not isExistFirstStep then
--未完成成第一步新手引导,就把家具摆放回去
self:InitPlayerData( player)
end
--初始化商店
player:InitShop()
skynet.server.audit:InitData( player , platform , curHardwareCode )
skynet.server.playerRecord:Add( player.userId , dataType.RecordType_1 , addr , curHardwareCode , c2sData.data.version)
--增加登录历史
self:AddLoginHistory( player )
end
--进入平台
function PlayerCenter:UserEnter( c2sData , playerData )
local socketId = c2sData.socketId
local addr = c2sData.addr
local platform = c2sData.data.platform
local curHardwareCode = tostring(c2sData.data.hardwareCode)
local userId = tonumber(playerData.basicInfo.userID)
local account = playerData.basicInfo.accountName
playerData.basicInfo.userID = userId --老版本的还是字符串,这里强制改成数字型
if self.playerList[ userId ] then
--关闭其它Tcp连接
local oldHardwareCode = tostring( self.playerList[ userId ].player.basicInfo.hardwareCode )
local oldSocketId = self.playerList[ userId ].socketId
if oldHardwareCode ~= curHardwareCode and "" ~= oldHardwareCode and "" ~= curHardwareCode then
skynet.server.gameServer:SendMsgToUser( userId , "CMD_S2C_UserExit" , { exitType = 2 })
log.info(string.format("玩家 %d 登陆设备信息不一致 开始顶号 原设备 %s 当前设备码 %s" ,userId , oldHardwareCode , curHardwareCode))
end
self:CloseSocket( oldSocketId )
log.info(string.format("玩家 %d socket %d 帐号 %s 重新进入游戏 关闭原 socket %d 当前设备码 %s" , userId , socketId , account , oldSocketId , curHardwareCode))
self.playerList[ userId ].player.basicInfo.hardwareCode = curHardwareCode
--计算在线时间
local gameTime = os.time() - self.playerList[ userId ].player.tmpData.intoTime
self.playerList[ userId ].player.basicInfo.allGameTime = self.playerList[ userId ].player.basicInfo.allGameTime + gameTime
else
playerData.basicInfo.hardwareCode = curHardwareCode
local newPlayer = player.new( userId , playerData )
self.playerList[ userId ] = {}
self.playerList[ userId ].player = newPlayer
log.info(string.format("玩家 %d socket %d 帐号 %s 进入游戏 设备码 %s" , userId , socketId , account , "" == curHardwareCode and "暂无" or curHardwareCode))
end
self.playerList[ userId ].socketId = socketId
self.playerList[ userId ].platform = platform
self.playerList[ userId ].userId = userId
self.playerList[ userId ].account = account
self.playerList[ userId ].addr = addr
self.playerList[ userId ].status = self.Status_Playing
self.playerList[ userId ].offlineTime = 0
self.playerList[ userId ].pingTime = 0
self.playerList[ userId ].isIntervalSave = false --是否间隔保存
self.playerList[ userId ].lastIntervalSaveTime = skynet.GetTime() --上一次间隔保存
self.playerList[ userId ].onlineMailList = {} --在线发送的邮件列表
self.playerList[ userId ].onlineAnnounceList = {} --在线发送的公告列表
self.playerList[ userId ].player:Init( c2sData )
self.playerList[ userId ].player.tmpData.intoTime = os.time()
if nil == self.playerList[ userId ].lastExtraRevenueTime or 0 == self.playerList[ userId ].lastExtraRevenueTime then
self.playerList[ userId ].lastExtraRevenueTime = skynet.GetTime() --上一次计算额外奖励时间
end
--初始化玩家
self:InitPlayer( self.playerList[ userId ].player , c2sData )
end
--退出平台
function PlayerCenter:UserExit( userId )
local socketId = self.playerList[ userId ].socketId
local account = self.playerList[ userId ].account
if self:CloseSocket( socketId ) then
log.info(string.format("玩家 %d socket %d 帐号 %s 退出游戏" , userId , socketId , account))
else
log.info(string.format("玩家 %d socket %d 帐号 %s 退出游戏 未成功关闭socket" , userId , socketId , account))
end
self.playerList[ userId ].player = nil
self.playerList[ userId ]= nil
skynet.server.playerRecord:Add( userId , dataType.RecordType_3 )
return true
end
--Ping时间
function PlayerCenter:Ping( userId )
self.playerList[ userId ].pingTime = skynet.GetTime()
end
--掉线
function PlayerCenter:UserOffline( userId )
if not self.playerList[ userId ] then
return
end
self.playerList[ userId ].status = self.Status_Offline
self.playerList[ userId ].offlineTime = skynet.GetTime()
skynet.server.playerRecord:Add( userId , dataType.RecordType_2 )
log.info(string.format("玩家 %d 掉线" , userId ))
end
--获取玩家数据
function PlayerCenter:Get( userId )
if not self.playerList[ userId ] then
return nil
end
return self.playerList[ userId ]
end
--获取玩家数据
function PlayerCenter:GetPlayer( userId )
if not self.playerList[ userId ] then
return nil
end
return self.playerList[ userId ].player
end
--获取玩家数据
function PlayerCenter:GetPlayerForAccount( account )
for k, v in pairs( self.playerList ) do
if account == v.account then
return v.player
end
end
return nil
end
--获取玩家数据列表
function PlayerCenter:GetPlayerList()
return self.playerList
end
--获取当前在线玩家数理
function PlayerCenter:GetOnlineCount()
return #self.playerList
end
--更新间隔保存
function PlayerCenter:UpdateIntervalSave( userId )
if not self.playerList[ userId ].isIntervalSave then
self.playerList[ userId ].isIntervalSave = true --是否间隔保存
self.playerList[ userId ].lastIntervalSaveTime = skynet.GetTime() --上一次间隔保存
end
end
--增加登陆历史
function PlayerCenter:AddLoginHistory( player )
local data = player.basicInfo.loginHistory
data.curIndex = data.curIndex + 1
--最多保存30条
if data.curIndex > 30 then
data.curIndex = 1
end
data.history[ data.curIndex ] = { serverId = serverId , time = skynet.server.common:GetStrTime(skynet.GetTime())}
end
--获取玩家登陆数据
function PlayerCenter:GetLoginInfo( playerData )
local userId = tonumber(playerData.basicInfo.userID)
if not self.playerList[ userId ] then
return nil
end
local userData = {}
local playerData = self.playerList[ userId ].player
--用户数据
userData.userId = tonumber(playerData.basicInfo.userID)
userData.account = playerData.basicInfo.accountName
userData.playerData = nil
userData.announce = ""
userData.serverTime = skynet.GetTime()
userData.msgVersion = 2
userData.nickName = playerData.gameData.nickName
local money = {}
table.insert( money , { type = pb.enum("EnumGoodsType","Coin") , count = playerData.gameData.coin })
table.insert( money , { type = pb.enum("EnumGoodsType","Clovers") , count = playerData.gameData.clovers })
table.insert( money , { type = pb.enum("EnumGoodsType","VoluteCoin") , count = playerData.gameData.volute })
userData.money = money
userData.level = playerData.gameData.level
userData.exp = playerData.gameData.exp
--当前房子ID和方案ID
local houseId = playerData.gameData.curHouseID
userData.curHouseID = houseId
userData.curSchemeID = playerData.gameData.house[ houseId ].curSchemeId
--获取方案信息
userData.schemeInfo = {}
for k, v in pairs( playerData.gameData.house[ houseId ].scheme ) do
table.insert( userData.schemeInfo , { id = v.id , name = v.name , status = v.status })
end
--当前房子和当前方案下的家具信息
userData.furnitureInfo = skynet.server.house:GetCurSchemeFurniture( playerData , houseId , userData.curSchemeID )
userData.decorateInfo = skynet.server.house:GetCurSchemeDecorate( playerData , houseId , userData.curSchemeID )
--当前已经解锁的区域ID
userData.areaId = {}
for areaId, v in pairs( playerData.gameData.house[ houseId ].unlockAreaList ) do
if true == v then
table.insert( userData.areaId , areaId )
end
end
--提示信息
userData.tipsInfo = skynet.server.msgTips:GetAllTips( playerData )
userData.finishGuide = playerData.gameData.finishGuide --完成的引导记录
--将未解锁的宠物发给玩家
userData.lockPetId = {}
for k, v in pairs( playerData.gameData.pet ) do
if dataType.PetStatus_Lock == v.status then
table.insert( userData.lockPetId , v.skinId )
end
end
--获取拥有的房子数量
userData.houseCount = skynet.server.house:GetHouseCount( playerData )
userData.isVip = {}
if userData.passCheck then
table.insert(userData.isVip ,userData.passCheck.isVip )
else
table.insert(userData.isVip , false)
end
userData.goodsStat = {}
local goodsType = dataType.GoodsType_Furniture
table.insert( userData.goodsStat , { goodsType = goodsType , goodsCount = skynet.server.bag:GetGoodsStat( playerData , goodsType )})
userData.allGameTime = playerData.basicInfo.allGameTime
--是否给玩家显示新人签到
userData.canShowPlayerLand = playerData.gameData.playerLand.isShow
return userData
end
--赠送默认家具到房间
function PlayerCenter:InitPlayerData( player , goodsType )
local goodsType = dataType.GoodsType_Furniture
local cfgSValue = skynet.server.gameConfig.SValue
player.gameData.coin = cfgSValue.initCoin
--player.gameData.clovers = cfgSValue.initVoluteCoin
--player.gameData.coin = 10000
--player.gameData.clovers = 10000
player.gameData.volute = cfgSValue.initVoluteCoin
player.gameData.level = 1
player.gameData.exp = 0
player.gameData.bag = {}
player.gameData.bagCount = {}
player.gameData.used.logisticsInfo = {}
--存在装修商店数据就处理一下
local shopType = dataType.ShopType_Decorate
if player.gameData.shop[ shopType ] then
player.gameData.shop[ shopType ].door = {}
player.gameData.shop[ shopType ].nextRefreshTime = 0
player.gameData.shop[ shopType ].firstRefresh = true
skynet.server.decorateShop:RefreshShop( player , shopType )
end
--赠送一个免费的物流
table.insert( player.gameData.used.logisticsInfo , { goodsId = 53 , npcNameId = 2 , copyId = 2 , goodsStatus = skynet.server.used.GoodsStatus_AlreadyReach , reachTime = 0 , deliverTime = 0 } )
--赠送家具到背包
skynet.server.bag:AddGoods( player , goodsType , 1 , 1)
skynet.server.bag:AddGoods( player , goodsType , 10 , 1)
--赠送家具到背包 需要摆放到房间的
skynet.server.bag:AddGoods( player , goodsType , 197 , 1)
skynet.server.bag:AddGoods( player , goodsType , 200 , 1)
skynet.server.bag:AddGoods( player , goodsType , 511 , 1)
skynet.server.bag:AddGoods( player , goodsType , 510 , 1)
skynet.server.bag:AddGoods( player , goodsType , 202 , 1)
skynet.server.bag:AddGoods( player , goodsType , 199 , 1)
skynet.server.bag:AddGoods( player , goodsType , 199 , 1)
--赠送默认衣服
local cfgDefalutClothes = skynet.server.gameConfig.SValue.DefalutClothes
for k, v in pairs( cfgDefalutClothes ) do
skynet.server.bag:AddGoods( player , dataType.GoodsType_Clothes , v , 1)
end
--赠送房间
local houseId = 4
player.gameData.curHouseID = houseId
skynet.server.house:Add( player , houseId, {})
--获取当前房间当前方案
local schemeInfo = skynet.server.house:GetCurScheme( player )
schemeInfo.furniture = {}
schemeInfo.decorate = skynet.server.house:InitDecorate( player , houseId )
--在室内摆放家具
skynet.server.house:AddFurniture( player , { type = goodsType , id = 197 , nowPos ={ x= -4.348 , y= 4.89} , rotateType = 0 } , 1 )
skynet.server.house:AddFurniture( player , { type = goodsType , id = 200 , nowPos ={ x= -7.698 , y= 7.29} , rotateType = 0 } , 1 )
skynet.server.house:AddFurniture( player , { type = goodsType , id = 511 , nowPos ={ x= -10.378 , y= 7.29} , rotateType = 1 } , 1 )
skynet.server.house:AddFurniture( player , { type = goodsType , id = 510 , nowPos ={ x= -4.013 , y= 8.690001} , rotateType = 0 } , 1 )
skynet.server.house:AddFurniture( player , { type = goodsType , id = 202 , nowPos ={ x= 0.006999969 , y= 8.29} , rotateType = 1 } , 1 )
skynet.server.house:AddFurniture( player , { type = goodsType , id = 199 , nowPos ={ x= -9.222 , y= 13.58} , rotateType = 0 } , 1 )
skynet.server.house:AddFurniture( player , { type = goodsType , id = 199 , nowPos ={ x= 1.49 , y= 11.407} , rotateType = 0 } , 1 )
--个人和宠物的装扮
skynet.server.personal:InitData( player )
skynet.server.levelTask:CheckNew( player )
player.gameData.design.basicFreeTime = skynet.GetTime()
player.gameData.design.advancedFreeTime = skynet.GetTime()
end
skynet.server.playerCenter = PlayerCenter
return PlayerCenter