This was done correctly in 1.16.5. I discovered this issue while attempting to help with a MinecraftForge hook around a block entity being loaded and it's chunk reaching ticking state.
The actual transition into ticking for most of game logic happens when ChunkHolder.tickingChunkFuture future completes - that's when a chunk is actually ready to be ticked.
LevelChunk.isTicking used for BlockEntity ticking checks the chunk's ticketLevel, which by my understanding of the code is actually the target level to be reached, not necessarily it's current level. This results in block entities sometimes being ticked a tick too early.
1.16.5 actually checked for the ChunkHolder ticking future instead.
By modifying the code in ServerChunkCache.getChunk to check for completable future that isn't done yet, we were able to confirm that it does in fact cause a hopper on a chunk border to wait for the chunk to load because it has been ticked too early.
Comments 5
They don't keep ticking in border chunks, it's only that they tick in chunks that are going to become ticking as soon as things finish loading, but aren't yet because some chunks are still loading. This is not going to be easy to see ingame without a debugger attached.
I was debugging, invited into hopper tick()
Then made it only send a message if it was not in ticking chunks. I was only able to get entity_ticking chunks
How did you check it? If you check the ticket level (getFullStatus()), that's the same thing as what it's doing. That is getting the target/ticket level. The actual "is ticking" would be ServerChunkCache.isTickingChunk which checks whether the ticking chunk future in ChunkHolder is complete and successful.
I was not able to recreate fully
I was able to notice that some hoppers would tick inside of entity_ticking chunks but not border chunks or anything else.