投注扣钱及结算扣钱
This commit is contained in:
parent
fc13e7625c
commit
f2133bfb80
@ -63,6 +63,10 @@ func (r *BaseRoom[Seat]) GameId() int {
|
|||||||
return r.gameId
|
return r.gameId
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (r *BaseRoom[Seat]) GetService() service.IService {
|
||||||
|
return r.srv
|
||||||
|
}
|
||||||
|
|
||||||
// 入座玩家数量
|
// 入座玩家数量
|
||||||
func (r *BaseRoom[Seat]) SeatPlayerNum(playerType PlayerType) int {
|
func (r *BaseRoom[Seat]) SeatPlayerNum(playerType PlayerType) int {
|
||||||
num := 0
|
num := 0
|
||||||
|
@ -41,6 +41,10 @@ func (r *HundredRoom) GameId() int {
|
|||||||
return r.room.GameId()
|
return r.room.GameId()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (r *HundredRoom) GetService() service.IService {
|
||||||
|
return r.room.GetService()
|
||||||
|
}
|
||||||
|
|
||||||
// 房间玩家数量
|
// 房间玩家数量
|
||||||
func (r *HundredRoom) GetPlayerNum(playerType PlayerType) int {
|
func (r *HundredRoom) GetPlayerNum(playerType PlayerType) int {
|
||||||
if playerType == PT_All {
|
if playerType == PT_All {
|
||||||
|
@ -9,6 +9,8 @@ import (
|
|||||||
"github.com/fox/fox/log"
|
"github.com/fox/fox/log"
|
||||||
"github.com/go-redis/redis/v8"
|
"github.com/go-redis/redis/v8"
|
||||||
"gorm.io/gorm"
|
"gorm.io/gorm"
|
||||||
|
"reflect"
|
||||||
|
"strconv"
|
||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -42,7 +44,23 @@ func (s *TableOp[T]) redisKey(id int64) string {
|
|||||||
return fmt.Sprintf("%s:%d", s.tableName(), id)
|
return fmt.Sprintf("%s:%d", s.tableName(), id)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 查找并返回结构体
|
||||||
func (s *TableOp[T]) findByRedis(id int64) *T {
|
func (s *TableOp[T]) findByRedis(id int64) *T {
|
||||||
|
maps := s.findByRedisMaps(id)
|
||||||
|
if len(maps) == 0 {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
us, err := serialization.MapToStruct[T](maps)
|
||||||
|
if err != nil {
|
||||||
|
log.ErrorF("serialization map to struct err: %v", err)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
//log.DebugF("findByRedis redis-key:%v result:%v", s.redisKey(id), us)
|
||||||
|
return us
|
||||||
|
}
|
||||||
|
|
||||||
|
// 查找并返回map
|
||||||
|
func (s *TableOp[T]) findByRedisMaps(id int64) map[string]string {
|
||||||
if s.rds == nil {
|
if s.rds == nil {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
@ -54,13 +72,7 @@ func (s *TableOp[T]) findByRedis(id int64) *T {
|
|||||||
if len(maps) == 0 {
|
if len(maps) == 0 {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
us, err := serialization.MapToStruct[T](maps)
|
return maps
|
||||||
if err != nil {
|
|
||||||
log.ErrorF("serialization map to struct err: %v", err)
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
//log.DebugF("findByRedis redis-key:%v result:%v", s.redisKey(id), us)
|
|
||||||
return us
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *TableOp[T]) writeRedis(id int64, t *T) {
|
func (s *TableOp[T]) writeRedis(id int64, t *T) {
|
||||||
@ -94,22 +106,6 @@ func (s *TableOp[T]) updateRedis(id int64, maps map[string]any) {
|
|||||||
_ = s.rds.Expire(context.Background(), s.redisKey(id), TableExpire).Err()
|
_ = s.rds.Expire(context.Background(), s.redisKey(id), TableExpire).Err()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *TableOp[T]) addRedis(id int64, maps map[string]int64) map[string]int64 {
|
|
||||||
if s.rds == nil {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
rets := map[string]int64{}
|
|
||||||
for k, v := range maps {
|
|
||||||
if ret, err := s.rds.HIncrBy(context.Background(), s.redisKey(id), k, v).Result(); err != nil {
|
|
||||||
log.ErrorF("redis-key:%v HIncrBy field err: %v", s.redisKey(id), k, err)
|
|
||||||
} else {
|
|
||||||
rets[k] = ret
|
|
||||||
}
|
|
||||||
}
|
|
||||||
_ = s.rds.Expire(context.Background(), s.redisKey(id), TableExpire).Err()
|
|
||||||
return rets
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *TableOp[T]) deleteRedis(id int64) {
|
func (s *TableOp[T]) deleteRedis(id int64) {
|
||||||
if s.rds == nil {
|
if s.rds == nil {
|
||||||
return
|
return
|
||||||
@ -166,7 +162,64 @@ func (s *TableOp[T]) Update(id int64, updates map[string]any) (*T, pb.ErrCode) {
|
|||||||
return &result.V, pb.ErrCode_OK
|
return &result.V, pb.ErrCode_OK
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *TableOp[T]) Add(id int64, res map[string]int64) (map[string]int64, pb.ErrCode) {
|
// 辅助函数:将map的keys转为字符串slice
|
||||||
|
func keysToStringSlice(m map[string]int64) []string {
|
||||||
|
keys := make([]string, 0, len(m))
|
||||||
|
for k := range m {
|
||||||
|
keys = append(keys, k)
|
||||||
|
}
|
||||||
|
return keys
|
||||||
|
}
|
||||||
|
|
||||||
|
// 获取资源
|
||||||
|
func (s *TableOp[T]) GetInt(id int64, resName []string) (map[string]int64, pb.ErrCode) {
|
||||||
|
mapFields := s.findByRedisMaps(id)
|
||||||
|
// 查询更新后的值到map
|
||||||
|
updatedValues := make(map[string]int64)
|
||||||
|
if len(mapFields) != 0 {
|
||||||
|
for _, name := range resName {
|
||||||
|
v, _ := strconv.ParseInt(mapFields[name], 10, 64)
|
||||||
|
updatedValues[name] = v
|
||||||
|
}
|
||||||
|
return updatedValues, pb.ErrCode_OK
|
||||||
|
}
|
||||||
|
|
||||||
|
// redis中没有值,从表中加载并写入redis
|
||||||
|
mapAny := make(map[string]any)
|
||||||
|
err := s.db.Model(new(T)).
|
||||||
|
Where("id = ?", id).
|
||||||
|
Take(&mapAny). // 扫描到map
|
||||||
|
Error
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
log.ErrorF("query updated values table:%v id:%v err:%v", s.tableName(), id, err)
|
||||||
|
return nil, pb.ErrCode_SystemErr
|
||||||
|
}
|
||||||
|
s.updateRedis(id, mapAny)
|
||||||
|
|
||||||
|
// 查询更新后的值到map
|
||||||
|
updatedValues = make(map[string]int64)
|
||||||
|
for _, name := range resName {
|
||||||
|
if val, ok := mapAny[name]; ok {
|
||||||
|
var v64 int64
|
||||||
|
switch v := val.(type) {
|
||||||
|
case int64:
|
||||||
|
v64 = v
|
||||||
|
case int, int32, uint, uint32, uint64:
|
||||||
|
v64 = reflect.ValueOf(v).Int()
|
||||||
|
case float32, float64:
|
||||||
|
v64 = int64(reflect.ValueOf(v).Float())
|
||||||
|
default:
|
||||||
|
// 处理无法转换的情况
|
||||||
|
}
|
||||||
|
updatedValues[name] = v64
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return updatedValues, pb.ErrCode_OK
|
||||||
|
}
|
||||||
|
|
||||||
|
// 增加或减少资源
|
||||||
|
func (s *TableOp[T]) AddInt(id int64, res map[string]int64) (map[string]int64, pb.ErrCode) {
|
||||||
addRes := map[string]any{}
|
addRes := map[string]any{}
|
||||||
for k, v := range res {
|
for k, v := range res {
|
||||||
addRes[k] = gorm.Expr(fmt.Sprintf("%v + ?", k), v)
|
addRes[k] = gorm.Expr(fmt.Sprintf("%v + ?", k), v)
|
||||||
@ -177,8 +230,26 @@ func (s *TableOp[T]) Add(id int64, res map[string]int64) (map[string]int64, pb.E
|
|||||||
log.ErrorF("add table:%v id:%v err:%v", s.tableName(), id, err)
|
log.ErrorF("add table:%v id:%v err:%v", s.tableName(), id, err)
|
||||||
return nil, pb.ErrCode_SystemErr
|
return nil, pb.ErrCode_SystemErr
|
||||||
}
|
}
|
||||||
rets := s.addRedis(id, res)
|
|
||||||
return rets, pb.ErrCode_OK
|
// 查询更新后的值到map
|
||||||
|
updatedValues := make(map[string]int64)
|
||||||
|
err = s.db.Model(new(T)).
|
||||||
|
Select(keysToStringSlice(res)). // 只选择需要返回的字段
|
||||||
|
Where("id = ?", id).
|
||||||
|
Take(&updatedValues). // 扫描到map
|
||||||
|
Error
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
log.ErrorF("query updated values table:%v id:%v err:%v", s.tableName(), id, err)
|
||||||
|
return nil, pb.ErrCode_SystemErr
|
||||||
|
}
|
||||||
|
|
||||||
|
mapAny := make(map[string]any)
|
||||||
|
for k, v := range updatedValues {
|
||||||
|
mapAny[k] = v
|
||||||
|
}
|
||||||
|
s.updateRedis(id, mapAny)
|
||||||
|
return updatedValues, pb.ErrCode_OK
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *TableOp[T]) Delete(id int64) (*T, pb.ErrCode) {
|
func (s *TableOp[T]) Delete(id int64) (*T, pb.ErrCode) {
|
||||||
|
@ -15,7 +15,7 @@ enum ErrCode
|
|||||||
VersionTooLow = 115; // 版本太低,无法登陆
|
VersionTooLow = 115; // 版本太低,无法登陆
|
||||||
|
|
||||||
Maintain = 120; // 系统维护
|
Maintain = 120; // 系统维护
|
||||||
GoldNotEnough = 125; // 金币不足
|
GoldNotEnough = 125; // 金币或其它资源不足
|
||||||
NotBetCount = 126; // 数场不投注被踢出
|
NotBetCount = 126; // 数场不投注被踢出
|
||||||
NotLeaveRoom = 127; // 无法离开房间(有下注)
|
NotLeaveRoom = 127; // 无法离开房间(有下注)
|
||||||
// color game
|
// color game
|
||||||
|
@ -215,7 +215,7 @@ message NtfColorSettle
|
|||||||
repeated UserBetAreaMul userAreaWin = 1; // 每个投注区域的下注及输赢
|
repeated UserBetAreaMul userAreaWin = 1; // 每个投注区域的下注及输赢
|
||||||
|
|
||||||
repeated ColorType threeDice = 2; // 骰子开出颜色
|
repeated ColorType threeDice = 2; // 骰子开出颜色
|
||||||
int64 totalWin = 3; // 总输赢
|
int64 totalWin = 3; // 总输赢,税后包含本金
|
||||||
int64 totalBet = 4; // 总投注
|
int64 totalBet = 4; // 总投注
|
||||||
int64 totalWinBaseBet = 6; // 赢钱区域的总投注
|
int64 totalWinBaseBet = 6; // 赢钱区域的总投注
|
||||||
int64 tax = 5; // 税
|
int64 tax = 5; // 税
|
||||||
|
@ -37,3 +37,9 @@ message RspLeaveRoom
|
|||||||
ErrCode code = 1;
|
ErrCode code = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// 加钱或扣钱失败通知
|
||||||
|
message NtfPayoutFail
|
||||||
|
{
|
||||||
|
ErrCode code = 1;
|
||||||
|
}
|
||||||
|
@ -18,6 +18,7 @@ enum MsgId
|
|||||||
RspEnterRoomId = 1003;
|
RspEnterRoomId = 1003;
|
||||||
ReqLeaveRoomId = 1004; // 离开房间
|
ReqLeaveRoomId = 1004; // 离开房间
|
||||||
RspLeaveRoomId = 1005;
|
RspLeaveRoomId = 1005;
|
||||||
|
NtfPayoutFailId = 1010; // 加减钱失败
|
||||||
|
|
||||||
// 聊天服 2000-2099
|
// 聊天服 2000-2099
|
||||||
ReqChatId = 2000; // 玩家聊天消息
|
ReqChatId = 2000; // 玩家聊天消息
|
||||||
|
@ -247,6 +247,59 @@ func (x *RspLeaveRoom) GetCode() ErrCode {
|
|||||||
return ErrCode_OK
|
return ErrCode_OK
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 加钱或扣钱失败通知
|
||||||
|
type NtfPayoutFail struct {
|
||||||
|
state protoimpl.MessageState `protogen:"open.v1"`
|
||||||
|
Code ErrCode `protobuf:"varint,1,opt,name=code,proto3,enum=pb.ErrCode" json:"code,omitempty"`
|
||||||
|
UserId int64 `protobuf:"varint,2,opt,name=userId,proto3" json:"userId,omitempty"`
|
||||||
|
unknownFields protoimpl.UnknownFields
|
||||||
|
sizeCache protoimpl.SizeCache
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *NtfPayoutFail) Reset() {
|
||||||
|
*x = NtfPayoutFail{}
|
||||||
|
mi := &file_common_proto_msgTypes[5]
|
||||||
|
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||||
|
ms.StoreMessageInfo(mi)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *NtfPayoutFail) String() string {
|
||||||
|
return protoimpl.X.MessageStringOf(x)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (*NtfPayoutFail) ProtoMessage() {}
|
||||||
|
|
||||||
|
func (x *NtfPayoutFail) ProtoReflect() protoreflect.Message {
|
||||||
|
mi := &file_common_proto_msgTypes[5]
|
||||||
|
if x != nil {
|
||||||
|
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||||
|
if ms.LoadMessageInfo() == nil {
|
||||||
|
ms.StoreMessageInfo(mi)
|
||||||
|
}
|
||||||
|
return ms
|
||||||
|
}
|
||||||
|
return mi.MessageOf(x)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Deprecated: Use NtfPayoutFail.ProtoReflect.Descriptor instead.
|
||||||
|
func (*NtfPayoutFail) Descriptor() ([]byte, []int) {
|
||||||
|
return file_common_proto_rawDescGZIP(), []int{5}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *NtfPayoutFail) GetCode() ErrCode {
|
||||||
|
if x != nil {
|
||||||
|
return x.Code
|
||||||
|
}
|
||||||
|
return ErrCode_OK
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *NtfPayoutFail) GetUserId() int64 {
|
||||||
|
if x != nil {
|
||||||
|
return x.UserId
|
||||||
|
}
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
var File_common_proto protoreflect.FileDescriptor
|
var File_common_proto protoreflect.FileDescriptor
|
||||||
|
|
||||||
const file_common_proto_rawDesc = "" +
|
const file_common_proto_rawDesc = "" +
|
||||||
@ -262,7 +315,10 @@ const file_common_proto_rawDesc = "" +
|
|||||||
"\broomType\x18\x03 \x01(\x05R\broomType\"\x0e\n" +
|
"\broomType\x18\x03 \x01(\x05R\broomType\"\x0e\n" +
|
||||||
"\fReqLeaveRoom\"/\n" +
|
"\fReqLeaveRoom\"/\n" +
|
||||||
"\fRspLeaveRoom\x12\x1f\n" +
|
"\fRspLeaveRoom\x12\x1f\n" +
|
||||||
"\x04code\x18\x01 \x01(\x0e2\v.pb.ErrCodeR\x04codeB\x11Z\x0fcommon/proto/pbb\x06proto3"
|
"\x04code\x18\x01 \x01(\x0e2\v.pb.ErrCodeR\x04code\"H\n" +
|
||||||
|
"\rNtfPayoutFail\x12\x1f\n" +
|
||||||
|
"\x04code\x18\x01 \x01(\x0e2\v.pb.ErrCodeR\x04code\x12\x16\n" +
|
||||||
|
"\x06userId\x18\x02 \x01(\x03R\x06userIdB\x11Z\x0fcommon/proto/pbb\x06proto3"
|
||||||
|
|
||||||
var (
|
var (
|
||||||
file_common_proto_rawDescOnce sync.Once
|
file_common_proto_rawDescOnce sync.Once
|
||||||
@ -276,24 +332,26 @@ func file_common_proto_rawDescGZIP() []byte {
|
|||||||
return file_common_proto_rawDescData
|
return file_common_proto_rawDescData
|
||||||
}
|
}
|
||||||
|
|
||||||
var file_common_proto_msgTypes = make([]protoimpl.MessageInfo, 5)
|
var file_common_proto_msgTypes = make([]protoimpl.MessageInfo, 6)
|
||||||
var file_common_proto_goTypes = []any{
|
var file_common_proto_goTypes = []any{
|
||||||
(*NtfKickOutUser)(nil), // 0: pb.NtfKickOutUser
|
(*NtfKickOutUser)(nil), // 0: pb.NtfKickOutUser
|
||||||
(*ReqEnterRoom)(nil), // 1: pb.ReqEnterRoom
|
(*ReqEnterRoom)(nil), // 1: pb.ReqEnterRoom
|
||||||
(*RspEnterRoom)(nil), // 2: pb.RspEnterRoom
|
(*RspEnterRoom)(nil), // 2: pb.RspEnterRoom
|
||||||
(*ReqLeaveRoom)(nil), // 3: pb.ReqLeaveRoom
|
(*ReqLeaveRoom)(nil), // 3: pb.ReqLeaveRoom
|
||||||
(*RspLeaveRoom)(nil), // 4: pb.RspLeaveRoom
|
(*RspLeaveRoom)(nil), // 4: pb.RspLeaveRoom
|
||||||
(ErrCode)(0), // 5: pb.ErrCode
|
(*NtfPayoutFail)(nil), // 5: pb.NtfPayoutFail
|
||||||
|
(ErrCode)(0), // 6: pb.ErrCode
|
||||||
}
|
}
|
||||||
var file_common_proto_depIdxs = []int32{
|
var file_common_proto_depIdxs = []int32{
|
||||||
5, // 0: pb.NtfKickOutUser.code:type_name -> pb.ErrCode
|
6, // 0: pb.NtfKickOutUser.code:type_name -> pb.ErrCode
|
||||||
5, // 1: pb.RspEnterRoom.code:type_name -> pb.ErrCode
|
6, // 1: pb.RspEnterRoom.code:type_name -> pb.ErrCode
|
||||||
5, // 2: pb.RspLeaveRoom.code:type_name -> pb.ErrCode
|
6, // 2: pb.RspLeaveRoom.code:type_name -> pb.ErrCode
|
||||||
3, // [3:3] is the sub-list for method output_type
|
6, // 3: pb.NtfPayoutFail.code:type_name -> pb.ErrCode
|
||||||
3, // [3:3] is the sub-list for method input_type
|
4, // [4:4] is the sub-list for method output_type
|
||||||
3, // [3:3] is the sub-list for extension type_name
|
4, // [4:4] is the sub-list for method input_type
|
||||||
3, // [3:3] is the sub-list for extension extendee
|
4, // [4:4] is the sub-list for extension type_name
|
||||||
0, // [0:3] is the sub-list for field type_name
|
4, // [4:4] is the sub-list for extension extendee
|
||||||
|
0, // [0:4] is the sub-list for field type_name
|
||||||
}
|
}
|
||||||
|
|
||||||
func init() { file_common_proto_init() }
|
func init() { file_common_proto_init() }
|
||||||
@ -308,7 +366,7 @@ func file_common_proto_init() {
|
|||||||
GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
|
GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
|
||||||
RawDescriptor: unsafe.Slice(unsafe.StringData(file_common_proto_rawDesc), len(file_common_proto_rawDesc)),
|
RawDescriptor: unsafe.Slice(unsafe.StringData(file_common_proto_rawDesc), len(file_common_proto_rawDesc)),
|
||||||
NumEnums: 0,
|
NumEnums: 0,
|
||||||
NumMessages: 5,
|
NumMessages: 6,
|
||||||
NumExtensions: 0,
|
NumExtensions: 0,
|
||||||
NumServices: 0,
|
NumServices: 0,
|
||||||
},
|
},
|
||||||
|
@ -35,6 +35,7 @@ const (
|
|||||||
MsgId_RspEnterRoomId MsgId = 1003
|
MsgId_RspEnterRoomId MsgId = 1003
|
||||||
MsgId_ReqLeaveRoomId MsgId = 1004 // 离开房间
|
MsgId_ReqLeaveRoomId MsgId = 1004 // 离开房间
|
||||||
MsgId_RspLeaveRoomId MsgId = 1005
|
MsgId_RspLeaveRoomId MsgId = 1005
|
||||||
|
MsgId_NtfPayoutFailId MsgId = 1010 // 加减钱失败
|
||||||
// 聊天服 2000-2099
|
// 聊天服 2000-2099
|
||||||
MsgId_ReqChatId MsgId = 2000 // 玩家聊天消息
|
MsgId_ReqChatId MsgId = 2000 // 玩家聊天消息
|
||||||
MsgId_RspChatId MsgId = 2001 // 复用C2SChatMsg
|
MsgId_RspChatId MsgId = 2001 // 复用C2SChatMsg
|
||||||
@ -74,6 +75,7 @@ var (
|
|||||||
1003: "RspEnterRoomId",
|
1003: "RspEnterRoomId",
|
||||||
1004: "ReqLeaveRoomId",
|
1004: "ReqLeaveRoomId",
|
||||||
1005: "RspLeaveRoomId",
|
1005: "RspLeaveRoomId",
|
||||||
|
1010: "NtfPayoutFailId",
|
||||||
2000: "ReqChatId",
|
2000: "ReqChatId",
|
||||||
2001: "RspChatId",
|
2001: "RspChatId",
|
||||||
2100: "ReqUserLoginId",
|
2100: "ReqUserLoginId",
|
||||||
@ -106,6 +108,7 @@ var (
|
|||||||
"RspEnterRoomId": 1003,
|
"RspEnterRoomId": 1003,
|
||||||
"ReqLeaveRoomId": 1004,
|
"ReqLeaveRoomId": 1004,
|
||||||
"RspLeaveRoomId": 1005,
|
"RspLeaveRoomId": 1005,
|
||||||
|
"NtfPayoutFailId": 1010,
|
||||||
"ReqChatId": 2000,
|
"ReqChatId": 2000,
|
||||||
"RspChatId": 2001,
|
"RspChatId": 2001,
|
||||||
"ReqUserLoginId": 2100,
|
"ReqUserLoginId": 2100,
|
||||||
@ -163,7 +166,7 @@ var File_msgId_proto protoreflect.FileDescriptor
|
|||||||
|
|
||||||
const file_msgId_proto_rawDesc = "" +
|
const file_msgId_proto_rawDesc = "" +
|
||||||
"\n" +
|
"\n" +
|
||||||
"\vmsgId.proto\x12\x02pb*\xaa\x05\n" +
|
"\vmsgId.proto\x12\x02pb*\xc0\x05\n" +
|
||||||
"\x05MsgId\x12\x0e\n" +
|
"\x05MsgId\x12\x0e\n" +
|
||||||
"\n" +
|
"\n" +
|
||||||
"MI_Unknown\x10\x00\x12\x12\n" +
|
"MI_Unknown\x10\x00\x12\x12\n" +
|
||||||
@ -172,7 +175,8 @@ const file_msgId_proto_rawDesc = "" +
|
|||||||
"\x0eReqEnterRoomId\x10\xea\a\x12\x13\n" +
|
"\x0eReqEnterRoomId\x10\xea\a\x12\x13\n" +
|
||||||
"\x0eRspEnterRoomId\x10\xeb\a\x12\x13\n" +
|
"\x0eRspEnterRoomId\x10\xeb\a\x12\x13\n" +
|
||||||
"\x0eReqLeaveRoomId\x10\xec\a\x12\x13\n" +
|
"\x0eReqLeaveRoomId\x10\xec\a\x12\x13\n" +
|
||||||
"\x0eRspLeaveRoomId\x10\xed\a\x12\x0e\n" +
|
"\x0eRspLeaveRoomId\x10\xed\a\x12\x14\n" +
|
||||||
|
"\x0fNtfPayoutFailId\x10\xf2\a\x12\x0e\n" +
|
||||||
"\tReqChatId\x10\xd0\x0f\x12\x0e\n" +
|
"\tReqChatId\x10\xd0\x0f\x12\x0e\n" +
|
||||||
"\tRspChatId\x10\xd1\x0f\x12\x13\n" +
|
"\tRspChatId\x10\xd1\x0f\x12\x13\n" +
|
||||||
"\x0eReqUserLoginId\x10\xb4\x10\x12\x13\n" +
|
"\x0eReqUserLoginId\x10\xb4\x10\x12\x13\n" +
|
||||||
|
@ -165,7 +165,7 @@ func (m *UserBindService) HashServiceNode(typeId pb.ServiceTypeId, uid int64) (*
|
|||||||
|
|
||||||
// 要查找的服务必须是状态服,无状态服不需要查找指定服务。
|
// 要查找的服务必须是状态服,无状态服不需要查找指定服务。
|
||||||
// 如果玩家是首次使用该服务,则随机一个服务并保存玩家该服务节点。下次查找时返回该节点。
|
// 如果玩家是首次使用该服务,则随机一个服务并保存玩家该服务节点。下次查找时返回该节点。
|
||||||
func (m *UserBindService) FindServiceNode(userId int64, typeId pb.ServiceTypeId) (*etcd.ServiceNode, error) {
|
func (m *UserBindService) FindServiceNode(typeId pb.ServiceTypeId, userId int64) (*etcd.ServiceNode, error) {
|
||||||
if userId > 0 {
|
if userId > 0 {
|
||||||
// 向redis中查询。redis中保留的服务节点不一定是可用的,还需要向etcd中验证
|
// 向redis中查询。redis中保留的服务节点不一定是可用的,还需要向etcd中验证
|
||||||
sName := m.LoadFromRedis(userId, typeId)
|
sName := m.LoadFromRedis(userId, typeId)
|
||||||
@ -187,26 +187,24 @@ func (m *UserBindService) FindServiceNode(userId int64, typeId pb.ServiceTypeId)
|
|||||||
return node, nil
|
return node, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// 查找玩家所有的玩法节点
|
// 对玩家所在有所有节点做操作
|
||||||
func (m *UserBindService) GetAllUserInGameServiceNode(userId int64) ([]*etcd.ServiceNode, error) {
|
func (m *UserBindService) RangeUserAllServiceNode(userId int64, proc func(node *etcd.ServiceNode) bool) {
|
||||||
if userId > 0 {
|
maps, err := m.rdb.HGetAll(context.Background(), m.makeRedisKey(userId)).Result()
|
||||||
maps, err := m.rdb.HGetAll(context.Background(), m.makeRedisKey(userId)).Result()
|
if err != nil && err != redis.Nil {
|
||||||
if err != nil && err != redis.Nil {
|
log.ErrorF("user:%v get all service error:%v", userId, err.Error())
|
||||||
log.ErrorF("user:%v get all service error:%v", err.Error())
|
return
|
||||||
return nil, err
|
}
|
||||||
}
|
if len(maps) > 0 {
|
||||||
if len(maps) > 0 {
|
m.etcdRegistry.GetNodes().Range(func(k, v interface{}) bool {
|
||||||
inGames := make([]*etcd.ServiceNode, 0)
|
if node, ok := v.(etcd.ServiceNode); ok {
|
||||||
m.etcdRegistry.GetNodes().Range(func(k, v interface{}) bool {
|
if _, ok = maps[node.Name]; ok {
|
||||||
if node, ok := v.(etcd.ServiceNode); ok {
|
if !proc(&node) {
|
||||||
if _, ok = maps[node.Name]; ok && node.TypeId != int(pb.ServiceTypeId_STI_Gate) {
|
return false
|
||||||
inGames = append(inGames, &node)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return true
|
}
|
||||||
})
|
return true
|
||||||
return inGames, nil
|
})
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return nil, nil
|
return
|
||||||
}
|
}
|
||||||
|
@ -2,8 +2,6 @@ package room
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"game/common/proto/pb"
|
"game/common/proto/pb"
|
||||||
"game/common/userBindService"
|
|
||||||
"game/server/colorgame/model"
|
|
||||||
"github.com/fox/fox/ipb"
|
"github.com/fox/fox/ipb"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -55,9 +53,7 @@ func (rm *ColorRoom) checkLeaveRoom(user *ColorPlayer, iMsg *ipb.InternalMsg, re
|
|||||||
func (rm *ColorRoom) leaveRoom(user *ColorPlayer) {
|
func (rm *ColorRoom) leaveRoom(user *ColorPlayer) {
|
||||||
rm.DelPlayer(user.Id())
|
rm.DelPlayer(user.Id())
|
||||||
rm.userMgr.Del(user.ID)
|
rm.userMgr.Del(user.ID)
|
||||||
// 移除redis中玩家与本服务绑定关系
|
rm.bindService.DelUserService(user.ID, pb.ServiceTypeId_STI_ColorGame)
|
||||||
userService := userBindService.NewUserBindService(model.UserBindServiceRedis, nil)
|
|
||||||
userService.DelUserService(user.ID, pb.ServiceTypeId_STI_ColorGame)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (rm *ColorRoom) onLeaveRoom(user *ColorPlayer, iMsg *ipb.InternalMsg, req *pb.ReqLeaveRoom) {
|
func (rm *ColorRoom) onLeaveRoom(user *ColorPlayer, iMsg *ipb.InternalMsg, req *pb.ReqLeaveRoom) {
|
||||||
|
@ -4,7 +4,10 @@ import (
|
|||||||
"game/common/baseroom"
|
"game/common/baseroom"
|
||||||
"game/common/config/game"
|
"game/common/config/game"
|
||||||
"game/common/jackpot"
|
"game/common/jackpot"
|
||||||
|
modelUser "game/common/model/user"
|
||||||
"game/common/proto/pb"
|
"game/common/proto/pb"
|
||||||
|
"game/common/rpc"
|
||||||
|
"game/common/userBindService"
|
||||||
"game/server/chat/model"
|
"game/server/chat/model"
|
||||||
"github.com/fox/fox/log"
|
"github.com/fox/fox/log"
|
||||||
"github.com/fox/fox/processor"
|
"github.com/fox/fox/processor"
|
||||||
@ -13,7 +16,9 @@ import (
|
|||||||
|
|
||||||
type ColorRoom struct {
|
type ColorRoom struct {
|
||||||
*baseroom.HundredRoom
|
*baseroom.HundredRoom
|
||||||
userMgr *baseroom.PlayerMgr
|
userMgr *baseroom.PlayerMgr
|
||||||
|
bindService *userBindService.UserBindService
|
||||||
|
gameNo string
|
||||||
|
|
||||||
roomCfg *game.ColorRoomConfig
|
roomCfg *game.ColorRoomConfig
|
||||||
timingCfg *game.ColorGameTiming
|
timingCfg *game.ColorGameTiming
|
||||||
@ -32,11 +37,12 @@ type ColorRoom struct {
|
|||||||
betAreaInfo []*pb.ColorBetAreaInfo // 本局每个投注区域信息
|
betAreaInfo []*pb.ColorBetAreaInfo // 本局每个投注区域信息
|
||||||
}
|
}
|
||||||
|
|
||||||
func newColorRoom(id, roomType int, srv service.IService, userMgr *baseroom.PlayerMgr) (baseroom.IRoom, pb.ErrCode) {
|
func newColorRoom(id, roomType int, srv service.IService, userMgr *baseroom.PlayerMgr, bindService *userBindService.UserBindService) (baseroom.IRoom, pb.ErrCode) {
|
||||||
gameId := int(pb.ServiceTypeId_STI_ColorGame)
|
gameId := int(pb.ServiceTypeId_STI_ColorGame)
|
||||||
rm := &ColorRoom{
|
rm := &ColorRoom{
|
||||||
HundredRoom: nil,
|
HundredRoom: nil,
|
||||||
userMgr: userMgr,
|
userMgr: userMgr,
|
||||||
|
bindService: bindService,
|
||||||
roomCfg: &game.ColorRoomConfig{},
|
roomCfg: &game.ColorRoomConfig{},
|
||||||
timingCfg: &game.ColorGameTiming{},
|
timingCfg: &game.ColorGameTiming{},
|
||||||
status: 0,
|
status: 0,
|
||||||
@ -108,16 +114,42 @@ func (rm *ColorRoom) resetGameData() {
|
|||||||
rm.kickoutUsers()
|
rm.kickoutUsers()
|
||||||
}
|
}
|
||||||
|
|
||||||
// 当前拥有金币
|
func (rm *ColorRoom) GameNo() string {
|
||||||
func (rm *ColorRoom) GetGold(user *ColorPlayer) int64 {
|
return rm.gameNo
|
||||||
return user.Gold - user.totalBet
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// 加减金币
|
// 当前拥有金币
|
||||||
func (rm *ColorRoom) AddGold(user *ColorPlayer, add int64) (int64, bool) {
|
func (rm *ColorRoom) GetGold(user *ColorPlayer) int64 {
|
||||||
if user.Gold-user.totalBet+add < 0 {
|
return user.Gold
|
||||||
return user.Gold - user.totalBet, false
|
}
|
||||||
}
|
|
||||||
user.totalBet += add
|
// 加减金币 预加减,没有真实向db服请求
|
||||||
return user.Gold - user.totalBet, true
|
func (rm *ColorRoom) AddGold(user *ColorPlayer, add int64) (int64, bool) {
|
||||||
|
if user.Gold+add < 0 {
|
||||||
|
return user.Gold, false
|
||||||
|
}
|
||||||
|
user.Gold += add
|
||||||
|
return user.Gold, true
|
||||||
|
}
|
||||||
|
|
||||||
|
// 从db服拿到最新数据,重置玩家数据
|
||||||
|
func (rm *ColorRoom) setGold(user *ColorPlayer, gold int64) {
|
||||||
|
user.Gold = gold
|
||||||
|
}
|
||||||
|
|
||||||
|
// 加减金币 真实抠钱
|
||||||
|
func (rm *ColorRoom) rpcPayoutGold(user *ColorPlayer, add int64, reason string) (int64, bool) {
|
||||||
|
resName := "gold"
|
||||||
|
res, code := rpc.RpcAddUserRes(rm.bindService, rm.GetService(), user.Id(), &modelUser.AddUserRes{
|
||||||
|
GameId: rm.GameId(),
|
||||||
|
GameNo: rm.GameNo(),
|
||||||
|
Reason: reason,
|
||||||
|
AddRes: map[string]int64{
|
||||||
|
resName: add,
|
||||||
|
},
|
||||||
|
})
|
||||||
|
if code == pb.ErrCode_OK {
|
||||||
|
return res[resName], true
|
||||||
|
}
|
||||||
|
return 0, false
|
||||||
}
|
}
|
||||||
|
@ -3,14 +3,15 @@ package room
|
|||||||
import (
|
import (
|
||||||
"game/common/baseroom"
|
"game/common/baseroom"
|
||||||
"game/common/proto/pb"
|
"game/common/proto/pb"
|
||||||
|
"game/common/userBindService"
|
||||||
"github.com/fox/fox/service"
|
"github.com/fox/fox/service"
|
||||||
)
|
)
|
||||||
|
|
||||||
type RoomFactory struct {
|
type RoomFactory struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *RoomFactory) CreateRoom(id, roomType int, srv service.IService, userMgr *baseroom.PlayerMgr) (baseroom.IRoom, pb.ErrCode) {
|
func (r *RoomFactory) CreateRoom(id, roomType int, srv service.IService, userMgr *baseroom.PlayerMgr, bindService *userBindService.UserBindService) (baseroom.IRoom, pb.ErrCode) {
|
||||||
return newColorRoom(id, roomType, srv, userMgr)
|
return newColorRoom(id, roomType, srv, userMgr, bindService)
|
||||||
}
|
}
|
||||||
|
|
||||||
func GetPlayer(p baseroom.IPlayer) *ColorPlayer {
|
func GetPlayer(p baseroom.IPlayer) *ColorPlayer {
|
||||||
|
@ -14,6 +14,11 @@ import (
|
|||||||
"sync"
|
"sync"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
ReasonBet = "bet" // 扣钱原因:投注
|
||||||
|
ReasonSettle = "settle" // 扣钱或加钱原因:结算
|
||||||
|
)
|
||||||
|
|
||||||
func (rm *ColorRoom) setStatus(status pb.ColorGameStatus) {
|
func (rm *ColorRoom) setStatus(status pb.ColorGameStatus) {
|
||||||
rm.status = status
|
rm.status = status
|
||||||
rm.statusTime = xtime.Now().TimestampMilli()
|
rm.statusTime = xtime.Now().TimestampMilli()
|
||||||
@ -300,8 +305,8 @@ func (rm *ColorRoom) calculateUserScore(user *ColorPlayer, jpArea pb.ColorBetAre
|
|||||||
gold = win2 * (100 - rm.roomCfg.Rate) / 100
|
gold = win2 * (100 - rm.roomCfg.Rate) / 100
|
||||||
// 算税()
|
// 算税()
|
||||||
msg.Tax += win2 - gold
|
msg.Tax += win2 - gold
|
||||||
// 加回投注本金
|
//// 加回投注本金
|
||||||
gold += user.totalBets[winArea.Area]
|
//gold += user.totalBets[winArea.Area]
|
||||||
msg.TotalWin += gold
|
msg.TotalWin += gold
|
||||||
// 统计赢区的下注总额
|
// 统计赢区的下注总额
|
||||||
msg.TotalWinBaseBet += user.totalBets[winArea.Area]
|
msg.TotalWinBaseBet += user.totalBets[winArea.Area]
|
||||||
@ -313,8 +318,8 @@ func (rm *ColorRoom) calculateUserScore(user *ColorPlayer, jpArea pb.ColorBetAre
|
|||||||
gold = jpScore * (100 - rm.roomCfg.Rate) / 100
|
gold = jpScore * (100 - rm.roomCfg.Rate) / 100
|
||||||
// 算税()
|
// 算税()
|
||||||
msg.Tax += win2 - gold
|
msg.Tax += win2 - gold
|
||||||
// 加回投注本金
|
//// 加回投注本金
|
||||||
gold += user.totalBets[winArea.Area]
|
//gold += user.totalBets[winArea.Area]
|
||||||
msg.TotalWin += gold
|
msg.TotalWin += gold
|
||||||
// 统计赢区的下注总额
|
// 统计赢区的下注总额
|
||||||
msg.TotalWinBaseBet += user.totalBets[winArea.Area]
|
msg.TotalWinBaseBet += user.totalBets[winArea.Area]
|
||||||
@ -337,22 +342,24 @@ func (rm *ColorRoom) calculateUserScore(user *ColorPlayer, jpArea pb.ColorBetAre
|
|||||||
|
|
||||||
// 和平台做结算
|
// 和平台做结算
|
||||||
func (rm *ColorRoom) settle() {
|
func (rm *ColorRoom) settle() {
|
||||||
//var allWinner []*pb.ColorPinoyLiveBigWinner
|
|
||||||
rm.calculateAllUserScore()
|
rm.calculateAllUserScore()
|
||||||
wg := new(sync.WaitGroup)
|
wg := new(sync.WaitGroup)
|
||||||
rm.RangePlayer(func(u baseroom.IPlayer) bool {
|
rm.RangePlayer(func(u baseroom.IPlayer) bool {
|
||||||
wg.Add(1)
|
|
||||||
user := GetPlayer(u)
|
user := GetPlayer(u)
|
||||||
ksync.GoSafe(func() {
|
// 没有赢分
|
||||||
defer wg.Done()
|
if user.settleMsg.TotalWin < 1 {
|
||||||
if user.totalBet > 0 {
|
return true
|
||||||
// 和平台做赢钱结算
|
}
|
||||||
//_, err := rm.TransInoutGameEnd(u, 0, u.SettleMsg.TotalWin, u.SettleMsg.Tax)
|
ksync.GroupGo(wg, func() {
|
||||||
//if err != nil {
|
afterGold, ok := rm.rpcPayoutGold(user, user.settleMsg.TotalWin, ReasonSettle)
|
||||||
// log.Error(rm.Log(err.Error()))
|
if !ok {
|
||||||
//}
|
log.Error(rm.UserLog(user.ID, "add gold:%v fail", user.settleMsg.TotalWin))
|
||||||
|
} else {
|
||||||
|
rm.GetService().RunOnce(func() {
|
||||||
|
rm.setGold(user, afterGold)
|
||||||
|
})
|
||||||
}
|
}
|
||||||
}, nil)
|
})
|
||||||
return true
|
return true
|
||||||
})
|
})
|
||||||
wg.Wait()
|
wg.Wait()
|
||||||
@ -476,3 +483,41 @@ func (rm *ColorRoom) getProtoUser(user *ColorPlayer) *pb.ColorUser {
|
|||||||
}
|
}
|
||||||
return u
|
return u
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 结束下注,扣除投注玩家的投注金额
|
||||||
|
func (rm *ColorRoom) endBetPayoutUser() {
|
||||||
|
var failer []*ColorPlayer
|
||||||
|
var mt sync.Mutex
|
||||||
|
wg := &sync.WaitGroup{}
|
||||||
|
rm.RangePlayer(func(u baseroom.IPlayer) bool {
|
||||||
|
user := GetPlayer(u)
|
||||||
|
// 没有下注
|
||||||
|
if user.totalBet < 1 {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
ksync.GroupGo(wg, func() {
|
||||||
|
afterGold, ok := rm.rpcPayoutGold(user, -user.totalBet, ReasonBet)
|
||||||
|
if !ok {
|
||||||
|
mt.Lock()
|
||||||
|
failer = append(failer, user)
|
||||||
|
mt.Unlock()
|
||||||
|
} else {
|
||||||
|
rm.GetService().RunOnce(func() {
|
||||||
|
rm.setGold(user, afterGold)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
return true
|
||||||
|
})
|
||||||
|
wg.Wait()
|
||||||
|
|
||||||
|
// 移除扣钱失败玩家的投注信息
|
||||||
|
for _, u := range failer {
|
||||||
|
u.totalBet = 0
|
||||||
|
for pos := range u.totalBets {
|
||||||
|
u.totalBets[pos] = 0
|
||||||
|
}
|
||||||
|
rm.notifyPayoutFail(u, pb.ErrCode_GoldNotEnough)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -22,6 +22,7 @@ func (rm *ColorRoom) gameStartBetting() {
|
|||||||
|
|
||||||
func (rm *ColorRoom) gameEndBetting() {
|
func (rm *ColorRoom) gameEndBetting() {
|
||||||
rm.setStatus(pb.ColorGameStatus_CGS_BetEnd)
|
rm.setStatus(pb.ColorGameStatus_CGS_BetEnd)
|
||||||
|
rm.endBetPayoutUser()
|
||||||
rm.updateEndBetAreaMul()
|
rm.updateEndBetAreaMul()
|
||||||
rm.notifyEndBetting()
|
rm.notifyEndBetting()
|
||||||
rm.NewTimer(TtOpenThreeDices, time.Duration(rm.timingCfg.EndBetting)*time.Millisecond)
|
rm.NewTimer(TtOpenThreeDices, time.Duration(rm.timingCfg.EndBetting)*time.Millisecond)
|
||||||
|
@ -68,6 +68,11 @@ func (rm *ColorRoom) notifyKickoutUser(user *ColorPlayer, code pb.ErrCode) {
|
|||||||
rm.SendMsg(user, pb.MsgId_NtfKickOutUserId, &pb.NtfKickOutUser{Code: code})
|
rm.SendMsg(user, pb.MsgId_NtfKickOutUserId, &pb.NtfKickOutUser{Code: code})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 每秒更新各投注区域投注信息
|
||||||
|
func (rm *ColorRoom) notifyPayoutFail(user *ColorPlayer, code pb.ErrCode) {
|
||||||
|
rm.SendMsg(user, pb.MsgId_NtfPayoutFailId, &pb.NtfPayoutFail{Code: code})
|
||||||
|
}
|
||||||
|
|
||||||
// 推送房间信息给玩家
|
// 推送房间信息给玩家
|
||||||
func (rm *ColorRoom) notifyColorRoomInfo(user *ColorPlayer) {
|
func (rm *ColorRoom) notifyColorRoomInfo(user *ColorPlayer) {
|
||||||
ntf := &pb.NtfColorRoomInfo{
|
ntf := &pb.NtfColorRoomInfo{
|
||||||
|
@ -20,7 +20,7 @@ func (s *ColorService) initProcessor() {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
// 登录或注册
|
// 进房间
|
||||||
func (s *ColorService) onEnterRoom(iMsg *ipb.InternalMsg, req *pb.ReqMatchRoom) {
|
func (s *ColorService) onEnterRoom(iMsg *ipb.InternalMsg, req *pb.ReqMatchRoom) {
|
||||||
ksync.GoSafe(func() {
|
ksync.GoSafe(func() {
|
||||||
us, code := rpc.RpcGetGameUser(s.bindService, s, iMsg.UserId)
|
us, code := rpc.RpcGetGameUser(s.bindService, s, iMsg.UserId)
|
||||||
|
@ -54,7 +54,7 @@ func newColorService(serviceId int) service.IService {
|
|||||||
s := new(ColorService)
|
s := new(ColorService)
|
||||||
s.playerMgr = baseroom.NewPlayerMgr(nil)
|
s.playerMgr = baseroom.NewPlayerMgr(nil)
|
||||||
factory := &room.RoomFactory{}
|
factory := &room.RoomFactory{}
|
||||||
s.room, _ = factory.CreateRoom(int(pb.ServiceTypeId_STI_ColorGame), 0, s, s.playerMgr)
|
s.room, _ = factory.CreateRoom(int(pb.ServiceTypeId_STI_ColorGame), 0, s, s.playerMgr, s.bindService)
|
||||||
s.status = baseroom.SsWorking
|
s.status = baseroom.SsWorking
|
||||||
//s.roomMgr = baseroom.NewRoomMgr(&room.RoomFactory{})
|
//s.roomMgr = baseroom.NewRoomMgr(&room.RoomFactory{})
|
||||||
|
|
||||||
|
@ -84,7 +84,7 @@ func (s *DbService) onGetUserByUid(iMsg *ipb.InternalMsg) *ipb.InternalMsg {
|
|||||||
return iMsg
|
return iMsg
|
||||||
}
|
}
|
||||||
|
|
||||||
// 获取用户数据,没有则创建
|
// 获取用户资源数据,没有则创建
|
||||||
func (s *DbService) onGetUserResources(iMsg *ipb.InternalMsg) *ipb.InternalMsg {
|
func (s *DbService) onGetUserResources(iMsg *ipb.InternalMsg) *ipb.InternalMsg {
|
||||||
operationDb[user.UserResources](iMsg, func(res *user.UserResources) (*user.UserResources, pb.ErrCode) {
|
operationDb[user.UserResources](iMsg, func(res *user.UserResources) (*user.UserResources, pb.ErrCode) {
|
||||||
if us1, code := operation.NewUserResourcesOp().Find(res.UID); code != pb.ErrCode_OK {
|
if us1, code := operation.NewUserResourcesOp().Find(res.UID); code != pb.ErrCode_OK {
|
||||||
@ -96,7 +96,7 @@ func (s *DbService) onGetUserResources(iMsg *ipb.InternalMsg) *ipb.InternalMsg {
|
|||||||
return iMsg
|
return iMsg
|
||||||
}
|
}
|
||||||
|
|
||||||
// 添加用户资源,负数为减少
|
// 添加用户资源,负数为减少。资源不能为负数
|
||||||
func (s *DbService) onAddUserResources(iMsg *ipb.InternalMsg) *ipb.InternalMsg {
|
func (s *DbService) onAddUserResources(iMsg *ipb.InternalMsg) *ipb.InternalMsg {
|
||||||
addUserRes := &user.AddUserRes{}
|
addUserRes := &user.AddUserRes{}
|
||||||
err := json.Unmarshal(iMsg.Msg, addUserRes)
|
err := json.Unmarshal(iMsg.Msg, addUserRes)
|
||||||
@ -105,7 +105,26 @@ func (s *DbService) onAddUserResources(iMsg *ipb.InternalMsg) *ipb.InternalMsg {
|
|||||||
iMsg.RpcCode = int32(pb.ErrCode_SystemErr)
|
iMsg.RpcCode = int32(pb.ErrCode_SystemErr)
|
||||||
return iMsg
|
return iMsg
|
||||||
}
|
}
|
||||||
rets, code := operation.NewUserResourcesOp().Add(iMsg.UserId, addUserRes.AddRes)
|
// 获取资源的值并检查够不够操作
|
||||||
|
resOp := operation.NewUserResourcesOp()
|
||||||
|
var resNames []string
|
||||||
|
for name := range addUserRes.AddRes {
|
||||||
|
resNames = append(resNames, name)
|
||||||
|
}
|
||||||
|
userRes, code := resOp.GetInt(iMsg.UserId, resNames)
|
||||||
|
if code != pb.ErrCode_OK {
|
||||||
|
iMsg.RpcCode = int32(code)
|
||||||
|
return iMsg
|
||||||
|
}
|
||||||
|
for resName, resValue := range userRes {
|
||||||
|
// 如果add为负数则为扣除,
|
||||||
|
if addUserRes.AddRes[resName]+resValue < 1 {
|
||||||
|
iMsg.RpcCode = int32(pb.ErrCode_GoldNotEnough)
|
||||||
|
return iMsg
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
rets, code := resOp.AddInt(iMsg.UserId, addUserRes.AddRes)
|
||||||
if code != pb.ErrCode_OK {
|
if code != pb.ErrCode_OK {
|
||||||
iMsg.RpcCode = int32(code)
|
iMsg.RpcCode = int32(code)
|
||||||
return iMsg
|
return iMsg
|
||||||
|
@ -2,6 +2,7 @@ package server
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"game/common/proto/pb"
|
"game/common/proto/pb"
|
||||||
|
"github.com/fox/fox/etcd"
|
||||||
"github.com/fox/fox/ipb"
|
"github.com/fox/fox/ipb"
|
||||||
"github.com/fox/fox/processor"
|
"github.com/fox/fox/processor"
|
||||||
"github.com/fox/fox/service"
|
"github.com/fox/fox/service"
|
||||||
@ -15,7 +16,13 @@ func (s *LobbyService) initProcessor() {
|
|||||||
|
|
||||||
// 玩家上线,告诉玩家在哪个玩法中
|
// 玩家上线,告诉玩家在哪个玩法中
|
||||||
func (s *LobbyService) onUserOnline(iMsg *ipb.InternalMsg, msg *pb.NtfUserOnline) {
|
func (s *LobbyService) onUserOnline(iMsg *ipb.InternalMsg, msg *pb.NtfUserOnline) {
|
||||||
nodes, _ := s.bindService.GetAllUserInGameServiceNode(msg.UserId)
|
var nodes []*etcd.ServiceNode
|
||||||
|
s.bindService.RangeUserAllServiceNode(msg.UserId, func(node *etcd.ServiceNode) bool {
|
||||||
|
if node.TypeId != int(pb.ServiceTypeId_STI_Gate) {
|
||||||
|
nodes = append(nodes, node)
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
})
|
||||||
ntf := &pb.NtfUserInService{}
|
ntf := &pb.NtfUserInService{}
|
||||||
for _, node := range nodes {
|
for _, node := range nodes {
|
||||||
ntf.ServiceNames = append(ntf.ServiceNames, node.Name)
|
ntf.ServiceNames = append(ntf.ServiceNames, node.Name)
|
||||||
|
@ -1,152 +0,0 @@
|
|||||||
package model
|
|
||||||
|
|
||||||
//import (
|
|
||||||
// "errors"
|
|
||||||
// "github.com/fox/fox/log"
|
|
||||||
// "golang.org/x/crypto/bcrypt"
|
|
||||||
// "gorm.io/gorm"
|
|
||||||
// "time"
|
|
||||||
//)
|
|
||||||
//
|
|
||||||
//const (
|
|
||||||
// AccountNormal = 1 // 正常
|
|
||||||
// AccountFrozen = 2 // 冻结
|
|
||||||
// AccountBanned = 3 // 封禁
|
|
||||||
//)
|
|
||||||
//
|
|
||||||
//// 玩家账户表
|
|
||||||
//type UserAccount struct {
|
|
||||||
// gorm.Model
|
|
||||||
// Username string `gorm:"type:varchar(32);uniqueIndex;not null"` // 用户名
|
|
||||||
// Password string `gorm:"type:varchar(255);not null"` // 密码哈希
|
|
||||||
// Email string `gorm:"type:varchar(100)"` // 邮箱(可选)
|
|
||||||
// Phone string `gorm:"type:varchar(20)"` // 手机号(可选)
|
|
||||||
// DeviceID string `gorm:"type:varchar(64);index"` // 设备ID
|
|
||||||
// LastLoginIP string `gorm:"type:varchar(45)"` // 最后登录IP(支持IPv6)
|
|
||||||
// LastLoginTime time.Time // 最后登录时间
|
|
||||||
// Status int `gorm:"type:tinyint;default:1"` // 账号状态 1-正常 2-冻结 3-封禁
|
|
||||||
// RegisterIP string `gorm:"type:varchar(45)"` // 注册IP
|
|
||||||
// RegisterTime time.Time `gorm:"type:TIMESTAMP;default:CURRENT_TIMESTAMP"` // 注册时间
|
|
||||||
//}
|
|
||||||
//
|
|
||||||
//// 玩家登录记录表
|
|
||||||
//type UserLoginLog struct {
|
|
||||||
// gorm.Model
|
|
||||||
// PlayerID uint `gorm:"index"` // 关联玩家ID
|
|
||||||
// LoginIP string `gorm:"type:varchar(45);not null"` // 登录IP
|
|
||||||
// LoginTime time.Time `gorm:"type:TIMESTAMP;default:CURRENT_TIMESTAMP"` // 登录时间
|
|
||||||
// DeviceInfo string `gorm:"type:varchar(255)"` // 设备信息(JSON格式)
|
|
||||||
// LoginResult bool // 登录结果 true-成功 false-失败
|
|
||||||
// FailReason string `gorm:"type:varchar(100)"` // 失败原因
|
|
||||||
//}
|
|
||||||
//
|
|
||||||
//type UserLoginOp struct {
|
|
||||||
// db *gorm.DB
|
|
||||||
// logDb *gorm.DB
|
|
||||||
//}
|
|
||||||
//
|
|
||||||
//func NewUserLoginOp() *UserLoginOp {
|
|
||||||
// return &UserLoginOp{db: UserDB, logDb: LogDB}
|
|
||||||
//}
|
|
||||||
//
|
|
||||||
//var (
|
|
||||||
// ErrUserOrPassword = errors.New("user or password was error")
|
|
||||||
// ErrAccountFrozen = errors.New("account frozen")
|
|
||||||
// ErrAccountBanned = errors.New("account banned")
|
|
||||||
//)
|
|
||||||
//
|
|
||||||
//func (s *UserLoginOp) Login(username, password, ip, deviceID string) (*UserAccount, error) {
|
|
||||||
// var user UserAccount
|
|
||||||
// err := s.db.Where("username = ?", username).First(&user).Error
|
|
||||||
// if err != nil {
|
|
||||||
// return nil, err
|
|
||||||
// }
|
|
||||||
// // 验证密码
|
|
||||||
// if err = bcrypt.CompareHashAndPassword([]byte(user.Password), []byte(password)); err != nil {
|
|
||||||
// s.recordLoginLog(user.ID, ip, deviceID, false, ErrUserOrPassword.Error())
|
|
||||||
// return nil, ErrUserOrPassword
|
|
||||||
// }
|
|
||||||
// // 检查账号状态
|
|
||||||
// switch user.Status {
|
|
||||||
// case AccountNormal:
|
|
||||||
//
|
|
||||||
// case AccountFrozen:
|
|
||||||
// s.recordLoginLog(user.ID, ip, deviceID, false, ErrAccountFrozen.Error())
|
|
||||||
// return nil, ErrAccountFrozen
|
|
||||||
// case AccountBanned:
|
|
||||||
// s.recordLoginLog(user.ID, ip, deviceID, false, ErrAccountBanned.Error())
|
|
||||||
// return nil, ErrAccountBanned
|
|
||||||
// }
|
|
||||||
// // 更新最后登录信息
|
|
||||||
// user.LastLoginIP = ip
|
|
||||||
// user.LastLoginTime = time.Now()
|
|
||||||
// _ = s.db.Save(&user).Error
|
|
||||||
//
|
|
||||||
// // 记录成功登录日志
|
|
||||||
// s.recordLoginLog(user.ID, ip, deviceID, true, "")
|
|
||||||
//
|
|
||||||
// // 6. 生成访问令牌
|
|
||||||
// token, err := generateToken(user.ID, user.Username)
|
|
||||||
// if err != nil {
|
|
||||||
// return nil, err
|
|
||||||
// }
|
|
||||||
// user.Password = token
|
|
||||||
// return &user, err
|
|
||||||
//}
|
|
||||||
//
|
|
||||||
//// 注册新用户
|
|
||||||
//func (s *UserLoginOp) RegisterNewUser(username, password, ip, deviceID string) (*UserAccount, error) {
|
|
||||||
// // 密码加密
|
|
||||||
// hashedPassword, err := bcrypt.GenerateFromPassword([]byte(password), bcrypt.DefaultCost)
|
|
||||||
// if err != nil {
|
|
||||||
// return nil, err
|
|
||||||
// }
|
|
||||||
// user := UserAccount{
|
|
||||||
// Username: username,
|
|
||||||
// Password: string(hashedPassword),
|
|
||||||
// DeviceID: deviceID,
|
|
||||||
// RegisterIP: ip,
|
|
||||||
// Status: 1,
|
|
||||||
// LastLoginIP: ip,
|
|
||||||
// LastLoginTime: time.Now(),
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// if err := s.db.Create(&user).Error; err != nil {
|
|
||||||
// return nil, err
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// s.recordLoginLog(user.ID, ip, deviceID, true, "")
|
|
||||||
//
|
|
||||||
// // 生成访问令牌
|
|
||||||
// token, err := generateToken(user.ID, user.Username)
|
|
||||||
// if err != nil {
|
|
||||||
// return nil, err
|
|
||||||
// }
|
|
||||||
// user.Password = token
|
|
||||||
//
|
|
||||||
// return &user, nil
|
|
||||||
//}
|
|
||||||
//
|
|
||||||
//// 记录登录日志
|
|
||||||
//func (s *UserLoginOp) recordLoginLog(userID uint, ip, deviceID string, success bool, failReason string) {
|
|
||||||
// logEntry := UserLoginLog{
|
|
||||||
// PlayerID: userID,
|
|
||||||
// LoginIP: ip,
|
|
||||||
// DeviceInfo: deviceID,
|
|
||||||
// LoginResult: success,
|
|
||||||
// FailReason: failReason,
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// if err := s.logDb.Create(&logEntry).Error; err != nil {
|
|
||||||
// log.ErrorF("记录登录日志失败: %v", err)
|
|
||||||
// }
|
|
||||||
//}
|
|
||||||
//
|
|
||||||
//// 生成JWT令牌(简化版)
|
|
||||||
//func generateToken(userID uint, username string) (string, error) {
|
|
||||||
// _ = userID
|
|
||||||
// _ = username
|
|
||||||
// // 这里应该使用JWT库生成实际令牌
|
|
||||||
// // 简化实现,实际项目中请使用安全的JWT实现
|
|
||||||
// return "generated-token-placeholder", nil
|
|
||||||
//}
|
|
@ -24,7 +24,7 @@ func NewMatchMgr() *MatchMgr {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//func (mgr *MatchMgr) Add(us *MatchPlayer, sid pb.ServiceTypeId, roomType int32) {
|
//func (mgr *MatchMgr) AddInt(us *MatchPlayer, sid pb.ServiceTypeId, roomType int32) {
|
||||||
// users, _ := mgr.users[sid]
|
// users, _ := mgr.users[sid]
|
||||||
// for _, u := range users {
|
// for _, u := range users {
|
||||||
// if u.ID == us.ID {
|
// if u.ID == us.ID {
|
||||||
|
@ -18,7 +18,7 @@ func (s *MatchService) onMatchRoom(iMsg *ipb.InternalMsg, req *pb.ReqMatchRoom)
|
|||||||
gameId := pb.ServiceTypeId(req.GameId)
|
gameId := pb.ServiceTypeId(req.GameId)
|
||||||
switch gameId {
|
switch gameId {
|
||||||
case pb.ServiceTypeId_STI_ColorGame:
|
case pb.ServiceTypeId_STI_ColorGame:
|
||||||
node, err := s.bindService.FindServiceNode(iMsg.UserId, gameId)
|
node, err := s.bindService.FindServiceNode(gameId, iMsg.UserId)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.ErrorF("db service node error:%v", err)
|
log.ErrorF("db service node error:%v", err)
|
||||||
s.SendServiceMsg(service.TopicEx(iMsg.ServiceName), iMsg.ConnId, iMsg.UserId,
|
s.SendServiceMsg(service.TopicEx(iMsg.ServiceName), iMsg.ConnId, iMsg.UserId,
|
||||||
|
Loading…
x
Reference in New Issue
Block a user