# 状态

**URL:** https://heroiclabs.com/docs/zh/nakama/concepts/status/
**Summary:** Nakama 用户可以在连接时设置状态消息，并在在线时进行更新。状态为每一连接而设置，用户断开连接时被擦除。用户可以彼此关注，从而获得状态变化通知。知道好友何时在线，在做什么，太好了。

---


# 状态

Nakama 用户可以在连接时设置状态消息，并在在线时进行更新。

用户可以彼此关注，从而获得状态变化通知。知道好友在线，在做什么，太好了。

状态为每一连接而设置，用户断开连接时被擦除。如果用户从多个设备连接，则允许每个设备具有不同的状态。

## 设置状态

默认情况下，用户首次连接时没有状态，而且不会对其关注者显示在线。为显示在线，用户必须设置状态。

状态可以很简单，比如用户发给其关注者的文字消息，也可以是包含复杂信息的结构化 JSON 字符串，例如用户当前所在的[实时多人游戏比赛 ID](../multiplayer/relayed/) – 这样他们的好友就可以加入他们！

{{< code type="client" >}}
```javascript
socket.updateStatus("Hello everyone!");
```
{{< / code >}}

{{< code type="client" >}}
```csharp
await socket.UpdateStatusAsync("Hello everyone!");
```
{{< / code >}}

{{< code type="client" >}}
```cpp
rtClient->updateStatus("Hello everyone!");
```
{{< / code >}}

{{< code type="client" >}}
```java
socket.updateStatus("Hello everyone!").get();
```
{{< / code >}}

{{< code type="client" framework="godot3" >}}
```gdscript
var update : NakamaAsyncResult = yield(socket.update_status_async(JSON.print({"status": "happy"})), "completed")
if update.is_exception():
    print("An error occurred: %s" % update)
    return
print("Status updated")
```
{{< / code >}}

{{< code type="client" framework="defold" >}}
```lua
socket.status_update(socket, "Hello everyone!")
```
{{< / code >}}

{{< missing type="client" lang="bash" />}}
{{< missing type="client" lang="shell" />}}

通过此操作，可以随时设置和更新此状态。

## 显示离线

如用户需要显示离线或“不可见”，他们可以擦除其状态，达到这个目的。如果用户断开连接，其关注者将接收到与此相同的状态更新。

{{< code type="client" >}}
```javascript
socket.updateStatus();
```
{{< / code >}}

{{< code type="client" >}}
```csharp
await socket.UpdateStatusAsync(null);
```
{{< / code >}}

{{< code type="client" >}}
```cpp
rtClient->updateStatus("");
```
{{< / code >}}

{{< code type="client" >}}
```java
socket.updateStatus(null).get();
```
{{< / code >}}

{{< code type="client" framework="godot3" >}}
```gdscript
var leave : NakamaAsyncResult = yield(socket.update_status_async(""), "completed")
if leave.is_exception():
    print("An error occurred: %s" % leave)
    return
print("Status updated")
```
{{< / code >}}

{{< missing type="client" lang="lua" framework="defold" />}}
{{< missing type="client" lang="bash" />}}
{{< missing type="client" lang="shell" />}}

## 接收状态更新

在用户更新其状态时，其所有关注者都将接收到一个事件，其中包含旧的和新的状态。客户端注册一个事件处理程序，会在收到状态更新事件时调用它。

{{< code type="client" >}}
```javascript
socket.onstatuspresence = (statuspresence) => {
    statuspresence.leaves.forEach((leave) => {
        console.log("User %o no longer has status %o", leave.user_id, leave.status);
    });
    statuspresence.joins.forEach((join) => {
        console.log("User %o now has status %o", join.user_id, join.status);
    });
};
```
{{< / code >}}

{{< code type="client" >}}
```csharp
socket.ReceivedStatusPresence += presenceEvent =>
{
    Console.WriteLine(presenceEvent);
    foreach (var joined in presenceEvent.Joins)
    {
        Console.WriteLine("User id '{0}' status joined '{1}'", joined.UserId, joined.Status);
    }
    foreach (var left in presenceEvent.Leaves)
    {
        Console.WriteLine("User id '{0}' status left '{1}'", left.UserId, left.Status);
    }
};
```
{{< / code >}}

{{< code type="client" >}}
```cpp
rtListener->setStatusPresenceCallback([](const NStatusPresenceEvent& event)
{
    for (auto& presence : event.leaves)
    {
        std::cout << "User " << presence.username << " no longer has status " << presence.status << std::endl;
    }

    for (auto& presence : event.joins)
    {
        std::cout << "User " << presence.username << " now has status " << presence.status << std::endl;
    }
});
```
{{< / code >}}

{{< code type="client" >}}
```java
SocketListener listener = new AbstractSocketListener() {
    @Override
    public void onStatusPresence(final StatusPresenceEvent presence) {
        for (UserPresence userPresence : presence.getJoins()) {
            System.out.println("User ID: " + userPresence.getUserId() + " Username: " + userPresence.getUsername() + " Status: " + userPresence.getStatus());
        }

        for (UserPresence userPresence : presence.getLeaves()) {
            System.out.println("User ID: " + userPresence.getUserId() + " Username: " + userPresence.getUsername() + " Status: " + userPresence.getStatus());
        }
    }
};
```
{{< / code >}}

{{< code type="client" framework="godot3" >}}
```gdscript
func _ready():
    # First, setup the socket as explained in the authentication section.
    socket.connect("received_status_presence", self, "_on_status_presence")

func _on_status_presence(p_presence : NakamaRTAPI.StatusPresenceEvent):
    print(p_presence)
    for j in p_presence.joins:
        print("%s joined with status: %s" % [j.user_id, j.status])
    for j in p_presence.leaves:
        print("%s left with status: %s" % [j.user_id, j.status])
```
{{< / code >}}

{{< missing type="client" lang="lua" framework="defold" />}}
{{< missing type="client" lang="bash" />}}
{{< missing type="client" lang="shell" />}}

如果用户断开连接或显示为离线，他们将退出其以前的状态，但不会有相应的新状态。

## 关注用户

用户只能接收他们关注的人的状态更新。用户可以关注他们感兴趣的任何人，但通常会关注一些好友来查看他们何时在线，他们在做什么。

关注一组用户后，该操作将立即返回当前在线并设置了可见状态的用户的状态。

对用户的关注仅在当前会话中有效。当用户断开连接时，他们会自动取消关注在连接时关注的任何人。

{{< code type="client" >}}
```javascript
var status = await socket.followUsers(["<user id>"]);
status.presences.forEach((presence) => {
  console.log("User %o has status %o", presence.user_id, presence.status);
});
```
{{< / code >}}

{{< code type="client" >}}
```csharp
await socket.FollowUsersAsync(new[] { "<user id>" });
```
{{< / code >}}

{{< code type="client" >}}
```cpp
auto successCallback = [](const NStatus& status)
{
    for (auto& presence : status.presences)
    {
        std::cout << "User " << presence.username << " has status " << presence.status << std::endl;
    }
};

rtClient->followUsers({ "<user id>" }, successCallback);
```
{{< / code >}}

{{< code type="client" >}}
```java
socket.followUsers("<user id>").get();
```
{{< / code >}}

{{< code type="client" framework="godot3" >}}
```gdscript
var user_ids = ["<user-id1>", "<user-id2>"]
var status : NakamaRTAPI.Status = yield(socket.follow_users_async(user_ids), "completed")
if status.is_exception():
    print("An error occurred: %s" % status)
    return
print(status)
```
{{< / code >}}

{{< missing type="client" lang="lua" framework="defold" />}}
{{< missing type="client" lang="bash" />}}
{{< missing type="client" lang="shell" />}}

## 取消关注用户

取消关注一组用户后，此用户将立即停止接收这些用户的任何进一步状态更新。

{{< code type="client" >}}
```javascript
socket.unfollowUsers(["<user id>"]);
```
{{< / code >}}

{{< code type="client" >}}
```csharp
await socket.UnfollowUsersAsync(new[] { "<user id>" });
```
{{< / code >}}

{{< code type="client" >}}
```cpp
rtClient->unfollowUsers({ "<user id>" });
```
{{< / code >}}

{{< code type="client" >}}
```java
socket.unfollowUsers("<user id>").get();
```
{{< / code >}}

{{< code type="client" framework="godot3" >}}
```gdscript
var user_ids = ["<user-id1>", "<user-id2>"]
var status : NakamaAsyncResult = yield(socket.unfollow_users_async(user_ids), "completed")
if status.is_exception():
    print("An error occurred: %s" % status)
    return
print(status)
```
{{< / code >}}
