#bevy_replicon

1 messages ยท Page 11 of 1

spring raptor
#

You mentioned that it consists of bools

#

Or is there more information?

hexed cove
#

just bools

spring raptor
#

Maybe grid as components would be more useful? This way you could replicate only actually changed data.

hexed cove
#

i don't know if that's actually more performant

spring raptor
#

Only one way to find out ๐Ÿ˜…

hexed cove
#

yeahhhh

#

well currently i just need to update a grid of bools

#

as opposed to querying the coordinate, updating the entity, sending to the client the entity with the new state

#

i've been weighing it in my head all day and it just doesn't seem worth

#

working on the renet build currently

spring raptor
#

It will require additional lookup for coordinate - entity, but other then that - it should save a lot of traffic. And traffic is the most valuable resource.

hexed cove
#

grid of bools with mostly repeated 1s and 0s seems very easily compressable

spring raptor
#

Ah, true...

#

And you don't need to attach entity to each cell ๐Ÿค”

hexed cove
#

or pretty cheap even without

#

it'd have to be benchmarked

#

but it also works well enough

#

i feel like all of game dev is just "works well enough" lol

spring raptor
#

Yeah, always focus on the game. You can optimize it later.

#

The game is the hardest stuff and the requirement of "make it fun" is super vague

#

So it's better to figure out what is fun and then iterate on performance

#

For crates it's different. You have the requirements and you need to choose the right architecture.

hexed cove
#

I'm getting this error with trying to switch to renet as the backend

spring raptor
#

Make sure to use compatible versions

hexed cove
#

I moved grids to their own components and had them be handled with events and it worked perfectly, although I'm still getting the "datagram too large" issue when spawning ~20 ants. This is after setting up replicate_with for transforms

spring raptor
hexed cove
#

what was the size quinnet needs again? I can just use a fork

#

I tried renet but couldn't get it to work, skill issue I think

#

renet replicon has a lot of similar types as replicon, renet ClientId vs replicon ClientId, ServerEvent, etc

#

quinnet felt easier to use

spring raptor
spring raptor
spring raptor
# hexed cove 1162

Could you open a PR to adjust the constant? This way I will be able to publish a patch-release.

hexed cove
#

38 bytes of pain

#

yup

spring raptor
#

It's not a proper fix, but an acceptable workaround. We definitely should allow backends to set this value.

hexed cove
#

yeah i see the TODO

#

made pr, although might need to adjust the tests

#

why is this asserted as false?

spring raptor
hexed cove
#

apparently it was changed to triggers or something?

#

going from 0.29 -> 0.30 for replicon

spring raptor
#

Don't forget to update the quinnet as well.

hexed cove
#

yup

hexed cove
#

getting this error when setting the visibility with the observable

#

removing the visibility, it does appear to be fixed

#

I do get this issue when summoning like 10k ants

#

so there is a limit lol

#

it keeps running, just gets laggy

spring raptor
hexed cove
#

these two lines on the bottom are problematic

spring raptor
# hexed cove these two lines on the bottom are problematic

Ah, I see what is happening here. Basically, when a new client is connected (emitted by backend) I create an entry in connected clients. But looks like your call is calling earlier.
Make sure you setup your plugins after replicon's. I think observers should be triggered in their registration order.

hexed cove
#

they should be registered after already?

spring raptor
hexed cove
#

hmm

#

i can log if the debug shows up

spring raptor
#

Well, as a temporary workaround, you can create your own event and trigger it from your own observer. This way you will be able to properly set the visibility. But it's junky ๐Ÿค”

#

@hexed cove Better, create OnAdd observer for your teams and setup the visibility there.

#

But it's strange, I thought that observers fire in their registration order ๐Ÿค”

hexed cove
#

they do

#

client connected -> setting visibility

#

well they do in this case, Idk if it's actually documented

spring raptor
# hexed cove

On the screenshot I see logs only from Replicon, they are expected.

hexed cove
#

the bottom log "setting visibility" was placed by me

spring raptor
# hexed cove

But judging by this panic, your function is running before.

hexed cove
#

on the function

spring raptor
#

Let me put a quick fix.

hexed cove
#

and they're ordered in a way that causes a 1f delay?

spring raptor
#

They fire in the same frame, but since you observe for ClientConnected, your function was called earlier.

hexed cove
#

Oh I see

#

ClientConnected triggers both my observer and the replicated clients observer

#

that then generates it

spring raptor
#

Yes, and yours fire earlier due to how commands are flushed

#

Won't be an issue anymore :)

#

Once koe review both PRs, I will draft a patch release ASAP.
In the meanwhile just these apply changes locally.

hexed cove
#

Sounds good

hexed cove
#

trying to replicate the grid triggers this again, so it still happens with one large entity

spring raptor
# hexed cove :(

Interesting. Could you try to print the used value and the max size?
I would include this information in the error message. So find the string, patch the crate (maybe PR to the author, good to have) and try it.

hexed cove
#

do you know why these logs might not be showing up?

spring raptor
# hexed cove do you know why these logs might not be showing up?

Not quite sure ๐Ÿค” I would assume that they are not called. Double check if you have only a single registration for the TeamVisibility. If you have a registration with more components and TeamVisibility, it takes priority.
For example, (Transform, TeamVisibility) will be picked over regular TeamVisibility rule.

hexed cove
#

Oh yup

#

lmao

spring raptor
#

๐Ÿ˜…

#

But could you disable compression and check the size? ๐Ÿ™‚

hexed cove
#

oh

#

what if you want a bundle + replicate_with

#

like i dont want to replicate every transform

#

but I also want to use replicate_with

#

like replicate_group_with<(Ant, Transform)>();

hexed cove
spring raptor
hexed cove
#

Oh I see

spring raptor
#

(Component, Component) is a bundle. Just create your own struct instead and implement ReplicationGroup

hexed cove
#

yup, missed it in the docs

spring raptor
hexed cove
#

I see it now

hexed cove
spring raptor
hexed cove
#

serializing works, this happens when attempting to deserialize

spring raptor
#

Interesting, are you sure that functions are the same on client and server?

#

The panic means a problem with registration

hexed cove
#

yes

#

these are registered in my core crate

#

so they run on both client/server

spring raptor
#

Hm... The error means that the received ID doesn't exist

#

Function ID

hexed cove
#

what function id?

spring raptor
#

When you register a replication group or component, you create its function IDs internally.
When transmitted over the network, we include this ID.
Error means that there is no such function registered for such ID.

#

Let me improve the error message, so we could see what is happening more clearly.

hexed cove
#

maybe my compression thing is bad

spring raptor
#

I don't see an issue with the provided code ๐Ÿค”

#

Let's work on one thing at a time.

hexed cove
#

just gonna double check if transform works properly

spring raptor
#

Let's take a look at the datagram limit (I suspect that it's dynamic) and I improve the panic.

hexed cove
#

oh true

#

testing datagram logs

hexed cove
spring raptor
hexed cove
#

yup

spring raptor
#

And max size is different: 1414

#

It's probably dynamic ๐Ÿค”

hexed cove
#

I think so

spring raptor
#

Okay, let's back to compression. I guess if we solve this problem, we won't need to worry about it.

hexed cove
#

50kb per team_visibility

#

yeah compression brings it to like

spring raptor
#

Huge ๐Ÿ˜…

hexed cove
#

50 apparentl;y

#

again, grid full of repeated 1s and 0s

spring raptor
hexed cove
#

probably not

spring raptor
hexed cove
#

I couldn't find a clean way to add it as part of the error

#

the error prints the error from quinn

spring raptor
#

Ah, I see :(

hexed cove
#

maybe a match to send a unique error for specifically TooLarge

#

and everything else uses the original

#

Ill submit a pr

spring raptor
#

Maybe just edit the display for the error ๐Ÿค”

#

I.e. include more info in the TooLarge and adjust Display impl. But it's not as simple change as I thought. Maybe worth keeping as is.

hexed cove
#

could edit the display

#

but getting access to the size is a problem then

spring raptor
#

Yep, this is why I suggesting to include this data in the error to display it properly

#

But the author might dislike the increased error size

hexed cove
spring raptor
# hexed cove

181 is a huge number. It means that you have 181 functions registered. Which is unlikely.
This could mean that we are trying to read some garbage.

#

On deserialization

#

Let me think

hexed cove
#

im gonna check if transform works

spring raptor
#

I think we have tests with custom serialization, but yeah, double check just in case.

#

Ah, I see the issue

spring raptor
#

We trying to not allocate for performance reasons, this is why I pass the buffer ๐Ÿ˜…

hexed cove
#

Oh I see

#

I misunderstood how that works

spring raptor
#

Yeah, it's a possible pitfall. But it's very important to keep replication fast.

hexed cove
#

hmm

#

well

#

this works for a single tick

#

it fails to decode, but i think it successfully decodes a single time

#

because the correct vision shows up for a single frame

spring raptor
#

Serialize the buffer size first

#

Then on deserialization check the size first and then pass a slice of such size to zstd

hexed cove
#

that makes sense

#

it works but it does eventually grow too large

#

compression isnt enough ๐Ÿ˜”

spring raptor
#

You need to make it deterministic

hexed cove
#

deterministic ants?

#

although my end goal is multiplayer ant combat so serverside visibility is my current goal

spring raptor
spring raptor
hexed cove
#

not sure, I've been quite confused by quic

spring raptor
hexed cove
#

Yup

hexed cove
#

entities will never be able to be split across packets right?

spring raptor
#

Yes, it's by design :)

#

Otherwise the game logic might break based on network conditions

hexed cove
#

would it be possible to pass larger entities through a different channel type?

spring raptor
hexed cove
#

well

#

transmitting grids through events does work

#

so I think there's some way to make it work through ordered or unordered channels

spring raptor
#

Replication utilizes both channels. Insertions, removals, despawns and spawns go through reliable channel. Mutation go through unreliable channels. It's because there is no sense in resending the old value, if the packet gets dropped, we send the latest value.

#

If you want to go this route, the events is the right tool for it.

hexed cove
#

that makes sense

#

max entity size probably needs some sort of documenting though

spring raptor
#

I agree. Didn't expect someone to transfer that much ๐Ÿ˜…

spring raptor
#

@hexed cove the release with triggers fix is on crates.io.
I will provide a fix for backend message size later. But In your case you want to use events anyway.
Highly suggest to somehow minimize the amount of transferred data and more rely on determinism.

hexed cove
#

yup

#

I figured out a way

hexed cove
#

it might be worth adding a fn or recipe in the docs for replicating/events with custom serialization + mapping

raw idol
#

I was thinking of writing a UART or ESP32 wifi transport anyway for fun

spring raptor
hexed cove
#

I will try tomorrow

#

bc it's something I'm doing

#

which option do you think makes more sense here?

spring raptor
# raw idol ๐Ÿค” could we have bevy_replicon no_std?

I'm curious about this as well ๐Ÿค”
But I have small experience with no_std from work, we provide minimalistic hal for our cores.
But this sounds like fun to try.

From what I understand, we need to replace all std with core, switch to bevy_* (or wait for #1303128171352293410 message), add std feature and disable std by default for bytes and postcard. And the figure out what to do with the buffer I allocate to prepare messages (replace with alloc?)

raw idol
#

oh, and Instant will be a problem. this is the main issue I had with making no_std aeronet_io

spring raptor
raw idol
spring raptor
spring raptor
raw idol
#

that's great then, I thought you might have used it for something in replication. I use it in the IO layer.

spring raptor
#

Lackily I use it only in benchmarks ๐Ÿ™‚

#

I think main problem will be Bevy. We might need to support master :(

#

I mean it's fine, but we won't be able to release it to public

raw idol
#

yeah, 0.15 isn't no_std right now I don't think

#

this is more of an experiment than anything, at least until 0.16

spring raptor
#

Yeah, I probably could create a branch ๐Ÿค”

raw idol
#

I'm gonna make an aeronet no_std testing branch, and try to port aeronet_io over to no_std + add esp32 wifi support, if that's even possible

#

and see if I can port the transport over, which might be more challenging

#

are you pinning to a specific bevy rev?

spring raptor
#

How practical it is? Totally unpractical.
But how fun is it? Very fun ๐Ÿ˜…

spring raptor
#

So you can start, I will catch a bit up later.
Replicon should be easier to migrate since we basically just read data from Bevy and feed it back.

hexed cove
#

are you building a multiplayer project w no_std?

dire aurora
spring raptor
# hexed cove are you building a multiplayer project w no_std?

I trying to build a regular game: #1264625779296174110.
But Bevy community recently expanding no_std support. I wanted to join the hype, but I needed a backend that can utilize that.
@raw idol mentioned in #networking that he have esp32 and considering supporting no_std in aeronet, so how can I resist now? ๐Ÿ˜…

dire aurora
#

Bevy community
You say like it's not just @twilit islanddoing 90% of the work ... I'm sure they would appreciate seeing a no_std networking crate tho

spring raptor
twilit island
dire aurora
dire aurora
spring raptor
twilit island
dire aurora
dire aurora
dire aurora
#

Looks like on the serialization benchmark (if we just look at bandwidth) the only ones that really consistently beat bincode are postcard, bitcode and whatever dlhn is ๐Ÿค”

spring raptor
# dire aurora I think they actually dropped support for those attributes in the custom derive ...

I mean they provide more efficient bare-serialization via https://docs.rs/bitcode/latest/bitcode/fn.encode.html / https://docs.rs/bitcode/latest/bitcode/fn.decode.html. Their trait implemented for built-in types and requires Encode/Decode derive for custom types. And with serde feature they provide https://docs.rs/bitcode/latest/bitcode/fn.serialize.html / https://docs.rs/bitcode/latest/bitcode/fn.deserialize.html. With streaming support we could use encode/decode for our replication messages data (ticks, manual arrays) and serde for components. So users won't need to use any custom derives, just regular Serialize/Deserialize.

spring raptor
spring raptor
raw idol
hexed cove
#

working on the pr now, can't figure out how to map the entity without having access to the component

#

since we're trying to only serialize/deserialize the entity inside

spring raptor
#

Just merged migration to postcard ๐ŸŽ‰
It's the best option for now. Looking forward to streaming support in bitcode.

spring raptor
#

Basically, the changes :

hexed cove
#

yup, just drop in from bitcode

spring raptor
#

And Cursor now just Bytes

hexed cove
#

ill test it

#

oh wait i see an isseu

spring raptor
# hexed cove this probably works i think

Yep, looks good.
But it's actually mirrors default ser/de functions:
https://github.com/projectharmonia/bevy_replicon/blob/postcard/src/core/replication/replication_registry/rule_fns.rs#L212
https://github.com/projectharmonia/bevy_replicon/blob/postcard/src/core/replication/replication_registry/rule_fns.rs#L195

So maybe add an extra field to the component and write a comment that we skipping the filed for replication? I.e. just to showcase a somehwat real use case scenario.

hexed cove
#

somewhat real use imo would be to just

#

for compression or something

#

(my usecase)

#

if you just needed to exclude fields you could just seperate the component xd

#

but sure

spring raptor
hexed cove
#

yeah agree

#

wait

#

you can't just send serialize and send "entity" though

hexed cove
#

no component to call map_entities on

#

unless I create a new one

spring raptor
#

But not very practical ๐Ÿค”

hexed cove
#

yeah

#

like that lol

spring raptor
#

What if we create a function compress inside the example that actually does nothing? ๐Ÿค”

hexed cove
#

yeah real usecases would be like

#

compression or if you want to manually do bit manip to like

#

hyper optimize

spring raptor
#

Yeah, and in the example it's not necessary should be a real function

#

We can hide it by prepending #

hexed cove
#

that makes sense to me

spring raptor
#

So just copy what you have for you game and replace zstd with dummy compress๐Ÿ˜…

hexed cove
#

the compression does use cursors, but i think it can use any thing that impls Read

#

compression also requires you pass the size in as well

#

ill try writing something up

hexed cove
#

does this look right to you?

#

not sure if I did the #s correctly

spring raptor
spring raptor
#

And Bytes on main

hexed cove
#

I think im currently on the latest release

#

oh i see the issue

hexed cove
spring raptor
#

This function doesn't do anything anyway ๐Ÿ˜…

hexed cove
#

there's a few more bugs i fixed

spring raptor
#

Thanks to postcard I switched to varint encoding for ticks: https://github.com/projectharmonia/bevy_replicon/pull/411

We use 32-bit ticks.
With bincode, ticks would start to use 5 bytes after 2^16 (which happens after ~18 minutes with 60 ticks/s).
But with postcard it happens only after 2^28 and with 60 ticks/s it starts to take 5 bytes after ~51 day.
So don't run your sessions for 51 days, otherwise messages will start to take 1 more byte ๐Ÿ˜…

GitHub

Because postcard provides more efficient encoding for it.
Partially reverts #371.

hexed cove
hexed cove
#

do player/server only observables exist

hexed cove
#

workaround, use some sort of marker through resources or state and check in the observable

#

conditional observables should probably be added to bevy

hexed cove
#

oh it's GroupReplication

#

mb

#

if an entity has GridCoords, VisionRange, and TeamLabel, they should all be replicated in the same entity right?

#

for some reason these components go missing on the client though

#

no error on the server

#

maybe they aren't added at the same time

#

on insert doesn't work either, maybe it's added one by one

#

Triggering it every time any of the 3 get added, then returning if it doesn't have all 3 is a working solution, but a little junky xd

spring raptor
hexed cove
#

yesh

#

currently I can check the resources to see if it's server/client as well

#

there's workarounds but it's cleaner w observer conditions

spring raptor
spring raptor
hexed cove
#

you're saying they should all be inserted even with separate registerations?

spring raptor
#

But maybe I misunderstanding how obsevers work ๐Ÿค”

#

I would expect them to be called after the flush

hexed cove
#

I can double check my code tomorrow, but all three of those components should be replicated

spring raptor
#

Could you do commands.entity(entity).log_components inside your observers?

hexed cove
#

GridCoords, Replicated, VisionRange, ConfirmHistory

#

but I can do that tomorrow

spring raptor
#

Except TeamLabel

#

And that's the one you insert later with events, right?

hexed cove
#

nope, that should be replicated

#

replicate mapped if that matters

spring raptor
#

Weird, for some reason you have other components inserted and this one missed ๐Ÿค”

#

Are you sure that you don't have an entity with these components and without TeamLabel?

hexed cove
#

I shouldn't, but I will double check tomorrow

#

need sleep, it's 6am

#

xd

spring raptor
#

Good night ๐Ÿ™‚

spring raptor
hexed cove
#

i only spawn vision range in 2 places and both have teamlabel

spring raptor
hexed cove
#

all components on an entity need to be sent together right?

spring raptor
#

And insert them via commands

#

And then flush them.

#

Basically commands.entity(entity).insert(a).insert(b) and then flush.

hexed cove
#

weird

thorn forum
#

hello ! just to confirm, its not currently possible to replicate the whole Transform for insertion, and then only the translation ? im looking at .replicate_with(), but it seems to only allow the DEserialization to be different on insert and in place, but the serialization we can't choose ?
if i understood correctly then, the best way would be to replicate with Transform with only the translation, and on replicate a InitialTransform to set it initially, and after only the translation is sent.
this is for minimizing the server egress.
thanks !

dire aurora
spring raptor
#

We switched to postcard on the main, but the idea is the same.

thorn forum
# spring raptor Yeah, it's not currently possible. But you can do a workaround - create your own...

oh yeah thats good too ill try. honestly im even wondering if i can just not even replicate my troops and projectiles positions, even with this method to only send translation. a 5min game goes from 2mb to 5mb, which mean practically 2x more expensive games to host. this amout seems normal ? here's a peek of my game, do you think its reasonable to not replicate movement ?

#

thanks for the answers !

spring raptor
thorn forum
#

thanks ! ill continue to not replicate transform then. here's some test with spawning multiples buildings with multiples troops etc:
no transform: 2mb
initialtransform: 5mb
transform: 11mb
running a game without doing anything, so nothing is being replicated, no event etc, its still 0.9mb. looking with wireshark there's a lot of packets every seconds of len 68 or 72, i guess keep alive / tick, but it seems a bit excessive for a idle state or its normal ?
if you have some experience with bandwidth usage in games, do you find these numbers normal for a game of my type ?
thanks !

spring raptor
#

As for traffic, I can't tell, simply don't have experience to compare. But if you are optimizing, maybe you would like to try the latest master? I did a bunch of optimizations to reduce the packet size recently.
Use patching in Cargo.toml since backends rely on release version.

#

@thorn forum you can also check what replicon sends by enabling tracing

#

RUST_LOG=bevy_replicon=trace cargo run ..

thorn forum
#

thanks for the everything!
I'll try master.
I already tried tracing and there only tick that's changing !

thorn forum
#

I don't know much about the inner protocol of renet and networking library, but I would have thought a idle game would use less bandwidth.

spring raptor
spring raptor
#

Let me know if you need any help with the latest master.

echo lion
#

Yes the renet ack protocol is a naive design. It really needs a rework (or at least a full analysis with improvements), but I don't have the time to work on it.

thorn forum
thorn forum
spring raptor
#

Looks like this was also merged, nice!

dire aurora
thorn forum
#

hi again, what happens on the client when is it disconnected from the server ? like does it modify/remove some components ?
on the end screen im still showing the game in the background but stopped, and when the server quit and so the client are disconnected, multiples things are modified, including non replicated component, but these are maybe modified indirectly through my systems.

#

example here. the serve quit 2s after the game ended, to demonstrate the change when the client are disconnected. at the end the health bar are blank, and the animation plays again. i struggle to find the cause.

#

i dont have any .run_if(client_connected) systems too

#

it seems that some replicated component are re added to some entities ? i have a Added<Troop> for new troops, and it get triggered on disconnect

dire aurora
thorn forum
spring raptor
spring raptor
echo lion
thorn forum
thorn forum
spring raptor
spring raptor
thorn forum
thorn forum
spring raptor
#

Yeah, with resources as entities we can just insert server or client component on backend client or server ๐Ÿค”

thorn forum
#

ohh yeah I got confused with the network backend resources which we add ourselves

spring raptor
raw idol
#

@spring raptor I was curious, how would you handle user accounts via replicon?

#

I'm starting to think that I need another intermediary layer somewhere above IO for Auth, but I can't quite think of a system for this yet

#

or rather, keep encryption as the responsibility of the IO layer, and have game-specific Auth above

spring raptor
raw idol
#

so that would be below replicon?

spring raptor
#

I think so ๐Ÿค”

#

Not sure what special we can provide to help

raw idol
#

well normally replication starts immediately after connection right

#

perhaps a "connect", "authenticate", "start replicate"

spring raptor
spring raptor
raw idol
#

true, but all of the current transport implementations immediately send a replicon connect after a client connect

spring raptor
#

In renet auth is baked into connection

#

I.e. you receive a token

raw idol
#

renet is a bit different to what I'm thinking, since a part of the auth process happens before there's even a connection, i.e. talking to an http service to generate and request a token

spring raptor
#

So the workflow looks like this: connect to authorization server, it generates the token and then you connect to the game server.

raw idol
#

yeah

#

id like to do all the auth in one shot, with one server

#

anyway I'm gonna go to sleep and think about this a bit more

spring raptor
#

Then maybe you need something on top of Replicon, not sure

spring raptor
#

Have a good night ๐Ÿ™‚

echo lion
spring raptor
#

Or Counter-Strike

echo lion
thorn forum
spring raptor
#

But I planning to fix it with the upcoming rework of replicon resources as entities.

raw idol
# echo lion I disagree with this, connecting to your backend infra as a 'user' is distinct f...

renet's way is one valid way of doing it, and I do like it. I think it works nice when you have a central authority for accounts, and it should be a supported way of doing auth. however, that's not the architecture that I would like for my game, since I want a "one-shot" auth + connect flow, where each server manages its own accounts and there is no central authority. and this is a perfectly valid way of doing auth as well.

#

in general, I'd like both ways to be possible, and require switching between the two to require minimal code changes (at the actual "connect" stage anyway - if you need an auth token from some other authority, then there's obviously more work you have to do)

#

I'm just not sure where this should live in the networking stack. right now, I'm thinking above the transport layer but below replication.

thorn forum
#

about my Added<Troop> being re triggered on the client on disconnect, i fixed it, but i would like to understand how it happened.
i used bevy track change detection to print the troop's changed_by():

2025-02-10T12:50:15.449560Z  INFO bevy_dev_tools::states: app::game::GameState transition: Some(StartCountdown) => Some(Running)
2025-02-10T12:50:41.337506Z DEBUG app::card::systems: handling Added<Troop> entity 877v6. Troop changed_by at Tick { tick: 309739 } by [...]/bevy_replicon-0.30.1/src/core/replication/replication_registry/command_fns.rs:93:42
2025-02-10T12:50:47.547765Z  INFO app::game::systems: received EndGameEvent(Some(ClientId(1739191812323)))
2025-02-10T12:50:47.564847Z  INFO bevy_dev_tools::states: app::game::GameState transition: Some(Running) => Some(Ended)
2025-02-10T12:50:48.570843Z ERROR renetcode2::client: Failed to update client: disconnected: connection terminated by server
2025-02-10T12:50:48.605955Z DEBUG app::card::systems: handling Added<Troop> entity 877v6. Troop changed_by at Tick { tick: 309739 } [...]/bevy_replicon-0.30.1/src/core/replication/replication_registry/command_fns.rs:93:42

i dont spawn or insert any Troop after the first one. so i dont know why Troop is marked as just added.
bevy's changed_by() should show from where its been added, but its showing the first add from replicon, not the second one which is added from nowhere.
could it be a bug with bevy's change detection ? because the two last_changed() are at the same tick and location, but just changed to added true (and so changed true too)

thorn forum
#

i dont insert or modify the Troop component or &mut it anywhere, only &Troop. and its still marked as added + changed

spring raptor
# thorn forum about my Added<Troop> being re triggered on the client on disconnect, i fixed it...

Agree, it's better to investigate! Let's take a look together.

So, backend (I assume you use renet2) systems update RepliconClient state in ClientSet::ReceivePackets.

Then we run ClientSet::Receive (the order is configured here).
Which contains the system that applies the replicated data here.

To me it's configured as expected. Client becomes disconnected first, then run receive_replication only if we are conneected ๐Ÿค”
But maybe the condition under run_if is evaluated at the beginning of the schedule? That would explain the issue.

thorn forum
#

we agree that its not normal for bevy's detectchanges to register the component was re-added, but it doesn't have the tick or location info ?

spring raptor
#

If you want to investigate

dire aurora
thorn forum
#

i found the problem, sorry for wasting all your time...
the system with the Added<Troop> was running on Update on the client and FixedUpdate on the server.
the fixedupdate system ran after disconnection because of the server_or_singleplayer. yesterday i tried removing it to assert it was the client update system that was running, but i must have failed to do it correctly. the second log was from the system in fixedupdate running for the first time, and so the Added was true. i learned that the same system in different schedule have different states

spring raptor
pale charm
#

is there any example how to use replicon with avian3d? For some reason i'm having a hard time figuring it out ....

dire aurora
pale charm
#

ah thanks, no idea why i havent tried that tho.... thank you very much

spring raptor
pale charm
#

just playing around. i did a small game for a gamejame with lightyear and wanted to try replicon now. But my brain seems to be afk today, so i'm struggling with pretty basic stuff

#

but thank you very much for your help ๐Ÿ™‚

spring raptor
# pale charm just playing around. i did a small game for a gamejame with lightyear and wanted...

Ah, got it!

If you want to build a physics-based game you need a special technique called "client-side prediction". The idea is to remove input delay by applying all actions immediately locally and when server confirms the changes, correct the local state.
Under the hood it rollback your game state in time, applies server changes and re-plays local input on top of it.

And there are 2 ways of doing it:

  1. Rollback pre-entity. It's cheap, perfert fit for shooters, but not so good for physics-based games or for games where you have a lot of stuff to rollback (it's cheaper to rollback the whole world instead of checking each entity individually for rollback). That's what Lightyear provides.
  2. Rollback the whole world. Usually more performance-heavy, but perfect fit for physics-based games or games with a lot of rollbackable entities.

Replicon is completely abstracted from it and allows to build any of these methods on top. But the problem is that we currently don't have a crate that does it ๐Ÿ˜…
@dire aurora is working on a crate for 2, but quite busy with other stuff recently.

I planning to give a talk about replication on the next Bevy meetup, I will try to cover these topics ๐Ÿ™‚ Maybe this will encourage someone to write a crate for 1.

pale charm
#

thank you for your explanation. i'm looking forward to your talk ๐Ÿ™‚

i really love how easy it was to setup replicon and how helpful the docs where. damn good job

dire aurora
dire aurora
#

@spring raptor How are we actually supposed to use the example backend? It just throws this panic:

bevy_replicon_example_backend::server::set_running could not access system parameter ResMut<RepliconServer>
```Which happens because the example backend uses the the one from the git dependency, while your code uses the versioned replicon ๐Ÿค”
spring raptor
#

I think it's quite explicit that it's just for example ๐Ÿค”

spring raptor
#

@dire aurora will it work if I set the version of replicon in Cargo.toml?

scarlet imp
#

Hello! I'm updating some of my game's server events to use the new server triggers, but when I run it as a listen server only the non-server clients are receiving the triggers, not the one running the listen server. It runs as expected in single player mode, and it worked previously as a server event. The server_trigger documentation mentions triggering locally if ClientId::SERVER is a recipient of the event, but I can't find how to make it a recipient. Using SendMode::Direct(ClientID::SERVER) as the mode in the trigger also didn't appear to work. I'm was hoping to get some help with that. I've got the following code snippets:

#[derive(Event, Serialize, Deserialize)]
pub struct SetTurnBasedState {
    pub state: TurnBasedState,
}```
```rust
app.add_server_trigger::<SetTurnBasedState>(ChannelKind::Ordered);
app.add_observer(receive_turn_based_state);```
```rust
commands.server_trigger(ToClients {
    mode: SendMode::Broadcast,
    event: SetTurnBasedState {
        state: TurnBasedState::RoundBeginning,
    },
});```
```rust
fn receive_turn_based_state(
    trigger: Trigger<SetTurnBasedState>,

) {
    warn!("Received new turn based state: {:?}", trigger.state);
}```
Thanks for the help!
spring raptor
scarlet imp
#

Thanks! I managed to build a workaround, but I'd be happy to provide any additional context tomorrow if it would help. ๐Ÿ™‚

dire aurora
spring raptor
#

I'll just publish it. For convenience the version number will match the replicon version.

spring raptor
thorn forum
spring raptor
thorn forum
#

oh ok thanks :)

spring raptor
#

It should work exactly as remote events.

dire aurora
#

It takes some real mental gymnastics to use a crate with such a warning and example in all the names as a real backend ๐Ÿ˜‚

spring raptor
dire aurora
#

Could use same major but different patch releases

#

I don't think pushing features to just the example backend outside of a replicon update would be particularly worth it at least

spring raptor
dire aurora
#

Quite a surprising error to get ... Did StartReplication become a trigger? ๐Ÿค”

Requested resource bevy_ecs::event::collections::Events<bevy_replicon::server::StartReplication> does not exist in the `World`
spring raptor
#

I mentioned it in the changelog

dire aurora
#

I guess this just shows how painful the Trigger vs EventReader thing is with Event merged as one concept bavy

spring raptor
#

And you can't know if the type is a trigger or an event by trait impls, you need to rely on authors to explicitly state it in the docs.

dire aurora
#

Having to integrate both loading of inputs while resimulating and listen servers really makes me need to rethink some of the design of my input queue and rollback stuff ...
Questions like:

  • How do I avoid generating new inputs while resimulating
  • How do I make sure the listen server's inputs have been written before sending
  • How can I make the input queue load inputs instead of expecting the generation when it doesn't know rollback exists
spring raptor
dire aurora
#

So the first one is pretty obvious, as a part of FixedMain you need to generate inputs, but only if it's a real frame, and not a resimulation. I could do some run condition or system set dance but that seems very error prone

The second is a bit more specific to how I've set things up. I receive inputs from clients, use them to update the input queues, then send the inputs. I do this in PreUpdate, however if you are a listen server you also generate inputs, but in FixedMain, and thus miss them. If you send inputs after FixedMain (for example in PostUpdate), you can miss updates because they got consumed from the InputQueue while the listen server was running

For the last one I need resimulations to load inputs from the input history for all players, including the one with authority, instead of only trying to load it if there is no authority (they are unlikely to be there, but I check it just in case anyway, since it can avoid some mispredictions)

spring raptor
dire aurora
#

On the lister server we don't re-simulate, I just need the server to send an accurate list of inputs before it starts consuming them

#

So clients have inputs for resimulating

spring raptor
#

Ah, got it now!
I have an issue similar to 2 in my input crate. I need to read inputs in PreUpdate but in FixedMain I need to output it at specific point in time.
LWIM does it, but I still didn't get to it.

#

Not the same as your problem, but related

dire aurora
#

Yea ... They sort of come from the same source, which is the fact that we can't really determine during PreUpdate where the inputs should go

#

If we could, I could easily populate my input history in PreUpdate and immediately send the inputs (now including the host's inputs)

#

I guess I'll just ignore this specific problem for now and send the inputs at the end of the frame instead, it contains 3 of the past inputs too, so the server needs quite a bit of lag for it to matter ๐Ÿค”

#

Still leaves the other two issues ... I guess the simple solution for the first one is to just generate inputs in FixedPreUpdate, I only resimulate FixedUpdate by default, and if you change things you can just use a custom schedule ... The last one ... I guess I should just make it a bit smarter with when it loads, inputs aren't stored until FixedPostUpdate, so if I only load something if there is history I think the problem should be non-existent, but ofc the responsibility to clear the previous frame's input is now in the developer's hand ... Which I guess is fine, it's their type anyway ๐Ÿค”

#

Actually I guess the last issue would also not exist if inputs could be generated ahead of time, then you could just always load from the history

#

Seems to work, but then I suddenly hit this:

bevy_replicon-0.30.1/src/core/replicon_client.rs:209:32:
client should have a channel with id 98
Encountered a panic in system `bevy_replicon_example_backend::client::receive_packets`!
#

Also seems to happen the other way around ๐Ÿ˜‚

bevy_replicon-0.30.1/src/core/replicon_server.rs:175:32:
server should have a receive channel with id 10
Encountered a panic in system `bevy_replicon_example_backend::server::receive_packets`!
spring raptor
dire aurora
#

Pretty sure I don't ๐Ÿ˜‚

#

The only events I register:

.add_client_event::<Connect>(RepliconChannel::from(ChannelKind::Unordered))
.add_server_event::<CurrentTick>(RepliconChannel::from(ChannelKind::Unreliable))
.add_client_event::<LocalEntities>(RepliconChannel::from(ChannelKind::Unordered))
spring raptor
#

Just tried with multiple channels, still can't reproduce

#

Could you show how the events look like?

dire aurora
#
#[serde(bound(deserialize = "T: for<'de2> serde::Deserialize<'de2>"))]
pub struct InputHistory<T: InputTrait> {
    list: VecDeque<T>,
    updated_at: RepliconTick,
}
``````rust
#[serde(bound(deserialize = "T: for<'de2> serde::Deserialize<'de2>"))]
struct HistoryFor<T: InputTrait> {
    entity: Entity,
    tick: RepliconTick,
    past: ArrayVec<(u8, T), 3>,
    future: ArrayVec<(u8, T), 7>,
}
```The T in question:
```rust
struct GameInput {
    direction: Option<Dir2>,
}
struct Connect;
struct CurrentTick(GameTick);
struct LocalEntities {
    car: Entity,
    ball: Entity,
}
#

It seems to happen after some period of time, never right away ๐Ÿค”

spring raptor
#

But let's start with a few simple things

scarlet imp
#

Thank you! I'll give it a shot a bit later today.

spring raptor
#

@dire aurora could you try with trace logging enabled? Just to see that the amount of sending bytes matches the amount of received.

#

I.e. RUST_LOG=bevy_replicon=trace cargo run ..

dire aurora
spring raptor
spring raptor
dire aurora
#

The world's most painful migration for sure:

-    cursor: &mut Cursor<&[u8]>,
-) -> bevy_replicon::bincode::Result<()> {
+    cursor: &mut Bytes,
+) -> bevy_replicon::postcard::Result<()> {
#

And changing the example backend version to 0.1 for unknown reasons ๐Ÿ˜‚

#

client:

2025-02-12T17:31:57.629624Z TRACE bevy_replicon::core::replicon_client: sending 13 bytes over channel 2
2025-02-12T17:31:57.645861Z TRACE bevy_replicon::core::replicon_client: sending 2 bytes over channel 0
2025-02-12T17:31:57.646642Z TRACE bevy_replicon::core::replicon_client: sending 13 bytes over channel 2
2025-02-12T17:31:57.662504Z TRACE bevy_replicon::core::replicon_client: sending 2 bytes over channel 0
2025-02-12T17:31:57.663042Z TRACE bevy_replicon::core::replicon_client: sending 13 bytes over channel 2

server:

2025-02-12T17:31:57.646761Z TRACE bevy_replicon::core::replicon_server: received 1 message(s) totaling 2 bytes from channel 0
2025-02-12T17:31:57.646768Z TRACE bevy_replicon::core::replication::replicated_clients: ClientId(56474) acknowledged mutate message with Tick { tick: 441520 }
2025-02-12T17:31:57.646780Z TRACE bevy_replicon::core::replicon_server: received 0 message(s) totaling 0 bytes from channel 2
2025-02-12T17:31:57.646788Z TRACE bevy_replicon::core::replicon_server: received 0 message(s) totaling 0 bytes from channel 3
2025-02-12T17:31:57.646792Z TRACE bevy_replicon::core::replicon_server: received 0 message(s) totaling 0 bytes from channel 4
bevy_replicon-6598e87287870c1c/13d2c93/src/core/replicon_server.rs:179:32:
server should have a receive channel with id 10
Encountered a panic in system `bevy_replicon_example_backend::server::receive_packets`!
2025-02-12T17:31:57.663598Z TRACE bevy_replicon::core::replicon_server: received 0 message(s) totaling 0 bytes from channel 0
2025-02-12T17:31:57.663613Z TRACE bevy_replicon::core::replicon_server: received 0 message(s) totaling 0 bytes from channel 2
2025-02-12T17:31:57.663617Z TRACE bevy_replicon::core::replicon_server: received 0 message(s) totaling 0 bytes from channel 3
2025-02-12T17:31:57.663621Z TRACE bevy_replicon::core::replicon_server: received 0 message(s) totaling 0 bytes from channel 4
#

Before that the server still seemed to receive the constant 13 bytes over channel 2 and 2 over channel 0 fine ๐Ÿค”

spring raptor
spring raptor
spring raptor
dire aurora
spring raptor
dire aurora
spring raptor
spring raptor
#

Pushed a less ugly fix to avoid extra allocations.

dire aurora
#

Not sure if it fixes it (since it's a pretty rare bug) but at the very least it's harder to hit now ๐Ÿค”

#

I guess to really make it reliable the reading side should also ensure it either reads everything or nothing ๐Ÿค”

#

Otherwise it could still go wrong on ticks with a lot of data that might cause things to be split up over different packets

spring raptor
spring raptor
dire aurora
#

Does require a buffered reader tho I think

spring raptor
dire aurora
#

Oh it does have a peek ... Nice so it's basically free to fix

spring raptor
#

I managed to replace &World in the replication sending system with FilteredEntityRef. It allows other systems that write to non-replicated components to run in parallel. But I started all this to to make it work nicely with server as a component ๐Ÿ˜…

The logic is almost the same, but I access the pointers via FilteredEntityRef.
The downside is that it's 2x slower (!) due to the extra lookups.

However, I think I can create a custom system parameter that provides access to the replicated components, just like before, but with granular access similar to FilteredEntityRef ๐Ÿค”

dire aurora
spring raptor
dire aurora
#

You mean the switch from the unsafe get_component_unchecked to get_by_id(id).unwrap_unchecked)?

dire aurora
#

Interesting ... I'm surprised it makes that much of a difference ... I guess this just shows how efficient the architecture is otherwise ... Iterating over archetypes and using an archetype cache is pretty cheap after all ๐Ÿ˜…

spring raptor
#

Yeah, I also didn't expect it ๐Ÿ™‚
I will try wrapping UnsafeWorldCell into a SystemParam with granular access. Will work just like before, but Bevy should be able to parallelize it nicely. And without that ugly ParamSet.

dire aurora
#

In case anyone is wondering what the issue is: There are certain things that should always happen before and after the simulation, and you really don't want to schedule every system around them ... Things like loading inputs and storing the new prediction

spring raptor
spring raptor
# spring raptor I managed to replace `&World` in the replication sending system with `FilteredEn...

Done: https://github.com/projectharmonia/bevy_replicon/pull/418
The performance is the same for single thread and Bevy can parallelize it better.

GitHub

This allows replication to run in parallel with other systems that write to non-replicated components.
Benchmarks show the same performance, but we run them without multi_threaded.
Supersedes #417.

spring raptor
#

But my main goal is to make components as entities to work nicely.
Now I need something similar for the receive side. But the problem is that user can write data into non-replicated components ๐Ÿค”

spring raptor
dire aurora
spring raptor
spring raptor
#

@dire aurora quick question: do you need full world access in write functions or only ComponentId?

dire aurora
#

I need read access to some specific resoureces too, we could make a way to whitelist those tho ๐Ÿค”

spring raptor
#

Yeah, this could work.
And the same for components.

dire aurora
#

You mean like non-replicated components you can modify?

#

That would be necessary too I guess, my write functions are for any component, but they always write to the AuthoritativeHistory component

spring raptor
#

I also have another idea to try: provide a special world that blocks access to resources used by replication receiving system.

neon canopy
#

So folks, [I'm looking into still setting up a basic synced app. ](#networking message)

And I know @spring raptor has helped me out but I'm still struggling to set up a good way to set up synced camera and a synced up mesh, which I plan to be changing in the future. Basically 2 seperate apps should have the transform components of their cameras synced up as well as the Mesh3d shape and it's texture as well. I haven't even gotten to syncing textures yet and I'm not even sure if swapping the path on the material will even be the way to do it. But for now just having a camera perma synced would be massive help.

I tried doing the replicated components path and a Camera marker component and it replicates, but it's not too fab as you get a No Camera warning a few times until replication starts. So maybe there's a thing there of creating a window on the client only when the replication starts.

And the second thing is that in the required component path I need a nice way to access my global settings resource as the z value of the camera position is set in the settings, which I'm struggling to grok how to do.

Maybe I should start a thread in the help forum if this would be more helpful.

spring raptor
# neon canopy So folks, [I'm looking into still setting up a basic synced app. ](https://disco...

but it's not too fab as you get a No Camera warning a few times until replication starts
That's expected. In actual game you most likely need a camera to draw menu stuff and when you receive the replication, just despawn the original camera via a trigger.

I need a nice way to access my global settings resource
For that you want to mix it with the blueprint pattern: create a trigger that listens for in-game camera insertion and just update the value from settings.

Maybe I should start a thread in the help forum
This thread is a good place to ask questions like this.

thorn forum
#

on wasm im getting a panic

replication_registry.rs:141:32:
replication `FnsId(63)` should be registered first

im not using any fns or custom impl, only some replicate mapped
thanks :)

spring raptor
#

Does it happen constantly?

thorn forum
#

it happen everytime when connecting, but only on wasm with websocket renet2 (native socket no problems).
im using the branch trigger-listen-server. since i didn't encounter the panic after switching wifi, i stopped using the branch disabling it.
no i have two replicate_mapped component, and none of them are spawned when connecting

#

i triend branch main and same thing

spring raptor
echo lion
#

The transport should not be mangling messages

spring raptor
echo lion
#

So I imagine itโ€™s a replicon issue, possibly UB

spring raptor
echo lion
thorn forum
#

wasn't hapenning before i was using unsecure connection, and now it happen since using serverconnecttoken, but it can just be a change i made in my code ordering

echo lion
#

mirsella can you test webtransport? Should work on chrome

spring raptor
#

Okay, let's try to debug it. @thorn forum could you enable logging to see how much bytes we receiving and sending first. Just in case.

thorn forum
spring raptor
thorn forum
#

oh its not yet merged mb

spring raptor
#

Yep, I pushed it yesterday, but forgot to request a review. @echo lion will merge it once he have time.
It's not related to your problem, just a fix for the previous commit in master.

thorn forum
#

with bevy_replicon=trace and with the fix-replication-read-ub branch

spring raptor
#

I see, a lot of bytes ๐Ÿค”

#

Now could you show logging from the server as well?

#

RepliconTick(839), we definitely receive something weird

thorn forum
#

hm yeah seems a lot, dunno if thats just my usage, im replicating a few things on startup

spring raptor
#

Yeah, it's quite suspicious. The idea is to compare how much replicon sends and receives.
These are bytes without any transport data, just pure replication and events.

echo lion
thorn forum
#

on client the "applying message for replicontick" is 51 like on the server

2025-02-17T16:51:06.967353Z TRACE bevy_replicon::server: incremented ResMut(ServerTick(RepliconTick(50)))
2025-02-17T16:51:07.016956Z DEBUG bevy_replicon::server: `ClientId(811578)` connected
2025-02-17T16:51:07.016986Z DEBUG bevy_replicon::core::connected_clients: adding connected `ClientId(811578)`
2025-02-17T16:51:07.017001Z DEBUG bevy_replicon::core::replication::replicated_clients: starting replication for `ClientId(811578)`
2025-02-17T16:51:07.017075Z  INFO app::game::replicon::systems: client ClientId(811578) connected
2025-02-17T16:51:07.017089Z  INFO app::game::replicon::systems: spawning castle for new ClientId(811578) at Tile(3, 4)
2025-02-17T16:51:07.017625Z TRACE bevy_replicon::core::replicon_server: received 0 message(s) totaling 0 bytes from channel 2
2025-02-17T16:51:07.017636Z TRACE bevy_replicon::core::replicon_server: received 0 message(s) totaling 0 bytes from channel 3
2025-02-17T16:51:07.017642Z TRACE bevy_replicon::core::replicon_server: received 0 message(s) totaling 0 bytes from channel 4
2025-02-17T16:51:07.017657Z TRACE bevy_replicon::core::replicon_server: received 0 message(s) totaling 0 bytes from channel 0
2025-02-17T16:51:07.018208Z TRACE bevy_replicon::server: incremented ResMut(ServerTick(RepliconTick(51)))
2025-02-17T16:51:07.018468Z TRACE bevy_replicon::server: sending update message to ClientId(811578)
2025-02-17T16:51:07.018478Z TRACE bevy_replicon::core::replicon_server: sending 8851 bytes over channel 0
#

had to truncate the logs for discord, but nothing before or after

#

nothing in the sense no changes or messages are sent

thorn forum
thorn forum
#

should just use ms since epoch instead

spring raptor
thorn forum
#

yep the sent bytes matches, both 8972 this run

spring raptor
#

That's a lot of data to send. I wonder what takes so much. Let me improve the logging.

thorn forum
#

i just tested its also this much data when connecting with native. but it doesn't crash on native. could it be something on wasm being buggy and that much bytes corrupt something ?

spring raptor
thorn forum
#

i set

[patch.crates-io]
bevy_replicon = { git = "https://github.com/newclarityex/bevy_replicon" }

but i get

warning: Patch `bevy_replicon v0.30.0 (https://github.com/newclarityex/bevy_replicon#673caad1)` was not used in the crate graph.
Check that the patched package version and available features are compatible
with the dependency requirements. If the patch has a different version from
what is locked in the Cargo.lock file, run `cargo update` to use the new
version. This may also occur with an optional dependency that is not enabled.
#

i ran cargo update and deleted cargo.lock to try but same thing

spring raptor
echo lion
#

It shouldnโ€™t be a packet size limit, because the message arrives with the same size on the client

thorn forum
#

doesn't work i get serde function IDs should be obtained from the same instance on wasm and on native it works like always. i think its not really using the newclarityex:master branch

#

do i still try locally changing the limit ?

#

yes server and client native and client wasm where recompiled

spring raptor
thorn forum
spring raptor
thorn forum
#

oh yeah

spring raptor
#

Maybe packets ordering is swapped ๐Ÿค”

thorn forum
#

ill try locally.
btw i think the patched version doesn't work because its version 30.0 while your versin is 30.1, even if its patch version change maybe its incompatible since its a lower patch version

echo lion
#

mirsella do you use renet2_setup on both server and client?

echo lion
#

Ok. I will try to test extra-big messages in an hour or so.

thorn forum
#

@spring raptor ive sent max_pack_size to 1000, but same thing. anyway even 1000 is still bigger than what im sending ~8900 bytes so it doesn't matter ?

thorn forum
echo lion
#

Right I will test all the transports

thorn forum
#

do you still want me to try webtransport ?

echo lion
spring raptor
#

Okay, one more thing to try :)

#

Could you add byte printing to the debug message locally?

thorn forum
spring raptor
# thorn forum oh okay, so no need to put it even lower

No, why?
Single packet size is limited. And replicon tries to split data up to maximum size. But it depends on the transport. It usually bigger then 1000. We currently have a hardcoded constant, but I planning to fix it in the next release :)
If you have the same error with 1000, then it's not what causes the issue.

spring raptor
#

The idea is to compare what we send on client and server.

thorn forum
#

looking at my code, there shouldn't be even close to 8900 bytes sent, in not replicating a lot

#

ill try updating the trace

#

i just print the raw bytes u8 ?

spring raptor
spring raptor
thorn forum
#

btw i tried not spawning my tiles, and so not even sending start game event, and it didn't crash

spring raptor
echo lion
thorn forum
thorn forum
#

wtf

#

they're marked as public but doesn't work

echo lion
#

Although that does seem a little too big, not sure

thorn forum
spring raptor
thorn forum
#

oh ok sorry

thorn forum
echo lion
#

Hmm well transform is ~40bytes afaict. Name is probably 10bytes or so.

thorn forum
#

do you want me to just check if the message on the server is the same as on the client ? simpler than sending two pastebin

thorn forum
#

what the hell i worked

#

ill re try it

#

the only two things that changed is the message length is smaller, and especially running the server in release

#

the web wasm app was always compiled in release, while the server was in debug. the serialization are different i guess

thorn forum
#

its working everytime now

echo lion
thorn forum
#

thanks as always for all your helps :)))))

#

i tested more, and it seems to be this, Name being replicate on server, and not on client

#

i tried debug server, release client, and it work as long as both have the same thing for replicate Name

#

but the amount of data sent, and the number of FnsId is still weird ๐Ÿค”

spring raptor
#

Name is quite huge, so I don't see anything suspicious

thorn forum
#

I didn't see the problem being debug vs release, because usually when I mismatch compilation mode I get "serde function IDs should be obtained from the same instance" but not this time

spring raptor
thorn forum
#

but with release client and debug server it didn't panic, so I didn't see the two had different compilation mode

spring raptor
#

Ah, I see, interesting ๐Ÿค”

Maybe we should send a hash of the defined protocol? Just to avoid footguns like this.

echo lion
#

The error message can include a list of possible reasons for mismatch: rule registration order not the same, replicon channels not the same, different features affecting replicon rules enabled on server/client, etc.

spring raptor
echo lion
#

When you check the hash and it doesnโ€™t match

spring raptor
#

Working on receiving right now

spring raptor
#

I had previously finished sending, but today I opened a PR with a small fix.

spring raptor
spring raptor
#

Our current approach with removing all required resources isn't bad.
I just can't do the same with components.

dire aurora
spring raptor
dire aurora
#

Oh, that shouldn't be a major issue then ... Not really sure why any other code would even try to touch it tho ๐Ÿค”

brittle mulch
dire aurora
#

Depends on what you mean by interest management ... It could be as simple as using per-entity visibility or as complex as needing to add features to bevy_replicon ๐Ÿค”

spring raptor
spring raptor
# brittle mulch Might I ask how one implemente i nterest management? With replicon

Yeah, it's a bit of a broad term.
We provide a per-entity toggle: https://docs.rs/bevy_replicon/latest/bevy_replicon/core/replication/replicated_clients/client_visibility/struct.ClientVisibility.html
With a policy on the server plugin: https://docs.rs/bevy_replicon/latest/bevy_replicon/core/replication/replicated_clients/enum.VisibilityPolicy.html
It's fast and opt-in.
Third-party plugins can built on top of it things like this: https://github.com/UkoeHB/bevy_replicon_attributes
It would be nice to have a plugin that automatically toggles visibility based on distance or visibility ๐Ÿค” Shouldn't be hard to implement.

dire aurora
#

I mean fwiw it's a broad term because you kind of need all the approaches to end up with usable interest management ... Just per-entity visibility isn't enough, you want component visibility, priority + packet limits, send rates, etc

spring raptor
#

Yep, component visibility, priority, and other features are planned. I don't think it can be implemented as a third-party crate. I just haven't gotten to it yet ๐Ÿ™‚

pulsar garnet
pulsar garnet
#

Ahh, I was using MinimalPlugins on the server, switching it to DefaultPlugins made it work. Wonder which bevy plugin was missing

#

I'm getting these logs even using DefaultPlugins, are there specific bevy features that need to be enabled for replicon to function properly? I have default-features = false in cargo.toml.

2025-02-20T00:37:38.947731Z  WARN bevy_ecs::system::system: System 'bevy_replicon::server::reset' has not run for 3258167296 ticks. Changes older than 3258167295 ticks will not be detected.
2025-02-20T00:37:38.947749Z  WARN bevy_ecs::system::system: System 'bevy_replicon_renet::server::RepliconRenetServerPlugin::set_stopped' has not run for 3258167296 ticks. Changes older than 3258167295 ticks will not be detected.
pulsar garnet
spring raptor
spring raptor
pulsar garnet
#

I'm curious if there's a way to have a "replicate only once/on insert" kind of behaviour. I have logic components that are replicated that are basically what certain units are doing, like "move to X". With those replicated the same behaviour will play out on each client. The only issue is when a new player connects they don't get the other units current Transform because I don't have it replicating, so they see the other unit walking from Transform::default().

My best idea is to query for Query<&Transform, With<Replicated>> on the server when a player joins and send them all over with an event to patch the initial positions.

spring raptor
pulsar garnet
# spring raptor It's a planned feature: https://github.com/projectharmonia/bevy_replicon/issues/...

Ah yea, makes sense. I initially expected Replicated to be an enum with that kind of choice, for what it's worth ๐Ÿ™‚

I don't know if that would help, I'm trying to avoid syncing positions constantly, if I replicated InitialTransform wouldn't that leave me in the same boat? Sorry if I didn't make the criteria I was going for earlier more clear :). I'm going with click on ground to move, so replicating a component that says "moving to x,y" is the only thing that needs to be transmitted ideally (assuming the unit starts in roughly the correct place ๐Ÿ˜› )

spring raptor
spring raptor
#

We also have writing function that provides world access.

#

It's executed after receiving on client. This way you can override writing into Transform, for example, into something else.

#

Serialization happens as usual.
What is your use case?

#

Have you considered using reflection?

#

It's a bit more expensive, but if you need to send dynamic data, it might work

#

That'll work, yeah

#

But you will have to track changes on your own

#

Why not use reflection?

#

We provide access to the type registry

spring raptor
#

@dire aurora do you need access to client's ticks on server? ๐Ÿค”

spring raptor
# dire aurora In what context? ๐Ÿค”

I working on a component-based API. The idea is to replace these resources:
https://docs.rs/bevy_replicon/latest/bevy_replicon/core/replication/replicated_clients/struct.ReplicatedClients.html
https://docs.rs/bevy_replicon/latest/bevy_replicon/core/connected_clients/struct.ConnectedClients.html
https://docs.rs/bevy_replicon/latest/bevy_replicon/server/client_entity_map/struct.ClientEntityMap.html
that map ClientId into data with entities with data as components. It makes it way more ergonomic. And I additionally split ReplicatedClient into ClientVisibility and ClientTicks. And I wonder if this ClientTicks even needs to be exposed. It stores methods like mutation_tick, update_tick, etc (like ones on the current ReplicatedClient).

dire aurora
#

There are context where the acked ticks are useful, but you'd probably want to explicitly receive it then anyway

#

Like delta compression

#

Otherwise I don't really use it

spring raptor
#

It's for listen server and singleplayer case. Useful if your game needs to work in both modes.

#

No, singleplayer is when your server is not running.

#

No, listen server is when server is also a client. All events just getting re-emitted locally. And other players can connect. No packets actually sent locally for efficiency, it's just work.
Singleplayer mode is when you don't use server at all.

Of course you can implement singleplayer by running server locally, but with replicon it's not needed.

#

In the quick start guide I tried to explain the trick we use to support all modes. Just navigate to the events section because for listen server you don't run replication locally.

spring raptor
#

You don't send packets. You send events. And events are re-triggered locally. See the events section in the quick start guide.

#

You can also try running any example in singeplayer mode

#

@vocal violet
To simplify:

  1. When you emit ToClients<T> on server and singleplayer, it's also emitted locally as T.
  2. When you emit T it's also emited as FromClient<T> on server and in singeplayer mode.
    In singleplayer server won't be running, but events will still be re-triggered.
    Let me know if I can somehow improve the quick start guide to make it more clear.
spring raptor
spring raptor
#

Why?
You are a server (or singleplayer) and emit T - you get FromClient<T> locally.
You are a client and emit T - server receives FromClient<T>.

#

Not at all, I really need to put a table or something like this to make it more clear ๐Ÿค”

#

If you have any ideas how to improve the docs - let me know.

#

I think it's there, but I'll double check.

#

Good idea. If you have a vision of it, a PR would be appreciated.
But I planning to take a look into it myself before the next release.

spring raptor
#

@dire aurora do you still calculate statistic on your own? ๐Ÿค”

#

I.e. stuff like packet loss, rtt

dire aurora
spring raptor
dire aurora
#

Would be helpful for anyone that uses statistics from a backend if they ever want to switch ... Could also maybe simplify clock sync in cases where a more accurate out-of-band measurement isn't practical (yet) ๐Ÿค”

spring raptor
dire aurora
#

The backends run as part of the bevy update loop, which adds latency on each side based on how the packets align with the frames/updates

#

In theory backends could have an async part to them to avoid that ofc, but not many of them do

spring raptor
#

But why? ๐Ÿค”

spring raptor
#

Yes, I can't provide world access there, unfortunately.

spring raptor
#

The example runs on CI

#

Make sure you have all necessary imports

#

use serde::de::DeserializeSeed;, for example

brittle mulch
#

@spring raptor Mr shatur are u experienced with ai development?

spring raptor
#

Ah, I think it's only for events ๐Ÿค”
Do you have a component with reflection inside?

#

I can provide it like I did for events. Could you open an issue for it? I'll fix it soon, just need to finish some other work.

I can't provide all resources or world access nicely. But having TypeRegistry is reasonable.

spring raptor
spring raptor
# echo lion What problem does this solve?

I dislike our current ergonomics.
Data related to connected clients is located in separate resources, and accessing it is inconvenient. For example, to configure visibility, I have to get ReplicatedClient from ReplicatedClients using client ID (O(n)), and then call visibility_mut. Fetching it from a query is more direct and O(1).

Since we now have identifiers, I removed ClientId because conversions between them were quite confusing for users.
This change leads to using OnAdd / OnRemove triggers to listen for connect/disconnect events. As a result, I removed the special triggers along with the disconnect reason (which we also can't represent nicely).

Not entirety sure about the API, but I think that the direction is promising. It feels more Bevy-way. I'm open to suggestions.

raw idol
#

it's the same conclusion I eventually reached, that as much as possible should just be in the ECS since it makes access easier and more ergonomic (unless there's a very good reason to store it in my own data structure in a resource)

swift hamlet
#

Does any of the messaging backends for replicon implement nat traversal?

spring raptor
dire aurora
swift hamlet
dire aurora
#

So you want a player host to be reachable by other players while everyone is behind NAT?

swift hamlet
#

So when the connection gets established, there would be a similar implementation of what Matchbox is doing, most clients would be able to direct message each other instead of going through a relay. Which is both lower cost and faster.

dire aurora
#

Yea, you'd probably need a custom transport in a backend for that ... I do something similar for my game (except I only have clients behind NAT but the server is a dedicated one without NAT issues), I handle an initial handshake trough a web API and that allows me to immediately connect afterwards

flat holly
#

Is there a preferred way with replicon how to despawn entities with an effect so that they are not removed instantly? (e. g. showing different animations if an entity dies, teleports away or going out of range etc.)

#

just an animation should be fine, can you explain the difference between fully use state and dead state? my first simple search would be something like, fully use state -> client can handle the identification itself, dead state, the server sends every state and client have to follow?

#

Ah I see, thats somewhat not yet defined since I would adapt it based on libs like replicon which works best

#

would you create a new entity on its own with the state on the server and sync or send the dead animation via channels

#

but I think thats actually it with the new entity then there are no conflicts of the order of changes

#

ok thanks I will give that a try

dire aurora
#

Despawning + spawning a new entity should work fine if I understand the way replicon handles despawns and spawns correctly

spring raptor
#

Replicating death component or some component removal is inefficient.
It's better to just despawn the entity on server, client replicates it and on despawn spawns a special decoy entity.

dire aurora
#

Yea the exception would be if the thing that died can come back to life, in which case you need to retain everything, and have some way to prevent them from moving

#

(That's the reason why death is a status effect in my game, tho I currently still just despawn enemies immediately when their HP hits 0)

thorn forum
#

hello :) on server commands.server_trigger(ToClients { mode: SendMode::Broadcast, event: () }); doesn't trigger the event locally if the feature client is not active, only the clients are triggered

swift hamlet
dire aurora
swift hamlet
dire aurora
spring raptor
#

@echo lion Quick remainder about the review ๐Ÿ™‚
After that I'll open a few PRs with fixes and cut a new release.

echo lion
thorn forum
dire aurora
#

The good news: The rollback example seems to function decently without nearly as many hacks as my own game had
The bad news: I suck at this example game thonk

brittle mulch
#

For some reason that made me notious very trippy

#

lol

dire aurora
#

You mean nauseous? Understandable with my poor driving skills + the awful controls + the complete lack of any references to comprehand what is happening ๐Ÿ˜‚

brittle mulch
#

yes nauseous

#

But it is nice too se a working physical sample in replicon

#

Congrats on your achievement

dire aurora
#

Now we can brag about how the worst rocket league clone in the history of rocket league is written with bevy_replicon thonk

spring raptor
spring raptor
thorn forum
spring raptor
thorn forum
#

alright then, but maybe we can improve the documentation to say the server_trigger are not received if the client feature is not activated

spring raptor
#

Will adjust docs soon, need to merge one big PR first to avoid conflicts :)

dire aurora
#

Not yet, but it's in a state where I could probably publish it soon, just need to make the two smaller crates compile again

#

And then solve the biggest problem: I don't have a name, so it's currently called some_networking_thing_idk ๐Ÿ˜‚

#

The repo has some stuff for entity disabling (might be able to remove that if I account for changes on main), entity management (mostly reusing existing entities if the spawn conditions are identical), input queue stuff, and of course rollback

brittle mulch
dire aurora
# brittle mulch Mind describing it I like to think I can help

It's basically a set of tools for networking more complex things on top of replicon, so the naming will probably be x_rollback, x_input_queue, etc ... See my previous message for the list of what I currently have in there ... Still need to add some clock sync stuff tho

swift hamlet
#

RepliconRewind? Or are you look for something more abstract?

#

RepliconImpulse?

spring raptor
#

Naming is so hard for me as well. I still don't have a good name for my life simulation game...

dire aurora
#

I do have a better name for it, I just haven't put in the tiny amount of effort to do the rename ๐Ÿ˜‚

spring raptor
brittle mulch
#

How about Mr Shatur, game of life

spring raptor
#

Game of life is also quite recognizable, it's an old school classic.
And a game named just "Harmonia" also exists ๐Ÿ˜ข

spring raptor
#

I wonder if I violate EA's IP by calling my game "Shatur's The Sims" ๐Ÿค”

brittle mulch
#

Probably yes

swift hamlet
#

The sims had other names before (during development):

  • Dollhouse
  • Home Tactics
  • People Simulator

Bur probably none of them have that certain feeling to it.

spring raptor
thorn forum
spring raptor
spring raptor
dire aurora
#

I could push the repo if you want to fix it, but I probably won't have much time to fix it for a while cause I've been focusing more on getting the CNC stuff done

spring raptor
dire aurora
#

Ah yea, 2 hours is definitely too short to fix this example ๐Ÿ˜‚

#

It's in a pretty rough shape

dire aurora
#

I guess with how long your presentation took it's good we didn't have fancy demos ๐Ÿ˜‚

spring raptor
#

It also was my first time going public like this. In the beginning of the presentation I was very nervous ๐Ÿ™‚
I'm an introvert person, but like to try new things.

#

So it was a stressful but interesting experience for me ๐Ÿ˜…

dire aurora
#

I think you did pretty well overall ... And unlike Jondolf you actually had a functioning microphone ๐Ÿ˜…

brittle mulch
#

Wait

#

I lost the presentation

dire aurora
#

It was streamed on youtube so you can just watch it back

#

I have to say the most disappointing part was when the 0.16 features were brought up and no one mentioned entity disabling ferris_sob

spring raptor
#

I definitely needed you there as a 3rd talker, I would be able to cut 4 slides ๐Ÿ™‚

dire aurora
spring raptor
#

True, I really just rushed through them ๐Ÿ˜…

dire aurora
waxen barn
#

great job

#

And honestly I find networking really hard to vocalize

spring raptor
#

Thanks!
You probably know all of this stuff, it's more for beginners ๐Ÿ™‚

dire aurora
#

Just wait until we get to part 3 and even Joy learns new stuff ๐Ÿ˜‚

waxen barn
#

hahaa

#

quantum entangled messaging system, true zero lag

spring raptor
#

Ah, yeah, I think the way we replicate in ECS might be new ๐Ÿ™‚

I also planned to make a small call for action in the end: encourage people to build their crates. It would be really nice to see a shooter-style rollback crate.
And things like the mentioned asset streameing could also be a neat crate that utilizes replicon.

#

But I forgot about that ๐Ÿ˜…

swift hamlet
#

Still hoping @dire aurora will release their crate this week ๐Ÿค—. At least thatโ€™s already one ๐Ÿ˜‰

swift hamlet
#

Is there a way in Replicon to add artificial lag, jitter and package loss?

spring raptor
swift hamlet
#

As far as I understood those work on the network interface and wonโ€™t work if you are testing with localhost? Or do they also allow you to test network conditions locally?

spring raptor
dire aurora
#

Yea I usually do this on localhost with some tc commands ... I have observed it to cause some undesirable side effects however, like adding latency to communication to the session API from both the client and the server ... As long as you're aware of what side effects it could cause it shouldn't be a major problem tho

dire aurora
swift hamlet
spring raptor
dire aurora
#

Also wish 0.16 included Resources as Entities ... The part where I do rollback on resources is easily the worst

#

I think I'll steal that "rewind" name, tho I still have to figure out how I'm going to make the subcrates sensibly structured ๐Ÿค”

spring raptor
#

Same, I really hoped for that.
Maybe use singletone entities in the meanwhile? Or do you have some third-party you want to rollback?

dire aurora
#

The only resource I use rollback on is Collisions from avian

#

Outside of that resources just aren't part of my game's simulation ferris_sob

spring raptor
#

Ah, from Avian, right...

spring raptor
#

But if we get a shooter-style rollback, it might be a bit confusing ๐Ÿค”

#

Maybe better go with bevy_replicon_rewind to clarify that it's for networking

dire aurora
#

Yea I'm planning to do bevy_replicon_rewind, tho I'd probably also claim bevy_rewind in case I ever make it generic across replication layers, or something like replicon gets upstreamed but rollback doesn't

#

Just gonna need to figure out how to name all the subcrates, there's the rollback, input queue, entity management, and disabling (still have to experiment on bevy main if this is still necessary tho)

spring raptor
#

Yeah, naming them as bevy_replicon_rewind_something would be weird

#

I remember you mentioned that they are fairly standalone? Maybe just call them bevy_replicon_something?

dire aurora
#

The input queue is standalone at least, would have to check for the other two

#

They aren't entirely separate tho, like you could use the input queue outside of rollback, but making your own input queue that plays well with this rollback would be annoying

spring raptor
#

Understandable.
I wish we could have scopes in crates.io

#

I would just put them under bevy_replicon_something even if some of them rely on rewind

dire aurora
#

Hmmm, entity management is coupled to rollback (which makes sense I guess, otherwise it ends up doing extra work for entities that aren't even predicted)
The other one I'm not super sure I can remove yet ... Upstream entity disabling has no counter in Disabled, nor does it trigger anything when you disable/enable entities ... Those triggers aren't super necessary but OnAdd/OnRemove observers would need filters (or we'd need query observers) to easily get the same behavior ๐Ÿค”

spring raptor
dire aurora
#

I think it would be viable in my game, I don't have all that many predicted entities, and the majority of them are the ones I'd need the observers for

#

I think it mainly depends on the timeline of this feature

spring raptor
dire aurora
#

Idk if I would necessarily say better, it lacks features because they would've been controversial, but this makes utilizing it much harder

dire aurora
#

I knew there was something I still had to do for the entity management crate ...

has_authority: (), // TODO

It doesn't support cases where server vs client isn't statically compiled ferris_sob

dire aurora
#

Ah yes, of course I can't get this working on 0.15 ... Would be difficult to get a working example on bevy main tho, considering they don't track main ๐Ÿค”

spring raptor
spring raptor
dire aurora
spring raptor
#

Ah, right!

dire aurora
spring raptor
dire aurora
#

Would probably be ideal ... Especially if we also want to mess around with the relations networking before the release ... Would be amazing if we the replicon release for 0.16 would include something for that ๐Ÿค”

#

Iirc the state of networking related entities is that the rework to make it possible was done, but the feature isn't there, right?

spring raptor
dire aurora
#

Yea the only thing we'd need is the ability to group them into the same packet ... And I guess a way to specify which relations should have that behavior (only ones where desynchronized state can cause problems would want this I guess?)

spring raptor
#

On second thought, if there weren't any insertions, spawns, or removals, but some entities changed their parents and the changes get split, it might be weird to see only half of the changes applied.

#

So you are right, we might better group related entities smartly

dire aurora
#

Yea, there's quite a few cases where them updating separately results in something that is wrong in some way

#

Which is why I currently still use that map for status effects (even if it is wildly inefficient because it now sends all of them when the map changes, rather than just the status that changed)

spring raptor
#

Definitely will try to look into it before the release

dire aurora
#

But yea it's definitely gonna be important to have some control over this ... Not every relation will need this, and even when we need it, it might not be needed for every instance, though I'm not sure if replicating huge hierarchies of replicated entities is currently a thing people do ๐Ÿค”

spring raptor
dire aurora
#

Yea without relations these usecases aren't easy anyway

#

The replication/rollback side of my status effects is a mess, but so is keeping the stupid map up-to-date ๐Ÿ˜‚

spring raptor
spring raptor
dire aurora
#

koe's main concern seems to be the removal of client ids

#

Which I guess makes some sense ... With things like he indexing feature on main (at least if that got merged) or a map from client id to entity we could have both pretty easily however ... The ergonomics of working with entities instead of maps with client id -> client data is definitely better tho

spring raptor
sand radish
#

I'm using bevy_replicon (with renet) and replication works fine, but when trying to get events to work, I get a panic with Called 'send_message' with invalid channel 2 (same but with receive on server side). I just use the default channel init, so I'm not sure if I'm missing something obvious here, anyone knows where to look further?

spring raptor
sand radish
spring raptor
#

Try running with RUST_LOG=bevy_replicon=debug cargo run ..., it should show us what you registering

sand radish
#

you mean add_client_event should be called before the insert_resource of client/transport?

#

doesn't seem to change anything if I change that order

#

```2025-03-07T19:25:42.448582Z DEBUG bevy_replicon_renet: creating channel config ChannelConfig { channel_id: 0, max_memory_usage_bytes: 5242880, send_type: ReliableOrdered { resend_time: 0ns } }
2025-03-07T19:25:42.448615Z DEBUG bevy_replicon_renet: creating channel config ChannelConfig { channel_id: 1, max_memory_usage_bytes: 5242880, send_type: Unreliable }
2025-03-07T19:25:42.448620Z DEBUG bevy_replicon_renet: creating channel config ChannelConfig { channel_id: 0, max_memory_usage_bytes: 5242880, send_type: ReliableOrdered { resend_time: 0ns } }
2025-03-07T19:25:42.448624Z DEBUG bevy_replicon_renet: creating channel config ChannelConfig { channel_id: 1, max_memory_usage_bytes: 5242880, send_type: Unreliable }
2025-03-07T19:25:42.448774Z DEBUG bevy_replicon::core::event::client_event: registering event gizmo::entities::Controller
2025-03-07T19:25:42.448784Z DEBUG bevy_replicon::core::channels: creating a client channel with ID 2
2025-03-07T19:25:42.577590Z DEBUG bevy_replicon::core::replicon_server: changing RepliconServer running status to true
2025-03-07T19:25:43.295525Z DEBUG bevy_replicon_renet::server: forwarding event ClientConnected { client_id: 0 }
2025-03-07T19:25:43.295622Z DEBUG bevy_replicon::server: ClientId(0) connected
2025-03-07T19:25:43.295637Z DEBUG bevy_replicon::core::connected_clients: adding connected ClientId(0)
2025-03-07T19:25:43.295645Z DEBUG bevy_replicon::core::replication::replicated_clients: starting replication for ClientId(0)

thread 'Compute Task Pool (6)' panicked at /home/ales/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/renet-1.0.0/src/remote_connection.rs:349:13:
Called 'receive_message' with invalid channel 2```

#

that's server

spring raptor
spring raptor
sand radish
#

aaah

#

that could use a warning section in the quickstart ๐Ÿ˜„

spring raptor
#

Yep, I definitely need to rework my quickstart guide. My todo before the next release ๐Ÿ™‚

spring raptor
sand radish
#

what's the expectaion of mapping "this entity is what the player on a client controls" ? I have things set up such that server is standalone and creates the whole world using replication, including the "player controlled" entity. How should the flagging be typically handled for the client? e.g. how can I inform a client "this newly replicated entity? that's your thing for controlling"

spring raptor
# sand radish what's the expectaion of mapping "this entity is what the player on a client con...

2 options:

sand radish
#

i mean I guess I could send the entity id over as an event to specific clients?

#

right ๐Ÿ™‚

#

thanks

sand radish
#

is it safe to use an Event as both an event and as a Component ?

#

e.g. I have a component on an entity, that's also an event I actually send over for event handling

sand radish
#

how does ParentSync work exactly? Do I assign it to the children entities, the parents, both? Do I need to register it for replication?

sand radish
#

and do I need to add it to app.replicate ?

#

ah no, works without that ๐Ÿ˜„

spring raptor
#

Won't be needed for Bevy 0.16. In 0.16 you will be able to just register Parent for replication.

#

Because of relations

#

In 0.15 this helper is still needed.

sand radish
#

how would you go about "hybrid" replication for physics simulated entities you don't want to fully replicate movement of (e.g. fast moving simulated projectiles)? I was thinking if I could somehow "init replicate" them with physical properties, but then let them simulate fully on the client that'd be best (of course "resolution" events would be server authoritative but that's out of the scope of this)

spring raptor
# sand radish how would you go about "hybrid" replication for physics simulated entities you d...

With the described approach you would rely on determinism. And it's really hard to guarantee.
I would recommend taking the Rocket League approach. In short: you simulate locally, the server sends you the state, and you correct it by rolling back the entire world to the last confirmed tick and re-simulating until your current timeline.
@dire aurora is working on a crate that implements this on top of Replicon ๐Ÿ™‚

sand radish
#

so e.g. a shot on the client will "fly through" and not impact a target unless the server replicates the despawn and impact info

#

I'd need to implement a sort of "init only" approach to replication on these tho, e.g. "create a shot with initial transform and velocity" through replication but then stop replicating transform

spring raptor
sand radish
#

it's a top down (2d plane) space shooter kind of game, using capital ships with mounted/aiming weapons

#

I'm hoping to come up with a replication scheme that will make it viable for up to 10 players

#

there will be hitscan but most things will be projectiles, physics plays a role since everything is essentially simulated and gravity is a gameplay mechanic (e.g. black hole, that sort of thing)

spring raptor
#

Then I would go with Rocket League approach

#

Is starts with physics, so skip to 23:30 for the networking part

dire aurora
#

Definitely sounds like a good usecase for the rocket league approach yes ... Things like projectiles are already kind of a pain with the shooter approach, but it gets so much worse when physics are involved

sand radish
#

I'll at least try and see how much discrepancy I get with the "init and forget" approach. My hope is if I rollback and re-apply the shot physics (e.g. move the shot physics simulation forward to "server time" on client side replication moment) it should minimize visible discrepancies. But I need to test this. Right now I'm just happy to have a jerky basic game going. Thanks for the library btw! it's great. I also love how ECS starts to click on all these things so nicely

sand radish
#

Am I correct in assuming that replication and events are not ordered in any order? e.g. if I spawn something replicating on the server and then send it's mapped entity over in an event, the client could get that event before the replication spawn on its end?

spring raptor
sand radish
#

Hmm, I'm seeing a very odd issue, not sure if it's bevy or replicon/bevy level. If I run my server and client (both render, but slightly in different ways) in one workspace (e.g. 2 windows side by side) things seem to work fine. If I put one on another workspace things get extremely choppy to the point of beeing frozen on both sides. And I don't mean just input event level things, even basic simulation on the server stops. Interestingly tho, debug log shows things such as client sending input events on mouse moves normally

#

even the initial connection sometimes takes like 10s when done like this, they both sit there, server reports connected, client reports connecting, but nothing happens for a while and when it does it's like 10s lag

#

I'm guessing it's a window focus issue

sand radish
#

nah, not focus, just "visible at all" issue. even unfocused, with continuous winit setting it works, but as soon as the server window is obscured completely it stops processing

#

works if I go headless

spring raptor
#

Merged connected clients as entities with all concerns addressed ๐ŸŽ‰
Planning to submit a few more minor fixes and draft a new release.

dire aurora
spring raptor
dire aurora
#

I like the general approach, but with the avian porting work I'm doing I'm just a bit confused about it

#

There's 3 traits for this now and they aren't all compatible

#

If they were compatible this could really cut down on a lot of multiplayer boilerplate tho ferris_sob

#

Could even get rid of mapped vs non-mapped if the trait can always provide the mapping and that gets optimized out when unnecessary

spring raptor
dire aurora
#

Yes and MapEntities also still exists

spring raptor
#

I agree, I don't quite understand why VisitEntities, VisitEntitiesMut are still needed, Component provide these methods

dire aurora
#

You also get some fun issues like how EntityHashMap can't be marked with #[entities]

#

Because it doesn't have VisitEntitiesMut

spring raptor