514 lines
14 KiB
Go
514 lines
14 KiB
Go
package pvp
|
|
|
|
import (
|
|
"encoding/json"
|
|
"fmt"
|
|
"go_dreamfactory/comm"
|
|
"go_dreamfactory/lego/base"
|
|
"go_dreamfactory/lego/core"
|
|
"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"
|
|
"google.golang.org/protobuf/proto"
|
|
)
|
|
|
|
/*
|
|
模块名:支付系统
|
|
描述:充值商城
|
|
开发:李伟
|
|
*/
|
|
func NewModule() core.IModule {
|
|
m := new(Pvp)
|
|
return m
|
|
}
|
|
|
|
type Pvp struct {
|
|
modules.ModuleBase
|
|
service base.IRPCXService
|
|
battle comm.IBattle
|
|
gameInvite comm.IGameInvite
|
|
practice comm.IPractice
|
|
apicomp *apiComp
|
|
modelPvpComp *modelPvpComp
|
|
lock sync.RWMutex
|
|
battles map[string]*BattleItem
|
|
}
|
|
|
|
// 模块名
|
|
func (this *Pvp) GetType() core.M_Modules {
|
|
return comm.ModulePvp
|
|
}
|
|
|
|
// 模块初始化接口 注册用户创建角色事件
|
|
func (this *Pvp) Init(service core.IService, module core.IModule, options core.IModuleOptions) (err error) {
|
|
this.battles = make(map[string]*BattleItem)
|
|
if err = this.ModuleBase.Init(service, module, options); err != nil {
|
|
return
|
|
}
|
|
this.service = service.(base.IRPCXService)
|
|
return
|
|
}
|
|
|
|
func (this *Pvp) Start() (err error) {
|
|
if err = this.ModuleBase.Start(); err != nil {
|
|
return
|
|
}
|
|
var module core.IModule
|
|
if module, err = this.service.GetModule(comm.ModuleBattle); err != nil {
|
|
return
|
|
}
|
|
this.battle = module.(comm.IBattle)
|
|
if module, err = this.service.GetModule(comm.ModuleGameInvite); err != nil {
|
|
return
|
|
}
|
|
this.gameInvite = module.(comm.IGameInvite)
|
|
if module, err = this.service.GetModule(comm.ModulePractice); err != nil {
|
|
return
|
|
}
|
|
this.practice = module.(comm.IPractice)
|
|
// event.RegisterGO(comm.EventUserLogin, this.userlogin)
|
|
// event.RegisterGO(comm.EventUserOffline, this.useroffline)
|
|
// this.service.RegisterFunctionName(string(comm.RPC_PVPTrusteeship), this.trusteeship)
|
|
return
|
|
}
|
|
|
|
// 装备组件
|
|
func (this *Pvp) OnInstallComp() {
|
|
this.ModuleBase.OnInstallComp()
|
|
this.apicomp = this.RegisterComp(new(apiComp)).(*apiComp)
|
|
this.modelPvpComp = this.RegisterComp(new(modelPvpComp)).(*modelPvpComp)
|
|
}
|
|
|
|
func (this *Pvp) QueryBattle(id string) (battle *pb.DBPvpBattle, err error) {
|
|
battle, err = this.modelPvpComp.querypvp(id)
|
|
return
|
|
}
|
|
|
|
// 创建Pvp
|
|
func (this *Pvp) CreateRoom(sessions []comm.IUserSession, rulesStr string) (roomid string, err error) {
|
|
this.Debug("CreatePvp", log.Field{Key: "rulesStr", Value: rulesStr}, log.Field{Key: "sessions", Value: sessions})
|
|
var (
|
|
rules *pb.DBPvpRules = &pb.DBPvpRules{}
|
|
battle *BattleItem
|
|
red, blue *pb.DBUser
|
|
)
|
|
if err = json.Unmarshal([]byte(rulesStr), rules); err != nil {
|
|
this.Error("解析规则json", log.Field{Key: "err", Value: err.Error()})
|
|
return
|
|
}
|
|
roomid = primitive.NewObjectID().Hex()
|
|
battle = &BattleItem{
|
|
Id: roomid,
|
|
Ptype: rules.Ptype,
|
|
State: pb.PvpState_ready,
|
|
RedSession: sessions[0],
|
|
BlueSession: sessions[1],
|
|
Red: comm.GetUserBaseInfo(red),
|
|
Blue: comm.GetUserBaseInfo(blue),
|
|
readytimer: timewheel.Add(time.Second*60, this.readyTimeOut, roomid),
|
|
curroperate: &pb.ComWaitInputSkill{},
|
|
}
|
|
//发起者 red
|
|
red, err = this.ModuleUser.GetUser(sessions[0].GetUserId())
|
|
if err != nil {
|
|
this.Error("未找到红方信息", log.Field{Key: "uid", Value: sessions[0].GetUserId()})
|
|
return
|
|
}
|
|
blue, err = this.ModuleUser.GetUser(sessions[1].GetUserId())
|
|
if err != nil {
|
|
this.Error("未找到蓝方信息", log.Field{Key: "uid", Value: sessions[1].GetUserId()})
|
|
return
|
|
}
|
|
this.lock.Lock()
|
|
this.battles[battle.Id] = battle
|
|
this.lock.Unlock()
|
|
if err = this.SendMsgToSession(string(comm.ModulePvp), "ready", &pb.PvpReadyPush{
|
|
ServicePath: fmt.Sprintf("%s/%s", this.service.GetType(), this.service.GetId()),
|
|
Battleid: battle.Id,
|
|
Red: battle.Red,
|
|
Blue: battle.Blue,
|
|
Countdown: 60,
|
|
}, battle.RedSession, battle.BlueSession); err != nil {
|
|
this.Errorln(err)
|
|
}
|
|
return
|
|
}
|
|
|
|
// 推送战斗输出指令
|
|
func (this *Pvp) PvpOutCmdPush(out *pb.PvpOutCmdPush) {
|
|
this.Debug("PvpOutCmdPush", log.Field{Key: "args", Value: out})
|
|
var (
|
|
battle *BattleItem
|
|
ok bool
|
|
errdata *pb.ErrorData
|
|
data []byte
|
|
err error
|
|
)
|
|
this.lock.RLock()
|
|
battle, ok = this.battles[out.Battleid]
|
|
this.lock.RUnlock()
|
|
if ok {
|
|
battle.lock.Lock()
|
|
if err = this.SendMsgToSession(string(comm.ModulePvp), "outcmd", &pb.PvpOutCmdPush{
|
|
Battleid: battle.Id,
|
|
Cmd: out.Cmd,
|
|
}, battle.RedSession, battle.BlueSession); err != nil {
|
|
this.Errorln(err)
|
|
}
|
|
battle.lock.Unlock()
|
|
for _, v := range out.Cmd {
|
|
if v.Cmdtype == "ComWaitInputSkill" {
|
|
if err = proto.Unmarshal(v.Value, battle.curroperate); err != nil {
|
|
this.Errorln(err)
|
|
}
|
|
if battle.curroperate.Side == 1 && battle.RedOffline { //已经离线
|
|
battle.curroperate.Auto = true
|
|
data, _ = proto.Marshal(battle.curroperate)
|
|
if errdata = this.battle.InCmdBattle(&pb.BattleInCmdReq{
|
|
Battleid: battle.Id,
|
|
Side: battle.curroperate.Side,
|
|
In: &pb.BattleCmd{
|
|
Cmdtype: "ComWaitInputSkill",
|
|
Value: data,
|
|
},
|
|
}); errdata != nil {
|
|
return
|
|
}
|
|
return
|
|
}
|
|
if battle.curroperate.Side == 2 && battle.BlueOffline { //已经离线
|
|
battle.curroperate.Auto = true
|
|
data, _ = proto.Marshal(battle.curroperate)
|
|
if errdata = this.battle.InCmdBattle(&pb.BattleInCmdReq{
|
|
Battleid: battle.Id,
|
|
Side: battle.curroperate.Side,
|
|
In: &pb.BattleCmd{
|
|
Cmdtype: "ComWaitInputSkill",
|
|
Value: data,
|
|
},
|
|
}); errdata != nil {
|
|
return
|
|
}
|
|
return
|
|
}
|
|
}
|
|
}
|
|
|
|
}
|
|
}
|
|
|
|
// 推送战斗结束
|
|
func (this *Pvp) PvpFinishPush(out *pb.BattleFinishPush) {
|
|
var (
|
|
battle *BattleItem
|
|
err error
|
|
ok bool
|
|
)
|
|
this.lock.RLock()
|
|
battle, ok = this.battles[out.Battleid]
|
|
this.lock.RUnlock()
|
|
if ok {
|
|
this.lock.RLock()
|
|
delete(this.battles, out.Battleid)
|
|
this.lock.RUnlock()
|
|
switch battle.Ptype {
|
|
case pb.PvpType_friends:
|
|
go func() {
|
|
this.gameInvite.GameInviteEnd(3, battle.Red.Uid)
|
|
this.practice.ChallengeResults(out.Battleid, battle.Red.Uid, battle.Blue.Uid, out.WinSide)
|
|
}()
|
|
break
|
|
}
|
|
this.modelPvpComp.delpvp(out.Battleid)
|
|
this.PutUserSession(battle.RedSession)
|
|
this.PutUserSession(battle.BlueSession)
|
|
if err = this.SendMsgToUsers(string(comm.ModulePvp), "finish", &pb.PvpFinishPush{
|
|
Battleid: battle.Id,
|
|
}, battle.Red.Uid, battle.Blue.Uid); err != nil {
|
|
this.Errorln(err)
|
|
}
|
|
}
|
|
}
|
|
|
|
// 准备超时 取消战斗
|
|
func (this *Pvp) readyTimeOut(task *timewheel.Task, args ...interface{}) {
|
|
this.Debug("readyTimeOut", log.Field{Key: "args", Value: args})
|
|
var (
|
|
id string
|
|
battle *BattleItem
|
|
ok bool
|
|
err error
|
|
)
|
|
id = args[0].(string)
|
|
this.lock.RLock()
|
|
battle, ok = this.battles[id]
|
|
this.lock.RUnlock()
|
|
if ok && battle.State == pb.PvpState_ready {
|
|
battle.lock.Lock()
|
|
battle.State = pb.PvpState_cancel
|
|
battle.lock.Unlock()
|
|
this.lock.Lock()
|
|
delete(this.battles, id)
|
|
this.lock.Unlock()
|
|
if err = this.SendMsgToSession(string(comm.ModulePvp), "cancel", &pb.PvpCancelPush{
|
|
ServicePath: fmt.Sprintf("%s/%s", this.service.GetType(), this.service.GetId()),
|
|
Battleid: battle.Id,
|
|
}, battle.RedSession, battle.BlueSession); err != nil {
|
|
this.Errorln(err)
|
|
}
|
|
|
|
switch battle.Ptype {
|
|
case pb.PvpType_friends:
|
|
var winside int32 = 0
|
|
if battle.Redformation != nil {
|
|
winside = 1
|
|
}
|
|
if battle.Blueformation != nil {
|
|
winside = 2
|
|
}
|
|
go func() {
|
|
this.gameInvite.GameInviteEnd(3, battle.Red.Uid)
|
|
this.practice.ChallengeResults(battle.Id, battle.Red.Uid, battle.Blue.Uid, winside)
|
|
}()
|
|
break
|
|
}
|
|
|
|
}
|
|
}
|
|
|
|
// 操作倒计时
|
|
func (this *Pvp) operateTimeOut(task *timewheel.Task, args ...interface{}) {
|
|
this.Debug("operateTimeOut", log.Field{Key: "args", Value: args})
|
|
var (
|
|
id string
|
|
battle *BattleItem
|
|
ok bool
|
|
errdata *pb.ErrorData
|
|
data []byte
|
|
)
|
|
id = args[0].(string)
|
|
this.lock.RLock()
|
|
battle, ok = this.battles[id]
|
|
this.lock.RUnlock()
|
|
if ok && battle.State == pb.PvpState_battle {
|
|
battle.curroperate.Auto = true
|
|
data, _ = proto.Marshal(battle.curroperate)
|
|
if errdata = this.battle.InCmdBattle(&pb.BattleInCmdReq{
|
|
Battleid: battle.Id,
|
|
Side: battle.curroperate.Side,
|
|
In: &pb.BattleCmd{
|
|
Cmdtype: "ComWaitInputSkill",
|
|
Value: data,
|
|
},
|
|
}); errdata != nil {
|
|
return
|
|
}
|
|
|
|
}
|
|
}
|
|
|
|
// 开始战斗
|
|
func (this *Pvp) startBattle(battle *BattleItem) {
|
|
this.Debug("PVPStart", log.Field{Key: "battleId", Value: battle.Id})
|
|
var (
|
|
record *pb.DBBattleRecord
|
|
info *pb.BattleInfo
|
|
errdata *pb.ErrorData
|
|
err error
|
|
)
|
|
if errdata, record = this.battle.CreateRtPvpBattle(&pb.BattleRTPVPReq{
|
|
Rulesid: 111,
|
|
Ptype: pb.PlayType_friendsmeet,
|
|
Title: "",
|
|
RedCompId: battle.Red.Uid,
|
|
Redformat: []*pb.BattleFormation{battle.Redformation},
|
|
BlueCompId: battle.Blue.Uid,
|
|
Bulefformat: []*pb.BattleFormation{battle.Blueformation},
|
|
}); errdata != nil {
|
|
this.lock.Lock()
|
|
delete(this.battles, battle.Id)
|
|
this.lock.Unlock()
|
|
if err = this.SendMsgToSession(string(comm.ModulePvp), "cancel", &pb.PvpCancelPush{
|
|
ServicePath: fmt.Sprintf("%s/%s", this.service.GetType(), this.service.GetId()),
|
|
Battleid: battle.Id,
|
|
}, battle.RedSession, battle.BlueSession); err != nil {
|
|
this.Errorln(err)
|
|
}
|
|
return
|
|
} else {
|
|
record.Id = battle.Id
|
|
info = &pb.BattleInfo{
|
|
Id: record.Id,
|
|
Title: record.Title,
|
|
Rulesid: 111,
|
|
Btype: record.Btype,
|
|
Ptype: record.Ptype,
|
|
RedCompId: record.RedCompId,
|
|
Redflist: record.Redflist,
|
|
BlueCompId: record.BlueCompId,
|
|
Buleflist: record.Buleflist,
|
|
}
|
|
if errdata = this.battle.CreateBattleServer(info); errdata != nil {
|
|
this.lock.Lock()
|
|
delete(this.battles, battle.Id)
|
|
this.lock.Unlock()
|
|
if err = this.SendMsgToSession(string(comm.ModulePvp), "cancel", &pb.PvpCancelPush{
|
|
ServicePath: fmt.Sprintf("%s/%s", this.service.GetType(), this.service.GetId()),
|
|
Battleid: battle.Id,
|
|
}, battle.RedSession, battle.BlueSession); err != nil {
|
|
this.Errorln(err)
|
|
}
|
|
} else {
|
|
if err = this.SendMsgToSession(string(comm.ModulePvp), "start", &pb.PvpStartPush{
|
|
Info: info,
|
|
}, battle.RedSession, battle.BlueSession); err != nil {
|
|
this.Errorln(err)
|
|
}
|
|
|
|
this.modelPvpComp.addpvp(&pb.DBPvpBattle{
|
|
Id: info.Id,
|
|
ServicePath: fmt.Sprintf("%s/%s", this.service.GetType(), this.service.GetId()),
|
|
Ptype: battle.Ptype,
|
|
State: battle.State,
|
|
Red: battle.Red,
|
|
Blue: battle.Blue,
|
|
})
|
|
}
|
|
}
|
|
}
|
|
|
|
// // 用户离线处理
|
|
// func (this *Pvp) useroffline(uid, sessionid string) {
|
|
// var (
|
|
// result []*pb.DBPvpBattle
|
|
// lockpath string = fmt.Sprintf("%s/%s", this.service.GetType(), this.service.GetId())
|
|
// service map[string][]string = make(map[string][]string)
|
|
// err error
|
|
// )
|
|
// if result, err = this.modelPvpComp.querypvps(); err != nil {
|
|
// this.Errorln(err)
|
|
// return
|
|
// }
|
|
// for _, v := range result {
|
|
// if v.Red.Uid == uid || v.Blue.Uid == uid {
|
|
// if service[v.ServicePath] == nil {
|
|
// service[v.ServicePath] = make([]string, 0)
|
|
// }
|
|
// service[v.ServicePath] = append(service[v.ServicePath], v.Id)
|
|
// }
|
|
// }
|
|
|
|
// for k, v := range service {
|
|
// if k == lockpath { //在当前服务器上
|
|
// this.trusteeship(context.Background(), &pb.RPC_PVPTrusteeshipReq{Battleid: v, Uid: uid}, nil)
|
|
// } else { //在别的服务器上
|
|
// ctx, _ := context.WithTimeout(context.Background(), time.Second*5)
|
|
// _, err = this.service.RpcGo(
|
|
// ctx,
|
|
// k,
|
|
// string(comm.RPC_PVPTrusteeship),
|
|
// &pb.RPC_PVPTrusteeshipReq{Battleid: v, Uid: uid},
|
|
// nil)
|
|
// if err != nil {
|
|
// this.Errorln(err)
|
|
// return
|
|
// }
|
|
// }
|
|
// }
|
|
|
|
// }
|
|
|
|
func (this *Pvp) UserOffline(roomid string, uid string) (err error) {
|
|
var (
|
|
battle *BattleItem
|
|
ok bool
|
|
side int32
|
|
data []byte
|
|
errdata *pb.ErrorData
|
|
)
|
|
this.lock.RLock()
|
|
battle, ok = this.battles[roomid]
|
|
this.lock.RUnlock()
|
|
if ok {
|
|
if battle.Red.Uid == uid || battle.Blue.Uid == uid {
|
|
if uid == battle.Red.Uid {
|
|
side = 1
|
|
battle.RedOffline = true
|
|
} else {
|
|
side = 2
|
|
battle.BlueOffline = true
|
|
}
|
|
|
|
if battle.curroperate.Side == side {
|
|
if battle.operatetimer != nil {
|
|
timewheel.Remove(battle.operatetimer)
|
|
}
|
|
battle.curroperate.Auto = true
|
|
data, _ = proto.Marshal(battle.curroperate)
|
|
if errdata = this.battle.InCmdBattle(&pb.BattleInCmdReq{
|
|
Battleid: battle.Id,
|
|
Side: battle.curroperate.Side,
|
|
In: &pb.BattleCmd{
|
|
Cmdtype: "ComWaitInputSkill",
|
|
Value: data,
|
|
},
|
|
}); errdata != nil {
|
|
return
|
|
}
|
|
}
|
|
}
|
|
}
|
|
return
|
|
}
|
|
|
|
// // 托管
|
|
// func (this *Pvp) trusteeship(ctx context.Context, req *pb.RPC_PVPTrusteeshipReq, resp *pb.RPC_PVPTrusteeshipResp) (err error) {
|
|
// var (
|
|
// battle *BattleItem
|
|
// ok bool
|
|
// side int32
|
|
// data []byte
|
|
// errdata *pb.ErrorData
|
|
// )
|
|
// for _, bid := range req.Battleid {
|
|
// this.lock.RLock()
|
|
// battle, ok = this.battles[bid]
|
|
// this.lock.RUnlock()
|
|
// if ok {
|
|
// if battle.Red.Uid == req.Uid || battle.Blue.Uid == req.Uid {
|
|
// if req.Uid == battle.Red.Uid {
|
|
// side = 1
|
|
// battle.RedOffline = true
|
|
// } else {
|
|
// side = 2
|
|
// battle.BlueOffline = true
|
|
// }
|
|
|
|
// if battle.curroperate.Side == side {
|
|
// if battle.operatetimer != nil {
|
|
// timewheel.Remove(battle.operatetimer)
|
|
// }
|
|
// battle.curroperate.Auto = true
|
|
// data, _ = proto.Marshal(battle.curroperate)
|
|
// if errdata = this.battle.InCmdBattle(&pb.BattleInCmdReq{
|
|
// Battleid: battle.Id,
|
|
// Side: battle.curroperate.Side,
|
|
// In: &pb.BattleCmd{
|
|
// Cmdtype: "ComWaitInputSkill",
|
|
// Value: data,
|
|
// },
|
|
// }); errdata != nil {
|
|
// return
|
|
// }
|
|
// }
|
|
// }
|
|
// }
|
|
// }
|
|
// return
|
|
// }
|