package pvp import ( "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" "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 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) err = this.ModuleBase.Init(service, module, options) this.service = service.(base.IRPCXService) return } func (this *Pvp) Start() (err error) { err = this.ModuleBase.Start() 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.ModulePractice); err != nil { return } this.practice = module.(comm.IPractice) // event.RegisterGO(comm.EventUserLogin, this.userlogin) event.RegisterGO(comm.EventUserOffline, this.useroffline) 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) CreatePvp(red, blue *pb.PvpUserInfo, ptype pb.PvpType) (battleId string, code pb.ErrorCode) { this.Debug("CreatePvp", log.Field{Key: "ptype", Value: ptype.String()}, log.Field{Key: "red", Value: red.String()}, log.Field{Key: "blue", Value: blue.String()}) var ( battle *BattleItem err error ok bool ) battleId = primitive.NewObjectID().Hex() battle = &BattleItem{ Id: battleId, Ptype: ptype, State: pb.PvpState_ready, Red: red, Blue: blue, readytimer: timewheel.Add(time.Second*60, this.readyTimeOut, battleId), curroperate: &pb.ComWaitInputSkill{}, } if battle.RedSession, ok = this.GetUserSession(red.Uid); !ok { code = pb.ErrorCode_BattleUserOff return } if battle.BlueSession, ok = this.GetUserSession(blue.Uid); !ok { code = pb.ErrorCode_BattleUserOff 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) code = pb.ErrorCode_RpcFuncExecutionError } return } //推送战斗输出指令 func (this *Pvp) PvpOutCmdPush(out *pb.PvpOutCmdPush) { this.Debug("PvpOutCmdPush", log.Field{Key: "args", Value: out}) var ( battle *BattleItem ok bool data []byte code pb.ErrorCode 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 code = this.battle.InCmdBattle(&pb.BattleInCmdReq{ Battleid: battle.Id, Side: battle.curroperate.Side, In: &pb.BattleCmd{ Cmdtype: "ComWaitInputSkill", Value: data, }, }); code != pb.ErrorCode_Success { return } return } if battle.curroperate.Side == 2 && battle.BlueOffline { //已经离线 battle.curroperate.Auto = true data, _ = proto.Marshal(battle.curroperate) if code = this.battle.InCmdBattle(&pb.BattleInCmdReq{ Battleid: battle.Id, Side: battle.curroperate.Side, In: &pb.BattleCmd{ Cmdtype: "ComWaitInputSkill", Value: data, }, }); code != pb.ErrorCode_Success { 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 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 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 code pb.ErrorCode 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 code = this.battle.InCmdBattle(&pb.BattleInCmdReq{ Battleid: battle.Id, Side: battle.curroperate.Side, In: &pb.BattleCmd{ Cmdtype: "ComWaitInputSkill", Value: data, }, }); code != pb.ErrorCode_Success { return } } } //开始战斗 func (this *Pvp) startBattle(battle *BattleItem) { this.Debug("PVPStart", log.Field{Key: "battleId", Value: battle.Id}) var ( record *pb.DBBattleRecord info *pb.BattleInfo code pb.ErrorCode err error ) if code, record = this.battle.CreateRtPvpBattle(&pb.BattleRTPVPReq{ Ptype: pb.PlayType_friendsmeet, Title: "", RedCompId: battle.Red.Uid, Redformat: []*pb.BattleFormation{battle.Redformation}, BlueCompId: battle.Blue.Uid, Bulefformat: []*pb.BattleFormation{battle.Blueformation}, }); code != pb.ErrorCode_Success { 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 { 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 code = this.battle.CreateBattleServer(info); code != pb.ErrorCode_Success { 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) userlogin(session comm.IUserSession) { // var ( // result []*pb.DBPvpBattle // userpvp []*pb.DBPvpBattle // push *pb.PvpListPush // err error // ) // if result, err = this.modelPvpComp.querypvps(); err != nil { // this.Errorln(err) // return // } // userpvp = make([]*pb.DBPvpBattle, 0, len(userpvp)) // for _, v := range result { // if v.Red.Uid == session.GetUserId() || v.Blue.Uid == session.GetUserId() { // userpvp = append(userpvp, v) // } // } // if len(userpvp) <= 0 { // return // } // push = &pb.PvpListPush{} // for _, v := range result { // push.List = append(push.List, &pb.DBPvpBattle{ // Id: v.Id, // ServicePath: v.ServicePath, // Ptype: v.Ptype, // State: v.State, // Red: v.Red, // Blue: v.Blue, // }) // } // session.SendMsg(string(comm.ModulePvp), "list", push) // session.Push() // this.Debug("GetPvpInfo", log.Field{Key: "uid", Value: session.GetSessionId()}, log.Field{Key: "list", Value: push.String()}) } //用户离线处理 func (this *Pvp) useroffline(uid, sessionid string) { var ( side int32 data []byte code pb.ErrorCode ) this.lock.RLock() for _, v := range this.battles { if v.Red.Uid == uid || v.Blue.Uid == uid { if uid == v.Red.Uid { side = 1 v.RedOffline = true } else { side = 2 v.BlueOffline = true } if v.curroperate.Side == side { if v.operatetimer != nil { timewheel.Remove(v.operatetimer) } v.curroperate.Auto = true data, _ = proto.Marshal(v.curroperate) if code = this.battle.InCmdBattle(&pb.BattleInCmdReq{ Battleid: v.Id, Side: v.curroperate.Side, In: &pb.BattleCmd{ Cmdtype: "ComWaitInputSkill", Value: data, }, }); code != pb.ErrorCode_Success { return } } } } this.lock.RUnlock() }