fix world converter
This commit is contained in:
parent
8f1eae4330
commit
0ad588fd33
@ -46,10 +46,14 @@ static void process_blocks_data(
|
|||||||
report.dataLoss.push_back(name + ": discard data");
|
report.dataLoss.push_back(name + ": discard data");
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
auto incapatibility = layout.checkCompatibility(*def->dataStruct);
|
if (layout != *def->dataStruct) {
|
||||||
if (!incapatibility.empty()) {
|
|
||||||
ContentIssue issue {ContentIssueType::BLOCK_DATA_LAYOUTS_UPDATE};
|
ContentIssue issue {ContentIssueType::BLOCK_DATA_LAYOUTS_UPDATE};
|
||||||
report.issues.push_back(issue);
|
report.issues.push_back(issue);
|
||||||
|
report.dataLayoutsUpdated = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto incapatibility = layout.checkCompatibility(*def->dataStruct);
|
||||||
|
if (!incapatibility.empty()) {
|
||||||
for (const auto& error : incapatibility) {
|
for (const auto& error : incapatibility) {
|
||||||
report.dataLoss.push_back(
|
report.dataLoss.push_back(
|
||||||
"[" + name + "] field " + error.name + " - " +
|
"[" + name + "] field " + error.name + " - " +
|
||||||
@ -57,9 +61,6 @@ static void process_blocks_data(
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (layout != *def->dataStruct) {
|
|
||||||
report.dataLayoutsUpdated = true;
|
|
||||||
}
|
|
||||||
report.blocksDataLayouts[name] = std::move(layout);
|
report.blocksDataLayouts[name] = std::move(layout);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -100,22 +100,7 @@ void WorldConverter::createConvertTasks() {
|
|||||||
tasks.push(ConvertTask {ConvertTaskType::PLAYER, wfile->getPlayerFile()});
|
tasks.push(ConvertTask {ConvertTaskType::PLAYER, wfile->getPlayerFile()});
|
||||||
}
|
}
|
||||||
|
|
||||||
WorldConverter::WorldConverter(
|
void WorldConverter::createBlockFieldsConvertTasks() {
|
||||||
const std::shared_ptr<WorldFiles>& worldFiles,
|
|
||||||
const Content* content,
|
|
||||||
std::shared_ptr<ContentReport> reportPtr,
|
|
||||||
bool upgradeMode
|
|
||||||
)
|
|
||||||
: wfile(worldFiles),
|
|
||||||
report(std::move(reportPtr)),
|
|
||||||
content(content),
|
|
||||||
upgradeMode(upgradeMode)
|
|
||||||
{
|
|
||||||
if (upgradeMode) {
|
|
||||||
createUpgradeTasks();
|
|
||||||
} else if (report->hasContentReorder()) {
|
|
||||||
createConvertTasks();
|
|
||||||
} else {
|
|
||||||
// blocks data conversion requires correct block indices
|
// blocks data conversion requires correct block indices
|
||||||
// so it must be done AFTER voxels conversion
|
// so it must be done AFTER voxels conversion
|
||||||
const auto& regions = wfile->getRegions();
|
const auto& regions = wfile->getRegions();
|
||||||
@ -132,6 +117,29 @@ WorldConverter::WorldConverter(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
WorldConverter::WorldConverter(
|
||||||
|
const std::shared_ptr<WorldFiles>& worldFiles,
|
||||||
|
const Content* content,
|
||||||
|
std::shared_ptr<ContentReport> reportPtr,
|
||||||
|
ConvertMode mode
|
||||||
|
)
|
||||||
|
: wfile(worldFiles),
|
||||||
|
report(std::move(reportPtr)),
|
||||||
|
content(content),
|
||||||
|
mode(mode)
|
||||||
|
{
|
||||||
|
switch (mode) {
|
||||||
|
case ConvertMode::UPGRADE:
|
||||||
|
createUpgradeTasks();
|
||||||
|
break;
|
||||||
|
case ConvertMode::REINDEX:
|
||||||
|
createConvertTasks();
|
||||||
|
break;
|
||||||
|
case ConvertMode::BLOCK_FIELDS:
|
||||||
|
createBlockFieldsConvertTasks();
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
WorldConverter::~WorldConverter() {
|
WorldConverter::~WorldConverter() {
|
||||||
@ -142,11 +150,11 @@ std::shared_ptr<Task> WorldConverter::startTask(
|
|||||||
const Content* content,
|
const Content* content,
|
||||||
const std::shared_ptr<ContentReport>& report,
|
const std::shared_ptr<ContentReport>& report,
|
||||||
const runnable& onDone,
|
const runnable& onDone,
|
||||||
bool upgradeMode,
|
ConvertMode mode,
|
||||||
bool multithreading
|
bool multithreading
|
||||||
) {
|
) {
|
||||||
auto converter = std::make_shared<WorldConverter>(
|
auto converter = std::make_shared<WorldConverter>(
|
||||||
worldFiles, content, report, upgradeMode);
|
worldFiles, content, report, mode);
|
||||||
if (!multithreading) {
|
if (!multithreading) {
|
||||||
converter->setOnComplete([=]() {
|
converter->setOnComplete([=]() {
|
||||||
converter->write();
|
converter->write();
|
||||||
@ -208,14 +216,14 @@ void WorldConverter::convertPlayer(const fs::path& file) const {
|
|||||||
void WorldConverter::convertBlocksData(int x, int z, const ContentReport& report) const {
|
void WorldConverter::convertBlocksData(int x, int z, const ContentReport& report) const {
|
||||||
logger.info() << "converting blocks data";
|
logger.info() << "converting blocks data";
|
||||||
wfile->getRegions().processBlocksData(x, z,
|
wfile->getRegions().processBlocksData(x, z,
|
||||||
[=](BlocksMetadata& heap, std::unique_ptr<ubyte[]> voxelsData) {
|
[=](BlocksMetadata* heap, std::unique_ptr<ubyte[]> voxelsData) {
|
||||||
Chunk chunk(0, 0);
|
Chunk chunk(0, 0);
|
||||||
chunk.decode(voxelsData.get());
|
chunk.decode(voxelsData.get());
|
||||||
|
|
||||||
const auto& indices = content->getIndices()->blocks;
|
const auto& indices = content->getIndices()->blocks;
|
||||||
|
|
||||||
BlocksMetadata newHeap;
|
BlocksMetadata newHeap;
|
||||||
for (const auto& entry : heap) {
|
for (const auto& entry : *heap) {
|
||||||
size_t index = entry.index;
|
size_t index = entry.index;
|
||||||
const auto& def = indices.require(chunk.voxels[index].id);
|
const auto& def = indices.require(chunk.voxels[index].id);
|
||||||
const auto& newStruct = *def.dataStruct;
|
const auto& newStruct = *def.dataStruct;
|
||||||
@ -229,7 +237,7 @@ void WorldConverter::convertBlocksData(int x, int z, const ContentReport& report
|
|||||||
uint8_t* dst = newHeap.allocate(index, newStruct.size());
|
uint8_t* dst = newHeap.allocate(index, newStruct.size());
|
||||||
newStruct.convert(prevStruct, entry.data(), dst, true);
|
newStruct.convert(prevStruct, entry.data(), dst, true);
|
||||||
}
|
}
|
||||||
heap = std::move(newHeap);
|
*heap = std::move(newHeap);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -286,13 +294,22 @@ bool WorldConverter::isActive() const {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void WorldConverter::write() {
|
void WorldConverter::write() {
|
||||||
if (upgradeMode) {
|
logger.info() << "applying changes";
|
||||||
logger.info() << "refreshing version";
|
|
||||||
wfile->patchIndicesVersion("region-version", REGION_FORMAT_VERSION);
|
auto patch = dv::object();
|
||||||
} else {
|
switch (mode) {
|
||||||
logger.info() << "writing world";
|
case ConvertMode::UPGRADE:
|
||||||
wfile->write(nullptr, content);
|
patch["region-version"] = REGION_FORMAT_VERSION;
|
||||||
|
break;
|
||||||
|
case ConvertMode::REINDEX:
|
||||||
|
WorldFiles::createContentIndicesCache(content->getIndices(), patch);
|
||||||
|
break;
|
||||||
|
case ConvertMode::BLOCK_FIELDS:
|
||||||
|
WorldFiles::createBlockFieldsIndices(content->getIndices(), patch);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
wfile->patchIndicesFile(patch);
|
||||||
|
wfile->write(nullptr, nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
void WorldConverter::waitForEnd() {
|
void WorldConverter::waitForEnd() {
|
||||||
|
|||||||
@ -37,6 +37,12 @@ struct ConvertTask {
|
|||||||
RegionLayerIndex layer;
|
RegionLayerIndex layer;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
enum class ConvertMode {
|
||||||
|
UPGRADE,
|
||||||
|
REINDEX,
|
||||||
|
BLOCK_FIELDS,
|
||||||
|
};
|
||||||
|
|
||||||
class WorldConverter : public Task {
|
class WorldConverter : public Task {
|
||||||
std::shared_ptr<WorldFiles> wfile;
|
std::shared_ptr<WorldFiles> wfile;
|
||||||
std::shared_ptr<ContentReport> const report;
|
std::shared_ptr<ContentReport> const report;
|
||||||
@ -44,7 +50,7 @@ class WorldConverter : public Task {
|
|||||||
std::queue<ConvertTask> tasks;
|
std::queue<ConvertTask> tasks;
|
||||||
runnable onComplete;
|
runnable onComplete;
|
||||||
uint tasksDone = 0;
|
uint tasksDone = 0;
|
||||||
bool upgradeMode;
|
ConvertMode mode;
|
||||||
|
|
||||||
void upgradeRegion(
|
void upgradeRegion(
|
||||||
const fs::path& file, int x, int z, RegionLayerIndex layer) const;
|
const fs::path& file, int x, int z, RegionLayerIndex layer) const;
|
||||||
@ -60,12 +66,13 @@ class WorldConverter : public Task {
|
|||||||
|
|
||||||
void createUpgradeTasks();
|
void createUpgradeTasks();
|
||||||
void createConvertTasks();
|
void createConvertTasks();
|
||||||
|
void createBlockFieldsConvertTasks();
|
||||||
public:
|
public:
|
||||||
WorldConverter(
|
WorldConverter(
|
||||||
const std::shared_ptr<WorldFiles>& worldFiles,
|
const std::shared_ptr<WorldFiles>& worldFiles,
|
||||||
const Content* content,
|
const Content* content,
|
||||||
std::shared_ptr<ContentReport> report,
|
std::shared_ptr<ContentReport> report,
|
||||||
bool upgradeMode
|
ConvertMode mode
|
||||||
);
|
);
|
||||||
~WorldConverter();
|
~WorldConverter();
|
||||||
|
|
||||||
@ -86,7 +93,7 @@ public:
|
|||||||
const Content* content,
|
const Content* content,
|
||||||
const std::shared_ptr<ContentReport>& report,
|
const std::shared_ptr<ContentReport>& report,
|
||||||
const runnable& onDone,
|
const runnable& onDone,
|
||||||
bool upgradeMode,
|
ConvertMode mode,
|
||||||
bool multithreading
|
bool multithreading
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|||||||
@ -25,6 +25,7 @@
|
|||||||
#include "settings.hpp"
|
#include "settings.hpp"
|
||||||
#include "typedefs.hpp"
|
#include "typedefs.hpp"
|
||||||
#include "util/data_io.hpp"
|
#include "util/data_io.hpp"
|
||||||
|
#include "util/stringutil.hpp"
|
||||||
#include "voxels/Block.hpp"
|
#include "voxels/Block.hpp"
|
||||||
#include "voxels/Chunk.hpp"
|
#include "voxels/Chunk.hpp"
|
||||||
#include "voxels/voxel.hpp"
|
#include "voxels/voxel.hpp"
|
||||||
@ -111,13 +112,17 @@ static void write_indices(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void WorldFiles::writeIndices(const ContentIndices* indices) {
|
void WorldFiles::createContentIndicesCache(
|
||||||
dv::value root = dv::object();
|
const ContentIndices* indices, dv::value& root
|
||||||
root["region-version"] = REGION_FORMAT_VERSION;
|
) {
|
||||||
write_indices(indices->blocks, root.list("blocks"));
|
write_indices(indices->blocks, root.list("blocks"));
|
||||||
write_indices(indices->items, root.list("items"));
|
write_indices(indices->items, root.list("items"));
|
||||||
write_indices(indices->entities, root.list("entities"));
|
write_indices(indices->entities, root.list("entities"));
|
||||||
|
}
|
||||||
|
|
||||||
|
void WorldFiles::createBlockFieldsIndices(
|
||||||
|
const ContentIndices* indices, dv::value& root
|
||||||
|
) {
|
||||||
auto& structsMap = root.object("blocks-data");
|
auto& structsMap = root.object("blocks-data");
|
||||||
for (const auto* def : indices->blocks.getIterable()) {
|
for (const auto* def : indices->blocks.getIterable()) {
|
||||||
if (def->dataStruct == nullptr) {
|
if (def->dataStruct == nullptr) {
|
||||||
@ -125,6 +130,14 @@ void WorldFiles::writeIndices(const ContentIndices* indices) {
|
|||||||
}
|
}
|
||||||
structsMap[def->name] = def->dataStruct->serialize();
|
structsMap[def->name] = def->dataStruct->serialize();
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void WorldFiles::writeIndices(const ContentIndices* indices) {
|
||||||
|
dv::value root = dv::object();
|
||||||
|
root["region-version"] = REGION_FORMAT_VERSION;
|
||||||
|
|
||||||
|
createContentIndicesCache(indices, root);
|
||||||
|
createBlockFieldsIndices(indices, root);
|
||||||
|
|
||||||
files::write_json(getIndicesFile(), root);
|
files::write_json(getIndicesFile(), root);
|
||||||
}
|
}
|
||||||
@ -178,14 +191,17 @@ bool WorldFiles::readResourcesData(const Content* content) {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void WorldFiles::patchIndicesVersion(const std::string& field, uint version) {
|
void WorldFiles::patchIndicesFile(const dv::value& map) {
|
||||||
fs::path file = getIndicesFile();
|
fs::path file = getIndicesFile();
|
||||||
if (!fs::is_regular_file(file)) {
|
if (!fs::is_regular_file(file)) {
|
||||||
logger.error() << file.filename().u8string() << " does not exists";
|
logger.error() << file.filename().u8string() << " does not exists";
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
auto root = files::read_json(file);
|
auto root = files::read_json(file);
|
||||||
root[field] = version;
|
for (const auto& [key, value] : map.asObject()) {
|
||||||
|
logger.info() << "patching indices.json: update " << util::quote(key);
|
||||||
|
root[key] = value;
|
||||||
|
}
|
||||||
files::write_json(file, root, true);
|
files::write_json(file, root, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -51,7 +51,14 @@ public:
|
|||||||
std::optional<WorldInfo> readWorldInfo();
|
std::optional<WorldInfo> readWorldInfo();
|
||||||
bool readResourcesData(const Content* content);
|
bool readResourcesData(const Content* content);
|
||||||
|
|
||||||
void patchIndicesVersion(const std::string& field, uint version);
|
static void createContentIndicesCache(
|
||||||
|
const ContentIndices* indices, dv::value& root
|
||||||
|
);
|
||||||
|
static void createBlockFieldsIndices(
|
||||||
|
const ContentIndices* indices, dv::value& root
|
||||||
|
);
|
||||||
|
|
||||||
|
void patchIndicesFile(const dv::value& map);
|
||||||
|
|
||||||
/// @brief Write all unsaved data to world files
|
/// @brief Write all unsaved data to world files
|
||||||
/// @param world target world
|
/// @param world target world
|
||||||
|
|||||||
@ -318,7 +318,7 @@ void WorldRegions::processBlocksData(int x, int z, const BlockDataProc& func) {
|
|||||||
BlocksMetadata blocksData;
|
BlocksMetadata blocksData;
|
||||||
blocksData.deserialize(datData.get(), datLength);
|
blocksData.deserialize(datData.get(), datLength);
|
||||||
try {
|
try {
|
||||||
func(blocksData, std::move(voxData));
|
func(&blocksData, std::move(voxData));
|
||||||
} catch (const std::exception& err) {
|
} catch (const std::exception& err) {
|
||||||
logger.error() << "an error ocurred while processing blocks "
|
logger.error() << "an error ocurred while processing blocks "
|
||||||
"data in chunk (" << gx << ", " << gz << "): " << err.what();
|
"data in chunk (" << gx << ", " << gz << "): " << err.what();
|
||||||
|
|||||||
@ -67,7 +67,7 @@ struct regfile {
|
|||||||
using RegionsMap = std::unordered_map<glm::ivec2, std::unique_ptr<WorldRegion>>;
|
using RegionsMap = std::unordered_map<glm::ivec2, std::unique_ptr<WorldRegion>>;
|
||||||
using RegionProc = std::function<std::unique_ptr<ubyte[]>(std::unique_ptr<ubyte[]>,uint32_t*)>;
|
using RegionProc = std::function<std::unique_ptr<ubyte[]>(std::unique_ptr<ubyte[]>,uint32_t*)>;
|
||||||
using InventoryProc = std::function<void(Inventory*)>;
|
using InventoryProc = std::function<void(Inventory*)>;
|
||||||
using BlockDataProc = std::function<void(BlocksMetadata&, std::unique_ptr<ubyte[]>)>;
|
using BlockDataProc = std::function<void(BlocksMetadata*, std::unique_ptr<ubyte[]>)>;
|
||||||
|
|
||||||
/// @brief Region file pointer keeping inUse flag on until destroyed
|
/// @brief Region file pointer keeping inUse flag on until destroyed
|
||||||
class regfile_ptr {
|
class regfile_ptr {
|
||||||
|
|||||||
@ -49,6 +49,14 @@ std::shared_ptr<Task> create_converter(
|
|||||||
const std::shared_ptr<ContentReport>& report,
|
const std::shared_ptr<ContentReport>& report,
|
||||||
const runnable& postRunnable
|
const runnable& postRunnable
|
||||||
) {
|
) {
|
||||||
|
ConvertMode mode;
|
||||||
|
if (report->isUpgradeRequired()) {
|
||||||
|
mode = ConvertMode::UPGRADE;
|
||||||
|
} else if (report->hasContentReorder()) {
|
||||||
|
mode = ConvertMode::REINDEX;
|
||||||
|
} else {
|
||||||
|
mode = ConvertMode::BLOCK_FIELDS;
|
||||||
|
}
|
||||||
return WorldConverter::startTask(
|
return WorldConverter::startTask(
|
||||||
worldFiles,
|
worldFiles,
|
||||||
content,
|
content,
|
||||||
@ -59,7 +67,7 @@ std::shared_ptr<Task> create_converter(
|
|||||||
menu->setPage("main", false);
|
menu->setPage("main", false);
|
||||||
engine->getGUI()->postRunnable([=]() { postRunnable(); });
|
engine->getGUI()->postRunnable([=]() { postRunnable(); });
|
||||||
},
|
},
|
||||||
report->isUpgradeRequired(),
|
mode,
|
||||||
true
|
true
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@ -79,9 +87,9 @@ void show_convert_request(
|
|||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
std::wstring message = L"world.convert-request";
|
std::wstring message = L"world.convert-block-layouts";
|
||||||
if (report->hasUpdatedLayouts()) {
|
if (report->hasContentReorder()) {
|
||||||
message = L"world.convert-block-layouts";
|
message = L"world.convert-request";
|
||||||
}
|
}
|
||||||
if (report->isUpgradeRequired()) {
|
if (report->isUpgradeRequired()) {
|
||||||
message = L"world.upgrade-request";
|
message = L"world.upgrade-request";
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user