go_dreamfactory/modules/pvp/module.go
2024-03-06 17:56:26 +08:00

483 lines
13 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
realarena comm.IRealarena
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)
if module, err = this.service.GetModule(comm.ModuleRealarena); err != nil {
return
}
this.realarena = module.(comm.IRealarena)
// 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
}
//发起者 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
}
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
}
// 创建Pvp
func (this *Pvp) CreateRoomById(id string, ptype pb.PvpType, sessions []comm.IUserSession, uinfos []*pb.BaseUserInfo) (err error) {
this.Debug("CreatePvp", log.Field{Key: "ptype", Value: ptype}, log.Field{Key: "sessions", Value: sessions})
var (
battle *BattleItem
)
battle = &BattleItem{
Id: id,
Ptype: ptype,
State: pb.PvpState_ready,
RedSession: sessions[0],
BlueSession: sessions[1],
Red: uinfos[0],
Blue: uinfos[1],
readytimer: timewheel.Add(time.Second*60, this.readyTimeOut, id),
curroperate: &pb.ComWaitInputSkill{},
}
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 == pb.CmdType_EComWaitInputSkill {
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: pb.CmdType_EComWaitInputSkill,
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: pb.CmdType_EComWaitInputSkill,
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
case pb.PvpType_realarena:
go func() {
this.realarena.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: pb.CmdType_EComWaitInputSkill,
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(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: pb.CmdType_EComWaitInputSkill,
Value: data,
},
}); errdata != nil {
return
}
}
}
}
return
}