619 lines
15 KiB
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
|
|
})
|
|
}
|