# Java/Android

**URL:** https://heroiclabs.com/docs/zh/nakama/client-libraries/java/
**Summary:** 官方Java客户端实时处理与服务器的所有通信。该客户端可实现服务器中的所有功能。本指南将介绍如何开发游戏的Nakama特有部分，从而展示如何在Java中使用Nakama的核心功能。

---


# Java/Android客户端指南

本客户端库指南将介绍如何开发名为Sagi-shi（“Imposter”的日语名称）游戏的Nakama特有部分（无完整的游戏逻辑或UI），此游戏受[Among Us（外部）](https://www.innersloth.com/games/among-us/)启发，从而展示如何在**Java** 使用Nakama的核心功能。

<figure>
  <img src="/docs/nakama/client-libraries/images/gameplay.png" alt="Sagi-shi gameplay screen">
  <figcaption>Sagi-shi gameplay</figcaption>
</figure>

## 前提条件

开始之前，确保您已经：

- 安装[Nakama服务器](../../getting-started/install/docker/)
- 下载[Nakama Java SDK](https://github.com/heroiclabs/nakama-java/releases/latest)。您可以下载“nakama java-$version.jar”或“nakama-$version all.jar”，其中包括所有依赖项的卷影副本。

为使用Java客户端，您想要[Gradle](https://gradle.org/)等构建工具，以及[IntelliJ](https://www.jetbrains.com/idea/)、[Eclipse](https://eclipse.org/ide/)或[Visual Studio Code](https://code.visualstudio.com/)等编辑器/IDE。


### 完整版API文档

请在[API文档](https://heroiclabs.github.io/nakama-java/)中查看完整版API文档。

## 设置

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

### 通过Gradle安装

<!-- code examples -->

### 通过Maven安装

<!-- code examples -->

### 通过JAR安装

<!-- code examples -->

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

### 日志

Nakama Java SDK 使用 SLF4J 日志 API。通过阅读[SLF4J用户手册](https://www.slf4j.org/manual.html)，您可以找到如何使用此API及不同日志绑定的更多信息。

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

<!-- code examples -->

### 对于Android

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

<!-- code examples -->

### 异步编程
许多Nakama API为异步、非阻塞，可从使用[`ListenableFuture`](https://guava.dev/releases/snapshot/api/docs/com/google/common/util/concurrent/ListenableFuture.html)对象的Java SDK中获得，这些对象在Google Guava库中。

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

<!-- code examples -->

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

<!-- code examples -->

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

<!-- code examples -->


### 处理异常

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

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

<!--
### Handling retries
The Java SDK doesn't provide RetryConfiguration options
 -->


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

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

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

<!-- code examples -->


#### JSON

使用`com.google.gson.Gson`包。

<!-- code examples -->


#### 二进制

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

<!-- code examples -->


## 新手入门

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

<!-- simple system diagram of Java Nakama client, Nakama client socket, connecting to Nakama server -->


### Nakama客户端

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

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

<!-- code examples -->

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

### 配置请求超时时长

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

<!-- code examples -->

### Nakama套接字

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

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

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

从客户端创建套接字：

<!-- code examples -->


## 身份验证

Nakama支持许多[身份验证方法](../../concepts/authentication)，也支持在服务器上创建[自定义身份验证](../../concepts/authentication#custom)。

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

<figure>
  <img src="/docs/nakama/client-libraries/images/login.png" alt="Sagi-shi login screen">
  <figcaption>Login screen and Authentication options</figcaption>
</figure>


### 设备身份验证

Nakama[设备身份验证](../../concepts/authentication/#device)使用物理设备的唯一标识符轻松验证用户，也可以为没有账户的设备创建账户。

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

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

<!-- code examples -->

### Facebook身份验证

Nakama [Facebook身份验证](../../concepts/authentication/#facebook)操作简便，您可以有选择性地导入玩家的Facebook好友，并将这些好友添加到玩家的Nakama好友列表。

<!-- code examples -->


### 自定义身份验证

Nakama支持[自定义身份验证](../../concepts/authentication/#custom)方法，以便与其他身份服务相集成。

示例请见[Itch.io自定义身份验证](../../client-libraries/snippets/custom-authentication/)配方。


### 链接身份验证

Nakama允许玩家在进行身份验证后通过[链接身份验证](../../concepts/authentication/#link-or-unlink) 方法前往玩家账户。


**链接设备ID身份验证**

<!-- code examples -->


**链接Facebook身份验证**

<!-- code examples -->


### 会话变量

<!-- TODO: test, missing from concept docs -->

在身份验证时可以存储Nakama [会话变量](../../concepts/session/#session-variables)，并且只要会话处于活动状态，就可以在客户端和服务器上使用Nakama会话变量。

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

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

<!-- code examples -->
要访问客户端的会话变量，请使用`Session`对象上的`Vars`属性：

<!-- code examples -->


### 会话生命周期

Nakama [会话](../../concepts/session/)在您的服务器[配置](../../getting-started/configuration#session)中设定的时间之后过期。使不活动会话过期是良好的安全做法。

建议存储会话中的身份验证令牌，并在启动时检查它是否已过期。如果令牌过期，必须重新进行身份验证。在服务器中可将令牌过期时间当作[设置](../../getting-started/configuration#common-properties)予以更改。

<!-- code examples -->

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

<!-- code examples -->

<!-- No Refresh API -->

<!-- No Logout API -->


## 用户账户

Nakama [用户账户](../../concepts/user-accounts/)存储Nakama定义的用户信息和自定义的开发者元数据。

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

<figure>
  <img src="/docs/nakama/client-libraries/images/profile.png" alt="Sagi-shi player profile screen">
  <figcaption>Player profile</figcaption>
</figure>


### 获取用户账户

<!-- TODO: no API docs for Account, User
TODO: some account stuff seems to be duplicated in sessions and account, eg. getUsername -->

通过经身份验证的会话可以访问Nakama的许多功能，例如[获取用户帐户](../../concepts/user-accounts/#fetch-account)。

获取Sagi-shi玩家的完整用户账户，包括基本[用户信息](../../concepts/user-accounts/#fetch-account) 和用户ID：

<!-- code examples -->


### 更新用户账户

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

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

<!-- code examples -->


### 获取用户

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

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

<!-- code examples -->


### 存储元数据

<!-- TODO: missing Account, User API docs. Aren't defined as Java classes.
TODO: no metadata concept data. -->

Nakama[用户元数据](../../concepts/user-accounts/#user-metadata)允许开发人员使用公开的用户字段扩展用户账户。

仅可在服务器上更新用户元数据。示例请见[更新用户元数据](../../client-libraries/snippets/user-metadata)配方。

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


### 读取元数据

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

<!-- code examples -->

<!-- code examples -->

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


### 钱包

Nakama[用户钱包](../../concepts/user-accounts/#virtual-wallet)可以将多种数字货币存储为字符串/整数的键/值对。

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

#### 访问钱包

<!-- TODO: missing Account, User API docs.
TODO: no virtual wallets concept data. -->

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

<!-- code examples -->


#### 更新钱包

仅可在服务器上更新钱包。示例请见[用户账户虚拟钱包](../../concepts/user-accounts#virtual-wallet)文档。


#### 验证应用内的购买行为

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

示例请见[应用程序内购买行为验证](../../concepts/iap-validation/)文档。


## 存储引擎

Nakama[存储引擎](../../concepts/storage/)是为您的游戏而设的分布式、可扩展的基于文件的存储解决方案。

通过存储引擎，您可以更好地控制数据在集合中的[访问方式](../../concepts/storage/permissions/#object-permissions)和[结构](../../concepts/storage/collections/)。

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

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

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

<figure>
  <img src="/docs/nakama/client-libraries/images/player-items.png" alt="Sagi-shi player items screen">
  <figcaption>Player items</figcaption>
</figure>


### 读取存储对象

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

<!-- code examples -->

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


### 写入存储对象

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

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

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

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

<!-- code examples -->

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

<!-- code examples -->

### 条件性写入

存储引擎[条件写入](../../concepts/storage/collections/#conditional-writes)确保仅当对象在您访问后未改变时才会发生写入操作。

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

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

<!-- code examples -->


### 列出存储对象

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

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

<!-- code examples -->


### 分页结果

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

例如：
- 如果游标的值为5，您将从第五个对象开始获取结果。
- 如果游标的值为`null`，您将从第一个对象开始获取结果。

<!-- code examples -->


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

可以在服务器上保护Nakama存储引擎操作，从而保护不应被玩家修改的数据（即 游戏解锁或进度）。参见[经授权写入存储引擎](../../client-libraries/snippets/authoritative-write/)配方。


## 远程程序调用

Nakama[服务器](../../server-framework/)允许开发人员写入自定义逻辑，并将其作为[RPC](../../server-framework/introduction/#functionality)向客户端公开。

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

<!-- PRC flow diagram -->


### 创建服务器逻辑

关于创建远程过程检查玩家在装备设备之前是否拥有设备的示例，参见[经授权处理玩家设备](../../client-libraries/snippets/authoritative-read/)配方。


### 客户端RPC

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

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

<!-- code examples -->


### 套接字RPC

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

<!-- todo: the explanation of how this interfaces with real-time functionality is not clear -->

<!-- code examples -->


## 好友

Nakama[好友](../../concepts/friends/)提供完整的社交图谱系统来管理玩家之间的好友关系。

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

<figure>
  <img src="/docs/nakama/client-libraries/images/friends.png" alt="Sagi-shi Friends screen">
  <figcaption>Friends screen</figcaption>
</figure>


### 添加好友

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

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


<!-- code examples -->


### 好友关系的状态

在Nakama中，好友关系分为以下几 种[状态](../../concepts/friends#friend-state)：

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


### 列出好友

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

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

<!-- code examples -->


### 接受好友请求

在Nakama中接受好友请求时，玩家会添加[双向好友关系](../../concepts/friends/best-practices/#modeling-relationships)。

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

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

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

<!-- code examples -->


### 删除好友

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

<!-- code examples -->


### 屏蔽用户

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

<!-- code examples -->

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


## 状态与显示

Nakama[状态](../../concepts/status/)是一种实时状态与显示的服务，允许用户设置显示的在线状态，更新状态消息并关注其他用户的更新。

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

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

<figure>
  <img src="/docs/nakama/client-libraries/images/status.png" alt="Sagi-shi status update screen">
  <figcaption>Updating player status</figcaption>
</figure>


### 关注用户

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

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

<!-- todo: follow users query needs explaining -->

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

<!-- code examples -->


### 取消关注用户

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

<!-- code examples -->


### 更新玩家状态

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

<!-- code examples -->


## 群组

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

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

<figure>
  <img src="/docs/nakama/client-libraries/images/groups-list.png" alt="Sagi-shi groups screen">
  <figcaption>Groups list screen</figcaption>
</figure>


### 创建群组

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

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

<!-- code examples -->


### 更新群组的可见性

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

<!-- code examples -->


### 更新群组规模

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

参见[更新群组规模](../../concepts/groups/#updating-group-size)配方示例和[群组服务器功能参考](../../server-framework/typescript-runtime/function-reference#groups)，以进一步了解在服务器上更新群组的信息。

<figure>
  <img src="/docs/nakama/client-libraries/images/group-edit.png" alt="Sagi-shi group edit screen">
  <figcaption>Sagi-shi group edit</figcaption>
</figure>


### 列出和过滤群组

群组可以像Nakama的其他资源一样列出，也可以使用通配符群组名称进行[过滤](../../concepts/groups/#list-and-filter-groups)。

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


<!-- code examples -->


### 删除群组

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

开发人员可以完全禁用此功能，请在[Guarding API指南](../../guides/server-framework/guarding-apis/)中查看如何保护Nakama各种API的示例。

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

<!-- code examples -->


### 群组元数据

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

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

仅可在服务器上更新群组元数据。示例请见[更新群组元数据](../../client-libraries/snippets/group-metadata)配方。

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

<!-- code examples -->


### 群组成员资格状态

在Nakama中，成员资格可以有以下几种[状态](../../concepts/groups/#groups-and-clans)：

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


### 加入群组

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

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

<!-- code examples -->


### 列出用户的群组

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

<!-- code examples -->


### 列出成员

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

<!-- code examples -->


### 接受加入请求

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

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


<!-- code examples -->


### 升级成员

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

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

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

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

<!-- code examples -->


### 降级成员

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

<!-- code examples -->


### 踢出成员

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

<!-- code examples -->


### 封禁成员

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

<!-- code examples -->

### 退出群组

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

<!-- code examples -->


## 聊天

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

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

<figure>
  <img src="/docs/nakama/client-libraries/images/chat.png" alt="Sagi-shi chat screen">
  <figcaption>Sagi-shi Chat</figcaption>
</figure>


### 加入动态聊天室

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

<!-- code examples -->


### 加入群组聊天

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

<!-- code examples -->


### 加入直接聊天

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

<!-- code examples -->


### 发送消息

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

<!-- code examples -->


### 列出消息历史

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

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

<!-- code examples -->

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

<!-- code examples -->


### 更新消息

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

例如玩家发送以下消息：

<!-- code examples -->


## 比赛

Nakama支持[服务器授权](../../concepts/multiplayer/authoritative/)和[服务器中继](../../concepts/multiplayer/relayed/)的多人比赛。

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

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

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

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

<!-- flow chat of server relayed matches, to be fleshed out -->


### 创建比赛

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

<!-- code examples -->

### 加入比赛

如果知道id，Sagi-shi玩家可以尝试加入已有比赛：
<!-- code examples -->

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

<!-- code examples -->


**按玩家状态加入比赛**

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

<!-- code examples -->

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

<!-- code examples -->

### 列出比赛

[比赛列表](../../concepts/multiplayer/authoritative/#match-label)需要一些标准来过滤比赛，包括玩家人数、匹配标签和可以进行更复杂的[搜索查询](../../concepts/multiplayer/authoritative/#search-query)的选项。

<!-- todo: we don't have concept or client side docs for match listing labels or search queries -->

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

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

<!-- code examples -->

找到标签为`"AnExactMatchLabel"`的比赛：

<!-- code examples -->

<!--
There doesn't appear to be a way to specify a query param in the java sdk for client.listMatches.

**Advanced:**

In order to use a more complex structured query, the match label must be in JSON format.

To find a match where it expects player skill level to be `>100` and optionally has a game mode of `"sabotage"`:

<!-- code examples --> -->


### 生成玩家

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

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

<!-- code examples -->

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

<!-- code examples -->


### 发送比赛状态

Nakama拥有实时网络，可以在玩家移动和与游戏世界互动时[发送](../../concepts/multiplayer/relayed/#send-data-messages)和[接收](../../concepts/multiplayer/relayed/#receive-data-messages)比赛状态。

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

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

Sagi-shi使用的操作代码示例：
- 1：玩家位置
- 2：玩家调用投票


**发送玩家位置**

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

<!-- code examples -->

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

<!-- code examples -->


**操作代码作为静态属性**

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

<!-- code examples -->


### 接收比赛状态

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

<!-- code examples -->


## 配对程序

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

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

<!-- matchmaker flow chart, to be fleshed out -->


### 添加配对程序

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

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

<!-- code examples -->

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

<!-- code examples -->

<!-- todo: add a stand alone guide/recipe for widening the matchmaker criteria as it's a more complex example to include here -->


<!--
TODO: There is no party API in the Java SDK

## Parties

Nakama [Parties](../../concepts/parties/) is a real-time system that allows players to form short lived parties that don't persist after all players have disconnected.

Sagi-shi allows friends to form a party and matchmake together.


### Creating parties

The player who creates the party is the party's leader. Parties have maximum number of players and can be open to automatically accept players or closed so that the party leader can accept incoming join requests.

Sagi-shi uses closed parties with a maximum of 4 players:

<!-- code examples -->

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

<!-- code examples -->


### 加入派对

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

<!-- code examples -->

### 升级成员

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

<!-- code examples -->

### 退出派对

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

<!-- code examples -->


### 派对配对

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

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

<!-- code examples -->

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

<!-- code examples -->
-->


## 排行榜

Nakama[排行榜](../../concepts/leaderboards/)为您的游戏引入竞争因素，提高了玩家的参与度和保留率。

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

<figure>
  <img src="/docs/nakama/client-libraries/images/leaderboard.png" alt="Sagi-shi leaderboard screen">
  <figcaption>Sagi-shi Leaderboard</figcaption>
</figure>


### 创建排行榜

必须在服务器上创建排行榜，请在[排行榜](../../concepts/leaderboards#create-a-leaderboard)文档中查看有关创建排行榜的详细信息。


### 提交分数

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

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

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

<!-- code examples -->

### 列出最高记录

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

<!-- code examples -->


**列出用户周围的记录**

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

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

<!-- code examples -->


**列出一系列用户的记录**

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

<!-- code examples -->

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

<!-- code examples -->


### 删除记录

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

<!-- code examples -->


## 锦标赛

Nakama[锦标赛](../../concepts/tournaments/)是玩家争夺奖励的短暂比赛。

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

<figure>
  <img src="/docs/nakama/client-libraries/images/tournaments.png" alt="Sagi-shi tournaments screen">
  <figcaption>Sagi-shi Tournaments</figcaption>
</figure>


### 创建锦标赛

必须在服务器上创建锦标赛，请在[锦标赛](../../concepts/tournaments#create-tournament)文档中查看有关创建锦标赛的详细信息。

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


### 加入锦标赛

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

<!-- code examples -->

### 列出锦标赛

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

<!-- code examples -->

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


### 列出记录

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

<!-- code examples -->


**列出用户周围的记录**

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

<!-- code examples -->


### 提交分数

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

<!-- code examples -->


## 通知

游戏服务器可利用Nakama[通知](../../concepts/notifications/)向玩家广播实时消息。

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

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

<figure>
  <img src="/docs/nakama/client-libraries/images/notifications.png" alt="Sagi-shi notification screen">
  <figcaption>Sagi-shi notifications</figcaption>
</figure>


### 接收通知

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

Nakama使用代码区分通知。`0` 和以下代码是为Nakama内部构件保留的[系统代码](../../concepts/notifications/#notification-codes)。

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

<!-- code examples -->


### 列出通知

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

<!-- code examples -->


**分页及可缓存游标**

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

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

<!-- code examples -->


### 删除通知

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

<!-- code examples -->
