using System; using UnityEngine; using System.Linq; using Newtonsoft.Json; using Unity.VisualScripting; using System.Collections.Generic; public class Node : MonoBehaviour { #region Variables or objects [SerializeField] private GameObject nodeOccupiedView; [SerializeField] private GameObject nodeUnoccupiedView; [SerializeField] private Material occupiedMat; [SerializeField] private Material unOccupiedMat; [SerializeField] private MeshRenderer meshRenderer; [SerializeField] private Transform[] m_NodePlacements; [SerializeField] private int totalSlotsInNode = 12; [SerializeField] private GameObject gameOverEmoji; private int m_NodePlacementLength = 0; public bool isNodeOccupied = false; private NodePlacementData[] m_NodePlacementDatas; private List neighborsHexOffsets = new List(); #region Dictionaries for item data collection private Dictionary goodsSetDict = new Dictionary(); private Dictionary> itemBasesCollection = new Dictionary>(); private Dictionary cachedGoodsSet = new Dictionary(); private Dictionary> cachedItemBases = new Dictionary>(); #endregion #region Managers private NodeManager nodeManager; private GoodsManager goodsManager; private GoodsSortingManager goodsSortingManager; private ObjectPoolManager objectPoolManager; #endregion #endregion #region Getter methods public Dictionary> GetItemBasesCollection => itemBasesCollection; public int GetItemTypeCount() => goodsSetDict.Count; public int GetTotalSlotsInNode() => totalSlotsInNode; public bool HasEmptySlots(out int availSlots) { int totalSlotsOccupied = 0; foreach (var set in goodsSetDict) { totalSlotsOccupied += set.Value; } availSlots = totalSlotsInNode - totalSlotsOccupied; return availSlots != 0; } public bool IsEmpty() { return !isNodeOccupied; } public bool HasCachedData() { return cachedGoodsSet.Count > 0; // TODO :: Improve the check if req while moving forward } public ItemType[] GetCachedKeys() { return cachedGoodsSet.Keys.ToArray(); } public int GetCachedData(ItemType matchType) // TODO :: change return type and data to send back here { return cachedGoodsSet.ContainsKey(matchType) ? cachedGoodsSet[matchType] : 0; } public int GetTotalCachedSetsCount() { int setsCount = 0; foreach (var data in cachedGoodsSet) setsCount += data.Value; return setsCount; } public Dictionary GetSetDict() => goodsSetDict; public List GetSetKeys() { return goodsSetDict.Keys.ToList(); } public int GetSetKeysCount() { return goodsSetDict.Keys.Count; } public bool HasCachedItemType(ItemType type) { return cachedItemBases.ContainsKey(type); } public List GetCachedItemBase(ItemType itemType) { return cachedItemBases[itemType]; } public bool GetNextKeyAfterCurrent(ItemType currentType, out ItemType itemType) { Debug.Log($"GetNextKeyAfterCurrent"); Debug.Log($"goodsSetDict: {goodsSetDict.Count}"); foreach (var goodSet in goodsSetDict) { if (goodSet.Key == currentType) { continue; } else { itemType = goodSet.Key; Debug.Log($"currentType: {currentType}, itemType: {itemType}"); return true; } } itemType = ItemType.MAX; Debug.Log($"currentType: {currentType}, itemType: {itemType}"); return false; } public int GetItemBaseCount() { int itemBaseCount = 0; foreach (var data in itemBasesCollection) itemBaseCount += data.Value.Count; return itemBaseCount; } public int GetTotalGoodsSetsCount() { int setsCount = 0; foreach (var data in goodsSetDict) setsCount += data.Value; return setsCount; } public List GetKeysForItems() { return itemBasesCollection.Keys.ToList(); } public int GetSetsCountForItemType(ItemType itemType) { return itemBasesCollection[itemType].Count; } public ItemBase GetItemBase(int index, ItemType itemType) { return itemBasesCollection[itemType][index]; } public List GetSpecificItems(ItemType itemType) { try { return itemBasesCollection[itemType]; // return itemBasesCollection.ContainsKey(itemType) ? itemBasesCollection[itemType] : new List(); // return itemBasesCollection.Select(item => item).Where(item => item.ItemType == itemType).ToList(); } catch (Exception ex) { Debug.LogError("Caught exception: " + ex.Message); } return new List(); } public string GetNodePos() => $"{transform.position}"; public int GetNeighborsCount() => neighborsHexOffsets.Count; public int GetNeighborHexOffsetLength() => neighborsHexOffsets.Count; public Vector3 GetNeighborHexOffset(int index) { return neighborsHexOffsets[index]; } public int GetGoodsSetCountForSpecificItem(ItemType itemType) { return goodsSetDict.ContainsKey(itemType) ? goodsSetDict[itemType] : 0; } public bool HasCachedDataRef(ItemType[] cachedItemKeys, out ItemType foundKey) { foundKey = ItemType.MAX; foreach (ItemType item in cachedItemKeys) { if (HasGoodsSet(item)) { foundKey = item; return true; } } return false; } public bool HasGoodsSet(ItemType itemType) { return goodsSetDict.ContainsKey(itemType); } public bool IsNodeFilled() { return !HasEmptySlots(out int availSlots) && goodsSetDict.Count == 1; } public bool IsThereDifferentKey(ItemType itemType) { if (goodsSetDict.Count > 0) { return itemType != goodsSetDict.Keys.Last(); return goodsSetDict.Keys.Contains(itemType); } else { // Debug.Log($"IsLastKey:: not last key"); return false; } } public NodePlacementData RetrieveNodePlacementData(int index) { return m_NodePlacementDatas[index]; } #endregion public void StoreCachedData(ItemType otherSetItemKey, int cacheCount) { // store the goods set // store the item bases if (!cachedGoodsSet.ContainsKey(otherSetItemKey)) cachedGoodsSet.Add(otherSetItemKey, cacheCount); else cachedGoodsSet[otherSetItemKey] += cacheCount; } public void FreeUpGoodsSet(ItemType otherSetItemKey, int cacheCount) { if (goodsSetDict.ContainsKey(otherSetItemKey)) { goodsSetDict[otherSetItemKey] -= cacheCount; } } public void CacheAndStoreItemBases(ItemType otherSetItemKey, int cacheCount) { if (!cachedItemBases.ContainsKey(otherSetItemKey)) { cachedItemBases.Add(otherSetItemKey, new List()); AddToCachedItemBases(otherSetItemKey, cacheCount); } else AddToCachedItemBases(otherSetItemKey, cacheCount); } private void AddToCachedItemBases(ItemType otherSetItemKey, int cacheCount) { for (int indexI = 0; indexI < cacheCount; indexI++) { cachedItemBases[otherSetItemKey].Add(RemoveFromItemBasesCollection(otherSetItemKey)); } } public void InitNodeManager(NodeManager nodeManager) { this.nodeManager = nodeManager; } public bool CheckIfSetItemMatches(ItemType itemType, out int goodsCount) { Debug.Log($"JsonData: {JsonConvert.SerializeObject(goodsSetDict)}"); goodsCount = goodsSetDict.ContainsKey(itemType) ? goodsSetDict[itemType] : 0; // Debug.Log($"Test 5: DoesNeighborHaveSimilarItem: itemType: " + itemType + ", goodsCount: " + goodsCount); return goodsSetDict.ContainsKey(itemType); } public void InitItemsData() { goodsManager = goodsManager == null ? InterfaceManager.Instance?.GetInterfaceInstance() : goodsManager; var itemBaseObjects = goodsManager.GoodsHandler.CurrentGoodsPlacer.GetBaseObjects(); foreach (var baseObj in itemBaseObjects) AddToItemBasesCollection(baseObj); // foreach (var item in itemBaseObjects) // { // Debug.Log($"### Test 9: item.Type: {item.ItemType}, item.Value: {item}"); // } // foreach (var item in itemBasesCollection) // { // Debug.Log($"### Test 10: item.Type: {item.Key}, item.Value: {item.Value.Count}"); // } var goodsDataSet = goodsManager.GoodsHandler.CurrentGoodsPlacer.GetGoodsDataSet(); foreach (var data in goodsDataSet) AddItemsDataToNode(data.type, data.setCount); } #region NODE_DATA_UPDATION public void AddItemsDataToNode(ItemType itemType, int itemsToAddCount) { // Debug.Log($"AddItemsDataToNode"); // foreach (var data in goodsSetDict) // { // Debug.Log($"GoodsKey: {data.Key}, GoodsCount: {data.Value}"); // } // Debug.Log($"Before updating goods set"); // Debug.Log($"number of goods sets: {goodsSetDict.Count}"); // int itemsCount = goodsSetDict.ContainsKey(itemType) ? goodsSetDict[itemType] : 0; // Debug.Log($"number of goods for set({itemType}): {itemsCount}"); if (!goodsSetDict.ContainsKey(itemType)) goodsSetDict.Add(itemType, itemsToAddCount); else goodsSetDict[itemType] += itemsToAddCount; // Debug.Log($"After updating goods set"); // Debug.Log($"number of goods sets: {goodsSetDict.Count}"); // itemsCount = goodsSetDict.ContainsKey(itemType) ? goodsSetDict[itemType] : 0; // Debug.Log($"number of goods for set({itemType}): {itemsCount}"); } public void RemoveItemsDataFromNode(ItemType itemType, int itemsToRemoveCount) { if (goodsSetDict.ContainsKey(itemType)) { int availCount = goodsSetDict[itemType]; if (availCount > itemsToRemoveCount) { availCount -= itemsToRemoveCount; goodsSetDict[itemType] = availCount; if (goodsSetDict[itemType] == 0) goodsSetDict.Remove(itemType); } else //if (availCount == itemsToRemoveCount) { // TODO :: double check condition goodsSetDict.Remove(itemType); } } } public void SortItemBases() { var sortedDict = itemBasesCollection.OrderByDescending(pair => pair.Value.Count).ToList(); itemBasesCollection.Clear(); goodsSetDict.Clear(); foreach (var sortedItem in sortedDict) { itemBasesCollection.Add(sortedItem.Key, sortedItem.Value); goodsSetDict.Add(sortedItem.Key, sortedItem.Value.Count); } } public void SortItemsData() { var sortedDict = goodsSetDict.OrderByDescending(pair => pair.Value); goodsSetDict.Clear(); foreach (var data in sortedDict) goodsSetDict.Add(data.Key, data.Value); } #endregion #region ITEMS_UPDATION public void AddToItemBasesCollection(ItemBase baseObj) { if (!itemBasesCollection.ContainsKey(baseObj.ItemType)) itemBasesCollection.Add(baseObj.ItemType, new List() { baseObj }); else itemBasesCollection[baseObj.ItemType].Add(baseObj); } public ItemBase RemoveFromItemBasesCollection(ItemType itemType) { // if (!itemBasesCollection.ContainsKey(itemType) || itemBasesCollection[itemType].Count < 1) return null; Debug.Log($"#### itemBasesCollection: {itemBasesCollection != null}"); Debug.Log($"ItemToRemove: {itemBasesCollection.Count}"); ItemBase itemToRemove = itemBasesCollection[itemType][0]; itemBasesCollection[itemType].RemoveAt(0); Debug.Log($"ItemType based count: {itemBasesCollection[itemType].Count}"); if (itemBasesCollection[itemType].Count == 0) { Debug.Log($"Removing item"); itemBasesCollection.Remove(itemType); Debug.Log($"after removal itemBasesCollection: {itemBasesCollection.Count}"); } return itemToRemove; } public void RemoveItemsDataFromCachedData(ItemType cachedKey, int availSlots) { if (cachedGoodsSet.ContainsKey(cachedKey)) { cachedGoodsSet[cachedKey] -= availSlots; if (cachedGoodsSet[cachedKey] == 0) cachedGoodsSet.Remove(cachedKey); } } public ItemBase RemoveAndRetrieveFromCachedItemBases(ItemType itemType) { ItemBase itemToRemove = cachedItemBases[itemType][0]; cachedItemBases[itemType].RemoveAt(0); if (cachedItemBases[itemType].Count == 0) { Debug.Log($"Removing item"); cachedItemBases.Remove(itemType); Debug.Log($"after removal itemBasesCollection: {cachedItemBases.Count}"); } return itemToRemove; } #endregion public void AddNeighborsData(Vector3 hexOffset) { neighborsHexOffsets.Add(hexOffset); } public void OnMouseDown() { if (!isNodeOccupied) // game's not over { nodeManager.OnNodeClickedOrFound(this); } else { nodeManager.OnNodeBeingOccupied(this); } } public void SetNodeOccupiedState(bool state) { Debug.Log($"totalOccupiedNodesState({name}): isNodeOccupied: {isNodeOccupied}, state: {state}"); if (isNodeOccupied == state) return; isNodeOccupied = state; meshRenderer.material = isNodeOccupied ? occupiedMat : unOccupiedMat; // nodeManager.UpdateOccupiedNodesCount(state ? 1 : -1); nodeOccupiedView.SetActive(isNodeOccupied); nodeUnoccupiedView.SetActive(!isNodeOccupied); } private void Awake() { m_NodePlacementLength = m_NodePlacements.Length; m_NodePlacementDatas = new NodePlacementData[m_NodePlacementLength]; for (int i = 0; i < m_NodePlacementLength; i++) { m_NodePlacementDatas[i] = new NodePlacementData(); m_NodePlacementDatas[i].isOccupied = false; m_NodePlacementDatas[i].transform = m_NodePlacements[i]; } } public bool IsNodeFullOrCleared() { var itemBaseCount = GetItemBaseCount(); return (itemBasesCollection.Count == 1 && totalSlotsInNode == itemBaseCount) || itemBaseCount == 0; } public void CheckIfNodeIsFullOrCleared() { var itemBaseCount = GetItemBaseCount(); Debug.Log($"GameOverCheck :: CheckIfNodeIsFullOrCleared() :: Nodename: {this.name}, itemBaseCount: {itemBaseCount}"); if (itemBasesCollection.Count == 1 && totalSlotsInNode == itemBaseCount) { OnNodeFull(); goodsSetDict.Clear(); itemBasesCollection.Clear(); SetNodeOccupiedState(false); } else if (itemBaseCount == 0) { // goodsSetDict.Clear(); // itemBasesCollection.Clear(); SetNodeOccupiedState(false); } } private void OnNodeFull() { nodeManager.OnNodeFilled(this, goodsSetDict.First().Key); } public void UpdateOccupiedSlotsState() { var itemsCount = GetItemBaseCount(); for (int index = 0; index < totalSlotsInNode; index++) { m_NodePlacementDatas[index].isOccupied = index < itemsCount; } } public void UpdateOccupiedNodes() { var itemsCount = GetItemBaseCount(); Debug.Log($"NodeData :: {name} :: itemsCount: {itemsCount}"); if (itemsCount == 0 || itemsCount == totalSlotsInNode) { Debug.Log($"NodeData :: remove from occupied nodes list for {name}"); nodeManager.UpdateOccupiedNodes(toAdd: false, GetNodePos()); } else { Debug.Log($"NodeData :: Updating occupied nodes list for {name}"); nodeManager.UpdateOccupiedNodes(toAdd: true, GetNodePos()); } } public void ClearOrResetGoodsDataAndView() { objectPoolManager = objectPoolManager == null ? InterfaceManager.Instance?.GetInterfaceInstance() : objectPoolManager; goodsSetDict.Clear(); cachedGoodsSet.Clear(); foreach (var pair in itemBasesCollection) { foreach (var itemBase in itemBasesCollection[pair.Key]) { objectPoolManager.PassObjectToPool($"{pair.Key}", PoolType.Item, itemBase); itemBase.gameObject.SetActive(false); } } itemBasesCollection.Clear(); cachedItemBases.Clear(); SetNodeOccupiedState(state: false); UpdateOccupiedSlotsState(); UpdateOccupiedNodes(); } public void SetGameOverEmoji(bool state) { gameOverEmoji.SetActive(state); } }