#bevy_renet

1532 messages · Page 2 of 2 (latest)

autumn canopy
#

rustc 1.75.0 (82e1608df 2023-12-21)

#

so a little newer but hasn't changed in a little while

#

I can try to roll back

hollow karma
#

ill upgrade, been wanting to anyway

#

i doubt this is it tho like you said, that's from 2023

#

ya seems fine

autumn canopy
#

Yeah, I appreciate the help. I want to just uninstall everything and start fresh VSCode setup but I would like to figure out what is going on to learn....

hollow karma
#

yeah these are the worst problems

#

C:\Users\D\.cargo\registry\src\index.crates.io-6f17d22bba15001f\renet-0.0.14\src\transport\client.rs:87:12

#

has this been cleaned out?

autumn canopy
#

let me go look.

#

nope...

hollow karma
#

(no idea what happens if you delete it)

autumn canopy
#

lmao

#

lets find out

#

I am deleting the whole .cargo folder.

#

Going hard core lmao

hollow karma
#

DO IT LIVE

autumn canopy
#

ok deleting the whole folder, not a good idea. Deleting the registry data now. 😛

hollow karma
#

oh ya that sounds gross, I'd just start by deleting that one renet folder

autumn canopy
#

ok, building again. Lets see.

#

Well son of a gun... It worked.

#

So apparently those registry folders can get corrupt sometimes. Good to know. Nice find and thanks for that, didn't think about that.

#

and cargo clean doesn't remove them.

hollow karma
#

odd, but great to know

autumn canopy
#

Thanks so much man, it was nice to have someone to work with on figuring this out and you saved me some headache.

hollow karma
#

no worries! cheers

autumn canopy
#

Hopefully one day I can return the favor. If you ever run into an issue, ping me. We might get lucky and I can help. 😄

hollow karma
#

hahah noted!

normal bay
#

I will also look into refactoring renetcode a bit so more of it can be used by the webtransport transport (which should be maintained in a new crate, either by @fleet crescent, myself, or some other enterprising soul).

near juniper
bleak token
normal bay
normal bay
#

With this, renet would have two levels of abstraction. At a high level the RenetClient/RenetServer provide a uniform surface for user code. Then at a lower level the NetcodeServerTransport/NetcodeClientTransport abstract over a source of unreliable packets.

#

@eternal crater @bleak token @weary moat @prime imp @feral crane pinging all of you who have been interested in this kind of abstraction.

bleak token
bleak token
prime imp
# normal bay New PR to make the `netcode` transports agnostic to the underlying packet source...

I just saw this, mb for late response. My opinion is that it's a good start, but I'm not super sure about some parts:

  • This locks renet into using netcode, with no opportunity to swap out the protocol
  • Parts of netcode are not necessary on some transports, like you've already said webtransport already encrypts packets, but it goes further: steamworks doesn't require fragmentation, channel transport doesn't require fragmentation or ordering or anything. IMO this is an unacceptable tradeoff, and different transports should be able to use only the features they need to function - no "double-layering".
  • I assume, because this uses netcode, that this works exclusively with [u8]s. I'm not a fan of this, and in aeronet I take the approach of instead having a user-defined message type, which may be converted to/from [u8]s if needed by the transport. This:
    • makes it so serialization is not required for channel transports
    • makes the API surface clearer (imo), since you know exactly what type of message is sent on atransport
normal bay
#

If you don't want netcode, you write your own transports (that are compatible with RenetClient/RenetServer) as usual. That is necessary for steam which is too far removed.

prime imp
near juniper
#

That's already how it works, I believe. The transport layer just promises to try to send packets of bits from the source to the target, and then the RenetClient/RenetServer implement everything on top of that

prime imp
normal bay
bleak token
prime imp
#

each packet is an entity?

bleak token
#

Just a crazy idea

bleak token
#

Or transport is an entity

#

protocol*

prime imp
# bleak token Yeah, imagine that

personally I think it's a bad idea in the context of an ECS, specifically because the packet doesn't really represent anything important. it's like treating your game save file as an entity; what's the point? what can you do with it?

#

the purpose of packets/save files/etc. is to be used to populate the world, rather than exist in it

bleak token
#

Yeah, it's not efficient, just a fun idea which occured to me.

#

I mean you mentioned "components" and an association came up :)

prime imp
#

hmm that's true

#

maybe "layers" is a better term for it

#

like layers of the TCP/IP stack

near juniper
normal bay
near juniper
#

How does that PR work for the in-memory case? What would you use as the address and stuff when doing in-memory things that don't have actual sockets?

normal bay
#

From renet's point of view, the SocketAddr is just an identifier.

near juniper
#

You can have multiple clients with the in-memory transport layer

#

I guess you can just invent random SocketAddr ss you go though

#

Just put localhost:1 and increment the port from there

normal bay
#

The in-memory server transport will internally have a map of senders/receivers for each client. You can overload the clients' SocketAddrs to record their index. That's also what the WebTransport server transport would need to do.

glad sonnet
#

i often get error "send channel 2 with error: reliable channel memory usage was exausted" and disconnected. i saw the default channel buffer is 5 MB, what if use Vec as channel buffer and dynamic allocate if needed?

eternal crater
glad sonnet
#

thank you, i am making a 3d Voxel Game, the error occours when sending ChunkData of voxel terrain.

message pooling sounds good but it might should be implement by the library instead of myself?

at the end, i just increase the channel config from 5 MB -> 20 MB and 'solved'

#

actually i have another question: i think it's useful if a custom disconnect-reason string could be send to client if server disconnect a client.

e.g. when i implement "Login", i assume i should use "user_data" to provide UserId and PasswordDigest, then if the password is wrong or the account is already logged in, a custom message should be send while disconnect.

eternal crater
#

No, the user_data should not be used for that.

When generating a token, you need to make sure the user is already authenticated so that in the server you can assume the user_data is valid/safe.
For this you would need login/auth service, and you only generate the token for the client when he is authenticated and you can send the serialized ConnectToken to the client safely/secured.

#

The user_data is encrypted, so that only the auth/login service and the server can use it. The client will not be able to tamper/read it

fleet crescent
mortal robin
#

Hey y'all, I'm new to Bevy Renet and I'm trying to create a server browser similar to Minecraft. It just needs to go across a list of IPs and ask them for a LobbyData struct that has stuff like player count, map, etc.
I feel like opening a NetcodeClientTransport and closing it for each server doesn't make much sense but I don't really know what else to do, any advice?

hollow karma
#

Like, where are clients getting the list of IPs in the first place?

#

IMO a way to do this is have a master server, and when a new server goes up, it posts to that master server. "Hey I'm here, and here's my IP address, my server name, my active map, etc". Then clients ask the master server for this info, they can even do it over HTTP

#

That being said, if you want to display ping in the server browser, the clients will need to likely open a NetcodeClientTransport and then close it.

#

I have more thoughts, but I'll wait till you reply to see where you're at with the above

mortal robin
#

In Minecraft, you add servers by adding their IP to the list and it'll display info about them, I don't think there's a master server. That said though, this is a project simply to learn Bevy stuff and it's probably more useful to have a master server and create a community browser experience similar to older Source games like TF2

#

Which would connect to a master server and display all the servers it knows of

#

I suppose the better way to do that is to connect with a NetcodeClientTransport to a master server?

near juniper
#

You can either do it through renet, or you could just make an https endpoint and do a normal GET that returns the list of known servers and their most recent status

normal bay
mortal robin
#

Makes sense, I'll look into these options, ty!

scarlet cradle
#

Would crate author consider adding a broadcast for a specific list of clients? also all except a list

normal bay
bleak token
#

I think it's not a good idea since it will require allocation.
It's better to use a loop.

scarlet cradle
#

can a protocol be described without a huge enum with renet?

prime imp
scarlet cradle
#

I'm expecting hundreds of message types in some channels, doing like the example is feeling pretty cumersome

#

I probably need a u16 message id

#

are there any examples of doing it this way I could reference, not sure exactly what you are suggesting I do, the issue I'm having is more dealing with it on the bevy side, ie. handling hundreds of cases in an event reader

#

if let Client::Message(0) { else if let .... ... ... ...

bleak token
#

You can also define separate channels for different messages.

scarlet cradle
#

this is considered already

#

there are still hundreds of messages in some channels

#

or will be

bleak token
#

I mean create a separate channel for each message.

#

Or do you mean that you reached the limit of 255 channels and squished some messages into one channel?

scarlet cradle
#

I guess I could do that, I'll take a look at the code later and see how much of an issue I'll have patching it to suit my whims

#

on, I was also concerned about the boilerplate of doing that, and thought it may not be a good thing to try

#

but I'll look into that

#

thanks for your input btw, appreciated

bleak token
scarlet cradle
#

and yes I would probably hit the 255 limit on channels doing that

bleak token
#

Like 255 different totally different things?

scarlet cradle
#

it's planned to be yes

#

I have about 100 client messages right now

#

for in game messages

#

and more for non-game stuff

bleak token
scarlet cradle
#

I don't sync any bevy components

#

it's all lock-step and hand-rolled

bleak token
#

Ah, I see. You can replicate data from server by utilizing a single channel, it's much easier then defining hundreds of messages.
And keep other channels only for the game logic.

scarlet cradle
#

besides a few road bumps, renet is seeming like my best option still, so there's that at least =)

bleak token
#

I mean I imagine that you have messages like SpawnTank, DespawnTank, etc.

scarlet cradle
#

I want this protocol to not rely on bevy tho

#

that's a design choice

#

I may switch engines someday

bleak token
#

Ah, I see, then I don't think that you can avoid the boilerplate.

scarlet cradle
#

it is what it is, thanks again =)

bleak token
# scarlet cradle I may switch engines someday

But just to clarify, the idea is not Bevy-specific.
If you will switch the engine, it will most likely work as I described: replication from server to client and messages only for game logic, like "Get this quest", etc.

scarlet cradle
#

oh, there's a lot of filtering that would need to be done on the client list so, I need to make rooms that frequenctly update the clients in the server room. many events are only sent to client if they pass some predicate, including spatial and logical seperations of game ares, ex. only units in the same zone that pass a predicate get a message such as spawn a villain, reveal map data in radius

#

i do want to broadcast to rooms tho

#

where possible

#

I'll see what it ends up looking like, just ported my server code working on the client now

scarlet cradle
#

well took about 1.5 days to port, everything working as expected, virtually no pain points

atomic elk
#

this is gonna sound dumb but how do I stop a server once I've created it?

#

I'm assuming RenetServer resource in Replicon is the same as the one in this package? Like Replicon just builds off this crate so they should be the same right?

#

at least, it's listed as a dependent in bevy replicon

#

does the server just stop after I remove the transport and server resource?

#

yeah it looks like that's what happens. at least I can no longer connect to the server after I remove those resources

#

still not entirely sure if I'm disposing of it properly

bleak token
atomic elk
#

sweet thanks!

scarlet cradle
#

One more question, has anyone done long-lived server processes with renet? just curious if I'd run into issues if a server ran for a few months.

near juniper
#

You should never run a server for a few months anyway

scarlet cradle
#

ya, that's an outer-bound for sure

#

I can see a month tho

#

most of my stuff would be under a day as far as game instance go, chat and few other backend server I'm implementing as a long-living unix daemons in headless bevy app

#

something akin to Battle.net like services is the idea here

#

I will shard most things ofc, just looking for gotchas in the extremes

hollow karma
#

Not exactly the extreme you're looking for but I did leave my server and client running for a week by accident and when I came back home I ran around the level a bit and didn't notice any issues.

scarlet cradle
hollow karma
#

What is user_data and how do I access it on the server?

#

I figure I can put a username in there or something

normal bay
#

Just some raw bytes in the connect token that are readable on the server (but not the client, they are encrypted).

hollow karma
normal bay
scarlet cradle
#

i'm probably just blind, but where do you find connecting/connected client address

scarlet cradle
#

ah thanks, I was looking in the wrong place for it =p

bleak token
eternal crater
normal bay
eternal crater
normal bay
#

Thanks for releasing btw :) lots of people on the edge of their seats for renet haha

eternal crater
#

BTW, why you are having this problem? Why not remove the RenetClient when the disconnect happens

normal bay
#

Also now that you're here, what are your thoughts on #145?

normal bay
#

Afaik there is no advantage to updating a disconnected client, so disabling it on disconnect is a small quality-of-life boost to the API. And more explicitly aligns with the actual behavior.

eternal crater
# normal bay Also now that you're here, what are your thoughts on #145?

I haven't checked it fully, but using traits for injecting sockets in the netcode transport was a thing I tried before.
I tried for the first steam implementation (now I just don't use netcode for it, only steam with renet).

I prefer to manually implement a new transport instead of impl a trait. Most of the time the traits need tweaking when adding new stuff, and then we have blank impl for some functions, only half ones are used by some.

Also some people don't need netcode when making a new transport, and this just adds complexity to the netcode implementation.

normal bay
# eternal crater I haven't checked it fully, but using traits for injecting sockets in the netcod...

I agree with all your caveats about when a trait is not useful/inconvenient. However it is very useful for:

  • Sticking netcode on top of different transports. Right now there is no reasonable solution for using netcode in the browser other than completely forking renetcode, which IMO is a big problem. The webtransport PR is essentially useless for games without something like netcode on top (regardless of whatever extremely dubious ideas people have about using raw unreliable packets).
  • Using netcode in unit tests and benchmarks with an in-memory transport.
  • Layering network effects between the socket and netcode for programmatic testing, e.g. inserting latency/jitter/packet loss. If renet had a third-party crate with a cross-platform network-effect instrument, that would be huge.
near juniper
#

Is the steam transport released now?

eternal crater
# near juniper Is the steam transport released now?

Soon,
BTW, does anyone want to test the renet_steam pretty quickly. Just need to get the main branch of renet_steam and run the example to sse if everything works. Before I had a notebook to test, don't want to download a VM just for this quick test :0

eternal crater
normal bay
normal bay
#

New PR to support servers with multiple data sources (sockets): https://github.com/lucaspoffo/renet/pull/150. This PR would make it easy to have both native and WASM clients connecting to the same server, and make it possible for clients to switch between native and browser mid-game (assuming you have a reconnect framework).

ember flame
#

Hi! I am writing a multiplayer game and noticed that there is a flood of small packets (26 bytes payload) between the server and the client, in my case it is several thousand, probably because my server runs with MinimalPlugins, which does not limit the framerate, which ended up sending 3000-7000 packets per second. Are these the keepalive packets? Is there any way to tune the frequency of those?

#

I noticed the same packets in the renet demo_bevy are sent at about 250 packets per second.

scarlet cradle
#

2024-02-25T17:54:08.850129Z ERROR log: Failed to process packet: no private key was found for this address spams until the client drops the connection ^ the above seems to be the cause why I get this flooding too =)

#

that's a previously connected client attempting to send to a new server process

#

it's repeating due to the above issue

ember flame
#

I don't have the error message and the packets do not get sent before I start the fresh client, so I am pretty sure it is not the cause. I am testing everything on my localhost

#

I was able to reduce the flooding by introducing a delay to the ScheduleRunnerPlugin (which also helped the CPU usage)

scarlet cradle
#

the error message is tangential to the flooding to be clear

#

the error only happens if you connect to a server, restart the server process while connected

#

server rejects the packets in this case, but due to the flooding I get hundreds of these messages

ember flame
#

Got it, sorry misunderstood initially 😅

scarlet cradle
#

I'm going to look into what is happening with send-rate later, maybe there's a config option or something I missed for that

final beacon
scarlet cradle
#

it's still an issue with a fixed timestep

#

just less of an issue

#

no need for per-frame heartbeat if that's what it is

scarlet cradle
#

I think what can be done here is adding a new field for heartbeat, also server never should respond to a heartbeat IMO, just track that the client sends one at around the expected delta

#

also I've fouind I needed to patch bevy_renet to use Time<Fixed> and FixedUpdate schedules

#

there's a branch or two I noticed could be removed with some slight refactoring, not a huge win but something

bleak token
eternal crater
#

And since we send every frame, running at really high framerate really pumps up the cost for this packet.

scarlet cradle
#

ya, I figured that out after =)

scarlet cradle
scarlet cradle
#

would upstream be down for allowing for a codec and transport trait end-users can implement?

#

I did manage to integrate an alternate protocol into renet and bevy_renet without too much patching but it was still somewhat intrusive to the higher level crates

pure bramble
#

i bind the client socket to 0.0.0.0:0, the server socket to 0.0.0.0:PORT, and connect the client to CLOUD_PUBLIC_IP:PORT
the server on cloud is not getting anything from my client (everything worked when testing locally)
(i did not forward the port or setup a proxy or do anything extra on the cloud)
(yes i always double check the public ip of the cloud VM since it changes)

#

in my client

#

in my server

#

(i try to connect to the cloud with cargo run -p client online)

hollow karma
#

BTW you can do this instead SocketAddr::new(IpAddr::V4(Ipv4Addr::UNSPECIFIED), port);

How is PORT getting there? Is the port correct?

#

You are also putting 0.0.0.0:PORT as the public address, I wonder if that needs to be the actual IP of the VM

#

Although, mine is like that too and my friend can connect to my PC, but maybe there's something funky going on with that when it's in a VM, internal vs external

#

I'm working on my cloud impl right now so I can post here if I find anything

pure bramble
pure bramble
pure bramble
hollow karma
#

Like is it in a Docker container

pure bramble
#

nono, just a linux vm running a server executable

#

also something confusing, there is a difference between "public" IP from what i can see when i curl ipconfig.io in the VM, and what GCP states as the "external" IP

#

they are different, i think i tried both, and in both cases the cloud server isnt receiving anything from my local client

hollow karma
#

So you tried binding to 0.0.0.0, and set the public address to the external ?

pure bramble
#

in the client yes

#

i will try both again just to make sure

hollow karma
#

I would try that on the server, I think you always want to bind to 0.0.0.0, but you may want the public_addresses array to contain whatever GCP states as the external ip

near juniper
#

The way I have it set up is:
server:
public_address: <actual address>:<actual port>
socket: 0.0.0.0:<actual port>

client:
server_address: <actual address>:<actual port>
socket: 0.0.0.0:0

#

Looking at your code your public address on the server is wrong

hollow karma
#

yeah

#

thats gotta be it

#

and in this case the actual_address is the external address

pure bramble
pure bramble
#

the server still cannot get anything from the client.. 🤔

#

client, binds to 0.0.0.0:0 and connects to EXTERNAL_IP:PORT

#

server, binds to 0.0.0.0:PORT and public_addresses is EXTERNAL_IP:PORT

normal bay
pure bramble
eternal crater
pure bramble
pure bramble
#

thank youuuu!!!!!

#

SOLVED ✅

hollow karma
#

Awesome

pure bramble
#

do you just just register your server network code to Update, or do something extra/special?
my server is pretty slow on a super basic game with only a few clients, or frequent messages
it could be because im sending too many client messages over ReliableOrdered i guess
but i wonder if server could run recursively, without waiting for a bevy time step or something (i dont really understand this but yea..)
(my server is on MinimalPlugins, and all of my transfer is Strings which i parse (will use bincode soon))

pure bramble
hollow glade
#

Anyone had luck or have an example of running a renet server in a docker container?

I can’t seem to connect to a locally running container, despite exposing and mounting the UDP socket to my host. Not sure if it’s a socket/renet config or host network issue.

#

Or possibly an iptables issue within the container? I’m using the Rust slim buster as my base..

hollow karma
# hollow glade Anyone had luck or have an example of running a renet server in a docker contain...

yes:


# STAGE1: Build the binary
FROM rust:bullseye as builder

# Install build dependencies
RUN apt-get update && \
    apt-get install -y libasound2-dev libudev-dev

# Create a new empty shell project
WORKDIR /quantsum

# Copy over the Cargo.toml files to the shell project
COPY Cargo.toml Cargo.lock ./

# Build and cache the dependencies
RUN mkdir src && echo "fn main() {}" > src/main.rs
RUN cargo fetch
RUN cargo build --release
RUN rm src/main.rs

# Copy the actual code files and build the application
COPY src ./src/
COPY assets ./assets/
# Update the file date
RUN touch src/main.rs
RUN cargo build --release

# STAGE2: create a slim image with the compiled binary
FROM debian:bullseye as runner

EXPOSE 7777/udp

# Copy the binary from the builder stage
WORKDIR /quantsum
COPY --from=builder /quantsum/target/release/quantsum quantsum
COPY --from=builder /quantsum/assets assets
RUN apt-get update && \
    apt-get install -y libasound2-dev libudev-dev
CMD [ "./quantsum", "dedicated-server" ]
fn insert_server(
    server_has_player: bool,
    mut commands: Commands,
    mut gamemode_controller: ResMut<GameModeController>,
    game_mode: Option<GameMode>,
    map: Option<String>,
    port: u16,
) {
    let server_addr = SocketAddr::new(IpAddr::V4(Ipv4Addr::UNSPECIFIED), port);
    if let Ok(socket) = UdpSocket::bind(server_addr) {
        let server_config = ServerConfig {
            current_time: SystemTime::now()
                .duration_since(SystemTime::UNIX_EPOCH)
                .unwrap(),
            max_clients: 64,
            protocol_id: PROTOCOL_ID,
            public_addresses: vec![server_addr],
            authentication: ServerAuthentication::Unsecure,
        };

        if let Ok(transport) = NetcodeServerTransport::new(server_config, socket) {
            commands.insert_resource(ids::IdPooler::new(server_has_player));
            commands.insert_resource(player::LocalPlayer {
                client_id: ClientId::from_raw(0),
                ..default()
            });
            commands.insert_resource(RenetServer::new(crate::net::connection_config()));
            commands.insert_resource(transport);

            let map = if let Some(map) = map {
                map
            } else {
                "m4".to_string()
            };

            let game_mode = if let Some(game_mode) = game_mode {
                game_mode
            } else {
                GameMode::Coop
            };

            gamemode_controller.set_map_and_gamemode(&map, game_mode);
        }
    }
}```
hollow glade
hollow karma
# hollow glade Thank you! Only obvious difference I see is the use of an “unspecified” server a...

Port is the external port

                let client_id = utils::timestamp_millis_since_epoch();

                let authentication = ClientAuthentication::Unsecure {
                    server_addr: SocketAddr::new(client.ip, client.port),
                    client_id: client_id,
                    user_data: None,
                    protocol_id: PROTOCOL_ID,
                };

                let socket =
                    UdpSocket::bind(SocketAddr::new(IpAddr::V4(Ipv4Addr::UNSPECIFIED), 0)).unwrap();

                let current_time = SystemTime::now()
                    .duration_since(SystemTime::UNIX_EPOCH)
                    .unwrap();

                if let Ok(transport) =
                    NetcodeClientTransport::new(current_time, authentication, socket)
                {
                    commands.insert_resource(ids::IdPooler::new(false));
                    commands.insert_resource(client.clone());
                    commands.insert_resource(player::LocalPlayer {
                        client_id: ClientId::from_raw(client_id),
                        ..default()
                    });
                    commands.insert_resource(RenetClient::new(crate::net::connection_config()));
                    commands.insert_resource(transport);
                }
hollow glade
#

External port being the 7777 you have exposed and I assume mounted to the host?

hollow glade
#

Thanks for the examples, got it working!

heady root
#

Hello - I feel like I'm missing something really obvious, but trying to run any of the renet steam examples gives me:
thread 'main' panicked at renet_steam\examples\echo.rs:147:84: called Result::unwrap()on anErr value: InvalidHandle

I have Steam open, I'm on Windows.

Thank you!

eternal crater
heady root
#
  • cargo r --example echo server
  • copied the id from here: SteamInternal_SetMinidumpSteamID: Caching Steam ID: <THIS_STEAM_ID> [API loaded no]
  • cargo r --example echo client <ID>
heady root
eternal crater
#

Does this happens with the server or client. Are you running both in the same machine?

heady root
#

Server starts and works, client fails SteamClientTransport::new(...) call and panics on unwrap. Running on the same machine.

#

Can it not run on the same machine this way? 🤔

eternal crater
#

No, you can have only one app running with steam. Need to add it to the README. You need another machine (could use a VM) with another steam account running

heady root
#

Oh, looking at the example .webp I really count not tell

eternal crater
#

If you want you can try connecting to my server just to check:
cargo r --example echo client **********

heady root
#

Thanks - I managed with my laptop and a 2nd account as you said

eternal crater
#

Nice

#

Yeah, if you have any problem you can ping me, renet_steam is new, so bug reports are welcomed, also any problems with the API

heady root
#

Thank you, much appreciated

hollow glade
#

What’s the right way to ensure a client is connected to a server before proceeding into systems that send messages? I’m trying to work out a “server selection” menu and want to confirm I’m actually connected before asking for map information, for example.

normal bay
hollow glade
#

hmm actually I was wrong, it does wait for RenetConnectionStatus::Connected let me try rejiggering some things

bleak token
#

@eternal crater May I ask you to take a look at this issue before the next release? https://github.com/lucaspoffo/renet/issues/153
It should be quite simple to add. Needed for bevy_replicon_renet to work with IDs in a transport-independent way.

GitHub

Right now in order to access to ClientId on client I need to interact with NetcodeClientTransport::client_id. It would be convenient to being able to obtain CleintId in a transport-independent way....

prime imp
#

not all transports will use a u64 client id

#

I use a slotmap key for example, another might use a SocketAddr (but i wouldnt recommend this), etc.

bleak token
prime imp
#

currently for replicon integration I use uh

#

1 sec

#
#[derive(Derivative, Resource)]
#[derivative(
    Debug(bound = "T::ClientKey: Debug"),
    Clone(bound = "T::ClientKey: Clone")
)]
pub struct ClientKeys<P: TransportProtocol, T: ServerTransport<P>> {
    id_map: BiHashMap<T::ClientKey, ClientId, ahash::RandomState, ahash::RandomState>,
    next_id: ClientId,
}
#

T::ClientKey being the transport's underlying client id type, and ClientId from replicon

bleak token
#

Got it, makes sense.

prime imp
#

so the client key can't safely be represented as a u64, but it can be mapped like this

bleak token
#

It would be great to have something like this in renet as well...

prime imp
#

wdym exactly

#

the associated type for client keys?

#

or a mapping between ClientId and a T?

bleak token
#

Mapping, yes

prime imp
#

ehh

#

just use a bimap::BiHashMap

bleak token
#

I mean in get an ID from renet, I have to interact with transport which is not good. For each new transport I have to set client id.

#

The only reason why client ID is optional is because I want to support switching transports. If you disable netcode, the ID won't be set. And user need either to set it manually or write an integration for my integration with renet 😅

prime imp
#

yeah it gets complicated when trying to use types from different crates

#

imo the best solution would have been an associated client id type, but its sorta too late for that

#

so the best you can do is just map between their client ID and your client ID type

prime imp
#

yea

#
trait Transport {
  type ClientId: Send + Sync + ...;
}
bleak token
#

This would require generics all over the place.

prime imp
#

that's true

#

but i haven't found it to be a dealbreaker for my code

#

and usually i dont like excessive generics

#

all of my event types have 2 type params, 1 for protocol, 1 for transport

bleak token
#

I think mapping IDs are totally fine. Especially when mappings are simple 1 to 1 without a lookup.

prime imp
#

yeah the fact that it's 1 to 1 helps a lot

#

makes it not a nightmare to deal with

#

just a tiny bit of overhead

#

or make it a u128 and let people pack whatever data they want in that 😈

bleak token
#

Is your ID bigger then u64?

prime imp
#
pub struct KeyData {
    idx: u32,
    version: NonZeroU32,
}
#

its same size as u64 actually

#

but you cant guarantee that ofc

#

because of rustc

bleak token
#

The size will always be 64 bit.

prime imp
#

technically it's not guaranteed because of padding and whatever

#

if it was repr(C) it would be tho

bleak token
#

Yes, but you don't need to do it.

#

Just create a new u64 and bitshift your data into it.

prime imp
#

hmmmmm true

bleak token
#

And you will get rid of the mapping.

prime imp
#

im not a fan of relying on slotmap's KeyData layout though

#

since i dont have control over slotmap

#

actually

bleak token
# prime imp actually

Good, I think like it would be applicable in this case.

But the discussion goes beyond renet :)

prime imp
#

oh right, I can't actually rely on this, because T::ClientKey might not be from a slotmap

prime imp
#

mb

bleak token
prime imp
#

that forces all users of a transport to have a key which can be converted to/from a u64

#

so the replicon integration only works for transports whose client keys can be converted to/from u64s

#

and i would much rather just use a mapping than an encoding like this

bleak token
#

I don't think that it's a hard limitation, but it's up to you.

prime imp
#

well if the hashmap ever pops up in a profiler, then maybe it would be reason to switch over

#

for now i gotta get the actual ordering working 😭😭😭

eternal crater
#

@bleak token How is the ID used in the Client renet integration?

bleak token
scarlet cradle
#

speaking of replacing things with a hashmap, I did exactly that with connection tokens

#

kinda had to since I set 64k max clients

#

seemed like the code was trying to act like a hashmap that avoided allocations anyways, if allocation amortization was the reason for this it's a non-issue as far as I can tell

eternal crater
scarlet cradle
#

aye, fair, just an observation i made while refactoring things

bleak token
zealous wigeon
#

hi! for some reason my server drops clients randomly after a few minutes with a transport layer error. it does that regardless of whether they are running on the same machine or a dedicated server/client. i had similar symptoms when i forgot calculate the delta time for server update. any ideas what it could be?

hollow karma
#

are you doing that?

#

oh, wait, what's the error?

zealous wigeon
#

oh, not an actual error, just a client disconnect event with the reason "connection terminated by the transport layer"

hollow karma
zealous wigeon
#

i'll try..

#

one sec, ill add the client code too

#

client_sync just reads, and player_movement just sends one input message

#

does the bevy renet client need any updating like the regular one that i'm missing or is that automatic?

zealous wigeon
#

also, in wireshark, i could see that the client was still sending packets after the server stopped responding, and it didn't throw any errors

hollow karma
#

I'm not too familiar with just renet, only bevy_renet, but I honestly don't see where the problem could be

How often is the client sending to the server?

#

hopefully Poffo sees this

zealous wigeon
#

it only sends messages on input, but there is constant traffic back and forth even without that

scarlet cradle
#

renet sends acks every frame is what you're seeing there

zealous wigeon
#

that was my assumption, also, i misremembered, the input data is sent every fixed update, regardles in input state

#

oh, and when multiple clients are connected, only one is dropped at a time

eternal crater
#

You can get the transport error from the emitted event NetcodeTransportError:
transport_error: EventReader<NetcodeTransportError>

This will help debug the problem

zealous wigeon
#

unfortunately the server doesn't run inside bevy

#

i guess i could try to insert some debug statements inside the bevy server, i just didn't really want to touch crate code

#

i have that event reader on the client, but it doesn't report any errors

eternal crater
zealous wigeon
#

sure, I'll try that

#

i saw that delay in examples, but wrote mine under the assumption that it would have enough clients, didn't really think of how i would test it tho

near juniper
#

Add in some intelligent sleep, that sleeps for a while if it's not under high enough load

#

Like framepacing

zealous wigeon
#

yeah, i was thinking of that too

#

but i'm still not sure if this solves the problem

#

i don't have a reliable way to reproduce it, just waiting until it happens

#

unfortunately it didn't :{

#

one of the three clients was disconnected without any error reported on its side

zealous wigeon
#

i tried printing every message, and for some reason it does seem to be stable. maybe 16ms just wasn't enough

zealous wigeon
zealous wigeon
#

the problem seems to be with the client. the system just stops running, but i don't see any errors and the app doesn't freeze

eternal crater
#

You can try enabling the logs on the client side, it should print something or emit an event with the error

#

Maybe its the client_id that is generating repeated values if running the clients at the same time.

zealous wigeon
#

i tried logging both messages as well as rtt and packet loss. it would eventually stop printing for like 20 secs and then resume printing the same rtt as before and an increasing rate of packet loss. the first thing that system did was print the logs, so it stopping would mean that either it, or some other system was blocking something.

#

it does print transport errors when for example i stop the server, but not here.

#

it's a debug build with editor_pls, so there might be some interference

#

Oh, good news. i had done those previous test without the thread sleep, because that seemed to improve it and i was trying to reproduce it to see the logs.

#

if delta_time.as_millis() < 32 { thread::sleep(Duration::from_millis(32) - delta_time); };

#

with this, it has been running fine with 3 clients for half an hour

#

thanks for the help :}

hollow karma
#

Is it possible to query a server without connecting to it? My use-case is calculating ping for a server browser.

hollow karma
#

I can think of a way of doing it but curious if this is built in

hollow glade
#

@hollow karma I’d be curious what you came up with if you can share

normal bay
#

@fleet crescent are you around? I'm struggling to run the webtransport client example.

fleet crescent
normal bay
#

I ran this but it's rejecting the files no matter what I do:

cargo build --target wasm32-unknown-unknown --release \
&& wasm-bindgen --no-typescript --out-name echo_client_wt --out-dir pkg --target web ../../target/wasm32-unknown-unknown/release/echo_client_wt.wasm
fleet crescent
#

It needs a index.html yeah, but i mean you need to build the lib. The path is: renet_webtransport/examples. It was either just a Cargo build or a command from the wasm doc page, but it was a one liner for sure and not something crazy like that

#

Ahhh I think it was wasm-pack build

normal bay
#

I'll try that out thanks!

normal bay
#

Still WIP but will announce it once it actually works.

fleet crescent
frail wren
#

what is the diffrence between NetcodeServerTransport and RenetServer?

bleak token
normal bay
fleet crescent
normal bay
bleak pecan
#

i have made compiling client and server but when i run server then client i dont see connected message in the server console

server:

fn main() {
    let mut app = App::new();
    app.add_plugins(RenetServerPlugin);
    
    let server = RenetServer::new(ConnectionConfig::default());
    app.insert_resource(server);

// Transport layer setup
app.add_plugins(NetcodeServerPlugin);
let server_addr = "127.0.0.1:5000".parse().unwrap();
let socket = UdpSocket::bind(server_addr).unwrap();
let server_config = ServerConfig {
    current_time: SystemTime::now().duration_since(SystemTime::UNIX_EPOCH).unwrap(),
    max_clients: 64, 
    protocol_id: 0,
    public_addresses: vec![server_addr], 
    authentication: ServerAuthentication::Unsecure
};
let transport = NetcodeServerTransport::new(server_config, socket).unwrap();
app.insert_resource(transport);
app.add_systems(Startup, handle_events_system);
}

fn handle_events_system(mut server_events: EventReader<ServerEvent>) {
    for event in server_events.read() {
        match event {
            ServerEvent::ClientConnected { client_id } => {
                println!("Client {client_id} connected");
            }
            ServerEvent::ClientDisconnected { client_id, reason } => {
                println!("Client {client_id} disconnected: {reason}");
            }
        }
    }
}
#

client:

    let mut app = App::new();
    app.insert_resource(AmbientLight {
            color: Color::WHITE,
            brightness: 10000.0,
        });
        app.insert_resource(ClearColor(Color::hex("D4F5F5").unwrap()));
        app.insert_resource(RapierConfiguration::default());
        app.add_plugins(DefaultPlugins);
        app.add_plugins(RapierPhysicsPlugin::<NoUserData>::default());

        app.add_plugins(RapierDebugRenderPlugin::default());
        app.add_plugins(FpsControllerPlugin);
        app.add_plugins(
            WorldInspectorPlugin::default().run_if(input_toggle_active(true, KeyCode::KeyL)),
        );
        app.insert_resource(Initem("default".to_string()));
        app.insert_resource(HandItem(100));
        app.insert_resource(AOItems(2));
        app.add_systems(Startup, setup);
        app.add_plugins(GameUI);
        app.add_plugins(UserInv);
        app.add_systems(
            Update,
            (manage_cursor, scene_colliders, respawn, find_interactable,upd_handitem_vis),
        );
        app.add_plugins(RenetClientPlugin);
        let client = RenetClient::new(ConnectionConfig::default());
        
        // Setup the transport layer
        // app.add_plugins(NetcodeClientPlugin);

        let authentication = ClientAuthentication::Unsecure {
            server_addr: "127.0.0.1:5000".parse().unwrap(),
            client_id: 0,
            user_data: None,
            protocol_id: 0,
        };
        let socket = UdpSocket::bind("127.0.0.1:0").unwrap();
        let current_time = SystemTime::now().duration_since(SystemTime::UNIX_EPOCH).unwrap();
        let mut transport = NetcodeClientTransport::new(current_time, authentication, socket).unwrap();

        app.insert_resource(transport);



        app.insert_resource(client);
        app.run();
#

any help is appreciated

eternal crater
bleak pecan
bleak pecan
# hollow glade Yes

when i add the run it fails to run because of Resource requested by bevy_renet::RenetServerPlugin::update_system does not exist: bevy_time::time::Time

eternal crater
#

You need to add the DefaultPlugins in the server also

bleak pecan
hardy cape
#

Hello! I am trying to connect to my server w/ my external ip. I have verified the correct IP is being encoded into the ClientAuthentication::Unsecure enum when trying to connect. However, when I try to connect no connection can be established with the server, and nothing gets logged in the server's console. I pinged my external IP's UDP port and it did hit the server (I got an error message about too small of a packet in my server's console), so I know it is possible to connect to the server using that IP.
Client log when trying to connect:

 INFO cosmos_client::netty::connect: Connecting to [myip]:1337
ERROR log: Failed to update client: client has no more servers to connect    

And nothing gets printed into the server console.

The code to create the ClientAuthentication enum (in client):

let auth = ClientAuthentication::Unsecure {
    client_id,
    protocol_id: PROTOCOL_ID,
    server_addr,
    user_data: Some(token),
};

info!("Connecting to {server_addr}");

NetcodeClientTransport::new(current_time, auth, socket).unwrap()

Any clue why my client can't reach the server?

For context, netcat -v -u -z [myip] 1337 does reach the server, and the client is able to connect if my local IP address is used instead.

eternal crater
hardy cape
# eternal crater Can you show the server setup/configuration?
let public_addr = format!("{addr}:{port}").parse().unwrap();

let socket = UdpSocket::bind(format!("0.0.0.0:{port}")).unwrap();
socket.set_nonblocking(true).expect("Cannot set non-blocking mode!");

let current_time = SystemTime::now().duration_since(SystemTime::UNIX_EPOCH).unwrap();

let server_config = ServerConfig {
    max_clients: 20,
    protocol_id: PROTOCOL_ID,
    public_addresses: vec![public_addr],
    current_time,
    authentication: ServerAuthentication::Unsecure,
};

let transport = NetcodeServerTransport::new(server_config, socket).unwrap();
let server = RenetServer::new(connection_config());
normal bay
hardy cape
normal bay
hardy cape
# normal bay Best guess is whatever you're doing with `server_addr` on the client is not the ...

This is the NetcodeClientTransport creation logic I have in the client:

let addr = format!("{host}:{port}"); // [myip]:1337
let server_addr = addr
        .parse()
        .unwrap_or_else(|e| panic!("Error creating IP address for {host}:{port}. Error: {e:?}"));

let socket = UdpSocket::bind("0.0.0.0:0").unwrap();

socket.set_nonblocking(true).expect("Unable to make UDP non-blocking!");

let current_time = SystemTime::now().duration_since(UNIX_EPOCH).unwrap();
let client_id = current_time.as_millis() as u64;

let name = "CoolPlayer";

let mut token = [0; 256];

// Bincode because this is stored un a u8, with a fixed length of 256
let serialized_name = bincode::serialize(&name).expect("Unable to serialize name");
for (i, byte) in serialized_name.iter().enumerate() {
    token[i] = *byte;
}

let auth = ClientAuthentication::Unsecure {
    client_id,
    protocol_id: PROTOCOL_ID,
    server_addr,
    user_data: Some(token),
};

info!("Connecting to {server_addr}"); // this does print "Connecting to [myip]:1337"

NetcodeClientTransport::new(current_time, auth, socket).unwrap()

I don't see anything out of the ordinary here, or that would otherwise restrict connections

normal bay
hardy cape
eternal crater
normal bay
hardy cape
eternal crater
#

Can you try accessing the server with another computer?
This could be a harpin NAT problem that could be from firewall/router

#

Prob not since you can ping it using the netcat, but never know

hardy cape
#

I'll check on my laptop, but it'll take a sec to compile it

hardy cape
# eternal crater Can you try accessing the server with another computer? This could be a harpin N...

looks like my laptop on the same network can't connect even using the local IP. I don't think it's a firewall/router issue, because I ran an http server on the same port and tried to connect on my laptop, and that worked fine, even with the non-local ip. I ran tcpdump -ni any port 1337 and am not getting anything when I try to connect to the server w/ my laptop. I do get stuff logged when I connect to the http server via my laptop. Could the client be rejecting the outgoing connection?

normal bay
hardy cape
# normal bay `socket.local_addr()` will not print the wildcard... it will print the bound add...

I bound 0.0.0.0 to it

let socket = UdpSocket::bind(format!("0.0.0.0:{port}")).unwrap();
info!("Server Local Addr: {:?}", socket.local_addr()); // -> 2024-07-03T23:46:09.606856Z  INFO cosmos_server::init::init_server: Server Local Addr: Ok(0.0.0.0:1337)

socket.set_nonblocking(true).expect("Cannot set non-blocking mode!");

let public_addr = socket.local_addr().unwrap();

let current_time = SystemTime::now().duration_since(SystemTime::UNIX_EPOCH).unwrap();

let server_config = ServerConfig {
    max_clients: 20,
    protocol_id: PROTOCOL_ID,
    public_addresses: vec![public_addr],
    current_time,
    authentication: ServerAuthentication::Unsecure,
};

let transport = NetcodeServerTransport::new(server_config, socket).unwrap();
let server = RenetServer::new(connection_config());

app.insert_resource(ServerLobby::default())
    .insert_resource(NetworkTick(0))
    .insert_resource(ClientTicks::default())
    .insert_resource(server)
    .insert_resource(transport);

info!("Public address: {public_addr}"); // -> 2024-07-03T23:46:09.606955Z  INFO cosmos_server::init::init_server: Public address: 0.0.0.0:1337
normal bay
hardy cape
#

All good, I appreciate the help

bleak token
#

@eternal crater any chance you could consider adding a simple getter for ClientId for RenetClient?
Because right I can automatically set it only for NetcodeClientTransport:
https://github.com/projectharmonia/bevy_replicon_renet/blob/dfd1a584e83ddff6a2b453a8948f89f850530ea9/src/lib.rs#L210

For all other transports I need to ask users to set it manually :(

GitHub

Integration with renet for bevy_replicon. Contribute to projectharmonia/bevy_replicon_renet development by creating an account on GitHub.

normal bay
#

Would require changing the constructor

bleak token
eternal crater
#

My problem with this, is that I would need to pass it to the constructor just for the getter. The client does not use it

bleak token
near juniper
#

Maybe change the connected state enum to have a Connected(ClientId), so that when the transport changes the status to connected it has to provide a ClientId, and then just have a getter that returns an Option (which is then guaranteed to always be Some if it's connected)

bleak token
#

Makes total sense, that's how we doing it in bevy_replicon.

bleak token
glad sonnet
eternal crater
#

Just released a new version with the bevy update. If there is any problem you can ping me or open an issue 👍 @bleak token @glad sonnet

grim orchid
#

Is there some timing consideration to be aware of on server side?

I have a basic move system (forward/backward) that moves my player way slower than expected (like 5px/second instead of 90px/second).

I copy pasted the exact same move logic on client side and it works perfectly.

fn handle_move_events(
    mut move_events: EventReader<FromClient<Move>>,
    mut players_query: Query<(&mut Transform, &PlayerMarker)>,
    time: Res<Time>
) {
    for FromClient { client_id, event } in move_events.read() {
        'inner: for (mut transform, player) in &mut players_query {
            if player.client_id == *client_id {
                let (direction, mut speed) = match event.move_direction {
                    MoveDirection::Forward => (transform.up(), 3.),
                    MoveDirection::Backward => (transform.down(), 1.5)
                };

                if event.is_running { speed *= 2. }

                transform.translation += direction.normalize() * ONE_METER * speed * time.delta_seconds();
                break 'inner;
            }
        }
    }
}
grim orchid
#

Wake up revelation! not tested yet, still in the bed

Because it's a continuous move, my problem is probably this:
While the Move message goes to the server and the new position is returned to the client, multiple frames occurs on the client side.

Because I rely on the delta time, the move is correctly calculated but only for this server frame. When the new position get back to the client, probably 5 or 6 frames were executed and ignored on the client side.

The solution are:

  • calculate the move not on the delta time but on the delta from when the last message was sent back to the client (question included: does renet have some kind of registry for the events I could rely on?)
  • translate the entity on both the client and the server, my move message should include the current position and the direction, the server would only be a validator and calculate if my character could have done this move from the server-known position to the client-known position, if it's ok, the server only returns a validation, if not, the server returns the last possible position.
bleak token
grim orchid
vocal aspen
#

thanks @normal bay (linking from [here](#1090432346907492443 message))! maybe dumb question -- how do i reduce the tick rate? do i need to copy the plugin code to my own implementation? i didn't see a setting when i looked through, but maybe i missed it

normal bay
vocal aspen
#

oh of course, overall tick rate, not something renet specific. thanks!

normal bay
vocal aspen
#

i appreciate it!

vocal aspen
#

i'm new to the code, and this might be an intentional part of the netcode protocol, but:

it seems like the "empty" payload being sent is a Packet::Ack.

whenever a packet is sent pending_acks is set to sequence..sequence + 1 here. that range will never return false for is_empty here.

because of this, there is always a new Packet::Ack to send, even when all packets have actually been acked.

would that make sense at all?

vocal aspen
#

i’ll move it to the issue 🙂

normal bay
eternal crater
#

the ack can ackt as a keep alive as you think @normal bay, this PR seems to work pretty well, but never finished it and tested completed, I think the rrt calculation were being messed up since before, there was never a delay in acks.

eternal crater
eternal crater
vocal aspen
#

interesting! if nothing else this made me realize i was running my server with an unbounded tick rate, so thank you 🙂

bleak token
#

@eternal crater I see that you updated the crate to 0.15, could you draft a new release on crates.io?

eternal crater
#

BTW, this will be a 1.0 release, the library seems pretty stable for me and the API should not change much after the release

#

If anyone who is using renet wants to showcase it, I can put a link/image in the 1.0 release (would be nice).
Some people I know that are using: @slim torrent @odd palm @bleak token

odd palm
slim torrent
odd palm
bleak token
rare warren
#

Hi all, does anyone have any information what happens if I want to make a server without Bevy as a separate project? on the renet library, but bevy_renet will send packets to regular renet, will something break?

normal bay
hollow karma
#

yeah like koe suggested, I dont see why it wouldn't work. Just match whatever settings bevy_renet uses

wispy ferry
#

does anyone know what 2025-03-13T22:21:42.548331Z ERROR renetcode::server: Failed to process packet: no private key was found for this address means?

hollow karma
#

I may have discovered a silent failure with Renet's Unreliable messaging

So, I'm resending inputs 3 times to the server, over an Unreliable channel. I was not getting any logs saying packets were dropped, or any Renet logs at all.

What I was experiencing was the server receiving them extremely delayed, like several seconds.

How I was sending them:

  • 1 message per input
  • resend each frame
  • at 128hz
  • this means several messages being sent out per frame

Workaround/Solution:

  • bundled them in an array and send them in a single message, meaning only 1 message per frame
  • this completely solved the problem
eternal crater
hollow karma
#

kk will do

#

Must be something on my end though, if that's the case

eternal crater
hollow karma
#

awesome thank you

eternal crater
#

I might actually add a real log::warn there 🤔

bleak token
#

@eternal crater looks like you forgot to release a new version of the bevy_renet on crates.io

hardy cape
#

Has anyone else used renet's steam feature and gotten this error on the server when sending a lot of data?
2025-07-27T21:11:51.753766Z ERROR renet_steam::server: Failed flush message for <my steam id>: limit exceeded

I'm trying to figure out a way to send a large quantity of data without getting this error message spammed, which causes tons of packets to be dropped and having to be re-sent.

Eventually all the data makes it, but it takes a while for everything to get through. When I was just using netcode, this was not an issue. Renet shrinks messages into 1200 byte packets, and I tried reducing the size to 1000 just to make sure the size wasn't a problem. It seems the quantity of packets being sent is the issue, but I'm not sure if there is a way to fix that 🤔

bleak token
hardy cape
#

I think the fix that works best so far is reducing the amount of data sent per tick to a small number of KB and increasing the packet non-acknowledged resend time. This isn't an amazing solution, but seems to work well enough for now

eternal crater
bronze cedar
#

is there a standard way of shutting down the server? (while notifying all the clients instead of them getting timed out)

#

re-starting the server by reconstructing the resources makes clients unable to connect

bleak token
#

Released bevy_replicon_renet targeting the bevy_renet 2.0 release.

eternal crater
eternal crater
#

What transport you are using?

#

Are you recreating the clients also?

bronze cedar
bronze cedar
#

i just destroy the resources and construct new ones

eternal crater
bronze cedar
#

is there a way to notify a client that server is running at a different protocol id than the client?

bronze cedar
eternal crater
#

This is useful when you change the game version and wanna make sure different versions of the game don't ever connect

bronze cedar
eternal crater
#

Yeah, the client will timeout if the protocol differs. Otherwise, it is pretty much up to the matchmaking/server coordinator/lobby system/.... to handle the different versions.

bronze cedar
eternal crater
#

Not really, this implementation follows this standard: https://github.com/mas-bandwidth/netcode/blob/main/STANDARD.md
That tells to ignore packets with different protocol_id. So the client will just timeout. But you should handle it before creating the ConnectToken, and return a error to the user.

Example: when the user searchs for a match, and the client it is not updated, the matchmaking should return an error and request a game restart/update to the client

#

This could be applied to the lobby system/ and other stuff

bronze cedar
eternal crater
#

No 🙁 .Netcode is built with in mind of something middle man that manages who generates the ConnectToken. This could be matchmaking/lobby/..

#

You would need to do the check yourself in some way.

#

Wouldn't worry about it in early development

bronze cedar
#

i guess i could do something like a query port, isn't that what some steam games do?

eternal crater
#

yeah, like a status check. Not sure what some steam games do.

#

I guess they would use a metadata in the lobby with the game version.

#

Or steam handle it automatically for you. Would need to check

tough sandal
#

hello kind people, i have a question about the renet examples, and more precisely about the demo with the pills shooting spheres on client side. everything works nicely, on local or over network. however on client input when holding a movement key down, the pill gets noticeable microtwitches. those microtwitches only appear on the client side window initiating the input. i suppose im not the first to notice this and its not something “on my machine”. im digging and poking around to find a solution, but i wonder if someone knows a fix or a direction to take. i didnt try playing with lerping in the camera follow, or maybe it needs chaining of player input and camera follow when adding systems but that didnt help so far.

help or direction appreciated, so far having great fun playing with it🙏✨

(edit: running on through xorg server native winit but probably not related)

normal bay
tough sandal
# normal bay The examples are very basic, there is no client side prediction or rollback. You...

Thank you for getting back at me. Thankfully the examples are basic, makes it great to poke around and try to wrap my head around whats happening!
So I take "variant latency" as you mean the server is trying to be authoritative and is sending back a transform to my own client, which overrides my own current transform "naively".
Ideal case would be if client does graceful reconciliation not exposing the timing mismatch. I assume working around a fixed server tickrate would also help smooth that out, which I guess isnt handled here.
i'll try to probe and confirm if thats the case (i guess try and filter out my own client id from incoming commands, verifying with my own eyes that's the case).
Did some googling and came across a really cool blog post https://gabrielgambetta.com/client-side-prediction-server-reconciliation.html#server-reconciliation
Thanks again ✨

glossy dust
#

I have an error that I don't understand:

Send + Sync resource renet_steam::server::SteamServerTransport initialized as non_send. It may have been inserted via World::insert_non_send_resource by accident. Try using World::insert_resource instead.

I explicitly insert the transport with world.insert_resource().

Also,

fn test<T>()
where
    T: Send + Sync + 'static,
{
    println!("Hello");
}

test::<SteamServerTransport>();

compiles, so I'm not sure what the issue is.

stiff cradle
bleak token
#

I updated renet to 0.18:
https://github.com/lucaspoffo/renet/pull/193

The author asked me to change the API slightly to avoid Renet depending directly on Bevy. This is because he released Renet 1.0, and since Bevy updates quite often, he have to bump the major version every time.

To address this, I wrapped renet types into newtypes inside bevy_renet.

I would appreciate user feedback on this.

bleak token
#

Drafted a new release of the bevy_replicon_renet with bevy 0.18 and bevy_renet 4.0.

#

renet no longer depends on bevy_ecs, so bevy_renet now wrap all types.
If you migrate, you need to change the imports from renet to bevy_renet (or to bevy_replicon_renet which re-exports renet). See the changes in examples in the PR above.