115 lines
3.0 KiB
Go
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
|
|
}
|