diff --git a/common/constant.go b/common/constant.go index 936c429..0b8cdeb 100644 --- a/common/constant.go +++ b/common/constant.go @@ -86,6 +86,7 @@ const ( GameId_CaoThap = 605 //CaoThap GameId_AngerUncle = 606 // 愤怒大叔 GameId_SmallRoket = 607 // 小火箭 + GameId_Clawdoll = 609 // 娃娃机 __GameId_ThrGame_Min__ = 700 //################三方类################ GameId_Thr_Dg = 701 //DG Game GameId_Thr_XHJ = 901 //DG Game @@ -104,6 +105,7 @@ const ( GameDifTamQuoc = "305" // 百战成神 GameDifFruits = "306" // 水果机 GameDifRichblessed = "307" // 多彩多福 + GameDifClawdoll = "609" // 娃娃机 ) // IsTienLenYuLe TienLen娱乐 diff --git a/gamerule/clawdoll/constants.go b/gamerule/clawdoll/constants.go new file mode 100644 index 0000000..5f361d0 --- /dev/null +++ b/gamerule/clawdoll/constants.go @@ -0,0 +1,25 @@ +package clawdoll + +import "time" + +// 场景状态 +const ( + ClawDollSceneStateWait int = iota //等待状态 + ClawDollSceneStateStart //开始倒计时 + ClawDollSceneStatePlayGame //游戏中 + ClawDollSceneStateBilled //结算 + ClawDollSceneStateMax +) + +const ( + ClawDollSceneWaitTimeout = time.Second * 2 //等待倒计时 + ClawDollSceneStartTimeout = time.Second * 6 //开始倒计时 + ClawDollSceneBilledTimeout = time.Second * 2 //结算 +) + +// 玩家操作 +const ( + ClawDollPlayerOpScore = iota + 1 // 上分 + ClawDollPlayerOpGo // 下抓 + ClawDollPlayerOpMove // 移动方向 +) diff --git a/gamerule/clawdoll/logic.go b/gamerule/clawdoll/logic.go new file mode 100644 index 0000000..78f1018 --- /dev/null +++ b/gamerule/clawdoll/logic.go @@ -0,0 +1,4 @@ +package clawdoll + +type Logic struct { +} diff --git a/gamesrv/clawdoll/action_clawdoll.go b/gamesrv/clawdoll/action_clawdoll.go new file mode 100644 index 0000000..591aca8 --- /dev/null +++ b/gamesrv/clawdoll/action_clawdoll.go @@ -0,0 +1,55 @@ +package clawdoll + +import ( + "mongo.games.com/game/common" + "mongo.games.com/game/gamesrv/base" + "mongo.games.com/game/protocol/clawdoll" + "mongo.games.com/goserver/core/logger" + "mongo.games.com/goserver/core/netlib" +) + +type CSPlayerOpPacketFactory struct { +} + +type CSPlayerOpHandler struct { +} + +func (f *CSPlayerOpPacketFactory) CreatePacket() interface{} { + pack := &clawdoll.CSCLAWDOLLOp{} + return pack +} + +func (h *CSPlayerOpHandler) Process(s *netlib.Session, packetid int, data interface{}, sid int64) error { + logger.Logger.Trace("CSPlayerOpHandler Process recv ", data) + if msg, ok := data.(*clawdoll.CSCLAWDOLLOp); ok { + p := base.PlayerMgrSington.GetPlayer(sid) + if p == nil { + logger.Logger.Warn("CSPlayerOpHandler p == nil") + return nil + } + scene := p.GetScene() + if scene == nil { + logger.Logger.Warn("CSPlayerOpHandler p.scene == nil") + return nil + } + + if scene.KeyGameDif != common.GameDifClawdoll { + logger.Logger.Error("CSPlayerOpHandler gameId Error ", scene.GameId) + return nil + } + if !scene.HasPlayer(p) { + return nil + } + sp := scene.GetScenePolicy() + if sp != nil { + sp.OnPlayerOp(scene, p, int(msg.GetOpCode()), msg.GetParams()) + } + return nil + } + return nil +} + +func init() { + common.RegisterHandler(int(clawdoll.CLAWDOLLPacketID_PACKET_CS_CLAWDOLL_PLAYEROP), &CSPlayerOpHandler{}) + netlib.RegisterFactory(int(clawdoll.CLAWDOLLPacketID_PACKET_CS_CLAWDOLL_PLAYEROP), &CSPlayerOpPacketFactory{}) +} diff --git a/gamesrv/clawdoll/player_clawdoll.go b/gamesrv/clawdoll/player_clawdoll.go new file mode 100644 index 0000000..170aa61 --- /dev/null +++ b/gamesrv/clawdoll/player_clawdoll.go @@ -0,0 +1,71 @@ +package clawdoll + +import ( + "mongo.games.com/game/gamesrv/base" + "mongo.games.com/goserver/core/logger" +) + +type PlayerEx struct { + *base.Player //玩家信息 + + gainCoin int64 // 本局赢的金币 + taxCoin int64 // 本局税收 + odds int32 +} + +func (this *PlayerEx) Clear(baseScore int32) { + this.UnmarkFlag(base.PlayerState_WaitNext) + this.UnmarkFlag(base.PlayerState_GameBreak) + this.MarkFlag(base.PlayerState_Ready) + + this.gainCoin = 0 + this.taxCoin = 0 + this.odds = 0 +} + +func (this *PlayerEx) CanOp(sceneEx *SceneEx) bool { + if !this.IsGameing() { + logger.Logger.Trace("(this *PlayerEx) CanOp return false ", this.SnId) + return false + } + return true +} + +func (this *PlayerEx) CanPayCoinByPos() bool { + + return false +} + +// 游戏新一局 设置数据 +func (this *PlayerEx) ReStartGame() { + this.ReBetDataStartGame() + this.gainCoin = 0 + this.taxCoin = 0 + this.odds = 0 +} + +// 初始化 +func (this *PlayerEx) InitData(baseScore int32) { + +} + +// 重置下注数据 +func (this *PlayerEx) ResetBetData() { + +} + +// 游戏新一局 设置数据 +func (this *PlayerEx) ReBetDataStartGame() { + +} + +func (this *PlayerEx) CanPlayerOpInState(sceneState int) bool { + + return false +} + +// 能否退出游戏 +func (this *PlayerEx) CanLeaveScene(sceneState int) bool { + + return true +} diff --git a/gamesrv/clawdoll/scene_clawdoll.go b/gamesrv/clawdoll/scene_clawdoll.go new file mode 100644 index 0000000..fd6a518 --- /dev/null +++ b/gamesrv/clawdoll/scene_clawdoll.go @@ -0,0 +1,205 @@ +package clawdoll + +import ( + "mongo.games.com/game/protocol/clawdoll" + "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" +) + +type PlayerData struct { + SnId int32 + Head int32 //头像框 + VIP int32 //VIP帐号 等级 + Name string //名字 + Sex int32 //性别 + IsRob bool + + Coin int64 + gainCoin int64 //本局赢的金币 + taxCoin int64 //本局税收 + isBilled bool //是否结算 + CurIsWin int64 //当局输赢 负数:输 正数:赢 + + InviterId int32 //邀请人Id + BeUnderAgentCode string //隶属经销商(推广人) + IsPlayerFirst bool + + Platform string //平台 + Channel string //渠道信息 + PackageID string //推广包标识 对应客户端的packagetag + flag int +} + +type SceneEx struct { + *base.Scene // 场景 + logic *rule.Logic // + players map[int32]*PlayerEx // 玩家信息 + PlayerBackup map[int32]*PlayerData // 本局离场玩家数据备份 + seats []*PlayerEx // 本局游戏中的玩家状态数据 + + RoundId int // 局数,第几局 + robotNum int // 参与游戏的机器人数量 + logid string +} + +// 游戏是否能开始 +func (this *SceneEx) CanStart() bool { + //人数>=1自动开始 + if len(this.players) >= 0 && (this.GetRealPlayerNum() >= 0 || this.IsPreCreateScene()) { + return true + } + return false +} + +// 从房间删除玩家 +func (this *SceneEx) delPlayer(p *base.Player) { + if p, exist := this.players[p.SnId]; exist { + this.seats[p.GetPos()] = nil + delete(this.players, p.SnId) + } +} + +// 广播玩家离开 +func (this *SceneEx) BroadcastPlayerLeave(p *base.Player, reason int) { + scLeavePack := &clawdoll.SCCLAWDOLLPlayerLeave{ + Pos: proto.Int(p.GetPos()), + } + proto.SetDefaults(scLeavePack) + + this.Broadcast(int(clawdoll.CLAWDOLLPacketID_PACKET_SC_CLAWDOLL_PlayerLeave), scLeavePack, p.GetSid()) +} + +// 玩家离开事件 +func (this *SceneEx) OnPlayerLeave(p *base.Player, reason int) { + this.delPlayer(p) + this.BroadcastPlayerLeave(p, reason) +} +func (this *SceneEx) SceneDestroy(force bool) { + //销毁房间 + this.Scene.Destroy(force) +} + +func (e *SceneEx) playerOpPack(snId int32, opcode int, opRetCode clawdoll.OpResultCode, params []int64) *clawdoll.SCCLAWDOLLOp { + pack := &clawdoll.SCCLAWDOLLOp{ + SnId: proto.Int32(snId), + OpCode: proto.Int32(int32(opcode)), + Params: params, + OpRetCode: clawdoll.OpResultCode_OPRC_Success, + } + + proto.SetDefaults(pack) + return pack +} + +// OnPlayerSCOp 发送玩家操作情况 +func (e *SceneEx) OnPlayerSCOp(p *base.Player, opcode int, opRetCode clawdoll.OpResultCode, params []int64) { + pack := e.playerOpPack(p.SnId, opcode, opRetCode, params) + p.SendToClient(int(clawdoll.CLAWDOLLPacketID_PACKET_SC_CLAWDOLL_PLAYEROP), pack) + logger.Logger.Tracef("OnPlayerSCOp %s", pack) +} + +// 房间信息打包 +func (this *SceneEx) ClawdollCreateRoomInfoPacket(s *base.Scene, p *base.Player) interface{} { + pack := &clawdoll.SCCLAWDOLLRoomInfo{ + RoomId: proto.Int(s.GetSceneId()), + GameId: proto.Int(s.GetGameId()), + RoomMode: proto.Int(s.GetSceneMode()), + Params: common.CopySliceInt64ToInt32(s.Params), + State: proto.Int(s.GetSceneState().GetState()), + TimeOut: proto.Int(s.GetSceneState().GetTimeout(s)), + TotalPlayer: proto.Int(len(this.players)), + RoundId: proto.Int(this.RoundId), + ParamsEx: nil, + GameFreeId: 0, + BaseScore: proto.Int32(this.GetBaseScore()), + } + + // 玩家信息 + for _, playerEx := range this.players { + + if p.SnId == playerEx.SnId { + pd := &clawdoll.CLAWDOLLPlayerData{ + SnId: proto.Int32(playerEx.SnId), + Name: proto.String(playerEx.Name), + Head: proto.Int32(playerEx.Head), + Sex: proto.Int32(playerEx.Sex), + Coin: proto.Int64(playerEx.Coin), + Flag: proto.Int(playerEx.GetFlag()), + HeadOutLine: proto.Int32(playerEx.HeadOutLine), + VIP: proto.Int32(playerEx.VIP), + + WinCoin: proto.Int64(playerEx.gainCoin), + } + + pack.Players = append(pack.Players, pd) + } + } + + proto.SetDefaults(pack) + if p != nil { + p.SyncFlag() + } + + return pack +} + +func NewClawdollSceneData(s *base.Scene) *SceneEx { + sceneEx := &SceneEx{ + Scene: s, + logic: new(rule.Logic), + players: make(map[int32]*PlayerEx), + seats: make([]*PlayerEx, s.GetPlayerNum()), + PlayerBackup: make(map[int32]*PlayerData), + } + + return sceneEx +} + +func (this *SceneEx) init() bool { + this.Clear() + return true +} + +// 检查上分是否合法 +func (this *SceneEx) CheckPayOp(betVal int64, takeMul int64) bool { //游戏底分 + return true +} + +func (this *SceneEx) Clear() { + this.robotNum = 0 + this.PlayerBackup = make(map[int32]*PlayerData) + this.RoundId = 0 + + for i := 0; i < this.GetPlayerNum(); i++ { + if this.seats[i] != nil { + this.seats[i].Clear(this.GetBaseScore()) + } + } +} + +func (this *SceneEx) BackupPlayer(p *PlayerEx, isBilled bool) { + this.PlayerBackup[p.SnId] = &PlayerData{ + SnId: p.SnId, + gainCoin: p.gainCoin, + taxCoin: p.taxCoin, + isBilled: isBilled, + IsRob: p.IsRob, + Coin: p.Coin, + Head: p.Head, + flag: p.GetFlag(), + Platform: p.Platform, + Channel: p.Channel, + PackageID: p.PackageID, + CurIsWin: p.CurIsWin, + Name: p.Name, + Sex: p.Sex, + VIP: p.VIP, + InviterId: p.InviterId, + IsPlayerFirst: this.IsPlayerFirst(p.Player), + BeUnderAgentCode: p.BeUnderAgentCode, + } +} diff --git a/gamesrv/clawdoll/scenepolicy_clawdoll.go b/gamesrv/clawdoll/scenepolicy_clawdoll.go new file mode 100644 index 0000000..e8597fd --- /dev/null +++ b/gamesrv/clawdoll/scenepolicy_clawdoll.go @@ -0,0 +1,582 @@ +package clawdoll + +import ( + "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 +} + +// SCDeviceAction 娃娃机操作信息 +type SCDeviceAction struct { + DeviceID string `json:"id"` //设备ID + Action int `json:"action"` //操作信息 +} + +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) + } +} + +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 + } + + 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 + } + + 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 + }) +} diff --git a/protocol/clawdoll/clawdoll.proto b/protocol/clawdoll/clawdoll.proto new file mode 100644 index 0000000..e7091b2 --- /dev/null +++ b/protocol/clawdoll/clawdoll.proto @@ -0,0 +1,103 @@ +syntax = "proto3"; +package clawdoll; +option go_package = "mongo.games.com/game/protocol/clawdoll"; + +//娃娃机 +enum CLAWDOLLPacketID { + PACKET_CLAWDOLL_ZERO = 0; //弃用消息号 + PACKET_SC_CLAWDOLL_ROOMINFO = 5601; //房间信息 + PACKET_CS_CLAWDOLL_PLAYEROP = 5602; //玩家操作(客户->服务) + PACKET_SC_CLAWDOLL_PLAYEROP = 5603; //玩家操作(服务->客户) + PACKET_SC_CLAWDOLL_ROOMSTATE = 5604; //房间状态 + PACKET_SC_CLAWDOLL_GAMEBILLED = 5605; //游戏结算 + PACKET_SC_CLAWDOLL_PlayerEnter = 5606; // 玩家进入 + PACKET_SC_CLAWDOLL_PlayerLeave = 5607; // 玩家离开 + PACKET_SC_CLAWDOLL_PLAYERINFO = 5608; // 玩家状态信息变化 +} + +//操作结果 +enum OpResultCode { + OPRC_Success = 0; //成功 + OPRC_Error = 1; //失败 + OPRC_CoinNotEnough = 2; //钱不够 + OPRC_PosAlReadyPlaying = 3; //本局位置已存在玩家 +} + +message CLAWDOLLPlayerData { + string Name = 1; //名字 + int32 SnId = 2; //账号 + int32 Head = 3; //头像 + int32 Sex = 4; //性别 + int64 Coin = 5; //金币 + int32 HeadOutLine = 6; //头像框 + int32 VIP = 7; + int32 Flag = 8; //二进制标记 第一位:是否掉线(0:在线 1:掉线) 第二位:是否准备(0:未准备 1:已准备) + + int64 WinCoin = 9; // 本局赢分 + +} + +//房间信息 +message SCCLAWDOLLRoomInfo { + int32 RoomId = 1; //房间id + int32 GameId = 2; //游戏id + int32 RoomMode = 3; //游戏模式 + repeated int32 Params = 4; //规则参数 + int32 State = 5; //房间当前状态 + int32 TimeOut = 6; //该状态已经历时间 单位:秒 + repeated CLAWDOLLPlayerData Players = 7; //房间内的玩家信息 + int32 TotalPlayer = 8; //房间总人数 + int32 RoundId = 9; //当前局数ID + repeated int32 ParamsEx = 10; //其他参数 + + int32 GameFreeId = 15; + int32 BaseScore = 16; //基础分 +} + +//玩家操作 +message CSCLAWDOLLOp { + int32 OpCode = 1; + repeated int64 Params = 2; +} + +//玩家操作返回 +message SCCLAWDOLLOp { + int32 SnId = 1; //玩家ID + int32 OpCode = 2; //操作码 + repeated int64 Params = 3; //操作参数 同上 CSCLAWDOLLOp + OpResultCode OpRetCode = 4; //操作结果 +} + +//发送给客户端的数据 单局结算 +message SCCLAWDOLLRoundGameBilled { + int32 RoundId = 1; //牌局ID + int32 ClowResult = 2; //抓取结果 + int64 Award = 3; //获奖金额 + int64 Balance = 4; //玩家余额 +} + +//房间状态 +message SCCLAWDOLLRoomState { + int32 State = 1; //房间当前状态 + repeated float Params = 2; +} + +//玩家信息 +message SCCLAWDOLLPlayerInfo { + int32 SnId = 1; //玩家ID + int64 gainCoin = 2; //本局赢取 + int64 Coin = 3; // 玩家 +} + + +//玩家进入 +//PACKET_SCCLAWDOLLPlayerEnter +message SCCLAWDOLLPlayerEnter { + CLAWDOLLPlayerData Data = 1; +} + +//玩家离开 +//PACKET_SCCLAWDOLLPlayerLeave +message SCCLAWDOLLPlayerLeave { + int32 Pos = 1; //玩家位置 +} \ No newline at end of file