diff --git a/Nocturnis.csproj b/Nocturnis.csproj
index abb1f47..ce52fee 100644
--- a/Nocturnis.csproj
+++ b/Nocturnis.csproj
@@ -7,7 +7,7 @@
-
+
diff --git a/src/Controls/IStateControl.cs b/src/Controls/IStateControl.cs
new file mode 100644
index 0000000..a8e9320
--- /dev/null
+++ b/src/Controls/IStateControl.cs
@@ -0,0 +1,11 @@
+using Nocturnis.DataStructures.States;
+
+namespace Nocturnis.Controls;
+
+public interface IStateControl
+{
+ string this[string path] { get; set; }
+ void Load();
+ void Save();
+ public void AddRule(string path, StateTransferRule rule);
+}
\ No newline at end of file
diff --git a/src/DataStructures/DoubleKeyDictionary.cs b/src/DataStructures/DoubleKeyDictionary.cs
new file mode 100644
index 0000000..0615945
--- /dev/null
+++ b/src/DataStructures/DoubleKeyDictionary.cs
@@ -0,0 +1,35 @@
+namespace Nocturnis.DataStructures;
+
+public class DoubleKeyDictionary : Dictionary>
+{
+ public DoubleKeyDictionary(TValue defaultValue)
+ {
+ DefaultValue = defaultValue;
+ }
+
+ private TValue DefaultValue { get; set; }
+
+ public TValue this[TKey pk1, TKey pk2]
+ {
+ get
+ {
+ try
+ {
+ return this[pk1][pk2];
+ }
+ catch (KeyNotFoundException)
+ {
+ return DefaultValue;
+ }
+ }
+ set
+ {
+ if(!ContainsKey(pk1))
+ this[pk1] = new Dictionary();
+ this[pk1][pk2] = value;
+ }
+ }
+
+ public bool ContainsKey(TKey pk1, TKey pk2) => ContainsKey(pk1) && this[pk1].ContainsKey(pk2);
+
+}
\ No newline at end of file
diff --git a/src/DataStructures/States/StateTransferRule.cs b/src/DataStructures/States/StateTransferRule.cs
new file mode 100644
index 0000000..a172166
--- /dev/null
+++ b/src/DataStructures/States/StateTransferRule.cs
@@ -0,0 +1,3 @@
+namespace Nocturnis.DataStructures.States;
+
+public delegate bool StateTransferRule (string path, string fromState, string toState);
diff --git a/src/GlobalManagement/Controls/EnigmosControl.cs b/src/GlobalManagement/Controls/EnigmosControl.cs
index 061f281..33db3a1 100644
--- a/src/GlobalManagement/Controls/EnigmosControl.cs
+++ b/src/GlobalManagement/Controls/EnigmosControl.cs
@@ -37,7 +37,7 @@ public class EnigmosControl
EngineUp = true;
}
- public double Energy { get; set; } = 0d;
+ public double Energy { get; set; } = 1d;
public bool EngineUp { get; private set; }
public double IdlePower => CreatureControl.Instance.CurrentCharacter.MotherBoard.IdlePower + VoidPower;
public double VoidPower { get; set; } = 0;
diff --git a/src/GlobalManagement/Controls/StateControl.cs b/src/GlobalManagement/Controls/StateControl.cs
new file mode 100644
index 0000000..a16ce56
--- /dev/null
+++ b/src/GlobalManagement/Controls/StateControl.cs
@@ -0,0 +1,76 @@
+using System.Text.Json;
+using Nocturnis.Controls;
+using Nocturnis.DataStructures.States;
+using FileAccess = Godot.FileAccess;
+
+namespace Nocturnis.GlobalManagement.Controls;
+
+public sealed class StateControl
+{
+ public const string NullState = "NullState";
+
+ private HashSet Rules { get; set; }
+ public Dictionary States { get; set; }
+
+ private StateControl()
+ {
+ States = new Dictionary();
+ Rules = new HashSet();
+ }
+ private static StateControl _instance = null;
+ public static StateControl Instance => _instance ??= new StateControl();
+
+ public void Load()
+ {
+ if (!FileAccess.FileExists("States.json"))
+ return;
+ using FileAccess file = FileAccess.Open("States.json", FileAccess.ModeFlags.Read);
+ string jsonData = file.GetAsText();
+ States = JsonSerializer.Deserialize>(jsonData);
+ }
+
+ public void Save()
+ {
+ string jsonData = JsonSerializer.Serialize(States);
+ using FileAccess file = FileAccess.Open("States.json", FileAccess.ModeFlags.Write);
+ file.StoreString(jsonData);
+ }
+
+ public bool Transfer(string path, string state)
+ {
+ foreach (var rule in Rules)
+ if (rule(path, States[path], state))
+ {
+ States[path] = state;
+ return true;
+ }
+ return false;
+
+ }
+
+
+ public string this[string path]
+ {
+ get
+ {
+ try
+ {
+ return States[path];
+ }
+ catch (KeyNotFoundException)
+ {
+ return NullState;
+ }
+ }
+ set
+ {
+ if(!States.ContainsKey(path))
+ States[path] = NullState;
+ Transfer(path, value);
+ }
+ }
+ public void AddRule(StateTransferRule rule)
+ {
+ Rules.Add(rule);
+ }
+}
diff --git a/src/GlobalManagement/Controls/TopicControl.cs b/src/GlobalManagement/Controls/TopicControl.cs
new file mode 100644
index 0000000..c36013f
--- /dev/null
+++ b/src/GlobalManagement/Controls/TopicControl.cs
@@ -0,0 +1,70 @@
+using System.Text.Json;
+using Nocturnis.GlobalManagement.Providers;
+using Nocturnis.Hermeteus.BracketSystem;
+
+namespace Nocturnis.GlobalManagement.Controls;
+
+public class TopicControl
+{
+ private static TopicControl _instance;
+ public static TopicControl Instance => _instance ??= new TopicControl();
+ public HashSet ActiveTopics { get; set; }
+ public Dictionary Topics { get; set; }
+ private TopicControl()
+ {
+ ActiveTopics = new HashSet();
+ Topics = new Dictionary();
+ }
+
+ public void Load(string topicName)
+ {
+ string jsonContent = GlobalProvider.FileAccessProvider.Read($"res://Resources/Topics/{topicName}.json");
+ TopicData topicData = JsonSerializer.Deserialize(jsonContent);
+ IBracketTopic topic = GlobalProvider.ConstructorProvider.NewBracketTopic();
+ topic.Topic = topicData.topic;
+ topic.Reusable = topicData.reusable;
+ topic.Finished = false;
+ topic.LineMap = new Dictionary();
+ foreach (var lineData in topicData.lines)
+ {
+ IBracketLine line = GlobalProvider.ConstructorProvider.NewBracketLine();
+ line.Conditions = lineData.conditions;
+ line.Line = lineData.line;
+ line.Successors = new HashSet();
+ topic.LineMap[lineData.line] = line;
+ line.BraLines = lineData.braLines;
+ line.KetLines = lineData.ketLines;
+ line.ArrowMarkers = lineData.arrows;
+ line.CleanPrevious = lineData.cleanPrevious;
+ line.Topic = topicData.topic;
+ }
+
+ foreach (LineData lineData in topicData.lines)
+ {
+ IBracketLine line = topic.LineMap[lineData.line];
+ foreach (string successorId in lineData.successors)
+ line.Successors.Add(topic.LineMap[successorId]);
+ }
+ topic.Root = topic.LineMap[topicData.lines[0].line];
+ topic.CurrentLine = topic.Root;
+ Topics.Add(topic.Topic, topic);
+ }
+
+ private class TopicData
+ {
+ public bool reusable { get; set; }
+ public string topic { get; set; }
+ public LineData[] lines { get; set; }
+ }
+
+ private class LineData
+ {
+ public bool cleanPrevious { get; set; }
+ public string line { get; set; }
+ public string[] conditions { get; set; }
+ public string[] successors { get; set; }
+ public string[] braLines { get; set; }
+ public string[] ketLines { get; set; }
+ public string[] arrows { get; set; }
+ }
+}
diff --git a/src/GlobalManagement/Providers/GlobalProvider.cs b/src/GlobalManagement/Providers/GlobalProvider.cs
index 2e008b6..da1dfe0 100644
--- a/src/GlobalManagement/Providers/GlobalProvider.cs
+++ b/src/GlobalManagement/Providers/GlobalProvider.cs
@@ -1,5 +1,4 @@
using Godot;
-using Nocturnis.DataStructures.DataTypes;
using Nocturnis.Enigmos.Modules;
using Nocturnis.Inventories.Items;
@@ -15,6 +14,10 @@ public static class GlobalProvider
public static IDataTypeProvider DataTypeProvider { get; set; }
public static IProcessProvider ProcessProvider { get; set; }
public static ITextureProvider TextureProvider { get; set; }
+
+ public static IConstructorProvider ConstructorProvider { get; set; }
+
+ public static IFileAccessProvider FileAccessProvider { get; set; }
public static class ModulePreviewMapper
where TModule : IBaseModule
diff --git a/src/GlobalManagement/Providers/IConstructorProvider.cs b/src/GlobalManagement/Providers/IConstructorProvider.cs
new file mode 100644
index 0000000..fdf9f6d
--- /dev/null
+++ b/src/GlobalManagement/Providers/IConstructorProvider.cs
@@ -0,0 +1,9 @@
+using Nocturnis.Hermeteus.BracketSystem;
+
+namespace Nocturnis.GlobalManagement.Providers;
+
+public interface IConstructorProvider
+{
+ IBracketTopic NewBracketTopic();
+ IBracketLine NewBracketLine();
+}
diff --git a/src/GlobalManagement/Providers/IDataAccessProvider.cs b/src/GlobalManagement/Providers/IDataAccessProvider.cs
new file mode 100644
index 0000000..4237b90
--- /dev/null
+++ b/src/GlobalManagement/Providers/IDataAccessProvider.cs
@@ -0,0 +1,10 @@
+using FileAccess = Godot.FileAccess;
+
+namespace Nocturnis.GlobalManagement.Providers;
+
+public interface IFileAccessProvider
+{
+ public string Read(string path);
+ public void Write(string path, string content);
+ public string ResRead(string path);
+}
diff --git a/src/Hermeteus/BracketSystem/IBracketLine.cs b/src/Hermeteus/BracketSystem/IBracketLine.cs
new file mode 100644
index 0000000..0f729fd
--- /dev/null
+++ b/src/Hermeteus/BracketSystem/IBracketLine.cs
@@ -0,0 +1,15 @@
+namespace Nocturnis.Hermeteus.BracketSystem;
+
+public interface IBracketLine
+{
+ string Topic { get; set; }
+ string Line { get; set; }
+ bool CleanPrevious { get; set; }
+ string[] BraLines { get; set; }
+ string[] KetLines { get; set; }
+ string[] ArrowMarkers { get; set; }
+ string[] Conditions { get; set; }
+ HashSet Successors { get; set; }
+ bool IsReady { get; }
+}
+
\ No newline at end of file
diff --git a/src/Hermeteus/BracketSystem/IBracketTopic.cs b/src/Hermeteus/BracketSystem/IBracketTopic.cs
new file mode 100644
index 0000000..54f6d69
--- /dev/null
+++ b/src/Hermeteus/BracketSystem/IBracketTopic.cs
@@ -0,0 +1,13 @@
+namespace Nocturnis.Hermeteus.BracketSystem;
+
+public interface IBracketTopic
+{
+ bool Reusable { get; set; }
+ string Topic { get; set; }
+ bool Finished { get; set; }
+ IBracketLine Root { get; set; }
+ IBracketLine CurrentLine { get; set; }
+ void Activate();
+ void Finish();
+ Dictionary LineMap { get; set; }
+}
diff --git a/src/Hermeteus/ICondition.cs b/src/Hermeteus/BracketSystem/ICondition.cs
similarity index 59%
rename from src/Hermeteus/ICondition.cs
rename to src/Hermeteus/BracketSystem/ICondition.cs
index 6d4b421..16b4a98 100644
--- a/src/Hermeteus/ICondition.cs
+++ b/src/Hermeteus/BracketSystem/ICondition.cs
@@ -1,4 +1,4 @@
-namespace Nocturnis.Hermeteus;
+namespace Nocturnis.Hermeteus.BracketSystem;
public interface ICondition
{
diff --git a/src/Hermeteus/IInstructionAgent.cs b/src/Hermeteus/BracketSystem/IInstructionAgent.cs
similarity index 75%
rename from src/Hermeteus/IInstructionAgent.cs
rename to src/Hermeteus/BracketSystem/IInstructionAgent.cs
index ae43c8c..205910c 100644
--- a/src/Hermeteus/IInstructionAgent.cs
+++ b/src/Hermeteus/BracketSystem/IInstructionAgent.cs
@@ -1,13 +1,13 @@
using Godot;
using Nocturnis.UIElements.Layers;
-namespace Nocturnis.Hermeteus;
+namespace Nocturnis.Hermeteus.BracketSystem;
public interface IInstructionAgent : INodeInterface
{
void Load(string content, Action callBack);
void Clean(Action callBack);
- void LoadArrows(Vector2[] ends);
+ void LoadArrows(string[] ends);
void CleanArrows();
void Init(IInstructionLayer insLayer);
-}
\ No newline at end of file
+}
diff --git a/src/Hermeteus/Processors/IBracketProcessor.cs b/src/Hermeteus/BracketSystem/Processors/IBracketProcessor.cs
similarity index 78%
rename from src/Hermeteus/Processors/IBracketProcessor.cs
rename to src/Hermeteus/BracketSystem/Processors/IBracketProcessor.cs
index 7464022..c4ebf8c 100644
--- a/src/Hermeteus/Processors/IBracketProcessor.cs
+++ b/src/Hermeteus/BracketSystem/Processors/IBracketProcessor.cs
@@ -1,6 +1,4 @@
-using Nocturnis.UIElements;
-
-namespace Nocturnis.Hermeteus.Processors;
+namespace Nocturnis.Hermeteus.BracketSystem.Processors;
public interface IBracketProcessor
{
@@ -13,5 +11,5 @@ public interface IBracketProcessor
double BracketEsc { get; set; }
string Status { get; set; }
void Init(IInstructionAgent bra, IInstructionAgent pointer, IInstructionAgent ket);
- void SyncLoad(IBracketTalk talk);
+ void SyncLoad(IBracketLine talk);
}
diff --git a/src/Hermeteus/EBracketRouter.cs b/src/Hermeteus/EBracketRouter.cs
deleted file mode 100644
index 5dd4427..0000000
--- a/src/Hermeteus/EBracketRouter.cs
+++ /dev/null
@@ -1,16 +0,0 @@
-namespace Nocturnis.Hermeteus;
-
-public static class EBracketRouter
-{
- public static IBracketRouter RouteAndSkip(this IBracketRouter router)
- {
- IBracketRouter pr = router.Route();
- while (pr is IBracketTalk { CanSkip: true } prt)
- {
- prt.Finished = true;
- pr = pr.RouteAndSkip();
- }
- return pr;
- }
-}
-
diff --git a/src/Hermeteus/IBracketChapter.cs b/src/Hermeteus/IBracketChapter.cs
deleted file mode 100644
index aafbb13..0000000
--- a/src/Hermeteus/IBracketChapter.cs
+++ /dev/null
@@ -1,14 +0,0 @@
-using Skeleton.DataStructure.Tree;
-
-namespace Nocturnis.Hermeteus;
-
-public interface IBracketChapter : IBracketRouter
-{
- IBracketStory Story { get; set; }
- string State { get; set; }
- bool Finished { get; set; }
- string Chapter { get; set; }
- IBracketTopic CurrentTopic { get; set; }
- HashSet Children { get; set; }
- HashSet Conditions { get; set; }
-}
diff --git a/src/Hermeteus/IBracketRouter.cs b/src/Hermeteus/IBracketRouter.cs
deleted file mode 100644
index 466ff47..0000000
--- a/src/Hermeteus/IBracketRouter.cs
+++ /dev/null
@@ -1,6 +0,0 @@
-namespace Nocturnis.Hermeteus;
-
-public interface IBracketRouter
-{
- IBracketRouter Route();
-}
\ No newline at end of file
diff --git a/src/Hermeteus/IBracketStory.cs b/src/Hermeteus/IBracketStory.cs
deleted file mode 100644
index 8c2e36e..0000000
--- a/src/Hermeteus/IBracketStory.cs
+++ /dev/null
@@ -1,12 +0,0 @@
-using Nocturnis.Hermeteus.Processors;
-using Skeleton.DataStructure.Tree;
-
-namespace Nocturnis.Hermeteus;
-
-public interface IBracketStory : IBracketRouter
-{
- IBracketChapter CurrentChapter { get; set; }
- IBracketChapter[] Children { get; set; }
- IBracketRouter CurrentRouter { get; set; }
- bool Process(IBracketProcessor processor);
-}
diff --git a/src/Hermeteus/IBracketTalk.cs b/src/Hermeteus/IBracketTalk.cs
deleted file mode 100644
index 2a3bcb7..0000000
--- a/src/Hermeteus/IBracketTalk.cs
+++ /dev/null
@@ -1,18 +0,0 @@
-using Godot;
-
-namespace Nocturnis.Hermeteus;
-
-public interface IBracketTalk : IBracketRouter
-{
- IBracketTopic Topic { get; set; }
- string TriggerStatus { get; set; }
- string EnterStatus { get; set; }
- double TriggerEsc { get; set; }
- bool CleanPrevious { get; set; }
- string[] BraLines { get; set; }
- string[] KetLines { get; set; }
- HashSet Conditions { get; set; }
- Vector2[] ArrowMarkers { get; set; }
- bool Finished { get; set; }
- bool CanSkip { get; set; }
-}
diff --git a/src/Hermeteus/IBracketTopic.cs b/src/Hermeteus/IBracketTopic.cs
deleted file mode 100644
index 046fdcb..0000000
--- a/src/Hermeteus/IBracketTopic.cs
+++ /dev/null
@@ -1,13 +0,0 @@
-using Skeleton.DataStructure.Tree;
-
-namespace Nocturnis.Hermeteus;
-
-public interface IBracketTopic : IBracketRouter
-{
- IBracketChapter Chapter { get; set; }
- string Topic { get; set; }
- bool Finished { get; set; }
- HashSet Children { get; set; }
- IBracketTalk CurrentTalk { get; set; }
- HashSet Conditions { get; set; }
-}
diff --git a/src/Hermeteus/QuerySystem/IQueryEngine.cs b/src/Hermeteus/QuerySystem/IQueryEngine.cs
new file mode 100644
index 0000000..1012a7a
--- /dev/null
+++ b/src/Hermeteus/QuerySystem/IQueryEngine.cs
@@ -0,0 +1,8 @@
+using Godot;
+
+namespace Nocturnis.Hermeteus.QuerySystem;
+
+public interface IQueryEngine
+{
+ bool Check(string query);
+}
diff --git a/src/INodeInterface.cs b/src/INodeInterface.cs
index 89e6e0f..2425d6e 100644
--- a/src/INodeInterface.cs
+++ b/src/INodeInterface.cs
@@ -7,4 +7,5 @@ public interface INodeInterface
void RemoveChild(Node node);
void AddChild(Node node, bool forceReadableName = false, Node.InternalMode @internal = (Node.InternalMode)(0));
bool Visible { get; set; }
+ Node GetNode(NodePath path);
}
diff --git a/src/Scenes/IRootScene.cs b/src/Scenes/IRootScene.cs
index a68c49e..8be9e55 100644
--- a/src/Scenes/IRootScene.cs
+++ b/src/Scenes/IRootScene.cs
@@ -5,7 +5,7 @@ using Nocturnis.UIElements.Layers;
namespace Nocturnis.Scenes;
-public interface IRootScene
+public interface IRootScene : INodeInterface
{
void ChangeScene(Node scene);
IKeyListener KeyListener { get; set; }
diff --git a/src/UIElements/Layers/IInstructionLayer.cs b/src/UIElements/Layers/IInstructionLayer.cs
index a42028a..ebc706e 100644
--- a/src/UIElements/Layers/IInstructionLayer.cs
+++ b/src/UIElements/Layers/IInstructionLayer.cs
@@ -1,5 +1,6 @@
using Nocturnis.Hermeteus;
-using Nocturnis.Hermeteus.Processors;
+using Nocturnis.Hermeteus.BracketSystem;
+using Nocturnis.Hermeteus.BracketSystem.Processors;
namespace Nocturnis.UIElements.Layers;