world初步

This commit is contained in:
EmsiaetKadosh
2025-03-23 13:23:10 +08:00
parent 037e532748
commit a335259edc
27 changed files with 982 additions and 313 deletions
+154 -13
View File
@@ -6,34 +6,175 @@
#include "..\..\def.h"
#include "..\entity\Entity.h"
#include "Block.h"
class World {
QWORD idEntity = 0;
class World;
class WorldManager;
class World : public IRenderable, public ITickable {
friend class WorldManager;
friend class Garbage<World>;
WorldID idWorld;
Map<QWORD, Entity*> entities;
Map<BlockLocation, Block*, BlockLocation::Less> blocks;
using IterEntity = Map<QWORD, Entity*>::const_iterator;
using IterBlock = Map<BlockLocation, Block*, BlockLocation::Less>::const_iterator;
public:
protected:
World() = default;
int addEntity(Entity* entity) {
~World() override {
Logger.debug(L"~World() called");
for (auto& [location, block] : blocks) {
block->onExitWorld(this, WorldTransportReason::Shutdown);
block->location.setWorld(0);
block->world = nullptr;
block->onRemove();
}
for (auto& [id, entity] : entities) {
entity->onExitWorld(this, WorldTransportReason::Shutdown);
entity->location.setWorld(0);
entity->world = nullptr;
// entity->onRemove() 交给EntityManager调用
}
}
public:
void render(const double tickDelta) const noexcept override {
for (const auto& [location, block] : blocks) block->render(tickDelta);
for (const auto& [id, entity] : entities) entity->render(tickDelta);
for (const auto& [location, block] : blocks) block->renderShadow();
}
virtual int addEntity(Entity* entity, const WorldTransportReason reason) {
if (!entity) Failed();
if (entity->id) Failed();
entities.emplace(++idEntity, entity);
if (!entity->idEntity) Failed();
if (entity->location.getWorld()) Failed();
if (entity->world) Failed();
if (!reason.isEntityReason()) Failed();
entity->onEnterWorld(this, reason);
entity->location.setWorld(idWorld);
entity->world = this;
entities.emplace(entity->idEntity, entity);
Success();
}
int removeEntity(Entity* entity) {
virtual int removeEntity(Entity* entity, const WorldTransportReason reason) {
if (!entity) Failed();
if (!entity->id) Failed();
const IterEntity iter = entities.find(entity->id);
if (iter != entities.end()) Failed();
entities.erase(iter);
entity->onRemove();
entity->id = 0;
if (!entity->idEntity) Failed();
if (!entities.erase(entity->idEntity)) Failed();
if (!reason.isEntityReason()) Failed();
entity->onExitWorld(this, reason);
entity->location.setWorld(0);
entity->world = nullptr;
Success();
}
virtual int addBlock(Block* block, const WorldTransportReason reason) {
if (!block) Failed();
if (block->getLocation().getWorld()) Failed();
if (block->world) Failed();
if (blocks.contains(block->getLocation())) Failed();
if (!reason.isBlockReason()) Failed();
blocks.emplace(block->getLocation(), block);
block->onEnterWorld(this, reason);
block->location.setWorld(idWorld);
block->world = this;
Success();
}
virtual int removeBlock(Block* block, const WorldTransportReason reason) {
if (!block) Failed();
if (block->getLocation().getWorld() != idWorld) Failed();
if (!blocks.erase(block->getLocation())) Failed();
if (!reason.isBlockReason()) Failed();
block->onExitWorld(this, reason);
block->location.setWorld(0);
block->world = nullptr;
Success();
}
virtual int removeBlockAt(const BlockLocation& location, const WorldTransportReason reason) {
if (!reason.isBlockReason()) Failed();
if (location.getWorld() != idWorld) Failed();
const IterBlock it = blocks.find(location);
if (it == blocks.cend()) Failed();
Block* block = it->second;
blocks.erase(it);
block->onExitWorld(this, reason);
block->location.setWorld(0);
block->world = nullptr;
Success();
}
virtual void onRemove() {
// Entity不需要再此处删除,交给EntityManager管理
for (auto& [id, entity] : entities) {
entity->onExitWorld(this, WorldTransportReason::WorldCollapse);
entity->location.setWorld(0);
entity->world = nullptr;
}
for (auto& [location, block] : blocks) {
block->onExitWorld(this, WorldTransportReason::WorldCollapse);
block->location.setWorld(0);
block->world = nullptr;
block->onRemove();
}
gc.submit<World>(this);
}
};
class WorldManager {
friend class Game;
WorldID nextID = 0;
Map<WorldID, World*> worlds;
World* current = nullptr;
WorldManager() = default;
~WorldManager() {
Logger.debug(L"~WorldManager() called");
for (auto& [id, world] : worlds) world->onRemove();
}
public:
int addWorld(World* world) {
if (!world) Failed();
if (world->idWorld) Failed();
world->idWorld = ++nextID;
worlds.emplace(world->idWorld, world);
Success();
}
int removeWorld(World* world) {
if (!world) Failed();
if (!world->idWorld) Failed();
world->idWorld = 0;
worlds.erase(world->idWorld);
world->onRemove();
Success();
}
int setWorld(World* world) {
if (!world) Failed();
if (world->idWorld) Failed();
current = world;
Success();
}
};
class StartWorld final : public World {
StartWorld() = default;
~StartWorld() override { Logger.debug(L"~StartWorld() called"); }
public:
void tick() noexcept override {}
static StartWorld* create() {
StartWorld* world = allocatedFor(new StartWorld);
world->addBlock(PureBarrierBlock::create(BlockLocation(0, 0)), WorldTransportReason::InitialGeneration);
world->addBlock(PureBarrierBlock::create(BlockLocation(1, 0)), WorldTransportReason::InitialGeneration);
world->addBlock(PureBarrierBlock::create(BlockLocation(2, 0)), WorldTransportReason::InitialGeneration);
world->addBlock(PureBarrierBlock::create(BlockLocation(3, 0)), WorldTransportReason::InitialGeneration);
world->addBlock(PureBarrierBlock::create(BlockLocation(4, 0)), WorldTransportReason::InitialGeneration);
return world;
}
};