-
Notifications
You must be signed in to change notification settings - Fork 326
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
Optimizing getPossibleEyeHeights() #1732
Optimizing getPossibleEyeHeights() #1732
Conversation
You could just cache the list/array. It would need to be recalculated if the scale changes though. |
The thought crossed my mind but I saw the scale and wasn't sure how to handle it being changed. I don't know how to detect when an attribute has been changed to know when to update the list/array. In addition, I'm unsure if I need to do anything special in order to propagate that change in a latency-compensated way if I cached the array. (IE how to handle the case where a laggy player has scale 2 and the server sets their scale to 1 but the player doesn't receive that packet until 500 ms later. |
I've cached what I can and added additional checks to see if the player is gliding, swimming, or sneaking and returning a different array for each of these cases. I've been told by Cotander that these are desynced, which is why we need to return an array of possible eye heights to begin with. Regardless I've found this code reduces iterations for when the player is standing, sneaking, or flying by ~3x as expected. Even in situations where the player desyncs, which are comparatively rare to the norm, correctness will obviously not be affected. In addition to the existing checks that use this function, I've found it to be a big boon to the performance of LineOfSightPlace and @SamB440's experimental reach checks All that remains is to recalculate on scale changes. I'd appreciate your guidance in helping me with that if possible. |
I've handled changing the array when scale changes with a setRewriter. However while making these changes I've come across 1 major and 2 minor concerns. We don't check when the player is crawling?
|
Update: Vanilla's isCrawling() function just returns isSwimming && !touchingWater If we go vanilla's route of not storing a bool for crawling, we may made need to rethink how we treat isSwimming, especially in simulation. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You should get the attribute on GrimPlayer and do the set rewriter there. Currently you are doing it for every entity.
Tested on 1.8 and 1.21. Everything works. LOSP gets the correct ray on the first iteration basically everytime, effectively making LOSP O(1). In summary, I believe this PR in its current form is ready for merging. For future todos, the only thing would be to fix ViaVersion/ViaRewind/ViaBackwards to deal with legacy players who have scales that aren't 1. I discovered that ViaVersion doesn't handle a player joining on 1.21 -> changing scale -> joining on legacy version very well. We also flagged simulation a ton. I changed the attribute setWriter to accommodate this and most of the instant simulation falses were fixed. Nevertheless via veresion still have issues that persist without grimac being installed |
src/main/java/ac/grim/grimac/utils/data/packetentity/PacketEntitySelf.java
Outdated
Show resolved
Hide resolved
@SamB440 Done. Can you merge this? |
src/main/java/ac/grim/grimac/checks/impl/scaffolding/FarPlace.java
Outdated
Show resolved
Hide resolved
src/main/java/ac/grim/grimac/utils/data/attribute/ValuedAttribute.java
Outdated
Show resolved
Hide resolved
src/main/java/ac/grim/grimac/utils/data/packetentity/PacketEntity.java
Outdated
Show resolved
Hide resolved
…ove unused imports
All requested changes have been made/addressed |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM
This PR makes getPossibleEyeHeights() return double[] and in Standing -> Sneaking -> Elytra order, which is far more likely, reducing the number of average iterations taken in practice to process these checks. In addition, there's no reason to use the list object over the more efficient primitive type, which this PR also changes.
getPossibleEyeHeights() is called for 5 checks in the current codebase. In most cases, its return values are iterated over in a loop to verify some player behavior's like reach or block placement is legitimate. In each of these cases it is far more likely that the player is standing than say flying on an elytra or swimming and hitting an entity.