Golang游戏社交基础设施Nakama使用指南(v2.15版)
Golang游戏社交基础设施Nakama使用指南(v2.15版)
分布式服务器,适用于社交和实时游戏及应用。- heroiclabs/nakama
Nakama 是一个开源的分布式服务器,专为社交和实时游戏及应用而设计。使用 Go 语言编写。
功能特性
- 用户 - 通过社交网络、电子邮件或设备 ID 注册/登录新用户。
- 存储 - 在集合中存储用户记录、设置和其他对象。
- 社交 - 用户可以连接好友并加入群组。内置社交图谱,用于查看用户之间的连接关系。
- 聊天 - 用户之间可以进行一对一、群组和全局聊天。持久化消息以保存聊天历史。
- 多人游戏 - 支持实时或回合制的主动和被动多人游戏。
- 排行榜 - 动态、季节性排行榜,可获取顶部成员或用户周围的成员。数量不限。
- 锦标赛 - 邀请玩家共同竞争奖品。可将多个锦标赛链接在一起创建联赛。
- 运行时代码 - 使用 Lua 或原生 Go 代码编写的自定义逻辑来扩展服务器。
- 匹配系统、仪表板、指标统计等更多功能。
我们计划在 2021 年 1 月发布 v3.0 版本。该版本的一个关键新增功能是为 Nakama 的脚本层添加了 JavaScript 运行时,该脚本层目前支持 Go 和 Lua。
更多关于Golang游戏社交基础设施Nakama使用指南(v2.15版)的实战教程也可以访问 https://www.itying.com/category-94-b0.html
预期的使用场景/用户流程是什么?README 文件对此描述得不够清楚。这是一个用于管理用户的库吗?比如,为已经编写了视频游戏并需要用户管理功能的人准备的?
此外,除了使用场景,你还可以(也应该)在 README 中添加一些架构图。
更多关于Golang游戏社交基础设施Nakama使用指南(v2.15版)的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html
Nakama v2.15 是一个功能强大的游戏服务器后端框架,以下是如何使用其核心功能的示例代码。
1. 用户认证
使用设备ID进行快速认证:
import (
"context"
"github.com/heroiclabs/nakama-common/api"
"github.com/heroiclabs/nakama/runtime"
)
func AuthenticateDevice(ctx context.Context, logger runtime.Logger, nk runtime.NakamaModule) error {
deviceID := "unique_device_id_123"
username := "player1"
create := true
// 设备认证
auth, err := nk.AuthenticateDevice(ctx, deviceID, username, create)
if err != nil {
logger.Error("认证失败: %v", err)
return err
}
logger.Info("用户认证成功,Token: %s", auth.Token)
return nil
}
2. 存储操作
存储和读取用户数据:
func StoreUserData(ctx context.Context, logger runtime.Logger, nk runtime.NakamaModule) error {
userID := "user_id_123"
// 写入存储
objects := []*runtime.StorageWrite{
{
Collection: "saves",
Key: "game_state",
UserID: userID,
Value: `{"level": 5, "score": 1000, "items": ["sword", "shield"]}`,
},
}
if _, err := nk.StorageWrite(ctx, objects); err != nil {
logger.Error("存储写入失败: %v", err)
return err
}
// 读取存储
objectIDs := []*runtime.StorageRead{
{
Collection: "saves",
Key: "game_state",
UserID: userID,
},
}
records, err := nk.StorageRead(ctx, objectIDs)
if err != nil {
logger.Error("存储读取失败: %v", err)
return err
}
logger.Info("读取的数据: %v", records[0].Value)
return nil
}
3. 实时多人匹配
创建和加入实时匹配:
func CreateRealTimeMatch(ctx context.Context, logger runtime.Logger, nk runtime.NakamaModule) error {
userID := "user_id_123"
// 创建匹配
matchID, err := nk.MatchCreate(ctx, "realtime_pvp", map[string]interface{}{
"max_players": 4,
"mode": "deathmatch",
})
if err != nil {
logger.Error("创建匹配失败: %v", err)
return err
}
logger.Info("匹配创建成功,ID: %s", matchID)
// 加入匹配
ticket, err := nk.MatchTicketAdd(ctx, matchID, userID, nil)
if err != nil {
logger.Error("加入匹配失败: %v", err)
return err
}
logger.Info("匹配加入凭证: %s", ticket.Ticket)
return nil
}
4. 排行榜系统
更新和获取排行榜数据:
func UpdateLeaderboard(ctx context.Context, logger runtime.Logger, nk runtime.NakamaModule) error {
leaderboardID := "global_scores"
userID := "user_id_123"
// 提交分数
_, err := nk.LeaderboardRecordWrite(ctx, leaderboardID, userID, "username", 1500, 100, nil)
if err != nil {
logger.Error("排行榜写入失败: %v", err)
return err
}
// 获取排行榜前10名
records, _, _, err := nk.LeaderboardRecordsList(ctx, leaderboardID, []string{}, 10, "", 0)
if err != nil {
logger.Error("获取排行榜失败: %v", err)
return err
}
for _, record := range records {
logger.Info("玩家: %s, 分数: %d", record.Username, record.Score)
}
return nil
}
5. 实时聊天
发送和接收聊天消息:
func SendChatMessage(ctx context.Context, logger runtime.Logger, nk runtime.NakamaModule) error {
senderID := "user_id_123"
receiverID := "user_id_456"
// 发送私聊消息
channel, err := nk.ChannelMessageSend(ctx, senderID, receiverID, "private",
map[string]interface{}{
"message": "你好,一起玩游戏吗?",
"type": "text",
})
if err != nil {
logger.Error("发送消息失败: %v", err)
return err
}
logger.Info("消息发送成功,频道ID: %s", channel.Id)
// 获取聊天历史
messages, _, _, err := nk.ChannelMessagesList(ctx, channel.Id, 10, "", false)
if err != nil {
logger.Error("获取消息历史失败: %v", err)
return err
}
for _, msg := range messages {
logger.Info("消息: %v", msg.Content)
}
return nil
}
6. RPC调用
自定义服务器逻辑:
func RegisterRPCFunctions(initializer runtime.Initializer) error {
// 注册RPC函数
if err := initializer.RegisterRpc("health_check", rpcHealthCheck); err != nil {
return err
}
if err := initializer.RegisterRpc("get_player_stats", rpcGetPlayerStats); err != nil {
return err
}
return nil
}
func rpcHealthCheck(ctx context.Context, logger runtime.Logger, nk runtime.NakamaModule, payload string) (string, error) {
return `{"status": "healthy", "timestamp": "` + time.Now().Format(time.RFC3339) + `"}`, nil
}
func rpcGetPlayerStats(ctx context.Context, logger runtime.Logger, nk runtime.NakamaModule, payload string) (string, error) {
var request struct {
UserID string `json:"user_id"`
}
if err := json.Unmarshal([]byte(payload), &request); err != nil {
return "", err
}
stats := map[string]interface{}{
"level": 10,
"exp": 5000,
"rank": "gold",
"playtime": 3600,
}
response, _ := json.Marshal(stats)
return string(response), nil
}
7. 匹配处理器
实现自定义匹配逻辑:
type MatchHandler struct{}
func (m *MatchHandler) MatchInit(ctx context.Context, logger runtime.Logger, nk runtime.NakamaModule, params map[string]interface{}) (interface{}, int, string) {
state := map[string]interface{}{
"players": make(map[string]interface{}),
"game_state": "waiting",
"start_time": time.Now().Unix(),
}
tickRate := 30 // 每秒30帧
label := "pvp_match"
return state, tickRate, label
}
func (m *MatchHandler) MatchJoinAttempt(ctx context.Context, logger runtime.Logger, nk runtime.NakamaModule, dispatcher runtime.MatchDispatcher, tick int64, state interface{}, presence runtime.Presence, metadata map[string]string) (interface{}, bool, string) {
matchState := state.(map[string]interface{})
players := matchState["players"].(map[string]interface{})
if len(players) >= 4 {
return matchState, false, "房间已满"
}
return matchState, true, ""
}
func (m *MatchHandler) MatchJoin(ctx context.Context, logger runtime.Logger, nk runtime.NakamaModule, dispatcher runtime.MatchDispatcher, tick int64, state interface{}, presences []runtime.Presence) interface{} {
matchState := state.(map[string]interface{})
players := matchState["players"].(map[string]interface{})
for _, presence := range presences {
players[presence.GetUserId()] = map[string]interface{}{
"username": presence.GetUsername(),
"ready": false,
}
}
matchState["players"] = players
return matchState
}
这些示例展示了Nakama v2.15的核心功能使用方式,包括用户系统、存储、实时匹配、排行榜、聊天和自定义逻辑扩展。

