Esempio n. 1
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 Modify(ref Vector3Int pos, BlockData blockData, bool setBlockModified,
                           Action <ModifyBlockContext> onModified = null)
        {
            Vector3Int chunkPos = Chunk.ContainingChunkPos(ref pos);
            Chunk      chunk    = world.chunks.Get(ref chunkPos);

            if (chunk == null)
            {
                return;
            }

            Vector3Int blockPos = new Vector3Int(
                Helpers.Mod(pos.x, Env.ChunkSize),
                Helpers.Mod(pos.y, Env.ChunkSize),
                Helpers.Mod(pos.z, Env.ChunkSize)
                );
            int index = Helpers.GetChunkIndex1DFrom3D(blockPos.x, blockPos.y, blockPos.z);

            // 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, world, index, index, blockData, setBlockModified);
            }

            chunk.blocks.Modify(new ModifyOpBlock(blockData, index, setBlockModified, context));
        }
Esempio n. 2
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 ModifyRange(ref Vector3Int posFrom, ref Vector3Int posTo, BlockData blockData, bool setBlockModified,
                                Action <ModifyBlockContext> onModified = null)
        {
            // Let's make sure that ranges are okay
            if (posFrom.x > posTo.x || posFrom.y > posTo.y || posFrom.z > posTo.z)
            {
                return;
            }

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

            ModifyBlockContext context = null;

            if (onModified != null)
            {
                context = new ModifyBlockContext(onModified, world,
                                                 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.ChunkSize);

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

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

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

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

                        chunk.blocks.Modify(
                            new ModifyOpCuboid(
                                blockData,
                                new Vector3Int(minX, minY, minZ),
                                new Vector3Int(maxX, maxY, maxZ),
                                setBlockModified,
                                context)
                            );
                    }
                }
            }
        }
Esempio n. 3
0
        public bool Set(ref Vector3Int pos, Chunk chunk)
        {
            Assert.IsTrue(Helpers.IsMainThread);
            Vector3Int p = Chunk.ContainingChunkPos(ref pos);

            // Let's keep it within allowed world bounds
            if (!world.IsCoordInsideWorld(ref p))
            {
                return(false);
            }

            chunks[p] = chunk;
            return(true);
        }
Esempio n. 4
0
        /// <summary> Returns the chunk at the given position </summary>
        /// <param name="pos">Position of the chunk in the world coordinates</param>
        /// <returns>The chunk that contains the given block position or null if there is none</returns>
        public Chunk Get(ref Vector3Int pos)
        {
            Vector3Int p = Chunk.ContainingChunkPos(ref pos);

            // If we previously searched for this chunk there is no need to look it up again

            /*if (p == lastChunkPos && lastChunk != null)
             *  return lastChunk;
             *
             * lastChunkPos = p;*/

            Chunk containerChunk;

            chunks.TryGetValue(p, out containerChunk);

            return(containerChunk);
        }
Esempio n. 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 SetRangeRaw(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;
            }

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

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

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

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

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

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

                        Vector3Int from = new Vector3Int(minX, minY, minZ);
                        Vector3Int to   = new Vector3Int(maxX, maxY, maxZ);
                        chunk.blocks.SetRangeRaw(ref from, ref to, blockData);
                    }
                }
            }
        }
Esempio n. 6
0
        /// <summary>Instantiates a new chunk at a given position. If the chunk already exists, it returns it</summary>
        /// <param name="pos">Position to create this chunk on in the world coordinates.</param>
        /// <param name="chunk">Chunk at a given world position</param>
        /// <returns>True if a new chunk was created. False otherwise</returns>
        public bool CreateOrGetChunk(ref Vector3Int pos, out Chunk chunk)
        {
            Assert.IsTrue(Helpers.IsMainThread);
            Vector3Int p = Chunk.ContainingChunkPos(ref pos);

            // Let's keep it within allowed world bounds
            if (!world.IsCoordInsideWorld(ref p))
            {
                chunk = null;
                return(false);
            }

            /*// If we previously searched for this chunk there is no need to look it up again
             * if (pos==lastChunkPos && lastChunk!=null)
             * {
             *  chunk = lastChunk;
             *  return false;
             * }
             *
             * lastChunkPos = pos;*/

            // Don't recreate the chunk if it already exists
            chunk = Get(ref p);
            if (chunk != null)
            {
                return(false);
            }

            // Create a new chunk
            chunk = Chunk.CreateChunk(world, p);

            lock (chunks)
            {
                chunks.Add(p, chunk);
            }

            return(true);
        }