go_dreamfactory/modules/parkour/module.go
2023-11-21 16:06:25 +08:00

764 lines
19 KiB
Go

package parkour
import (
"context"
"fmt"
"go_dreamfactory/comm"
"go_dreamfactory/lego/base"
"go_dreamfactory/lego/core"
"go_dreamfactory/lego/sys/event"
"go_dreamfactory/lego/sys/log"
"go_dreamfactory/lego/sys/timewheel"
"go_dreamfactory/modules"
"go_dreamfactory/pb"
cfg "go_dreamfactory/sys/configure/structs"
"sync"
"time"
"go.mongodb.org/mongo-driver/bson/primitive"
)
/*
模块名:跑酷系统
描述:捕羊大赛
开发:李伟
*/
const moduleName = "补羊大赛"
var _ comm.IParkour = (*Parkour)(nil)
func NewModule() core.IModule {
m := new(Parkour)
return m
}
type Parkour struct {
modules.ModuleBase
service base.IRPCXService
dragon comm.IDragon
api *apiComp
ai *aiComp
matchTrain *matchTrainComp
matchrank *matchrankComp
configure *configureComp
parkourComp *ModelParkourComp
lock sync.RWMutex
battles map[string]*RaceItem
}
// 模块名
func (this *Parkour) GetType() core.M_Modules {
return comm.ModuleParkour
}
// 模块初始化
func (this *Parkour) Init(service core.IService, module core.IModule, options core.IModuleOptions) (err error) {
if err = this.ModuleBase.Init(service, module, options); err != nil {
return
}
this.service = service.(base.IRPCXService)
this.battles = map[string]*RaceItem{}
return
}
func (this *Parkour) Start() (err error) {
if err = this.ModuleBase.Start(); err != nil {
return
}
// this.service.RegisterFunctionName(string(comm.RPC_ParkourMatchSucc), this.createbattle)
this.service.RegisterFunctionName(string(comm.RPC_ParkourTrusteeship), this.trusteeship)
event.RegisterGO(comm.EventUserOffline, this.useroffline)
var module core.IModule
if module, err = this.service.GetModule(comm.ModuleDragon); err != nil {
return
}
this.dragon = module.(comm.IDragon)
return
}
// 装备组件
func (this *Parkour) OnInstallComp() {
this.ModuleBase.OnInstallComp()
this.api = this.RegisterComp(new(apiComp)).(*apiComp)
this.ai = this.RegisterComp(new(aiComp)).(*aiComp)
this.matchTrain = this.RegisterComp(new(matchTrainComp)).(*matchTrainComp)
this.matchrank = this.RegisterComp(new(matchrankComp)).(*matchrankComp)
this.configure = this.RegisterComp(new(configureComp)).(*configureComp)
this.parkourComp = this.RegisterComp(new(ModelParkourComp)).(*ModelParkourComp)
}
// 匹配成功 创建战斗
func (this *Parkour) createbattle(rtype pb.RaceType, red []*pb.DBRaceMember, bule []*pb.DBRaceMember) (err error) {
var (
race *pb.DBRace
battle *RaceItem
sessions []comm.IUserSession = make([]comm.IUserSession, 0)
)
this.Debug("createbattle", log.Field{Key: "red", Value: red}, log.Field{Key: "bule", Value: bule})
race = &pb.DBRace{
Id: primitive.NewObjectID().Hex(),
ServicePath: fmt.Sprintf("%s/%s", this.service.GetType(), this.service.GetId()),
Redmember: red,
Bulemember: bule,
}
battle = &RaceItem{
Id: race.Id,
Rtype: rtype,
Session: make(map[string]comm.IUserSession),
}
for _, v := range red {
v.Currhp = v.Property[comm.Dhp]
if !v.Isai { //非AI
session, online := this.GetUserSession(v.User.Uid)
v.Isoff = !online
if online {
battle.Session[v.User.Uid] = session
}
if err = this.parkourComp.Change(v.User.Uid, map[string]interface{}{
"state": pb.RaceTeamState_raceing,
"rtype": rtype,
"roomid": battle.Id,
"roompath": race.ServicePath,
}); err != nil {
this.Errorln(err)
return
}
} else {
v.Ready = true
}
}
battle.RedMember = red
for _, v := range bule {
v.Currhp = v.Property[comm.Dhp]
if !v.Isai { //非AI
session, online := this.GetUserSession(v.User.Uid)
v.Isoff = !online
if online {
battle.Session[v.User.Uid] = session
}
} else {
v.Ready = true
}
}
battle.BuleMember = bule
for _, v := range battle.Session {
sessions = append(sessions, v)
}
this.lock.Lock()
this.battles[race.Id] = battle
this.lock.Unlock()
if err = this.SendMsgToSession(string(this.GetType()), "racematchsucc", &pb.ParkourRaceMatchSuccPush{
Race: race,
}, sessions...); err != nil {
this.Errorln(err)
}
return
}
func (this *Parkour) startbattle(id string) {
this.Debug("startbattle", log.Field{Key: "id", Value: id})
var (
battle *RaceItem
ok bool
member []*pb.DBRaceMember = make([]*pb.DBRaceMember, 0)
sessions []comm.IUserSession = make([]comm.IUserSession, 0)
err error
)
this.lock.RLock()
battle, ok = this.battles[id]
this.lock.RUnlock()
if ok {
for _, v := range battle.RedMember {
if v.Isai {
member = append(member, v)
}
}
for _, v := range battle.BuleMember {
if v.Isai {
member = append(member, v)
}
}
if err = this.ai.createAi(battle.Id, battle.Rtype, member); err != nil {
this.Errorln(err)
return
}
for _, v := range battle.Session {
sessions = append(sessions, v)
}
battle.overtimer = timewheel.Add(time.Duration(this.ModuleTools.GetGlobalConf().BuzkashiTime)*time.Second, this.overtimer, battle.Id)
if err = this.SendMsgToSession(string(this.GetType()), "racestart", &pb.ParkourRaceStartPush{
Countdown: 3,
}, sessions...); err != nil {
this.Errorln(err)
}
}
}
// 射门
func (this *Parkour) qte(id string, uid string, time float32, conf *cfg.GameBuzkashiQteLvData) {
this.Debug("qte", log.Field{Key: "id", Value: id}, log.Field{Key: "time", Value: time})
var (
battle *RaceItem
side int32
ok bool
member *pb.DBRaceMember
teamScores int32
sessions []comm.IUserSession = make([]comm.IUserSession, 0)
err error
)
this.lock.RLock()
battle, ok = this.battles[id]
this.lock.RUnlock()
if ok {
ok = false
for _, v := range battle.RedMember {
if v.User.Uid == uid {
ok = true
v.Scores += conf.Value
side = 1
member = v
break
}
}
if !ok {
for _, v := range battle.BuleMember {
if v.User.Uid == uid {
ok = true
v.Scores += conf.Value
side = 2
member = v
break
}
}
}
if !ok {
this.Error("qte on found Member !", log.Field{Key: "uid", Value: uid})
return
}
if side == 1 {
battle.RedScore += conf.Value
teamScores = battle.RedScore
} else {
battle.BuleScore += conf.Value
teamScores = battle.BuleScore
}
for _, v := range battle.Session {
sessions = append(sessions, v)
}
if err = this.SendMsgToSession(string(this.GetType()), "qteoperate", &pb.ParkourQTEOperatePush{
Uid: uid,
Time: time,
Teamscore: teamScores,
Playerscore: member.Scores,
}, sessions...); err != nil {
this.Errorln(err)
}
}
}
// 射门
func (this *Parkour) shot(id string, uid string) {
this.Debug("shot", log.Field{Key: "id", Value: id})
var (
battle *RaceItem
side int32
ok bool
member *pb.DBRaceMember
teamScores int32
sessions []comm.IUserSession = make([]comm.IUserSession, 0)
err error
)
this.lock.RLock()
battle, ok = this.battles[id]
this.lock.RUnlock()
if ok {
ok = false
for _, v := range battle.RedMember {
if v.User.Uid == uid {
v.Scores += this.ModuleTools.GetGlobalConf().BuzkashiGoalscore
v.Shot++
ok = true
side = 1
member = v
}
}
if !ok {
for _, v := range battle.BuleMember {
if v.User.Uid == uid {
v.Scores += this.ModuleTools.GetGlobalConf().BuzkashiGoalscore
v.Shot++
ok = true
side = 2
member = v
}
}
}
if !ok {
this.Error("shot on found Member !", log.Field{Key: "uid", Value: uid})
return
}
if side == 1 {
battle.RedScore += this.ModuleTools.GetGlobalConf().BuzkashiGoalteamscore
teamScores = battle.RedScore
} else {
battle.BuleScore += this.ModuleTools.GetGlobalConf().BuzkashiGoalteamscore
teamScores = battle.BuleScore
}
for _, v := range battle.Session {
sessions = append(sessions, v)
}
if err = this.SendMsgToSession(string(this.GetType()), "shotoperate", &pb.ParkourShotOperatePush{
Uid: uid,
Shotnum: member.Shot,
Teamscore: teamScores,
Playerscore: member.Scores,
}, sessions...); err != nil {
this.Errorln(err)
}
}
}
// 躲避障碍物
func (this *Parkour) avoid(id string, uid string, distance float32, atype int32, conf *cfg.GameBuzkashiGradeData) {
this.Debug("shot", log.Field{Key: "id", Value: id})
var (
battle *RaceItem
winSide int32
ok bool
member *pb.DBRaceMember
teamScores int32
sessions []comm.IUserSession = make([]comm.IUserSession, 0)
err error
)
this.lock.RLock()
battle, ok = this.battles[id]
this.lock.RUnlock()
if ok {
ok = false
for _, v := range battle.RedMember {
if v.User.Uid == uid {
member = v
ok = true
winSide = 1
teamScores = battle.RedScore
}
}
if !ok {
for _, v := range battle.BuleMember {
if v.User.Uid == uid {
member = v
ok = true
winSide = 2
teamScores = battle.BuleScore
}
}
}
if !ok {
this.Error("avoid on found Member !", log.Field{Key: "uid", Value: uid})
return
}
for _, v := range battle.Session {
sessions = append(sessions, v)
}
if conf == nil {
member.Currhp -= this.ModuleTools.GetGlobalConf().BuzkashiSpeedbumphp
if member.Currhp <= 0 {
timewheel.Add(time.Second*time.Duration(this.ModuleTools.GetGlobalConf().BuzkashiResurrection), this.resurrectiontimer, battle.Id, member.User.Uid)
}
} else {
member.Scores += conf.Value
member.Energy += conf.Energy
member.Weekintegral += conf.Matchvalue
if conf.Num == 1 {
member.Dodge++
}
teamScores += conf.Matchvalue
if winSide == 1 {
battle.RedScore = teamScores
} else {
battle.BuleScore = teamScores
}
}
if err = this.SendMsgToSession(string(this.GetType()), "avoidoperate", &pb.ParkourAvoidOperatePush{
Uid: uid,
Hp: member.Currhp,
Distance: distance,
Atype: atype,
Teamscore: teamScores,
Playerscore: member.Scores,
}, sessions...); err != nil {
this.Errorln(err)
}
}
}
// 恢复hp值
func (this *Parkour) recoverhp(id string, uid string, hp int32) {
this.Debug("recoverhp", log.Field{Key: "id", Value: id}, log.Field{Key: "hp", Value: hp}, log.Field{Key: "uid", Value: uid})
var (
battle *RaceItem
ok bool
player *pb.DBRaceMember
teamScores int32
sessions []comm.IUserSession = make([]comm.IUserSession, 0)
err error
)
this.lock.RLock()
battle, ok = this.battles[id]
this.lock.RUnlock()
if ok {
ok = false
for _, v := range battle.RedMember {
if v.User.Uid == uid {
player = v
v.Currhp += hp
if v.Currhp > v.Property[comm.Dhp] {
v.Currhp = v.Property[comm.Dhp]
}
teamScores = battle.RedScore
ok = true
break
}
}
for _, v := range battle.BuleMember {
if v.User.Uid == uid {
player = v
v.Currhp += hp
if v.Currhp > v.Property[comm.Dhp] {
v.Currhp = v.Property[comm.Dhp]
}
teamScores = battle.BuleScore
ok = true
break
}
}
if !ok {
this.Error("recoverhp on found Member !", log.Field{Key: "uid", Value: uid})
return
}
for _, v := range battle.Session {
sessions = append(sessions, v)
}
if err = this.SendMsgToSession(string(this.GetType()), "recoverhpoperate", &pb.ParkourRecoverHpOperatePush{
Uid: uid,
Hp: player.Currhp,
Teamscore: teamScores,
Playerscore: player.Scores,
}, sessions...); err != nil {
this.Errorln(err)
}
}
}
// 战斗结束
func (this *Parkour) overtimer(task *timewheel.Task, args ...interface{}) {
this.Debug("overtimer", log.Field{Key: "id", Value: args})
var (
battle *RaceItem
ok bool
side int32
sessions []comm.IUserSession = make([]comm.IUserSession, 0)
conf *cfg.GameQualifyingData
lvconf *cfg.GameBuzkashiLvData
danconf *cfg.GameQualifyingData
awards map[string][]*cfg.Gameatn = make(map[string][]*cfg.Gameatn)
award map[string][]*pb.UserAtno = make(map[string][]*pb.UserAtno)
errdata *pb.ErrorData
err error
)
id := args[0].(string)
this.lock.RLock()
battle, ok = this.battles[id]
this.lock.RUnlock()
if ok {
this.lock.Lock()
delete(this.battles, id)
this.lock.Unlock()
this.ai.removeAi(id)
if battle.RedScore > battle.BuleScore {
side = 1
for _, v := range battle.RedMember {
if conf, err = this.configure.getActiveRewardById(v.Dan); err != nil {
this.Errorln(err)
return
}
v.Integral += conf.WinValue
if lvconf, err = this.configure.getGameBuzkashiLv(v.Scores); err != nil {
this.Errorln(err)
return
}
v.Rating = lvconf.Num
v.Weekintegral += lvconf.Point
if !v.Isai {
if battle.Rtype == pb.RaceType_ordinary {
awards[v.User.Uid] = conf.MatewinReward
} else {
awards[v.User.Uid] = conf.RankwinReward
}
}
}
for _, v := range battle.BuleMember {
if conf, err = this.configure.getActiveRewardById(v.Dan); err != nil {
this.Errorln(err)
return
}
v.Integral += conf.FailValue
if lvconf, err = this.configure.getGameBuzkashiLv(v.Scores); err != nil {
this.Errorln(err)
return
}
v.Rating = lvconf.Num
v.Weekintegral += lvconf.Point
if !v.Isai {
if battle.Rtype == pb.RaceType_ordinary {
awards[v.User.Uid] = conf.MatefailReward
} else {
awards[v.User.Uid] = conf.RankfailReward
}
}
}
} else {
side = 2
for _, v := range battle.RedMember {
if conf, err = this.configure.getActiveRewardById(v.Dan); err != nil {
this.Errorln(err)
return
}
v.Integral += conf.FailValue
if lvconf, err = this.configure.getGameBuzkashiLv(v.Scores); err != nil {
this.Errorln(err)
return
}
v.Rating = lvconf.Num
v.Weekintegral += lvconf.Point
if !v.Isai {
if battle.Rtype == pb.RaceType_ordinary {
awards[v.User.Uid] = conf.MatefailReward
} else {
awards[v.User.Uid] = conf.RankfailReward
}
}
}
for _, v := range battle.BuleMember {
if conf, err = this.configure.getActiveRewardById(v.Dan); err != nil {
this.Errorln(err)
return
}
v.Integral += conf.WinValue
if lvconf, err = this.configure.getGameBuzkashiLv(v.Scores); err != nil {
this.Errorln(err)
return
}
v.Rating = lvconf.Num
v.Weekintegral += lvconf.Point
if !v.Isai {
if battle.Rtype == pb.RaceType_ordinary {
awards[v.User.Uid] = conf.MatewinReward
} else {
awards[v.User.Uid] = conf.RankwinReward
}
}
}
}
for _, v := range battle.Session {
if errdata, award[v.GetUserId()] = this.DispenseAtno(v, awards[v.GetUserId()], true); errdata != nil {
this.Errorln(errdata)
return
}
v.SendMsg(string(this.GetType()), "raceover", &pb.ParkourRaceOverPush{
Winside: side,
Race: &pb.DBRace{
Id: battle.Id,
Redmember: battle.RedMember,
Redscores: battle.RedScore,
Bulemember: battle.BuleMember,
Bulescores: battle.BuleScore,
},
Award: award[v.GetUserId()],
})
go this.AsynHandleSession(v, func(session comm.IUserSession) {
this.WriteUserLog(session.GetUserId(), 0, "ParkourRaceOverPush", award[v.GetUserId()])
})
sessions = append(sessions, v)
}
for _, v := range battle.RedMember {
if !v.Isai {
if danconf, err = this.configure.getActiveRewardByS(v.Integral); err != nil {
this.Errorln(err)
continue
}
if err = this.parkourComp.Change(v.User.Uid, map[string]interface{}{
"integral": v.Integral,
"weekintegral": v.Weekintegral,
"dan": danconf.LvId,
"state": 0,
"roomid": "",
"roompath": "",
}); err != nil {
this.Errorln(err)
return
}
}
}
for _, v := range battle.BuleMember {
if !v.Isai {
if danconf, err = this.configure.getActiveRewardByS(v.Integral); err != nil {
this.Errorln(err)
continue
}
if err = this.parkourComp.Change(v.User.Uid, map[string]interface{}{
"integral": v.Integral,
"weekintegral": v.Weekintegral,
"dan": danconf.LvId,
"state": 0,
"roomid": "",
"roompath": "",
}); err != nil {
this.Errorln(err)
return
}
}
}
for _, v := range sessions {
this.ModuleBuried.TriggerBuried(v, comm.GetBuriedParam(comm.Rtype234, 1))
v.Push()
this.PutUserSession(v)
}
}
}
// 用户离线处理
func (this *Parkour) useroffline(uid, sessionid string) {
var (
info *pb.DBParkour
err error
)
if info, err = this.parkourComp.queryinfo(uid); err != nil {
this.Error("用户离线!", log.Field{Key: "err", Value: err.Error()})
return
}
if info.State == pb.RaceTeamState_matching {
if info.Rtype == pb.RaceType_ordinary {
this.matchTrain.CancelMatch(uid)
} else {
this.matchrank.CancelMatch(uid)
}
if err = this.parkourComp.Change(uid, map[string]interface{}{
"state": 0,
}); err != nil {
this.Error("用户离线! 处理数据", log.Field{Key: "uid", Value: uid}, log.Field{Key: "err", Value: err.Error()})
return
}
} else if info.State == pb.RaceTeamState_raceing {
var (
lockpath string = fmt.Sprintf("%s/%s", this.service.GetType(), this.service.GetId())
)
if lockpath != info.Roompath { //在当前房间下
_, err = this.service.RpcGo(
context.Background(),
info.Roompath,
string(comm.RPC_ParkourTrusteeship),
&pb.RPC_ParkourTrusteeshipReq{Battleid: info.Roomid, Uid: uid},
nil)
if err != nil {
this.Errorln(err)
return
}
} else {
this.trusteeship(context.Background(), &pb.RPC_ParkourTrusteeshipReq{Battleid: info.Roomid, Uid: uid}, nil)
}
}
}
// 托管
func (this *Parkour) trusteeship(ctx context.Context, req *pb.RPC_ParkourTrusteeshipReq, resp *pb.RPC_ParkourTrusteeshipResp) (err error) {
var (
battle *RaceItem
ok bool
)
this.lock.RLock()
battle, ok = this.battles[req.Battleid]
this.lock.RUnlock()
if ok {
battle.lock.Lock()
for _, v := range battle.BuleMember {
if v.User.Uid == v.User.Uid {
v.Isoff = true
}
}
for _, v := range battle.RedMember {
if v.User.Uid == v.User.Uid {
v.Isoff = true
}
}
delete(battle.Session, req.Uid)
battle.lock.Unlock()
}
return
}
// 定时复活
func (this *Parkour) resurrectiontimer(task *timewheel.Task, args ...interface{}) {
var (
battleid string
uid string
battle *RaceItem
member *pb.DBRaceMember
sessions []comm.IUserSession = make([]comm.IUserSession, 0)
ok bool
err error
)
battleid = args[0].(string)
uid = args[1].(string)
this.lock.RLock()
battle, ok = this.battles[battleid]
this.lock.RUnlock()
if ok {
ok = false
for _, v := range battle.RedMember {
if v.User.Uid == uid {
member = v
ok = true
}
}
if !ok {
for _, v := range battle.BuleMember {
if v.User.Uid == uid {
member = v
ok = true
}
}
}
if ok {
member.Currhp = member.Property[comm.Dhp]
for _, v := range battle.Session {
sessions = append(sessions, v)
}
if err = this.SendMsgToSession(string(this.GetType()), "revivalplayer", &pb.ParkourRevivalPlayerPush{
Uid: uid,
Hp: member.Currhp,
}, sessions...); err != nil {
this.Errorln(err)
}
}
} else {
this.Error("战斗结束 复活失效", log.Field{Key: "bid", Value: battleid})
}
}