#pragma once #include #include #include #include #include #include #include "Tile.h" #include "Item.h" #include "WorldGen.h" #include "Entity.h" #include "Collection.h" #include "Resource.h" #include "OS.h" #include "util.h" namespace Swan { class Mod { public: Mod(std::string name): name_(std::move(name)) {} virtual ~Mod() = default; void registerImage(const std::string &id); void registerTile(Tile::Builder tile); void registerItem(Item::Builder item); void registerWorldGen(const std::string &name, std::unique_ptr gen); template void registerWorldGen(const std::string &name) { worldgens_.push_back(WorldGen::Factory{ .name = name_ + "::" + name, .create = [](World &world) -> std::unique_ptr { return std::make_unique(world); } }); } template void registerEntity(const std::string &name) { static_assert( std::is_move_constructible_v, "Entities must be movable"); entities_.push_back(EntityCollection::Factory{ .name = name_ + "::" + name, .create = [](std::string name) -> std::unique_ptr { return std::make_unique>(std::move(name)); } }); } const std::string name_; std::vector images_; std::vector tiles_; std::vector items_; std::vector worldgens_; std::vector entities_; }; class ModWrapper { public: ModWrapper(std::unique_ptr mod, std::string path, OS::Dynlib lib): mod_(std::move(mod)), path_(std::move(path)), dynlib_(std::move(lib)) {} ModWrapper(ModWrapper &&other) noexcept = default; ~ModWrapper() { // Mod::~Mod will destroy stuff allocated by the dynlib, // so we must run its destructor before deleting the dynlib mod_.reset(); } Iter> buildImages(SDL_Renderer *renderer); Iter> buildTiles(const ResourceManager &resources); Iter> buildItems(const ResourceManager &resources); Iter getWorldGens(); Iter getEntities(); std::unique_ptr mod_; std::string path_; OS::Dynlib dynlib_; }; }