mirror of
https://github.com/zhenyan121/Cubed.git
synced 2026-08-08 17:57:02 +08:00
feat(gameplay): spawn creatures during chunk generation
Add creature spawning to chunk generation with a configurable SpawnConfig, including a default pig spawn. Spawning occurs in the final generation phase and registers entities through the server world's entity manager. Also destroy entities when their chunk is unloaded to prevent orphaned entities and expose the entity manager from ServerWorld.
This commit is contained in:
@@ -9,6 +9,7 @@
|
||||
#include "Cubed/gameplay/builders/river_builder.hpp"
|
||||
#include "Cubed/gameplay/builders/snowy_plain_builder.hpp"
|
||||
#include "Cubed/gameplay/cave_path.hpp"
|
||||
#include "Cubed/gameplay/creatures/spawn.hpp"
|
||||
#include "Cubed/gameplay/river.path.hpp"
|
||||
#include "Cubed/gameplay/server_chunk.hpp"
|
||||
#include "Cubed/gameplay/server_world.hpp"
|
||||
@@ -17,6 +18,8 @@
|
||||
#include "Cubed/tools/cubed_hash.hpp"
|
||||
#include "Cubed/tools/math_tools.hpp"
|
||||
#include "Cubed/tools/perlin_noise.hpp"
|
||||
|
||||
#include <algorithm>
|
||||
namespace Cubed {
|
||||
|
||||
namespace {
|
||||
@@ -805,6 +808,35 @@ void ChunkGenerator::generate_river() {
|
||||
}
|
||||
}
|
||||
|
||||
void ChunkGenerator::spawn_creature() {
|
||||
auto biome = m_chunk.biome();
|
||||
const auto& blocks = m_chunk.blocks();
|
||||
const auto& heightmap = m_chunk.heightmap();
|
||||
const auto& chunk_pos = m_chunk.chunk_pos();
|
||||
if (std::ranges::contains(SpawnDefaults::PIG.biomes, biome)) {
|
||||
|
||||
if (m_random.random_bool(SpawnDefaults::PIG.probability)) {
|
||||
int want =
|
||||
m_random.random_int(0, SpawnDefaults::PIG.max_spawn_count);
|
||||
for (int i = 0; i < want; ++i) {
|
||||
int x = m_random.random_int(0, CHUNK_SIZE - 1);
|
||||
int z = m_random.random_int(0, CHUNK_SIZE - 1);
|
||||
int y = static_cast<int>(heightmap[x][z]);
|
||||
glm::vec3 pos(x, y + 1, z);
|
||||
auto type = blocks[Chunk::index(pos)];
|
||||
if (type != 0) {
|
||||
continue;
|
||||
}
|
||||
auto [world_x, world_y, world_z] = Chunk::block_to_world(
|
||||
x, y + 1, z, chunk_pos.x, chunk_pos.z);
|
||||
m_chunk.world().entity_manager().add_entity(
|
||||
SpawnDefaults::PIG.name,
|
||||
glm::vec3{world_x, world_y, world_z});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ServerChunk& ChunkGenerator::chunk() { return m_chunk; }
|
||||
|
||||
Random& ChunkGenerator::random() { return m_random; }
|
||||
|
||||
@@ -141,6 +141,7 @@ void ServerChunk::gen_phase_five() {
|
||||
m_generator->generate_cave();
|
||||
|
||||
m_generator->generate_vegetation();
|
||||
m_generator->spawn_creature();
|
||||
m_generator = nullptr;
|
||||
}
|
||||
|
||||
|
||||
@@ -37,6 +37,8 @@ void ServerEntityManager::update() {
|
||||
for (auto e : view) {
|
||||
const auto& c = view.get<BaseServerCreature>(e);
|
||||
if (!m_world.get_chunk_ref_count(c.transform.position.value)) {
|
||||
const auto& entity = m_registry.get<Entity>(e);
|
||||
destory(entity.id);
|
||||
continue;
|
||||
}
|
||||
update_ai(e);
|
||||
@@ -102,9 +104,9 @@ void ServerEntityManager::handle_task() {
|
||||
}
|
||||
|
||||
void ServerEntityManager::add_entity(std::string_view name,
|
||||
const glm::vec3& pos) {
|
||||
const glm::vec3& world_pos) {
|
||||
m_tasks.emplace(Command::CREATE,
|
||||
EntityCreateElement{std::string(name), pos});
|
||||
EntityCreateElement{std::string(name), world_pos});
|
||||
}
|
||||
|
||||
void ServerEntityManager::destory(EntityID id) {
|
||||
|
||||
@@ -1114,5 +1114,5 @@ BlockType ServerWorld::get_block_tpye(const glm::ivec3& block_pos) const {
|
||||
}
|
||||
|
||||
int ServerWorld::get_per_tick_time() const { return m_per_tick_time; }
|
||||
|
||||
ServerEntityManager& ServerWorld::entity_manager() { return m_entity_manager; }
|
||||
} // namespace Cubed
|
||||
Reference in New Issue
Block a user