543 lines
15 KiB
Go
543 lines
15 KiB
Go
package entertainment
|
|
|
|
import (
|
|
"fmt"
|
|
"go_dreamfactory/comm"
|
|
"go_dreamfactory/lego/sys/timewheel"
|
|
"go_dreamfactory/modules"
|
|
"go_dreamfactory/pb"
|
|
cfg "go_dreamfactory/sys/configure/structs"
|
|
"time"
|
|
|
|
"go.mongodb.org/mongo-driver/bson/primitive"
|
|
"google.golang.org/protobuf/proto"
|
|
)
|
|
|
|
const (
|
|
MaxPs = 2 // 最大体力
|
|
//MaxRound = 7 // 最大回合数
|
|
MaxTime = 1800 // 游戏操作时间
|
|
)
|
|
|
|
//游戏房间
|
|
type Room struct {
|
|
modules.ModuleBase
|
|
Id string // 房间id
|
|
szSession []comm.IUserSession
|
|
player1 *pb.PlayerData // 玩家1
|
|
player2 *pb.PlayerData // 玩家2
|
|
chessboard *MapData
|
|
module *Entertainment
|
|
round int32 // 轮数
|
|
operatetimer *timewheel.Task //操作倒计时定时器
|
|
curPower string // 当前操作的玩家
|
|
NexPower string // 下一个操作的玩家
|
|
MaxRound int32
|
|
rd1 bool
|
|
rd2 bool
|
|
}
|
|
|
|
func (this *Room) operateTimeOut(task *timewheel.Task, args ...interface{}) {
|
|
|
|
if this.player1.Userinfo.Uid == this.curPower { // 给玩家2
|
|
this.player1.Ps--
|
|
if this.player1.Ps <= 0 { // 体力消耗完权限给下一个人
|
|
this.NexPower = this.player2.Userinfo.Uid
|
|
this.player2.Ps = MaxPs // 恢复体力
|
|
}
|
|
} else { // 权限给1号玩家
|
|
this.player2.Ps--
|
|
if this.player2.Ps <= 0 {
|
|
this.curPower = this.player1.Userinfo.Uid
|
|
this.player1.Ps = MaxPs // 恢复体力
|
|
|
|
this.round++
|
|
if this.operatetimer != nil {
|
|
timewheel.Remove(this.operatetimer)
|
|
} // 回合+1
|
|
this.operatetimer = timewheel.Add(time.Second*MaxTime, this.operateTimeOut) // 开启新的定时器
|
|
}
|
|
}
|
|
|
|
var szMap []*pb.MapData
|
|
szMap = append(szMap, &pb.MapData{
|
|
Data: this.chessboard.Plat,
|
|
})
|
|
if err := this.module.SendMsgSyncToSession(string(this.module.GetType()), "operatorrst", &pb.EntertainOperatorRstPush{
|
|
Mpadata: szMap,
|
|
Power: this.NexPower,
|
|
Curpower: this.curPower,
|
|
Score: 0,
|
|
Round: this.round,
|
|
User1: this.player1,
|
|
User2: this.player2,
|
|
Itype: 0,
|
|
Curid: 0,
|
|
Targetid: 0,
|
|
}, this.szSession...); err != nil {
|
|
this.Errorln(err)
|
|
}
|
|
// 变更权限
|
|
this.curPower = this.NexPower
|
|
if this.round > this.MaxRound { // 游戏结束
|
|
if this.player1.Score == this.player2.Score {
|
|
this.MaxRound += 1 // 增加一回合
|
|
} else {
|
|
this.GameOver()
|
|
}
|
|
return
|
|
}
|
|
}
|
|
|
|
func (this *Room) InitRoom(module *Entertainment, p1 *pb.PlayerData, p2 *pb.PlayerData) *Room {
|
|
var room *Room
|
|
this.module = module
|
|
this.chessboard = new(MapData)
|
|
this.chessboard.InitMap(module) // 初始化棋盘
|
|
if s1, ok := this.module.GetUserSession(p1.Userinfo.Uid); !ok {
|
|
this.module.PutUserSession(s1)
|
|
} else {
|
|
this.szSession = append(this.szSession, s1.Clone())
|
|
}
|
|
|
|
if p2.Userinfo.Uid != "999" { // 是否是机器人
|
|
if s2, ok := this.module.GetUserSession(p2.Userinfo.Uid); !ok {
|
|
this.module.PutUserSession(s2)
|
|
} else {
|
|
this.szSession = append(this.szSession, s2.Clone())
|
|
}
|
|
}
|
|
this.MaxRound = module.ModuleTools.GetGlobalConf().ConsumeRounds
|
|
|
|
room = &Room{
|
|
ModuleBase: modules.ModuleBase{},
|
|
Id: primitive.NewObjectID().Hex(),
|
|
szSession: this.szSession,
|
|
player1: p1,
|
|
player2: p2,
|
|
chessboard: this.chessboard,
|
|
module: module,
|
|
round: 1,
|
|
MaxRound: this.MaxRound,
|
|
}
|
|
|
|
if err := this.module.SendMsgSyncToSession(string(this.module.GetType()), "enterroom", &pb.EntertainEnterRoomPush{
|
|
Rooid: room.Id,
|
|
Servepath: fmt.Sprintf("%s/%s", this.module.service.GetType(), this.module.service.GetId()),
|
|
User1: room.player1,
|
|
User2: room.player2,
|
|
}, this.szSession...); err != nil {
|
|
this.Errorln(err)
|
|
}
|
|
return room
|
|
}
|
|
|
|
// AI 操作了
|
|
func (this *Room) AiOperator() {
|
|
var (
|
|
curScore int32
|
|
szMap []*pb.MapData
|
|
bAddPs bool
|
|
oid1 int32
|
|
oid2 int32
|
|
)
|
|
|
|
this.player2.Ps--
|
|
// 交换元素
|
|
szMap, oid1, oid2, bAddPs = this.chessboard.AiSwapGirde()
|
|
for _, v := range szMap { //
|
|
this.player2.Energy += v.CurEnergy
|
|
v.CurEnergy = this.player2.Energy
|
|
curScore += v.CurSocre
|
|
this.player2.Score += v.CurSocre
|
|
v.CurSocre = this.player2.Score
|
|
}
|
|
|
|
if bAddPs {
|
|
this.player2.Ps++
|
|
if this.player2.Ps > MaxPs {
|
|
this.player2.Ps = MaxPs
|
|
}
|
|
}
|
|
if this.player2.Ps <= 0 { // 权限给下一个人
|
|
this.NexPower = this.player1.Userinfo.Uid
|
|
this.player1.Ps = MaxPs
|
|
this.round++
|
|
}
|
|
|
|
// 广播消息
|
|
if err := this.module.SendMsgSyncToSession(string(this.module.GetType()), "operatorrst", &pb.EntertainOperatorRstPush{
|
|
Mpadata: szMap,
|
|
Power: this.NexPower,
|
|
Curpower: this.curPower,
|
|
Score: curScore,
|
|
Round: this.round,
|
|
User1: this.player1,
|
|
User2: this.player2,
|
|
Itype: 0,
|
|
Curid: oid1,
|
|
Targetid: oid2,
|
|
}, this.szSession...); err != nil {
|
|
this.Errorln(err)
|
|
}
|
|
|
|
if this.round > this.MaxRound { // 游戏结束
|
|
if this.player1.Score == this.player2.Score {
|
|
this.MaxRound += 1 // 增加一回合
|
|
} else {
|
|
this.GameOver()
|
|
}
|
|
return
|
|
}
|
|
this.curPower = this.NexPower
|
|
if len(this.szSession) == 1 && this.curPower == this.player2.Userinfo.Uid {
|
|
this.AiOperator()
|
|
}
|
|
}
|
|
|
|
func (this *Room) ReceiveMessage(session comm.IUserSession, stype string, msg proto.Message) (errdata *pb.ErrorData) {
|
|
switch stype {
|
|
case "operator": // 操作消息
|
|
var (
|
|
curScore int32 // 该次操作的得分
|
|
AIOperator bool
|
|
oid1 int32 // 唯一id
|
|
oid2 int32
|
|
color int32 // 校验消除的颜色
|
|
bAddPs bool
|
|
)
|
|
var szMap []*pb.MapData
|
|
req := msg.(*pb.EntertainOperatorReq)
|
|
if session.GetUserId() != this.curPower { // 校验是不是你的权限
|
|
errdata = &pb.ErrorData{
|
|
Code: pb.ErrorCode_EntertainNoPower,
|
|
Title: pb.ErrorCode_EntertainNoPower.ToString(),
|
|
}
|
|
return
|
|
}
|
|
if this.curPower == this.player1.Userinfo.Uid {
|
|
color = 1
|
|
} else {
|
|
color = 2
|
|
}
|
|
if req.Itype == 1 { //释放技能
|
|
// 能量校验
|
|
if color == 1 { // 玩家1 放技能
|
|
conf, err := this.module.configure.GetGameConsumeHero(this.player1.Cardid)
|
|
if err != nil {
|
|
errdata = &pb.ErrorData{
|
|
Code: pb.ErrorCode_EntertainNoHeroSkill,
|
|
Title: pb.ErrorCode_EntertainNoHeroSkill.ToString(),
|
|
}
|
|
return
|
|
}
|
|
if this.player1.Energy >= conf.Skillload {
|
|
this.player1.Energy = 0 // 清零
|
|
if m := this.chessboard.SkillUp(conf.Skilleffect, conf.Skillvalue); len(m) > 0 {
|
|
szMap = append(szMap, m...)
|
|
} else {
|
|
szMap = append(szMap, &pb.MapData{
|
|
Data: this.chessboard.GetPalatData(),
|
|
})
|
|
}
|
|
for _, v := range szMap {
|
|
curScore += v.CurSocre
|
|
this.player1.Score += v.CurSocre
|
|
v.CurSocre = this.player1.Score
|
|
}
|
|
|
|
} else {
|
|
errdata = &pb.ErrorData{
|
|
Code: pb.ErrorCode_EntertainNoEnergy,
|
|
Title: pb.ErrorCode_EntertainNoEnergy.ToString(),
|
|
}
|
|
return
|
|
}
|
|
this.NexPower = this.curPower
|
|
} else {
|
|
conf, err := this.module.configure.GetGameConsumeHero(this.player2.Cardid)
|
|
if err != nil {
|
|
errdata = &pb.ErrorData{
|
|
Code: pb.ErrorCode_EntertainNoHeroSkill,
|
|
Title: pb.ErrorCode_EntertainNoHeroSkill.ToString(),
|
|
}
|
|
return
|
|
}
|
|
if this.player2.Energy >= conf.Skillload {
|
|
this.player2.Energy = 0 // 清零
|
|
if m := this.chessboard.SkillUp(conf.Skilleffect, conf.Skillvalue); len(m) > 0 {
|
|
szMap = append(szMap, m...)
|
|
} else {
|
|
szMap = append(szMap, &pb.MapData{
|
|
Data: this.chessboard.GetPalatData(),
|
|
})
|
|
}
|
|
for _, v := range szMap {
|
|
curScore += v.CurSocre
|
|
this.player2.Score += v.CurSocre
|
|
v.CurSocre = this.player2.Score
|
|
}
|
|
|
|
} else {
|
|
errdata = &pb.ErrorData{
|
|
Code: pb.ErrorCode_EntertainNoEnergy,
|
|
Title: pb.ErrorCode_EntertainNoEnergy.ToString(),
|
|
}
|
|
return
|
|
}
|
|
this.NexPower = this.curPower
|
|
}
|
|
if err := this.module.SendMsgSyncToSession(string(this.module.GetType()), "operatorrst", &pb.EntertainOperatorRstPush{
|
|
Mpadata: szMap,
|
|
Power: this.NexPower,
|
|
Curpower: this.curPower,
|
|
Score: curScore,
|
|
Round: this.round,
|
|
User1: this.player1,
|
|
User2: this.player2,
|
|
Itype: req.Itype,
|
|
Curid: oid1,
|
|
Targetid: oid2,
|
|
}, this.szSession...); err != nil {
|
|
this.Errorln(err)
|
|
}
|
|
return
|
|
}
|
|
oid1 = this.chessboard.Plat[req.Curid].Oid
|
|
oid2 = this.chessboard.Plat[req.Targetid].Oid
|
|
// 交换元素
|
|
if b := this.chessboard.SwapGirde(req.Curid, req.Targetid); !b { // 交换格子
|
|
errdata = &pb.ErrorData{
|
|
Code: pb.ErrorCode_EntertainCantSwap, // 不能交换 直接返回
|
|
Title: pb.ErrorCode_EntertainCantSwap.ToString(),
|
|
}
|
|
return
|
|
}
|
|
|
|
if m, b := this.chessboard.CheckMap(color, true); len(m) > 0 {
|
|
// curScore += score
|
|
szMap = append(szMap, m...)
|
|
bAddPs = b
|
|
} else { // 不能消除
|
|
this.chessboard.SwapGirde(req.Targetid, req.Curid) // 换到原来的位置
|
|
errdata = &pb.ErrorData{
|
|
Code: pb.ErrorCode_EntertainCantSwap, // 不能交换 直接返回
|
|
Title: pb.ErrorCode_EntertainCantSwap.ToString(),
|
|
}
|
|
return
|
|
}
|
|
|
|
if this.curPower == this.player1.Userinfo.Uid { //权限校验
|
|
this.player1.Score += curScore
|
|
this.player1.Ps--
|
|
if bAddPs {
|
|
this.player1.Ps++
|
|
if this.player1.Ps > MaxPs {
|
|
this.player1.Ps = MaxPs
|
|
}
|
|
}
|
|
|
|
if this.player1.Ps <= 0 {
|
|
this.NexPower = this.player2.Userinfo.Uid
|
|
if len(this.szSession) == 1 { // 校验2号玩家是不是AI
|
|
AIOperator = true
|
|
}
|
|
this.player2.Ps = MaxPs
|
|
}
|
|
|
|
} else { // this.curPower == this.player2.Uid
|
|
this.player2.Score += curScore
|
|
this.player2.Ps--
|
|
if bAddPs {
|
|
this.player2.Ps++
|
|
if this.player2.Ps > MaxPs {
|
|
this.player2.Ps = MaxPs
|
|
}
|
|
}
|
|
if this.player2.Ps <= 0 {
|
|
this.NexPower = this.player1.Userinfo.Uid
|
|
this.player1.Ps = MaxPs
|
|
this.round++
|
|
if this.operatetimer != nil {
|
|
timewheel.Remove(this.operatetimer)
|
|
this.operatetimer = timewheel.Add(time.Second*MaxTime, this.operateTimeOut) // 开启新的定时器
|
|
}
|
|
}
|
|
}
|
|
for _, v := range szMap { //
|
|
curScore += v.CurSocre
|
|
if color == 1 {
|
|
this.player1.Score += v.CurSocre
|
|
v.CurSocre = this.player1.Score
|
|
this.player1.Energy += v.CurEnergy
|
|
v.CurEnergy = this.player1.Energy
|
|
} else {
|
|
this.player2.Score += v.CurSocre
|
|
v.CurSocre = this.player2.Score
|
|
this.player2.Energy += v.CurEnergy
|
|
v.CurEnergy = this.player2.Energy
|
|
}
|
|
}
|
|
|
|
// 广播消息
|
|
if err := this.module.SendMsgSyncToSession(string(this.module.GetType()), "operatorrst", &pb.EntertainOperatorRstPush{
|
|
Mpadata: szMap,
|
|
Power: this.NexPower,
|
|
Curpower: this.curPower,
|
|
Score: curScore,
|
|
Round: this.round,
|
|
User1: this.player1,
|
|
User2: this.player2,
|
|
Itype: req.Itype,
|
|
Curid: oid1,
|
|
Targetid: oid2,
|
|
}, this.szSession...); err != nil {
|
|
this.Errorln(err)
|
|
}
|
|
if this.round > this.MaxRound { // 游戏结束
|
|
if this.player1.Score == this.player2.Score {
|
|
this.MaxRound += 1 // 增加一回合
|
|
} else {
|
|
this.GameOver()
|
|
}
|
|
return
|
|
}
|
|
// 变更权限
|
|
this.curPower = this.NexPower
|
|
if AIOperator { // AI操作
|
|
this.AiOperator()
|
|
}
|
|
case "ready":
|
|
if len(this.szSession) == 1 { // AI对战的话直接开始游戏
|
|
this.NexPower = this.player1.Userinfo.Uid
|
|
this.curPower = this.player1.Userinfo.Uid
|
|
this.player1.Ps = MaxPs
|
|
this.player2.Ps = 0
|
|
this.module.Debugf("match ai")
|
|
if err := this.module.SendMsgSyncToSession(string(this.module.GetType()), "startgame", &pb.EntertainStartGamePush{
|
|
User1: this.player1,
|
|
User2: this.player2,
|
|
Mpadata: &pb.MapData{Data: this.chessboard.Plat},
|
|
Power: this.NexPower,
|
|
Round: this.round,
|
|
Roomid: this.Id, // 房间ID
|
|
}, this.szSession...); err != nil {
|
|
this.Errorln(err)
|
|
}
|
|
this.operatetimer = timewheel.Add(time.Second*MaxTime, this.operateTimeOut)
|
|
} else {
|
|
if this.player1.Userinfo.Uid == session.GetUserId() {
|
|
this.rd1 = true
|
|
} else if this.player2.Userinfo.Uid == session.GetUserId() {
|
|
this.rd2 = true
|
|
}
|
|
this.module.Debugf("match user1ready:%v,ready2:%v", this.rd1, this.rd2)
|
|
if this.rd1 && this.rd2 { // 两个玩家都准备好了 那么就开始游戏
|
|
this.NexPower = this.player1.Userinfo.Uid
|
|
this.curPower = this.player1.Userinfo.Uid
|
|
this.player1.Ps = MaxPs
|
|
this.player2.Ps = 0
|
|
if err := this.module.SendMsgSyncToSession(string(this.module.GetType()), "startgame", &pb.EntertainStartGamePush{
|
|
User1: this.player1,
|
|
User2: this.player2,
|
|
Mpadata: &pb.MapData{Data: this.chessboard.Plat},
|
|
Power: this.NexPower,
|
|
Round: this.round,
|
|
Roomid: this.Id,
|
|
}, this.szSession...); err != nil {
|
|
this.Errorln(err)
|
|
}
|
|
|
|
this.operatetimer = timewheel.Add(time.Second*MaxTime, this.operateTimeOut)
|
|
}
|
|
}
|
|
case "reconnect": // 重连
|
|
session.SendMsg(string(this.module.GetType()), "reconnect", &pb.EntertainReconnectResp{
|
|
Roomid: this.Id,
|
|
Mpadata: &pb.MapData{
|
|
Data: this.chessboard.GetPalatData(),
|
|
CurSocre: 0,
|
|
CurEnergy: 0,
|
|
},
|
|
Power: this.NexPower,
|
|
Curpower: this.curPower,
|
|
Score: 0,
|
|
Round: this.round,
|
|
User1: this.player1,
|
|
User2: this.player2,
|
|
})
|
|
}
|
|
|
|
return
|
|
}
|
|
|
|
// 游戏结束
|
|
func (this *Room) GameOver() (errdata *pb.ErrorData) {
|
|
var (
|
|
atno []*pb.UserAtno
|
|
winindex int32
|
|
bReward bool
|
|
res []*cfg.Gameatn
|
|
winner string
|
|
lostPlayer *pb.PlayerData // 输的玩家
|
|
)
|
|
if this.operatetimer != nil {
|
|
timewheel.Remove(this.operatetimer)
|
|
}
|
|
winner = this.player1.Userinfo.Uid
|
|
bReward = true
|
|
if this.player1.Score < this.player2.Score {
|
|
winner = this.player2.Userinfo.Uid
|
|
winindex = 1
|
|
if len(this.szSession) == 1 { // 赢家是AI 的话不发奖
|
|
bReward = false
|
|
}
|
|
}
|
|
|
|
if bReward { // 发奖
|
|
if user, err := this.module.ModuleUser.GetUser(winner); err == nil {
|
|
if conf, err := this.module.configure.GetGameConsumeintegral(user.Consumeexp); err == nil {
|
|
//res = append(res, conf.Onereward...) 这奖励手动领取
|
|
res = append(res, conf.Rewards...)
|
|
|
|
if errdata, atno = this.module.DispenseAtno(this.szSession[winindex], res, true); errdata != nil {
|
|
return
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// 失败的一方扣除卡
|
|
if this.player1.Userinfo.Uid != winner {
|
|
lostPlayer = this.player1
|
|
} else {
|
|
lostPlayer = this.player2
|
|
}
|
|
// 失败卡类型
|
|
if conf, err := this.module.configure.GetGameConsumeHero(lostPlayer.Cardid); err == nil && lostPlayer.Userinfo.Uid != "999" {
|
|
if conf.Type != 1 { //卡片类型不为1
|
|
if list, err := this.module.model.getEntertainmList(lostPlayer.Userinfo.Uid); err == nil {
|
|
if list.Card[lostPlayer.Cardid] > 1 {
|
|
list.Card[lostPlayer.Cardid] -= 1
|
|
this.module.model.modifyEntertainmList(lostPlayer.Userinfo.Uid, map[string]interface{}{
|
|
"card": list.Card,
|
|
})
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
this.module.SendMsgSyncToSession(string(this.module.GetType()), "gameover", &pb.EntertainGameOverPush{
|
|
User1: this.player1,
|
|
User2: this.player2,
|
|
Mpadata: &pb.MapData{
|
|
Data: this.chessboard.Plat,
|
|
},
|
|
Power: "", // 清理权限
|
|
Round: this.round,
|
|
Win: winner,
|
|
Reward: atno,
|
|
}, this.szSession...)
|
|
return
|
|
}
|