Advertisement
MaoChessy

endless generate room

Oct 6th, 2022
786
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C# 9.15 KB | Gaming | 0 0
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Linq;
  4. using MaoUtility.DILocator.Atr;
  5. using MaoUtility.MaoExts;
  6. using RoomsSystem.RoomAndPart;
  7. using Sirenix.OdinInspector;
  8. using Sirenix.Utilities;
  9. using UnityEngine;
  10. using Random = UnityEngine.Random;
  11.  
  12. namespace RoomsSystem
  13. {
  14.     [DiMark]
  15.     public class EndlessGenerateRoom : MonoBehaviour
  16.     {
  17.         [DiInject] private RoomFactory roomFactory;
  18.        
  19.         [SerializeField, Min(1)] private int _maxCountRoomByCenter;
  20.         [SerializeField] private Room[] _prefabs;
  21.         [SerializeField] private bool _logInfo;
  22.  
  23.         public Room Center => _center;
  24.         [SerializeField]private Room _center;
  25.        
  26.         private HashSet<Room> _rooms;
  27.         private RoomEntity _trackEntity;
  28.         private int _seed;
  29.         [ShowInInspector, ReadOnly]private Dictionary<int, DataRoom> _dataRoomsBySeed;
  30.  
  31.         private void Start()
  32.         {
  33.             _rooms=new HashSet<Room>();
  34.             _dataRoomsBySeed = new Dictionary<int, DataRoom>();
  35.         }
  36.  
  37.         public void Init(RoomEntity entity, int? seed = null)
  38.         {
  39.             if (!entity.IsPlayer)
  40.             {
  41.                 Debug.LogError("Попытка иницилизировать генератор не игроком");
  42.                 return;
  43.             }
  44.             ClearAll();
  45.            
  46.             _trackEntity = entity;
  47.             _seed = seed != null ? seed.Value : Random.Range(int.MinValue, int.MaxValue);
  48.            
  49.             _trackEntity.EnterRoom += OnEnterRoom;
  50.             UpdateRoomByCurrent();
  51.             var point = Center.GetPart<PointForPlayer>();
  52.             if (!point) Debug.LogWarning($"У этой комнаты (клик по мне), не точки для игрока", Center);
  53.             else point.SetPlayerPos(entity);
  54.         }
  55.  
  56.         [Button]
  57.         public void UpdateRoomByCurrent()
  58.         {
  59.             if(_center==null) SpawnFirst(_prefabs.GetRandom());
  60.            
  61.             HashSet<Room> chekedRooms = new HashSet<Room>();
  62.             HashSet<Room> roomOnCheck = new HashSet<Room>() {Center};
  63.             int radius = 0;
  64.  
  65.             while (roomOnCheck.Count>0 && radius<_maxCountRoomByCenter)
  66.             {
  67.                 HashSet<Room> newRoomSet = new HashSet<Room>();
  68.                 if(radius<_maxCountRoomByCenter)
  69.                     roomOnCheck.ForEach(room =>
  70.                     {
  71.                         chekedRooms.Add(room);
  72.                         room.ConnectRooms.ForEach(connect =>
  73.                         {
  74.                             if (connect.Link) return;
  75.                             if (_dataRoomsBySeed.ContainsKey(SeedRoom(room)))
  76.                             {
  77.                                 var data = _dataRoomsBySeed[SeedRoom(room)];
  78.                                 var connectData = data.Points.FirstOrDefault(x => x.SelfGuid == connect.GUID);
  79.                                 if (connectData != null && connectData.IsValid()) SpawnByConnectData(connect, connectData);
  80.                                 else RndSpawn();
  81.                             }
  82.                             else
  83.                             {
  84.                                 RndSpawn();
  85.                             }
  86.                            
  87.                             void RndSpawn()
  88.                             {
  89.                                 var rnd = GetRandByPoint(connect);
  90.                                 var prefab = _prefabs[rnd.Next(0, _prefabs.Length)];
  91.                                 SpawnWithConnect(connect, prefab, ()=>rnd.Next(0, prefab.ConnectRooms.Count));    
  92.                             }
  93.                         });
  94.                         room.ConnectRooms.ForEach(connect =>
  95.                         {
  96.                             if(connect.Link)
  97.                                 if (!chekedRooms.Contains(connect.Link.Room)) newRoomSet.Add(connect.Link.Room);
  98.                         });
  99.                     });
  100.                 roomOnCheck = newRoomSet;
  101.                 radius++;
  102.             }
  103.             roomOnCheck.ForEach(x => chekedRooms.Add(x));
  104.            
  105.             var collectToDelete = _rooms.Except(chekedRooms);
  106.             _rooms = _rooms.Except(collectToDelete).ToHashSet();
  107.             collectToDelete.ForEach(x => roomFactory.DeleteRoom(x));
  108.         }
  109.  
  110.         private void SpawnByConnectData(ConnectPointRoom connect, PointConnectData connectData)
  111.         {
  112.             var roomdata = _dataRoomsBySeed[connectData.SeedConnectRoom.Value];
  113.             var prefab = _prefabs.First(x => x.GUID == roomdata.Guid);
  114.             var pointConnect = prefab.ConnectRooms.First(x => x.GUID == connectData.GuidPointConnect);
  115.             SpawnWithConnect(connect, prefab, ()=>prefab.ConnectRooms.ToList().IndexOf(pointConnect));
  116.         }
  117.  
  118.         private System.Random GetRandByPoint(ConnectPointRoom connect)
  119.         {
  120.             var seed = SeedPoint(connect);
  121.             return new System.Random(seed);
  122.         }
  123.  
  124.         [Button]
  125.         private void SpawnWithConnect(ConnectPointRoom connectPointRoom, Room prefab, Func<int> getIndex)
  126.         {
  127.             //замена рандома
  128.             int index = getIndex();
  129.             var poinNewRoom = prefab.ConnectRooms.ToArray()[index];
  130.             var transPos = connectPointRoom.GetTransformValue(poinNewRoom);
  131.            
  132.             if (roomFactory.CheckExistCreate(prefab, transPos.pos, transPos.rotate))
  133.             {
  134.                 var r = roomFactory.CreateRoom(prefab, transPos.pos, transPos.rotate);
  135.                 r.transform.SetParent(transform);
  136.                 var newPoint = r.ConnectRooms.ToArray()[index];
  137.                 connectPointRoom.Connect(newPoint);
  138.                 _rooms.Add(r);
  139.                
  140.                 _dataRoomsBySeed.TryAdd(SeedRoom(r), new DataRoom(r, this));
  141.                 InitDataConnect(connectPointRoom);
  142.                 InitDataConnect(newPoint);
  143.             }
  144.             else
  145.             {
  146.                 if(_logInfo) Debug.Log("Нельзя создать комнату.");
  147.             }
  148.  
  149.             void InitDataConnect(ConnectPointRoom first)
  150.                 => _dataRoomsBySeed[SeedRoom(first.Room)].Points.First(x=>x.SelfGuid==first.GUID).Init(first);
  151.         }
  152.  
  153.         private void SpawnFirst(Room prefab)
  154.         {
  155.             _center = roomFactory.CreateRoom(prefab, Vector3.zero, Vector3.zero).With(x => x.transform.SetParent(transform));
  156.             _dataRoomsBySeed.Add(SeedRoom(_center), new DataRoom(_center, this));
  157.             _rooms.Add(_center);
  158.         }
  159.  
  160.         private int SeedRoom(Room room)
  161.             => _seed + (int)room.transform.position.x + (int)room.transform.position.y + (int)room.transform.position.z;
  162.  
  163.         private int SeedPoint(ConnectPointRoom point)
  164.             => _seed + (int)point.transform.position.x + (int)point.transform.position.y + (int)point.transform.position.z;
  165.  
  166.         public void ClearAll()
  167.         {
  168.             _rooms.ForEach(x => roomFactory.DeleteRoom(x));
  169.             _rooms.Clear();
  170.             if (_trackEntity)
  171.             {
  172.                 _trackEntity.EnterRoom += OnEnterRoom;
  173.             }
  174.  
  175.             _trackEntity = null;
  176.         }
  177.  
  178.         private void OnEnterRoom(Room obj)
  179.         {
  180.             if(obj==Center) return;
  181.             _center = obj;
  182.             UpdateRoomByCurrent();
  183.         }
  184.  
  185.         [System.Serializable]
  186.         private class DataRoom
  187.         {
  188.             [ShowInInspector]public int Seed { get; private set; }
  189.             [ShowInInspector]public string Guid { get; private set; }
  190.             public PointConnectData[] Points;
  191.  
  192.             public DataRoom(Room room, EndlessGenerateRoom generator)
  193.             {
  194.                 Guid = room.GUID;
  195.                 Seed = generator.SeedRoom(room);
  196.                 Points = new PointConnectData[room.ConnectRooms.Count];
  197.                 int count = 0;
  198.                 room.ConnectRooms.ForEach(x =>
  199.                 {
  200.                     Points[count] = new PointConnectData(x, generator);
  201.                     count++;
  202.                 });
  203.             }
  204.         }
  205.        
  206.         [System.Serializable]
  207.         private class PointConnectData
  208.         {
  209.             private EndlessGenerateRoom _gen;
  210.             [ShowInInspector]public string SelfGuid { get; private set; }
  211.             [ShowInInspector]public int? SeedConnectRoom { get; private set; }
  212.             [ShowInInspector]public string GuidPointConnect { get; private set; }
  213.  
  214.             public PointConnectData(ConnectPointRoom point, EndlessGenerateRoom generator)
  215.             {
  216.                 SelfGuid = point.GUID;
  217.                 SeedConnectRoom = null;
  218.                 GuidPointConnect = null;
  219.                 _gen = generator;
  220.             }
  221.  
  222.             public void Init(ConnectPointRoom otherPoint)
  223.             {
  224.                 if (!otherPoint.Link) return;
  225.                 if (IsValid()) return;
  226.                 GuidPointConnect = otherPoint.Link.GUID;
  227.                 SeedConnectRoom = _gen.SeedRoom(otherPoint.Link.Room);
  228.             }
  229.  
  230.             public bool IsValid() => SeedConnectRoom != null && !string.IsNullOrWhiteSpace(GuidPointConnect);
  231.         }
  232.     }
  233. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement