game_sync/gamesrv/clawdoll/scenepolicy_clawdoll.go

748 lines
18 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

package clawdoll
import (
"mongo.games.com/game/gamesrv/action"
"mongo.games.com/game/protocol/clawdoll"
"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()
}
if sceneEx.machineId != 0 {
machineStatus := action.GetDollMachineStatus(sceneEx.machineId)
if machineStatus == 0 {
//链接状态不可用 踢出所有玩家
for _, p := range sceneEx.players {
sceneEx.delPlayer(p.Player)
}
sceneEx.machineStatus = 0
logger.Logger.Trace("娃娃机离线,当前场景暂停服务!")
//通知客户单房间不可用
} else {
if sceneEx.machineStatus == 0 {
sceneEx.machineStatus = machineStatus
//通知客户端房间可用
}
}
}
}
}
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 {
playerEx := &PlayerEx{Player: p}
sceneEx.players[p.SnId] = playerEx
baseScore := sceneEx.GetBaseScore()
p.ExtraData = playerEx
playerEx.Clear(baseScore)
if sceneEx.playingSnid == 0 {
p.MarkFlag(base.PlayerState_WaitNext)
p.UnmarkFlag(base.PlayerState_Ready)
sceneEx.playingSnid = p.GetSnId()
}
sceneEx.AddWaitPlayer(playerEx)
//给自己发送房间信息
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 {
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))
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
}
}
}
func (this *StateWait) OnPlayerOp(s *base.Scene, p *base.Player, opcode int, params []int64) bool {
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 sceneEx.IsHasPlaying() {
return false
}
if !playerEx.CanPayCoin() {
return false
}
// 1-前 2-后 3-左 4-右 5-投币
sceneEx.OnPlayerSMPerateOp(p.SnId, int32(sceneEx.machineId), rule.ButtonPayCoin)
if sceneEx.CanStart() {
s.ChangeSceneState(rule.ClawDollSceneStateStart)
}
}
return false
}
//=====================================
// 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:
case rule.ClawDollSceneStateWait:
return true
}
return false
}
func (this *StateStart) OnEnter(s *base.Scene) {
this.BaseState.OnEnter(s)
if sceneEx, ok := s.ExtraData.(*SceneEx); ok {
ClawdollBroadcastRoomState(s)
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 {
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.ClawDollPlayerOpGo:
if !playerEx.CanGrab() {
return false
}
grapType := sceneEx.GetPlayGrabType(playerEx)
logger.Logger.Trace("StatePlayGame OnPlayerOp-----SnId:", p.SnId, " grapType: ", grapType)
//1-弱力抓 2 -强力抓
sceneEx.OnPlayerSMGrabOp(p.SnId, int32(sceneEx.machineId), grapType)
case rule.ClawDollPlayerOpMove:
if !playerEx.CanMove() {
return false
}
if params[0] < rule.ButtonFront || params[0] > rule.ButtonRight {
logger.Logger.Trace("StatePlayGame OnPlayerOp-----SnId:", p.SnId, " opcode: ", opcode, " params:", params)
return false
}
// 1-前 2-后 3-左 4-右 5-投币
sceneEx.OnPlayerSMPerateOp(p.SnId, int32(sceneEx.machineId), int32(params[0]))
}
return false
}
func (this *PlayGame) OnTick(s *base.Scene) {
this.BaseState.OnTick(s)
if sceneEx, ok := s.ExtraData.(*SceneEx); ok {
if time.Now().Sub(sceneEx.StateStartTime) > rule.ClawDollScenePlayTimeout {
if sceneEx.TimeOutPlayGrab() {
}
s.ChangeSceneState(rule.ClawDollSceneStateBilled)
return
}
}
}
//=====================================
// 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 {
s.ChangeSceneState(rule.ClawDollSceneWaitPayCoin)
return
}
}
}
//=====================================
// StateWaitPayCoin 等待下一局投币
//=====================================
type StateWaitPayCoin struct {
BaseState
}
func (this *StateWaitPayCoin) GetState() int {
return rule.ClawDollSceneWaitPayCoin
}
func (this *StateWaitPayCoin) CanChangeTo(s base.SceneState) bool {
switch s.GetState() {
case rule.ClawDollSceneStateStart:
case rule.ClawDollSceneStateWait:
return true
}
return false
}
func (this *StateWaitPayCoin) 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 sceneEx.playingSnid != playerEx.SnId {
logger.Logger.Trace("StateWaitPayCoin OnPlayerOp-----sceneEx.playingSnid:", sceneEx.playingSnid, " playerEx.SnId: ", playerEx.SnId)
return false
}
// 投币检测
if !playerEx.CanPayCoin() {
logger.Logger.Trace("StateWaitPayCoin OnPlayerOp-----CanPayCoin: false")
return false
}
sceneEx.OnPlayerSMPerateOp(p.SnId, int32(sceneEx.machineId), rule.ButtonPayCoin)
s.ChangeSceneState(rule.ClawDollSceneStateStart)
//sceneEx.OnPlayerSCOp(p, opcode, clawdoll.OpResultCode_OPRC_Success, params)
}
return false
}
func (this *StateWaitPayCoin) OnEnter(s *base.Scene) {
logger.Logger.Trace("(this *StateWaitPayCoin) OnEnter, sceneid=", s.GetSceneId())
this.BaseState.OnEnter(s)
}
func (this *StateWaitPayCoin) OnLeave(s *base.Scene) {
logger.Logger.Trace("(this *StateWaitPayCoin) 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 *StateWaitPayCoin) OnTick(s *base.Scene) {
this.BaseState.OnTick(s)
if sceneEx, ok := s.ExtraData.(*SceneEx); ok {
if time.Now().Sub(sceneEx.StateStartTime) > rule.ClawDollSceneWaitPayCoinimeout {
// 时间到重置scene数据
sceneEx.WaitNextPlayer()
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{})
PolicyClawdollSingleton.RegisteSceneState(&StateWaitPayCoin{})
core.RegisteHook(core.HOOK_BEFORE_START, func() error {
base.RegisteScenePolicy(common.GameId_Clawdoll, 0, PolicyClawdollSingleton)
return nil
})
}