move puzzle implementations out of engine

This commit is contained in:
2023-03-22 09:44:17 +01:00
parent e1bfecbd4b
commit 30d8f986df
70 changed files with 82 additions and 46 deletions

View File

@@ -0,0 +1,80 @@
using EscapeRoomEngine.Engine.Runtime.Utilities;
using NaughtyAttributes;
namespace EscapeRoomEngine.Engine.Runtime.Modules.State
{
public enum DoorEventType
{
Locked, Unlocked, Connected, ExitedFrom
}
public delegate void DoorEventHandler(DoorModule source, DoorEventType e);
/// <summary>
/// The <see cref="ModuleState"/> of a <see cref="DoorModule"/>. Handles all events that can occur for a door.
/// </summary>
public class DoorState : ModuleState
{
/// <summary>
/// Add event handlers to this hook to receive all events concerning this door.
/// </summary>
public event DoorEventHandler DoorEvent;
/// <summary>
/// The door module this state belongs to.
/// </summary>
protected 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;
protected void OnDoorEvent(DoorEventType type)
{
Logger.Log($"{Module} has been {type}", LogType.PuzzleFlow);
DoorEvent?.Invoke(Module, type);
}
public override void SetModule(Module module)
{
Module = DoorModule.FromModule(module);
}
public void Connect() => OnDoorEvent(DoorEventType.Connected);
#region Debug Buttons
[Button(enabledMode: EButtonEnableMode.Playmode)]
internal void Unlock() => Unlocked = true;
[Button(enabledMode: EButtonEnableMode.Playmode)]
internal void Lock() => Unlocked = false;
[Button(enabledMode: EButtonEnableMode.Playmode)]
protected internal void ExitFrom() => OnDoorEvent(DoorEventType.ExitedFrom);
#endregion
public static DoorState FromState(ModuleState state)
{
if (state is DoorState doorState)
{
return doorState;
}
throw new WrongTypeException(typeof(DoorState), state.GetType(), typeof(ModuleState));
}
}
}

View File

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

View File

@@ -0,0 +1,21 @@
using UnityEngine;
namespace EscapeRoomEngine.Engine.Runtime.Modules.State
{
/// <summary>
/// An abstract module state. Example implementations are <see cref="DoorState"/> and <see cref="PuzzleState"/>.
/// </summary>
[SelectionBase]
public abstract class ModuleState : MonoBehaviour
{
[Tooltip("The size of this module in meters.")]
public Vector2Int size = Vector2Int.one;
public abstract void SetModule(Module module);
public override string ToString()
{
return name;
}
}
}

View File

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

View File

@@ -0,0 +1,106 @@
using System;
using EscapeRoomEngine.Engine.Runtime.Utilities;
using JetBrains.Annotations;
using NaughtyAttributes;
using Logger = EscapeRoomEngine.Engine.Runtime.Utilities.Logger;
using LogType = EscapeRoomEngine.Engine.Runtime.Utilities.LogType;
namespace EscapeRoomEngine.Engine.Runtime.Modules.State
{
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);
/// <summary>
/// The <see cref="ModuleState"/> of a <see cref="PuzzleModule"/>. Handles all events that can occur for a door.
/// </summary>
public class PuzzleState : ModuleState
{
/// <summary>
/// Add event handlers to this hook to receive all events concerning this puzzle.
/// </summary>
public event PuzzleEventHandler PuzzleEvent;
/// <summary>
/// The puzzle module this state belongs to.
/// </summary>
protected PuzzleModule Module { get; private 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;
protected virtual void Start()
{
OnPuzzleEvent(PuzzleEventType.Restarted);
}
private void OnPuzzleEvent(PuzzleEventType type)
{
Logger.Log(type.Description(Module), LogType.PuzzleFlow);
PuzzleEvent?.Invoke(Module, type);
}
public override void SetModule(Module module)
{
Module = PuzzleModule.FromModule(module);
}
#region Debug Buttons
[Button(enabledMode: EButtonEnableMode.Playmode)]
public void Solve() => Solved = true;
[UsedImplicitly]
[Button(enabledMode: EButtonEnableMode.Playmode)]
public void Restart() => Solved = false;
[Button("Trigger Wrong Input", EButtonEnableMode.Playmode)]
public void WrongInput()
{
if (!Solved)
{
OnPuzzleEvent(PuzzleEventType.WrongInput);
}
}
#endregion
public static PuzzleState FromState(ModuleState state)
{
if (state is PuzzleState puzzleState)
{
return puzzleState;
}
throw new WrongTypeException(typeof(PuzzleState), state.GetType(), typeof(ModuleState));
}
}
}

View File

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

View File

@@ -0,0 +1,13 @@
namespace EscapeRoomEngine.Engine.Runtime.Modules.State
{
/// <summary>
/// The spawn door is used in the first room.
/// </summary>
internal class Spawn : DoorState
{
private void Start()
{
ExitFrom();
}
}
}

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 404f750726904ea98f8a85feaca0df66
timeCreated: 1670779750