go_dreamfactory/modules/parkour/module.go
2023-06-15 22:43:35 +08:00

705 lines
17 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"
"sync"
"time"
"go.mongodb.org/mongo-driver/bson/primitive"
)
/*
模块名:跑酷系统
描述:捕羊大赛
开发:李伟
*/
var _ comm.IParkour = (*Parkour)(nil)
func NewModule() core.IModule {
m := new(Parkour)
return m
}
type Parkour struct {
modules.ModuleBase
service base.IRPCXService
api *apiComp
ai *aiComp
configure *configureComp
parkourComp *ModelParkourComp
raceComp *ModelRaceComp
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) {
err = this.ModuleBase.Init(service, module, options)
this.service = service.(base.IRPCXService)
this.battles = map[string]*RaceItem{}
return
}
func (this *Parkour) Start() (err error) {
err = this.ModuleBase.Start()
this.service.RegisterFunctionName(string(comm.RPC_ParkourMatchSucc), this.createbattle)
event.RegisterGO(comm.EventUserOffline, this.useroffline)
return
}
//装备组件
func (this *Parkour) OnInstallComp() {
this.ModuleBase.OnInstallComp()
this.api = this.RegisterComp(new(apiComp)).(*apiComp)
this.ai = this.RegisterComp(new(aiComp)).(*aiComp)
this.configure = this.RegisterComp(new(configureComp)).(*configureComp)
this.parkourComp = this.RegisterComp(new(ModelParkourComp)).(*ModelParkourComp)
this.raceComp = this.RegisterComp(new(ModelRaceComp)).(*ModelRaceComp)
}
//添加坐骑资源
func (this *Parkour) AddMounts(session comm.IUserSession, mounts map[string]int32, bPush bool) (errdata *pb.ErrorData) {
var (
result *pb.DBParkour
err error
)
if result, err = this.parkourComp.addUserMounts(session.GetUserId(), mounts); err != nil {
errdata = &pb.ErrorData{
Code: pb.ErrorCode_DBError,
Title: pb.ErrorCode_DBError.ToString(),
Message: err.Error(),
}
return
}
if bPush {
session.SendMsg(string(this.GetType()), "infochange", &pb.ParkourInfoChangePush{Info: result})
}
return
}
//匹配
func (this *Parkour) match(team *pb.DBParkour) (err error) {
ctx, _ := context.WithTimeout(context.Background(), time.Second*5)
err = this.service.RpcCall(
ctx,
comm.Service_Mainte,
string(comm.RPC_ParkourJoinMatch),
&pb.RPCParkourJoinMatchReq{Captainid: team.Captainid, Member: team.Member},
&pb.RPCParkourJoinMatchResp{})
if err != nil {
this.Errorln(err)
return
}
return
}
//匹配成功 创建战斗
func (this *Parkour) createbattle(ctx context.Context, req *pb.RPCParkourMatchSuccReq, resp *pb.RPCParkourMatchSuccResp) (err error) {
var (
race *pb.DBRace
battle *RaceItem
sessions []comm.IUserSession = make([]comm.IUserSession, 0)
)
this.Debug("createbattle", log.Field{Key: "req", Value: req.String()})
race = &pb.DBRace{
Id: primitive.NewObjectID().Hex(),
ServicePath: fmt.Sprintf("%s/%s", this.service.GetType(), this.service.GetId()),
Redmember: req.Red,
Bulemember: req.Bule,
}
battle = &RaceItem{
Id: race.Id,
Session: make(map[string]comm.IUserSession),
overtimer: timewheel.Add(time.Minute*3, this.overtimer, race.Id),
}
for _, v := range req.Red {
v.Currhp = v.Maxhp
if !v.Isai { //非AI
session, online := this.GetUserSession(v.Uid)
v.Isoff = !online
if online {
battle.Session[v.Uid] = session
}
} else {
v.Ready = true
}
}
battle.RedMember = req.Red
for _, v := range req.Bule {
v.Currhp = v.Maxhp
if !v.Isai { //非AI
session, online := this.GetUserSession(v.Uid)
v.Isoff = !online
if online {
battle.Session[v.Uid] = session
}
} else {
v.Ready = true
}
}
battle.BuleMember = req.Bule
for _, v := range battle.Session {
sessions = append(sessions, v)
}
if err = this.raceComp.addrace(race); err != nil {
return
}
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, member); err != nil {
this.Errorln(err)
return
}
for _, v := range battle.Session {
sessions = append(sessions, v)
}
if err = this.SendMsgToSession(string(this.GetType()), "racestart", &pb.ParkourRaceStartPush{
Countdown: 3,
}, 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
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.Uid == uid {
ok = true
side = 1
}
}
if !ok {
for _, v := range battle.BuleMember {
if v.Uid == uid {
ok = true
side = 2
}
}
}
if side == 1 {
battle.RedScore += 3
} else {
battle.BuleScore += 3
}
for _, v := range battle.Session {
sessions = append(sessions, v)
}
if err = this.SendMsgToSession(string(this.GetType()), "scorechanage", &pb.ParkourScoreChanagePush{
Redscore: battle.RedScore,
Redenergy: battle.RedEnergy,
Bluescore: battle.BuleScore,
Blueenergy: battle.BuleEnergy,
}, sessions...); err != nil {
this.Errorln(err)
}
}
}
//躲避障碍物
func (this *Parkour) avoid(id string, uid string, dis float32) {
this.Debug("shot", log.Field{Key: "id", Value: id})
var (
battle *RaceItem
ok bool
side int32
member *pb.DBRaceMember
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.Uid == uid {
member = v
ok = true
side = 1
}
}
if !ok {
for _, v := range battle.BuleMember {
if v.Uid == uid {
member = v
ok = true
side = 2
}
}
}
if !ok {
this.Error("躲避障碍物逻辑异常 未找到玩家!", log.Field{Key: "battleid", Value: id}, log.Field{Key: "uid", Value: uid})
return
}
for _, v := range battle.Session {
sessions = append(sessions, v)
}
if dis < 0 {
member.Currhp--
if member.Currhp <= 0 {
timewheel.Add(time.Second*10, this.resurrectiontimer, battle.Id, member.Uid)
}
} else {
if side == 1 {
battle.RedEnergy += 3
} else {
battle.BuleEnergy += 3
}
if err = this.SendMsgToSession(string(this.GetType()), "playerhpchanage", &pb.ParkourScoreChanagePush{
Redscore: battle.RedScore,
Redenergy: battle.RedEnergy,
Bluescore: battle.BuleScore,
Blueenergy: battle.BuleEnergy,
}, sessions...); err != nil {
this.Errorln(err)
}
}
if err = this.SendMsgToSession(string(this.GetType()), "playerhpchanage", &pb.ParkourPlayerHPChanagePush{
Change: map[string]int32{uid: member.Currhp},
}, sessions...); err != nil {
this.Errorln(err)
}
}
}
//恢复hp值
func (this *Parkour) recoverhp(id string, hp int32, uids ...string) {
this.Debug("recoverhp", log.Field{Key: "id", Value: id}, log.Field{Key: "hp", Value: hp}, log.Field{Key: "uids", Value: uids})
var (
battle *RaceItem
ok bool
chanage map[string]int32 = make(map[string]int32)
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 {
for _, v1 := range uids {
if v.Uid == v1 {
v.Currhp += hp
if v.Currhp > v.Maxhp {
v.Currhp = v.Maxhp
}
chanage[v.Uid] = v.Currhp
break
}
}
}
for _, v := range battle.BuleMember {
for _, v1 := range uids {
if v.Uid == v1 {
v.Currhp += hp
if v.Currhp > v.Maxhp {
v.Currhp = v.Maxhp
}
chanage[v.Uid] = v.Currhp
break
}
}
}
for _, v := range battle.Session {
sessions = append(sessions, v)
}
if err = this.SendMsgToSession(string(this.GetType()), "playerhpchanage", &pb.ParkourPlayerHPChanagePush{
Change: chanage,
}, sessions...); err != nil {
this.Errorln(err)
}
}
}
//战斗结束
func (this *Parkour) overtimer(task *timewheel.Task, args ...interface{}) {
this.Debug("shot", log.Field{Key: "id", Value: args})
var (
battle *RaceItem
ok bool
side int32
sessions []comm.IUserSession = make([]comm.IUserSession, 0)
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.raceComp.delrace(id)
this.ai.removeAi(id)
if battle.RedScore > battle.BuleScore {
side = 1
} else {
side = 2
}
for _, v := range battle.Session {
sessions = append(sessions, v)
}
if err = this.SendMsgToSession(string(this.GetType()), "raceover", &pb.ParkourRaceOverPush{
Winside: side,
}, sessions...); err != nil {
this.Errorln(err)
return
}
for _, v := range battle.RedMember {
if !v.Isai {
if err = this.parkourComp.Change(v.Uid, map[string]interface{}{
"captainid": "",
"state": 0,
"invite": []*pb.DBRaceInvite{},
"member": []*pb.DBRaceMember{},
}); err != nil {
this.Errorln(err)
return
}
}
}
for _, v := range battle.BuleMember {
if !v.Isai {
if err = this.parkourComp.Change(v.Uid, map[string]interface{}{
"captainid": "",
"state": 0,
"invite": []*pb.DBRaceInvite{},
"member": []*pb.DBRaceMember{},
}); err != nil {
this.Errorln(err)
return
}
}
}
}
}
//用户离线处理
func (this *Parkour) useroffline(uid, sessionid string) {
var (
info *pb.DBParkour
team *pb.DBParkour
member *pb.DBRaceMember
users []string
keep bool
index int32
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_teaming {
if info.Captainid == uid {
users = make([]string, 0)
for _, v := range info.Member {
if v.Uid != uid && !v.Isai {
users = append(users, v.Uid)
if err = this.parkourComp.Change(v.Uid, map[string]interface{}{
"captainid": "",
"state": 0,
}); err != nil {
this.Error("用户离线! 解散队伍处理", log.Field{Key: "uid", Value: v.Uid}, log.Field{Key: "err", Value: err.Error()})
return
}
}
}
info.Invite = info.Invite[:0]
info.Member = info.Member[:0]
if err = this.parkourComp.Change(uid, map[string]interface{}{
"captainid": "",
"state": 0,
"Invite": info.Invite,
"member": info.Member,
}); err != nil {
this.Error("用户离线! 处理数据", log.Field{Key: "uid", Value: uid}, log.Field{Key: "err", Value: err.Error()})
return
}
if len(users) > 0 {
if err = this.SendMsgToUsers(string(comm.ModulePvp), "teamdisbandnotice", &pb.ParkourTeamDisbandNoticePush{}, users...); err != nil {
this.Errorln(err)
}
}
} else {
if team, err = this.parkourComp.queryinfo(info.Captainid); err != nil {
this.Error("用户离线!", log.Field{Key: "Captainid", Value: info.Captainid}, log.Field{Key: "err", Value: err.Error()})
return
}
users = make([]string, 0)
for i, v := range team.Member {
if v.Uid == uid {
index = int32(i)
member = v
keep = true
continue
}
if v.Uid != uid && !v.Isai {
users = append(users, v.Uid)
}
}
if keep {
team.Member = append(team.Member[0:index], team.Member[index+1:]...)
if err = this.parkourComp.Change(team.Uid, map[string]interface{}{
"member": team.Member,
}); err != nil {
this.Error("用户离线! 解散队伍处理", log.Field{Key: "uid", Value: team.Uid}, log.Field{Key: "err", Value: err.Error()})
return
}
if len(users) > 0 {
this.SendMsgToUsers(string(this.GetType()), "teamquitnotice",
&pb.ParkourTeamQuitNoticePush{Member: member}, users...)
this.SendMsgToUsers(string(this.GetType()), "teamchanage",
&pb.ParkourTeamChanagePush{Team: team}, users...)
}
}
}
} else if info.State == pb.RaceTeamState_matching {
if info.Captainid == uid {
err = this.service.RpcCall(
context.Background(),
comm.Service_Mainte,
string(comm.RPC_ParkourCancelMatch),
&pb.RPCParkourCancelMatchReq{Captainid: info.Captainid},
&pb.RPCParkourCancelMatchResp{})
if err != nil {
this.Errorln(err)
return
}
if err = this.parkourComp.Change(uid, map[string]interface{}{
"captainid": "",
"state": 0,
"Invite": info.Invite,
"member": info.Member,
}); err != nil {
this.Error("用户离线! 处理数据", log.Field{Key: "uid", Value: uid}, log.Field{Key: "err", Value: err.Error()})
return
}
users = make([]string, 0)
for _, v := range info.Member {
if v.Uid != uid && !v.Isai {
users = append(users, v.Uid)
if err = this.parkourComp.Change(v.Uid, map[string]interface{}{
"captainid": "",
"state": 0,
}); err != nil {
this.Error("用户离线! 解散队伍处理", log.Field{Key: "uid", Value: v.Uid}, log.Field{Key: "err", Value: err.Error()})
return
}
}
}
if len(users) > 0 {
if err = this.SendMsgToUsers(string(comm.ModulePvp), "teamdisbandnotice", &pb.ParkourTeamDisbandNoticePush{}, users...); err != nil {
this.Errorln(err)
}
}
}
} else if info.State == pb.RaceTeamState_raceing {
var (
lockpath string = fmt.Sprintf("%s/%s", this.service.GetType(), this.service.GetId())
result []*pb.DBRace
)
if result, err = this.raceComp.queryraces(); err != nil {
this.Errorln(err)
return
}
for _, v := range result {
for _, v1 := range v.Redmember {
if !v1.Isai && v1.Uid == uid {
if lockpath == v.ServicePath {
this.trusteeship(context.Background(), &pb.RPC_ParkourTrusteeshipReq{Battleid: v.Id, Uid: uid}, nil)
return
} else {
ctx, _ := context.WithTimeout(context.Background(), time.Second*5)
_, err = this.service.RpcGo(
ctx,
comm.Service_Mainte,
string(comm.RPC_ParkourJoinMatch),
&pb.RPC_ParkourTrusteeshipReq{Battleid: v.Id, Uid: uid},
nil)
if err != nil {
this.Errorln(err)
return
}
return
}
}
}
for _, v1 := range v.Bulemember {
if !v1.Isai && v1.Uid == uid {
if lockpath == v.ServicePath {
this.trusteeship(context.Background(), &pb.RPC_ParkourTrusteeshipReq{Battleid: v.Id, Uid: uid}, nil)
return
} else {
ctx, _ := context.WithTimeout(context.Background(), time.Second*5)
_, err = this.service.RpcGo(
ctx,
comm.Service_Mainte,
string(comm.RPC_ParkourJoinMatch),
&pb.RPC_ParkourTrusteeshipReq{Battleid: v.Id, Uid: uid},
nil)
if err != nil {
this.Errorln(err)
return
}
return
}
}
}
}
}
}
//托管
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.Uid == v.Uid {
v.Isoff = true
}
}
for _, v := range battle.RedMember {
if v.Uid == v.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.Uid == uid {
member = v
ok = true
}
}
if !ok {
for _, v := range battle.BuleMember {
if v.Uid == uid {
member = v
ok = true
}
}
}
if ok {
member.Currhp = 2
for _, v := range battle.Session {
sessions = append(sessions, v)
}
if err = this.SendMsgToSession(string(this.GetType()), "playerhpchanage", &pb.ParkourPlayerHPChanagePush{
Change: map[string]int32{uid: member.Currhp},
}, sessions...); err != nil {
this.Errorln(err)
}
}
} else {
this.Error("战斗结束 复活失效", log.Field{Key: "bid", Value: battleid})
}
}