mojira.dev
MC-100341

Getting the lightlevel of a block at a chunkborder causes the neighbor chunk to be loaded

Hey,

several frequently called methods need to check the light-level of a block. For example crops, grass etc. to see if they can grow or not.

The check for the current light at a specific location looks at the light-values of the five blocks near it (up,north,east,south,west). If a neighboring chunk is not loaded it will be synchronously be loaded at this point.

As the algorithm for growth is pretty basic an vague this happens very often resulting in a increased base load of the whole process.

A simple fix would be to return a light level of zero if the chunk is currently not loaded. The impact on gameplay would be negligible.

Comments

Erik Broes

Could you provide a world or setup to reproduce this issue?

migrated

Hey, thank you for responding. Showing this via a worldmap would be quite difficult. I hope relating to the code helps:

This is based on the currently available minecraft_server.1.9.4.jar (and deopfuscated spigot codes)
Obfuscated:
Class: aht.java
Method (~Line 426): public int c(cl \u2603, boolean \u2603)

Deobfuscated:
Class: World.java
Method ( ~Line: 623): public int c(BlockPosition blockposition, boolean flag)

This method would be something like getMaxLightLevel(Position position, boolean firstCall).
The method will try to get the highest light level. It returns the light-level of the block itself if it has one (air/non-solid block)
or the highest of the five closest blocks (up,north,east,south,west). This second part has the problematic code.

Methodflow should be:

  • Return 15 (maxLight) if invalid position

  • if(firstCall && getBlockType(position).isSolid())

    • recursive call to self with neighbor1-block and firstCall = false

    • recursive call to self with neighbor2-block and firstCall = false

    • recursive call to self with neighbor3-block and firstCall = false

    • recursive call to self with neighbor4-block and firstCall = false

    • recursive call to self with neighbor5-block and firstCall = false

    • return highestValue of those calls

  • *else*

    • *Chunk c = getChunkAt(position)* (this is called for all 5 recursive calls from above and results in a forced-chunk-load if the chunk is not yet loaded)

    • return c.getLightLevel(position)

Chunkloads based on this code will happen every time the growth-algorithm tries to grow a plant at the border of a players visible (loaded) area.

Adding something like this code before the highlighted chunk-loading would fix this

if(!isLoaded(position)){ //kade edit; do not load a chunk just to look at the light-value
    	return 0;
   }

On a side-note the same happens when trying to spread grass, mushrooms, mycel, cocoa etc.
In these files there are checks to get the blocktypes of the surrounding blocks and try to spread these blocks afterwards.
Those calls force sync-chunkloads too.

Let me know if there is something missing or additional information are needed.

migrated

Is this still an issue in the latest snapshot 16w44a? If so please update the affected versions.

This is an automated comment on any open or reopened issue with out-of-date affected versions.

wobst.michael

Is this still an issue in the most recent versions (currently that is 1.11) of Minecraft? If so, please update the affected versions and help us keeping this ticket updated from time to time. If you are the owner/reporter of this ticket, you can modify the affected version(s) yourself.

migrated

Erik Broes

Unconfirmed

Minecraft 1.9.1, Minecraft 1.9.2

Retrieved