Jump to content

Recommended Posts

Posted

First off: hello all! Awesome work on MinecraftForge :) (first post, needs to be celebrated, right?)

 

 

 

The last 3 days I have been working on my own mod, mostly out of boredom. For the last hour I have been tracking an issue that appears to be in Vanilla MC. Normally I would make a patch (or at least an attempt to) and put it on the Issue tracker of github, but I have a hard time finding a solution that is easy and clean. Of course I might also just be plain wrong, so I hope to get some input here. It is rather complex I am afraid. So here it goes:

 

I created an Entity, which moves over a 'track'. Every time it has to turn, it changes motion[XYZ], and sends it to the clients (by setting isAirBorne to true, which is in fact forceUpdate, but who is counting ;)). The Entity has an ISpawnHandler as I have some custom fields to fill, and it is registered so EntityTrackerEntry is doing the updates, both in the position as the motion[XYZ]. This works very well, much more responsive than I expected.

 

In SSP, there is absolutely no issue, which comes as no real surprise.

 

In SMP, it works flawless for all players as long as they are all nearby. And here comes the issue.

 

When the Entity is spawned, it uses pos[XYZ] to tell the client where it is. Next, serverPos[XYZ] is synced with this value, and the Entity is where it should be.

 

Next, the server has its EntityTrackerEntry update. He uses encodedPos[XYZ] (better name would be lastUpdatedPos[XYZ], to give you an idea what this value does) and the pos[XYZ] of the Entity. It calculates its offset, and sends this to all the clients with a RelEntityMove. The client adds the diff to serverPost[XYZ], and here is the issue:

 

This works fine for clients which were there to see the Entity spawn when the server spawned it. But when you receive the spawn packet at any later stage, pos[XYZ] != encodedPos[XYZ]. The next relative move you get brings you to a different position than you should be. So you always end up further in the direction that you are moving, with all the issues and trouble. To me it appears that this is also the reason you sometimes see players/mobs inside stuff or moving 'slightly' wrong.

 

After 400 ticks EntityTrackerEntry sends a Teleport packet, correcting any mistake there might be. At this moment you see the Entity jumping to its real position, and from there on all clients track it correctly.

 

I hope this story is a bit clear. Now of course the question: how to solve it.

 

A few solution I have been pondering about. One obvious would be to store encodedPos[XYZ] in Entity, not EntityTrackerEntry, and send this value with the Spawn packets. This is not as trivial as it sounds, as every vanilla object has its own code to spawn. But, it is just a matter of doing to trace all those locations and make the correct adjustments. The drawback of this approach is that it should be done only on the server.

 

An other solution, which is basically the same solution, would be to tell the Entity about the EntityTrackerEntry object, so it can use encodedPos[XYZ] when needed. This too should be done server-only, and appears to be even more dirty.

 

The other thing I came up with, was to put the new player in a special queue, and first send all the EntityTrackerEntry information, before doing any other packet. But as I am relative new to this code, I wouldn't even know where to start with that.

 

Hence, this post. I am really hoping I missed something obvious, or there is a simple fix to avoid this issue. How this problem appears to me, it is rather nasty, and a 'by design' issue. So I hope you guys have some good input for me.

 

Sorry about the wall of text :D

 

The only thing necessary for the triumph of evil is for good men to do nothing.

Posted

After a lot of digging, it seems one of these 3 solutions would be best:

 

1)

After sending

par1EntityPlayerMP.playerNetServerHandler.sendPacket(this.getSpawnPacket());

send a Teleport packet. This will correct serverPos[XYZ], and it will work. The downside is, that the packet will be at an older position till the first sync (so within 64 ticks it will be at the correct position). It can lag 'tickUpdate - 1' ticks behind, basically, depending on the motion etc.

 

2)

After sending

par1EntityPlayerMP.playerNetServerHandler.sendPacket(this.getSpawnPacket());

send a new packet which sets serverPos[XYZ] (by sending encodedPos[XYZ]), and only that, once.

 

3)

Change all the SpawnPacket to also include encodedPos[XYZ], and use that for serverPos[XYZ] at the client.

 

 

To sum it up:

 

1) is a dirty hack, but patch-wise very small, and does the job (tested it and everything)

2) is most elegant, but requires yet another packet (not a big deal I guess)

3) is most clean, but much more invasive. This should really be fixed in Vanilla MC, and I can only hope they did in 1.3 .. one can dream, not? :)

 

I think I will make a pull request for 2), and see how that works out. Any input would be much appreciated :)

 

[Edit] As promised, a Pull Request is up for 2). It works rather nice, in my test case anyway.

 

The only thing necessary for the triumph of evil is for good men to do nothing.

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.

Announcements



×
×
  • Create New...

Important Information

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