@@ -11,13 +11,19 @@ | |||
#include "WorldGen.h" | |||
#include "Entity.h" | |||
#include "Resource.h" | |||
#include "OS.h" | |||
#include "util.h" | |||
namespace Swan { | |||
class Mod { | |||
public: | |||
Mod(const std::string &path): path_(path) {} | |||
Mod(const std::string &path, OS::Dynlib &&dynlib): | |||
path_(path), dynlib_(std::move(dynlib)) {} | |||
// We have to manually ensure anything created from the dynlib | |||
// is destructed before the dynlib itself is destructed | |||
~Mod(); | |||
void init(const std::string &name); | |||
@@ -43,6 +49,7 @@ private: | |||
std::vector<std::unique_ptr<Entity::Factory>> entities_; | |||
std::string path_; | |||
OS::Dynlib dynlib_; | |||
bool inited_ = false; | |||
}; | |||
@@ -12,6 +12,8 @@ bool isTTY(FILE *f); | |||
class Dynlib { | |||
public: | |||
Dynlib(const std::string &path); | |||
Dynlib(const Dynlib &) = delete; | |||
Dynlib(Dynlib &&dl); | |||
~Dynlib(); | |||
template<typename T> T get(const std::string &name) { return (T)getVoid(name); } |
@@ -13,14 +13,13 @@ namespace Swan { | |||
std::unique_ptr<Mod> Game::loadMod(const std::string &path) { | |||
OS::Dynlib dl(path + "/mod"); | |||
auto init = dl.get<void (*)(Swan::Mod &)>("mod_init"); | |||
if (init == NULL) { | |||
warn << path << ": No 'mod_init' function!"; | |||
return NULL; | |||
return nullptr; | |||
} | |||
std::unique_ptr<Mod> mod = std::make_unique<Mod>(path); | |||
std::unique_ptr<Mod> mod = std::make_unique<Mod>(path, std::move(dl)); | |||
init(*mod); | |||
return mod; | |||
} |
@@ -8,6 +8,14 @@ | |||
namespace Swan { | |||
Mod::~Mod() { | |||
images_.clear(); | |||
tiles_.clear(); | |||
items_.clear(); | |||
worldgens_.clear(); | |||
entities_.clear(); | |||
} | |||
void Mod::init(const std::string &name) { | |||
name_ = name; | |||
inited_ = true; |
@@ -16,13 +16,19 @@ bool isTTY(FILE *f) { | |||
Dynlib::Dynlib(const std::string &path) { | |||
handle_ = dlopen((path + ".so").c_str(), RTLD_LAZY); | |||
if (handle_ == NULL) { | |||
if (handle_ == nullptr) { | |||
throw std::runtime_error(dlerror()); | |||
} | |||
} | |||
Dynlib::Dynlib(Dynlib &&dl) { | |||
handle_ = dl.handle_; | |||
dl.handle_ = nullptr; | |||
} | |||
Dynlib::~Dynlib() { | |||
dlclose(handle_); | |||
if (handle_ != nullptr) | |||
dlclose(handle_); | |||
} | |||
void *Dynlib::getVoid(const std::string &name) { |