Skip to content

Commit 74bc2e8

Browse files
committed
fix: ensure mods are unloaded when the server stops #303
1 parent ebf942c commit 74bc2e8

File tree

2 files changed

+40
-8
lines changed

2 files changed

+40
-8
lines changed

src/legacy/api/EventAPI.cpp

Lines changed: 33 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -78,11 +78,15 @@ bool hasListened[int(EVENT_TYPES::EVENT_COUNT)] = {false};
7878

7979
//////////////////// APIs ////////////////////
8080

81+
Local<Value> listenCancellable(ScriptEngine* engine, const string& eventName, const Local<Function>& func);
8182
Local<Value> McClass::listen(const Arguments& args) {
8283
CHECK_ARGS_COUNT(args, 2);
8384
CHECK_ARG_TYPE(args[0], ValueKind::kString);
8485
CHECK_ARG_TYPE(args[1], ValueKind::kFunction);
8586

87+
if (args.size() >= 3 && args[2].isBoolean() && args[2].asBoolean().value()) {
88+
return listenCancellable(EngineScope::currentEngine(), args[0].asString().toString(), args[1].asFunction());
89+
}
8690
try {
8791
return Boolean::newBoolean(
8892
LLSEAddEventListener(EngineScope::currentEngine(), args[0].asString().toString(), args[1].asFunction())
@@ -91,6 +95,29 @@ Local<Value> McClass::listen(const Arguments& args) {
9195
CATCH("Fail to Bind Listener!");
9296
}
9397

98+
Local<Value> listenCancellable(ScriptEngine* engine, const string& eventName, const Local<Function>& func) {
99+
try {
100+
auto event_enum = magic_enum::enum_cast<EVENT_TYPES>(eventName);
101+
auto eventId = int(event_enum.value());
102+
auto event =
103+
listenerList[eventId].insert(listenerList[eventId].end(), {engine, script::Global<Function>(func)});
104+
if (!hasListened[eventId]) {
105+
hasListened[eventId] = true;
106+
EnableEventListener(eventId);
107+
}
108+
return Function::newFunction([eventId{eventId}, event{event}](const Arguments&) -> Local<Value> {
109+
listenerList[eventId].erase(event);
110+
return Local<Value>();
111+
});
112+
} catch (...) {
113+
lse::LegacyScriptEngine::getInstance().getSelf().getLogger().error("Event {} not found!"_tr(eventName));
114+
lse::LegacyScriptEngine::getInstance().getSelf().getLogger().error(
115+
"In Plugin: " + getEngineData(engine)->pluginName
116+
);
117+
return Local<Value>();
118+
}
119+
}
120+
94121
//////////////////// Funcs ////////////////////
95122

96123
bool LLSEAddEventListener(ScriptEngine* engine, const string& eventName, const Local<Function>& func) {
@@ -135,14 +162,13 @@ bool LLSECallEventsOnHotLoad(ScriptEngine* engine) {
135162
}
136163

137164
bool LLSECallEventsOnUnload(ScriptEngine* engine) {
138-
if (ll::getGamingStatus() == ll::GamingStatus::Running) {
139-
ll::service::getLevel()->forEachPlayer([&](Player& pl) -> bool {
140-
FakeCallEvent(engine, EVENT_TYPES::onLeft, PlayerClass::newPlayer(&pl));
141-
return true;
142-
});
143-
}
165+
// Players may be online when the server is stopping
166+
ll::service::getLevel()->forEachPlayer([&](Player& pl) -> bool {
167+
FakeCallEvent(engine, EVENT_TYPES::onLeft, PlayerClass::newPlayer(&pl));
168+
return true;
169+
});
170+
EngineScope scope(engine);
144171
for (auto& [index, cb] : getEngineData(engine)->unloadCallbacks) {
145-
EngineScope scope(engine);
146172
try {
147173
cb(engine);
148174
}

src/lse/PluginManager.cpp

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -158,8 +158,8 @@ ll::Expected<> PluginManager::load(ll::mod::Manifest manifest) {
158158

159159
BindAPIs(scriptEngine);
160160

161-
auto& self = LegacyScriptEngine::getInstance().getSelf();
162161
#ifndef LEGACY_SCRIPT_ENGINE_BACKEND_NODEJS // NodeJs backend load depends code in another place
162+
auto& self = LegacyScriptEngine::getInstance().getSelf();
163163
// Load BaseLib.
164164
auto baseLibPath = self.getModDir() / "baselib" / BaseLibFileName;
165165
auto baseLibContent = ll::file_utils::readFile(baseLibPath);
@@ -208,6 +208,12 @@ ll::Expected<> PluginManager::load(ll::mod::Manifest manifest) {
208208
}
209209
ExitEngineScope exit;
210210
plugin->onLoad([](ll::mod::Mod&) { return true; });
211+
plugin->onDisable([this](ll::mod::Mod& self) {
212+
if (ll::getGamingStatus() == ll::GamingStatus::Stopping) {
213+
unload(self.getName());
214+
}
215+
return true;
216+
});
211217

212218
return plugin->onLoad().transform([&, this] { addMod(manifest.name, plugin); });
213219
} catch (const Exception& e) {

0 commit comments

Comments
 (0)