game_sync/gamesrv/clawdoll/scenepolicy_clawdoll.go

619 lines
15 KiB
Go

package clawdoll
import (
"mongo.games.com/game/gamesrv/action"
"mongo.games.com/game/protocol/clawdoll"
"mongo.games.com/game/protocol/dollmachine"
"time"
"mongo.games.com/goserver/core"
"mongo.games.com/goserver/core/logger"
"mongo.games.com/game/common"
rule "mongo.games.com/game/gamerule/clawdoll"
"mongo.games.com/game/gamesrv/base"
"mongo.games.com/game/proto"
)
var PolicyClawdollSingleton = &PolicyClawdoll{}
type PolicyClawdoll struct {
base.BaseScenePolicy
states [rule.ClawDollSceneStateMax]base.SceneState
}
func (this *PolicyClawdoll) CreateSceneExData(s *base.Scene) interface{} {
sceneEx := NewClawdollSceneData(s)
if sceneEx != nil {
if sceneEx.init() {
s.ExtraData = sceneEx
}
}
return sceneEx
}
func (this *PolicyClawdoll) CreatePlayerExData(s *base.Scene, p *base.Player) interface{} {
playerEx := &PlayerEx{Player: p}
if playerEx != nil {
p.ExtraData = playerEx
}
return playerEx
}
func (this *PolicyClawdoll) OnStart(s *base.Scene) {
logger.Logger.Trace("(this *PolicyClawdoll) OnStart, sceneId=", s.GetSceneId())
sceneEx := NewClawdollSceneData(s)
if sceneEx != nil {
if sceneEx.init() {
s.ExtraData = sceneEx
s.ChangeSceneState(rule.ClawDollSceneStateWait)
}
}
}
func (this *PolicyClawdoll) OnStop(s *base.Scene) {
logger.Logger.Trace("(this *PolicyClawdoll) OnStop , sceneId=", s.GetSceneId())
}
func (this *PolicyClawdoll) OnTick(s *base.Scene) {
if s == nil {
return
}
if s.SceneState != nil {
s.SceneState.OnTick(s)
}
sceneEx, ok := s.ExtraData.(*SceneEx)
if ok {
if sceneEx.machineId == 0 {
sceneEx.machineId = action.GetFreeDollMachineId()
}
}
}
func (this *PolicyClawdoll) OnPlayerEnter(s *base.Scene, p *base.Player) {
if s == nil || p == nil {
return
}
logger.Logger.Trace("(this *PolicyClawdoll) OnPlayerEnter, sceneId=", s.GetSceneId(), " player=", p.SnId)
if sceneEx, ok := s.ExtraData.(*SceneEx); ok {
pos := -1
for i := 0; i < sceneEx.GetPlayerNum(); i++ {
if sceneEx.seats[i] == nil {
pos = i
break
}
}
if pos != -1 {
playerEx := &PlayerEx{Player: p}
sceneEx.seats[pos] = playerEx
sceneEx.players[p.SnId] = playerEx
baseScore := sceneEx.GetBaseScore()
p.Pos = pos
p.ExtraData = playerEx
playerEx.Clear(baseScore)
if sceneEx.Gaming {
p.MarkFlag(base.PlayerState_WaitNext)
p.UnmarkFlag(base.PlayerState_Ready)
}
//给自己发送房间信息
this.SendRoomInfo(s, p, sceneEx)
s.FirePlayerEvent(p, base.PlayerEventEnter, nil)
}
}
}
func (this *PolicyClawdoll) OnPlayerLeave(s *base.Scene, p *base.Player, reason int) {
logger.Logger.Trace("(this *PolicyClawdoll) OnPlayerLeave, sceneId=", s.GetSceneId(), " player=", p.SnId)
if s == nil || p == nil {
return
}
if !this.CanChangeCoinScene(s, p) {
return
}
sceneEx, ok := s.ExtraData.(*SceneEx)
if !ok {
return
}
playerEx, ok := p.ExtraData.(*PlayerEx)
if !ok {
return
}
isBilled := false
// 游戏已开始,玩家离开,备份玩家数据
if sceneEx.Gaming {
sceneEx.BackupPlayer(playerEx, isBilled)
}
// 清理玩家数据
sceneEx.OnPlayerLeave(p, reason)
s.FirePlayerEvent(p, base.PlayerEventLeave, nil)
}
func (this *PolicyClawdoll) OnPlayerDropLine(s *base.Scene, p *base.Player) {
if s == nil || p == nil {
return
}
logger.Logger.Trace("(this *PolicyClawdoll) OnPlayerDropLine, sceneId=", s.GetSceneId(), " player=", p.SnId)
s.FirePlayerEvent(p, base.PlayerEventDropLine, nil)
}
func (this *PolicyClawdoll) OnPlayerRehold(s *base.Scene, p *base.Player) {
if s == nil || p == nil {
return
}
logger.Logger.Trace("(this *PolicyClawdoll) OnPlayerRehold, sceneId=", s.GetSceneId(), " player=", p.SnId)
if sceneEx, ok := s.ExtraData.(*SceneEx); ok {
if _, ok := p.ExtraData.(*PlayerEx); ok {
//发送房间信息给自己
if p.IsGameing() {
p.MarkFlag(base.PlayerState_Ready)
}
this.SendRoomInfo(s, p, sceneEx)
s.FirePlayerEvent(p, base.PlayerEventRehold, nil)
}
}
}
func (this *PolicyClawdoll) OnPlayerReturn(s *base.Scene, p *base.Player) {
if s == nil || p == nil {
return
}
logger.Logger.Trace("(this *PolicyClawdoll) OnPlayerRehold, sceneId=", s.GetSceneId(), " player=", p.SnId)
if sceneEx, ok := s.ExtraData.(*SceneEx); ok {
if _, ok := p.ExtraData.(*PlayerEx); ok {
//发送房间信息给自己
if p.IsGameing() {
p.MarkFlag(base.PlayerState_Ready)
}
this.SendRoomInfo(s, p, sceneEx)
s.FirePlayerEvent(p, base.PlayerEventReturn, nil)
}
}
}
func (this *PolicyClawdoll) OnPlayerOp(s *base.Scene, p *base.Player, opcode int, params []int64) bool {
if s == nil || p == nil {
return false
}
logger.Logger.Trace("(this *PolicyClawdoll) OnPlayerOp, sceneId=", s.GetSceneId(), " player=", p.SnId, " opcode=", opcode, " params=", params)
if s.SceneState != nil {
p.LastOPTimer = time.Now()
p.Trusteeship = 0
return s.SceneState.OnPlayerOp(s, p, opcode, params)
}
return true
}
func (this *PolicyClawdoll) OnPlayerEvent(s *base.Scene, p *base.Player, evtcode int, params []int64) {
if s == nil || p == nil {
return
}
logger.Logger.Trace("(this *PolicyClawdoll) OnPlayerEvent, sceneId=", s.GetSceneId(), " player=", p.SnId, " eventcode=", evtcode, " params=", params)
if s.SceneState != nil {
s.SceneState.OnPlayerEvent(s, p, evtcode, params)
}
}
func (this *PolicyClawdoll) IsCompleted(s *base.Scene) bool {
if s == nil {
return false
}
if sceneEx, ok := s.ExtraData.(*SceneEx); ok {
return !sceneEx.Gaming
}
return false
}
func (this *PolicyClawdoll) IsCanForceStart(s *base.Scene) bool {
if sceneEx, ok := s.ExtraData.(*SceneEx); ok {
return len(s.Players) >= 2 && !sceneEx.Gaming
}
return false
}
func (this *PolicyClawdoll) ForceStart(s *base.Scene) {
if sceneEx, ok := s.ExtraData.(*SceneEx); ok {
if sceneEx.SceneState.GetState() == rule.ClawDollSceneStateWait {
s.ChangeSceneState(rule.ClawDollSceneStateStart)
}
}
}
// 当前状态能否退出游戏
func (this *PolicyClawdoll) CanChangeCoinScene(s *base.Scene, p *base.Player) bool {
if s == nil || p == nil {
return false
}
if s.GetSceneState() != nil {
return s.GetSceneState().CanChangeCoinScene(s, p)
}
return true
}
func (this *PolicyClawdoll) SendRoomInfo(s *base.Scene, p *base.Player, sceneEx *SceneEx) {
pack := sceneEx.ClawdollCreateRoomInfoPacket(s, p)
p.SendToClient(int(clawdoll.CLAWDOLLPacketID_PACKET_SC_CLAWDOLL_ROOMINFO), pack)
}
// 广播房间状态
func ClawdollBroadcastRoomState(s *base.Scene, params ...float32) {
pack := &clawdoll.SCCLAWDOLLRoomState{
State: proto.Int(s.SceneState.GetState()),
Params: params,
}
s.Broadcast(int(clawdoll.CLAWDOLLPacketID_PACKET_SC_CLAWDOLL_ROOMSTATE), pack, 0)
}
//=====================================
// BaseState 状态基类
//=====================================
type BaseState struct {
}
func (this *BaseState) GetTimeout(s *base.Scene) int {
if sceneEx, ok := s.ExtraData.(*SceneEx); ok {
return int(time.Now().Sub(sceneEx.StateStartTime) / time.Second)
}
return 0
}
func (this *BaseState) CanChangeTo(s base.SceneState) bool {
return true
}
func (this *BaseState) CanChangeCoinScene(s *base.Scene, p *base.Player) bool {
//playerEx, ok := p.ExtraData.(*PlayerEx)
//if !ok {
// return false
//}
//
//if !playerEx.CanLeaveScene(s.GetSceneState().GetState()) {
// return false
//}
return true
}
func (this *BaseState) OnEnter(s *base.Scene) {
if sceneEx, ok := s.ExtraData.(*SceneEx); ok {
sceneEx.StateStartTime = time.Now()
}
}
func (this *BaseState) OnLeave(s *base.Scene) {}
func (this *BaseState) OnTick(s *base.Scene) {
}
func (this *BaseState) OnPlayerOp(s *base.Scene, p *base.Player, opcode int, params []int64) bool {
return false
}
func (this *BaseState) OnPlayerEvent(s *base.Scene, p *base.Player, evtcode int, params []int64) {
}
//=====================================
// StateWait 等待中
//=====================================
type StateWait struct {
BaseState
}
func (this *StateWait) GetState() int {
return rule.ClawDollSceneStateWait
}
func (this *StateWait) CanChangeTo(s base.SceneState) bool {
if s.GetState() == rule.ClawDollSceneStateStart {
return true
}
return false
}
func (this *StateWait) GetTimeout(s *base.Scene) int {
return this.BaseState.GetTimeout(s)
}
func (this *StateWait) OnEnter(s *base.Scene) {
this.BaseState.OnEnter(s)
if sceneEx, ok := s.ExtraData.(*SceneEx); ok {
if s.Gaming {
s.NotifySceneRoundPause()
}
s.Gaming = false
ClawdollBroadcastRoomState(s, float32(0), float32(0))
if sceneEx.CanStart() {
s.ChangeSceneState(rule.ClawDollSceneStateStart)
}
}
}
// 玩家事件
func (this *StateWait) OnPlayerEvent(s *base.Scene, p *base.Player, evtcode int, params []int64) {
logger.Logger.Trace("(this *StateWait) OnPlayerEvent, sceneId=", s.GetSceneId(), " player=", p.SnId, " evtcode=", evtcode)
this.BaseState.OnPlayerEvent(s, p, evtcode, params)
if _, ok := s.ExtraData.(*SceneEx); ok {
switch evtcode {
case base.PlayerEventLeave:
case base.PlayerEventEnter:
if !p.IsReady() {
p.MarkFlag(base.PlayerState_Ready)
p.SyncFlag()
}
}
}
}
func (this *StateWait) OnTick(s *base.Scene) {
this.BaseState.OnTick(s)
if sceneEx, ok := s.ExtraData.(*SceneEx); ok {
if s.CheckNeedDestroy() {
sceneEx.SceneDestroy(true)
return
}
if time.Now().Sub(sceneEx.StateStartTime) > rule.ClawDollSceneWaitTimeout {
//切换到准备开局状态
if sceneEx.CanStart() {
s.ChangeSceneState(rule.ClawDollSceneStateStart)
}
}
}
}
//=====================================
// StateStart 开始倒计时
//=====================================
type StateStart struct {
BaseState
}
func (this *StateStart) GetState() int {
return rule.ClawDollSceneStateStart
}
func (this *StateStart) CanChangeTo(s base.SceneState) bool {
switch s.GetState() {
case rule.ClawDollSceneStatePlayGame:
return true
}
return false
}
func (this *StateStart) OnEnter(s *base.Scene) {
this.BaseState.OnEnter(s)
if sceneEx, ok := s.ExtraData.(*SceneEx); ok {
ClawdollBroadcastRoomState(s, float32(0), float32(0))
s.Gaming = false
sceneEx.GameNowTime = time.Now()
sceneEx.NumOfGames++
}
}
func (this *StateStart) OnTick(s *base.Scene) {
this.BaseState.OnTick(s)
if sceneEx, ok := s.ExtraData.(*SceneEx); ok {
if time.Now().Sub(sceneEx.StateStartTime) > rule.ClawDollSceneStartTimeout {
//切换到等待操作状态
if sceneEx.CanStart() {
s.ChangeSceneState(rule.ClawDollSceneStatePlayGame)
} else {
s.ChangeSceneState(rule.ClawDollSceneStateWait)
}
}
}
}
func (this *StateStart) OnPlayerOp(s *base.Scene, p *base.Player, opcode int, params []int64) bool {
if this.BaseState.OnPlayerOp(s, p, opcode, params) {
return true
}
switch opcode {
case rule.ClawDollPlayerOpPayCoin:
}
return false
}
func (this *StateStart) OnPlayerEvent(s *base.Scene, p *base.Player, evtcode int, params []int64) {
logger.Logger.Trace("(this *StateStart) OnPlayerEvent, sceneId=", s.GetSceneId(), " player=", p.SnId, " evtcode=", evtcode)
this.BaseState.OnPlayerEvent(s, p, evtcode, params)
if sceneEx, ok := s.ExtraData.(*SceneEx); ok {
switch evtcode {
case base.PlayerEventLeave:
if !sceneEx.CanStart() {
s.ChangeSceneState(rule.ClawDollSceneStateWait)
}
case base.PlayerEventEnter:
if !p.IsReady() {
p.MarkFlag(base.PlayerState_Ready)
p.SyncFlag()
}
}
}
}
// =====================================
// PlayGame 游戏中
// =====================================
type PlayGame struct {
BaseState
}
func (this *PlayGame) GetState() int {
return rule.ClawDollSceneStatePlayGame
}
func (this *PlayGame) CanChangeTo(s base.SceneState) bool {
switch s.GetState() {
case rule.ClawDollSceneStateBilled:
return true
}
return false
}
func (this *PlayGame) OnEnter(s *base.Scene) {
logger.Logger.Trace("(this *PlayGame) OnEnter, sceneid=", s.GetSceneId())
this.BaseState.OnEnter(s)
s.Gaming = true
ClawdollBroadcastRoomState(s, float32(0), float32(0))
}
func (this *PlayGame) OnPlayerOp(s *base.Scene, p *base.Player, opcode int, params []int64) bool {
logger.Logger.Trace("StatePlayGame OnPlayerOp-----SnId:", p.SnId, " opcode: ", opcode, " params:", params)
if this.BaseState.OnPlayerOp(s, p, opcode, params) {
return true
}
sceneEx, ok := s.ExtraData.(*SceneEx)
if !ok {
return false
}
playerEx, ok := p.ExtraData.(*PlayerEx)
if !ok {
return false
}
switch opcode {
case rule.ClawDollPlayerOpPayCoin:
// 投币检测
if !playerEx.CanPayCoin() {
return false
}
sceneEx.OnPlayerSCOp(p, opcode, clawdoll.OpResultCode_OPRC_Success, params)
case rule.ClawDollPlayerOpGo:
pack := &dollmachine.SMDollMachineMove{
Snid: proto.Int32(playerEx.SnId),
Id: proto.Int32(int32(opcode)),
Direction: proto.Int32(int32(params[0])),
}
sceneEx.SendToMachine(int(dollmachine.DollMachinePacketID_PACKET_SMDollMachineMove), pack)
case rule.ClawDollPlayerOpMove:
}
return false
}
func (this *PlayGame) OnTick(s *base.Scene) {
this.BaseState.OnTick(s)
}
//=====================================
// StateBilled 结算
//=====================================
type StateBilled struct {
BaseState
}
func (this *StateBilled) GetState() int {
return rule.ClawDollSceneStateBilled
}
func (this *StateBilled) CanChangeTo(s base.SceneState) bool {
switch s.GetState() {
case rule.ClawDollSceneStateStart:
return true
}
return false
}
func (this *StateBilled) OnPlayerOp(s *base.Scene, p *base.Player, opcode int, params []int64) bool {
return false
}
func (this *StateBilled) OnEnter(s *base.Scene) {
logger.Logger.Trace("(this *StateBilled) OnEnter, sceneid=", s.GetSceneId())
this.BaseState.OnEnter(s)
}
func (this *StateBilled) OnLeave(s *base.Scene) {
logger.Logger.Trace("(this *StateBilled) OnLeave, sceneid=", s.GetSceneId())
this.BaseState.OnLeave(s)
if sceneEx, ok := s.ExtraData.(*SceneEx); ok {
sceneEx.PlayerBackup = make(map[int32]*PlayerData)
if s.CheckNeedDestroy() {
sceneEx.SceneDestroy(true)
}
}
}
func (this *StateBilled) OnTick(s *base.Scene) {
this.BaseState.OnTick(s)
if sceneEx, ok := s.ExtraData.(*SceneEx); ok {
if time.Now().Sub(sceneEx.StateStartTime) > rule.ClawDollSceneBilledTimeout {
if sceneEx.CanStart() {
s.ChangeSceneState(rule.ClawDollSceneStateStart)
} else {
s.ChangeSceneState(rule.ClawDollSceneStateWait)
}
return
}
}
}
// // //////////////////////////////////////////////////////////////////////////////
func (this *PolicyClawdoll) RegisteSceneState(state base.SceneState) {
if state == nil {
return
}
stateid := state.GetState()
if stateid < 0 || stateid >= rule.ClawDollSceneStateMax {
return
}
this.states[stateid] = state
}
func (this *PolicyClawdoll) GetSceneState(s *base.Scene, stateid int) base.SceneState {
if stateid >= 0 && stateid < rule.ClawDollSceneStateMax {
return this.states[stateid]
}
return nil
}
func init() {
PolicyClawdollSingleton.RegisteSceneState(&StateWait{})
PolicyClawdollSingleton.RegisteSceneState(&StateStart{})
PolicyClawdollSingleton.RegisteSceneState(&PlayGame{})
PolicyClawdollSingleton.RegisteSceneState(&StateBilled{})
core.RegisteHook(core.HOOK_BEFORE_START, func() error {
base.RegisteScenePolicy(common.GameId_Clawdoll, 0, PolicyClawdollSingleton)
return nil
})
}