using System; using System.Collections; using System.Collections.Generic; using System.Linq; using UnityEngine; [CreateAssetMenu(fileName = "BlocksMap", menuName = "BlocksMap", order = 0)] public class BlocksMap : ScriptableObject { [System.NonSerialized] public Dictionary> blocks = new Dictionary>(); public List allNodes = new List(); public BlockNode rootNode; public long calcTotalNodes() { long totalNodes = 0; foreach (Dictionary map in blocks.Values) totalNodes += map.Count; return totalNodes; } /// /// Ensures that the main dictionary and all nested dictionaries are initialized to prevent null reference issues. /// public void init(BlocksMap blocksMap = null) { if (blocks == null) blocks = new Dictionary>(); if (allNodes == null) allNodes = new List(); // load all block types into the main dictionary with null maps to ensure they exist List blockDataList = Resources.LoadAll("BlocksData").ToList(); foreach (BlockData blockData in blockDataList) { if (!blocks.ContainsKey(blockData.blockName)) blocks[blockData.blockName] = new Dictionary(); } // add root node if it exists in the blocksMap if (blocksMap != null && blocksMap.rootNode != null) { Vector3 roundedPos = RoundPosition(blocksMap.rootNode.position); Quaternion roundedRot = RoundRotation(blocksMap.rootNode.rotation); rootNode = new BlockNode(blocksMap.rootNode.blockData, roundedPos, roundedRot); blocks[rootNode.blockData.blockName][rootNode.position] = rootNode; // instantiate the root node's block type without adding it to execute stack CreateBlockCommand command = new CreateBlockCommand(rootNode.blockData.blockName, rootNode.position, rootNode.rotation, true); command.execute(); } } private void OnEnable() { RebuildDictionary(); } /// /// rebuild the already filled BlocksMap /// private void RebuildDictionary() { blocks = new Dictionary>(); List blockDataList = Resources.LoadAll("BlocksData").ToList(); foreach (BlockData blockData in blockDataList) blocks[blockData.blockName] = new Dictionary(); // rebuild from serialized allNodes foreach (BlockNode node in allNodes) { if (node?.blockData == null) continue; if (!blocks.ContainsKey(node.blockData.blockName)) blocks[node.blockData.blockName] = new Dictionary(); blocks[node.blockData.blockName][node.position] = node; } } public void setRootNode(BlockNode node) { rootNode = node; } public static Vector3 RoundPosition(Vector3 position, float precision = 100f) { return new Vector3( Mathf.Round(position.x * precision) / precision, Mathf.Round(position.y * precision) / precision, Mathf.Round(position.z * precision) / precision); } public static Quaternion RoundRotation(Quaternion rotation, float precision = 10f) { Vector3 euler = rotation.eulerAngles; return Quaternion.Euler( Mathf.Round(euler.x * precision) / precision, Mathf.Round(euler.y * precision) / precision, Mathf.Round(euler.z * precision) / precision); } }