#lightyear

1 messages · Page 7 of 1

wintry dome
#

but on edgegap you have to set NATS_HOST etc as env vars in the application version config irrc

#

the matchmaker and other bits needs the env file, gameserver needs envs set in the edgegap settings

dreamy silo
#

Thanks for guiding

wintry dome
#

gl 🙂

#

getting a public nats instance up is probably the most annoying part tbh

dreamy silo
#

Will definitely try this

tulip violet
#

Does anyone have an example of changing the client transport once the bevy app is running (i.e. clicking a button etc to connect through steam vs local vs udp)?

wintry dome
stiff quiver
wintry dome
#

yeah step 1 is probably be disconnected.. make the change to clientconfig, then connect

#

never tried it myself

stiff quiver
#

should work given that connect() basically rebuilds everything needed

digital cedar
#

Hi I need help on hierarchy replication. How does the client recieve hierarchy replication, what special components do they have? and will they still be in a hierarchy? thank you :D

pine cape
pine cape
# digital cedar Hi I need help on hierarchy replication. How does the client recieve hierarchy r...

HierarchyReplication should be enabled by default. There is an internal component ParentSync used to sync parent/child relationships

You can see more here https://github.com/cBournhonesque/lightyear/blob/main/lightyear%2Fsrc%2Fshared%2Freplication%2Fhierarchy.rs

GitHub

A networking library to make multiplayer games for the Bevy game engine - cBournhonesque/lightyear

digital cedar
pine cape
#

Yes

sudden tendon
#

@pine cape I'm targeting bevy_remote so yeah just getting it ready for 0.15 via the RC1. Seems like you have it under control.

#

We can compare notes once you land next week or whenever

pine cape
#

If you already have some changes made, feel free to start a PR! It would be helpful for me as a starting point

sudden tendon
#

It will be a bit rough as there's no avian/leafwing/parry forks to refer to ATM. I will work something out with those and PR

pine cape
#

Just the lightyear changes is probably fine, for those it's probably better to just wait

#

Thanks a lot btw

sudden tendon
#

Agreed

#

No, thank you for all of your hard work on the crate. It's been a pleasure to use

#

I'm cooking up some editor/blueprint-esque stuff against this all. Looking forward to publishing that all but first things first with the 0.15

unkempt sedge
#

Question about this specific component in avian_2d example, Position. Where and how he gets updated? I cant seen to find it is like he magically just updates

#

Is he from lightyear itself? The imports are a little confusing

inner hill
unkempt sedge
#

Well it seens like rapier doesnt have that global rigidbody position.

#

It just directly apply to transform them global transform

unkempt sedge
#

oh boio this gonna be hard

unkempt sedge
#
pub(crate) fn replicate_inputs(
    mut connection: ResMut<ConnectionManager>,
    mut input_events: ResMut<Events<MessageEvent<InputMessage<CharacterAction>>>>,
) {
    for mut event in input_events.drain() {
        let client_id = *event.context();
        // Rebroadcast the input to other clients.
        connection
            .send_message_to_target::<InputChannel, _>(
                &mut event.message,
                NetworkTarget::AllExceptSingle(client_id),
            )
            .unwrap()
    }
}``` In the avian 3d example there is the replicate inputs to all other clients, I guess that is due to avian 2d example. But alas the entities in avian 3d are interpolated always not pre predicted like in 2d. Anyone know why is this here?
pine cape
#

Probably just a mistake

unkempt sedge
#

Avian 2d i think it is broken, gonna open a pr to slight fix both

pine cape
#

What is the issue with avian 2d?

unkempt sedge
#

It seens to be not be able to take input

#

In separate client and server mode

#

Might be something on my end tho

frozen carbon
#

sorry for the random question , I just don't know what I'm missing here 🥲

Resource requested by our_server::replicate_inputs does not exist: bevy_ecs::event::Events<lightyear::shared::events::components::MessageEvent<lightyear::inputs::native::input_buffer::InputMessage<shared_networking::PlayerActions>, lightyear::connection::id::ClientId>>

I added app.add_plugins(LeafwingInputPlugin::<PlayerActions>::default()); to the app, and the leafwing feature, is there something else necessary for this?

frozen carbon
dreamy silo
#

I havent managed to get it working with a nat yet. do you know when you get time writing a full tutorial for getting it running? i would appriciate it alot 🙂

wintry dome
#

I'll be back at it next week, when my kids are back at school 💪

unkempt sedge
#

oh god i finally manage to fully migrate my physics

#

Who did the spaceships example, deserves a godamm oscar

unkempt sedge
#

Well it seen when I add gravity into my game it breaks everything

#

oh god why

inner hill
#

did you filter for real entities

#

@unkempt sedge

#

vs confirmed from server ones

unkempt sedge
#

You mean apply the force only on entities predicted?

inner hill
#

and the ones on the server

unkempt sedge
#

oh

#

Yeah that does make sense

unkempt sedge
#

@pine cape Mr Peri, mutating the replicate components such as sync target and such will not adjust the type of replication? Like for example let say I change synctarget to one to all that wont automatically spawn predicted entities in all my clients if replication is default correct? I should use rooms correct?

pine cape
#

Mutating the components should work for some of them, for example the replication target. I'm not sure if it works for the sync target

unkempt sedge
#

I wonder what might cause that

#
fn listener_join_lobby(
    mut events: EventReader<MessageEvent<EnterLobby>>,
    mut lobbies: ResMut<Lobbies>,
    mut room_manager: ResMut<RoomManager>,
    player_entity_map: Res<PlayerEntityMap>,
    mut online_state: Query<&mut PlayerStateConnection>,
    mut connection_manager: ResMut<ConnectionManager>,
    mut commands: Commands,
) {
    for event in events.read() {
        let client_id = event.context();
        let lobby_id = lobbies.lobbies[0].lobby_id;
        info!("Inserted player {} unto lobby {}", client_id, lobby_id);
        lobbies.lobbies[0].players.push(*client_id);

        info!(
            "Added physics component in server for client id {}",
            client_id
        );
        add_physics_to_server_player(
            *client_id,
            &player_entity_map,
            &mut online_state,
            &mut commands,
        );
    }
}```
#

First he does this to the client that told to enter lobby

#

Them he does this for all client inside lobby[0]

#
 for client in lobbies.lobbies[0].players.iter() {
      if let Some(player) = player_entity_map.0.get(client) {
          info!("Inserted player unto room manager {}", player);
          // FOR NOW WE ONLY HAVE ONE ROOM
          let lobby_id = lobbies.lobbies[0].lobby_id.clone();
          room_manager.add_client(*client, RoomId(lobby_id));
          room_manager.add_entity(*player, RoomId(lobby_id));

          info!("Defining type of replicatinon for that player important to know he is from replication_group 1");
          let replicate = Replicate {
              sync: SyncTarget {
                  prediction: NetworkTarget::Only(lobbies.lobbies[0].players.clone()),
                  ..default()
              },
              controlled_by: ControlledBy {
                  target: NetworkTarget::Single(*client_id),
                  ..default()
              },
              group: REPLICATION_GROUP,
              ..default()
          };
          commands.entity(*player).insert(replicate);
      }
  }
#

Overiding replicate value to follow new logic

#

I think my question is, how does one. Tell server to start predicting new entities inside a lobby

pine cape
#

So the entity should be predicted by all players, not just one?

#

So the ReplicationTarget change takes effect (i.e. the entity gets replicated to the new player), but not the SyncTarget change?

unkempt sedge
#

My ideas was, first spawn the guy with a simple predict all. But when entering a room mutate his replicate so only players in that room should predict him

unkempt sedge
pine cape
#

Yes I think the way prediction/interpolation is design right now is a bit flimsy. It's purely a client concern but right now the setting is defined on the server which is a bit strange

sonic citrus
#

does lightyear support custom IO layers?

pine cape
sonic citrus
#

no world access there unfortunately

#

I've got some ideas anyway

pine cape
#

What do you have in mind?

sonic citrus
#

my IO layer is a component on an entity

#

I can probably use spsc

pine cape
#

but haven't had the time for that

#

also I'm waiting for relations to ship to make this kind of stuff easier

sonic citrus
#

what's your use case for relationships here?

pine cape
#

To be able to query stuff like Connected<ClientId> where maybe each ClientId would be a separate component

#

haven't thought it through to much

sonic citrus
#

ah right, you have a separate ClientId

unkempt sedge
unkempt sedge
pine cape
#

Hm the logic here would have to change: https://github.com/cBournhonesque/lightyear/blob/main/lightyear/src/server/replication.rs#L600
Right now i'm only updating replication if:

  • replication target gets updated
  • a new client gets connected

Maybe try updating the replication-target to only include the players in the lobby? In which case the logic in this function (which also handles prediction/interpolation) would apply.
Are you using rooms or ReplicationTarget::All currently?

GitHub

A networking library to make multiplayer games for the Bevy game engine - cBournhonesque/lightyear

unkempt sedge
#

Hmm, I think I just need to grab the ref to Sync Target

#

And do it

unkempt sedge
pine cape
#

I meant that you could try in your code to update the replication target, you wouldn't need to make a pr to lightyear

mighty mason
#

Hey I'm getting some compile errors related to leafwing?

#

I haven't used rust in awhile not sure what all of this is

inner hill
#

@pine cape sorry, haven't been able to make a repo for the rollback stuff yet

#

been busy with contract work

digital cedar
#

u need to make sure all of the enums are convered

mighty mason
#

I thought it was

#

cause it doesn't happen while compiling my code its while compiling lightyear

digital cedar
#

oh looks like it is...

#

are u using a leafwing version that is different from lightyear?

unkempt sedge
#

So what you are telling me is to change replication target from all to only lobby players? That oughta sync it

#

Oh my gawd

#

It worked

#

I sometimes ask myself if you are a wizard

unkempt sedge
#

this is for u

wintry dome
#

@dreamy silo ^

#

i'm also in the middle of changing bevygap client plugin to use a websocket to talk to the matchmaker

#

so these docs aren't in sync with main atm

unkempt sedge
#

Like it scales up and down

#

According to user amount?

wintry dome
#

it's a system to automatically deploy servers in response to player demand, around the world

#

using Edgegap

#

so the flow is the game client clicks connect, the matchmaker waits while edgegap starts a new server near your players or finds an existing on, and then you pass back the server details to the client so it can make the lightyear connection

#

full tutorial pending..

dreamy silo
#

Definitely helpful

#

Will try setup later tonight or tomorrow

wintry dome
pine cape
pine cape
unkempt sedge
#

but it is ifey

#

Sometimes works sometimes doenst

pine cape
#

hm, yea it's just a stopgap solution

unkempt sedge
#

hahahahaha

#

First need to set to none replication target

#

them change as if it is the same client it does not consider as changed

#

NOW animations

#

and gravity that doesnt break everything

pine cape
#

very nice!

mighty mason
#

I'm not sure what I'm doing

#
[workspace.dependencies]
bevy = "0.14"
bevy_egui = "0.30"
bevy-inspector-egui = "0.27"
serde = {version = "1.0.188", features = [ "derive" ]}
bincode = "1.3.3"
avian2d = {version =  "0.1.1", features = ["serialize"]}
lightyear = {version = "0.17" , features = [ "leafwing", "avian2d" ] }
leafwing-input-manager = "0.15"
pine cape
#

this uses the version 0.17 version of lightyear

mighty mason
#

?

#

what version do I change it to?

pine cape
#

you should use something like lightyear = { git = "../path/to/git/repo", branch = "main" }

mighty mason
#

oh alright

pine cape
#

yes

mighty mason
#

alright thank you

#

oh it works nice

mighty mason
#

I'm sorry for bothering you again but I'm getting another error

resource does not exist: lightyear::protocol::component::ComponentRegistry```
dreamy silo
# wintry dome cool, see if you can get to the point where nats-cli is connecting. the bevygap ...

I did take a small dive tonight. Good guide so far. I also took another look at synadia cloud’s option and that was definitely alot easier to setup in terms of stuff needed for the nats cli context. JWT based, just had to give it a .creds file. Their free tier would be nice to use now during development. I just need to tweak your crate a lil and add a optional nats async connection option using creds or creds file in bevy_shared

pine cape
mighty mason
#
thread 'main' panicked at C:\Users\poopn\.cargo\registry\src\index.crates.io-6f17d22bba15001f\bevy_ecs-0.14.2\src\world\mod.rs:1867:32:
resource does not exist: lightyear::protocol::component::ComponentRegistry
stack backtrace:
   0: std::panicking::begin_panic_handler
             at /rustc/f6e511eec7342f59a25f7c0534f1dbea00d01b14\library/std\src\panicking.rs:662
   1: core::panicking::panic_fmt
             at /rustc/f6e511eec7342f59a25f7c0534f1dbea00d01b14\library/core\src\panicking.rs:74
   2: bevy_ecs::world::World::resource_scope<lightyear::protocol::component::ComponentRegistry,tuple$<>,lightyear::protocol::component::impl$4::register_component::closure_env$0<common::player::PlayerId> >
             at C:\Users\poopn\.cargo\registry\src\index.crates.io-6f17d22bba15001f\bevy_ecs-0.14.2\src\world\mod.rs:1867
   3: lightyear::protocol::component::impl$4::register_component
             at C:\Users\poopn\.cargo\git\checkouts\lightyear-2cfb5e6660946fe3\12b95e7\lightyear\src\protocol\component.rs:1066
   4: common::player::register
             at .\common\src\player.rs:16
   5: common::register
             at .\common\src\lib.rs:48
   6: server::main
             at .\server\src\main.rs:34
   7: core::ops::function::FnOnce::call_once
             at /rustc/f6e511eec7342f59a25f7c0534f1dbea00d01b14\library\core\src\ops\function.rs:250
mighty mason
#

oh it's just cargo clean

#

mb

#

is there a new way of setting up lightyear now?

pine cape
#

no, nothing changed

wintry dome
mighty mason
#

I cleaned it out completely and nothings changed

unkempt sedge
#

So I have the following issue with leafing input, I already have a predicted client spawned and aligned with in my server. And it tries to reproduce it is input message to my current client, even tho he doesnt even have a replicated confirmed entity. Any ideas on what might be causing this?

#

2024-11-06T10:27:39.002115Z ERROR lightyear::client::input::leafwing: received remote player input message for unrecognized entity The error message

#

Oh found the reason.

unkempt sedge
#

@wintry dome Hey Rj might I ask you something, in the spaceships example you add input staleness. What happens in live games, if you dont do that? Stutter teleportin and such?

wintry dome
#

it's so you can decide how many frames ahead you want to predict inputs from remote players. if your prediction is wrong, your client does a rollback to reposition players, which will look like a stutter in some cases

#

perhaps you think it's ok to assume same inputs as previous frame, for up to 5 frames, after that you assume no inputs. pretty safe to just ignore entirely to begin with i think, bit of a niche case

unkempt sedge
#

I tought lightyear had that imbued, then I noticed your comment

        // config.prediction.maximum_input_delay_before_prediction = settings.input_delay_ticks;```
wintry dome
#

i think lightyear may have changed those settings since i wrote spacehsips code, not sure though

unkempt sedge
pine cape
#

Only a fixed input delay currently works, the other input-config settings cause some issues

frozen carbon
unkempt sedge
#

But client wasnt yet replicating

#

So basically i needed to set replication to only lobbie

unkempt sedge
#

I found out that constant collisions caused a lot of jittering

#

And flickering

#

No idea why

frozen carbon
frozen carbon
river perch
#

Anyone have an example of how to use tnua-controller with lightyear and avian? The main issue I'm having is: the host player's movement is choppy for the non-host clients, while the clients' movements are fine on the host server's game. I'm wondering which components I need to replicate to the clients so they can properly interpolate the movement of the other players

pine cape
#

Try replicating GlobalTransform, i think that's what tnua uses under the hood

river perch
#

thanks I'll give it a try

#

in addition to avian's Position, or just GlobalTransform?

pine cape
#

Just globaltransform

river perch
#

i guess I should be replicating Transform too? seems like just replicating GlobalTransform, it gets out of sync with Transform on the Predicted entity on the client. I guess since GlobalTransform is built from Transform each frame, not the other way around

#

looks like tnua is just updating avian's LinearVelocity and AngularVelocity every frame, maybe it's enough to replicate those plus Position/Rotation. I will play around with that

unkempt sedge
#

god i have an stability issue that i have no idea what causes it

#

So annoying

#

man i swear to god everytime i cry in here i find the reason why it is amazing

pine cape
river perch
# pine cape You need to replicate all the components that let you do prediction on the clien...

is this the example you mentioned? https://github.com/panjeet/networked_cube_test/blob/master/src/protocol.rs. Looks like they commented out their GlobalTransform replication at some point, with the commit message:

try only syncing transform, and sync linearvelocity to the current player
https://github.com/panjeet/networked_cube_test/commit/7b43891cf45fc0d5fd51ee84f730ca58da65bc4d#diff-d8c31d407e43532e4152070bdaf92d7fff58c81b39b4308cad7c769519d31376. who knows which approached worked better 😆

pine cape
#

yes that was the one! Maybe try both then 😛

river perch
#

will do. appreciate the help!

calm gale
#

Is there any video tutorial for lightyear? The lightyear book example ain't that great to follow.

wintry dome
calm gale
#

They are all based on the same starter example.

unkempt sedge
#

You know what I think i am gonna do a cris and make a tutorial video on lightyear

calm gale
#

Would be lovely

unkempt sedge
#

But I can give you a short summary

calm gale
#

Might just also be, because i'm trying to split the code out more. Like separate app directory for server and client

unkempt sedge
#

Is better to follow the common examples crate

#

IF you are a newbee to network games

wintry dome
#

i have a version of the spaceships example split into a dedicated server (no gui) and client, and shared. if you build without default features per the readme i think the bevygap bits get out of the way. https://github.com/RJ/bevygap-spaceships it only supports webtransport.

calm gale
#

@wintry dome nice i'll take a look at that. Yeah I'm trying to go more towards a microservice setup with event driven message bus design and such

#

The use of nats is intresting. It's a combo of redis and kafka as far as i see

wintry dome
#

yeah, you need comms between the game servers and the matchmaker bits, and need a bit of key/val storage for config, so it made sense.

#

maybe i should have used redis, it's easier to deploy 🙂

calm gale
#

uhu i was thinking to use kafka, dragonfly and scylladb.

wintry dome
#

that's a lot of infrastructure

#

depends on your game i suppose

calm gale
#

i'm a infra kind of guy 😄

wintry dome
#

heh

#

no one inflicts that on themselves otherwise 😛

calm gale
#

for me it's more to learn about a high scaling infra for something like a game. Not the game itself 🧐

#

it's pretty easy to spin up such a thing in docker together with prometheus/grafana for data gathering

dreamy silo
#

I realize good infrastructure is incredibly important in multiplayer games, especially MMOs

calm gale
#

yeah. Also if you can split off the lobby manager. You can spin up new containers per lobby for example

#

that's why i like the prometheus support in bevy. Means you can monitor everything and scale on the load info of that for example

dreamy silo
calm gale
#

in theory yes. That's sort of how they do it. Don't know how far lightyear supports it

sonic citrus
#

I'm looking at the Transport trait now, what are the guarantees I have to uphold for the packet sending and receiving? And how are the SocketAddrs used? (Especially on platforms like steam which don't use socketaddrs directly to identify clients)

#

My end goal is that network connections are represented as entities with the Session component in aeronet, and I want packet sending/receiving to go through Session::send: Vec<Bytes> and Session::recv: Vec<Bytes>. Just wanted to ask what the general process would be for enabling this. Probably would involve an mpsc/spsc somewhere?

pine cape
#

Transport is to send raw bytes to a socketaddr, and then you have the ClientConnection and ServerConnection traits to build connections.
Connections don't have to reuse the transport logic if the connection already has a way to pass bytes

#

For example for steam

#

I don't think having connections be entities is possible in the current design, you would have to make a PR to change how lightyear stores the ClientConnection and ServerConnection (which are in a resource currently)

bronze elm
unkempt sedge
#

Avian 3d example is also extremely vulnerable to breakage and sync issue

#

@pine cape mind if I refactor it adding forces like gravity and such?

#

Elements when ststionary try to correct even tho they are perfectly aligned in server

sonic citrus
#
pub enum ServerConnection {
    Netcode(Server),
    Steam(Server),
}

looks like this might not be possible, since the connection is hardcoded 😕

river perch
#

The client's controlled entity is a little bit jittery still so not perfect, but definitely working a lot better than before. Still gotta fine tune it

dreamy silo
#

Would it be possible to serve multiple worlds on the same light year server, just different ports?

bronze elm
boreal inlet
boreal inlet
wintry dome
#

@boreal inlet i've run into the "ring breaks wasm builds" issue a couple of times, trying to remember how i solved it. i've also run into a gnarly silent linker failure that only causes issues at runtime (a js issue), which is fixed by using clang instead of gnu cc, at least on my machines. i build wasm with these flags:

TARGET_CC=/usr/bin/clang RUSTFLAGS=--cfg=web_sys_unstable_apis CARGO_BUILD_TARGET=wasm32-unknown-unknown cargo build etc..

i skimmed your pr to remove ring, and that seems helpful.

unkempt sedge
#

Avian physics example is broken the cubes dont movee

unkempt sedge
#

@wintry dome Rj I dont know if you have a better understanding than me when it comes to the visual interpolate. But from what I understand he should be attached to the visual entities that have position and rotation correct?

#

In my case scenario I have child entities that move based on transform, but well they are based on my rigidbody postion

#

Should I attach that component to them or nah?

unkempt sedge
#

goddamm

#

Found out what was my issue

#

camera following

#

LOL

wintry dome
unkempt sedge
#

FINALLY

wintry dome
#

looks smooth 😎

wintry dome
unkempt sedge
dreamy silo
#

Wait, should a camera that follows be on visual interpolation?

unkempt sedge
#

No, it should follow transform normally, but it need to be set after physicsset sync, and before transform propagate

#

You can also try to make it follow the vec3 from position as that also would be interpolated

#

BUT

#

when rollback or lag spikes occur camera would teleport

#

@wintry dome Do you know what this guy sets? max_prediction_ticks: 100? I dont find him anywhere in config and in docs

wintry dome
river perch
unkempt sedge
#

I would say you need to put your camera slightly upfront of your predicted entity

#

And follow predicted entity transform. With an offset that keeps player camera slightly ahead of model head.

river perch
#

I see, the camera transform can be set after the physics and correction has finished

#

im actually just not spawning a player model for the controlled player right now, so you won't see a head or anything in the way

unkempt sedge
#

hold up i have code for you, that way you can just follow along

river perch
#

nice!

unkempt sedge
#
pub fn sync_player_camera(
  
    player_q: Query<&Transform, (With<Predicted>, With<Controlled>)>,
    mut cam_q: Query<(&mut CamInfo, &mut Transform), Without<Predicted>>,
) {
    if let Ok(player_transform) = player_q.get_single() {
        let (cam, mut cam_transform) = cam_q.get_single_mut().expect("Camera to exist");

        let rotation_matrix = Mat3::from_quat(cam_transform.rotation);

        // Offset actually
        let offset = rotation_matrix.mul_vec3(Vec3::new(0.0, 0.5, cam.zoom.radius));

        // Update the camera translation
        cam_transform.translation = offset + player_transform.translation;
    }
}
river perch
#

I just separated my camera from the player, just observing the scene from above now, and I noticed the jittering on the player is still there, so there must be some other correction issue unrelated to the camera I must solve 🙃

river perch
#

what does your Replicate config look like?

#

I've got this:

Replicate {
    sync: SyncTarget {
        prediction: NetworkTarget::All,
        ..default()
    },
    controlled_by: ControlledBy {
        target: NetworkTarget::Single(client_id),
        ..default()
    },
    hierarchy: ReplicateHierarchy { recursive: false },
    group: REPLICATION_GROUP,
    ..default()
}
unkempt sedge
#

Oh yeah zoom i think zoom needs to be upfront so probably negative

unkempt sedge
river perch
#

are you using bevy_tnua for movement?

#

I heard that might be an issue, seems difficult to get it to work with lightyear

unkempt sedge
#

No wouldnt dare use it for me it is api is a little too confusing

river perch
#

ah okay

unkempt sedge
river perch
#

that's just with

app.add_plugins(LeafwingInputPlugin::<PlayerAction>::default());

right?

unkempt sedge
#

No your server need to replicate it back to your client

#

Is like hey me client am being predicted take my input -> takes inputs -> okay here is your input by me so we can sray aligned server

river perch
#

Oh I see. right now just Position is being sent back to the client, not the server's account of the inputs, so it just teleports?

#

LeafwingInputPlugin does include

app.register_component::<ActionState<A>>(ChannelDirection::ClientToServer);

but I guess that doesn't replicate back to the client? I am a bit unsure about how this works tbh

unkempt sedge
#

No that just debugs

main grove
#

is there any way to run lightyear servers on arm? or a way to disable steamworks because that is creating issues when trying to host a server from the examples on my arm server

wintry dome
#

i think the examples in the repo enable all the transports by default including steam

main grove
wintry dome
#

(it just uses webtransport)

fervent karma
#

Hey, I'm just setting up a HostServer, and it seems to work pretty seamlessly with the existing code I have for networked clients, but I was wondering what happens when I set things like prediction for local players. Should I make sure that I don't set that, or will lightyear realize that local clients shouldn't be predicted even though I requested it?

boreal inlet
unkempt sedge
#

Has anyone here even ran into the issue where if server replication send interval is low about 10 ms, we get constant rollbacks? \

#

I think only mr peri can solve that one

sonic citrus
#

is it possible that ClientTransport and ServerTransport could be turned into traits?

pine cape
pine cape
unkempt sedge
fervent karma
unkempt sedge
#

So I have the following struct

#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, Component, Reflect)]
pub struct SunPosition(pub Quat);

impl SunPosition {
    /// Spherically interpolates between two `SunPosition`s by `t`, where `t` is a factor between 0.0 and 1.0.
    /// `t = 0.0` will yield `self`, and `t = 1.0` will yield `target`.
    pub fn slerp(&self, target: &SunPosition, t: f32) -> SunPosition {
        SunPosition(self.0.slerp(target.0, t))
    }
    pub fn default() -> SunPosition {
        return SunPosition(Quat::from_rotation_x(-std::f32::consts::PI / 4.));
    }
}```
In protocol
```app.register_component::<SunPosition>(ChannelDirection::ServerToClient)
            .add_interpolation(ComponentSyncMode::Full)
            .add_interpolation_fn(SunPosition::slerp)
            .add_correction_fn(SunPosition::slerp);```
#

I move them in server like this

fn tick_sun_cycle(
    mut cycle_time: ResMut<CycleTimer>,
    time: Res<Time>,
    mut suns: Query<(Entity, &mut SunPosition), With<SunMarker>>,
) {
    cycle_time.0.tick(time.delta());
    for (sun, mut sun_position) in suns.iter_mut() {
        if cycle_time.0.finished() {
            let t = time.elapsed_seconds_wrapped() / 2.0;
            info!("Sun should move");
            sun_position.0 = Quat::from_rotation_x(-t);
        }
    }
}```
wintry dome
dreamy silo
#

Resource requested by <ProjectName>::shared::shared_plugin::handle_hit_event does not exist: lightyear::server::connection::ConnectionManager

use lightyear::prelude::*; should get it right?

#

I split my .rs files into folder in src/, tying them together using pub use and mod.rs file in each folder. how do I make sure this resource is available across these folders? shared, client, server.

#

also struggling to read events in src/server/server_plugin.rs that is written in src/shared/shared_plugin.rs. not sure what thats all about. event has been added in shared_plugin.rs using app.add_event::<BulletHitEvent>();...and in server_plugin.rs fn handle_hit_event system is on .run_if(on_event::<BulletHitEvent>() after system process_collisions which should be working right? this exact logic is almost identical to the one found in the spaceships example.

#

I tested and event reader and writer works well if I put handle hit event system which is in server.rs originally , and move it to run locally inside shared.rs. But I don’t want server authoritative code to run on shared.rs. Not sure what I’m missing here.

wintry dome
dreamy silo
#

I’ll probably have to do some digging.

dreamy silo
#

ok so connectionmanager only lives on the server. cant run it anywhere else thats understood.

dreamy silo
#

know other events work on server because it handles connections fine. which are triggered on connection events. very strange. bleh

stiff quiver
#

@pine cape maybe it would make sense to use the existing easing capabilities of bevy_math for interpolation instead for 0.15? thonk

fervent karma
#

Heyy, I'm trying send over a list of entities to the server (to update their targets), but I can't find a way to convert the client local Entity ids to the server ones, do I have to hand roll it?

#

I expected each replicated entity to have a component that is their Server Entity, but I can't find anything like that. I found lots of EntityMaps, but I can't figure out how to make use of any of them

unkempt sedge
#

Their network targets?

fervent karma
#

Nono, they're minions that move towards a target, and that's what I'm updating, just wanted to give a tiny bit of context, but I think I made it more confusing 😋

dreamy silo
#

Does lightyear help with replication of events?

dreamy silo
#

Like other than network related ones

pine cape
pine cape
dreamy silo
# pine cape It's not handled automatically for now, you would have to create your own Messag...

Then I’m not sure how BulletHitEvent is actually reaching server and every other client. Works when I run the spaceships example. Doesn’t work when I try to implement it in my own code exactly the same way. Tried reading the reader locally in the same file it’s being sent (shared.rs) and that works fine. Also works fine in client code (client.rs). Anything I’m overlooking? or any clever way I can debug this? @wintry dome

Shared event sender:

https://github.com/cBournhonesque/lightyear/blob/7d714079a540f3d0233a084de5a0603c7fc5caa9/examples/spaceships/src/shared.rs#L422

Client receiver (works both here and in my code):

https://github.com/cBournhonesque/lightyear/blob/7d714079a540f3d0233a084de5a0603c7fc5caa9/examples/spaceships/src/client.rs#L53

Server receiver (not working in my code, but works fine here):

https://github.com/cBournhonesque/lightyear/blob/7d714079a540f3d0233a084de5a0603c7fc5caa9/examples/spaceships/src/server.rs#L65

event struct (works both here and on my end):

https://github.com/cBournhonesque/lightyear/blob/7d714079a540f3d0233a084de5a0603c7fc5caa9/examples/spaceships/src/protocol.rs#L154

GitHub

A networking library to make multiplayer games for the Bevy game engine - cBournhonesque/lightyear

GitHub

A networking library to make multiplayer games for the Bevy game engine - cBournhonesque/lightyear

GitHub

A networking library to make multiplayer games for the Bevy game engine - cBournhonesque/lightyear

GitHub

A networking library to make multiplayer games for the Bevy game engine - cBournhonesque/lightyear

fervent karma
wintry dome
#

if you do an info! log at the point where shared::process_collisions emits the event, do you see that on both client and server? you should do

#

iirc the server uses that event to update the scores, and clients use it to show explosion effects

#

make sure you've only defined BulletHitEvent once and both client and server code are referring to the same struct

#

are you carving up spaceships into a new split server/client arrangement? i'll have a look if you've got a github link or something

unkempt sedge
#

Question I made a sun orbit timer, that is constantly being ticked by server should I make it so he has a unique channel for it. Would that make his ticks more continously? Avoiding slight time desyncs?

dreamy silo
wintry dome
#

some system should be reading avian physics collisions and using a EventWriter<BulletHitEvent> to emit those events

#

in spaceships, process_collisions is in the shared plugin, so runs on server and clients.

#

heading out for bit, back in a couple of hours

dreamy silo
stiff quiver
#

otherwise yes, having an ordered unreliable channel for that would make sense imo

wintry dome
#

@viva what's the easiest way to cause a collision? i just see my ship on the client

unkempt sedge
#

I made a resource that is ticked by server

#

replicate it to client, client moves according to resource timer

#

Thanks for the tip RJ avoiding the structuring in server spared me some time

wintry dome
dreamy silo
#

Right. I did that for testing.

wintry dome
#

server plugin shouldn't call add_event, just shared. dunno if that matters

dreamy silo
#

Shared should only do it I remember correctly

#

Didn’t matter for my part

wintry dome
#

also, although commented out, be careful about your debug_events, if you consume the EventReader<> in an Update system, the events will be gone before a FixedUpdate system runs

#

stick to only reading the events in FixedUpdate

dreamy silo
#

Agreed

wintry dome
#

what's the easiest way to cause a collision so i can test

dreamy silo
#

Run server, then two clients c0 and c1

#

Then shoot the other using arrows and space

#

From either client doesn’t matter

wintry dome
stiff quiver
# unkempt sedge I did that

ok let me explain what i actually meant:
lightyear automatically tells the client the servers tick, now think of the server tick as a "seed" for the timer, if you then have the client use the same seed for its local timer you dont need to send anything (other than the server tick which the server automatically syncs).

#

ofc its a minor optimization at best but in prod we want to minimize bandwidth as much as possible

stiff quiver
unkempt sedge
#

I have no idea how to get lightyear timer

wintry dome
stiff quiver
wintry dome
#

i'm not convinced the server is even spawning the bullet. add some logging to the code that processes player inputs and make sure that a bullet spawn happens on the server.

#

probably the fact that player inputs are rebroadcast means it looks like it's working on the other client, but the server isn't moving or spawning bullets

dreamy silo
#

thanks for the pointer

#

avian3d not working properly in server prob

#

its debugging the colliders tho

#

the ships are just small dots inside the box on server

wintry dome
#

but is the server spawning bullets in response to keypresses on clients?

dreamy silo
#

good question. theyre spawning on both clients at least

wintry dome
#

player inputs are replicated, which is separate from whether the srver does it

dreamy silo
#

will debug some more later tn

#

thanks

unkempt sedge
#

@wintry dome Do you know of a way of cuptaring failure to connect?

#

Need to adapt my ui when occurs

dreamy silo
wintry dome
wintry dome
unkempt sedge
#

I think I will just make an UI system that gets state when so, basically get stuck in main menu

#

And you can try to reconnect now that i have no idea how to do that

desert saffron
#

is there any plans to bump lightyear to the 0.15-rc anytime soon?

dull lion
unkempt sedge
#

Yeah if noone is available I will do it, but I dont know the release candidate is just about finished perhaps just wait for 0.15

river perch
#

Hello, I copied this replicate_inputs system from avian_3d_character example:

pub(crate) fn replicate_inputs(
    mut connection: ResMut<ConnectionManager>,
    mut input_events: ResMut<Events<MessageEvent<InputMessage<CharacterAction>>>>,
) {
    for mut event in input_events.drain() {
        let client_id = *event.context();
        // Rebroadcast the input to other clients.
        connection
            .send_message_to_target::<InputChannel, _>(
                &mut event.message,
                NetworkTarget::AllExceptSingle(client_id),
            )
            .unwrap()
    }
}```
but it doesn't send messages for the `HostServer` client. For example, if I have 3 clients (1 host server + 2 more), the 2 non-hosts receive each other's inputs, but they do not receiver the host's inputs. Is there a simple way to emit the host's inputs as well?
pine cape
#

Hm it should work, that might be a bug

#

In general I would copy the avian_physics example, I think it's more trustworthy

#

But this looks like it should definitely work. Could you please open an issue?

river perch
#

Thanks. I can investigate further/open an issue later today or tomorrow

unkempt sedge
tardy swallow
river perch
river perch
#

For context, what I'm trying to do is change each player model's animation based on that player's inputs. For example, walk animation if WASD are pressed, otherwise, idle animation. Originally I was just going to use things like velocity to determine the animation, but I don't want a walking animation if a player gets moved by something else for instance

unkempt sedge
#

pub(crate) fn replicate_inputs(
mut connection: ResMut<ConnectionManager>,
mut input_events: ResMut<Events<MessageEvent<InputMessage<CharacterAction>>>>,
) {
for mut event in input_events.drain() {
let client_id = *event.context();
// Rebroadcast the input to other clients.
connection
.send_message_to_target::<InputChannel, _>(
&mut event.message,
NetworkTarget::AllExceptSingle(client_id),
)
.unwrap()
}
} yes you are

#

try just all

unkempt sedge
unkempt sedge
#

everything is clear now

unkempt sedge
#

Might I ask why you do this, is an optimization technique?

wintry dome
#

do what, use the .after bit, or the run_if?

unkempt sedge
#

run_if

#

After is also interesting but i theorize is because you wanna despawn bullet first so two collisions dont do two damage

wintry dome
#

it's an optimisation to only run if there's an event to process, but also to self document so you know it's only needed for events. it was written before observers existed, perhaps observers would be more appropriate now

#

nowadays BulletHitEvent could be triggered instead of EventWriter'ed i think, then you could use an observer.

#

the /after is because process_collisions turns the avian physics collision data into BulletHitEvents, without the after you may end up processing the collision one frame later (eg if handle_hit_event ran before process_collisions)

stiff quiver
wintry dome
stiff quiver
unkempt sedge
split zealot
#

did you ever fix this? the same log spam issue exists for the reverse situation: when a server disconnects and the client cannot receive any packets.

#

for now i've forked the project and emit a new event so my user-space code can detect a connection error

dreamy silo
#

How lightyear doing for coming 0.15 release?

pine cape
#

I can do some of the bevy changes, but we'll have to wait for leafwing/avian to have 0.15 branches

pine cape
#

there is one test failing for some reason

stiff quiver
#

Yea seems to be the case

#

it never really worked soo shrug

pine cape
#

No it's another one

digital cedar
#

I have a question on spawning a scene from glb and then perform the networking ncessary for sub objects, what are the ways I can achieve this?

How do i spawn on server and client and have them both sync up afterwards?

pine cape
#

I think a scene is just an entity with some children entities, right?
I would either add Replicate to the parent of the scene, and all the children will get replicated recursively (if their components are registered)
or just add the scene on the client if some Message or Event has been received

stiff quiver
unkempt sedge
unkempt sedge
#

well fuck me

#

WHY in tarnation it is so strong

unkempt sedge
# stiff quiver Yes

Hmm thing is my camera should also have a input map if she also is moved according to motion, I wonder if that is going to cause desyncs

split zealot
#

do the examples still work with steam?

#

doesn't seem to work for me, I'm trying out the lobby demo and after fixing the egui version mismatch i get this

2024-11-20T21:29:28.805964Z  INFO lightyear::connection::steam::server: Steam socket has been closed.
CreateBoundSocket: ::bind couldn't find an open port between 27016 and 27016
thread 'main' panicked at lightyear\src\connection\server.rs:162:18:
could not create steam server: SteamInitError(FailedGeneric("InitGameServer failed"))

my existing steamworks code works (i was using renet before), so i know it should be able to work, i'm not sure what i'm missing to get these examples running with steam

dreamy silo
young prawn
#

has been since Nov 1st

#

but no actual release yet

dreamy silo
#

Sweet

#

I didn’t actually check, sorry about that

young prawn
#

no worries :)

dreamy silo
#

Leaf seems to be too? Just not released yet either

#

Oh my bad that’s LW release

#

Not related to bevy version

stiff quiver
#

@pine cape what do u think about having custom data in connect tokens? Kinda like jwts

#

Or maybe the correct approach would be to associate the data with the connect token and sign that somehow

#

hm

#

like the problem is that if you dont want to / cant communicate from ur game server to your backend but still want to have verifyable data from the backend u need to somehow associate that with the session & sign/encrypt it with a shared key

wintry dome
#

there is a small user data field isn't there? or am i remembering renet instead

stiff quiver
wintry dome
#

256 bytes of USER_DATA i think

wintry dome
#
    /// Sets the user data that will be added to the token, this can be any data you want.
    pub fn user_data(mut self, user_data: [u8; USER_DATA_BYTES]) -> Self {
        self.user_data = user_data;
        self
    }

from the ConnectTokenBuilder

stiff quiver
#

ah

wintry dome
#

you could pass small stuff like a nickname or something in that maybe

stiff quiver
#

256 aint a lot

wintry dome
#

the connect tokens are already signed, so once a connection is established you can trust stuff the client sends you

stiff quiver
#

maybe im overthinking it and should just communicate with the backend from the gameserver

#

tho i dont really like it

wintry dome
#

oh sorry you're talking about comms from client to backend which is separate to the gameserver..

stiff quiver
#

yes

wintry dome
#

yeah i think you need your gameservers to be able to talk to your backend services somehow

#

i'm using NATS for that, since it's pubsub and also KV storage

stiff quiver
#

Ah okay

wintry dome
#

if you don't need to expose it to the web, redis might be a decent choice too

#

but whatever you choose it's a bit annoying because you probably want to talk to it async from your bevy game server, so you have to do some plumbing..

unkempt sedge
wintry dome
unkempt sedge
#

But it is weird is like as I override it resets

wintry dome
#

that's for 2D, so the player turns towards where the mouse cursor is

river perch
#

Hey, anyone notice that the avian_physics example is a bit broken in main right now? Running in host-server mode right now. The client's box isn't moving in the client's game, but it is moving on the host server's client

#

the red box on the client, as far as I can tell, has PrePredicted, but not Predicted. There is also an entity on the client side with the single component Confirmed, pointing to the PrePredicted client box

#

If I spawn a 3rd client, both clients spam the following error message in the logs:

2024-11-21T16:22:47.572310Z ERROR lightyear::client::input::leafwing: received input message for unrecognized entity entity=Entity { index: 55, generation: 1 } diffs=[[], [], []] end_tick=Tick(32002)

#

And neither can see each other's box. The host-server can still receiver the clients' inputs and control the 3 player's boxes just fine though

#

I'll open an issue on github

river perch
split zealot
pine cape
# river perch https://github.com/cBournhonesque/lightyear/issues/701

Thanks, I found the issue. I recently distinguish between Replicated (an entity that is currently being replicated from the remote) and InitialReplicated (an entity that was initially spawned from a remote).
In the case of pre-prediction, the current ordering is:

  • client spawns entity with PrePredicted
  • server receives it and adds Replicated and InitialReplicated
  • server observer notices the PrePredicted and transfer the authority from client to server, removing the Replicated component (since the entity is now owned by the server)
  • the system in server.rs queries on Replicated, but the component does not exist anymore.

The solution is for now to update it to use InitialReplicated. It's a bit confusing annoying and not ideal but I don't see an easier fix right now

#

Some weird things are happening though.. even with the fix I can see desyncs, I wonder when these issues started happening

#

Like the client entity should be synced back to the Confirmed entity position in case of any desync

pine cape
#

@river perch I should have fixed your immediate problem, but it seems like there might be an issue with how inputs are handled for pre-predicted entities. They seem to be received by the remote client but not by the client that has the pre-predicted entity. I don't know how I introduced this because I thought I had tested the changes, but I probably introduced a bug while updating the PrePrediction logic .. Created this issue: https://github.com/cBournhonesque/lightyear/issues/702

GitHub

In examples client_replication or avian_physics, it looks like inputs are being sent to the remote entity but are not being sent/used correctly for the client that is issuing the inputs. TODO: add ...

river perch
#

Awesome! I appreciate the quick fix. I am noticing those desync issues now as well... at least they don't seem to be manifesting in non-pre-predicted entities as far as I can tell

unkempt sedge
#

Curiosity, is it common to have such an amount of roolbacks? Right when spawning my entity

#

And it just keeps getting higher and higher

unkempt sedge
#

Found out what is was I was adding physics bundle every frame hihi

#

@pine cape Mr Peri is it possible for a component in a entity, have a different authority? Or only entities may have different authorities

unkempt sedge
#

Ah you can filter out what components to send via target

wintry dome
#

i encountered a small footgun switching from a system to an observer relating to PreSpawnedPlayerObject for bullets.

my approach to the blueprint pattern for spawning stuff that is replicated involves spawning with a minimal bundle which includes a marker component, then a decorator system that filters on Added<MarkerComponent> to insert all the non-replicated physics (etc) components. i tried to switch that system to an observer on Trigger<OnAdd, MarkerComponent>

i'm using PreSpawnedPlayerObject::default_with_salt(client_id.to_bits()) , and spawning can happen on client or server for bullets. when i switched to an observer, the server's compute prespawned hash code runs when there are just the bundle's components on the entity, but the client sees all the decorated components too. must be an ordering issue of some sort. it makes the hashes different, so i can't use an observer for the decorator unless i calculate the hash myself.

here's my bullet plugin showing the two options: https://gist.github.com/RJ/e08f16e4953267ed6cfbde39003af817

Gist

spacepit bullet plugin, observer vs system ordering issue for PreSpawnedPlayerObject hashes - bullet_plugin.rs

stiff quiver
unkempt sedge
unkempt sedge
#

I guess the correct approach is client replicate cam forward to other clients

#

And spin it in a shared system

stiff quiver
#

how is this related to desyncs

stiff quiver
#

Shrug

#

Makes sense if u want to do serverside culling

wintry dome
#

what's the best way on my client to detect when another client disconnects? I want to get the disconnecting player's Player component to find their name.

#

if i use bevy's RemovedComponents<Player> it's too late to grab the Player component. seems like i can listen for lightyear's EntityDespawnEvent but 99% of those are useless for this

#

i suppose i should just make the server broadcast a message for joins/leaves

stiff quiver
fervent karma
#

Especially since there may be other valid reasons that a Player entity is despawned, obviously depending on your type of game

wintry dome
#

yeah taht's a good point

#

will send a msg from the server

pine cape
wintry dome
#

in fact i think it only uses components with a netid anyway, so maybe it already does that

pine cape
#

I see; in that case it's probably best to stick to using systems. The downside of observers is that they cannot be ordered

wintry dome
#

yeah. i'll probably use observers for that pattern for everything except stuff with PreSpawn

pine cape
#

Maybe the hash computation could be done in a ComponentHook (which runs before any observers), I would have to think about the ordering to see if it could work

wintry dome
#

hm, yes maybe that would work.. that would run instantly on insert i think

#

not a big deal, just wanted to flag it in case i missed an easier solution

stiff quiver
unkempt sedge
wintry dome
unkempt sedge
#

Oh it is 2d

#

Hahaha well at least the logic to grab input remains the same

unkempt sedge
#

So I was making this function that makes my player look at camera, via action input

fn camera_rotate_to(
    q_transform: Query<&Transform, With<MarkerMainCamera>>,
    mut player_action_state: Query<&mut ActionState<PlayerAction>, With<Predicted>>,
) {
    if let Ok(cam_transform) = q_transform.get_single() {
        let (yaw, pitch, roll) = cam_transform.rotation.to_euler(EulerRot::YXZ);
        println!("yaw {}", yaw);
        if let Ok(mut action_state) = player_action_state.get_single_mut() {
            action_state.set_axis_pair(&PlayerAction::RotateToCamera, Vec2::new(yaw, pitch));
        }
    }
}```
#

Weirdly my player rotate in a really weird manner no idea why

 let camera_rotation = action_state.axis_pair(&PlayerAction::RotateToCamera);

    let quat_rotation = Quat::from_euler(EulerRot::YXZ, camera_rotation.y, 0.0, 0.0);

    character.rotation.0 = character.rotation.0.slerp(quat_rotation, 0.1)
#

What am I doing wrong

unkempt sedge
#

ah great i put my x on the wron place ?>(

hexed birch
#

In the avian_physics example I'm trying to remove Velocity in replacement for manually changing x/y
But manually changing the position doesn't handle collisions correctly with avian2d.
Any ideas?

wintry dome
wintry dome
# pine cape Maybe the hash computation could be done in a ComponentHook (which runs before a...

doing compute_hash in a hook on PreSpawnPlayerObject fixed my ordering issues. I don't think there are any downsides: https://github.com/cBournhonesque/lightyear/pull/710

GitHub

After changing my bullet decorator from a system to an observer, i was seeing an ordering discrepency between server/clients, causing a different hash to be computed.
By changing compute_hash step ...

#

ah those recent dependabot updates for wtransport need some minor fixes too, will sort it

#

there are compilation failures because now lightyear pulls in hashbrown @ 0.15.2, and bevy 0.14.2 uses hashbrown 0.14.5. bevy reexports hashbrown, so i think the safest approach might be to remove lightyear's dep on hashbrown and just say use bevy::utils::hashbrown; whereever it's needed?

wintry dome
#

also made a PR to fix issues caused by recent dependency updates

unkempt sedge
#

Might be a pain in the ass and avian does that for you with kinematics but sometimes you dont wanna change your rigidbody i dont know

dull lion
#

Is there any way to replicate bevy events in lightyear? I suppose I could do it manually

unkempt sedge
#

Send message to target

#

Is a function that does that

#

You can send it from client to server client to another client and such

dull lion
#

yeah, that's what i meant by manually

#

it's not too bad though

pine cape
dull lion
#

made an issue

pine cape
#

Right now i'm trying to fix a bug where the avian_physics example doesn't work anymore for some reason.
The basic movement works correctly but it starts failing as soon as the player collides with a ball

dull lion
#

how did the job hunt go? still hectic with real life things?

pine cape
#

Got close a few times but didn't find anything i was willing to change for. I'm taking a break from it for a while

pine cape
dreamy silo
#

Best way to send username and passwords from a system on client to a system/function on the server?

pine cape
#

I guess as a message with some encryption on top of it?

pine cape
#

Disabling Correction completely fixes the issue, so it must be related to that. Also there are still rollbacks on collisions, which I thought had been fixed (cc @young prawn I think you had made collisions determinstic right?)

unkempt sedge
#

Oh yeah I was about to question that

dreamy silo
unkempt sedge
#

Spaceship, avian 3d, every single one flickers when collisions occura or rollbacks

dreamy silo
#

Oh perfect just what I want

young prawn
stiff quiver
young prawn
pine cape
#

That's good to know, thanks

dreamy silo
dreamy silo
# dreamy silo followed this example, just reversing it from client to server instead of server...

pub(crate) fn send_login_request(
    _trigger: Trigger<LoginToServerRequest>,
    commands: Commands,
    mut client: ResMut<ConnectionManager>,
    username_query: Query<&Text, With<UsernameInput>>,
    password_query: Query<&Text, With<PasswordInput>>,
) {
    info!("client: {:?}", client);
    info!("Sending login request");
    let username = username_query.get_single().unwrap();
    let password = password_query.get_single().unwrap();
    info!("username: {}", username.sections[0].value);
    info!("password: {}", password.sections[0].value);
    let mut message = LoginRequest{username: username.sections[0].value.to_string(), password: password.sections[0].value.to_string()};
    info!("Send login message: {:?}", message);
    client
            .send_message::<LoginChannel, LoginRequest>(&mut message)
            .unwrap_or_else(|e| {
                error!("Failed to send message: {:?}", e);
            });
    info!("Sent login request");
}````

my code on client side looks like this.

and on server its like this:

```/// System to receive messages on the server
pub(crate) fn receive_login_request(mut reader: EventReader<MessageEvent<LoginRequest>>) {
    for event in reader.read() {
        info!("Received login request message: {:?}", event.message());
    }
}```

protocol.rs has it all added like this:

```// Channels
#[derive(Channel)]
pub struct LoginChannel;

// Messages

#[derive(Serialize, Deserialize, Clone, Debug, PartialEq)]
pub struct LoginRequest{
    pub username: String,
    pub password: String,
}....

....         // messages
         app.register_message::<LoginRequest>(ChannelDirection::ClientToServer);
         
         //channels
        
        app.add_channel::<LoginChannel>(ChannelSettings {
            mode: ChannelMode::OrderedReliable(ReliableSettings::default()),
            ..Default::default()
        });````
#

made sure systems added to the app

pine cape
#

Are you running in host-server mode?

#

It's not obvious to me right now; are you sure that the client/server are connected?

#

Try setting the ChannelDirection to Bidirectional just to try

dreamy silo
#

I guess its similar to a client, server acting like one.

dreamy silo
#

ill go at it again tomorrow see if I get anywhere

pine cape
#

Did you run client.connect()?

pine cape
#

I just merged a simple change that should fix a subtle issue that was preventing PrePrediction from working correctly. The relevant examples (avian_physics, bullet_prespawn, etc.) should now be working much better!

The next thing i'd like to fix are the constant rollbacks in the avian_3d example, or the rollbacks that happen on ball-player contact in avian_physics example (which shouldn't happen if the simulation is deterministic and everything is working correctly)

dreamy silo
#

Don’t think I’m using client.connect() anywhere in my code

wicked tulip
#

Just to be sure I didn't miss anything. The best way to sync a 3d Transform is to create separate components for position, rotation and scale.

There is not a way to define for an existing component (like Transform) how it should be networked correct?

(like with quantization, interpolation etc.)

earnest rover
#

I am struggling a bit with how to organize my code again after a two month break, forgotten a lot, and trying to simplify and understand again.
I have this map with hexes (which are only local to the client there will be many more hexes), and insert Occupied and Base on them, as well as adding replicate. This works fine except for the mapping to the correct hex.
I store the hex on the Occupied and Base components and thought I could use that to look up the correct hex on the client. Attaching a picture, and some code that tries to explain it.
Ideally I would be able to lookup on receiving a message in my own maptable what entity (Hex) it belongs to.

Probably I'm going about the wrong way, but I hope intentions are somewhat clear. Any pointers?

    base: Query<&Base>,
    occupied: Query<&Occupied>
) {
    for event in reader.read() {
        if let Ok(occupied) = occupied.get(event.entity()) {
            if let Some(parent) = map.entities.get(&occupied.hex){
                if let Some(mut entity) = commands.get_entity(*parent) {
                    entity.insert(occupied.clone());
                }
            }
        }
       
        
        info!(
            "Received component Occupied insert for entity: {:?}",
            event.entity()
        );
    }
}```
wintry dome
# earnest rover I am struggling a bit with how to organize my code again after a two month break...

broadly speaking, the client performs an action like clicking a hex to set it to occupied or whatever, the client input, eg ActionState, is sent to the server. perhaps the actionstate is an enum including ClickedToOccupy(hex_coords, etc). the server executes the logic to update the game state based on inputs, and any changes to hex entities on the server would autmatically be replicated to clients, as long as the components are in the protocol. So things like Occupied components would automatically replicate to clients. So you'd just do a query for Query<...., Added<Occupied>> or something on the client

#

if you're including entities in your messages/components you can implement MapEntities (iirc), check the examples for usage. that will translate the server entity to client entity for you once replicated.

earnest rover
earnest rover
wintry dome
#

the simplest approach is probably to have each hex be an entity with replicated components like Occupied, and use mapentities where needed. there may be an upper limit on scalability with that approach though..

#

not very lightyeary, but you could also have client/server store their own hexmap data structure and use command pattern: server broadcasts commands which mutate the map state, using an ordered reliable channel. then your map can be massive with minimal replication bandwidth, assuming commands are deterministic

earnest rover
pine cape
# wicked tulip Just to be sure I didn't miss anything. The best way to sync a 3d Transform is t...

No, you can network Transform or GlobalTransform directly. An interpolation function for Transform is provided here: https://github.com/cBournhonesque/lightyear/blob/5845699d02ee953b73fa6f341224fe0df9dfa12b/lightyear/src/utils/bevy.rs#L10-L10

GitHub

A networking library to make multiplayer games for the Bevy game engine - cBournhonesque/lightyear

#

MapEntities is just required if you have components that contain other Entities.
Lightyear will make sure to 'translate' the entity inside the component from the local world to the remote world when it's replicated. Apart from that you don't really need to worry about much.
Does your Occupied or Base component contain another entity?

earnest rover
#

No they don't. They just don't get attach to the hexes on the client. since they don't match up between the worlds.

#

And I'm not sure it's solvable either 🙂 Just something I'm trying

pine cape
#

No but I mean what does the component actually look like?
Is it

   tile: Entity
}

or

pub struct Base {
   tile_x: int,
   tile_y: int,
}
earnest rover
pine cape
#

and what is Hex

earnest rover
#

is just ```pub struct Hex {
/// x axial coordinate (sometimes called q or i)
pub x: i32,
/// y axial coordinate (sometimes called r or j)
pub y: i32,
}

pine cape
#

Then why does it not work? You can just use the Hex x, y to find which entity is being referred to, no?

earnest rover
#

Because when I want to show the base indicator (the red in the image), that is a transormation on child of the Hex, with an Occupied component. I run HostServer, and the image is on the server. On the client the Base and Occuped does not attach to the Hex (understandebly so)

#

But you are right, I am thinking about this in the wrong way again I think. I'll take a step back, make some food and start again.

pine cape
#

Sure, let me know. But this situation can definitely be handled with lightyear. Parent-child hierarchies can also be replicated

earnest rover
#

Cool. I'll check out that before I start going further.

unkempt sedge
unkempt sedge
earnest rover
# pine cape Sure, let me know. But this situation can definitely be handled with lightyear. ...

FYI; I reverted back to to keeping the in game state (related to each hex) beeing totally seperated from the visual hexgrid. If the entity ids were predictable (for the visual hexgrid, looking at Entity:from_raw) I think the approach would have worked out of the box. But since it was warned not to use it, I did not go that route. Also I could not figure out how to bend lightyear my way with regards to this, but it works pretty good as it is now, like @wintry dome described.

dreamy silo
#

Where can I see what port by bevy server/game is running on? Would it be possible to run multiple bevy worlds on different ports on the same server?

pine cape
#

You choose which port to use in the server config; and yes you should be able to have multiple bevy words on different ports

dreamy silo
#

what's a non-bevy way of accessing number of connected clients to existing lightyear server? want to try to do sequential clientid assignment and let user just do cargo run -- client and get the next available spot.

wintry dome
dreamy silo
wintry dome
#

i'm generating random clientids for prod, but i don't have it linked to a database or anything. i suppose if you have a db of user accounts you might make the clientid the same as the primary key for the user table or something like that

#

random is easiest unless you already have a user database i think

#

if you really need to know the join order of players i would insert a specific component with a sequence number for that, rather than depend on client id

dreamy silo
#

yeah thats the thing, im working on a user database rn. I dont see how client_id is related to say a userid, so i was thinking of keeping userid and clientid seperate and let only lightyear take care of client ids, and userid is database stuff. since client_id kinda is just the id to the actual device/machine thats connected? or am i misunderstanding the meaning of a clientid?

#

only clientid relation ill make in the user database might be a column like "last_clientid" and "current_clientid" assigned upon login and logout. incase I gotta debug and ive logged out clientid instead of userid somewhere.

wintry dome
#

i think as long as you have a way for game servers to lookup the user from a client id it'll be fine

dreamy silo
unkempt sedge
pine cape
#

Yep it's buggy still

#

I haven't figured out how to update the InputBuffer if the input delay is changing dynamic ally

#

That's the only missing piece

unkempt sedge
#

Gonna fix it and check it out

pine cape
#

I think even without parallel there is no determinism, or there's still extra rollbacks for some reason

unkempt sedge
#

@pine cape Stale inputs ...

pine cape
#

?

unkempt sedge
#

I think i figured out what it is, I will test it out and make sure

stiff quiver
#

Finally got around to working on the webrtc transport thingy :)
Its a lot more annoying to implement than ws/wt but whatever. One question tho, is there any way you know of to use env or smth with rust cuz having to hardcode turn server credentials into the app sounds kinda like a bad idea thonk @pine cape

#

maybe i should just let the user handle that and just let them supply an basic/bearer auth string

#

its a bit awkward security wise either way since any user could just "steal" the turn server credentials no matter how we store it since they need to authenticate with them

#

Maybe the best option would be to generate credentials for each new connection on the fly

#

but again thats something the user has to do themselves

wintry dome
#

i have my server generating a new self signed cert each boot, which is fine when there's a matchmaeker that can pass the digest to the clients. would be useful to have an http server plugin that lightyear could use to serve up the connect token and cert digest. would make wasm clients much easier to play with

stiff quiver
#

Maybe useful for dev but thats all i think

dreamy silo
#

I finally got time to setup my nats server up and running last night. Felt great. Will continue on the bevygap stuff later tonight

unkempt sedge
#

++

pine cape
wintry dome
unkempt sedge
#

For some reason when he reached 3 KABOOM

#

Now he doesnt do that anymore

#

It seens the delay caused for very stale inputs to be passed to the apply_character action function causing some sort of rollback loop

pine cape
#

Well if delay is high there is no delay yea

#

But even if 0 delay, there shouldn't be any rollbacks with only one player

#

But there are

unkempt sedge
#

But only if I eliminate the block from sample

#
pub(crate) fn set(&mut self, tick: Tick, value: &ActionState<T>) {
        let Some(start_tick) = self.start_tick else {
            // initialize the buffer
            self.start_tick = Some(tick);
            self.buffer.push_back(BufferItem::Data(value.clone()));
            return;
        };

        // cannot set lower values than start_tick
        if tick < start_tick {
            warn!("You set a tick lower thant the start tick in input buffer");
           return;
        }

The cause lied in this function https://github.com/cBournhonesque/lightyear/blob/5845699d02ee953b73fa6f341224fe0df9dfa12b/lightyear/src/inputs/leafwing/input_buffer.rs#L99, when he has a input delay of about 6, he tries to grab a tick that is a lower than start tick so he just returns and doesnt set tick.I added a warning but basically the entire vecdeque from buffer breaks

#

Now why dont know probably because input delay diminishes by -6 or something like that, going way before start tick

pine cape
#

Can you try adding an explanation in the PR so I can review?

unkempt sedge
#

It is not fully functional I am just trying to figure out what is causing the rollbacks. But alas you can see what I am trying to do

unkempt sedge
#

God finally figured it out

#

Gravity + input delay are the two main reasons

dreamy silo
fervent karma
# pine cape How are you sending the entities? Did you implement the MapEntities trait on you...

Hey, I finally got around to trying this, but it's not triggering automatically, and I don't understand how it would do it automatically, but it seems you have to do something extra. I put printlns in the implementation and it's not being called.
I have this for now:

#[derive(Component, Serialize, Deserialize, Clone, Debug, PartialEq)]
pub enum Inputs {
    Direction(Direction),
    Spawn,
    Target(Vec<Entity>, Vec2),
    None,
}

impl MapEntities for Inputs {
    fn map_entities<M: EntityMapper>(&mut self, entity_mapper: &mut M) {
        match self {
            Inputs::Target(entities, _) => {
                for entity in entities {
                    *entity = entity_mapper.map_entity(*entity)
                }
            }
            Inputs::Direction(_) | Inputs::Spawn | Inputs::None => todo!(),
        }
    }
}

How is this intended to work?

pine cape
#

You also have to add something like .add_map_entities() when registering the component in the protocol

fervent karma
#

Okay I figured there was something like that, I just couldn't find it when searching, thank you!

#

Hmm, I've run into a bit of a sang. The thing I'm trying to entity map is the inputs, as you can see, however internally when you add the input plugin it adds a message of InputMessage<Inputs>, but there's no implementation of MapEntities for lightyear::inputs::native::InputMessage. It looks like there's one for the leafwing InputMessage though, so I'm guessing this was just forgotten?
Also the user experience of mapping entities for inputs can definitely be improved, as it's not immediately obvious that you need to wrap your InputMessage.
Also I saw your comment in add_map_entities: "or should we just have add_message_map_entities and add_component_map_entities?", and to answer your question, if you split it up you can add extra bounds on the two new functions, Message and Component respectively, which would remove the issue that I just had of calling add_map_entities::<Inputs>(), which silently does nothing

#

For now I'll try migrating to leafwing to unblock this, but I'm happy to raise a ticket (and make a PR if want 😄) for this

pine cape
#

I didn't expect you to apply MapEntities on the inputs, I don't think this is supported. Even the MapEntities implementation for leafwing inputs is for pre-prediction and not for users

fervent karma
#

Ah, hmm

#

Maybe I'm using inputs for the wrong purpose. I'm trying to have an input that when you right click it'll update the target position for the currently selected minions (so it takes a list of minions and a new target position), and then in the server input handler it updates the targets, which then updates the minions (and it's then replicated and stuff), should I just be using a normal message for this?

pine cape
#

I would use normal messages for this

#

but I think it makes sense that inputs should try to support stuff like that

#

i'll open an issue

#

Also the update for bevy 0.15 is basically ready, I'm just waiting for new avian and leafwing versions to be released to also release a new version

fervent karma
pine cape
#

yes I would have to change the way leafwing input works

unkempt sedge
#

@pine cape Question replicated entities inbound from server that are predicted should they cause rollback with one sole client?

pine cape
#

No there should never be rollbacks with one client

#

If client and server worlds are deterministic

#

That's why avian_physics shouldn't rollback on collisions

unkempt sedge
pine cape
unkempt sedge
#

How I rollback it tho i know how to replicate it

pine cape
#

stepper.client_app.add_resource_rollback::<TestResource>();

pine cape
unkempt sedge
fervent karma
#

Does anyone have good ideas for how to implement prediction ergonomically? The only way I can come up with is to implement it twice, but one adds an extra filter for Predicted, and then two systems. Ideally I would have a system that I could just add to both my server and client plugins and it would just work

unkempt sedge
#

Also necessary when using lobbies

fervent karma
#

I do that too, I meant for like predicting the movement of an NPC (or the player) I have to implement the logic twice, since the client needs it to only affect Predicted creatures, but on the server it should affect everything

#

Obviously in a simple case the only change is adding a filter, but in the most complicated case you have to change the logic slightly to account for the fsct that you may need data from all of them, but only update some

pine cape
# fervent karma Does anyone have good ideas for how to implement prediction ergonomically? The o...

You can have a shared system with a Filter that works for both server and client-predicted entities: https://github.com/cBournhonesque/lightyear/blob/main/examples/bullet_prespawn/src/shared.rs#L186
I use ReplicationTarget on the server to only target entities that are replicated to the client

GitHub

A networking library to make multiplayer games for the Bevy game engine - cBournhonesque/lightyear

pine cape
unkempt sedge
#

After removing it the rollback loop

#

Stopped

pine cape
#

You disabled it via

        app.insert_resource(NarrowPhaseConfig {
            match_contacts: false,
            ..default()
        });
```?
unkempt sedge
#

Yeah

#

Interesting enough we still have rollbacks only when collision occurs with two clients, but I oughta to think that is expected

#

Also they dont seen to be uncontrollable, the remain decent so just like once in a while

unkempt sedge
pine cape
pine cape
#

I tried running your branch but i still see constant rollbacks on collisions, with only 1 client

unkempt sedge
#

wut

unkempt sedge
pine cape
#

i'm just jumping on the purple cube

unkempt sedge
unkempt sedge
unkempt sedge
#

Well at least I can say it did help

earnest rover
#

I'm tweaking my leave/enter lobby and trying to stop and start the server and connect, and I see some leaks (I think) with regards ControlledEntities which seems to remain after stopping the server in HostServer mode.

on_connect_host_server spawns it, but on_disconnect_host_server does not despawn it.

Not sure I'm looking at the correct spot in the code though, could there be a bug?

I can remove it manually, if my scenario is a bit off

unkempt sedge
# pine cape i'm just jumping on the purple cube

Yeah I tried everything, removed each component that might be causing rollbacks on collision but well nothing. Interesting enough sometimes it works, sometimes it doesnt. Probably is deterministic and sometimes it isnt. When more strong collisions or multiple occur it seens determinism goes kablooei

#

When simple ones occur, like static rigid for example it remains okay

#

Perhaps advancing with deterninism test would be more efficient

pine cape
earnest rover
digital cedar
#

when registering a component, how do I make it such that it just syncs by overriding rather than having a interpolation?

interpolation:

        app.register_component::<MaxHealth>(ChannelDirection::ServerToClient)
            .add_prediction(client::ComponentSyncMode::Full)
            .add_interpolation(client::ComponentSyncMode::Full);
#

is it like this?

        app.register_component::<MaxHealth>(ChannelDirection::ServerToClient)
            .add_correction_fn(|_, x, _| *x);
wintry dome
#

that will just replace the client's component on the predicted entity with server values as they arrive without any interp

pine cape
#

You can also just completely disable prediction/interpolation and just let the replication override the value every time it's updated

wintry dome
sonic citrus
#

I'm curious, if I decided to send 100000 messages along a reliable ordered channel, is it guaranteed that all 100000 will make it to the other side? Or is it undefined what happens when you do that kind of extreme thing?

unkempt sedge
digital cedar
#

cuz I have other components that are both predicted and interpolated in the same entity

digital cedar
#

has anyone tried hosting server via port forwarding? how was the process?

unkempt sedge
#

Since it is max health, i think the goto should be

#

app.register_component::<MaxHealth>(ChannelDirection::ServerToClient)
.add_prediction(client::ComponentSyncMode::Simple);

#

Simple only mutating when you tell server to mutate that component

digital cedar
unkempt sedge
#

Exactly

#

You can make it so client defines it but you know if competitive great chance hackers might abuse that

digital cedar
pine cape
pine cape
stiff quiver
earnest rover
#

@pine cape , I would just like to give a shoutout. Once I got past not understanding anything, to understanding something, your library works GREAT! Really awesome work has been done in lightyear!

pine cape
#

Thanks! Really appreciated

unkempt sedge
#

@pine cape Mr Peri how can we buy you a cofee?

#

I followed the style of built you used on steam

#

And it was perfect

#

Also you should clear your stale branches

pine cape
#

No need, just appreciating the library is enough 😉

unkempt sedge
#

@pine cape Gonna be honest here, perhaps it would be best we make lifetime persistent the common usage the amount of warning I get because of entity despawn before hand errors is a biggie, just my opinion tho

pine cape
#

the easiest solution might be to have a despawn_without_warning function in bevy

#

Do you get this on the client?

unkempt sedge
#

Oh btw I am making a tutorial about your crate if you dont mind

split violet
# unkempt sedge Oh btw I am making a tutorial about your crate if you dont mind

Can you dm me or tag me the link, if this becomes available at any point? I'm new to bevy and lightyear and I don't really understand how messages are supposed to be transferred across applications (server/client). I've looked at the examples, but I can't really find out how to do it:
I looked at some of (https://github.com/search?q=repo%3AcBournhonesque%2Flightyear MessageEvent&type=code).
Here's my pretty minimal example:
I define a Message: https://github.com/phaack/troopy_bevy/blob/b2872634c470a7f7315e145a28eb5bec62100b1d/src/game/networking/messages.rs#L15
Then I send that even on the client:
https://github.com/phaack/troopy_bevy/blob/b2872634c470a7f7315e145a28eb5bec62100b1d/src/game/core/interaction/ui.rs#L151
Then (onUpdate?) I try to receive the Message on the server:
https://github.com/phaack/troopy_bevy/blob/b2872634c470a7f7315e145a28eb5bec62100b1d/src/game/networking/server.rs#L72
Where the client and server use the protocol w/ SharedPlugin:
https://github.com/phaack/troopy_bevy/blob/b2872634c470a7f7315e145a28eb5bec62100b1d/src/game/networking/protocol.rs#L50

unkempt sedge
#

You are not defining the target, and you are actually using bevys, send function

#

Instead of lightyear send_message, this is how you send a message in lightyear

#
fn my_system(
  tick_manager: Res<TickManager>,
  mut connection: ResMut<ClientConnectionManager>
) {
   // send a message to the server
   connection.send_message::<MyChannel, MyMessage>("Hello, server!");
   // send a message to some other client with ClientId 2
   connection.send_message_to_target::<MyChannel, MyMessage>("Hello, server!", NetworkTarget::Single(2));
}```
split violet
# unkempt sedge ```RUST fn my_system( tick_manager: Res<TickManager>, mut connection: ResMut...

Alright, but how do I receive the events then?

fn received_send_troops_message(mut events: EventReader<MessageEvent<SendTroopsMessage>>) {
    for event in events.read() {
        println!("Received SendTroopsMessage: {:?}", event.message);
    }
}

Doesn't seem right as a system. (At least I don't seem to receive anything) when using:

let mut msg = SendTroopsMessage {
                    action: SendTroopsAction::default(&start_entity, &end_entity),
                    player: Player::new(Some(1)),
                };
let _ = connection.send_message::<GameChannel, SendTroopsMessage>(&mut msg);

(https://github.com/phaack/troopy_bevy/blob/3de52e043d44f3eff927111eb00b37eaec2b9292/src/game/networking/server.rs#L82)
Sorry, if this is somewhere in the docs, but I seriously don't see much in the docs. I guess I must be blind

I also make sure to add the channel, so that shouldn't be a problem:

app.add_channel::<GameChannel>(ChannelSettings {
            mode: ChannelMode::OrderedReliable(ReliableSettings::default()),
            ..default()
        });
``` (https://github.com/phaack/troopy_bevy/blob/3de52e043d44f3eff927111eb00b37eaec2b9292/src/game/networking/shared.rs#L34C9-L37C12)
I'll check out your linked video out now, sorry if that's already shown there.
unkempt sedge
split violet
wintry dome
#

has anyone used lightyear wasm client in firefox sucessfully, with webtransport? it never seems to work for me. (fine in chrome)

stiff quiver
#

cert hashes arent in stable release yet

#

or smth like that

wintry dome
stiff quiver
tardy swallow
#

Setting that replication group for characters in avian_3d_character to something not used by the purple blocks appears to stop the constant rollbacks.

Now, rollbacks only trigger when a character interacts with a purple box but will constantly trigger rollbacks until the boxes stop moving despite the character no longer interacting with it before it stopped. Not sure why. There are rare occasions where the rollbacks do not stop ever. More characters results in higher chance of nonstop rollbacks

Spawning the boxes with an initial velocity (thus motion without the intervention of a client) does not trigger rollbacks.

Characters interacting with other characters does not trigger rollbacks and yet characters interacting with the purple boxes does.

pine cape
#

Hm I would expect that all predicted entities have to be in the same replication group to guarantee that rollbacks work correctly

wintry dome
#

i'd like to be able to compile the examples as dedicated servers without having to compile steam or gui stuff. although you can run them just as a --server at the mo, it's all still compiled in

#

i'll add suitable features to examples_common

unkempt sedge
#

Constant rollbacks on dynamic bodies collision tho seens to be an issue correlated to avian determinism

#

I think Periwink had a test for that, interesting enough with rapier I dont get the same result as in there is no rollbacks with collisions

unkempt sedge
#

It will be pretty cool if it did

tardy swallow
#

I added some log statements before and after the physics systems execute. On the server side, a purple block will be completely stationary (it's position, rotation, & velocity are unchanging). On the client side after a rollback where a block's physics-related components sync with the server, I see that after the physic systems execute there is an incredibly small linear velocity applied to the block that de-syncs the client block's position and rotation by an incredibly small value. Before the physics systems executed, the block was sync'd and did not have any velocity, force, impulse, or angular velocity. There shouldn't be any velocity applied to the block as it should be completely stationary. My guess is that there is state information within avian that avian_3d_character isn't rollbacking.

I also tried disabling contact matching in the narrow phase:

app.insert_resource(NarrowPhaseConfig {
    match_contacts: false,
    ..default()
});
unkempt sedge
pine cape
# unkempt sedge Is there an observer for connect events?
GitHub

A networking library to make multiplayer games for the Bevy game engine - cBournhonesque/lightyear

GitHub

A networking library to make multiplayer games for the Bevy game engine - cBournhonesque/lightyear

pine cape
# tardy swallow I added some log statements before and after the physics systems execute. On the...

I thought that lightyear was using a version that had https://github.com/Jondolf/avian/pull/480
It's possible that some resources that are needed are not being rolled back

GitHub

Objective

Fixes Determinism with contacts #406

We noticed an issue where the Collisions were using the order of Entity directly to sort the pair of entities in a contact.
The issue is that for ne...

#

It might be possible to just rollback these resources

unkempt sedge
tardy swallow
pine cape
#

There's a few resources that are used by avian to handle collisions correctly, yea

stiff quiver
#

just a thought:

  • have two servers
  • one gets the authority for handling all the physics and other gamelogic related systems
  • the other one is the one that all clients get connected to and handles all io and replicates the world forward to the clients from the "game logic" server while preprocessing inputs for the game logic server

isnt that basically star citizens server meshing with native lightyear? :o

not sure if this actually works but if it does would be a cool poc

#

s1 would need good single core spd and s2 would need as many cores as possible to handle as many clients as possible

#

smth like that

wintry dome
#

if anyone can't build on wasm: (will fix properly in due course, down a rabbit hole atm..)

# TODO 0.3.3+ is a breaking change.. pin to 0.3.2 for now
bevy_web_keepalive = "0.3.2"
#

field name in WebKeepalivePlugin changed. and bevy 14->15

stiff quiver
#

shoulda been a major version change

#

err minor

#

But not patch

pine cape
#

good to know, thanks!

wintry dome
#

it's always a painful time waiting for various deps to support the newest bevy versions after release

pine cape
#

yea

stiff quiver
stiff quiver
wintry dome
#

i'm adding some conditional compilation bits to the examples and refactoring cargo files in order to be able to build the examples as headless servers and/or wasm clients. will do a draft pr for more discussion once i have something legible to show

#

ultimate goal to conditionally compile in bevygap plugins and host all the examples on edgegap 🙂

pine cape
#

that would be so cool

wintry dome
#

would be great to provide an easy route to hosting a game on edgegap if you use lightyear. making a simple game work locally is only half the battle at the mo

unkempt sedge
#

For example, in save_files I intend to use client_id as acessor to that user info. Or would I need to make some sort of unique user and password for it? If sowell fuck

pine cape
#

You can choose the client_id

unkempt sedge
#

Imagine a on production environment, tho. Would I be able to choose it is client_id even so?

wintry dome
unkempt sedge
#

Ah I see

unkempt sedge
wintry dome
#

can anyone help with my cargo/deps problem?

bevygap has a dependency on lightyear.
i'm currently working on a feature branch of lightyear, and i've added bevygap as a dep to lightyear.

I want bevygap's lightyear dep to use my local checkout of lightyear (ie, path = "./lightyear") but i don't know if this is possible with cargo's patch system. can't get it to work.

if i don't use the exact same version of lightyear then it fails because bevygap code can't find the lightyear resource (because bevygap has compiled a different version of lightyear so it's technically not the same resource the game has inserted)

stiff quiver
wintry dome
#
# bevygap for deploying on Edgegap
bevygap_server_plugin = {git = "https://github.com/RJ/bevygap.git", tag = "v0.2.2"}
bevygap_client_plugin = {git = "https://github.com/RJ/bevygap.git", tag = "v0.2.2"}

# Make sure bevygap's lightyear dep is our exact version:
[patch."https://github.com/RJ/bevygap.git"]
lightyear = {path = "./lightyear" }

#

i tried this, since my bevygap dep is from github

stiff quiver
#

Okay maybe to clarify;
your structure is like this?:

a = lightyear depending on bevygap
b = bevygap depending on c
c = current lightyear without bevygap

now you want b to use a instead of c?

wintry dome
#

in fact, in the bevygap cargo file, it has this dep for ly:
lightyear = {git = "https://github.com/cBournhonesque/lightyear.git", rev = "5845699d02ee953b73fa6f341224fe0df9dfa12b", default-features = false}

#

structure at present without patches is:

#

lightyear (local checkout) depends on bevygap from github
bevygap from github depends on lightyear pointing to a specific github revision

#

i want to patch it so bevygap uses the local checkout of lightyear

stiff quiver
wintry dome
#

using cargo tree i can see that the bevygap_client_plugin (for example) is causing the wrong lightyear dep to be pulled in. ie it's pulling the one from its cargo file, not my patch to point to ./lightyear

stiff quiver
wintry dome
#

oh wait, i've committed my cargo.lock to bevygap repo, that seems like a bad idea

wintry dome
#

and i nuked my local lock file and did cargo clean 🤔

stiff quiver
#

:/ im out of ideas

wintry dome
#

ah i think i've got it:

[patch."https://github.com/cBournhonesque/lightyear.git"]
lightyear = {path = "./lightyear", version = "0.17.0"}

that patches anything trying to use that github url for lightyear, which is what bevygap does. phew.

#

and pretty sure the version not necessary

dull lion
#

I wonder how hard it would be to support https://github.com/projectharmonia/bevy_enhanced_input in lightyear. I'm guessing adding another input crate introduces a ton of edge cases, and if it lives in the main crate it introduces yet another bottleneck for keeping lightyear up to date with bevy. So probably, in order to support it you'd need to abstract away LWIM support in Lightyear behind some sort of input adapter interface

#

(and then implement support for LWIM/bevy_enhanced_input as separate crates implementing the interface)

wintry dome
#

in chrome^

#

hi whos on the german server

dull lion
#

me

#

seems to work!

wintry dome
#

cool

dull lion
#

seeing a little bit of stuttering/flickering

wintry dome
#

hmm your ping is ~80ms. can't remember what the input delay and settings are tbh. it's not at all tuned well

#

pretty smooth here, at ~67ms

dull lion
#

it is smooth like 95% of the time

wintry dome
#

i'm working on the infrastructure for deployment atm, but def want to get that buttery smooth at some point

dull lion
#

some of the flickering was purely graphical. like, the border around the arena was flickering a bit during rollbacks I think

wintry dome
#

yeah i've noticed that

dull lion
#

tbf i'm in an environment with uh... adversarial network conditions aka terrible wifi, which might explain the stuttering

unkempt sedge
#

A VERY annoying bug

wintry dome
#

some non-determinism still lurking yeah

unkempt sedge
#

The stuttering is probably non adaptable input delay, with high latency certain configs should be adjusted

wintry dome
#

i don't think the input delay is auto-adjusting based on lag, perhaps it should be. and need to review defaults / minimum value. i feel like it shouldn't drop any lower than input delay of 3 ticks for spaceships

pine cape
#

Awesome! simple_box works well for me, but on spaceships my inputs don't seem to do anything

pine cape
pine cape
wintry dome
pine cape
#

LWIM had some careful work done to make sure that inputs work well within the FixedUpdate schedule, we would have to check if bevy_enhanced_input has the same

#

Yeah the re-render on rollback is a bit annoying, idk why that happens

split zealot
#

dumb question, by default there aren't any conditioners added that would cause visual jitter, right?

dull lion
split zealot
#

i am interpolating the transforms, but badly! 😅

#

i really want to use avian physics but the lack of motor support is a blocker, so i'm using rapier. syncing up the transforms has been tricky fs

split zealot
#

if rapier uses transform/velocity as the source of truth, what's the best way to interpolate those values for clients? would it be adding transform/velocity to the protocol or creating a new component that copies the source transform every fixed update?

#

i'm confused as to whether the replication is reading the world state during the fixed update or the normal update

pine cape
#

Replication is reading the world state at a given tick t during FixedUpdate

#

Yes I would try adding Transform to the protocol

wintry dome
wintry dome
#

it looks like that shouldn't be possible. the spaceships server inserts the Player component and the ControlledBy all at once when spawning ships for newly connected players.

wintry dome
#

could it happen that clientside the Predicted component is inserted on a different tick to Controlled (or my Player component i suppose), causing that system not to notice our own player? i wanted to look at the "copy replicated components from confirmed to predicted" logic when an entity is received on the client, but can't find it

unkempt sedge
unkempt sedge
#

I think you will also need to make him visual interpolate, via the visual interpolate plugin. No 100% sure on that one.

wintry dome
#

hm, well i caught it with the ignoring-inputs error but it definitely detected the controlled player and added the input map, so back to the drawing board.

wintry dome
pine cape
stiff quiver
#

@pine cape do yk if i just need to impl this myself for js val?

#

or should i convert this into a str?

#

cuz this is a js Error wrapped in jsvalue

#

so in theory i can just .toString() it

stiff quiver
#

this seems to work

unkempt sedge
#

@pine cape Say Mr Peri, I have a currency struct. And of course I want my server to validate if player can have that amount of currency. My currenct workflow is as follows, I change predicted entity (Player in this case) and inform server of that adjustment. Server checks and if he okays it he changes confirmed, and the resource that stores the currency amount of that client. If not he rollbacks, is that the correct approach?

pine cape
#

You just have apply the same logic on the predicted or confirmed entity. (client vs server)
It's possible that the predicted entity has a different currency amount temporarily, but eventually the server value will become the source of truth

#

Same with collisions; it's possible that on the client there is no collision. But on the server that actually is a collision, so the entity loses some health points on the server and the changes are applied via rollback to the client entity

unkempt sedge
#

Oh my

#

well not gonna lie that lowkey kinda sucks when you want to apply local changes, and later validate them. For example, players tests skin. Can he still hold it after?

#

But i guess it makes sense

unkempt sedge
pine cape
#

It already uses rooms

wintry dome
#

i wrote a cli tool to interact with the edgegap api, so now examples/ server builds can automatically update the docker tag configured in edgegap for insta-deploy https://crates.io/crates/arbctl – now i can say arbctl application patch-version simple_box v1 --patch /docker_tag '"sha-1234567890"'
i'm using it to migrate all the examples stuff into a Lightyear org within my edgegap account for now

unkempt sedge
pine cape
#

I tried upgrading to the latest leafwing version, seems to work well.
Although the examples have a bunch of changes needed + bevy-screen-diagnostics

wintry dome
#

cool. are all the other lightyear deps on 0.15 now?

pine cape
#

just need avian, which will upgrade end of this week

#

bevy_screen_diagnostics might need some more work though... maybe i'll switch to one of the other libraries

wintry dome
#

there's iyves something or other i wanted to try

pine cape
#

yea same

wintry dome
pine cape
#

lol

wintry dome
#

jinx

pine cape
#

not released 0.15, but seems to be on 0.15-rc3

wintry dome
#

quite a few changes to examples stuff in my examples branch, gonna suck to merge that after 0.15 change.. but i've only done 2.5 of the examples so far

pine cape
#

maybe merge them now?

#

I've only changed bullet_prespawn for now

wintry dome
#

actually should be fine to upstream what i've done, i left the default features so they would behave as it does now (building gui for everything)

#

could be worthwhile, because i moved some of the common ui stuff to lightyear_examples_common, so that would probably be the place to add a debug perf ui. but i don't have much free time for the next 3 weeks, and it might be a pain if you're doing 0.15 work.

#

did you take a look at the diff?

#

are you happy with the cargo file refactoring to push deps up to the top level workspace cargo file? i think it's sane, not sure if there any downsides apart from a big ugly diff.

unkempt sedge
#

Perhaps it would be wiser to just make a very simple perfui on lightyear itself

#

For what I know all the variables like rollback and such are easily acessible

pine cape
#

We can do it in whichever order you prefer, i'm fine with merging your changes before the 0.15 upgrade

#

Your changes are amazing btw

wintry dome
#

great. i responded to the review comments you left. i'll try and get things tidied up enough to merge, even though i've only got a couple of the examples working on wasm so far. we'll just need to disable the new workflows while i'm still working on it in my fork.

plain charm
#

looking at using lightyear for a project, and I was curious if there were any plans or context around server migrations (or w/e it’s called, voluntary switchovers or some kind of post-server-crash designated survivor)

Thing is, it’ll be a long while before I’ll ever need it, and I could contribute to a generalized lightyear implementation later on, if it’s within the crates scope

pine cape
#

What do you mean by server migrations?
A server crashes, a new one gets spawned automatically and all the clients switch to talking to that new one without loss of user data?

plain charm
#

In that general ballpark, yeah. Also, transferring to new hosting server, or between Separate and HostServer modes, etc

#

Plenty of complexity, naturally.

pine cape
#

It is currently possible for clients to disconnect from a server and connect to a new one; I guess most of the work would be:

  • how to serialize the state of the World on the previous server
  • load it in the new server
  • update the entity-mappings on the client and make sure that the replication doesn't spawn new entities on the clients
plain charm
#

Right, and I’ll bet there’ll be lots of unexpected cases to resolve. At the moment though, I was planning on writing my own specialized, project-specific implementation later. But, it might be better to contribute a general implementation to lightyear instead, if the author/maintainers believe that feature to be in scope

pine cape
#

Sure that would be worthwhile; it would probably be as a separate project/plugin

#

Let me know if you encounter any blockers

wintry dome
#

what's the earliest schedule to render something once it's been VisualInterpolated?

#

right after transform propagate?

wintry dome
#

ok this is in decent shape now to merge i think. i got clippy/lints etc down to zero, but there are 4 failing tests – but i don't think they are necessarily due to my changes. https://github.com/cBournhonesque/lightyear/pull/732

GitHub

Refactor Cargo workspace and examples
(Precursor work to hosting live examples on edgegap)

moved all dependencies to top-level Cargo file, under workspace.dependencies. this helps ensure we are al...

#

i'll continue the examples refactoring in a follow-up pr later, but i switched all of them to use workspace deps so it should be easier to upgrade to bevy 0.15 in the meantime

pine cape
#

I merged it for now, can follow up on smaller PRs. I disabled the Edgegap workflow; the other two have the message "This workflow has a workflow_dispatch event trigger."

wintry dome
#

btw the Edgegap workflow isn't from my branch.. the new ones are called "Build WASM frontend" and "Build servers for examples", which will both (harmlessly) fail on your branch at the mo so can be disabled to reduce noise.

pine cape
#

Yep; there's just no button to disable them for some reason

wintry dome
pine cape
#

@wintry dome do you get warnings like lightyear_examples_common::renderer::handle_disconnection did not run because it requested inaccessible system parameter Res<Events<DisconnectEvent>> when you run with --server?

#

I imagine they go away if I run with only the feature server enabled (instead of both client and server)

#

but it would be nice if fiddling with features wasn't necessary at runtime

pine cape
#

I've ported the auth example, but right now it's a bit cumbersome because the user must run the examples with cargo run --features client -- client and cargo run --features server -- server which is not ideal

wintry dome
#

we could change the cli bit so if only server feature is on, and client disabled, assume "server" (ie, no need to pass that on the command line)

#

same for client. if server feature disabled we could just run the client without passing "client"

#

but doubt people just trying out the examples need to care about that really

wintry dome
stiff quiver
# pine cape but it would be nice if fiddling with features wasn't necessary at runtime

is that even necessary? could conditionally compile in server and/or client runner in based on the feature usage, dont really see any why a -- server/client argument would even be necessary in the first place 🤔 sure it means your compile time is basically double but its still more ergonomic to not have to specify server/client as a parameter

#

iirc cargo has feature specific cache now too, so not even iterative builds should be a problem, otherwise having different --target-dir's might make sense, i did that for an old project

pine cape
#

Because when server and client features are enabled you could still do host-server or client-and-server

stiff quiver
pine cape
#

I don't think there's any huge issues, I just want to think about this a bit to not hurt the ergonomics of examples

stiff quiver
#

features are pretty much the standard way to do this kinda thing in rust after all

#

so i'd expect this to be much more ergonomic for the avg user instead of a cli

pine cape
#

Agreed

unkempt sedge
#

Is there an example, off a interpolatable/rollbackable transform component? I think I saw one here

wintry dome
#

if i'm right that would cause all kinds of weirdness 🤔

#

at least the 3 physics sets should be chained, anyway

#

yes but also with a chain at the end (second to last line)

#

edit your message to add?

#
                ).chain(),
            ).chain(),  // <---
        );
unkempt sedge
#
impl Plugin for Avian2dPlugin {
    fn build(&self, app: &mut App) {
        app.configure_sets(
            FixedPostUpdate,
            (
                // run physics after setting the PreSpawned hash to avoid any physics interaction affecting the hash
                // TODO: maybe use observers so that we don't have any ordering requirements?
                (
                    InternalReplicationSet::<ClientMarker>::SetPreSpawnedHash,
                    InternalReplicationSet::<ServerMarker>::SetPreSpawnedHash,
                ).chain(),
                (
                    PhysicsSet::Prepare,
                    PhysicsSet::StepSimulation,
                    PhysicsSet::Sync,
                ).chain(),
                // run physics before updating the prediction history
                (
                    PredictionSet::UpdateHistory,
                    PredictionSet::IncrementRollbackTick,
                    InterpolationSet::UpdateVisualInterpolationState,
                ).chain(),
            ),
        ).chain();
    }
}```
wintry dome
#

yes. that's the same as not having the three sub-tuples and just having one chain. but perhaps the InternalReplicationSet bits could run in any order. we definitely need the physics sets to be chained though. i expect your above message was the original intention of the code

#

@pine cape can you comment on that? could it be a source of non determinisitic stuff with physics

unkempt sedge
#

oh it seens you are right, when doing sole tuple you let them run in parallel

wintry dome
#

perhaps the avian plugin is enforcing the ordering for us, i'm not sure

#

seems like it should inherit the ordering from the avian plugin, although we have a few places where we still use FixedUpdate. should get all the examples over to FixedPostUpdate, the avian default. #1124043933886976171 message

#

what's happening in the spaceships example, is lightyear adds its Avian2dPlugin (or 3d), which configures the schedules in FixedPostUpdate without chain, which doesn't matter because the schedule ordering is setup using chain() by avian's PhysicsSchedulePlugin which also uses FixedPostUpdate. the spaceships example then does app.add_plugins( PhysicsPlugins::new(FixedUpdate)... so avian chains them in FixedUpdate.

#

so the sets get configured in FixedPostUpdate, and then in FixedUpdate. presumable they don't run twice.. really need to change to use FixedPostUpdate anyway, that will remove some of the confusion.

unkempt sedge
#

how are you running examples, in this new lightyear version. Keep getting some werid certificates error

#

Could not deserialize the settings file: SpannedError { code: MissingStructField { field: "certificate", outer: Some("WebTransport") }, position: Position { line: 39, col: 17 } }
note: run with RUST_BACKTRACE=1 environment variable to display a backtrace

wintry dome
#

the examples are being refactored a bit at the mo since the recent commit by me in main, some of them need more work.for that error, add this to your settings.ron:

        server: ServerSettings(
             ...
             transport: [
                WebTransport(
                    local_port: 5000,
                    certificate: FromFile(     <---------- this bit
                       cert: "../certificates/cert.pem",
                       key: "../certificates/key.pem",
                    )
                ),
#

or this:

            WebTransport(
                local_port: 5000,
                certificate: AutoSelfSigned(["localhost", "127.0.0.1"]),
            ),
#

in which case it will generate a self-signed cert each time the server starts

#

(i just made PR #734 to fix that)

pine cape
#

But yes everything should be moved to the same schedule

pine cape
stiff quiver
#

nice 💯

wintry dome
#

working on porting some examples for 0.15. are we just getting rid of ScreenDiagnostics for now?

#

we also don't need FixedSet::{Main, Physics} any more, now we'll be using avian's default of FixedPostUpdate. we can simplify and just put our example systems in FixedUpdate

#

i like the required components change