diff --git a/.claude/settings.local.json b/.claude/settings.local.json new file mode 100644 index 0000000..6378bdf --- /dev/null +++ b/.claude/settings.local.json @@ -0,0 +1,11 @@ +{ + "permissions": { + "allow": [ + "Bash(nul)", + "Bash(go build:*)", + "Bash(gofmt:*)" + ], + "deny": [], + "ask": [] + } +} diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 0000000..d2b8ebd --- /dev/null +++ b/.gitattributes @@ -0,0 +1,2 @@ +* text=auto eol=lf +*.go text eol=lf \ No newline at end of file diff --git a/server/slgserver/controller/war.go b/server/slgserver/controller/war.go index 3a9adad..240dee0 100644 --- a/server/slgserver/controller/war.go +++ b/server/slgserver/controller/war.go @@ -14,17 +14,16 @@ import ( var DefaultWar = War{} type War struct { - } -func (this*War) InitRouter(r *net.Router) { +func (this *War) InitRouter(r *net.Router) { g := r.Group("war").Use(middleware.ElapsedTime(), middleware.Log(), middleware.CheckRole()) g.AddRouter("report", this.report) g.AddRouter("read", this.read) } -func (this*War) report(req *net.WsMsgReq, rsp *net.WsMsgRsp) { +func (this *War) report(req *net.WsMsgReq, rsp *net.WsMsgRsp) { reqObj := &proto.WarReportReq{} rspObj := &proto.WarReportRsp{} @@ -40,7 +39,7 @@ func (this*War) report(req *net.WsMsgReq, rsp *net.WsMsgRsp) { err := db.MasterDB.Table(model.WarReport{}).Where("a_rid=? or d_rid=?", role.RId, role.RId).Desc("ctime").Limit(100, 0).Find(&l) - if err != nil{ + if err != nil { slog.Warn("db error", "error", err) rsp.Body.Code = constant.DBError return @@ -52,7 +51,7 @@ func (this*War) report(req *net.WsMsgReq, rsp *net.WsMsgRsp) { } } -func (this*War) read(req *net.WsMsgReq, rsp *net.WsMsgRsp) { +func (this *War) read(req *net.WsMsgReq, rsp *net.WsMsgRsp) { reqObj := &proto.WarReadReq{} rspObj := &proto.WarReadRsp{} @@ -65,16 +64,39 @@ func (this*War) read(req *net.WsMsgReq, rsp *net.WsMsgRsp) { role := r.(*model.Role) if reqObj.Id == 0 { + // 批量标记所有战报为已读 - 使用事务优化 m := model.WarReport{AttackIsRead: true, DefenseIsRead: true} - _, err := db.MasterDB.Table(model.WarReport{}).Where("a_rid=?", role.RId).Cols("a_is_read").Update(m) - if err != nil { - slog.Error("db error", "error", err) + sess := db.MasterDB.NewSession() + defer sess.Close() + + if err := sess.Begin(); err != nil { + slog.Error("begin transaction error", "error", err) + rsp.Body.Code = constant.DBError + return } - _, err = db.MasterDB.Table(model.WarReport{}).Where("d_rid=?", role.RId).Cols("d_is_read").Update(m) - if err != nil { - slog.Error("db error", "error", err) + + // 更新攻击方战报 + if _, err := sess.Table(model.WarReport{}).Where("a_rid=?", role.RId).Cols("a_is_read").Update(m); err != nil { + slog.Error("update attack reports error", "error", err) + sess.Rollback() + rsp.Body.Code = constant.DBError + return } - }else{ + + // 更新防守方战报 + if _, err := sess.Table(model.WarReport{}).Where("d_rid=?", role.RId).Cols("d_is_read").Update(m); err != nil { + slog.Error("update defense reports error", "error", err) + sess.Rollback() + rsp.Body.Code = constant.DBError + return + } + + if err := sess.Commit(); err != nil { + slog.Error("commit transaction error", "error", err) + rsp.Body.Code = constant.DBError + return + } + } else { wr := &model.WarReport{} ok, err := db.MasterDB.Table(model.WarReport{}).Where("id=?", reqObj.Id).Get(wr) @@ -90,11 +112,11 @@ func (this*War) read(req *net.WsMsgReq, rsp *net.WsMsgRsp) { wr.AttackIsRead = true db.MasterDB.Table(wr).ID(wr.Id).Cols("a_is_read").Update(wr) rsp.Body.Code = constant.OK - }else if wr.DefenseRid == role.RId { + } else if wr.DefenseRid == role.RId { wr.DefenseIsRead = true db.MasterDB.Table(wr).ID(wr.Id).Cols("d_is_read").Update(wr) rsp.Body.Code = constant.OK - }else{ + } else { rsp.Body.Code = constant.InvalidParam } } diff --git a/server/slgserver/logic/mgr/general_mgr.go b/server/slgserver/logic/mgr/general_mgr.go index a06754e..17ac906 100644 --- a/server/slgserver/logic/mgr/general_mgr.go +++ b/server/slgserver/logic/mgr/general_mgr.go @@ -20,36 +20,65 @@ type generalMgr struct { var GMgr = &generalMgr{ genByRole: make(map[int][]*model.General), - genByGId: make(map[int]*model.General), + genByGId: make(map[int]*model.General), } -func (this*generalMgr) updatePhysicalPower() { +func (this *generalMgr) updatePhysicalPower() { limit := static_conf.Basic.General.PhysicalPowerLimit recoverCnt := static_conf.Basic.General.RecoveryPhysicalPower for true { - time.Sleep(1*time.Hour) + time.Sleep(1 * time.Hour) this.mutex.RLock() + + // 收集需要更新的武将ID和体力值 + updateList := make([]*model.General, 0) for _, g := range this.genByGId { - if g.PhysicalPower < limit{ + if g.PhysicalPower < limit { g.PhysicalPower = util.MinInt(limit, g.PhysicalPower+recoverCnt) - g.SyncExecute() + updateList = append(updateList, g) } } this.mutex.RUnlock() + + // 批量更新数据库 - 使用事务提升性能 + if len(updateList) > 0 { + sess := db.MasterDB.NewSession() + defer sess.Close() + + if err := sess.Begin(); err != nil { + slog.Warn("begin transaction error", "error", err) + continue + } + + for _, g := range updateList { + if _, err := sess.ID(g.Id).Cols("physical_power").Update(g); err != nil { + slog.Warn("update general physical power error", "gid", g.Id, "error", err) + sess.Rollback() + goto CONTINUE + } + } + + if err := sess.Commit(); err != nil { + slog.Warn("commit transaction error", "error", err) + } else { + slog.Debug("batch update general physical power", "count", len(updateList)) + } + } + CONTINUE: } } -//创建npc -func (this*generalMgr) createNPC() ([]*model.General, bool){ +// 创建npc +func (this *generalMgr) createNPC() ([]*model.General, bool) { gs := make([]*model.General, 0) sess := db.MasterDB.NewSession() sess.Begin() for _, v := range general.General.GMap { - if v.Star >= 3{ - arr := []int8{1,5,10,20} - for _, level := range arr{ + if v.Star >= 3 { + arr := []int8{1, 5, 10, 20} + for _, level := range arr { r, ok := this.NewGeneral(v.CfgId, 0, level) if ok == false { sess.Rollback() @@ -61,18 +90,18 @@ func (this*generalMgr) createNPC() ([]*model.General, bool){ } } - if err := sess.Commit(); err != nil{ + if err := sess.Commit(); err != nil { slog.Warn("db error", "error", err) return nil, false - }else{ + } else { return gs, true } } -func (this*generalMgr) add(g *model.General) { +func (this *generalMgr) add(g *model.General) { this.mutex.Lock() - if _,ok := this.genByRole[g.RId]; ok == false{ + if _, ok := this.genByRole[g.RId]; ok == false { this.genByRole[g.RId] = make([]*model.General, 0) } this.genByRole[g.RId] = append(this.genByRole[g.RId], g) @@ -81,9 +110,7 @@ func (this*generalMgr) add(g *model.General) { this.mutex.Unlock() } - - -func (this*generalMgr) Load(){ +func (this *generalMgr) Load() { err := db.MasterDB.Table(model.General{}).Where("state=?", model.GeneralNormal).Find(this.genByGId) @@ -94,20 +121,20 @@ func (this*generalMgr) Load(){ } for _, v := range this.genByGId { - if _, ok := this.genByRole[v.RId]; ok==false { + if _, ok := this.genByRole[v.RId]; ok == false { this.genByRole[v.RId] = make([]*model.General, 0) } this.genByRole[v.RId] = append(this.genByRole[v.RId], v) } - if len(this.genByGId) == 0{ + if len(this.genByGId) == 0 { this.createNPC() } go this.updatePhysicalPower() } -func (this*generalMgr) GetByRId(rid int) ([]*model.General, bool){ +func (this *generalMgr) GetByRId(rid int) ([]*model.General, bool) { this.mutex.Lock() r, ok := this.genByRole[rid] this.mutex.Unlock() @@ -115,7 +142,7 @@ func (this*generalMgr) GetByRId(rid int) ([]*model.General, bool){ if ok { out := make([]*model.General, 0) for _, g := range r { - if g.IsActive(){ + if g.IsActive() { out = append(out, g) } } @@ -132,86 +159,86 @@ func (this*generalMgr) GetByRId(rid int) ([]*model.General, bool){ this.add(g) } return gs, true - }else{ + } else { slog.Warn("general not fount", "rid", rid) return nil, false } - }else{ + } else { slog.Warn("db error", "error", err) return nil, false } } -//查找将领 -func (this*generalMgr) GetByGId(gid int) (*model.General, bool){ +// 查找将领 +func (this *generalMgr) GetByGId(gid int) (*model.General, bool) { this.mutex.RLock() g, ok := this.genByGId[gid] this.mutex.RUnlock() if ok { - if g.IsActive(){ + if g.IsActive() { return g, true - }else{ + } else { return nil, false } - }else{ + } else { g := &model.General{} r, err := db.MasterDB.Table(new(model.General)).Where( "id=? and state=?", gid, model.GeneralNormal).Get(g) - if err == nil{ + if err == nil { if r { this.add(g) return g, true - }else{ + } else { slog.Warn("general gid not found", "gid", gid) return nil, false } - }else{ + } else { slog.Warn("general gid not found", "gid", gid) return nil, false } } } -//这个角色是否有这个武将 -func (this*generalMgr) HasGeneral(rid int ,gid int) (*model.General,bool){ +// 这个角色是否有这个武将 +func (this *generalMgr) HasGeneral(rid int, gid int) (*model.General, bool) { r, ok := this.GetByRId(rid) if ok { for _, v := range r { t := v if t.Id == gid { - return t,true + return t, true } } } - return nil,false + return nil, false } -func (this*generalMgr) HasGenerals(rid int, gIds []int) ([]*model.General,bool){ +func (this *generalMgr) HasGenerals(rid int, gIds []int) ([]*model.General, bool) { gs := make([]*model.General, 0) for i := 0; i < len(gIds); i++ { - g,ok := this.HasGeneral(rid, gIds[i]) - if ok{ - gs = append(gs,g) - }else{ - return gs,false + g, ok := this.HasGeneral(rid, gIds[i]) + if ok { + gs = append(gs, g) + } else { + return gs, false } } - return gs,true + return gs, true } -func (this*generalMgr) Count(rid int) int{ +func (this *generalMgr) Count(rid int) int { gs, ok := this.GetByRId(rid) if ok { return len(gs) - }else{ + } else { return 0 } } -func (this*generalMgr) NewGeneral(cfgId int, rid int, level int8) (*model.General, bool) { +func (this *generalMgr) NewGeneral(cfgId int, rid int, level int8) (*model.General, bool) { g, ok := model.NewGeneral(cfgId, rid, level) if ok { this.add(g) @@ -222,37 +249,36 @@ func (this*generalMgr) NewGeneral(cfgId int, rid int, level int8) (*model.Genera /* 如果不存在则去创建 */ -func (this*generalMgr) GetOrCreateByRId(rid int) ([]*model.General, bool){ +func (this *generalMgr) GetOrCreateByRId(rid int) ([]*model.General, bool) { r, ok := this.GetByRId(rid) if ok { return r, true - }else{ + } else { //创建 gs := make([]*model.General, 0) sess := db.MasterDB.NewSession() sess.Begin() - g, ok := this.RandCreateGeneral(rid,3) - if ok == false{ + g, ok := this.RandCreateGeneral(rid, 3) + if ok == false { sess.Rollback() return nil, false } gs = g - if err := sess.Commit(); err != nil{ + if err := sess.Commit(); err != nil { slog.Warn("db error", "error", err) return nil, false - }else{ + } else { return gs, true } } } - /* 随机创建一个 */ -func (this*generalMgr) RandCreateGeneral(rid int, nums int) ([]*model.General, bool){ +func (this *generalMgr) RandCreateGeneral(rid int, nums int) ([]*model.General, bool) { gs := make([]*model.General, 0) sess := db.MasterDB.NewSession() sess.Begin() @@ -260,43 +286,42 @@ func (this*generalMgr) RandCreateGeneral(rid int, nums int) ([]*model.General, b for i := 0; i < nums; i++ { cfgId := general.General.Draw() g, ok := this.NewGeneral(cfgId, rid, 1) - if ok == false{ + if ok == false { sess.Rollback() return nil, false } gs = append(gs, g) } - if err := sess.Commit(); err != nil{ + if err := sess.Commit(); err != nil { slog.Warn("db error", "error", err) return nil, false - }else{ + } else { return gs, true } } - -//获取npc武将 -func (this*generalMgr) GetNPCGenerals(cnt int, star int8, level int8) ([]model.General, bool) { +// 获取npc武将 +func (this *generalMgr) GetNPCGenerals(cnt int, star int8, level int8) ([]model.General, bool) { gs, ok := this.GetByRId(0) if ok == false { return make([]model.General, 0), false - }else{ + } else { target := make([]model.General, 0) for _, g := range gs { - if g.Level == level && g.Star == star{ + if g.Level == level && g.Star == star { target = append(target, *g) } } - if len(target) < cnt{ + if len(target) < cnt { return make([]model.General, 0), false - }else{ + } else { m := make(map[int]int) for true { r := rand.Intn(len(target)) m[r] = r - if len(m) == cnt{ + if len(m) == cnt { break } } @@ -311,7 +336,7 @@ func (this*generalMgr) GetNPCGenerals(cnt int, star int8, level int8) ([]model.G } } -func (this *generalMgr) GetDestroy(army *model.Army) int{ +func (this *generalMgr) GetDestroy(army *model.Army) int { destroy := 0 for _, g := range army.Gens { if g != nil { @@ -321,32 +346,70 @@ func (this *generalMgr) GetDestroy(army *model.Army) int{ return destroy } -//体力是否足够 -func (this*generalMgr) PhysicalPowerIsEnough(army *model.Army, cost int) bool{ +// 体力是否足够 +func (this *generalMgr) PhysicalPowerIsEnough(army *model.Army, cost int) bool { for _, g := range army.Gens { - if g == nil{ + if g == nil { continue } - if g.PhysicalPower < cost{ + if g.PhysicalPower < cost { return false } } return true } -//尝试使用体力 -func (this *generalMgr) TryUsePhysicalPower(army *model.Army, cost int) bool{ +// 尝试使用体力 +func (this *generalMgr) TryUsePhysicalPower(army *model.Army, cost int) bool { - if this.PhysicalPowerIsEnough(army, cost) == false{ + if this.PhysicalPowerIsEnough(army, cost) == false { return false } + // 收集需要更新的武将 + updateList := make([]*model.General, 0, len(army.Gens)) for _, g := range army.Gens { - if g == nil{ + if g == nil { continue } g.PhysicalPower -= cost - g.SyncExecute() + updateList = append(updateList, g) + } + + // 批量更新数据库 - 使用事务 + if len(updateList) > 0 { + sess := db.MasterDB.NewSession() + defer sess.Close() + + if err := sess.Begin(); err != nil { + slog.Warn("begin transaction error", "error", err) + // 回滚内存中的修改 + for _, g := range updateList { + g.PhysicalPower += cost + } + return false + } + + for _, g := range updateList { + if _, err := sess.ID(g.Id).Cols("physical_power").Update(g); err != nil { + slog.Warn("update general physical power error", "gid", g.Id, "error", err) + sess.Rollback() + // 回滚内存中的修改 + for _, g := range updateList { + g.PhysicalPower += cost + } + return false + } + } + + if err := sess.Commit(); err != nil { + slog.Warn("commit transaction error", "error", err) + // 回滚内存中的修改 + for _, g := range updateList { + g.PhysicalPower += cost + } + return false + } } return true diff --git a/server/slgserver/logic/mgr/role_attribute_mgr.go b/server/slgserver/logic/mgr/role_attribute_mgr.go index 9f97f3f..9010d85 100644 --- a/server/slgserver/logic/mgr/role_attribute_mgr.go +++ b/server/slgserver/logic/mgr/role_attribute_mgr.go @@ -8,7 +8,7 @@ import ( ) type roleAttributeMgr struct { - mutex sync.RWMutex + mutex sync.RWMutex attribute map[int]*model.RoleAttribute //key:rid } @@ -16,7 +16,7 @@ var RAttrMgr = &roleAttributeMgr{ attribute: make(map[int]*model.RoleAttribute), } -func (this*roleAttributeMgr) Load() { +func (this *roleAttributeMgr) Load() { //加载 t := make(map[int]*model.RoleAttribute) err := db.MasterDB.Find(t) @@ -25,28 +25,42 @@ func (this*roleAttributeMgr) Load() { } //获取联盟id - for _, v:= range t { + for _, v := range t { this.attribute[v.RId] = v } l := UnionMgr.List() + // 收集需要创建的角色属性 + needCreate := make([]*model.RoleAttribute, 0) for _, c := range l { for _, rid := range c.MemberArray { attr, ok := this.attribute[rid] if ok { attr.UnionId = c.Id - }else{ - attr := this.create(rid) - if attr != nil{ - attr.UnionId = c.Id - } + } else { + // 批量收集需要创建的属性 + newAttr := &model.RoleAttribute{RId: rid, ParentId: 0, UnionId: c.Id} + needCreate = append(needCreate, newAttr) + this.attribute[rid] = newAttr } } } + + // 批量插入缺失的角色属性 + if len(needCreate) > 0 { + if _, err := db.MasterDB.Insert(&needCreate); err != nil { + slog.Error("batch insert role attributes error", "error", err) + // 回滚内存中的修改 + for _, attr := range needCreate { + delete(this.attribute, attr.RId) + } + } else { + slog.Info("batch inserted role attributes", "count", len(needCreate)) + } + } } - -func (this*roleAttributeMgr) Get(rid int) (*model.RoleAttribute, bool){ +func (this *roleAttributeMgr) Get(rid int) (*model.RoleAttribute, bool) { this.mutex.RLock() r, ok := this.attribute[rid] @@ -54,16 +68,16 @@ func (this*roleAttributeMgr) Get(rid int) (*model.RoleAttribute, bool){ if ok { return r, true - }else { + } else { return nil, false } } -func (this*roleAttributeMgr) TryCreate(rid int) (*model.RoleAttribute, bool){ +func (this *roleAttributeMgr) TryCreate(rid int) (*model.RoleAttribute, bool) { attr, ok := this.Get(rid) if ok { return attr, true - }else{ + } else { this.mutex.Lock() defer this.mutex.Unlock() attr := this.create(rid) @@ -71,19 +85,18 @@ func (this*roleAttributeMgr) TryCreate(rid int) (*model.RoleAttribute, bool){ } } -func (this*roleAttributeMgr) create(rid int) *model.RoleAttribute { +func (this *roleAttributeMgr) create(rid int) *model.RoleAttribute { roleAttr := &model.RoleAttribute{RId: rid, ParentId: 0, UnionId: 0} - if _ , err := db.MasterDB.Insert(roleAttr); err != nil { + if _, err := db.MasterDB.Insert(roleAttr); err != nil { slog.Error("insert RoleAttribute error", "error", err) return nil - }else{ + } else { this.attribute[rid] = roleAttr return roleAttr } } - -func (this*roleAttributeMgr) IsHasUnion(rid int) bool{ +func (this *roleAttributeMgr) IsHasUnion(rid int) bool { this.mutex.RLock() r, ok := this.attribute[rid] @@ -91,12 +104,12 @@ func (this*roleAttributeMgr) IsHasUnion(rid int) bool{ if ok { return r.UnionId != 0 - }else { - return false + } else { + return false } } -func (this*roleAttributeMgr) UnionId(rid int) int{ +func (this *roleAttributeMgr) UnionId(rid int) int { this.mutex.RLock() r, ok := this.attribute[rid] @@ -104,12 +117,12 @@ func (this*roleAttributeMgr) UnionId(rid int) int{ if ok { return r.UnionId - }else { - return 0 + } else { + return 0 } } -func (this*roleAttributeMgr) List() []*model.RoleAttribute { +func (this *roleAttributeMgr) List() []*model.RoleAttribute { this.mutex.RLock() defer this.mutex.RUnlock() ret := make([]*model.RoleAttribute, 0) @@ -118,4 +131,3 @@ func (this*roleAttributeMgr) List() []*model.RoleAttribute { } return ret } - diff --git a/server/slgserver/logic/mgr/role_build_mgr.go b/server/slgserver/logic/mgr/role_build_mgr.go index 0a906a1..b446ce1 100644 --- a/server/slgserver/logic/mgr/role_build_mgr.go +++ b/server/slgserver/logic/mgr/role_build_mgr.go @@ -45,17 +45,28 @@ func (this *roleBuildMgr) Load() { db.MasterDB.Where("type = ? or type = ?", model.MapBuildSysCity, model.MapBuildSysFortress).Delete(new(model.MapRoleBuild)) - for _, sysBuild := range NMMgr.sysBuild { - build := model.MapRoleBuild{ - RId: 0, - Type: sysBuild.Type, - Level: sysBuild.Level, - X: sysBuild.X, - Y: sysBuild.Y, + // 批量插入系统建筑 + if len(NMMgr.sysBuild) > 0 { + builds := make([]model.MapRoleBuild, 0, len(NMMgr.sysBuild)) + for _, sysBuild := range NMMgr.sysBuild { + build := model.MapRoleBuild{ + RId: 0, + Type: sysBuild.Type, + Level: sysBuild.Level, + X: sysBuild.X, + Y: sysBuild.Y, + } + build.Init() + builds = append(builds, build) + } + // 批量插入 + if _, err := db.MasterDB.Insert(&builds); err != nil { + slog.Error("batch insert system builds error", "error", err) + panic("batch insert error: " + err.Error()) + } else { + slog.Info("batch inserted system builds", "count", len(builds)) } - build.Init() - db.MasterDB.InsertOne(&build) } } } @@ -129,8 +140,32 @@ func (this *roleBuildMgr) CheckGiveUp() []int { } this.giveUpMutex.Unlock() - for _, build := range builds { - this.RemoveFromRole(build) + // 批量处理放弃的土地 - 使用事务 + if len(builds) > 0 { + sess := db.MasterDB.NewSession() + defer sess.Close() + + if err := sess.Begin(); err != nil { + slog.Warn("begin transaction error", "error", err) + return ret + } + + for _, build := range builds { + build.Reset() + if _, err := sess.ID(build.Id).Update(build); err != nil { + slog.Warn("update giveup build error", "id", build.Id, "error", err) + sess.Rollback() + return ret + } + // 从角色列表移除(仅内存操作) + this.removeFromRoleMemory(build) + } + + if err := sess.Commit(); err != nil { + slog.Warn("commit transaction error", "error", err) + } else { + slog.Debug("batch process giveup builds", "count", len(builds)) + } } return ret @@ -154,13 +189,65 @@ func (this *roleBuildMgr) CheckDestroy() []int { } this.destroyMutex.Unlock() - for _, build := range builds { - build.ConvertToRes() - build.SyncExecute() + // 批量处理拆除的建筑 - 使用事务 + if len(builds) > 0 { + sess := db.MasterDB.NewSession() + defer sess.Close() + + if err := sess.Begin(); err != nil { + slog.Warn("begin transaction error", "error", err) + return ret + } + + for _, build := range builds { + build.ConvertToRes() + if _, err := sess.ID(build.Id).Update(build); err != nil { + slog.Warn("update destroy build error", "id", build.Id, "error", err) + sess.Rollback() + return ret + } + } + + if err := sess.Commit(); err != nil { + slog.Warn("commit transaction error", "error", err) + } else { + slog.Debug("batch process destroy builds", "count", len(builds)) + } } return ret } +// 辅助函数:从角色内存列表中移除建筑(不涉及数据库) +func (this *roleBuildMgr) removeFromRoleMemory(build *model.MapRoleBuild) { + this.baseMutex.Lock() + rb, ok := this.roleRB[build.RId] + if ok { + for i, v := range rb { + if v.Id == build.Id { + this.roleRB[build.RId] = append(rb[:i], rb[i+1:]...) + break + } + } + } + this.baseMutex.Unlock() + + //移除放弃事件 + t := build.GiveUpTime + this.giveUpMutex.Lock() + if ms, ok := this.giveUpRB[t]; ok { + delete(ms, build.Id) + } + this.giveUpMutex.Unlock() + + //移除拆除事件 + t = build.EndTime.Unix() + this.destroyMutex.Lock() + if ms, ok := this.destroyRB[t]; ok { + delete(ms, build.Id) + } + this.destroyMutex.Unlock() +} + /* 该位置是否被角色占领 */ diff --git a/server/slgserver/logic/mgr/role_res_mgr.go b/server/slgserver/logic/mgr/role_res_mgr.go index 2171c3f..edb1614 100644 --- a/server/slgserver/logic/mgr/role_res_mgr.go +++ b/server/slgserver/logic/mgr/role_res_mgr.go @@ -13,7 +13,7 @@ import ( ) type roleResMgr struct { - mutex sync.RWMutex + mutex sync.RWMutex rolesRes map[int]*model.RoleRes } @@ -31,7 +31,7 @@ func GetYield(rid int) model.Yield { y.Stone = by.Stone + cy.Stone + static_conf.Basic.Role.StoneYield y.Iron = by.Iron + cy.Iron + static_conf.Basic.Role.IronYield y.Grain = by.Grain + cy.Grain + static_conf.Basic.Role.GrainYield - y.Wood = by.Wood + cy.Wood + static_conf.Basic.Role.WoodYield + y.Wood = by.Wood + cy.Wood + static_conf.Basic.Role.WoodYield return y } @@ -41,7 +41,7 @@ func GetDepotCapacity(rid int) int { return RFMgr.GetDepotCapacity(rid) + static_conf.Basic.Role.DepotCapacity } -func (this*roleResMgr) Load() { +func (this *roleResMgr) Load() { rr := make([]*model.RoleRes, 0) err := db.MasterDB.Find(&rr) @@ -57,13 +57,12 @@ func (this*roleResMgr) Load() { } +func (this *roleResMgr) Get(rid int) (*model.RoleRes, bool) { -func (this*roleResMgr) Get(rid int) (*model.RoleRes, bool){ - this.mutex.RLock() r, ok := this.rolesRes[rid] this.mutex.RUnlock() - + if ok { return r, true } @@ -71,36 +70,36 @@ func (this*roleResMgr) Get(rid int) (*model.RoleRes, bool){ m := &model.RoleRes{} ok, err := db.MasterDB.Table(new(model.RoleRes)).Where("rid=?", rid).Get(m) if ok { - + this.mutex.Lock() this.rolesRes[rid] = m this.mutex.Unlock() - + return m, true - }else{ - if err == nil{ + } else { + if err == nil { slog.Warn("RoleRes not found", "rid", rid) return nil, false - }else{ + } else { slog.Warn("db error", "error", err) return nil, false } } } -func (this*roleResMgr) Add(res *model.RoleRes) (){ - +func (this *roleResMgr) Add(res *model.RoleRes) { + this.mutex.Lock() this.rolesRes[res.RId] = res this.mutex.Unlock() } -func (this*roleResMgr) TryUseNeed(rid int, need facility.NeedRes) int{ - +func (this *roleResMgr) TryUseNeed(rid int, need facility.NeedRes) int { + this.mutex.RLock() rr, ok := this.rolesRes[rid] this.mutex.RUnlock() - + if ok { if need.Decree <= rr.Decree && need.Grain <= rr.Grain && need.Stone <= rr.Stone && need.Wood <= rr.Wood && @@ -114,60 +113,58 @@ func (this*roleResMgr) TryUseNeed(rid int, need facility.NeedRes) int{ rr.SyncExecute() return constant.OK - }else{ - if need.Decree > rr.Decree{ + } else { + if need.Decree > rr.Decree { return constant.DecreeNotEnough - }else{ + } else { return constant.ResNotEnough } } - }else { + } else { return constant.RoleNotExist } } //政令是否足够 -func (this*roleResMgr) DecreeIsEnough(rid int, cost int) bool { - +func (this *roleResMgr) DecreeIsEnough(rid int, cost int) bool { + this.mutex.RLock() rr, ok := this.rolesRes[rid] this.mutex.RUnlock() - + if ok { if rr.Decree >= cost { return true - }else{ + } else { return false } - }else{ + } else { return false } } -func (this*roleResMgr) TryUseDecree(rid int, decree int) bool{ - +func (this *roleResMgr) TryUseDecree(rid int, decree int) bool { + this.mutex.RLock() rr, ok := this.rolesRes[rid] this.mutex.RUnlock() - + if ok { if rr.Decree >= decree { rr.Decree -= decree rr.SyncExecute() return true - }else{ + } else { return false } - }else{ + } else { return false } } - - //金币是否足够 -func (this*roleResMgr) GoldIsEnough(rid int, cost int) bool { - +func (this *roleResMgr) GoldIsEnough(rid int, cost int) bool { + this.mutex.RLock() rr, ok := this.rolesRes[rid] this.mutex.RUnlock() @@ -175,74 +172,111 @@ func (this*roleResMgr) GoldIsEnough(rid int, cost int) bool { if ok { if rr.Gold >= cost { return true - }else{ + } else { return false } - }else{ + } else { return false } } +func (this *roleResMgr) TryUseGold(rid int, gold int) bool { -func (this*roleResMgr) TryUseGold(rid int, gold int) bool{ - this.mutex.RLock() rr, ok := this.rolesRes[rid] this.mutex.RUnlock() - + if ok { if rr.Gold >= gold { rr.Gold -= gold rr.SyncExecute() return true - }else{ + } else { return false } - }else{ + } else { return false } } - -func (this*roleResMgr) produce() { +func (this *roleResMgr) produce() { index := 1 for true { t := static_conf.Basic.Role.RecoveryTime time.Sleep(time.Duration(t) * time.Second) this.mutex.RLock() + + // 收集需要更新的角色资源 + updateList := make([]*model.RoleRes, 0, len(this.rolesRes)) for _, v := range this.rolesRes { //加判断是因为爆仓了,资源不无故减少 capacity := GetDepotCapacity(v.RId) yield := GetYield(v.RId) - if v.Wood < capacity{ + needUpdate := false + + if v.Wood < capacity { v.Wood += util.MinInt(yield.Wood/6, capacity) + needUpdate = true } - if v.Iron < capacity{ + if v.Iron < capacity { v.Iron += util.MinInt(yield.Iron/6, capacity) + needUpdate = true } - if v.Stone < capacity{ + if v.Stone < capacity { v.Stone += util.MinInt(yield.Stone/6, capacity) + needUpdate = true } - if v.Grain < capacity{ + if v.Grain < capacity { v.Grain += util.MinInt(yield.Grain/6, capacity) + needUpdate = true } - if v.Gold < capacity{ - v.Grain += util.MinInt(yield.Grain/6, capacity) + if v.Gold < capacity { + v.Gold += util.MinInt(yield.Gold/6, capacity) + needUpdate = true } - if index%6 == 0{ - if v.Decree < static_conf.Basic.Role.DecreeLimit{ - v.Decree+=1 + if index%6 == 0 { + if v.Decree < static_conf.Basic.Role.DecreeLimit { + v.Decree += 1 + needUpdate = true } } - v.SyncExecute() + + if needUpdate { + updateList = append(updateList, v) + } } index++ this.mutex.RUnlock() + + // 批量更新数据库 - 使用事务 + if len(updateList) > 0 { + sess := db.MasterDB.NewSession() + defer sess.Close() + + if err := sess.Begin(); err != nil { + slog.Warn("begin transaction error", "error", err) + continue + } + + for _, v := range updateList { + if _, err := sess.ID(v.RId).Cols("wood", "iron", "stone", "grain", "gold", "decree").Update(v); err != nil { + slog.Warn("update role res error", "rid", v.RId, "error", err) + sess.Rollback() + goto CONTINUE + } + } + + if err := sess.Commit(); err != nil { + slog.Warn("commit transaction error", "error", err) + } else { + slog.Debug("batch update role resources", "count", len(updateList)) + } + } + CONTINUE: } } -