Example #1
0
        /// <summary>
        /// Fills chunk with layer data starting at startPlaceHeight and ending at endPlaceHeight
        /// </summary>
        /// <param name="chunk">Chunk filled with data</param>
        /// <param name="x">Position on x axis in local coordinates</param>
        /// <param name="z">Position on z axis in local coordinates</param>
        /// <param name="startPlaceHeight">Starting position on y axis in world coordinates</param>
        /// <param name="endPlaceHeight">Ending position on y axis in world coordinates</param>
        /// <param name="blockData">Block data to set</param>
        protected static void SetBlocks(Chunk chunk, int x, int z, int startPlaceHeight, int endPlaceHeight, BlockData blockData)
        {
            int chunkY    = chunk.Pos.y;
            int chunkYMax = chunkY + Env.CHUNK_SIZE;

            int y    = startPlaceHeight > chunkY ? startPlaceHeight : chunkY;
            int yMax = endPlaceHeight < chunkYMax ? endPlaceHeight : chunkYMax;

            ChunkBlocks blocks = chunk.Blocks;
            int         index  = Helpers.GetChunkIndex1DFrom3D(x, y - chunkY, z);

            while (y++ < yMax)
            {
                blocks.SetRaw(index, blockData);
                index += Env.CHUNK_SIZE_WITH_PADDING_POW_2;
            }
        }
Example #2
0
        public override void Build(Chunk chunk, int id, ref Vector3Int worldPos, TerrainLayer layer)
        {
            World world = chunk.World;

            int noise =
                Helpers.FastFloor(NoiseUtils.GetNoise(layer.Noise.Noise, worldPos.x, worldPos.y, worldPos.z, 1f, 3, 1f));
            int leavesRange  = MIN_CROWN_SIZE + noise;
            int leavesRange1 = leavesRange - 1;
            int trunkHeight  = MIN_TRUNK_SIZE + noise;

            // Make the crown an ellipsoid flattened on the y axis
            float a2inv = 1.0f / (leavesRange * leavesRange);
            float b2inv = 1.0f / (leavesRange1 * leavesRange1);

            int x1 = worldPos.x - leavesRange;
            int x2 = worldPos.x + leavesRange;
            int y1 = worldPos.y + 1 + trunkHeight;
            int y2 = y1 + 1 + 2 * leavesRange1;
            int z1 = worldPos.z - leavesRange;
            int z2 = worldPos.z + leavesRange;

            int cx, cy, cz;
            int minX, minY, minZ;
            int maxX, maxY, maxZ;

            AABBInt       bounds   = new AABBInt(x1, worldPos.y, z1, x2, y2, z2);
            Vector3Int    chunkPos = chunk.Pos;
            StructureInfo info     = null;

            // Generate the crown
            Vector3Int posFrom      = new Vector3Int(x1, y1, z1);
            Vector3Int posTo        = new Vector3Int(x2, y2, z2);
            Vector3Int chunkPosFrom = Helpers.ContainingChunkPos(ref posFrom);
            Vector3Int chunkPosTo   = Helpers.ContainingChunkPos(ref posTo);

            minY = Helpers.Mod(posFrom.y, Env.CHUNK_SIZE);
            for (cy = chunkPosFrom.y; cy <= chunkPosTo.y; cy += Env.CHUNK_SIZE, minY = 0)
            {
                maxY = System.Math.Min(posTo.y - cy, Env.CHUNK_SIZE_1);
                minZ = Helpers.Mod(posFrom.z, Env.CHUNK_SIZE);
                for (cz = chunkPosFrom.z; cz <= chunkPosTo.z; cz += Env.CHUNK_SIZE, minZ = 0)
                {
                    maxZ = System.Math.Min(posTo.z - cz, Env.CHUNK_SIZE_1);
                    minX = Helpers.Mod(posFrom.x, Env.CHUNK_SIZE);
                    for (cx = chunkPosFrom.x; cx <= chunkPosTo.x; cx += Env.CHUNK_SIZE, minX = 0)
                    {
                        maxX = System.Math.Min(posTo.x - cx, Env.CHUNK_SIZE_1);

                        int xOff = cx - worldPos.x;
                        int yOff = cy - y1 - leavesRange1;
                        int zOff = cz - worldPos.z;

                        if (cx != chunk.Pos.x || cy != chunk.Pos.y || cz != chunk.Pos.z)
                        {
                            Vector3Int pos = new Vector3Int(cx, cy, cz);
                            Vector3Int min = new Vector3Int(minX, minY, minZ);
                            Vector3Int max = new Vector3Int(maxX, maxY, maxZ);

                            if (info == null)
                            {
                                info = new StructureInfo(id, ref chunkPos, ref bounds);
                            }

                            world.RegisterPendingStructure(info, new StructureContextTreeCrown(id, ref pos, ref worldPos, ref min, ref max, noise));

                            continue;
                        }

                        // Actual crown construction
                        ChunkBlocks blocks  = chunk.Blocks;
                        int         index   = Helpers.GetChunkIndex1DFrom3D(minX, minY, minZ);
                        int         yOffset = Env.CHUNK_SIZE_WITH_PADDING_POW_2 - (maxZ - minZ + 1) * Env.CHUNK_SIZE_WITH_PADDING;
                        int         zOffset = Env.CHUNK_SIZE_WITH_PADDING - (maxX - minX + 1);
                        for (int y = minY; y <= maxY; ++y, index += yOffset)
                        {
                            for (int z = minZ; z <= maxZ; ++z, index += zOffset)
                            {
                                for (int x = minX; x <= maxX; ++x, ++index)
                                {
                                    int xx = x + xOff;
                                    int yy = y + yOff;
                                    int zz = z + zOff;

                                    float _x = xx * xx * a2inv;
                                    float _y = yy * yy * b2inv;
                                    float _z = zz * zz * a2inv;
                                    if (_x + _y + _z <= 1.0f)
                                    {
                                        blocks.SetRaw(index, leaves);
                                    }
                                }
                            }
                        }
                    }
                }
            }

            // Generate the trunk
            posFrom      = new Vector3Int(worldPos.x, worldPos.y, worldPos.z);
            posTo        = new Vector3Int(worldPos.x, worldPos.y + trunkHeight, worldPos.z);
            chunkPosFrom = Helpers.ContainingChunkPos(ref posFrom);
            chunkPosTo   = Helpers.ContainingChunkPos(ref posTo);

            cx = Helpers.MakeChunkCoordinate(worldPos.x);
            cz = Helpers.MakeChunkCoordinate(worldPos.z);

            int tx = Helpers.Mod(worldPos.x, Env.CHUNK_SIZE);
            int tz = Helpers.Mod(worldPos.z, Env.CHUNK_SIZE);

            minY = Helpers.Mod(posFrom.y, Env.CHUNK_SIZE);
            for (cy = chunkPosFrom.y; cy <= chunkPosTo.y; cy += Env.CHUNK_SIZE, minY = 0)
            {
                maxY = System.Math.Min(posTo.y - cy, Env.CHUNK_SIZE_1);

                if (cx != chunk.Pos.x || cy != chunk.Pos.y || cz != chunk.Pos.z)
                {
                    Vector3Int pos = new Vector3Int(cx, cy, cz);
                    Vector3Int min = new Vector3Int(tx, minY, tz);
                    Vector3Int max = new Vector3Int(tx, maxY, tz);

                    if (info == null)
                    {
                        info = new StructureInfo(id, ref chunkPos, ref bounds);
                    }

                    world.RegisterPendingStructure(info, new StructureContextTreeTrunk(id, ref pos, ref min, ref max));

                    continue;
                }

                // Actual trunk construction
                ChunkBlocks blocks = chunk.Blocks;
                int         index  = Helpers.GetChunkIndex1DFrom3D(tx, minY, tz);
                for (int y = minY; y <= maxY; ++y, index += Env.CHUNK_SIZE_WITH_PADDING_POW_2)
                {
                    blocks.SetRaw(index, log);
                }
            }
        }
Example #3
0
        public bool DoDecompression()
        {
            LocalPools    pools    = Globals.WorkPool.GetPool(Chunk.ThreadID);
            BlockProvider provider = Chunk.World.blockProvider;

            if (IsDifferential)
            {
                int blockPosSize  = StructSerialization.TSSize <BlockPos> .ValueSize;
                int blockDataSize = StructSerialization.TSSize <BlockData> .ValueSize;

                positionsModified = new BlockPos[positionsBytes.Length / blockPosSize];
                blocksModified    = new BlockData[blocksBytes.Length / blockDataSize];

                int i, j;
                unsafe
                {
                    // Extract positions
                    fixed(byte *pSrc = positionsBytes)
                    {
                        for (i = 0, j = 0; j < positionsModified.Length; i += blockPosSize, j++)
                        {
                            positionsModified[j] = *(BlockPos *)&pSrc[i];
                            Chunk.Blocks.modifiedBlocks.Add(positionsModified[j]);
                        }
                    }

                    // Extract block data
                    fixed(byte *pSrc = blocksBytes)
                    {
                        for (i = 0, j = 0; j < blocksModified.Length; i += blockDataSize, j++)
                        {
                            BlockData *bd = (BlockData *)&pSrc[i];
                            // Convert global block types into internal optimized version
                            ushort type = provider.GetTypeFromTypeInConfig(bd->Type);

                            blocksModified[j] = new BlockData(type, bd->Solid);
                        }
                    }
                }
            }
            else
            {
                int blockDataSize     = StructSerialization.TSSize <BlockData> .ValueSize;
                int requestedByteSize = Env.CHUNK_SIZE_POW_3 * blockDataSize;

                // Pop a large enough buffers from the pool
                byte[] bytes = pools.byteArrayPool.Pop(requestedByteSize);
                {
                    // Decompress data
                    int decompressedLength = CLZF2.lzf_decompress(blocksBytes, blocksBytes.Length, ref bytes);
                    if (decompressedLength != Env.CHUNK_SIZE_POW_3 * blockDataSize)
                    {
                        blocksBytes = null;
                        return(false);
                    }

                    // Fill chunk with decompressed data
                    ChunkBlocks blocks = Chunk.Blocks;
                    int         i      = 0;
                    unsafe
                    {
                        fixed(byte *pSrc = bytes)
                        {
                            int index   = Helpers.ZERO_CHUNK_INDEX;
                            int yOffset = Env.CHUNK_SIZE_WITH_PADDING_POW_2 - Env.CHUNK_SIZE * Env.CHUNK_SIZE_WITH_PADDING;
                            int zOffset = Env.CHUNK_SIZE_WITH_PADDING - Env.CHUNK_SIZE;

                            for (int y = 0; y < Env.CHUNK_SIZE; ++y, index += yOffset)
                            {
                                for (int z = 0; z < Env.CHUNK_SIZE; ++z, index += zOffset)
                                {
                                    for (int x = 0; x < Env.CHUNK_SIZE; ++x, i += blockDataSize, ++index)
                                    {
                                        BlockData *bd = (BlockData *)&pSrc[i];

                                        // Convert global block type into internal optimized version
                                        ushort type = provider.GetTypeFromTypeInConfig(bd->Type);

                                        blocks.SetRaw(index, new BlockData(type, bd->Solid));
                                    }
                                }
                            }
                        }
                    }
                }
                // Return our temporary buffer back to the pool
                pools.byteArrayPool.Push(bytes);
            }

            ResetTemporary();
            return(true);
        }