HomeServer/lualib-src/Server-main/Common/Player/PlayerCenter.lua

511 lines
18 KiB
Lua
Raw Normal View History

2024-11-20 15:41:09 +08:00
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