I have been trying to solve it myself but that kind of failed so im gonna ask for help here.
Placing Blocks and torches doesnt seem to help in 90% of cases. If i hit the source its gone on the clientside but if i rejoin its all back. I get the feeling the changes/updates to the light isnt saved or smth.
P.S. is every level 14, 13, 12, 11 etc. done on the clientside or could as server sent a mix of 0 and 15 in theory? I mean its an array so i would guess it could
Interestingly i have never seen this bug when placing/breaking torches or when a fire is mext to me. It seems to be tied to "dead"/unloaded chunks
You are correct about it being due to unloaded chunks, or rather, chunks that are at the edges of the loaded area, which are subject to various restrictions on what can happen in order to avoid loading unloaded chunks (for example, entities are only active if a 5x5 chunk area around them is loaded). In particular, light updates are only performed if chunks are loaded within 17 blocks:
public void updateLightByType(EnumSkyBlock par1EnumSkyBlock, int par2, int par3, int par4)
{
if (this.doChunksNearChunkExist(par2, par3, par4, 17))
{
This is also the main source of lighting errors in general, like torches in mineshafts not producing light, lava-filled ravines with water flowing into them still being lit up (the light actually comes from the obsidian itself, which is why placing blocks over it doesn't fix it, until one of the random light checks that are performed around the player happens to hit an affected block), etc, mitigated to a degree in 1.7 by improving the post-generation light checks (in 1.6.4 they run very slowly and may never complete at all if the chunk is unloaded before then, and only occur within a 15x15 chunk area so there is a 3 chunk margin (view distance 10 = 21x21 chunks) where they won't occur unless you come closer).
I made similar changes, although certain conditions (flowing liquids) can still cause lighting issues. I'm also not sure why the game can't properly relight blocks by simply placing and removing a light source, as if the lighting code thinks a glitched block is actually emitting light (a related bug: placing a torch on redstone ore, causing it to also light up, then removing it will reveal that it is "saving" the higher light level from the torch next to it. This can be useful as an indicator of lava next it it though, the cause of this specific issue is that the game considers light-emitting blocks to be transparent, which I fixed by considering their light opacity, but why do they "save" light like that?).
Lighting issues that reappear on world load are likely caused by the fact the server only sends sections that contain any non-air blocks to the client, which will affect adjacent blocks along section boundaries, but does not affect game mechanics (e.g. mobs will not spawn in such darkened areas):
All you have to do to fix this is change this method (ExtendedBlockStorage in 1.6.4) to always return false (the only time it is used in in the code that sends chunks to the client), with minimal overhead (one major exception: once a section has been generated server-side it is never removed; 1.6.4 always generates all 16 sections in Superflat worlds, leading to higher memory usage than default worlds even in vanilla, and much higher if this fix is implemented without fixing the generation code), and you can even remove the need to keep track of the block count (I removed tons of code by doing so*, same for keeping track of whether a section has tickable blocks, as I saw a negligible impact on performance, which is better anyway because of other changes):
public boolean isEmpty()
{
return this.blockRefCount == 0;
}
*The contrast between vanilla's "setExtBlockId" method and my equivalent is amazing, and mine is as simple as you can get (I also removed the support for 4096 IDs since I see no need for it for the foreseeable future, eliminating another check; vanilla itself needs significant code changes to properly use such IDs as Mojang never fully implemented support, moving to a completely different system by 1.13, and arguably, as recent as 1.8, aka "block states"):
public void setBlockID(int posX, int posY, int posZ, int block)
{
this.blockArray[posY << 8 | posZ << 4 | posX] = (byte)block;
}
I also removed this entire method, which is called as each section is loaded, both server and client-side, and whose main purpose, MCP naming aside, is to count up the non-empty and ticking blocks; I also made "null" blocks impossible since I added a "placeholder block" which is assigned to every unused ID (except air but that is already covered by checking if the ID is nonzero, there can be cases where it might be better to have air set to an actual block, eliminating any ID checks, for similar reasons I set "null" chunk sections to an "empty" section, eliminating a null check (the JVM can optimize them away but only if it never actually happens, which will not be the case for chunk sections):
I also added this code to actually remove sections which are totally empty, with minimal overhead since on average a chunk is only checked once every 10 ticks, and the check for blocks/light itself checks from bottom-up, with any data more likely to be in the bottom, and two blocks at once can be checked for light (vanilla uses a "NibbleArray" wrapper for this data so you can only access one block at a time, it does make its internal "data" array public though):
// Checks for and removes empty chunk sections starting from the top down. "Empty" means only air blocks, all 0 block
// light, and all 15 sky light. Each chunk is checked once every 2250 ticks (ticked chunk area is 225 chunks so this
// is one chunk every 10 ticks) and one section is removed per check.
public void removeEmptySections()
{
++this.chunkCheckIndex;
if (this.chunkCheckIndex >= 2250)
{
this.chunkCheckIndex = 0;
for (int i = 15; i >= 0; --i)
{
// isEmpty checks if section is a completely empty section while isSectionEmpty checks if there is any
// block or light data
if (!this.storageArrays[i].isEmpty())
{
if (this.storageArrays[i].isSectionEmpty())
{
this.storageArrays[i] = EMPTY_SECTION;
this.isModified = true;
// Schedules next check for next tick (one section is removed per tick)
this.chunkCheckIndex = 2250;
}
break;
}
}
}
}
// Checks if section is empty, meaning only air blocks, all 0 block light, and all 15 sky light
public boolean isSectionEmpty()
{
if (this.hasSkyLight)
{
for (int i = 0; i < 2048; ++i)
{
// Checks lower and upper 2048 bytes for non-air blocks
if (this.blockArray[i] != 0 || this.blockArray[i + 2048] != 0) return false;
// Checks both nibbles at once
if (this.blocklightArray[i] != 0) return false;
// -1 is 11111111 in byte form (both halves are 15)
if (this.skylightArray[i] != -1) return false;
}
}
else
{
for (int i = 0; i < 2048; ++i)
{
if (this.blockArray[i] != 0 || this.blockArray[i + 2048] != 0) return false;
if (this.blocklightArray[i] != 0) return false;
}
}
return true;
}
I have been trying to solve it myself but that kind of failed so im gonna ask for help here.
Placing Blocks and torches doesnt seem to help in 90% of cases. If i hit the source its gone on the clientside but if i rejoin its all back. I get the feeling the changes/updates to the light isnt saved or smth.
P.S. is every level 14, 13, 12, 11 etc. done on the clientside or could as server sent a mix of 0 and 15 in theory? I mean its an array so i would guess it could
Interestingly i have never seen this bug when placing/breaking torches or when a fire is mext to me. It seems to be tied to "dead"/unloaded chunks
Thanks for any help!
Minecraft 1.6.4 Performance Comparison
This is also the main source of lighting errors in general, like torches in mineshafts not producing light, lava-filled ravines with water flowing into them still being lit up (the light actually comes from the obsidian itself, which is why placing blocks over it doesn't fix it, until one of the random light checks that are performed around the player happens to hit an affected block), etc, mitigated to a degree in 1.7 by improving the post-generation light checks (in 1.6.4 they run very slowly and may never complete at all if the chunk is unloaded before then, and only occur within a 15x15 chunk area so there is a 3 chunk margin (view distance 10 = 21x21 chunks) where they won't occur unless you come closer).
I made similar changes, although certain conditions (flowing liquids) can still cause lighting issues. I'm also not sure why the game can't properly relight blocks by simply placing and removing a light source, as if the lighting code thinks a glitched block is actually emitting light (a related bug: placing a torch on redstone ore, causing it to also light up, then removing it will reveal that it is "saving" the higher light level from the torch next to it. This can be useful as an indicator of lava next it it though, the cause of this specific issue is that the game considers light-emitting blocks to be transparent, which I fixed by considering their light opacity, but why do they "save" light like that?).
Lighting issues that reappear on world load are likely caused by the fact the server only sends sections that contain any non-air blocks to the client, which will affect adjacent blocks along section boundaries, but does not affect game mechanics (e.g. mobs will not spawn in such darkened areas):
MC-80966 Lightcalculation of ChunkSelection faulty implemented resulting in client bugs (empty chunks don’t show light/render dark)
Another manifestation of this can cause sunlight to appear where it shouldn't:
MC-911 Sunlight in big caves and under overhangs
All you have to do to fix this is change this method (ExtendedBlockStorage in 1.6.4) to always return false (the only time it is used in in the code that sends chunks to the client), with minimal overhead (one major exception: once a section has been generated server-side it is never removed; 1.6.4 always generates all 16 sections in Superflat worlds, leading to higher memory usage than default worlds even in vanilla, and much higher if this fix is implemented without fixing the generation code), and you can even remove the need to keep track of the block count (I removed tons of code by doing so*, same for keeping track of whether a section has tickable blocks, as I saw a negligible impact on performance, which is better anyway because of other changes):
*The contrast between vanilla's "setExtBlockId" method and my equivalent is amazing, and mine is as simple as you can get (I also removed the support for 4096 IDs since I see no need for it for the foreseeable future, eliminating another check; vanilla itself needs significant code changes to properly use such IDs as Mojang never fully implemented support, moving to a completely different system by 1.13, and arguably, as recent as 1.8, aka "block states"):
TMCW/World1; that's it?!
I also removed this entire method, which is called as each section is loaded, both server and client-side, and whose main purpose, MCP naming aside, is to count up the non-empty and ticking blocks; I also made "null" blocks impossible since I added a "placeholder block" which is assigned to every unused ID (except air but that is already covered by checking if the ID is nonzero, there can be cases where it might be better to have air set to an actual block, eliminating any ID checks, for similar reasons I set "null" chunk sections to an "empty" section, eliminating a null check (the JVM can optimize them away but only if it never actually happens, which will not be the case for chunk sections):
I also added this code to actually remove sections which are totally empty, with minimal overhead since on average a chunk is only checked once every 10 ticks, and the check for blocks/light itself checks from bottom-up, with any data more likely to be in the bottom, and two blocks at once can be checked for light (vanilla uses a "NibbleArray" wrapper for this data so you can only access one block at a time, it does make its internal "data" array public though):
TheMasterCaver's First World - possibly the most caved-out world in Minecraft history - includes world download.
TheMasterCaver's World - my own version of Minecraft largely based on my views of how the game should have evolved since 1.6.4.
Why do I still play in 1.6.4?