Merge branch 'sdk' into online

This commit is contained in:
hahwu 2026-01-07 14:18:06 +08:00
commit a890c515f3
159 changed files with 2610 additions and 3014 deletions

1
.gitignore vendored
View File

@ -17,3 +17,4 @@ src/server/goroutine.prof
src/server/heap_after.pb.gz
src/server/test/logs/*
src/server/test/teLog/*
src/server/*.exe*

16
src/server/README.MD Normal file
View File

@ -0,0 +1,16 @@
## 命名规范
- **清晰优先**:名称应准确表达含义,避免歧义。
- **导出规则**:导出标识符首字母大写,未导出首字母小写。
- **包名**:小写单词,简短且描述职责(如 `store`、`auth`)。
- **文件名**:小写(可下划线分隔),测试文件以 `_test.go` 结尾。
- **函数/变量/类型**:驼峰命名;导出使用 PascalCase例如 `UserService`、`CreateUser`)。
- **接口**:以行为命名,常用 `-er` 结尾(如 `Reader`、`Store`),避免 `I` 前缀。
- **缩写**:统一大小写(例如导出使用 `ID`、`URL`;未导出使用 `id`、`url`)。
- **错误**:包级错误使用 `Err` 前缀(如 `ErrNotFound`)。
- **Context 与并发**:统一使用 `ctx` 作 `context.Context`,通道命名要有语义(如 `done`, `jobs`)。
- **构造函数/选项**:使用 `NewType` 与 `WithXxx` 约定,避免多个布尔参数。

View File

@ -6,7 +6,6 @@ import (
"server/game"
"server/game/mod/msg"
"testing"
"time"
)
// func TestBenchInit(t *testing.T) {
@ -20,34 +19,23 @@ import (
// }
// }
// }
func BenchmarkGame(b *testing.B) {
runtime.GOMAXPROCS(2)
fmt.Print("BenchmarkGame")
f := "wmz00%d"
for i := 0; i < 10000; i++ {
go func() {
UserName := fmt.Sprintf(f, i)
p1 := new(game.Player)
err := p1.InitPlayer(UserName)
if err != nil {
fmt.Println(err)
/*
*
cluster 消息处理基准测试
36716 34961 ns/op 1690 B/op 38 allocs/op
*/
func BenchmarkClusterMsg(b *testing.B) {
game.ClusterMgrInit()
runtime.GOMAXPROCS(8)
game.G_getGameLogic()
for i := 0; i < b.N; i++ {
m := &msg.Msg{
HandleType: msg.HANDLE_MOD_PLAYER_LOGIN,
Extra: 0,
}
game.G_GameLogicPtr.SetPlayer(p1)
for {
time.Sleep(1 * time.Second)
game.Benchmark(p1)
}
}()
}
go func() {
time.Sleep(20 * time.Second)
game.G_GameLogicPtr.ChampshipMgrSend(&msg.Msg{
Type: msg.HANDLE_TYPE_CHAMPSHIP_GROUP,
})
}()
for {
time.Sleep(1 * time.Second)
printMemUsage()
game.MessageHandle(m)
}
}

View File

@ -3,9 +3,9 @@ package mergeCluster
import (
"fmt"
"math"
"server/GoUtil"
"server/conf"
"server/game/mod/msg"
GoUtil "server/game_util"
"server/pkg/github.com/name5566/leaf/log"
"server/pkg/github.com/name5566/leaf/network"
"sync"
@ -30,7 +30,7 @@ func Init() {
server = new(network.TCPServer)
server.Addr = conf.Server.ListenAddr
server.MaxConnNum = int(math.MaxInt32)
server.PendingWriteNum = conf.PendingWriteNum
server.PendingWriteNum = 1 << 14
server.LenMsgLen = 4
server.MaxMsgLen = 4096
server.NewAgent = newServerAgent

View File

@ -2,9 +2,9 @@ package mergeCluster
import (
"fmt"
"server/GoUtil"
"server/conf"
"server/game/mod/msg"
GoUtil "server/game_util"
"server/pkg/github.com/name5566/leaf/log"
"server/pkg/github.com/name5566/leaf/network"
"time"
@ -27,14 +27,14 @@ func HandShake(a *Agent) {
log.Debug("HandShake GobMarshal err %v", err)
return
}
// log.Debug("握手 server id :%d", conf.Server.ServerID)
log.Debug("握手 server id :%d", conf.Server.ServerID)
a.WriteMsg(data)
}
// 握手回调
func HandShakeRecv(a *Agent, m *msg.Msg) error {
ServerId := m.From
// log.Debug("收到握手回复 ServerId %v", ServerId)
log.Debug("收到握手回复 ServerId %v", ServerId)
a.ServerId = ServerId
serverAgent.Store(ServerId, a)
@ -48,19 +48,14 @@ func HandShakeRecv(a *Agent, m *msg.Msg) error {
RemoteAddr: m.Extra.(string),
},
})
}
} else {
syncMsg := &msg.Msg{
Type: msg.CLUSTER_FRIEND_SYNC,
To: ServerId,
HandleType: msg.HANDLE_MOD_CLUSTER_SYNC,
}
sendGameMsg(syncMsg)
// fmt.Print("现有区服连接:")
// serverAgent.Range(func(key, value interface{}) bool {
// fmt.Print(key)
// fmt.Print(",")
// return true
// })
// fmt.Println()
}
return nil
}
@ -79,7 +74,7 @@ func ClusterJoin(a *Agent, m *msg.Msg) error {
return nil
}
log.Debug("ClusterJoin ServerId %v", clusterJoin.ServerId)
connectRemote(clusterJoin.RemoteAddr, clusterJoin.ServerId, "server")
//connectRemote(clusterJoin.RemoteAddr, clusterJoin.ServerId, "server")
return nil
}
@ -96,23 +91,27 @@ func connectRemote(RemoteAddr string, ConnType int, ConnLabel string) error {
client := new(network.TCPClient)
client.Addr = RemoteAddr
client.ConnNum = 1
client.PendingWriteNum = conf.PendingWriteNum
client.PendingWriteNum = 1 << 14
client.LenMsgLen = 4
client.MaxMsgLen = 4096
client.NewAgent = newAgent
client.ConnType = ConnType
client.ConnLabel = ConnLabel
client.ConnectInterval = time.Duration(time.Minute * 5)
client.ConnectInterval = time.Duration(time.Minute * 1)
if ConnType == ClusterCenterId { // 中心服断开重连
client.AutoReconnect = true
}
client.Start()
Center = client
clients = append(clients, client)
log.Debug("connet remote to addr:%s", RemoteAddr)
return nil
}
func SendServerMsg(m *msg.Msg, serverId int) error {
if m.UniKey == "" {
m.UniKey = GoUtil.UniKey(fmt.Sprintf("%v,Cluster Msg", m))
}
if v, ok := serverAgent.Load(serverId); ok {
data, err := GoUtil.GobMarshal(m)
if err != nil {
@ -126,25 +125,32 @@ func SendServerMsg(m *msg.Msg, serverId int) error {
}
func CallServerMsg(m *msg.Msg, serverId int) (*msg.Msg, error) {
if m.UniKey == "" {
m.UniKey = GoUtil.UniKey(fmt.Sprintf("%v,Cluster Msg", m))
if v, ok := serverAgent.Load(serverId); ok {
}
v, ok := serverAgent.Load(serverId)
// 之后再发送消息
if !ok {
return nil, fmt.Errorf("server %d not online", serverId)
}
// 先注册回调通道,避免发送出去后对方快速返回导致丢失
newChan := make(chan *msg.Msg, 1)
registerChanel(m.UniKey, newChan)
defer unregisterChanel(m.UniKey)
data, err := GoUtil.GobMarshal(m)
if err != nil {
log.Debug("CallServerMsg GobMarshal err %v", err)
return nil, err
}
v.(network.Agent).WriteMsg(data)
}
newChan := make(chan *msg.Msg, 1)
registerChanel(m.UniKey, newChan)
timeout := time.After(15 * time.Second)
// 等待返回(直接接收一次)
timeout := time.After(5 * time.Second)
select {
case <-newChan:
backm := <-newChan
unregisterChanel(m.UniKey)
case backm := <-newChan:
if backm == nil {
return nil, fmt.Errorf("server %d not response", serverId)
}
log.Debug("CallServerMsg reply %v", backm)
return backm, nil
case <-timeout:
return nil, fmt.Errorf("timeout waiting for server %d response", serverId)
@ -165,13 +171,7 @@ func SendMsgAll(m *msg.Msg) {
func processMsg(a *Agent, m *msg.Msg) error {
var err error
// 先处理同步回调
if m.UniKey != "" {
if chanel, ok := CallbackChan[m.UniKey]; ok {
chanel <- m
}
return nil
}
if fun, ok := FuncMap[m.Type]; ok {
err = fun(a, m)
} else {

View File

@ -1,9 +1,9 @@
package activityCfg
import (
"server/GoUtil"
languageCfg "server/conf/language"
"server/game/mod/item"
GoUtil "server/game_util"
"server/gamedata"
"server/msg"
"server/pkg/github.com/name5566/leaf/log"

View File

@ -1,8 +1,8 @@
package cardCfg
import (
"server/GoUtil"
"server/game/mod/item"
GoUtil "server/game_util"
"server/gamedata"
"server/pkg/github.com/name5566/leaf/log"
"strconv"

View File

@ -1,8 +1,8 @@
package catnipCfg
import (
"server/GoUtil"
"server/game/mod/item"
GoUtil "server/game_util"
"server/gamedata"
)
@ -112,6 +112,21 @@ func GetProgressReward(Id int, Rewards []int, Progress int) ([]*item.Item, []int
return Items, Ids
}
func GetProgressNum(Id int) int {
TemplateId := GetTemplateId(Id)
data, err := gamedata.GetData(CATNIP_GAME_CFG_NAME)
if err != nil {
return 0
}
Num := 0
for _, v := range data {
if gamedata.GetIntValue(v, "Template") == TemplateId {
Num++
}
}
return Num
}
func GetItemCost(Id, Mul int) []*item.Item {
data, err := gamedata.GetDataByIntKey(CATNIP_TEMPLATE_CFG_NAME, Id)
if err != nil {

View File

@ -1,8 +1,8 @@
package champshipCfg
import (
"server/GoUtil"
"server/game/mod/item"
GoUtil "server/game_util"
"server/gamedata"
)

View File

@ -1,8 +1,8 @@
package chargeCfg
import (
"server/GoUtil"
"server/game/mod/item"
GoUtil "server/game_util"
"server/gamedata"
"sort"
"strings"

View File

@ -1,8 +1,8 @@
package collectCfg
import (
"server/GoUtil"
"server/game/mod/item"
GoUtil "server/game_util"
"server/gamedata"
)

View File

@ -7,10 +7,10 @@ import (
var (
// log conf
LogFlag = log.LstdFlags
LogFlag = log.LstdFlags | log.Lmicroseconds
// gate conf
PendingWriteNum = 2000
PendingWriteNum = 2000 // 客户端链接的写入消息队列长度
MaxMsgLen uint32 = 65536 // 16KB
HTTPTimeout = 10 * time.Second
LenMsgLen = 2

View File

@ -1,7 +1,7 @@
package emojiCfg
import (
"server/GoUtil"
GoUtil "server/game_util"
"server/gamedata"
)

View File

@ -0,0 +1,19 @@
package friendCfg
import "server/gamedata"
const (
CFG_NPC_FRIENDS = "NPCFriends"
)
func init() {
gamedata.InitCfg(CFG_NPC_FRIENDS)
}
func IsNpcFriend(Id int) bool {
_, err := gamedata.GetDataByIntKey(CFG_NPC_FRIENDS, Id)
if err != nil {
return false
}
return true
}

View File

@ -1,8 +1,8 @@
package friendTreasureCfg
import (
"server/GoUtil"
"server/game/mod/item"
GoUtil "server/game_util"
"server/gamedata"
)

View File

@ -1,8 +1,8 @@
package guesscolorCfg
import (
"server/GoUtil"
"server/game/mod/item"
GoUtil "server/game_util"
"server/gamedata"
"strings"
)

View File

@ -1,8 +1,8 @@
package GuideTaskCfg
import (
"server/GoUtil"
"server/game/mod/item"
GoUtil "server/game_util"
"server/gamedata"
"server/pkg/github.com/name5566/leaf/log"
"strconv"

View File

@ -1,8 +1,8 @@
package limitedTimeEventCfg
import (
"server/GoUtil"
"server/game/mod/item"
GoUtil "server/game_util"
"server/gamedata"
"server/pkg/github.com/name5566/leaf/log"
"sort"

View File

@ -2,9 +2,9 @@ package mailCfg
import (
"fmt"
"server/GoUtil"
languageCfg "server/conf/language"
"server/game/mod/item"
GoUtil "server/game_util"
"server/gamedata"
"server/msg"
"strings"

View File

@ -2,8 +2,8 @@ package mergeDataCfg
import (
"errors"
"server/GoUtil"
"server/game/mod/item"
GoUtil "server/game_util"
"server/gamedata"
"server/pkg/github.com/name5566/leaf/log"
"strconv"

View File

@ -1,8 +1,8 @@
package miningCfg
import (
"server/GoUtil"
"server/game/mod/item"
GoUtil "server/game_util"
"server/gamedata"
"strconv"
"strings"

View File

@ -1,8 +1,8 @@
package playroomCfg
import (
"server/GoUtil"
"server/game/mod/item"
GoUtil "server/game_util"
"server/gamedata"
"server/pkg/github.com/name5566/leaf/log"
"strings"

View File

@ -1,7 +1,7 @@
package randnameCfg
import (
"server/GoUtil"
GoUtil "server/game_util"
"server/gamedata"
"strconv"
)

View File

@ -14,7 +14,7 @@
"AppPath": "./app",
"TELOGDIR" : "./teLog/",
"GameName": "Merge_Pet_Local",
"GameName": "pet_home_local",
"ServerType":"node",
@ -22,12 +22,12 @@
"ServerOpenTime": "2018-01-01 00:00:00",
"ServerName": "Merge_Pet",
"ServerStatus" : 1,
"ServerCenter" : 1,
"ServerCenter" : 0,
"GameConfPath": "D:/Github/pet_home_server/src/server/gamedata/config/",
"ListenAddr":":9001",
"CenterAddr": "pethome.bywaystudios.com:9000",
"RemoteAddr":"host.docker.internal:9001",
"CenterAddr": "127.0.0.1:7000",
"RemoteAddr":"127.0.0.1:9001",
"RedisAddr":"127.0.0.1",
"RedisPort" :"6379",

View File

@ -3,9 +3,9 @@ package db
import (
"fmt"
"reflect"
"server/GoUtil"
"server/MergeConst"
"server/conf"
GoUtil "server/game_util"
"server/pkg/github.com/name5566/leaf/log"
"strings"
"sync"
@ -16,13 +16,6 @@ import (
"github.com/jmoiron/sqlx"
)
type user struct {
Id int `db:"user_id"`
Sex int `db:"sex"`
UserName string `db:"username"`
Email string `db:"email"`
}
var SqlDb *sqlx.DB
var sqlDbMu sync.Mutex
@ -271,6 +264,22 @@ func GetPlayerBaseInfoFromDbByName(name string) *ResPlayerBaseInfo {
return &res
}
func GetPlayerBan(name string) int64 {
sqlStr := "SELECT ban FROM t_player_baseinfo WHERE user_name = ?"
var ban int64
if err := SqlDb.Get(&ban, sqlStr, name); err != nil {
log.Debug("table: %s, sql :%s, exec failed, err:%v\n", "PlayerBaseInfo", sqlStr, err)
return 0
}
return ban
}
func UpdatePlayerBan(uid int64, ban int64) error {
sqlStr := "UPDATE t_player_baseinfo SET ban = ? WHERE dwUin = ?"
_, err := SqlDb.Exec(sqlStr, ban, uid)
return err
}
func UpdatePlayerBaseInfoName(oldName, newName string) error {
sqlStr := "UPDATE t_player_baseinfo SET user_name = ? WHERE user_name = ?"
_, err := SqlDb.Exec(sqlStr, newName, oldName)
@ -297,6 +306,17 @@ func GetAccountInfoFromDb(name string) *Db_Account {
return &res
}
func ResetAccountData(oldName, newName string) error {
sqlStr := "UPDATE t_account SET user_name = ? WHERE user_name = ?"
_, err := SqlDb.Exec(sqlStr, newName, oldName)
if err != nil {
return err
}
sqlStr = "UPDATE t_player_baseinfo SET user_name = ? WHERE user_name = ?"
_, err = SqlDb.Exec(sqlStr, newName, oldName)
return err
}
func UpdateAccountInfoToDb(account *Db_Account) (err error) {
_, err = SqlDb.Exec("UPDATE t_account SET user_password = ? WHERE user_name = ?", account.UserPassword, account.UserName)
return

View File

@ -164,6 +164,17 @@ func RedisGetKey(key string) (string, error) {
return val, nil
}
func RedisGetKeyBytes(key string) ([]byte, error) {
if RdbRead == nil {
return nil, nil
}
val, err := RdbRead.Get(ctx, key).Bytes()
if err != nil {
return nil, err
}
return val, nil
}
func RedisDelKey(key string) {
if RdbWrite == nil {
log.Debug("redis write client is nil")

View File

@ -37,12 +37,12 @@ type ResPlayerBaseInfo struct {
Guild int32 `db:"guild"`
PackUnlockCount int32 `db:"pack_unlock_count"`
LastPlayTime int32 `db:"last_play_time"`
EnergyBuyCount int32 `db:"EnergyBuyCount"`
Ban int64 `db:"ban"`
UserName string `db:"user_name"`
NickName string `db:"nick_name"`
LoginTime int32 `db:"login_time"`
LogoutTime int32 `db:"logout_time"`
Todayolinetime int32 `db:"todayolinetime"`
Node int32 `db:"node"`
Rolecreatetime int32 `db:"rolecreatetime"`
EmitOrderCnt int32 `db:"EmitOrderCnt"`
DailyRenewTime int32 `db:"DailyRenewTime"`

View File

@ -1,69 +0,0 @@
package game
import (
"encoding/gob"
"server/GoUtil"
)
type BanMgr struct {
*ServerMod
}
type BanData struct {
NewBanList map[int64]*BanInfo // 新增的封禁列表
}
type BanInfo struct {
UserId int64 // 玩家ID
EndTime int64 // 封禁结束时间0表示永久封禁
Reason string // 封禁原因
}
func (f *BanMgr) Init() {
gob.Register(&BanData{})
f.key = BAN_MGR_KEY
f.data = &BanData{
NewBanList: make(map[int64]*BanInfo),
}
// 注册处理函数
f.init()
if f.data.(*BanData).NewBanList == nil {
f.data.(*BanData).NewBanList = make(map[int64]*BanInfo)
}
}
func (f *BanMgr) IsBanned(userId int64) bool {
if f.data.(*BanData).NewBanList == nil {
return false
}
Info, banned := f.data.(*BanData).NewBanList[userId]
if !banned {
return false
}
return Info.EndTime > GoUtil.Now() || Info.EndTime == -1 // 如果EndTime为0表示永久封禁
}
func (f *BanMgr) GetBanInfo(userId int64) *BanInfo {
if f.data.(*BanData).NewBanList == nil {
return &BanInfo{}
}
Info, banned := f.data.(*BanData).NewBanList[userId]
if !banned {
return &BanInfo{}
}
return Info
}
func (f *BanMgr) BanUser(userId int64, endTime int64, reason string) {
f.data.(*BanData).NewBanList[userId] = &BanInfo{
UserId: userId,
EndTime: endTime,
Reason: reason,
}
f.SaveData()
}
func (f *BanMgr) UnbanUser(userId int64) {
delete(f.data.(*BanData).NewBanList, userId)
f.SaveData()
}

View File

@ -6,10 +6,10 @@ import (
"encoding/json"
"fmt"
"os"
"server/GoUtil"
"server/MergeConst"
"server/conf"
userCfg "server/conf/user"
GoUtil "server/game_util"
"strconv"
"sync"
@ -83,8 +83,8 @@ type GameLogic struct {
MailMgr *MailMgr // 邮件管理器
ChampshipMgr *ChampshipMgr // 锦标赛管理器
VarMgr *VarMgr // 变量管理器
BanMgr *BanMgr // 封号管理器
StartTime int64 // 服务器启动时间
MessageMgr *MessageMgr // 消息管理器
}
type ServerInfo struct {
@ -179,7 +179,7 @@ func (ad *GameLogic) NewAccountInsertDataToDB() bool {
return false
}
insertId = insertId + int64(conf.Server.ServerID*100000) + int64(conf.Server.AppID*100000000)
insertId = insertId + int64(100000) + int64(conf.Server.AppID*100000000)
playerInfo := &db.ResPlayerBaseInfo{}
playerInfo.DwUin = int64(insertId)
playerInfo.Energy = int32(userCfg.GetInitEnergy())
@ -192,11 +192,10 @@ func (ad *GameLogic) NewAccountInsertDataToDB() bool {
playerInfo.MusicCode = 1
playerInfo.Guild = 1
playerInfo.PackUnlockCount = 5
playerInfo.EnergyBuyCount = 0
playerInfo.UserName = ad.Db_AccountInfo.UserName
playerInfo.LoginTime = (int32)(time.Now().Unix())
playerInfo.LogoutTime = 0
playerInfo.Todayolinetime = 0
playerInfo.Node = int32(conf.Server.ServerID)
playerInfo.Rolecreatetime = (int32)(time.Now().Unix())
playerInfo.FaceBookId = ""
db.FormatAllMemInsertDb(playerInfo, "t_player_baseinfo")
@ -271,67 +270,6 @@ func (ad *GameLogic) CreateFriendMgr() {
ad.FriendMgr.Init()
}
func (ad *GameLogic) FriendMgrSend(m *MsgMod.Msg) {
ad.FriendMgr.Send(m)
}
func (ad *GameLogic) SetUserData(Uid int, Op int, Data interface{}) {
ad.FriendMgr.Send(&MsgMod.Msg{
From: Uid,
To: Uid,
Type: MsgMod.HANDLE_TYPE_VAR_USER_SET,
SendT: GoUtil.Now(),
Extra: VarOpration{Type: Op, Data: Data},
})
}
func (ad *GameLogic) SetDataSync(Uid int, Op int, Data interface{}) error {
_, err := ad.VarMgr.Call(&MsgMod.Msg{
From: Uid,
To: Uid,
Type: MsgMod.HANDLE_TYPE_VAR_EXPIRE_SET,
SendT: GoUtil.Now(),
Extra: VarOpration{Type: Op, Data: Data},
})
return err
}
func (ad *GameLogic) SetCatnipPartner(Uid int, GameId int, PartnerUid int) error {
_, err := ad.VarMgr.Call(&MsgMod.Msg{
From: Uid,
To: Uid,
Type: MsgMod.HANDLE_TYPE_SET_CATNIP_PARTNER,
SendT: GoUtil.Now(),
Extra: map[string]interface{}{
"uid": Uid,
"game_id": GameId,
"partner_uid": PartnerUid,
},
})
return err
}
func (ad *GameLogic) GetUserData(Uid int) *VarUserData {
result, err := ad.FriendMgr.Call(&MsgMod.Msg{
From: Uid,
To: Uid,
Type: MsgMod.HANDLE_TYPE_VAR_USER_GET,
SendT: GoUtil.Now(),
})
if err != nil {
return &VarUserData{}
}
return result.(*VarUserData)
}
func (ad *GameLogic) FriendMgrCall(m *MsgMod.Msg) interface{} {
result, err := ad.FriendMgr.Call(m)
if err != nil {
return nil
}
return result
}
// 排行榜管理器
func (ad *GameLogic) CreateRankMgr() {
ad.RankMgr = &RankMgr{
@ -360,6 +298,13 @@ func (ad *GameLogic) CreateMailMgr() {
ad.MailMgr.Init()
}
func (ad *GameLogic) CreateMessageMgr() {
ad.MessageMgr = &MessageMgr{
ServerMod: new(ServerMod),
}
ad.MessageMgr.MessageMgrInit()
}
func (ad *GameLogic) MailMgrSend(m *MsgMod.Msg) {
ad.MailMgr.Send(m)
}
@ -412,26 +357,6 @@ func (ad *GameLogic) VarMgrCall(m *MsgMod.Msg) interface{} {
return result
}
// 封号管理器
func (ad *GameLogic) CreateBanMgr() {
ad.BanMgr = &BanMgr{
ServerMod: new(ServerMod),
}
ad.BanMgr.Init()
}
func (ad *GameLogic) BanMgrSend(m *MsgMod.Msg) {
ad.BanMgr.Send(m)
}
func (ad *GameLogic) BanMgrCall(m *MsgMod.Msg) interface{} {
result, err := ad.BanMgr.Call(m)
if err != nil {
return nil
}
return result
}
func (ad *GameLogic) GetSimplePlayerByUid(Id int) *PlayerSimpleData {
if Id == 0 {
return nil
@ -525,6 +450,7 @@ func (ad *GameLogic) GetResFriendPlayerByUid(Id int) *msg.ResFriendPlayerSimple
DressSet: GoUtil.MapIntToInt32(player.DressSet),
Friend: GoUtil.IntToInt32(player.Friend),
Physiology: GoUtil.MapIntToInt32(player.Physiology),
PetName: player.PetName,
}
}
@ -544,12 +470,14 @@ func G_getGameLogic() *GameLogic {
G_GameLogicPtr.InitActivity() // 初始化活动
G_GameLogicPtr.GetVersion() // 获取版本号
G_GameLogicPtr.CreateLogManager() //加载日志管理器
if conf.Server.ServerType == "center" {
G_GameLogicPtr.CreateFriendMgr() //创建好友管理器
G_GameLogicPtr.CreateRankMgr() //创建排行榜管理器
G_GameLogicPtr.CreateMailMgr() //创建邮件管理器
G_GameLogicPtr.CreateChampshipMgr() // 创建竞标赛管理器
G_GameLogicPtr.CreateVarMgr() // 创建变量管理器
G_GameLogicPtr.CreateBanMgr() // 创建封号管理器
}
G_GameLogicPtr.CreateRankMgr() //创建排行榜管理器
G_GameLogicPtr.CreateMailMgr() //创建邮件管理器
G_GameLogicPtr.CreateMessageMgr() // 创建消息管理器
ClusterMgrInit() //初始化集群
G_GameLogicPtr.StartTime = time.Now().Unix()
// G_GameLogicPtr.CreateHttpManager()
@ -605,12 +533,12 @@ func (ad *GameLogic) ClearData(args []interface{}) {
if player != nil && player.M_DwUin != 0 {
player.agent = nil
log.Debug("player %d 断开连接", player.M_DwUin)
player.CallEvent(300*time.Second, func() {
player.CallEvent(120*time.Second, func() {
player.lock.Lock()
defer player.lock.Unlock()
if player.agent == nil {
player.ClearData()
log.Debug("player %d 延迟300s关闭", player.M_DwUin)
log.Debug("player %d 延迟120s关闭", player.M_DwUin)
}
}, "LateClose")
}
@ -654,7 +582,6 @@ func (ad *GameLogic) ReplaceExistPlayerAndAgent(a gate.Agent, player *Player) er
if ok {
Timer.Stop()
}
player.SyncFriendMsg()
log.Debug("player %d 重连", player.M_DwUin)
return nil
}
@ -731,7 +658,6 @@ func (ad *GameLogic) RegisterNetWorkFunc() {
RegisterMsgProcessFunc("ReqSetPetName", ReqSetPetName) // 设置宠物名字
RegisterMsgProcessFunc("ReqSetFacebookUrl", ReqSetFacebookUrl) // 设置facebook地址
RegisterMsgProcessFunc("ReqPlayerBaseInfo", ReqPlayerBaseInfofunction) // 请求玩家基本信息
RegisterMsgProcessFunc("UpdateBaseItemInfo", UpdateBaseItemInfofunction) // 保存引导
RegisterMsgProcessFunc("ReqKv", ReqKv) // 保存客户端数据
RegisterMsgProcessFunc("ReqGetEnergyByAD", ReqGetEnergyByAD) // 看广告获取能量
RegisterMsgProcessFunc("ReqBuyEnergy", ReqBuyEnergy) // 购买能量
@ -987,11 +913,9 @@ func (ad *GameLogic) GetStartTime() int64 {
}
func NotifyPlayer(Uid int, m *MsgMod.Msg) {
p := G_GameLogicPtr.GetPlayer(int64(Uid))
if p == nil || p.stop {
return
}
p.Send(m)
m.To = Uid
m.HandleType = MsgMod.HANDLE_MOD_PLAYER_MSG
CenterPlayerMsgHandler(m)
}
func Destroy() {
@ -1007,7 +931,6 @@ func Destroy() {
G_GameLogicPtr.ChampshipMgr.SaveData()
G_GameLogicPtr.MailMgr.SaveData()
G_GameLogicPtr.VarMgr.SaveData()
G_GameLogicPtr.BanMgr.SaveData()
G_GameLogicPtr.MLogManager.Close()
}
log.Debug("服务器下线完成")

View File

@ -1,154 +0,0 @@
package game
import (
"encoding/gob"
"fmt"
"server/GoUtil"
"server/game/mod/card"
"server/game/mod/msg"
"time"
)
type VarMgr struct {
*ServerMod
}
type VarData struct {
Var map[string]interface{}
VarExpire map[string]*VarExpireData
UserVar map[string]*VarUserData
ZeroTime int64
}
const (
VAR_GOLD_CARD = "gold_card"
VAR_PLAYROOM_UPVOTE = "playroom_upvote"
VAR_USER_DATA = "user_data"
)
const (
VAR_OP_UPVOTE = 1
VAR_OP_CHIP = 2
VAR_OP_KISS = 3
VAR_OP_CHIP_SET = 4
VAR_OP_CATNIP_LOCK = 5
)
func (f *VarMgr) Init() {
gob.Register(&VarGoldCard{})
f.key = VAR_MGR_KEY
f.data = &VarData{
Var: map[string]interface{}{},
}
// 注册处理函数
f.init()
if f.data.(*VarData).Var == nil {
f.data.(*VarData).Var = make(map[string]interface{})
}
if f.data.(*VarData).UserVar == nil {
f.data.(*VarData).UserVar = make(map[string]*VarUserData)
}
if f.data.(*VarData).VarExpire == nil {
f.data.(*VarData).VarExpire = make(map[string]*VarExpireData)
}
if f.getData().ZeroTime == GoUtil.ZeroTimestamp() {
f.ZeroUpdate(&msg.Msg{})
}
f.RegisterHandler(msg.SERVER_ZERO_UPDATE, f.ZeroUpdate)
f.RegisterHandler(msg.HANDLE_TYPE_SET_CATNIP_PARTNER, f.SetCatnipPartner)
f.mDispatr.AfterFunc(time.Duration(GoUtil.NextZeroTimestampDuration())*time.Second, func() {
f.Send(&msg.Msg{
Type: msg.SERVER_ZERO_UPDATE,
})
})
}
func (f *VarMgr) SetGlobalData(m *msg.Msg) (interface{}, error) {
return nil, nil
}
func (f *VarMgr) ZeroUpdate(m *msg.Msg) (interface{}, error) {
f.getData().ZeroTime = GoUtil.ZeroTimestamp()
// 随机生成两个金卡
Card1, Card2 := card.RankGoldCard()
f.SetVar(VAR_GOLD_CARD, &VarGoldCard{
Four: Card1,
Five: Card2,
})
for k, v := range f.getData().VarExpire {
if v.T < GoUtil.ZeroTimestamp() {
delete(f.getData().VarExpire, k)
}
}
return nil, nil
}
func (f *VarMgr) SetCatnipPartner(m *msg.Msg) (interface{}, error) {
if Param, ok := m.Extra.(map[string]interface{}); ok {
MyUid := GoUtil.Int(Param["uid"])
CatnipGameId := GoUtil.Int(Param["game_id"])
CatnipPartnerId := GoUtil.Int(Param["partner_uid"])
myKey := fmt.Sprintf("catnip_partner_%d", MyUid)
key := fmt.Sprintf("catnip_partner_%d", CatnipPartnerId)
OtherPartnerInfo := f.GetExpireVar(key)
MyPartnerInfo := f.GetExpireVar(myKey)
MyOfPartnerList := GoUtil.IntSlice(MyPartnerInfo.D)
OtherOfPartnerList := GoUtil.IntSlice(OtherPartnerInfo.D)
if len(MyOfPartnerList) > 4 || len(OtherOfPartnerList) > 4 {
return nil, fmt.Errorf("catnip partner already full for uid %d in game %d", CatnipPartnerId, CatnipGameId)
}
f.SetExpireVar(key, &VarExpireData{
D: append(OtherOfPartnerList, MyUid),
T: m.End,
})
f.SetExpireVar(myKey, &VarExpireData{
D: append(MyOfPartnerList, CatnipPartnerId),
T: m.End,
})
return nil, nil
}
return nil, fmt.Errorf("invalid parameters for setting catnip partner")
}
func (f *VarMgr) SetVar(key string, value interface{}) {
f.getData().Var[key] = value
}
func (f *VarMgr) GetVar(key string) interface{} {
return f.getData().Var[key]
}
func (f *VarMgr) SetExpireVar(key string, value *VarExpireData) {
f.getData().VarExpire[key] = value
}
func (f *VarMgr) GetExpireVar(key string) *VarExpireData {
if v, ok := f.getData().VarExpire[key]; ok {
return v
}
data := &VarExpireData{}
f.getData().VarExpire[key] = data
return data
}
func (f *VarMgr) SetUserVar(key string, value *VarUserData) {
f.getData().UserVar[key] = value
}
func (f *VarMgr) GetUserVar(key string) *VarUserData {
if v, ok := f.getData().UserVar[key]; ok {
return v
}
data := &VarUserData{}
f.getData().UserVar[key] = data
return data
}
func (f *VarMgr) DelVar(key string) {
delete(f.getData().Var, key)
}
func (f *VarMgr) getData() *VarData {
return f.data.(*VarData)
}

View File

@ -1,12 +1,11 @@
package game
import (
"fmt"
"server/GoUtil"
activityCfg "server/conf/activity"
catnipCfg "server/conf/catnip"
guesscolorCfg "server/conf/guessColor"
guesscolorCfg "server/conf/guess_color"
itemCfg "server/conf/item"
languageCfg "server/conf/language"
mailCfg "server/conf/mail"
miningCfg "server/conf/mining"
passCfg "server/conf/pass"
@ -14,6 +13,7 @@ import (
"server/game/mod/activity"
"server/game/mod/item"
"server/game/mod/mail"
GoUtil "server/game_util"
"server/msg"
)
@ -60,9 +60,18 @@ func (p *Player) ActivityLogin() {
// 猫草大作战
ActivityId = p.GetActivityId(activity.ACT_TYPE_CATNIP)
CatnipMod := p.PlayMod.getCatnipMod()
OldId = CatnipMod.Login(ActivityId)
if OldId != 0 {
OldId, CatnipUnReward := CatnipMod.Login(ActivityId)
if OldId != 0 && len(CatnipUnReward) > 0 {
// 清空猫草大作战数据无需发邮件
MailMod := p.PlayMod.getMailMod()
MailMod.SendMail(&mail.MailStruct{
Title: languageCfg.GetLanguage(msg.LANG_TYPE_LANG_CN, "backend_gardenend_mail_title"),
TitleEn: languageCfg.GetLanguage(msg.LANG_TYPE_LANG_EN, "backend_gardenend_mail_title"),
Content: languageCfg.GetLanguage(msg.LANG_TYPE_LANG_CN, "backend_gardenend_mail_content"),
ContentEn: languageCfg.GetLanguage(msg.LANG_TYPE_LANG_EN, "backend_gardenend_mail_content"),
Items: CatnipUnReward,
Type: mail.MAIL_TYPE_NORMAL,
})
}
// 通行证
@ -337,6 +346,7 @@ func (p *Player) CatnipBackData() {
Reward: GoUtil.SliceIntToInt32(v.Reward),
Emoji: int32(v.EmojiId),
FriendProgress: int32(v.PartnerAdd),
SendEmoji: int32(v.SendEmoji),
}
if v.Partner != 0 {
PlayerData := G_getGameLogic().GetResSimplePlayerByUid(v.Partner)
@ -349,38 +359,42 @@ func (p *Player) CatnipBackData() {
}
tmpData := make(map[int]*msg.CatnipInvite)
InviteList := make([]*msg.CatnipInvite, 0)
for Uid, Info := range CatnipMod.InviteList {
tmpData[Uid] = &msg.CatnipInvite{
Uid: int64(Uid),
Time: Info.Time,
for uid, info := range CatnipMod.InviteList {
tmpData[uid] = &msg.CatnipInvite{
Uid: int64(uid),
Time: info.Time,
Type: 1,
}
}
for Uid, Info := range CatnipMod.BeInvitedList {
tmpData[Uid] = &msg.CatnipInvite{
Uid: int64(Uid),
Time: Info.Time,
for uid, info := range CatnipMod.BeInvitedList {
tmpData[uid] = &msg.CatnipInvite{
Uid: int64(uid),
Time: info.Time,
Type: 2,
}
}
for Uid := range FriendMod.NewFriendList {
key := fmt.Sprintf("catnip_partner_%d", Uid)
Var := G_GameLogicPtr.VarMgr.GetExpireVar(key)
if len(GoUtil.IntSlice(Var.D)) >= 4 {
tmpData[Uid] = &msg.CatnipInvite{
Uid: int64(Uid),
for uid := range FriendMod.NewFriendList {
partnerList := p.GetCatnipPartner(uid)
if len(GoUtil.IntSlice(partnerList)) >= 4 {
tmpData[uid] = &msg.CatnipInvite{
Uid: int64(uid),
Type: 3,
}
continue
}
if _, ok := tmpData[Uid]; !ok {
tmpData[Uid] = &msg.CatnipInvite{
Uid: int64(Uid),
if _, ok := tmpData[uid]; !ok {
tmpData[uid] = &msg.CatnipInvite{
Uid: int64(uid),
Type: 0,
}
}
}
for _, v := range CatnipMod.Game {
if invite, ok := tmpData[v.Partner]; ok {
invite.Type = 4 // 已参与游戏的好友不显示邀请
}
}
for _, v := range tmpData {
ResPlayerSimple := G_getGameLogic().GetResSimplePlayerByUid(int(v.Uid))
if ResPlayerSimple != nil {
@ -401,14 +415,3 @@ func (p *Player) CatnipBackData() {
}
p.PushClientRes(res)
}
// 设置猫草大作战游戏锁
func (p *Player) SetCatnipGameLock(Uid int, GameId int) error {
ActivityInfo := p.GetActivityInfoById(activity.ACT_TYPE_CATNIP)
return G_GameLogicPtr.SetDataSync(int(p.M_DwUin), VAR_OP_CATNIP_LOCK, CatnipLock{
Uid: int(p.M_DwUin),
Partner: Uid,
GameId: GameId,
End: int(ActivityInfo.EndT), // 锁
})
}

View File

@ -4,11 +4,11 @@ import (
"encoding/json"
"fmt"
"runtime"
"server/GoUtil"
"server/MergeConst"
"server/conf"
"server/db"
Msg "server/game/mod/msg"
GoUtil "server/game_util"
"server/gamedata"
"server/msg"
"server/pkg/github.com/name5566/leaf/gate"
@ -100,7 +100,7 @@ func VerifyUser(accountInfo *db.Db_Account, detail *msg.ReqLogin) (ResLogin *msg
return
}
if G_GameLogicPtr.BanMgr.IsBanned(playerbaseinfo.DwUin) {
if playerbaseinfo.Ban > GoUtil.Now() || playerbaseinfo.Ban == -1 {
ResLogin = &msg.ResLogin{
ResultCode: MergeConst.Protocol_Error_Account_Ban,
DwUin: 0,
@ -176,7 +176,7 @@ func AdminPlayerInfo(args []interface{}) error {
res["Cumulative"] = player.PlayMod.getBaseMod().Cumulative
res["RegisterTime"] = player.GetPlayerBaseMod().GetRegisterTime()
res["TodayCumulative"] = player.PlayMod.getBaseMod().TodayCumulative
res["Ban"] = G_GameLogicPtr.BanMgr.GetBanInfo(player.M_DwUin).EndTime
res["Ban"] = db.GetPlayerBan(player.PlayMod.getBaseMod().Account)
if online {
res["Cumulative"] = int64(player.PlayMod.getBaseMod().Cumulative) + GoUtil.Now() - int64(player.PlayMod.getBaseMod().LoginTime)
res["TodayCumulative"] = int64(player.PlayMod.getBaseMod().TodayCumulative) + GoUtil.Now() - int64(player.PlayMod.getBaseMod().LoginTime)
@ -219,14 +219,22 @@ func ReqServerInfo(args []interface{}) error {
runtime.ReadMemStats(&m)
res["TotalAlloc"] = fmt.Sprintf("%dM", m.TotalAlloc/(1024*1024))
// 2. 获取系统内存使用信息
vmStat, err := mem.VirtualMemory()
if err == nil {
res["Sys"] = fmt.Sprintf("%.2f%%", vmStat.UsedPercent)
}
vmStat, _ := mem.VirtualMemory()
// 3. 获取 CPU 使用率(一秒内采样)
cpuPercent, err := cpu.Percent(time.Second, false)
if err == nil && len(cpuPercent) > 0 {
res["CPU"] = fmt.Sprintf("%.2f%%", cpuPercent[0])
res["CPU"] = cpuPercent[0]
}
res["Alloc"] = fmt.Sprintf("%dM", m.Alloc/(1024*1024))
res["Sys"] = m.Sys / (1024 * 1024)
res["NumGC"] = m.NumGC
res["NumGoroutine"] = runtime.NumGoroutine()
if vmStat != nil {
res["FreeMem"] = vmStat.Available / (1024 * 1024)
res["UsageMem"] = vmStat.Used / (1024 * 1024)
} else {
res["UsageMem"] = 0
res["FreeMem"] = 0
}
res["Version"] = conf.Server.Version
AdminPlayerBack(a, res)
@ -283,7 +291,7 @@ func ReqAdminBan(args []interface{}) error {
res := make(map[string]interface{})
res["Code"] = 0
res["Msg"] = "ok"
G_GameLogicPtr.BanMgr.BanUser(req.Uid, int64(req.Time), req.Reason)
db.UpdatePlayerBan(req.Uid, int64(req.Time))
AdminPlayerBack(a, res)
return nil
}

View File

@ -2,10 +2,10 @@ package game
import (
"math"
"server/GoUtil"
champshipCfg "server/conf/champship"
randnameCfg "server/conf/randname"
"server/game/mod/msg"
GoUtil "server/game_util"
proto "server/msg"
"server/pkg/github.com/name5566/leaf/log"
"sort"
@ -81,67 +81,53 @@ func (c *ChampshipMgr) Init() {
}
// 注册处理函数
c.init()
c.RegisterHandler(msg.HANDLE_TYPE_CHAMPSHIP_GROUP, c.group)
c.RegisterHandler(msg.HANDLE_TYPE_CHAMPSHIP_INRANK, c.inRank)
c.RegisterHandler(msg.HANDLE_TYPE_CHAMPSHIP_AI, c.ai)
c.RegisterHandler(msg.SERVER_ZERO_UPDATE, c.ZeroUpdate)
c.RegisterHandler(msg.HANDLE_TYPE_CHAMPSHIP_NOTIFY2, c.NotifyAll)
Now := GoUtil.Now()
ZeroTime := GoUtil.ZeroTimestamp()
if c.getData().ZeroTime != ZeroTime {
c.ZeroUpdate(&msg.Msg{})
c.ZeroUpdate()
}
Remain := Now - ZeroTime
Remain1 := 1800 - Remain%1800
c.mDispatr.AfterFunc(time.Duration(Remain1)*time.Second, func() { // 30分钟后重新分组
c.Send(&msg.Msg{
Type: msg.HANDLE_TYPE_CHAMPSHIP_GROUP,
})
c.group()
})
c.mDispatr.AfterFunc(time.Duration(60)*time.Second, func() {
c.Send(&msg.Msg{
Type: msg.HANDLE_TYPE_CHAMPSHIP_AI,
})
c.ai()
})
c.mDispatr.AfterFunc(time.Duration(GoUtil.NextZeroTimestampDuration())*time.Second, func() {
c.Send(&msg.Msg{
Type: msg.SERVER_ZERO_UPDATE,
})
c.ZeroUpdate()
})
}
func (c *ChampshipMgr) NotifyAll(m *msg.Msg) (interface{}, error) {
G_GameLogicPtr.NotifyAll(&msg.Msg{
func (c *ChampshipMgr) NotifyAll() (interface{}, error) {
NotifyAllPlayerMsg(&msg.Msg{
Type: msg.HANDLE_TYPE_CHAMPSHIP_NOTIFY,
HandleType: msg.HANDLE_MOD_PLAYER_MSG,
})
return nil, nil
}
func (c *ChampshipMgr) ZeroUpdate(m *msg.Msg) (interface{}, error) {
func (c *ChampshipMgr) ZeroUpdate() (interface{}, error) {
log.Debug("ChampshipMgr ZeroUpdate")
c.getData().ZeroTime = GoUtil.ZeroTimestamp()
c.getData().PreRank = c.getData().Rank
c.getData().PreRobot = c.getData().Robot
c.getData().PreGroupInfo = c.getData().GroupInfo
c.getData().AutoId = 0
c.getData().RobotId = 1
c.getData().Robot = make(map[int]*ChampshipRobot, 0)
c.getData().Rank = make(map[int][]*ChampshipRank, 0)
c.getData().GroupInfo = make(map[int]int, 0)
c.update = true
c.mDispatr.AfterFunc(time.Duration(GoUtil.NextZeroTimestampDuration())*time.Second, func() {
c.Send(&msg.Msg{
Type: msg.SERVER_ZERO_UPDATE,
})
c.ZeroUpdate()
})
c.NotifyPlayer()
c.mDispatr.AfterFunc(time.Duration(1800)*time.Second, func() {
c.Send(&msg.Msg{
Type: msg.HANDLE_TYPE_CHAMPSHIP_NOTIFY2,
})
c.NotifyAll()
})
return nil, nil
}
@ -158,7 +144,7 @@ func (c *ChampshipMgr) NotifyPlayer() {
}
}
func (c *ChampshipMgr) ai(m *msg.Msg) (interface{}, error) {
func (c *ChampshipMgr) ai() (interface{}, error) {
ChampshipData := c.getData()
Now := GoUtil.Now()
for k, v := range ChampshipData.Rank {
@ -205,9 +191,7 @@ func (c *ChampshipMgr) ai(m *msg.Msg) (interface{}, error) {
ChampshipData.Rank[k] = v
}
c.mDispatr.AfterFunc(time.Duration(60)*time.Second, func() {
c.Send(&msg.Msg{
Type: msg.HANDLE_TYPE_CHAMPSHIP_AI,
})
c.ai()
})
return nil, nil
}
@ -265,6 +249,8 @@ func (c *ChampshipMgr) GetPreRankMsg(Uid int) *proto.ResChampshipPreRank {
RankList: RL,
}
}
// TODO 待优化
func (c *ChampshipMgr) GetRankMsg(Uid int) *proto.ResChampshipRank {
ChampshipData := c.getData()
GroupId := ChampshipData.GroupInfo[Uid]
@ -320,11 +306,9 @@ func (c *ChampshipMgr) GetRankMsg(Uid int) *proto.ResChampshipRank {
}
// 分组
func (c *ChampshipMgr) group(m *msg.Msg) (interface{}, error) {
func (c *ChampshipMgr) group() (interface{}, error) {
c.mDispatr.AfterFunc(time.Duration(1800)*time.Second, func() { // 30分钟后重新分组
c.Send(&msg.Msg{
Type: msg.HANDLE_TYPE_CHAMPSHIP_GROUP,
})
c.group()
})
Now := GoUtil.Now()
Zero := GoUtil.ZeroTimestamp()

View File

@ -4,7 +4,6 @@ import (
"encoding/json"
"fmt"
"os/exec"
"server/GoUtil"
"server/MergeConst"
"server/conf"
activityCfg "server/conf/activity"
@ -14,8 +13,9 @@ import (
"server/game/mod/activity"
"server/game/mod/item"
MsgMod "server/game/mod/msg"
"server/game/mod/piggyBank"
piggyBank "server/game/mod/piggy_bank"
"server/game/mod/quest"
GoUtil "server/game_util"
proto "server/msg"
"server/pkg/github.com/name5566/leaf/log"
"strings"
@ -35,7 +35,7 @@ func (p *Player) Charge(ChargeId int) {
}
func (p *Player) SendCharge(d *ChargeExtra) {
G_GameLogicPtr.FriendMgrSend(&MsgMod.Msg{
FriendMgrSend(&MsgMod.Msg{
From: int(p.M_DwUin),
Type: MsgMod.HANDLE_TYPE_SEND_CHARGE,
To: int(d.Uid),

View File

@ -11,20 +11,12 @@ func ClusterMgrInit() {
go func() {
for {
m := <-mergeCluster.MsgChan
clusterHandlerProcess(m)
MessageHandle(m)
}
}()
}
func clusterHandlerProcess(m *msg.Msg) {
if fun, ok := clusterHandler[m.Type]; ok {
fun(m)
} else {
FriendMgrSend(m)
}
}
func RegisterClusterHandler(t int, fun func(*msg.Msg) error) {
clusterHandler[t] = fun
}
@ -39,6 +31,7 @@ func init() {
RegisterClusterHandler(msg.CLUSTER_FRIEND_SYNC, ClusterFriendSync)
RegisterClusterHandler(msg.HANDLE_TYPE_CHAMPSHIP_INRANK, champshipInrankHandler)
RegisterClusterHandler(msg.HANDLE_TYPE_CHAMPSHIP_RANK_INFO, champshipRankInfoHandler)
RegisterClusterHandler(msg.HANDLE_TYPE_CHAMPSHIP_MY_RANK, champshipMyRankHandler)
}
func champshipInrankHandler(m *msg.Msg) error {
@ -54,3 +47,12 @@ func champshipRankInfoHandler(m *msg.Msg) error {
FriendMgrSend(m)
return nil
}
func champshipMyRankHandler(m *msg.Msg) error {
MyRank := G_GameLogicPtr.ChampshipMgr.getMyRank(m.From)
m.To = m.From
m.From = 0
m.Extra = MyRank
FriendMgrSend(m)
return nil
}

View File

@ -3,10 +3,10 @@ package game
import (
"fmt"
"reflect"
"server/GoUtil"
"server/MergeConst"
"server/conf"
"server/game/internal"
GoUtil "server/game_util"
"strings"
"time"

View File

@ -1,9 +1,9 @@
package game
import (
"server/GoUtil"
"server/db"
"server/game/mod/msg"
GoUtil "server/game_util"
"server/pkg/github.com/name5566/leaf/log"
"sort"
)

View File

@ -3,14 +3,13 @@ package game
import (
"encoding/gob"
"fmt"
"server/GoUtil"
"server/MergeConst"
mergeCluster "server/cluster"
"server/conf"
"server/game/mod/card"
"server/game/mod/friend"
"server/game/mod/item"
"server/game/mod/msg"
GoUtil "server/game_util"
"server/pkg/github.com/name5566/leaf/log"
)
@ -45,7 +44,6 @@ func (f *FriendMgr) Init() {
f.RegisterHandler(msg.HANDLE_TYPE_APPLY, f.sendToPlayer)
f.RegisterHandler(msg.HADNLE_TYPE_AGREE, f.sendToPlayer)
f.RegisterHandler(msg.HANDLE_TYPE_DEL, f.sendToPlayer)
f.RegisterHandler(msg.HANDLE_TYPE_SYNC, f.sync)
f.RegisterHandler(msg.HANDLE_TYPE_REFUSE, f.sendToPlayer)
f.RegisterHandler(msg.HANDLE_TYPE_INVITE_ADD_FRIEND, f.sendToPlayer)
f.RegisterHandler(msg.HANDLE_TYPE_INVITE_FRIEND, f.sendToPlayer)
@ -88,12 +86,8 @@ func (f *FriendMgr) Init() {
f.RegisterHandler(msg.HANDLE_TYPE_PLAYROOM_KISS, f.sendToPlayerOnline)
f.RegisterHandler(msg.HANDLE_TYPE_PLAYROOM_GAME, f.sendToPlayer)
f.RegisterHandler(msg.HANDLE_TYPE_VAR_USER_GET, f.GetVarUserData)
f.RegisterHandler(msg.HANDLE_TYPE_VAR_USER_SET, f.SetVarUserData)
f.RegisterHandler(msg.HANDLE_TYPE_VAR_EXPIRE_SET, f.SetExpireVarData)
f.RegisterHandler(msg.HANDLE_TYPE_CHAMPSHIP_LOGIN, f.SendMsgToCenter)
f.RegisterHandler(msg.HANDLE_TYPE_CHAMPSHIP_INRANK, f.SendMsgToCenter)
}
func (f *FriendMgr) getData() *FirendData {
@ -138,71 +132,6 @@ func (f *FriendMgr) sendToPlayerOnline(m *msg.Msg) (interface{}, error) {
return nil, nil
}
// 同步信息
func (f *FriendMgr) sync(m *msg.Msg) (interface{}, error) {
data := f.getData().List[m.From]
return data, nil
}
func (f *FriendMgr) GetVarUserData(m *msg.Msg) (interface{}, error) {
Key := GoUtil.GetUserKey(int64(m.To))
data := G_GameLogicPtr.VarMgr.GetUserVar(Key)
if data == nil {
data = &VarUserData{
Upvote: 0,
}
}
return data, nil
}
func (f *FriendMgr) SetVarUserData(m *msg.Msg) (interface{}, error) {
VarOp := m.Extra.(VarOpration)
Key := GoUtil.GetUserKey(int64(m.To))
data := G_GameLogicPtr.VarMgr.GetUserVar(Key)
switch VarOp.Type {
case VAR_OP_UPVOTE:
data.Upvote++
case VAR_OP_CHIP:
data.Chip += VarOp.Data.(int)
case VAR_OP_CHIP_SET:
data.Chip = VarOp.Data.(int)
case VAR_OP_KISS:
data.Kiss = VarOp.Data.(int)
}
return &VarOpration{
Data: data,
Code: MergeConst.SUCCESS,
}, nil
}
func (f *FriendMgr) SetExpireVarData(m *msg.Msg) (interface{}, error) {
VarOp := m.Extra.(VarOpration)
switch VarOp.Type {
case VAR_OP_CATNIP_LOCK:
data := VarOp.Data.(CatnipLock)
MyKey := GoUtil.GetCatnipLockKey(data.Uid, data.GameId)
OtherKey := GoUtil.GetCatnipLockKey(data.Partner, data.GameId)
ExpireData := G_GameLogicPtr.VarMgr.GetExpireVar(OtherKey)
if _, ok := ExpireData.D.(*CatnipLock); ok {
return nil, fmt.Errorf("catnip lock already exists for %d in game %d", data.Uid, data.GameId)
}
G_GameLogicPtr.VarMgr.SetExpireVar(MyKey, &VarExpireData{
T: int64(data.End + 24*3600), // 设置过期时间
D: &data,
})
G_GameLogicPtr.VarMgr.SetExpireVar(OtherKey, &VarExpireData{
T: int64(data.End + 24*3600), // 设置过期时间
D: &CatnipLock{
Uid: data.Partner,
Partner: data.Uid,
GameId: data.GameId,
End: data.End,
},
})
}
return nil, nil
}
// 发送消息给玩家
func sendToPlayer(m *msg.Msg) error {
p := G_GameLogicPtr.GetPlayer(int64(m.To))
@ -222,24 +151,6 @@ func sendToPlayerOnline(m *msg.Msg) error {
return nil
}
func FriendMgrSend(m1 *msg.Msg) error {
if m1.SendT == 0 {
m1.SendT = GoUtil.Now()
}
m := m1.Clone()
ToServer := GoUtil.GetServerIdByUid(m.To)
if ToServer != conf.Server.ServerID {
err := mergeCluster.SendServerMsg(m, ToServer)
if err != nil { // 区服不在线
G_GameLogicPtr.FriendMgrSend(m)
return err
}
return nil
}
G_GameLogicPtr.FriendMgrSend(m)
return nil
}
// 集群好友消息同步
func ClusterFriendSync(m *msg.Msg) error {
if v, ok := G_GameLogicPtr.FriendMgr.getData().ClusterMsg[m.To]; ok {
@ -264,16 +175,3 @@ func (f *FriendMgr) SendMsgToCenter(m *msg.Msg) (interface{}, error) {
func (f *FriendMgr) CallMsgToCenter(m *msg.Msg) (interface{}, error) {
return mergeCluster.CallServerMsg(m, conf.Server.CenterNode)
}
func FriendMgrCall(m *msg.Msg) interface{} {
ToServer := GoUtil.GetServerIdByUid(m.To)
if ToServer != conf.Server.ServerID {
r, err := mergeCluster.CallServerMsg(m, ToServer)
if err != nil { // 区服不在线
log.Debug("FriendMgrCall err %v", err)
return nil
}
return r
}
return G_GameLogicPtr.FriendMgrCall(m.Clone())
}

View File

@ -2,9 +2,13 @@ package game
import (
"encoding/gob"
"server/game/mod/card"
"server/game/mod/friend"
"server/game/mod/limitedTimeEvent"
"server/game/mod/item"
limitedTimeEvent "server/game/mod/limited_time_event"
"server/game/mod/msg"
proto "server/msg"
"sync"
)
type PlayerSimpleData struct {
@ -49,11 +53,21 @@ type VarUserData struct {
Upvote int
Chip int
Kiss int
mu sync.Mutex
}
type VarExpireData struct {
D interface{}
T int64
T int64 // 过期时间戳
U int64 // 最后更新时间
mu sync.Mutex
}
type CatnipPartner struct {
Uid int
Partner int
GameId int
EndTime int64
}
const (
@ -108,7 +122,13 @@ func init() {
gob.Register(&VarUserData{})
gob.Register(&ActivityInfo{})
gob.Register(&ChargeExtra{})
gob.Register(&GameResult{})
gob.Register(CatnipMsg{})
gob.Register(&CatnipLock{})
gob.Register(CRank{})
gob.Register(&proto.ResChampshipRank{})
gob.Register(&proto.ResChampshipPreRank{})
gob.Register(card.CardInfo{})
gob.Register(item.Item{})
gob.Register([]*item.Item{}) // 注册 []*item.Item 类型
gob.Register(friend.ReplyInfo{})
}

View File

@ -5,14 +5,13 @@ import (
"encoding/gob"
"fmt"
"os"
"server/GoUtil"
"server/conf"
avatarCfg "server/conf/avatar"
cardCfg "server/conf/card"
chargeCfg "server/conf/charge"
emojiCfg "server/conf/emoji"
faceCfg "server/conf/face"
mergeDataCfg "server/conf/mergeData"
mergeDataCfg "server/conf/merge_data"
playroomCfg "server/conf/playroom"
"server/db"
"server/game/mod/activity"
@ -23,14 +22,17 @@ import (
"server/game/mod/emoji"
"server/game/mod/face"
"server/game/mod/friend"
"server/game/mod/handbook"
"server/game/mod/item"
MsgMod "server/game/mod/msg"
"server/game/mod/order"
"server/game/mod/playroom"
GoUtil "server/game_util"
"server/msg"
"server/pkg/github.com/name5566/leaf/log"
"strconv"
"strings"
"time"
"google.golang.org/protobuf/proto"
)
@ -49,7 +51,7 @@ func ReqGmCommand_(player *Player, Command string) error {
// log.Error("ReqGmCommand panic: %v", err)
// }
// }()
if conf.Server.GameName != "pet_home" && conf.Server.GameName != "merge_pet_sdk" && conf.Server.GameName != "Merge_Pet_Local" {
if conf.Server.GameName != "pet_home" && conf.Server.GameName != "merge_pet_sdk" && conf.Server.GameName != "Merge_Pet_Local" && conf.Server.GameName != "pet_home_local" {
return fmt.Errorf("Player %d ReqGmCommand not support in game %s, command %s", player.M_DwUin, conf.Server.GameName, Command)
}
player.TeLog("gm", map[string]interface{}{
@ -154,19 +156,19 @@ func ReqGmCommand_(player *Player, Command string) error {
ChessMod.PartBag.List = make(map[int]chess.PartBagGrid)
}
ChessMod.PartBag.List[1505] = chess.PartBagGrid{
Num: 10000,
Num: 100,
PartId: 1505,
}
ChessMod.PartBag.List[1515] = chess.PartBagGrid{
Num: 10000,
Num: 100,
PartId: 1515,
}
ChessMod.PartBag.List[1525] = chess.PartBagGrid{
Num: 10000,
Num: 100,
PartId: 1525,
}
ChessMod.PartBag.List[1535] = chess.PartBagGrid{
Num: 10000,
Num: 100,
PartId: 1535,
}
case "AllFace":
@ -280,7 +282,14 @@ func ReqGmCommand_(player *Player, Command string) error {
HandbookMod := player.PlayMod.getHandbookMod()
for _, v := range mergeDataCfg.GetAllId() {
HandbookMod.SetHandbook(v)
HandbookMod.BookList[v] = handbook.STATUS_REWARD
}
case "handbookReward":
HandbookMod := player.PlayMod.getHandbookMod()
for _, v := range mergeDataCfg.GetAllId() {
HandbookMod.BookList[v] = handbook.STATUS_REWARD
}
player.PushClientRes(HandbookMod.BackData())
case "deleteOrder":
Id, _ := strconv.Atoi(arg[1])
OrderMod := player.PlayMod.getOrderMod()
@ -393,16 +402,12 @@ func ReqGmCommand_(player *Player, Command string) error {
CardList := cardCfg.GetAllCardId(CardMod.Round)
for _, v := range CardList {
player.AddCard(v)
CardMod.Handbook[v] = card.HANDBOOK_STATUS_GET
}
player.PushClientRes(CardMod.NotifyCard())
case "resetRankUser":
O := G_GameLogicPtr.RankMgr.getAllRank(RANK_TYPE_USER)
for _, v := range O {
Uid := strconv.Itoa(v.Uid)
TimeSort := fmt.Sprintf("0.%d", RANK_TIME_SORT-GoUtil.Now())
TimeSortF, _ := strconv.ParseFloat(TimeSort, 64)
db.RedisZAdd(RANK_USER, Uid, v.Score+TimeSortF)
}
db.RedisDelKey(RANK_USER)
db.RedisDelKey(fmt.Sprintf("%s_%s", RANK_COUNTRY_USER, conf.Server.CountryCode))
case "addFriendStar":
FriendTreasureMod := player.PlayMod.getFriendTreasureMod()
FriendTreasureMod.AddStar(200)
@ -441,6 +446,7 @@ func ReqGmCommand_(player *Player, Command string) error {
DecorateMod.FinishList[i] = struct{}{}
}
DecorateMod.Progress = S
player.PushClientRes(DecorateMod.BackData())
case "resetCardSeasonFirst":
CardMod := player.PlayMod.getCardMod()
CardMod.SeasonFirst = false
@ -515,7 +521,9 @@ func ReqGmCommand_(player *Player, Command string) error {
BaseMod := p1.PlayMod.getBaseMod()
BaseMod.Uid = player.M_DwUin
BaseMod.NickName = player.PlayMod.getBaseMod().NickName
BaseMod.Account = player.PlayMod.getBaseMod().Account
BaseMod.LoginTime = GoUtil.Now()
BaseMod.AddCode = fmt.Sprintf("MMM-%s-%s", "156", GoUtil.UniqueStringFromInt(int(BaseMod.Uid)))
// deep copy p1.PlayMod.mod_list to avoid sharing internal pointers
var modCopy PlayerModList
var buf bytes.Buffer
@ -553,6 +561,20 @@ func ReqGmCommand_(player *Player, Command string) error {
PlayroomMod := player.PlayMod.getPlayroomMod()
PlayroomMod.WeeklyDiscount = make(map[int]int)
player.PlayroomBackData()
case "resetPlayer":
de := time.Now().Format("2006-01-02 15:04:05")
BaseMod := player.PlayMod.getBaseMod()
account := BaseMod.Account
newAccount := fmt.Sprintf("%s_reset_%s", account, de)
err := db.ResetAccountData(account, newAccount)
if err != nil {
log.Error("resetPlayer err:%s", err.Error())
return err
}
log.Debug("player reset: old account: %s; new account %s", account, newAccount)
BaseMod.Account = newAccount
player.GetPlayerBaseMod().Data.UserName = newAccount
player.PushAndSendClienRes(&msg.ForceKickOut{})
case "resetCode":
BaseMod := player.PlayMod.getBaseMod()
BaseMod.AddCode = fmt.Sprintf("MMM-%s-%s", "156", GoUtil.UniqueStringFromInt(int(BaseMod.Uid)))

View File

@ -1,8 +1,8 @@
package internal
import (
"server/GoUtil"
"server/MergeConst"
GoUtil "server/game_util"
"sync"
"server/pkg/github.com/name5566/leaf/gate"

View File

@ -1,8 +1,8 @@
package internal
import (
"server/GoUtil"
"server/base"
GoUtil "server/game_util"
"server/pkg/github.com/name5566/leaf/module"
)

View File

@ -3,14 +3,14 @@ package game
import (
"fmt"
"math"
"server/GoUtil"
playroomCfg "server/conf/playroom"
userCfg "server/conf/user"
"server/game/mod/card"
"server/game/mod/item"
"server/game/mod/limitedTimeEvent"
limitedTimeEvent "server/game/mod/limited_time_event"
MsgMod "server/game/mod/msg" // Ensure this package exists and is correctly referenced
"server/game/mod/playroom"
GoUtil "server/game_util"
"server/msg"
"time"
)

View File

@ -197,6 +197,15 @@ func (L *LogMgr) InitManager() {
}
func (L *LogMgr) AddLog(logs *Log) {
// 复制结构体和 Param map避免并发修改导致 json.Marshal 时 panic
copyLog := *logs
if logs.Param != nil {
newParam := make(map[string]interface{}, len(logs.Param))
for k, v := range logs.Param {
newParam[k] = v
}
copyLog.Param = newParam
}
// 如果已经开始关闭,直接丢弃
L.Lock.Lock()
if L.closing {

View File

@ -2,10 +2,10 @@ package game
import (
"encoding/json"
"server/GoUtil"
"server/db"
"server/game/mod/item"
"server/game/mod/msg"
GoUtil "server/game_util"
"server/pkg/github.com/name5566/leaf/log"
"strings"
)

View File

@ -2,15 +2,14 @@ package game
import (
"fmt"
"server/GoUtil"
mergeCluster "server/cluster"
cardCfg "server/conf/card"
catnipCfg "server/conf/catnip"
decorateCfg "server/conf/decorate"
itemCfg "server/conf/item"
limitedTimeEventCfg "server/conf/limitedTimeEvent"
limitedTimeEventCfg "server/conf/limited_time_event"
mailCfg "server/conf/mail"
mergeDataCfg "server/conf/mergeData"
mergeDataCfg "server/conf/merge_data"
orderCfg "server/conf/order"
playroomCfg "server/conf/playroom"
userCfg "server/conf/user"
@ -18,11 +17,12 @@ import (
"server/game/mod/card"
"server/game/mod/friend"
"server/game/mod/item"
"server/game/mod/limitedTimeEvent"
limitedTimeEvent "server/game/mod/limited_time_event"
"server/game/mod/mail"
"server/game/mod/msg"
"server/game/mod/order"
"server/game/mod/playroom"
GoUtil "server/game_util"
proto "server/msg"
"server/pkg/github.com/name5566/leaf/log"
"sort"
@ -416,7 +416,18 @@ func (p *Player) handle(m *msg.Msg) error {
}
CatnipMod.BeInvited(int(m.From), m.SendT)
FriendMod := p.PlayMod.getFriendMod()
FriendMod.AddReplyInfo(m.From, friend.REPLY_TYPE_CATNIP, fmt.Sprintf("%d", CatnipMsg.GameId), m.End, nil)
ReplyInfo := FriendMod.AddReplyInfo(m.From, friend.REPLY_TYPE_CATNIP, fmt.Sprintf("%d", CatnipMsg.GameId), m.End, nil)
PlayerSimpleData := G_GameLogicPtr.GetResSimplePlayerByUid(m.From)
p.PushClientRes(&proto.ResFriendReplyNotify{
Info: &proto.ResFriendReply{
Player: PlayerSimpleData,
Param: ReplyInfo.Param,
Type: int32(ReplyInfo.Type),
Id: int32(ReplyInfo.Id),
},
Type: int32(friend.REPLY_TYPE_CATNIP),
Time: int32(m.SendT),
})
case msg.HANDLE_TYPE_CATNIP_AGREE: // 同意好友参与猫咪游戏
CatnipMod := p.PlayMod.getCatnipMod()
CatnipMsg, ok := m.Extra.(CatnipMsg)
@ -464,7 +475,18 @@ func (p *Player) handle(m *msg.Msg) error {
if CatnipMsg.FriendItems > 0 {
Items := catnipCfg.GetItemCost(ActivityId, CatnipMsg.FriendItems)
FriendMod := p.PlayMod.getFriendMod()
FriendMod.AddReplyInfo(m.From, friend.REPLY_TYPE_CATNIP_ITEMS, "", m.End, Items)
ReplyInfo := FriendMod.AddReplyInfo(m.From, friend.REPLY_TYPE_CATNIP_ITEMS, "", m.End, Items)
PlayerSimpleData := G_GameLogicPtr.GetResSimplePlayerByUid(m.From)
p.PushClientRes(&proto.ResFriendReplyNotify{
Info: &proto.ResFriendReply{
Player: PlayerSimpleData,
Param: ReplyInfo.Param,
Type: int32(ReplyInfo.Type),
Id: int32(ReplyInfo.Id),
},
Type: int32(friend.REPLY_TYPE_CATNIP_ITEMS),
Time: int32(m.SendT),
})
}
p.CatnipBackData()
case msg.HANDLE_TYPE_CATNIP_SEND_EMOJI:
@ -487,38 +509,6 @@ func (p *Player) handle(m *msg.Msg) error {
return nil
}
// 同步好友请求
func (p *Player) SyncFriendMsg() {
MsgList := G_GameLogicPtr.FriendMgrCall(&msg.Msg{Type: msg.HANDLE_TYPE_SYNC, From: int(p.M_DwUin)})
FriendMod := p.PlayMod.getFriendMod()
MsgId := FriendMod.GetSyncId()
if MsgList == nil {
return
}
ml := MsgList.([]*msg.Msg)
if len(ml) == 0 {
return
}
sort.Slice(ml, func(i, j int) bool {
return ml[i].Id < ml[j].Id
})
maxId := int64(0)
for _, v := range ml {
maxId = max(maxId, v.Id)
if v.H == 1 {
continue
}
if v.Id > 0 && v.Id <= MsgId {
continue
}
log.Debug("uid : %d, handle friend msg : %v", p.M_DwUin, v)
p.handle(v)
v.H = 1
}
FriendMod.SetSyncId(maxId)
p.PlayMod.save()
}
func SyncMailMsg(p *Player) {
ServerMailList := G_GameLogicPtr.MailMgr.Sync(int(p.M_DwUin), p.GetPlayerBaseMod().GetRegisterTime())
MailMod := p.PlayMod.getMailMod()
@ -586,6 +576,9 @@ func GetCardInfoMsg(CardInfo *card.CardInfo) *proto.ResFriendCard {
}
ps := G_GameLogicPtr.GetSimplePlayerByUid(Uid)
if ps == nil {
return &proto.ResFriendCard{}
}
return &proto.ResFriendCard{
Uid: int64(Uid),
Name: ps.Name,
@ -711,7 +704,7 @@ func NotifyChampshipResult(Uid, Rank int) {
SendT: GoUtil.Now(),
Extra: []int{Rank, GoUtil.GetServerOpenDay()},
}
FriendMgrSend(Msg)
CenterPlayerMsgHandler(Msg)
}
}
@ -1277,3 +1270,18 @@ func (player *Player) IsWeeklyDiscount() bool {
LimitEventMod := player.PlayMod.getLimitedTimeEventMod()
return ChargeMod.IsWeeklyDiscountDay() || LimitEventMod.CheckExist(limitedTimeEvent.EVENT_TYPE_CAT_DAY_SALE)
}
func (p *Player) SetCatnipPartner(GameId, Partner int, EndTime int64) error {
_, err := SendMsgToCenterSync(&msg.Msg{
From: int(p.M_DwUin),
To: int(p.M_DwUin),
Type: msg.HANDLE_MOD_CATNIP_PARTNER,
Extra: CatnipPartner{
GameId: GameId,
Partner: Partner,
EndTime: EndTime,
Uid: int(p.M_DwUin),
},
})
return err
}

View File

@ -0,0 +1,781 @@
package game
import (
"context"
"encoding/gob"
"fmt"
"runtime/debug"
mergeCluster "server/cluster"
"server/conf"
"server/game/mod/msg"
GoUtil "server/game_util"
"server/pkg/github.com/name5566/leaf/log"
"sync"
"time"
)
var id = 1
// 中间件函数类型
type MessageMiddleware func(MessageHandlerFunc) MessageHandlerFunc
var save_msg_type = []int{
msg.HANDLE_MOD_PLAYER_MSG,
msg.HANDLE_MDO_CHAMPSHIP_INRANK,
msg.HANDLE_MOD_USER_VAR_SET,
}
type MessageMgr struct {
*ServerMod
middlewares []MessageMiddleware
workerPool *WorkerPool
handler map[int]MessageHandlerFunc
}
type MessageData struct {
MessageList map[int64]*MessageList
PlayerList map[int64]int
mu sync.Mutex
}
type MessageList struct {
Messages []*msg.Msg
mu sync.Mutex
}
// Worker Pool 结构
type WorkerPool struct {
workers int
minWorkers int
maxWorkers int
taskQueue chan *MessageTask
wg sync.WaitGroup
ctx context.Context
cancel context.CancelFunc
maxQueue int
mu sync.Mutex
workerCancels []context.CancelFunc
monitorTick *time.Ticker
}
// 消息任务
type MessageTask struct {
Msg *msg.Msg
Handler MessageHandlerFunc
Result chan *TaskResult
id int
}
// 任务结果
type TaskResult struct {
Data interface{}
Error error
}
func (m *MessageMgr) MessageMgrInit() {
m.key = MESSAGE_MGR_KEY + fmt.Sprintf("_%d", conf.Server.ServerID)
m.data = &MessageData{
MessageList: make(map[int64]*MessageList),
PlayerList: make(map[int64]int),
}
gob.Register(msg.VarData{})
gob.Register(GameResult{})
// 注册处理函数
m.init()
m.handler = make(map[int]MessageHandlerFunc)
m.middlewares = []MessageMiddleware{}
// 初始化 Worker Pool (10个worker, 1000个队列大小)
m.workerPool = NewWorkerPool(50, 10000)
// 注册默认中间件
m.Use(RecoveryMiddleware())
m.Use(LoggingMiddleware())
m.Use(TimeoutMiddleware(5 * time.Second))
m.NodeRegister()
m.CenterRegister()
}
// 注册处理器
func (s *MessageMgr) RegisterHandler(HandlerType int, fun MessageHandlerFunc) {
s.handler[HandlerType] = fun
}
func (m *MessageMgr) NodeRegister() {
if conf.Server.ServerType == "node" {
m.RegisterHandler(msg.HANDLE_MOD_PLAYER_MSG, MessageHandlerFunc(PlayerMsgHandler))
m.RegisterHandler(msg.HANDLE_MOD_REPLY_PLAYER_MSG, MessageHandlerFunc(PlayerReplyMsgHandler))
m.RegisterHandler(msg.HANDLE_MOD_CLUSTER_SYNC, MessageHandlerFunc(ClusterSyncHandler))
}
}
func (m *MessageMgr) CenterRegister() {
if conf.Server.ServerType == "center" {
m.RegisterHandler(msg.HANDLE_MOD_PLAYER_LOGIN, MessageHandlerFunc(PlayerLoginHandler))
m.RegisterHandler(msg.HANDLE_MDO_PLAYER_LOGOUT, MessageHandlerFunc(PlayerLogoutHandler))
m.RegisterHandler(msg.HANDLE_MOD_PLAYER_MSG, MessageHandlerFunc(CenterPlayerMsgHandler))
m.RegisterHandler(msg.HANDLE_MOD_COMSUME_MSG, MessageHandlerFunc(ComsumerMsgHandler))
m.RegisterHandler(msg.HANDLE_MOD_VAR_SET, MessageHandlerFunc(SetVarDataHandler))
m.RegisterHandler(msg.HANDLE_MOD_VAR_GET, MessageHandlerFunc(GetVarDataHandler))
m.RegisterHandler(msg.HANDLE_MOD_USER_VAR_SET, MessageHandlerFunc(SetUserVarDataHandler))
m.RegisterHandler(msg.HANDLE_MOD_USER_VAR_GET, MessageHandlerFunc(GetUserVarDataHandler))
m.RegisterHandler(msg.HANDLE_MOD_CATNIP_PARTNER, MessageHandlerFunc(CatnipPartnerHandler))
m.RegisterHandler(msg.HANDLE_MDO_CHAMPSHIP_INRANK, MessageHandlerFunc(ChampshipInRankHandler))
m.RegisterHandler(msg.HANDLE_MOD_CHAMPSHIP_RANK_INFO, MessageHandlerFunc(ChampshipRankInfoHandler))
m.RegisterHandler(msg.HANDLE_MOD_CHAMPSHIP_RANK_LIST, MessageHandlerFunc(ChampshipRankListHandler))
m.RegisterHandler(msg.HANDLE_MOD_CHAMPSHIP_PRE_RANK, MessageHandlerFunc(ChampshipRankPreHandler))
}
}
func getMessageData() *MessageData {
return G_GameLogicPtr.MessageMgr.data.(*MessageData)
}
// ----------------------------------- 处理函数实现 ---------------------------
func ChampshipRankPreHandler(data *msg.Msg) (interface{}, error) {
PlayerId := data.From
PreRankMsg := G_GameLogicPtr.ChampshipMgr.GetPreRankMsg(PlayerId)
ReplyPlayerMsgASync(data, PreRankMsg)
return nil, nil
}
func ChampshipRankListHandler(data *msg.Msg) (interface{}, error) {
PlayerId := data.From
RankMsg := G_GameLogicPtr.ChampshipMgr.GetRankMsg(PlayerId)
ReplyPlayerMsgASync(data, RankMsg)
return nil, nil
}
func ChampshipRankInfoHandler(data *msg.Msg) (interface{}, error) {
PlayerId := data.From
MyRank := G_GameLogicPtr.ChampshipMgr.getMyRank(PlayerId)
MyPreRank := G_GameLogicPtr.ChampshipMgr.getLastMyRank(PlayerId)
ReplyPlayerMsgASync(data, []int{MyRank, MyPreRank})
return nil, nil
}
func NotifyAllPlayerMsg(m *msg.Msg) {
messageMgrData := getMessageData()
for PlayerId, node := range messageMgrData.PlayerList {
m.To = int(PlayerId)
SendMsgToNodeAsync(m, node)
}
}
func ChampshipInRankHandler(data *msg.Msg) (interface{}, error) {
G_GameLogicPtr.ChampshipMgr.inRank(data)
return nil, nil
}
func CatnipPartnerHandler(data *msg.Msg) (interface{}, error) {
m, ok := data.Extra.(*CatnipPartner)
if !ok {
return nil, fmt.Errorf("invalid catnip partner data")
}
return G_GameLogicPtr.VarMgr.HandleCatnipPartner(m.Uid, m.Partner, m.GameId, m.EndTime)
}
func ReplyPlayerMsgASync(m *msg.Msg, reply interface{}) (interface{}, error) {
clone := m.Reply(reply)
messageMgrData := getMessageData()
if node, ok := messageMgrData.PlayerList[int64(m.From)]; ok {
SendMsgToNodeAsync(clone, node)
}
return nil, nil
}
// 节点连接时,同步消息
func ClusterSyncHandler(data *msg.Msg) (interface{}, error) {
// 遍历所有玩家,发送登录消息
G_GameLogicPtr.M_Players.Range(func(k, v interface{}) bool {
SendMsgToCenterAsync(&msg.Msg{
From: int(v.(*Player).M_DwUin),
HandleType: msg.HANDLE_MOD_PLAYER_LOGIN,
Extra: conf.Server.ServerID,
})
return true
})
// 发送暂存区消息
messageMgrData := getMessageData()
messageMgrData.mu.Lock()
TempMessageList := messageMgrData.MessageList
messageMgrData.MessageList = make(map[int64]*MessageList)
defer messageMgrData.mu.Unlock()
log.Debug("[Middleware] Cluster sync send temp message len: %d", len(TempMessageList))
for _, Message := range TempMessageList {
for _, msgItem := range Message.Messages {
SendMsgToCenterAsync(msgItem)
}
}
return nil, nil
}
func PlayerLoginHandler(data *msg.Msg) (interface{}, error) {
// 关闭 Worker Pool
node := data.Extra.(int)
messageMgrData := getMessageData()
messageMgrData.PlayerList[int64(data.From)] = node
log.Debug("[Middleware] Player login success player id: %v, node: %v", data.From, data.Extra.(int))
// 对玩家消息列表加锁
messages := getMessge(int64(data.From))
messages.mu.Lock()
defer messages.mu.Unlock()
// 发送离线消息
len := len(messages.Messages)
for _, message := range messages.Messages {
SendMsgToNodeAsync(message, node)
}
log.Debug("[Middleware] Player sync logout message player id: %v, len: %d", data.From, len)
ReplyPlayerMsgASync(data, nil)
return nil, nil
}
func PlayerLogoutHandler(data *msg.Msg) (interface{}, error) {
messageMgrData := getMessageData()
delete(messageMgrData.PlayerList, int64(data.From))
log.Debug("[Middleware] Player logout success player id: %v", data.From)
return nil, nil
}
func ComsumerMsgHandler(data *msg.Msg) (interface{}, error) {
messages := getMessge(int64(data.From))
messages.mu.Lock()
defer messages.mu.Unlock()
for i, msgItem := range messages.Messages {
if msgItem.UniKey == data.UniKey {
// 删除消息
messages.Messages = append(messages.Messages[:i], messages.Messages[i+1:]...)
log.Debug("[Middleware] Comsume message success type: %d, player id: %v", msgItem.Type, msgItem.From)
break
}
}
return nil, nil
}
func CenterPlayerMsgHandler(data *msg.Msg) (interface{}, error) {
PlayerId := int64(data.To)
messageMgrData := getMessageData()
// 遍历消息列表,发送消息给在线玩家
messages := getMessge(PlayerId)
messages.mu.Lock()
defer messages.mu.Unlock()
messages.Messages = append(messages.Messages, data)
if node, ok := messageMgrData.PlayerList[int64(PlayerId)]; ok {
SendMsgToNodeAsync(data, node)
}
return nil, nil
}
func PlayerMsgHandler(data *msg.Msg) (interface{}, error) {
p := G_GameLogicPtr.GetPlayer(int64(data.To))
// 不在线 不处理
if p == nil || p.stop {
return nil, nil
}
p.Send(data.Clone())
// 处理完后发送消费消息
if data.HandleType == msg.HANDLE_MOD_PLAYER_MSG {
data.HandleType = msg.HANDLE_MOD_COMSUME_MSG
SendMsgToCenterAsync(data)
}
return nil, nil
}
func PlayerReplyMsgHandler(data *msg.Msg) (interface{}, error) {
// 先处理同步回调
if data.UniKey != "" {
if chanel, ok := mergeCluster.CallbackChan[data.UniKey]; ok {
log.Debug("reply message ")
chanel <- data
}
}
return nil, nil
}
// 添加中间件
func (m *MessageMgr) Use(middleware MessageMiddleware) {
m.middlewares = append(m.middlewares, middleware)
}
// 应用所有中间件到处理函数
func (m *MessageMgr) applyMiddlewares(handler MessageHandlerFunc) MessageHandlerFunc {
// 从后往前应用中间件
for i := len(m.middlewares) - 1; i >= 0; i-- {
handler = m.middlewares[i](handler)
}
return handler
}
type MessageHandlerFunc func(message *msg.Msg) (interface{}, error)
func (m *MessageMgr) RegisterMessageHandler(hType int, handler MessageHandlerFunc) {
m.RegisterHandler(hType, handler)
}
func (m *MessageMgr) Handle(msg *msg.Msg) (interface{}, error) {
if fun, ok := m.handler[msg.Type]; ok {
return fun(msg)
}
log.Error("server mod key:%s handle not exist handle type:%d", m.key, msg.Type)
return nil, fmt.Errorf("server mod handler err")
}
// 异步处理消息 (多线程版本)
func (m *MessageMgr) MessageHandleAsync(message *msg.Msg) error {
if message.End != 0 && message.End < GoUtil.Now() {
log.Debug("message had expired type:%d,to:%d", message.Type, message.To)
return nil
}
if fun, ok := m.handler[message.HandleType]; ok {
// 应用中间件
handlerWithMiddleware := m.applyMiddlewares(fun)
id++
// 创建任务
task := &MessageTask{
id: id,
Msg: message,
Handler: handlerWithMiddleware,
Result: make(chan *TaskResult, 1),
}
// 提交到 Worker Pool
if err := m.workerPool.Submit(task); err != nil {
log.Error("Failed to submit message task: %v", err)
return err
}
// 可以选择等待结果或直接返回
go func() {
result := <-task.Result
if result.Error != nil {
log.Error("Message handle error: %v", result.Error)
}
}()
return nil
}
log.Error("server mod key:%s handle not exist handle type:%d", m.key, message.Type)
return fmt.Errorf("server mod handler err")
}
// 兼容旧版本的函数
func MessageHandle(m *msg.Msg) error {
log.Debug("RecvMessage m %v", m)
// 这里可以调用 MessageMgr 的处理方法
G_GameLogicPtr.MessageMgr.MessageHandleAsync(m)
return nil
}
// ==================== Worker Pool 实现 ====================
// 创建 Worker Pool
func NewWorkerPool(workers, maxQueue int) *WorkerPool {
ctx, cancel := context.WithCancel(context.Background())
if workers <= 0 {
workers = 1
}
pool := &WorkerPool{
workers: 0,
minWorkers: workers,
maxWorkers: workers * 40,
taskQueue: make(chan *MessageTask, maxQueue),
ctx: ctx,
cancel: cancel,
maxQueue: maxQueue,
}
pool.start()
// 启动监控协程,负责动态扩缩容
pool.monitorTick = time.NewTicker(3000 * time.Millisecond)
go pool.monitor()
return pool
}
// 启动 Worker Pool
func (p *WorkerPool) start() {
// 启动最小数量的 worker
for i := 0; i < p.minWorkers; i++ {
p.spawnWorker()
}
}
// spawnWorker 启动一个 worker使用独立的 cancelable context
func (p *WorkerPool) spawnWorker() {
p.mu.Lock()
defer p.mu.Unlock()
childCtx, childCancel := context.WithCancel(p.ctx)
p.workerCancels = append(p.workerCancels, childCancel)
id := len(p.workerCancels)
p.wg.Add(1)
p.workers++
go p.worker(childCtx, id)
}
// Worker 工作函数,监听其子上下文以便单独停止
func (p *WorkerPool) worker(ctx context.Context, id int) {
defer p.wg.Done()
log.Debug("Worker %d started", id)
for {
select {
case <-ctx.Done():
log.Debug("Worker %d stopped", id)
return
case <-p.ctx.Done():
log.Debug("Worker %d pool closed", id)
return
case task, ok := <-p.taskQueue:
if !ok {
log.Debug("Worker %d: task queue closed", id)
return
}
// 执行任务
result, err := task.Handler(task.Msg)
// 发送结果
task.Result <- &TaskResult{
Data: result,
Error: err,
}
close(task.Result)
}
}
}
// 提交任务
func (p *WorkerPool) Submit(task *MessageTask) error {
// 当队列已满时,等待并重试入队,直到成功或 pool 关闭
for {
select {
case <-p.ctx.Done():
return fmt.Errorf("worker pool is closed")
case p.taskQueue <- task:
// 如果队列接近满时,尝试扩容少量 worker
queued := len(p.taskQueue)
capQ := cap(p.taskQueue)
if capQ > 0 && queued > capQ*3/4 {
go func() {
p.mu.Lock()
deficit := p.maxWorkers - p.workers
p.mu.Unlock()
if deficit > 0 {
// 最多扩容 2 个以避免剧烈波动
add := 2
if deficit < add {
add = deficit
}
p.ScaleUp(add)
}
}()
}
return nil
default:
// 队列已满,短暂等待后重试
select {
case <-p.ctx.Done():
return fmt.Errorf("worker pool is closed")
case <-time.After(50 * time.Millisecond):
// 重试
}
}
}
}
// 关闭 Worker Pool
func (p *WorkerPool) Shutdown() {
log.Debug("Shutting down worker pool...")
// 停止监控
if p.monitorTick != nil {
p.monitorTick.Stop()
}
// 取消根 context会让所有子 worker 退出
p.cancel()
// 关闭任务通道,释放阻塞的接收者
close(p.taskQueue)
// 等待所有 worker 退出
p.wg.Wait()
log.Debug("Worker pool shut down complete")
}
// ScaleUp 按数量增加 worker
func (p *WorkerPool) ScaleUp(n int) {
if n <= 0 {
return
}
p.mu.Lock()
can := p.maxWorkers - p.workers
if can <= 0 {
p.mu.Unlock()
return
}
if n > can {
n = can
}
p.mu.Unlock()
for i := 0; i < n; i++ {
p.spawnWorker()
}
}
// ScaleDown 按数量减少 worker
func (p *WorkerPool) ScaleDown(n int) {
if n <= 0 {
return
}
p.mu.Lock()
for i := 0; i < n && len(p.workerCancels) > 0 && p.workers > p.minWorkers; i++ {
last := len(p.workerCancels) - 1
cancel := p.workerCancels[last]
// 从 slice 中移除
p.workerCancels = p.workerCancels[:last]
p.workers--
// 调用 cancel 让对应 worker 退出
cancel()
}
p.mu.Unlock()
}
// monitor 周期性检查队列长度并做扩缩容
func (p *WorkerPool) monitor() {
for {
select {
case <-p.ctx.Done():
return
case <-p.monitorTick.C:
queued := len(p.taskQueue)
capQ := cap(p.taskQueue)
if capQ == 0 {
continue
}
// 扩容条件
if queued > capQ*3/4 {
p.mu.Lock()
deficit := p.maxWorkers - p.workers
p.mu.Unlock()
if deficit > 0 {
add := 1
if deficit >= 2 {
add = 2
}
p.ScaleUp(add)
}
}
// 缩容条件
if queued < capQ/4 {
p.mu.Lock()
extra := p.workers - p.minWorkers
p.mu.Unlock()
if extra > 0 {
// 每次缩一个,避免抖动
p.ScaleDown(1)
}
}
}
}
}
// ==================== 中间件实现 ====================
// 日志中间件
func LoggingMiddleware() MessageMiddleware {
return func(next MessageHandlerFunc) MessageHandlerFunc {
return func(message *msg.Msg) (interface{}, error) {
start := time.Now()
log.Debug("[Middleware] Processing message : %v, time: %v", message, start)
result, err := next(message)
duration := time.Since(start)
if err != nil {
log.Error("[Middleware] Message : %v failed, duration: %v, error: %v", message, duration, err)
} else {
log.Debug("[Middleware] Message : %v success, duration: %v", message, duration)
}
return result, err
}
}
}
// 恢复 Panic 中间件
func RecoveryMiddleware() MessageMiddleware {
return func(next MessageHandlerFunc) MessageHandlerFunc {
return func(message *msg.Msg) (result interface{}, err error) {
defer func() {
if r := recover(); r != nil {
log.Error("[Middleware] Panic recovered: %v\nStack: %s", r, debug.Stack())
err = fmt.Errorf("panic recovered: %v", r)
}
}()
return next(message)
}
}
}
// 超时中间件
func TimeoutMiddleware(timeout time.Duration) MessageMiddleware {
return func(next MessageHandlerFunc) MessageHandlerFunc {
return func(message *msg.Msg) (interface{}, error) {
resultChan := make(chan *TaskResult, 1)
go func() {
result, err := next(message)
resultChan <- &TaskResult{Data: result, Error: err}
}()
select {
case result := <-resultChan:
return result.Data, result.Error
case <-time.After(timeout):
log.Error("[Middleware] Message : %v timeout after %v", message, timeout)
GoUtil.SendFeishuFatal(0, "message_mgr", fmt.Sprintf("Message Handler Timeout\nMessage: %v\nTimeout: %v", message, timeout))
return nil, fmt.Errorf("message handler timeout")
}
}
}
}
// 重试中间件
func RetryMiddleware(maxRetries int) MessageMiddleware {
return func(next MessageHandlerFunc) MessageHandlerFunc {
return func(message *msg.Msg) (interface{}, error) {
var result interface{}
var err error
for i := 0; i <= maxRetries; i++ {
result, err = next(message)
if err == nil {
return result, nil
}
if i < maxRetries {
log.Debug("[Middleware] Retry %d/%d for message : %v, error: %v", i+1, maxRetries, message, err)
time.Sleep(time.Millisecond * 100 * time.Duration(i+1))
}
}
return result, fmt.Errorf("failed after %d retries: %w", maxRetries, err)
}
}
}
// 验证中间件
func ValidationMiddleware() MessageMiddleware {
return func(next MessageHandlerFunc) MessageHandlerFunc {
return func(message *msg.Msg) (interface{}, error) {
// 添加消息验证逻辑
if message == nil {
return nil, fmt.Errorf("message is nil")
}
if message.Type <= 0 {
return nil, fmt.Errorf("invalid message type: %d", message.Type)
}
return next(message)
}
}
}
// ----------------------------------- 发送消息相关函数 ---------------------------
func SendMsgToCenterAsync(m *msg.Msg) {
go sendMessageAsync(m, conf.Server.CenterNode)
}
func SendMsgToCenterSync(m *msg.Msg) (*msg.Msg, error) {
return sendMessageSync(m, conf.Server.CenterNode)
}
func SendMsgToNodeAsync(m *msg.Msg, node int) {
go sendMessageAsync(m, node)
}
func SendMsgToNodeSync(m *msg.Msg, node int) (*msg.Msg, error) {
return sendMessageSync(m, node)
}
func SendPlayerMsgAsync(m *msg.Msg) error {
if m.SendT == 0 {
m.SendT = GoUtil.Now()
}
clone := m.Clone()
clone.HandleType = msg.HANDLE_MOD_PLAYER_MSG
SendMsgToCenterAsync(clone)
return nil
}
func SendPlayerMsgSync(m *msg.Msg) (interface{}, error) {
clone := m.Clone()
clone.HandleType = msg.HANDLE_MOD_PLAYER_MSG
return SendMsgToCenterSync(clone)
}
func FriendMgrSend(m1 *msg.Msg) error {
SendPlayerMsgAsync(m1)
return nil
}
// 异步发送消息到指定节点 节点不在线则保存消息
func sendMessageAsync(m *msg.Msg, node int) error {
err := mergeCluster.SendServerMsg(m, node)
if err != nil && GoUtil.InArray(m.HandleType, save_msg_type) {
saveMessage(m)
return err
}
deleteMessage(m)
return nil
}
// 同步消息到指定节点 节点不在线则保存消息
func sendMessageSync(m *msg.Msg, node int) (*msg.Msg, error) {
msg, err := mergeCluster.CallServerMsg(m, node)
if err != nil && conf.Server.ServerType == "center" && GoUtil.InArray(m.HandleType, save_msg_type) {
saveMessage(m)
return nil, err
}
deleteMessage(m)
return msg, nil
}
// 保存消息到本地
func saveMessage(m *msg.Msg) error {
data := getMessageData()
data.mu.Lock()
defer data.mu.Unlock()
messages := getMessge(int64(m.To))
messages.mu.Lock()
defer messages.mu.Unlock()
messages.Messages = append(messages.Messages, m)
return nil
}
func GetUserData(PlayerId int64, Key string) (*msg.Msg, error) {
return SendMsgToCenterSync(&msg.Msg{
From: int(PlayerId),
HandleType: msg.HANDLE_MOD_USER_VAR_GET,
Extra: msg.VarData{Key: Key},
})
}
func getMessge(PlayerId int64) *MessageList {
messageMgrData := getMessageData()
messageMgrData.mu.Lock()
defer messageMgrData.mu.Unlock()
if _, ok := messageMgrData.MessageList[int64(PlayerId)]; !ok {
messageMgrData.MessageList[int64(PlayerId)] = &MessageList{
Messages: []*msg.Msg{},
}
}
return messageMgrData.MessageList[int64(PlayerId)]
}
func deleteMessage(m *msg.Msg) error {
messages := getMessge(int64(m.To))
messages.mu.Lock()
defer messages.mu.Unlock()
for i, msgItem := range messages.Messages {
if msgItem.UniKey == m.UniKey {
// 删除消息
messages.Messages = append(messages.Messages[:i], messages.Messages[i+1:]...)
log.Debug("[Middleware] send message success; message: %v, player id: %v", msgItem, msgItem.From)
break
}
}
return nil
}

View File

@ -3,9 +3,9 @@ package activity
import (
"encoding/gob"
"fmt"
"server/GoUtil"
activityCfg "server/conf/activity"
"server/game/mod/item"
GoUtil "server/game_util"
"server/gamedata"
)

View File

@ -2,9 +2,9 @@ package activity
import (
"fmt"
"server/GoUtil"
activityCfg "server/conf/activity"
"server/game/mod/item"
GoUtil "server/game_util"
)
func (a *Activity) Fire(Id int) ([]*item.Item, error) {

View File

@ -2,8 +2,8 @@ package avatar
import (
"fmt"
"server/GoUtil"
avatarCfg "server/conf/avatar"
GoUtil "server/game_util"
"server/msg"
)

View File

@ -2,10 +2,10 @@ package base
import (
"fmt"
"server/GoUtil"
"server/conf"
baseCfg "server/conf/base"
"server/game/mod/item"
GoUtil "server/game_util"
"server/msg"
)

View File

@ -2,9 +2,9 @@ package card
import (
"fmt"
"server/GoUtil"
cardCfg "server/conf/card"
"server/game/mod/item"
GoUtil "server/game_util"
"server/msg"
"server/pkg/github.com/name5566/leaf/log"
)

View File

@ -1,8 +1,8 @@
package card
import (
"server/GoUtil"
cardCfg "server/conf/card"
GoUtil "server/game_util"
)
func randCard(Round, Star, IsGold int, Except []int) int {

View File

@ -2,9 +2,9 @@ package catnip
import (
"fmt"
"server/GoUtil"
catnipCfg "server/conf/catnip"
"server/game/mod/item"
GoUtil "server/game_util"
)
type CatnipMod struct {
@ -28,7 +28,7 @@ type CatnipGame struct {
PartnerAdd int // 伙伴贡献
Reward []int // 已领取阶段奖励
Status int // 0: Not Started, 1: In Progress, 2: Completed
SendEmoji int // 发送的表情ID
EmojiId int // 表情ID
}
@ -52,15 +52,16 @@ func (c *CatnipMod) InitData() {
}
}
func (c *CatnipMod) Login(Id int) int {
func (c *CatnipMod) Login(Id int) (int, []*item.Item) {
OldId := c.Id
if Id == 0 {
c.Id = 0
return OldId
return OldId, nil
}
if c.Id == Id {
return 0
return 0, nil
}
Items := c.GetUnGetReward()
c.Id = Id
c.IsGetGrandReward = false // Reset grand reward status on login
c.Game = make(map[int]*CatnipGame)
@ -76,7 +77,7 @@ func (c *CatnipMod) Login(Id int) int {
Status: GAME_STATUS_IDLE, // Not started
}
}
return c.Id
return c.Id, Items
}
func (c *CatnipMod) ZeroUpdate(Id int) {
@ -189,7 +190,11 @@ func (c *CatnipMod) Reward(Id int) ([]*item.Item, *CatnipGame, error) {
return nil, nil, fmt.Errorf("game with Progress %d does not exist", Id)
}
Items, Ids := catnipCfg.GetProgressReward(c.Id, GameInfo.Reward, GameInfo.Progress)
ProgressNum := catnipCfg.GetProgressNum(c.Id)
GameInfo.Reward = append(GameInfo.Reward, Ids...)
if len(GameInfo.Reward) == ProgressNum {
GameInfo.Status = GAME_STATUS_COMPLETED
}
if Items == nil {
return nil, nil, fmt.Errorf("no reward found for progress %d in game ID %d", GameInfo.Progress, Id)
}
@ -252,3 +257,20 @@ func (c *CatnipMod) GetMultiple() int {
func (c *CatnipMod) GetGameInfo(Id int) *CatnipGame {
return c.Game[Id]
}
func (c *CatnipMod) SetSendEmoji(Id, EmojiId int) {
c.Game[Id].SendEmoji = EmojiId
}
func (c *CatnipMod) GetUnGetReward() []*item.Item {
var rewards []*item.Item
for _, v := range c.Game {
Items, _, _ := c.Reward(v.Id)
rewards = append(rewards, Items...)
}
BigReward, err := c.GrandReward()
if err == nil {
rewards = append(rewards, BigReward...)
}
return rewards
}

View File

@ -2,10 +2,10 @@ package champship
import (
"fmt"
"server/GoUtil"
champshipCfg "server/conf/champship"
mergeDataCfg "server/conf/mergeData"
mergeDataCfg "server/conf/merge_data"
"server/game/mod/item"
GoUtil "server/game_util"
"server/msg"
)

View File

@ -3,12 +3,12 @@ package charge
import (
"fmt"
"math"
"server/GoUtil"
chargeCfg "server/conf/charge"
mergeDataCfg "server/conf/mergeData"
mergeDataCfg "server/conf/merge_data"
playroomCfg "server/conf/playroom"
"server/game/mod/item"
"server/game/mod/order"
GoUtil "server/game_util"
"server/msg"
"server/pkg/github.com/name5566/leaf/log"
)

View File

@ -3,11 +3,11 @@ package chess
import (
"errors"
"fmt"
"server/GoUtil"
mergeDataCfg "server/conf/mergeData"
startMergeCfg "server/conf/startMerge"
mergeDataCfg "server/conf/merge_data"
startMergeCfg "server/conf/start_merge"
userCfg "server/conf/user"
"server/game/mod/item"
GoUtil "server/game_util"
"server/msg"
"sort"
"strings"

View File

@ -2,9 +2,9 @@ package collect
import (
"fmt"
"server/GoUtil"
collectCfg "server/conf/collect"
"server/game/mod/item"
GoUtil "server/game_util"
"server/msg"
)

View File

@ -1,8 +1,8 @@
package compensation
import (
"server/GoUtil"
"server/game/mod/item"
GoUtil "server/game_util"
)
type Compensation struct {

View File

@ -2,9 +2,9 @@ package dailyTask
import (
"math"
"server/GoUtil"
dailyTaskCfg "server/conf/dailyTask"
dailyTaskCfg "server/conf/daily_task"
"server/game/mod/item"
GoUtil "server/game_util"
"sort"
)

View File

@ -2,10 +2,10 @@ package dailyTask
import (
"fmt"
"server/GoUtil"
dailyTaskCfg "server/conf/dailyTask"
dailyTaskCfg "server/conf/daily_task"
"server/game/mod/item"
"server/game/mod/quest"
GoUtil "server/game_util"
"server/msg"
"server/pkg/github.com/name5566/leaf/log"
"sort"

View File

@ -3,10 +3,10 @@ package decorate
import (
"fmt"
"math"
"server/GoUtil"
decorateCfg "server/conf/decorate"
limitedTimeEventCfg "server/conf/limitedTimeEvent"
limitedTimeEventCfg "server/conf/limited_time_event"
"server/game/mod/item"
GoUtil "server/game_util"
"server/msg"
"sort"
)

View File

@ -2,8 +2,8 @@ package emoji
import (
"fmt"
"server/GoUtil"
emojiCfg "server/conf/emoji"
GoUtil "server/game_util"
"server/msg"
)

View File

@ -1,9 +1,9 @@
package endless
import (
Util "server/GoUtil"
endlessCfg "server/conf/endless"
"server/game/mod/item"
Util "server/game_util"
)
// 初始化奖励

View File

@ -2,8 +2,8 @@ package face
import (
"fmt"
"server/GoUtil"
faceCfg "server/conf/face"
GoUtil "server/game_util"
"server/msg"
)

View File

@ -2,10 +2,11 @@ package friend
import (
"fmt"
"server/GoUtil"
cardCfg "server/conf/card"
friendCfg "server/conf/friend"
"server/game/mod/card"
"server/game/mod/item"
GoUtil "server/game_util"
"server/msg"
)
@ -214,8 +215,17 @@ func (f *FriendMod) GetNpc() []int {
return f.Npc
}
func (f *FriendMod) SetNpc(id int) {
func (f *FriendMod) SetNpc(id int) error {
if !friendCfg.IsNpcFriend(id) {
return fmt.Errorf("not npc friend")
}
for _, v := range f.Npc {
if v == id {
return fmt.Errorf("npc already exist")
}
}
f.Npc = append(f.Npc, id)
return nil
}
func (f *FriendMod) GetSyncId() int64 {
@ -502,9 +512,9 @@ func (f *FriendMod) GetActLogLast() *ActLogInfo {
return f.ActivityLog[len(f.ActivityLog)-1]
}
func (f *FriendMod) AddReplyInfo(Uid int, Type int, Param string, EndTime int64, Items []*item.Item) {
func (f *FriendMod) AddReplyInfo(Uid int, Type int, Param string, EndTime int64, Items []*item.Item) *ReplyInfo {
f.AutoId++
f.ReplyList = append(f.ReplyList, &ReplyInfo{
ReplyInfo := &ReplyInfo{
Id: f.AutoId,
Uid: Uid,
Type: Type,
@ -513,7 +523,9 @@ func (f *FriendMod) AddReplyInfo(Uid int, Type int, Param string, EndTime int64,
AddTime: GoUtil.Now(),
EndTime: EndTime,
Items: Items,
})
}
f.ReplyList = append(f.ReplyList, ReplyInfo)
return ReplyInfo
}
func (f *FriendMod) ReplyFriend(LogId int) *ReplyInfo {

View File

@ -2,9 +2,9 @@ package friendTreasure
import (
"fmt"
"server/GoUtil"
friendTreasureCfg "server/conf/friendTreasure"
friendTreasureCfg "server/conf/friend_treasure"
"server/game/mod/item"
GoUtil "server/game_util"
"server/msg"
"server/pkg/github.com/name5566/leaf/log"
)

View File

@ -2,10 +2,10 @@ package guesscolor
import (
"fmt"
"server/GoUtil"
guesscolorCfg "server/conf/guessColor"
guesscolorCfg "server/conf/guess_color"
randnameCfg "server/conf/randname"
"server/game/mod/item"
GoUtil "server/game_util"
)
type GuessColorMod struct {

View File

@ -0,0 +1,132 @@
package guesscolor
import (
"fmt"
guesscolorCfg "server/conf/guess_color"
randnameCfg "server/conf/randname"
"server/game/mod/item"
GoUtil "server/game_util"
)
type GuessColorMod struct {
Id int
Pass int
Opponent simplePlayer
MapList []map[int32]int32
OMap map[int32]int32
WinTime int
First bool
Guess int
}
type simplePlayer struct {
Name string
Face int
Avatar int
Progress int
}
const (
GAME_STATUS_SUCCESS = 1
GAME_STATUS_FAIL = 2
)
func (g *GuessColorMod) InitData() {
if g.MapList == nil {
g.MapList = make([]map[int32]int32, 0)
}
if g.OMap == nil {
g.OMap = make(map[int32]int32)
}
if g.Pass == 0 || g.WinTime == 0 {
g.Pass = 1
g.WinTime = guesscolorCfg.GetWinTime(g.Pass)
}
if g.Opponent.Name == "" {
g.Opponent = simplePlayer{
Name: randnameCfg.GetRandName(),
Face: GoUtil.RandNum(1, 10),
Avatar: GoUtil.RandNum(1, 10),
Progress: 0,
}
}
}
func (g *GuessColorMod) Login(Id int) int {
OldId := g.Id
if Id == 0 {
g.Id = 0
return g.Id
}
if g.Id == Id {
return 0
}
g.Id = Id
g.Pass = 1
g.Opponent = simplePlayer{
Name: randnameCfg.GetRandName(),
Face: GoUtil.RandNum(1, 10),
Avatar: GoUtil.RandNum(1, 10),
Progress: 0,
}
g.Guess = 0
g.MapList = make([]map[int32]int32, 0)
g.OMap = make(map[int32]int32)
g.WinTime = guesscolorCfg.GetWinTime(g.Pass)
return OldId
}
func (g *GuessColorMod) ZeroUpdate(Id int) {
g.Login(Id)
}
func (g *GuessColorMod) FirstIn() []*item.Item {
if g.First {
return nil
}
g.First = true
return guesscolorCfg.GetFirstItem(g.Id)
}
func (g *GuessColorMod) Take(Map map[int32]int32, OMap map[int32]int32) {
if len(Map) > 0 {
g.MapList = append(g.MapList, Map)
g.Guess++
}
g.OMap = OMap
}
func (g *GuessColorMod) GetLoseItem() []*item.Item {
Items := guesscolorCfg.GetLoseItem(g.Id)
Num := guesscolorCfg.GetPassNum(g.Pass)
if len(g.MapList) > 0 {
LastMap := g.MapList[len(g.MapList)-1]
for _, v := range LastMap {
if v > 10 {
Num--
}
}
}
return item.MutilItem(Items, Num)
}
func (g *GuessColorMod) GetReward() ([]*item.Item, error) {
if g.Pass == 0 {
return nil, fmt.Errorf("not pass")
}
// Num := guesscolorCfg.GetPassNum(g.Pass)
if g.Guess < g.WinTime {
return nil, fmt.Errorf("guess process not finish")
}
Type := GAME_STATUS_FAIL
if g.Guess == guesscolorCfg.GetPassNum(g.Pass) {
Type = GAME_STATUS_SUCCESS
}
Item := guesscolorCfg.GetRewardItem(g.Pass, Type)
g.Pass++
g.Guess = 0
g.WinTime = guesscolorCfg.GetWinTime(g.Pass)
g.MapList = make([]map[int32]int32, 0)
g.OMap = make(map[int32]int32)
return Item, nil
}

View File

@ -2,9 +2,9 @@ package guide
import (
"fmt"
"server/GoUtil"
guidecfg "server/conf/guide"
"server/game/mod/item"
GoUtil "server/game_util"
"server/msg"
)

View File

@ -2,10 +2,10 @@ package guideTask
import (
"fmt"
"server/GoUtil"
GuideTaskCfg "server/conf/guideTask"
GuideTaskCfg "server/conf/guide_task"
"server/game/mod/item"
"server/game/mod/quest"
GoUtil "server/game_util"
"server/msg"
)

View File

@ -4,7 +4,7 @@ import (
"errors"
"fmt"
handbookCfg "server/conf/handbook"
startMergeCfg "server/conf/startMerge"
startMergeCfg "server/conf/start_merge"
"server/game/mod/item"
"server/msg"
)

View File

@ -2,9 +2,9 @@ package invite
import (
"fmt"
"server/GoUtil"
inviteCfg "server/conf/invite"
"server/game/mod/item"
GoUtil "server/game_util"
"server/msg"
)

View File

@ -3,10 +3,10 @@ package limitedTimeEvent
import (
"fmt"
"math"
"server/GoUtil"
limitedTimeEventCfg "server/conf/limitedTimeEvent"
mergeDataCfg "server/conf/mergeData"
limitedTimeEventCfg "server/conf/limited_time_event"
mergeDataCfg "server/conf/merge_data"
"server/game/mod/item"
GoUtil "server/game_util"
"server/msg"
)

View File

@ -2,8 +2,8 @@ package mail
import (
"fmt"
"server/GoUtil"
"server/game/mod/item"
GoUtil "server/game_util"
"server/msg"
)

View File

@ -13,11 +13,43 @@ type Msg struct {
Id int64
UniKey string // 回调监听唯一键值
H int //处理类型
HandleType int //处理类型
}
type VarData struct {
Key string
Value interface{}
SetType int // 操作类型 0 设置 1 增加 2 减少 3 覆盖
}
const (
VAR_OP_ADD = 1
VAR_OP_SUB = 2
VAR_OP_SET = 3
)
var MSG_ZERO_UPDATE = &Msg{Type: SERVER_ZERO_UPDATE}
var MSG_NOON_UPDATE = &Msg{Type: SERVER_NOON_UPDATE}
const (
HANDLE_MOD_PLAYER_MSG = 20001 // 玩家消息
HANDLE_MOD_CLUSTER_MSG = 20002 // 集群消息
HANDLE_MOD_PLAYER_LOGIN = 20003 // 玩家登录消息
HANDLE_MOD_COMSUME_MSG = 20004 // 消费消息
HANDLE_MOD_CLUSTER_SYNC = 20005 // 集群同步消息
HANDLE_MDO_PLAYER_LOGOUT = 20006 // 玩家登出消息
HANDLE_MOD_VAR_GET = 20007 // 获取变量
HANDLE_MOD_VAR_SET = 20008 // 设置变量
HANDLE_MOD_CATNIP_PARTNER = 20009 // 猫薄荷伙伴
HANDLE_MOD_USER_VAR_GET = 20010 // 获取玩家变量
HANDLE_MOD_USER_VAR_SET = 20011 // 设置玩家变量
HANDLE_MOD_REPLY_PLAYER_MSG = 20012 // 回复玩家消息
HANDLE_MDO_CHAMPSHIP_INRANK = 20013 // 锦标赛入榜
HANDLE_MOD_CHAMPSHIP_RANK_INFO = 20014 // 锦标赛排名信息
HANDLE_MOD_CHAMPSHIP_RANK_LIST = 20015 // 锦标赛排行榜
HANDLE_MOD_CHAMPSHIP_PRE_RANK = 20016 // 锦标赛上期排名
)
const (
//好友操作
HANDLE_TYPE_APPLY = iota //申请好友
@ -112,6 +144,9 @@ const (
HANDLE_TYPE_CHAMPSHIP_RANK_INFO // 锦标赛排名信息
HANDLE_TYPE_SET_CATNIP_PARTNER // 设置猫薄荷伙伴
HANDLE_TYPE_CATNIP_SEND_EMOJI // 发送猫薄荷表情
HANDLE_TYPE_CHAMPSHIP_MY_RANK // 锦标赛我的排名
HANDLE_TYPE_LOGIN // 玩家登录处理
)
const (
@ -135,6 +170,22 @@ func (m *Msg) Clone() *Msg {
Extra: m.Extra,
Id: m.Id,
H: m.H,
UniKey: m.UniKey,
}
}
func (m *Msg) Reply(data interface{}) *Msg {
return &Msg{
Type: m.Type,
To: m.From,
Item: m.Item,
SendT: m.SendT,
End: m.End,
Extra: data,
Id: m.Id,
H: m.H,
UniKey: m.UniKey,
HandleType: HANDLE_MOD_REPLY_PLAYER_MSG,
}
}

View File

@ -2,11 +2,11 @@ package order
import (
"fmt"
"server/GoUtil"
limitedTimeEventCfg "server/conf/limitedTimeEvent"
mergeDataCfg "server/conf/mergeData"
limitedTimeEventCfg "server/conf/limited_time_event"
mergeDataCfg "server/conf/merge_data"
orderCfg "server/conf/order"
"server/game/mod/item"
GoUtil "server/game_util"
"server/msg"
"strings"
"time"

View File

@ -3,10 +3,10 @@ package order
import (
"log"
"math"
"server/GoUtil"
mergeDataCfg "server/conf/mergeData"
mergeDataCfg "server/conf/merge_data"
orderCfg "server/conf/order"
userCfg "server/conf/user"
GoUtil "server/game_util"
"sort"
)

View File

@ -1,9 +1,9 @@
package pass
import (
"server/GoUtil"
passCfg "server/conf/pass"
"server/game/mod/item"
GoUtil "server/game_util"
)
type PassMod struct {

Some files were not shown because too many files have changed in this diff Show More