Browse Source

mods are responsible for creating the mod object now, not just init

opengl-renderer-broken
Martin Dørum 4 years ago
parent
commit
e9c9c862e8

+ 73
- 65
core.mod/src/main.cc View File

@@ -6,77 +6,85 @@

static Swan::EventListener break_listener;

extern "C" void mod_init(Swan::Mod &mod, Swan::World &world) {
mod.init("core");
class CoreMod: public Swan::Mod {
public:
CoreMod(Swan::World &world): Swan::Mod("core") {
break_listener_ = world.evt_tile_break_.subscribe(
std::bind_front(&CoreMod::onTileBreak, this));

break_listener = world.evt_tile_break_.subscribe([](
const Swan::Context &ctx, Swan::TilePos pos, Swan::Tile &tile) {
registerImage("tile/air");
registerImage("tile/stone");
registerImage("tile/dirt");
registerImage("tile/grass");
registerImage("tile/tree-trunk");
registerImage("tile/leaves");
registerImage("entity/player-running");
registerImage("entity/player-still");
registerImage("misc/background-cave");

registerTile({
.name = "air",
.image = "core/tile/air",
.is_solid = false,
});
registerTile({
.name = "stone",
.image = "core/tile/stone",
.dropped_item = "core::stone",
});
registerTile({
.name = "dirt",
.image = "core/tile/dirt",
.dropped_item = "core::dirt",
});
registerTile({
.name = "grass",
.image = "core/tile/grass",
.dropped_item = "core::dirt",
});
registerTile({
.name = "tree-trunk",
.image = "core/tile/tree-trunk",
.dropped_item = "core::tree-trunk",
});
registerTile({
.name = "leaves",
.image = "core/tile/leaves",
});

registerItem({
.name = "stone",
.image = "core/tile/stone",
});
registerItem({
.name = "dirt",
.image = "core/tile/dirt",
});
registerItem({
.name = "grass",
.image = "core/tile/grass",
});
registerItem({
.name = "tree-trunk",
.image = "core/tile/tree-trunk",
});

registerWorldGen<DefaultWorldGen>("default");

registerEntity<PlayerEntity>("player");
registerEntity<ItemStackEntity>("item-stack");
}

void onTileBreak(const Swan::Context &ctx, Swan::TilePos pos, Swan::Tile &tile) {
if (tile.dropped_item_) {
ctx.plane.spawnEntity(std::make_unique<ItemStackEntity>(
ctx, pos, *tile.dropped_item_));
}
});

mod.registerImage("tile/air");
mod.registerImage("tile/stone");
mod.registerImage("tile/dirt");
mod.registerImage("tile/grass");
mod.registerImage("tile/tree-trunk");
mod.registerImage("tile/leaves");
mod.registerImage("entity/player-running");
mod.registerImage("entity/player-still");
mod.registerImage("misc/background-cave");

mod.registerTile({
.name = "air",
.image = "core/tile/air",
.is_solid = false,
});
mod.registerTile({
.name = "stone",
.image = "core/tile/stone",
.dropped_item = "core::stone",
});
mod.registerTile({
.name = "dirt",
.image = "core/tile/dirt",
.dropped_item = "core::dirt",
});
mod.registerTile({
.name = "grass",
.image = "core/tile/grass",
.dropped_item = "core::dirt",
});
mod.registerTile({
.name = "tree-trunk",
.image = "core/tile/tree-trunk",
.dropped_item = "core::tree-trunk",
});
mod.registerTile({
.name = "leaves",
.image = "core/tile/leaves",
});

mod.registerItem({
.name = "stone",
.image = "core/tile/stone",
});
mod.registerItem({
.name = "dirt",
.image = "core/tile/dirt",
});
mod.registerItem({
.name = "grass",
.image = "core/tile/grass",
});
mod.registerItem({
.name = "tree-trunk",
.image = "core/tile/tree-trunk",
});
}

mod.registerWorldGen<DefaultWorldGen>("default");
Swan::EventListener break_listener_;
};

mod.registerEntity<PlayerEntity>("player");
mod.registerEntity<ItemStackEntity>("item-stack");
extern "C" std::unique_ptr<Swan::Mod> mod_create(Swan::World &world) {
return std::make_unique<CoreMod>(world);
}

+ 2
- 1
libswan/include/swan/Game.h View File

@@ -3,6 +3,7 @@
#include <bitset>
#include <map>
#include <string>
#include <optional>
#include <SDL.h>

#include "common.h"
@@ -18,7 +19,7 @@ public:
win_(win),
mouse_pos_(0, 0) {}

std::unique_ptr<Mod> loadMod(const std::string &path, World &world);
std::optional<ModWrapper> loadMod(std::string path, World &world);
void createWorld(const std::string &worldgen, std::vector<std::string> mods);

void onKeyDown(SDL_Keysym sym) {

+ 24
- 18
libswan/include/swan/Mod.h View File

@@ -18,14 +18,8 @@ namespace Swan {

class Mod {
public:
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);
Mod(std::string name): name_(std::move(name)) {}
virtual ~Mod() = default;

void registerImage(const std::string &id);
void registerTile(Tile::Builder tile);
@@ -54,24 +48,36 @@ public:
});
}

Iter<std::unique_ptr<ImageResource>> buildImages(SDL_Renderer *renderer);
Iter<std::unique_ptr<Tile>> buildTiles(const ResourceManager &resources);
Iter<std::unique_ptr<Item>> buildItems(const ResourceManager &resources);
Iter<WorldGen::Factory> getWorldGens();
Iter<Entity::Factory> getEntities();

std::string name_ = "@uninitialized";

private:
const std::string name_;
std::vector<std::string> images_;
std::vector<Tile::Builder> tiles_;
std::vector<Item::Builder> items_;
std::vector<WorldGen::Factory> worldgens_;
std::vector<Entity::Factory> entities_;
};

class ModWrapper {
public:
ModWrapper(std::unique_ptr<Mod> 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<std::unique_ptr<ImageResource>> buildImages(SDL_Renderer *renderer);
Iter<std::unique_ptr<Tile>> buildTiles(const ResourceManager &resources);
Iter<std::unique_ptr<Item>> buildItems(const ResourceManager &resources);
Iter<WorldGen::Factory> getWorldGens();
Iter<Entity::Factory> getEntities();

std::unique_ptr<Mod> mod_;
std::string path_;
OS::Dynlib dynlib_;
bool inited_ = false;
};

}

+ 3
- 2
libswan/include/swan/World.h View File

@@ -24,7 +24,7 @@ class World {
public:
World(Game *game, unsigned long rand_seed);

void addMod(std::unique_ptr<Mod> mod);
void addMod(ModWrapper &&mod);
void setWorldGen(std::string gen);
void spawnPlayer();

@@ -46,7 +46,8 @@ public:
EventEmitter<const Context &, TilePos, Tile &>
evt_tile_break_;

std::vector<std::unique_ptr<Mod>> mods_;
// World owns all mods
std::vector<ModWrapper> mods_;

// World owns tiles and items, the mod just has Builder objects
std::vector<std::unique_ptr<Tile>> tiles_;

+ 6
- 4
libswan/include/swan/util.h View File

@@ -12,12 +12,14 @@ namespace Swan {

// Inherit from this class to make a class non-copyable
class NonCopyable {
protected:
NonCopyable() = default;
NonCopyable(NonCopyable &&) = default;

public:
NonCopyable(const NonCopyable &) = delete;
NonCopyable &operator=(const NonCopyable &) = delete;
NonCopyable(NonCopyable &&) noexcept = default;

protected:
NonCopyable() = default;
~NonCopyable() = default;
};

// Take a deleter function, turn it into a class with an operator() for unique_ptr

+ 11
- 9
libswan/src/Game.cc View File

@@ -11,24 +11,26 @@

namespace Swan {

std::unique_ptr<Mod> Game::loadMod(const std::string &path, World &world) {
std::optional<ModWrapper> Game::loadMod(std::string path, World &world) {
OS::Dynlib dl(path + "/mod");
auto init = dl.get<void (*)(Mod &, World &)>("mod_init");
if (init == NULL) {
warn << path << ": No 'mod_init' function!";
return nullptr;
auto create = dl.get<std::unique_ptr<Mod> (*)(World &)>("mod_create");
if (create == NULL) {
warn << path << ": No 'mod_create' function!";
return std::nullopt;
}

std::unique_ptr<Mod> mod = std::make_unique<Mod>(path, std::move(dl));
init(*mod, world);
return mod;
std::unique_ptr<Mod> mod = create(world);
return std::make_optional<ModWrapper>(
std::move(mod), std::move(path), std::move(dl));
}

void Game::createWorld(const std::string &worldgen, std::vector<std::string> modpaths) {
world_.reset(new World(this, time(NULL)));

for (auto &modpath: modpaths) {
world_->addMod(std::move(loadMod(modpath, *world_)));
auto mod = loadMod(modpath, *world_);
if (mod)
world_->addMod(std::move(*mod));
}

world_->setWorldGen(worldgen);

+ 15
- 25
libswan/src/Mod.cc View File

@@ -8,21 +8,6 @@

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;

info << "Mod initing: " << name_;
}

void Mod::registerImage(const std::string &id) {
images_.push_back(name_ + "/" + id);
info << " Adding image: " << images_.back();
@@ -40,32 +25,37 @@ void Mod::registerItem(Item::Builder item) {
info << " Adding item: " << item.name;
}

Iter<std::unique_ptr<ImageResource>> Mod::buildImages(SDL_Renderer *renderer) {
return map(begin(images_), end(images_), [renderer, this](const std::string &id) {
Iter<std::unique_ptr<ImageResource>> ModWrapper::buildImages(SDL_Renderer *renderer) {
return map(begin(mod_->images_), end(mod_->images_),
[renderer, this](const std::string &id) {
return std::make_unique<ImageResource>(renderer, path_, id);
});
}

Iter<std::unique_ptr<Tile>> Mod::buildTiles(const ResourceManager &resources) {
return map(begin(tiles_), end(tiles_), [&](const Tile::Builder &builder) {
Iter<std::unique_ptr<Tile>> ModWrapper::buildTiles(const ResourceManager &resources) {
return map(begin(mod_->tiles_), end(mod_->tiles_),
[&](const Tile::Builder &builder) {
return std::make_unique<Tile>(resources, builder);
});
}

Iter<std::unique_ptr<Item>> Mod::buildItems(const ResourceManager &resources) {
return map(begin(items_), end(items_), [&](const Item::Builder &builder) {
Iter<std::unique_ptr<Item>> ModWrapper::buildItems(const ResourceManager &resources) {
return map(begin(mod_->items_), end(mod_->items_),
[&](const Item::Builder &builder) {
return std::make_unique<Item>(resources, builder);
});
}

Iter<WorldGen::Factory> Mod::getWorldGens() {
return map(begin(worldgens_), end(worldgens_), [](WorldGen::Factory &fact) {
Iter<WorldGen::Factory> ModWrapper::getWorldGens() {
return map(begin(mod_->worldgens_), end(mod_->worldgens_),
[](WorldGen::Factory &fact) {
return fact;
});
}

Iter<Entity::Factory> Mod::getEntities() {
return map(begin(entities_), end(entities_), [](Entity::Factory &fact){
Iter<Entity::Factory> ModWrapper::getEntities() {
return map(begin(mod_->entities_), end(mod_->entities_),
[](Entity::Factory &fact){
return fact;
});
}

+ 7
- 7
libswan/src/World.cc View File

@@ -42,31 +42,31 @@ void World::ChunkRenderer::tick(WorldPlane &plane, ChunkPos abspos) {
}
}

void World::addMod(std::unique_ptr<Mod> mod) {
info << "World: adding mod " << mod->name_;
void World::addMod(ModWrapper &&mod) {
info << "World: adding mod " << mod.mod_->name_;

for (auto i: mod->buildImages(game_->win_.renderer_)) {
for (auto i: mod.buildImages(game_->win_.renderer_)) {
resources_.addImage(std::move(i));
}

for (auto t: mod->buildTiles(resources_)) {
for (auto t: mod.buildTiles(resources_)) {
Tile::ID id = tiles_.size();
tiles_map_[t->name_] = id;
tiles_.push_back(std::move(t));
}

for (auto i: mod->buildItems(resources_)) {
for (auto i: mod.buildItems(resources_)) {
items_[i->name_] = std::move(i);
}

for (auto gen: mod->getWorldGens()) {
for (auto gen: mod.getWorldGens()) {
worldgens_.emplace(
std::piecewise_construct,
std::forward_as_tuple(gen.name),
std::forward_as_tuple(gen));
}

for (auto ent: mod->getEntities()) {
for (auto ent: mod.getEntities()) {
ents_.emplace(
std::piecewise_construct,
std::forward_as_tuple(ent.name),

Loading…
Cancel
Save