using System; using System.Collections.Generic; using EscapeRoomEngine.Engine.Runtime.Modules; using EscapeRoomEngine.Engine.Runtime.Modules.Description; using EscapeRoomEngine.Engine.Runtime.UI; using EscapeRoomEngine.Engine.Runtime.Utilities; using UnityEngine; using Logger = EscapeRoomEngine.Engine.Runtime.Utilities.Logger; using LogType = EscapeRoomEngine.Engine.Runtime.Utilities.LogType; using Object = UnityEngine.Object; using Range = EscapeRoomEngine.Engine.Runtime.Utilities.Range; namespace EscapeRoomEngine.Engine.Runtime { /// /// The space is responsible for placing and instantiating any modules in it. /// public class Space { /// /// The room relative (RR) dimensions of this space. /// internal readonly Placement rrPlacement; /// /// The room this space is in. /// internal readonly Room room; /// /// A list of all modules. /// internal List Modules { get; } = new(2); /// /// A list of all staged and added modules. /// internal List AllModules { get { var modules = new List(Modules); if (_stagedModules.Count > 0) { modules.AddRange(_stagedModules); } return modules; } } private GameObject _spaceObject, _spaceTiles; private List _stagedModules = new(); internal Space(Room room, Passage entrance) { this.room = room; rrPlacement = new Placement { position = Vector3Int.zero, size = new Vector2Int(GameControl.Instance.RoomSize.x, GameControl.Instance.RoomSize.y) }; // connect the space to its entrance passage entrance.PlaceEntrance(new DoorModule(this, ((DoorModuleDescription)entrance.fromOut.description).connectedDoorDescription)); Modules.Add(entrance.toIn); } internal bool AddModuleWithRequirements(Module module) { var requirementsFulfilled = module.CheckRequirements(); if (requirementsFulfilled) { // add all previously staged modules first ... for (var i = _stagedModules.Count - 1; i >= 0; i--) { Modules.Add(_stagedModules[i]); } // ... and then add the module itself Modules.Add(module); } // always clear the staged modules. if a module isn't added, its corresponding staged modules should be discarded _stagedModules = new List(); return requirementsFulfilled; } /// /// Stage a module if its requirements are currently met. It will be added as soon as the next module is added by . /// /// The module to stage /// Whether the requirements were met and the module was staged internal bool StageModuleWithRequirements(Module module) { var requirementsFulfilled = module.CheckRequirements(); if (requirementsFulfilled) { _stagedModules.Add(module); } return requirementsFulfilled; } internal void InstantiateSpace(Transform parent, string name) { _spaceObject = new GameObject($"Space {name}"); _spaceObject.transform.SetParent(parent, false); _spaceObject.transform.localPosition = new Vector3(rrPlacement.position.x, 0, rrPlacement.position.z); // build the space floor out of tiles _spaceTiles = new GameObject($"Space Geometry"); _spaceTiles.transform.SetParent(_spaceObject.transform, false); _spaceTiles.isStatic = true; for (var z = 0; z < rrPlacement.size.y; z++) { for (var x = 0; x < rrPlacement.size.x; x++) { var left = x == 0; var right = x == rrPlacement.size.x - 1; var bottom = z == 0; var top = z == rrPlacement.size.y - 1; TileLocation location; if (bottom) location = left ? TileLocation.SW : right ? TileLocation.SE : TileLocation.S; else if (top) location = left ? TileLocation.NW : right ? TileLocation.NE : TileLocation.N; else location = left ? TileLocation.W : right ? TileLocation.E : TileLocation.C; var tileObject = Object.Instantiate(Engine.Theme.spaceTile, _spaceTiles.transform, false); tileObject.transform.localPosition = new Vector3(x, 0, z); tileObject.showTile = location; } } // instantiate all modules inside this space Modules.ForEach(module => module.InstantiateModule(_spaceObject.transform)); } /// /// Convert a position relative to this space to one relative to the room. /// /// The space relative (SR) position that should be converted to a room relative (RR) position. internal Vector3Int ToRoomRelative(Vector3Int srPosition) => srPosition + rrPlacement.position; /// /// Convert a position relative to the room to one relative to this space. /// /// The room relative (RR) position that should be converted to a space relative (SR) position. internal Vector3Int ToSpaceRelative(Vector3Int rrPosition) => rrPosition - rrPlacement.position; } }