예제 #1
0
        unsafe void HandleBulkBlockUpdate()
        {
            int   count   = reader.ReadUInt8() + 1;
            World map     = game.World;
            int   mapSize = map.HasBlocks ? map.blocks.Length : 0;

            int *indices = stackalloc int[bulkCount];

            for (int i = 0; i < count; i++)
            {
                indices[i] = reader.ReadInt32();
            }
            reader.Skip((bulkCount - count) * sizeof(int));

            BlockID *blocks = stackalloc BlockID[bulkCount];

            for (int i = 0; i < count; i++)
            {
                blocks[i] = reader.buffer[reader.index + i];
            }
            reader.Skip(bulkCount);

            if (reader.ExtendedBlocks)
            {
                for (int i = 0; i < count; i += 4)
                {
                    byte flags = reader.buffer[reader.index + (i >> 2)];
                    blocks[i + 0] |= (BlockID)((flags & 0x03) << 8);
                    blocks[i + 1] |= (BlockID)((flags & 0x0C) << 6);
                    blocks[i + 2] |= (BlockID)((flags & 0x30) << 4);
                    blocks[i + 3] |= (BlockID)((flags & 0xC0) << 2);
                }
                reader.Skip(bulkCount / 4);
            }

            for (int i = 0; i < count; i++)
            {
                int index = indices[i];
                if (index < 0 || index >= mapSize)
                {
                    continue;
                }

                int x = index % map.Width;
                int y = index / (map.Width * map.Length);
                int z = (index / map.Width) % map.Length;
                if (map.IsValidPos(x, y, z))
                {
                    game.UpdateBlock(x, y, z, blocks[i]);
                }
            }
        }
예제 #2
0
        public unsafe override void LightHint(int startX, int startZ, BlockID *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 (!CalculateHeightmapCoverage(x1, z1, xCount, zCount, elemsLeft, skip, mapPtr))
            {
                FinishHeightmapCoverage(x1, z1, xCount, zCount, skip);
            }
        }
예제 #3
0
        bool BuildChunk(int x1, int y1, int z1, ref bool allAir)
        {
            light = game.Lighting;
            PreStretchTiles(x1, y1, z1);
            BlockID *chunkPtr  = stackalloc BlockID[extChunkSize3]; chunk = chunkPtr;
            byte *   countsPtr = stackalloc byte[chunkSize3 * Side.Sides]; counts = countsPtr;
            int *    bitsPtr   = stackalloc int[extChunkSize3]; bitFlags = bitsPtr;

            MemUtils.memset((IntPtr)chunkPtr, 0, 0, extChunkSize3 * sizeof(BlockID));
            if (ReadChunkData(x1, y1, z1, ref allAir))
            {
                return(false);
            }
            MemUtils.memset((IntPtr)countsPtr, 1, 0, chunkSize3 * Side.Sides);

            chunkEndX = Math.Min(x1 + chunkSize, width);
            chunkEndZ = Math.Min(z1 + chunkSize, length);
            Stretch(x1, y1, z1);
            PostStretchTiles(x1, y1, z1);

            int xMax = Math.Min(width, x1 + chunkSize);
            int yMax = Math.Min(height, y1 + chunkSize);
            int zMax = Math.Min(length, z1 + chunkSize);

            for (int y = y1, yy = 0; y < yMax; y++, yy++)
            {
                for (int z = z1, zz = 0; z < zMax; z++, zz++)
                {
                    int chunkIndex = (yy + 1) * extChunkSize2 + (zz + 1) * extChunkSize + (0 + 1);
                    for (int x = x1, xx = 0; x < xMax; x++, xx++)
                    {
                        curBlock = chunk[chunkIndex];
                        if (info.Draw[curBlock] != DrawType.Gas)
                        {
                            int index = ((yy << 8) | (zz << 4) | xx) * Side.Sides;
                            X      = x; Y = y; Z = z;
                            cIndex = chunkIndex;
                            RenderTile(index);
                        }
                        chunkIndex++;
                    }
                }
            }
            return(true);
        }
예제 #4
0
        unsafe void MapSet(BlockID *ptr, int yStart, int yEnd, BlockID 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) * sizeof(BlockID);
                                #if USE16_BIT
                MemUtils.memset((IntPtr)ptr, (byte)block, startIndex + offset, bytes);
                                #else
                MemUtils.memset((IntPtr)ptr, block, startIndex + offset, bytes);
                                #endif

                offset         += bytes;
                CurrentProgress = (float)offset / count;
            }
        }
예제 #5
0
        bool BuildChunk(int x1, int y1, int z1, ref bool allAir)
        {
            light = game.Lighting;
            PreStretchTiles(x1, y1, z1);
            BlockID *chunkPtr  = stackalloc BlockID[extChunkSize3]; chunk = chunkPtr;
            byte *   countsPtr = stackalloc byte[chunkSize3 * Side.Sides]; counts = countsPtr;
            int *    bitsPtr   = stackalloc int[extChunkSize3]; bitFlags = bitsPtr;

            MemUtils.memset((IntPtr)chunkPtr, 0, 0, extChunkSize3 * sizeof(BlockID));

            bool allSolid = false;

            fixed(BlockRaw *mapPtr = map.blocks)
            {
                                #if !ONLY_8BIT
                if (BlockInfo.MaxUsed >= 256)
                {
                    ReadChunkData_16Bit(x1, y1, z1, mapPtr, ref allAir, ref allSolid);
                }
                else
                {
                    ReadChunkData_8Bit(x1, y1, z1, mapPtr, ref allAir, ref allSolid);
                }
                                #else
                ReadChunkData_8Bit(x1, y1, z1, mapPtr, ref allAir, ref allSolid);
                                #endif

                if (x1 == 0 || y1 == 0 || z1 == 0 || x1 + chunkSize >= width ||
                    y1 + chunkSize >= height || z1 + chunkSize >= length)
                {
                    allSolid = false;
                }

                if (allAir || allSolid)
                {
                    return(false);
                }
                light.LightHint(x1 - 1, z1 - 1, mapPtr);
            }

            MemUtils.memset((IntPtr)countsPtr, 1, 0, chunkSize3 * Side.Sides);
            int xMax = Math.Min(width, x1 + chunkSize);
            int yMax = Math.Min(height, y1 + chunkSize);
            int zMax = Math.Min(length, z1 + chunkSize);

            chunkEndX = xMax; chunkEndZ = zMax;
            Stretch(x1, y1, z1);
            PostStretchTiles(x1, y1, z1);

            for (int y = y1, yy = 0; y < yMax; y++, yy++)
            {
                for (int z = z1, zz = 0; z < zMax; z++, zz++)
                {
                    int chunkIndex = (yy + 1) * extChunkSize2 + (zz + 1) * extChunkSize + (0 + 1);
                    for (int x = x1, xx = 0; x < xMax; x++, xx++)
                    {
                        curBlock = chunk[chunkIndex];
                        if (BlockInfo.Draw[curBlock] != DrawType.Gas)
                        {
                            int index = ((yy << 8) | (zz << 4) | xx) * Side.Sides;
                            X      = x; Y = y; Z = z;
                            cIndex = chunkIndex;
                            RenderTile(index);
                        }
                        chunkIndex++;
                    }
                }
            }
            return(true);
        }
        unsafe bool CalculateHeightmapCoverage(int x1, int z1, int xCount, int zCount, int elemsLeft, int *skip, BlockID *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 && info.BlocksLight[mapPtr[mapIndex]])
                        {
                            int lightOffset = (info.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);
        }
예제 #7
0
 public unsafe override void LightHint(int startX, int startZ, BlockID *mapPtr)
 {
 }
예제 #8
0
 // 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, BlockID* mapPtr);