HomeServer/Server/AllServer/GameServer/Group/Group.lua
2024-11-20 15:41:37 +08:00

540 lines
20 KiB
Lua
Raw Permalink 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 oo = require "Class"
local pb = require "pb"
local log = require "Log"
local json =require "json"
local errorInfo = require "ErrorInfo"
local dataType = require "DataType"
local redisKeyUrl = require "RedisKeyUrl"
local curServerId = tonumber(skynet.getenv "serverId")
local Group = oo.class()
Group.MaxQueryCount = 4 --最大查询数量
Group.MaxMapCount = 12 --最大地图数量
Group.RankStatus_Acc = 1 --累加状态
Group.RankStatus_Calc = 2 --结算状态
Group.PutType_House = 1 --放房间
Group.PutType_Bag = 2 --放背包
Group.PutType_Move = 3 --移动
Group.PutType_Operate = 4 --原地操作
Group.ArchType_House = 1 --房子
Group.ArchType_Garden = 2 --花园景观
Group.MaxMsgRecordToClient = 50 --发送给客户端最大的消息记录数量
Group.IdentityType_Leader = 1 --园长
Group.IdentityType_ViceLeader = 2 --副园长
Group.IdentityType_Member = 3 --成员
Group.ArchType_Park = 1 --公园
Group.ArchType_Market = 2 --集市
Group.ArchType_Library = 3 --图书馆
Group.ArchType_Dessert = 4 --甜品店
Group.ArchType_Road = 5 --路面
Group.ContributeType_Wood = 1 --木材
Group.ContributeType_Cement = 2 --水泥
Group.ContributeType_Rebar = 3 --钢筋
Group.GroupOpType_Create = 1 --创建
Group.GroupOpType_Update = 2 --更新
Group.GroupOpType_Dissolve = 3 --解散
Group.onlineGroupList = {}
--初始建筑
Group.InitArchs =
{
{ id = 62 , nowPos = { x = 0, y = 0 } , rotateType = 0 , isPutInFurniture = false , clickType = 1 },
{ id = 56 , nowPos = { x = -5.705, y = -3.18999958 } , rotateType = 0 , isPutInFurniture = false , clickType = 1 },
{ id = 57 , nowPos = { x = -3.36000013, y = -1.38999963 } , rotateType = 0 , isPutInFurniture = false , clickType = 1 }
}
--初始化地块
function Group:InitScenePlot( player , groupId , plotId , partnerId )
local myPartnerId = player.gameData.partner.id
local redisKey = string.format( redisKeyUrl.GameServerGroupPrivatePlot, groupId )
local plotInfo =
{
plotId = plotId ,
partnerId = partnerId ,
archs = skynet.server.common:DeepCopy( self.InitArchs )
}
--如果已经初始化了庭院,就用初始化后的庭院数据,只有自己才会同步 有可能是群主审核通过player是群主的后面考虑优化
local curHouse = player.gameData.house[ 11 ]
if myPartnerId == partnerId and curHouse and #curHouse.groupGarden.archs > 0 then
plotInfo.archs = curHouse.groupGarden.archs
end
skynet.server.redis:lset( redisKey , plotId - 1 , json:encode( plotInfo ))
end
--重置土地
function Group:ResetScenePlot( groupId , plotId )
local redisKey = string.format( redisKeyUrl.GameServerGroupPrivatePlot, groupId )
local plotInfo = {}
plotInfo.plotId = plotId
plotInfo.partnerId = ""
plotInfo.archs = {}
skynet.server.redis:lset( redisKey , plotId - 1 , json:encode(plotInfo))
end
--是否存在家园
function Group:IsExistGroup( groupId )
local redisKey = string.format( redisKeyUrl.GameServerGroupInfoHash , groupId )
if not skynet.server.redis:exists( redisKey) then
return false
end
return true
end
--是否为园长
function Group:IsLeader( myPartnerId )
local curDetail = skynet.server.personal:GetDetail( myPartnerId )
if self.IdentityType_Leader == curDetail.groupIdentityType then
return true
else
return false
end
end
--是否为管理员
function Group:IsManage( myPartnerId )
local curDetail = skynet.server.personal:GetDetail( myPartnerId )
if self.IdentityType_Leader == curDetail.groupIdentityType or self.IdentityType_ViceLeader == curDetail.groupIdentityType then
return true
else
return false
end
end
--获取家园ID
function Group:GetGroupID( player )
local myPartnerId = player.gameData.partner.id
local curDetail = skynet.server.personal:GetDetail( myPartnerId )
if not curDetail then
return ""
end
return curDetail.groupId or ""
end
--获取家园
function Group:GetGroup( groupId )
local redisKey = string.format( redisKeyUrl.GameServerGroupInfoHash , groupId )
if not skynet.server.redis:exists( redisKey) then
return nil
end
local basicInfo = skynet.server.redis:hgetall(redisKey)
basicInfo = redisKeyUrl:CovertTable(basicInfo)
return basicInfo
end
--获取当前家园所有信息
function Group:GetGroupAllInfo( player )
local curPartner = player.gameData.partner
local partnerId = curPartner.id
local curDetail = skynet.server.personal:GetDetail( partnerId )
local groupId = curDetail.groupId
local groupInfo = {}
local curGroupInfo = self:GetGroup( groupId )
if curGroupInfo then
groupInfo = {}
groupInfo.id = curGroupInfo.id
groupInfo.name = curGroupInfo.name
groupInfo.level = curGroupInfo.communityLevel
groupInfo.exp = curGroupInfo.communityExp
groupInfo.declaration = curGroupInfo.declaration
groupInfo.badgeId = curGroupInfo.badgeId
groupInfo.myTotalScore = curDetail.groupContributeScore
groupInfo.signInType = curDetail.groupSignInType
groupInfo.joinType = curGroupInfo.joinType
groupInfo.minJoinLevel = curGroupInfo.minJoinLevel
groupInfo.member = self:GetMember( groupId , partnerId )
end
return groupInfo
end
--设置家园信息
function Group:SetGroupInfo( groupId , ... )
local redisKey = string.format( redisKeyUrl.GameServerGroupInfoHash , groupId )
skynet.server.redis:hmset( redisKey , ... )
end
--获取家园信息
function Group:GetGroupInfo( groupId , ... )
local redisKey = string.format( redisKeyUrl.GameServerGroupInfoHash , groupId )
return skynet.server.redis:hmget( redisKey , ... )
end
--累加家园信息数量
function Group:AccGroupInfo( groupId , param , count )
local redisKey = string.format( redisKeyUrl.GameServerGroupInfoHash , groupId )
skynet.server.redis:hincrby( redisKey , param , count )
end
function Group:GetMember( groupId , myPartnerId )
local member = {}
--获取所有的分数排行
local redisKey = string.format( redisKeyUrl.GameServerGroupContributionScoreZSet, groupId )
local memeberScore = skynet.server.redis:zrange( redisKey , 0 , -1 , "withscores")
memeberScore = redisKeyUrl:CovertTable(memeberScore)
--获取我的好友列表
local redisKey = string.format( redisKeyUrl.GameServerPartnerMyFriendZSet , myPartnerId )
local friendList = skynet.server.redis:zrange( redisKey , 0 , -1 )
--是否为好友
local function IsFriend( otherPartnerId )
for k, v in pairs( friendList ) do
if otherPartnerId == v then
return true
end
end
return false
end
for partnerId, v in pairs( memeberScore ) do
--获取个人信息
local detail = skynet.server.personal:GetDetail( partnerId )
local medals = {}
table.insert( medals , detail.medals1)
table.insert( medals , detail.medals2)
table.insert( medals , detail.medals3)
--衣服数据
local clothesData = {}
table.insert( clothesData , detail.clothesData1 or 2 )
table.insert( clothesData , detail.clothesData2 or 3 )
table.insert( clothesData , detail.clothesData3 or 10 )
table.insert( clothesData , detail.clothesData4 or 14 )
table.insert( clothesData , detail.clothesData5 or 17 )
table.insert( clothesData , detail.clothesData6 or 16 )
table.insert( clothesData , detail.clothesData7 or 0 )
table.insert( clothesData , detail.clothesData8 or 0 )
table.insert( clothesData , detail.clothesData9 or 0 )
table.insert( clothesData , detail.clothesData10 or 0 )
--肤色
local colorData = {}
table.insert( colorData , detail.colorData1 or 1 )
table.insert( colorData , detail.colorData2 or 6 )
table.insert( colorData , detail.colorData3 or 26 )
--自定义头像处理
if detail.birthdayShow==false then
detail.birthdayDate=""
end
if detail.headId ==0 and detail.DIYHeadInfo ~=nil then
table.insert( member , {
partnerId = detail.partnerId ,
nickName = detail.nickName ,
level = detail.level ,
headId = detail.headId ,
headFrameId = detail.headFrameId ,
identityType = detail.groupIdentityType ,
contributionScore = v ,
joinTime = detail.groupJoinTime ,
isFriend = IsFriend( partnerId ) ,
title1 = detail.title1,
title2 = detail.title2,
medals = medals ,
clothesData = clothesData ,
colorData = colorData,
DIYHeadInfo = detail.DIYHeadInfo,
birthdayDate=detail.birthdayDate
})
else
table.insert( member , {
partnerId = detail.partnerId ,
nickName = detail.nickName ,
level = detail.level ,
headId = detail.headId ,
headFrameId = detail.headFrameId ,
identityType = detail.groupIdentityType ,
contributionScore = v ,
joinTime = detail.groupJoinTime ,
isFriend = IsFriend( partnerId ) ,
title1 = detail.title1,
title2 = detail.title2,
medals = medals ,
clothesData = clothesData ,
colorData = colorData,
birthdayDate=detail.birthdayDate
})
end
end
return member
end
--计算排行榜状态和时间
function Group:CalcRankStatusAndTime()
local curDay = skynet.server.common:GetDayInWeek()
local curTime = skynet.server.common:GetTableTime()
if 7 == curDay and curTime.hour >= 20 then --周天晚上8点进行结算
local nexRankStatusTime = skynet.server.common:GetAfterSomeDayTime(1)
return self.RankStatus_Calc,nexRankStatusTime
else
local nexRankStatusTime = skynet.server.common:GetAfterSomeDayTime( 7 - curDay , 20 )
return self.RankStatus_Acc,nexRankStatusTime
end
end
--计算福利结算时间
function Group:CalcContributeRewardTime()
local curDay = skynet.server.common:GetDayInWeek()
local curTime = skynet.server.common:GetTableTime()
if 7 == curDay and curTime.hour >= 12 then --周天中午12点进行结算
return skynet.server.common:GetAfterSomeDayTime( 7 , 12 )
else
return skynet.server.common:GetAfterSomeDayTime( 7 - curDay , 12 )
end
end
--是否有效地块
function Group:IsVaildMapId( mapId )
if mapId < 1 or mapId > self.MaxMapCount then
return false
else
return true
end
end
--家园合法参数检测
function Group:IsVaildParam( key , value )
if nil == key or nil == value then
return false
end
if "groupId" == key and 10 == #value then
return true
elseif "partnerId" == key and 12 == #value then
return true
elseif "groupName" == key and #value >= 1 and #value <= 30 then
return true
elseif "declaration" == key and #value <= 150 then
return true
elseif "badgeId" == key then --and tonumber(value) > 0 and tonumber(value) < 10 then
return true
elseif "joinType" == key and tonumber(value) >= self.JoinType_Freedom and tonumber(value) <= self.JoinType_Audit then
return true
elseif "minJoinLevel" == key and tonumber(value) > 0 and tonumber(value) < 100 then
return true
elseif "identityType" == key and tonumber(value) >= self.IdentityType_Leader and tonumber(value) <= self.IdentityType_Member then
return true
elseif "plotId" == key and tonumber(value) > 0 and tonumber(value) <= self.MaxMapCount then
return true
elseif "msgText" == key and #value >= 1 and #value < 90 then
return true
elseif "archType" == key and value >= self.ArchType_Park and value <= self.ArchType_Road then
return true
elseif "contributeType" == key and value >= self.ContributeType_Wood and value <= self.ContributeType_Rebar then
return true
end
log.warning("错误参数 ",key,value)
return false
end
--获取消息ID
function Group:GetLastMsgID( groupId )
local redisKey = string.format( redisKeyUrl.GameServerGroupMsgID , groupId )
local msgId = skynet.server.redis:incr( redisKey )
return msgId,redisKey
end
--将群信息同步到其它游戏服
function Group:SyncOnlineGroupInfo( groupId , groupOpType , isSync )
if self.GroupOpType_Create == groupOpType then
--同步本地
local curInfo = self:GetGroup( groupId )
if curInfo then
table.insert( self.onlineGroupList , curInfo)
end
elseif self.GroupOpType_Update == groupOpType then
for k, v in pairs( self.onlineGroupList ) do
if groupId == v.id then
local curInfo = self:GetGroup( groupId )
if curInfo then
self.onlineGroupList[ k ] = curInfo
end
break
end
end
elseif self.GroupOpType_Dissolve == groupOpType then
--同步本地
for k, v in pairs( self.onlineGroupList ) do
if groupId == v.id then
self.onlineGroupList[ k ] = nil
break
end
end
end
if isSync then
--同步其它服
local c2sData = {}
c2sData.groupOpType = groupOpType
c2sData.groupId = groupId
local minGameId = skynet.server.clusterServer.gameServerMinID
local maxGameId = skynet.server.clusterServer.gameServerMaxID
local serverCmd = skynet.server.gameServer.GameToGame_SyncOnlineGroup
for k, v in pairs( skynet.server.gameServer.clusterInfo ) do
if curServerId ~= v.serverId and v.serverId >= minGameId and v.serverId <= maxGameId and skynet.server.clusterServer.Status_Running == v.status then
skynet.server.gameServer:SendMsgToServer( v.serverId , serverCmd, c2sData )
end
end
end
end
--是否为房屋ID
function Group:IsHouseID( player , houseId )
local cfgCurGarden = skynet.server.gameConfig:GetPlayerCurCfg( player, "Garden" , houseId )
if cfgCurGarden and 4 == cfgCurGarden.gardenType then
return true
end
return false
end
--排行榜排序
function Group:SortRank( rankList )
local sortRank = {}
for k, v in pairs( rankList ) do
table.insert( sortRank , { partnerId = k , score = v })
end
table.sort( sortRank , function (a , b)
return a.score > b.score
end)
return sortRank
end
--同步家园庭院数据
function Group:SyncGarden( player , groupId , plotId, allArchs )
if self:IsVaildParam( "groupId" , groupId ) then
local redisKey = string.format( redisKeyUrl.GameServerGroupPrivatePlot, groupId )
local plotInfo = skynet.server.redis:lindex( redisKey , plotId - 1 ) --获取家园信息
plotInfo = json:decode(plotInfo)
plotInfo.archs = allArchs
skynet.server.redis:lset( redisKey , plotId - 1 , json:encode(plotInfo))
end
end
--记录单个向往一日家园任务数据
function Group:SaveDreamLifeTask( player , taskId , finishTime )
local groupId = self:GetGroupID( player )
local redisKey = string.format( redisKeyUrl.GameServerGroupDreamLifeTaskList , groupId)
--确保有家园 再保存任务数据
if self:GetGroup( groupId ) then
local taskInfo = {}
taskInfo.taskId = taskId
taskInfo.partnerId = player.gameData.partner.id
taskInfo.finishTime = finishTime
taskInfo.isCheck = 0 --该状态记录是否被检查过 0 否 1 是
skynet.server.redis:lpush( redisKey , json:encode(taskInfo) )
local redisKey1 = string.format( redisKeyUrl.GameServerGroupInfoHash , groupId )
skynet.server.redis:hmset(redisKey1 , "dailyTaskTime" , skynet.GetTime() ) --dailyTaskTime 日常任务记录时间 ,后面可能有周任务记录时间
end
end
--检查家园中是否有完成的向往一日家园任务
function Group:CheckDreamLifeTask( player )
local groupId = self:GetGroupID( player )
local redisKey = string.format( redisKeyUrl.GameServerGroupDreamLifeTaskList , groupId)
--确保有家园和对应任务数据
if self:GetGroup( groupId ) and skynet.server.redis:exists(redisKey) then
local allTaskInfo = skynet.server.redis:lrange(redisKey , 0 , -1)
for k , v in pairs(allTaskInfo) do
local taskInfo = json:decode( v )
--检查任务是否已经完成
if skynet.GetTime() >= taskInfo.finishTime and taskInfo.isCheck == 0 then
--修改对应任务数据
self:UpdateDreamLifeTask(player , dataType.GroupTaskType_DreamLife , taskInfo.taskId)
taskInfo.isCheck = 1
skynet.server.redis:lset(redisKey , k-1 , json:encode(taskInfo))
end
end
end
end
--获取玩家对应任务是否完成
function Group:GetDreamLifeTaskState(player , taskId)
local partnerId = player.gameData.partner.id
local groupId = self:GetGroupID( player )
local redisKey = string.format( redisKeyUrl.GameServerGroupDreamLifeTaskList , groupId)
--确保有家园和对应任务数据
if self:GetGroup( groupId ) and skynet.server.redis:exists(redisKey) then
local allTaskInfo = skynet.server.redis:lrange(redisKey , 0 , -1)
for k , v in pairs(allTaskInfo) do
local taskInfo = json:decode( v )
if taskInfo.partnerId == partnerId and taskInfo.taskId == taskId then
if taskInfo.isCheck == 1 then
return true
else
return false
end
end
end
end
return false
end
--更新任务
function Group:UpdateDreamLifeTask( player , taskType , taskId )
local groupId = self:GetGroupID( player )
local redisKey = string.format( redisKeyUrl.GameServerGroupInfoHash , groupId )
--拼接对应的key 例如 DreamLifeTask_5
local stringKey = taskType .. "_" .. taskId
skynet.server.redis:hincrby( redisKey , stringKey , 1)
end
--获取任务次数
function Group:GetTaskCount( player , taskType , taskId )
local t = skynet.GetTime()
local groupId = self:GetGroupID( player )
local curGroup = self:GetGroup( groupId )
if not curGroup then
log.warning("家园 获取任务次数 未找到家园信息 ", player.gameData.partner.id ,groupId )
return 0
end
local redisKey = string.format( redisKeyUrl.GameServerGroupInfoHash , groupId )
local stringKey = taskType .. "_" .. taskId
local dailyTaskTime = curGroup.dailyTaskTime
if dailyTaskTime and not skynet.server.common:IsSameDay( t , dailyTaskTime ) then
--新的一天,初始化日常任务的数据
skynet.server.redis:hmset(redisKey , "dailyTaskTime" , t )
if taskType == dataType.GroupTaskType_DreamLife then
local cfgDreamLifeTask = skynet.server.gameConfig:GetPlayerAllCfg(player , taskType)
for k , v in pairs(cfgDreamLifeTask) do
if v.taskType == 2 then
local key = taskType .. "_" .. v.id
skynet.server.redis:hmset(redisKey , key , 0 )
end
end
end
--移除前一天的任务数据
local redisKey1 = string.format( redisKeyUrl.GameServerGroupDreamLifeTaskList , groupId)
skynet.server.redis:del(redisKey1)
curGroup[stringKey] = 0
end
return curGroup[stringKey] or 0
end
--清理所有的提示信息
function Group:ResetAllMsgTips( partnerId )
skynet.server.partner:SendMsgTips( partnerId , 38 , false )
skynet.server.partner:SendMsgTips( partnerId , 39 , false )
skynet.server.partner:SendMsgTips( partnerId , 60 , false )
skynet.server.partner:SendMsgTips( partnerId , 65 , false )
skynet.server.partner:SendMsgTips( partnerId , 66 , false )
end
skynet.server.group = Group
return Group