[SPIGOT-957] Lightcalculation of ChunkSelection faulty implemented resulting in clientbugs Created: 02/Jun/15 Updated: 25/Jun/16 Resolved: 25/Jun/16 |
|
Status: | Resolved |
Project: | Spigot |
Component/s: | None |
Affects Version/s: | None |
Fix Version/s: | None |
Type: | Bug | Priority: | Major |
Reporter: | Kademlia | Assignee: | Unassigned |
Resolution: | Fixed | Votes: | 0 |
Labels: | 1.8, bug, chunk, chunkselection, light, spigot | ||
Environment: |
[11:52:53 INFO]: [Chunkli] running on Java 1.7.0_80 amd64 |
Attachments: |
![]() ![]() ![]() ![]() |
Description |
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: public boolean a() { 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. The screenshots show the issue very well. The missing light-information is clearly visible. The faulty chunk has blocks exactly up to 63. At 64 a new Chunkselection starts and the light-Information stored in that selection are not delivered to the client This can be fixed by changing the code: |
Comments |
Comment by Kademlia [ 19/Jul/15 ] |
> perhaps combined with some logic when chunks are saved to strip empty chunk sections (if this doesn't cause more lighting issues). I actually wrote that over the last few days to see how much space i get back from the *.mca Files if i do this. In the End it was about 15% size-decrease on a heavily used server (150.000+ Chunk-Plots). I´d expect much less on 'normal' servers. These 15% are mostly due to once created but in the end unused spaces in the *.mca-DataStructure. Only a very small percentage was caused by EmptyChunk-Regions. But still - 15% less *.mca Files is 15% less Data-Cache on the Server Memory/SSD which is nice. On the other hand the maxima here is quite interesting. If you populate a ChunkRegion (32x32Chunks) with random Data your *.mca File will grow to 50+MB and never decrease in size. Optimizing this decreases the size to ~4 MB again. So if you tested alot of stuff with WorldEdit etc. this actually helps a lot. Parsign all that Data an loading or saving chunks would be overkill imo. |
Comment by md_5 [ 19/Jul/15 ] |
Comment by Antony Riley [ 19/Jul/15 ] |
I avoid clientside stuff, so I'll take your word for it. Checked up on the minecraft generator, it only generates chunk sections for sections with non-air blocks. Some comments I read on mojang's bug tracker led me to believe it allocated them all. After some testing it appears the lighting engine causes these sections to be allocated (e.g. placing a torch in an adjacent chunk section). Not all spigot servers are survival or use mojang's chunk generator, some do have large amounts of empty chunk sections, and would still be adversely affected by the fix. I'm half convinced, still think it might be better as an optional thing in spigot which defaults to being disabled, perhaps combined with some logic when chunks are saved to strip empty chunk sections (if this doesn't cause more lighting issues). |
Comment by Kademlia [ 19/Jul/15 ] |
> I don't think it serializes the world data via packets That's actually exactly what happens in SP. This was not always the case but i think at least since release of 1.0 the SP is just a MP-Server wrapped with some code. You can see this with a stacktracer like visualvm inside the jdk and flying around the world/loading many chunks at once Please review the detailed Mojang-Bug report - its SP too: https://bugs.mojang.com/browse/MC-80966 |
Comment by Antony Riley [ 19/Jul/15 ] |
The screenshot was a local world (I did say that), I don't think it serializes the world data via packets, so there shouldn't be any desync between the client and the server (since they're working off the same data model). I did say I'd have to write some code to test if the server side really suffers from that lighting bug. |
Comment by Kademlia [ 19/Jul/15 ] |
An alternative way to fix the problem would be to check the light similar to the ChunkSection -> nonEmptyBlockCount The method public void recalcBlockCounts() checkes on every load if a section should be delivered or not (way more expensive compared to some more networkdata). You could introduce a new variable for the light: public int nonEmptyLightDataCount; // kade fix light public boolean a() { // return this.nonEmptyBlockCount == 0; return this.nonEmptyBlockCount == 0 && this.nonEmptyLightDataCount == 0 ; //kade fix, bukkit reports wrongly if a part of a chunk is empty or not. } public void recalcBlockCounts() { this.nonEmptyBlockCount = 0; this.tickingBlockCount = 0; this.nonEmptyLightDataCount = 0; // kade fix light for (int i = 0; i < 16; ++i) { for (int j = 0; j < 16; ++j) { for (int k = 0; k < 16; ++k) { Block block = this.b(i, j, k); if (block != Blocks.AIR) { ++this.nonEmptyBlockCount; if (block.isTicking()) { ++this.tickingBlockCount; } } if(this.d(i, j, k) != 0 || this.e(i, j, k) != 0){ // kade fix light this.nonEmptyLightDataCount++; } } } } } But as stated above i think the downside of this would be bigger as the CPU-bottleneck is generally more frequent and i rarely hear about bandwidth-problems. Still - this would be the correct fix for the problem. |
Comment by Kademlia [ 19/Jul/15 ] |
Hey, your screenshot is the result of the missing emittedLight-Data for a ChunkSection. The ChunkSection was not delivered as the method mentioned above reported it was not needed - when in fact it is needed to correct the lightning. The lightning on the server is not broken - just the delivery to the client if no blocks are in that section. ChunkSizes: Where did you find it generates all the sections? I´d argue against that - but i dont know what you are referring to with "fix lightning". Regarding the size: You heavily misjudge the implications.
A special case - visible in your secreenshot - would be a empty section somewhere in the middle. This could increase the amount of sections per chunk by more than one. But still - look at how shitty it looks if you dont send that information. I dont view the argument about bandwidth-size as valid in those cases. "Would have to write some serverside lighting debug code to verify though." |
Comment by Antony Riley [ 19/Jul/15 ] |
> 1. "But the server does not send lighting information to the client at all, it is computed clientside." > In fact Chunks cannot decrease in size once they grow. I think the lighting model is broken serverside as well: Would have to write some serverside lighting debug code to verify though. An empty chunk section adds 8192 bytes of block data, 2048 bytes for emitted light and another 2048 bytes for the sky light info, apparently minecraft generates all the chunk sections up to the max height to fix lighting (but not custom generators - that might be a separate bug), so that's an extra 4-8 * 12288 bytes per chunk (before compression to be fair) bytes. I don't think you can call this a negligible performance impact, especially as the chunk may be sent to multiple players. Also of note, packets are compressed separately for each player receiving the chunk. |
Comment by Kademlia [ 19/Jul/15 ] |
Hey, there are several errors in your logic. I guess this is caused by not fully knowing what the difference between skyLight & emittedLight is. I´ll try to explain: 1. "But the server does not send lighting information to the client at all, it is computed clientside." 2. "Your proposed fix won't actually work if there are ChunkSectionss which have always been empty". 3. "downside of doubling the size of the chunk update packet since you'd normally have 8-4 unsent chunk sections out of a max of 16." The implications of this fix are described here as mentioned: https://bugs.mojang.com/browse/MC-80966 Edit: This here is the Server-Bug and the presented fix for that Bug. The ClientBugs are just the Side-Effect of that Bug. Please review the Mojang Topic and the Video explanation ( https://www.youtube.com/watch?v=sfikoyETsJU ). The Video shows the wrongly hold back light-information by the server on a ChunkSection-Change (63 to 64 Y ). |
Comment by md_5 [ 19/Jul/15 ] |
>Your proposed fix won't actually work if there are ChunkSectionss which have always been empty as they will be null on the server so it will never reach the .a() method you propose changing, and it also has the downside of doubling the size of the chunk update packet since you'd normally have 8-4 unsent chunk sections out of a max of 16. Yeah that's more or less the conclusion we came to. |
Comment by Antony Riley [ 19/Jul/15 ] |
But the server does not send lighting information to the client at all, it is computed clientside. I assume the bug is that the client (and server) can't compute lighting for unallocated ChunkSections, because the lighting map is contained in those ChunkSections. Your proposed fix won't actually work if there are ChunkSectionss which have always been empty as they will be null on the server so it will never reach the .a() method you propose changing, and it also has the downside of doubling the size of the chunk update packet since you'd normally have 8-4 unsent chunk sections out of a max of 16. Given the performance issues, and that this is a workaround for a cosmetic client bug, if this is ever fixed, I hope the fix defaults to being disabled. Also of note, the server suffers from almost exactly the same bug (with the caveat that lighting can be computed for empty chunksections which are allocated either by the world generator or by placing and removing blocks). |
Comment by Black Hole [ 04/Jun/15 ] |
Your video shows that the light map is not working in the way I thought it'll work. Obviously it will only be used for transparent blocks and illuminate the neighbor blocks. |
Comment by Kademlia [ 04/Jun/15 ] |
This bug is present in Vanilla Minecraft. |
Comment by Kademlia [ 03/Jun/15 ] |
Let me try to explain it another way: 1. I do not change anything in the world. Placing any block inside the problematic chunk above forcing the ChunkSelection to be instantiated will fix the problem. |
Comment by Black Hole [ 03/Jun/15 ] |
Now I see, you're manipulating the light map and want Spigot to support that. Vanilla behaviour is that AIR blocks don't emit light, so it's not a Spigot bug. Rather you're making a "feature" request. |
Comment by Kademlia [ 03/Jun/15 ] |
@BlackHole This bug ist only visible to players as the server fails to send all the needed chunk-information. And this happens because of the "this.nonEmptyBlockCOunt == 0;" check. Think about it: If the Blocks are only in Chunksection 1 (0-15) and the light-values for layer 15 need to be stored in Y=16. Those information get lost because of the check above. |
Comment by Black Hole [ 03/Jun/15 ] |
Lightning issues occur because lightning caluculation is only done if all neighbor chunks are loaded. So WorldEdit updates far away from players will lead to this. Some lightning issues occor while generating the world. These are also independant from chunk sections. |