登陆服
This commit is contained in:
parent
ae28cbb0e8
commit
e2f75e2db7
@ -7,6 +7,8 @@ type Common[T any] struct {
|
|||||||
Etcd Etcd `json:"etcd"`
|
Etcd Etcd `json:"etcd"`
|
||||||
Redis Redis `json:"redis"`
|
Redis Redis `json:"redis"`
|
||||||
Nats Nats `json:"nats"`
|
Nats Nats `json:"nats"`
|
||||||
|
Mysql Mysql `json:"mysql"`
|
||||||
|
MysqlLog Mysql `json:"mysql_log"`
|
||||||
Special *T `json:"special"`
|
Special *T `json:"special"`
|
||||||
GitCommit string `json:"git_commit"` // 服务当前的hash值
|
GitCommit string `json:"git_commit"` // 服务当前的hash值
|
||||||
GitBranch string `json:"git_branch"` // 服务当前的版本分支
|
GitBranch string `json:"git_branch"` // 服务当前的版本分支
|
||||||
@ -25,11 +27,12 @@ type Rabbitmq struct {
|
|||||||
VHost string `json:"v_host"`
|
VHost string `json:"v_host"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type DB struct {
|
type Mysql struct {
|
||||||
Host string `json:"host"`
|
Host string `json:"host"`
|
||||||
Port string `json:"port"`
|
Port string `json:"port"`
|
||||||
Username string `json:"username"`
|
Username string `json:"username"`
|
||||||
Password string `json:"password"`
|
Password string `json:"password"`
|
||||||
|
DbName string `json:"db_name"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type Redis struct {
|
type Redis struct {
|
||||||
|
@ -13,14 +13,21 @@ import (
|
|||||||
|
|
||||||
const (
|
const (
|
||||||
//ModeDev = "dev" // 开发服
|
//ModeDev = "dev" // 开发服
|
||||||
etcdKey = "etcd_config"
|
etcdKey = "etcd_config"
|
||||||
etcdAddress = "114.132.124.145:2379"
|
etcdAddress = "114.132.124.145:2379"
|
||||||
natsKey = "nats_config"
|
natsKey = "nats_config"
|
||||||
natsAddress = "nats://114.132.124.145:4222"
|
natsAddress = "nats://114.132.124.145:4222"
|
||||||
redisKey = "redis_config"
|
redisKey = "redis_config"
|
||||||
redisAddress = testHelper.Host
|
redisAddress = testHelper.Host
|
||||||
redisPort = testHelper.RedisPort
|
redisPort = testHelper.RedisPort
|
||||||
redisPassword = testHelper.RedisPassword
|
redisPassword = testHelper.RedisPassword
|
||||||
|
mysqlKey = "mysql_config"
|
||||||
|
mysqlAddress = "114.132.124.145"
|
||||||
|
mysqlPort = "3306"
|
||||||
|
mysqlUser = "game"
|
||||||
|
mysqlPasswd = "fox379@@zyxi"
|
||||||
|
mysqlDBName = "game"
|
||||||
|
mysqlLogDBName = "game_log"
|
||||||
)
|
)
|
||||||
|
|
||||||
func LoadSpecialConfig[T any](rd *redis.Client, specialKey string, comm *Common[T]) error {
|
func LoadSpecialConfig[T any](rd *redis.Client, specialKey string, comm *Common[T]) error {
|
||||||
@ -102,6 +109,26 @@ func LoadCommonConfig[T any](rd *redis.Client, GitCommit, GitBranch, BuildDate s
|
|||||||
} else {
|
} else {
|
||||||
err = json.Unmarshal([]byte(s), &comm.Redis)
|
err = json.Unmarshal([]byte(s), &comm.Redis)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 初始化mysql
|
||||||
|
s, err = rd.Get(context.Background(), mysqlKey).Result()
|
||||||
|
if err != nil && !errors.Is(err, redis.Nil) {
|
||||||
|
log.FatalF("init config:%v", err)
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
if s == "" {
|
||||||
|
log.DebugF("load config:empty mysql key")
|
||||||
|
comm.Mysql = Mysql{Host: mysqlAddress, Port: mysqlPort, Password: mysqlPasswd, Username: mysqlUser, DbName: mysqlDBName}
|
||||||
|
if bs, err := json.Marshal(&comm.Redis); err == nil {
|
||||||
|
err = rd.Set(context.Background(), mysqlKey, string(bs), 0).Err()
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
err = json.Unmarshal([]byte(s), &comm.Mysql)
|
||||||
|
}
|
||||||
|
|
||||||
|
comm.MysqlLog = comm.Mysql
|
||||||
|
comm.MysqlLog.DbName = mysqlLogDBName
|
||||||
|
|
||||||
return &comm, nil
|
return &comm, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
package serviceName
|
package serviceName
|
||||||
|
|
||||||
const (
|
const (
|
||||||
Gate = "gate"
|
Gate = "gate"
|
||||||
Chat = "chat"
|
Chat = "chat"
|
||||||
|
Login = "login"
|
||||||
)
|
)
|
||||||
|
36
docker.txt
Normal file
36
docker.txt
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
docker run -d --name my-nats \
|
||||||
|
-p 4222:4222 -p 8222:8222 \
|
||||||
|
nats
|
||||||
|
|
||||||
|
sudo docker run -d \
|
||||||
|
--name my-etcd \
|
||||||
|
-p 2379:2379 \
|
||||||
|
-p 2380:2380 \
|
||||||
|
quay.io/coreos/etcd:v3.6.0 \
|
||||||
|
etcd \
|
||||||
|
--name etcd-single \
|
||||||
|
--data-dir /etcd-data \
|
||||||
|
--initial-advertise-peer-urls http://0.0.0.0:2380 \
|
||||||
|
--listen-peer-urls http://0.0.0.0:2380 \
|
||||||
|
--advertise-client-urls http://0.0.0.0:2379 \
|
||||||
|
--listen-client-urls http://0.0.0.0:2379 \
|
||||||
|
--initial-cluster etcd-single=http://0.0.0.0:2380
|
||||||
|
|
||||||
|
docker run -d --name etcdkeeper -p 8080:8080 evildecay/etcdkeeper
|
||||||
|
|
||||||
|
sudo docker run -d \
|
||||||
|
--name my-redis \
|
||||||
|
-p 6379:6379 \
|
||||||
|
-e REDIS_PASSWORD=fox379@@zyxi \
|
||||||
|
redis:latest \
|
||||||
|
--requirepass fox379@@zyxi
|
||||||
|
|
||||||
|
|
||||||
|
sudo docker run -d \
|
||||||
|
--name mysql-server \
|
||||||
|
-e MYSQL_ROOT_PASSWORD=fox379@@zyxi \
|
||||||
|
-e MYSQL_DATABASE=game \
|
||||||
|
-e MYSQL_USER=game \
|
||||||
|
-e MYSQL_PASSWORD=fox379@@zyxi \
|
||||||
|
-p 3306:3306 \
|
||||||
|
mysql:8.0
|
31
server/login/cmd/cmd.go
Normal file
31
server/login/cmd/cmd.go
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
package cmd
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"game/server/login/config"
|
||||||
|
"game/server/login/model"
|
||||||
|
"game/server/login/server"
|
||||||
|
"github.com/fox/fox/log"
|
||||||
|
"os"
|
||||||
|
"os/signal"
|
||||||
|
"syscall"
|
||||||
|
)
|
||||||
|
|
||||||
|
func initRepo() {
|
||||||
|
model.InitRedis()
|
||||||
|
model.InitDb()
|
||||||
|
}
|
||||||
|
|
||||||
|
func Run(GitCommit, GitBranch, BuildDate string) {
|
||||||
|
config.LoadConfig(GitCommit, GitBranch, BuildDate)
|
||||||
|
log.Info(fmt.Sprintf("版本分支:%v,hash值:%v,编译时间:%v", GitBranch, GitCommit, BuildDate))
|
||||||
|
initRepo()
|
||||||
|
|
||||||
|
server.Init()
|
||||||
|
// 截获 SIGINT 和 SIGTERM 信号
|
||||||
|
c := make(chan os.Signal, 1)
|
||||||
|
signal.Notify(c, syscall.SIGINT, syscall.SIGTERM)
|
||||||
|
sig := <-c
|
||||||
|
server.Stop()
|
||||||
|
log.Info(fmt.Sprintf("received %s, initiating shutdown...", sig))
|
||||||
|
}
|
35
server/login/config/config.go
Normal file
35
server/login/config/config.go
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
package config
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"game/common/config"
|
||||||
|
"github.com/fox/fox/db"
|
||||||
|
"github.com/fox/fox/log"
|
||||||
|
)
|
||||||
|
|
||||||
|
var Command *config.Command
|
||||||
|
var Cfg *config.Common[LoginConfig]
|
||||||
|
|
||||||
|
type LoginConfig struct {
|
||||||
|
}
|
||||||
|
|
||||||
|
func initLog() {
|
||||||
|
log.Open(fmt.Sprintf("login_%v.log", Command.VMod), log.DebugL)
|
||||||
|
}
|
||||||
|
|
||||||
|
func LoadConfig(GitCommit, GitBranch, BuildDate string) {
|
||||||
|
Command = config.ParseCommand()
|
||||||
|
initLog()
|
||||||
|
rdb, err := db.InitRedis(Command.RedisPassword, Command.RedisHost, Command.RedisPort, 0)
|
||||||
|
if err != nil {
|
||||||
|
log.Error(err.Error())
|
||||||
|
return
|
||||||
|
}
|
||||||
|
defer func() { _ = rdb.Close() }()
|
||||||
|
Cfg, err = config.LoadCommonConfig[LoginConfig](rdb, GitCommit, GitBranch, BuildDate)
|
||||||
|
if err != nil {
|
||||||
|
log.Error(err.Error())
|
||||||
|
return
|
||||||
|
}
|
||||||
|
log.DebugF("load common config success")
|
||||||
|
}
|
24
server/login/main.go
Normal file
24
server/login/main.go
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"game/server/login/cmd"
|
||||||
|
"github.com/fox/fox/ksync"
|
||||||
|
"github.com/fox/fox/log"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
GitCommit = "unknown"
|
||||||
|
GitBranch = "unknown"
|
||||||
|
BuildDate = "unknown"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
tm, err := time.Parse("20060102150405", BuildDate)
|
||||||
|
if err == nil {
|
||||||
|
BuildDate = tm.Format("2006-01-02 15:04:05")
|
||||||
|
}
|
||||||
|
ksync.RunSafe(func() {
|
||||||
|
cmd.Run(GitBranch, GitCommit, BuildDate)
|
||||||
|
}, func() { log.ErrorF("reset run") })
|
||||||
|
}
|
57
server/login/model/db.go
Normal file
57
server/login/model/db.go
Normal file
@ -0,0 +1,57 @@
|
|||||||
|
package model
|
||||||
|
|
||||||
|
import (
|
||||||
|
"game/server/login/config"
|
||||||
|
"github.com/fox/fox/db"
|
||||||
|
"github.com/fox/fox/log"
|
||||||
|
"github.com/go-redis/redis/v8"
|
||||||
|
"gorm.io/gorm"
|
||||||
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
UserRedis *redis.Client
|
||||||
|
UserDB *gorm.DB
|
||||||
|
LogDB *gorm.DB
|
||||||
|
)
|
||||||
|
|
||||||
|
func InitRedis() {
|
||||||
|
var err error
|
||||||
|
cfg := &config.Cfg.Redis
|
||||||
|
UserRedis, err = db.InitRedis(cfg.Password, cfg.Host, cfg.Port, 0)
|
||||||
|
if err != nil {
|
||||||
|
log.Fatal(err.Error())
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func InitDb() {
|
||||||
|
var err error
|
||||||
|
cfg := &config.Cfg.Mysql
|
||||||
|
UserDB, err = db.InitMysql(cfg.Username, cfg.Password, cfg.Host, cfg.Port, cfg.DbName)
|
||||||
|
if err != nil {
|
||||||
|
log.Fatal(err.Error())
|
||||||
|
return
|
||||||
|
}
|
||||||
|
cfg = &config.Cfg.MysqlLog
|
||||||
|
LogDB, err = db.InitMysql(cfg.Username, cfg.Password, cfg.Host, cfg.Port, cfg.DbName)
|
||||||
|
if err != nil {
|
||||||
|
log.Fatal(err.Error())
|
||||||
|
return
|
||||||
|
}
|
||||||
|
// 自动迁移game库表结构
|
||||||
|
err = UserDB.AutoMigrate(
|
||||||
|
&UserAccount{},
|
||||||
|
)
|
||||||
|
if err != nil {
|
||||||
|
log.Fatal(err.Error())
|
||||||
|
return
|
||||||
|
}
|
||||||
|
// 自动迁移game_log库表结构
|
||||||
|
err = LogDB.AutoMigrate(
|
||||||
|
&UserLoginLog{},
|
||||||
|
)
|
||||||
|
if err != nil {
|
||||||
|
log.Fatal(err.Error())
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
117
server/login/model/userAccount.go
Normal file
117
server/login/model/userAccount.go
Normal file
@ -0,0 +1,117 @@
|
|||||||
|
package model
|
||||||
|
|
||||||
|
import (
|
||||||
|
"errors"
|
||||||
|
"github.com/fox/fox/log"
|
||||||
|
"golang.org/x/crypto/bcrypt"
|
||||||
|
"gorm.io/gorm"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
AccountNormal = 0 // 正常
|
||||||
|
AccountFrozen = 1 // 冻结
|
||||||
|
AccountBanned = 2 // 封禁
|
||||||
|
)
|
||||||
|
|
||||||
|
// 玩家账户表
|
||||||
|
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);uniqueIndex"` // 邮箱(可选)
|
||||||
|
Phone string `gorm:"type:varchar(20);uniqueIndex"` // 手机号(可选)
|
||||||
|
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:"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:"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) 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) {
|
||||||
|
// 这里应该使用JWT库生成实际令牌
|
||||||
|
// 简化实现,实际项目中请使用安全的JWT实现
|
||||||
|
return "generated-token-placeholder", nil
|
||||||
|
}
|
93
server/login/server/processor.go
Normal file
93
server/login/server/processor.go
Normal file
@ -0,0 +1,93 @@
|
|||||||
|
package server
|
||||||
|
|
||||||
|
import (
|
||||||
|
"game/common/proto/pb"
|
||||||
|
"game/common/topicName"
|
||||||
|
"github.com/fox/fox/log"
|
||||||
|
"github.com/fox/fox/processor"
|
||||||
|
"github.com/fox/fox/service"
|
||||||
|
"golang.org/x/crypto/bcrypt"
|
||||||
|
"gorm.io/gorm"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
func (s *LoginService) initProcessor() {
|
||||||
|
s.processor.RegisterMessages(processor.RegisterMetas{
|
||||||
|
//pb.MsgId_C2SChatId: {pb.C2SChat{}, s.onChat},
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// 登录或注册
|
||||||
|
func (s *LoginService) LoginOrRegister(req *pb.C2SUserLogin) {
|
||||||
|
// 1. 尝试查找用户
|
||||||
|
var user models.UserAccount
|
||||||
|
err := s.db.Where("username = ?", req.Username).First(&user).Error
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
// 如果是用户不存在错误,则注册新用户
|
||||||
|
if errors.Is(err, gorm.ErrRecordNotFound) {
|
||||||
|
return s.registerNewUser(req)
|
||||||
|
}
|
||||||
|
// 其他数据库错误
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// 2. 验证密码
|
||||||
|
if err := bcrypt.CompareHashAndPassword([]byte(user.Password), []byte(req.Password)); err != nil {
|
||||||
|
// 记录失败登录日志
|
||||||
|
s.recordLoginLog(user.ID, req.IP, req.DeviceID, false, "密码错误")
|
||||||
|
return nil, errors.New("用户名或密码错误")
|
||||||
|
}
|
||||||
|
|
||||||
|
// 3. 检查账号状态
|
||||||
|
if user.Status != 1 {
|
||||||
|
var reason string
|
||||||
|
switch user.Status {
|
||||||
|
case 2:
|
||||||
|
reason = "账号已冻结"
|
||||||
|
case 3:
|
||||||
|
reason = "账号已封禁"
|
||||||
|
}
|
||||||
|
s.recordLoginLog(user.ID, req.IP, req.DeviceID, false, reason)
|
||||||
|
return nil, errors.New(reason)
|
||||||
|
}
|
||||||
|
|
||||||
|
// 4. 更新最后登录信息
|
||||||
|
user.LastLoginIP = req.IP
|
||||||
|
user.LastLoginTime = time.Now()
|
||||||
|
if err := s.db.Save(&user).Error; err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// 5. 记录成功登录日志
|
||||||
|
s.recordLoginLog(user.ID, req.IP, req.DeviceID, true, "")
|
||||||
|
|
||||||
|
// 6. 生成访问令牌
|
||||||
|
token, err := generateToken(user.ID, user.Username)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return &models.LoginResponse{
|
||||||
|
UserID: user.ID,
|
||||||
|
Username: user.Username,
|
||||||
|
Token: token,
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// 收到登陆成功消息,判断是否顶号
|
||||||
|
func (s *LoginService) onLogin(uid int64, msg *pb.C2SUserLogin) {
|
||||||
|
|
||||||
|
switch msg.Type {
|
||||||
|
case pb.ChatType_CT_Private:
|
||||||
|
sName, err := s.bindService.FindServiceName(msg.DstUser.UserId, pb.ServiceTypeId_STI_Gate)
|
||||||
|
if err != nil {
|
||||||
|
log.DebugF("find user:%v in gate err: %v", uid, err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
s.SendServiceMsg(service.TopicEx(sName), msg.DstUser.UserId, int32(pb.MsgId_S2CChatId), msg)
|
||||||
|
default:
|
||||||
|
s.SendServiceMsg(service.TopicEx(topicName.WorldMessage), uid, int32(pb.MsgId_S2CChatId), msg)
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
115
server/login/server/service.go
Normal file
115
server/login/server/service.go
Normal file
@ -0,0 +1,115 @@
|
|||||||
|
package server
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"game/common/proto/ipb"
|
||||||
|
"game/common/proto/pb"
|
||||||
|
"game/common/serviceName"
|
||||||
|
"game/common/userBindService"
|
||||||
|
"game/server/login/config"
|
||||||
|
"game/server/login/model"
|
||||||
|
"github.com/fox/fox/log"
|
||||||
|
"github.com/fox/fox/processor"
|
||||||
|
"github.com/fox/fox/service"
|
||||||
|
"github.com/golang/protobuf/proto"
|
||||||
|
)
|
||||||
|
|
||||||
|
var Login []*LoginService
|
||||||
|
|
||||||
|
type LoginService struct {
|
||||||
|
*service.NatsService
|
||||||
|
processor *processor.Processor
|
||||||
|
bindService *userBindService.UserBindService
|
||||||
|
}
|
||||||
|
|
||||||
|
func Init() {
|
||||||
|
for i := 0; i < config.Command.ServiceNum; i++ {
|
||||||
|
sid := config.Command.ServiceId + i
|
||||||
|
if srv := newLoginService(sid); srv != nil {
|
||||||
|
Login = append(Login, srv)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func Stop() {
|
||||||
|
for _, srv := range Login {
|
||||||
|
srv.NotifyStop()
|
||||||
|
}
|
||||||
|
for _, srv := range Login {
|
||||||
|
srv.WaitStop()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func newLoginService(serviceId int) *LoginService {
|
||||||
|
var err error
|
||||||
|
s := new(LoginService)
|
||||||
|
|
||||||
|
sName := fmt.Sprintf("%v-%d", serviceName.Login, serviceId)
|
||||||
|
if s.NatsService, err = service.NewNatsService(&service.InitNatsServiceParams{
|
||||||
|
EtcdAddress: config.Cfg.Etcd.Address,
|
||||||
|
EtcdUsername: "",
|
||||||
|
EtcdPassword: "",
|
||||||
|
NatsAddress: config.Cfg.Nats.Address,
|
||||||
|
ServiceType: serviceName.Login,
|
||||||
|
ServiceName: sName,
|
||||||
|
OnFunc: s,
|
||||||
|
TypeId: int(pb.ServiceTypeId_STI_Login),
|
||||||
|
Version: config.Cfg.BuildDate,
|
||||||
|
}); err != nil {
|
||||||
|
log.Fatal(err.Error())
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
s.bindService = userBindService.NewUserBindService(model.UserRedis, s.ServiceEtcd())
|
||||||
|
s.processor = processor.NewProcessor()
|
||||||
|
s.initProcessor()
|
||||||
|
s.OnInit()
|
||||||
|
return s
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *LoginService) OnInit() {
|
||||||
|
// if err := s.NatsService.QueueSubscribe(service.GroupTopic(s), service.GroupQueue(s)); err != nil {
|
||||||
|
// log.Error(err.Error())
|
||||||
|
// }
|
||||||
|
s.NatsService.Run()
|
||||||
|
log.Debug("onInit")
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *LoginService) CanStop() bool {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *LoginService) OnStop() {
|
||||||
|
s.NatsService.OnStop()
|
||||||
|
log.Debug("OnStop")
|
||||||
|
}
|
||||||
|
|
||||||
|
// 处理其它服发送过来的消息
|
||||||
|
func (s *LoginService) OnMessage(data []byte) error {
|
||||||
|
var iMsg = &ipb.InternalMsg{}
|
||||||
|
var err error
|
||||||
|
if err = proto.Unmarshal(data, iMsg); err != nil {
|
||||||
|
log.Error(err.Error())
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if req, err := s.processor.Unmarshal(iMsg.MsgId, iMsg.Msg); err == nil {
|
||||||
|
err = s.processor.Dispatch(iMsg.MsgId, iMsg.UserId, req)
|
||||||
|
}
|
||||||
|
//log.Debug(s.Log("on message:%v", string(msg)))
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// 向内部服务发送消息
|
||||||
|
func (s *LoginService) SendServiceData(topic string, userId int64, msgId int32, data []byte) {
|
||||||
|
iMsg := &ipb.InternalMsg{ConnId: 0, UserId: userId, MsgId: msgId, Msg: data}
|
||||||
|
dMsg, _ := proto.Marshal(iMsg)
|
||||||
|
_ = s.Send(topic, dMsg)
|
||||||
|
}
|
||||||
|
|
||||||
|
// 向内部服务发送消息
|
||||||
|
func (s *LoginService) SendServiceMsg(topic string, userId int64, msgId int32, msg proto.Message) {
|
||||||
|
iMsg := &ipb.InternalMsg{ConnId: 0, UserId: userId, MsgId: msgId}
|
||||||
|
iMsg.Msg, _ = proto.Marshal(msg)
|
||||||
|
dMsg, _ := proto.Marshal(iMsg)
|
||||||
|
_ = s.Send(topic, dMsg)
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user