sm64coopdx/data/dynos_mgr_bhv.cpp
djoslin0 24b92ecc2a
Some checks are pending
Build coop / build-linux (push) Waiting to run
Build coop / build-steamos (push) Waiting to run
Build coop / build-windows-opengl (push) Waiting to run
Build coop / build-windows-directx (push) Waiting to run
Build coop / build-macos-arm (push) Waiting to run
Build coop / build-macos-intel (push) Waiting to run
Add a safer version of Lua's require() (#847)
I didn't add standard Lua require() because I've always been
afraid of it. I'm not sure we can guarantee which files it
will read (or not read).

Instead, here is a custom implementation. It should work more
or less the same and allow for more modular code.

For backwards compatibility reasons, all of the lua files in
the base mod folder will be loaded as in the past. Aka one at
a time and alphabetically.

However, now coop will look for Lua files in subdirectories
and will load them in when another Lua file calls require().

The file search order is more reasonable than normal Lua
require(). It will first look for files relative to the
currently running script. If there is no matching relative
file, it will pick from any Lua file that is in any of the
mod's subdirectories.

---------

Co-authored-by: MysterD <myster@d>
2025-06-14 19:49:07 +10:00

113 lines
No EOL
3.5 KiB
C++

#include "dynos.cpp.h"
extern "C" {
#include "engine/behavior_script.h"
#include "pc/network/packets/packet.h"
#include "pc/lua/smlua_hooks.h"
}
Array<Pair<const char *, GfxData *>> &DynOS_Bhv_GetArray() {
static Array<Pair<const char *, GfxData *>> sDynosCustomBehaviorScripts;
return sDynosCustomBehaviorScripts;
}
void DynOS_Bhv_Activate(s32 modIndex, const SysPath &aFilename, const char *aBehaviorName) {
auto &_CustomBehaviorScripts = DynOS_Bhv_GetArray();
// check for duplicates
for (s32 i = 0; i < _CustomBehaviorScripts.Count(); ++i) {
if (!strcmp(_CustomBehaviorScripts[i].first, aBehaviorName)) {
return;
}
}
u16 behaviorLen = strlen(aBehaviorName);
char *behaviorName = (char *)calloc(1, sizeof(char) * (behaviorLen + 1));
strcpy(behaviorName, aBehaviorName);
GfxData *_Node = DynOS_Bhv_LoadFromBinary(aFilename, behaviorName);
if (!_Node) {
free(behaviorName);
return;
}
// Remember index
_Node->mModIndex = modIndex;
// Add to behaviors
_CustomBehaviorScripts.Add({ behaviorName, _Node });
}
void DynOS_Bhv_ModShutdown() {
auto &_CustomBehaviorScripts = DynOS_Bhv_GetArray();
while (_CustomBehaviorScripts.Count() > 0) {
auto &pair = _CustomBehaviorScripts[0];
Delete(pair.second);
free((void *)pair.first);
_CustomBehaviorScripts.Remove(0);
}
}
GfxData *DynOS_Bhv_GetActiveGfx(BehaviorScript *bhvScript) {
auto &_CustomBehaviorScripts = DynOS_Bhv_GetArray();
for (s32 i = 0; i < _CustomBehaviorScripts.Count(); ++i) {
auto &gfxData = _CustomBehaviorScripts[i].second;
auto &scripts = gfxData->mBehaviorScripts;
if (scripts.Count() == 0) { continue; }
if (bhvScript == scripts[scripts.Count() - 1]->mData) {
return gfxData;
}
}
return NULL;
}
bool DynOS_Bhv_GetActiveModIndex(BehaviorScript *bhvScript, s32 *modIndex, s32 *modFileIndex) {
auto &_CustomBehaviorScripts = DynOS_Bhv_GetArray();
for (s32 i = 0; i < _CustomBehaviorScripts.Count(); ++i) {
auto &gfxData = _CustomBehaviorScripts[i].second;
auto &scripts = gfxData->mBehaviorScripts;
if (scripts.Count() == 0) { continue; }
if (bhvScript == scripts[scripts.Count() - 1]->mData) {
*modIndex = gfxData->mModIndex;
*modFileIndex = gfxData->mModFileIndex;
return true;
}
}
return false;
}
const char *DynOS_Bhv_GetToken(BehaviorScript *bhvScript, u32 index) {
GfxData *gfxData = DynOS_Bhv_GetActiveGfx(bhvScript);
if (gfxData == NULL) {
return NULL;
}
// have to 1-index due to to pointer read code
index = index - 1;
if (index >= gfxData->mLuaTokenList.Count()) {
return NULL;
}
return gfxData->mLuaTokenList[index].begin();
}
void DynOS_Bhv_HookAllCustomBehaviors() {
auto &_CustomBehaviorScripts = DynOS_Bhv_GetArray();
for (s32 i = 0; i < _CustomBehaviorScripts.Count(); ++i) {
auto &scriptName = _CustomBehaviorScripts[i].first;
auto &aGfxData = _CustomBehaviorScripts[i].second;
if (aGfxData->mBehaviorScripts.Count() == 0) { continue; }
auto *node = aGfxData->mBehaviorScripts[aGfxData->mBehaviorScripts.Count() - 1];
if (node == nullptr) { continue; }
auto &script = node->mData;
// Theres currently no better place but to do this here.
if (smlua_hook_custom_bhv(script, scriptName) == 0) {
PrintDataError(" ERROR: Failed to add custom behavior '%s'!", scriptName);
}
}
}