47 changed files with 6206 additions and 0 deletions
@ -0,0 +1,118 @@ |
|||
{ |
|||
"Comment": "WinPro 庄稼赢得概率 RoomLimit 房间限红 RechargeLimit 弹充值限制 AreaID 区域ID(1-10) AreaName 区域名字(9-16) AreaPro 区域赔付比例 AreaLimit 区域限红", |
|||
"Comment2": "TimeSelectPoker 二阶段多久翻一次牌", |
|||
"RoomLimit" : [200000000,200000000], |
|||
"PlayerLimit" : [20000000,20000000], |
|||
"RechargeLimit" : 10000, |
|||
"ChipList": [10000,20000,50000,100000,200000,500000], |
|||
"AreaConfig": [ |
|||
{ |
|||
"AreaID": 1, |
|||
"AreaName": "ANDAR", |
|||
"AreaPro": 0.95, |
|||
"AreaLimit": 50000000 |
|||
}, |
|||
{ |
|||
"AreaID": 2, |
|||
"AreaName": "BAHAR", |
|||
"AreaPro": 1.05, |
|||
"AreaLimit": 50000000 |
|||
}, |
|||
{ |
|||
"AreaID": 3, |
|||
"AreaName": "♥️", |
|||
"AreaPro": 1, |
|||
"AreaLimit": 50000000 |
|||
}, |
|||
{ |
|||
"AreaID": 4, |
|||
"AreaName": "♠️", |
|||
"AreaPro": 1, |
|||
"AreaLimit": 50000000 |
|||
}, |
|||
{ |
|||
"AreaID": 5, |
|||
"AreaName": "♣️", |
|||
"AreaPro": 1, |
|||
"AreaLimit": 50000000 |
|||
}, |
|||
{ |
|||
"AreaID": 6, |
|||
"AreaName": "♦️", |
|||
"AreaPro": 1, |
|||
"AreaLimit": 50000000 |
|||
}, |
|||
{ |
|||
"AreaID": 7, |
|||
"AreaName": "1~8", |
|||
"AreaPro": 1, |
|||
"AreaLimit": 50000000 |
|||
}, |
|||
{ |
|||
"AreaID": 8, |
|||
"AreaName": "9~16", |
|||
"AreaPro": 2.5, |
|||
"AreaLimit": 50000000 |
|||
}, |
|||
{ |
|||
"AreaID": 9, |
|||
"AreaName": "17~24", |
|||
"AreaPro": 4, |
|||
"AreaLimit": 30000000 |
|||
}, |
|||
{ |
|||
"AreaID": 10, |
|||
"AreaName": "25", |
|||
"AreaPro": 7, |
|||
"AreaLimit": 20000000 |
|||
} |
|||
], |
|||
"GearConfigComment": "正数血池抽中控制 控系统赢 负数血池控系统输", |
|||
"GearConfig": [ |
|||
{ |
|||
"GearID": 3000, |
|||
"WinPro": 6000 |
|||
},{ |
|||
"GearID": 2000, |
|||
"WinPro": 3000 |
|||
},{ |
|||
"GearID": 1000, |
|||
"WinPro": 500 |
|||
},{ |
|||
"GearID": -1000, |
|||
"WinPro": 0 |
|||
},{ |
|||
"GearID": -2000, |
|||
"WinPro": 1500 |
|||
},{ |
|||
"GearID": -3000, |
|||
"WinPro": 3000 |
|||
} |
|||
], |
|||
"AndroidOprateConfig": { |
|||
"CountMin": 2, |
|||
"CountMax": 3, |
|||
"FlushHZ": 300, |
|||
"LeavePro": [[1,500],[4,2000],[6,3000],[9,5000]], |
|||
"LeastMin": 2 |
|||
}, |
|||
"AndroidBetConfigComment1": "ColorXXX 花色区域配置 NormalXXX AB区域配置 SpecialXXX 次数区域配置", |
|||
"AndroidBetConfigComment2": "区域说明 【A区域 1】【B区域2】【红3】【黑4】【梅5】【方6】【1~8 7】【9~16 8】【17~24 9】【25~more 10】", |
|||
"AndroidBetConfig": { |
|||
"ColorPro": [[3,2500],[4,2500],[5,2500],[6,2500]], |
|||
"ColorBet": [[3,100000,5000000],[4,100000,5000000],[5,100000,5000000],[6,100000,5000000]], |
|||
"MaxCha": 1500000, |
|||
"NormalArea": [[1,5000],[2,5000]], |
|||
"NormalBet": [[1,100000,3000000],[2,500000,3000000]], |
|||
"SpecialPro": 3000, |
|||
"SpecialArea": [[7,4500],[8,2500],[9,1500],[10,500]], |
|||
"SpecialBet": [[7,500000,3000000],[8,500000,2000000],[9,300000,2000000],[10,200000,2000000]] |
|||
}, |
|||
"TimeOutBegin" : 3000, |
|||
"TimeOutBetFirst" : 15000, |
|||
"TimeOutFirstResult" : 5000, |
|||
"TimeOutBetFinal" : 15000, |
|||
"TimeOutFinalResult" : 5000, |
|||
"TimeSelectPoker" : 100, |
|||
"TimeKickTimes" :5 |
|||
} |
@ -0,0 +1,126 @@ |
|||
# 进程号 |
|||
pid = "./run/game.pid" |
|||
# 统一时区设置。项目中的时间获取请使用xtime.Now() |
|||
timezone = "Local" |
|||
|
|||
[cluster] |
|||
[cluster.node] |
|||
# 实例名称 |
|||
name = "TTZ" |
|||
# 编解码器。可选:json | proto |
|||
codec = "json" |
|||
|
|||
[config] |
|||
[config.file] |
|||
# 配置文件或配置目录路径 |
|||
path = "./config" |
|||
# 读写模式。可选:read-only | read-write,默认为read-only |
|||
mode = "read-write" |
|||
[config.etcd] |
|||
# 客户端连接地址+ |
|||
addrs = ["127.0.01:2379"] |
|||
# 客户端拨号超时时间,支持单位:纳秒(ns)、微秒(us | µs)、毫秒(ms)、秒(s)、分(m)、小时(h)、天(d)。默认为5s |
|||
dialTimeout = "5s" |
|||
# 路径。默认为/config |
|||
path = "/config" |
|||
# 读写模式。可选:read-only | read-write,默认为read-only |
|||
mode = "read-only" |
|||
|
|||
[locate] |
|||
[locate.redis] |
|||
# 客户端连接地址 |
|||
addrs = ["127.0.01:62331"] |
|||
# 数据库号 |
|||
db = 0 |
|||
# 用户名 |
|||
username = "" |
|||
# 密码 |
|||
password = "zetdCehWe5t3z9" |
|||
# 最大重试次数 |
|||
maxRetries = 3 |
|||
# key前缀 |
|||
prefix = "xgame" |
|||
|
|||
[registry] |
|||
[registry.etcd] |
|||
# 客户端连接地址 |
|||
addrs = ["127.0.01:2379"] |
|||
# 客户端拨号超时时间(秒) |
|||
dialTimeout = 5 |
|||
# 命名空间 |
|||
namespace = "services" |
|||
# 超时时间(秒) |
|||
timeout = 3 |
|||
# 心跳重试次数 |
|||
retryTimes = 3 |
|||
# 心跳重试间隔(秒) |
|||
retryInterval = 10 |
|||
[registry.consul] |
|||
# 客户端连接地址 |
|||
addr = "127.0.01:8500" |
|||
# 是否启用健康检查 |
|||
healthCheck = true |
|||
# 健康检查时间间隔(秒),仅在启用健康检查后生效 |
|||
healthCheckInterval = 10 |
|||
# 健康检查超时时间(秒),仅在启用健康检查后生效 |
|||
healthCheckTimeout = 5 |
|||
# 是否启用心跳检查 |
|||
heartbeatCheck = true |
|||
# 心跳检查时间间隔(秒),仅在启用心跳检查后生效 |
|||
heartbeatCheckInterval = 10 |
|||
# 健康检测失败后自动注销服务时间(秒) |
|||
deregisterCriticalServiceAfter = 30 |
|||
|
|||
[transport] |
|||
[transport.rpcx] |
|||
# RPCX服务器相关配置 |
|||
[transport.rpcx.server] |
|||
# 服务器监听地址,空或:0时系统将会随机端口号 |
|||
addr = ":0" |
|||
# 秘钥文件 |
|||
keyFile = "" |
|||
# 证书文件 |
|||
certFile = "" |
|||
# RPCX服务器相关配置 |
|||
[transport.rpcx.client] |
|||
# 证书文件 |
|||
certFile = "" |
|||
# 证书域名 |
|||
serverName = "" |
|||
# 连接池大小,默认为10 |
|||
poolSize = 10 |
|||
|
|||
[packet] |
|||
# 字节序,默认为big。可选:little | big |
|||
byteOrder = "big" |
|||
# 路由字节数,默认为2字节 |
|||
routeBytes = 4 |
|||
# 序列号字节数,默认为2字节 |
|||
seqBytes = 4 |
|||
# 消息字节数,默认为5000字节 |
|||
bufferBytes = 100000 |
|||
|
|||
[log] |
|||
[log.zap] |
|||
# 日志输出文件 |
|||
file = "./log/xgame.log" |
|||
# 日志输出级别,可选:debug | info | warn | error | fatal | panic |
|||
level = "debug" |
|||
# 日志输出格式,可选:text | json |
|||
format = "text" |
|||
# 是否输出到终端 |
|||
stdout = true |
|||
# 时间格式,标准库时间格式 |
|||
timeFormat = "2006/01/02 15:04:05.000000" |
|||
# 堆栈的最低输出级别,可选:debug | info | warn | error | fatal | panic |
|||
stackLevel = "error" |
|||
# 文件最大留存时间,d:天、h:时、m:分、s:秒 |
|||
fileMaxAge = "7d" |
|||
# 文件最大尺寸限制,单位(MB) |
|||
fileMaxSize = 100 |
|||
# 文件切割方式 |
|||
fileCutRule = "day" |
|||
# 是否启用调用文件全路径 |
|||
callerFullPath = false |
|||
# 是否启用分级存储 |
|||
classifiedStorage = false |
@ -0,0 +1,41 @@ |
|||
# 以下配置为游戏固定配置,修改必需重启游戏生效 |
|||
|
|||
# 游戏配置(游戏模型基础配置,不可随意变动配置名) |
|||
[game] |
|||
# 游戏ID |
|||
id = 20013 |
|||
# 游戏类型 |
|||
type = 1 |
|||
# 游戏名称 |
|||
name = "TTZ" |
|||
# 最小牌桌数 |
|||
minTableNum = 1 |
|||
# 最大牌桌数 |
|||
maxTableNum = 1 |
|||
# 是否动态牌桌 |
|||
isDynamicTable = false |
|||
# 最小座位数 |
|||
minSeatNum = 0 |
|||
# 最大座位数 |
|||
maxSeatNum = 0 |
|||
# 是否动态座位 |
|||
isDynamicSeat = true |
|||
# 是否回合制游戏,例如:(回合制游戏:麻将)(非回合制游戏:slots) |
|||
isTurnBasedGame = false |
|||
# 是否需要底池接口 |
|||
isNeedPot = false |
|||
# 是否需要奖池接口 |
|||
isNeedPrizePool = true |
|||
# 是否需要血池接口 |
|||
isNeedBloodPool = false |
|||
# 自定义配置(由开发人员自行定义) |
|||
[custom] |
|||
# 押注时长(秒) |
|||
BaseLineCount = 25 |
|||
# 准备起飞时长(秒) |
|||
readyingDuration = 4 |
|||
# 结算时长(秒) |
|||
settlementDuration = 5 |
|||
|
|||
|
|||
|
@ -0,0 +1,13 @@ |
|||
package app |
|||
|
|||
import ( |
|||
"base/cluster/node" |
|||
"xgame/game/TTZ/app/core" |
|||
"xgame/game/TTZ/app/gamemanage" |
|||
) |
|||
|
|||
func Init(proxy *node.Proxy) { |
|||
// 初始化游戏
|
|||
gamemanage.GameProxy = proxy |
|||
core.NewCore(proxy).Init() |
|||
} |
@ -0,0 +1,67 @@ |
|||
package conf |
|||
|
|||
import ( |
|||
"base/config" |
|||
"base/log" |
|||
) |
|||
|
|||
//var (
|
|||
// prizePoolCfg *prizePoolConfig
|
|||
//)
|
|||
|
|||
const ( |
|||
ConfigBloodName = "blood" |
|||
fileType = ".json" |
|||
) |
|||
|
|||
type BloodCtrl struct { |
|||
GameRound int `json:"GameRound"` |
|||
RechargeLimit int64 `json:"RechargeLimit"` |
|||
MinGameScore int64 `json:"MinGameScore"` |
|||
ChipList []int64 `json:"ChipList"` |
|||
GearConfig []struct { |
|||
GearID int `json:"GearID"` |
|||
WinPro int `json:"WinPro"` |
|||
BankerPro int `json:"BankerPro"` |
|||
GetBankerPro int `json:"GetBankerPro"` |
|||
WinBetPro [][]int `json:"WinBetPro"` |
|||
LoseBetPro [][]int `json:"LoseBetPro"` |
|||
BankerWinPro int `json:"BankerWinPro"` |
|||
} `json:"GearConfig"` |
|||
AndroidOprateConfig struct { |
|||
MustBanker int `json:"MustBanker"` |
|||
InGold [][]int `json:"InGold"` |
|||
CreateTableHZ int64 `json:"CreateTableHZ"` |
|||
TableCreatePro [][]int32 `json:"TableCreatePro"` |
|||
CountMax0 [][]int `json:"CountMax0"` |
|||
CountMax1 [][]int `json:"CountMax1"` |
|||
CountMax2 [][]int `json:"CountMax2"` |
|||
CountMax3 [][]int `json:"CountMax3"` |
|||
CountMax4 [][]int `json:"CountMax4"` |
|||
CountMax5 [][]int `json:"CountMax5"` |
|||
JoinHZ []int `json:"JoinHZ"` |
|||
FlushHZ int `json:"FlushHZ"` |
|||
} `json:"AndroidOprateConfig"` |
|||
TimeoutDestroy int64 `json:"TimeoutDestroy"` |
|||
TimeOutBegin int64 `json:"TimeOutBegin"` |
|||
TimeOutGetBanker int64 `json:"TimeOutGetBanker"` |
|||
TimeOutBB int64 `json:"TimeOutBB"` |
|||
TimeOutDT int64 `json:"TimeOutDT"` |
|||
TimeOutBet int64 `json:"TimeOutBet"` |
|||
TimeOutCP int64 `json:"TimeOutCP"` |
|||
TimeOutResult int64 `json:"TimeOutResult"` |
|||
TimeKickTimes int64 `json:"TimeKickTimes"` |
|||
} |
|||
|
|||
func ReadBloodConfig() BloodCtrl { |
|||
log.Debug("获取配置 表名", ConfigBloodName) |
|||
var readData BloodCtrl |
|||
err := config.Get(ConfigBloodName).Scan(&readData) |
|||
if err != nil { |
|||
log.Fatalf("Read AB BloodConfig err:%v", err) |
|||
} |
|||
|
|||
log.Debug("获取配置成功 ", readData.RechargeLimit) |
|||
|
|||
return readData |
|||
} |
@ -0,0 +1,35 @@ |
|||
package blood |
|||
|
|||
import ( |
|||
"base/cluster/node" |
|||
"base/log" |
|||
"xgame/game/service/rpc_client" |
|||
) |
|||
|
|||
type BoolePool struct { |
|||
BoolPoolSockNum int64 // 血池库存
|
|||
BoolPoolId int64 // 血池ID
|
|||
StockConf string //房间取库存配置
|
|||
RoomGears string //房间当前挡位值
|
|||
NowTurnPoint int64 //房间当前拐点值
|
|||
} |
|||
|
|||
// SetBoole 设置血池
|
|||
func (b *BoolePool) SetBoole(Proxy *node.Proxy, BloodID int64) bool { |
|||
|
|||
reply, err := rpc_client.GetGameBloodByGameIdAndRoomId(Proxy, BloodID) |
|||
if err != nil { |
|||
log.Error("获取血池失败", err) |
|||
return false |
|||
} |
|||
|
|||
b.BoolPoolSockNum = reply.StockNum |
|||
b.BoolPoolId = reply.Id |
|||
b.StockConf = reply.StockConf |
|||
b.RoomGears = reply.RoomGears |
|||
b.NowTurnPoint = reply.NowTurnPoint |
|||
|
|||
log.Debug("获取血池 ", reply) |
|||
|
|||
return true |
|||
} |
@ -0,0 +1,7 @@ |
|||
package comm |
|||
|
|||
//销毁房间回调
|
|||
type DestoryCB func(int64) |
|||
|
|||
// 大厅通知回调
|
|||
type NotifyDTUser func(int32, interface{}) |
@ -0,0 +1,95 @@ |
|||
package core |
|||
|
|||
import ( |
|||
"base/cluster" |
|||
"base/cluster/node" |
|||
"base/log" |
|||
"base/task" |
|||
"fmt" |
|||
"xgame/game/TTZ/app/core/room" |
|||
"xgame/game/TTZ/app/gamemanage" |
|||
"xgame/game/TTZ/app/route" |
|||
"xgame/internal/entity" |
|||
userevt "xgame/internal/event/user" |
|||
"xgame/internal/middleware" |
|||
) |
|||
|
|||
type Core struct { |
|||
Proxy *node.Proxy |
|||
playerMgr *entity.PlayerMgr |
|||
} |
|||
|
|||
func NewCore(proxy *node.Proxy) *Core { |
|||
return &Core{ |
|||
Proxy: proxy, |
|||
playerMgr: entity.NewPlayerMgr(proxy), |
|||
} |
|||
} |
|||
|
|||
func (c *Core) Init() { |
|||
|
|||
//go agent.StartAgent()
|
|||
|
|||
c.Proxy.Router().Group(func(group *node.RouterGroup) { |
|||
// 注册中间件
|
|||
group.Middleware(middleware.Auth) |
|||
group.AddRouteHandler(route.Enter, false, gamemanage.EnterGame) // 进入游戏
|
|||
group.AddRouteHandler(route.JoinTable, false, gamemanage.JoinTable) // 进入游戏
|
|||
group.AddRouteHandler(route.Bet, false, gamemanage.UserBet) // 下注请求
|
|||
group.AddRouteHandler(route.LogoutTable, false, gamemanage.LogoutTable) // 退出游戏请求
|
|||
group.AddRouteHandler(route.AllTable, false, gamemanage.AllTable) // 进入游戏
|
|||
group.AddRouteHandler(route.GetBanker, false, gamemanage.GetBanker) // 抢庄
|
|||
group.AddRouteHandler(route.WatchToDown, false, gamemanage.WatchToDown) // 主动观战转坐下
|
|||
}) |
|||
|
|||
// 断线重连-好像没用
|
|||
c.Proxy.AddEventHandler(cluster.Reconnect, gamemanage.Reconnect) |
|||
// 断开连接-好像没用
|
|||
c.Proxy.AddEventHandler(cluster.Disconnect, gamemanage.Disconnect) |
|||
room.Init(c.Proxy) |
|||
|
|||
userevt.SubscribeGoldChange(func(uid int64) { |
|||
gamemanage.UpdateUserGold(uid) |
|||
}) |
|||
|
|||
userevt.SubscribeTableConfigChange(func(gameID int64) { |
|||
gamemanage.UpdateTableConfig(gameID) |
|||
}) |
|||
} |
|||
|
|||
// Reconnect 掉线重连
|
|||
func Reconnect(event *node.Event) { |
|||
|
|||
task.AddTask(func() { |
|||
if event.UID <= 0 { |
|||
return |
|||
} |
|||
//Ctx.Context()
|
|||
/* |
|||
* 只能配合客户端想办法了,实在没办法,这服务器架构设计的有缺陷 |
|||
*/ |
|||
uid := event.UID |
|||
r := room.Gh.GetRoomObject(uid) |
|||
if r != nil { |
|||
r.OnReconnect(uid) |
|||
fmt.Println(uid, "断线重连") |
|||
} |
|||
}) |
|||
} |
|||
|
|||
// Disconnect 掉线
|
|||
func Disconnect(event *node.Event) { |
|||
|
|||
task.AddTask(func() { |
|||
if event.UID <= 0 { |
|||
return |
|||
} |
|||
uid := event.UID |
|||
//r := room.GetRoomByUid(uid)
|
|||
r := room.Gh.GetRoomObject(uid) |
|||
if r != nil { |
|||
r.OnDisconnect(uid) |
|||
log.Debug(uid, "玩家掉线,设置为离线状态") |
|||
} |
|||
}) |
|||
} |
@ -0,0 +1,297 @@ |
|||
package game |
|||
|
|||
import ( |
|||
"base/cluster/node" |
|||
"base/log" |
|||
"context" |
|||
"math/rand" |
|||
"sort" |
|||
"sync" |
|||
"time" |
|||
conf "xgame/game/TTZ/app/config" |
|||
"xgame/game/TTZ/app/core/blood" |
|||
"xgame/game/TTZ/app/core/protocol" |
|||
"xgame/game/TTZ/app/core/types" |
|||
"xgame/internal/option/room" |
|||
gamepb "xgame/internal/service/game/pb" |
|||
|
|||
"github.com/roylee0704/gron" |
|||
"github.com/shopspring/decimal" |
|||
) |
|||
|
|||
const ( |
|||
NORMAL_END = int32(1) //正常结算
|
|||
) |
|||
|
|||
const ( |
|||
INVALID_VALUE = 0xFFFF //无效值
|
|||
GAME_NAME = "推筒子" //游戏名字
|
|||
GAME_ID = 20013 //游戏ID
|
|||
MAX_USER_NUM = 5 //房间最大人数
|
|||
MAX_ROBOT_BUN = 3 //房间最多机器人
|
|||
NEXT_GAME_TIME_OUT = 3000 //开始倒计时
|
|||
GET_BANKER_TIME_OUT = 10000 //抢庄倒计时
|
|||
BB_TIME_OUT = 3000 //抢庄后到开始下注的等待时间
|
|||
DT_TIME_OUT = 3000 //丢骰子动画展示倒计时
|
|||
BET_TIME_OUT = 15000 //下注倒计时
|
|||
CP_TIME_OUT = 12000 //搓牌倒计时
|
|||
RESULT_TIME_OUT = 5000 //结算倒计时
|
|||
GIVEUP_COUNT = 5 //多少轮不下注踢出去
|
|||
DESTROY_TIME_OUT = 60000 //房间销毁的时间
|
|||
ROBOT_ENTER_TIME_MIN = 2000 //机器人最低入场时间
|
|||
ROBOT_ENTER_TIME_MAX = 6000 //机器人最高入场时间
|
|||
MIN_GAME_SCORE = 50000 // 最低能玩的金额 限制50
|
|||
) |
|||
|
|||
const ( |
|||
USER_OFF_LINE = 0 // 离线
|
|||
USER_ON_LINE = 1 // 在线
|
|||
USER_LEAVE = 2 // 离开
|
|||
) |
|||
|
|||
const ( |
|||
//桌子状态
|
|||
EN_TABLE_STATE_UNKNOWN int32 = 0 // 缺省
|
|||
EN_TABLE_STATE_READY_TO_START int32 = 1 // 准备开始
|
|||
EN_TABLE_STATE_PLAYING int32 = 2 // 游戏中
|
|||
EN_TABLE_STATE_FINISH int32 = 3 // 结算中
|
|||
) |
|||
|
|||
type PokerUserType struct { // 用户牌型排序
|
|||
ChairId int32 |
|||
Bei int |
|||
HandPoker types.PokerSlice // 玩家手牌
|
|||
} |
|||
|
|||
type Room struct { |
|||
RoomProxy *node.Proxy |
|||
Ctx context.Context |
|||
Opt *room.Options //房间的参数
|
|||
TableConfig *gamepb.GameTableTotal |
|||
DestroyRoomFunc func(int64) //销毁房间回调
|
|||
QuitRoomFunc func(int64) //退出房间回调
|
|||
NotifyFunc func(int32, interface{}) //大厅通知回调
|
|||
RId int64 //房间ID
|
|||
RoomID int32 //
|
|||
GameID int32 //
|
|||
ReasonString string //原因字符串
|
|||
AgentID int32 //
|
|||
OffsetHours float64 //时区差
|
|||
MaxPlayerCount int32 //最大玩家数
|
|||
MaxRobotPlayerCount int32 //最大允许机器玩家数
|
|||
PersonalRate int64 // 个人倍率
|
|||
RoomRate int64 // 房间倍率
|
|||
RoomLimit decimal.Decimal //int64// 房间进入条件
|
|||
PlayerMap map[int32]*Player //
|
|||
PlayerWatchMap []*Player //
|
|||
MaxPlayerNum int32 //
|
|||
State int32 //房间状态 0空闲,1准备开始,2花色下注,3花色结算,4二轮下注,5二轮结算
|
|||
PokerIndex int32 //
|
|||
PokersCount int32 //
|
|||
CurrOperationPlayer int32 //
|
|||
CurrentGameState int32 //游戏阶段
|
|||
CreatorId int64 //创建者 0 主房间 其它表示是为哪个点控玩家生成的房间
|
|||
StartTimer int64 //
|
|||
EndTimer int64 //
|
|||
RobotMgr *RobotManager //
|
|||
Round int32 //轮数
|
|||
GameMaxRound int32 //总轮数
|
|||
CurrBanker int32 //当前庄家
|
|||
CurrBeginUser int32 //当前开始玩家
|
|||
BankerLimitMax int64 //庄家最大限红
|
|||
WinPlayer int32 //上一把赢家
|
|||
EndReason int32 //上一把结束原因
|
|||
BoolePool *blood.BoolePool //
|
|||
StockValue int64 //库存值[在初始化房间时候获取,在解散房间时候落地]
|
|||
GronTimer *gron.Cron //
|
|||
CurrentOperationTimer int64 //当前操作时间(单位:毫秒)
|
|||
roomRWLock sync.RWMutex //
|
|||
IsP2pControls bool //
|
|||
shuffleRandPointer *rand.Rand //
|
|||
BetList []int64 //筹码列表
|
|||
UserScore map[int32]decimal.Decimal //本局总输赢
|
|||
|
|||
BaoDiBanker bool //是否保底过
|
|||
GetBankerList []int32 //抢庄的列表
|
|||
NoGetBankerList []int32 //未抢庄的列表
|
|||
CardList types.PokerSlice // 牌堆
|
|||
DropCardList types.PokerSlice // 弃牌堆
|
|||
Record []protocol.HistoryRecord //历史记录
|
|||
BloodCtrl conf.BloodCtrl //血池控制
|
|||
isUserCtl bool //本桌是否人物点控
|
|||
UserCtlGear int64 //人物点控档位
|
|||
|
|||
GuoScore int64 // 锅的钱
|
|||
MinGameScore int64 //最低能玩的金额
|
|||
TimeOutBegin int64 //开始倒计时DT
|
|||
TimeOutGetBanker int64 //抢庄倒计时
|
|||
TimeOutBB int64 //抢庄动画展示倒计时
|
|||
TimeOutDT int64 //丢骰子动画展示倒计时
|
|||
TimeOutBet int64 //下注倒计时
|
|||
TimeOutCP int64 //搓牌倒计时
|
|||
TimeOutResult int64 //结算倒计时
|
|||
TimeKickTimes int64 //多少轮不下注踢出去
|
|||
TimeoutDestroy int64 //不开场房间销毁的时间
|
|||
} |
|||
|
|||
// GetRoomId 获取房间ID
|
|||
func (rr *Room) GetRoomId() int64 { |
|||
return int64(rr.RoomID) |
|||
} |
|||
|
|||
func (rr *Room) GetRId() int64 { // 获取房间RId
|
|||
return rr.RId |
|||
} |
|||
|
|||
func (rr *Room) GetState() int32 { // 获取房间状态
|
|||
return rr.CurrentGameState |
|||
} |
|||
|
|||
func (rr *Room) GetRoomState() int32 { // GetRoomState 房间状态
|
|||
|
|||
if rr.GetRoomPlayerCount() > rr.MaxPlayerCount { |
|||
return 1 //房间满了
|
|||
} |
|||
|
|||
return 0 |
|||
} |
|||
|
|||
// OnPlayerReady 玩家准备
|
|||
func (rr *Room) OnPlayerReady(userId int64, p interface{}) { |
|||
|
|||
} |
|||
|
|||
// GetRoomPlayer 获取玩家-chairId==椅子号
|
|||
func (rr *Room) GetRoomPlayer(chairId int32) *Player { |
|||
return rr.PlayerMap[chairId] |
|||
} |
|||
|
|||
func (rr *Room) GetRoomRealCanBetPlayerCount() int32 { |
|||
count := int32(0) |
|||
for _, v := range rr.PlayerMap { |
|||
if !v.IsRobot && v.CanBet { |
|||
count++ |
|||
} |
|||
} |
|||
return count |
|||
} |
|||
|
|||
// GetRoomPlayerCount 房间人数
|
|||
func (rr *Room) GetRoomPlayerCount() int32 { |
|||
return int32(len(rr.PlayerMap)) |
|||
} |
|||
|
|||
func (rr *Room) GetRoomCanBetPlayerCount() int32 { // 房间可以玩的人
|
|||
count := int32(0) |
|||
for _, v := range rr.PlayerMap { |
|||
if v.CanBet { |
|||
count++ |
|||
} |
|||
} |
|||
return count |
|||
} |
|||
|
|||
func (rr *Room) GetRoomRealPlayerCount() int32 { |
|||
count := int32(0) |
|||
for _, v := range rr.PlayerMap { |
|||
if !v.IsRobot { |
|||
count++ |
|||
} |
|||
} |
|||
return count |
|||
} |
|||
|
|||
// GetRoomPlayerByUid 通过uid取player_obj
|
|||
func (rr *Room) GetRoomPlayerByUid(uid int64) *Player { |
|||
for _, p := range rr.PlayerMap { |
|||
if p.Uid == uid { |
|||
return p |
|||
} |
|||
} |
|||
|
|||
for _, p := range rr.PlayerWatchMap { |
|||
if p.Uid == uid { |
|||
return p |
|||
} |
|||
} |
|||
// for i := rr.players.Front(); i != nil; i = i.Next() {
|
|||
// pPlayer := i.Value.(*Player)
|
|||
// if pPlayer.Uid == uid {
|
|||
// return pPlayer
|
|||
// }
|
|||
// }
|
|||
return nil |
|||
} |
|||
|
|||
func (rr *Room) SetPlayerState(uid int64, state int32) bool { |
|||
p := rr.GetRoomPlayerByUid(uid) |
|||
if p != nil { |
|||
p.OnlineState = state |
|||
return true |
|||
} |
|||
return false |
|||
} |
|||
|
|||
// OnGameOperate 操作
|
|||
func (rr *Room) OnGameOperate(uid int64, state int32) bool { |
|||
|
|||
return true |
|||
} |
|||
func (rr *Room) OnGetGameId() int32 { |
|||
return rr.GameID |
|||
} |
|||
|
|||
// 乱序函数
|
|||
func (rr *Room) shuffleDeck(deck *[]types.Poker) { |
|||
rand.NewSource(time.Now().UnixNano()) // 用当前时间作为随机种子
|
|||
for i := len(*deck) - 1; i > 0; i-- { |
|||
j := rand.Intn(i + 1) // 生成随机索引
|
|||
(*deck)[i], (*deck)[j] = (*deck)[j], (*deck)[i] // 交换
|
|||
} |
|||
} |
|||
|
|||
// 乱序函数
|
|||
func (rr *Room) shuffleDeck2(deck *[]types.PokerSlice) { |
|||
for i := len(*deck) - 1; i > 0; i-- { |
|||
j := rand.Intn(i + 1) // 生成随机索引
|
|||
(*deck)[i], (*deck)[j] = (*deck)[j], (*deck)[i] // 交换
|
|||
} |
|||
} |
|||
|
|||
// 初始化牌组
|
|||
func (rr *Room) InitCardList(CardCount int) { |
|||
rr.CardList = rr.CardList[:0] |
|||
rr.DropCardList = rr.DropCardList[:0] |
|||
|
|||
var TempPoker []types.Poker |
|||
for i := 0; i < CardCount; i++ { |
|||
for _, poker := range types.OnePokers { |
|||
TempPoker = append(TempPoker, poker) |
|||
} |
|||
} |
|||
rr.shuffleDeck(&TempPoker) |
|||
for PokerIndex := 0; PokerIndex < len(TempPoker); PokerIndex++ { |
|||
rr.CardList = append(rr.CardList, TempPoker[PokerIndex]) |
|||
} |
|||
} |
|||
|
|||
func (rr *Room) SearchTypeHandCard() []types.PokerSlice { // 计算一个获胜类型的牌组出来
|
|||
var ResultPokerList []types.PokerSlice |
|||
|
|||
// 先选好五套牌
|
|||
for i := 0; i < MAX_USER_NUM; i++ { |
|||
ResultPokerList[i] = append(ResultPokerList[i], rr.CardList[len(rr.CardList)-2:]...) |
|||
rr.DropCardList = append(rr.DropCardList, ResultPokerList[i]...) |
|||
rr.CardList = rr.CardList[:len(rr.CardList)-2] |
|||
} |
|||
|
|||
log.Debug(" 桌子号 ", rr.RId, " 选好的五套牌 ", ResultPokerList) |
|||
|
|||
// 排序
|
|||
sort.Slice(ResultPokerList, func(i, j int) bool { |
|||
return ResultPokerList[i].Compare(ResultPokerList[j]) == 1 |
|||
}) |
|||
log.Debug(" 桌子号 ", rr.RId, " 排序后 选好的五套牌 ", ResultPokerList) |
|||
|
|||
return ResultPokerList |
|||
} |
@ -0,0 +1,110 @@ |
|||
package game |
|||
|
|||
import ( |
|||
"base/log" |
|||
"github.com/shopspring/decimal" |
|||
"strconv" |
|||
"time" |
|||
"xgame/game/TTZ/app/core/protocol" |
|||
"xgame/game/TTZ/app/route" |
|||
) |
|||
|
|||
func (rr *Room) OnUserBet(uid int64, msg interface{}, Auto bool) { // 用户下注
|
|||
message := msg.(*protocol.BetReq) |
|||
BetRes := &protocol.BetRes{} |
|||
NotifyBet := &protocol.NotifyBet{} |
|||
|
|||
ChairId := int32(-1) |
|||
for _, player := range rr.PlayerMap { |
|||
if player.Uid == uid { |
|||
ChairId = player.ChairId |
|||
break |
|||
} |
|||
} |
|||
|
|||
if ChairId == -1 { |
|||
log.Debug("ChairId == -1") |
|||
return |
|||
} |
|||
|
|||
if rr.CurrentGameState != protocol.STATE_BET { |
|||
log.Debug("玩家", ChairId, "非下注时间不能下注 当前阶段 ", rr.CurrentGameState) |
|||
BetRes.Code = protocol.ErrorCodeBetError |
|||
BetRes.CodeMsg = "非下注时间不能下注 当前阶段 " + strconv.Itoa(int(rr.CurrentGameState)) |
|||
rr.Send(rr.PlayerMap[ChairId], route.BetRes, BetRes) |
|||
return |
|||
} |
|||
|
|||
if message.BetAmount%rr.Opt.MinBetAsset != 0 { |
|||
log.Debug("玩家", ChairId, "必须是最小下注的整数倍 ", rr.Opt.MinBetAsset) |
|||
BetRes.Code = protocol.ErrorCodeBetError |
|||
BetRes.CodeMsg = "必须是最小下注的整数倍 当前最小下注 " + strconv.Itoa(int(rr.Opt.MinBetAsset)) |
|||
rr.Send(rr.PlayerMap[ChairId], route.BetRes, BetRes) |
|||
return |
|||
} |
|||
|
|||
// 下注区域判断
|
|||
player := rr.PlayerMap[ChairId] |
|||
|
|||
if rr.CurrBanker == player.ChairId { |
|||
log.Debug("玩家", ChairId, "是庄家不能下注 ") |
|||
BetRes.Code = protocol.ErrorCodeBetError |
|||
BetRes.CodeMsg = "庄家不能下注 " |
|||
rr.Send(rr.PlayerMap[ChairId], route.BetRes, BetRes) |
|||
return |
|||
} |
|||
|
|||
if !player.IsRobot && message.BetAmount > rr.PlayerMap[ChairId].Gold.IntPart() { |
|||
log.Debug("玩家", ChairId, "个人下注总值", message.BetAmount, " 拥有的钱: ", rr.PlayerMap[ChairId].Gold.IntPart()) |
|||
BetRes.Code = protocol.ErrorCodeBetError |
|||
BetRes.CodeMsg = "玩家最多再下注 " + strconv.Itoa(int(rr.PlayerMap[ChairId].Gold.IntPart())) |
|||
rr.Send(player, route.BetRes, BetRes) |
|||
return |
|||
} |
|||
|
|||
rr.UserScore[ChairId] = rr.UserScore[ChairId].Sub(decimal.NewFromInt(message.BetAmount)) |
|||
player.Gold = player.Gold.Sub(decimal.NewFromInt(message.BetAmount)) |
|||
|
|||
if !player.IsRobot && (player.Ctx != nil) { |
|||
AfterGold, BloodPool, StockNum := rr.WriteUserScore(player, 1, message.BetAmount, 0, 0, rr.ReasonString, "", "", 0) |
|||
log.Debug("WriteUserScore 后 AfterGold=", AfterGold, " BloodPool=", BloodPool, " StockNum=", StockNum) |
|||
} |
|||
|
|||
// 下过注
|
|||
rr.PlayerMap[ChairId].CurrentRoundBet = true |
|||
rr.PlayerMap[ChairId].BetScore = message.BetAmount |
|||
|
|||
BetRes.ChairID = ChairId |
|||
BetRes.TableTotalWin = rr.PlayerMap[ChairId].TableWin |
|||
BetRes.UserScore = rr.PlayerMap[ChairId].Gold.IntPart() |
|||
|
|||
NotifyBet.ChairID = BetRes.ChairID |
|||
NotifyBet.TableTotalWin = BetRes.TableTotalWin |
|||
|
|||
for _, TempPlayer := range rr.PlayerMap { |
|||
if TempPlayer.ChairId == ChairId { |
|||
rr.Send(TempPlayer, route.BetRes, BetRes) |
|||
} else { |
|||
rr.Send(TempPlayer, route.NotifyBet, NotifyBet) |
|||
} |
|||
} |
|||
|
|||
for _, TempPlayer := range rr.PlayerWatchMap { |
|||
rr.Send(TempPlayer, route.NotifyBet, NotifyBet) |
|||
} |
|||
|
|||
// 判断是否提前结束
|
|||
bEnd := true |
|||
for _, TempPlayer := range rr.PlayerMap { |
|||
if TempPlayer.CanBet && !TempPlayer.CurrentRoundBet { |
|||
bEnd = false |
|||
break |
|||
} |
|||
} |
|||
|
|||
if !Auto && bEnd { // 不是自动才能提前结算
|
|||
log.Debug("OnUserBet 桌子号 ", rr.RId, " 提前结束 ") |
|||
milliseconds := time.Now().UnixMilli() |
|||
rr.CurrentOperationTimer = milliseconds |
|||
} |
|||
} |
@ -0,0 +1,24 @@ |
|||
package game |
|||
|
|||
// check检查[]
|
|||
func (rr *Room) check() bool { |
|||
//1.检查人数[机器人加真玩家]
|
|||
if rr.GetRoomPlayerCount() < 1 { |
|||
return false |
|||
} |
|||
|
|||
if rr.GetInRoomRobotCount() <= 0 { |
|||
return false |
|||
} |
|||
|
|||
return true |
|||
} |
|||
|
|||
func (rr *Room) IsJoinRoom() bool { |
|||
|
|||
if rr.GetRoomPlayerCount() >= MAX_USER_NUM { |
|||
return false |
|||
} |
|||
|
|||
return true |
|||
} |
@ -0,0 +1,103 @@ |
|||
package game |
|||
|
|||
import ( |
|||
"math/rand" |
|||
"sort" |
|||
"time" |
|||
) |
|||
|
|||
func (rr *Room) ColorGroup(arr []int) map[int][]int { |
|||
|
|||
cardMap := map[int][]int{} |
|||
|
|||
for _, c := range arr { |
|||
clo := c >> 4 |
|||
cardMap[clo] = append(cardMap[clo], c) |
|||
} |
|||
temphandCards := map[int][]int{} |
|||
for i, items := range cardMap { |
|||
var tempItem []int |
|||
for _, item := range items { |
|||
tempItem = append(tempItem, item) |
|||
} |
|||
sort.Ints(tempItem) |
|||
temphandCards[i] = tempItem |
|||
} |
|||
|
|||
return temphandCards |
|||
} |
|||
|
|||
// GetInRoomRobotCount 获取房间机器人数量
|
|||
func (rr *Room) GetInRoomRobotCount() int32 { |
|||
unm := int32(0) |
|||
|
|||
for _, player := range rr.PlayerMap { |
|||
if player.IsRobot == true { |
|||
unm++ |
|||
} |
|||
} |
|||
return unm |
|||
} |
|||
|
|||
// MakeChairId 分配椅子号 如果分配到-1表示房间满了
|
|||
func (rr *Room) MakeChairId() int32 { |
|||
|
|||
chairId := int32(-1) |
|||
for i := int32(0); i < rr.MaxPlayerCount; i++ { |
|||
if rr.GetRoomPlayer(i) == nil { |
|||
chairId = i |
|||
break |
|||
} |
|||
} |
|||
|
|||
return chairId |
|||
} |
|||
|
|||
// ArrayToMap arr装map
|
|||
func (rr *Room) ArrayToMap(arr []int) map[int]int { |
|||
var tempMap map[int]int |
|||
for _, v := range arr { |
|||
tempMap[v]++ |
|||
} |
|||
return tempMap |
|||
} |
|||
|
|||
// MapToArray map装arr
|
|||
func (rr *Room) MapToArray(m map[int]int) []int { |
|||
var tempArr = make([]int, 0) |
|||
for k, v := range m { |
|||
for i := 0; i < v; i++ { |
|||
tempArr = append(tempArr, k) |
|||
} |
|||
} |
|||
return tempArr |
|||
} |
|||
|
|||
// BoolPoolConfigToRoomConfig 数据库中的配置形式转成自己的形式
|
|||
func (rr *Room) BoolPoolConfigToRoomConfig() { |
|||
//rr.boolePool.BoolPoolConfig.ControValue
|
|||
} |
|||
|
|||
// CalWeight 权重计算
|
|||
func (rr *Room) CalWeight(weightVal []int32) int32 { |
|||
l := len(weightVal) |
|||
sum := int32(0) |
|||
for _, val := range weightVal { |
|||
sum += val |
|||
} |
|||
|
|||
R := rand.New(rand.NewSource(int64(uint64(time.Now().UnixNano())))) |
|||
randVal := R.Int31n(sum) |
|||
|
|||
grade := int32(0) |
|||
|
|||
for i := int32(0); i < int32(l); i++ { |
|||
if randVal <= weightVal[i] { |
|||
grade = i |
|||
break |
|||
} |
|||
randVal -= weightVal[i] |
|||
} |
|||
|
|||
return grade |
|||
} |
@ -0,0 +1,72 @@ |
|||
package game |
|||
|
|||
import ( |
|||
"base/log" |
|||
conf "xgame/game/TTZ/app/config" |
|||
) |
|||
|
|||
func (rr *Room) InitBloodControl() { |
|||
rr.BloodCtrl = conf.ReadBloodConfig() |
|||
|
|||
log.Debug("InitBloodControl: GameRound=", rr.BloodCtrl.GameRound) |
|||
|
|||
if rr.BloodCtrl.TimeOutBegin == 0 { |
|||
rr.TimeOutBegin = NEXT_GAME_TIME_OUT |
|||
} else { |
|||
rr.TimeOutBegin = rr.BloodCtrl.TimeOutBegin |
|||
} |
|||
|
|||
if rr.BloodCtrl.TimeOutGetBanker == 0 { |
|||
rr.TimeOutGetBanker = GET_BANKER_TIME_OUT |
|||
} else { |
|||
rr.TimeOutGetBanker = rr.BloodCtrl.TimeOutGetBanker |
|||
} |
|||
|
|||
if rr.BloodCtrl.TimeOutBB == 0 { |
|||
rr.TimeOutBB = BB_TIME_OUT |
|||
} else { |
|||
rr.TimeOutBB = rr.BloodCtrl.TimeOutBB |
|||
} |
|||
|
|||
if rr.BloodCtrl.TimeOutDT == 0 { |
|||
rr.TimeOutDT = DT_TIME_OUT |
|||
} else { |
|||
rr.TimeOutDT = rr.BloodCtrl.TimeOutDT |
|||
} |
|||
|
|||
if rr.BloodCtrl.TimeOutBet == 0 { |
|||
rr.TimeOutBet = BET_TIME_OUT |
|||
} else { |
|||
rr.TimeOutBet = rr.BloodCtrl.TimeOutBet |
|||
} |
|||
|
|||
if rr.BloodCtrl.TimeOutCP == 0 { |
|||
rr.TimeOutCP = CP_TIME_OUT |
|||
} else { |
|||
rr.TimeOutCP = rr.BloodCtrl.TimeOutCP |
|||
} |
|||
|
|||
if rr.BloodCtrl.TimeOutResult == 0 { |
|||
rr.TimeOutResult = RESULT_TIME_OUT |
|||
} else { |
|||
rr.TimeOutResult = rr.BloodCtrl.TimeOutResult |
|||
} |
|||
|
|||
if rr.BloodCtrl.TimeKickTimes == 0 { |
|||
rr.TimeKickTimes = GIVEUP_COUNT |
|||
} else { |
|||
rr.TimeKickTimes = rr.BloodCtrl.TimeKickTimes |
|||
} |
|||
|
|||
if rr.BloodCtrl.TimeoutDestroy == 0 { |
|||
rr.TimeoutDestroy = DESTROY_TIME_OUT |
|||
} else { |
|||
rr.TimeoutDestroy = rr.BloodCtrl.TimeoutDestroy |
|||
} |
|||
|
|||
if rr.BloodCtrl.MinGameScore == 0 { |
|||
rr.MinGameScore = MIN_GAME_SCORE |
|||
} else { |
|||
rr.MinGameScore = rr.BloodCtrl.MinGameScore |
|||
} |
|||
} |
@ -0,0 +1,121 @@ |
|||
package game |
|||
|
|||
import ( |
|||
"base/encoding/json" |
|||
"base/log" |
|||
"github.com/roylee0704/gron" |
|||
"github.com/shopspring/decimal" |
|||
"time" |
|||
"xgame/game/TTZ/app/core/protocol" |
|||
"xgame/game/service/rpc_client" |
|||
optionRoom "xgame/internal/option/room" |
|||
"xgame/internal/service/game/pb" |
|||
) |
|||
|
|||
func (rr *Room) Copy(SrcRoom *Room, Uid int64) { |
|||
// 获取当前时间
|
|||
now := time.Now() |
|||
|
|||
// 获取当前时区的偏移量
|
|||
_, offset := now.Zone() |
|||
|
|||
// 将偏移量转换为小时数
|
|||
offsetHours := float64(offset) / 3600 |
|||
|
|||
rr.OffsetHours = offsetHours |
|||
log.Debug("当前时间 ", now, " 当前时区偏差值", rr.OffsetHours) |
|||
// 读取配置文件
|
|||
rr.InitBloodControl() |
|||
|
|||
//配置库存[房间的库存]
|
|||
rr.StockValue = rr.BoolePool.BoolPoolSockNum |
|||
|
|||
//2.初始化配置设置房间 opts
|
|||
rr.Opt = &optionRoom.Options{} |
|||
var replyOpt *pb.FetchRoomsReply |
|||
if rr.RoomID < 6 { |
|||
replyOpt = rpc_client.GetSrcRoomByLevel(rr.RoomProxy, rr.GameID, rr.AgentID, rr.RoomID) |
|||
} else { |
|||
replyOpt = rpc_client.GetSrcRoom(rr.RoomProxy, rr.GameID, rr.AgentID, rr.RoomID) |
|||
} |
|||
|
|||
if replyOpt == nil { |
|||
log.Debug("初始化房间失败") |
|||
} else { |
|||
err1 := json.Unmarshal([]byte(replyOpt.RoomOpts), rr.Opt) |
|||
if err1 != nil { |
|||
log.Debug(err1) |
|||
} |
|||
} |
|||
|
|||
log.Debug("房间配置: ", rr.Opt) |
|||
|
|||
//1.初始化血池
|
|||
if rr.BoolePool.SetBoole(rr.RoomProxy, rr.Opt.BloodId) == false { |
|||
log.Debug("初始化血池失败") |
|||
} |
|||
|
|||
//机器人数
|
|||
rr.MaxRobotPlayerCount = MAX_ROBOT_BUN |
|||
//房间最大人数
|
|||
rr.MaxPlayerCount = MAX_USER_NUM |
|||
// 个人倍率
|
|||
rr.PersonalRate = rr.Opt.PersonalRate |
|||
// 房间倍率
|
|||
rr.RoomRate = rr.Opt.RoomRate |
|||
// 最大轮数
|
|||
rr.GameMaxRound = 1000 // todo 这里需要从配置获取
|
|||
// 房间进入条件
|
|||
rr.RoomLimit = decimal.NewFromFloat(float64(rr.Opt.MinEnterAsset)) |
|||
// 底注
|
|||
rr.BetList = rr.Opt.BetAssetOptions |
|||
|
|||
//new一个定时器
|
|||
if rr.GronTimer != nil { |
|||
rr.GronTimer.Stop() |
|||
rr.GronTimer = nil |
|||
} |
|||
|
|||
rr.GronTimer = gron.New() |
|||
rr.GronTimer.AddFunc(gron.Every(50*time.Millisecond), func() { |
|||
rr.run() |
|||
}) |
|||
|
|||
rr.GronTimer.Start() |
|||
|
|||
//初始化机器人配置
|
|||
rr.RobotMgr.OnInit("", rr) |
|||
|
|||
// 复制桌子上的人过来
|
|||
for i, i2 := range SrcRoom.PlayerMap { |
|||
if i2.IsRobot { |
|||
rr.PlayerMap[i] = i2 |
|||
rr.RobotMgr.CopyRobotsEnterGameRoom(i2) |
|||
} |
|||
|
|||
if Uid == i2.Uid { |
|||
rr.PlayerMap[i] = i2 |
|||
} |
|||
} |
|||
|
|||
// 删除挪过来的人
|
|||
for i, i2 := range SrcRoom.PlayerMap { |
|||
if Uid == i2.Uid { |
|||
SrcRoom.PlayerMap[i] = nil |
|||
delete(SrcRoom.PlayerMap, i) |
|||
break |
|||
} |
|||
} |
|||
|
|||
// 复制记录
|
|||
for _, record := range SrcRoom.Record { |
|||
rr.Record = append(rr.Record, record) |
|||
} |
|||
|
|||
rr.State = EN_TABLE_STATE_READY_TO_START |
|||
milliseconds := time.Now().UnixMilli() |
|||
rr.CurrentGameState = protocol.STATE_BEGIN |
|||
rr.CurrentOperationTimer = milliseconds + rr.TimeOutBegin |
|||
|
|||
return |
|||
} |
@ -0,0 +1,46 @@ |
|||
package game |
|||
|
|||
import ( |
|||
"base/log" |
|||
"math/rand" |
|||
"strconv" |
|||
) |
|||
|
|||
func (rr *Room) GetCtrlBlood() int { // 0 不控 1 系统赢 2 系统输
|
|||
//return 0 // 测试添加
|
|||
|
|||
TemPro := 10000 // todo 测试后删除
|
|||
//log.Debug(" 桌子号", rr.RId, "房间当前血池 :", rr.BoolePool)
|
|||
CurrentGears := 0 |
|||
TempRoomGears, err := strconv.Atoi(rr.BoolePool.RoomGears) |
|||
if err == nil { |
|||
CurrentGears = TempRoomGears |
|||
//log.Debug(" 桌子号", rr.RId, "房间当前血池档位1 :", TempRoomGears, " CurrentGears :", CurrentGears)
|
|||
} |
|||
|
|||
//判断点控
|
|||
if rr.CreatorId != 0 && rr.isUserCtl { |
|||
CurrentGears = int(rr.UserCtlGear) |
|||
//log.Debug(" 桌子号", rr.RId, "房间当前血池档位2 :", rr.UserCtlGear, " CurrentGears :", CurrentGears)
|
|||
} |
|||
|
|||
for _, TempGearConfig := range rr.BloodCtrl.GearConfig { |
|||
if TempGearConfig.GearID == CurrentGears { |
|||
TemPro = TempGearConfig.WinPro |
|||
break |
|||
} |
|||
} |
|||
|
|||
log.Debug(" 桌子号", rr.RId, "房间当前血池 :", rr.BoolePool, "是否个人点控 :", rr.isUserCtl, "点控档位 :", CurrentGears, " 房间点控", TempRoomGears, " 当前的概率", TemPro) |
|||
|
|||
// 正数血池抽中控制 控系统赢 负数血池控系统输
|
|||
if rr.GetInRoomRobotCount() > 0 && rand.Intn(10000) < TemPro { |
|||
if CurrentGears >= 0 { |
|||
return 1 |
|||
} else { |
|||
return 2 |
|||
} |
|||
} else { |
|||
return 0 |
|||
} |
|||
} |
@ -0,0 +1,36 @@ |
|||
package game |
|||
|
|||
import "base/log" |
|||
|
|||
/* |
|||
OnReconnect(userId int64, proxy *node.Proxy) // 断线重连
|
|||
OnDisconnect(userId int64, proxy *node.Proxy) // 玩家离线
|
|||
*/ |
|||
// OnDisconnect 玩家离线 保存正在游戏的进度
|
|||
func (rr *Room) OnDisconnect(userId int64) { |
|||
rr.roomRWLock.Lock() |
|||
|
|||
log.Debug(" 桌子号", rr.RId, "玩家", userId, "离线") |
|||
|
|||
for _, player := range rr.PlayerMap { |
|||
if player != nil { |
|||
if player.Uid == userId { |
|||
player.OnlineState = USER_OFF_LINE |
|||
break |
|||
} |
|||
} |
|||
} |
|||
|
|||
for _, player := range rr.PlayerWatchMap { |
|||
if player != nil { |
|||
if player.Uid == userId { |
|||
player.OnlineState = USER_OFF_LINE |
|||
rr.roomRWLock.Unlock() |
|||
rr.OnGetOutRoom(player.Uid) |
|||
rr.roomRWLock.Lock() |
|||
break |
|||
} |
|||
} |
|||
} |
|||
rr.roomRWLock.Unlock() |
|||
} |
@ -0,0 +1,10 @@ |
|||
package game |
|||
|
|||
func (rr *Room) IsCanDissolution() bool { // IsCanDissolution是否能解散房间
|
|||
|
|||
return false |
|||
} |
|||
|
|||
func (rr *Room) OnDestroy(uid int64) { |
|||
rr.DestroyRoomFunc(uid) |
|||
} |
@ -0,0 +1,64 @@ |
|||
package game |
|||
|
|||
import ( |
|||
"base/log" |
|||
"time" |
|||
"xgame/game/TTZ/app/core/protocol" |
|||
"xgame/game/TTZ/app/route" |
|||
) |
|||
|
|||
func (rr *Room) OnUserGetBanker(uid int64, msg interface{}) { // 用户抢庄
|
|||
message := msg.(*protocol.GetBankerReq) |
|||
BankerRes := &protocol.GetBankerRes{} |
|||
NotifyBanker := &protocol.NotifyBanker{} |
|||
|
|||
ChairId := int32(-1) |
|||
for _, player := range rr.PlayerMap { |
|||
if player.Uid == uid { |
|||
ChairId = player.ChairId |
|||
break |
|||
} |
|||
} |
|||
|
|||
if ChairId == -1 { |
|||
log.Error("致命错误") |
|||
return |
|||
} |
|||
|
|||
if rr.CurrentGameState != protocol.STATE_GET_BANKER { |
|||
log.Debug("玩家", ChairId, "非等待时间不能抢庄 ", rr.CurrentGameState) |
|||
BankerRes.Code = protocol.ErrorGetBanker |
|||
BankerRes.CodeMsg = "非抢庄时间不能抢庄" |
|||
rr.Send(rr.PlayerMap[ChairId], route.GetBankerRes, BankerRes) |
|||
return |
|||
} |
|||
|
|||
NotifyBanker.ChairID = ChairId |
|||
NotifyBanker.State = message.State |
|||
for _, TempPlayer := range rr.PlayerMap { |
|||
if TempPlayer.ChairId == ChairId { |
|||
rr.Send(TempPlayer, route.GetBankerRes, BankerRes) |
|||
} else { |
|||
rr.Send(TempPlayer, route.NotifyBanker, NotifyBanker) |
|||
} |
|||
} |
|||
for _, TempPlayer := range rr.PlayerWatchMap { |
|||
rr.Send(TempPlayer, route.NotifyBanker, NotifyBanker) |
|||
} |
|||
|
|||
if message.State == 0 { |
|||
rr.BaoDiBanker = true |
|||
rr.GetBankerList = append(rr.GetBankerList, ChairId) |
|||
//log.Debug(" 桌子号", rr.RId, "玩家", ChairId, " 抢庄 是否机器人", rr.PlayerMap[ChairId].IsRobot)
|
|||
} else { |
|||
rr.NoGetBankerList = append(rr.NoGetBankerList, ChairId) |
|||
//log.Debug(" 桌子号", rr.RId, "玩家", ChairId, " 不抢 是否机器人", rr.PlayerMap[ChairId].IsRobot)
|
|||
} |
|||
|
|||
// 判断是否提前结束
|
|||
if len(rr.PlayerMap) == (len(rr.GetBankerList) + len(rr.NoGetBankerList)) { // 提前开始
|
|||
//log.Debug("OnUserBet 桌子号 ", rr.RId, " 抢庄提前结束 ")
|
|||
milliseconds := time.Now().UnixMilli() |
|||
rr.CurrentOperationTimer = milliseconds |
|||
} |
|||
} |
@ -0,0 +1,128 @@ |
|||
package game |
|||
|
|||
import ( |
|||
"base/cluster/node" |
|||
"base/log" |
|||
"time" |
|||
"xgame/game/TTZ/app/core/protocol" |
|||
"xgame/game/TTZ/app/route" |
|||
) |
|||
|
|||
func (rr *Room) OnGetRoomInfo(uid int64, ctx *node.Context) interface{} { |
|||
var pPlayer *Player |
|||
|
|||
TableInfo := &protocol.RoomInfoRes{} |
|||
now := time.Now() |
|||
|
|||
TableInfo.RoomId = int32(rr.RId) |
|||
TableInfo.ServerLocation = rr.OffsetHours |
|||
TableInfo.ServerTimestamp = now.UnixMilli() |
|||
TableInfo.RoomStatus = rr.CurrentGameState |
|||
TableInfo.StatusChangeTimestamp = rr.CurrentOperationTimer |
|||
TableInfo.SingleMaxBet = rr.BankerLimitMax |
|||
TableInfo.RoomConfig = &protocol.TableConfig{ |
|||
AlwaysBet: rr.Opt.AlwaysBet, |
|||
RechargeLimit: rr.BloodCtrl.RechargeLimit, |
|||
TaxMing: rr.Opt.BrightRate, |
|||
} |
|||
|
|||
for _, player := range rr.PlayerMap { |
|||
if player.Uid == uid { |
|||
pPlayer = player |
|||
} |
|||
|
|||
TableSeat := &protocol.RoomPlayer{} |
|||
TableSeat.Uid = player.Uid |
|||
TableSeat.ChairID = player.ChairId |
|||
TableSeat.State = rr.State |
|||
TableSeat.Avatar = player.Avatar |
|||
TableSeat.Gold = player.Gold.IntPart() |
|||
TableSeat.Nickname = player.Nickname |
|||
TableSeat.Sex = player.Sex |
|||
TableSeat.Vip = 0 |
|||
TableSeat.Level = player.Level |
|||
TableSeat.Exp = 0 |
|||
TableSeat.BetScore = player.BetScore |
|||
TableSeat.EndScore = player.WinScore |
|||
TableSeat.CanBet = player.CanBet |
|||
if player.ChairId == rr.CurrBanker { |
|||
TableSeat.IsBanker = 1 |
|||
} |
|||
for _, poker := range player.HandPoker { |
|||
TableSeat.HandPoker = append(TableSeat.HandPoker, int32(poker)) |
|||
} |
|||
|
|||
TableSeat.PokerType, TableSeat.Point = player.HandPoker.GetCardType() |
|||
TableSeat.BetScore = player.BetScore |
|||
|
|||
TableInfo.PlayerList = append(TableInfo.PlayerList, TableSeat) |
|||
} |
|||
|
|||
for _, player := range rr.PlayerWatchMap { |
|||
if player.Uid == uid { |
|||
pPlayer = player |
|||
} |
|||
|
|||
TableSeat := &protocol.RoomPlayer{} |
|||
TableSeat.Uid = player.Uid |
|||
TableSeat.ChairID = player.ChairId |
|||
TableSeat.State = rr.State |
|||
TableSeat.Avatar = player.Avatar |
|||
TableSeat.Gold = player.Gold.IntPart() |
|||
TableSeat.Nickname = player.Nickname |
|||
TableSeat.Sex = player.Sex |
|||
TableSeat.Vip = 0 |
|||
TableSeat.Level = player.Level |
|||
TableSeat.Exp = 0 |
|||
TableSeat.EndScore = player.WinScore |
|||
TableSeat.CanBet = player.CanBet |
|||
if player.ChairId == rr.CurrBanker { |
|||
TableSeat.IsBanker = 1 |
|||
} |
|||
for _, poker := range player.HandPoker { |
|||
TableSeat.HandPoker = append(TableSeat.HandPoker, int32(poker)) |
|||
} |
|||
|
|||
TableSeat.PokerType, TableSeat.Point = player.HandPoker.GetCardType() |
|||
TableSeat.BetScore = player.BetScore |
|||
TableInfo.PlayerWatchMap = append(TableInfo.PlayerWatchMap, TableSeat) |
|||
} |
|||
|
|||
TableInfo.Record = rr.Record |
|||
|
|||
log.Debug("TableInfo==>", TableInfo) |
|||
if pPlayer != nil && !pPlayer.IsRobot { |
|||
for index, record := range rr.Record { |
|||
log.Debug("现在有 ", len(rr.Record), " 个记录 当前第 ", index, " 个 值:", record) |
|||
} |
|||
} |
|||
|
|||
////加分测试
|
|||
//if !pPlayer.IsRobot && (pPlayer.Ctx != nil) {
|
|||
// rpc_client.IncrAsset(pPlayer.Ctx, int64(10000000),int32(model.UserGoldChangeReasonRummy))
|
|||
//}
|
|||
|
|||
pPlayer.Ctx = ctx |
|||
rr.SendTableInfo(pPlayer, route.RoomInfoRes, TableInfo) |
|||
|
|||
// 发送完桌子消息 再激活用户状态
|
|||
pPlayer.OnlineState = USER_ON_LINE |
|||
|
|||
//判断开场
|
|||
if rr.CurrentGameState < protocol.STATE_GET_BANKER && rr.GetRoomPlayerCount() > 1 { |
|||
rr.State = EN_TABLE_STATE_PLAYING |
|||
milliseconds := time.Now().UnixMilli() |
|||
rr.CurrentGameState = protocol.STATE_GET_BANKER |
|||
rr.CurrentOperationTimer = milliseconds + rr.TimeOutGetBanker |
|||
rr.RepeatRoomUser() |
|||
|
|||
rr.SendAllMessage(route.NotifyStateTime, &protocol.NotifyStateTime{ |
|||
NextState: protocol.STATE_GET_BANKER, |
|||
NextTimestamp: rr.CurrentOperationTimer, |
|||
}) |
|||
// 抢庄做了加一秒的容错判断
|
|||
rr.CurrentOperationTimer += 1000 |
|||
} |
|||
|
|||
return TableInfo |
|||
} |
@ -0,0 +1,138 @@ |
|||
package game |
|||
|
|||
import ( |
|||
"base/encoding/json" |
|||
"base/log" |
|||
"strconv" |
|||
"time" |
|||
"xgame/game/TTZ/app/core/protocol" |
|||
"xgame/game/service/rpc_client" |
|||
optionRoom "xgame/internal/option/room" |
|||
"xgame/internal/service/game/pb" |
|||
|
|||
"github.com/roylee0704/gron" |
|||
"github.com/shopspring/decimal" |
|||
) |
|||
|
|||
type ReadData struct { |
|||
Pokers []int `json:"pokers"` |
|||
CardType int `json:"card_type"` |
|||
Code int `json:"code"` |
|||
} |
|||
|
|||
type ConstantDelaySchedule struct { |
|||
Delay time.Duration |
|||
} |
|||
|
|||
// Every returns a crontab Schedule that activates once every duration.
|
|||
// Delays of less than a second are not supported (will round up to 1 second).
|
|||
// Any fields less than a Second are truncated.
|
|||
func Every(duration time.Duration) ConstantDelaySchedule { |
|||
MinTime := 100 * time.Millisecond |
|||
if duration < MinTime { |
|||
duration = MinTime |
|||
} |
|||
return ConstantDelaySchedule{ |
|||
Delay: duration, |
|||
} |
|||
} |
|||
|
|||
func (schedule ConstantDelaySchedule) Next(t time.Time) time.Time { |
|||
return t.Add(schedule.Delay) |
|||
} |
|||
|
|||
// OnInit 初始化房间
|
|||
func (rr *Room) OnInit() bool { |
|||
// 获取当前时间
|
|||
now := time.Now() |
|||
|
|||
// 获取当前时区的偏移量
|
|||
_, offset := now.Zone() |
|||
|
|||
// 将偏移量转换为小时数
|
|||
offsetHours := float64(offset) / 3600 |
|||
|
|||
rr.OffsetHours = offsetHours |
|||
log.Debug("当前时间 ", now, " 当前时区偏差值", rr.OffsetHours) |
|||
|
|||
// 读取配置文件
|
|||
rr.InitBloodControl() |
|||
|
|||
var gameTableConfig *pb.FetchGameTableTotalsReply |
|||
TableType := int64(1) //1 系统 2玩家
|
|||
if rr.CreatorId != 0 { |
|||
TableType = 2 |
|||
} |
|||
gameTableConfig = rpc_client.GetTableCtrlConfig(rr.RoomProxy, int64(rr.GameID), strconv.Itoa(int(rr.RoomID)), TableType) |
|||
if len(gameTableConfig.List) == 0 { |
|||
log.Error(" 21点后台获取桌子配置 无配置 房间等级 ", rr.RoomID) |
|||
} else { |
|||
rr.TableConfig = gameTableConfig.List[0] |
|||
log.Debug(" 21点后台获取桌子配置 房间等级 ", rr.RoomID, " 配置 ", rr.TableConfig) |
|||
} |
|||
|
|||
//配置库存[房间的库存]
|
|||
rr.StockValue = rr.BoolePool.BoolPoolSockNum |
|||
|
|||
//2.初始化配置设置房间 opts
|
|||
rr.Opt = &optionRoom.Options{} |
|||
var replyOpt *pb.FetchRoomsReply |
|||
if rr.RoomID < 6 { |
|||
replyOpt = rpc_client.GetSrcRoomByLevel(rr.RoomProxy, rr.GameID, rr.AgentID, rr.RoomID) |
|||
} else { |
|||
replyOpt = rpc_client.GetSrcRoom(rr.RoomProxy, rr.GameID, rr.AgentID, rr.RoomID) |
|||
} |
|||
|
|||
if replyOpt == nil { |
|||
log.Debug("初始化房间失败") |
|||
} else { |
|||
err1 := json.Unmarshal([]byte(replyOpt.RoomOpts), rr.Opt) |
|||
if err1 != nil { |
|||
log.Debug(err1) |
|||
} |
|||
} |
|||
|
|||
log.Debug("房间配置: ", rr.Opt) |
|||
|
|||
//1.初始化血池
|
|||
if rr.BoolePool.SetBoole(rr.RoomProxy, rr.Opt.BloodId) == false { |
|||
log.Debug("初始化血池失败") |
|||
} |
|||
|
|||
//机器人数
|
|||
rr.MaxRobotPlayerCount = MAX_ROBOT_BUN |
|||
//房间最大人数
|
|||
rr.MaxPlayerCount = MAX_USER_NUM |
|||
// 个人倍率
|
|||
rr.PersonalRate = rr.Opt.PersonalRate |
|||
// 房间倍率
|
|||
rr.RoomRate = rr.Opt.RoomRate |
|||
// 最大轮数
|
|||
rr.GameMaxRound = 1000 // todo 这里需要从配置获取
|
|||
// 房间进入条件
|
|||
rr.RoomLimit = decimal.NewFromFloat(float64(rr.Opt.MinEnterAsset)) |
|||
// 底注
|
|||
rr.BetList = rr.Opt.BetAssetOptions |
|||
|
|||
//new一个定时器
|
|||
if rr.GronTimer != nil { |
|||
rr.GronTimer.Stop() |
|||
rr.GronTimer = nil |
|||
} |
|||
|
|||
rr.GronTimer = gron.New() |
|||
rr.GronTimer.AddFunc(Every(50*time.Millisecond), func() { |
|||
rr.run() |
|||
}) |
|||
|
|||
rr.GronTimer.Start() |
|||
//初始化机器人配置
|
|||
rr.RobotMgr.OnInit("", rr) |
|||
|
|||
rr.State = EN_TABLE_STATE_READY_TO_START |
|||
milliseconds := time.Now().UnixMilli() |
|||
rr.CurrentGameState = protocol.STATE_WAIT |
|||
rr.CurrentOperationTimer = milliseconds + rr.TimeoutDestroy |
|||
|
|||
return true |
|||
} |
@ -0,0 +1,130 @@ |
|||
package game |
|||
|
|||
import ( |
|||
"base/log" |
|||
"github.com/shopspring/decimal" |
|||
"xgame/game/TTZ/app/core/protocol" |
|||
"xgame/game/TTZ/app/route" |
|||
) |
|||
|
|||
// JoinRoom 玩家加入房间 0==加入房间成功,-1==满员了
|
|||
func (rr *Room) JoinRoom(pPlayer *Player, isWatching int32) int32 { |
|||
rr.roomRWLock.Lock() |
|||
defer rr.roomRWLock.Unlock() |
|||
|
|||
//res := &protocol.SitDownRes{}
|
|||
chairId := rr.MakeChairId() |
|||
//// 测试添加
|
|||
//if pPlayer.Uid == 75 {
|
|||
// chairId = -1
|
|||
//}
|
|||
//if -1 == chairId {
|
|||
// //说明满员了
|
|||
// //rr.Send(pPlayer.Uid, 0, res)
|
|||
// res.Code = -1
|
|||
// res.CodeMsg = "满员了"
|
|||
// if pPlayer.Ctx != nil && !pPlayer.IsRobot {
|
|||
// pPlayer.Ctx.Request.Message.Route = route.Enter
|
|||
// err := pPlayer.Ctx.Response(res)
|
|||
// if err != nil {
|
|||
// log.Errorf("response message failed: %v", err)
|
|||
// }
|
|||
// }
|
|||
// return -1
|
|||
//}
|
|||
|
|||
//钱不够 不能进
|
|||
if pPlayer.Gold.LessThan(rr.RoomLimit) { |
|||
return -1 |
|||
} |
|||
|
|||
//钱不够 直接观战
|
|||
if pPlayer.Gold.LessThan(decimal.NewFromInt(rr.MinGameScore)) { |
|||
chairId = -1 |
|||
} |
|||
|
|||
//要求观战
|
|||
if isWatching == 1 { |
|||
chairId = -1 |
|||
} |
|||
|
|||
//rr.RoomLimit
|
|||
|
|||
pPlayer.ChairId = chairId |
|||
pPlayer.OnlineState = USER_LEAVE |
|||
pPlayer.IsCheat = false |
|||
pPlayer.CanBet = false |
|||
rr.isUserCtl = false |
|||
pPlayer.CheatType = 0 |
|||
pPlayer.CheatValue = 0 |
|||
|
|||
if !pPlayer.IsRobot { |
|||
Reply := rr.GetUserGameControl(rr.RoomProxy, pPlayer.Uid, int64(rr.GameID), 0) |
|||
if Reply != nil && Reply.CheatValue != 0 { |
|||
log.Debug(" 桌子号", rr.RId, "房间:", rr.RoomID, "真玩家uid==", pPlayer.Uid, " 更新点控:", Reply) |
|||
rr.isUserCtl = true |
|||
pPlayer.IsCheat = true |
|||
pPlayer.CheatType = Reply.CheatType |
|||
pPlayer.CheatValue = Reply.CheatValue |
|||
} |
|||
log.Debug(" 桌子号", rr.RId, "房间:", rr.RoomID, "真玩家uid==", pPlayer.Uid, " 点控类型:", pPlayer.CheatType, " 点控值:", pPlayer.CheatValue, " 是否点控", pPlayer.IsCheat) |
|||
} |
|||
|
|||
log.Debug(" 桌子号", rr.RId, "玩家名字:", pPlayer.Nickname, " 桌位号:", chairId, "加入房间==>") |
|||
|
|||
SitDownRes := &protocol.SitDownRes{ |
|||
Code: 0, |
|||
CodeMsg: "sit success", |
|||
PlayerInfo: &protocol.RoomPlayer{}, |
|||
} |
|||
|
|||
NotifySitDown := &protocol.NoticeSitDown{ |
|||
PlayerInfo: &protocol.RoomPlayer{}, |
|||
} |
|||
|
|||
TableSeat := &protocol.RoomPlayer{} |
|||
TableSeat.Uid = pPlayer.Uid |
|||
TableSeat.ChairID = pPlayer.ChairId |
|||
TableSeat.State = rr.State |
|||
TableSeat.Avatar = pPlayer.Avatar |
|||
TableSeat.Gold = pPlayer.Gold.IntPart() |
|||
TableSeat.Nickname = pPlayer.Nickname |
|||
TableSeat.Sex = pPlayer.Sex |
|||
TableSeat.Vip = 0 |
|||
TableSeat.Level = pPlayer.Level |
|||
TableSeat.Exp = 0 |
|||
TableSeat.BetScore = pPlayer.BetScore |
|||
TableSeat.EndScore = pPlayer.WinScore |
|||
SitDownRes.PlayerInfo = TableSeat |
|||
NotifySitDown.PlayerInfo = TableSeat |
|||
|
|||
if chairId == -1 { |
|||
// 观战
|
|||
rr.PlayerWatchMap = append(rr.PlayerWatchMap, pPlayer) |
|||
} else { |
|||
rr.PlayerMap[pPlayer.ChairId] = pPlayer |
|||
} |
|||
|
|||
for temChairID, temPlayer := range rr.PlayerMap { |
|||
if temChairID != pPlayer.ChairId { |
|||
rr.Send(temPlayer, route.NotifySitDown, NotifySitDown) |
|||
} |
|||
} |
|||
|
|||
for _, temPlayer := range rr.PlayerWatchMap { |
|||
rr.Send(temPlayer, route.NotifySitDown, NotifySitDown) |
|||
} |
|||
|
|||
rr.SendTableInfo(pPlayer, route.SitDownRes, SitDownRes) |
|||
|
|||
return 0 |
|||
} |
|||
|
|||
func (rr *Room) LeaveRoom(uid int64) int32 { |
|||
rr.roomRWLock.Lock() |
|||
defer rr.roomRWLock.Unlock() |
|||
|
|||
log.Debug("玩家", uid, "申请离开游戏") |
|||
|
|||
return 0 |
|||
} |
@ -0,0 +1,362 @@ |
|||
package game |
|||
|
|||
import ( |
|||
"base/cluster/node" |
|||
"base/log" |
|||
"time" |
|||
"xgame/game/TTZ/app/core/protocol" |
|||
"xgame/game/TTZ/app/route" |
|||
) |
|||
|
|||
// UpdateCtx 这里是无奈之举
|
|||
func (rr *Room) UpdateCtx(uid int64, ctx *node.Context) { |
|||
rr.roomRWLock.Lock() |
|||
defer rr.roomRWLock.Unlock() |
|||
|
|||
for Index, p := range rr.PlayerMap { |
|||
if p.Uid == uid { |
|||
log.Debug("桌子ID", rr.RId, "PlayerMap User ", uid, " 用户名字 ", p.Nickname, "原来的 ", p.Ctx, "新的 Ctx", ctx) |
|||
rr.PlayerMap[Index].OnlineState = USER_ON_LINE |
|||
rr.PlayerMap[Index].Ctx = ctx |
|||
break |
|||
} |
|||
} |
|||
|
|||
for Index, p := range rr.PlayerWatchMap { |
|||
if p.Uid == uid { |
|||
log.Debug("桌子ID", rr.RId, "PlayerWatchMap User ", uid, " 用户名字 ", p.Nickname, "原来的 ", p.Ctx, "新的 Ctx", ctx) |
|||
rr.PlayerWatchMap[Index].OnlineState = USER_ON_LINE |
|||
rr.PlayerWatchMap[Index].Ctx = ctx |
|||
break |
|||
} |
|||
} |
|||
} |
|||
|
|||
func (rr *Room) UpdateUserOut(uid int64) { // 更新用户退出状态
|
|||
rr.roomRWLock.Lock() |
|||
defer rr.roomRWLock.Unlock() |
|||
|
|||
for Index, p := range rr.PlayerMap { |
|||
if p.Uid == uid { |
|||
rr.PlayerMap[Index].UserNeedOut = true |
|||
break |
|||
} |
|||
} |
|||
|
|||
} |
|||
|
|||
func (rr *Room) run() { |
|||
|
|||
milliseconds := time.Now().UnixMilli() |
|||
|
|||
if rr.State == EN_TABLE_STATE_UNKNOWN { |
|||
return |
|||
} |
|||
|
|||
switch rr.CurrentGameState { |
|||
//等待开场
|
|||
case protocol.STATE_WAIT: |
|||
{ |
|||
if milliseconds >= rr.CurrentOperationTimer { |
|||
for _, player := range rr.PlayerMap { |
|||
// 没人就解散房间
|
|||
log.Debug("PlayerMap 用户 ", player.Nickname, " 没人就解散房间 ", rr.RId) |
|||
rr.OnGetOutRoom(player.Uid) |
|||
} |
|||
|
|||
for _, player := range rr.PlayerWatchMap { |
|||
// 没人就解散房间
|
|||
log.Debug("PlayerWatchMap 用户 ", player.Nickname, " 没人就解散房间 ", rr.RId) |
|||
rr.OnGetOutRoom(player.Uid) |
|||
} |
|||
} |
|||
} |
|||
//下一把
|
|||
case protocol.STATE_BEGIN: |
|||
{ |
|||
// 等待过程中人数又不足了 重新等待开场
|
|||
if rr.GetRoomPlayerCount() <= 4 { |
|||
log.Debug(" 桌子号 ", rr.RId, " 等待过程中人数又不足了 重新等待开场 ") |
|||
rr.State = EN_TABLE_STATE_READY_TO_START |
|||
rr.CurrentGameState = protocol.STATE_WAIT |
|||
rr.CurrentOperationTimer = milliseconds + rr.TimeoutDestroy |
|||
rr.SendAllMessage(route.NotifyStateTime, &protocol.NotifyStateTime{ |
|||
NextState: protocol.STATE_WAIT, |
|||
NextTimestamp: rr.CurrentOperationTimer, |
|||
}) |
|||
break |
|||
} |
|||
|
|||
if milliseconds >= rr.CurrentOperationTimer { |
|||
log.Debug(" 桌子号 ", rr.RId, " 开始抢庄 ") |
|||
//设置游戏状态
|
|||
rr.State = EN_TABLE_STATE_PLAYING |
|||
rr.Round++ //轮数+1
|
|||
|
|||
rr.CurrentOperationTimer = milliseconds + rr.TimeOutGetBanker |
|||
rr.SendAllMessage(route.NotifyStateTime, &protocol.NotifyStateTime{ |
|||
NextState: protocol.STATE_GET_BANKER, |
|||
NextTimestamp: rr.CurrentOperationTimer, |
|||
}) |
|||
|
|||
// 抢庄做了加一秒的容错判断
|
|||
rr.CurrentOperationTimer += 1000 |
|||
} |
|||
return |
|||
} |
|||
//等待抢庄
|
|||
case protocol.STATE_GET_BANKER: |
|||
{ |
|||
// 保底抢庄
|
|||
if !rr.BaoDiBanker && milliseconds >= rr.CurrentOperationTimer-1000 { |
|||
rr.BaoDiBanker = true |
|||
|
|||
for _, player := range rr.PlayerMap { |
|||
if player.IsRobot { |
|||
CanGetBanker := true |
|||
for _, UserChairID := range rr.NoGetBankerList { |
|||
if UserChairID == player.ChairId { |
|||
CanGetBanker = false |
|||
break |
|||
} |
|||
} |
|||
|
|||
if CanGetBanker { |
|||
rr.OnUserGetBanker(player.Uid, &protocol.GetBankerReq{ |
|||
State: 0, |
|||
}) |
|||
break |
|||
} |
|||
} |
|||
} |
|||
} |
|||
|
|||
if milliseconds >= rr.CurrentOperationTimer { |
|||
log.Debug(" 桌子号 ", rr.RId, " 等待开始下注 ") |
|||
rr.CurrentGameState = protocol.STATE_BB |
|||
rr.CurrentOperationTimer = milliseconds + rr.TimeOutBB |
|||
|
|||
rr.OnGameSelectBanker() |
|||
|
|||
rr.SendAllMessage(route.NotifyStateTime, &protocol.NotifyStateTime{ |
|||
NextState: rr.CurrentGameState, |
|||
NextTimestamp: rr.CurrentOperationTimer, |
|||
}) |
|||
} |
|||
} |
|||
case protocol.STATE_BB: |
|||
{ |
|||
if milliseconds >= rr.CurrentOperationTimer { |
|||
log.Debug(" 桌子号 ", rr.RId, " 等待丢骰子 ") |
|||
|
|||
rr.OnGameBeginUser() |
|||
|
|||
rr.CurrentGameState = protocol.STATE_DT |
|||
rr.CurrentOperationTimer = milliseconds + rr.TimeOutDT |
|||
|
|||
rr.SendAllMessage(route.NotifyStateTime, &protocol.NotifyStateTime{ |
|||
NextState: rr.CurrentGameState, |
|||
NextTimestamp: rr.CurrentOperationTimer, |
|||
}) |
|||
} |
|||
} |
|||
case protocol.STATE_DT: |
|||
{ |
|||
if milliseconds >= rr.CurrentOperationTimer { |
|||
log.Debug(" 桌子号 ", rr.RId, " 开始下注 ") |
|||
rr.CurrentGameState = protocol.STATE_BET |
|||
rr.CurrentOperationTimer = milliseconds + rr.TimeOutBet |
|||
|
|||
rr.SendAllMessage(route.NotifyStateTime, &protocol.NotifyStateTime{ |
|||
NextState: rr.CurrentGameState, |
|||
NextTimestamp: rr.CurrentOperationTimer, |
|||
}) |
|||
} |
|||
} |
|||
case protocol.STATE_BET: |
|||
{ |
|||
if milliseconds >= rr.CurrentOperationTimer { |
|||
rr.CurrentOperationTimer = milliseconds + 60*1000 |
|||
|
|||
// 未下注的自动下最低注
|
|||
for index, tempPlayer := range rr.PlayerMap { |
|||
if !tempPlayer.CanBet || tempPlayer.ChairId == rr.CurrBanker || rr.PlayerMap[index].CurrentRoundBet { |
|||
continue |
|||
} |
|||
|
|||
rr.OnUserBet(tempPlayer.Uid, &protocol.BetReq{ |
|||
BetAmount: rr.Opt.MinBetAsset, |
|||
}, true) |
|||
} |
|||
|
|||
log.Debug(" 桌子号 ", rr.RId, " 开始搓牌 ") |
|||
rr.CurrentGameState = protocol.STATE_CP |
|||
rr.CurrentOperationTimer = milliseconds + rr.TimeOutCP |
|||
|
|||
rr.SendAllMessage(route.NotifyStateTime, &protocol.NotifyStateTime{ |
|||
NextState: rr.CurrentGameState, |
|||
NextTimestamp: 0, |
|||
}) |
|||
} |
|||
} |
|||
case protocol.STATE_CP: |
|||
{ |
|||
if milliseconds >= rr.CurrentOperationTimer { |
|||
log.Debug(" 桌子号 ", rr.RId, " 开始结算 ") |
|||
// 先弄个长点的时间防止出问题
|
|||
rr.CurrentOperationTimer = milliseconds + 30000 |
|||
|
|||
rr.OnEventGameConclude() |
|||
} |
|||
} |
|||
case protocol.STATE_RESULT: |
|||
{ |
|||
if milliseconds >= rr.CurrentOperationTimer { |
|||
log.Debug(" 桌子号 ", rr.RId, " 等待下一局开始 ") |
|||
// 先弄个长点的时间防止出问题
|
|||
rr.CurrentOperationTimer = milliseconds + 30000 |
|||
|
|||
for _, player := range rr.PlayerWatchMap { |
|||
if player.IsRobot { |
|||
continue |
|||
} |
|||
|
|||
if player.OnlineState != USER_ON_LINE { |
|||
log.Debug("观战用户 ", player.Nickname, " 不在线 ", rr.RId) |
|||
rr.OnGetOutRoom(player.Uid) |
|||
} else if !player.IsRobot && player.PlayWatchCount >= int(3) { |
|||
log.Debug("用户 ", player.Nickname, " 连续观战了3局 ", rr.RId) |
|||
rr.OnGetOutRoom(player.Uid) |
|||
} |
|||
} |
|||
|
|||
// 钱不够转为观战
|
|||
for _, player := range rr.PlayerMap { |
|||
if player.IsRobot { |
|||
continue |
|||
} |
|||
|
|||
if player.Gold.IntPart() <= rr.MinGameScore { |
|||
log.Debug("用户 ", player.Nickname, " 钱不够转为观战 拥有钱:", player.Gold.IntPart(), " 需要的钱:", rr.MinGameScore) |
|||
TempChairID := player.ChairId |
|||
player.ChairId = -1 |
|||
rr.SendAllMessage(route.NotifyDownToWatch, &protocol.NotifyDownToWatch{ |
|||
ChairID: TempChairID, |
|||
}) |
|||
|
|||
// 通知大厅有人离开或观战
|
|||
NotifySitDown := &protocol.NotifyDTSitDown{ |
|||
Uid: player.Uid, |
|||
RoomID: rr.RoomID, |
|||
TableID: rr.RId, |
|||
ChairID: TempChairID, |
|||
Avatar: player.Avatar, |
|||
State: rr.CurrentGameState, |
|||
} |
|||
rr.NotifyFunc(route.NotifyDTStandUp, NotifySitDown) |
|||
|
|||
delete(rr.PlayerMap, TempChairID) |
|||
rr.PlayerWatchMap = append(rr.PlayerWatchMap, player) |
|||
} |
|||
} |
|||
|
|||
//设置游戏状态
|
|||
rr.State = EN_TABLE_STATE_READY_TO_START |
|||
|
|||
rr.CurrentGameState = protocol.STATE_BEGIN |
|||
rr.CurrentOperationTimer = milliseconds + rr.TimeOutBegin |
|||
|
|||
//0.复位房间一些相关数据
|
|||
rr.RepeatRoom() |
|||
rr.RepeatRoomUser() |
|||
|
|||
//人数不足了 重新等待开场
|
|||
if rr.GetRoomPlayerCount() <= 1 || rr.GetRoomRealPlayerCount() < 1 { |
|||
rr.State = EN_TABLE_STATE_READY_TO_START |
|||
rr.CurrentGameState = protocol.STATE_WAIT |
|||
rr.CurrentOperationTimer = milliseconds + rr.TimeoutDestroy |
|||
rr.SendAllMessage(route.NotifyStateTime, &protocol.NotifyStateTime{ |
|||
NextState: protocol.STATE_WAIT, |
|||
NextTimestamp: rr.CurrentOperationTimer, |
|||
}) |
|||
break |
|||
} else { |
|||
|
|||
if rr.GuoScore <= 10 { |
|||
log.Debug(" 桌子号 ", rr.RId, " 等待下一大局开始 ") |
|||
rr.SendAllMessage(route.NotifyStateTime, &protocol.NotifyStateTime{ |
|||
NextState: protocol.STATE_BEGIN, |
|||
NextTimestamp: rr.CurrentOperationTimer, |
|||
}) |
|||
} else { |
|||
log.Debug(" 桌子号 ", rr.RId, " 下一小局开始 等待丢骰子 ") |
|||
rr.OnGameBeginUser() |
|||
|
|||
rr.CurrentGameState = protocol.STATE_DT |
|||
rr.CurrentOperationTimer = milliseconds + rr.TimeOutDT |
|||
|
|||
rr.SendAllMessage(route.NotifyStateTime, &protocol.NotifyStateTime{ |
|||
NextState: rr.CurrentGameState, |
|||
NextTimestamp: rr.CurrentOperationTimer, |
|||
}) |
|||
} |
|||
} |
|||
} |
|||
} |
|||
} |
|||
} |
|||
|
|||
func (rr *Room) Send(player *Player, msgId int32, message interface{}) { |
|||
//if msgId != route.NotifyBet {
|
|||
// log.Info("Nickname==", player.Nickname, " MsgId==", msgId, " :", message)
|
|||
// log.Printf(1, "内容: %+v\n", message)
|
|||
//}
|
|||
|
|||
if !player.IsRobot { |
|||
if player.OnlineState == USER_ON_LINE && player.Ctx != nil { |
|||
if msgId > 0 { |
|||
player.Ctx.Request.Message.Route = msgId |
|||
} |
|||
if err := player.Ctx.Response(message); err != nil { |
|||
log.Debug("response message failed: ", err, "uid====>", player.Uid) |
|||
} |
|||
} |
|||
} else { |
|||
rr.RobotMgr.OnRobotMessage(msgId, player, message) |
|||
} |
|||
} |
|||
|
|||
func (rr *Room) SendTableInfo(player *Player, msgId int32, message interface{}) { |
|||
//log.Info("Nickname==", player.Nickname, " MsgId==", msgId, " :", message)
|
|||
//log.Printf(1, "内容: %+v\n", message)
|
|||
|
|||
if !player.IsRobot { |
|||
if player.Ctx != nil { |
|||
if msgId > 0 { |
|||
player.Ctx.Request.Message.Route = msgId |
|||
} |
|||
if err := player.Ctx.Response(message); err != nil { |
|||
log.Debug("response message failed: ", err, "uid====>", player.Uid) |
|||
} |
|||
} |
|||
} else { |
|||
rr.RobotMgr.OnRobotMessage(msgId, player, message) |
|||
} |
|||
} |
|||
|
|||
func (rr *Room) SendAllMessage(msgId int32, message interface{}) { |
|||
//log.Info("桌子号", rr.RId, " MsgId==", msgId, " :", message)
|
|||
go func() { |
|||
for _, pPlayer := range rr.PlayerMap { |
|||
if pPlayer != nil { |
|||
rr.Send(pPlayer, msgId, message) |
|||
} |
|||
} |
|||
|
|||
for _, pPlayer := range rr.PlayerWatchMap { |
|||
if pPlayer != nil { |
|||
rr.Send(pPlayer, msgId, message) |
|||
} |
|||
} |
|||
}() |
|||
} |
@ -0,0 +1,47 @@ |
|||
package game |
|||
|
|||
import ( |
|||
"base/cluster/node" |
|||
"context" |
|||
"github.com/shopspring/decimal" |
|||
"strconv" |
|||
"sync" |
|||
"xgame/game/TTZ/app/core/blood" |
|||
"xgame/game/TTZ/app/core/comm" |
|||
) |
|||
|
|||
func New(Uid, rid int64, RoomID, GameID, AgentID int32, destory comm.DestoryCB, qiut comm.DestoryCB, Notify comm.NotifyDTUser, RoomProxy *node.Proxy) *Room { |
|||
r := &Room{ |
|||
RoomProxy: RoomProxy, |
|||
Ctx: context.Background(), |
|||
RId: rid, |
|||
RoomID: RoomID, |
|||
GameID: GameID, |
|||
ReasonString: strconv.Itoa(int(GameID)) + "|" + strconv.Itoa(int(RoomID)), |
|||
AgentID: AgentID, |
|||
PlayerMap: make(map[int32]*Player), |
|||
PlayerWatchMap: make([]*Player, 0), |
|||
RobotMgr: NewRobotManager(), |
|||
Round: 0, |
|||
WinPlayer: INVALID_VALUE, |
|||
EndReason: 0, |
|||
CreatorId: Uid, |
|||
roomRWLock: sync.RWMutex{}, |
|||
BoolePool: &blood.BoolePool{}, |
|||
StockValue: 0, |
|||
DestroyRoomFunc: destory, |
|||
QuitRoomFunc: qiut, |
|||
NotifyFunc: Notify, |
|||
CurrentOperationTimer: 0, |
|||
RoomLimit: decimal.Zero, |
|||
IsP2pControls: false, |
|||
BetList: make([]int64, 0), |
|||
UserScore: make(map[int32]decimal.Decimal), |
|||
//ControValueMap: make(map[int64]decimal.Decimal),
|
|||
//MessageQueue: mq,
|
|||
//players: list.New(),
|
|||
//autoTimer: time.NewTimer(1 * time.Second),
|
|||
} |
|||
|
|||
return r |
|||
} |
@ -0,0 +1,232 @@ |
|||
package game |
|||
|
|||
import ( |
|||
"base/log" |
|||
"xgame/game/TTZ/app/core/protocol" |
|||
"xgame/game/TTZ/app/route" |
|||
) |
|||
|
|||
func (rr *Room) UpdateSeat() { |
|||
l := rr.GetRoomPlayerCount() |
|||
for i := int32(0); i < l; i++ { |
|||
p := rr.PlayerMap[i] |
|||
if p == nil { |
|||
ChairId := rr.MakeChairId() |
|||
rr.PlayerMap[ChairId].ChairId = ChairId |
|||
} |
|||
} |
|||
|
|||
for _, pPlayer := range rr.PlayerMap { |
|||
if pPlayer == nil { |
|||
continue |
|||
} |
|||
} |
|||
} |
|||
|
|||
// OnGetOutRoom 退出房间
|
|||
func (rr *Room) OnGetOutRoom(uid int64) bool { |
|||
rr.roomRWLock.Lock() |
|||
defer rr.roomRWLock.Unlock() |
|||
|
|||
LeaveTableRes := &protocol.LeaveTableRes{} |
|||
NotifyLeaveRoomRes := &protocol.NotifyLeaveRoomRes{} |
|||
|
|||
ret := false |
|||
|
|||
var tempPlayerMap = map[int32]*Player{} |
|||
var OutUser *Player |
|||
for seatId, pPlayer := range rr.PlayerMap { |
|||
if pPlayer == nil { |
|||
continue |
|||
} |
|||
tempPlayerMap[seatId] = pPlayer |
|||
|
|||
if pPlayer.Uid == uid { |
|||
OutUser = pPlayer |
|||
} |
|||
} |
|||
|
|||
NotifyLeaveRoomRes.ChairID = 0xFF |
|||
if OutUser == nil { |
|||
for TempIndex, pPlayer := range rr.PlayerWatchMap { |
|||
if pPlayer == nil { |
|||
continue |
|||
} |
|||
|
|||
if pPlayer.Uid == uid { |
|||
rr.Send(pPlayer, route.LogoutTableRes, LeaveTableRes) |
|||
NotifyLeaveRoomRes.ChairID = -1 |
|||
OutUser = pPlayer |
|||
|
|||
if !pPlayer.IsRobot { |
|||
pPlayer.OnlineState = USER_LEAVE |
|||
pPlayer.Ctx = nil |
|||
|
|||
rr.QuitRoomFunc(pPlayer.Uid) |
|||
if TempIndex == len(rr.PlayerWatchMap)-1 { |
|||
rr.PlayerWatchMap = rr.PlayerWatchMap[:TempIndex] |
|||
} else { |
|||
rr.PlayerWatchMap = append(rr.PlayerWatchMap[:TempIndex], rr.PlayerWatchMap[TempIndex+1:]...) |
|||
} |
|||
} else { |
|||
//针对机器人的删除
|
|||
if TempIndex == len(rr.PlayerWatchMap)-1 { |
|||
rr.PlayerWatchMap = rr.PlayerWatchMap[:TempIndex] |
|||
} else { |
|||
rr.PlayerWatchMap = append(rr.PlayerWatchMap[:TempIndex], rr.PlayerWatchMap[TempIndex+1:]...) |
|||
} |
|||
} |
|||
|
|||
break |
|||
} |
|||
} |
|||
} |
|||
|
|||
for _, pPlayer := range rr.PlayerMap { |
|||
if pPlayer == nil { |
|||
continue |
|||
} |
|||
|
|||
if pPlayer.Uid == uid { |
|||
rr.Send(pPlayer, route.LogoutTableRes, LeaveTableRes) |
|||
|
|||
if !pPlayer.IsRobot /*&& !tempPlayerMap[pPlayer.ChairId].IsRobot*/ { |
|||
pPlayer.OnlineState = USER_LEAVE |
|||
pPlayer.Ctx = nil |
|||
|
|||
// 如果抢庄了 需要从庄家列表删除
|
|||
for TempIndex, TempChairID := range rr.GetBankerList { |
|||
if TempChairID == pPlayer.ChairId { |
|||
if TempIndex == len(rr.GetBankerList)-1 { |
|||
rr.GetBankerList = rr.GetBankerList[:TempIndex] |
|||
} else { |
|||
rr.GetBankerList = append(rr.GetBankerList[:TempIndex], rr.GetBankerList[TempIndex+1:]...) |
|||
} |
|||
break |
|||
} |
|||
} |
|||
|
|||
//为了下面的rr.PlayerMap = tempPlayerMap这个表达式
|
|||
tempPlayerMap[pPlayer.ChairId].OnlineState = USER_LEAVE |
|||
tempPlayerMap[pPlayer.ChairId].Ctx = nil |
|||
rr.QuitRoomFunc(pPlayer.Uid) |
|||
|
|||
// 通知大厅有人离开
|
|||
NotifySitDown := &protocol.NotifyDTSitDown{ |
|||
Uid: pPlayer.Uid, |
|||
RoomID: rr.RoomID, |
|||
TableID: rr.RId, |
|||
ChairID: pPlayer.ChairId, |
|||
Avatar: pPlayer.Avatar, |
|||
State: rr.CurrentGameState, |
|||
} |
|||
rr.NotifyFunc(route.NotifyDTStandUp, NotifySitDown) |
|||
|
|||
delete(tempPlayerMap, pPlayer.ChairId) |
|||
} else { |
|||
//针对机器人的删除
|
|||
delete(tempPlayerMap, pPlayer.ChairId) |
|||
} |
|||
|
|||
ret = true |
|||
} else { |
|||
if OutUser != nil { |
|||
NotifyLeaveRoomRes.ChairID = OutUser.ChairId |
|||
} else { |
|||
NotifyLeaveRoomRes.ChairID = 0xFF |
|||
} |
|||
NotifyLeaveRoomRes.LeaveReason = 0 |
|||
rr.Send(pPlayer, route.NotifyGetOutGame, NotifyLeaveRoomRes) |
|||
} |
|||
} |
|||
|
|||
for _, pPlayer := range rr.PlayerWatchMap { |
|||
if pPlayer == nil { |
|||
continue |
|||
} |
|||
|
|||
rr.Send(pPlayer, route.NotifyGetOutGame, NotifyLeaveRoomRes) |
|||
} |
|||
|
|||
rr.PlayerMap = tempPlayerMap |
|||
|
|||
//for i, v := range rr.PlayerMap {
|
|||
// log.Debug(" 桌子号", rr.RId, "退出房间后,房间中的玩家", i, "的信息", v.Uid, ":", v)
|
|||
//}
|
|||
|
|||
//// 观战转坐下
|
|||
//TempChairID := int32(0)
|
|||
//for TempChairID = 0; TempChairID < MAX_USER_NUM; TempChairID++ {
|
|||
// if _, exists := rr.PlayerMap[TempChairID]; !exists {
|
|||
// for TempIndex, TempWatchPlayer := range rr.PlayerWatchMap {
|
|||
// // 金币足才可以自动坐下
|
|||
// if TempWatchPlayer.Gold.IntPart() > rr.MinGameScore {
|
|||
// WatchUser := rr.PlayerWatchMap[TempIndex]
|
|||
// WatchUser.ChairId = TempChairID
|
|||
// rr.SendAllMessage(route.NotifyWatchToDown, &protocol.NotifyWatchToDown{
|
|||
// Uid: WatchUser.Uid,
|
|||
// ChairID: TempChairID,
|
|||
// })
|
|||
//
|
|||
// // 通知大厅有人坐下
|
|||
// NotifySitDown := &protocol.NotifyDTSitDown{
|
|||
// Uid: WatchUser.Uid,
|
|||
// RoomID: rr.RoomID,
|
|||
// TableID: rr.RId,
|
|||
// ChairID: TempChairID,
|
|||
// Avatar: WatchUser.Avatar,
|
|||
// State: rr.CurrentGameState,
|
|||
// }
|
|||
// rr.NotifyFunc(route.NotifyDTSitDown, NotifySitDown)
|
|||
//
|
|||
// rr.PlayerMap[TempWatchPlayer.ChairId] = TempWatchPlayer
|
|||
//
|
|||
// if TempIndex == len(rr.PlayerWatchMap)-1 {
|
|||
// rr.PlayerWatchMap = rr.PlayerWatchMap[:TempIndex]
|
|||
// } else {
|
|||
// rr.PlayerWatchMap = append(rr.PlayerWatchMap[:TempIndex], rr.PlayerWatchMap[TempIndex+1:]...)
|
|||
// }
|
|||
// break
|
|||
// }
|
|||
// }
|
|||
// }
|
|||
//}
|
|||
|
|||
if ret { |
|||
log.Debug(" 桌子号", rr.RId, "玩家", uid, "退出房间成功") |
|||
playerCount := rr.GetRoomPlayerCount() |
|||
|
|||
robotCount := rr.GetInRoomRobotCount() |
|||
|
|||
log.Debug(" 桌子号", rr.RId, "玩家人数", playerCount) |
|||
|
|||
if playerCount == 0 || (rr.CreatorId != 0 && playerCount == robotCount) { |
|||
//退出所有观战玩家
|
|||
for _, pPlayer := range rr.PlayerWatchMap { |
|||
if pPlayer == nil { |
|||
continue |
|||
} |
|||
|
|||
rr.Send(pPlayer, route.LogoutTableRes, LeaveTableRes) |
|||
} |
|||
rr.PlayerWatchMap = rr.PlayerWatchMap[:0] |
|||
//关闭定时器
|
|||
rr.GronTimer.Stop() |
|||
rr.RobotMgr.GronTimer.Stop() |
|||
|
|||
for i := int32(0); i < playerCount; i++ { |
|||
p := rr.PlayerMap[i] |
|||
if p == nil { |
|||
continue |
|||
} |
|||
rr.PlayerMap[i] = nil |
|||
delete(rr.PlayerMap, i) |
|||
//这里面来全是机器人的,所有不需要调用 rr.QuitRoomFunc
|
|||
} |
|||
|
|||
log.Debug(" 桌子号", rr.RId, "点控房间 全是机器人,房间没意义,销毁") |
|||
rr.DestroyRoomFunc(rr.RId) |
|||
} |
|||
} |
|||
return true |
|||
} |
@ -0,0 +1,687 @@ |
|||
package game |
|||
|
|||
import ( |
|||
"base/encoding/json" |
|||
"base/log" |
|||
"fmt" |
|||
"github.com/shopspring/decimal" |
|||
"math/rand" |
|||
"sort" |
|||
"strconv" |
|||
"time" |
|||
"xgame/game/TTZ/app/core/protocol" |
|||
"xgame/game/TTZ/app/core/types" |
|||
"xgame/game/TTZ/app/route" |
|||
"xgame/game/service/rpc_client" |
|||
writeUserScorepb "xgame/internal/service/writeUserScore/pb" |
|||
"xgame/tools" |
|||
) |
|||
|
|||
func (rr *Room) OnBuildOtherResultPoker() { //计算扑克
|
|||
log.Debug(" 桌子号", rr.RId, " 计算扑克 ") |
|||
// 洗牌
|
|||
if len(rr.CardList) == 0 { |
|||
rr.InitCardList(1) |
|||
} |
|||
rr.PokersCount = int32(len(rr.CardList)) |
|||
|
|||
//点控
|
|||
rr.isUserCtl = false |
|||
rr.UserCtlGear = 0 |
|||
PlayerCount := rr.GetRoomPlayerCount() |
|||
for i := int32(0); i < PlayerCount; i++ { |
|||
p := rr.PlayerMap[i] |
|||
if p == nil || p.IsRobot { |
|||
continue |
|||
} |
|||
|
|||
//取点控
|
|||
p.CheatValue = 0 |
|||
p.CheatType = 0 |
|||
p.CheatValueBefore = 0 |
|||
p.IsCheat = false |
|||
playerControl := rpc_client.GetUserGameControl(p.Ctx, int64(rr.GameID), int64(rr.RoomID)) |
|||
if playerControl != nil { |
|||
log.Debug("获取到的玩家点控 玩家 ", p.Uid, " 名字:", p.Nickname, " 点控", playerControl) |
|||
if playerControl.CheatType != 0 { |
|||
rr.isUserCtl = true |
|||
rr.UserCtlGear = playerControl.CheatType |
|||
p.IsCheat = true |
|||
p.CheatValue = playerControl.CheatValue |
|||
p.CheatType = playerControl.CheatType |
|||
p.CheatValueBefore = p.CheatValue |
|||
log.Debug("设置点控成功 点控类型 ", p.CheatType, " 点控值:", p.CheatValueBefore) |
|||
} |
|||
} |
|||
} |
|||
|
|||
WinType := 0 |
|||
CurrentGears := 0 |
|||
TempRoomGears, err := strconv.Atoi(rr.BoolePool.RoomGears) |
|||
if err == nil { |
|||
CurrentGears = TempRoomGears |
|||
//log.Debug(" 桌子号", r.GameRoom.RId, "房间当前血池档位1 :", TempRoomGears, " CurrentGears :", CurrentGears)
|
|||
} |
|||
|
|||
if rr.isUserCtl { |
|||
CurrentGears = int(rr.UserCtlGear) |
|||
} |
|||
log.Debug(" 桌子号", rr.RId, "房间当前血池档位 :", TempRoomGears, " 人物控制后实际血池:", CurrentGears) |
|||
|
|||
CurrentGearConfig := rr.BloodCtrl.GearConfig[0] |
|||
for _, GearConfig := range rr.BloodCtrl.GearConfig { |
|||
if GearConfig.GearID == CurrentGears { |
|||
CurrentGearConfig = GearConfig |
|||
break |
|||
} |
|||
} |
|||
|
|||
if rr.GetRoomRealCanBetPlayerCount() == 0 && rr.PlayerMap[rr.CurrBanker].IsRobot { |
|||
// 没有真人玩 随机
|
|||
WinType = 0 |
|||
} else { |
|||
WinType = 2 |
|||
// 随机机器人的输赢
|
|||
for i := int32(0); i < MAX_USER_NUM; i++ { |
|||
if _, exists := rr.PlayerMap[i]; exists { |
|||
tempPlayer := rr.PlayerMap[i] |
|||
tempPlayer.RobotWin = false |
|||
if !tempPlayer.CanBet && tempPlayer.ChairId != rr.CurrBanker { |
|||
continue |
|||
} |
|||
|
|||
if tempPlayer.IsRobot && rand.Intn(10000) < CurrentGearConfig.WinPro { |
|||
tempPlayer.RobotWin = true |
|||
log.Debug(" 用户 ", tempPlayer.ChairId, " 是否机器人 ", tempPlayer.IsRobot, " 赢") |
|||
} |
|||
} |
|||
} |
|||
|
|||
// 机器人庄的输赢
|
|||
if rr.PlayerMap[rr.CurrBanker].IsRobot { |
|||
if rand.Intn(10000) < CurrentGearConfig.BankerWinPro { |
|||
rr.PlayerMap[rr.CurrBanker].RobotWin = true |
|||
} else { |
|||
{ |
|||
rr.PlayerMap[rr.CurrBanker].RobotWin = false |
|||
} |
|||
} |
|||
} |
|||
|
|||
//判断输赢
|
|||
tempHandCard := rr.SearchTypeHandCard() |
|||
switch WinType { |
|||
case 0: |
|||
// 不控制
|
|||
log.Debug(" 桌子号", rr.RId, " 不控制 :") |
|||
|
|||
rr.shuffleDeck2(&tempHandCard) |
|||
|
|||
for tempIndex, _ := range rr.PlayerMap { |
|||
rr.PlayerMap[tempIndex].HandPoker = rr.PlayerMap[tempIndex].HandPoker[:0] |
|||
rr.PlayerMap[tempIndex].HandPoker = append(rr.PlayerMap[tempIndex].HandPoker, tempHandCard[tempIndex]...) |
|||
} |
|||
case 2: |
|||
log.Debug(" 桌子号", rr.RId, " 牌是 :", tempHandCard) |
|||
|
|||
if rr.PlayerMap[rr.CurrBanker].IsRobot && rr.PlayerMap[rr.CurrBanker].RobotWin { |
|||
// 如果庄家是机器人 并且需要赢
|
|||
RealCanBetUserCount := rr.GetRoomRealCanBetPlayerCount() |
|||
|
|||
// 随机牌的起始位置
|
|||
BeginIndex := rand.Intn(MAX_USER_NUM - int(RealCanBetUserCount)) |
|||
rr.PlayerMap[rr.CurrBanker].HandPoker = rr.PlayerMap[rr.CurrBanker].HandPoker[:0] |
|||
rr.PlayerMap[rr.CurrBanker].HandPoker = append(rr.PlayerMap[rr.CurrBanker].HandPoker, tempHandCard[BeginIndex]...) |
|||
WinPoker := tempHandCard[:BeginIndex] |
|||
var LosePoker []types.PokerSlice |
|||
if BeginIndex < 4 { |
|||
LosePoker = tempHandCard[BeginIndex+1:] |
|||
} |
|||
|
|||
rr.shuffleDeck2(&WinPoker) |
|||
rr.shuffleDeck2(&LosePoker) |
|||
|
|||
// 先分配要输的真人
|
|||
for tempIndex, tempPlayer := range rr.PlayerMap { |
|||
if len(LosePoker) == 0 { |
|||
break |
|||
} |
|||
if tempPlayer.CanBet && !tempPlayer.IsRobot { |
|||
rr.PlayerMap[tempIndex].HandPoker = rr.PlayerMap[tempIndex].HandPoker[:0] |
|||
rr.PlayerMap[tempIndex].HandPoker = append(rr.PlayerMap[tempIndex].HandPoker, LosePoker[0]...) |
|||
if len(LosePoker) > 1 { |
|||
LosePoker = LosePoker[1:] |
|||
} else { |
|||
LosePoker = LosePoker[:0] |
|||
} |
|||
} |
|||
} |
|||
|
|||
// 再分配其它机器人
|
|||
for tempIndex, tempPlayer := range rr.PlayerMap { |
|||
if len(LosePoker) == 0 { |
|||
break |
|||
} |
|||
if tempPlayer.CanBet && tempPlayer.IsRobot { |
|||
rr.PlayerMap[tempIndex].HandPoker = rr.PlayerMap[tempIndex].HandPoker[:0] |
|||
rr.PlayerMap[tempIndex].HandPoker = append(rr.PlayerMap[tempIndex].HandPoker, LosePoker[0]...) |
|||
if len(LosePoker) > 1 { |
|||
LosePoker = LosePoker[1:] |
|||
} else { |
|||
LosePoker = LosePoker[:0] |
|||
} |
|||
} |
|||
} |
|||
|
|||
for tempIndex, tempPlayer := range rr.PlayerMap { |
|||
if len(WinPoker) == 0 { |
|||
break |
|||
} |
|||
if tempPlayer.CanBet && tempPlayer.IsRobot && len(rr.PlayerMap[tempIndex].HandPoker) == 0 { |
|||
rr.PlayerMap[tempIndex].HandPoker = rr.PlayerMap[tempIndex].HandPoker[:0] |
|||
rr.PlayerMap[tempIndex].HandPoker = append(rr.PlayerMap[tempIndex].HandPoker, WinPoker[0]...) |
|||
if len(WinPoker) > 1 { |
|||
WinPoker = WinPoker[1:] |
|||
} else { |
|||
WinPoker = WinPoker[:0] |
|||
} |
|||
} |
|||
} |
|||
|
|||
for _, tempPlayer := range rr.PlayerMap { |
|||
log.Debug(" 桌子号 ", rr.RId, " 庄家 ", rr.CurrBanker, " 当前 ", tempPlayer.ChairId, " 当前是否机器人 ", tempPlayer.IsRobot, " 是否需要赢 ", tempPlayer.RobotWin, " 手牌 ", tempPlayer.HandPoker) |
|||
} |
|||
} else if rr.PlayerMap[rr.CurrBanker].IsRobot && !rr.PlayerMap[rr.CurrBanker].RobotWin { |
|||
// 如果庄家是机器人 并且需要输
|
|||
RealCanBetUserCount := rr.GetRoomRealCanBetPlayerCount() |
|||
|
|||
// 随机牌的起始位置
|
|||
BeginIndex := int(RealCanBetUserCount) + rand.Intn(MAX_USER_NUM-int(RealCanBetUserCount)) |
|||
rr.PlayerMap[rr.CurrBanker].HandPoker = rr.PlayerMap[rr.CurrBanker].HandPoker[:0] |
|||
rr.PlayerMap[rr.CurrBanker].HandPoker = append(rr.PlayerMap[rr.CurrBanker].HandPoker, tempHandCard[BeginIndex]...) |
|||
WinPoker := tempHandCard[:BeginIndex] |
|||
var LosePoker []types.PokerSlice |
|||
if BeginIndex < 4 { |
|||
LosePoker = tempHandCard[BeginIndex+1:] |
|||
} |
|||
|
|||
rr.shuffleDeck2(&WinPoker) |
|||
rr.shuffleDeck2(&LosePoker) |
|||
|
|||
// 先分配要赢的真人
|
|||
for tempIndex, tempPlayer := range rr.PlayerMap { |
|||
if len(WinPoker) == 0 { |
|||
break |
|||
} |
|||
if tempPlayer.CanBet && !tempPlayer.IsRobot { |
|||
rr.PlayerMap[tempIndex].HandPoker = rr.PlayerMap[tempIndex].HandPoker[:0] |
|||
rr.PlayerMap[tempIndex].HandPoker = append(rr.PlayerMap[tempIndex].HandPoker, WinPoker[0]...) |
|||
if len(WinPoker) > 1 { |
|||
WinPoker = WinPoker[1:] |
|||
} else { |
|||
WinPoker = WinPoker[:0] |
|||
} |
|||
} |
|||
} |
|||
|
|||
// 再分配其它机器人
|
|||
for tempIndex, tempPlayer := range rr.PlayerMap { |
|||
if len(LosePoker) == 0 { |
|||
break |
|||
} |
|||
if tempPlayer.CanBet && tempPlayer.IsRobot { |
|||
rr.PlayerMap[tempIndex].HandPoker = rr.PlayerMap[tempIndex].HandPoker[:0] |
|||
rr.PlayerMap[tempIndex].HandPoker = append(rr.PlayerMap[tempIndex].HandPoker, LosePoker[0]...) |
|||
if len(LosePoker) > 1 { |
|||
LosePoker = LosePoker[1:] |
|||
} else { |
|||
LosePoker = LosePoker[:0] |
|||
} |
|||
} |
|||
} |
|||
|
|||
for tempIndex, tempPlayer := range rr.PlayerMap { |
|||
if len(WinPoker) == 0 { |
|||
break |
|||
} |
|||
if tempPlayer.CanBet && tempPlayer.IsRobot && len(rr.PlayerMap[tempIndex].HandPoker) == 0 { |
|||
rr.PlayerMap[tempIndex].HandPoker = rr.PlayerMap[tempIndex].HandPoker[:0] |
|||
rr.PlayerMap[tempIndex].HandPoker = append(rr.PlayerMap[tempIndex].HandPoker, WinPoker[0]...) |
|||
if len(WinPoker) > 1 { |
|||
WinPoker = WinPoker[1:] |
|||
} else { |
|||
WinPoker = WinPoker[:0] |
|||
} |
|||
} |
|||
} |
|||
|
|||
for _, tempPlayer := range rr.PlayerMap { |
|||
log.Debug(" 桌子号 ", rr.RId, " 庄家 ", rr.CurrBanker, " 当前 ", tempPlayer.ChairId, " 当前是否机器人 ", tempPlayer.IsRobot, " 是否需要赢 ", tempPlayer.RobotWin, " 手牌 ", tempPlayer.HandPoker) |
|||
} |
|||
} else { |
|||
// 玩家是庄家
|
|||
NeedWinRobotCount := 0 |
|||
for _, tempPlayer := range rr.PlayerMap { |
|||
if tempPlayer.IsRobot && tempPlayer.CanBet && tempPlayer.RobotWin { |
|||
NeedWinRobotCount++ |
|||
} |
|||
} |
|||
|
|||
// 随机牌的起始位置
|
|||
WinPoker := tempHandCard[:NeedWinRobotCount] |
|||
LosePoker := tempHandCard[NeedWinRobotCount:] |
|||
|
|||
rr.shuffleDeck2(&WinPoker) |
|||
rr.shuffleDeck2(&LosePoker) |
|||
|
|||
// 先分配要赢的机器人
|
|||
for tempIndex, tempPlayer := range rr.PlayerMap { |
|||
if len(WinPoker) == 0 { |
|||
break |
|||
} |
|||
if tempPlayer.IsRobot && tempPlayer.CanBet && tempPlayer.RobotWin { |
|||
rr.PlayerMap[tempIndex].HandPoker = rr.PlayerMap[tempIndex].HandPoker[:0] |
|||
rr.PlayerMap[tempIndex].HandPoker = append(rr.PlayerMap[tempIndex].HandPoker, WinPoker[0]...) |
|||
if len(WinPoker) > 1 { |
|||
WinPoker = WinPoker[1:] |
|||
} else { |
|||
WinPoker = WinPoker[:0] |
|||
} |
|||
} |
|||
} |
|||
|
|||
// 再分配其它人
|
|||
for tempIndex, tempPlayer := range rr.PlayerMap { |
|||
if len(LosePoker) == 0 { |
|||
break |
|||
} |
|||
|
|||
if tempPlayer.CanBet && len(rr.PlayerMap[tempIndex].HandPoker) == 0 { |
|||
rr.PlayerMap[tempIndex].HandPoker = rr.PlayerMap[tempIndex].HandPoker[:0] |
|||
rr.PlayerMap[tempIndex].HandPoker = append(rr.PlayerMap[tempIndex].HandPoker, LosePoker[0]...) |
|||
if len(LosePoker) > 1 { |
|||
LosePoker = LosePoker[1:] |
|||
} else { |
|||
LosePoker = LosePoker[:0] |
|||
} |
|||
} |
|||
} |
|||
|
|||
for _, tempPlayer := range rr.PlayerMap { |
|||
log.Debug(" 桌子号 ", rr.RId, " 庄家 ", rr.CurrBanker, " 当前 ", tempPlayer.ChairId, " 当前是否机器人 ", tempPlayer.IsRobot, " 是否需要赢 ", tempPlayer.RobotWin, " 手牌 ", tempPlayer.HandPoker) |
|||
} |
|||
} |
|||
} |
|||
} |
|||
} |
|||
|
|||
func (rr *Room) insertIntoSlice(slice types.PokerSlice, index int, value types.Poker) types.PokerSlice { |
|||
// 确保 index 在合适的范围内
|
|||
if index < 0 || index > len(slice) { |
|||
return slice // 返回原slice,或处理错误
|
|||
} |
|||
|
|||
// 创建一个新切片,长度为原切片长度 + 1
|
|||
newSlice := make(types.PokerSlice, len(slice)+1) |
|||
|
|||
// 将切片的前部分复制到新切片
|
|||
copy(newSlice, slice[:index]) |
|||
|
|||
// 插入新元素
|
|||
newSlice[index] = value |
|||
|
|||
// 将后面的部分复制到新切片
|
|||
copy(newSlice[index+1:], slice[index:]) |
|||
|
|||
return newSlice |
|||
} |
|||
|
|||
func (rr *Room) OnEventGameConclude() { // 结束-结算
|
|||
milliseconds := time.Now().UnixMilli() |
|||
|
|||
// 结算展示时间
|
|||
rr.CurrentGameState = protocol.STATE_RESULT |
|||
rr.CurrentOperationTimer = milliseconds + rr.TimeOutResult |
|||
|
|||
rr.SendAllMessage(route.NotifyStateTime, &protocol.NotifyStateTime{ |
|||
NextState: rr.CurrentGameState, |
|||
NextTimestamp: rr.CurrentOperationTimer, |
|||
}) |
|||
|
|||
//结算
|
|||
GameOver := &protocol.NotifyGameConclude{} |
|||
|
|||
// 计算玩家赢得区域
|
|||
var sArea string |
|||
var sPlayers string |
|||
|
|||
for _, player := range rr.PlayerMap { |
|||
if !player.IsRobot { |
|||
if len(sPlayers) == 0 { |
|||
sPlayers = sPlayers + player.UserNo |
|||
} else { |
|||
sPlayers = sPlayers + "," + player.UserNo |
|||
} |
|||
} |
|||
} |
|||
|
|||
BankerWinScore := int64(0) // 庄家赢得钱
|
|||
|
|||
for _, player := range rr.PlayerMap { |
|||
player.PlayWatchCount = 0 |
|||
player.PlayCount++ |
|||
|
|||
if player.ChairId != rr.CurrBanker && !player.CurrentRoundBet { |
|||
player.NoBetCount++ |
|||
} else { |
|||
player.NoBetCount = 0 |
|||
} |
|||
} |
|||
|
|||
sArea = "" |
|||
var RecordInfo []protocol.RecordInfoPlayer |
|||
|
|||
// 先放庄家
|
|||
BankerPlayer := rr.PlayerMap[rr.CurrBanker] |
|||
RecordInfo = append(RecordInfo, protocol.RecordInfoPlayer{ |
|||
ChairID: rr.CurrBanker, |
|||
UserNo: BankerPlayer.UserNo, |
|||
}) |
|||
|
|||
for _, poker := range BankerPlayer.HandPoker { |
|||
RecordInfo[0].HandPoker = append(RecordInfo[0].HandPoker, int32(poker)) |
|||
} |
|||
RecordInfo[0].PokerType, RecordInfo[0].PokerPoint = BankerPlayer.HandPoker.GetCardType() |
|||
|
|||
// 再放其它人
|
|||
for _, player := range rr.PlayerMap { |
|||
if !player.CanBet { |
|||
continue |
|||
} |
|||
|
|||
// 庄家先拿所有下注
|
|||
BankerWinScore += player.BetScore |
|||
|
|||
var TempRecordInfoPlayer protocol.RecordInfoPlayer |
|||
TempRecordInfoPlayer.ChairID = player.ChairId |
|||
TempRecordInfoPlayer.UserNo = player.UserNo |
|||
|
|||
for _, poker := range player.HandPoker { |
|||
TempRecordInfoPlayer.HandPoker = append(TempRecordInfoPlayer.HandPoker, int32(poker)) |
|||
} |
|||
TempRecordInfoPlayer.PokerType, TempRecordInfoPlayer.PokerPoint = BankerPlayer.HandPoker.GetCardType() |
|||
|
|||
if BankerPlayer.HandPoker.Compare(player.HandPoker) == 1 { |
|||
TempRecordInfoPlayer.IsWin = false |
|||
} else { |
|||
TempRecordInfoPlayer.IsWin = true |
|||
} |
|||
|
|||
RecordInfo = append(RecordInfo, TempRecordInfoPlayer) |
|||
} |
|||
|
|||
options, err := json.Marshal(RecordInfo) |
|||
if err != nil { |
|||
log.Debug("RecordInfo 序列化失败") |
|||
} |
|||
sArea = string(options) |
|||
|
|||
// 先收所有输给庄家的钱
|
|||
for _, player := range rr.PlayerMap { |
|||
if !player.CanBet { |
|||
continue |
|||
} |
|||
|
|||
if rr.PlayerMap[rr.CurrBanker].HandPoker.Compare(player.HandPoker) == 2 { |
|||
continue |
|||
} |
|||
|
|||
TableSeat := &protocol.RoomPlayer{} |
|||
|
|||
//输赢
|
|||
TempUserWinScore := -int64(player.HandPoker.GetCardTypeBei()) * player.BetScore |
|||
if -TempUserWinScore > player.Gold.IntPart() { |
|||
TempUserWinScore = -player.Gold.IntPart() |
|||
} |
|||
BankerWinScore += -TempUserWinScore |
|||
|
|||
player.WinBetScore = 0 |
|||
|
|||
//记录输赢并写分
|
|||
UserRealBet := player.BetScore // 计算打码量
|
|||
|
|||
if !player.IsRobot && (player.BetScore != 0) && (player.Ctx != nil) { |
|||
AfterGold, BloodPool, StockNum := rr.WriteUserScore(player, 2, player.BetScore, player.WinBetScore, TempUserWinScore, rr.ReasonString, sArea, sPlayers, UserRealBet) |
|||
log.Debug("WriteUserScore 后 AfterGold=", AfterGold, " BloodPool=", BloodPool, " StockNum=", StockNum, " GameID", rr.GameID, " RoomID", rr.RoomID) |
|||
rr.UserScore[player.ChairId] = decimal.NewFromInt(AfterGold) |
|||
player.Gold = decimal.NewFromInt(AfterGold) |
|||
} |
|||
|
|||
TableSeat.Uid = player.Uid |
|||
TableSeat.ChairID = player.ChairId |
|||
if rr.CurrBanker == player.ChairId { |
|||
TableSeat.IsBanker = 1 |
|||
} |
|||
TableSeat.State = rr.State |
|||
TableSeat.Avatar = player.Avatar |
|||
TableSeat.Gold = player.Gold.IntPart() |
|||
TableSeat.Nickname = player.Nickname |
|||
TableSeat.Sex = player.Sex |
|||
TableSeat.Vip = 0 |
|||
TableSeat.Level = player.Level |
|||
TableSeat.Exp = 0 |
|||
TableSeat.EndScore = TempUserWinScore |
|||
TableSeat.WinLose = 2 |
|||
|
|||
for _, poker := range player.HandPoker { |
|||
TableSeat.HandPoker = append(TableSeat.HandPoker, int32(poker)) |
|||
} |
|||
|
|||
TableSeat.PokerType, TableSeat.Point = player.HandPoker.GetCardType() |
|||
TableSeat.BetScore = player.BetScore |
|||
GameOver.PlayList = append(GameOver.PlayList, TableSeat) |
|||
} |
|||
|
|||
// 然后从最大的开始赔
|
|||
var WinPlayer []PokerUserType // 找到赢家
|
|||
for _, player := range rr.PlayerMap { |
|||
if !player.CanBet { |
|||
continue |
|||
} |
|||
|
|||
if rr.PlayerMap[rr.CurrBanker].HandPoker.Compare(player.HandPoker) == 1 { |
|||
continue |
|||
} |
|||
|
|||
var TempWinPlayer PokerUserType |
|||
TempWinPlayer.ChairId = player.ChairId |
|||
TempWinPlayer.Bei = player.HandPoker.GetCardTypeBei() |
|||
TempWinPlayer.HandPoker = player.HandPoker |
|||
|
|||
WinPlayer = append(WinPlayer, TempWinPlayer) |
|||
} |
|||
|
|||
sort.Slice(WinPlayer, func(i, j int) bool { |
|||
return WinPlayer[i].Bei >= WinPlayer[j].Bei |
|||
}) |
|||
|
|||
for _, tempWinPlayer := range WinPlayer { |
|||
TableSeat := &protocol.RoomPlayer{} |
|||
|
|||
player := rr.PlayerMap[tempWinPlayer.ChairId] |
|||
//输赢
|
|||
TempUserWinScore := int64(tempWinPlayer.Bei) * player.BetScore |
|||
if TempUserWinScore > BankerWinScore+rr.GuoScore { |
|||
TempUserWinScore = BankerWinScore + rr.GuoScore |
|||
} |
|||
BankerWinScore -= TempUserWinScore |
|||
|
|||
player.WinBetScore = player.BetScore |
|||
|
|||
//记录输赢并写分
|
|||
UserRealBet := player.BetScore // 计算打码量
|
|||
|
|||
if TempUserWinScore > 0 { |
|||
TempRateAfter := int64(float64(TempUserWinScore) * (1 - rr.Opt.BrightRate)) |
|||
rr.UserScore[player.ChairId] = rr.UserScore[player.ChairId].Add(decimal.NewFromInt(TempRateAfter)) |
|||
player.Gold = rr.UserScore[player.ChairId].Add(decimal.NewFromInt(TempRateAfter)) |
|||
TableSeat.EndScore = TempRateAfter |
|||
} |
|||
|
|||
if !player.IsRobot && (player.BetScore != 0) && (player.Ctx != nil) { |
|||
AfterGold, BloodPool, StockNum := rr.WriteUserScore(player, 2, player.BetScore, player.WinBetScore, TempUserWinScore, rr.ReasonString, sArea, sPlayers, UserRealBet) |
|||
log.Debug("WriteUserScore 后 AfterGold=", AfterGold, " BloodPool=", BloodPool, " StockNum=", StockNum, " GameID", rr.GameID, " RoomID", rr.RoomID) |
|||
rr.UserScore[player.ChairId] = decimal.NewFromInt(AfterGold) |
|||
player.Gold = decimal.NewFromInt(AfterGold) |
|||
} |
|||
|
|||
TableSeat.Uid = player.Uid |
|||
TableSeat.ChairID = player.ChairId |
|||
if rr.CurrBanker == player.ChairId { |
|||
TableSeat.IsBanker = 1 |
|||
} |
|||
TableSeat.State = rr.State |
|||
TableSeat.Avatar = player.Avatar |
|||
TableSeat.Gold = player.Gold.IntPart() |
|||
TableSeat.Nickname = player.Nickname |
|||
TableSeat.Sex = player.Sex |
|||
TableSeat.Vip = 0 |
|||
TableSeat.Level = player.Level |
|||
TableSeat.Exp = 0 |
|||
TableSeat.WinLose = 1 |
|||
|
|||
for _, poker := range player.HandPoker { |
|||
TableSeat.HandPoker = append(TableSeat.HandPoker, int32(poker)) |
|||
} |
|||
|
|||
TableSeat.PokerType, TableSeat.Point = player.HandPoker.GetCardType() |
|||
TableSeat.BetScore = player.BetScore |
|||
GameOver.PlayList = append(GameOver.PlayList, TableSeat) |
|||
} |
|||
|
|||
// 剩余的是庄家赢得
|
|||
TempRateAfter := BankerWinScore |
|||
var UserRealBet int64 |
|||
var WinBetGold int64 |
|||
var WinGold int64 |
|||
|
|||
if BankerWinScore > 0 { |
|||
TempRateAfter = int64(float64(BankerWinScore) * (1 - rr.Opt.BrightRate)) |
|||
WinBetGold = BankerWinScore |
|||
WinGold = 0 |
|||
} else { |
|||
WinBetGold = 0 |
|||
WinGold = BankerWinScore |
|||
} |
|||
|
|||
BankerPlayer.TableWin += TempRateAfter |
|||
BankerPlayer.WinScore = TempRateAfter |
|||
rr.UserScore[BankerPlayer.ChairId] = rr.UserScore[BankerPlayer.ChairId].Add(decimal.NewFromInt(TempRateAfter)) |
|||
if TempRateAfter < 0 { |
|||
UserRealBet = -TempRateAfter |
|||
} |
|||
|
|||
if !BankerPlayer.IsRobot && (BankerPlayer.WinScore != 0) && (BankerPlayer.Ctx != nil) { |
|||
AfterGold, BloodPool, StockNum := rr.WriteUserScore(BankerPlayer, 3, 0, WinBetGold, WinGold, rr.ReasonString, "", sPlayers, UserRealBet) |
|||
log.Debug("WriteUserScore 后 AfterGold=", AfterGold, " BloodPool=", BloodPool, " StockNum=", StockNum, " GameID", rr.GameID, " RoomID", rr.RoomID) |
|||
rr.UserScore[BankerPlayer.ChairId] = decimal.NewFromInt(AfterGold) |
|||
BankerPlayer.Gold = decimal.NewFromInt(AfterGold) |
|||
} |
|||
|
|||
// 庄家数据
|
|||
TableSeat := &protocol.RoomPlayer{} |
|||
TableSeat.Uid = BankerPlayer.Uid |
|||
TableSeat.ChairID = BankerPlayer.ChairId |
|||
if rr.CurrBanker == BankerPlayer.ChairId { |
|||
TableSeat.IsBanker = 1 |
|||
} |
|||
TableSeat.State = rr.State |
|||
TableSeat.Avatar = BankerPlayer.Avatar |
|||
TableSeat.Gold = BankerPlayer.Gold.IntPart() |
|||
TableSeat.Nickname = BankerPlayer.Nickname |
|||
TableSeat.Sex = BankerPlayer.Sex |
|||
TableSeat.Vip = 0 |
|||
TableSeat.Level = BankerPlayer.Level |
|||
TableSeat.Exp = 0 |
|||
TableSeat.WinLose = 2 |
|||
if BankerPlayer.WinScore > 0 { |
|||
TableSeat.WinLose = 1 |
|||
} |
|||
|
|||
for _, poker := range BankerPlayer.HandPoker { |
|||
TableSeat.HandPoker = append(TableSeat.HandPoker, int32(poker)) |
|||
} |
|||
|
|||
TableSeat.PokerType, TableSeat.Point = BankerPlayer.HandPoker.GetCardType() |
|||
TableSeat.BetScore = BankerPlayer.BetScore |
|||
GameOver.PlayList = append(GameOver.PlayList, TableSeat) |
|||
|
|||
sort.Slice(GameOver.PlayList, func(i, j int) bool { |
|||
return GameOver.PlayList[i].ChairID < GameOver.PlayList[j].ChairID |
|||
}) |
|||
|
|||
GameOver.Record = rr.Record |
|||
//for index, record := range rr.Record {
|
|||
// log.Debug("结束 现在有 ", len(rr.Record), " 个记录 当前第 ", index, " 个 值:", record)
|
|||
//}
|
|||
|
|||
for _, player := range rr.PlayerWatchMap { |
|||
player.PlayWatchCount++ |
|||
} |
|||
|
|||
rr.State = EN_TABLE_STATE_FINISH //结算状态
|
|||
|
|||
rr.SendAllMessage(route.NotifyGameConclude, GameOver) |
|||
|
|||
log.Debug(rr.TimeOutResult/1000, ":秒后开始下一局倒计时") |
|||
} |
|||
|
|||
func (rr *Room) WriteUserScore(User *Player, BetType int32, BetGold int64, WinBetGold int64, WinGold int64, reason string, Area string, Players string, UserRealBet int64) (int64, float64, int64) { |
|||
currentDate := time.Now().Format("20060102") |
|||
roundNo := fmt.Sprintf(fmt.Sprintf("%s%s%s", currentDate, strconv.Itoa(int(rr.RoomID)), rpc_client.GenerateRoundNo())) |
|||
Req := writeUserScorepb.WriteUserScoreArgs{ |
|||
UID: User.Uid, |
|||
AgentID: User.AgentID, |
|||
ChannelID: 0, |
|||
Reason: reason, |
|||
GameType: 2, |
|||
GameName: rr.Opt.Name, |
|||
GameID: GAME_ID, |
|||
RoomID: int64(rr.RoomID), |
|||
SeatID: User.ChairId, |
|||
RoundNO: roundNo, |
|||
MingTax: rr.Opt.BrightRate, |
|||
AnTax: rr.Opt.DarkRate, |
|||
CurrentRoomNum: rr.GetRoomRealPlayerCount(), |
|||
RoomGears: rr.BoolePool.RoomGears, |
|||
BloodID: rr.BoolePool.BoolPoolId, |
|||
Stock: rr.BoolePool.BoolPoolSockNum, |
|||
StockConfig: rr.BoolePool.StockConf, |
|||
StockThresholdValue: tools.Int64ToStr(rr.BoolePool.NowTurnPoint), |
|||
IsCtrl: User.IsCheat, |
|||
AssetKind: 1, |
|||
BetAmount: BetGold, |
|||
WinAmount: WinGold, |
|||
BeforeBalance: 0, |
|||
AfterBalance: 0, |
|||
CheatType: User.CheatType, |
|||
CheatValueBefore: User.CheatValueBefore, |
|||
CheatValueAfter: 0, |
|||
UserAmount: BetGold, |
|||
BetType: int64(BetType), |
|||
UserWinBetAmount: WinBetGold, |
|||
Area: Area, |
|||
Players: Players, |
|||
UserRealBet: UserRealBet, |
|||
TableId: rr.RId, |
|||
RobotCount: int64(rr.GetRoomPlayerCount() - rr.GetRoomRealPlayerCount()), |
|||
} |
|||
if BetType == 3 { |
|||
Req.UserAmount = 0 |
|||
} |
|||
log.Debug("用户", User.Uid, "名字", User.Nickname, "写分 ", Req) |
|||
Res := rpc_client.WriteUserScore(rr.RoomProxy, Req) |
|||
log.Debug("写分返回 ", Res) |
|||
|
|||
return Res.Gold, Res.BloodPool, Res.StockNum |
|||
} |
@ -0,0 +1,48 @@ |
|||
package game |
|||
|
|||
import ( |
|||
"base/cluster/node" |
|||
"github.com/shopspring/decimal" |
|||
"xgame/game/TTZ/app/core/types" |
|||
) |
|||
|
|||
const ( |
|||
MAX_UNM = 100 //房间最大人数
|
|||
) |
|||
|
|||
type Player struct { |
|||
Ctx *node.Context |
|||
Uid int64 //userId
|
|||
UserNo string //
|
|||
AgentID int32 //代理ID
|
|||
ChairId int32 //椅子号
|
|||
IsRobot bool //是否是机器人
|
|||
Gold decimal.Decimal // 玩家金币
|
|||
Diamond decimal.Decimal // 玩家钻石
|
|||
Ticket decimal.Decimal // 玩家点券
|
|||
Nickname string // 姓名
|
|||
Avatar string // 玩家头像
|
|||
OnlineState int32 // USER_OFF_LINE
|
|||
Sex int32 //
|
|||
Level int32 //
|
|||
IsCheat bool //是否有控制
|
|||
CheatType int64 //控制类型
|
|||
RoomGears string //玩家拐点值
|
|||
CheatValueBefore int64 //库存 变化前数据
|
|||
CheatValue int64 //控制值[CheatValue这个是数据库取出来的,石总那边配置]
|
|||
CurrCheatValue decimal.Decimal //当前控制值[CheatValue这个是数据库取出来的,石总那边配置,CurrCheatValue这个是每局输赢计算,游戏开始之前都要与CheatValue比较用于确定是否点控该玩家]
|
|||
|
|||
RobotWin bool // true 赢 false 输
|
|||
HandPoker types.PokerSlice // 玩家手牌
|
|||
PlayCount int //在桌子上呆了几局
|
|||
PlayWatchCount int //在桌子连续观战了几局
|
|||
CurrentRoundBet bool //本局是否下注了
|
|||
CanBet bool //玩家是否可以下注
|
|||
NoBetCount int //在桌子上未下注的局数
|
|||
TableWin int64 // 桌子上的总输赢
|
|||
BetScore int64 // 结算时的总下注
|
|||
WinScore int64 // 结算时的总输赢
|
|||
WinBetScore int64 // 赢的区域的总下注
|
|||
|
|||
UserNeedOut bool //退出状态
|
|||
} |
@ -0,0 +1,30 @@ |
|||
package game |
|||
|
|||
import ( |
|||
"base/cluster" |
|||
"base/session" |
|||
"xgame/game/rummy/app/core/protocol" |
|||
"xgame/internal/route" |
|||
) |
|||
|
|||
// OnReconnect 断线重连
|
|||
func (rr *Room) OnReconnect(userId int64) { |
|||
rr.roomRWLock.Lock() |
|||
defer rr.roomRWLock.Unlock() |
|||
|
|||
//本身这里是可以:检查到该玩的游戏还没结束,在玩家登录了成功后服务器该本身主动推送房间和玩家的信息的
|
|||
//但是由于服务器的缺陷,拿不到Ctx,只能先通知客户端你有个游戏还在继续,让客户端主动拉取房间信息
|
|||
_ = rr.RoomProxy.Push(rr.Ctx, &cluster.PushArgs{ |
|||
Kind: session.User, |
|||
Target: userId, |
|||
//Target: uid,
|
|||
Message: &cluster.Message{ |
|||
Route: route.ResumeGame, |
|||
Data: &protocol.ResumeGameNotice{ |
|||
RoomId: rr.RoomID, |
|||
GameId: rr.GameID, |
|||
}, |
|||
}, |
|||
}) |
|||
|
|||
} |
@ -0,0 +1,46 @@ |
|||
package game |
|||
|
|||
import ( |
|||
"base/log" |
|||
"xgame/game/TTZ/app/core/protocol" |
|||
) |
|||
|
|||
// RepeatRoom 复位桌子
|
|||
func (rr *Room) RepeatRoom() { |
|||
|
|||
rr.BaoDiBanker = false |
|||
rr.PokerIndex = 0 //
|
|||
rr.PokersCount = 0 //
|
|||
rr.CurrOperationPlayer = -1 //
|
|||
rr.CurrBanker = INVALID_VALUE //
|
|||
rr.IsP2pControls = false //点控
|
|||
|
|||
// 重新获得血池 测试关闭
|
|||
if rr.BoolePool.SetBoole(rr.RoomProxy, rr.Opt.BloodId) == false { |
|||
log.Debug(" 桌子号", rr.RId, "复位桌子获取血池失败") |
|||
} |
|||
|
|||
} |
|||
|
|||
func (rr *Room) RepeatRoomUser() { //复位玩家的数据
|
|||
if rr.CurrentGameState == protocol.STATE_GET_BANKER { |
|||
for index, _ := range rr.PlayerMap { |
|||
rr.PlayerMap[index].CurrentRoundBet = false |
|||
rr.PlayerMap[index].CanBet = true |
|||
rr.PlayerMap[index].BetScore = 0 |
|||
rr.PlayerMap[index].WinScore = 0 |
|||
rr.PlayerMap[index].RobotWin = false |
|||
rr.PlayerMap[index].HandPoker = rr.PlayerMap[index].HandPoker[:0] |
|||
} |
|||
|
|||
for index, _ := range rr.PlayerWatchMap { |
|||
rr.PlayerWatchMap[index].CurrentRoundBet = false |
|||
rr.PlayerWatchMap[index].CanBet = true |
|||
rr.PlayerWatchMap[index].BetScore = 0 |
|||
rr.PlayerWatchMap[index].WinScore = 0 |
|||
rr.PlayerWatchMap[index].RobotWin = false |
|||
rr.PlayerWatchMap[index].HandPoker = rr.PlayerWatchMap[index].HandPoker[:0] |
|||
} |
|||
} |
|||
|
|||
} |
@ -0,0 +1,8 @@ |
|||
package game |
|||
|
|||
// 恢复游戏信息
|
|||
func (rr *Room) OnResumeGameData(uid int64) { |
|||
rr.roomRWLock.Lock() |
|||
defer rr.roomRWLock.Unlock() |
|||
|
|||
} |
@ -0,0 +1,495 @@ |
|||
package game |
|||
|
|||
import ( |
|||
"base/codes" |
|||
"base/log" |
|||
"math/rand" |
|||
"strconv" |
|||
"sync" |
|||
"time" |
|||
"xgame/game/TTZ/app/core/protocol" |
|||
"xgame/game/TTZ/app/route" |
|||
|
|||
"github.com/cognusion/randomnames" |
|||
"github.com/roylee0704/gron" |
|||
"github.com/shopspring/decimal" |
|||
) |
|||
|
|||
const ( |
|||
RobotUid = 900000000 |
|||
BetTimer = 0x1000 |
|||
) |
|||
|
|||
var ( |
|||
CurRobotUserCount = int64(0) |
|||
RobotBet = int32(1000) |
|||
) |
|||
|
|||
type RobotBetCtrlInfo struct { |
|||
BetAmount int64 //下注金额
|
|||
MinBet int64 // 最低下注
|
|||
MaxBet int64 // 最高下注
|
|||
} |
|||
|
|||
type RobotManager struct { |
|||
GronTimer *gron.Cron |
|||
Lock sync.RWMutex |
|||
GameRoom *Room |
|||
FirstEnterTimer int64 //首个机器人进入时间
|
|||
NextEnterTimer int64 //下个机器人进入时间
|
|||
FlushCountTimer int64 //下次刷新机器人数量的时间
|
|||
MaxCount int //机器人数量
|
|||
PlayerMaps map[int32]*Player //当前有的机器人
|
|||
playerBetCtrl map[int32]*RobotBetCtrlInfo //当前有的机器人
|
|||
playerStat map[int32]int32 //机器人的状态
|
|||
RobotTimer map[int32]int64 //机器人的操作时间
|
|||
} |
|||
|
|||
func NewRobotManager() *RobotManager { |
|||
rm := &RobotManager{ |
|||
Lock: sync.RWMutex{}, |
|||
PlayerMaps: make(map[int32]*Player), |
|||
playerStat: make(map[int32]int32), |
|||
playerBetCtrl: make(map[int32]*RobotBetCtrlInfo), |
|||
RobotTimer: make(map[int32]int64), |
|||
} |
|||
return rm |
|||
} |
|||
|
|||
func (r *RobotManager) OnInit(conf string, GameRoom *Room) { |
|||
r.GameRoom = GameRoom |
|||
|
|||
if r.GronTimer != nil { |
|||
r.GronTimer.Stop() |
|||
r.GronTimer = nil |
|||
} |
|||
|
|||
r.GronTimer = gron.New() |
|||
|
|||
r.GronTimer.AddFunc(gron.Every(time.Duration(50)*time.Millisecond), func() { |
|||
r.run() |
|||
}) |
|||
|
|||
nowUnixNano := time.Now().UnixNano() |
|||
nowMilliSeconds := nowUnixNano / 1e6 |
|||
|
|||
// 第一个进入的机器人 只判断一次
|
|||
r.FirstEnterTimer = 0 |
|||
if r.GameRoom.CreatorId != 0 { |
|||
FirstMinTime := r.GameRoom.TableConfig.FirstRobotCheckMinFrequency * 1000 |
|||
FirstMaxTime := r.GameRoom.TableConfig.FirstRobotCheckMaxFrequency * 1000 |
|||
if FirstMaxTime <= FirstMinTime { |
|||
r.FirstEnterTimer = nowMilliSeconds + FirstMaxTime |
|||
} else { |
|||
r.FirstEnterTimer = nowMilliSeconds + rand.Int63n(FirstMaxTime-FirstMinTime) + FirstMinTime |
|||
} |
|||
} |
|||
|
|||
// 间隔多少时间正常进个机器人
|
|||
MinInterTime := 0 |
|||
MaxInterTime := 0 |
|||
if r.GameRoom.TableConfig != nil { |
|||
MinInterTime = int(r.GameRoom.TableConfig.RobotCheckMinFrequency) * 1000 |
|||
MaxInterTime = int(r.GameRoom.TableConfig.RobotCheckMaxFrequency) * 1000 |
|||
log.Debug(" 后台配置 机器人进入频率 最小 ", MinInterTime, " 最大 ", MaxInterTime) |
|||
} else { |
|||
MinInterTime = r.GameRoom.BloodCtrl.AndroidOprateConfig.JoinHZ[0] * 1000 |
|||
MaxInterTime = r.GameRoom.BloodCtrl.AndroidOprateConfig.JoinHZ[1] * 1000 |
|||
} |
|||
|
|||
rTime := int64(0) |
|||
if MaxInterTime <= MinInterTime { |
|||
rTime = int64(MinInterTime) |
|||
} else { |
|||
rTime = int64(rand.Intn(MaxInterTime-MinInterTime) + MinInterTime) |
|||
} |
|||
|
|||
//处理个意外
|
|||
if rTime == 0 { |
|||
rTime = 2000 |
|||
log.Error(" 出现0了 是不行的 ", r.GameRoom.RoomID) |
|||
} |
|||
|
|||
r.NextEnterTimer = nowMilliSeconds + rTime |
|||
|
|||
if GameRoom.TableConfig != nil { |
|||
r.MaxCount = 0 |
|||
|
|||
if GameRoom.TableConfig.TableType == 2 { |
|||
if GameRoom.TableConfig.OneMaxNum <= GameRoom.TableConfig.OneMinNum { |
|||
r.MaxCount = int(GameRoom.TableConfig.OneMinNum) |
|||
} else { |
|||
r.MaxCount = int(rand.Int63n(GameRoom.TableConfig.OneMaxNum-GameRoom.TableConfig.OneMinNum+1) + GameRoom.TableConfig.OneMinNum) |
|||
} |
|||
} else { |
|||
if GameRoom.TableConfig.ZeroMaxNum <= GameRoom.TableConfig.ZeroMinNum { |
|||
r.MaxCount = int(GameRoom.TableConfig.ZeroMinNum) |
|||
} else { |
|||
r.MaxCount = int(rand.Int63n(GameRoom.TableConfig.ZeroMaxNum-GameRoom.TableConfig.ZeroMinNum+1) + GameRoom.TableConfig.ZeroMinNum) |
|||
} |
|||
} |
|||
|
|||
r.FlushCountTimer = nowMilliSeconds + GameRoom.TableConfig.CheckFrequency*1000 |
|||
|
|||
log.Debug("从后台配置 最大机器人数 ", r.MaxCount, " 刷新时间 ", GameRoom.TableConfig.CheckFrequency) |
|||
} else { |
|||
ProMax := 0 |
|||
for _, tempCount := range GameRoom.BloodCtrl.AndroidOprateConfig.CountMax0 { |
|||
ProMax += tempCount[1] |
|||
} |
|||
ProNow := rand.Intn(ProMax) |
|||
r.MaxCount = 0 |
|||
for _, tempCount := range GameRoom.BloodCtrl.AndroidOprateConfig.CountMax0 { |
|||
if ProNow < tempCount[1] { |
|||
r.MaxCount = tempCount[0] |
|||
break |
|||
} else { |
|||
ProNow -= tempCount[1] |
|||
} |
|||
} |
|||
r.FlushCountTimer = nowMilliSeconds + int64(GameRoom.BloodCtrl.AndroidOprateConfig.FlushHZ*1000) |
|||
} |
|||
|
|||
r.GronTimer.Start() |
|||
} |
|||
|
|||
// NewGameRobot new个机器人
|
|||
func (r *RobotManager) NewGameRobot() *Player { |
|||
//待定先从数据库user表中获取,没有就new一个注册到user中去
|
|||
MinGold := r.GameRoom.BloodCtrl.AndroidOprateConfig.InGold[r.GameRoom.RoomID][0] |
|||
ManGold := r.GameRoom.BloodCtrl.AndroidOprateConfig.InGold[r.GameRoom.RoomID][1] |
|||
gold := rand.Intn(ManGold-MinGold) + MinGold |
|||
diamond := rand.Int63n(1000) + 1000 |
|||
ticket := rand.Int63n(1000) + 1000 |
|||
CurRobotUserCount++ |
|||
if CurRobotUserCount > 10000 { |
|||
CurRobotUserCount = 1 |
|||
} |
|||
//随机头像
|
|||
avatar := rand.Intn(180) + 1 |
|||
return &Player{ |
|||
Uid: CurRobotUserCount + RobotUid, |
|||
Gold: decimal.NewFromFloat(float64(gold)), // 玩家金币
|
|||
Diamond: decimal.NewFromFloat(float64(diamond)), // 玩家钻石
|
|||
Ticket: decimal.NewFromFloat(float64(ticket)), // 玩家点券
|
|||
IsRobot: true, |
|||
Avatar: strconv.Itoa(avatar), |
|||
Nickname: randomnames.RandomName(), |
|||
} |
|||
|
|||
} |
|||
|
|||
// RobotsEnterGameRoom 机器人进入房间
|
|||
func (r *RobotManager) RobotsEnterGameRoom() { |
|||
|
|||
pPlayer := r.NewGameRobot() |
|||
if 0 != r.GameRoom.JoinRoom(pPlayer, 0) { |
|||
log.Debug(" 桌子号", r.GameRoom.RId, "机器人加入房间失败") |
|||
return |
|||
} |
|||
|
|||
// 发送完桌子消息 再激活用户状态
|
|||
pPlayer.OnlineState = USER_ON_LINE |
|||
|
|||
// 通知大厅有机器人坐下
|
|||
NotifySitDown := &protocol.NotifyDTSitDown{ |
|||
Uid: pPlayer.Uid, |
|||
RoomID: r.GameRoom.RoomID, |
|||
TableID: r.GameRoom.RId, |
|||
ChairID: pPlayer.ChairId, |
|||
Avatar: pPlayer.Avatar, |
|||
State: r.GameRoom.CurrentGameState, |
|||
} |
|||
r.GameRoom.NotifyFunc(route.NotifyDTSitDown, NotifySitDown) |
|||
|
|||
//判断开场
|
|||
if r.GameRoom.State < EN_TABLE_STATE_PLAYING && r.GameRoom.GetRoomPlayerCount() > 4 { |
|||
log.Debug(" 桌子号", r.GameRoom.RId, " 可以开场当前人数", r.GameRoom.GetRoomPlayerCount()) |
|||
r.GameRoom.State = EN_TABLE_STATE_PLAYING |
|||
milliseconds := time.Now().UnixMilli() |
|||
r.GameRoom.CurrentGameState = protocol.STATE_BEGIN |
|||
r.GameRoom.CurrentOperationTimer = milliseconds + r.GameRoom.TimeOutBegin |
|||
|
|||
r.GameRoom.SendAllMessage(route.NotifyStateTime, &protocol.NotifyStateTime{ |
|||
NextState: protocol.STATE_BEGIN, |
|||
NextTimestamp: r.GameRoom.CurrentOperationTimer, |
|||
}) |
|||
} |
|||
|
|||
r.Lock.Lock() |
|||
defer r.Lock.Unlock() |
|||
r.PlayerMaps[pPlayer.ChairId] = pPlayer |
|||
r.playerStat[pPlayer.ChairId] = 1 |
|||
r.playerBetCtrl[pPlayer.ChairId] = &RobotBetCtrlInfo{} |
|||
//随机一个下次判断行为时间
|
|||
milliseconds := time.Now().UnixMilli() |
|||
//rTime := rand.Int63n(5) + 2
|
|||
r.RobotTimer[pPlayer.ChairId] = milliseconds + 60*1000 |
|||
log.Debug(" 桌子号", r.GameRoom.RId, " UID:", pPlayer.Uid, " 名字 ", pPlayer.Nickname, "机器人加入房间Ok:", codes.OK.Code(), " 当前机器人个数", r.GameRoom.GetInRoomRobotCount()) |
|||
} |
|||
|
|||
func (r *RobotManager) CopyRobotsEnterGameRoom(pPlayer *Player) { // 复制的机器人进入房间
|
|||
r.Lock.Lock() |
|||
defer r.Lock.Unlock() |
|||
|
|||
r.PlayerMaps[pPlayer.ChairId] = pPlayer |
|||
r.playerStat[pPlayer.ChairId] = 1 |
|||
r.playerBetCtrl[pPlayer.ChairId] = &RobotBetCtrlInfo{} |
|||
//随机一个下次判断行为时间
|
|||
milliseconds := time.Now().UnixMilli() |
|||
//rTime := rand.Int63n(5) + 2
|
|||
r.RobotTimer[pPlayer.ChairId] = milliseconds + 60*1000 |
|||
log.Debug(" 桌子号", r.GameRoom.RId, " UID:", pPlayer.Uid, " 名字 ", pPlayer.Nickname, "机器人加入房间Ok:", codes.OK.Code(), " 当前机器人个数", r.GameRoom.GetInRoomRobotCount()) |
|||
} |
|||
|
|||
func (r *RobotManager) AddLeaveRobot(chairId int32) { // 机器人离开
|
|||
r.Lock.Lock() |
|||
defer r.Lock.Unlock() |
|||
|
|||
robot := r.PlayerMaps[chairId] |
|||
if robot == nil { |
|||
return |
|||
} |
|||
|
|||
delete(r.PlayerMaps, chairId) |
|||
delete(r.RobotTimer, chairId) |
|||
delete(r.playerStat, chairId) |
|||
delete(r.playerBetCtrl, chairId) |
|||
} |
|||
|
|||
func (r *RobotManager) UpdateRobot() { // 更新机器人
|
|||
|
|||
} |
|||
|
|||
func (r *RobotManager) OnRobotMessage(msgId int32, player *Player, msg interface{}) { // 消息相应
|
|||
//if msgId != route.NotifyBet {
|
|||
// log.Debug(" 桌子号", r.GameRoom.RId, "机器人收到消息", msgId)
|
|||
// log.Printf(1, "内容: %+v\n", msg)
|
|||
//}
|
|||
|
|||
switch msgId { |
|||
case route.NotifySitDown: // 加入游戏
|
|||
{ |
|||
if player == nil { |
|||
log.Debug("加入游戏==>机器人不能为空") |
|||
return |
|||
} |
|||
if !player.IsRobot { |
|||
log.Debug("加入游戏==>这不是一个机器人") |
|||
return |
|||
} |
|||
break |
|||
} |
|||
|
|||
case route.NotifyStateTime: // 通知阶段倒计时
|
|||
{ |
|||
if player == nil { |
|||
log.Debug("开始游戏==>机器人不能为空") |
|||
return |
|||
} |
|||
if !player.IsRobot { |
|||
log.Debug("开始游戏==>这不是一个机器人") |
|||
return |
|||
} |
|||
if _, exists := r.playerBetCtrl[player.ChairId]; !exists { |
|||
log.Debug("机器人还没进来") |
|||
return |
|||
} |
|||
|
|||
message := msg.(*protocol.NotifyStateTime) |
|||
|
|||
if message == nil { |
|||
log.Debug("通知退出==>解析 NotifyLeaveRoomRes 结构体失败") |
|||
return |
|||
} |
|||
|
|||
//随机一个下次判断行为时间
|
|||
CurrentGears := 0 |
|||
TempRoomGears, err := strconv.Atoi(r.GameRoom.BoolePool.RoomGears) |
|||
if err == nil { |
|||
CurrentGears = TempRoomGears |
|||
//log.Debug(" 桌子号", r.GameRoom.RId, "房间当前血池档位1 :", TempRoomGears, " CurrentGears :", CurrentGears)
|
|||
} |
|||
|
|||
CurrentGearConfig := r.GameRoom.BloodCtrl.GearConfig[0] |
|||
for _, GearConfig := range r.GameRoom.BloodCtrl.GearConfig { |
|||
if GearConfig.GearID == CurrentGears { |
|||
CurrentGearConfig = GearConfig |
|||
break |
|||
} |
|||
} |
|||
|
|||
// 判断下注的档位
|
|||
milliseconds := time.Now().UnixMilli() |
|||
if message.NextState == protocol.STATE_BET { |
|||
if r.playerBetCtrl[player.ChairId].MinBet > 0 { |
|||
tempRand := rand.Intn(100) |
|||
tempBetAmount := r.playerBetCtrl[player.ChairId].MinBet |
|||
if tempRand < 10 && r.playerBetCtrl[player.ChairId].MinBet*5 < r.playerBetCtrl[player.ChairId].MaxBet { |
|||
tempBetAmount *= 5 |
|||
} else if tempRand < 20 && r.playerBetCtrl[player.ChairId].MinBet*4 < r.playerBetCtrl[player.ChairId].MaxBet { |
|||
tempBetAmount *= 4 |
|||
} else if tempRand < 40 && r.playerBetCtrl[player.ChairId].MinBet*3 < r.playerBetCtrl[player.ChairId].MaxBet { |
|||
tempBetAmount *= 3 |
|||
} else if tempRand < 60 && r.playerBetCtrl[player.ChairId].MinBet*2 < r.playerBetCtrl[player.ChairId].MaxBet { |
|||
tempBetAmount *= 2 |
|||
} |
|||
r.playerBetCtrl[player.ChairId].BetAmount = tempBetAmount |
|||
} else { |
|||
r.playerBetCtrl[player.ChairId].BetAmount = r.GameRoom.Opt.MinBetAsset |
|||
} |
|||
|
|||
//随机一个下次判断行为时间 第一轮要加7秒动动画
|
|||
rTime := rand.Int63n(8000) + 2000 |
|||
r.Lock.Lock() |
|||
r.RobotTimer[player.ChairId] = milliseconds + rTime |
|||
r.Lock.Unlock() |
|||
//log.Debug(r.GameRoom.RId, " 机器人 ", player.Uid, "随机的金额", r.playerBetCtrl[player.ChairId].BetAmount, " ", rTime, "秒后下注")
|
|||
} else { |
|||
r.playerBetCtrl[player.ChairId].BetAmount = 0 |
|||
} |
|||
|
|||
// 判断抢庄
|
|||
if message.NextState == protocol.STATE_GET_BANKER { |
|||
if rand.Intn(10000) < CurrentGearConfig.BankerPro { |
|||
go func() { |
|||
SelectTime := rand.Int63n(r.GameRoom.BloodCtrl.TimeOutGetBanker-2000) + 2000 |
|||
time.Sleep(time.Duration(SelectTime) * time.Millisecond) |
|||
r.GameRoom.OnUserGetBanker(player.Uid, &protocol.GetBankerReq{ |
|||
State: 0, |
|||
}) |
|||
}() |
|||
} else { |
|||
go func() { |
|||
SelectTime := rand.Int63n(r.GameRoom.BloodCtrl.TimeOutGetBanker-2000) + 2000 |
|||
time.Sleep(time.Duration(SelectTime) * time.Millisecond) |
|||
r.GameRoom.OnUserGetBanker(player.Uid, &protocol.GetBankerReq{ |
|||
State: 1, |
|||
}) |
|||
}() |
|||
} |
|||
} |
|||
|
|||
break |
|||
} |
|||
|
|||
case route.NotifyCurrentBeginUser: // 通知开始骰子玩家
|
|||
{ |
|||
if player == nil { |
|||
log.Debug("开始游戏==>机器人不能为空") |
|||
return |
|||
} |
|||
if !player.IsRobot { |
|||
log.Debug("开始游戏==>这不是一个机器人") |
|||
return |
|||
} |
|||
|
|||
message := msg.(*protocol.NotifyCurrentBeginUser) |
|||
|
|||
if message == nil { |
|||
log.Debug("通知退出==>解析 NotifyLeaveRoomRes 结构体失败") |
|||
return |
|||
} |
|||
|
|||
if _, exists := r.playerBetCtrl[player.ChairId]; exists { |
|||
r.playerBetCtrl[player.ChairId].MinBet = message.MinBet |
|||
r.playerBetCtrl[player.ChairId].MaxBet = message.MaxBet |
|||
} |
|||
|
|||
break |
|||
} |
|||
case route.NotifyPoker: // 通知翻牌
|
|||
{ |
|||
if player == nil { |
|||
log.Debug("开始游戏==>机器人不能为空") |
|||
return |
|||
} |
|||
if !player.IsRobot { |
|||
log.Debug("开始游戏==>这不是一个机器人") |
|||
return |
|||
} |
|||
|
|||
break |
|||
} |
|||
|
|||
case route.NotifyGetOutGame: // 退出房间
|
|||
{ |
|||
if player == nil { |
|||
log.Debug("通知退出==>机器人不能为空") |
|||
return |
|||
} |
|||
|
|||
if !player.IsRobot { |
|||
log.Debug("通知退出==>这不是一个机器人") |
|||
return |
|||
} |
|||
|
|||
message := msg.(*protocol.NotifyLeaveRoomRes) |
|||
|
|||
if message == nil { |
|||
log.Debug("通知退出==>解析 NotifyLeaveRoomRes 结构体失败") |
|||
return |
|||
} |
|||
|
|||
break |
|||
} |
|||
|
|||
case route.NotifyBet: //出牌
|
|||
{ |
|||
if player == nil { |
|||
log.Debug("出牌==>机器人不能为空") |
|||
return |
|||
} |
|||
|
|||
if !player.IsRobot { |
|||
log.Debug("出牌==>这不是一个机器人") |
|||
return |
|||
} |
|||
|
|||
break |
|||
} |
|||
case route.NotifyGameConclude: |
|||
{ |
|||
if player == nil { |
|||
log.Debug("结算==>机器人不能为空") |
|||
return |
|||
} |
|||
|
|||
if !player.IsRobot { |
|||
log.Debug("结算==>这不是一个机器人") |
|||
return |
|||
} |
|||
|
|||
message := msg.(*protocol.NotifyGameConclude) |
|||
if message == nil { |
|||
log.Debug("结算==>解析 NotifyGameConclude 结构体失败") |
|||
return |
|||
} |
|||
|
|||
//结束时候判断是否机器人要离开
|
|||
//if message.GameState == 1 {
|
|||
if r.GameRoom.GetInRoomRobotCount() > int32(r.MaxCount) { |
|||
r.GameRoom.OnGetOutRoom(player.Uid) |
|||
log.Debug(r.GameRoom.RId, " 机器人 ", player.Uid, " 需要离开 当前机器人个数", r.GameRoom.GetInRoomRobotCount(), "需要的人数", r.MaxCount) |
|||
} |
|||
//}
|
|||
} |
|||
case route.LogoutTableRes: |
|||
if player == nil { |
|||
log.Debug("结算==>机器人不能为空") |
|||
return |
|||
} |
|||
|
|||
if !player.IsRobot { |
|||
log.Debug("结算==>这不是一个机器人") |
|||
return |
|||
} |
|||
|
|||
r.AddLeaveRobot(player.ChairId) |
|||
log.Debug(r.GameRoom.RId, " 机器人 ", player.Uid, " 已经离开 当前机器人个数", r.GameRoom.GetInRoomRobotCount()) |
|||
default: |
|||
{ |
|||
break |
|||
} |
|||
} |
|||
} |
@ -0,0 +1,190 @@ |
|||
package game |
|||
|
|||
import ( |
|||
"base/log" |
|||
"math/rand" |
|||
"time" |
|||
"xgame/game/TTZ/app/core/protocol" |
|||
) |
|||
|
|||
// KickRobotTimer 踢人定时器
|
|||
func (r *RobotManager) KickRobotTimer() { |
|||
|
|||
} |
|||
|
|||
func (r *RobotManager) run() { |
|||
milliseconds := time.Now().UnixMilli() |
|||
|
|||
if r.FirstEnterTimer != 0 && milliseconds >= r.FirstEnterTimer { |
|||
r.FirstEnterTimer = 0 |
|||
if r.GameRoom.GetInRoomRobotCount() < int32(r.MaxCount) { |
|||
//r.Lock.Lock()
|
|||
r.RobotsEnterGameRoom() |
|||
} |
|||
} |
|||
|
|||
if milliseconds >= r.NextEnterTimer { |
|||
if r.GameRoom.GetInRoomRobotCount() < int32(r.MaxCount) { |
|||
//r.Lock.Lock()
|
|||
r.RobotsEnterGameRoom() |
|||
|
|||
MinInterTime := 0 |
|||
MaxInterTime := 0 |
|||
if r.GameRoom.TableConfig != nil { |
|||
MinInterTime = int(r.GameRoom.TableConfig.RobotCheckMinFrequency) * 1000 |
|||
MaxInterTime = int(r.GameRoom.TableConfig.RobotCheckMaxFrequency) * 1000 |
|||
log.Debug(" 后台配置 机器人进入频率 最小 ", MinInterTime, " 最大 ", MaxInterTime) |
|||
} else { |
|||
MinInterTime = r.GameRoom.BloodCtrl.AndroidOprateConfig.JoinHZ[0] * 1000 |
|||
MaxInterTime = r.GameRoom.BloodCtrl.AndroidOprateConfig.JoinHZ[1] * 1000 |
|||
} |
|||
|
|||
rTime := int64(0) |
|||
if MaxInterTime <= MinInterTime { |
|||
rTime = int64(MinInterTime) |
|||
} else { |
|||
rTime = int64(rand.Intn(MaxInterTime-MinInterTime) + MinInterTime) |
|||
} |
|||
|
|||
//处理个意外
|
|||
if rTime == 0 { |
|||
rTime = 2000 |
|||
log.Error(" 出现0了 是不行的 ", r.GameRoom.RoomID) |
|||
} |
|||
|
|||
r.NextEnterTimer = milliseconds + rTime |
|||
//r.Lock.Unlock()
|
|||
|
|||
} |
|||
} |
|||
|
|||
if r.GameRoom.TableConfig != nil { |
|||
if milliseconds >= r.FlushCountTimer { |
|||
switch r.GameRoom.GetRoomRealPlayerCount() { |
|||
case 0: |
|||
r.MaxCount = 0 |
|||
if r.GameRoom.TableConfig.ZeroMaxNum <= r.GameRoom.TableConfig.ZeroMinNum { |
|||
r.MaxCount = int(r.GameRoom.TableConfig.ZeroMinNum) |
|||
} else { |
|||
r.MaxCount = int(rand.Int63n(r.GameRoom.TableConfig.ZeroMaxNum-r.GameRoom.TableConfig.ZeroMinNum+1) + r.GameRoom.TableConfig.ZeroMinNum) |
|||
} |
|||
case 1: |
|||
r.MaxCount = 0 |
|||
if r.GameRoom.TableConfig.OneMaxNum <= r.GameRoom.TableConfig.OneMinNum { |
|||
r.MaxCount = int(r.GameRoom.TableConfig.OneMinNum) |
|||
} else { |
|||
r.MaxCount = int(rand.Int63n(r.GameRoom.TableConfig.OneMaxNum-r.GameRoom.TableConfig.OneMinNum+1) + r.GameRoom.TableConfig.OneMinNum) |
|||
} |
|||
case 2: |
|||
r.MaxCount = 0 |
|||
if r.GameRoom.TableConfig.TwoMaxNum <= r.GameRoom.TableConfig.TwoMinNum { |
|||
r.MaxCount = int(r.GameRoom.TableConfig.TwoMinNum) |
|||
} else { |
|||
r.MaxCount = int(rand.Int63n(r.GameRoom.TableConfig.TwoMaxNum-r.GameRoom.TableConfig.TwoMinNum+1) + r.GameRoom.TableConfig.TwoMinNum) |
|||
} |
|||
case 3: |
|||
r.MaxCount = 0 |
|||
if r.GameRoom.TableConfig.ThreeMaxNum <= r.GameRoom.TableConfig.ThreeMinNum { |
|||
r.MaxCount = int(r.GameRoom.TableConfig.ThreeMinNum) |
|||
} else { |
|||
r.MaxCount = int(rand.Int63n(r.GameRoom.TableConfig.ThreeMaxNum-r.GameRoom.TableConfig.ThreeMinNum+1) + r.GameRoom.TableConfig.ThreeMinNum) |
|||
} |
|||
case 4: |
|||
r.MaxCount = 0 |
|||
if r.GameRoom.TableConfig.FourMaxNum <= r.GameRoom.TableConfig.FourMinNum { |
|||
r.MaxCount = int(r.GameRoom.TableConfig.FourMinNum) |
|||
} else { |
|||
r.MaxCount = int(rand.Int63n(r.GameRoom.TableConfig.FourMaxNum-r.GameRoom.TableConfig.FourMinNum+1) + r.GameRoom.TableConfig.FourMinNum) |
|||
} |
|||
case 5: |
|||
r.MaxCount = 0 |
|||
if r.GameRoom.TableConfig.FiveMaxNum <= r.GameRoom.TableConfig.FiveMinNum { |
|||
r.MaxCount = int(r.GameRoom.TableConfig.FiveMinNum) |
|||
} else { |
|||
r.MaxCount = int(rand.Int63n(r.GameRoom.TableConfig.FiveMaxNum-r.GameRoom.TableConfig.FiveMinNum+1) + r.GameRoom.TableConfig.FiveMinNum) |
|||
} |
|||
} |
|||
|
|||
r.FlushCountTimer = milliseconds + r.GameRoom.TableConfig.CheckFrequency*1000 |
|||
log.Debug("从后台配置 最大机器人数 ", r.MaxCount, " 刷新时间 ", r.GameRoom.TableConfig.CheckFrequency) |
|||
} |
|||
} else { |
|||
if milliseconds >= r.FlushCountTimer { |
|||
var TempCountMax [][]int |
|||
switch r.GameRoom.GetRoomRealPlayerCount() { |
|||
case 0: |
|||
TempCountMax = r.GameRoom.BloodCtrl.AndroidOprateConfig.CountMax0 |
|||
case 1: |
|||
TempCountMax = r.GameRoom.BloodCtrl.AndroidOprateConfig.CountMax1 |
|||
case 2: |
|||
TempCountMax = r.GameRoom.BloodCtrl.AndroidOprateConfig.CountMax2 |
|||
case 3: |
|||
TempCountMax = r.GameRoom.BloodCtrl.AndroidOprateConfig.CountMax3 |
|||
case 4: |
|||
TempCountMax = r.GameRoom.BloodCtrl.AndroidOprateConfig.CountMax4 |
|||
case 5: |
|||
TempCountMax = r.GameRoom.BloodCtrl.AndroidOprateConfig.CountMax5 |
|||
} |
|||
ProMax := 0 |
|||
for _, tempCount := range TempCountMax { |
|||
ProMax += tempCount[1] |
|||
} |
|||
ProNow := 0 |
|||
if ProMax != 0 { |
|||
ProNow = rand.Intn(ProMax) |
|||
} |
|||
r.MaxCount = 0 |
|||
for _, tempCount := range TempCountMax { |
|||
if ProNow < tempCount[1] { |
|||
r.MaxCount = tempCount[0] |
|||
break |
|||
} else { |
|||
ProNow -= tempCount[1] |
|||
} |
|||
} |
|||
|
|||
r.FlushCountTimer = milliseconds + int64(r.GameRoom.BloodCtrl.AndroidOprateConfig.FlushHZ*1000) |
|||
} |
|||
} |
|||
|
|||
for Index, player := range r.PlayerMaps { |
|||
r.Lock.Lock() |
|||
func() { |
|||
defer r.Lock.Unlock() |
|||
}() |
|||
if _, exists := r.RobotTimer[Index]; !exists { |
|||
log.Debug("机器人 ", player.Uid, " RobotTimer状态不存在 ", r.PlayerMaps, r.playerStat, r.RobotTimer) |
|||
} else { |
|||
if _, exists2 := r.playerStat[Index]; !exists2 { |
|||
log.Debug("机器人 ", player.Uid, " 状态不存在 ", r.PlayerMaps, r.playerStat, r.RobotTimer) |
|||
} else { |
|||
if r.playerStat[Index] != 0 && milliseconds >= r.RobotTimer[Index] { |
|||
// 可以下注并且到了下注时间
|
|||
if r.GameRoom.CurrBanker == player.ChairId { |
|||
//log.Debug("机器人 ", player.Uid, " 坐庄的的机器人 不能下注")
|
|||
continue |
|||
} |
|||
|
|||
if !player.CanBet { |
|||
//log.Debug("机器人 ", player.Uid, " 第一轮不能下注")
|
|||
continue |
|||
} |
|||
|
|||
if r.playerBetCtrl[Index].BetAmount < 0 { |
|||
log.Debug("机器人 ", player.Uid, " 没有可下注额度了") |
|||
continue |
|||
} |
|||
|
|||
// 随机下注金额
|
|||
req := &protocol.BetReq{ |
|||
BetAmount: r.playerBetCtrl[Index].BetAmount, |
|||
} |
|||
r.GameRoom.OnUserBet(player.Uid, req, false) |
|||
|
|||
// 下次操作时间
|
|||
r.RobotTimer[Index] = milliseconds + 60*1000 |
|||
} |
|||
} |
|||
} |
|||
} |
|||
} |
@ -0,0 +1,214 @@ |
|||
package game |
|||
|
|||
import ( |
|||
"base/log" |
|||
"math/rand" |
|||
"strconv" |
|||
"xgame/game/TTZ/app/core/protocol" |
|||
"xgame/game/TTZ/app/core/types" |
|||
"xgame/game/TTZ/app/route" |
|||
) |
|||
|
|||
func (rr *Room) OnGameSelectBanker() { // 定庄
|
|||
NotifyCurrentBanker := &protocol.NotifyCurrentBanker{} |
|||
//log.Debug(" 桌子号", rr.RId, "定庄 庄家列表 :", rr.GetBankerList)
|
|||
|
|||
// 抢庄时候重置一下所有可下注的状态
|
|||
for index, TempPlayer := range rr.PlayerMap { |
|||
rr.PlayerMap[index].CanBet = true |
|||
|
|||
NoHave := true |
|||
for _, i2 := range rr.GetBankerList { |
|||
if i2 == TempPlayer.ChairId { |
|||
NoHave = false |
|||
break |
|||
} |
|||
} |
|||
|
|||
if NoHave { |
|||
for _, i2 := range rr.NoGetBankerList { |
|||
if i2 == TempPlayer.ChairId { |
|||
NoHave = false |
|||
break |
|||
} |
|||
} |
|||
|
|||
if NoHave { |
|||
rr.GetBankerList = append(rr.GetBankerList, TempPlayer.ChairId) |
|||
} |
|||
} |
|||
} |
|||
//log.Debug(" 桌子号", rr.RId, "定庄 庄家列表 2 :", rr.GetBankerList)
|
|||
|
|||
if len(rr.GetBankerList) == 0 { |
|||
NotifyCurrentBanker.Reason = 1 |
|||
for _, player := range rr.PlayerMap { |
|||
rr.GetBankerList = append(rr.GetBankerList, player.ChairId) |
|||
} |
|||
NotifyCurrentBanker.ChairID = rr.GetBankerList[rand.Intn(len(rr.GetBankerList))] |
|||
rr.CurrBanker = NotifyCurrentBanker.ChairID |
|||
rr.GetBankerList = rr.GetBankerList[:0] |
|||
rr.NoGetBankerList = rr.NoGetBankerList[:0] |
|||
} else { |
|||
NotifyCurrentBanker.Reason = 0 |
|||
NotifyCurrentBanker.ChairID = rr.GetBankerList[rand.Intn(len(rr.GetBankerList))] |
|||
|
|||
CurrentGears := 0 |
|||
TempRoomGears, err := strconv.Atoi(rr.BoolePool.RoomGears) |
|||
if err == nil { |
|||
CurrentGears = TempRoomGears |
|||
//log.Debug(" 桌子号", rr.RId, "房间当前血池档位1 :", TempRoomGears, " CurrentGears :", CurrentGears)
|
|||
} |
|||
|
|||
CurrentGearConfig := rr.BloodCtrl.GearConfig[0] |
|||
for _, GearConfig := range rr.BloodCtrl.GearConfig { |
|||
if GearConfig.GearID == CurrentGears { |
|||
CurrentGearConfig = GearConfig |
|||
break |
|||
} |
|||
} |
|||
|
|||
// 判断是不是优先机器人
|
|||
if rand.Intn(10000) < CurrentGearConfig.GetBankerPro { |
|||
for _, GetBankerList := range rr.GetBankerList { |
|||
if rr.PlayerMap[GetBankerList].IsRobot { |
|||
log.Debug(" 桌子号", rr.RId, "必须机器人当庄 档位:", TempRoomGears, " 上庄列表 :", GetBankerList) |
|||
NotifyCurrentBanker.ChairID = GetBankerList |
|||
break |
|||
} |
|||
} |
|||
} |
|||
|
|||
rr.CurrBanker = NotifyCurrentBanker.ChairID |
|||
rr.GetBankerList = rr.GetBankerList[:0] |
|||
rr.NoGetBankerList = rr.NoGetBankerList[:0] |
|||
} |
|||
|
|||
// TODO 这里从哪儿获取
|
|||
rr.GuoScore = 100000 |
|||
|
|||
rr.SendAllMessage(route.NotifyCurrentBanker, NotifyCurrentBanker) |
|||
|
|||
log.Debug(" 桌子号", rr.RId, "确定庄家 :", rr.CurrBanker) |
|||
|
|||
// 庄家不能下注
|
|||
rr.PlayerMap[rr.CurrBanker].CanBet = false |
|||
|
|||
} |
|||
|
|||
func (rr *Room) OnGameBeginUser() { // 开始发牌玩家
|
|||
// 计算出扑克
|
|||
rr.OnBuildOtherResultPoker() |
|||
|
|||
var AllUser []int32 |
|||
for _, player := range rr.PlayerMap { |
|||
if player.CanBet || player.ChairId == rr.CurrBanker { |
|||
AllUser = append(AllUser, player.ChairId) |
|||
} |
|||
} |
|||
|
|||
CurrentChairID := rr.GetBankerList[rand.Intn(len(rr.GetBankerList))] |
|||
rr.CurrBeginUser = CurrentChairID |
|||
|
|||
//计算锅导致的最大下注
|
|||
bHaveBB := false |
|||
MaxBet := int64(0) |
|||
for _, poker := range rr.DropCardList { |
|||
if poker == 10 { |
|||
bHaveBB = true |
|||
break |
|||
} |
|||
} |
|||
|
|||
if bHaveBB { |
|||
MaxBet = rr.GuoScore / 3 |
|||
MaxBet = MaxBet / rr.Opt.MinBetAsset |
|||
MaxBet = MaxBet * rr.Opt.MinBetAsset |
|||
} else { |
|||
MaxBet = rr.GuoScore / 4 |
|||
MaxBet = MaxBet / rr.Opt.MinBetAsset |
|||
MaxBet = MaxBet * rr.Opt.MinBetAsset |
|||
} |
|||
|
|||
for _, pPlayer := range rr.PlayerMap { |
|||
if pPlayer != nil { |
|||
NewMaxBet := int64(0) |
|||
|
|||
if bHaveBB { |
|||
NewMaxBet = pPlayer.Gold.IntPart() / 3 |
|||
NewMaxBet = NewMaxBet / rr.Opt.MinBetAsset |
|||
NewMaxBet = NewMaxBet * rr.Opt.MinBetAsset |
|||
} else { |
|||
NewMaxBet = pPlayer.Gold.IntPart() / 4 |
|||
NewMaxBet = NewMaxBet / rr.Opt.MinBetAsset |
|||
NewMaxBet = NewMaxBet * rr.Opt.MinBetAsset |
|||
} |
|||
|
|||
if NewMaxBet > MaxBet { |
|||
NewMaxBet = MaxBet |
|||
} |
|||
|
|||
NotifyCurrentBeginUser := protocol.NotifyCurrentBeginUser{ |
|||
ChairID: rr.CurrBeginUser, |
|||
MinBet: rr.Opt.MinBetAsset, |
|||
MaxBet: NewMaxBet, |
|||
} |
|||
|
|||
for _, poker := range pPlayer.HandPoker { |
|||
NotifyCurrentBeginUser.HandPoker = append(NotifyCurrentBeginUser.HandPoker, int32(poker)) |
|||
} |
|||
|
|||
NotifyCurrentBeginUser.PokerType, NotifyCurrentBeginUser.Point = pPlayer.HandPoker.GetCardType() |
|||
|
|||
rr.Send(pPlayer, route.NotifyCurrentBeginUser, NotifyCurrentBeginUser) |
|||
} |
|||
} |
|||
|
|||
// 计算骰子需要多少
|
|||
var TzIDList []types.Poker |
|||
var UserList []int32 |
|||
CurrentTzID := int32(1) |
|||
for i := rr.CurrBanker; i < rr.CurrBanker+MAX_USER_NUM; i++ { |
|||
TempChairID := i |
|||
if TempChairID >= MAX_USER_NUM { |
|||
TempChairID -= MAX_USER_NUM |
|||
} |
|||
|
|||
if _, exist := rr.PlayerMap[TempChairID]; exist { |
|||
UserList = append(UserList, TempChairID) |
|||
} |
|||
} |
|||
UserList = append(UserList, UserList...) |
|||
|
|||
for index, chairID := range UserList { |
|||
if index == 0 { |
|||
continue |
|||
} |
|||
|
|||
if chairID == rr.CurrBeginUser { |
|||
if index < 7 { |
|||
TzIDList = append(TzIDList, types.Poker(index)) |
|||
} else { |
|||
break |
|||
} |
|||
} |
|||
} |
|||
|
|||
rr.shuffleDeck(&TzIDList) |
|||
|
|||
if len(TzIDList) > 0 { |
|||
CurrentTzID = int32(TzIDList[0]) |
|||
} |
|||
|
|||
for _, pPlayer := range rr.PlayerWatchMap { |
|||
if pPlayer != nil { |
|||
rr.Send(pPlayer, route.NotifyCurrentBeginUser, protocol.NotifyCurrentBeginUser{ |
|||
ChairID: rr.CurrBeginUser, |
|||
TzID: CurrentTzID, |
|||
}) |
|||
} |
|||
} |
|||
|
|||
log.Debug(" 桌子号", rr.RId, "开始发牌玩家 :", rr.CurrBeginUser) |
|||
|
|||
} |
@ -0,0 +1,44 @@ |
|||
package game |
|||
|
|||
import ( |
|||
"base/cluster/node" |
|||
"base/log" |
|||
"context" |
|||
"xgame/internal/service/basic" |
|||
pb2 "xgame/internal/service/basic/pb" |
|||
gameservice "xgame/internal/service/game" |
|||
gamepb "xgame/internal/service/game/pb" |
|||
) |
|||
|
|||
// GetSrcRoomByCtx 获取原始房间 通过ctx
|
|||
func (rr *Room) GetSrcRoomByCtx(Proxy *node.Proxy, gameID, agentID, srcRoomId int32) *gamepb.FetchRoomsReply { |
|||
client, err := gameservice.NewClient(Proxy.NewServiceClient) |
|||
if err != nil { |
|||
return nil |
|||
} |
|||
|
|||
reply, err := client.FetchRoomByID(context.Background(), &gamepb.FetchRoomByIdArgs{ |
|||
GameID: gameID, |
|||
AgentID: agentID, |
|||
RoomID: srcRoomId, |
|||
}) |
|||
|
|||
return reply |
|||
} |
|||
|
|||
// GetUserGameControl 获取用户游戏控制 通过Ctx上下文
|
|||
func (rr *Room) GetUserGameControl(Proxy *node.Proxy, uId, gameId, roomId int64) *pb2.GetUserGameControlInfoReply { |
|||
client, err := basic.NewClient(Proxy.NewServiceClient) |
|||
if err != nil { |
|||
log.Debug("error .获取用户游戏控制=>", err) |
|||
return nil |
|||
} |
|||
|
|||
userControl, err := client.GetUserGameControlInfo(context.Background(), &pb2.GetUserGameControlInfoArgs{ |
|||
UID: uId, |
|||
GameId: gameId, |
|||
RoomId: roomId, |
|||
}) |
|||
|
|||
return userControl |
|||
} |
@ -0,0 +1,62 @@ |
|||
package game |
|||
|
|||
import ( |
|||
"base/log" |
|||
"github.com/shopspring/decimal" |
|||
assetservice "xgame/internal/service/asset" |
|||
assetspb "xgame/internal/service/asset/pb" |
|||
) |
|||
|
|||
func (rr *Room) OnUpdateGold(userId int64) { // 更新用户的钱
|
|||
rr.roomRWLock.Lock() |
|||
defer rr.roomRWLock.Unlock() |
|||
|
|||
for i, player := range rr.PlayerMap { |
|||
if player.Uid == userId { |
|||
|
|||
client2, err := assetservice.NewClient(player.Ctx.Proxy.NewServiceClient) |
|||
if err != nil { |
|||
log.Errorf("assetservice NewClient failed: %v", err) |
|||
return |
|||
} |
|||
|
|||
reply3, err := client2.GetAsset(player.Ctx.Context(), &assetspb.GetAssetArgs{ |
|||
UID: player.Uid, |
|||
}) |
|||
|
|||
if err != nil { |
|||
return |
|||
} |
|||
|
|||
rr.PlayerMap[i].Gold = decimal.NewFromFloat(float64(reply3.Gold)) |
|||
|
|||
log.Debug("更新玩家 ", player.Uid, " 名字:", player.Nickname, " 金币:", rr.PlayerMap[i].Gold) |
|||
break |
|||
} |
|||
} |
|||
|
|||
for i, player := range rr.PlayerWatchMap { |
|||
if player.Uid == userId { |
|||
|
|||
client2, err := assetservice.NewClient(player.Ctx.Proxy.NewServiceClient) |
|||
if err != nil { |
|||
log.Errorf("assetservice NewClient failed: %v", err) |
|||
return |
|||
} |
|||
|
|||
reply3, err := client2.GetAsset(player.Ctx.Context(), &assetspb.GetAssetArgs{ |
|||
UID: player.Uid, |
|||
}) |
|||
|
|||
if err != nil { |
|||
return |
|||
} |
|||
|
|||
rr.PlayerWatchMap[i].Gold = decimal.NewFromFloat(float64(reply3.Gold)) |
|||
|
|||
log.Debug("更新玩家 ", player.Uid, " 名字:", player.Nickname, " 金币:", rr.PlayerWatchMap[i].Gold) |
|||
break |
|||
} |
|||
} |
|||
|
|||
} |
@ -0,0 +1,111 @@ |
|||
package game |
|||
|
|||
import ( |
|||
"base/log" |
|||
"time" |
|||
"xgame/game/TTZ/app/core/protocol" |
|||
"xgame/game/TTZ/app/route" |
|||
) |
|||
|
|||
func (rr *Room) OnUserWatchToDown(uid int64, msg interface{}) { // 主动观战转坐下
|
|||
message := msg.(*protocol.WatchToDownReq) |
|||
WatchToDownRes := &protocol.WatchToDownRes{} |
|||
|
|||
//判断用户是否在观战
|
|||
var WToDUser *Player |
|||
for _, TempWatchPlayer := range rr.PlayerWatchMap { |
|||
if TempWatchPlayer.Uid == uid { |
|||
WToDUser = TempWatchPlayer |
|||
} |
|||
} |
|||
|
|||
if WToDUser == nil { |
|||
log.Debug("玩家", uid, "不在观战席") |
|||
return |
|||
} |
|||
|
|||
////判断座位是否合法
|
|||
//if message.ChairID < 0 || message.ChairID >= MAX_USER_NUM {
|
|||
// log.Debug("玩家", uid, "要坐的座位 ", message.ChairID, " 不存在 ")
|
|||
// WatchToDownRes.Code = protocol.ErrorWatchToDownNoExist
|
|||
// WatchToDownRes.CodeMsg = "要坐的座位不存在"
|
|||
// rr.Send(WToDUser, route.WatchToDownRes, WatchToDownRes)
|
|||
//}
|
|||
//
|
|||
////判断座位是否空着
|
|||
//if TempPlayer, exist := rr.PlayerMap[message.ChairID]; !exist {
|
|||
// log.Debug("玩家", uid, "座位 ", message.ChairID, " 不空 ", " 上面坐着:", TempPlayer.Uid)
|
|||
// WatchToDownRes.Code = protocol.ErrorWatchToDownPlayerExist
|
|||
// WatchToDownRes.CodeMsg = "座位不空 不能坐下"
|
|||
// rr.Send(WToDUser, route.WatchToDownRes, WatchToDownRes)
|
|||
//}
|
|||
|
|||
//临时修改为找一个空位
|
|||
TempChairId := rr.MakeChairId() |
|||
if TempChairId == -1 { |
|||
log.Debug("没有空座位") |
|||
WatchToDownRes.Code = protocol.ErrorWatchToDownPlayerExist |
|||
WatchToDownRes.CodeMsg = "没有空座位" |
|||
rr.Send(WToDUser, route.WatchToDownRes, WatchToDownRes) |
|||
return |
|||
} else { |
|||
message.ChairID = TempChairId |
|||
} |
|||
|
|||
for TempIndex, TempWatchPlayer := range rr.PlayerWatchMap { |
|||
if TempWatchPlayer.Uid == uid { |
|||
//判断钱是否够
|
|||
if TempWatchPlayer.Gold.IntPart() <= rr.MinGameScore { |
|||
log.Debug("玩家", uid, "钱不够 不能坐下 ", TempWatchPlayer.Gold.IntPart(), " 需要的钱:", rr.MinGameScore) |
|||
WatchToDownRes.Code = protocol.ErrorWatchToDownGoldLess |
|||
WatchToDownRes.CodeMsg = "钱不够 不能坐下" |
|||
rr.Send(TempWatchPlayer, route.WatchToDownRes, WatchToDownRes) |
|||
break |
|||
} |
|||
|
|||
WatchUser := rr.PlayerWatchMap[TempIndex] |
|||
WatchUser.ChairId = message.ChairID |
|||
rr.SendAllMessage(route.NotifyWatchToDown, &protocol.NotifyWatchToDown{ |
|||
Uid: WatchUser.Uid, |
|||
ChairID: message.ChairID, |
|||
}) |
|||
|
|||
// 通知大厅有人坐下
|
|||
NotifySitDown := &protocol.NotifyDTSitDown{ |
|||
Uid: WatchUser.Uid, |
|||
RoomID: rr.RoomID, |
|||
TableID: rr.RId, |
|||
ChairID: message.ChairID, |
|||
Avatar: WatchUser.Avatar, |
|||
State: rr.CurrentGameState, |
|||
} |
|||
rr.NotifyFunc(route.NotifyDTSitDown, NotifySitDown) |
|||
|
|||
rr.PlayerMap[WatchUser.ChairId] = WatchUser |
|||
|
|||
if TempIndex == len(rr.PlayerWatchMap)-1 { |
|||
rr.PlayerWatchMap = rr.PlayerWatchMap[:TempIndex] |
|||
} else { |
|||
rr.PlayerWatchMap = append(rr.PlayerWatchMap[:TempIndex], rr.PlayerWatchMap[TempIndex+1:]...) |
|||
} |
|||
|
|||
break |
|||
} |
|||
} |
|||
|
|||
//判断开场
|
|||
if rr.CurrentGameState < protocol.STATE_GET_BANKER && rr.GetRoomPlayerCount() > 1 { |
|||
rr.State = EN_TABLE_STATE_PLAYING |
|||
milliseconds := time.Now().UnixMilli() |
|||
rr.CurrentGameState = protocol.STATE_GET_BANKER |
|||
rr.CurrentOperationTimer = milliseconds + rr.TimeOutGetBanker |
|||
rr.RepeatRoomUser() |
|||
|
|||
rr.SendAllMessage(route.NotifyStateTime, &protocol.NotifyStateTime{ |
|||
NextState: protocol.STATE_GET_BANKER, |
|||
NextTimestamp: rr.CurrentOperationTimer, |
|||
}) |
|||
// 抢庄做了加一秒的容错判断
|
|||
rr.CurrentOperationTimer += 1000 |
|||
} |
|||
} |
@ -0,0 +1,227 @@ |
|||
package protocol |
|||
|
|||
type JoinRoomReq struct { // 加入房间的请求
|
|||
RoomID int32 `json:"roomID"` // 房间ID 0初级场 1中级场 2高级场
|
|||
TableID int64 `json:"tableID"` // 桌子ID 快速加入时桌子ID用0 创建桌子用1 不然用TableInfo里的TableID
|
|||
GameID int32 `json:"gameID"` // 游戏ID
|
|||
AgentID int32 `json:"agentID"` // 代理ID
|
|||
IsWatching int32 `json:"isWatching"` // 是否观战身份加入游戏
|
|||
} |
|||
|
|||
type AllTableReq struct { // 获取所有桌子
|
|||
RoomID int32 `json:"roomID"` // 房间ID 0初级场 1中级场 2高级场
|
|||
GameID int32 `json:"gameID"` // 游戏ID
|
|||
AgentID int32 `json:"agentID"` // 代理ID
|
|||
} |
|||
|
|||
type SitDownRes struct { //玩家坐下返回
|
|||
Code int32 `json:"code"` //错误码
|
|||
CodeMsg string `json:"codeMsg"` //错误内容
|
|||
PlayerInfo *RoomPlayer `json:"playerList"` //用户信息
|
|||
} |
|||
|
|||
type AllTableRes struct { //所有桌子的信息返回
|
|||
Code int32 `json:"code"` //错误码
|
|||
CodeMsg string `json:"codeMsg"` //错误内容
|
|||
TableInfo []TableInfo `json:"tableInfo"` //桌子信息
|
|||
} |
|||
|
|||
type NoticeSitDown struct { //通知玩家坐下
|
|||
PlayerInfo *RoomPlayer `json:"playerList"` //用户信息
|
|||
} |
|||
|
|||
type NotifyDTSitDown struct { //通知大厅玩家坐下
|
|||
Uid int64 `json:"uid"` // userId
|
|||
RoomID int32 `json:"roomID"` // 房间ID 0初级场 1中级场 2高级场
|
|||
TableID int64 `json:"tableID"` // 桌子ID 快速加入时桌子ID用0 不然用TableInfo里的TableID
|
|||
ChairID int32 `json:"chairId"` // 座位号
|
|||
Avatar string `json:"avatar"` // 玩家头像
|
|||
State int32 `json:"state"` // 房间状态
|
|||
} |
|||
|
|||
type RoomInfoRes struct { |
|||
RoomId int32 `json:"roomId"` //房间ID
|
|||
RoomConfig *TableConfig `json:"roomConfig,omitempty"` //房间配置
|
|||
ServerLocation float64 `json:"serverLocation"` //同步服务器时区
|
|||
ServerTimestamp int64 `json:"serverTimestamp"` //同步服务器时间戳
|
|||
SingleMaxBet int64 `json:"singleMaxBet"` //单人最大下注额度
|
|||
PlayerList []*RoomPlayer `json:"playerList,omitempty"` //用户列表
|
|||
PlayerWatchMap []*RoomPlayer `json:"playerWatchMap,omitempty"` //观战用户列表
|
|||
RoomStatus int32 `json:"roomStatus"` //房间的状态
|
|||
StatusChangeTimestamp int64 `json:"statusChangeTimestamp"` //下一次变更状态的时间戳
|
|||
Record []HistoryRecord `json:"record,omitempty"` //历史记录
|
|||
} |
|||
|
|||
// ResumeGameNotice 通知恢复游戏
|
|||
type ResumeGameNotice struct { |
|||
RoomId int32 `json:"roomId"` //房间ID
|
|||
GameId int32 `json:"gameId"` //游戏ID
|
|||
} |
|||
|
|||
type BetReq struct { //下注请求
|
|||
BetAmount int64 `json:"betAmount,omitempty"` //下注
|
|||
} |
|||
|
|||
type BetRes struct { //下注返回
|
|||
Code int32 `json:"code"` //错误码
|
|||
CodeMsg string `json:"codeMsg"` //错误内容
|
|||
ChairID int32 `json:"chairId"` //座位ID
|
|||
TableTotalWin int64 `json:"tableTotalWin"` //在桌子上的总输赢
|
|||
UserScore int64 `json:"userScore"` //用户剩余分数
|
|||
} |
|||
|
|||
type NotifyBet struct { //通知下注
|
|||
ChairID int32 `json:"chairId"` //座位ID
|
|||
TableTotalWin int64 `json:"tableTotalWin"` //在桌子上的总输赢
|
|||
} |
|||
|
|||
type LeaveTable struct { //退出桌子请求
|
|||
} |
|||
|
|||
type LeaveTableRes struct { // 退出桌子返回
|
|||
Code int32 `json:"code"` //错误码
|
|||
CodeMsg string `json:"codeMsg"` //错误内容
|
|||
} |
|||
|
|||
type GetBankerReq struct { //抢庄请求
|
|||
State int32 `json:"state"` //0 抢庄 1 不抢
|
|||
} |
|||
|
|||
type GetBankerRes struct { // 抢庄返回
|
|||
Code int32 `json:"code"` //错误码
|
|||
CodeMsg string `json:"codeMsg"` //错误内容
|
|||
} |
|||
|
|||
type WatchToDownReq struct { //主动观战转坐下请求
|
|||
ChairID int32 `json:"chairId"` //座位ID
|
|||
} |
|||
|
|||
type WatchToDownRes struct { //主动观战转坐下返回
|
|||
Code int32 `json:"code"` //错误码
|
|||
CodeMsg string `json:"codeMsg"` //错误内容
|
|||
} |
|||
|
|||
type NotifyBanker struct { // 通知抢庄
|
|||
ChairID int32 `json:"chairId"` //座位ID
|
|||
State int32 `json:"state"` //0 抢庄 1 不抢
|
|||
} |
|||
|
|||
type NotifyCurrentBanker struct { // 通知庄家
|
|||
ChairID int32 `json:"chairId"` //座位ID
|
|||
Reason int32 `json:"reason"` //定庄原因 0 正常随机 1 所有人未抢庄所有人随机
|
|||
} |
|||
|
|||
type NotifyCurrentBeginUser struct { // 通知开始玩家
|
|||
ChairID int32 `json:"chairId"` // 开始玩家的座位ID
|
|||
TzID int32 `json:"tzID"` // 骰子大小
|
|||
MinBet int64 `json:"minBet"` // 最低下注
|
|||
MaxBet int64 `json:"maxBet"` // 最高下注
|
|||
HandPoker []int32 `json:"handPoker,omitempty"` // 用户当前手牌
|
|||
PokerType byte `json:"pokerType" ` // 牌类型
|
|||
Point int `json:"point"` // 点数
|
|||
} |
|||
|
|||
type NotifyLeaveRoomRes struct { // 通知退出桌子
|
|||
Uid int64 `json:"uid"` // userId
|
|||
ChairID int32 `json:"chairId"` // 座位号
|
|||
LeaveReason int32 `json:"leaveReason"` // 离开原因 0主动离开 1踢出房间
|
|||
} |
|||
|
|||
type NotifyStateTime struct { // 通知阶段倒计时
|
|||
NextState int32 `json:"nextState"` // 下阶段类型
|
|||
NextTimestamp int64 `json:"nextTimestamp"` // 下阶段开始时间戳
|
|||
} |
|||
|
|||
type NotifyPoker struct { // 通知翻牌
|
|||
PokerArea int32 `json:"pokerArea"` // 扑克区域 0 中间区域 1 A区域 2 B区域
|
|||
Poker int32 `json:"poker"` // 扑克
|
|||
} |
|||
|
|||
type NotifyGameConclude struct { // 通知游戏结束结算
|
|||
PlayList []*RoomPlayer `json:"playList,omitempty"` //用户列表更新
|
|||
Record []HistoryRecord `json:"record,omitempty"` //历史记录
|
|||
} |
|||
|
|||
type NotifyDownToWatch struct { // 通知玩家坐下转观战
|
|||
ChairID int32 `json:"chairId"` // 座位号
|
|||
} |
|||
|
|||
type NotifyWatchToDown struct { // 通知玩家观战转坐下
|
|||
Uid int64 `json:"uid"` // userId
|
|||
ChairID int32 `json:"chairId"` // 座位号
|
|||
} |
|||
|
|||
type NotifyRoomDestroy struct { // 通知房间销毁
|
|||
RoomID int32 `json:"roomID"` // 房间ID 0初级场 1中级场 2高级场
|
|||
TableID int64 `json:"tableID"` // 桌子ID
|
|||
} |
|||
|
|||
type Marquee struct { |
|||
Enable bool `json:"enable"` // 是否启用
|
|||
MinWinMultiple float64 `json:"minWinMultiple"` // 最低赢钱倍数
|
|||
MinWinAsset int64 `json:"minWinAsset"` // 最低赢钱数额
|
|||
} |
|||
|
|||
type Jackpot struct { |
|||
Enable bool `json:"enable"` // 是否启用
|
|||
MinWinMultiple float64 `json:"minWinMultiple"` // 最低赢钱倍数
|
|||
MinWinAsset int64 `json:"minWinAsset"` // 最低赢钱数额
|
|||
} |
|||
|
|||
type Control struct { |
|||
Enable bool `json:"enable"` // 是否启用
|
|||
Stock int64 `json:"stock"` // 库存值
|
|||
Lines []*ControlLine `json:"lines"` // 控制线
|
|||
} |
|||
|
|||
type ControlLine struct { |
|||
MaxRate float64 `json:"maxRate"` // 最大库存率
|
|||
MaxMultiple float64 `json:"maxMultiple"` // 最大限制倍数
|
|||
LoseProbability float64 `json:"loseProbability"` // 输的概率
|
|||
} |
|||
|
|||
type Options struct { |
|||
ID int `json:"id"` // 房间ID
|
|||
Name string `json:"name"` // 房间名称
|
|||
IsAllowWatch bool `json:"isAllowWatch"` // 是否允许观战
|
|||
TaxRate float64 `json:"taxRate"` // 房间税率
|
|||
AssetKind int `json:"assetKind"` // 使用的资产类型(1:金币 2:钻石)
|
|||
MinEnterAsset int64 `json:"minEnterAsset"` // 最小进入限制
|
|||
MaxEnterAsset int64 `json:"maxEnterAsset"` // 最大进入限制
|
|||
MinBetAsset int64 `json:"minBetAsset"` // 最小押注限制
|
|||
MaxBetAsset int64 `json:"maxBetAsset"` // 最大押注限制
|
|||
MinBetMultiple float64 `json:"minBetMultiple"` // 最小押注倍率
|
|||
MaxBetMultiple float64 `json:"maxBetMultiple"` // 最大押注倍率
|
|||
BetAssetOptions []int64 `json:"betAssetOptions"` // 押注资产选项
|
|||
BetMultipleOptions []float64 `json:"betMultipleOptions"` // 押注的倍率选项
|
|||
Rtp int `json:"rtp"` // 押注的倍率选项
|
|||
BootValue int64 `json:"bootValue"` // 下注金额
|
|||
RoomLimit int64 `json:"roomLimit"` // 房间进入条件
|
|||
PersonalRate int64 `json:"personalRate"` // 个人倍率
|
|||
RoomRate int64 `json:"roomRate"` // 房间倍率
|
|||
MaxRound int32 `json:"maxRound"` // 最大轮数
|
|||
AiRangeMin int64 `json:"aiRangeMin"` // AI随机范围下限
|
|||
AiRangeMax int64 `json:"aiRangeMax"` // AI随机范围上限
|
|||
AiVipRangeMin int64 `json:"aiVipRangeMin"` // AI VIP随机范围下限
|
|||
AiVipRangeMax int64 `json:"aiVipRangeMax"` // AI VIP随机范围上限
|
|||
Marquee *Marquee `json:"marquee"` // 跑马灯触发项
|
|||
Jackpot *Jackpot `json:"jackpot"` // 大奖信息触发项
|
|||
Control *Control `json:"control"` // 控制信息项
|
|||
Country string `json:"country"` // 国家
|
|||
BalanceLine int64 `json:"balanceLine"` // 平衡线
|
|||
DefaultBet int64 `json:"defaultBet"` // 默认下注
|
|||
RoundTime int64 `json:"roundTime"` // 每轮回合的轮次时间
|
|||
} |
|||
|
|||
type RecordInfoPlayer struct { // 存储的结构显示
|
|||
ChairID int32 `json:"chairId"` //座位ID
|
|||
UserNo string `json:"userNo"` //用户ID
|
|||
HandPoker []int32 `json:"handPoker,omitempty"` // 用户当前手牌
|
|||
PokerType byte `json:"pokerType" ` // 牌类型
|
|||
PokerPoint int `json:"pokerPoint" ` // 牌点数
|
|||
IsWin bool `json:"isWin"` |
|||
} |
|||
|
|||
type RecordInfo struct { // 存储的结构显示
|
|||
Player []RecordInfoPlayer `json:"player,omitempty"` // 单独用户信息
|
|||
} |
@ -0,0 +1,104 @@ |
|||
package protocol |
|||
|
|||
import "xgame/game/TTZ/app/core/types" |
|||
|
|||
const ( |
|||
ErrorCodeLessThanMinEnter = 20013001 //低于最小进入条件
|
|||
ErrorCodeGameNoStart = 20013002 //游戏未开启
|
|||
ErrorCodeUnknown = 20013003 //未知错误
|
|||
ErrorCodeNoBetState = 20013004 //非下注阶段
|
|||
ErrorCodeBetError = 20013005 //下注失败
|
|||
ErrorLongTimeKickUser = 20013006 //长时间未下注踢人 连续5局未下注
|
|||
ErrorGetBanker = 20013007 //抢庄失败
|
|||
ErrorWatchToDownGoldLess = 20013008 //观战转坐下 钱不够
|
|||
ErrorWatchToDownNoExist = 20013009 //观战转坐下 座位不存在
|
|||
ErrorWatchToDownPlayerExist = 20013010 //观战转坐下 座位已经有人
|
|||
ErrorLeaveTableBanker = 20013011 //庄家不能离开房间
|
|||
ErrorWatchToDownNotInWatch = 20013012 //观战转坐下 人不在观战席
|
|||
) |
|||
|
|||
const ( |
|||
Win = 1 //赢
|
|||
Lose = 2 //输
|
|||
He = 3 //和
|
|||
) |
|||
|
|||
const ( |
|||
PokerTypeBiShi = 1 // 闭十 相加为10 1倍
|
|||
PokerTypeBanQiDown = 2 // 7.5以下 1倍
|
|||
PokerTypeBanQiUp = 3 // 7.5以上 2倍
|
|||
PokerTypeDui = 4 // 对子 3倍
|
|||
PokerTypeEBG = 5 // 二八杠 3倍
|
|||
PokerTypeSB = 6 // 双百至尊 4倍
|
|||
) |
|||
|
|||
type RoomPlayer struct { //房间的用户信息
|
|||
Uid int64 `json:"uid"` // userId
|
|||
ChairID int32 `json:"chairId"` // 座位号
|
|||
IsBanker int32 `json:"isBanker"` // 0 非庄 1 庄
|
|||
State int32 `json:"state"` // 状态
|
|||
Avatar string `json:"avatar"` // 玩家头像
|
|||
Gold int64 `json:"gold"` // 玩家金币
|
|||
Nickname string `json:"nickname"` // 姓名
|
|||
Sex int32 `json:"sex"` // 性别
|
|||
Vip int32 `json:"vip"` // VIP
|
|||
Level int32 `json:"level"` // 等级
|
|||
Exp int32 `json:"exp"` // 经验
|
|||
EndScore int64 `json:"endScore"` // 本次结算分数 这个只有赢的值
|
|||
BetScore int64 `json:"betScore"` // 结算时的总下注
|
|||
WinLose int32 `json:"winLose"` // 本轮输赢 0 无效 1 赢 2 输 3 和
|
|||
CanBet bool `json:"canBet"` // 玩家是否需要等待下一局开始
|
|||
HandPoker []int32 `json:"handPoker,omitempty"` // 用户当前手牌
|
|||
PokerType byte `json:"pokerType" ` // 牌类型
|
|||
Point int `json:"point"` // 点数
|
|||
} |
|||
|
|||
type TablePlayer struct { //桌子的用户信息
|
|||
ChairID int32 `json:"chairId"` // 座位号
|
|||
Avatar string `json:"avatar"` // 玩家头像
|
|||
} |
|||
|
|||
type HistoryRecordSub struct { //历史记录信息
|
|||
ChairID []int32 `json:"chairId"` // 座位号
|
|||
Avatar []string `json:"avatar"` // 玩家头像
|
|||
HandPoker []types.PokerSlice `json:"handPoker"` // 手牌
|
|||
PokerType []int32 `json:"pokerType"` // 类型
|
|||
Point []int32 `json:"point"` // 点数
|
|||
} |
|||
|
|||
type HistoryRecord struct { //历史记录信息
|
|||
List []HistoryRecordSub `json:"list"` // 记录列表
|
|||
} |
|||
|
|||
const ( |
|||
AREA_INVALUE int32 = 0 |
|||
AREA_ANDAR int32 = 1 |
|||
AREA_BANHAR int32 = 2 |
|||
) |
|||
|
|||
const ( |
|||
STATE_INVALUE int32 = 0 // 无效阶段
|
|||
STATE_WAIT int32 = 1 // 等人阶段等不到就结束房间
|
|||
STATE_BEGIN int32 = 2 // 开始
|
|||
STATE_GET_BANKER int32 = 3 // 抢庄
|
|||
STATE_BB int32 = 4 // 抢庄动画过渡
|
|||
STATE_DT int32 = 5 // 丢骰子定谁开牌的动画时间
|
|||
STATE_BET int32 = 6 // 下注
|
|||
STATE_CP int32 = 7 // 搓牌
|
|||
STATE_RESULT int32 = 8 // 结算
|
|||
) |
|||
|
|||
type TableConfig struct { // 桌子配置
|
|||
AlwaysBet int64 `json:"alwaysBet"` // 房费
|
|||
RechargeLimit int64 `json:"rechargeLimit"` // 弹充值限制
|
|||
TaxMing float64 `json:"taxMing"` // 明税
|
|||
} |
|||
|
|||
type TableInfo struct { // 桌子信息
|
|||
RoomID int32 `json:"roomID"` // 房间ID 0初级场 1中级场 2高级场
|
|||
TableID int64 `json:"tableId"` // 桌子ID
|
|||
GameID int32 `json:"gameID"` // 游戏ID
|
|||
AgentID int32 `json:"agentID"` // 代理ID
|
|||
State int32 `json:"state"` // 房间状态
|
|||
TablePlayer []TablePlayer `json:"playerList"` // 桌子上的用户信息
|
|||
} |
@ -0,0 +1,48 @@ |
|||
package room |
|||
|
|||
import ( |
|||
"base/cluster/node" |
|||
"flag" |
|||
"golang.org/x/exp/rand" |
|||
"time" |
|||
"xgame/game/TTZ/app/core/game" |
|||
) |
|||
|
|||
type HomeBase interface { |
|||
OnInit() bool // 初始化房间
|
|||
OnPlayerReady(userId int64, p interface{}) // 准备
|
|||
OnReconnect(userId int64) // 断线重连
|
|||
OnDisconnect(userId int64) // 玩家离线
|
|||
JoinRoom(pPlayer *game.Player, isWatching int32) int32 // 加入房间
|
|||
LeaveRoom(uid int64) int32 // 离开房间
|
|||
GetRoomId() int64 // 获取房间Id
|
|||
GetRId() int64 // 获取房间RId
|
|||
GetState() int32 // 获取房间状态
|
|||
OnGetGameId() int32 // 游戏ID
|
|||
GetRoomState() int32 // 获取房间的状态
|
|||
GetRoomPlayerCount() int32 // 获取房间里的人数
|
|||
GetRoomPlayer(chairId int32) *game.Player // 通过椅子号获取玩家对象
|
|||
GetRoomPlayerByUid(uid int64) *game.Player // 通过uid获取玩家对象
|
|||
SetPlayerState(uid int64, state int32) bool // 设置玩家状态
|
|||
OnGetOutRoom(uid int64) bool // 退出房间
|
|||
IsCanDissolution() bool // 是否能解散房间
|
|||
UpdateCtx(uid int64, ctx *node.Context) // 无奈加的,更新node.Context
|
|||
UpdateUserOut(uid int64) // 更新用户退出状态
|
|||
OnUserBet(uid int64, msg interface{}, Auto bool) // 用户下注
|
|||
OnUserGetBanker(uid int64, msg interface{}) // 用户抢庄
|
|||
OnUserWatchToDown(uid int64, msg interface{}) // 用户观战转坐下
|
|||
OnResumeGameData(uid int64) //
|
|||
OnDestroy(uid int64) // 销毁房间
|
|||
OnGetRoomInfo(uid int64, ctx *node.Context) interface{} //
|
|||
IsJoinRoom() bool //
|
|||
OnUpdateGold(userId int64) // 更新用户的钱
|
|||
} |
|||
|
|||
var ( |
|||
GsId = flag.Int64("i", 1, "gs_id") |
|||
R *rand.Rand |
|||
) |
|||
|
|||
func init() { |
|||
R = rand.New(rand.NewSource(uint64(time.Now().UnixNano()))) |
|||
} |
@ -0,0 +1,362 @@ |
|||
package room |
|||
|
|||
import ( |
|||
"base/cluster/node" |
|||
"base/log" |
|||
"context" |
|||
"github.com/roylee0704/gron" |
|||
"math/rand" |
|||
"sort" |
|||
"strconv" |
|||
"sync" |
|||
"time" |
|||
conf "xgame/game/TTZ/app/config" |
|||
"xgame/game/TTZ/app/core/game" |
|||
"xgame/game/TTZ/app/core/protocol" |
|||
"xgame/game/TTZ/app/route" |
|||
"xgame/game/service/rpc_client" |
|||
gameservice "xgame/internal/service/game" |
|||
gamepb "xgame/internal/service/game/pb" |
|||
) |
|||
|
|||
const ( |
|||
RoomFree = 0 |
|||
RoomStared = 1 |
|||
RoomFull = 2 |
|||
) |
|||
|
|||
type Home struct { |
|||
GronTimer *gron.Cron |
|||
GameProxy *node.Proxy |
|||
BloodCtrl conf.BloodCtrl //血池控制
|
|||
NextCreateTable int64 //下个机器人创建房间的时间
|
|||
TableCount []int32 //各等级的房间个数
|
|||
TableNeedCount []int32 //各等级需要的房间个数
|
|||
Rhb map[int64]HomeBase |
|||
RhbEx map[int64]int64 |
|||
RhbRoom map[int64]*game.Room |
|||
EnterUser map[int64]*node.Context |
|||
NextId int64 |
|||
lock sync.Mutex |
|||
RoomsReply *gamepb.FetchRoomsReply |
|||
TableConfig []*gamepb.GameTableTotal |
|||
} |
|||
|
|||
var Gh *Home |
|||
|
|||
func Init(GameProxy *node.Proxy) { |
|||
Gh = &Home{ |
|||
Rhb: make(map[int64]HomeBase), |
|||
RhbEx: make(map[int64]int64), |
|||
RhbRoom: make(map[int64]*game.Room), |
|||
EnterUser: make(map[int64]*node.Context), |
|||
TableCount: []int32{0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, |
|||
TableNeedCount: []int32{0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, |
|||
} |
|||
|
|||
Gh.GameProxy = GameProxy |
|||
Gh.InitBloodControl() |
|||
Gh.InitBloodControlByBackend() |
|||
milliseconds := time.Now().UnixMilli() |
|||
Gh.NextCreateTable = milliseconds + 300 |
|||
|
|||
if Gh.GronTimer != nil { |
|||
Gh.GronTimer.Stop() |
|||
Gh.GronTimer = nil |
|||
} |
|||
|
|||
Gh.GronTimer = gron.New() |
|||
|
|||
Gh.GronTimer.AddFunc(gron.Every(time.Duration(50)*time.Millisecond), func() { |
|||
Gh.run() |
|||
}) |
|||
|
|||
Gh.GronTimer.Start() |
|||
} |
|||
|
|||
func (h *Home) InitBloodControl() { |
|||
h.BloodCtrl = conf.ReadBloodConfig() |
|||
|
|||
//log.Debug("roommgr InitBloodControl:", h.BloodCtrl)
|
|||
log.Debug("h.BloodCtrl.AndroidOprateConfig.CreateTableHZ = ", h.BloodCtrl.AndroidOprateConfig.CreateTableHZ) |
|||
|
|||
if h.BloodCtrl.AndroidOprateConfig.CreateTableHZ == 0 { |
|||
h.BloodCtrl.AndroidOprateConfig.CreateTableHZ = 30000 |
|||
} |
|||
} |
|||
|
|||
func (h *Home) InitBloodControlByBackend() { |
|||
// 按等级从后台获取到配置
|
|||
var replyOpt *gamepb.FetchGameTableTotalsReply |
|||
replyOpt = rpc_client.GetTableCtrlConfig(h.GameProxy, game.GAME_ID, "", 1) |
|||
h.TableConfig = replyOpt.List |
|||
if len(h.TableConfig) == 0 { |
|||
log.Error(game.GAME_ID, " 21点后台获取桌子配置 无配置") |
|||
} else { |
|||
log.Debug(" 21点获取后台桌子配置 ", h.TableConfig) |
|||
} |
|||
} |
|||
|
|||
func (h *Home) run() { |
|||
milliseconds := time.Now().UnixMilli() |
|||
|
|||
if milliseconds >= h.NextCreateTable { |
|||
for _, SingleTableConfig := range h.TableConfig { |
|||
tempRoomID, err := strconv.Atoi(SingleTableConfig.RoomId) |
|||
if err == nil { |
|||
if SingleTableConfig.TableMaxNum <= SingleTableConfig.TableMinNum { |
|||
h.TableNeedCount[tempRoomID] = int32(SingleTableConfig.TableMinNum) |
|||
} else { |
|||
h.TableNeedCount[tempRoomID] = int32(rand.Int63n(SingleTableConfig.TableMaxNum-SingleTableConfig.TableMinNum) + SingleTableConfig.TableMinNum) |
|||
} |
|||
} |
|||
log.Debug(" 场次 ", tempRoomID, " 个数 ", h.TableNeedCount[tempRoomID]) |
|||
} |
|||
|
|||
go func() { |
|||
for LevelID, NeedCount := range h.TableNeedCount { |
|||
for h.TableCount[LevelID] < NeedCount { |
|||
h.CreateRoom(0, int32(LevelID), game.GAME_ID, 0, h.GameProxy) |
|||
log.Debug("创建房间成功 当前等级 ", LevelID, " 个数 ", h.TableCount[LevelID]) |
|||
} |
|||
} |
|||
}() |
|||
|
|||
h.NextCreateTable = milliseconds + h.TableConfig[0].CheckFrequency*1000 |
|||
} |
|||
} |
|||
|
|||
func gen() (int64, int64, bool) { |
|||
Gh.NextId++ |
|||
try := 0 |
|||
for try < 30 { |
|||
id := int64(0) |
|||
r := R.Int63n(70000) + 10000 |
|||
first := r / 10000 |
|||
first ^= *GsId |
|||
id = r*10 + first |
|||
if _, ok := Gh.Rhb[id]; !ok { |
|||
return id, Gh.NextId, true |
|||
} |
|||
try++ |
|||
} |
|||
return 0, 0, false |
|||
} |
|||
|
|||
func (h *Home) CreateRoom(Uid int64, RoomID, GameID, AgentID int32, GameProxy *node.Proxy) HomeBase { |
|||
h.lock.Lock() |
|||
defer h.lock.Unlock() |
|||
|
|||
//创建新房间
|
|||
for { |
|||
rid, _, ret := gen() |
|||
if !ret { |
|||
continue |
|||
} |
|||
|
|||
r := game.New(Uid, rid, RoomID, GameID, AgentID, h.Destroy, h.QuitRoom, h.NotifyDTUser, GameProxy) |
|||
r.OnInit() |
|||
Gh.Rhb[rid] = r |
|||
Gh.RhbEx[Uid] = rid |
|||
Gh.RhbRoom[rid] = r |
|||
log.Debug("创建房间ok", rid, "所有房间==>", Gh.Rhb) |
|||
Gh.TableCount[RoomID]++ |
|||
|
|||
return r |
|||
} |
|||
|
|||
} |
|||
|
|||
func (h *Home) Send(msgId int32, message interface{}) { //发送给在桌子列表界面的玩家
|
|||
for TempUserID, UserCtx := range Gh.EnterUser { |
|||
if msgId > 0 { |
|||
UserCtx.Request.Message.Route = msgId |
|||
} |
|||
err := UserCtx.Response(message) |
|||
if err != nil { |
|||
log.Debug("response message failed: ", err, "uid====>", TempUserID) |
|||
} |
|||
} |
|||
} |
|||
|
|||
func (h *Home) CopyRoom(Uid int64, GameProxy *node.Proxy) HomeBase { |
|||
RoomID := Gh.GetRoomIdByUid(0) |
|||
GameRoom := Gh.GetGameRoomByRoomId(RoomID) |
|||
|
|||
h.lock.Lock() |
|||
defer h.lock.Unlock() |
|||
|
|||
//创建新房间
|
|||
for { |
|||
rid, _, ret := gen() |
|||
if !ret { |
|||
continue |
|||
} |
|||
|
|||
r := game.New(Uid, rid, GameRoom.RoomID, GameRoom.GameID, GameRoom.AgentID, h.Destroy, h.QuitRoom, h.NotifyDTUser, GameProxy) |
|||
r.Copy(GameRoom, Uid) |
|||
Gh.Rhb[rid] = r |
|||
Gh.RhbEx[Uid] = rid |
|||
Gh.RhbRoom[rid] = r |
|||
log.Debug("复制房间ok", rid, "所有房间==>", Gh.Rhb) |
|||
|
|||
return r |
|||
} |
|||
|
|||
} |
|||
|
|||
// uid 获取房间对象
|
|||
func (h *Home) GetRoomObject(UID int64) HomeBase { |
|||
//这里不用枷锁
|
|||
roomId := h.GetRoomIdByUid(UID) |
|||
if roomId <= 0 { |
|||
//log.Debug("Get RoomId failed. you get outed room")
|
|||
return nil |
|||
} |
|||
|
|||
r := h.GetRoomByRoomId(roomId) |
|||
|
|||
return r |
|||
} |
|||
|
|||
func (h *Home) SearchRoom() HomeBase { |
|||
h.lock.Lock() |
|||
defer h.lock.Unlock() |
|||
|
|||
for _, h := range Gh.Rhb { |
|||
if h.IsJoinRoom() { |
|||
return h |
|||
} |
|||
} |
|||
|
|||
return nil |
|||
} |
|||
|
|||
func (h *Home) SearchCZGRoom(RoomID int64) HomeBase { |
|||
h.lock.Lock() |
|||
defer h.lock.Unlock() |
|||
|
|||
for _, h := range Gh.Rhb { |
|||
if h.GetRoomId() != RoomID { |
|||
continue |
|||
} |
|||
if h.IsJoinRoom() { |
|||
return h |
|||
} |
|||
} |
|||
|
|||
return nil |
|||
} |
|||
|
|||
func (h *Home) AllRoomInfo() []protocol.TableInfo { |
|||
h.lock.Lock() |
|||
defer h.lock.Unlock() |
|||
|
|||
var AllTableInfo []protocol.TableInfo |
|||
for _, roomInfo := range Gh.RhbRoom { |
|||
tableInfo := protocol.TableInfo{ |
|||
RoomID: roomInfo.RoomID, |
|||
TableID: roomInfo.RId, |
|||
GameID: game.GAME_ID, |
|||
AgentID: roomInfo.AgentID, |
|||
State: roomInfo.CurrentGameState, |
|||
} |
|||
|
|||
for _, player := range roomInfo.PlayerMap { |
|||
TablePlayer := protocol.TablePlayer{ |
|||
ChairID: player.ChairId, |
|||
Avatar: player.Avatar, |
|||
} |
|||
tableInfo.TablePlayer = append(tableInfo.TablePlayer, TablePlayer) |
|||
} |
|||
|
|||
AllTableInfo = append(AllTableInfo, tableInfo) |
|||
} |
|||
sort.Slice(AllTableInfo, func(i, j int) bool { |
|||
return AllTableInfo[i].TableID < AllTableInfo[j].TableID |
|||
}) |
|||
return AllTableInfo |
|||
} |
|||
|
|||
// 通过uid获取房间Id
|
|||
func (h *Home) GetRoomIdByUid(uid int64) int64 { |
|||
h.lock.Lock() |
|||
defer h.lock.Unlock() |
|||
//log.Debug("玩家绑定的roomid==>", Gh.RhbEx)
|
|||
r := Gh.RhbEx[uid] |
|||
|
|||
return r |
|||
} |
|||
|
|||
// 通过房间id获取房间对象
|
|||
func (h *Home) GetRoomByRoomId(roomId int64) HomeBase { |
|||
h.lock.Lock() |
|||
defer h.lock.Unlock() |
|||
//log.Debug("roomId绑定的room对象", Gh.Rhb)
|
|||
r := Gh.Rhb[roomId] |
|||
|
|||
return r |
|||
} |
|||
|
|||
func (h *Home) GetGameRoomByRoomId(roomId int64) *game.Room { // 通过房间id获取房间对象
|
|||
h.lock.Lock() |
|||
defer h.lock.Unlock() |
|||
//log.Debug("roomId绑定的room对象", Gh.Rhb)
|
|||
r := Gh.RhbRoom[roomId] |
|||
|
|||
return r |
|||
} |
|||
|
|||
func (h *Home) QuitRoom(uid int64) { // 退出房间
|
|||
h.lock.Lock() |
|||
defer h.lock.Unlock() |
|||
log.Debug("Home==>退出房间") |
|||
|
|||
delete(Gh.RhbEx, uid) |
|||
//delete(Gh.EnterUser, uid)
|
|||
} |
|||
|
|||
func (h *Home) Destroy(roomId int64) { // 销毁房间
|
|||
r := h.GetGameRoomByRoomId(roomId) |
|||
h.lock.Lock() |
|||
defer h.lock.Unlock() |
|||
log.Debug("Home==>销毁房间") |
|||
|
|||
// 通知房间销毁
|
|||
h.Send(route.NotifyRoomDestroy, protocol.NotifyRoomDestroy{ |
|||
RoomID: r.RoomID, |
|||
TableID: r.RId, |
|||
}) |
|||
|
|||
Gh.TableCount[r.RoomID]-- |
|||
delete(Gh.Rhb, roomId) |
|||
delete(Gh.RhbRoom, roomId) |
|||
} |
|||
|
|||
func (rr *Home) GetSrcRoomByCtx(Proxy *node.Proxy, gameID, agentID, srcRoomId int32) *gamepb.FetchRoomsReply { |
|||
|
|||
client, err := gameservice.NewClient(Proxy.NewServiceClient) |
|||
if err != nil { |
|||
return nil |
|||
} |
|||
|
|||
reply, err := client.FetchRoomByID(context.Background(), &gamepb.FetchRoomByIdArgs{ |
|||
GameID: gameID, |
|||
AgentID: agentID, |
|||
RoomID: srcRoomId, |
|||
}) |
|||
|
|||
if err != nil { |
|||
log.Debug("err==>", err) |
|||
} |
|||
|
|||
rr.RoomsReply = reply |
|||
return reply |
|||
} |
|||
|
|||
func (h *Home) NotifyDTUser(messageID int32, message interface{}) { // 通知大厅的消息
|
|||
h.lock.Lock() |
|||
defer h.lock.Unlock() |
|||
log.Debug("通知大厅的消息 消息号", messageID) |
|||
h.Send(messageID, message) |
|||
} |
@ -0,0 +1,142 @@ |
|||
package types |
|||
|
|||
import ( |
|||
"base/log" |
|||
"fmt" |
|||
) |
|||
|
|||
type Poker byte // Poker 扑克牌
|
|||
type CardType = byte // CardType 牌型
|
|||
|
|||
const ( |
|||
PokerTypeBiShi = 1 // 闭十 相加为10 1倍
|
|||
PokerTypeBanQiDown = 2 // 7.5以下 1倍
|
|||
PokerTypeBanQiUp = 3 // 7.5以上 2倍
|
|||
PokerTypeDui = 4 // 对子 3倍
|
|||
PokerTypeEBG = 5 // 二八杠 3倍
|
|||
PokerTypeSB = 6 // 双百至尊 4倍
|
|||
) |
|||
|
|||
// OnePokers 一副牌
|
|||
var OnePokers = [20]Poker{ |
|||
1, 2, 3, 4, 5, 6, 7, 8, 9, 10, // 1-9 白板
|
|||
1, 2, 3, 4, 5, 6, 7, 8, 9, 10, // 1-9 白板
|
|||
} |
|||
|
|||
// IsValidValue 判断是否是有效值
|
|||
func (p Poker) IsValidValue() bool { |
|||
for _, poker := range OnePokers { |
|||
if poker == p { |
|||
return true |
|||
} |
|||
} |
|||
return false |
|||
} |
|||
|
|||
// PokerSlice 手牌牌组
|
|||
type PokerSlice []Poker |
|||
|
|||
// Insert 插入
|
|||
func (p *PokerSlice) Insert(index int, Card Poker) { |
|||
if index < 0 || index > len(*p) { |
|||
fmt.Println("Index out of range") |
|||
return |
|||
} |
|||
|
|||
// 追加一个空元素到切片中以便腾出空间
|
|||
*p = append(*p, 0) // 先扩展切片
|
|||
|
|||
// 将插入点及之后的元素向后移动
|
|||
copy((*p)[index+1:], (*p)[index:]) // 向后拷贝元素
|
|||
(*p)[index] = Card // 插入新
|
|||
} |
|||
|
|||
// Delete 删除
|
|||
func (p *PokerSlice) Delete(index int) { |
|||
if index < 0 || index >= len(*p) { |
|||
fmt.Println("Index out of range") |
|||
return |
|||
} |
|||
|
|||
// 使用 copy 函数将后面的元素前移
|
|||
copy((*p)[index:], (*p)[index+1:]) // 从 index 开始拷贝后续元素
|
|||
*p = (*p)[:len(*p)-1] // 切片长度减一
|
|||
} |
|||
|
|||
// GetCardType 获取牌型,点数
|
|||
func (p *PokerSlice) GetCardType() (CardType, int) { |
|||
Sum := Poker(0) |
|||
for _, tempPoker := range *p { |
|||
if tempPoker < 10 { |
|||
Sum += tempPoker * 10 |
|||
} else { |
|||
Sum += 5 |
|||
} |
|||
|
|||
if Sum >= 100 { |
|||
Sum -= 100 |
|||
} |
|||
} |
|||
|
|||
if (*p)[0] == 10 && (*p)[1] == 10 { |
|||
return PokerTypeSB, int(Sum) |
|||
} else if (*p)[0] == 2 && (*p)[1] == 8 { |
|||
return PokerTypeEBG, int(Sum) |
|||
} else if (*p)[0] == (*p)[1] { |
|||
return PokerTypeDui, int(Sum) |
|||
} else if Sum > 70 { |
|||
return PokerTypeBanQiUp, int(Sum) |
|||
} else if Sum == 100 { |
|||
return PokerTypeBiShi, int(Sum) |
|||
} else { |
|||
return PokerTypeBanQiDown, int(Sum) |
|||
} |
|||
} |
|||
|
|||
func (p *PokerSlice) GetCardTypeBei() int { // 获取倍数
|
|||
srcType, _ := p.GetCardType() |
|||
switch srcType { |
|||
case PokerTypeSB: |
|||
return 4 |
|||
case PokerTypeEBG: |
|||
return 3 |
|||
case PokerTypeDui: |
|||
return 3 |
|||
case PokerTypeBanQiUp: |
|||
return 2 |
|||
case PokerTypeBanQiDown: |
|||
return 1 |
|||
case PokerTypeBiShi: |
|||
return 1 |
|||
} |
|||
|
|||
log.Debug(" 牌型错误 牌是:", *p, " 牌型是(6 双白 5 二八 4 对子 3 板七上 2 板七下 1 闭十): ", srcType) |
|||
return 1 |
|||
} |
|||
|
|||
func (p *PokerSlice) Compare(desPoker PokerSlice) int32 { //比较输赢 赢 1 输 2 和 3
|
|||
srcType, srcPoint := p.GetCardType() |
|||
desType, desPoint := desPoker.GetCardType() |
|||
|
|||
// 先比较类型
|
|||
if srcType > desType { |
|||
return 1 |
|||
} else if srcType == desType { |
|||
if srcType == PokerTypeDui { |
|||
if (*p)[0] >= (*p)[1] { |
|||
return 1 |
|||
} else { |
|||
return 2 |
|||
} |
|||
} else { |
|||
// 再比较点数
|
|||
if srcPoint >= desPoint { |
|||
return 1 |
|||
} else { |
|||
return 2 |
|||
} |
|||
} |
|||
} else { |
|||
return 2 |
|||
} |
|||
} |
@ -0,0 +1,451 @@ |
|||
package gamemanage |
|||
|
|||
import ( |
|||
"base/cluster/node" |
|||
"base/log" |
|||
"base/task" |
|||
"fmt" |
|||
"xgame/game/TTZ/app/core/game" |
|||
"xgame/game/TTZ/app/core/protocol" |
|||
"xgame/game/TTZ/app/core/room" |
|||
"xgame/game/TTZ/app/route" |
|||
"xgame/internal/code" |
|||
accountservice "xgame/internal/service/account" |
|||
accountpb "xgame/internal/service/account/pb" |
|||
assetservice "xgame/internal/service/asset" |
|||
assetspb "xgame/internal/service/asset/pb" |
|||
gameservice "xgame/internal/service/game" |
|||
gamepb "xgame/internal/service/game/pb" |
|||
|
|||
"base/encoding/json" |
|||
|
|||
"github.com/shopspring/decimal" |
|||
) |
|||
|
|||
var GameProxy *node.Proxy |
|||
|
|||
func EnterGame(ctx *node.Context) { |
|||
Ctx := ctx.Clone() |
|||
task.AddTask(func() { |
|||
room.Gh.EnterUser[Ctx.Request.UID] = Ctx |
|||
}) |
|||
} |
|||
|
|||
func JoinTable(ctx *node.Context) { |
|||
Ctx := ctx.Clone() |
|||
task.AddTask(func() { |
|||
if Ctx.Request.UID <= 0 { |
|||
return |
|||
} |
|||
req := &protocol.JoinRoomReq{} |
|||
res := &protocol.SitDownRes{} |
|||
//0.解析消息
|
|||
if err := Ctx.Request.Parse(req); err != nil { |
|||
log.Debugf("response protocol.JoinRoomReq message failed: %v", err) |
|||
return |
|||
} |
|||
|
|||
//3.new个Player 初始化
|
|||
client2, err := assetservice.NewClient(Ctx.Proxy.NewServiceClient) |
|||
if err != nil { |
|||
log.Errorf("assetservice NewClient failed: %v", err) |
|||
return |
|||
} |
|||
|
|||
client1, err := accountservice.NewClient(Ctx.Proxy.NewServiceClient) |
|||
if err != nil { |
|||
log.Errorf("accountservice NewClient failed: %v", err) |
|||
return |
|||
} |
|||
//4.个人信息
|
|||
user, err := client1.GetUser(Ctx.Context(), &accountpb.GetUserArgs{ |
|||
UID: Ctx.Request.UID, |
|||
}) |
|||
if err != nil { |
|||
return |
|||
} |
|||
|
|||
//5.个人资产
|
|||
reply3, err := client2.GetAsset(Ctx.Context(), &assetspb.GetAssetArgs{ |
|||
UID: Ctx.Request.UID, |
|||
}) |
|||
if err != nil { |
|||
return |
|||
} |
|||
|
|||
client3, err := gameservice.NewClient(Ctx.Proxy.NewServiceClient) |
|||
if err != nil { |
|||
return |
|||
} |
|||
//6.房间信息
|
|||
reply4, err := client3.FetchRoomByID(Ctx.Context(), &gamepb.FetchRoomByIdArgs{ |
|||
GameID: req.GameID, |
|||
AgentID: req.AgentID, |
|||
RoomID: req.RoomID, |
|||
}) |
|||
if err != nil { |
|||
return |
|||
} |
|||
|
|||
//6.5判断是否满足创建房间
|
|||
var item protocol.Options |
|||
err2 := json.Unmarshal([]byte(reply4.RoomOpts), &item) |
|||
if err2 != nil { |
|||
return |
|||
} |
|||
|
|||
if reply3.Gold < item.MinEnterAsset { |
|||
res.Code = -2 |
|||
res.CodeMsg = "加入游戏失败,资产不足" |
|||
log.Debug(res.CodeMsg) |
|||
if err := Ctx.Response(res); err != nil { |
|||
log.Debugf("EnterGame ==> response message failed: %v", err) |
|||
} |
|||
return |
|||
} |
|||
|
|||
log.Debug("玩家", Ctx.Request.UID, " 加入房间 req:", req) |
|||
|
|||
if req.TableID == 1 && req.IsWatching == 1 { |
|||
res.Code = -4 |
|||
res.CodeMsg = "不能以观战的身份创建桌子" |
|||
log.Debug(res.CodeMsg) |
|||
if err := Ctx.Response(res); err != nil { |
|||
log.Debugf("EnterGame ==> response message failed: %v", err) |
|||
} |
|||
return |
|||
} |
|||
|
|||
//在房间中
|
|||
var roomObj room.HomeBase |
|||
RoomID := room.Gh.GetRoomIdByUid(Ctx.Request.UID) |
|||
roomObj = room.Gh.GetRoomByRoomId(RoomID) |
|||
log.Debug("EnterGame user:", user.Nickname, " ==> RoomID:", RoomID, " roomObj", roomObj) |
|||
if roomObj == nil { |
|||
if req.TableID == 0 { |
|||
roomObj = room.Gh.SearchCZGRoom(int64(req.RoomID)) |
|||
if roomObj == nil { |
|||
roomObj = room.Gh.CreateRoom(Ctx.Request.UID, req.RoomID, req.GameID, req.AgentID, GameProxy) |
|||
} |
|||
} else if req.TableID == 1 { |
|||
roomObj = room.Gh.CreateRoom(Ctx.Request.UID, req.RoomID, req.GameID, req.AgentID, GameProxy) |
|||
} else { |
|||
roomObj = room.Gh.GetRoomByRoomId(req.TableID) |
|||
if roomObj == nil { |
|||
res.Code = -3 |
|||
res.CodeMsg = "加入游戏失败,桌子不存在" |
|||
log.Debug(res.CodeMsg, "桌子id :", req.TableID) |
|||
if err := Ctx.Response(res); err != nil { |
|||
log.Debugf("EnterGame ==> response message failed: %v", err) |
|||
} |
|||
return |
|||
} |
|||
} |
|||
} else { |
|||
log.Debug("玩家", Ctx.Request.UID, " name:", user.Nickname, "====>在房间中 发送最新的房间信息") |
|||
|
|||
log.Debug("UpdateCtx EnterGame ", Ctx.Request.UID, " UserId", Ctx.Request.UserId, " UID", Ctx.Request.UID, " Request", Ctx.Request) |
|||
roomObj.OnGetRoomInfo(Ctx.Request.UID, Ctx) |
|||
return |
|||
} |
|||
|
|||
_player := &game.Player{ |
|||
Uid: Ctx.Request.UID, |
|||
IsRobot: false, |
|||
Ctx: Ctx, |
|||
Gold: decimal.NewFromFloat(float64(reply3.Gold)), |
|||
Diamond: decimal.NewFromFloat(float64(reply3.Diamond)), |
|||
Ticket: decimal.NewFromFloat(float64(reply3.Ticket)), |
|||
Nickname: user.Nickname, |
|||
Avatar: user.Avatar, |
|||
UserNo: user.UserNo, |
|||
AgentID: user.AgentID, |
|||
} |
|||
|
|||
//6.判断玩家资产是否满足进入房间的需求
|
|||
bRet := roomObj.JoinRoom(_player, req.IsWatching) |
|||
if -1 == bRet { |
|||
res.Code = -1 |
|||
res.CodeMsg = "你已经在房间中了" |
|||
log.Debug(res.CodeMsg) |
|||
if err := Ctx.Response(res); err != nil { |
|||
log.Debugf("EnterGame ==> response message failed: %v", err) |
|||
} |
|||
|
|||
return |
|||
} |
|||
|
|||
if -2 == bRet { |
|||
res.Code = -2 |
|||
res.CodeMsg = "资产不足" |
|||
log.Debug(res.CodeMsg) |
|||
if err := Ctx.Response(res); err != nil { |
|||
log.Debugf("EnterGame ==> response message failed: %v", err) |
|||
} |
|||
|
|||
return |
|||
} |
|||
|
|||
room.Gh.RhbEx[Ctx.Request.UID] = roomObj.GetRId() |
|||
|
|||
roomObj.OnGetRoomInfo(Ctx.Request.UID, Ctx) |
|||
NotifySitDown := &protocol.NotifyDTSitDown{ |
|||
Uid: _player.Uid, |
|||
RoomID: req.RoomID, |
|||
TableID: roomObj.GetRId(), |
|||
ChairID: _player.ChairId, |
|||
Avatar: _player.Avatar, |
|||
State: roomObj.GetState(), |
|||
} |
|||
room.Gh.Send(route.NotifyDTSitDown, NotifySitDown) |
|||
|
|||
err = Ctx.BindNode() |
|||
|
|||
if err != nil { |
|||
log.Error("绑定失败==>", Ctx.Request.UID) |
|||
return |
|||
} |
|||
}) |
|||
} |
|||
|
|||
// Reconnect 掉线重连
|
|||
func Reconnect(event *node.Event) { |
|||
|
|||
task.AddTask(func() { |
|||
if event.UID <= 0 { |
|||
return |
|||
} |
|||
//Ctx.Context()
|
|||
/* |
|||
* 只能配合客户端想办法了,实在没办法,这服务器架构设计的有缺陷 |
|||
*/ |
|||
uid := event.UID |
|||
r := room.Gh.GetRoomObject(uid) |
|||
if r != nil { |
|||
r.OnReconnect(uid) |
|||
fmt.Println(uid, "断线重连") |
|||
} |
|||
}) |
|||
} |
|||
|
|||
// Disconnect 掉线
|
|||
func Disconnect(event *node.Event) { |
|||
|
|||
task.AddTask(func() { |
|||
if event.UID <= 0 { |
|||
return |
|||
} |
|||
uid := event.UID |
|||
//r := room.GetRoomByUid(uid)
|
|||
r := room.Gh.GetRoomObject(uid) |
|||
if r != nil { |
|||
r.OnDisconnect(uid) |
|||
log.Debug(uid, "玩家掉线,设置为离线状态") |
|||
} |
|||
}) |
|||
} |
|||
|
|||
func UpdateUserGold(uid int64) { //更新用户的钱
|
|||
task.AddTask(func() { |
|||
r := room.Gh.GetRoomObject(uid) |
|||
if r != nil { |
|||
r.OnUpdateGold(uid) |
|||
fmt.Println(uid, "更新用户的钱") |
|||
} |
|||
}) |
|||
} |
|||
|
|||
func UpdateTableConfig(gameID int64) { //更新桌子的配置
|
|||
task.AddTask(func() { |
|||
log.Debug(gameID, " 更新桌子的配置 ", gameID) |
|||
if game.GAME_ID == gameID { |
|||
room.Gh.InitBloodControlByBackend() |
|||
log.Debug(gameID, " 更新桌子的配置") |
|||
} |
|||
}) |
|||
} |
|||
|
|||
func UserBet(ctx *node.Context) { // 用户下注
|
|||
Ctx := ctx.Clone() |
|||
task.AddTask(func() { |
|||
|
|||
r := room.Gh.GetRoomObject(Ctx.Request.UID) |
|||
if r == nil { |
|||
log.Error("StrokeCard==>>>>>>,不在该房间") |
|||
return |
|||
} |
|||
|
|||
req := &protocol.BetReq{} |
|||
if err := Ctx.Request.Parse(req); err != nil { |
|||
log.Errorf("Parse StrokeCardReq failed. %v", err) |
|||
return |
|||
} |
|||
|
|||
log.Debug("UpdateCtx UserBet ", Ctx.Request.UID, " UserId", ctx.Request.UserId, " UID", ctx.Request.UID, " Request", ctx.Request) |
|||
r.UpdateCtx(Ctx.Request.UID, Ctx) |
|||
|
|||
r.OnUserBet(Ctx.Request.UID, req, false) |
|||
}) |
|||
} |
|||
|
|||
func GetBanker(ctx *node.Context) { // 抢庄
|
|||
Ctx := ctx.Clone() |
|||
task.AddTask(func() { |
|||
|
|||
RoomID := room.Gh.GetRoomIdByUid(Ctx.Request.UID) |
|||
r := room.Gh.GetGameRoomByRoomId(RoomID) |
|||
if r == nil { |
|||
log.Error("StrokeCard==>>>>>>,不在该房间") |
|||
return |
|||
} |
|||
|
|||
req := &protocol.GetBankerReq{} |
|||
if err := Ctx.Request.Parse(req); err != nil { |
|||
log.Errorf("Parse StrokeCardReq failed. %v", err) |
|||
return |
|||
} |
|||
|
|||
log.Debug("UpdateCtx GetBanker ", Ctx.Request.UID, " UserId", ctx.Request.UserId, " UID", ctx.Request.UID, " Request", ctx.Request) |
|||
r.UpdateCtx(Ctx.Request.UID, Ctx) |
|||
|
|||
r.OnUserGetBanker(Ctx.Request.UID, req) |
|||
}) |
|||
} |
|||
|
|||
func WatchToDown(ctx *node.Context) { // 主动观战转坐下
|
|||
Ctx := ctx.Clone() |
|||
task.AddTask(func() { |
|||
|
|||
RoomID := room.Gh.GetRoomIdByUid(Ctx.Request.UID) |
|||
r := room.Gh.GetGameRoomByRoomId(RoomID) |
|||
if r == nil { |
|||
log.Error("StrokeCard==>>>>>>,不在该房间") |
|||
return |
|||
} |
|||
|
|||
req := &protocol.WatchToDownReq{} |
|||
if err := Ctx.Request.Parse(req); err != nil { |
|||
log.Errorf("Parse StrokeCardReq failed. %v", err) |
|||
return |
|||
} |
|||
|
|||
log.Debug("UpdateCtx WatchToDown ", Ctx.Request.UID, " UserId", ctx.Request.UserId, " UID", ctx.Request.UID, " Request", ctx.Request) |
|||
r.UpdateCtx(Ctx.Request.UID, Ctx) |
|||
|
|||
//判断用户是否在观战
|
|||
var WToDUser *game.Player |
|||
for _, TempWatchPlayer := range r.PlayerWatchMap { |
|||
if TempWatchPlayer.Uid == Ctx.Request.UID { |
|||
WToDUser = TempWatchPlayer |
|||
} |
|||
} |
|||
|
|||
if WToDUser == nil { |
|||
log.Debug("玩家", Ctx.Request.UID, "不在观战席") |
|||
WatchToDownRes := &protocol.WatchToDownRes{} |
|||
WatchToDownRes.Code = protocol.ErrorWatchToDownNotInWatch |
|||
WatchToDownRes.CodeMsg = "不在观战席 不能坐下" |
|||
|
|||
Ctx.Request.Message.Route = route.WatchToDownRes |
|||
if err := Ctx.Response(WatchToDownRes); err != nil { |
|||
log.Debugf("WatchToDown ==> response message failed: %v", err) |
|||
} |
|||
return |
|||
} |
|||
|
|||
r.OnUserWatchToDown(Ctx.Request.UID, req) |
|||
}) |
|||
} |
|||
|
|||
func LogoutTable(ctx *node.Context) { // 用户退出游戏请求
|
|||
Ctx := ctx.Clone() |
|||
task.AddTask(func() { |
|||
RoomID := room.Gh.GetRoomIdByUid(Ctx.Request.UID) |
|||
RoomInfo := room.Gh.GetGameRoomByRoomId(RoomID) |
|||
var TempPlayer *game.Player |
|||
if RoomInfo != nil { |
|||
TempPlayer = RoomInfo.GetRoomPlayerByUid(Ctx.Request.UID) |
|||
if TempPlayer != nil { |
|||
log.Debug("LogoutTable 没有获取到用户 ", Ctx.Request.UID) |
|||
} |
|||
|
|||
if RoomInfo != nil && RoomInfo.CurrentGameState > protocol.STATE_BEGIN && RoomInfo.CurrentGameState != protocol.STATE_RESULT { |
|||
if TempPlayer.ChairId != -1 && (TempPlayer.ChairId == RoomInfo.CurrBanker || TempPlayer.CanBet) { |
|||
log.Debug("LogoutTable 开始游戏后不能退出游戏 ", " Request", ctx.Request) |
|||
LeaveTableRes := &protocol.LeaveTableRes{ |
|||
Code: code.ErrorWaitGameEndOut.Code(), |
|||
CodeMsg: "开始游戏后不能退出游戏", |
|||
} |
|||
|
|||
Ctx.Request.Message.Route = route.LogoutTableRes |
|||
if err := Ctx.Response(LeaveTableRes); err != nil { |
|||
log.Debugf("开始游戏后不能退出游戏 出错了: %v", err) |
|||
} |
|||
|
|||
RoomInfo.UpdateUserOut(Ctx.Request.UID) |
|||
return |
|||
} |
|||
} |
|||
|
|||
if TempPlayer != nil && TempPlayer.ChairId == RoomInfo.CurrBanker && RoomInfo.CurrentGameState > protocol.STATE_GET_BANKER && RoomInfo.CurrentGameState != protocol.STATE_RESULT { |
|||
log.Debug("LogoutTable 庄家不能离开房间 ", " Request", ctx.Request) |
|||
LeaveTableRes := &protocol.LeaveTableRes{ |
|||
Code: protocol.ErrorLeaveTableBanker, |
|||
CodeMsg: "庄家不能离开房间", |
|||
} |
|||
|
|||
Ctx.Request.Message.Route = route.LogoutTableRes |
|||
if err := Ctx.Response(LeaveTableRes); err != nil { |
|||
log.Debugf("庄家不能离开房间出错了: %v", err) |
|||
} |
|||
return |
|||
} |
|||
} |
|||
|
|||
r := room.Gh.GetRoomObject(Ctx.Request.UID) |
|||
if r == nil { |
|||
delete(room.Gh.EnterUser, Ctx.Request.UID) |
|||
log.Debug(Ctx.Request.UID, " 不在该房间 退出游戏") |
|||
return |
|||
} |
|||
|
|||
log.Debug("UpdateCtx LogoutTable ", Ctx.Request.UID, " UserId", ctx.Request.UserId, " UID", ctx.Request.UID, " Request", ctx.Request) |
|||
r.UpdateCtx(Ctx.Request.UID, Ctx) |
|||
|
|||
r.OnGetOutRoom(Ctx.Request.UID) |
|||
|
|||
log.Debug("UpdateCtx LogoutTable RoomInfo ", RoomInfo, " TempPlayer ", TempPlayer) |
|||
//if RoomInfo != nil {
|
|||
// if TempPlayer != nil {
|
|||
// NotifySitDown := &protocol.NotifyDTSitDown{
|
|||
// Uid: TempPlayer.Uid,
|
|||
// RoomID: RoomInfo.RoomID,
|
|||
// TableID: RoomInfo.RId,
|
|||
// ChairID: TempPlayer.ChairId,
|
|||
// Avatar: TempPlayer.Avatar,
|
|||
// State: RoomInfo.CurrentGameState,
|
|||
// }
|
|||
// log.Debug("UpdateCtx LogoutTable 发送用户退出")
|
|||
// room.Gh.Send(route.NotifyDTStandUp, NotifySitDown)
|
|||
// }
|
|||
//}
|
|||
}) |
|||
} |
|||
|
|||
func AllTable(ctx *node.Context) { // 用户下注
|
|||
Ctx := ctx.Clone() |
|||
task.AddTask(func() { |
|||
res := &protocol.AllTableRes{ |
|||
Code: 0, |
|||
CodeMsg: "获取成功", |
|||
} |
|||
|
|||
res.TableInfo = room.Gh.AllRoomInfo() |
|||
log.Debug("当前的所有房间信息 : ", res) |
|||
|
|||
Ctx.Request.Message.Route = route.AllTableInfoRes |
|||
if err := Ctx.Response(res); err != nil { |
|||
log.Debugf("AllTable ==> response message failed: %v", err) |
|||
} |
|||
}) |
|||
} |
@ -0,0 +1,39 @@ |
|||
package route |
|||
|
|||
const ( |
|||
// 客户端发送
|
|||
Enter int32 = 2001301 // 进入游戏大厅
|
|||
Bet int32 = 2001302 // 下注请求
|
|||
LogoutTable int32 = 2001303 // 退出游戏请求
|
|||
AllTable int32 = 2001304 // 获取所有桌子
|
|||
JoinTable int32 = 2001305 // 加入桌子
|
|||
GetBanker int32 = 2001306 // 抢庄
|
|||
WatchToDown int32 = 2001307 // 主动观战转坐下
|
|||
|
|||
// 服务端返回
|
|||
BetRes int32 = 2001311 // 下注返回
|
|||
LogoutTableRes int32 = 2001312 // 退出游戏返回
|
|||
SitDownRes int32 = 2001313 // 玩家坐下返回
|
|||
RoomInfoRes int32 = 2001314 // 房间的信息返回
|
|||
AllTableInfoRes int32 = 2001315 // 所有桌子的信息返回
|
|||
GetBankerRes int32 = 2001316 // 抢庄返回
|
|||
WatchToDownRes int32 = 2001317 // 主动观战转坐下返回
|
|||
|
|||
// 服务端通知
|
|||
NotifySitDown int32 = 2001321 // 通知玩家坐下
|
|||
NotifyStateTime int32 = 2001322 // 通知阶段倒计时
|
|||
NotifyPoker int32 = 2001323 // 通知翻牌
|
|||
NotifyBet int32 = 2001324 // 通知下注
|
|||
NotifyGameConclude int32 = 2001325 // 通知结束结算
|
|||
NotifyGetOutGame int32 = 2001326 // 通知退出房间
|
|||
NotifyReEnter int32 = 2001327 // 通知点控重连
|
|||
NotifyBanker int32 = 2001328 // 通知抢庄
|
|||
NotifyCurrentBanker int32 = 2001329 // 通知本轮庄家
|
|||
NotifyDTSitDown int32 = 2001330 // 通知大厅玩家坐下
|
|||
NotifyDTStandUp int32 = 2001331 // 通知大厅玩家离开
|
|||
NotifyWatchToDown int32 = 2001332 // 通知玩家观战转坐下
|
|||
NotifyDownToWatch int32 = 2001333 // 通知玩家坐下转观战
|
|||
NotifyRoomDestroy int32 = 2001334 // 通知房间销毁
|
|||
|
|||
NotifyCurrentBeginUser int32 = 2001380 // 通知本轮开始发牌的玩家
|
|||
) |
@ -0,0 +1,100 @@ |
|||
{ |
|||
"CommentRechargeLimit": "低于多少钱弹充值", |
|||
"RechargeLimit" : 10000, |
|||
"CommentMinGameScore": "最低能玩的金额", |
|||
"MinGameScore" : 50000, |
|||
"CommentChipList": "默认的筹码列表 后台有按后台的来", |
|||
"ChipList": [10000], |
|||
"GearConfigComment": "GearID 血池 WinPro AI胜率 BankerPro 抢庄概率 GetBankerPro 中庄概率 WinBetPro 赢下注权重 LoseBetPro 输下注权重 BankerWinPro 庄家胜率", |
|||
"GearConfig": [ |
|||
{ |
|||
"GearID": 3000, |
|||
"WinPro": 6000, |
|||
"BankerPro": 2000, |
|||
"GetBankerPro": 2000, |
|||
"WinBetPro": [[1,6000],[2,2000],[3,1000],[4,9999]], |
|||
"LoseBetPro": [[1,6000],[2,2000],[3,1000],[4,9999]], |
|||
"BankerWinPro": 5000 |
|||
},{ |
|||
"GearID": 2000, |
|||
"WinPro": 3000, |
|||
"BankerPro": 2000, |
|||
"GetBankerPro": 2000, |
|||
"WinBetPro": [[1,6000],[2,2000],[3,1000],[4,9999]], |
|||
"LoseBetPro": [[1,6000],[2,2000],[3,1000],[4,9999]], |
|||
"BankerWinPro": 5000 |
|||
},{ |
|||
"GearID": 1000, |
|||
"WinPro": 500, |
|||
"BankerPro": 2000, |
|||
"GetBankerPro": 2000, |
|||
"WinBetPro": [[1,6000],[2,2000],[3,1000],[4,9999]], |
|||
"LoseBetPro": [[1,6000],[2,2000],[3,1000],[4,9999]], |
|||
"BankerWinPro": 5000 |
|||
},{ |
|||
"GearID": -1000, |
|||
"WinPro": 0, |
|||
"BankerPro": 2000, |
|||
"GetBankerPro": 2000, |
|||
"WinBetPro": [[1,6000],[2,2000],[3,1000],[4,9999]], |
|||
"LoseBetPro": [[1,6000],[2,2000],[3,1000],[4,9999]], |
|||
"BankerWinPro": 5000 |
|||
},{ |
|||
"GearID": -2000, |
|||
"WinPro": 1500, |
|||
"BankerPro": 2000, |
|||
"GetBankerPro": 2000, |
|||
"WinBetPro": [[1,6000],[2,2000],[3,1000],[4,9999]], |
|||
"LoseBetPro": [[1,6000],[2,2000],[3,1000],[4,9999]], |
|||
"BankerWinPro": 5000 |
|||
},{ |
|||
"GearID": -3000, |
|||
"WinPro": 3000, |
|||
"BankerPro": 2000, |
|||
"GetBankerPro": 2000, |
|||
"WinBetPro": [[1,6000],[2,2000],[3,1000],[4,9999]], |
|||
"LoseBetPro": [[1,6000],[2,2000],[3,1000],[4,9999]], |
|||
"BankerWinPro": 5000 |
|||
} |
|||
], |
|||
"CommentAndroidOprateConfig": "机器人的配置", |
|||
"AndroidOprateConfig": { |
|||
"CommentMustBanker": "是否兜底上庄 1是 0不是", |
|||
"MustBanker": 1, |
|||
"CommentInGold": "场次携带金币上下范围", |
|||
"InGold": [[1000000,2000000],[1000000,2000000],[1000000,2000000],[1000000,2000000],[1000000,2000000],[1000000,2000000]], |
|||
"CommenCreateTableHZ": "创建桌子的频率", |
|||
"CreateTableHZ": 30000, |
|||
"CommentTableCreatePro": "低于多少桌时创建桌子的概率 高于最后一个配置不再创建桌子", |
|||
"TableCreatePro": [[3,10000],[6,8000]], |
|||
"CommentCountMax": "房间多少个真实玩家情况下 机器人的个数概率", |
|||
"CountMax0": [[0,0],[1,0],[2,3000],[3,5000],[4,1500],[5,0]], |
|||
"CountMax1": [[0,0],[1,3000],[2,3000],[3,5000],[4,1500],[5,500]], |
|||
"CountMax2": [[0,0],[1,5000],[2,2000],[3,1000],[4,500],[5,0]], |
|||
"CountMax3": [[0,3000],[1,5000],[2,50],[3,0],[4,0],[5,0]], |
|||
"CountMax4": [[0,8000],[1,2000],[2,0],[3,0],[4,0],[5,0]], |
|||
"CountMax5": [[0,0],[1,0],[2,0],[3,0],[4,0],[5,0]], |
|||
"CommentJoinHZ": "机器人加入房间的时间间隔", |
|||
"JoinHZ": [10,30], |
|||
"CommentFlushHZ": "刷新机器人进房间的频率", |
|||
"FlushHZ": 300 |
|||
}, |
|||
"CommentTimeoutDestroy": "创建房间后没人的销毁时间", |
|||
"TimeoutDestroy": 60000, |
|||
"CommentTimeOutBegin": "下一局开始倒计时", |
|||
"TimeOutBegin" : 3000, |
|||
"CommentTimeOutGetBanker": "抢庄时间", |
|||
"TimeOutGetBanker" : 10000, |
|||
"CommentTimeOutBB": "抢庄后到开始下注的等待时间", |
|||
"TimeOutBB" : 5000, |
|||
"CommentTimeOutDT": "丢骰子动画展示倒计时", |
|||
"TimeOutDT" : 5000, |
|||
"CommentTimeOutBet": "下注时间", |
|||
"TimeOutBet" : 15000, |
|||
"CommentTimeOutCP": "搓牌时间", |
|||
"TimeOutCP" : 12000, |
|||
"CommentTimeOutResult": "结算的时间", |
|||
"TimeOutResult" : 10000, |
|||
"CommentTimeKickTimes": "多少次不下注踢出房间", |
|||
"TimeKickTimes" :5 |
|||
} |
@ -0,0 +1,126 @@ |
|||
# 进程号 |
|||
pid = "./run/game.pid" |
|||
# 统一时区设置。项目中的时间获取请使用xtime.Now() |
|||
timezone = "Local" |
|||
|
|||
[cluster] |
|||
[cluster.node] |
|||
# 实例名称 |
|||
name = "TTZ" |
|||
# 编解码器。可选:json | proto |
|||
codec = "json" |
|||
|
|||
[config] |
|||
[config.file] |
|||
# 配置文件或配置目录路径 |
|||
path = "./config" |
|||
# 读写模式。可选:read-only | read-write,默认为read-only |
|||
mode = "read-write" |
|||
[config.etcd] |
|||
# 客户端连接地址+ |
|||
addrs = ["127.0.0.1:2379"] |
|||
# 客户端拨号超时时间,支持单位:纳秒(ns)、微秒(us | µs)、毫秒(ms)、秒(s)、分(m)、小时(h)、天(d)。默认为5s |
|||
dialTimeout = "5s" |
|||
# 路径。默认为/config |
|||
path = "/config" |
|||
# 读写模式。可选:read-only | read-write,默认为read-only |
|||
mode = "read-only" |
|||
|
|||
[locate] |
|||
[locate.redis] |
|||
# 客户端连接地址 |
|||
addrs = ["127.0.0.1:62331"] |
|||
# 数据库号 |
|||
db = 0 |
|||
# 用户名 |
|||
username = "" |
|||
# 密码 |
|||
password = "zetdCehWe5t3z9" |
|||
# 最大重试次数 |
|||
maxRetries = 3 |
|||
# key前缀 |
|||
prefix = "xgame" |
|||
|
|||
[registry] |
|||
[registry.etcd] |
|||
# 客户端连接地址 |
|||
addrs = ["127.0.0.1:2379"] |
|||
# 客户端拨号超时时间(秒) |
|||
dialTimeout = 5 |
|||
# 命名空间 |
|||
namespace = "services" |
|||
# 超时时间(秒) |
|||
timeout = 3 |
|||
# 心跳重试次数 |
|||
retryTimes = 3 |
|||
# 心跳重试间隔(秒) |
|||
retryInterval = 10 |
|||
[registry.consul] |
|||
# 客户端连接地址 |
|||
addr = "127.0.0.1:8500" |
|||
# 是否启用健康检查 |
|||
healthCheck = true |
|||
# 健康检查时间间隔(秒),仅在启用健康检查后生效 |
|||
healthCheckInterval = 10 |
|||
# 健康检查超时时间(秒),仅在启用健康检查后生效 |
|||
healthCheckTimeout = 5 |
|||
# 是否启用心跳检查 |
|||
heartbeatCheck = true |
|||
# 心跳检查时间间隔(秒),仅在启用心跳检查后生效 |
|||
heartbeatCheckInterval = 10 |
|||
# 健康检测失败后自动注销服务时间(秒) |
|||
deregisterCriticalServiceAfter = 30 |
|||
|
|||
[transport] |
|||
[transport.rpcx] |
|||
# RPCX服务器相关配置 |
|||
[transport.rpcx.server] |
|||
# 服务器监听地址,空或:0时系统将会随机端口号 |
|||
addr = ":0" |
|||
# 秘钥文件 |
|||
keyFile = "" |
|||
# 证书文件 |
|||
certFile = "" |
|||
# RPCX服务器相关配置 |
|||
[transport.rpcx.client] |
|||
# 证书文件 |
|||
certFile = "" |
|||
# 证书域名 |
|||
serverName = "" |
|||
# 连接池大小,默认为10 |
|||
poolSize = 10 |
|||
|
|||
[packet] |
|||
# 字节序,默认为big。可选:little | big |
|||
byteOrder = "big" |
|||
# 路由字节数,默认为2字节 |
|||
routeBytes = 4 |
|||
# 序列号字节数,默认为2字节 |
|||
seqBytes = 4 |
|||
# 消息字节数,默认为5000字节 |
|||
bufferBytes = 100000 |
|||
|
|||
[log] |
|||
[log.zap] |
|||
# 日志输出文件 |
|||
file = "./log/xgame.log" |
|||
# 日志输出级别,可选:debug | info | warn | error | fatal | panic |
|||
level = "debug" |
|||
# 日志输出格式,可选:text | json |
|||
format = "text" |
|||
# 是否输出到终端 |
|||
stdout = true |
|||
# 时间格式,标准库时间格式 |
|||
timeFormat = "2006/01/02 15:04:05.000000" |
|||
# 堆栈的最低输出级别,可选:debug | info | warn | error | fatal | panic |
|||
stackLevel = "error" |
|||
# 文件最大留存时间,d:天、h:时、m:分、s:秒 |
|||
fileMaxAge = "7d" |
|||
# 文件最大尺寸限制,单位(MB) |
|||
fileMaxSize = 100 |
|||
# 文件切割方式 |
|||
fileCutRule = "day" |
|||
# 是否启用调用文件全路径 |
|||
callerFullPath = false |
|||
# 是否启用分级存储 |
|||
classifiedStorage = false |
@ -0,0 +1,41 @@ |
|||
# 以下配置为游戏固定配置,修改必需重启游戏生效 |
|||
|
|||
# 游戏配置(游戏模型基础配置,不可随意变动配置名) |
|||
[game] |
|||
# 游戏ID |
|||
id = 20013 |
|||
# 游戏类型 |
|||
type = 1 |
|||
# 游戏名称 |
|||
name = "TTZ" |
|||
# 最小牌桌数 |
|||
minTableNum = 1 |
|||
# 最大牌桌数 |
|||
maxTableNum = 1 |
|||
# 是否动态牌桌 |
|||
isDynamicTable = false |
|||
# 最小座位数 |
|||
minSeatNum = 0 |
|||
# 最大座位数 |
|||
maxSeatNum = 0 |
|||
# 是否动态座位 |
|||
isDynamicSeat = true |
|||
# 是否回合制游戏,例如:(回合制游戏:麻将)(非回合制游戏:slots) |
|||
isTurnBasedGame = false |
|||
# 是否需要底池接口 |
|||
isNeedPot = false |
|||
# 是否需要奖池接口 |
|||
isNeedPrizePool = true |
|||
# 是否需要血池接口 |
|||
isNeedBloodPool = false |
|||
# 自定义配置(由开发人员自行定义) |
|||
[custom] |
|||
# 押注时长(秒) |
|||
BaseLineCount = 25 |
|||
# 准备起飞时长(秒) |
|||
readyingDuration = 4 |
|||
# 结算时长(秒) |
|||
settlementDuration = 5 |
|||
|
|||
|
|||
|
@ -0,0 +1,161 @@ |
|||
package main |
|||
|
|||
import ( |
|||
"base/cluster/node" |
|||
"base/config" |
|||
"base/config/file" |
|||
"base/encoding/json" |
|||
"base/eventbus" |
|||
"base/eventbus/nats" |
|||
"base/locate/redis" |
|||
"base/log" |
|||
"base/log/zap" |
|||
"base/registry/consul" |
|||
"base/transport/rpcx" |
|||
"github.com/shopspring/decimal" |
|||
"testing" |
|||
"xgame/game/TTZ/app/core" |
|||
"xgame/game/TTZ/app/core/game" |
|||
"xgame/game/TTZ/app/core/protocol" |
|||
"xgame/game/TTZ/app/core/types" |
|||
"xgame/game/TTZ/app/gamemanage" |
|||
"xgame/game/service/rpc_client" |
|||
optionRoom "xgame/internal/option/room" |
|||
) |
|||
|
|||
func TestTable11_test(T *testing.T) { |
|||
// 设置日志
|
|||
log.SetLogger(zap.NewLogger(zap.WithCallerSkip(2))) |
|||
// 初始化事件总线
|
|||
eventbus.SetEventbus(nats.NewEventbus()) |
|||
// 设置配置中心
|
|||
config.SetConfigurator(config.NewConfigurator(config.WithSources(file.NewSource()))) |
|||
// 创建容器
|
|||
//container := base.NewContainer()
|
|||
// 创建用户定位器
|
|||
locator := redis.NewLocator() |
|||
// 创建服务发现
|
|||
registry := consul.NewRegistry() |
|||
// 创建RPC传输器
|
|||
transporter := rpcx.NewTransporter(rpcx.WithClientDiscovery(registry)) |
|||
// 创建网关组件
|
|||
component := node.NewNode( |
|||
node.WithLocator(locator), |
|||
node.WithRegistry(registry), |
|||
node.WithTransporter(transporter), |
|||
) |
|||
|
|||
// 初始化游戏
|
|||
gamemanage.GameProxy = component.Proxy() |
|||
core.NewCore(component.Proxy()).Init() |
|||
|
|||
//// 添加网关组件
|
|||
//container.Add(component)
|
|||
//// 启动容器
|
|||
//container.Serve()
|
|||
|
|||
//创建新房间
|
|||
|
|||
//RoomID := room.Gh.GetRoomIdByUid(0)
|
|||
//rr := room.Gh.GetGameRoomByRoomId(RoomID)
|
|||
rr := game.New(0, 123, 0, 20005, 0, nil, nil, gamemanage.GameProxy) |
|||
//rr.OnInit()
|
|||
|
|||
//1.初始化血池
|
|||
rr.BoolePool.RoomGears = "3000" |
|||
//if rr.BoolePool.SetBoole(rr.RoomProxy, rr.GameID, rr.RoomID, "AB") == false {
|
|||
// log.Debug("初始化血池失败")
|
|||
//}
|
|||
|
|||
// 读取配置文件
|
|||
rr.InitBloodControl() |
|||
|
|||
//配置库存[房间的库存]
|
|||
rr.StockValue = rr.BoolePool.BoolPoolSockNum |
|||
|
|||
//2.初始化配置设置房间 opts
|
|||
rr.Opt = &optionRoom.Options{} |
|||
|
|||
replyOpt := rpc_client.GetSrcRoom(rr.RoomProxy, rr.GameID, rr.AgentID, rr.RoomID) |
|||
if replyOpt == nil { |
|||
log.Debug("初始化房间失败") |
|||
} else { |
|||
err1 := json.Unmarshal([]byte(replyOpt.RoomOpts), rr.Opt) |
|||
if err1 != nil { |
|||
log.Debug(err1) |
|||
} |
|||
} |
|||
|
|||
log.Debug("房间配置: ", rr.Opt) |
|||
|
|||
//机器人数
|
|||
rr.MaxRobotPlayerCount = 0 |
|||
//房间最大人数
|
|||
rr.MaxPlayerCount = 100 |
|||
// 个人倍率
|
|||
rr.PersonalRate = rr.Opt.PersonalRate |
|||
// 房间倍率
|
|||
rr.RoomRate = rr.Opt.RoomRate |
|||
// 最大轮数
|
|||
rr.GameMaxRound = 1000 // todo 这里需要从配置获取
|
|||
// 房间进入条件
|
|||
rr.RoomLimit = decimal.NewFromFloat(float64(rr.Opt.MinEnterAsset)) |
|||
// 底注
|
|||
rr.BetList = rr.Opt.BetAssetOptions |
|||
// 区域当前下注
|
|||
for _, s := range rr.BloodCtrl.AreaConfig { |
|||
rr.AreaAmount = append(rr.AreaAmount, protocol.BetAreaInfo{ |
|||
BetArea: s.AreaID, |
|||
}) |
|||
} |
|||
|
|||
OneWinCount := []int{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} |
|||
for i := 0; i < 1000000; i++ { |
|||
if i%1000 == 0 { |
|||
log.Debug("已经跑了 ", i, " 次了") |
|||
} |
|||
rr.RepeatRoom() |
|||
rr.OnEventGameConclude(2) |
|||
|
|||
//赢得区域
|
|||
switch rr.PokerMiddle.Color() { |
|||
case types.Red: |
|||
OneWinCount[protocol.AREA_HONG]++ |
|||
case types.Black: |
|||
OneWinCount[protocol.AREA_HEI]++ |
|||
case types.Plum: |
|||
OneWinCount[protocol.AREA_MEI]++ |
|||
case types.Diamond: |
|||
OneWinCount[protocol.AREA_FANG]++ |
|||
} |
|||
|
|||
rr.OnBuildOtherResultPoker() |
|||
|
|||
for i, poker := range rr.CardList { |
|||
if poker.Point() == rr.PokerMiddle.Point() { |
|||
if i%2 == 1 { |
|||
OneWinCount[protocol.AREA_BANHAR]++ |
|||
} else { |
|||
OneWinCount[protocol.AREA_ANDAR]++ |
|||
} |
|||
|
|||
TotalABCount := i + 1 |
|||
if TotalABCount < 9 { |
|||
OneWinCount[protocol.AREA_8]++ |
|||
} else if TotalABCount < 17 { |
|||
OneWinCount[protocol.AREA_16]++ |
|||
} else if TotalABCount < 25 { |
|||
OneWinCount[protocol.AREA_24]++ |
|||
} else { |
|||
OneWinCount[protocol.AREA_99]++ |
|||
} |
|||
|
|||
break |
|||
} |
|||
} |
|||
} |
|||
|
|||
log.Debug("♥️个数", OneWinCount[protocol.AREA_HONG], " ♠️个数", OneWinCount[protocol.AREA_HEI], " ♣️个数", OneWinCount[protocol.AREA_MEI], " ♦️个数", OneWinCount[protocol.AREA_FANG]) |
|||
log.Debug("A个数", OneWinCount[protocol.AREA_ANDAR], " B个数", OneWinCount[protocol.AREA_BANHAR]) |
|||
log.Debug("(1~8)个数", OneWinCount[protocol.AREA_8], " (9~16)个数", OneWinCount[protocol.AREA_16], " (17~24)个数", OneWinCount[protocol.AREA_24], " (>25)个数", OneWinCount[protocol.AREA_99]) |
|||
} |
@ -0,0 +1,48 @@ |
|||
package main |
|||
|
|||
import ( |
|||
"base/config/file" |
|||
"base/eventbus" |
|||
"base/eventbus/nats" |
|||
"xgame/game/TTZ/app" |
|||
|
|||
"base" |
|||
"base/cluster/node" |
|||
"base/config" |
|||
"base/locate/redis" |
|||
"base/log" |
|||
"base/log/zap" |
|||
"base/registry/consul" |
|||
"base/transport/rpcx" |
|||
) |
|||
|
|||
func main() { |
|||
// 设置日志
|
|||
log.SetLogger(zap.NewLogger(zap.WithCallerSkip(2))) |
|||
// 初始化事件总线
|
|||
eventbus.SetEventbus(nats.NewEventbus()) |
|||
// 设置配置中心
|
|||
config.SetConfigurator(config.NewConfigurator(config.WithSources(file.NewSource()))) |
|||
// 创建容器
|
|||
container := base.NewContainer() |
|||
// 创建用户定位器
|
|||
locator := redis.NewLocator() |
|||
// 创建服务发现
|
|||
registry := consul.NewRegistry() |
|||
// 创建RPC传输器
|
|||
transporter := rpcx.NewTransporter(rpcx.WithClientDiscovery(registry)) |
|||
// 创建网关组件
|
|||
component := node.NewNode( |
|||
node.WithLocator(locator), |
|||
node.WithRegistry(registry), |
|||
node.WithTransporter(transporter), |
|||
) |
|||
|
|||
// 初始化应用
|
|||
app.Init(component.Proxy()) |
|||
// 添加网关组件
|
|||
container.Add(component) |
|||
// 启动容器
|
|||
container.Serve() |
|||
|
|||
} |
Loading…
Reference in new issue