Веб-сайт самохостера Lotigara

summaryrefslogtreecommitdiff
path: root/source/game/scripting/StarLuaComponents.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'source/game/scripting/StarLuaComponents.cpp')
-rw-r--r--source/game/scripting/StarLuaComponents.cpp155
1 files changed, 155 insertions, 0 deletions
diff --git a/source/game/scripting/StarLuaComponents.cpp b/source/game/scripting/StarLuaComponents.cpp
new file mode 100644
index 0000000..000e787
--- /dev/null
+++ b/source/game/scripting/StarLuaComponents.cpp
@@ -0,0 +1,155 @@
+#include "StarLuaComponents.hpp"
+#include "StarUtilityLuaBindings.hpp"
+#include "StarRootLuaBindings.hpp"
+
+namespace Star {
+
+LuaBaseComponent::LuaBaseComponent() {
+ addCallbacks("sb", LuaBindings::makeUtilityCallbacks());
+ addCallbacks("root", LuaBindings::makeRootCallbacks());
+ setAutoReInit(true);
+}
+
+LuaBaseComponent::~LuaBaseComponent() {}
+
+StringList const& LuaBaseComponent::scripts() const {
+ return m_scripts;
+}
+
+void LuaBaseComponent::setScript(String script) {
+ setScripts({move(script)});
+}
+
+void LuaBaseComponent::setScripts(StringList scripts) {
+ if (initialized())
+ throw LuaComponentException("Cannot call LuaWorldComponent::setScripts when LuaWorldComponent is initialized");
+
+ m_scripts = move(scripts);
+}
+
+void LuaBaseComponent::addCallbacks(String groupName, LuaCallbacks callbacks) {
+ if (!m_callbacks.insert(groupName, callbacks).second)
+ throw LuaComponentException::format("Duplicate callbacks named '%s' in LuaBaseComponent", groupName);
+
+ if (m_context)
+ m_context->setCallbacks(groupName, callbacks);
+}
+
+bool LuaBaseComponent::removeCallbacks(String const& groupName) {
+ if (m_callbacks.remove(groupName)) {
+ if (m_context)
+ m_context->remove(groupName);
+ return true;
+ }
+ return false;
+}
+
+bool LuaBaseComponent::autoReInit() const {
+ return (bool)m_reloadTracker;
+}
+
+void LuaBaseComponent::setAutoReInit(bool autoReInit) {
+ if (autoReInit) {
+ m_reloadTracker = make_shared<TrackerListener>();
+ Root::singleton().registerReloadListener(m_reloadTracker);
+ } else {
+ m_reloadTracker.reset();
+ }
+}
+
+void LuaBaseComponent::setLuaRoot(LuaRootPtr luaRoot) {
+ m_luaRoot = move(luaRoot);
+}
+
+LuaRootPtr const& LuaBaseComponent::luaRoot() {
+ return m_luaRoot;
+}
+
+bool LuaBaseComponent::init() {
+ uninit();
+
+ if (!m_luaRoot)
+ return false;
+
+ m_error.reset();
+ try {
+ m_context = m_luaRoot->createContext(m_scripts);
+ } catch (LuaException const& e) {
+ Logger::error("Exception while creating lua context for scripts '%s': %s", m_scripts, outputException(e, true));
+ m_error = String(printException(e, false));
+ m_context.reset();
+ return false;
+ }
+ contextSetup();
+
+ if (m_context->containsPath("init")) {
+ try {
+ m_context->invokePath("init");
+ } catch (LuaException const& e) {
+ Logger::error("Exception while calling script init: %s", outputException(e, true));
+ m_error = String(printException(e, false));
+ m_context.reset();
+ return false;
+ }
+ }
+
+ return true;
+}
+
+void LuaBaseComponent::uninit() {
+ if (m_context) {
+ if (m_context->containsPath("uninit")) {
+ try {
+ m_context->invokePath("uninit");
+ } catch (LuaException const& e) {
+ Logger::error("Exception while calling script uninit: %s", outputException(e, true));
+ m_error = String(printException(e, false));
+ }
+ }
+ contextShutdown();
+ m_context.reset();
+ }
+
+ m_error.reset();
+}
+
+bool LuaBaseComponent::initialized() const {
+ return m_context.isValid();
+}
+
+Maybe<String> const& LuaBaseComponent::error() const {
+ return m_error;
+}
+
+Maybe<LuaContext> const& LuaBaseComponent::context() const {
+ return m_context;
+}
+
+Maybe<LuaContext>& LuaBaseComponent::context() {
+ return m_context;
+}
+
+void LuaBaseComponent::contextSetup() {
+ m_context->setPath("self", m_context->createTable());
+
+ for (auto const& p : m_callbacks)
+ m_context->setCallbacks(p.first, p.second);
+}
+
+void LuaBaseComponent::contextShutdown() {}
+
+void LuaBaseComponent::setError(String error) {
+ m_context.reset();
+ m_error = move(error);
+}
+
+bool LuaBaseComponent::checkInitialization() {
+ // We should re-initialize if we are either already initialized or in an
+ // error state (which means we WERE initialized until we had an error)
+ bool shouldBeInitialized = initialized() || error();
+ if (shouldBeInitialized && m_reloadTracker && m_reloadTracker->pullTriggered())
+ init();
+ return initialized();
+}
+
+}