Lightcalculation of ChunkSelection faulty implemented resulting in client bugs (empty chunks don’t show light/render dark)
The code in ChunkSelection.java that reports if a specific part of a chunk needs to be delivered to a client or not is faulty:
I'm not sure what the Class is named in the obfuscation. In the partially deobfuscated code it's ChunkSelection.java and the method's name is public boolean a().
I'm guessing it's public boolean hasBlockData() in the original code
public boolean a(){ return this.nonEmptyBlockCount == 0; }
This method is called when a Chunk is placed in the OutgoingQueue to a client. It checks if a ChunkSelection should be delivered or not.
The code does not consider the fact that - even if there is no block in a chunkselection - there may still be light-information for that selection.
This results in light-Bugs on the client side if a Chunk hast light-information in a chunkselection that does not contain any blocks.
- World Seed for reproduction: -9208998853395889608 ( 1.8.x WorldGenerator. Specifically 1.8.6 singleplayer in the video)
This Video presents the bug: https://www.youtube.com/watch?v=sfikoyETsJU ( 63 Seconds )
Video content:
- Connecting to a Singleplayer World (same in Multiplayer)
- Two chunks have obvious light-Information missing
- Teleporting does not fix the problem
- Placing a Block inside that specific chunkselection - thus working around the bug - does not fix the bug initially as the information only get updated on ChunkSending.
- Teleporting post the workaround does fix the bug
- Removing the Block - recreating the empty chunkselection and recreating the bug does work post teleport
- F3 shows we are exactly at the edge of a chunkSelection (63/64)
- The client-side light-updates in the area around a player does only fix the problem temporarily
This can be fixed by changing the code:
public boolean a(){ // return this.nonEmptyBlockCount == 0; return false; //kade fix, bukkit/mc reports wrongly if a part of a chunk is empty or not. }
Performance and Gameplay implications of this bugfix
- Performance
The performance impact is negligible. The problem occurs in <5% of chunks. Specifically: It occurs in every Chunk that has Blocks at the top of one ChunkSelection and light-information in the one above that but no blocks.
- Bandwidth
The Bandwidth increases a small amount for the <5% Chunks. But as all that is being sent is the light-map we are talking about a compressed data of only some bytes more.
- Gameplay
There are absolutely no side-effects of this fix. I have been running this code-change on my servers for at least 1 1/2 years now (concurrent playercount > 300).
Conclusion
In essence the Idea behind the "nonEmptyBlockCount == 0"-Check is good. But its neglecting the fact that there might be light-information present. As ChunkSelections without any lightinformation are null anyways there is no need for that check.
Linked Issues
is duplicated by47
relates to6
Created Issue:
Lightcalculation of ChunkSelection faulty implemented resulting in clientbugs
The Code in ChunkSelection.java that reports if a specific part of a chunk needs to be delivered to a client or not is faulty:
I'm not sure what the Class is named in the obfuscation. In the partially deobfuscated code its ChunkSelection.java and the Methodname ist "public boolean a()".
Im guessing its "public boolean hasBlockData()" in the original code
ChunkSelection.javapublic boolean a(){ return this.nonEmptyBlockCount == 0; }This method is called when a Chunk is placed in the OutgoingQueue to a Client. It checks if a ChunkSelection should be delivered or not.
The code does not consider the fact that - even if there is no block in a chunkselection - there may still be light-information for that selection.This results in light-Bugs on the client side if a Chunk hast light-information in a chunkselection that does not contain any blocks.
- World Seed for reproduction: -9208998853395889608
This Video presents the bug: https://www.youtube.com/watch?v=sfikoyETsJU ( 63 Seconds )Video Content:
- Connecting to a Singleplayer World (same in Multiplayer)
- Two Chunks have obvious light-Information missing
- Teleporting does not fix the problem
- Placing a Block inside that specific chunkselection - thus working around the bug - does not fix the bug initially as the information only get updated on ChunkSending.
- Teleporting post the workaround does fix the bug
- Removing the Block - recreating the empty chunkselection and recreating the bug does work post teleport
- F3 Shows we are exactly at the edge of a chunkSelection (63/64)
- The client-side light-updates in the area around a player does only fix the problem temporarily
This can be fixed by changing the code:
ChunkSelection.javapublic boolean a(){ // return this.nonEmptyBlockCount == 0; return false; //kade fix, bukkit/mc reports wrongly if a part of a chunk is empty or not. }Performance and Gameplay implications of this bugfix
- Performance
The performance impact is negligible. The problem occurs in <5% of chunks. Specifically: It occurs in every Chunk that has Blocks at the top of one ChunkSelection and light-information in the one above that but no blocks.
- Bandwidth
The Bandwidth increases a small amount for the <5% Chunks. But as all that is being sent is the light-map we are talking about a compressed data of only some bytes more.
- Gameplay
There are absolutely no side-effects of this fix. I have been running this code-change on my servers for at least 1 1/2 years now (concurrent playercount > 300).Conclusion
In essence the Idea behind the "nonEmptyBlockCount == 0"-Check is good. But its neglecting the fact that there might be light-information present. As ChunkSelections without any lightinformation are null anyways there is no need for that check.Environment
any environment
The Code in ChunkSelection.java that reports if a specific part of a chunk needs to be delivered to a client or not is faulty:
I'm not sure what the Class is named in the obfuscation. In the partially deobfuscated code its ChunkSelection.java and the Methodname ist "public boolean a()".
Im guessing its "public boolean hasBlockData()" in the original code
ChunkSelection.javapublic boolean a(){ return this.nonEmptyBlockCount == 0; }This method is called when a Chunk is placed in the OutgoingQueue to a Client. It checks if a ChunkSelection should be delivered or not.
The code does not consider the fact that - even if there is no block in a chunkselection - there may still be light-information for that selection.This results in light-Bugs on the client side if a Chunk hast light-information in a chunkselection that does not contain any blocks.
- World Seed for reproduction: -9208998853395889608 ( 1.8.x WorldGenerator. Specifically 1.8.6 singleplayer in the video)
This Video presents the bug: https://www.youtube.com/watch?v=sfikoyETsJU ( 63 Seconds )Video Content:
- Connecting to a Singleplayer World (same in Multiplayer)
- Two Chunks have obvious light-Information missing
- Teleporting does not fix the problem
- Placing a Block inside that specific chunkselection - thus working around the bug - does not fix the bug initially as the information only get updated on ChunkSending.
- Teleporting post the workaround does fix the bug
- Removing the Block - recreating the empty chunkselection and recreating the bug does work post teleport
- F3 Shows we are exactly at the edge of a chunkSelection (63/64)
- The client-side light-updates in the area around a player does only fix the problem temporarily
This can be fixed by changing the code:
ChunkSelection.javapublic boolean a(){ // return this.nonEmptyBlockCount == 0; return false; //kade fix, bukkit/mc reports wrongly if a part of a chunk is empty or not. }Performance and Gameplay implications of this bugfix
- Performance
The performance impact is negligible. The problem occurs in <5% of chunks. Specifically: It occurs in every Chunk that has Blocks at the top of one ChunkSelection and light-information in the one above that but no blocks.
- Bandwidth
The Bandwidth increases a small amount for the <5% Chunks. But as all that is being sent is the light-map we are talking about a compressed data of only some bytes more.
- Gameplay
There are absolutely no side-effects of this fix. I have been running this code-change on my servers for at least 1 1/2 years now (concurrent playercount > 300).Conclusion
In essence the Idea behind the "nonEmptyBlockCount == 0"-Check is good. But its neglecting the fact that there might be light-information present. As ChunkSelections without any lightinformation are null anyways there is no need for that check.
is duplicated by
is duplicated by
is duplicated by
is duplicated by
Lightcalculation of ChunkSelection faulty implemented resulting in client bugs
is duplicated by
A comment with security level 'global-moderators' was removed.
any environment
is duplicated by
is duplicated by
is duplicated by
is duplicated by
is duplicated by
relates to
is duplicated by
is duplicated by
is duplicated by
is duplicated by
is duplicated by
The Code in ChunkSelection.java that reports if a specific part of a chunk needs to be delivered to a client or not is faulty:
I'm not sure what the Class is named in the obfuscation. In the partially deobfuscated code its ChunkSelection.java and the Methodname ist "public boolean a()".
Im guessing its "public boolean hasBlockData()" in the original code
ChunkSelection.javapublic boolean a(){ return this.nonEmptyBlockCount == 0; }This method is called when a Chunk is placed in the OutgoingQueue to a
Client. It checks if a ChunkSelection should be delivered or not.
The code does not consider the fact that - even if there is no block in a chunkselection - there may still be light-information for that selection.This results in light-Bugs on the client side if a Chunk hast light-information in a chunkselection that does not contain any blocks.
- World Seed for reproduction: -9208998853395889608 ( 1.8.x WorldGenerator. Specifically 1.8.6 singleplayer in the video)
This Video presents the bug: https://www.youtube.com/watch?v=sfikoyETsJU ( 63 Seconds )Video
Content:
- Connecting to a Singleplayer World (same in Multiplayer)
- Two
Chunks have obvious light-Information missing- Teleporting does not fix the problem
- Placing a Block inside that specific chunkselection - thus working around the bug - does not fix the bug initially as the information only get updated on ChunkSending.
- Teleporting post the workaround does fix the bug
- Removing the Block - recreating the empty chunkselection and recreating the bug does work post teleport
- F3 Shows we are exactly at the edge of a chunkSelection (63/64)
- The client-side light-updates in the area around a player does only fix the problem temporarily
This can be fixed by changing the code:
ChunkSelection.javapublic boolean a(){ // return this.nonEmptyBlockCount == 0; return false; //kade fix, bukkit/mc reports wrongly if a part of a chunk is empty or not. }Performance and Gameplay implications of this bugfix
- Performance
The performance impact is negligible. The problem occurs in <5% of chunks. Specifically: It occurs in every Chunk that has Blocks at the top of one ChunkSelection and light-information in the one above that but no blocks.
- Bandwidth
The Bandwidth increases a small amount for the <5% Chunks. But as all that is being sent is the light-map we are talking about a compressed data of only some bytes more.
- Gameplay
There are absolutely no side-effects of this fix. I have been running this code-change on my servers for at least 1 1/2 years now (concurrent playercount > 300).Conclusion
In essence the Idea behind the "nonEmptyBlockCount == 0"-Check is good. But its neglecting the fact that there might be light-information present. As ChunkSelections without any lightinformation are null anyways there is no need for that check.The code in ChunkSelection.java that reports if a specific part of a chunk needs to be delivered to a client or not is faulty:
I'm not sure what the Class is named in the obfuscation. In the partially deobfuscated code it's ChunkSelection.java and the method's name is public boolean a().
I'm guessing it's public boolean hasBlockData() in the original code
ChunkSelection.javapublic boolean a(){ return this.nonEmptyBlockCount == 0; }This method is called when a Chunk is placed in the OutgoingQueue to a client. It checks if a ChunkSelection should be delivered or not.
The code does not consider the fact that - even if there is no block in a chunkselection - there may still be light-information for that selection.This results in light-Bugs on the client side if a Chunk hast light-information in a chunkselection that does not contain any blocks.
- World Seed for reproduction: -9208998853395889608 ( 1.8.x WorldGenerator. Specifically 1.8.6 singleplayer in the video)
This Video presents the bug: https://www.youtube.com/watch?v=sfikoyETsJU ( 63 Seconds )Video content:
- Connecting to a Singleplayer World (same in Multiplayer)
- Two chunks have obvious light-Information missing
- Teleporting does not fix the problem
- Placing a Block inside that specific chunkselection - thus working around the bug - does not fix the bug initially as the information only get updated on ChunkSending.
- Teleporting post the workaround does fix the bug
- Removing the Block - recreating the empty chunkselection and recreating the bug does work post teleport
- F3 shows we are exactly at the edge of a chunkSelection (63/64)
- The client-side light-updates in the area around a player does only fix the problem temporarily
This can be fixed by changing the code:
ChunkSelection.javapublic boolean a(){ // return this.nonEmptyBlockCount == 0; return false; //kade fix, bukkit/mc reports wrongly if a part of a chunk is empty or not. }Performance and Gameplay implications of this bugfix
- Performance
The performance impact is negligible. The problem occurs in <5% of chunks. Specifically: It occurs in every Chunk that has Blocks at the top of one ChunkSelection and light-information in the one above that but no blocks.
- Bandwidth
The Bandwidth increases a small amount for the <5% Chunks. But as all that is being sent is the light-map we are talking about a compressed data of only some bytes more.
- Gameplay
There are absolutely no side-effects of this fix. I have been running this code-change on my servers for at least 1 1/2 years now (concurrent playercount > 300).Conclusion
In essence the Idea behind the "nonEmptyBlockCount == 0"-Check is good. But its neglecting the fact that there might be light-information present. As ChunkSelections without any lightinformation are null anyways there is no need for that check.
is duplicated by
is duplicated by
is duplicated by
is duplicated by
Lightcalculation of ChunkSelection faulty implemented resulting in client bugs (empty chunks don’t show light/render dark)
relates to
is duplicated by
is duplicated by
is duplicated by
relates to
Suspecting MC-80966, duplicate either way.
It actually duplicates MC-80966.
Thank you for your report!
However, this issue is a Duplicate of MC-80966.
It has been linked to this report. If you have additional information, please add it to that report.
Please search before reporting, as it's likely that one exists already.
Quick Links:
📓 Issue Guidelines – 💬 Community Support – 📧 Customer Support – 📖 Game Wiki
Thank you for your report!
However, this issue is a Duplicate of MC-80966.
It has been linked to this report. If you have additional information, please add it to that report.
Please search before reporting, as it's likely that one exists already.
Quick Links:
📓 Issue Guidelines – 💬 Community Support – 📧 Customer Support – 📖 Game Wiki
Could you show inages with the F3+G debug render on? it’s likely a different issue (MC-80966).
That’s MC-80966, yes.
More likely caused by MC-80966 – this is the only empty chunk visible in the screenshot (all other chunks contain blocks, such as cacti and dead bushes).
That’d be MC-80966 (empty cubic chunks don’t send over light information), this is about light not spreading correctly to chunk borders if just placed, and reloading chunks will fix this.
The first 2 images are duplicate of MC-80966.
I'm getting lighting bugs that are either this or MC-80966 in a 1.13.2 Java multiplayer server.
Here's the lighting bugs I'm getting in 1.13.2. The first two look like the others I'm seeing on this page, and the other two seem more like MC-80966 (the torch one happens at a chunk boundary).
This ticket's last fix version is for a 1.13 snapshot, so if the bug I'm seeing is indeed this issue instead of MC-80966, it would be great if it could be reopened and confirmed for 1.13.2.
















Still present in 16w07b.
Affects 1.9-pre2 also! Just tried. Same thing, place a torch in a chunk and it doesn't go across the boundary
Confirmed for 1.9pre4.
Confirmed 1.10; same seed same coordinates
Using MCP Names: ChunkSelection is ExtendedBlockStorage, and a is isEmpty. In 1.10 ExtendedBlockStorage is obfuscated as asw (you can find this in any version by searching for a String found in Chunk, and then finding the storage array member - the string I used was "Could not set level chunk heightmap, array length is ").
MCP names are way better for dealing with the base code than NMS, since it's got a lot more stuff renamed (and renamed sanely, and in separate packages... It's actually designed to be used by developers, unlike NMS where it's explicitly stated that things may be poorly named and direct use should be avoided. Also, even the non-renamed stuff is named uniquely, so there's only ever one non-renamed method named something (rather than there being two a methods, you'll see (for example) func_184161_a and func_184159_a)). You can also get the obfuscated names from the deobfuscated ones by looking at methods.csv or fields.csv and then using the SRG name found there in the joined.srg file (for class names you only need joined.srg). You can get MCP here.
That said: there is a performance cost to your fix, though it isn't as severe when network compression is factored in. You're still sending a chunk section of air, which is (due to the way the the chunk section is formatted) always going to use at least 4 bits per block (and would have used 16 in 1.8). That's 2048 bytes per section, uncompressed, though all the data is the same and it'll probably be pretty small when compressed.
Also, there are two types of empty chunk sections that can be found. The first is when isEmpty returns true, and the second is when the section itself is null (see Chunk.NULL_BLOCK_STORAGE). Your solution only covers the case where isEmpty is true, but NULL_BLOCK_STORAGE may also apply (though it looks like there may not be any cases where a section should be lit but is null, since they're created when lighting hits them; it's still a possible concern).
I would recommend instead that a protocol change is made to allow using 0 bits per block to indicate a section that has no blocks, but still has light. Those sections (and their light data) would still be sent, but no block data would need to be sent. (And the bits per block field already exists and currently won't ever be 0, so it wouldn't require adding any new data to the packet). Depending on whether NULL_BLOCK_STORAGE turns out to be an issue, it may make sense to remove the primary bit mask from the chunk data packet, but it may not be necessary if it can be reasonably confirmed that there is no light data in those sections. The 0 bits per block thing would be implementable by another IBlockStatePalette, which only ever has a length of 0 and always returns air. It would require client and server code changes, so a serverside mod couldn't do that without client modification, but overall it would be an improvement.
The isEmpty solution does work for servers in the meantime, but it's not ideal.
I do not understand why you wrote this.
True, that section started out as a response to "public boolean a()" and got way too long as I expanded it several times; it's really not that important.
Indeed it is, sorry about that (I didn't have a chance to fully read it). I see that you mention that in the conclusion section, and I should have noticed that.
It isn't fully explained. You say "The Bandwidth increases a small amount for the <5% Chunks. But as all that is being sent is the light-map we are talking about a compressed data of only some bytes more." I feel like that doesn't correctly explain what additional data is being sent (it's a 16x16x16 cube of air blocks). While you may know that, I still feel like it's important to mention.
No, it doesn't overcomplicate it much. The server and client already decide how many bits per block to use (look at BlockStateContainer.func_186012_b). It would introduce some special considerations because right now BitArray doesn't handle a length of 0, but overall it would be better.
And while the data is compressed over the network, it still needs to be uncompressed clientside (and stored). 0 bits per block would eliminate the need to store the all-air sections in memory, both on the client and the server. (And there already is logic to resize the palette if the blocks in it change).
Yes, it is; that check should be removed. But that doesn't mean we can't keep the performance improvements it gives.
I understand what you are trying to say but this is still not very helpful to the ticket:
Your viewing the network/memory cost from the wrong side. By default all Sections are transferred (100% usage). Sometimes there are sections not transferred because of this faulty code (they should be anyways and everyone expects them to!). If you take typical values, lets say a viewdistance of 6 and and 5 sections each chunk. Thats 169 Chunks or 845 Sections. A missing section because of this bug is about 0,1%. This concern is not justified and even a recommendation to implement something to save 0,1% is a pretty hard sell.
It's a more significant issue when you consider artificial structures (for instance, large caves in custom maps), which is also where this issue is more annoying.
MC-911(which was recently made a duplicate of this issue) shows more examples of that. I agree entirely that these sections should be sent.Also, "By default all Sections are transferred (100% usage)." is incorrect, in that null sections aren't transferred. But "5 sections each chunk" does show that you already know that, so this entire paragraph is just me being pedantic.
I decided to do some more calculations and get concrete data.
Preparations
I modified SPacketChunkData to do some calculations on the chunks that are sent. You can see the modified version here (and the modifications themselves are visible on the revisions tab).
I'm comparing the 3 different possible behaviors:
This is done both with the compressed and uncompressed packet data. I'm also printing the chunk sections and whether they are empty, null, or otherwise.
I'm making the assumption that empty sections follow the normal format except that bits per block, palette length, and data array length are all 0 (and the palette and data array are not sent).
Lit superflat preset
First and foremost, there's what I would consider the worst-case scenario: the superflat preset 3;minecraft:bedrock,2*minecraft:dirt,minecraft:glowstone;1;village. That preset has a layer of glowstone on the top layer (somewhat reasonable, though also unlikely), whose light travels into the second chunk section. That means that in every chunk, there is one filled section, one empty section, and 14 null sections, IE 40% of the data sent would be for an empty chunk. Here the improvement is noticeable.
Normal world, but lit
This is another situation where some empty sections might be found: a lit-up world. And yes, the torches do generate some empty sections... but not much.
Amplified world
Amplified worlds sometimes have overhangs that might be empty chunks. Let's see...
Caver's delight customized preset
This preset generates some areas that might be empty chunks, or at least I thought. In reality, it doesn't do much.
Island world superflat preset
What about this one?
Caves of chaos superflat preset
This is probably the only other preset where the difference might be noticeable.
Summary
Basically, you were right. This is a needless optimization, and even skipping empty sections in comparison to sending them doesn't help much. My suggested optimization really doesn't matter too much, since it effectively only reduces the amount of data sent in a section by a third, and there really isn't much data sent when compression is factored in (WOW! We could save a whole byte in the packet that takes 4500 bytes!)
Hi, I'm seeing a similar issue in 1.10.2 and 16w39a in one of my worlds, and trying to figure out if it's related or if I should file a new issue. Here are some screenshots: http://imgur.com/a/OOUVA. Could someone take a quick look and let me know?
@Mike Hays Press F3+G to view chunk borders. If the lighting glitch is right on the edge, then it is this bug; otherwise it might be something else. (Until this bug is fixed, you should be able to work around this bug by placing a piece of string or something else that's relatively hard to see but still isn't air within the 16x16x16 chunk section that has the lighting glitch).
@Pokechu22 Yep, that's why I included chunk borders in most of the pics. Anyway, thanks for confirming, won't file a dupe
Something has changed. From Minecraft 1.10 on, the problem shown in the pictures __1.png and __2.png from 27/Mar/2016 (on my server) is gone. The lighting there is now as it should be. This includes the current version Minecraft 1.11.2.
Confirmed for 1.13-pre1 see latest image
The fix is no longer valid for 1.13 - causes very subtle dark patches in the sky that can only be seen when you fly through them (or client mod)
https://hub.spigotmc.org/jira/browse/SPIGOT-4198
This bug is still present in 1.13.1
I'm getting something that looks like this bug in a 1.13.2 Java multiplayer server.
Here's what's happening in 1.13.2. The torch one is happening at a chunk boundary.
The issue was fixed in 18w43a (the first snapshot for 1.14), but is still present in 1.13.2 (it hadn't been fixed then, but since 18w43a was released 2 days after 1.13.2 it was never added). I've added 1.13.2 to the affected versions for clarity.
Thanks for the info. I'm rather clumsy with snapshot names and didn't realize it was fixed for 1.14.
I really don't understand where I'm supposed to change that code or if im supposed to, having this issue in 1.14 prerelease 2.
There's a different issue that produces similar effects,
MC-142134. Check that issue for more information. (The bug here is a very specific issue regarding empty chunks, and has been fixed, but there's a different, more sporadic issue that still occurs and that isMC-142134).