#bevy_replicon

14621 messages Β· Page 15 of 15 (latest)

lilac mantle
#

Seems a bit involved to setup, I find it a bit weird that it couldn't be common to all backends once you have messages going no ?

spring raptor
lilac mantle
spring raptor
lilac mantle
spring raptor
lilac mantle
spring raptor
#

I.e. backends add a few more bytes to each message and it's nice to count them, that's why the API is like this.

dire aurora
#

Only now finally getting around to doing the migration to 0.37 ... Is there anything I need to do to get the same behavior as the old blacklist visibility policy? My player entity never gets marked as Replicated and thus my game gets stuck on connecting πŸ€”

spring raptor
# dire aurora Only now finally getting around to doing the migration to 0.37 ... Is there anyt...

Is there anything I need to do to get the same behavior as the old blacklist visibility policy?
All entities are visible by default. If you want to hide something, just create a visibility filter component. Entities/components with this component will be hidden if client entities don't have this component.

My player entity never gets marked as Replicated and thus my game gets stuck on connecting
Could you elaborate on this part?

dire aurora
#

My game gets trough the usual connecting loop, then once the clocks are synced it spawns a player locally, throws a signature on it, and waits until Replicated is added when the server sends it back

#

But that last part doesn't seem to happen currently

spring raptor
dire aurora
#
2026-01-10T20:20:20.182040Z ERROR bevy_replicon::shared::message::server_message::message_buffer: ignoring direct message for non-authorized client `193v0`, mark it as independent to allow this
```Huh, why does this not tell you the message that was sent? πŸ€”
#
2026-01-10T20:25:40.464945Z DEBUG bevy_replicon::server: disconnecting client `193v0` due to protocol mismatch (client: `ProtocolHash(7823686126691282433)`, server: `ProtocolHash(5274629916445082958)`)
```Ah now this might be related ... But how does the protocol hash mismatch, I didn't change anything ![thonk](https://cdn.discordapp.com/emojis/1153851465765490742.webp?size=128 "thonk")
#

I mean to begin with all the types are shared between client and server ...

spring raptor
dire aurora
#

But if we know it's not marked as independent we fetched something from the registry and should have a name, right?

spring raptor
dire aurora
#

Only difference is that the client has this line twice:

enabling mutate message tracking
enabling mutate message tracking
```Does that matter?
spring raptor
dire aurora
#

I'm not sure tbh thonk

spring raptor
dire aurora
#

Ah, my own code calls it, then collback also calls it, but it's only on the client so it only gets called once

#

Why does calling it twice affect the hash, was that always the case?

spring raptor
spring raptor
dire aurora
#

Looks like it works now, so it being called twice is what broke everything πŸ€¦β€β™€οΈ

spring raptor
spring raptor
dire aurora
#

Should probably fix my game's code so that failing protocolhashes are actually noticable

spring raptor
#

Your backend should disconnect on missmatch πŸ€”

dire aurora
#

It does

#

But the client doesn't care and keeps waiting

#

While spamming the logs

spring raptor
#

Ah, okay πŸ˜…

#

@dire aurora maybe we should enable this via feature instead?

#

Will be easier for third-party crates to enable.

dire aurora
#

The track mutate thing? Both works and are about as annoying I guess, only worth the feature if there is some meaningful behavior to gate I think

spring raptor
dire aurora
#

Nah, it wouldn't be much more convenient, enabling the feature from the rollback crate would have the same issue since the server doesn't depend on it

#

As long as the timing (and number of times) of when track mutate gets called doesn't matter it shouldn't be a problem

spring raptor
#

Ah, right.
Okay, let me quickly fix the hashing with extra calls.

dire aurora
#

Hmmmm, now to implement visibility in the new system

#

Though I'm not quite sure how do approach this, since there seems to only be components matching against theirselves implemented

#

But a player can see multiple rooms, while things can only be in one πŸ€”

spring raptor
#

You can also have a single filter component with bitmasks

#

And you can also manually register and toggle the bits.
For example, you can associate the first bit with specific set of components or the whole entity and simply toggle it on the client entity.

#

But in most cases component-based API is more convenient.

dire aurora
dire aurora
spring raptor
dire aurora
#

Dungeons have many rooms, though atm I might still be able to get away with 1 u64, and later use a bitvec or just multiple u64s

spring raptor
#

If so, you can just store the ID of the room. And the visibility check will be !=.

dire aurora
#

Yes, but they can see the connected rooms

spring raptor
#

Ah, got it πŸ€”

dire aurora
#

So a player might have say 5 rooms they can see, but each entity is only one ID

spring raptor
#

Then I'd go with a bitmask, yes.
A u64 or a compile-time sized bitmask if you need more (assuming you have a known number of rooms)

dire aurora
#

I don't know the number of rooms, but I could have an upper bound in my code

spring raptor
dire aurora
#

Like currently my dungeon generation works as follows:

  1. It generates a main path between 8 and 10 rooms long
  2. It adds a single branching room
  3. It adds a branch of 1-2 rooms
  4. It adds two branch of 2-4 rooms
  5. It adds a branch of 3-6 rooms
#

Eventually I'll make this scale in some way to offer sizes, different levels of branching/linearity, and add small graph mutations to make them less noticable branching structures

#

But I could always just generate these numbers based on some known upper bound

#

So currently there's max 27 rooms

spring raptor
#

Makes total sense.
It's possible to store a dynamically-sized bitmask, but in your case you can fix the size without compromising much.

dire aurora
#

Got it to work πŸ₯³

#

Pretty sure this implementation is way more efficient too

#

Few minor differences this way that I can't "fix" but they aren't that relevant (The hallways have the mask of both connected rooms, so you see not just the current room, its hallways and the next rooms, but also all their hallways)

spring raptor
icy flame
#

Hey, new here. I'm playing around a bit with bevy_replicon. I feel like I'm missing something. I can't quite figure out how to replicate resources/global state between server and clients. For example if I have a State (playing/paused) on my server, is there no built in way to replicate that to the clients? And if not, is the best practice to then have it as an entity on the server, and sync that to an actual State on the clients? Not sure if my questioning makes sense.. but I tried πŸ˜…

Update: Just saw this one, I guess it kinda ties in with my question: bevy: Store resources as components on singleton entities

spring raptor
icy flame
#

Ok thanks! Then I’m at least not doing something horribly wrong

dire aurora
#

Since migrating my crates and my game aren't possible, guess I'll take the time to see if I can finally remove bevy_bundlication from my game πŸ€”

spring raptor
dire aurora
#

Hmmm, running into a bit of a problem with using the replicate_as nicely because a lot of wrapper types has From<T> and Deref<Target = T>, but not Into<T> πŸ€”

#

I could manually impl them on a wrapper but that's rather ugly

spring raptor
dire aurora
#

And my attempt at making one wrapper from From<T> + Deref<Target = T> into From<T> + Into<T> is getting foiled by impls like impl<T: From<Vec3>> From<AsVec3> for T { not being allowed due to orphan rules ferris_sob

#

And ofc implementing the reverse Into is blocked because the impls could overlap bavy

spring raptor
#

How your wrappers look like? I thought you define them in your crate. Is this some already existing types?

dire aurora
#
#[derive(Serialize, Deserialize)]
pub struct AsVec3(Vec3);
spring raptor
dire aurora
#

If I manually do them it'll work I guess, kinda ugly to do that for every use of the wrapper though thonk

spring raptor
#

I.e.

impl From<Transform> for AsVec3 {
    fn from(value: Transform) -> Self {
        Self(value.translation}
    }
}
spring raptor
#

Or what you had in mind?

dire aurora
#

Well, in this case, LinearVelocity, Position, etc all already implement From<Vec3>, so it would be nice if that translated to my wrapper

#

Similarly, for Rotation and other Quat types I already get From<Quat>

#

This compiles at least:

#[derive(Serialize, Deserialize)]
pub struct AsVec3(Vec3);

impl From<AsVec3> for LinearVelocity {
    fn from(value: AsVec3) -> Self {
        Self::from(value.0)
    }
}
impl From<AsVec3> for Position {
    fn from(value: AsVec3) -> Self {
        Self::from(value.0)
    }
}

impl<T: core::ops::Deref<Target = Vec3>> From<T> for AsVec3 {
    fn from(value: T) -> Self {
        Self(*value.deref())
    }
}
#

But like, LinearVelocity and Positon both just lean on existing From<Vec3>s now, this seems a bit silly thonk

#

Well, arguably still better than making one of those awful replicate_with wrappers again bavy

#

I made the future/past tick ones worse btw, they now handle arbitrary integer types instead of only u16

spring raptor
dire aurora
#

Hmmm, I could maybe serialize them directly now that you mention it πŸ€”

spring raptor
#

replicate_as is useful when you want to quantize values or replicate specific fields.
And for these cases you can't automate it, you need to write the actual logic.

dire aurora
#

Replaced one of the most cursed bundles now ...
Before:rust #[derive(NetworkedBundle, Bundle, TypePath, Default)] pub struct MovementDataBundle { /// The movement state pub state: MoveState, /// The tick at which the character was last grounded, automatically updated pub last_ground: LastGround, /// The position of the character #[bundlication(as = Vec3Data)] pub position: Position, /// The rotation of the character #[bundlication(as = QuatXYData)] pub rotation: Rotation, /// The current velocity of the entity #[bundlication(as = Vec3Data)] pub velocity: LinearVelocity, } After:```rust
.replicate_bundle_filtered::<(MoveState, Position, LinearVelocity), With<CharacterController>>()
.replicate_with_filtered::<_, With<CharacterController>>(
AsPastTick::<u8, LastGround>::default(),
)
.replicate_filtered_as::<Rotation, AsQuatXY, With<CharacterController>>()

spring raptor
#

Great!

dire aurora
#

AsQuatXY has the same issue as AsVec3, though being able to get rid of any impls of that just because types lack Serialize+Deserialize saves some code at least

spring raptor
dire aurora
#

It probably does, but I don't serialize it as a Quat

#

I only send x/y rotation since the character controller only allows those

spring raptor
#

Ah, makes sense

dire aurora
#

In my skill networking code I could clean up a lot of stuff πŸ‘€

#

Still did some manual mapping for some reason

#

And I network skills as effectively (u8, u16), but writing the Serialize/Deserialize logic for that had proven to be impossible since it's a pretty weird enum dispatch type

#

But now I can just impl a From both ways and it works

#

That did allow one weird edgecase to slip in, but tbh that never got handled better than a panic, so now the server can just send clients skills that it doesn't understand and they become an Invalid skill variant that does nothing thonk

spring raptor
dire aurora
#

In theory the (u8, u16) can be a value that is not a valid skill

#

This has happened before in some niche cases

spring raptor
#

Got it. Yes, I think having Invalid is better than panicking.

dire aurora
#

Hmmm, do we have something like a "send this if this visibility filter fails"? πŸ€”

#

Basically I have the logic that if a skill is from a player, they get all the info on the player, and everyone else just sees the skill exists, and doesn't know how it's configured or whose it is, but they do still get the stats they need to simulate the effects

spring raptor
dire aurora
#

The owning client needs the data, the other clients need the pre-calculated stuff

#

Those are mutually exclusive

spring raptor
dire aurora
#

Perhaps an additional scope that specifies what you see when it's invisible, or the ability to make 2 filters using the same actual component

spring raptor
dire aurora
#

No no, I mean 1 visibility filter component

#

By having the ability to specify the type

#
impl VisibilityFilter for NotOwner {
    type Component = Owner
    ...
}
#

Would cause you to burn trough those visibility bits faster though πŸ€”

spring raptor
#

You just can't specify the component directly due to orphan rule 😒

dire aurora
#

That would just make Health the target of visibility, no?

#

What I'd need is a pair of two visibility filters on the same rule with the opposite logic ... Or just a way to set 2 scopes, one for when it's there, one for when it's not

#

Or like an inverted scope πŸ€”

#

Like in this case it'd be (SkillModifications, SkillOwner, Hides<CalculatedStats>) or something like that

#

As you can see the first two if you own the skill, but the latter disappear when you own the skill

spring raptor
dire aurora
#

Ah, that's a decent hack at least

#

But yea, we really need a better solution for this I think 🀣

#

Also, it does feel a bit limiting that our filters require the same component on both entities. In this case I have a SkillOwner component that I could've matched already with the OwnedPlayer component on a client entity, but instead I'll have to make some new hack for that too :')

spring raptor
spring raptor
#

Another workaround is to manually control visibility.
You have direct access just like before. You associate a bit with components (or entity) and manually toggle the bit visibility via ClientVisibility

#

The VisibilityFilter is just an abstraction on top of it.

dire aurora
spring raptor
dire aurora
#

Yea, putting type ClientComponent = Self; (or the other way around, or whatever other name we pick) should be pretty easy anyway

spring raptor
dire aurora
#

Yep

spring raptor
#
GitHub

It's a bit limiting that our filters require the same component on both entities. For example, something like a SkillOwner that holds an entity doesn't work nicely as a visibility filter si...

GitHub

Allow to replicate one scope if the filter returns true and a different scope if the filter returns false. For example, you might want to replicate skill modificators to an owner, but for everyone ...

spring raptor
dire aurora
#

Knowing the entities involved could be useful, though I haven't encountered a case where I needed it yet. Might be because a lot of my visibility stuff is fairly primitive though πŸ€”

dire aurora
#

Got a couple of bugs and crashes to fix (likely due to some minor porting mistakes), but my game now compiles and mostly works without bevy_bundlication πŸ₯³

#
16 files changed, 344 insertions(+), 353 deletions(-)
```Saved a couple lines too, though it would've been more if I didn't need the hacks for my skill visibility stuff
#

BTW, I just realized something while messing with some of my marker components ... Is there any room for optimizations (not sending the data, not checking changes) for ZST components? πŸ€”

distant hazel
#

i have a habit of putting replicate_once for ZSTs which should be an at least slight optimization

spring raptor
dire aurora
#

Previously I always used the logic for skill owners, which wasn't ideal but who cares about some performance and cheat prevention while testing

spring raptor
#

(but it's a incredibly small gain)

lilac mantle
#

Hello, Is there an abstraction to send a message from one client to all other clients, (example chat messages), or am I forced to build myself a relay where it sends to the server and server sends to all

#

Also wondering if there are some existing lobby abstractions or if I have to build them myself

distant hazel
#

to my knowledge you have to relay through server, and I don't know of any "lobby" abstractions; what exactly do you want a lobby to do?

lilac mantle
#

Right now i'm wondering whats the best way to get my clients to go back to menu if host disconnects

distant hazel
#

yeah i don't think replicon comes with all that. Could make a nice third-party crate

lilac mantle
distant hazel
#

when the host leaves your ClientState should reset to ClientState::Disconnected. Then you can just go ahead and leave the lobby when OnEnter(ClientState::Disconnected) run_if(in_state(LobbyState::InLobby)), or something to that effect

spring raptor
#

@viscid jacinth about sending a despawn without despawning an entity on the server. Do you need this functionality per-client?

muted swan
#

hello!
was wondering if bevy enhanced input can be used with bevy_replicon to replicate inputs? or if there is any third party crate, or any other support?

lilac mantle
spring raptor
# muted swan hello! was wondering if bevy enhanced input can be used with bevy_replicon to re...

Hi!
https://github.com/NiseVoid/bevy_rewind has bevy_rewind_input. But it doesn't have BEI integration, it's general-purpose. It allows to send anything as buffered input.
I think the author uses it with BEI. Can you confirm, @dire aurora?

GitHub

Server-authoritative rollback networking for bevy. Contribute to NiseVoid/bevy_rewind development by creating an account on GitHub.

spring raptor
dire aurora
#

I do use it with BEI yes, I write data to a component from BEI observers, then network that using my crate

lilac mantle
spring raptor
dire aurora
#

I have put a deprecation warning on bevy_bundlication, so feel free to either remove it from the list of replicon, or move it to unmaintained

#

And I also finished up my commit for removing it from my game, after fixing the bugs I created along the way

spring raptor
#

Okay, thanks for the info! I think I'll move it to unmaintained

dire aurora
#

And since avian got a release I guess I'll update bevy_rewind now

spring raptor
#

Great!

dire aurora
#

I also encountered a new bug (that I for now just worked around in an ugly way) in bevy_rewind_input

#

Inputs are components, however #[entities] does not get handled πŸ˜…

spring raptor
dire aurora
#

Yea, shouldn't be super hard to fix, I just didn't touch it for now because it might open a whole new can of worms and I wanted to wrap the commit up first πŸ˜…

dire aurora
spring raptor
#

I think this release was one of the easiest to migrate.
I only afraid that on the next one we get all the changes that didn't get through due to holidays and sickness πŸ˜…

viscid jacinth
spring raptor
neon relic
#

Hi, I have an issue when trying to disconnect/reconnect a client when client_diagnostics feature is enabled
The issue comes from this https://github.com/simgine/bevy_replicon/blob/525d83827051c822749ce05d97529d068f7d891c/src/client/diagnostics.rs#L120

(replication_stats.entities_changed - last_replication_stats.entities_changed) as f64

This triggers an overflow sub (because Res<ClientReplicationStats> gets reset on disconnect but Local<ClientReplicationStats> sill holds previous values, I guess)
Is this something I can handle one my side or does it require a update to bevy_replicon, maybe use replication_stats.entities_changed .saturating_sub(last_replication_stats.entities_changed) instead ?

What is weird tho, is that this only happens when I build in debug (+ bevy/dynamic_linking feature), no error when building in release..

spring raptor
neon relic
#

"Yeah, Rust checks for overflow only in debug. In release it wraps." hoo, make sence then

No I clearly don't have that many entities, but from my understanding is not that entities_changed is too big.

But its that replication_stats.entities_changed (from resource) is 0 because it just got reseted by the https://github.com/simgine/bevy_replicon/blob/525d83827051c822749ce05d97529d068f7d891c/src/client.rs#L182 (OnExit(ClientState::Connected)).

But the last_replication_stats.entities_changed (from Local<ClientReplicationStats>) still have values before disconnect eg: 5 which result in 0 - 5 (on a usize)

spring raptor
spring raptor
thorn forum
#

hey ! i think im having a bug with replicated entities and relationship spawned in state transition before startup. what i do:

  • in OnEnter(GameState::Loading) (default state on the server, so runs before Startup) spawns lots of (A, Replicated).
  • still in the OnEnter schedule another system run after the first system, spawns some (B, MyRelationShipOf(some_A_entity), Replicated))

A, B, MyRelationShipOf are .replicated().

client side, A without any B relationship are fine and Replicated component on them.
but for some weird reasons, A entities that have the relationship DONT have the Replicated components, its never added. i tried On<Add, A> observer, and only the one that dont have any B linked have Replicated components.

spring raptor
neon relic
#

Hi @spring raptor its me again,
Is it possible to export your impl_filter_scope marcro (https://github.com/simgine/bevy_replicon/blob/c6daae80ff723741a59eb42159a764016b981c25/src/server/visibility.rs#L365C14-L365C31)

Or re-export your ComponentMask https://github.com/simgine/bevy_replicon/blob/c6daae80ff723741a59eb42159a764016b981c25/src/shared/replication/registry/component_mask.rs#L14 which is already pub (and make insert pub)

So we can create our custom visibility/filter scope with multiples Components

(I think you would also need to make init_component_fns pub from ReplicationRegistry)

spring raptor
neon relic
#

I would like to control the visibility of multiples components based on one other, example:

I have 2 entities with the following components:

  • Player(1), Position(1,2), Controlled, Stats { ... }
  • Player(2), Position(3,4), Controlled, Stats { ... }

I want to replicate Player & Position to all clients but I only want to replicate Controlled & Stats to the Client that is the "owner" of this player.

I currently make it works with just Controlled by adding a ControlledBy visibility filter

#[derive(Component, PartialEq, Clone)]
#[component(immutable)]
pub struct ControlledBy(pub ClientId);

impl VisibilityFilter for ControlledBy {
    type Scope = ComponentScope<Controlled>;

    fn is_visible(&self, reader: &Self) -> bool {
        reader.0 = client;
    }
}

Then I just need to add the ControlledBy component to each player entity and their respective client entity (if not the same).

Now I was guessing that a custom Scope would allow my to do something like this:

pub struct ComponentsScope<A: Component, B: Component>(PhantomData<(A, B)>);

impl<A: Component<Mutability: MutWrite<A>>, B: Component<Mutability: MutWrite<B>>> FilterScope
    for ComponentsScope<A, B>
{
    fn visibility_scope(world: &mut World, registry: &mut ReplicationRegistry) -> VisibilityScope {
        let mut mask = ComponentMask::default();
        let (index_a, _) = registry.init_component_fns::<A>(world);
        mask.insert(index_a);
        let (index_b, _) = registry.init_component_fns::<B>(world);
        mask.insert(index_b);
        VisibilityScope::Components(mask)
    }
}

#[derive(Component, PartialEq, Clone)]
#[component(immutable)]
pub struct ControlledBy(pub ClientId);

impl VisibilityFilter for ControlledBy {
    type Scope = ComponentsScope<Controlled, Stats>;

    fn is_visible(&self, reader: &Self) -> bool {
        reader.0 = client;
    }
}
spring raptor
neon relic
spring raptor
neon relic
spring raptor
neon relic
thorn forum
#

hey ! to use our own Hash with Signature component (i need components added later with entitycommands, that are not present when Signature on add hook runs), i need to use DeterministicHasher<Xxh3Default> like Signature does to support wasm ?

spring raptor
thorn forum
spring raptor
#

Or call with_salt

thorn forum
#

I guess it's the case for any tuple actually

spring raptor
viscid jacinth
thorn forum
#

hey ! i want to get my client to be able to do client - dedicated server and single player. it works currently by just not using replicon client_trigger and directly calling spawn systems, but i would have liked to simplify the code. so i would need i think to be able to at runtime on command disable or enable the bevy replicon server plugin ? client is always enabled, and server is enabled only in singleplayer, so i can use client_trigger / server_trigger in the same client ?

#

or server plugin needs to be always added, and i should instead early return in my observers if not authoritative ?

spring raptor
spring raptor
thorn forum
spring raptor
viscid jacinth
#

I just made the changes I need in the lightyear branch, I think i just made received_count pub

spring raptor
#

If it's still needed.

viscid jacinth
#

Yes i also do that in my branch

spring raptor
#

Ah, okay!
I'll wait for your PR then πŸ™‚ You can do it later if you want, once everything else is figured out.

I'll start working on replication pause.

thorn forum
#

hey Channel::Unreliable means what the messages might never arrive ? its more lightweight if everything goes well, but otherwise needs re sending if it wasn't received

thorn forum
spring raptor
#

Potentially we can try to move the events resend logic into shared πŸ€”

thorn forum
spring raptor
spring raptor
#

@viscid jacinth Realized that replication pause will also require additional handling for prediction libraries. And requires quite a careful handling when visibility system comes into play.
I'm still open implementing it, but could you explain your use case a bit more? Maybe I can come up with something more specific?

viscid jacinth
#

How can I stop sending replication updates for an entity without despawning the entity?

spring raptor
#

That's mainly why I'm asking. I'm trying to understand whether you need a fully generic replication pause/stop or just the ability to keep the entity on the client when replication stops.

viscid jacinth
#

Because if you don't continue the replication later on; it has consequences on how to do entity mapping cleanup on the receiver side?
I think just keep the entity on the client when replication stops is enough 99% of hte time

spring raptor
# viscid jacinth Because if you don't continue the replication later on; it has consequences on h...

Yes, and resuming requires careful tracking of what changed. Missing a component removal when the entity was paused is probably expected (like with despawns), but I'd probably expect insertions to be replicated on unpause πŸ€”
And with visibility, when the entity was hidden and then unpaused, the despawn should be replicated. Pausing is definitely doable, but it adds a bunch of corner cases to handle.

And then I remembered that initially you were asking about avoiding replicating despawns when the entity stops being replicated, so I decided to ask.
And just keeping an entity is actually already supported!
You just need to override this function: https://docs.rs/bevy_replicon/latest/bevy_replicon/shared/replication/registry/struct.ReplicationRegistry.html#structfield.despawn
It accepts an entity, so you can check if it contains any user-despawned component and skip the despawn. No changes required.

astral cipher
#

Does the VisibilityFilter work on the client entities themselves? (e.g. a visibility filter for client entity A that will only show replicated components of client A to ... client A)
I replicate the client entitites and there are some components I would wish to hide from other players.

spring raptor
# astral cipher Does the VisibilityFilter work on the client entities themselves? (e.g. a visibi...

Not yet. Currently you need to use the lower-level API by manually toggling the bits.

We're working on a better design for visibility filters that should unlock your use case: https://github.com/simgine/bevy_replicon/issues/642

GitHub

It's a bit limiting that our filters require the same component on both entities. For example, something like a SkillOwner that holds an entity doesn't work nicely as a visibility filter si...

wraith copper
#

@spring raptor came across your message here. for the noobs (me) - what tools are you aware of on the os-level that allow that kind of latency simulation (windows, macos.. whatever)

spring raptor
queen pendant
#

Hi, someone at work is seeing something strange in replicon. It seems as though 1 mutation of replicated type Foo<T> on the server leads to >1 runs of a system with Single<Foo<T>, Changed<Foo<T>>>. We're looking for bugs on our side, but is this a possible scenario in replicon?

queen pendant
#

We now debugged it to use the bevy feature .changed_by and on the client it shows 3 times changed in bevy_replicon-0.38.2/src/shared/replication/registry/command_fns.rs:106:49

spring raptor
queen pendant
spring raptor
queen pendant
spring raptor
#

Does it happen on mutation or insertion on the server side?

queen pendant
spring raptor
queen pendant
spring raptor
thorn forum
#

hey ! im getting some error log

ignoring message `ServerTriggerEvent<TookDamage>` that failed to deserialize: unable to map entities `[199v0]` from the server, make sure that the message references entities visible to the client

because im sending the event in the same frame as despawning the entity. is there a way to suppress this error for a specific event ?

spring raptor
#

The message will just be discarded

spring raptor
#

Ah, you probably don't know that it will be despawned when you dispatch the event πŸ€”
I can downgrade this event to a warning, but also consider somehow checking it since you send bytes that will be discarded.

thorn forum
#

thats what ive done, just checking if health == 0 but i dont like it, if the unit is revived, is healed, or whatever reason the event will not trigger.
thank you for proposing to downgrade the log level, but i dont want any warnings either in my game 🧹. is there any other solution ? i guess using a Message instead of a entity event, and mapping it manually on the client by querying the entity mapping hashmap, and silently failing if the entity doesn't exist ? but thats cumbersome.

#

i send the event at the moment the unit took damage in some observer, and its despawned later in a system that check for unit with health 0

spring raptor
thorn forum
#
  • i dont think i can re order as this event is triggered inside the observer setting the health to 0 (a took damage handler). the system despawning needs to run after to see the updated health after damages applied to despawn entities.
  • yeah i understood replicon side, not a fan too since its not really a fix.
  • replicon or user side ? this adds overhead but not much i guess.
    thanks.
spring raptor
#

Another option is to track which event stores which entities and drop them from the queue when related entities are despawned. But it will add quite some overhead.

#

I'd probably recommend to rethink the approach on your side.

thorn forum
#

actually ill just use two messages, one local and one for notifying the client

lucid coral
spring raptor
lucid coral
spring raptor
lucid coral
spring raptor
#

I planned to take a look, but got distracted and forgot πŸ˜…
I'll take a look today after work.

thorn forum
#

hey ! on the server, all messages send with ToClients<M> and SendMode::Broadcast are also send locally by send_locally ? it check for clientstate::disconnected, but on the server it always disconnected πŸ€”

spring raptor
#

Do you want to disable it?

thorn forum
#
pub fn plugin(app: &mut App) {
    app.add_mapped_server_message::<TookDamage>(Channel::Unordered)
        .add_systems(
            FixedUpdate,
            retransmit_took_damage
                .after(despawn_killed_entities)
                .run_if(is_authoritative),
        );
}

/// System that retransmits TookDamage messages after despawns.
/// Filters out messages for entities that no longer exist.
pub fn retransmit_took_damage(
    mut message_reader: MessageReader<TookDamage>,
    mut message_writer: MessageWriter<ToClients<TookDamage>>,
    mut commands: Commands,
) {
    for TookDamage(entity) in message_reader.read() {
        if commands.get_entity(*entity).is_ok() {
            message_writer.write(ToClients {
                mode: SendMode::BroadcastExcept(ClientId::Server),
                message: TookDamage(*entity),
            });
        }
    }
}
#

i just changed to BroadcastExcept(CliendId::Server), thanks :)

spring raptor
fallen vortex
#

Hi, big newbie here just playing around.

I actually don't actually know how many 'rooms' would exist at one time as players could be anywhere in the world, but one thing is they are always in 9 rooms (chunks)

Player 1

chunk1  (-1,  1)
chunk2  ( 0,  1)
chunk3  ( 1,  1)

chunk4  (-1,  0)
chunk5  ( 0,  0)
chunk6  ( 1,  0)

chunk7  (-1, -1)
chunk8  ( 0, -1)
chunk9  ( 1, -1)

Player2, Player3

chunk1  (44, 16)
chunk2  (45, 16)
chunk3  (46, 16)

chunk4  (44, 15)
chunk5  (45, 15)
chunk6  (46, 15)

chunk7  (44, 14)
chunk8  (45, 14)
chunk9  (46, 14)

Using this random example, If player 2 were to harvest a tree in any of those chunks, only player 3 would receive that update. I assume this is how it would work if I had it set up correctly, and if so is there any examples out there to help me out.

spring raptor
spring raptor
#

Speaking of filters πŸ™‚
I opened a new branch with a rework:
https://github.com/simgine/bevy_replicon/pull/659

@dire aurora it was mainly your request.
If you're interested, I'd recommend to just read the docs of the trait, don't bother looking at the diff.

GitHub

A new ClientComponent associated type allows specifying a different component for client entities. Use Self to preserve the previous behavior.
In is_visible, self now refers to the entity component...

GitHub

A server-authoritative replication crate for Bevy. - simgine/bevy_replicon

#

Once merged, I'll draft a new release.

I really need the cart's bsn branch for my game, so I'll open a draft PR targeting it for all my crates.
I just want to draft a new release with all the accumulated changes first.

spring raptor
#

Created a branch that targets the bsn branch.
All tests pass, and all examples compile.
I haven't used bsn! inside the examples yet because its syntax might still be unstable. I'd like to wait a bit.
The branch also includes long-awaited resource replication support! See the replicate_resource* methods.
https://github.com/simgine/bevy_replicon/pull/660

I ported bevy_replicon_renet as well:
https://github.com/simgine/bevy_replicon_renet/pull/74

GitHub

Targets latest Cart's branch with BSN. The PR also implements resource replication from the latest main.

dire aurora
scarlet imp
#

Resource replication will be a nice quality of life improvement, I'm looking forward to it! Does this also mean State replication should be possible? I'd love to cut some of the boilerplate needed to keep states in sync.

astral cipher
#

i'm a bit lost on the matter, but will bevy_replicon suffer significant changes with the bsn?
All i know is bsn brings better semantics to implement entity/scene graphs which I was looking forward for replicated UIs with replicon
thanks

spring raptor
thorn forum
#

hey, just wanted to say Signature component is really awesome :) using it to remap to existing entities on re connect

thorn forum
#

hello ! i think i have a case in my game where i SignatureMap doesn't get updated when a entity is despawned, dont know how/when, and so bevy_replicon panic:

The entity with ID 7v0 does not exist (enable `track_location` feature for more details)

    If you were attempting to apply a command to this entity,
    and want to handle this error gracefully, consider using `EntityCommands::queue_handled` or `queue_silenced`.
Encountered a panic in system `bevy_replicon::client::receive_replication`!
Encountered a panic in system `bevy_app::main_schedule::Main::run_main`!

is it ok to make it non panicking ? i can't find where its coming from.
its for my use case to remap entities on reconnect, and i also insert Signature component client on entities spawned by the server, it that could be that. im still on bevy_replicon 0.37.2 if something changed since.

thanks !

thorn forum
#

made this reproduction test:

fn signature_despawned_by_parent_cascade() {
    let mut server_app = App::new();
    let mut client_app = App::new();
    for app in [&mut server_app, &mut client_app] {
        app.add_plugins((
            MinimalPlugins,
            StatesPlugin,
            RepliconPlugins.set(ServerPlugin::new(PostUpdate)),
        ))
        .sync_related_entities::<ChildOf>()
        .finish();
    }

    server_app.connect_client(&mut client_app);

    let client_parent = client_app
        .world_mut()
        .spawn((Replicated, Signature::from(0u8)))
        .id();
    let client_child = client_app
        .world_mut()
        .spawn((Replicated, Signature::from(1u8), ChildOf(client_parent)))
        .id();

    let server_parent = server_app
        .world_mut()
        .spawn((Replicated, Signature::from(0u8)))
        .id();
    server_app
        .world_mut()
        .spawn((Replicated, Signature::from(1u8), ChildOf(server_parent)));

    server_app.update();
    server_app.exchange_with_client(&mut client_app);
    client_app.update();
    server_app.exchange_with_client(&mut client_app);

    assert!(client_app.world().get_entity(client_parent).is_ok());
    assert!(client_app.world().get_entity(client_child).is_ok());

    server_app.world_mut().despawn(server_parent);

    server_app.update();
    server_app.exchange_with_client(&mut client_app);
    client_app.update();

    assert!(client_app.world().get_entity(client_parent).is_err());
    assert!(client_app.world().get_entity(client_child).is_err());

    let server_parent = server_app
        .world_mut()
        .spawn((Replicated, Signature::from(0u8)))
        .id();
    server_app
        .world_mut()
        .spawn((Replicated, Signature::from(1u8), ChildOf(server_parent)));

    server_app.update();
    server_app.exchange_with_client(&mut client_app);
    client_app.update();
}

it was happening with towers and tower troops in my game.

#

im using stuff like the card/troop type, tile position and team for the signature hashing. there can be only one at a time, but maybe to workaround this problem i should make the hashing different with a counter for example ?

spring raptor
thorn forum
spring raptor
astral cipher
#

Right now my challenge is networking effects, specifically sound effects
sure I could send a Message from the server to the client of which sound to play, but I feel it is the weakest solution
anybody else had successful approaches?
i've been trying to trigger sound effects from ashared code, so both the server can play it and the client predictively play the sound, but came across desyncs, playing the effect twice and so on.

distant hazel
#

sound is surprisingly tricky to network. When you involve prediction, you often want to have a lot of control over how sounds play so you can do things like cut them out during a misprediction correction/rollback. I'd say you should make certain already networked events also cause a sound on the client side when possible. Also note that a dedicated server doesn't play sounds (since no one is listening), that's entirely a clientside issue.

spring raptor
#

Yeah, usually sound done on the client side based on some gameplay events that either predicted or replicated from the server.

spring raptor
distant hazel
#

is there a way to force replicon to send a final mutation before despawning an entity? Such that its final component values on client match the server?

spring raptor
distant hazel
#

thought so. Almost thought I had something by inserting instead, but that didn't work. Working on projectile replication/prediction and trying to make sure the authoritative projectile's final position got through so that the client can show an accurate resimulated projectile (it gets forwarded on the server based on RTT, so it might hit something in one tick for short range attacks, so I need clients to rewind the projectile visuals to be able to see it at all)

spring raptor
distant hazel
#

I would consider determinism more if there wasn't a physics engine involved but I don't want to have to deal with subtle floating point errors or whatever

#

or having to sync random seeds, etc.

#

the game will not have many characters nor many projectiles in play, so the cost of replication shouldn't be prohibitive?

#

solution ended up being "uninteresting" networkingwise, I just use bevy's new(ish) clone features to duplicate the replicated entity minus the networking parts, it has no visuals anyway, then apply visuals only to the duplicate and some extra logic to not have the duplicate be purely visual and despawn appropriately

spring raptor
spring raptor
distant hazel
#

because of two reasons:

  • on any client, projectiles from other clients need to be resimulated (pulled back to the start, then let loose again) so that they visually display correctly despite the server fast forwarding through RTT / 2 of the projectile's initial path to line it up with the owning client
  • doing this directly to the auth projectile on a listen server (which is technically a client) would defeat the purpose of forwarding in the first place, so there has to be a non-functional visual projectile as well as the functional but hidden projectile
spring raptor
distant hazel
#

that could work πŸ€”

spring raptor
#

Both approaches are functional, but markers could make it more convenient.

spring raptor
#

Just updated the docs to also mention despawns override in the quick start guide. Useful together with markers.

civic glacier
#

https://github.com/simgine/bevy_replicon/issues/315

Resources will become entities soon: bevyengine/bevy#17485
Our current implementation will just start working for resources as well. For now, I would suggest using singleton entities as a temporary workaround πŸ™‚
The linked issue is closed, is the plan still long term for resources to be represented as an entity or is this now something that is worth doing?

spring raptor
sinful reef
spring raptor
#

It's a draft for the next Bevy release

#

I wanted to try BSN and check how resource replication would work.

vital mist
#

Whats gonna be on next release?

#

Finally the editor? XD

spring raptor
#

I didn't track all changes, but I'm excited about resources and BSN

spring raptor
vital mist
astral cipher
#

I think my biggest gripe with BSN is that components are always 100% required
meanwhile in my implementation different components are added for a networked entity depending if its on the server or the client

so i could not do something like

bsn! {
  Tag("Car")
  Health # server side component
  WheelAnimation # client side component
}

im interest to see how I could get over this problem using replicon

spring raptor
astral cipher
#

honestly I'm still pretty unsure about it. I am planning to release my source code in a few weeks with possibly a solution for this head scratcher

spring raptor
#

My branch also uses an outdated branch. There is a new PR out.

untold hull
#

Are there any other examples of quinnet_replicon? I'm having trouble following along the boids / Tic tac toe examples

spring raptor
edgy burrow
#

I have a message which functions as both a client to server and server to client message. It is registered something like this,

    app.add_client_message::<MyMessage>(Channel::Ordered);
    app.add_server_message::<MyMessage>(Channel::Ordered);```
 When the client writes the message, it is never received on the server. Is it possible to have a message which is both or is the second registration overriding the previous? I try to pick up the message on the server with something like this: 
```    mut from_clients: MessageReader<FromClient<M>>,
    mut to_clients: MessageWriter<ToClients<M>>,```
spring raptor
sand radish
#

I'm switching to replicon from lightyear and I was wondering if there's something similar to lightyear's leafwing integration for input handling, or if I have to send and handle my Actionlike's via client to server messages manually? (authoritative headless server setup)

spring raptor
# sand radish I'm switching to replicon from lightyear and I was wondering if there's somethin...

We don't provide a built-in integration for it. But I'd do it like this:

  • Spawn contexts on both sides independently and use Signature to uniquely identify each context. The user will need to use game-specific components to calculate the hash, such as a player number.
  • When sending input, send context hash and index of the action in Actions<C> (since indices are small numbers, they'll take only 1 byte with varint encoding!).
  • Sending should be done redundantly: you send all inputs since the last tick confirmed by the server.

It would be really nice to have a crate for it πŸ™‚

sand radish
#

thanks, another issue I'm having is children entities. I noticed that when the server replicates the parent, it seems client doesn't get the children (I see the entity itself query ok on the client, but the children optionals are empty). I've read

Some components depend on each other. For example, ChildOf and Children. You can enable replication only for ChildOf and Children will be updated automatically on insertion. This will emit a B0004 warning which can be safely ignored. See #19776 for more details.```
But I'm a bit confused by the wording here. Does this imply I need to register `ChildOf` for replication?
spring raptor
#

And just ignore the warning. It will be fixed with 0.19

sand radish
#

hmm, thing is tho it doesn't seem to work, the children still come up empty on the client. I'm trying to see if it's something else I'm missing.

spring raptor
#

Children entities should have Replicate, just like their parents.

sand radish
#

you mean components?

spring raptor
#

Replicate component should be present on parent and children

sand radish
#

what I do is server gets client connect (works) -> spawns a ship entity (works) -> adds physical mount points for guns on ship entity as children (works, serverside) -> replicates ship to client (works, but it seems the ship has no children for some reason)
my replication setup on both sides looks like:

            // core
            app.replicate::<Transform>();
            app.replicate::<ChildOf>();
            // base game
            app.replicate::<Ship>();
            app.replicate::<Faction>();
            app.replicate::<Weapon>();
            app.replicate::<ShipMounts>();
            app.replicate::<Shot>();
            ...

So I'm a bit baffled why I get the Ship but the Option<Children> is empty even tho I see in server logs that server clearly added the weapons and the "shipmounts" flag in (that one also seems to be on the client)

#

the way my whole system is setup is "visuals are added on" systems (and audio too). so that server can handle physics but has no visual/audio dependencies

spring raptor
#

If inside observers, you'll likely to get 1 frame delay if I remember correctly.

#

Maybe not a frame delay, but some delay

sand radish
#
pub fn init_ship_visuals(
    mut commands: Commands,
    preload: Res<VisualPreload>,
    ships: Query<
        (Entity, &Ship, Option<&Children>, Option<&Player>),
        (With<ShipMounts>, Without<ShipVisuals>),
    >,
    weapons: Query<(Entity, &Weapon)>,
) {
    for (e, ship, subsystems, player) in ships.iter() {
        log::info!("init ship visuals");
        {
            // ensure ship has Visibility before we add children
            let mut ship_entity = commands.entity(e);
            ship_entity.insert(ShipVisuals);
        }
        // add sprites to weapons in mounts
        if let Some(subsystems) = subsystems {
            log::info!("init subsystem visuals"); // this never fires, no children
spring raptor
sand radish
#

ShipMounts seems to be in on the client side coz I see init ship visuals logged as well as the ship visual itself

#

FixedUpdate

#

coz I don't know when this will get replicated in

spring raptor
#

This makes sense. And Replicon will send all insertions together.
So I'm not sure what's happening. Try logging the entities that are supposed to be subsystems.

sand radish
#

oh hmm

#

I wonder if it's server doing thigns in 2 frames

#

oh wait no, coz ShipMounts only gets added once the weapon is in

#

just to clarify the logic is "spawn" -> Ship gets inserted. then another system (server side here) will pick up Ship without ShipMounts and put in the weapons as children and ShipMounts as "done with that" flag

#

and then on client it's supposed to pick those ships with ShipMounts and the weapon subsystem Children and spawn the visuals and mark with ShipVisuals

spring raptor
#

If you insert your mounts later.

sand radish
#

but I check for ShipMounts in that visual system, which gets added this way

pub fn arm_mountpoints(
    mut commands: Commands,
    ships: Query<(Entity, &Ship, &Faction), Without<ShipMounts>>,
) {
    for (e, ship, &faction) in ships.iter() {
        commands.entity(e).insert(ShipMounts);

        for mp in ship.class.mount_points() {
            let mut weapon = commands.spawn((
                faction,
                Weapon::light_plasma(),
                Transform::from_translation(mp.extend(10.0)),
            ));
            weapon.insert(WeaponState::default());
            let weapon = weapon.id();
            commands.entity(e).add_child(weapon);
        }
    }
}
spring raptor
sand radish
#

which is fine tho no?

#

coz I only query for Ship with ShipMounts and those should only be there if the Weapon children are done

spring raptor
#

Not sure If I get this πŸ€”
Yourr mounts are children, right? And your issue is that you don't have them on the client.

sand radish
#

ok so ShipMounts is not a child, it's a component that gets added to the Ship's entity, once the Weapon children are added (see above)

#

and then I use that component as a flag to query for ships that need visuals added

#
        (Entity, &Ship, Option<&Children>, Option<&Player>),
        (With<ShipMounts>, Without<ShipVisuals>),
    >,```
#

so this ^ query shouldn't pick any "ships that don't have weapons added yet"

#

so what I'm seeing is that somehow client gets the ShipMounts replicated, but has no children

spring raptor
#

First thing I'd try - log entities that are supposed to be children.

sand radish
#

is app.replicate::<ChildOf>(); all that's required for children to work?

spring raptor
#

No, you also need to add Replicated.

sand radish
#

I mean apart from the obvious Weapon being set too

spring raptor
#

To all children

#

If entity has Replicated and ChildOf, it will be replicated as a child.

sand radish
#

ah so all component spawns that are children need Replicated when spawning on server?

spring raptor
#

Yep

sand radish
#

aaah ok that explains it then

spring raptor
#

Just like any other replicated entity

#

Relations aren't special, they work just like any other components.

sand radish
#

yeah that was it, sorry for the long winded explanation πŸ˜„

#

I assumed Replicated parents would get all registered children replicated without explicit flagging

spring raptor
#

Maybe worth mentioning in the docs πŸ€”
I'm not a native speaker, but I tried my best to explain. If you want to help to improve the wording - a PR would be welcome.

sand radish
#

hmm actually let me bump it with clearer list including the ChildOf thing

spring raptor
sand radish
#

well that's 3. Add Replicated component to both child and parent entities. but I can make that into 2 steps I guess

#

done

spring raptor
# sand radish done

Left a suggestion with a shorter version. Let me know if this is still clear πŸ™‚

sand radish
#

sg, applied πŸ™‚

sand radish
#

I got my game working fully with bevy_replicon (YAY!) and it works smoothly so that's great! I have a few warnings to figure out though, one of them is:

2026-03-31T00:51:02.144441Z  WARN bevy_ecs::hierarchy: warning[B0004]: Entity 81v0 with the GlobalTransform component has a parent (82v0 entity) without GlobalTransform.
This will cause inconsistent behaviors! See: https://bevy.org/learn/errors/b0004

This seems to come from the weapons that we discussed that are added to the ship "mounts" as children. Transform is a required component for them, and I thought GlobalTransform would just be added client side on its own? Is there something I need to do here?

astral cipher
sand radish
#

I'm getting ERROR renetcode::client: Failed to update client: disconnected: server denied connection on trying to connect a second client, my client_id is just set to current timestamp u64 (millis) in this case and is not launched immediately so it shouldn't conflict. Is there something else that'd cause this?

#

the 1st one works fine

#

reconnects also work as long as it's 1 at a time

#

oh doh nvm. I forgot i just copy pastad the max_clients: 1 from example πŸ˜„

sand radish
#

how can I access the client's user_data or client_id (the one set on the client, not the entity on the server) when a client connects to the server?

astral cipher
spring raptor
spring raptor
spring raptor
astral cipher
spring raptor
astral cipher
spring raptor
astral cipher
# spring raptor Weird, I wrote a lot of different tests for them. Let me know if you reproduce.

I will try to reproduce it now, but I've not approached it yet, assuming it could be a possible desync from component lifetime observers and the fact it happens for other clients.
but a few details:

  • given human & item replicated entities
    item is inserted with Contained entity, which is a relationship with human as target
    contained also automatically inserts ChildOf to human (maintains)
  • other client joins in
    human has no replicated component, but the contained item does. (but this is just a symptom not a cause)
spring raptor
astral cipher
spring raptor
sand radish
#

What I was aiming for is a sort of "client client_id"

#

so that I can on the client know that this is meant for me πŸ˜„

#

what I was expecting was that I can get something from the master server and put it in the authentication as user_data and then use that as the "this is for client x" flag

#

e.g. in my case I use it to assign controls to the right entity when it gets replicated on each individual client

#

I just did it via messaging unsecure for now

spring raptor
sand radish
# spring raptor On the client or on the server?

So the intent is to have an id that identifies the client on the server such that if I send a msg or replicate an entity to the client i can flag things with that id and the client knows "this is for me specifically"

#

e.g. I replicate a Ship with ControlledBy(client_id) and then the client that has a matching client_id of some sort on its end will know to assign controls to that ship

astral cipher
sand radish
#

so not "exclusive" replication or sending only to that client, just assigning ownership in a way

spring raptor
astral cipher
#

i might be using the test code wrong tho.

sand radish
astral cipher
spring raptor
sand radish
#

my plan is to have a master server that will generate the Auth token and give it to the client. I was hoping I can put the "client id" in the auth token, and then the client would know it right off, and the server would see it as clients connect too so no need to ping-pong a unified client_id

astral cipher
sand radish
#

yes, hence my question of, can I get the user_data? πŸ˜„

#

there's a user_data field inside the auth

#

if I can access that on the server side, it solves this nicely

#

e.g.

    let authentication = ClientAuthentication::Unsecure {
        client_id,
        protocol_id: net::SHARED_SETTINGS.protocol_id,
        server_addr: addr.0,
        user_data: None, // access this on server when client connection is added
    };
astral cipher
spring raptor
astral cipher
#

just saw it, out of curiosity, what was happening underneath?

spring raptor
astral cipher
spring raptor
astral cipher
#

also, since we are at it...
could I propose two API changes?

spring raptor
astral cipher
#

sure, I can write more developed issue tomorrow, I just wanted to lay out a sort of draft here

#

it's specifically regarding these two:

  • Server Player Entity (I am sure you already tried this before, I think I've seen it, but you must've opted for the current method, but I would like to suggest it again)
  • Reforming FromClient
distant hazel
#

Is there a way to decide between replicate_once and replicate per entity with a filter component? Or any other way? For things like when every entity needs a component initialized on them but only a few actually need it updated.

I think there's a workaround with a component that gets replicate_once'd and replaces itself or something but its seems a little hacky and complicated.

#

ah wait I think I figured it out.

If an entity matches multiple rules, the functions from the rule with higher priority will take precedence for overlapping components. For example, a rule for Health and Player marker will take precedence over a rule for Health alone.
Think this will work, just make one rule for replicate_once and one for on_change

#

example for elaboration/anyone searching for this later

.replicate_once::<Transform>()
.replicate_with::<_>((
    RuleFns::<ReplicateTransform>::default(),
    (RuleFns::<Transform>::default(), ReplicationMode::OnChange),
))
spring raptor
distant hazel
spring raptor
#

Filters counts as components. So Transform and your marker rule has priority equal to 2.

distant hazel
#

oh that actually works... neat. I couldn't really tell from trying to look at the code because there's so much calling into another function with slightly tweaked parameters lol

spring raptor
distant hazel
#

ah i see

spring raptor
#

*sugar for replite_with_filtered.

replicate_with is replite_with_filtered with no filters πŸ˜…

astral cipher
#

few questions

  1. is there an order of which networked messages are applied? e.g. update components -> events -> messages?
  2. is there any difference between placing sync_related_entities() in shared or server code?
  3. do visibility filters update when ClientComponent is added/removed? I wrote a test for it and it seems to be failing
    thank you
spring raptor
astral cipher
#

Perhaps in the add_visibility_filter() we add a new observer for changing ClientComponent values?

spring raptor
astral cipher
#

I think I can draft a PR for this soon as it's more urgent for me

#

im glad to help

#

I feel like I'm prodding you too much with small changes ahaha

spring raptor
spring raptor
dire aurora
#

At least someone is asking for small changes for once, instead of me and my major feature requests 🀭

astral cipher
#

I have posted a draft PR.

astral cipher
#

saw it merged, cool
I am close to releasing the source code of my game, hopefully it'll bring more insights on how replicon is used aswell.

spring raptor
spring raptor
#

@dire aurora remember I borrowed your implementation for batched insertions from rewind? Turns out it's UB πŸ˜…
You're trying to align pointers relative to data in your Vec here:
https://github.com/NiseVoid/bevy_rewind/blob/17a47b618e063862a6235c7a0ac84d8f9e6b42e5/crates/bevy_rewind/src/history/batch.rs#L43-L48
But the actual pointer address to the Vec's data starts at the pointer to its allocation. And even if you try to align relative to it, any Vec reallocation can break the alignment again.
Later you pass pointers to Bevy as aligned (the API requires this, Aligned is the default param), while they most likely aren't:
https://github.com/NiseVoid/bevy_rewind/blob/main/crates/bevy_rewind/src/history/batch.rs#L72-L79
Which triggers UB, Miri catched it.

All modern CPUs support unaligned access, but compiler optimizations could break it.

Here is how I fixed it:
https://github.com/simgine/bevy_replicon/commit/ef10ad7ad505e61197c568fb6dada81b3319e2b4
It's not only simpler, but also 3–8% faster since the data is now actually aligned. Crazy stuff!

#

@viscid jacinth I also checked how it's done in Lightyear, and you have the same problem. You're writing data into a Vec in this function:
https://github.com/cBournhonesque/lightyear/blob/957b302d03ae7566b18e481feb901923980bcb59/lightyear_replication/src/registry/buffered.rs#L131
And later treat all pointers to it as aligned here:
https://github.com/cBournhonesque/lightyear/blob/957b302d03ae7566b18e481feb901923980bcb59/lightyear_replication/src/registry/buffered.rs#L112
But it probably doesn't matter since you're planning to migrate to Replicon.

vital mist
#

You guys gonna make lightyear and replicon together? @spring raptor

sinful reef
#

lightyear is gonna use replicon iirc

spring raptor
#

Yes, that's the plan. We'll provide replication and Lightyear higher level abstractions.

dire aurora
#

I'll see if I can apply your fix to rewind too

spring raptor
dire aurora
#

I had it fail before adding the alignment logic at least

#

And iirc niri always injects randomness into such things to make sure it fails in a couple of tries

ruby bloom
#

Hey gaymers,
I've just started with Bevy, and I'm not super familiar with Rust, so hopefully I don't look like too much of an idiot.

I'm using bevy_replicon with the bevy_replicon_renet messaging backend.
I've been experimenting with the examples in the bevy_replicon_renet repository for a few days now, and I've got something to work, but I'm not sure if it's implemented very well.
My code is currently based on the authoritative_rts.rs example, and it works fine, but I would like some tips on how I should be structuring my project.

I need a dedicated server binary for my game, so I've created & separated ClientPlugin, ServerPlugin and SharedPlugin into their own crates.
I would prefer that the game specific logic is not inside each of these plugins, but rather in feature plugins.
For example for chunk management I'd have a ChunkManagementPlugin, but that would have implementation details for Client, Server and Shared.

  • Would I need to separate it into server/client/shared ChunkManagementPlugins, or should I be using ClientState and the like to check which observers, systems and resources I should be loading?
  • Does this bloat the binary?
  • Would using feature flags to build a server binary be a better approach than separate crates for my use case?
  • Should I use separate client/server crates, plugins, and feature flags all at the same time?

Also, I'm really not sure if this is the right way to set up the client and server;
At the moment this is what I'm doing:

| Game mode     | ClientPlugin setup   | ServerPlugin setup   |
|---------------|----------------------|----------------------|
| client        | networking, entities | panic!               |
| server        | panic!               | networking, entities |
| singleplayer  | entities             | entities             |
| listen server | entities             | networking, entities |

If anyone could tell me how much I suck and everything that I'm doing wrong, that would be greatly appreciated.

#

For an idea of what I'm doing, here is my ClientPlugin:

spring raptor
# ruby bloom Hey gaymers, I've just started with Bevy, and I'm not super familiar with Rust, ...

From the table, looks like you actually need 2 compile-time configurations: full game and dedicated server.
In full game you can everything: singleplayer, connect to a server or host (I don't think it makes sense to have a separate "only client app" or "only singleplayer app").
In dedicated server you only run server logic.

So I'd probably won't separate anything plugin-wise. It's just easier to read the code when everything is in one place. And for dedicated server I'd go with cfg for server-specific things.

ruby bloom
#

I don't think it makes sense to have a separate "only client app" or "only singleplayer app"
huh yeah that makes sense actually
i think i was originally thinking that i would have a separate launcher to run the correct binary based on what the user wanted to launch, but that wouldn't make much sense since you would have 3 separate binaries doing effectively the same thing

#

what do you mean by going with cfg?

#

for the compile time configurations, i obviously want to minimize the dependencies of the dedicated server. should i use feature flags to avoid compiling client logic conditionally?

#

like a features = ["client", "server"] builds the full game, but features = ["server"] builds the dedicated server? (maybe this is excessive feature flags since i always want to build server?)

ruby bloom
#

yeah i think i'll give that a go

#

time for another refactor :D

#

i think i'll get rid of the client and server crates and have it all in client and server module directories instead, which will hopefully clean up the public api a bit heh

#

rust lang best lang

spring raptor
ruby bloom
#

yeah, i was thinking features = [ "client" ] and just always compile server features

spring raptor
#

Yep, that's what I suggesting

#

Maybe client is a better name.

ruby bloom
#

i'm pretty sure that i can get this in a workable state, thanks so much

untold hull
#

Dumb question homies--
When I last worked on my project, I had a function that spawned clients after a connection event, on the clients application.

fn spawnclients(
trigger: On<Add, ConnectedClient>,
... 

But haven't managed to get this working on newer versions of bevy or replicon. Is this due to changes with triggers / observers, or a change in replicon?

spring raptor
astral cipher
#

wanted to see poeple's opinion on this:
VisibilityFilter should not be feature gated by the server feature.
given shared and server code are in seperate crates, with server enabling replicon's server feature, components in shared cannot impl VisibilityFilter due to rust's orphan rule.
But this would be a bit contradictory due to visibility being overall a server only concern

spring raptor
astral cipher
spring raptor
astral cipher
#

posted a draft PR.

spring raptor
#

Going to sleep rn, will merge it tomorrow (I requested one last change) πŸ™‚

spring raptor
#

Merged. I'm planning to draft a new release with accumulated breaking changes once Bevy RC is out.
I'll do 2 releases:

  1. Targets 0.18 with all the breakages.
  2. Pure 0.19 RC update.
astral cipher
#

I really appreciate a new version purely just for the bevy version upgrade

spring raptor
viscid jacinth
#

In lightyear I was adding some special components first (Predicted, Interpolated) which would affect how components get replicated.

In replicon I set Predicted as a marker component but my custom marker write functions don't trigger on the initial replication since Predicted and Position are both part of the message

#

Any idea on how to solve this?

#

You might say to make Predicted purely a client component that is not replicated, but then I would still have the issue of: how can I add the marker on a replicated entity before the replicated components are added?

#

Maybe I could use set_receive_fns and check if the marker component is present in the components to be inserted in the DeferredEntity? (I would need a public method to access that)

spring raptor
# viscid jacinth You might say to make Predicted purely a client component that is not replicated...

Don't you need to write the first values as is, without any history management? πŸ€”
And once Predicted/Interpolated are inserted, you treat the current value as the first one in the history.

It's also possible to spawn an entity on the client with a matching Signature and Predicted/Interpolated.
I don't think it’s good to require client spawning for this, but I think the first suggestion above should work. Please, let me know what you think.

astral cipher
#

few questions before I try visibility rules further:

  1. is an entity visible when any or all FilterBits are true?
  2. (i havent tested this) when an entity becomes non visible in the client, does the entity despawn or does it act like a normal client disconnect (nothing happens)?
viscid jacinth
spring raptor
spring raptor
viscid jacinth
#

No i am receiving this entity for the first time, and I want to immediately add the received components to the history since this entity will be Predicted.

#

What you're saying is that after the entity is replicated, I could add Predicted on the client and use ConfirmTicks to find the remote tick for these components and put them in the history? Yes that could work too

spring raptor
viscid jacinth
#

Yea I added the OnAdd observer today after noticing that the marker was not triggering on the initial replication. That works for me; the marker thing is already very convenient!

untold hull
#

Been trying to port over some older code, and I find no matter what I do, I can't get the protocol hash to match.
Any replication / message at all is giving two different hash values on the client / server, any idea what might cause this?

untold hull
#

Seems like the problem I was having with Quinnet, just now on renet. I know the replication rules & order can affect the hash, but is there anything else I could be messing up to cause a mismatch

spring raptor
untold hull
# spring raptor You need to log only `shared::protocol`. Filter the messages by this and compare...

```2026-04-25T19:22:15.123835Z DEBUG bevy_replicon::shared::protocol: adding client event ProtocolHash
2026-04-25T19:22:15.123926Z DEBUG bevy_replicon::shared::protocol: adding server event ProtocolMismatch
2026-04-25T19:22:15.123968Z DEBUG bevy_replicon::shared::protocol: making event ProtocolMismatch independent
2026-04-25T19:22:15.124514Z DEBUG bevy_replicon::shared::protocol: adding server message MakeLocal
2026-04-25T19:22:15.138272Z DEBUG bevy_replicon::shared::protocol: calculated hash: 14397123909873343244

2026-04-25T19:22:21.092999Z DEBUG bevy_replicon::shared::protocol: adding client event ProtocolHash
2026-04-25T19:22:21.093105Z DEBUG bevy_replicon::shared::protocol: adding server event ProtocolMismatch
2026-04-25T19:22:21.093149Z DEBUG bevy_replicon::shared::protocol: making event ProtocolMismatch independent
2026-04-25T19:22:21.093815Z DEBUG bevy_replicon::shared::protocol: adding server message MakeLocal
2026-04-25T19:22:21.108571Z DEBUG bevy_replicon::shared::protocol: calculated hash: 899627540550343768

spring raptor
untold hull
#

It's quite unusual, with no replicon messages / replication events the hashes match. I assumed I set the server / client up wrong, but if that were the case the hashes shouldn't match in the first place.

spring raptor
#

Also the type definition should also be the same. I.e. your MakeLocal should be defined in a shared crate.

wraith copper
#

@spring raptor i am still on 0.39.2 is this following panic already fixed in newer releases?

thread 'Compute Task Pool (0)' (910073) panicked at /Users/stephan/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/bevy_replicon-0.39.2/src/server.rs:358:25:
messages from client `1426v1` should have been removed on disconnect
stack backtrace:
   0: __rustc::rust_begin_unwind
             at /rustc/fcd630976c460c819c4bbcaf107d0c94501205d8/library/std/src/panicking.rs:689:5
   1: core::panicking::panic_fmt
             at /rustc/fcd630976c460c819c4bbcaf107d0c94501205d8/library/core/src/panicking.rs:80:14
   2: bevy_replicon::server::receive_acks::{closure#0}
             at /Users/stephan/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/bevy_replicon-0.39.2/src/server.rs:358:25
   3: <core::result::Result<bevy_ecs::change_detection::params::Mut<bevy_replicon::shared::replication::client_ticks::ClientTicks>, bevy_ecs::query::error::QueryEntityError>>::unwrap_or_else::<bevy_replicon::server::receive_acks::{closure#0}>
             at /Users/stephan/.rustup/toolchains/nightly-2026-01-02-aarch64-apple-darwin/lib/rustlib/src/rust/library/core/src/result.rs:1622:23
   4: bevy_replicon::server::receive_acks
             at /Users/stephan/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/bevy_replicon-0.39.2/src/server.rs:357:61
   5: <bevy_replicon::server::receive_acks as core::ops::function::FnMut<(bevy_ecs::change_detection::params::ResMut<bevy_replicon::shared::backend::server_messages::ServerMessages>, bevy_ecs::change_detection::params::ResMut<bevy_replicon::server::client_pools::ClientPools>, bevy_ecs::system::query::Query<&mut bevy_replicon::shared::replication::client_ticks::ClientTicks>)>>::call_mut
             at /Users/stephan/.rustup/toolchains/nightly-2026-01-02-aarch64-apple-darwin/lib/rustlib/src/rust/library/core/src/ops/function.rs:166:5
   6: <&mut bevy_replicon::server::receive_acks as core::ops::function::FnMut<(bevy_ecs::change_detection::params::ResMut<bevy_replicon::shared::backend::server_messages::ServerMessages>, bevy_ecs::change_detection::params::ResMut<bevy_replicon::server::client_pools::ClientPools>, bevy_ecs::system::query::Query<&mut bevy_replicon::shared::replication::client_ticks::ClientTicks>)>>::call_mut
             at /Users/stephan/.rustup/toolchains/nightly-2026-01-02-aarch64-apple-darwin/lib/rustlib/src/rust/library/core/src/ops/function.rs:298:21
   7: <_ as bevy_ecs::system::function_system::SystemParamFunction<fn(_, _, _) -> _>>::run::call_inner::<(), bevy_ecs::change_detection::params::ResMut<bevy_replicon::shared::backend::server_messages::ServerMessages>, bevy_ecs::change_detection::params::ResMut<bevy_replicon::server::client_pools::ClientPools>, bevy_ecs::system::query::Query<&mut bevy_replicon::shared::replication::client_ticks::ClientTicks>, &mut bevy_replicon::server::receive_acks>
             at /Users/stephan/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/bevy_ecs-0.18.1/src/system/function_system.rs:908:21
   8: <bevy_replicon::server::receive_acks as bevy_ecs::system::function_system::SystemParamFunction<fn(bevy_ecs::change_detection::params::ResMut<bevy_replicon::shared::backend::server_messages::ServerMessages>, bevy_ecs::change_detection::params::ResMut<bevy_replicon::server::client_pools::ClientPools>, bevy_ecs::system::query::Query<&mut bevy_replicon::shared::replication::client_ticks::ClientTicks>)>>::run

...
spring raptor
untold hull
wraith copper
spring raptor
wraith copper
#

sorry

spring raptor
wraith copper
#

sry

spring raptor
# wraith copper a remote client rage quitting their game is enough

Let me take a look. Looks like the backend didn't clean messages. It's bevy_replicon_renet?
I use panics only for things that should never happen and impossible to recover. While this shouldn't happen, it's definitely a recoverable thing, so I'll switch to logging and try to fix the bug in the backend πŸ€”

wraith copper
spring raptor
#

Working on it

spring raptor
#

@wraith copper drafted a patch release

untold hull
wraith copper
spring raptor
untold hull
#

Can send you what I've got if you'd like, but I'll probably just ditch protocol matching if I can still get functionality without

spring raptor
# untold hull

This will trigger the problem because ReplicatedBool is not shared across 2 app.
Despite they look identical, for rust it's 2 different types, which will cause the hash to differ.

untold hull
#

Ah, I still had the error when I had Replicatedbool in Protocol.rs, I just didn't wanna send three files.

#
pub struct ReplicatedBool(bool);

in newfile.rs

use protocol::ReplicatedBool;```
in both of the files, would this still cause the mismatch?
spring raptor
torpid lance
#

Hello! is there ability to make visibility filter like blacklist using bevy_replicon?

spring raptor
#

You can also manually control what is visible.

pulsar garnet
#

For a scenario of only replicating entities that are within some distance of each client

spring raptor
torpid lance
#

Then, there's no way to make or filters?

#

I had a brilliant opportunity to separate my filter in this way

spring raptor
spring raptor
torpid lance
#

Hm okay, thank you

pulsar garnet
# spring raptor Filters are per-client. You insert a component on the client and on the entity.

oh, i kept reading AppVisibilityExt as AppRuleExt lol, docs blindness

I think it would have helped me if there was a section in the root crate doc thing that was about replication visibility and included all of the factors. like

For component Foo to be replicated:

  • Client is connected
  • Client entity on server has AuthorizedClient (added by default)
  • Game entity has Replicated component
  • Foo is registered for replication via app.replicate::<Foo>();
  • If Foo is registered with replicate_filtered the rules must pass
  • Any remote visibility filters registered via add_visibility_filter must be on the Client entity and must pass
  • Any manual bits set on ClientVisibility on the Client entity must be enabled
  • Allowed by Prioritization

Or that was use-case based. Like

  • Do you want to enable replication for a server entity? Add Replicated component
  • Do you want to replicate entities to only some clients? use app.add_visibility_filter with Scope=Entity
  • Do you want to replicate a component only if the entity also has another component? use app.replicate_filtered

There is a lot of moving parts of replicon that is hard to grasp even re-reading the docs multiple times. Maybe I'll try make a diagram or something to help me understand better

Aside, but did I miss any other ways of doing filtering in my list above?

spring raptor
spring raptor
#

On second thought, this will require some careful wording. For example, Foo should match a replication rule. Not sure if makes sense to duplicate information about each replicate_*. After 0.19 we'll get variants for resources for these methods.
Prioritization actually affects only mutations. So I don't think it makes a lot of sense to include it.

#

Filtering is something that is needed only if you use it. If no filters are present - everything is replicated.

#

And in the docs I explicitly mentioned that filters work as logical and

#

So I'm open to restructuring, but this requires careful adjustments. Maybe not in the form of a list πŸ€”

spring raptor
#

@astral cipher You were interested in this ^

astral cipher
#

oh cool didnt know this popped up, ill take a look

astral cipher
#

I like it, specially it hitting before 0.19, i thank you two.
when I have time to get back to my project I will try it out

spring raptor
#

Great, I'll draft a new release tomorrow (rn it's late night for me)

pulsar garnet
#

I'm a bit confused, so client or server can send a broadcast message, and all clients and server receive it?

astral cipher
pulsar garnet
astral cipher
pulsar garnet
spring raptor
spring raptor
#

@astral cipher I think it will be less confusing if we rename SendMode::Broadcast into SendMode::All πŸ€”

astral cipher
#

Alternatively you can call Broadcast either Raised Relay or Signal or Undirected

#

few names that came to my mind

spring raptor
#

Let's hold the release until we figure out the naming. It would be annoying to introduce a feature and rename everything related to it in the next release.

astral cipher
crude prairie
#

And here a real use of it for lights, that not only correctly allow to render lights, but also prevent extra bandwidth and hacking that will be allowed if therre was just bigger range of PVS entities replication

astral cipher
#

pretty cool -- bit of a tangent tho, do you also replicate the opaqueness of walls not in view?

astral cipher
#

also, after 0.19 I think there are some things I would like try to improve:

  • visibility rules not working on replicated client entities (correct me if im wrong)
  • allow adding replication rules + events/messages other than with App. e.g. wanting to replicate components declared at runtime
spring raptor
# astral cipher also, after 0.19 I think there are some things I would like try to improve: - v...

About the first one - yep, but I'm not sure how we can allow this. Filters check component on client entity and player entities. But any ideas will be welcome. Preferably as an issue first, so we can discuss.
You can also toggle visibility manually for specific entities, which could be done for client entities (if you mark them for replication).

About the second one - also not sure how, protocols should match on both client and server.

But sure, I welcome any improvements.

astral cipher
# spring raptor About the first one - yep, but I'm not sure how we can allow this. Filters check...

Filters check component on client entity and player entities
just to be clear, what is the difference between a client entity and player entity here?
If you mean when checking if it is visible via VisibilityFilter, both are passed as reference, so it should be fine, right?
About the second one - also not sure how, protocols should match on both client and server.
Is imposing a pinky promise that the user will not alter the protocol when RepliconChannels are being used too much?

spring raptor
# astral cipher > Filters check component on client entity and player entities just to be clear,...

just to be clear, what is the difference between a client entity and player entity here?
Client entities has client components that is used to filter and decide what to compare with.
The whole idea of visibility filters is to insert a component on player entity and client entity which will evaluate wheter the player entity is visible to a client entity.
Not sure how player and cliententity could be the same thing.

Is imposing a pinky promise that the user will not alter the protocol when RepliconChannels are being used too much?
I'm not sure what you mean. Protocol should match exactly, otherwise replication won't work. You can't add new events on the server, because the same thing should be done on the client and in the exact same order.

astral cipher
#

Not sure how player and cliententity could be the same thing.
I see what you mean, I thought you were calling a client entity also a player entity interchangeably. I will try to examine it further, but I think it is an inconsistency how client entities cannot have visibility rules applied to them as well. I think visibility filters might have value for replicated client entities here, e.g. secret components (like IP) for a given client should be exposed for admins only
Hopefully this does not bring a change that requires another big change to the visibility system.
Protocol should match exactly, otherwise replication won't work.
I agree with you 100%. What I imagine is both the server and client loading mods that register components at runtime during app.run(), and being able to add the exact same messages on the exact same order. This would occur before any connection -- and never during one
In case there is a protocol mismatch, the connection should fail, right?

spring raptor
# astral cipher > Not sure how player and cliententity could be the same thing. I see what you m...

Yes, you can replicate client entities to clients, it's just visibility filters expect comparison against client entities which determined by components on them.
I'm open to experiments with the API, so feel free to suggest alternatives. You can even write your custom visibility system inside your crate since these scoped filters built on top of the public low-level API. This way you can iterate quicker.

Yes, if you do this before connection in deterministic order - it won't break.
But I was imagining that mods just access App during plugin building and register the necessary things.
For example, you have a bunch of scripts and you expect them to have something like setup(app: &mut App) - during the app initialization you load the scripts and simply call this function. The scripting solution I'm currently working on will support this.
But I see what you mean, sometimes it might be convenient to do this at runtime πŸ€” Like you go into some mods menu and toggle a bunch of scripts... We should support this, I agree with you.
But we need to come up with some clever ID generation to avoid relying on the registration order.

astral cipher
viscid jacinth
#

Is it possible to replicate some components less frequently? I have some components 'Score' that can be replicated less frequently. They are on an entity that is otherwise replicated frequently

spring raptor
# viscid jacinth Is it possible to replicate some components less frequently? I have some compone...

We had it, but at some point I realized that it wasn't implemented properly 😒 I want all my features to be 100% working without bugs.
Right now you can do this only per-entity. But I want to bring the per-component tick rate back: https://github.com/simgine/bevy_replicon/issues/638

GitHub

bring back SendRate::Periodic (or equivalent) to be able to modify the replication send rate per component. #1090432346907492443 message m...

viscid jacinth
#

Sounds good, thanks πŸ‘