#pragma once #include #include #include #include #include #include #include #include #include "common.h" #include "traits/BodyTrait.h" #include "util.h" #include "Chunk.h" #include "Tile.h" #include "WorldGen.h" #include "Entity.h" #include "Collection.h" #include "LightServer.h" namespace Swan { class World; class Game; class WorldPlane final: NonCopyable, public LightCallback { public: using ID = uint16_t; WorldPlane( ID id, World *world, std::unique_ptr gen, std::vector> &&colls); EntityRef spawnEntity(const std::string &name, const Entity::PackObject ¶ms); template EntityRef spawnEntity(Args&&... args); Context getContext(); bool hasChunk(ChunkPos pos); Chunk &getChunk(ChunkPos pos); Chunk &slowGetChunk(ChunkPos pos); void setTileID(TilePos pos, Tile::ID id); void setTile(TilePos pos, const std::string &name); template EntityCollection &getCollectionOf(); EntityCollection &getCollectionOf(std::string name); EntityCollection &getCollectionOf(std::type_index type); Tile::ID getTileID(TilePos pos); Tile &getTile(TilePos pos); Iter getEntsInArea(Vec2 center, float radius); template ItergetEntsOfType() { return Iter([] { return std::nullopt; }); /* TODO return mapFilter(entities_.begin(), entities_.end(), [](std::unique_ptr &ent) -> std::optional { if (T *e = dynamic_cast(ent.get()); e != nullptr) return e; return std::nullopt; }); */ } EntityRef spawnPlayer(); void breakTile(TilePos pos); Cygnet::Color backgroundColor(); void draw(Cygnet::Renderer &rnd); void update(float dt); void tick(float dt); void debugBox(TilePos pos); void addLight(TilePos pos, float level); void removeLight(TilePos pos, float level); // LightingCallback implementation void onLightChunkUpdated(const LightChunk &chunk, Vec2i pos) final; ID id_; World *world_; std::unique_ptr gen_; std::mutex mut_; private: std::map, Chunk> chunks_; std::vector activeChunks_; std::vector> tickChunks_; std::vector> entColls_; std::unordered_map entCollsByType_; std::unordered_map entCollsByName_; std::deque chunkInitList_; std::vector debugBoxes_; // The lighting server must destruct first. Until it has been destructed, // it might call onLightChunkUpdated. If that happens after some other // members have destructed, we have a problem. // TODO: Rewrite this to not use a callback-based interface. std::unique_ptr lighting_; }; /* * WorldPlane */ template inline EntityRef WorldPlane::spawnEntity(Args&&... args) { return getCollectionOf(typeid(Ent)).spawn(std::forward(args)...); } template inline EntityCollection &WorldPlane::getCollectionOf() { return *entCollsByType_.at(typeid(Ent)); } inline EntityCollection &WorldPlane::getCollectionOf(std::string name) { return *entCollsByName_.at(name); } inline EntityCollection &WorldPlane::getCollectionOf(std::type_index type) { return *entCollsByType_.at(type); } }