11个版本 (6个重大更新)

0.7.0 2024年8月24日
0.6.0 2023年11月21日
0.5.3 2023年9月20日
0.4.1 2023年9月14日
0.1.0 2023年9月2日

#664 in 网络编程

Download history 3/week @ 2024-07-06 118/week @ 2024-07-27 6/week @ 2024-08-03

每月124次下载

MIT/Apache

42KB
498

Bevy客户端服务器事件

Bevy Client Server Events Latest version Documentation MIT Apache

Bevy的简单基于事件的客户端-服务器网络库。

轻松将事件从客户端发送到服务器或从服务器发送到客户端,无需担心序列化或网络传输细节。

基于renet/bevy_renet库构建,旨在简化通过网络发送的类型配置和管理。

目标:

  • 简化网络设置和配置
  • 轻松将任何类型从客户端发送到服务器或从服务器发送到客户端

要求:

  • serde用于在您的类型上派生SerializeDeserialize

事件

以下事件对服务器很有用

  • EventWriter<StartServer> - 发送此事件以启动服务器
  • EventWriter<StopServer> - 发送此事件以停止运行中的服务器
  • EventReader<ClientConnected> - 每次新客户端连接时都会收到
  • EventReader<ClientDisconnected> - 每次客户端断开连接时都会收到
  • EventReader<ReceiveFromClient<T>> - 当客户端向服务器发送类型T时收到
  • EventWriter<SendToClient<T>> - 发送此事件以便特定客户端接收类型T
  • EventWriter<SendToClients<T>> - 将此事件发送给所有已连接的客户端以接收类型 T

以下事件对客户端很有用

  • EventWriter<ConnectToServer> - 发送此事件以连接到服务器
  • EventWriter<DisconnectFromServer> - 发送此事件以从服务器断开连接
  • EventWriter<SendToServer<T>> - 发送此事件以使服务器接收类型 T
  • EventReader<ReceiveFromServer<T>> - 服务器向客户端发送类型 T 时收到

客户端和服务器都可以接收 EventReader<NetcodeTransportError> 事件来处理网络错误。

示例

examples/ 目录中有一些示例。

Ping

查看 examples/ping.rs 文件,了解一个简单的 ping-pong 示例。

在一个终端会话中,启动服务器: cargo run --example ping -- -s

在另一个终端会话中,连接客户端: cargo run --example ping

将客户端窗口置于焦点,按 ENTER 发送 Ping。服务器将以 Pong 响应。

在这个示例中,我们希望向服务器发送 Ping 事件并接收一个返回的 Pong 事件。

#[derive(Event, Serialize, Deserialize)]
pub struct Ping;

#[derive(Event, Serialize, Deserialize)]
pub struct Pong;

在设置我们的 App 时,我们需要将其传递给 client_server_events_plugin 宏并提供所有要通过网络发送的类型。

fn main() {
    // ...
    let mut app = App::new();
    client_server_events_plugin!(
        app,
        Ping => NetworkConfig::default(),
        Pong => NetworkConfig::default()
    );
    // ...

您可以提供特定于类型的网络配置,例如可靠性、重传时间、最大内存使用量等。

无论此实例将是服务器还是客户端,都应该运行此宏。

您可以选择启动服务器实例或作为客户端连接到服务器使用事件。

fn start_server(mut start_server: EventWriter<StartServer>) {
    start_server.send(StartServer::default()); // Binds to 127.0.0.1:5000 with no encryption by default.
}

fn connect_as_client(mut connect_to_server: EventWriter<ConnectToServer>) {
    connect_to_server.send(ConnectToServer::default()); // Connects to 127.0.0.1:5000 with no encryption by default.
}

然后您可以根据需要发送/接收事件。

fn update_client(
    mut send_ping: EventWriter<SendToServer<Ping>>,
    mut receive_pong: EventReader<ReceiveFromServer<Pong>>,
) {
    // ...
    send_ping.send(SendToServer { content: Ping });
    // ...
    for ReceiveFromServer { content } in receive_pong.read() {
        // Do something with content (Pong).
        // ...
    }
}

fn update_server(
    mut receive_ping: EventReader<ReceiveFromClient<Ping>>,
    mut send_pong: EventWriter<SendToClient<Pong>>,
) {
    for ReceiveFromClient { client_id, content } in receive_ping.read() {
        // Do something with content (Ping).
        send_pong.send(SendToClient {
            client_id,
            content: Pong,
        });
    }
}

功能示例

查看 examples/features.rs 文件,了解更多功能示例,如加密、广播、网络错误处理和客户端连接/断开事件。

在一个终端会话中,启动服务器: cargo run --example features -- -s

在另一个终端会话中,连接客户端: cargo run --example features

服务器和客户端将使用加密进行通信。

每 500 帧,服务器将广播其帧计数消息。

在服务器窗口上聚焦

  • ESC 键停止服务器
  • ENTER 键启动服务器

当焦点在客户端窗口时

  • ESC 键从服务器断开连接
  • ENTER 键重新连接到服务器
  • SPACE 键发送类型为 PlayerMovement 的消息

服务器将以 ServerResponse 消息响应 PlayerMovement 消息。

其他网络库

创建这个库是因为我想找到一种最快、最简单的方式来通过网络发送类型。

其他解决方案似乎让我陷入了传输/网络/通道细节的困境。

这个库非常适合原型设计和小型客户端-服务器游戏。

一个带有更多功能的替代方案是 bevy_replicon

一个更成熟的替代方案,具有更多可定制性的是 bevy_renet

Bevy 兼容性

bevy bevy_client_server_events
0.14 0.7
0.12 0.6
0.11 0.5

依赖项

~24MB
~438K SLoC