Jump to content

Updating Player Position and Velocity on Server


DanielP1

Recommended Posts

Hey,

I've been trying to get the position of a player on the server, but I found out that it's mostly wrong and doesn't update every tick. I tried doing this in the capability, but as I said, the position on the server doesn't update every tick (for example, for a few ticks per second, the previous posX would be equal to posX) and a lot of the time it's not accurate.

Right now, I'm sending a packet to the server that sends the client player position to the server in PlayerTickEvent every tick. This approach works, but I was wondering if there is a more efficient way to accomplish this.

Any help is appreciated.

Thank you! :)

Edited by DanielP1
Link to comment
Share on other sites

Minecraft does process the movement every tick.

It just doesn't send the player position to the server unless it "changes".

It does send it if 20 ticks pass without a change.

See LocalPlayer.sendPosition() called from LocalPlayer.tick() for the logic.

 

Quote

Right now, I'm sending a packet to the server that sends the client player position to the server in PlayerTickEvent every tick. 

This is pretty much the same place in the code as where sendPosition() is used. 

 

However, you should really regard the server's values as authoritative and the client's values as tentative/speculative (still to be accepted by the server).

Yes the values may differ because of latency, but any significant processing like combat always uses the server's values.

What the server sees is also what other players see (with some network delay).

Also, if the server thinks the player is moving wrongly it will send a packet to the client telling it to teleport the player to the correct place. 

 

Spamming your position packets may lead to performance degradation?

There is even code in ServerGamePacketListenerImpl to ignore packets if the client sends too many position packets too quickly. 

I assume this is to stop hacking? 

Edited by warjort

Boilerplate:

If you don't post your logs/debug.log we can't help you. For curseforge you need to enable the forge debug.log in its minecraft settings. You should also post your crash report if you have one.

If there is no error in the log file and you don't have a crash report then post the launcher_log.txt from the minecraft folder. Again for curseforge this will be in your curseforge/minecraft/Install

Large files should be posted to a file sharing site like https://gist.github.com  You should also read the support forum sticky post.

Link to comment
Share on other sites

5 hours ago, warjort said:

However, you should really regard the server's values as authoritative and the client's values as tentative/speculative (still to be accepted by the server).

 

Thank you for the reply.

How would I get the correct values for the previous position and the current position on the server? I'm making this item that needs you to catch your breath (i.e., stand in place) for 3 seconds before it does something. When I store in a capability, it periodically shows that I am not moving (the prev pos is equal to the current pos) for some ticks every second, even though I'm actively running. And when I stand in place, it tells me that I am standing in place, but at tick 20 it tells me I am moving for 1 tick and then standing (until I move again, making this a 4 second wait as it resets the 3 seconds).

I hope you understand what I mean and can help me understand why this is happening.

Link to comment
Share on other sites

Spit balling:

If it is just for a player, you could just do the calculation on the client. Then send a network packet to the server when your "out of breath" happens so it can do whatever processing you need it to do.

This will be more efficient and won't swamp the network with your position packets. The only additional network traffic is your out of breath packet.

 

There is nothing wrong with doing stuff on the client if it is more optimal. But any state changes that need saving or sending to other players need to be done on the server.

Of course this assumes you trust the client. Somebody could hack a client that removes your processing. 🙂

  • Like 1

Boilerplate:

If you don't post your logs/debug.log we can't help you. For curseforge you need to enable the forge debug.log in its minecraft settings. You should also post your crash report if you have one.

If there is no error in the log file and you don't have a crash report then post the launcher_log.txt from the minecraft folder. Again for curseforge this will be in your curseforge/minecraft/Install

Large files should be posted to a file sharing site like https://gist.github.com  You should also read the support forum sticky post.

Link to comment
Share on other sites

17 minutes ago, warjort said:

If it is just for a player, you could just do the calculation on the client. Then send a network packet to the server when your "out of breath" happens so it can do whatever processing you need it to do.

 

The thing is that the player will regenerate half a heart every 10 ticks and drinking sounds should be played (from the server) every about 25 ticks until he moves again. So I'm trying to continuously doing stuff on the server side after those 3 seconds, and I felt that it would make life easier if I could just get the proper position values on the server.

I have code for both approaches and the code works exactly the same, but if you're telling me that sending a packet every tick may cause networking issues rather than sending 2 packets every 10 and 25 ticks, then I will stick with the second approach.

Unless you have a different suggestion? :) Or do you think this is the best that can be done in this case?

Edited by DanielP1
Link to comment
Share on other sites

Its not just 1 packet every tick. Its potentially 1 packet to the server, then 1 packet to every other player.

Edited by warjort

Boilerplate:

If you don't post your logs/debug.log we can't help you. For curseforge you need to enable the forge debug.log in its minecraft settings. You should also post your crash report if you have one.

If there is no error in the log file and you don't have a crash report then post the launcher_log.txt from the minecraft folder. Again for curseforge this will be in your curseforge/minecraft/Install

Large files should be posted to a file sharing site like https://gist.github.com  You should also read the support forum sticky post.

Link to comment
Share on other sites

9 minutes ago, warjort said:

Its not just 1 packet every tick. Its potentially 1 packet to the server, then 1 packet to every other player.

So, if I send a packet to all clients around a player every tick to spawn particles for instance, would this be just as bad or not so bad (since you're not sending to the server)? I do this in my mod when a player has some custom effect going for example, so I was a little curious.

(thanks so much for the help btw!) 😁

Edited by DanielP1
Link to comment
Share on other sites

I don't really know what the acceptable limit is. I would try to be conservative so people don't shout at you. 🙂

100 players = 2000 packets/s the server has to send, on top of normal game packets.

Edited by warjort

Boilerplate:

If you don't post your logs/debug.log we can't help you. For curseforge you need to enable the forge debug.log in its minecraft settings. You should also post your crash report if you have one.

If there is no error in the log file and you don't have a crash report then post the launcher_log.txt from the minecraft folder. Again for curseforge this will be in your curseforge/minecraft/Install

Large files should be posted to a file sharing site like https://gist.github.com  You should also read the support forum sticky post.

Link to comment
Share on other sites

5 hours ago, diesieben07 said:

Player position is indeed controlled client side, so you should really apply this client side. Why do you need it server side? Please provide more context.

So after 3 seconds of standing still, everything like occasional healing, some particle effects, and drinking sounds are all done continuously on the server. Previously I was doing this in the client, sending packets every time there is a sound, every time there are particles, and every time the player should heal (since particles, healing, sounds, are all handled on the server). But I modified this after by just sending one packet, notifying the server that the player has stood still for 3 seconds, which will change a new boolean value in the player capability. Everything else is done from the server from there.

This way, it's just one packet when the player stood for 3 seconds, and one packet to send if the player moved after these 3 seconds (to stop the particles, healing, sounds, among other server-side actions on the player).

Hard to explain, but I hope it makes sense. Actually I like the approach I just described, minimal packets to send instead of sending 1 position packet every tick (which can be bad according to @warjort)

Edited by DanielP1
Link to comment
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Unfortunately, your content contains terms that we do not allow. Please edit your content to remove the highlighted words below.
Reply to this topic...

×   Pasted as rich text.   Restore formatting

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.



×
×
  • Create New...

Important Information

By using this site, you agree to our Terms of Use.