aozhiwei eaf14d6b2d 1
2024-04-09 18:03:58 +08:00

882 lines
22 KiB
Go

package guild
import (
"q5"
"f5"
"main/common"
"main/constant"
"fmt"
"mt"
)
type guildMgr struct {
idHash map[string]*guild
nameHash map[string]*guild
guildRankList []*guild
guildRankHash map[string]*guild
memberIdHash map[string]*member
usingNameHash map[string]int64
}
func (this *guildMgr) Init() {
this.idHash = make(map[string]*guild)
this.nameHash = make(map[string]*guild)
this.guildRankList = []*guild{}
this.guildRankHash = make(map[string]*guild)
this.memberIdHash = make(map[string]*member)
this.usingNameHash = make(map[string]int64)
this.loadFromDB()
}
func (this *guildMgr) UnInit() {
}
func (this *guildMgr) loadFromDB() {
this.loadGuild()
this.loadGuildMember()
}
func (this *guildMgr) loadGuild() {
f5.GetSysLog().Info("loadGuild begin")
lastIdx := f5.GetJsStyleDb().SyncBatchLoadFullTable(
constant.FRIEND_DB,
"SELECT * FROM t_guild WHERE idx > %d AND deleted = 0",
func (ds *f5.DataSet) {
p := newGuild()
p.loadFromDb(ds)
this.idHash[p.guildId] = p
this.nameHash[p.guildName] = p
},
func (err error) {
panic(fmt.Sprintf("loadGuild dberror:%s", err))
})
f5.GetSysLog().Info("loadGuild end lastIdx:%d idNum:%d nameNum:%d",
lastIdx,
len(this.idHash),
len(this.nameHash))
}
func (this *guildMgr) loadGuildMember() {
f5.GetSysLog().Info("loadGuildMember begin")
lastIdx := f5.GetJsStyleDb().SyncBatchLoadFullTable(
constant.FRIEND_DB,
"SELECT * FROM t_guild_member WHERE idx > %d AND deleted = 0",
func (ds *f5.DataSet) {
guildId := ds.GetByName("guild_id")
guildJob := q5.ToInt32(ds.GetByName("guild_job"))
memberId := ds.GetByName("member_id")
joinTime := q5.ToInt32(ds.GetByName("join_time"))
g := this.internalGetGuildByGuildId(guildId)
if g != nil {
p := newMember()
p.init(g, guildJob, memberId, joinTime)
g.addMember(p)
this.memberIdHash[memberId] = p
}
},
func (err error) {
panic(fmt.Sprintf("loadGuildMember dberror:%s", err))
})
f5.GetSysLog().Info("loadGuildMember end memberNum:%d",
lastIdx,
len(this.memberIdHash))
}
func (this *guildMgr) isNameTooLong(name string) bool {
return len(name) > 15
}
func (this *guildMgr) GetGuildByGuildId(guildId string) common.Guild {
if p := this.internalGetGuildByGuildId(guildId); p != nil {
return p
} else {
return nil
}
}
func (this *guildMgr) GetGuildJob(accountId string) int32 {
if m, ok := this.memberIdHash[accountId]; ok {
return m.guildJob
} else {
return constant.GuildMemberLevelDefault
}
}
func (this *guildMgr) GetGuildByAccountId(accountId string) common.Guild {
if p := this.internalGetGuildByAccountId(accountId); p != nil {
return p
} else {
return nil
}
}
func (this *guildMgr) GetGuildByGuildName(guildName string) common.Guild {
if p := this.internalGetGuildByGuildName(guildName); p != nil {
return p
} else {
return nil
}
}
func (this *guildMgr) internalGetGuildByAccountId(accountId string) *guild {
m := this.internalGetMemberByAccountId(accountId)
if m != nil {
return m.guild
}
return nil
}
func (this *guildMgr) internalGetMemberByAccountId(accountId string) *member {
if m, ok := this.memberIdHash[accountId]; ok {
return m
}
return nil
}
func (this *guildMgr) internalGetGuildByGuildId(guildId string) *guild {
if guild, ok := this.idHash[guildId]; ok {
return guild
}
return nil
}
func (this *guildMgr) internalGetGuildByGuildName(guildName string) *guild {
if guild, ok := this.nameHash[guildName]; ok {
return guild
}
return nil
}
func (this *guildMgr) addUsingName(name string) {
this.usingNameHash[name] = f5.GetApp().GetNowSeconds();
}
func (this *guildMgr) isUsingName(name string) bool {
if _, ok := this.usingNameHash[name]; ok {
return true
} else {
return false
}
}
func (this* guildMgr) removeUsingName(name string) {
delete(this.usingNameHash, name)
}
func (this *guildMgr) isValidGuildJob(guildJob int32) bool {
return guildJob == constant.GuildMemberLevelLeader ||
guildJob == constant.GuildMemberLevelViceLeader ||
guildJob == constant.GuildMemberLevelElite ||
guildJob == constant.GuildMemberLevelDefault
}
func (this *guildMgr) asyncCreateGuildTask(task *f5.AsyncTask,
guildId string, accountId string, avatar int32, name string,
cb func(int32, string, string)) {
if this.internalGetGuildByAccountId(accountId) != nil {
task.SetFail()
cb(3, "You already have a cube", "")
return
}
if this.internalGetGuildByGuildName(name) != nil {
task.SetFail()
cb(4, "Cube name already exists", "")
return
}
if this.isUsingName(name) {
task.SetFail()
cb(4, "Cube name already exists", "")
return
}
this.addUsingName(name)
nowTime := f5.GetApp().GetNowSeconds()
f5.GetJsStyleDb().Insert(
constant.FRIEND_DB,
"t_guild",
[][]string{
{"guild_id", guildId},
{"guild_name", name},
{"owner_id", accountId},
{"creator_id", accountId},
{"badge", q5.ToString(avatar)},
{"max_members", q5.ToString(constant.GuildMaxMembers)},
{"createtime", q5.ToString(nowTime)},
{"modifytime", q5.ToString(nowTime)},
},
func (err error, lastInsertId int64, rowsAffected int64) {
this.removeUsingName(name)
if err != nil {
task.SetFail()
cb(500, "server internal error", "")
return
}
f5.GetJsStyleDb().Upsert(
constant.FRIEND_DB,
"t_guild_member",
[][]string{
{"member_id", accountId},
},
[][]string{
{"guild_id", guildId},
{"guild_job", q5.ToString(constant.GuildMemberLevelLeader)},
{"deleted", q5.ToString(0)},
{"join_time", q5.ToString(nowTime)},
},
[][]string{
{"guild_id", guildId},
{"guild_job", q5.ToString(constant.GuildMemberLevelLeader)},
{"member_id", accountId},
{"join_time", q5.ToString(nowTime)},
{"createtime", q5.ToString(nowTime)},
{"modifytime", q5.ToString(nowTime)},
},
func (err error, lastInsertId int64, rowsAffected int64) {
if err != nil {
task.SetFail()
cb(500, "server internal error", "")
return
}
guild := newGuild()
{
guild.guildId = guildId
guild.guildName = name
guild.ownerId = accountId
guild.creatorId = accountId
guild.badge = avatar
guild.maxMemberNum = constant.GuildMaxMembers
guild.createTime = int32(nowTime)
guild.modifyTime = int32(nowTime)
}
this.idHash[guild.guildId] = guild
this.nameHash[guild.guildName] = guild
oldGuild := this.internalGetGuildByAccountId(accountId)
if oldGuild != nil {
task.SetFail()
panic(fmt.Sprintf("asyncCreateGuildTask:%s", ""))
} else {
m := newMember()
m.init(guild, constant.GuildMemberLevelLeader,
accountId, q5.ToInt32(nowTime))
guild.addMember(m)
this.memberIdHash[accountId] = m
task.SetSucc()
cb(0, "", guildId)
}
})
})
}
func (this *guildMgr) AsyncCreateGuild(accountId string, sessionId string, avatar int32, name string,
cb func(int32, string, string)) {
guildId := q5.ToString(f5.GetApp().NewNodeUuid())
f5.NewLockAsyncTask([][]string{
{constant.GUILD_ID_LOCK_KEY, guildId},
{constant.GUILD_NAME_LOCK_KEY, name},
{constant.GUILD_MEMBER_LOCK_KEY, accountId},
},
func (task *f5.LockAsyncTask) {
if len(name) <= 0 {
task.SetFail()
cb(1, "Name cantnot be empty", "")
return
}
if this.isNameTooLong(name) {
task.SetFail()
cb(2, "Name is to long", "")
return
}
if this.GetGuildByAccountId(accountId) != nil {
task.SetFail()
cb(3, "You already have a cube", "")
return
}
if this.GetGuildByGuildName(name) != nil {
task.SetFail()
cb(4, "Cube name already exists", "")
return
}
params := map[string]string{
"c": "Bag",
"a": "createGuildConsume",
"account_id": accountId,
"session_id": sessionId,
}
url := fmt.Sprintf("%s/webapp/index.php", mt.Table.Config.GetById(0).GetGameapiUrl())
rspObj := new(common.HeadRsp)
f5.GetHttpCliMgr().SendJsStyleJsonRspRequest(
url,
params,
&rspObj,
func(rsp f5.HttpCliResponse) {
if rspObj.Errcode != 0 {
task.SetFail()
cb(4, "item not enough", "")
return
}
this.asyncCreateGuildTask(task, guildId, accountId, avatar, name, cb)
})
})
}
func (this *guildMgr) AsyncGetApplyList(lastIdx int64, accountId string,
cb func(int32, string, int64, []string)) {
guild := this.GetGuildByAccountId(accountId)
if guild == nil {
cb(0, "", 0, nil)
return
}
f5.GetJsStyleDb().PageQuery(
constant.FRIEND_DB,
50,
0,
"SELECT * FROM t_guild_apply WHERE 1=1",
[]string{},
f5.GetDbFilter().Comp(
f5.GetDbFilter().GT("idx", q5.ToString(lastIdx)).And(),
f5.GetDbFilter().EQ("guild_id", guild.GetGuildId()).And(),
f5.GetDbFilter().EQ("status", q5.ToString(constant.GUILD_APPLY_STATUS_NONE)),
),
"",
func (err error, pg *f5.Pagination) {
var lastSinceId int64
accountIds := []string{}
if err != nil {
cb(500, "", lastSinceId, accountIds)
return
}
if pg.Rows.Next() {
idx := q5.ToInt64(pg.Rows.GetByName("idx"))
accountId := pg.Rows.GetByName("account_id")
if idx > lastSinceId {
lastSinceId = idx
} else {
panic(fmt.Sprintf("AsyncGetApply idx error:%s %s", idx, lastSinceId))
}
q5.AppendSlice(&accountIds, accountId)
}
cb(0, "", lastSinceId, accountIds)
return
})
}
func (this *guildMgr) AsyncApplyJoin(accountId string, guildId string, cb func(int32, string)) {
guild := this.GetGuildByAccountId(accountId)
if guild != nil {
cb(0, "")
return
}
nowTime := f5.GetApp().GetNowSeconds()
f5.GetJsStyleDb().Upsert(
constant.FRIEND_DB,
"t_guild_apply",
[][]string{
{"guild_id", guildId},
{"account_id", accountId},
},
[][]string{
{"status", q5.ToString(constant.GUILD_APPLY_STATUS_NONE)},
{"last_apply_time", q5.ToString(nowTime)},
},
[][]string{
{"guild_id", guildId},
{"account_id", accountId},
{"status", q5.ToString(constant.GUILD_APPLY_STATUS_NONE)},
{"last_apply_time", q5.ToString(nowTime)},
{"createtime", q5.ToString(nowTime)},
{"modifytime", q5.ToString(nowTime)},
},
func (err error, lastInsertId int64, rowsAffected int64) {
if err != nil {
cb(1, "")
return
}
cb(0, "")
})
}
func (this *guildMgr) asyncAcceptApplyTask(task *f5.AsyncTask, guild *guild,
accountId string, targetId string, cb func(int32, string)) {
if !guild.isOwner(accountId) {
task.SetFail()
cb(1, "")
return
}
if accountId == targetId {
task.SetFail()
cb(1, "")
return
}
if this.internalGetMemberByAccountId(targetId) != nil {
task.SetFail()
cb(1, "")
return
}
nowTime := q5.ToInt32(f5.GetApp().GetNowSeconds())
f5.GetJsStyleDb().Upsert(
constant.FRIEND_DB,
"t_guild_member",
[][]string{
{"member_id", targetId},
},
[][]string{
{"guild_id", guild.guildId},
{"guild_job", q5.ToString(constant.GuildMemberLevelDefault)},
{"deleted", q5.ToString(0)},
{"join_time", q5.ToString(nowTime)},
},
[][]string{
{"guild_id", guild.guildId},
{"member_id", targetId},
{"guild_job", q5.ToString(constant.GuildMemberLevelDefault)},
{"deleted", q5.ToString(0)},
{"join_time", q5.ToString(nowTime)},
{"createtime", q5.ToString(nowTime)},
{"modifytime", q5.ToString(nowTime)},
},
func (err error, lastInsertId int64, rowsAffected int64) {
if err != nil {
task.SetFail()
cb(1, "")
return
}
m := newMember()
m.init(guild, constant.GuildMemberLevelDefault, targetId, nowTime)
guild.addMember(m)
this.memberIdHash[targetId] = m
this.asyncSetApplyStatus(
targetId,
guild.guildId,
constant.GUILD_APPLY_STATUS_ACCEPT,
func (err error, lastInsertId int64, rowsAffected int64) {
task.SetSucc()
cb(0, "")
return
})
})
}
func (this *guildMgr) AsyncAcceptApply(accountId string, targetId string, cb func(int32, string)) {
guild := this.internalGetGuildByAccountId(accountId)
if guild == nil {
cb(0, "")
return;
}
f5.NewLockAsyncTask([][]string{
{constant.MEMBER_LOCK_KEY, accountId},
{constant.MEMBER_LOCK_KEY, targetId},
{constant.GUILD_ID_LOCK_KEY, guild.guildId},
},
func (task *f5.AsyncTask) {
this.asyncAcceptApplyTask(task, guild, accountId, targetId, cb)
})
}
func (this *guildMgr) AsyncRejectApply(accountId string, targetId string,
cb func(int32, string)) {
guild := this.internalGetGuildByAccountId(accountId)
if guild == nil {
cb(0, "")
return;
}
this.asyncSetApplyStatus(
targetId,
guild.guildId,
constant.GUILD_APPLY_STATUS_REJECT,
func (err error, lastInsertId int64, rowsAffected int64) {
cb(0, "")
})
}
func (this *guildMgr) AsyncLeave(accountId string, cb func(int32, string, []string)) {
members := []string{}
keys := [][]string{}
{
guild := this.internalGetGuildByAccountId(accountId)
if guild == nil {
cb(0, "", members)
return
}
keys = [][]string{
{constant.GUILD_ID_LOCK_KEY, guild.guildId},
{constant.GUILD_NAME_LOCK_KEY, guild.guildName},
};
guild.traverseMembers(
func (m *member) bool {
q5.AppendSlice(&keys, []string{constant.GUILD_MEMBER_LOCK_KEY, m.memberId})
q5.AppendSlice(&members, m.memberId)
return true
})
}
f5.NewLockAsyncTask(
keys,
func (task *f5.LockAsyncTask) {
guild := this.internalGetGuildByAccountId(accountId)
members := []string{}
if guild == nil {
task.SetSucc()
cb(0, "", members)
return
}
guild.asyncLeave(accountId,
func (errCode int32, errMsg string) {
if errCode != 0 {
task.SetFail()
cb(errCode, errMsg, members)
return
}
task.SetSucc()
cb(0, "", members)
return
})
})
}
func (this *guildMgr) AsyncSetGuildJob(accountId string, targetId string, guildJob int32,
cb func(int32, string)) {
if accountId == targetId {
cb(0, "")
return
}
guild := this.internalGetGuildByAccountId(accountId)
if guild == nil {
cb(0, "")
return
}
if !this.isValidGuildJob(guildJob) {
cb(1, "params error")
return
}
if !guild.isOwner(accountId) {
cb(0, "")
return;
}
owner := guild.getMember(accountId)
if owner == nil {
cb(0, "")
return;
}
member := guild.getMember(targetId)
if member == nil {
cb(0, "")
return;
}
f5.NewLockAsyncTask(
[][]string{
{constant.GUILD_ID_LOCK_KEY, guild.guildId},
{constant.GUILD_NAME_LOCK_KEY, guild.guildName},
{constant.GUILD_MEMBER_LOCK_KEY, accountId},
{constant.GUILD_MEMBER_LOCK_KEY, targetId},
},
func (task *f5.LockAsyncTask) {
f5.GetJsStyleDb().Update(
constant.FRIEND_DB,
"t_guild_member",
[][]string{
{"guild_job", q5.ToString(guildJob)},
},
[][]string{
{"member_id", member.memberId},
{"guild_id", guild.guildId},
},
func (err error, lastInsertId int64, rowsAffected int64) {
if err != nil {
task.SetFail()
cb(500, "")
return
}
member.guildJob = guildJob
if guildJob == constant.GuildMemberLevelLeader {
f5.GetJsStyleDb().Update(
constant.FRIEND_DB,
"t_guild_member",
[][]string{
{"guild_job", q5.ToString(constant.GuildMemberLevelDefault)},
},
[][]string{
{"member_id", owner.memberId},
{"guild_id", guild.guildId},
},
func (err error, lastInsertId int64, rowsAffected int64) {
if err != nil {
task.SetFail()
cb(500, "")
return
}
owner.guildJob = constant.GuildMemberLevelDefault
guild.asyncUpdateOwner(member.memberId,
func (errCode int32, errMsg string) {
if err != nil {
task.SetFail()
cb(500, "")
return
}
task.SetSucc()
cb(0, "")
})
})
} else {
task.SetSucc()
cb(0, "")
}
})
})
}
func (this *guildMgr) AsyncKickout(accountId string, targetId string, cb func(int32, string)) {
guild := this.internalGetGuildByAccountId(accountId)
if guild == nil {
cb(0, "")
return;
}
if accountId == targetId {
cb(0, "")
return;
}
if !guild.isOwner(accountId) {
cb(0, "")
return;
}
if guild.getMember(targetId) == nil {
cb(0, "")
return;
}
f5.NewLockAsyncTask(
[][]string{
{constant.GUILD_ID_LOCK_KEY, guild.guildId},
{constant.GUILD_NAME_LOCK_KEY, guild.guildName},
{constant.GUILD_MEMBER_LOCK_KEY, accountId},
{constant.GUILD_MEMBER_LOCK_KEY, targetId},
},
func (task *f5.LockAsyncTask) {
f5.GetJsStyleDb().Update(
constant.FRIEND_DB,
"t_guild_member",
[][]string{
{"deleted", "1"},
},
[][]string{
{"guild_id", guild.guildId},
{"member_id", targetId},
},
func (err error, lastInsertId int64, rowsAffected int64) {
if err != nil {
cb(500, "server internal error")
return
}
delete(guild.idHash, targetId)
delete(this.memberIdHash, targetId)
cb(0, "")
})
})
}
func (this *guildMgr) AsyncDisband(accountId string, cb func(int32, string, []string)) {
members := []string{}
keys := [][]string{}
{
guild := this.internalGetGuildByAccountId(accountId)
if guild == nil {
cb(0, "", members)
return
}
if !guild.isOwner(accountId) {
cb(1, "Disband only leader perm", members)
return
}
keys = [][]string{
{constant.GUILD_ID_LOCK_KEY, guild.guildId},
{constant.GUILD_NAME_LOCK_KEY, guild.guildName},
};
guild.traverseMembers(
func (m *member) bool {
q5.AppendSlice(&keys, []string{constant.GUILD_MEMBER_LOCK_KEY, m.memberId})
q5.AppendSlice(&members, m.memberId)
return true
})
}
f5.NewLockAsyncTask(
keys,
func (task *f5.LockAsyncTask) {
guild := this.internalGetGuildByAccountId(accountId)
members := []string{}
if guild == nil {
task.SetSucc()
cb(0, "", members)
return
}
if !guild.isOwner(accountId) {
task.SetFail()
cb(1, "Disband only leader perm", members)
return
}
f5.GetJsStyleDb().Update(
constant.FRIEND_DB,
"t_guild",
[][]string{
{"deleted", "1"},
},
[][]string{
{"guild_id", guild.guildId},
},
func (err error, lastInsertId int64, rowsAffected int64) {
if err != nil {
task.SetFail()
cb(500, "server internal error", members)
return
}
task.SetSucc()
guild.disband()
cb(0, "", members)
return
})
})
}
func (this *guildMgr) AsyncSearch(string, string, func(int32, string)) {
}
func (this *guildMgr) AsyncGetGuildLogs(string, string, func(int32, string)) {
}
func (this *guildMgr) AsyncUpdateGuild(accountId string, kv map[int32]string, cb func(int32, string)) {
guild := this.internalGetGuildByAccountId(accountId)
if guild == nil {
cb(1, "You don't have a cube yet")
return
}
if !guild.isOwner(accountId) {
cb(2, "Insufficient permissions")
return
}
guildName := f5.GetApp().NewGlobalUuid()
if name, ok := kv[constant.GUILD_UPDATE_FIELD_NAME]; ok {
if this.internalGetGuildByGuildName(name) != nil {
cb(4, "Cube name already exists")
return
}
if this.isUsingName(name) {
cb(4, "Cube name already exists")
return
}
this.addUsingName(name)
guildName = name
}
f5.NewLockAsyncTask([][]string{
{constant.GUILD_ID_LOCK_KEY, guild.guildId},
{constant.GUILD_NAME_LOCK_KEY, guild.guildName},
{constant.GUILD_NAME_LOCK_KEY, guildName},
{constant.GUILD_MEMBER_LOCK_KEY, accountId},
},
func (task *f5.LockAsyncTask) {
fields := [][]string{}
for k, v := range(kv) {
if k == constant.GUILD_UPDATE_FIELD_NOTICE {
q5.AppendSlice(&fields, []string{"notice", v})
} else if k == constant.GUILD_UPDATE_FIELD_AVATAR {
q5.AppendSlice(&fields, []string{"badge", v})
} else if k == constant.GUILD_UPDATE_FIELD_NAME {
q5.AppendSlice(&fields, []string{"guild_name", v})
} else if k == constant.GUILD_UPDATE_FIELD_COND_TYPE {
q5.AppendSlice(&fields, []string{"join_cond_type", v})
} else if k == constant.GUILD_UPDATE_FIELD_COND_VALUE {
q5.AppendSlice(&fields, []string{"join_cond_value", v})
}
}
if len(fields) <= 0 {
task.SetSucc()
cb(0, "")
return
}
f5.GetJsStyleDb().Update(
constant.FRIEND_DB,
"t_guild",
fields,
[][]string{
{"guild_id", guild.guildId},
},
func (err error, lastInsertId int64, rowsAffected int64) {
if err != nil {
task.SetFail()
cb(500, "server internal error")
return
}
guild.updateByKv(kv)
task.SetSucc()
cb(0, "")
return
})
}).OnExit(
func (task *f5.LockAsyncTask) {
if name, ok := kv[constant.GUILD_UPDATE_FIELD_NAME]; ok {
this.removeUsingName(name)
}
})
}
func (this *guildMgr) asyncSetApplyStatus(accountId string, guildId string, status int32,
cb func(error, int64, int64)) {
f5.GetJsStyleDb().Update(
constant.FRIEND_DB,
"t_guild_apply",
[][]string{
{"status", q5.ToString(status)},
{"modifytime", q5.ToString(f5.GetApp().GetNowSeconds())},
},
[][]string{
{"account_id", accountId},
{"guild_id", guildId},
},
cb)
}
func (this *guildMgr) AsyncGetGuildRank(num int32, cb func(int32, string, []string)) {
guildIds := []string{}
this.rearrangement()
cb(0, "", guildIds)
}
func (this *guildMgr) AsyncGetRecommendGuild(int32, func(int32, string, []string)) {
}
func (this *guildMgr) rearrangement() {
this.guildRankList = []*guild{}
this.guildRankHash = make(map[string]*guild)
this.traverseGuild(
func (g *guild) bool {
this.updateGuildRank(g)
return true
})
}
func (this* guildMgr) updateGuildRank(guild *guild) {
if _, ok := this.guildRankHash[guild.guildId]; ok {
this.rankSort()
return
}
if len(this.guildRankList) < constant.MAX_GUILD_TOP {
q5.AppendSlice(&this.guildRankList, guild)
this.guildRankHash[guild.guildId] = guild
this.rankSort()
} else if guild.totalStars > this.guildRankList[len(this.guildRankList) - 1].totalStars {
lastGuild := this.guildRankList[len(this.guildRankList) - 1]
delete(this.guildRankHash, lastGuild.guildId)
this.guildRankList[len(this.guildRankList) - 1] = guild
this.rankSort()
}
}
func (this* guildMgr) rankSort() {
}
func (this* guildMgr) traverseGuild(cb func(*guild) bool) {
for _, g := range(this.idHash) {
if !cb(g) {
break
}
}
}