Paragliders

Paragliders

4M Downloads

paraglider gets stuck in the "running" state after using a tinkers' construct skyslime sling

esotericist opened this issue ยท 1 comments

commented

forge 40.1.86, mantle 1.18.2-1.9.31, tconstruct 1.18.2-3.6.0.73, paraglider 1.18.2-1.6.0.4
(my test also had jei and my minimap loaded, but those have no interactions with player movement or controls, and those are the only other two mods present during my testing)

the tinkers' construct skyslime sling (the blue sling, which launches you forward) places the player into the sprinting state. it doesn't unset the sprinting state at any point, but it doesn't need to: vanilla mechanics handle this gracefully (fov returns to normal, speed returns to normal, saturation/hunger stops depleting; sprinting ends automatically).

immediately on using the skyslime sling, paragliders transitions to the RUNNING state according to the debug info, but even though the player stops sprinting for all game purposes shortly after, paraglider still thinks the player is in the RUNNING state, and will not exit the running state until the player manually sprints in some fashion.

if stamina consumption while running is enabled, this quickly results in the stamina wheel depleting. worse, if the stamina wheel reaches zero before the player manages to manually sprint, it becomes impossible to exit the running state, as the player can no longer initiate sprinting themselves.

i perceive two distinct issues here:

  1. paraglider isn't responding to whatever conditions vanilla does for "is the player still sprinting"
  2. paraglider doesn't have any kind of failsafe for zero'd stamina from an invalid state; in particular if the player is somehow still sprinting after stamina hits zero, paraglider should probably exit running anyway.
    • some kind of / command to forcibly reset player state would be nice, since removing the exhaustion effect from the player does nothing if it immediately gets readded on the next tick.

video attached demonstrating the issue (with paraglider's debug info enabled):
https://youtu.be/b9rFXZPrQ20

note that in the video i ultimately escape the permanently zero'd stamina state by using the green slimesling to trigger the 'using item' condition, to recover enough stamina to eventually manually sprint.

commented

I believe the root cause of this issue is a state desync caused by Sky Slime Sling item.

  • When it comes to 'sprinting' state of a player, the client has authority. Vanilla MC server does not set sprinting state to player (except for one weird case where the game sets the state to false when jump-attacking but it's kind of an obscure case and it's called on both sides anyway) so I think it's safe to call sprinting state a client-controlled state.
  • Client-to-server sync is done in LocalPlayer's tick method. Each tick the client re-evaluates sprinting state based on input and environment and such, compares the result with previous tick's result, and if it's different, it sends a packet to server.
  • Server-to-client sync is done with special flag holder attached to the player, which gets synced to clients tracking the player entity.
  • As the part of Sky Slime Sling item code you linked runs on both sides, the sprinting value is set on both sides too. On client, due to the execution order between item interaction and re-evaluating sprinting state, the value supplied by the code could be overwritten. If the previous state was false, and the state is re-evaluated to being false this tick, then the sprinting flag true set by Sky Slime Sling code is nullified. In this case, the client has no way of communicating server when did sprinting started and stopped, as the state change never happened.
  • On server, the new state is put on the special flag holder and is synced. Note that state re-evaluation is not present on the server; server cannot change the sprinting flag without getting new value from client or making new entity. Or jump attacking I guess.
  • This is the nitty-gritty behind state desync; on client, the flag is ignored. On server, the flag is set. This state persists until either server or client sends another a new state.

Additionally, you mentioned that:

vanilla mechanics handle this gracefully

This statement is quite bogus because the examples provided there are far from true.

  • I've seen FOV and movement speed getting stuck at sprinting state during my own singleplayer testing. It sometimes gets stuck and sometimes does not, interestingly. My guess is it's related to attribute syncing, because movement speed is set on both sides when setSprinting is called, but server syncs attribute to client when it changes. Depending on which action happens first (attribute update packet arriving or client setting the flag) it might've changed the outcome. Either way, it probably is another unrelated desync state caused by sprinting state desync.
  • Hunger depleting, although not observed right away, is not gone. The reason you never see hunger dropping like full sprinting is because movement exhaustion scales with move distance.

Now, about the interaction between Paragliders' stamina system...

  • As you already know, Paraglider uses isSprinting flag present on server player to evaluate movement state. The check is intentionally done on server-side because f**k clients. The evaluated state is then synced to client, along with the amount of stamina.
  • In this scenario of sprinting desync, nothing is wrong on server side, as player is ""running"" and movement state correctly reflects it.
  • Paraglider has a method of stopping player from sprinting if they run out of stamina, actually! Sadly it's client side only because sprinting state is essentially a client-controlled state. Unless this happens.

I'm hesitant to patch this from Paraglider's side because it doesn't really seem as originating from this mod. I guess I'll make a PR to TCon. Feel free to leave a comment if you have further questions. Have a nice day.