update WorldConverter (WIP)
This commit is contained in:
+125
-38
@@ -12,43 +12,111 @@
|
||||
#include "objects/Player.hpp"
|
||||
#include "util/ThreadPool.hpp"
|
||||
#include "voxels/Chunk.hpp"
|
||||
#include "items/Inventory.hpp"
|
||||
#include "WorldFiles.hpp"
|
||||
|
||||
namespace fs = std::filesystem;
|
||||
|
||||
static debug::Logger logger("world-converter");
|
||||
|
||||
class ConverterWorker : public util::Worker<convert_task, int> {
|
||||
class ConverterWorker : public util::Worker<ConvertTask, int> {
|
||||
std::shared_ptr<WorldConverter> converter;
|
||||
public:
|
||||
ConverterWorker(std::shared_ptr<WorldConverter> converter)
|
||||
: converter(std::move(converter)) {
|
||||
}
|
||||
|
||||
int operator()(const std::shared_ptr<convert_task>& task) override {
|
||||
int operator()(const std::shared_ptr<ConvertTask>& task) override {
|
||||
converter->convert(*task);
|
||||
return 0;
|
||||
}
|
||||
};
|
||||
|
||||
void WorldConverter::addRegionsTasks(
|
||||
RegionLayerIndex layerid,
|
||||
ConvertTaskType taskType
|
||||
) {
|
||||
const auto& regions = wfile->getRegions();
|
||||
auto regionsFolder = regions.getRegionsFolder(layerid);
|
||||
if (!fs::is_directory(regionsFolder)) {
|
||||
return;
|
||||
}
|
||||
for (const auto& file : fs::directory_iterator(regionsFolder)) {
|
||||
int x, z;
|
||||
std::string name = file.path().stem().string();
|
||||
if (!WorldRegions::parseRegionFilename(name, x, z)) {
|
||||
logger.error() << "could not parse region name " << name;
|
||||
continue;
|
||||
}
|
||||
tasks.push(ConvertTask {taskType, file.path(), x, z});
|
||||
}
|
||||
}
|
||||
|
||||
void WorldConverter::createUpgradeTasks() {
|
||||
const auto& regions = wfile->getRegions();
|
||||
for (auto& issue : report->getIssues()) {
|
||||
if (issue.issueType != ContentIssueType::REGION_FORMAT_UPDATE) {
|
||||
continue;
|
||||
}
|
||||
if (issue.regionLayer == REGION_LAYER_VOXELS) {
|
||||
addRegionsTasks(issue.regionLayer, ConvertTaskType::UPGRADE_VOXELS);
|
||||
} else {
|
||||
addRegionsTasks(issue.regionLayer, ConvertTaskType::UPGRADE_SIMPLE);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void WorldConverter::createConvertTasks() {
|
||||
auto handleReorder = [=](ContentType contentType) {
|
||||
switch (contentType) {
|
||||
case ContentType::BLOCK:
|
||||
addRegionsTasks(
|
||||
REGION_LAYER_VOXELS,
|
||||
ConvertTaskType::VOXELS
|
||||
);
|
||||
break;
|
||||
case ContentType::ITEM:
|
||||
addRegionsTasks(
|
||||
REGION_LAYER_INVENTORIES,
|
||||
ConvertTaskType::INVENTORIES
|
||||
);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
};
|
||||
|
||||
const auto& regions = wfile->getRegions();
|
||||
for (auto& issue : report->getIssues()) {
|
||||
switch (issue.issueType) {
|
||||
case ContentIssueType::REGION_FORMAT_UPDATE:
|
||||
break;
|
||||
case ContentIssueType::MISSING:
|
||||
throw std::runtime_error("issue can't be resolved");
|
||||
case ContentIssueType::REORDER:
|
||||
handleReorder(issue.contentType);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
tasks.push(ConvertTask {ConvertTaskType::PLAYER, wfile->getPlayerFile()});
|
||||
}
|
||||
|
||||
WorldConverter::WorldConverter(
|
||||
const std::shared_ptr<WorldFiles>& worldFiles,
|
||||
const Content* content,
|
||||
std::shared_ptr<ContentReport> report
|
||||
std::shared_ptr<ContentReport> reportPtr,
|
||||
bool upgradeMode
|
||||
)
|
||||
: wfile(worldFiles),
|
||||
report(std::move(report)),
|
||||
content(content) {
|
||||
fs::path regionsFolder =
|
||||
wfile->getRegions().getRegionsFolder(REGION_LAYER_VOXELS);
|
||||
if (!fs::is_directory(regionsFolder)) {
|
||||
logger.error() << "nothing to convert";
|
||||
return;
|
||||
}
|
||||
tasks.push(convert_task {convert_task_type::player, wfile->getPlayerFile()}
|
||||
);
|
||||
for (const auto& file : fs::directory_iterator(regionsFolder)) {
|
||||
tasks.push(convert_task {convert_task_type::region, file.path()});
|
||||
report(std::move(reportPtr)),
|
||||
content(content),
|
||||
upgradeMode(upgradeMode)
|
||||
{
|
||||
if (upgradeMode) {
|
||||
createUpgradeTasks();
|
||||
} else {
|
||||
createConvertTasks();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -60,9 +128,11 @@ std::shared_ptr<Task> WorldConverter::startTask(
|
||||
const Content* content,
|
||||
const std::shared_ptr<ContentReport>& report,
|
||||
const runnable& onDone,
|
||||
bool upgradeMode,
|
||||
bool multithreading
|
||||
) {
|
||||
auto converter = std::make_shared<WorldConverter>(worldFiles, content, report);
|
||||
auto converter = std::make_shared<WorldConverter>(
|
||||
worldFiles, content, report, upgradeMode);
|
||||
if (!multithreading) {
|
||||
converter->setOnComplete([=]() {
|
||||
converter->write();
|
||||
@@ -70,15 +140,15 @@ std::shared_ptr<Task> WorldConverter::startTask(
|
||||
});
|
||||
return converter;
|
||||
}
|
||||
auto pool = std::make_shared<util::ThreadPool<convert_task, int>>(
|
||||
auto pool = std::make_shared<util::ThreadPool<ConvertTask, int>>(
|
||||
"converter-pool",
|
||||
[=]() { return std::make_shared<ConverterWorker>(converter); },
|
||||
[=](int&) {}
|
||||
);
|
||||
auto& converterTasks = converter->tasks;
|
||||
while (!converterTasks.empty()) {
|
||||
const convert_task& task = converterTasks.front();
|
||||
auto ptr = std::make_shared<convert_task>(task);
|
||||
const ConvertTask& task = converterTasks.front();
|
||||
auto ptr = std::make_shared<ConvertTask>(task);
|
||||
pool->enqueueJob(ptr);
|
||||
converterTasks.pop();
|
||||
}
|
||||
@@ -89,19 +159,27 @@ std::shared_ptr<Task> WorldConverter::startTask(
|
||||
return pool;
|
||||
}
|
||||
|
||||
void WorldConverter::convertRegion(const fs::path& file) const {
|
||||
int x, z;
|
||||
std::string name = file.stem().string();
|
||||
if (!WorldRegions::parseRegionFilename(name, x, z)) {
|
||||
logger.error() << "could not parse name " << name;
|
||||
return;
|
||||
}
|
||||
logger.info() << "converting region " << name;
|
||||
wfile->getRegions().processRegionVoxels(x, z, [=](ubyte* data) {
|
||||
if (report) {
|
||||
Chunk::convert(data, report.get());
|
||||
}
|
||||
return true;
|
||||
void WorldConverter::upgradeSimple(const fs::path& file, int x, int z) const {
|
||||
throw std::runtime_error("unsupported region format");
|
||||
}
|
||||
|
||||
void WorldConverter::upgradeVoxels(const fs::path& file, int x, int z) const {
|
||||
throw std::runtime_error("unsupported region format");
|
||||
}
|
||||
|
||||
void WorldConverter::convertVoxels(const fs::path& file, int x, int z) const {
|
||||
logger.info() << "converting voxels region " << x << "_" << z;
|
||||
wfile->getRegions().processRegion(x, z, REGION_LAYER_VOXELS, CHUNK_DATA_LEN,
|
||||
[=](std::unique_ptr<ubyte[]> data, uint32_t*) {
|
||||
Chunk::convert(data.get(), report.get());
|
||||
return data;
|
||||
});
|
||||
}
|
||||
|
||||
void WorldConverter::convertInventories(const fs::path& file, int x, int z) const {
|
||||
logger.info() << "converting inventories region " << x << "_" << z;
|
||||
wfile->getRegions().processInventories(x, z, [=](Inventory* inventory) {
|
||||
inventory->convert(report.get());
|
||||
});
|
||||
}
|
||||
|
||||
@@ -112,14 +190,23 @@ void WorldConverter::convertPlayer(const fs::path& file) const {
|
||||
files::write_json(file, map.get());
|
||||
}
|
||||
|
||||
void WorldConverter::convert(const convert_task& task) const {
|
||||
void WorldConverter::convert(const ConvertTask& task) const {
|
||||
if (!fs::is_regular_file(task.file)) return;
|
||||
|
||||
switch (task.type) {
|
||||
case convert_task_type::region:
|
||||
convertRegion(task.file);
|
||||
case ConvertTaskType::UPGRADE_SIMPLE:
|
||||
upgradeSimple(task.file, task.x, task.z);
|
||||
break;
|
||||
case convert_task_type::player:
|
||||
case ConvertTaskType::UPGRADE_VOXELS:
|
||||
upgradeVoxels(task.file, task.x, task.z);
|
||||
break;
|
||||
case ConvertTaskType::VOXELS:
|
||||
convertVoxels(task.file, task.x, task.z);
|
||||
break;
|
||||
case ConvertTaskType::INVENTORIES:
|
||||
convertInventories(task.file, task.x, task.z);
|
||||
break;
|
||||
case ConvertTaskType::PLAYER:
|
||||
convertPlayer(task.file);
|
||||
break;
|
||||
}
|
||||
@@ -129,7 +216,7 @@ void WorldConverter::convertNext() {
|
||||
if (tasks.empty()) {
|
||||
throw std::runtime_error("no more regions to convert");
|
||||
}
|
||||
convert_task task = tasks.front();
|
||||
ConvertTask task = tasks.front();
|
||||
tasks.pop();
|
||||
tasksDone++;
|
||||
|
||||
@@ -157,7 +244,7 @@ bool WorldConverter::isActive() const {
|
||||
|
||||
void WorldConverter::write() {
|
||||
logger.info() << "writing world";
|
||||
wfile->write(nullptr, content);
|
||||
wfile->write(nullptr, upgradeMode ? nullptr : content);
|
||||
}
|
||||
|
||||
void WorldConverter::waitForEnd() {
|
||||
|
||||
Reference in New Issue
Block a user