<commit_before>﻿using System.Collections.Generic;
using Assets.Engine.Scripts.Common;
using Assets.Engine.Scripts.Common.DataTypes;
using Assets.Engine.Scripts.Core.Blocks;
using Assets.Engine.Scripts.Core.Chunks;
using Assets.Engine.Scripts.Physics;
using Assets.Engine.Scripts.Provider;
using UnityEngine;
using UnityEngine.Assertions;
using System.Linq;
using Assets.Engine.Scripts.Core.Threading;

namespace Assets.Engine.Scripts.Core
{
    public class Map: MonoBehaviour
    {
        #region Static Fields

        /// <summary>
        ///     The local instance of the Map.
        /// </summary>
        public static Map Current;

        #endregion Static Fields

        #region Private vars

        // Circular array containing the currently visible world
        //private BlockStorage m_blocks;
        private ChunkStorage m_chunks;
        private List<Chunk> m_removeList;

        private Rect m_viewRange;
        private Rect m_cachedRange;

        private Camera m_camera;
        private Plane[] m_cameraPlanes;

        private Vector2Int[] m_chunksToLoadByPos;

        #endregion Private vars

        #region Constructor

        public void Awake()
        {
            //m_blocks = new BlockStorage();
            m_chunks = new ChunkStorage();
            m_removeList = new List<Chunk>();
        }

        public void Start()
        {
            GameObject cameraGo = GameObject.FindGameObjectWithTag("MainCamera");
            m_camera = cameraGo.GetComponent<Camera>();
            
            UpdateRangeRects();
            InitCache();
            UpdateCache();
        }

        #endregion Constructor

        #region Public Fields

        public IChunkProvider ChunkProvider;

        // Position of viewer in chunk coordinates
        public Vector2Int ViewerChunkPos;

        #endregion Public Fields

        #region Public Methods

        /// <summary>
        ///     Gets the chunk at the given chunk coordinates.
        /// </summary>
        public Chunk GetChunk(int cx, int cz)
        {
            Chunk chunk = m_chunks.Check(cx, cz) ? m_chunks[cx, cz] : null;
            return chunk;
        }

        /// <summary>
        ///     Get the block at the world position
        /// </summary>
        public BlockData GetBlock(int wx, int wy, int wz)
        {
            if (wy<0 || wy>=EngineSettings.ChunkConfig.SizeYTotal)
                return BlockData.Air;

            int cx = wx>>EngineSettings.ChunkConfig.LogSizeX;
            int cz = wz>>EngineSettings.ChunkConfig.LogSizeZ;

            Chunk chunk = m_chunks[cx, cz];
            if (chunk==null)
                return BlockData.Air;

            int lx = wx&EngineSettings.ChunkConfig.MaskX;
            int lz = wz&EngineSettings.ChunkConfig.MaskZ;

            return chunk[lx, wy, lz];
        }

        /// <summary>
        ///     Damage the block at the world position
        /// </summary>
        public void DamageBlock(int wx, int wy, int wz, int damage)
        {
            if (wy<0 || wy>=EngineSettings.ChunkConfig.SizeYTotal)
                return;

            int cx = wx>>EngineSettings.ChunkConfig.LogSizeX;
            int cz = wz>>EngineSettings.ChunkConfig.LogSizeZ;

            Chunk chunk = GetChunk(cx, cz);
            if (chunk==null)
                return;

            int lx = wx&EngineSettings.ChunkConfig.MaskX;
            int lz = wz&EngineSettings.ChunkConfig.MaskZ;

            chunk.DamageBlock(lx, wy, lz, damage);
        }

        /// <summary>
        ///     Set the block at the world position
        /// </summary>
        public void SetBlock(BlockData block, int wx, int wy, int wz)
        {
            if (wy<0 || wy>=EngineSettings.ChunkConfig.SizeYTotal)
                return;

            int cx = wx>>EngineSettings.ChunkConfig.LogSizeX;
            int cz = wz>>EngineSettings.ChunkConfig.LogSizeZ;

            Chunk chunk = GetChunk(cx, cz);
            if (chunk==null)
                return;

            int lx = wx&EngineSettings.ChunkConfig.MaskX;
            int lz = wz&EngineSettings.ChunkConfig.MaskZ;

			chunk.ModifyBlock(lx, wy, lz, block);
        }

        // We'll only allow a certain amount of chunks to be created per update
        // Currently, this number is derived from the visible world size divided by the number of updates per second
        // !TODO: Let this value large for now. Change it back / adjust it later
        private static readonly int MaxChunksPerUpdate = 10000;//(EngineSettings.WorldConfig.VisibleRange * EngineSettings.WorldConfig.VisibleRange / 20);

        private bool IsWithinVisibilityRange(Chunk chunk)
        {
            // Chunk is close enough
            Vector2Int min = new Vector2Int(ViewerChunkPos.X - EngineSettings.WorldConfig.VisibleRange,
                                            ViewerChunkPos.Z - EngineSettings.WorldConfig.VisibleRange);
            Vector2Int max = new Vector2Int(ViewerChunkPos.X + EngineSettings.WorldConfig.VisibleRange,
                                            ViewerChunkPos.Z + EngineSettings.WorldConfig.VisibleRange);

            if (chunk.Pos.X>=min.X && chunk.Pos.Z>=min.Z && chunk.Pos.X<=max.X && chunk.Pos.Z<=max.Z)
            {
                // Check if the chunk lies within camera planes
				return true;//chunk.CheckFrustum(m_cameraPlanes);
            }

            return false;
        }

        private bool IsWithinCachedRange(Chunk chunk)
        {
            // Chunk is close enough
            Vector2Int min = new Vector2Int(ViewerChunkPos.X - EngineSettings.WorldConfig.CachedRange,
                                            ViewerChunkPos.Z - EngineSettings.WorldConfig.CachedRange);
            Vector2Int max = new Vector2Int(ViewerChunkPos.X + EngineSettings.WorldConfig.CachedRange,<commit_msg>[Update] Generate vertices only for chunks in view frustum<commit_after>﻿using System.Collections.Generic;
using Assets.Engine.Scripts.Common;
using Assets.Engine.Scripts.Common.DataTypes;
using Assets.Engine.Scripts.Core.Blocks;
using Assets.Engine.Scripts.Core.Chunks;
using Assets.Engine.Scripts.Physics;
using Assets.Engine.Scripts.Provider;
using UnityEngine;
using UnityEngine.Assertions;
using System.Linq;
using Assets.Engine.Scripts.Core.Threading;

namespace Assets.Engine.Scripts.Core
{
    public class Map: MonoBehaviour
    {
        #region Static Fields

        /// <summary>
        ///     The local instance of the Map.
        /// </summary>
        public static Map Current;

        #endregion Static Fields

        #region Private vars

        // Circular array containing the currently visible world
        //private BlockStorage m_blocks;
        private ChunkStorage m_chunks;
        private List<Chunk> m_removeList;

        private Rect m_viewRange;
        private Rect m_cachedRange;

        private Camera m_camera;
        private Plane[] m_cameraPlanes;

        private Vector2Int[] m_chunksToLoadByPos;

        #endregion Private vars

        #region Constructor

        public void Awake()
        {
            //m_blocks = new BlockStorage();
            m_chunks = new ChunkStorage();
            m_removeList = new List<Chunk>();
        }

        public void Start()
        {
            GameObject cameraGo = GameObject.FindGameObjectWithTag("MainCamera");
            m_camera = cameraGo.GetComponent<Camera>();
            
            UpdateRangeRects();
            InitCache();
            UpdateCache();
        }

        #endregion Constructor

        #region Public Fields

        public IChunkProvider ChunkProvider;

        // Position of viewer in chunk coordinates
        public Vector2Int ViewerChunkPos;

        #endregion Public Fields

        #region Public Methods

        /// <summary>
        ///     Gets the chunk at the given chunk coordinates.
        /// </summary>
        public Chunk GetChunk(int cx, int cz)
        {
            Chunk chunk = m_chunks.Check(cx, cz) ? m_chunks[cx, cz] : null;
            return chunk;
        }

        /// <summary>
        ///     Get the block at the world position
        /// </summary>
        public BlockData GetBlock(int wx, int wy, int wz)
        {
            if (wy<0 || wy>=EngineSettings.ChunkConfig.SizeYTotal)
                return BlockData.Air;

            int cx = wx>>EngineSettings.ChunkConfig.LogSizeX;
            int cz = wz>>EngineSettings.ChunkConfig.LogSizeZ;

            Chunk chunk = m_chunks[cx, cz];
            if (chunk==null)
                return BlockData.Air;

            int lx = wx&EngineSettings.ChunkConfig.MaskX;
            int lz = wz&EngineSettings.ChunkConfig.MaskZ;

            return chunk[lx, wy, lz];
        }

        /// <summary>
        ///     Damage the block at the world position
        /// </summary>
        public void DamageBlock(int wx, int wy, int wz, int damage)
        {
            if (wy<0 || wy>=EngineSettings.ChunkConfig.SizeYTotal)
                return;

            int cx = wx>>EngineSettings.ChunkConfig.LogSizeX;
            int cz = wz>>EngineSettings.ChunkConfig.LogSizeZ;

            Chunk chunk = GetChunk(cx, cz);
            if (chunk==null)
                return;

            int lx = wx&EngineSettings.ChunkConfig.MaskX;
            int lz = wz&EngineSettings.ChunkConfig.MaskZ;

            chunk.DamageBlock(lx, wy, lz, damage);
        }

        /// <summary>
        ///     Set the block at the world position
        /// </summary>
        public void SetBlock(BlockData block, int wx, int wy, int wz)
        {
            if (wy<0 || wy>=EngineSettings.ChunkConfig.SizeYTotal)
                return;

            int cx = wx>>EngineSettings.ChunkConfig.LogSizeX;
            int cz = wz>>EngineSettings.ChunkConfig.LogSizeZ;

            Chunk chunk = GetChunk(cx, cz);
            if (chunk==null)
                return;

            int lx = wx&EngineSettings.ChunkConfig.MaskX;
            int lz = wz&EngineSettings.ChunkConfig.MaskZ;

			chunk.ModifyBlock(lx, wy, lz, block);
        }

        // We'll only allow a certain amount of chunks to be created per update
        // Currently, this number is derived from the visible world size divided by the number of updates per second
        // !TODO: Let this value large for now. Change it back / adjust it later
        private static readonly int MaxChunksPerUpdate = 10000;//(EngineSettings.WorldConfig.VisibleRange * EngineSettings.WorldConfig.VisibleRange / 20);

        private bool IsWithinVisibilityRange(Chunk chunk)
        {
            // Chunk is close enough
            Vector2Int min = new Vector2Int(ViewerChunkPos.X - EngineSettings.WorldConfig.VisibleRange,
                                            ViewerChunkPos.Z - EngineSettings.WorldConfig.VisibleRange);
            Vector2Int max = new Vector2Int(ViewerChunkPos.X + EngineSettings.WorldConfig.VisibleRange,
                                            ViewerChunkPos.Z + EngineSettings.WorldConfig.VisibleRange);

            if (chunk.Pos.X>=min.X && chunk.Pos.Z>=min.Z && chunk.Pos.X<=max.X && chunk.Pos.Z<=max.Z)
            {
                // Check if the chunk lies within camera planes
				return chunk.CheckFrustum(m_cameraPlanes);
            }

            return false;
        }

        private bool IsWithinCachedRange(Chunk chunk)
        {
            // Chunk is close enough
            Vector2Int min = new Vector2Int(ViewerChunkPos.X - EngineSettings.WorldConfig.CachedRange,
                                            ViewerChunkPos.Z - EngineSettings.WorldConfig.CachedRange);
            Vector2Int max = new Vector2Int(ViewerChunkPos.X + EngineSettings.WorldConfig.CachedRange,
{'fraction_non_alphanumeric': 0.08647771896875533, 'fraction_numerical': 0.003414717432132491, 'mean_word_length': 1.8678090575275397, 'pattern_counts': {'":': 0, '<': 39, '<?xml version=': 0, '>': 63, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 12, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '4019231', 'n_tokens_mistral': 3186, 'n_tokens_neox': 3048, 'n_words': 817}