Beispiel #1
0
        /// <summary>
        /// Queues a modification of blocks in a given range
        /// </summary>
        /// <param name="posFrom">Starting positon in local chunk coordinates</param>
        /// <param name="posTo">Ending position in local chunk coordinates</param>
        /// <param name="blockData">BlockData to place at the given location</param>
        /// <param name="setBlockModified">Set to true to mark chunk data as modified</param>
        /// <param name="onModified">Action to perform once the operation finished</param>
        public void ModifyBlockDataRanged(ref Vector3Int posFrom, ref Vector3Int posTo, BlockData blockData, bool setBlockModified,
                                          Action <ModifyBlockContext> onModified = null)
        {
            // Make sure the values are okay.
            FixValues(ref posFrom.x, ref posTo.x);
            FixValues(ref posFrom.y, ref posTo.y);
            FixValues(ref posFrom.z, ref posTo.z);

            Vector3Int chunkPosFrom = Helpers.ContainingChunkPos(ref posFrom);
            Vector3Int chunkPosTo   = Helpers.ContainingChunkPos(ref posTo);

            ModifyBlockContext context = null;

            if (onModified != null)
            {
                context = new ModifyBlockContext(onModified, this,
                                                 Helpers.GetChunkIndex1DFrom3D(posFrom.x, posFrom.y, posFrom.z),
                                                 Helpers.GetChunkIndex1DFrom3D(posTo.x, posTo.y, posTo.z),
                                                 blockData, setBlockModified);
            }

            // Update all chunks in range
            int minY = Helpers.Mod(posFrom.y, Env.CHUNK_SIZE);

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

                for (int cz = chunkPosFrom.z; cz <= chunkPosTo.z; cz += Env.CHUNK_SIZE, minZ = 0)
                {
                    int maxZ = Math.Min(posTo.z - cz, Env.CHUNK_SIZE_1);
                    int minX = Helpers.Mod(posFrom.x, Env.CHUNK_SIZE);

                    for (int cx = chunkPosFrom.x; cx <= chunkPosTo.x; cx += Env.CHUNK_SIZE, minX = 0)
                    {
                        Vector3Int chunkPos = new Vector3Int(cx, cy, cz);
                        Chunk      chunk    = GetChunk(ref chunkPos);
                        if (chunk == null)
                        {
                            continue;
                        }

                        int maxX = Math.Min(posTo.x - cx, Env.CHUNK_SIZE_1);

                        chunk.Modify(
                            new ModifyOpCuboid(
                                blockData,
                                new Vector3Int(minX, minY, minZ),
                                new Vector3Int(maxX, maxY, maxZ),
                                setBlockModified,
                                context)
                            );
                    }
                }
            }
        }
 /// <summary>
 ///     Access internal array in a circular way
 /// </summary>
 public T this[int i]
 {
     get
     {
         int pos = Helpers.Mod(i + Offset, items.Length);
         return(items[pos]);
     }
     set
     {
         int pos = Helpers.Mod(i + Offset, items.Length);
         items[pos] = value;
     }
 }
Beispiel #3
0
        /// <summary>
        /// Sets the block data at given world coordinates
        /// </summary>
        /// <param name="pos">Global position of the block</param>
        /// <param name="blockData">A block to be placed on a given position</param>
        public void SetBlockData(ref Vector3Int pos, BlockData blockData)
        {
            // Transform the position into chunk coordinates
            Vector3Int chunkPos = Helpers.ContainingChunkPos(ref pos);

            Chunk chunk = GetChunk(ref chunkPos);

            if (chunk == null)
            {
                return;
            }

            int xx = Helpers.Mod(pos.x, Env.CHUNK_SIZE);
            int yy = Helpers.Mod(pos.y, Env.CHUNK_SIZE);
            int zz = Helpers.Mod(pos.z, Env.CHUNK_SIZE);

            chunk.Blocks.SetInner(Helpers.GetChunkIndex1DFrom3D(xx, yy, zz), blockData);
        }
Beispiel #4
0
        public BlockData GetBlockData(Vector3Int pos)
        {
            // Transform the position into chunk coordinates
            Vector3Int chunkPos = Helpers.ContainingChunkPos(ref pos);

            Chunk chunk = GetChunk(ref chunkPos);

            if (chunk == null)
            {
                // Return air if the chunk that do not exist
                return(BlockProvider.airBlock);
            }

            int xx = Helpers.Mod(pos.x, Env.CHUNK_SIZE);
            int yy = Helpers.Mod(pos.y, Env.CHUNK_SIZE);
            int zz = Helpers.Mod(pos.z, Env.CHUNK_SIZE);

            return(chunk.Blocks.Get(Helpers.GetChunkIndex1DFrom3D(xx, yy, zz)));
        }
Beispiel #5
0
        /// <summary>
        /// Sets blocks to a given value in a given range. It does not perform any logic. It simply sets the blocks.
        /// Use this function only when generating the terrain or structures.
        /// </summary>
        /// <param name="posFrom">Starting position in local chunk coordinates</param>
        /// <param name="posTo">Ending position in local chunk coordinates</param>
        /// <param name="blockData">A block to be placed on a given position</param>
        public void SetBlockDataRangedRaw(ref Vector3Int posFrom, ref Vector3Int posTo, BlockData blockData)
        {
            // Let's make sure that ranges are okay
            if (posFrom.x > posTo.x || posFrom.y > posTo.y || posFrom.z > posTo.z)
            {
                return;
            }

            // Transform positions into chunk coordinates
            Vector3Int chunkPosFrom = Helpers.ContainingChunkPos(ref posFrom);
            Vector3Int chunkPosTo   = Helpers.ContainingChunkPos(ref posTo);

            // Update all chunks in range
            int minY = Helpers.Mod(posFrom.y, Env.CHUNK_SIZE);

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

                for (int cz = chunkPosFrom.z; cz <= chunkPosTo.z; cz += Env.CHUNK_SIZE, minZ = 0)
                {
                    int maxZ = Math.Min(posTo.z - cz, Env.CHUNK_SIZE_1);
                    int minX = Helpers.Mod(posFrom.x, Env.CHUNK_SIZE);

                    for (int cx = chunkPosFrom.x; cx <= chunkPosTo.x; cx += Env.CHUNK_SIZE, minX = 0)
                    {
                        Vector3Int chunkPos = new Vector3Int(cx, cy, cz);
                        Chunk      chunk    = GetChunk(ref chunkPos);
                        if (chunk == null)
                        {
                            continue;
                        }

                        int maxX = Math.Min(posTo.x - cx, Env.CHUNK_SIZE_1);

                        Vector3Int from = new Vector3Int(minX, minY, minZ);
                        Vector3Int to   = new Vector3Int(maxX, maxY, maxZ);
                        chunk.Blocks.SetRangeRaw(ref from, ref to, blockData);
                    }
                }
            }
        }
Beispiel #6
0
        public override void GenerateStructures(Chunk chunk, int layerIndex)
        {
            //if (chunk.pos.x!=-30 || chunk.pos.y!=30 || chunk.pos.z!=0) return;

            int minX = chunk.Pos.x;
            int maxX = chunk.Pos.x + Env.CHUNK_SIZE_1;
            int minZ = chunk.Pos.z;
            int maxZ = chunk.Pos.z + Env.CHUNK_SIZE_1;

            int structureID = 0;

            for (int x = minX; x <= maxX; x++)
            {
                for (int z = minZ; z <= maxZ; z++)
                {
                    Vector3Int pos         = new Vector3Int(x, 0, z);
                    float      chanceAtPos = Randomization.RandomPrecise(pos.GetHashCode(), 44);

                    if (Chance > chanceAtPos)
                    {
                        if (Randomization.RandomPrecise(pos.Add(1, 0, 0).GetHashCode(), 44) > chanceAtPos &&
                            Randomization.RandomPrecise(pos.Add(-1, 0, 0).GetHashCode(), 44) > chanceAtPos &&
                            Randomization.RandomPrecise(pos.Add(0, 0, 1).GetHashCode(), 44) > chanceAtPos &&
                            Randomization.RandomPrecise(pos.Add(0, 0, -1).GetHashCode(), 44) > chanceAtPos)
                        {
                            int xx     = Helpers.Mod(x, Env.CHUNK_SIZE);
                            int zz     = Helpers.Mod(z, Env.CHUNK_SIZE);
                            int height = Helpers.FastFloor(terrainGen.GetTerrainHeightForChunk(chunk, xx, zz));

                            if (chunk.Pos.y <= height && chunk.Pos.y + Env.CHUNK_SIZE_1 >= height)
                            {
                                Vector3Int worldPos = new Vector3Int(x, height, z);
                                structure.Build(chunk, structureID++, ref worldPos, this);
                            }
                        }
                    }
                }
            }
        }
Beispiel #7
0
        /// <summary>
        /// Sets the block data at given world coordinates, updates the chunk and its
        /// neighbors if the Update chunk flag is true or not set.
        /// </summary>
        /// <param name="pos">Global position of the block</param>
        /// <param name="blockData">The block be placed</param>
        /// <param name="setBlockModified">Set to true to mark chunk data as modified</param>
        /// <param name="onModified">Action to perform once the operation finished</param>
        public void ModifyBlockData(ref Vector3Int pos, BlockData blockData, bool setBlockModified,
                                    Action <ModifyBlockContext> onModified = null)
        {
            // Transform the position into chunk coordinates
            Vector3Int chunkPos = Helpers.ContainingChunkPos(ref pos);

            Chunk chunk = GetChunk(ref chunkPos);

            if (chunk == null)
            {
                return;
            }

            int index = Helpers.GetChunkIndex1DFrom3D(
                Helpers.Mod(pos.x, Env.CHUNK_SIZE),
                Helpers.Mod(pos.y, Env.CHUNK_SIZE),
                Helpers.Mod(pos.z, Env.CHUNK_SIZE)
                );

            // Nothing for us to do if the block did not change
            BlockData oldBlockData = chunk.Blocks.Get(index);

            if (oldBlockData.Type == blockData.Type)
            {
                return;
            }

            ModifyBlockContext context = null;

            if (onModified != null)
            {
                context = new ModifyBlockContext(onModified, this, index, index, blockData, setBlockModified);
            }

            chunk.Modify(new ModifyOpBlock(blockData, index, setBlockModified, context));
        }
Beispiel #8
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);
                }
            }
        }
Beispiel #9
0
 public int GetThreadIDFromIndex(int index)
 {
     return(Helpers.Mod(index, pools.Length));
 }