2 个版本

0.0.2 2024 年 3 月 19 日
0.0.1 2024 年 2 月 18 日

#787 in 游戏开发

Download history 45/week @ 2024-03-29 10/week @ 2024-04-05 2/week @ 2024-05-31 1/week @ 2024-06-07

每月 100 次下载

Apache-2.0

68KB
1K SLoC

实体关系映射器(基于 bevy 构建)

一个 bevy 插件,旨在通过实体组件系统架构辅助数据库访问。

将单个用户请求传递到 ECS 作为事件。系统可以使用允许从数据库加载 ECS 中的实体的数据库查询。一旦实体现在内存中被修改,它们会在请求的刷新事件发生后刷新回数据库。每个请求都打开一个新的数据库事务,以保持请求之间的隔离。


   ┌────────────────────────────────────────────────────┐
   │                                                    │
   │                     Web Server                     │
   │                                                    │
   │                                                    │
   │    ┌─────────────────┐      ┌─────────────────┐    │
   │    │   Requests      │      │   Responses     │    │
   │    │                 │      │                 │    │
   │    │  ┌───────┐      │      │  ┌───────┐      │    │
   │    │  │       │      │      │  │       │      │    │
   │    │  └───────┘      │      │  └───────┘      │    │
   │    │                 │      │                 │    │
   │    │  ┌───────┐      │      │  ┌───────┐      │    │
   │    │  │       │      │      │  │       │      │    │
   │    │  └───────┘      │      │  └───────┘      │    │
   │    │                 │      │                 │    │
   │    │  ┌───────┐      │      │  ┌───────┐      │    │
   │    │  │       │      │      │  │       │      │    │
   │    │  └───────┘      │      │  └───────┘      │    │
   │    │                 │      │                 │    │
   │    └───┬─────────────┘      └─────────────▲───┘    │
   │        │                                  │        │
   │        │                                  │        │
   └────────┼──────────────────────────────────┼────────┘
            │                                  │
    Requests│                                  │Events
    create  │            ┌────────┐            │create
    events  │            │        │            │response
            │          ┌─┴──────┐ │            │
            │          │        │ │            │
            └──────────► Event  │ ├────────────┘
                       │        │ │
                       │        ├─┘
                       └───┬──▲─┘
                Systems    │  │
                process    │  │
                events     │  │
                       ┌───▼──┴──────────┐
                       │                 │
                   ┌───┴───────────────┐ │
                   │   Business Logic  │ │
                   │      Systems      │ │
                   │                   │ │
                   │                   │ │
                   │                   │ │
                   │                   │ │
                   │                   │ │
                   │                   │ │
                   │                   │ │
                   │                   │ │
                   │                   │ │
                   │                   ├─┘
                   └───┬─────────────▲─┘
                       │             │
             Queries   │             │ Queries
             access the│             │ return
             database  │             │ components
         ┌─────────────▼┐           ┌┴─────────────────────────────────────┐
         │   Database   │ loaded    │  Entities                            │
         │              │ in as     │                                      │
         │              │ components│            ┌────────┐   ┌────────┐   │
         │              ├───────────┤  Entity 1: │ Comp 1 │   │ Comp 2 │   │
         │              │           │     ───────┴────────┴───┴────────┘   │
         │              │           │                                      │
         │              │           │                         ┌────────┐   │
         │              │           │  Entity 2:              │ Comp 2 │   │
         │              │           │    ─────────────────────┴────────┘   │
         └──────────────┘           │                                      │
                                    └──────────────────────────────────────┘

使用方法

目前仅开发了 SQLite 数据库作为 Database Resource 实现。因此,这仅适用于 SQLite 数据库。请随意为新的数据库资源添加问题。

使用 DBQueryDerive 派生宏来生成组件映射器,将数据库行映射到组件。结构体上的每个属性都被视为 SQLite 数据库中的列。

例如,创建一个用户组件

use async_trait::async_trait;
use bevy::prelude::*;
use bevy_erm::*;
use bevy_erm_derive::DBQueryDerive;

#[derive(Component, sqlx::FromRow, DBQueryDerive)]
#[table_name = "users"]
pub struct User {
    pub name: String,
    pub age: i32,
}

例如,如果您有一个网络服务器资源,则可以从中提取消息。然后开始一个新的事务以获取用户的名称。

DatabaseResource 特性定义了如何查询访问实际数据库。使用 sqlx 的 Sqlite 数据库连接器已在 SqlxSqliteDatabaseResource 下。

use bevy::prelude::*;
use bevy_erm::*;

pub fn handle_webserver_events(
    db: Res<SqlxSqliteDatabaseResource>,
    webserver: Res<WebServer>, // Your own defined resource
) {
    while webserver.messages_to_handle() {
        let http_request = webserver.pop();
        let user_id = http_request.user_id;

        if let Some(request) = db.try_start_new_transaction() {
            let purchase_event = GetUserNameEvent {
                user_id,
                request,
            };

            // Forward the event on to the next system
            purchase_events.send(purchase_event);
        } else {
            // All connections are used 
            // wait for next round
            break;
        }
    }

}

添加一个系统来查询用户以处理 GetUserNameEvent。打印用户名称。

use bevy::prelude::*;
use bevy_erm::*;

pub fn print_user_names(
    users: DatabaseQuery<&User>,
    mut get_user_names_events: EventReader<GetUserNameEvent>,
) {
    for get_user_name_event in get_user_names_events.read() {
        let request = get_user_name_event.request;
        let user_id = get_user_name_event.user_id;

        let user = users.get(&(user_id, request))
            .await.unwrap();

        println!("{}", user.name);
    }

}

设置 bevy 应用


fn main() {
    App::new()
        .set_runner(runner)
        .init_resource::<WebServer>()
        .add_event::<GetUserNameEvent>()
        // Add the bevy_erm plugin
        .add_plugins(EntityRelationMapperPlugin)
        // Specify how if components were created or updated how they 
        // would be flushed to the database
        .add_systems(PostUpdate, flush_component_to_db::<Option<&User>, SqlxSqliteDatabaseResource>)
        // Add the created systems above
        .add_systems(Update, handle_webserver_events)
        .add_systems(Update, print_user_names)
        // Add other systems 
        // ...
        .run();

}

示例

位于 ./examples 中

依赖关系

62MB
~1M SLoC