585 lines
18 KiB
C#
Raw Normal View History

2026-01-05 12:16:58 +05:30
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<Vector3> neighborsHexOffsets = new List<Vector3>();
#region Dictionaries for item data collection
private Dictionary<ItemType, int> goodsSetDict = new Dictionary<ItemType, int>();
private Dictionary<ItemType, List<ItemBase>> itemBasesCollection = new Dictionary<ItemType, List<ItemBase>>();
private Dictionary<ItemType, int> cachedGoodsSet = new Dictionary<ItemType, int>();
private Dictionary<ItemType, List<ItemBase>> cachedItemBases = new Dictionary<ItemType, List<ItemBase>>();
#endregion
#region Managers
private NodeManager nodeManager;
private GoodsManager goodsManager;
private GoodsSortingManager goodsSortingManager;
private ObjectPoolManager objectPoolManager;
#endregion
#endregion
#region Getter methods
public Dictionary<ItemType, List<ItemBase>> 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<ItemType, int> GetSetDict() => goodsSetDict;
public List<ItemType> GetSetKeys()
{
return goodsSetDict.Keys.ToList();
}
public int GetSetKeysCount()
{
return goodsSetDict.Keys.Count;
}
public bool HasCachedItemType(ItemType type)
{
return cachedItemBases.ContainsKey(type);
}
public List<ItemBase> 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<ItemType> 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<ItemBase> GetSpecificItems(ItemType itemType)
{
try
{
return itemBasesCollection[itemType];
// return itemBasesCollection.ContainsKey(itemType) ? itemBasesCollection[itemType] : new List<ItemBase>();
// return itemBasesCollection.Select(item => item).Where(item => item.ItemType == itemType).ToList();
}
catch (Exception ex)
{
Debug.LogError("Caught exception: " + ex.Message);
}
return new List<ItemBase>();
}
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<ItemBase>());
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>() : 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<ItemBase>() { 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>() : objectPoolManager;
goodsSetDict.Clear();
cachedGoodsSet.Clear();
foreach (var pair in itemBasesCollection)
{
foreach (var itemBase in itemBasesCollection[pair.Key])
{
objectPoolManager.PassObjectToPool<ItemBase>($"{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);
}
}