split into multiple assemblies

This commit is contained in:
2022-11-20 12:52:22 +01:00
parent def03954a0
commit 9fdfafc3eb
373 changed files with 380 additions and 119 deletions

View File

@@ -0,0 +1,47 @@
using System;
using UnityEngine;
namespace EscapeRoomEngine.Engine.Runtime.Modules
{
public enum DoorType
{
Entrance = ModuleType.DoorEntrance, Exit = ModuleType.DoorExit
}
[Serializable]
public class DoorModule : Module
{
public bool IsEntrance => IsType((ModuleType)DoorType.Entrance);
public bool IsExit => IsType((ModuleType)DoorType.Exit);
internal DoorState DoorState
{
get
{
if (State is DoorState doorState)
{
return doorState;
}
throw new Exception("DoorModule must contain a DoorState");
}
}
internal DoorModule(Space space, DoorModuleDescription description) : base(space, description)
{
srDimensions.Size = Vector2Int.one; // door always has size 1x1
}
internal override void InstantiateModule(Transform parent)
{
base.InstantiateModule(parent);
space.room.AddDoor(this);
}
public override string ToString()
{
return $"{(IsEntrance ? "Entrance" : IsExit ? "Exit" : "Unknown")} door";
}
}
}

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 05af827f50ab469f952abbb62109877d
timeCreated: 1667226128

View File

@@ -0,0 +1,14 @@
using UnityEngine;
namespace EscapeRoomEngine.Engine.Runtime.Modules
{
[CreateAssetMenu(menuName = "Modules/Door")]
public class DoorModuleDescription : ModuleDescription
{
/// <summary>
/// The description for the door that should be connected with this one.
/// <example>If this is a teleporter entrance, the connected door should be a teleporter exit.</example>
/// </summary>
public DoorModuleDescription connectedDoorDescription;
}
}

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: f5c1202346c34ebc9c3f701a98b50877
timeCreated: 1667833660

View File

@@ -0,0 +1,66 @@
using System;
using EscapeRoomEngine.Engine.Runtime.Utilities;
using NaughtyAttributes;
namespace EscapeRoomEngine.Engine.Runtime.Modules
{
public enum DoorEventType
{
Locked, Unlocked
}
public delegate void DoorEventHandler(DoorModule source, DoorEventType e);
public class DoorState : ModuleState
{
public event DoorEventHandler DoorEvent;
private new DoorModule Module { get; set; }
public bool Unlocked
{
get => _unlocked;
private set
{
var type =
!_unlocked && value ? Some<DoorEventType>.Of(DoorEventType.Unlocked)
: _unlocked && !value ? Some<DoorEventType>.Of(DoorEventType.Locked)
: None<DoorEventType>.New();
_unlocked = value;
type.Match(some: OnDoorEvent);
}
}
private bool _unlocked;
private void OnDoorEvent(DoorEventType type)
{
Logger.Log($"{Module} has been {type}", LogType.PuzzleFlow);
DoorEvent?.Invoke(Module, type);
}
public override void SetModule(Module module)
{
if (module is DoorModule doorModule)
{
Module = doorModule;
}
else
{
throw new Exception("Tried to set wrong type of module.");
}
}
[Button(enabledMode: EButtonEnableMode.Playmode)]
internal void Unlock()
{
Unlocked = true;
}
[Button(enabledMode: EButtonEnableMode.Playmode)]
internal void Lock()
{
Unlocked = false;
}
}
}

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 696181e3eda449d49d4c1c88b07d7b05
timeCreated: 1668337769

View File

@@ -0,0 +1,111 @@
using System;
using System.Collections.Generic;
using System.Linq;
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;
namespace EscapeRoomEngine.Engine.Runtime.Modules
{
public enum Orientation
{
North = 0, East = 90, South = 180, West = 270
}
public class Module
{
public static HashSet<Orientation> EveryOrientation => new(new[]
{
Orientation.North, Orientation.East, Orientation.South, Orientation.West
});
/// <summary>
/// Get the space relative (<i>SR</i>) position of this module.
/// </summary>
internal Vector2Int SrPosition => srDimensions.Position;
/// <summary>
/// Get the room relative (<i>RR</i>) position of this module.
/// </summary>
internal Vector2Int RrPosition => space.ToRoomRelative(SrPosition);
internal ModuleState State { get; private set; }
internal readonly ModuleDescription description;
internal Orientation orientation;
/// <summary>
/// The space relative (<i>SR</i>) dimensions of this module.
/// </summary>
protected Dimensions srDimensions;
protected readonly Space space;
internal Module(Space space, ModuleDescription description)
{
this.space = space;
this.description = description;
}
internal bool IsType(ModuleType type)
{
return description.types.Contains(type);
}
/// <summary>
/// Place this module with a position relative to the room.
/// </summary>
/// <param name="rrPosition">The room relative (<i>RR</i>) position of this module. Must be inside the space dimensions.</param>
/// <exception cref="Exception">If the position is not inside the space dimensions.</exception>
internal void PlaceRoomRelative(Vector2Int rrPosition) => Place(space.ToSpaceRelative(rrPosition));
/// <summary>
/// Place this module with a position relative to the space it is in.
/// </summary>
/// <param name="srPosition">The space relative (<i>SR</i>) position of this module. Must be inside the space dimensions.</param>
/// <exception cref="Exception">If the position is not inside the space dimensions.</exception>
internal void Place(Vector2Int srPosition) {
if (space != null && !srPosition.IsInsideRelative(space.rrDimensions))
{
throw new Exception($"Trying to place {this} at {srPosition}, which is outside space dimensions {space.rrDimensions}.");
}
srDimensions.Position = srPosition;
Logger.Log($"{this} has been placed at {srPosition} (SR)", LogType.ModulePlacement);
}
/// <summary>
/// Convert a position relative to this module to one relative to its space.
/// <example>The module relative position <c>(0, 1)</c> should always be in front of the module, wherever it faces.</example>
/// </summary>
/// <param name="mrPosition">The module relative (<i>MR</i>) position that should be converted to a space relative (<i>SR</i>) position.</param>
/// <returns></returns>
internal Vector2Int ToSpaceRelative(Vector2Int mrPosition)
{
return srDimensions.Position + orientation switch
{
Orientation.North => mrPosition,
Orientation.East => new Vector2Int(mrPosition.y, -mrPosition.x),
Orientation.South => -mrPosition,
Orientation.West => new Vector2Int(-mrPosition.y, mrPosition.x),
_ => throw new ArgumentOutOfRangeException()
};
}
internal virtual void InstantiateModule(Transform parent)
{
Logger.Log($"Instantiating {this}", LogType.RoomGeneration);
State = Object.Instantiate(description.modulePrefab, parent, false);
State.transform.localPosition = new Vector3(srDimensions.x + .5f, 0, srDimensions.z + .5f);
State.transform.Rotate(Vector3.up, (float)orientation);
State.name = ToString();
State.SetModule(this);
}
public override string ToString()
{
return $"Module ({string.Join(", ", description.types.ToList().ConvertAll(type => type.ToString()))})";
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: bef95c0b6e3be5847939fffa4294f99f
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,15 @@
using System.Collections.Generic;
using EscapeRoomEngine.Engine.Runtime.Requirements;
using UnityEngine;
namespace EscapeRoomEngine.Engine.Runtime.Modules
{
[CreateAssetMenu(menuName = "Modules/Generic Module")]
public class ModuleDescription : ScriptableObject
{
public List<ModuleType> types = new();
public ModuleState modulePrefab;
public List<PlacementRequirement> placementRequirements = new();
public List<OrientationRequirement> orientationRequirements = new();
}
}

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: abf4a405f6c64073995bded39977563e
timeCreated: 1667831630

View File

@@ -0,0 +1,11 @@
using UnityEngine;
namespace EscapeRoomEngine.Engine.Runtime.Modules
{
public class ModuleState : MonoBehaviour
{
public Module Module { get; protected set; }
public virtual void SetModule(Module module) => Module = module;
}
}

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: efdc32c450f7411385748449459a17b4
timeCreated: 1668180361

View File

@@ -0,0 +1,8 @@
namespace EscapeRoomEngine.Engine.Runtime.Modules
{
public enum ModuleType
{
DoorEntrance, DoorExit, // door types
Puzzle,
}
}

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 602fa211234b4068bca5ff38a2f9593f
timeCreated: 1667230405

View File

@@ -0,0 +1,33 @@
using System;
using UnityEngine;
namespace EscapeRoomEngine.Engine.Runtime.Modules
{
public class PuzzleModule : Module
{
internal PuzzleState PuzzleState
{
get
{
if (State is PuzzleState puzzleState)
{
return puzzleState;
}
throw new Exception("PuzzleModule must contain a PuzzleState");
}
}
internal PuzzleModule(Space space, PuzzleModuleDescription description) : base(space, description)
{
srDimensions.Size = Vector2Int.one; // TODO: larger modules
}
internal override void InstantiateModule(Transform parent)
{
base.InstantiateModule(parent);
space.room.AddPuzzle(this);
}
}
}

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: ed86ddbc20ae479895ab3c538ea9226f
timeCreated: 1667873701

View File

@@ -0,0 +1,9 @@
using UnityEngine;
namespace EscapeRoomEngine.Engine.Runtime.Modules
{
[CreateAssetMenu(menuName = "Modules/Puzzle")]
public class PuzzleModuleDescription : ModuleDescription
{
}
}

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: f928b97941e3469a9015316bb5ac1309
timeCreated: 1667873701

View File

@@ -0,0 +1,92 @@
using System;
using EscapeRoomEngine.Engine.Runtime.Utilities;
using NaughtyAttributes;
using Logger = EscapeRoomEngine.Engine.Runtime.Utilities.Logger;
using LogType = EscapeRoomEngine.Engine.Runtime.Utilities.LogType;
namespace EscapeRoomEngine.Engine.Runtime.Modules
{
public enum PuzzleEventType
{
Restarted, Solved, WrongInput
}
public static class PuzzleEventExtensions
{
public static string Description(this PuzzleEventType type, PuzzleModule module)
{
return type switch
{
PuzzleEventType.Restarted => $"{module} has been restarted",
PuzzleEventType.Solved => $"{module} has been solved",
PuzzleEventType.WrongInput => $"Wrong input for {module}",
_ => throw new ArgumentOutOfRangeException(nameof(type), type, null)
};
}
}
public delegate void PuzzleEventHandler(PuzzleModule source, PuzzleEventType e);
public class PuzzleState : ModuleState
{
public event PuzzleEventHandler PuzzleEvent;
public EngineTheme theme;
private new PuzzleModule Module { get; set; }
public bool Solved
{
get => _solved;
private set
{
var type =
!_solved && value ? Some<PuzzleEventType>.Of(PuzzleEventType.Solved)
: _solved && !value ? Some<PuzzleEventType>.Of(PuzzleEventType.Restarted)
: None<PuzzleEventType>.New();
_solved = value;
type.Match(some: OnPuzzleEvent);
}
}
private bool _solved;
private void OnPuzzleEvent(PuzzleEventType type)
{
Logger.Log(type.Description(Module), LogType.PuzzleFlow);
PuzzleEvent?.Invoke(Module, type);
}
public override void SetModule(Module module)
{
if (module is PuzzleModule puzzleModule)
{
Module = puzzleModule;
}
else
{
throw new Exception("Tried to set wrong type of module.");
}
}
[Button(enabledMode: EButtonEnableMode.Playmode)]
public void Solve()
{
Solved = true;
}
[Button(enabledMode: EButtonEnableMode.Playmode)]
public void Restart()
{
Solved = false;
}
[Button("Trigger Wrong Input", EButtonEnableMode.Playmode)]
public void WrongInput()
{
if (!Solved)
{
OnPuzzleEvent(PuzzleEventType.WrongInput);
}
}
}
}

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 265ea1efb38042b282ea67c50ac3e878
timeCreated: 1668180832