Cached isIntact() — Frame integrity was being rechecked every 4 ticks for every registered gate. Result is now cached and only invalidated on block break events.
Cached getFrameBlocks() and getPortalBlocks() — Both methods were creating a new list on every call. Results are now cached and invalidated alongside isIntact().
All cache fields are marked transient to prevent Jackson from serializing them to the gate JSON files.
Impact
scanMobsInPortals() — ~14% per tick → < 2% per tick
isIntact() — ~13.70% per tick → ~0% per tick
getPortalBlocks() — recalculated every call → cached ✅
Thanks
Special thanks to @danyadanya for reporting this with a Spark profiler profile.