628 lines
15 KiB
Go
628 lines
15 KiB
Go
package baseroom
|
||
|
||
import (
|
||
"encoding/json"
|
||
"fmt"
|
||
"github.com/google/uuid"
|
||
"math/rand"
|
||
"samba/pkg/log"
|
||
"samba/pkg/servername"
|
||
pkgSrv "samba/pkg/service"
|
||
"samba/proto"
|
||
. "samba/server/game/player"
|
||
. "samba/server/game/service"
|
||
"samba/stub"
|
||
"samba/util/model"
|
||
"samba/util/routingKey"
|
||
"samba/util/state"
|
||
"samba/util/util"
|
||
"time"
|
||
)
|
||
|
||
var srv pkgSrv.IService
|
||
|
||
func SetService(s pkgSrv.IService) {
|
||
srv = s
|
||
}
|
||
|
||
type LastMsg struct {
|
||
Msg interface{}
|
||
MsgId string
|
||
Tm time.Time
|
||
}
|
||
|
||
type BaseRoom[Seat ISeat] struct {
|
||
RoomCnf *stub.Room
|
||
clubRoomCnf *model.ClubPlayInfo
|
||
id int
|
||
clubId int // 俱乐部id
|
||
roomType int // 房间配置id
|
||
playType int
|
||
GameNo string
|
||
status state.RoomStatus
|
||
Seats []Seat
|
||
timeTypes map[TimerType]uint32
|
||
timerHandler ITimerHandler
|
||
|
||
LastMsg map[int64]*LastMsg
|
||
truthRoom IRoom
|
||
baseGameLog BaseGameLog // 游戏操作汇总给后台
|
||
|
||
HasLuckyUser bool // 是否有幸运用户
|
||
}
|
||
|
||
func NewBaseRoom[Seat ISeat](id, roomType, clubId int) (*BaseRoom[Seat], proto.ErrorCode) {
|
||
playType := 0
|
||
var roomCnf stub.Room
|
||
var clubRoomCnf *model.ClubPlayInfo
|
||
if clubId == 0 {
|
||
cnf, code := stub.FindRoomCnf(roomType)
|
||
if code == proto.Ok {
|
||
roomCnf = *cnf
|
||
playType = roomCnf.PlayType
|
||
} else {
|
||
log.Error(fmt.Sprintf("room type %d not found", roomType))
|
||
return nil, proto.Internal
|
||
}
|
||
} else {
|
||
playInfo := model.NewClubPlayInfoOp().LoadAPlayInfo(clubId, roomType)
|
||
if playInfo == nil {
|
||
log.Error(fmt.Sprintf("room type %d not found.club:%v", roomType, clubId))
|
||
return nil, proto.NotClubPlayGame
|
||
}
|
||
if playInfo.State != 1 || playInfo.IsValid != 1 {
|
||
log.Error(fmt.Sprintf("room type %d is not valid.club:%v", roomType, clubId))
|
||
return nil, proto.NotClubPlayGame
|
||
}
|
||
if playInfo.Blind < 1 || playInfo.PlayerNum < 2 {
|
||
log.Error(fmt.Sprintf("room type %d p.club:%v,blind:%v playerNum:%v", roomType, clubId, playInfo.Blind, playInfo.PlayerNum))
|
||
return nil, proto.NotClubPlayGame
|
||
}
|
||
playType = playInfo.PlayType
|
||
for _, rm := range stub.Rooms {
|
||
if rm.PlayType == playType {
|
||
roomCnf = *rm
|
||
break
|
||
}
|
||
}
|
||
roomCnf.Valid = 1
|
||
roomCnf.TakeCoin = 0
|
||
roomCnf.Blind = playInfo.Blind
|
||
roomCnf.MinPlayers = playInfo.PlayerNum
|
||
roomCnf.Rate = playInfo.Fee
|
||
clubRoomCnf = playInfo
|
||
}
|
||
|
||
room := &BaseRoom[Seat]{
|
||
id: id,
|
||
clubId: clubId,
|
||
roomType: roomType,
|
||
playType: playType,
|
||
RoomCnf: &roomCnf,
|
||
clubRoomCnf: clubRoomCnf,
|
||
GameNo: uuid.NewString(),
|
||
timeTypes: make(map[TimerType]uint32),
|
||
LastMsg: make(map[int64]*LastMsg),
|
||
baseGameLog: BaseGameLog{
|
||
RoomId: id,
|
||
RoomType: roomType,
|
||
Level: roomCnf.Level,
|
||
PlayType: roomCnf.PlayType,
|
||
Blind: roomCnf.Blind,
|
||
GameNo: "", // 游戏开始之后生成gameNo
|
||
StartTime: 0, // 游戏开始之后赋值
|
||
EndTime: 0, // 游戏结束之后赋值
|
||
Players: nil, // 游戏结束之后赋值(涉及到输赢金币)
|
||
ClubId: clubId,
|
||
PlatformFee: 0, // 俱乐部分成之后赋值
|
||
ClubFee: 0, // 俱乐部分成之后赋值
|
||
},
|
||
}
|
||
if room.ClubId() > 0 {
|
||
log.Debug(room.Log("创建房间"))
|
||
}
|
||
room.UpdateClubPlayingRoomInfo()
|
||
|
||
return room, proto.Ok
|
||
}
|
||
|
||
func (r *BaseRoom[Seat]) Id() int {
|
||
return r.id
|
||
}
|
||
|
||
func (r *BaseRoom[Seat]) Type() int {
|
||
return r.roomType
|
||
}
|
||
|
||
func (r *BaseRoom[Seat]) SetTruthRoom(rm IRoom) {
|
||
r.truthRoom = rm
|
||
}
|
||
|
||
func (r *BaseRoom[Seat]) PlayType() int {
|
||
return r.playType
|
||
}
|
||
|
||
func (r *BaseRoom[Seat]) ClubId() int {
|
||
return r.clubId
|
||
}
|
||
|
||
func (r *BaseRoom[Seat]) BaseGameLog() *BaseGameLog {
|
||
return &r.baseGameLog
|
||
}
|
||
|
||
// 入座玩家数量(包含机器人)
|
||
func (r *BaseRoom[Seat]) SeatPlayerNum() int {
|
||
num := 0
|
||
for _, seat := range r.Seats {
|
||
if !seat.Empty() {
|
||
num++
|
||
}
|
||
}
|
||
return num
|
||
}
|
||
|
||
// 真实玩家数量
|
||
func (r *BaseRoom[Seat]) RealPlayerNum() int {
|
||
num := 0
|
||
for _, seat := range r.Seats {
|
||
if !seat.Empty() && !seat.Player().IsRobot() {
|
||
num++
|
||
}
|
||
}
|
||
return num
|
||
}
|
||
|
||
// 机器人数量
|
||
func (r *BaseRoom[Seat]) RobotPlayerNum() int {
|
||
num := 0
|
||
for _, seat := range r.Seats {
|
||
if !seat.Empty() && seat.Player().IsRobot() {
|
||
num++
|
||
}
|
||
}
|
||
return num
|
||
}
|
||
|
||
func (r *BaseRoom[Seat]) HasEmptySeat() bool {
|
||
for _, seat := range r.Seats {
|
||
if seat.Empty() {
|
||
return true
|
||
}
|
||
}
|
||
return false
|
||
}
|
||
|
||
// IsPlayerCurrentRoom 多个房间都有该玩家时,判断该房间是不是这个玩家的当前房间
|
||
func (r *BaseRoom[Seat]) IsPlayerCurrentRoom(uid int64) bool {
|
||
for _, seat := range r.Seats {
|
||
if !seat.Empty() && seat.Player().UID == uid {
|
||
return true
|
||
}
|
||
}
|
||
return false
|
||
}
|
||
|
||
func (r *BaseRoom[Seat]) HasPlayer(uid int64) bool {
|
||
for _, seat := range r.Seats {
|
||
if !seat.Empty() && seat.Player().UID == uid {
|
||
return true
|
||
}
|
||
}
|
||
return false
|
||
}
|
||
|
||
func (r *BaseRoom[Seat]) SetTimerHandler(th ITimerHandler) {
|
||
if r.timerHandler == nil {
|
||
r.timerHandler = th
|
||
}
|
||
}
|
||
|
||
func (r *BaseRoom[Seat]) SetCurrentRoom(uid int64, current bool) {
|
||
for _, seat := range r.Seats {
|
||
if !seat.Empty() && seat.Player().UID == uid {
|
||
if seat.IsPlayerCurrentRoom() != current {
|
||
seat.SetCurrentRoom(current)
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
// LatestSeatedTime 获取最后一个就座时间
|
||
func (r *BaseRoom[Seat]) LatestSeatedTime() time.Time {
|
||
var t time.Time
|
||
for _, seat := range r.Seats {
|
||
sTime := seat.SeatedTime()
|
||
if t.IsZero() || sTime.After(t) {
|
||
t = sTime
|
||
}
|
||
}
|
||
return t
|
||
}
|
||
|
||
func (r *BaseRoom[Seat]) AddPlayer(player *Player, seat int) {
|
||
if seat < 0 || seat >= len(r.Seats) {
|
||
log.Error(r.SeatLog(r.Seats[seat], "out of range"))
|
||
return
|
||
}
|
||
r.Seats[seat].SetPlayer(player)
|
||
// todo:默认最近一次进的房间为玩家正在玩的房间
|
||
r.Seats[seat].SetCurrentRoom(true)
|
||
return
|
||
}
|
||
|
||
func (r *BaseRoom[Seat]) RemovePlayer(player *Player) {
|
||
for _, seat := range r.Seats {
|
||
if !seat.Empty() && seat.Player().UID == player.UID {
|
||
seat.SetPlayer(nil)
|
||
break
|
||
}
|
||
}
|
||
}
|
||
|
||
func (r *BaseRoom[Seat]) Status() state.RoomStatus {
|
||
return r.status
|
||
}
|
||
|
||
func (r *BaseRoom[Seat]) SetStatus(s state.RoomStatus) {
|
||
r.status = s
|
||
}
|
||
|
||
func (r *BaseRoom[Seat]) OnMessage(_ string, _ map[string]interface{}) {}
|
||
|
||
func (r *BaseRoom[Seat]) DebugSendMsg(user *Player, msgId string, msg interface{}) {
|
||
sMsg, _ := json.Marshal(msg)
|
||
for _, seat := range r.Seats {
|
||
if !seat.Empty() && seat.Player().UID == user.UID {
|
||
log.Debug(r.SeatLog(seat, "send msg:%v %v", msgId, string(sMsg)))
|
||
break
|
||
}
|
||
}
|
||
}
|
||
|
||
func (r *BaseRoom[Seat]) SendMsg(user *Player, msgId string, msg interface{}, save bool) {
|
||
r.DebugSendMsg(user, msgId, msg)
|
||
if user.IsRobot() {
|
||
user.Robot.OnMessage(msgId, msg)
|
||
} else {
|
||
if save {
|
||
r.LastMsg[user.UID] = &LastMsg{MsgId: msgId, Msg: msg, Tm: time.Now()}
|
||
}
|
||
if msgId == proto.RspEnterRoomId || msgId == proto.RspReconnectId || msgId == proto.RspCachetaReconnectId {
|
||
SendMsgToGate(srv, user.UID, msgId, msg)
|
||
} else {
|
||
for _, seat := range r.Seats {
|
||
if !seat.Empty() && seat.Player().UID == user.UID && !seat.FakeLeave() {
|
||
SendMsgToGate(srv, user.UID, msgId, msg)
|
||
break
|
||
}
|
||
}
|
||
}
|
||
if user.IsHosting() {
|
||
user.Robot.OnMessage(msgId, msg)
|
||
}
|
||
}
|
||
|
||
}
|
||
|
||
func (r *BaseRoom[Seat]) Broadcast(msgId string, msg interface{}, save bool, exclude ...*Player) {
|
||
for _, seat := range r.Seats {
|
||
if !seat.Empty() {
|
||
exist := false
|
||
for _, excludePlayer := range exclude {
|
||
if excludePlayer.UID == seat.Player().UID {
|
||
exist = true
|
||
break
|
||
}
|
||
}
|
||
if !exist {
|
||
r.SendMsg(seat.Player(), msgId, msg, save)
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
func (r *BaseRoom[Seat]) NewTimer(timerType TimerType, duration time.Duration, args ...interface{}) {
|
||
if r.timerHandler == nil {
|
||
log.Error(r.Log("timer handler is nil"))
|
||
return
|
||
}
|
||
if _, ok := r.timeTypes[timerType]; ok {
|
||
log.Error(r.Log("timer type:%v is exist.can not new timer", timerType.String()))
|
||
//if timerType == TtPlayerAct {
|
||
// log.Debug(r.Log(log.StackTrace()))
|
||
//}
|
||
return
|
||
}
|
||
tid := srv.NewTimer(duration+time.Duration(10)*time.Millisecond, func() {
|
||
r.timerHandler.OnTimer(timerType, args...)
|
||
}, true, r.Log("start type:%v timer", timerType.String()))
|
||
r.timeTypes[timerType] = tid
|
||
//log.Debug(r.Log("start type:%v timer", timerType.String()))
|
||
}
|
||
|
||
func (r *BaseRoom[Seat]) CancelTimer(timerType TimerType) {
|
||
if tid, ok := r.timeTypes[timerType]; ok {
|
||
srv.CancelTimer(tid)
|
||
delete(r.timeTypes, timerType)
|
||
//log.Debug(r.Log("stop type:%v timer, rest timer:%+v", timerType.String(), r.timeTypes))
|
||
}
|
||
}
|
||
|
||
func (r *BaseRoom[Seat]) CancelAllTimer() {
|
||
for _, tid := range r.timeTypes {
|
||
srv.CancelTimer(tid)
|
||
//log.Debug(r.Log("start type:%v timer", timerType.String()))
|
||
}
|
||
r.timeTypes = make(map[TimerType]uint32)
|
||
}
|
||
|
||
func (r *BaseRoom[Seat]) Log(format string, a ...any) string {
|
||
head := fmt.Sprintf("room:%v type:%v ", r.id, r.roomType)
|
||
return head + fmt.Sprintf(format, a...)
|
||
}
|
||
|
||
func (r *BaseRoom[Seat]) SeatLog(seat Seat, format string, a ...any) string {
|
||
head := ""
|
||
if seat.Player() != nil {
|
||
head = fmt.Sprintf("room:%v type:%v seat:%v user:%v robot:%v ", r.id, r.roomType, seat.No(), seat.Player().UID, seat.Player().IsRobot())
|
||
} else {
|
||
head = fmt.Sprintf("room:%v type:%v seat:%v ", r.id, r.roomType, seat.No())
|
||
}
|
||
|
||
return head + fmt.Sprintf(format, a...)
|
||
}
|
||
|
||
func (r *BaseRoom[Seat]) UserLog(uid int64, format string, a ...any) string {
|
||
var seat Seat
|
||
exist := false
|
||
for _, st := range r.Seats {
|
||
if !st.Empty() && st.Player().UID == uid {
|
||
seat = st
|
||
exist = true
|
||
break
|
||
}
|
||
}
|
||
if exist {
|
||
return r.SeatLog(seat, format, a...)
|
||
} else {
|
||
return r.Log(format, a...)
|
||
}
|
||
}
|
||
|
||
func (r *BaseRoom[Seat]) RandRobotCnf() stub.RobotTemper {
|
||
var robotConfigs map[stub.RobotTemper]int
|
||
var wSum int
|
||
if r.ClubId() > 0 {
|
||
robotConfigs, wSum = stub.FindClubRobotConfig(r.RoomCnf.Blind, r.RoomCnf.PlayType).RobotTempers()
|
||
} else {
|
||
robotConfigs, wSum = r.RoomCnf.RobotTempers()
|
||
}
|
||
|
||
if wSum < 1 {
|
||
log.Error(r.Log("robot config not exist"))
|
||
return stub.RteUnknown
|
||
}
|
||
w := rand.Int() % wSum
|
||
for temper, weight := range robotConfigs {
|
||
if w < weight {
|
||
return temper
|
||
}
|
||
w -= weight
|
||
}
|
||
log.Error(r.Log("robot config not exist"))
|
||
return stub.RteUnknown
|
||
}
|
||
|
||
func (r *BaseRoom[Seat]) IsMVM() bool {
|
||
return r.RoomCnf.MinPlayers >= 4
|
||
}
|
||
|
||
// 玩家俱乐部房间玩游戏
|
||
func (r *BaseRoom[Seat]) GameStart() {
|
||
r.SetStatus(state.RsGaming)
|
||
r.UpdateClubPlayingRoomInfo()
|
||
if r.ClubId() > 0 {
|
||
for _, seat := range r.Seats {
|
||
if !seat.Empty() {
|
||
_ = model.NewUserQuickMatchOp().Save(seat.Player().UID, r.PlayType(), r.Type())
|
||
}
|
||
}
|
||
}
|
||
|
||
if r.RealPlayerNum() > 1 {
|
||
model.NewRealPlayGameOp().Update()
|
||
}
|
||
|
||
model.NewPlayGameOp().Update()
|
||
|
||
for _, seat := range r.Seats {
|
||
if !seat.Player().IsRobot() && !seat.Empty() && seat.Player().LuckyPoint.IsLuckyUser() {
|
||
r.HasLuckyUser = true
|
||
break
|
||
}
|
||
}
|
||
|
||
}
|
||
|
||
// 玩家俱乐部房间玩游戏
|
||
func (r *BaseRoom[Seat]) GameEnd() {
|
||
r.SetStatus(state.RsDelete)
|
||
r.RemovePlayingRoom()
|
||
}
|
||
|
||
// 尝试释放房间
|
||
func (r *BaseRoom[Seat]) TryReleaseRoom() {
|
||
if RoomMgr.Find(r.Id()) == nil {
|
||
return
|
||
}
|
||
emptyRoom := true
|
||
for _, seat := range r.Seats {
|
||
if !seat.Empty() {
|
||
emptyRoom = false
|
||
}
|
||
}
|
||
if emptyRoom {
|
||
r.CancelAllTimer()
|
||
r.GameEnd()
|
||
log.Debug(r.Log("删除房间"))
|
||
RoomMgr.Del(r.Id())
|
||
}
|
||
}
|
||
|
||
// 解散房间
|
||
func (r *BaseRoom[Seat]) ReleaseRoom() {
|
||
for _, st := range r.Seats {
|
||
if !st.Empty() {
|
||
msgL := util.MakeMessage(proto.ReqLeaveRoomId, &proto.ReqLeaveRoom{RoomId: r.Id()}, st.Player().UID, r.Id())
|
||
r.truthRoom.OnMessage(proto.ReqLeaveRoomId, msgL)
|
||
}
|
||
}
|
||
|
||
r.TryReleaseRoom()
|
||
|
||
if r.ClubId() > 1 {
|
||
err := model.NewClubWaitingRoomOp().Delete(r.clubId, r.id)
|
||
if err != nil {
|
||
log.Error(r.Log("删除俱乐部等待房间失败:%v", err))
|
||
}
|
||
}
|
||
}
|
||
|
||
// 玩家俱乐部房间玩游戏
|
||
func (r *BaseRoom[Seat]) TriggerClubMemberPlaying(uid int64, playing bool) {
|
||
if r.ClubId() < 1 {
|
||
return
|
||
}
|
||
ntf := proto.ReqUserInClubGame{
|
||
ClubId: r.ClubId(),
|
||
Playing: util.Tie(playing, 1, 0),
|
||
RoomId: r.Id(),
|
||
UserId: uid,
|
||
}
|
||
SendMsgToOther(srv, servername.Club, routingKey.Club, ntf.UserId, proto.ReqUserInClubGameId, ntf)
|
||
if playing {
|
||
r.UpdateClubPlayingRoomInfo()
|
||
}
|
||
}
|
||
|
||
// 更新俱乐部游戏状态
|
||
func (r *BaseRoom[Seat]) UpdateClubPlayingRoomInfo() {
|
||
if r.ClubId() < 1 {
|
||
return
|
||
}
|
||
// 未开始游戏时,更新俱乐部房间状态
|
||
playingRoom := &model.ClubPlayingRoom{
|
||
RoomId: r.Id(),
|
||
PlayType: r.PlayType(),
|
||
RoomType: r.Type(),
|
||
Blind: r.RoomCnf.Blind,
|
||
CurrPlayerNum: r.SeatPlayerNum(),
|
||
MaxPlayerNum: r.RoomCnf.MinPlayers,
|
||
Status: int(r.status),
|
||
MaxGameNum: 1,
|
||
ServiceTime: ServiceStartTime,
|
||
}
|
||
//log.Debug(r.Log("当前人数:%v", playingRoom.CurrPlayerNum))
|
||
model.NewClubPlayingRoomOp().Update(r.ClubId(), playingRoom)
|
||
}
|
||
|
||
// 游戏启动后,从俱乐部空房间列表中移除
|
||
func (r *BaseRoom[Seat]) RemovePlayingRoom() {
|
||
if r.ClubId() < 1 {
|
||
return
|
||
}
|
||
model.NewClubPlayingRoomOp().Del(r.ClubId(), r.Id())
|
||
}
|
||
|
||
// 游戏启动后,从俱乐部空房间列表中移除
|
||
func (r *BaseRoom[Seat]) MakeClubPlayGameInfo() *proto.ClubPlayGameInfo {
|
||
if r.ClubId() < 1 {
|
||
return nil
|
||
}
|
||
return &proto.ClubPlayGameInfo{
|
||
Id: r.clubRoomCnf.ID,
|
||
Name: r.clubRoomCnf.Name,
|
||
PlayType: r.clubRoomCnf.PlayType,
|
||
Blind: r.clubRoomCnf.Blind,
|
||
PlayerNum: r.clubRoomCnf.PlayerNum,
|
||
GameNum: r.clubRoomCnf.GameNum,
|
||
Fee: r.clubRoomCnf.Fee,
|
||
Valid: r.clubRoomCnf.IsValid,
|
||
}
|
||
}
|
||
|
||
// 更新俱乐部等待房间信息
|
||
func (r *BaseRoom[Seat]) UpdateClubWaitingRoom() {
|
||
if r.ClubId() < 1 {
|
||
return
|
||
}
|
||
if r.Status() != state.RsWait {
|
||
err := model.NewClubWaitingRoomOp().Delete(r.clubId, r.id)
|
||
if err != nil {
|
||
log.Error(r.Log("删除等待房间信息失败:%v", err))
|
||
}
|
||
return
|
||
}
|
||
|
||
seatsWithTime := make([]int64, 0, 2)
|
||
for _, seat := range r.Seats {
|
||
st := seat.SeatedTime()
|
||
seatsWithTime = append(seatsWithTime, util.Tie(st.IsZero(), 0, st.Unix()))
|
||
}
|
||
info := model.WaitingRoom{
|
||
RoomType: r.roomType,
|
||
RoomId: r.Id(),
|
||
CurrentPlayers: r.SeatPlayerNum(),
|
||
MaxPlayers: len(seatsWithTime),
|
||
SeatsWithTime: seatsWithTime,
|
||
}
|
||
err := model.NewClubWaitingRoomOp().Update(r.clubId, &info)
|
||
if err != nil {
|
||
log.Error(r.Log("更新等待房间信息失败:%v", err))
|
||
}
|
||
}
|
||
|
||
// 获取金币或者俱乐部币
|
||
func (r *BaseRoom[Seat]) GetCoin(uid int64) (coins int64) {
|
||
if r.ClubId() == 0 {
|
||
op := model.NewUserResourceOp()
|
||
coins, _ = op.Get(uid, model.ResCoins)
|
||
return coins
|
||
} else {
|
||
op := model.NewUserClubInfoOp()
|
||
if userClub, err := op.Load(uid, r.ClubId()); err == nil {
|
||
return userClub.Score + userClub.FreeScore + userClub.InOutFreeScore
|
||
} else {
|
||
return 0
|
||
}
|
||
}
|
||
}
|
||
|
||
// 获取携带的金币,俱乐部没有携带概念
|
||
func (r *BaseRoom[Seat]) GetTakeCoin(player *Player) (coins int64) {
|
||
return util.Tie(r.ClubId() == 0, player.TakeCoin, 0)
|
||
}
|
||
|
||
func (r *BaseRoom[Seat]) AddTakeCoin(player *Player, add int64, reason string) {
|
||
// holdTakeCoin在多开时,是多个房间的总携带,不是本房间的携带
|
||
if r.ClubId() == 0 {
|
||
if holdTakeCoin, ok := model.NewUserResourceOp().AddTakeCoin(player.UID, add); ok {
|
||
player.TakeCoin += add
|
||
res := &proto.ReqAddResource{
|
||
UserId: player.UID,
|
||
ResValue: add,
|
||
ResType: model.ResTakeCoins,
|
||
Reason: reason,
|
||
RoomId: r.Id(),
|
||
RoomType: r.Type(),
|
||
GameNo: r.GameNo,
|
||
Desc: "",
|
||
IsNotify: true,
|
||
}
|
||
model.NewResourceRecord(res, holdTakeCoin).Flush(srv)
|
||
}
|
||
} else {
|
||
log.Error(r.UserLog(player.UID, "club room:%v has not take_club_coin.room_type:%v play_type:%v club:%v ", r.Id(), r.Type(), r.PlayType(), r.ClubId()))
|
||
}
|
||
}
|