Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Resyncing entity positions' every 60 ticks breaks entity display's teleport_duration interpolation if the position gets sync during a interpolation #11694

Open
MrPowerGamerBR opened this issue Dec 1, 2024 · 3 comments · May be fixed by #11695
Labels

Comments

@MrPowerGamerBR
Copy link
Contributor

MrPowerGamerBR commented Dec 1, 2024

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.

javaw_6hxdzwAz6i.mp4

Steps/models to reproduce

  1. Spawn a display entity
  2. Set the teleportDuration to 59 ticks
  3. Wait 8 ticks (enough that it goes over the 60 tick position sync)
  4. Teleport the display entity
  5. 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
                        )
@Tsoccerguy3
Copy link

This is probably related to the issue with MTVehicles here https://github.com/MTVehicles/MinetopiaVehicles

The plugin was working fine in 1.21.1 and now in 1.21.3 or 1.21.4 the movement of the armorstand and tool is not tracking correctly .I can not see what was changed, maybe undocumented .

The vehicle textures are layed on top of the armorstand holding a damaged pickaxe . The location and axis are read and moved around the map with key presses or just W key and look steering (mouse polling). The vehicle can still move by the keys and mouse, but only when hitting other keys (spamming the keys) .Paper is slowing input to the Keys and mouse . The source for the plugin is above . You will see it works well in 1.21.1 and not in versions above . Viaversion is affected in the same way when on 1.21.1 and clients for 1.21.3 or 1.21.4 try to use the plugin. Maybe you still have not applied some patch yet, which is why i can not find documentation yet

@MrPowerGamerBR
Copy link
Contributor Author

@Tsoccerguy3 This patch was not merged to Paper yet, and the bug that causes this issue is in vanilla Minecraft for years already, so it is probably something else.


About the patch itself: I haven't edited it yet to add the Mojira link because I forgot, and because I was still trying to figure out if there's any issues with this solution because it wasn't battle tested.

(I'm not running this patch in production because my issues were solved by using packets for anything that required teleport interpolation, and using the display entity transformation matrix for any display entities that do not actually need to be teleported on the server itself)

@Tsoccerguy3
Copy link

The coder already recognized the problem, the new method when a button is pressed is only saved as a boolean, which only goes to true when the button is pressed again. Before, we used to get a float which showed us how far the key was pressed, so we could ensure continuous movement.
Dont know if this is even fixable going forward.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
Status: No status
2 participants