1 个不稳定版本
0.1.0 | 2024年1月22日 |
---|
#18 in #visibility
在 bevy_replicon_attributes 中使用
3KB
Bevy Replicon Attributes
通过属性控制服务器实体和事件的可见性来扩展 bevy_replicon。
基本示例
use bevy::prelude::*;
use bevy_replicon::prelude::{ClientId, Replicated};
use bevy_replicon_attributes::prelude::*;
#[derive(Component)]
struct Bat;
#[derive(Event)]
struct SpawnBat;
#[derive(Event, Copy, Clone)]
struct BatAlert;
#[derive(Event)]
struct GainedNightVision(ClientId);
#[derive(VisibilityAttribute, Default, PartialEq)]
struct HasNightVision;
#[derive(VisibilityAttribute, Default, PartialEq)]
struct IsAwake;
#[derive(VisibilityAttribute, Default, PartialEq)]
struct HatesBats;
fn spawn_bats(
mut commands : Commands,
mut events : EventReader<SpawnBat>,
mut sender : ServerEventSender<BatAlert>,
attributes : ClientAttributes,
){
for _ in events.read()
{
// Entity
commands.spawn((Bat, Replicated, vis!(HasNightVision)));
// Server event
sender.send(&attributes, BatAlert, vis!(all!(HasNightVision, IsAwake, HatesBats)));
}
}
fn gain_night_vision(
mut events : EventReader<GainedNightVision>,
mut attributes : ClientAttributes,
){
for client_id in events.read()
{
// Client attribute
attributes.add(client_id, HasNightVision);
}
}
用法
设置
将 replicon 添加到您的服务器应用程序中。此软件包仅适用于 VisibilityPolicy::All
和 VisibilityPolicy::Whitelist
。
有关设置 renet 服务器的信息,请参阅 renet。
use bevy::prelude::*;
use bevy_replicon::prelude::*;
app.add_plugins(bevy::time::TimePlugin) //required by bevy_renet
.add_plugins(RepliconPlugins
.build()
.disable::<ClientPlugin>()
.set(ServerPlugin{
visibility_policy: VisibilityPolicy::Whitelist,
..Default::default(),
})
);
将 VisibilityAttributesPlugin
添加到您的服务器应用程序中,并在 replicon 插件之后。如果使用了 VisibilityPolicy::Blacklist
,则插件会引发恐慌。您必须指定一个 ReconnectPolicy
use bevy_replicon_attributes::prelude::*;
app.add_plugins(VisibilityAttributesPlugin{ reconnect_policy: ReconnectPolicy::Reset });
如果选择了 ReconnectPolicy::Repair
,我们建议还使用 bevy_replicon_repair 以在客户端上保留复制的状态。
定义属性
可以使用 VisibilityAttribute
来派生属性,它需要 Default
和 PartialEq
。仅应使用零大小类型来使用此派生。
#[derive(VisibilityAttribute, Default, PartialEq)]
struct InStartingArea;
更复杂的属性应手动实现 VisibilityAttribute
。
struct InLocation(x: u32, y: u32);
impl VisibilityAttribute for InLocation
{
fn inner_attribute_id(&self) -> u64
{
((self.x as u64) << 32) + (self.y as u64)
}
}
此处定义的 inner_attribute_id
用于区分相同类型的属性实例。
将属性添加到客户端
使用ClientAttributes
系统参数向客户端添加属性。
当评估实体是否应该被复制到客户端的VisibilityConditions
时,使用客户端属性。
use bevy::prelude::*;
use bevy_replicon::prelude::ServerEvent;
use bevy_replicon_attributes::prelude::*;
#[derive(VisibilityAttribute, Default, PartialEq)]
struct IsDisconnected;
fn update_visibility_on_connect_events(
mut server_events : EventReader<ServerEvent>,
mut attributes : ClientAttributes,
){
for event in server_events.read()
{
match event
{
ServerEvent::ClientConnected{ id } =>
{
attributes.remove(id, IsDisconnected);
attributes.add(id, InStartingArea);
}
ServerEvent::ClientDisconnected{ id, _ } =>
{
attributes.add(id, IsDisconnected);
}
}
}
}
默认客户端属性
每次客户端连接时,都会分配Global
和Client
内置属性。
实体可见性
实体可见性由VisibilityConditions
控制,它们是VisibilityAttributes
和逻辑操作符not()
/and()
/or()
的任意组合。
将实体可见性条件与客户端属性列表进行比较,以确定实体是否可见。
为了方便,我们有一个vis!()
宏,它生成新的VisibilityCondition
组件。可以在vis!()
宏内部使用any!()
/all!()
/none!()
宏,除了not()
/and()
/or()
。
空可见性条件始终评估为false
。如果您想为实体设置全局可见性,请使用客户端连接时分配的内置Global
属性。
这里是一个低级示例,说明它是如何工作的。在实际应用中,您只需要将 VisibilityAttributes
添加到客户端,并将 VisibilityCondition
组件添加到实体中。这个包将负责将此信息转换为 bevy_replicon
中的实体可见性。
use bevy::prelude::*;
use bevy_replicon_attributes::prelude::*;
fn entity_demo(
mut commands : Commands,
mut attributes : ClientAttributes,
){
let client_id = ClientId::from_raw(0u64);
// Add location to client.
attributes.add(client_id, InLocation(0, 20));
// Make location condition.
let location = vis!(InLocation(0, 20));
// Evaluate condition.
let client_attributes = attributes.get(client_id).unwrap();
assert!(location.evaluate(|a| client_attributes.contains(&a)));
// Spawn entity.
commands.spawn((Replicated, location));
}
以下是一些更复杂的可见性条件示例
// Basic
vis!();
vis!(A);
vis!(not(B));
vis!(and(A, B));
vis!(or(A, B));
vis!(and(A, not(B)));
// Composition
vis!(and(A, vis!(B)));
// Helpers
vis!(any!(A, B, C)); // vis!(or(A, or(B, C)))
vis!(all!(A, B, C)); // vis!(and(A, and(B, C)))
vis!(none!(A, B, C)); // vis!(not(or(A, or(B, C)))))
// Modification
vis!()
.and(A) // vis!(A)
.or(B) // vis!(or(A, B))
.replace(or(A, B), and(C(1), D)) // vis!(and(C(1), D))
.replace_type::<C>(E(2)) // vis!(and(E(2), D))
.remove(E(2)) // vis!(D)
;
服务器事件
可以使用 ServerEventSender
系统参数来控制服务器事件的可见性。
服务器事件必须使用 bevy_replicon
进行注册。客户端将通过 EventReader<T>
接收服务器事件。
use bevy::prelude::*;
use bevy_replicon::prelude::*;
use bevy_replicon_attributes::prelude::*;
#[derive(Event, Copy, Clone)]
struct E;
fn setup(app: &mut App)
{
// Replicon server event registration
app.add_server_event::<E>(EventType::Ordered);
}
fn send_event(mut sender: ServerEventSender<E>, attributes: ClientAttributes)
{
sender.send(&attributes, E, vis!(any!(Client::from(1), Client::from(2), Client::from(3))));
}
bevy_replicon
兼容性
bevy_replicon |
bevy_replicon_attributes |
---|---|
0.26 | 0.5 - master |
0.25 | 0.4 |
0.21 | 0.1 - 0.3 |
依赖项
~260–700KB
~17K SLoC