public unsafe override void LightHint(int startX, int startZ, BlockRaw *mapPtr) { int x1 = Math.Max(startX, 0), x2 = Math.Min(width, startX + 18); int z1 = Math.Max(startZ, 0), z2 = Math.Min(length, startZ + 18); int xCount = x2 - x1, zCount = z2 - z1; int *skip = stackalloc int[xCount * zCount]; int elemsLeft = InitialHeightmapCoverage(x1, z1, xCount, zCount, skip); #if !ONLY_8BIT if (BlockInfo.MaxUsed >= 256) { fixed(BlockRaw *mapPtr2 = game.World.blocks2) { if (!CalculateHeightmapCoverage_16Bit(x1, z1, xCount, zCount, elemsLeft, skip, mapPtr, mapPtr2)) { FinishHeightmapCoverage(x1, z1, xCount, zCount, skip); } } return; } #endif if (!CalculateHeightmapCoverage_8Bit(x1, z1, xCount, zCount, elemsLeft, skip, mapPtr)) { FinishHeightmapCoverage(x1, z1, xCount, zCount, skip); } }
void ReadChunkData_16Bit(int x1, int y1, int z1, BlockRaw *mapPtr, ref bool outAllAir, ref bool outAllSolid) // only assign this variable once { bool allAir = true, allSolid = true; fixed(BlockRaw *mapPtr2 = map.blocks2) { for (int yy = -1; yy < 17; yy++) { int y = yy + y1; if (y < 0) { continue; } if (y >= height) { break; } for (int zz = -1; zz < 17; zz++) { int z = zz + z1; if (z < 0) { continue; } if (z >= length) { break; } int index = (y * length + z) * width + (x1 - 1 - 1); int chunkIndex = (yy + 1) * extChunkSize2 + (zz + 1) * extChunkSize + (-1 + 1) - 1; for (int xx = -1; xx < 17; xx++) { int x = xx + x1; index++; chunkIndex++; if (x < 0) { continue; } if (x >= width) { break; } BlockID rawBlock = (BlockID)(mapPtr[index] | (mapPtr2[index] << 8)); allAir = allAir && BlockInfo.Draw[rawBlock] == DrawType.Gas; allSolid = allSolid && BlockInfo.FullOpaque[rawBlock]; chunk[chunkIndex] = rawBlock; } } } outAllAir = allAir; outAllSolid = allSolid; } }
unsafe void MapSet(BlockRaw *ptr, int yStart, int yEnd, BlockRaw block) { yStart = Math.Max(yStart, 0); yEnd = Math.Max(yEnd, 0); int oneY = Width * Length, yHeight = (yEnd - yStart) + 1; CurrentProgress = 0; for (int y = yStart; y <= yEnd; y++) { MemUtils.memset((IntPtr)ptr, block, y * oneY, oneY); CurrentProgress = (float)(y - yStart) / yHeight; } }
unsafe void MapSet(BlockRaw *ptr, int yStart, int yEnd, BlockRaw block) { yStart = Math.Max(yStart, 0); yEnd = Math.Max(yEnd, 0); int startIndex = yStart * Length * Width; int endIndex = (yEnd * Length + (Length - 1)) * Width + (Width - 1); int count = (endIndex - startIndex) + 1, offset = 0; while (offset < count) { int bytes = Math.Min(count - offset, Width * Length); MemUtils.memset((IntPtr)ptr, block, startIndex + offset, bytes); offset += bytes; CurrentProgress = (float)offset / count; } }
unsafe bool CalculateHeightmapCoverage(int x1, int z1, int xCount, int zCount, int elemsLeft, int *skip, BlockRaw *mapPtr) { int prevRunCount = 0; for (int y = height - 1; y >= 0; y--) { if (elemsLeft <= 0) { return(true); } int mapIndex = x1 + width * (z1 + y * length); int heightmapIndex = x1 + z1 * width; for (int z = 0; z < zCount; z++) { int baseIndex = mapIndex; int index = z * xCount; for (int x = 0; x < xCount;) { int curRunCount = skip[index]; x += curRunCount; mapIndex += curRunCount; index += curRunCount; if (x < xCount && BlockInfo.BlocksLight[mapPtr[mapIndex]]) { int lightOffset = (BlockInfo.LightOffset[mapPtr[mapIndex]] >> Side.Top) & 1; heightmap[heightmapIndex + x] = (short)(y - lightOffset); elemsLeft--; skip[index] = 0; int offset = prevRunCount + curRunCount; int newRunCount = skip[index - offset] + 1; // consider case 1 0 1 0, where we are at 0 // we need to make this 3 0 0 0 and advance by 1 int oldRunCount = (x - offset + newRunCount) < xCount ? skip[index - offset + newRunCount] : 0; if (oldRunCount != 0) { skip[index - offset + newRunCount] = 0; newRunCount += oldRunCount; } skip[index - offset] = newRunCount; x += oldRunCount; index += oldRunCount; mapIndex += oldRunCount; prevRunCount = newRunCount; } else { prevRunCount = 0; } x++; mapIndex++; index++; } prevRunCount = 0; heightmapIndex += width; mapIndex = baseIndex + width; // advance one Z } } return(false); }
// Equivalent to // for x = startX; x < startX + 18; x++ // for z = startZ; z < startZ + 18; z++ // CalcHeightAt(x, maxY, z) if height == short.MaxValue // Except this function is a lot more optimised and minimises cache misses. public unsafe abstract void LightHint(int startX, int startZ, BlockRaw *mapPtr);