private void SpreadBlockLight(IBoundedLitBlockCollection[,] chunkMap, int lx, int ly, int lz) { BlockInfo primary = _blockset.GetInfo(lx, ly, lz); int primaryLight = _blockset.GetBlockLight(lx, ly, lz); int priLum = Math.Max(primary.Luminance - primary.Opacity, 0); if (primaryLight < priLum) { _blockset.SetBlockLight(lx, ly, lz, priLum); } if (primaryLight > primary.Luminance - 1 && !primary.TransmitsLight) { return; } int xdim = _xdim; int ydim = _ydim; int zdim = _zdim; Queue <LightRecord> spread = new Queue <LightRecord>(); if (ly > 0) { spread.Enqueue(new LightRecord(lx, ly - 1, lz, primary.Luminance - 1)); } if (ly < ydim - 1) { spread.Enqueue(new LightRecord(lx, ly + 1, lz, primary.Luminance - 1)); } spread.Enqueue(new LightRecord(lx - 1, ly, lz, primary.Luminance - 1)); spread.Enqueue(new LightRecord(lx + 1, ly, lz, primary.Luminance - 1)); spread.Enqueue(new LightRecord(lx, ly, lz - 1, primary.Luminance - 1)); spread.Enqueue(new LightRecord(lx, ly, lz + 1, primary.Luminance - 1)); while (spread.Count > 0) { LightRecord rec = spread.Dequeue(); int xi = rec.x + xdim; int zi = rec.z + zdim; IBoundedLitBlockCollection cc = chunkMap[xi / xdim, zi / zdim]; if (cc == null) { continue; } int x = xi % xdim; int y = rec.y; int z = zi % zdim; BlockInfo info = cc.GetInfo(x, y, z); int light = cc.GetBlockLight(x, y, z); int dimStr = Math.Max(rec.str - info.Opacity, 0); if (dimStr > light) { cc.SetBlockLight(x, y, z, dimStr); if (info.TransmitsLight) { int strength = (info.Opacity > 0) ? dimStr : dimStr - 1; if (rec.y > 0) { spread.Enqueue(new LightRecord(rec.x, rec.y - 1, rec.z, strength)); } if (rec.y < ydim - 1) { spread.Enqueue(new LightRecord(rec.x, rec.y + 1, rec.z, strength)); } spread.Enqueue(new LightRecord(rec.x - 1, rec.y, rec.z, strength)); spread.Enqueue(new LightRecord(rec.x + 1, rec.y, rec.z, strength)); spread.Enqueue(new LightRecord(rec.x, rec.y, rec.z - 1, strength)); spread.Enqueue(new LightRecord(rec.x, rec.y, rec.z + 1, strength)); } } } }
private void UpdateBlockLight() { IBoundedLitBlockCollection[,] chunkMap = LocalBlockLightMap(); int xdim = _xdim; int ydim = _ydim; int zdim = _zdim; while (_update.Count > 0) { BlockKey k = _update.Dequeue(); int index = LightBitmapIndex(k); _lightbit[index] = false; int xi = k.x + xdim; int zi = k.z + zdim; IBoundedLitBlockCollection cc = chunkMap[xi / xdim, zi / zdim]; if (cc == null) { continue; } int lle = NeighborLight(chunkMap, k.x, k.y, k.z - 1); int lln = NeighborLight(chunkMap, k.x - 1, k.y, k.z); int lls = NeighborLight(chunkMap, k.x, k.y, k.z + 1); int llw = NeighborLight(chunkMap, k.x + 1, k.y, k.z); int lld = NeighborLight(chunkMap, k.x, k.y - 1, k.z); int llu = NeighborLight(chunkMap, k.x, k.y + 1, k.z); int x = xi % xdim; int y = k.y; int z = zi % zdim; int lightval = cc.GetBlockLight(x, y, z); BlockInfo info = cc.GetInfo(x, y, z); int light = Math.Max(info.Luminance, 0); light = Math.Max(light, lle); light = Math.Max(light, lln); light = Math.Max(light, lls); light = Math.Max(light, llw); light = Math.Max(light, lld); light = Math.Max(light, llu); light = Math.Max(light - info.Opacity, 0); if (light != lightval) { //Console.WriteLine("Block Light: ({0},{1},{2}) " + lightval + " -> " + light, k.x, k.y, k.z); cc.SetBlockLight(x, y, z, light); if (info.TransmitsLight) { if (k.y > 0) { QueueRelight(new BlockKey(k.x, k.y - 1, k.z)); } if (k.y < ydim - 1) { QueueRelight(new BlockKey(k.x, k.y + 1, k.z)); } QueueRelight(new BlockKey(k.x - 1, k.y, k.z)); QueueRelight(new BlockKey(k.x + 1, k.y, k.z)); QueueRelight(new BlockKey(k.x, k.y, k.z - 1)); QueueRelight(new BlockKey(k.x, k.y, k.z + 1)); } } } }