From 2e6fcb1d048edd13a2ec69ddd226fc8ebabc2389 Mon Sep 17 00:00:00 2001
From: Loek Le Blansch <loek@pipeframe.xyz>
Date: Sat, 7 Dec 2024 16:01:19 +0100
Subject: add SaveManager to Script

---
 src/crepe/api/Script.cpp           | 11 +++++++----
 src/crepe/api/Script.h             |  4 ++++
 src/crepe/api/Script.hpp           |  6 ++----
 src/crepe/util/OptionalRef.h       | 10 +++++++++-
 src/crepe/util/OptionalRef.hpp     |  7 +++++++
 src/test/CMakeLists.txt            |  1 +
 src/test/ScriptSaveManagerTest.cpp | 36 ++++++++++++++++++++++++++++++++++++
 7 files changed, 66 insertions(+), 9 deletions(-)
 create mode 100644 src/test/ScriptSaveManagerTest.cpp

(limited to 'src')

diff --git a/src/crepe/api/Script.cpp b/src/crepe/api/Script.cpp
index 4091fd4..961e6e7 100644
--- a/src/crepe/api/Script.cpp
+++ b/src/crepe/api/Script.cpp
@@ -8,8 +8,7 @@ using namespace crepe;
 using namespace std;
 
 Script::~Script() {
-	Mediator & mediator = this->mediator;
-	EventManager & mgr = mediator.event_manager;
+	EventManager & mgr = this->mediator->event_manager;
 	for (auto id : this->listeners) {
 		mgr.unsubscribe(id);
 	}
@@ -21,7 +20,11 @@ void Script::subscribe(const EventHandler<CollisionEvent> & callback) {
 }
 
 void Script::set_next_scene(const string & name) {
-	Mediator & mediator = this->mediator;
-	SceneManager & mgr = mediator.scene_manager;
+	SceneManager & mgr = this->mediator->scene_manager;
 	mgr.set_next_scene(name);
 }
+
+SaveManager & Script::get_save_manager() const {
+	return this->mediator->save_manager;
+}
+
diff --git a/src/crepe/api/Script.h b/src/crepe/api/Script.h
index d99ab0e..024f1d7 100644
--- a/src/crepe/api/Script.h
+++ b/src/crepe/api/Script.h
@@ -7,6 +7,7 @@
 #include "../system/CollisionSystem.h"
 #include "../types.h"
 #include "../util/OptionalRef.h"
+#include "../ValueBroker.h"
 
 namespace crepe {
 
@@ -113,6 +114,9 @@ protected:
 	 */
 	void set_next_scene(const std::string & name);
 
+	//! Retrieve SaveManager reference
+	SaveManager & get_save_manager() const;
+
 	//! \}
 
 private:
diff --git a/src/crepe/api/Script.hpp b/src/crepe/api/Script.hpp
index 45f1ff1..23d69d9 100644
--- a/src/crepe/api/Script.hpp
+++ b/src/crepe/api/Script.hpp
@@ -20,8 +20,7 @@ T & Script::get_component() const {
 
 template <typename T>
 RefVector<T> Script::get_components() const {
-	Mediator & mediator = this->mediator;
-	ComponentManager & mgr = mediator.component_manager;
+	ComponentManager & mgr = this->mediator->component_manager;
 
 	return mgr.get_components_by_id<T>(this->game_object_id);
 }
@@ -34,8 +33,7 @@ void Script::logf(Args &&... args) {
 template <typename EventType>
 void Script::subscribe_internal(const EventHandler<EventType> & callback,
 								event_channel_t channel) {
-	Mediator & mediator = this->mediator;
-	EventManager & mgr = mediator.event_manager;
+	EventManager & mgr = this->mediator->event_manager;
 	subscription_t listener = mgr.subscribe<EventType>(
 		[this, callback](const EventType & data) -> bool {
 			bool & active = this->active;
diff --git a/src/crepe/util/OptionalRef.h b/src/crepe/util/OptionalRef.h
index 3201667..1b2cb3f 100644
--- a/src/crepe/util/OptionalRef.h
+++ b/src/crepe/util/OptionalRef.h
@@ -25,13 +25,21 @@ public:
 	 */
 	OptionalRef<T> & operator=(T & ref);
 	/**
-	 * \brief Retrieve this reference
+	 * \brief Retrieve this reference (cast)
 	 *
 	 * \returns Internal reference if it is set
 	 *
 	 * \throws std::runtime_error if this function is called while the reference it not set
 	 */
 	operator T &() const;
+	/**
+	 * \brief Retrieve this reference (member access)
+	 *
+	 * \returns Internal reference if it is set
+	 *
+	 * \throws std::runtime_error if this function is called while the reference it not set
+	 */
+	T * operator->() const;
 	/**
 	 * \brief Check if this reference is not empty
 	 *
diff --git a/src/crepe/util/OptionalRef.hpp b/src/crepe/util/OptionalRef.hpp
index 4608c9e..5e36b3a 100644
--- a/src/crepe/util/OptionalRef.hpp
+++ b/src/crepe/util/OptionalRef.hpp
@@ -18,6 +18,13 @@ OptionalRef<T>::operator T &() const {
 	return *this->ref;
 }
 
+template <typename T>
+T * OptionalRef<T>::operator->() const {
+	if (this->ref == nullptr)
+		throw std::runtime_error("OptionalRef: attempt to dereference nullptr");
+	return this->ref;
+}
+
 template <typename T>
 OptionalRef<T> & OptionalRef<T>::operator=(T & ref) {
 	this->ref = &ref;
diff --git a/src/test/CMakeLists.txt b/src/test/CMakeLists.txt
index 734e3ee..2cb7c7a 100644
--- a/src/test/CMakeLists.txt
+++ b/src/test/CMakeLists.txt
@@ -18,4 +18,5 @@ target_sources(test_main PUBLIC
 	ScriptSceneTest.cpp
 	Profiling.cpp
 	SaveManagerTest.cpp
+	ScriptSaveManagerTest.cpp
 )
diff --git a/src/test/ScriptSaveManagerTest.cpp b/src/test/ScriptSaveManagerTest.cpp
new file mode 100644
index 0000000..098afa0
--- /dev/null
+++ b/src/test/ScriptSaveManagerTest.cpp
@@ -0,0 +1,36 @@
+#include <gtest/gtest.h>
+
+// stupid hack to allow access to private/protected members under test
+#define private public
+#define protected public
+
+#include <crepe/manager/SaveManager.h>
+#include <crepe/facade/DB.h>
+
+#include "ScriptTest.h"
+
+using namespace std;
+using namespace crepe;
+using namespace testing;
+
+class ScriptSaveManagerTest : public ScriptTest {
+public:
+	class TestSaveManager : public SaveManager {
+		using SaveManager::SaveManager;
+
+		// in-memory database for testing
+		DB db{};
+		virtual DB & get_db() override { return this->db; }
+	};
+
+	TestSaveManager save_mgr{mediator};
+};
+
+TEST_F(ScriptSaveManagerTest, GetSaveManager) {
+	MyScript & script = this->script;
+
+	SaveManager & mgr = script.get_save_manager();
+
+	EXPECT_EQ(&mgr, &save_mgr);
+}
+
-- 
cgit v1.2.3