Java/Android客户端指南 #

本客户端库指南将介绍如何开发名为Sagi-shi(“Imposter”的日语名称)游戏的Nakama特有部分(无完整的游戏逻辑或UI),此游戏受Among Us(外部)启发,从而展示如何在Java 使用Nakama的核心功能。

Sagi-shi gameplay screen
Sagi-shi gameplay

前提条件 #

开始之前,确保您已经:

  • 安装Nakama服务器
  • 下载Nakama Java SDK。您可以下载“nakama java-$version.jar”或“nakama-$version all.jar”,其中包括所有依赖项的卷影副本。

为使用Java客户端,您想要Gradle等构建工具,以及IntelliJEclipseVisual Studio Code等编辑器/IDE。

完整版API文档 #

请在API文档中查看完整版API文档。

设置 #

在项目中安装Nakama Java SDK有几种不同的选项,具体取决于您使用的是Gradle、Maven或是直接使用JAR包。

通过Gradle安装 #

通过Maven安装 #

通过JAR安装 #

要更新到新版本的Nakama Java SDK,请替换Gradle/Maven配置文件中的版本/提交引用。

日志 #

Nakama Java SDK 使用 SLF4J 日志 API。通过阅读SLF4J用户手册,您可以找到如何使用此API及不同日志绑定的更多信息。

本指南中的所有示例均使用SLF4J Logger,其创建方法如下:

对于Android #

Android使用权限系统来确定此应用程序将请求使用哪些平台服务,并向用户请求权限。客户端使用网络与服务器通信,因此您必须添加“INTERNET”权限。

异步编程 #

许多Nakama API为异步、非阻塞,可从使用ListenableFuture对象的Java SDK中获得,这些对象在Google Guava库中。

Sagi-shi使用回调调用这些异步方法,不阻塞调用线程,从而保持游戏响应能力和效率。

如要将异步调用连在一起,可以使用AsyncFunction<>对象和Futures.transformAsync函数达到这个目的。

为简洁起见,本指南中的代码示例将使用更简单但却阻塞线程的.get()函数。

处理异常 #

网络编程需要额外的保护措施,防止出现连接和有效负载方面的问题。

如上所示,Sagi Shi中的API调用使用回调模式,同时提供成功回调和失败回调。如果API调用抛出异常,将在onFailure回调中处理异常,可以在throwable对象中访问异常详细信息。

对数据进行序列化和反序列化处理 #

通过网络发送和接收数据时,需要对数据进行适当的序列化和反序列化处理。使用JSON和二进制数据是两种最常见的方式。

两个示例都将展示如何对以下Map进行序列化和反序列化处理,但也可以用于任何可序列化处理的对象。

JSON #

使用com.google.gson.Gson包。

二进制 #

使用java.io.*包。仅当您想将序列化处理后的数据作为String发送和接收时,才有必要转换为Base64和从其转换;否则,您可以使用byte[]数组进行序列化和反序列化处理。

新手入门 #

新手入门需要使用Nakama客户端和套接字对象开始创建Sagi-shi和您自己的游戏。

Nakama客户端 #

Nakama客户端与Nakama服务器连接,是访问Nakama功能的入口。建议为每个游戏的每个服务器创建一个客户端。

要为Sagi-shi创建一个客户端,请将以下连接详情输入您的服务器:

Nakama Java SDK通过gRPC直接与Nakama服务器通信,因此您需要使用为Nakama server配置的gRPC端口号;默认情况下,这是7349

配置请求超时时长 #

客户端对Nakama发出的每个请求必须在一定时间内完成,超过这个时间段会被认为超时。您可以通过在客户端设置Timeout值来配置该时间段的长度(以秒为单位):

Nakama套接字 #

Nakama套接字用于玩法和实时延迟敏感功能,如聊天、派对、比赛和RPC。

套接字在服务器上的一个不同端口上向客户端公开。您想要在此指定一个不同的端口,确保成功建立连接。

客户端可以创建与服务器的一个或多个套接字。每个套接字都可以有自己的注册事件侦听器,处理从服务器接收的响应。

从客户端创建套接字:

身份验证 #

Nakama支持许多身份验证方法,也支持在服务器上创建自定义身份验证

Sagi-shi将通过设备和Facebook进行身份验证,链接到同一个用户账户,以便玩家可以使用不同的设备进行游戏。

Sagi-shi login screen
Login screen and Authentication options

设备身份验证 #

Nakama设备身份验证使用物理设备的唯一标识符轻松验证用户,也可以为没有账户的设备创建账户。

仅使用设备身份验证时无需使用登录UI,因为游戏启动时会自动验证玩家身份。

身份验证是从Nakama客户端实例访问Nakama功能的示例。

Facebook身份验证 #

Nakama Facebook身份验证操作简便,您可以有选择性地导入玩家的Facebook好友,并将这些好友添加到玩家的Nakama好友列表。

自定义身份验证 #

Nakama支持自定义身份验证方法,以便与其他身份服务相集成。

示例请见Itch.io自定义身份验证配方。

链接身份验证 #

Nakama允许玩家在进行身份验证后通过链接身份验证 方法前往玩家账户。

链接设备ID身份验证

链接Facebook身份验证

会话变量 #

在身份验证时可以存储Nakama 会话变量,并且只要会话处于活动状态,就可以在客户端和服务器上使用Nakama会话变量。

Sagi-shi使用会话变量执行分析、推荐和奖励计划等。

在进行身份验证时将会话变量作为参数传递即可存储会话变量:

要访问客户端的会话变量,请使用Session对象上的Vars属性:

会话生命周期 #

Nakama 会话在您的服务器配置中设定的时间之后过期。使不活动会话过期是良好的安全做法。

建议存储会话中的身份验证令牌,并在启动时检查它是否已过期。如果令牌过期,必须重新进行身份验证。在服务器中可将令牌过期时间当作设置予以更改。

Nakama提供了在不需要重新进行身份验证的情况下恢复会话的方法,例如当Sagi-shi玩家重新启动游戏时。

用户账户 #

Nakama 用户账户存储Nakama定义的用户信息和自定义的开发者元数据。

Sagi-shi允许玩家编辑自己的账户,并存储游戏进度和游戏内商品等内容的元数据。

Sagi-shi player profile screen
Player profile

获取用户账户 #

通过经身份验证的会话可以访问Nakama的许多功能,例如获取用户帐户

获取Sagi-shi玩家的完整用户账户,包括基本用户信息 和用户ID:

更新用户账户 #

Nakama为更新服务器存储的资源(如用户账户)提供了简单的方法。

Sagi-shi玩家需要能够更新其公开资料:

获取用户 #

除了获取当前经过身份验证的玩家的用户帐户之外,Nakama还有一个方便的方法,可以从其他玩家的ID、用户名或Facebook ID中获取他们的公开个人资料列表。

Sagi-shi在结合Nakama的其他功能时,通过这种方法显示用户的资料:

存储元数据 #

Nakama用户元数据允许开发人员使用公开的用户字段扩展用户账户。

仅可在服务器上更新用户元数据。示例请见更新用户元数据配方。

Sagi-shi将使用元数据存储玩家装备的游戏内商品:

读取元数据 #

定义描述元数据的分类,并对JSON元数据进行语法解析:

上述代码使用com.google.gson序列化/反序列化库。

钱包 #

Nakama用户钱包可以将多种数字货币存储为字符串/整数的键/值对。

Sagi-shi玩家可以使用游戏内的虚拟货币解锁或购买头衔、皮肤和帽子。

访问钱包 #

对用户账户中的JSON钱包数据进行语法解析:

更新钱包 #

仅可在服务器上更新钱包。示例请见用户账户虚拟钱包文档。

验证应用内的购买行为 #

Sagi-shi玩家可以通过应用程序内的购买行为购买游戏内的虚拟货币,这些购买行为需要经过服务器授权并且通过合法性验证。

示例请见应用程序内购买行为验证文档。

存储引擎 #

Nakama存储引擎是为您的游戏而设的分布式、可扩展的基于文件的存储解决方案。

通过存储引擎,您可以更好地控制数据在集合中的访问方式结构

这些集合会被命名,并将JSON数据存储在唯一的键和用户ID下。

默认玩家拥有创建、读取、更新和删除自己的存储对象的全部权限。

Sagi-shi玩家可以解锁或购买存储引擎中存储的许多商品。

Sagi-shi player items screen
Player items

读取存储对象 #

定义一个描述存储对象的类(或选用HashMap<String, Object>),并使用集合名称、键和用户id创建一个新的存储对象id。 最后,读取存储对象并对JSON数据进行语法解析:

要读取其他玩家的公开存储对象,应该使用其UserId。 玩家仅可读取自己拥有的存储对象或公开的存储对象(PermissionRead值为2)。

写入存储对象 #

Nakama允许开发人员从客户端和服务器写入存储引擎。

在决定写入逻辑的存放位置时,要考虑恶意用户会对您的游戏和财物产生何种不利影响,例如仅允许经过授权后写入数据(即游戏解锁或进度)。

Sagi-shi允许玩家收藏商品,以便在UI界面轻松查看这些商品,可以安全地通过客户端写入这些数据。

使用集合名称、键和JSON编码的数据创建写入存储对象。最后,将存储对象写入存储引擎:

您也可以将多个对象传递到client.writeStorageObjects方法:

条件性写入 #

存储引擎条件写入确保仅当对象在您访问后未改变时才会发生写入操作。

这样可以保护您的数据不被覆盖,例如,Sagi-shi服务器可能在玩家上次访问对象后更新对象。

要执行有条件写入,应该使用最新的对象版本向写入存储对象添加版本:

列出存储对象 #

您可以在一个集合中列出玩家可以查看的所有存储对象,而非通过单独的键发出多次读取请求。

Sagi-shi列出玩家未解锁或已购买的所有头衔、帽子和皮肤:

分页结果 #

Nakama列出结果的方法会退回游标,并将其传递给Nakama的后续调用,指示从集合中检索对象的起始位置。

例如:

  • 如果游标的值为5,您将从第五个对象开始获取结果。
  • 如果游标的值为null,您将从第一个对象开始获取结果。

保护服务器上的存储操作 #

可以在服务器上保护Nakama存储引擎操作,从而保护不应被玩家修改的数据(即 游戏解锁或进度)。参见经授权写入存储引擎配方。

远程程序调用 #

Nakama服务器允许开发人员写入自定义逻辑,并将其作为RPC向客户端公开。

Sagi-shi包含各种需要在服务器上保护的逻辑,例如在装备设备之前检查玩家是否拥有设备。

创建服务器逻辑 #

关于创建远程过程检查玩家在装备设备之前是否拥有设备的示例,参见经授权处理玩家设备配方。

客户端RPC #

可以从客户端调用Nakama远程过程,并获取可选的JSON负载。

Sagi-shi客户端允许RPC安全地装备帽子:

套接字RPC #

当您需要与Nakama的实时功能交流时,也可以从套接字中调用Nakama Remote Procedures。

好友 #

Nakama好友提供完整的社交图谱系统来管理玩家之间的好友关系。

Sagi-shi允许玩家添加好友,管理好友关系,组队玩游戏。

Sagi-shi Friends screen
Friends screen

添加好友 #

在Nakama中添加好友不会立即添加共同好友。它会向每个用户发送好友请求,需要用户接受请求。

Sagi-shi允许玩家按用户名或用户id添加好友:

好友关系的状态 #

在Nakama中,好友关系分为以下几 种状态

状态
0共同好友
1已发出的等待接受的好友请求
2已收到的等待接受的好友请求
4被封禁

列出好友 #

Nakama允许开发人员按好友关系的状态列出玩家的好友。

Sagi-shi列出最近20位共同好友:

接受好友请求 #

在Nakama中接受好友请求时,玩家会添加双向好友关系

Nakama会将两个玩家的好友状态从等待接受改变为共同好友。

在完整的游戏中,您可以允许玩家单独接受某些请求。

Sagi-shi仅获取并接受收到的所有好友请求:

删除好友 #

Sagi-shi玩家可以按用户名或用户id删除好友:

屏蔽用户 #

Sagi-shi玩家可以按用户名或用户id屏蔽用户:

被封堵的好友以朋友关系状态3表示。

状态与显示 #

Nakama状态是一种实时状态与显示的服务,允许用户设置显示的在线状态,更新状态消息并关注其他用户的更新。

玩家可以关注其他人但不与之成为好友。

Sagi-shi使用状态消息和显示的在线状态,当好友在线时通知玩家并分享比赛。

Sagi-shi status update screen
Updating player status

关注用户 #

Nakama实时API允许开发人员订阅套接字上的事件并实时接收这些事件,如状态显示变更。

关注用户的方法也会返回至当前的在线用户(即显示的在线状态)及其状态。

Sagi-shi关注玩家的好友,并当好友在线时通知玩家:

取消关注用户 #

Sagi-shi玩家可以取消关注其他人:

更新玩家状态 #

Sagi-shi玩家可以更改状态并向关注自己的人发布状态:

群组 #

Nakama群组是指一个公开/私密的群组或家族体系,拥有用户成员资格和权限、元数据和群组聊天功能。

Sagi-shi允许玩家创建和加入群组,以便参加社交或竞赛。

Sagi-shi groups screen
Groups list screen

创建群组 #

群组可以为公开或私密“开放”。每个人都可以加入公开的群组,但如想加入私密群组,必须要请求加入,得到超级管理员/管理员批准。

Sagi-shi玩家可以围绕共同的兴趣创建群组:

更新群组的可见性 #

Nakama允许群组的超级管理员或管理员成员从客户端更新某些属性,如开放可见性:

更新群组规模 #

其他属性只能在服务器上更改,例如群组成员的最大数量。

参见更新群组规模配方示例和群组服务器功能参考,以进一步了解在服务器上更新群组的信息。

Sagi-shi group edit screen
Sagi-shi group edit

列出和过滤群组 #

群组可以像Nakama的其他资源一样列出,也可以使用通配符群组名称进行过滤

Sagi-shi玩家可通过列出和过滤群组搜索加入现有群组:

删除群组 #

Nakama允许群组的超级管理员删除群组。

开发人员可以完全禁用此功能,请在Guarding API指南中查看如何保护Nakama各种API的示例。

Sagi-shi玩家可以删除自己担任超级管理员的群组:

群组元数据 #

与用户账户一样,群组可以拥有公开元数据。

Sagi-shi使用群组元数据存储群组的兴趣、玩家的活跃时间和使用的语言。

仅可在服务器上更新群组元数据。示例请见更新群组元数据配方。

Sagi-shi客户端使用群组元数据负载进行RPC:

群组成员资格状态 #

在Nakama中,成员资格可以有以下几种状态

代码用途
0超级管理员任何群组都必须拥有至少一位超级管理员。超级管理员拥有管理员的所有权限,另外还可以删除群组和升级管理员成员。
1管理员可以有一个或多个管理员。管理员可以更新群组,也可以接受、踢出、升级、降级、封禁或添加成员。
2成员群组常规成员。无法接受新用户的加入请求。
3加入请求新用户发来的新的加入请求。这不会被计入群组成员的最大数量。

加入群组 #

如果用户加入公开群组,可立即成为群组成员,但如果尝试加入私密群组,必须等待群组管理员接受请求。

Sagi-shi玩家可以加入群组:

列出用户的群组 #

Sagi-shi玩家可以列出其所在的群组:

列出成员 #

Sagi-shi玩家可以列出群组的成员:

接受加入请求 #

私密群组管理员或超级管理员可以通过将用户重新添加到群组来接受加入请求。

Sagi-shi首先列出处于请求加入状态的用户,然后遍历将这些用户添加到群组:

升级成员 #

Nakama群组成员可以升级为管理员或超级管理员角色,帮助管理规模不断扩大的群组,或在成员离开时接任。

管理员可以将其他成员升级为管理员,超级管理员可以将其他成员升级为超级管理员。

成员将被提升一级。例如:

  • 成员可以升级为管理员
  • 管理员可以升级为超级管理员

降级成员 #

Sagi-shi群组管理员和超级管理员可以降级成员:

踢出成员 #

Sagi-shi群组管理员和超级管理员可以移除群组成员:

封禁成员 #

当降级用户或踢出用户不够严重时,Sagi-shi群组管理员和超级管理员可以封禁成员:

退出群组 #

Sagi-shi玩家可以退出群组:

聊天 #

Nakama聊天是针对群组、私密/直接消息以及动态聊天室的实时聊天系统。

Sagi-shi在比赛期间使用动态聊天,玩家可以相互误导,讨论谁是内鬼,群组聊天和私密/直接消息。

Sagi-shi chat screen
Sagi-shi Chat

加入动态聊天室 #

Sagi-shi比赛设有非持久性聊天室,供玩家交流:

加入群组聊天 #

Sagi-shi群组成员可以在持久性群组聊天频道中跨越游戏会话进行交流:

加入直接聊天 #

Sagi-shi玩家也可以在比赛中或比赛后一对一私下交流,并查看消息历史记录:

发送消息 #

在每种聊天频道中,消息的发送都是一样的。消息包含聊天文本和表情,以JSON序列化数据的形式发送:

列出消息历史 #

消息列表需要一个参数来表示接收消息的顺序为从最早到最新(向前)或从最新到最早。

Sagi-shi玩家可以列出群组的消息历史:

聊天还有可缓存的游标,获取最新消息,您可以随意存储这些消息。

更新消息 #

Nakama还支持更新消息。您可以选择是否使用此功能,但在类似Sagi-shi的欺骗性游戏中,它可以增加额外的欺骗元素。

例如玩家发送以下消息:

比赛 #

Nakama支持服务器授权服务器中继的多人比赛。

在服务器授权比赛中,服务器控制玩法循环,并且必须使所有的客户端与游戏的当前状态保持同步。

在服务器中继比赛中,客户端处于控制地位,服务器仅将信息中继到其他连接的客户端。

在Sagi-shi之类的竞争性游戏中,服务器授权比赛可防止客户端以未经授权的方式与您的游戏交互。

在本指南中,为方便起见,采用了服务器中继模式。

创建比赛 #

Sagi-shi玩家可以自行创建比赛并邀请在线好友加入:

加入比赛 #

如果知道id,Sagi-shi玩家可以尝试加入已有比赛:

或者设置实时配对监听器,将自己加入到配对:

按玩家状态加入比赛

Sagi-shi玩家可以在加入新比赛时更新状态:

关注玩家的用户可以接收实时状态事件,并尝试加入比赛:

列出比赛 #

比赛列表需要一些标准来过滤比赛,包括玩家人数、匹配标签和可以进行更复杂的搜索查询的选项。

在大厅状态时可以开始Sagi-shi比赛。比赛会存在于服务器,但只有当加入的玩家人数足够时才会开始比赛。

之后,Sagi-shi可以列出正在等待更多玩家的比赛:

找到标签为"AnExactMatchLabel"的比赛:

-->

生成玩家 #

比赛对象有一个当前在线用户列表,称为显示在线的用户。

Sagi-shi使用比赛显示的在线状态在客户端(在此以Player对象表示玩家)上生成玩家:

Sagi-shi使用接收到的比赛显示的在线状态事件(作为套接字侦听器替代),使生成的玩家在离开和加入比赛时保持最新状态:

发送比赛状态 #

Nakama拥有实时网络,可以在玩家移动和与游戏世界互动时发送接收比赛状态。

比赛过程中,Sagi-shi的每个客户端都会将比赛状态发送到服务器,从而中继给其他客户端。

匹配状态包含一个操作代码,使接收者了解所接收的数据,以便对数据进行反序列化处理并更新其游戏视图。

Sagi-shi使用的操作代码示例:

  • 1:玩家位置
  • 2:玩家调用投票

发送玩家位置

定义一个类别来代表Sagi-shi玩家的位置状态。

在玩家的转换中创建一个实例,设置操作代码并发送JSON编码的状态:

操作代码作为静态属性

Sagi-shi有许多联网游戏动作。对操作代码使用静态常量类将使代码更容易理解和维护:

接收比赛状态 #

Sagi-shi玩家可以通过订阅比赛状态接收事件,从其他连接的客户端接收比赛数据:

配对程序 #

开发人员可以使用比赛列表或Nakama配对程序为玩家寻找匹配,使玩家能够加入实时匹配池,并在匹配到其他符合指定标准的玩家时收到通知。

配对可以帮助玩家找到一起玩游戏的伙伴,但不会创建比赛。这种解耦设计允许您将配对用于寻找游戏匹配之外的其他目的。例如,如果您想社交,可以使用配对来寻找其他人聊天。

添加配对程序 #

匹配标准可以很简单,即找到2名玩家,也可以更复杂,即找到2-10名对特定游戏模式感兴趣的拥有最低技能水平的玩家。

Sagi-shi允许玩家加入匹配池,让服务器将这些玩家与其他玩家匹配:

找到比赛后,可以直接从onMatchmakerMatched套接字处理程序加入其中。

Sagi-shi通过私密/直接消息将派对id分享给好友:

加入派对 #

Safi-shi玩家可以通过查看聊天消息中的派对id来加入派对:

升级成员 #

Sagi-shi派对成员可以升级为派对领导者:

退出派对 #

Sagi-shi玩家可以退出派对:

派对配对 #

加入派对的一个主要好处是,所有玩家都可以同时加入匹配池。

Sagi-shi玩家可以收听配对程序匹配事件,并在找到匹配人时加入比赛:

派对领导者将开始为派对进行匹配:

–>

排行榜 #

Nakama排行榜为您的游戏引入竞争因素,提高了玩家的参与度和保留率。

Sagi-shi有一个内鬼获胜的周排行榜,玩家每次获胜都会增加得分,同样,也有队员获胜的周排行榜。

Sagi-shi leaderboard screen
Sagi-shi Leaderboard

创建排行榜 #

必须在服务器上创建排行榜,请在排行榜文档中查看有关创建排行榜的详细信息。

提交分数 #

玩家提交分数时,Nakama将会把提交的分数值加到玩家的现有分数中。

除了分数值外,Nakama还有一个子分数,当分数值相同时可使用子分数进行排序。

Sagi-shi玩家可以向排行榜提交带有情境元数据的分数,例如取得分数的地图:

列出最高记录 #

Sagi-shi玩家可以列出排行榜的最高记录:

列出用户周围的记录

Nakama允许开发人员列出玩家周围的排行榜记录。

Sagi-shi向玩家简要介绍其与周围玩家的对抗情况:

列出一系列用户的记录

Sagi-shi玩家可以通过向所有者id参数提供他们的用户id来获取好友分数:

同样也可以通过向所有者id参数提供他们的用户id来获取群组成员的分数:

删除记录 #

Sagi-shi玩家可以删除自己的排行榜记录:

锦标赛 #

Nakama锦标赛是玩家争夺奖励的短暂比赛。

Sagi-shi玩家可以查看、过滤和加入正在进行的锦标赛。

Sagi-shi tournaments screen
Sagi-shi Tournaments

创建锦标赛 #

必须在服务器上创建锦标赛,请在锦标赛文档中查看有关创建锦标赛的详细信息。

Sagi-shi每周都会举行锦标赛,玩家需要投票给最准确的内鬼。本周结束时,排名靠前的玩家将获得游戏货币奖励。

加入锦标赛 #

默认Nakama玩家不必加入锦标赛也可提交分数,但Sagi-shi强制要求加入锦标赛后方可提交分数:

列出锦标赛 #

Sagi-shi玩家可以根据各种标准列出和筛选锦标赛:

出于性能方面的考虑,通过范围而不是单个数字来过滤类别。您可以利用这一点构建您的类别(例如,所有的PvE锦标赛属于1XX范围,所有的PvP锦标赛属于2XX范围)。

列出记录 #

Sagi-shi玩家可以列出锦标赛记录:

列出用户周围的记录

与排行榜类似,Sagi-shi玩家可以获取周围其他玩家的记录:

提交分数 #

Sagi-shi玩家可以向锦标赛提交分数、子分数和元数据:

通知 #

游戏服务器可利用Nakama通知向玩家广播实时消息。

通知可以是持续性(在玩家查看之前一直保留)或暂时性的(仅在玩家当前在线的情况下接收)。

Sagi-shi使用通知将获奖情况告知锦标赛获奖者。

Sagi-shi notification screen
Sagi-shi notifications

接收通知 #

必须通过服务器发送通知。

Nakama使用代码区分通知。0 和以下代码是为Nakama内部构件保留的系统代码

Sagi-shi玩家可以使用套接字侦听器订阅收到通知的事件。Sagi-shi使用代码100表示赢得锦标赛:

列出通知 #

Sagi-shi玩家可以列出离线时收到的通知:

分页及可缓存游标

与其他列出方法一样,可以使用游标或可缓存游标将通知结果分页。

假设可缓存文件已保存,则玩家下次登录时,可以通过可缓存游标列出未读通知。

删除通知 #

Sagi-shi玩家可以在阅读后删除通知: