Resyncing entity positions' every 60 ticks breaks entity display's `teleport_duration` interpolation if the position gets sync during a interpolation
Nobody has claimed this yet.
- Dominant language
- Java
- Stars
- 12.7k
- Forks
- 3.5k
- Avg merge
- 3d 13h
- Merged PRs (30d)
- 11
Description
Expected behavior
When spawning a display entity, delaying the teleport a bit (enough that it triggers the periodic pos/rot packet every 60 ticks lived), and then it with a set teleport_duration, the teleportation should work fine with a specific interpolation set.
By the way, THIS IS NOT A PAPER BUG, THIS IS A VANILLA BUG!!! ...but it would be nice if it is possible to fix this on Paper. :3
Observed/Actual behavior
The entity gets slow when it gets to the end of the interpolation.
https://github.com/user-attachments/assets/61b9d7b9-7074-444b-8c6f-afb5dd11b710
Steps/models to reproduce
- Spawn a display entity
- Set the
teleportDurationto 59 ticks - Wait 8 ticks (enough that it goes over the 60 tick position sync)
- Teleport the display entity
- Watch the entity
val cameraEntity = player.world.spawn(
originalCamera,
TextDisplay::class.java
) {
it.teleportDuration = 59
}
Bukkit.broadcastMessage("Camera Entity: ${cameraEntity.entityId}")
cameraEntity.text(textComponent {
content("hello")
})
Bukkit.getScheduler().runTaskLater(
m,
Runnable {
cameraEntity.teleport(originalCamera)
Bukkit.getScheduler().runTaskLater(
m,
Runnable {
cameraEntity.teleport(targetCamera)
},
4L
)
},
4L
)
Plugin and Datapack List
Not applicable
Paper version
This server is running SparklyPaper version 1.21.3-DEV-ver/1.21.3@6921e60 (2024-12-01T03:37:24Z) (Implementing API version 1.21.3-R0.1-SNAPSHOT)
(something something it is my own fork and stuff like that)
Other
This happens due to boolean flag2 = flag1 || this.tickCount % 60 == 0;, because it attempts to resync the position every 60 ticks, however I'm not sure how could that be fixed without tracking when the entity is interpolating on the client side. (which, due to circumstances, the entity may not be interpolating on the client when the teleport_duration is set, example: if you set the teleport duration and teleport the entity on the same tick)
Now, I must say that there is a workaround for this issue... and the workaround is "create a new entity display every 60 ticks".
This DOES NOT HAPPEN if you manually send the add entity + set data + teleport packets
val add = ClientboundAddEntityPacket(
newId,
UUID.randomUUID(),
-28.5,
108.0,
-58.5,
0f,
0f,
net.minecraft.world.entity.EntityType.TEXT_DISPLAY,
0,
Vec3.ZERO,
0.0
)
Bukkit.broadcastMessage(net.minecraft.world.entity.Display.DATA_POS_ROT_INTERPOLATION_DURATION_ID.id.toString())
val metadata = ClientboundSetEntityDataPacket(
newId,
listOf(
SynchedEntityData.DataValue(net.minecraft.world.entity.Display.DATA_POS_ROT_INTERPOLATION_DURATION_ID.id, EntityDataSerializers.INT, 59),
SynchedEntityData.DataValue(
23,
EntityDataSerializers.COMPONENT,
io.papermc.paper.adventure.PaperAdventure.asVanilla(
textComponent("test packet") {}
)
)
)
)
val nmsPlayer = (player as CraftPlayer).handle
nmsPlayer.connection.sendPacket(add)
nmsPlayer.connection.sendPacket(metadata)
Bukkit.getScheduler().runTaskLater(
m,
Runnable {
Bukkit.getScheduler().runTaskLater(
m,
Runnable {
nmsPlayer.connection.sendPacket(
ClientboundTeleportEntityPacket(
newId,
PositionMoveRotation(
Vec3(
targetCamera.x,
targetCamera.y,
targetCamera.z,
),
Vec3(
targetCamera.x,
targetCamera.y,
targetCamera.z,
),
0.0f,
0.0f
),
setOf(),
false
)
)
Bukkit.getScheduler().runTaskLater(
m,
Runnable {
nmsPlayer.connection.sendPacket(
ClientboundTeleportEntityPacket(
newId,
PositionMoveRotation(
Vec3(
targetCamera.x + 10.0,
targetCamera.y,
targetCamera.z,
),
Vec3(
targetCamera.x + 10.0,
targetCamera.y,
targetCamera.z,
),
0.0f,
0.0f
),
setOf(),
false
)
)
},
59L
)
},
4L
)
},
4L
)
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start by reproducing the display entity scenario with teleportDuration set to 59 ticks, then inspect the entity position-sync path containing flag2 = flag1 || this.tickCount % 60 == 0. Compare normal entity updates with the manual packet sequence described in the issue. Done means the periodic sync no longer disrupts client-side teleport interpolation while ordinary position synchronization still works.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- java
- Domain
- game-dev
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Stale
- Clarity
- Mostly clear
- Newbie friendliness
- 35/100