#include "WorldGenerator.h" #include #include #include #include "Dimension.h" #include "Game.h" #include "JsonUtils.h" #include "NoiseInterpolator.h" using namespace Framework; using namespace Framework::JSON; using namespace Framework::JSON::Validator; WorldGenerator::WorldGenerator(int seed) : Thread(), exit(0), seed(seed) { setName("World Generator"); Framework::Logging::info() << "loading world generator configs. Changes at the config files " "may lead to a sudden change in landscape."; JSONValidator* configValidator = JSONValidator::buildForArray() ->removeInvalidEntries() ->addAcceptedTypeInArray(Game::INSTANCE->zTypeRegistry() ->getValidator()) ->finishArray(); loadAllJsonsFromDirectory("data/generator", [this, configValidator, seed]( Framework::JSON::JSONValue* zValue, Framework::Text path) { Framework::Logging::info() << "loading dimension configs from '" << path << "'"; Framework::RCArray invalidParts; JSONValue* valid = configValidator->getValidParts(zValue, &invalidParts); for (JSONValidationResult* invalidPart : invalidParts) { Framework::Logging::error() << invalidPart->getInvalidInfo(); } if (valid) { for (JSONValue* config : *valid->asArray()) { DimensionGenerator* generator = Game::INSTANCE->zTypeRegistry() ->fromJson(config); generator->initialize(seed); dimensionGenerators.add(generator); } valid->release(); } }); configValidator->release(); start(); } WorldGenerator::~WorldGenerator() {} Dimension* WorldGenerator::createDimension(int dimensionId) { for (DimensionGenerator* generator : dimensionGenerators) { if (generator->getDimensionId() == dimensionId) return generator->createDimension(); } Framework::Logging::error() << "no dimension generator found for dimension " << dimensionId; return 0; } DimensionGenerator* WorldGenerator::zGenerator(int dimensionId) { for (DimensionGenerator* generator : dimensionGenerators) { if (generator->getDimensionId() == dimensionId) return generator; } return 0; } void WorldGenerator::thread() { while (!exit) { cs.lock(); Area next; bool hasNext = 0; if (requestQueue.getEintragAnzahl() > 0) { next = requestQueue.get(0); requestQueue.remove(0); hasNext = 1; } cs.unlock(); if (!hasNext) { Sleep(1000); continue; } Punkt start = Game::INSTANCE->getChunkCenter(next.startX, next.startY); Punkt end = Game::INSTANCE->getChunkCenter(next.endX, next.endY); int xDir = start.x > end.x ? -1 : 1; int yDir = start.y > end.y ? -1 : 1; for (int x = start.x; xDir < 0 ? x >= end.x : x <= end.x; x += CHUNK_SIZE * xDir) { for (int y = start.y; yDir < 0 ? y >= end.y : y <= end.y; y += CHUNK_SIZE * yDir) { if (!Game::INSTANCE->doesChunkExist(x, y, next.dimensionId)) { Chunk* generatedChunk = zGenerator(next.dimensionId)->generateChunk(x, y); ZeitMesser zm; zm.messungStart(); generatedChunk->initializeLightning(); zm.messungEnde(); Framework::Logging::trace() << "light calculation: " << zm.getSekunden(); zm.messungStart(); generatedChunk->removeUnusedBlocks(); zm.messungEnde(); Framework::Logging::trace() << "unused block removal: " << zm.getSekunden(); zm.messungStart(); Dimension* dim = Game::INSTANCE->zDimension(next.dimensionId); if (!dim) { dim = new Dimension(next.dimensionId); Game::INSTANCE->addDimension(dim); } dim->setChunk(generatedChunk, Punkt(x, y)); zm.messungEnde(); Framework::Logging::trace() << "adding chunk to map: " << zm.getSekunden(); } } } } Framework::Logging::info() << "World Generator thread exited"; } void WorldGenerator::requestGeneration(Area request) { cs.lock(); requestQueue.add(request); cs.unlock(); } void WorldGenerator::exitAndWait() { exit = 1; warteAufThread(10000); ende(); } Framework::Either WorldGenerator::generateSingleBlock( Framework::Vec3 location, int dimensionId) { return zGenerator(dimensionId)->generateBlock(location); } bool WorldGenerator::spawnStructure(Framework::Vec3 location, int dimensionId, std::function filter) { return zGenerator(dimensionId)->spawnStructure(location, filter); }