115 lines
3.0 KiB
Go

package handlers
import (
"context"
"database/sql"
"encoding/json"
"github.com/heroiclabs/nakama-common/runtime"
)
func RpcListMatches(ctx context.Context, logger runtime.Logger, db *sql.DB, nk runtime.NakamaModule, payload string) (string, error) {
limit := 100
authoritative := true
label := "" // 我们想列出所有 animal_minesweeper
minSize := 0
maxSize := 8
query := "*" // 默认查询
matches, err := nk.MatchList(ctx, limit, authoritative, label, &minSize, &maxSize, query)
if err != nil {
logger.Error("Failed to list matches: %v", err)
return "", err
}
result := make([]map[string]interface{}, 0)
for _, m := range matches {
var labelObj MatchLabel
if err := json.Unmarshal([]byte(m.GetLabel().Value), &labelObj); err != nil {
// 如果不是 minesweeper 房间,跳过
continue
}
result = append(result, map[string]interface{}{
"match_id": m.GetMatchId(),
"player_count": labelObj.PlayerCount,
"max_players": labelObj.MaxPlayers,
"started": labelObj.Started,
"open": labelObj.Open,
})
}
response, err := json.Marshal(result)
if err != nil {
return "", err
}
return string(response), nil
}
func RpcFindMyMatch(ctx context.Context, logger runtime.Logger, db *sql.DB, nk runtime.NakamaModule, payload string) (string, error) {
userID, ok := ctx.Value(runtime.RUNTIME_CTX_USER_ID).(string)
if !ok {
return "", runtime.NewError("user not authenticated", 16)
}
readObjects, err := nk.StorageRead(ctx, []*runtime.StorageRead{
{
Collection: "game_data",
Key: "active_match",
UserID: userID,
},
})
if err != nil {
logger.Error("Failed to read storage: %v", err)
return "", err
}
if len(readObjects) == 0 {
return "{}", nil
}
return readObjects[0].Value, nil
}
// RpcGetOnlineCount 返回当前在线玩家数量
func RpcGetOnlineCount(ctx context.Context, logger runtime.Logger, db *sql.DB, nk runtime.NakamaModule, payload string) (string, error) {
userID, ok := ctx.Value(runtime.RUNTIME_CTX_USER_ID).(string)
if !ok || userID == "" {
return "", runtime.NewError("user not authenticated", 16)
}
// 获取所有活跃比赛中的玩家数
matches, err := nk.MatchList(ctx, 100, true, "", nil, nil, "*")
if err != nil {
logger.Warn("Failed to list matches: %v", err)
}
inGameCount := 0
for _, m := range matches {
inGameCount += int(m.GetSize())
}
// 使用 Nakama 的 StreamCount 获取当前所有 WebSocket 连接数
// Mode 0 = Notifications stream, 所有已认证的 WebSocket 连接都会加入这个流
onlineCount, err := nk.StreamCount(0, "", "", "")
if err != nil {
logger.Warn("Failed to get stream count: %v", err)
onlineCount = inGameCount // 降级为比赛中玩家数
}
if onlineCount < 1 {
onlineCount = 1 // 至少自己在线
}
result := map[string]interface{}{
"online_count": onlineCount,
"match_count": len(matches),
"in_game_count": inGameCount,
}
response, _ := json.Marshal(result)
return string(response), nil
}