package model import ( "encoding/base64" "errors" "math/rand" "rocommon" "rocommon/service" "rocommon/util" model2 "roserver/baseserver/model" model3 "roserver/db/model" "roserver/serverproto" "sort" "strconv" ) const ( MAX_APPLY_COUNT = 10 WRITE_DB_MAX_COUTN = 100 //每次写入100个变化的公会 MAX_RECOMMEND_GUILD = 100 // ) const ( Recruit_None = iota Recruit_Refused = 1 //拒绝加入 Recruit_Verify = 2 //需要审核 Recruit_None_Verify = 3 //随意加入 ) const ( Guild_Title_Member = 0 //成员 Guild_Title_Vice_Pre = 1 //副会长 Guild_Title_Pre = 2 //会长 ) const ( Guild_Apply_None = 0 Guild_Apply_All_Accept = 1 //全部通过 Guild_Apply_All_Refused = 2 //全部拒绝 ) const ( Guild_Apply_Accept = 1 //同意入会 Guild_Apply_Refused = 2 //拒绝入会 Guild_Apply_Ignore = 3 //无处理 ) const MaxRecommend = 30 const MaxMsgRec = 20 const ( Guild_Event_Type_JoinGuild = 1 //玩家加入公会 Guild_Event_Type_KickGuild = 2 //玩家被踢出工会 Guild_Event_Type_LeaveGuild = 3 //玩家离开公会 Guild_Event_Type_VicePresident = 4 //提升为副会长 Guild_Event_Type_Member = 5 //降职为会员 Guild_Event_Type_ChangePresident = 6 //转让会长 Guild_Event_Type_DirectJoin = 7 //直接加入 Guild_Event_Type_GuildEliteBoss = 8 //精英boss开启 Guild_Event_Type_ChangeGuildPre = 9 //自动转让公会会长 ) const ( Guild_SysChat_Event_Online = 1 //公会管理员上线 Guild_SysChat_Event_PlayerJoin = 2 //会员上线 Guild_SysChat_Event_SummonBoss = 3 //召唤boss ) //公会boss const ( Guild_Boss_Type_Normal = 1 //普通公会boss Guild_Boss_Type_Elite = 2 //召唤公会boss ) //公会boss状态 const ( Guild_Boss_State_Wait_Summon = 1 //待召唤 Guild_Boss_State_Fight = 2 //战斗状态 Guild_Boss_State_Fight_Finish = 3 //结算状态 ) type RecommendInfo struct { GuildId uint32 Level int32 Active uint32 ActiveTime int64 } //公会做一个超时从内存移除机制//目前设定超时6小时,从内存移除 type GuildData struct { GuildBase *serverproto.GuildBase //公会基础信息 GuildMember *serverproto.MemberData //公会成员信息 ApplyList *serverproto.GuildApplayData //申请列表 GuildLogs *serverproto.GuildLogSet //公会日志 GuildMsg []*serverproto.MessageContentInfo //公会聊天记录 GuildSys *serverproto.SystemMessage //公会boos通知 GuildBoss map[uint32]*serverproto.GuildBossInfo //公会boss GuildDemon *serverproto.GuildDemon //公会魔王 LogLoad bool ApplyListTime int64 //上次拉去公会申请列表时间 CheckMemberGuild bool } type GuildManager struct { Guilds map[uint64]*GuildData //按照工会ID索引 //需要定义一个列表大小 GuildsIndex map[string]*serverproto.GuildIdex //按照工会名字索引 key:名字, value:公会ID RoleToGuilds map[uint64]*serverproto.GuildIdex //玩家公会映射 // CurGuildID uint64 //当前用到的ID ApplyData map[uint64]*serverproto.RoleApplayData //公会申请列表 // ChangeList map[uint32]int32 //有变化的公会Key:公会ID, value,变化类型: //公会推荐列表 RecommendGuildIndex map[uint64]int32 //推荐的公会索引 RecommendGuild []*serverproto.RecommendGuild //推荐公会//定时更新,只推荐人未满员,申请列表为满员的活跃公会。从Guilds中查找 GuildManagerInit bool BossTickTime int64 DemonTickTime uint64 } func newGuildManager() *GuildManager { guildMag := &GuildManager{} guildMag.Guilds = map[uint64]*GuildData{} guildMag.GuildsIndex = map[string]*serverproto.GuildIdex{} guildMag.RoleToGuilds = map[uint64]*serverproto.GuildIdex{} guildMag.ApplyData = map[uint64]*serverproto.RoleApplayData{} guildMag.GuildManagerInit = false guildMag.RecommendGuildIndex = make(map[uint64]int32) return guildMag } //TODO wangzhaocan 后期优化//定时更新推荐列表 func (this *GuildManager) Update(ms uint64) { if service.GetRedis() == nil { return } if this.GuildManagerInit == false { err := this.LoadRecommendGuild() if err != nil { } err = this.LoadGuildDataFromRedis() if err != nil { } err = this.LoadGuildNameIndex() if err != nil { } err = this.LoadRoleToGuildFromRedis() if err != nil { } this.GuildManagerInit = true } this.GuildBossReset(Guild_Boss_Type_Normal) this.GuildBossReset(Guild_Boss_Type_Elite) this.RefreshGuildDemonAll(ms) } //初始其服务器只加载推荐的公会。 func (this *GuildManager) LoadGuildDataFromRedis() error { if service.GetRedis() == nil { return errors.New("redis not ok") } if len(this.RecommendGuild) <= 0 { util.InfoF("[LoadGuildDataFromRedis] RecommendGuild empty") return nil } for _, data := range this.RecommendGuild { fieldStr := strconv.FormatUint(uint64(data.GuildId), 10) this.Guilds[data.GuildId] = &GuildData{ GuildBase: &serverproto.GuildBase{}, GuildMember: &serverproto.MemberData{}, ApplyList: &serverproto.GuildApplayData{}, GuildDemon: &serverproto.GuildDemon{}, } //加载公会基础信息 baseStr := model2.GuildBasePrefix guildBaseStr, baseErr := service.GetRedis().HGet(baseStr, fieldStr).Result() if baseErr == nil { guildBase := &serverproto.GuildBase{} err := model2.GetDecodeMessage(guildBase, guildBaseStr) if err == nil { this.Guilds[data.GuildId].GuildBase = guildBase } else { util.InfoF("[LoadGuildDataFromRedis] get guildBaseStr [%v] err:%v", guildBaseStr, err) return nil } } //加载公会成员信息 memberStr := model2.GuildMemberPrefix guildMemberStr, memberErr := service.GetRedis().HGet(memberStr, fieldStr).Result() if memberErr == nil { guildMember := &serverproto.MemberData{} err := model2.GetDecodeMessage(guildMember, guildMemberStr) if err == nil { this.Guilds[data.GuildId].GuildMember = guildMember } else { util.InfoF("[LoadGuildDataFromRedis] get guildMemberStr [%v] err:%v", guildMemberStr, err) return nil } /* if len(guildMember.MemberInfo) > 1 { this.CheckMemberGuild(this.Guilds[data.GuildId]) } */ } //加载公会申请数据 applyStr := model2.GuildApplyPrefix guildApplyStr, guildErr := service.GetRedis().HGet(applyStr, fieldStr).Result() if guildErr == nil { guildApply := &serverproto.GuildApplayData{} err := model2.GetDecodeMessage(guildApply, guildApplyStr) if err == nil { this.Guilds[data.GuildId].ApplyList = guildApply } else { util.InfoF("[LoadGuildDataFromRedis] get guildApplyStr [%v] err:%v", guildApplyStr, err) return nil } } err := this.LoadGuildDemon(this.Guilds[data.GuildId]) if err == nil { } } return nil } //服务器启动从DB加载进来 /* func (this *GuildManager)LoadGuildDataToRedis() error { if service.GetRedis() == nil { return errors.New("redis not ok") } keyStr := model2.GuildBasePrefix valueStr, err := service.GetRedis().HGetAll(keyStr).Result() if err != nil { util.InfoF("[LoadGuildDataToRedis] get GuildBasePrefix [%v] err:%v", keyStr, err) return err } for index, guildData := range valueStr { val, _ := model2.Str2Num(index) msgStr, err := base64.StdEncoding.DecodeString(guildData) if err != nil { util.InfoF("[LoadGuildDataToRedis] get GuildBasePrefix [%v] err:%v", index, err) continue } guildData := &serverproto.GuildBase{} err = rocommon.GetCodec().Unmarshal(msgStr, guildData) if err == nil { //做个优化。如果是3天之内有活跃度变化的加载进来,否则延迟加载 // guildId := guildData.GuildBrief.GuildId this.Guilds[uint32(val)] = &GuildData{ GuildBase: guildData, GuildMember: &serverproto.MemberData{}, ApplyList: &serverproto.GuildApplayData{}, } util.InfoF("[LoadGuildDataToRedis] get GuildBasePrefix :%v", this.Guilds[uint32(val)].ApplyList) } else { return err } } keyStr1 := model2.GuildMemberPrefix valueStr1, err1 := service.GetRedis().HGetAll(keyStr1).Result() if err1 != nil { util.InfoF("[LoadGuildDataToRedis] get GuildMemberPrefix [%v] err:%v", keyStr1, err) return err } for guildId, guildMember := range valueStr1 { val, _ := model2.Str2Num(guildId) msgStr, err := base64.StdEncoding.DecodeString(guildMember) if err != nil { util.InfoF("[LoadGuildDataToRedis] get GuildMemberPrefix [%v] err:%v", guildId, err) continue } memberData := &serverproto.MemberData{} err = rocommon.GetCodec().Unmarshal(msgStr, memberData) if err == nil { //做个优化。如果是3天之内有活跃度变化的加载进来,否则延迟加载 guildData := this.Guilds[uint32(val)] if guildData != nil { guildData.GuildMember = memberData } } else { return err } } //加载公会申请数据 keyStr2 := model2.GuildApplyPrefix valueStr2, err2 := service.GetRedis().HGetAll(keyStr2).Result() if err2 != nil { util.InfoF("[LoadGuildDataToRedis] get GuildApplyPrefix [%v] err:%v", keyStr2, err) return err } for guildId, guildApply := range valueStr2 { val, _ := model2.Str2Num(guildId) msgStr, err := base64.StdEncoding.DecodeString(guildApply) if err != nil { util.InfoF("[LoadGuildDataToRedis] get GuildApplyPrefix [%v] err:%v", guildId, err) continue } applyData := &serverproto.GuildApplayData{} err = rocommon.GetCodec().Unmarshal(msgStr, applyData) if err == nil { guildData := this.Guilds[uint32(val)] if guildData != nil { guildData.ApplyList = applyData util.InfoF("[LoadGuildDataToRedis] get GuildApplyPrefix err:%v", applyData) } } else { return err } } //加载 util.DebugF("[LoadGuildDataToRedis] get guild :%s", this.Guilds) return nil } */ func (this *GuildManager) RemoveGuildFromRedis(guildId uint64, guildName string) { this.DeleteGuildBaseFromRedis(guildId) this.DeleteGuildMemberFromRedis(guildId) this.DeleteGuildApplyFromRedis(guildId) this.RemoveGuildNameIndex(guildName) } //定时写入DB func (this *GuildManager) SaveGuildBase(guild *GuildData) { if guild == nil { return } fieldStr := strconv.FormatUint(uint64(guild.GuildBase.GuildBrief.GuildId), 10) keyStr := model2.GuildBasePrefix msgData, err := rocommon.GetCodec().Marshal(guild.GuildBase) if err != nil { util.InfoF("[SaveGuildBase] Marshal err:%v %v %s", err, fieldStr, msgData) return } msgStr := base64.StdEncoding.EncodeToString(msgData.([]byte)) ret, err := service.GetRedis().HSet(keyStr, fieldStr, msgStr).Result() if err != nil { util.InfoF("[SaveGuildBase] err:%v %v", err, ret) return } util.InfoF("[SaveGuildBase] save guild_base data success") } //从数据库中删除玩家申请数据 func (this *GuildManager) DeleteGuildBaseFromRedis(guildId uint64) { fieldStr := strconv.FormatUint(uint64(guildId), 10) service.GetRedis().HDel(model2.GuildBasePrefix, fieldStr) } //保存玩家申请的ID func (this *GuildManager) SaveRoleApplyData(uid uint64, applyData *serverproto.RoleApplayData) { if applyData == nil { return } //如果申请列表为空 if len(applyData.ApplyGuild) <= 0 { //从数据库中删除此人申请信息 this.RemoveRoleApplyFromRedis(uid) //从内存中删除申请信息 delete(this.ApplyData, uid) return } //申请列表不为空 fieldStr := strconv.FormatUint(uid, 10) keyStr := model2.RoleApplyPrefix msgData, err := rocommon.GetCodec().Marshal(applyData) if err != nil { util.InfoF("[SaveRoleApplyData] Marshal err:%v %v %s", err, fieldStr, msgData) return } msgStr := base64.StdEncoding.EncodeToString(msgData.([]byte)) ret, err := service.GetRedis().HSet(keyStr, fieldStr, msgStr).Result() if err != nil { util.InfoF("[SaveRoleApplyData] err:%v %v", err, ret) return } util.InfoF("[SaveRoleApplyData] save role_apply data success") } //查找玩家的申请ID func (this *GuildManager) GetRoleApplyInfo(uid uint64) *serverproto.RoleApplayData { applyData, ok := this.ApplyData[uid] if ok { return applyData } fieldStr := strconv.FormatUint(uint64(uid), 10) applyStr, applyErr := service.GetRedis().HGet(model2.RoleApplyPrefix, fieldStr).Result() if applyErr == nil { recordApply := &serverproto.RoleApplayData{} memberErr := model2.GetDecodeMessage(recordApply, applyStr) if memberErr == nil { this.ApplyData[uid] = recordApply return recordApply } else { return nil } } return nil } //从数据库中删除玩家申请数据 func (this *GuildManager) RemoveRoleApplyFromRedis(uid uint64) { fieldStr := strconv.FormatUint(uint64(uid), 10) service.GetRedis().HDel(model2.RoleApplyPrefix, fieldStr) } //公会成员存储 func (this *GuildManager) SaveGuildMember(guildData *GuildData) { if guildData == nil { return } //校验一下 // this.CheckMemberGuild(guildData) fieldStr := strconv.FormatUint(uint64(guildData.GuildBase.GuildBrief.GuildId), 10) keyStr := model2.GuildMemberPrefix msgData, err := rocommon.GetCodec().Marshal(guildData.GuildMember) if err != nil { util.InfoF("[SaveGuildMember] Marshal err:%v %v %s", err, fieldStr, msgData) return } msgStr := base64.StdEncoding.EncodeToString(msgData.([]byte)) ret, err := service.GetRedis().HSet(keyStr, fieldStr, msgStr).Result() if err != nil { util.InfoF("[SaveGuildMember] err:%v %v", err, ret) return } util.InfoF("[SaveGuildMember] save guild_member data success :%v", guildData.GuildMember) } //从数据库中删除玩家申请数据 func (this *GuildManager) DeleteGuildMemberFromRedis(guildId uint64) { fieldStr := strconv.FormatUint(uint64(guildId), 10) service.GetRedis().HDel(model2.GuildMemberPrefix, fieldStr) } func (this *GuildManager) SaveGuildApply(guildData *GuildData) { if guildData == nil { return } fieldStr := strconv.FormatUint(uint64(guildData.GuildBase.GuildBrief.GuildId), 10) keyStr := model2.GuildApplyPrefix msgData, err := rocommon.GetCodec().Marshal(guildData.ApplyList) if err != nil { util.InfoF("[SaveGuildApply] Marshal err:%v %v %s", err, fieldStr, msgData) return } msgStr := base64.StdEncoding.EncodeToString(msgData.([]byte)) ret, err := service.GetRedis().HSet(keyStr, fieldStr, msgStr).Result() if err != nil { util.InfoF("[SaveGuildApply] err:%v %v", err, ret) return } } //从数据库中删除玩家申请数据 func (this *GuildManager) DeleteGuildApplyFromRedis(guildId uint64) { fieldStr := strconv.FormatUint(uint64(guildId), 10) service.GetRedis().HDel(model2.GuildApplyPrefix, fieldStr) } func (this *GuildManager) SaveGuildNameIndex(name string) { guildIndex := this.GuildsIndex[name] if guildIndex.GuildId == 0 { return } fieldStr := name keyStr := model2.GuildNameIndexPrefix msgData, err := rocommon.GetCodec().Marshal(guildIndex) if err != nil { util.InfoF("[SaveGuildNameIndex] Marshal err:%v %v %s", err, fieldStr, msgData) return } msgStr := base64.StdEncoding.EncodeToString(msgData.([]byte)) ret, err := service.GetRedis().HSet(keyStr, fieldStr, msgStr).Result() if err != nil { util.InfoF("[SaveGuildNameIndex] err:%v %v", err, ret) return } } func (this *GuildManager) LoadGuildNameIndex() error { keyStr := model2.GuildNameIndexPrefix valueStr, err := service.GetRedis().HGetAll(keyStr).Result() if err != nil { util.InfoF("[LoadGuildNameIndex] get GuildNameIndexPrefix [%v] err:%v", keyStr, err) return err } for guildName, guildId := range valueStr { msgStr, err := base64.StdEncoding.DecodeString(guildId) if err != nil { util.InfoF("[LoadGuildNameIndex] get guildId [%v] err:%v", guildId, err) continue } guildIndex := &serverproto.GuildIdex{} err = rocommon.GetCodec().Unmarshal(msgStr, guildIndex) if err == nil { this.GuildsIndex[guildName] = guildIndex } else { return err } } return nil } func (this *GuildManager) RemoveGuildNameIndex(name string) { fieldStr := name service.GetRedis().HDel(model2.GuildNameIndexPrefix, fieldStr) delete(this.GuildsIndex, name) } func (this *GuildManager) SaveRoleToGuild(uid uint64) { guildId := this.RoleToGuilds[uid] if guildId != nil { //从redis删除 fieldStr := strconv.FormatUint(uint64(uid), 10) keyStr := model2.GuildRoleToGuildPrefix msgData, err := rocommon.GetCodec().Marshal(guildId) if err != nil { util.InfoF("[SaveRoleToGuild] Marshal err:%v %v %s", err, fieldStr, msgData) return } msgStr := base64.StdEncoding.EncodeToString(msgData.([]byte)) ret, err := service.GetRedis().HSet(keyStr, fieldStr, msgStr).Result() if err != nil { util.InfoF("[SaveRoleToGuild] err:%v %v", err, ret) return } util.InfoF("[SaveRoleToGuild] save success") } } func (this *GuildManager) RemoveRoleToGuild(uid uint64) { guildId := this.RoleToGuilds[uid] if guildId != nil { //从redis删除 fieldStr := strconv.FormatUint(uint64(uid), 10) keyStr := model2.GuildRoleToGuildPrefix service.GetRedis().HDel(keyStr, fieldStr) delete(this.RoleToGuilds, uid) } } func (this *GuildManager) LoadRoleToGuildFromRedis() error { keyStr := model2.GuildRoleToGuildPrefix valueStr, err := service.GetRedis().HGetAll(keyStr).Result() if err != nil { util.InfoF("[LoadRoleToGuildFromRedis] get GuildRoleToGuildPrefix [%v] err:%v", keyStr, err) return err } for uidStr, guildId := range valueStr { val, _ := model2.Str2NumU64(uidStr) msgStr, err := base64.StdEncoding.DecodeString(guildId) if err != nil { util.InfoF("[LoadRoleToGuildFromRedis] get guildId [%v] err:%v", guildId, err) continue } guildIndex := &serverproto.GuildIdex{} err = rocommon.GetCodec().Unmarshal(msgStr, guildIndex) if err == nil { this.RoleToGuilds[val] = guildIndex } else { return err } } util.InfoF("[LoadRoleToGuildFromRedis] load success") return nil } // func (this *GuildManager) RemoveGuildLogFromRedis(guildId uint64, guildLog *serverproto.GuildLog) { value := strconv.FormatUint(uint64(guildId), 10) keyStr := model2.GuildLogPrefix + value fieldStr := strconv.FormatUint(guildLog.EventTime, 10) service.GetRedis().HDel(keyStr, fieldStr) return } func (this *GuildManager) SaveGuildLogToRedis(guildId uint64, guildLog *serverproto.GuildLog) { if guildLog == nil { return } value := strconv.FormatUint(uint64(guildId), 10) keyStr := model2.GuildLogPrefix + value fieldStr := strconv.FormatUint(guildLog.EventTime, 10) msgData, err := rocommon.GetCodec().Marshal(guildLog) if err != nil { util.InfoF("[SetRoleHeroDataToRedis] Marshal err:%v %v", err, fieldStr) return } msgStr := base64.StdEncoding.EncodeToString(msgData.([]byte)) ret, err := service.GetRedis().HSet(keyStr, fieldStr, msgStr).Result() if err != nil { util.InfoF("[SetRoleHeroDataToRedis] err:%v %v", err, ret) return } } //加载1个公会的公会日志 func (this *GuildManager) GetGuildLog(guildId uint64, guild *GuildData) error { if guild == nil || guild.LogLoad == true { return nil } if guild.GuildLogs == nil { guild.GuildLogs = &serverproto.GuildLogSet{} } value := strconv.FormatUint(uint64(guildId), 10) keyStr := model2.GuildLogPrefix + value valueStr, err := service.GetRedis().HGetAll(keyStr).Result() if err != nil { util.InfoF("[GetGuildLog] get GuildLogPrefix [%v] err:%v", keyStr, err) return err } for _, logData := range valueStr { msgStr, err := base64.StdEncoding.DecodeString(logData) if err != nil { util.InfoF("[GetGuildLog] get guildId [%v] err:%v", guildId, err) continue } guildLog := &serverproto.GuildLog{} err = rocommon.GetCodec().Unmarshal(msgStr, guildLog) if err == nil { guild.GuildLogs.GuildLog = append(guild.GuildLogs.GuildLog, guildLog) } else { return err } } if len(guild.GuildLogs.GuildLog) > 1 { //按照时间排序 sort.Slice(guild.GuildLogs.GuildLog, func(i, j int) bool { return guild.GuildLogs.GuildLog[i].EventTime > guild.GuildLogs.GuildLog[j].EventTime }) } return nil } func (this *GuildManager) AddGuildLog(guild *GuildData, opTitle int32, opId uint64, beOpTitle int32, beOpId uint64, eventType int32) { if guild == nil { return } if guild.GuildLogs == nil { guild.GuildLogs = &serverproto.GuildLogSet{} } count := len(guild.GuildLogs.GuildLog) if count >= int(model2.GlobalGuildLogMaxCount) { this.RemoveGuildLogFromRedis(guild.GuildBase.GuildBrief.GuildId, guild.GuildLogs.GuildLog[model2.GlobalGuildLogMaxCount-1]) //从数据库中删除一个元素 newLog := append(guild.GuildLogs.GuildLog[:count-1]) guild.GuildLogs.GuildLog = newLog } var opName string = "" var beOpName string = "" if opId != 0 { opBrief := &serverproto.CommonPlayerBriefInfo{} err := model3.GetSystemDataFromRedis(model3.RolePlayerBriefPrefix, opId, opBrief) if err == nil { opName = opBrief.NickName } } if beOpId != 0 { beOpBrief := &serverproto.CommonPlayerBriefInfo{} err2 := model3.GetSystemDataFromRedis(model3.RolePlayerBriefPrefix, beOpId, beOpBrief) if err2 == nil { beOpName = beOpBrief.NickName } } log := &serverproto.GuildLog{ OpTitle: opTitle, OpName: opName, BeOpTitle: beOpTitle, BeOpName: beOpName, EventTime: uint64(util.GetCurrentTime()), EventType: eventType, } guild.GuildLogs.GuildLog = append([]*serverproto.GuildLog{log}, guild.GuildLogs.GuildLog...) this.SaveGuildLogToRedis(guild.GuildBase.GuildBrief.GuildId, log) } /* func (this *GuildManager) SaveGuildID() { keyStr := model2.GuildCurGuildIdPrefix curGuildId := &serverproto.GuildIdex{ GuildId: this.CurGuildID, } msgData, err := rocommon.GetCodec().Marshal(curGuildId) if err != nil { return } msgStr := base64.StdEncoding.EncodeToString(msgData.([]byte)) ret, err := service.GetRedis().Set(keyStr, msgStr, 0).Result() if err != nil { util.InfoF("SaveGuildID err=%v ret=%v", keyStr, ret) return } util.InfoF("SaveGuildID save guildIdIndex sucess : %v", curGuildId) } func (this *GuildManager) LoadGuildID() { keyStr := model2.GuildCurGuildIdPrefix ret, err := service.GetRedis().Get(keyStr).Result() if err != nil { util.InfoF("LoadGuildID get guildId key=%v err=%v\n", keyStr, err) return } if ret == "" { util.InfoF("key(%v)->val empty", keyStr) return } str, err := base64.StdEncoding.DecodeString(ret) if err != nil { util.InfoF("key(%v)->val DecodeString error", keyStr) return } curGuildId := &serverproto.GuildIdex{} err = rocommon.GetCodec().Unmarshal(str, curGuildId) if err == nil { this.CurGuildID = curGuildId.GuildId util.InfoF("LoadGuildID success:%v", this.CurGuildID) return } util.InfoF("LoadGuildID failed") } */ func (this *GuildManager) SaveGuildBoss(bossId uint32, guild *GuildData) { if guild == nil || guild.GuildBoss == nil { return } bossInfo, ok := guild.GuildBoss[bossId] if !ok { return } value := strconv.FormatUint(uint64(guild.GuildBase.GuildBrief.GuildId), 10) keyStr := model2.GuildBossPrefix + value fieldStr := strconv.FormatUint(uint64(bossId), 10) msgData, err := rocommon.GetCodec().Marshal(bossInfo) if err != nil { util.InfoF("[SaveGuildBoss] Marshal err:%v %v", err, fieldStr) return } msgStr := base64.StdEncoding.EncodeToString(msgData.([]byte)) ret, err := service.GetRedis().HSet(keyStr, fieldStr, msgStr).Result() if err != nil { util.InfoF("[SaveGuildBoss] err:%v %v", err, ret) return } } func (this *GuildManager) RemoveGuildBoss(bossId uint32, guild *GuildData) { if guild == nil || guild.GuildBoss == nil || len(guild.GuildBoss) <= 0 { return } fieldStr := strconv.FormatUint(uint64(bossId), 10) value := strconv.FormatUint(uint64(guild.GuildBase.GuildBrief.GuildId), 10) keyStr := model2.GuildBossPrefix + value service.GetRedis().HDel(keyStr, fieldStr) delete(guild.GuildBoss, bossId) } //加载1个公会的公会BOSS func (this *GuildManager) LoadGuildBoss(guild *GuildData) error { if guild == nil { return nil } if guild.GuildBoss == nil { guild.GuildBoss = map[uint32]*serverproto.GuildBossInfo{} } value := strconv.FormatUint(uint64(guild.GuildBase.GuildBrief.GuildId), 10) keyStr := model2.GuildBossPrefix + value valueStr, err := service.GetRedis().HGetAll(keyStr).Result() if err != nil { util.InfoF("[GetGuildBoss] get GuildBossPrefix [%v] err:%v", keyStr, err) return err } for bossId, bossData := range valueStr { id, _ := model2.Str2NumU64(bossId) msgStr, err := base64.StdEncoding.DecodeString(bossData) if err != nil { util.InfoF("[GetGuildBoss] get guildId [%v] err:%v", id, err) continue } bossInfo := &serverproto.GuildBossInfo{} err = rocommon.GetCodec().Unmarshal(msgStr, bossInfo) if err == nil { //超过两条需要排序,降序 if len(bossInfo.FightLog) >= 2 { sort.Slice(bossInfo.FightLog, func(i, j int) bool { return bossInfo.FightLog[j].FightTime > bossInfo.FightLog[i].FightTime }) } guild.GuildBoss[uint32(id)] = bossInfo } else { return err } } if guild.GuildBoss != nil { this.UpdateNormalBoss(guild) this.UpdateEliteBoss(guild) } return nil } func (this *GuildManager) LoadRecommendGuild() error { this.RecommendGuildIndex = make(map[uint64]int32) keyStr := model2.GuildRecommendPrefix ret, err := service.GetRedis().Get(keyStr).Result() if err != nil { util.InfoF("LoadRecommendGuild get guildId key=%v err=%v\n", keyStr, err) return err } if ret == "" { util.InfoF("key(%v)->val empty", keyStr) return err } str, err := base64.StdEncoding.DecodeString(ret) if err != nil { util.InfoF("key(%v)->val DecodeString error", keyStr) return err } recommend := &serverproto.RecommendSet{} err = rocommon.GetCodec().Unmarshal(str, recommend) if err == nil { for _, data := range recommend.Guild { this.RecommendGuild = append(this.RecommendGuild, data) this.RecommendGuildIndex[data.GuildId] = 1 } sort.Slice(this.RecommendGuild, func(i, j int) bool { if this.RecommendGuild[i].Level > this.RecommendGuild[j].Level { return true } else if this.RecommendGuild[i].Level < this.RecommendGuild[j].Level { return false } else { if this.RecommendGuild[i].ActiveTime > this.RecommendGuild[j].ActiveTime { return true } else if this.RecommendGuild[i].ActiveTime < this.RecommendGuild[j].ActiveTime { return false } else { if this.RecommendGuild[i].Active > this.RecommendGuild[j].Active { return true } return false } } }) util.InfoF("LoadRecommendGuild success:%v", len(this.RecommendGuild)) return nil } util.InfoF("LoadRecommendGuild failed") return err } func (this *GuildManager) SaveRecommendGuild() { if len(this.RecommendGuild) <= 0 { return } keyStr := model2.GuildRecommendPrefix recommend := &serverproto.RecommendSet{} for _, data := range this.RecommendGuild { recommend.Guild = append(recommend.Guild, data) } msgData, err := rocommon.GetCodec().Marshal(recommend) if err != nil { return } msgStr := base64.StdEncoding.EncodeToString(msgData.([]byte)) ret, err := service.GetRedis().Set(keyStr, msgStr, 0).Result() if err != nil { util.InfoF("SaveRecommendGuild err=%v ret=%v", keyStr, ret) return } util.InfoF("SaveRecommendGuild save recommend guild sucess : %v", len(recommend.Guild)) } //================================= 以上数据库相关操作 ====================================== //================================= 以下公会逻辑相关操作 ====================================== //内存找不到,从DB加载,再找不到说明查无此公会 func (this *GuildManager) GetGuild(guildId uint64) *GuildData { guild, ok := this.Guilds[guildId] if ok { return guild } //从数据库加载 guildData := &GuildData{ GuildBase: &serverproto.GuildBase{}, GuildMember: &serverproto.MemberData{}, ApplyList: &serverproto.GuildApplayData{}, GuildBoss: map[uint32]*serverproto.GuildBossInfo{}, } fieldStr := strconv.FormatUint(uint64(guildId), 10) baseStr, baseErr := service.GetRedis().HGet(model2.GuildBasePrefix, fieldStr).Result() if baseErr == nil { recordBase := &serverproto.GuildBase{} err := model2.GetDecodeMessage(recordBase, baseStr) if err == nil { guildData.GuildBase = recordBase } else { util.InfoF("[GetGuild] get baseStr [%v] err:%v", baseStr, err) return nil } } else { util.InfoF("[GetGuild] get baseStr [%v] err:%v", baseStr, baseErr) return nil } memberStr, memberErr := service.GetRedis().HGet(model2.GuildMemberPrefix, fieldStr).Result() if memberErr == nil { recordMember := &serverproto.MemberData{} err := model2.GetDecodeMessage(recordMember, memberStr) if err == nil { guildData.GuildMember = recordMember } else { util.InfoF("[GetGuild] get memberStr [%v] err:%v", memberStr, err) return nil } } else { util.InfoF("[GetGuild] get memberStr [%v] err:%v", memberStr, memberErr) return nil } applyStr, applyErr := service.GetRedis().HGet(model2.GuildApplyPrefix, fieldStr).Result() if applyErr == nil { recordMember := &serverproto.GuildApplayData{} err := model2.GetDecodeMessage(recordMember, applyStr) if err == nil { guildData.ApplyList = recordMember } else { util.InfoF("[GetGuild] get applyStr [%v] err:%v", applyStr, err) return nil } } err := this.LoadGuildBoss(guildData) if err != nil { } err2 := this.LoadGuildDemon(guildData) if err2 != nil { } this.Guilds[guildId] = guildData return guildData } func (this *GuildManager) GetMemberTitle(uid uint64, guildData *GuildData) int32 { if guildData == nil || guildData.GuildMember == nil { return -1 } for _, member := range guildData.GuildMember.MemberInfo { if member.MemberId == uid { return member.Title } } return -1 } func (this *GuildManager) GetUUId() uint64 { return model2.GenerateUid() } //创建工会 func (this *GuildManager) BuildGuild(uid uint64, guildName string, guildBadge int32) (serverproto.ErrorCode, *serverproto.GuildBrief) { //检查名字是否重复 guildId := this.RoleToGuilds[uid] if guildId != nil { guild := this.GetGuild(guildId.GuildId) if guild != nil { return serverproto.ErrorCode_ERROR_GUILD_ALREADY_EXIST, nil } } _, ok := this.GuildsIndex[guildName] if ok { return serverproto.ErrorCode_ERROR_GUILD_NAME_EXIST, nil } newGuildId := this.GetUUId() //添加公会 newGuild := &GuildData{ GuildBase: &serverproto.GuildBase{ GuildBrief: &serverproto.GuildBrief{ GuildId: newGuildId, GuildBadge: guildBadge, GuildName: guildName, GuildLevel: 1, // GuildExp: 0, }, RecruitLevel: model2.GlobalGuildJoinLevel, RecruitType: Recruit_None_Verify, }, GuildMember: &serverproto.MemberData{ PreId: uid, }, } member := &serverproto.GuildMember{ MemberId: uid, Title: 2, OfflineTime: 0, AddGuildTime: util.GetCurrentTime(), } newGuild.GuildMember.MemberInfo = append(newGuild.GuildMember.MemberInfo, member) newGuild.ApplyList = &serverproto.GuildApplayData{} newGuild.GuildDemon = &serverproto.GuildDemon{} this.Guilds[newGuildId] = newGuild //添加各类索引 var guildIndex serverproto.GuildIdex guildIndex.GuildId = newGuildId this.GuildsIndex[guildName] = &guildIndex this.RoleToGuilds[uid] = &serverproto.GuildIdex{ GuildId: newGuildId, } this.SaveGuildBase(newGuild) this.SaveGuildMember(newGuild) this.SaveGuildNameIndex(guildName) this.SaveRoleToGuild(uid) this.SaveGuildDemon(newGuild) //删除公会申请记录,删除个人申请 roleApply := this.GetRoleApplyInfo(uid) if roleApply != nil { for _, guildId := range roleApply.ApplyGuild { applyGuild := this.GetGuild(guildId) if applyGuild != nil { this.RemoveGuildApply(uid, applyGuild) this.SaveGuildApply(applyGuild) } } } //清除此人的所有申请 this.RemoveRoleApply(uid) this.InitGuildBoss(newGuildId) this.CheckAddRecommendGuild(newGuild) return serverproto.ErrorCode_ERROR_OK, newGuild.GuildBase.GuildBrief } //解散公会 func (this *GuildManager) DisbandGuild(uid uint64, guildId uint64) serverproto.ErrorCode { guild := this.GetGuild(guildId) if guild == nil || guild.GuildBase.GuildBrief.GuildId != guildId { return serverproto.ErrorCode_ERROR_FAIL } //判定公会是否在公会战中 _, bRet := GuildBattleMag.IsInGuildBattle(guildId) if bRet == true { return serverproto.ErrorCode_ERROR_GUILDBATTLE_In_GuildBattle } if guild.GuildMember.PreId != uid { return serverproto.ErrorCode_ERROR_GUILD_NO_AUTHORITY } //如果公会只有1个人 if len(guild.GuildMember.MemberInfo) != 1 { return serverproto.ErrorCode_ERROR_GUILD_DISBAND_FAILED } //遍历公会的加入申请信息,找到对应申请玩家,删除他们申请记录 if guild.ApplyList != nil && len(guild.ApplyList.ApplyGuild) > 0 { for _, data := range guild.ApplyList.ApplyGuild { //清空公会的加入申请 applyData := this.GetRoleApplyInfo(uid) if applyData == nil { continue } if data == uid { for idx, info := range applyData.ApplyGuild { if info == guildId { //删除 applyData.ApplyGuild = append(applyData.ApplyGuild[:idx], applyData.ApplyGuild[idx+1:]...) break } } } //TODO wangzhaocan //保存applyData 保存这个人的申请信息 this.SaveRoleApplyData(data, applyData) } } guildName := guild.GuildBase.GuildBrief.GuildName if guild.GuildBoss != nil { for id, _ := range guild.GuildBoss { this.RemoveGuildBoss(id, guild) } } //魔王排行榜删除该公会 this.RemoveGuildDemonRank(guildId, guild.GuildDemon) //推荐列表删除此公会 this.RemoveRecommendGuild(guildId) //删除数据库 this.RemoveGuildFromRedis(guildId, guildName) //删除公会 delete(this.Guilds, guildId) //删除玩家-公会索引 this.RemoveRoleToGuild(uid) //修改索引中的名字。 this.RemoveGuildNameIndex(guild.GuildBase.GuildBrief.GuildName) OnDisbandGuild(guildId) return serverproto.ErrorCode_ERROR_OK } func (this *GuildManager) GetMaxGuildMemberNum(guild *GuildData) int32 { if guild == nil { return 0 } cfgData, ok := serverproto.GuildLvCfgLoader[guild.GuildBase.GuildBrief.GuildLevel] if !ok { return 0 } return cfgData.PeopleLimit } func (this *GuildManager) OnChangeGuildName(guild *GuildData, ev rocommon.ProcEvent) { if guild == nil { return } ntfMsg := &serverproto.SSGuildNameChangeNtf{} ntfMsg.GuildId = guild.GuildBase.GuildBrief.GuildId ntfMsg.GuildName = guild.GuildBase.GuildBrief.GuildName for _, data := range guild.GuildMember.MemberInfo { ntfMsg.UidList = append(ntfMsg.UidList, data.MemberId) } SendSocial(ntfMsg) } func (this *GuildManager) ChangeGuildName(uid uint64, guildId uint64, name string, ev rocommon.ProcEvent) serverproto.ErrorCode { _, ok := this.GuildsIndex[name] if ok { return serverproto.ErrorCode_ERROR_GUILD_NAME_EXIST } guild := this.GetGuild(guildId) if guild == nil { return serverproto.ErrorCode_ERROR_GUILD_NOT_EXIST } if uid != guild.GuildMember.PreId { return serverproto.ErrorCode_ERROR_GUILD_NO_AUTHORITY } if guild.GuildBase.GuildBrief.GuildName == name { return serverproto.ErrorCode_ERROR_GUILD_SAME_NAME } //修改索引中的名字。 this.RemoveGuildNameIndex(guild.GuildBase.GuildBrief.GuildName) //新增索引 var guildIndex serverproto.GuildIdex guildIndex.GuildId = guild.GuildBase.GuildBrief.GuildId this.GuildsIndex[name] = &guildIndex this.SaveGuildNameIndex(name) //改名字 guild.GuildBase.GuildBrief.GuildName = name this.SaveGuildBase(guild) this.OnChangeGuildName(guild, ev) return serverproto.ErrorCode_ERROR_OK } //长度game有判定 func (this *GuildManager) ChangeGuildNotice(guildId uint64, notice string, uid uint64) serverproto.ErrorCode { guild := this.GetGuild(guildId) if guild == nil { return serverproto.ErrorCode_ERROR_GUILD_NOT_EXIST } if uid != guild.GuildMember.PreId { return serverproto.ErrorCode_ERROR_GUILD_NO_AUTHORITY } guild.GuildBase.Notice = notice this.SaveGuildBase(guild) return serverproto.ErrorCode_ERROR_OK } func (this *GuildManager) ChangeSetGuildInfo(msg *serverproto.CSSetGuildInfoReq) serverproto.ErrorCode { if msg == nil { return serverproto.ErrorCode_ERROR_FAIL } guild := this.GetGuild(msg.GuildId) if guild == nil { return serverproto.ErrorCode_ERROR_GUILD_NOT_EXIST } guild.GuildBase.GuildBrief.GuildBadge = msg.GuildBadge guild.GuildBase.RecruitLevel = msg.JoinLevel guild.GuildBase.RecruitType = msg.JoinType return serverproto.ErrorCode_ERROR_OK } //公会有活跃度变动时检查 func (this *GuildManager) CheckNeedChangePresident(guild *GuildData, needCheckTime bool) { if guild == nil { return } //检查会长是否超过5天未上线 var active uint32 = 0 var uid uint64 = 0 var addGuildTime uint64 = 0 var title int32 = 0 for _, member := range guild.GuildMember.MemberInfo { //会长离线不满4天,则返回 if member.MemberId == guild.GuildMember.PreId && needCheckTime { gapDay := util.GetDurationDay1(uint64(member.OfflineTime), util.GetTimeMilliseconds()) if member.OfflineTime == 0 || gapDay < model2.GlobalExchangeGuildPresident { return } //会长离线满了4天。 util.InfoF("[CheckNeedChangePresident] guild pre offline over 5 Days, guildId: %v guild pre : %v offlineTime :%v, gapDay:%v", guild.GuildBase.GuildBrief.GuildId, member.MemberId, member.OfflineTime, gapDay) } if member.MemberId != guild.GuildMember.PreId { gapDay := util.GetDurationDay1(uint64(member.OfflineTime), util.GetTimeMilliseconds()) if member.OfflineTime != 0 && gapDay >= model2.GlobalExchangeGuildPresident { continue } //查找转让会长 memActive := this.GetMemberActive(member) if title < member.Title { active = memActive uid = member.MemberId addGuildTime = member.AddGuildTime title = member.Title } else if title > member.Title { continue }else { //职位相等的情况下。 if memActive > active { active = memActive uid = member.MemberId addGuildTime = member.AddGuildTime title = member.Title } else if memActive == active { //都在线的情况下 if addGuildTime != 0 && member.AddGuildTime != 0 { //member 先加入公会 if addGuildTime > member.AddGuildTime { active = memActive uid = member.MemberId addGuildTime = member.AddGuildTime title = member.Title } } else { //uid小的(先注册的)为会长 if uid > member.MemberId { active = memActive uid = member.MemberId addGuildTime = member.AddGuildTime title = member.Title } } } } } } util.InfoF("[CheckNeedChangePresident] guildId :%v old_pre:%v new_preId:%v old_title:%v",guild.GuildBase.GuildBrief.GuildId, guild.GuildMember.PreId, uid, title) if uid != 0 && uid != guild.GuildMember.PreId { curPreUid := guild.GuildMember.PreId this.AddGuildLog(guild, Guild_Title_Pre, curPreUid, title, uid, Guild_Event_Type_ChangeGuildPre) for _, member := range guild.GuildMember.MemberInfo { if member.MemberId == guild.GuildMember.PreId { member.Title = Guild_Title_Member } if member.MemberId == uid { //如果是副会长则删除 if member.Title == Guild_Title_Vice_Pre { for index, data := range guild.GuildMember.VicePreId { if data == uid { guild.GuildMember.VicePreId = append(guild.GuildMember.VicePreId[:index], guild.GuildMember.VicePreId [index+1:]...) break } } } member.Title = Guild_Title_Pre } } guild.GuildMember.PreId = uid this.SaveGuildMember(guild) } } func (this *GuildManager) CanAddRecommendList(guild *GuildData) bool { if guild.GuildBase.RecruitType == Recruit_Refused { return false } if guild.GuildBase.RecruitType == Recruit_Verify { if guild.ApplyList == nil { return false } if len(guild.ApplyList.ApplyGuild) >= int(model2.GlobalGuildApplyListMax) { return false } } if guild.GuildBase.RecruitType == Recruit_None_Verify { if guild.GuildMember == nil { return false } count := this.GetMaxGuildMemberNum(guild) if int(count) < len(guild.GuildMember.MemberInfo) { return false } } return true } func (this *GuildManager) CheckAddRecommendGuild(guild *GuildData) { newId := guild.GuildBase.GuildBrief.GuildId _, ok := this.RecommendGuildIndex[newId] //原来有这个公会 if ok { for _, data := range this.RecommendGuild { if data.GuildId == newId { data.GuildId = guild.GuildBase.GuildBrief.GuildId data.Active = guild.GuildBase.GuildBrief.GuildActive data.ActiveTime = guild.GuildBase.ActiveTime data.Level = guild.GuildBase.GuildBrief.GuildLevel } } } else { if this.CanAddRecommendList(guild) == false { return } recommend := &serverproto.RecommendGuild{} recommend.GuildId = guild.GuildBase.GuildBrief.GuildId recommend.Active = guild.GuildBase.GuildBrief.GuildActive recommend.ActiveTime = guild.GuildBase.ActiveTime recommend.Level = guild.GuildBase.GuildBrief.GuildLevel this.RecommendGuild = append(this.RecommendGuild, recommend) } //排序 sort.Slice(this.RecommendGuild, func(i, j int) bool { if this.RecommendGuild[i].Level > this.RecommendGuild[j].Level { return true } else if this.RecommendGuild[i].Level < this.RecommendGuild[j].Level { return false } else { if this.RecommendGuild[i].ActiveTime > this.RecommendGuild[j].ActiveTime { return true } else if this.RecommendGuild[i].ActiveTime < this.RecommendGuild[j].ActiveTime { return false } else { if this.RecommendGuild[i].Active > this.RecommendGuild[j].Active { return true } return false } } }) this.RecommendGuildIndex[newId] = 1 if len(this.RecommendGuild) <= MAX_RECOMMEND_GUILD { this.SaveRecommendGuild() return } delId := this.RecommendGuild[0].GuildId delete(this.RecommendGuildIndex, delId) //超过100个则删除100之后的 this.RecommendGuild = append(this.RecommendGuild[:0], this.RecommendGuild[1:]...) //todo wangzhaocan 暂时实施村春,后续这个做定时存储 this.SaveRecommendGuild() } func (this *GuildManager) RemoveRecommendGuild(guildId uint64) { _, ok := this.RecommendGuildIndex[guildId] if !ok { return } for idx, data := range this.RecommendGuild { if data.GuildId == guildId { this.RecommendGuild = append(this.RecommendGuild[:idx], this.RecommendGuild[idx+1:]...) delete(this.RecommendGuildIndex, guildId) break } } this.SaveRecommendGuild() } func (this *GuildManager) GetPlayerGuildId(uid uint64) uint64 { guildId, ok := this.RoleToGuilds[uid] if !ok { return 0 } return uint64(guildId.GuildId) } func (this *GuildManager) CheckMemberGuild(guildData *GuildData) { if guildData == nil || guildData.GuildMember == nil { return } if guildData.CheckMemberGuild == true { return } guildData.CheckMemberGuild = true guildId := guildData.GuildBase.GuildBrief.GuildId for i:=0; i 0 { continue } nowTime := util.GetCurrentTimeNow() curWeekDay := nowTime.Weekday() if curWeekDay == 0 { curWeekDay = 7 } demonData, _ := model2.GetDemonInfo(int32(curWeekDay), nowTime) if demonData == nil { return } randDamage := rand.Int31n(1000000) msg := &serverproto.SSGuildDemonFightReq{ DemonId: demonData.DemonId, Damage: uint64(randDamage), GuildId: guild.GuildBase.GuildBrief.GuildId, Uid: guild.GuildMember.PreId, } ackMsg := &serverproto.SSGuildDemonFightAck{} this.GuildDemonFight(msg, ackMsg) } }