refactor ContentLoader.cpp (step 1)

This commit is contained in:
MihailRis 2025-04-10 22:04:35 +03:00
parent 8a21bd212c
commit e78661453b

View File

@ -590,171 +590,121 @@ void ContentLoader::loadBlockMaterial(
} }
} }
void ContentLoader::loadContent(const dv::value& root) { template <typename DefT>
static void load_defs(
const ContentPack& pack,
const dv::value& root,
const std::string& defsDir,
ContentUnitBuilder<DefT>& builder,
size_t& defCounter,
std::function<void(DefT&, const std::string&, const std::string&)> loader
) {
auto found = root.at(defsDir);
if (!found) {
return;
}
const auto& defsArr = *found;
std::vector<std::pair<std::string, std::string>> pendingDefs; std::vector<std::pair<std::string, std::string>> pendingDefs;
auto getJsonParent = [this](const std::string& prefix, const std::string& name) { auto getJsonParent = [&pack](const std::string& prefix, const std::string& name) {
auto configFile = pack->folder / (prefix + "/" + name + ".json"); auto configFile = pack.folder / (prefix + "/" + name + ".json");
std::string parent; std::string parent;
if (io::exists(configFile)) { if (io::exists(configFile)) {
auto root = io::read_json(configFile); auto root = io::read_json(configFile);
root.at("parent").get(parent); root.at("parent").get(parent);
} }
return parent; return parent;
}; };
auto processName = [this](const std::string& name) { auto processName = [&pack](const std::string& name) {
auto colon = name.find(':'); auto colon = name.find(':');
auto new_name = name; auto new_name = name;
std::string full = std::string full =
colon == std::string::npos ? pack->id + ":" + name : name; colon == std::string::npos ? pack.id + ":" + name : name;
if (colon != std::string::npos) new_name[colon] = '/'; if (colon != std::string::npos) new_name[colon] = '/';
return std::make_pair(full, new_name); return std::make_pair(full, new_name);
}; };
if (auto found = root.at("blocks")) { for (size_t i = 0; i < defsArr.size(); i++) {
const auto& blocksarr = *found; auto [full, name] = processName(defsArr[i].asString());
for (size_t i = 0; i < blocksarr.size(); i++) { auto parent = getJsonParent(defsDir, name);
auto [full, name] = processName(blocksarr[i].asString()); if (parent.empty() || builder.get(parent)) {
auto parent = getJsonParent("blocks", name); // No dependency or dependency already loaded/exists in another
if (parent.empty() || builder.blocks.get(parent)) { // content pack
// No dependency or dependency already loaded/exists in another bool created;
// content pack auto& def = builder.create(full, &created);
bool created; loader(def, full, name);
auto& def = builder.blocks.create(full, &created); defCounter += created;
loadBlock(def, full, name); } else {
stats->totalBlocks += created; // Dependency not loaded yet, add to pending content units
} else { pendingDefs.emplace_back(full, name);
// Dependency not loaded yet, add to pending items
pendingDefs.emplace_back(full, name);
}
}
// Resolve dependencies for pending items
bool progressMade = true;
while (!pendingDefs.empty() && progressMade) {
progressMade = false;
for (auto it = pendingDefs.begin(); it != pendingDefs.end();) {
auto parent = getJsonParent("blocks", it->second);
if (builder.blocks.get(parent)) {
// Dependency resolved or parent exists in another pack,
// load the item
bool created;
auto& def = builder.blocks.create(it->first, &created);
loadBlock(def, it->first, it->second);
stats->totalBlocks += created;
it = pendingDefs.erase(it); // Remove resolved item
progressMade = true;
} else {
++it;
}
}
}
if (!pendingDefs.empty()) {
// Handle circular dependencies or missing dependencies
// You can log an error or throw an exception here if necessary
throw std::runtime_error("Unresolved block dependencies detected.");
} }
} }
if (auto found = root.at("items")) { // Resolve dependencies for pending content units
const auto& itemsarr = *found; bool progressMade = true;
for (size_t i = 0; i < itemsarr.size(); i++) { while (!pendingDefs.empty() && progressMade) {
auto [full, name] = processName(itemsarr[i].asString()); progressMade = false;
auto parent = getJsonParent("items", name);
if (parent.empty() || builder.items.get(parent)) { for (auto it = pendingDefs.begin(); it != pendingDefs.end();) {
// No dependency or dependency already loaded/exists in another auto parent = getJsonParent(defsDir, it->second);
// content pack if (builder.get(parent)) {
// Dependency resolved or parent exists in another pack,
// load the content unit
bool created; bool created;
auto& def = builder.items.create(full, &created); auto& def = builder.create(it->first, &created);
loadItem(def, full, name); loader(def, it->first, it->second);
stats->totalItems += created; defCounter += created;
it = pendingDefs.erase(it); // Remove resolved content unit
progressMade = true;
} else { } else {
// Dependency not loaded yet, add to pending items ++it;
pendingDefs.emplace_back(full, name);
} }
} }
// Resolve dependencies for pending items
bool progressMade = true;
while (!pendingDefs.empty() && progressMade) {
progressMade = false;
for (auto it = pendingDefs.begin(); it != pendingDefs.end();) {
auto parent = getJsonParent("items", it->second);
if (builder.items.get(parent)) {
// Dependency resolved or parent exists in another pack,
// load the item
bool created;
auto& def = builder.items.create(it->first, &created);
loadItem(def, it->first, it->second);
stats->totalItems += created;
it = pendingDefs.erase(it); // Remove resolved item
progressMade = true;
} else {
++it;
}
}
}
if (!pendingDefs.empty()) {
// Handle circular dependencies or missing dependencies
// You can log an error or throw an exception here if necessary
throw std::runtime_error("Unresolved item dependencies detected.");
}
} }
if (auto found = root.at("entities")) { if (!pendingDefs.empty()) {
const auto& entitiesarr = *found; // Handle circular dependencies or missing dependencies
for (size_t i = 0; i < entitiesarr.size(); i++) { // You can log an error or throw an exception here if necessary
auto [full, name] = processName(entitiesarr[i].asString()); throw std::runtime_error(
auto parent = getJsonParent("entities", name); "Unresolved " + defsDir + " dependencies detected."
if (parent.empty() || builder.entities.get(parent)) { );
// No dependency or dependency already loaded/exists in another
// content pack
bool created;
auto& def = builder.entities.create(full, &created);
loadEntity(def, full, name);
stats->totalEntities += created;
} else {
// Dependency not loaded yet, add to pending items
pendingDefs.emplace_back(full, name);
}
}
// Resolve dependencies for pending items
bool progressMade = true;
while (!pendingDefs.empty() && progressMade) {
progressMade = false;
for (auto it = pendingDefs.begin(); it != pendingDefs.end();) {
auto parent = getJsonParent("entities", it->second);
if (builder.entities.get(parent)) {
// Dependency resolved or parent exists in another pack,
// load the item
bool created;
auto& def = builder.entities.create(it->first, &created);
loadEntity(def, it->first, it->second);
stats->totalEntities += created;
it = pendingDefs.erase(it); // Remove resolved item
progressMade = true;
} else {
++it;
}
}
}
if (!pendingDefs.empty()) {
// Handle circular dependencies or missing dependencies
// You can log an error or throw an exception here if necessary
throw std::runtime_error(
"Unresolved entities dependencies detected."
);
}
} }
} }
void ContentLoader::loadContent(const dv::value& root) {
load_defs<Block>(
*pack,
root,
"blocks",
builder.blocks,
stats->totalBlocks,
[this](auto& def, const auto& name, const auto& file) {
return loadBlock(def, name, file);
}
);
load_defs<ItemDef>(
*pack,
root,
"items",
builder.items,
stats->totalItems,
[this](auto& def, const auto& name, const auto& file) {
return loadItem(def, name, file);
}
);
load_defs<EntityDef>(
*pack,
root,
"entities",
builder.entities,
stats->totalEntities,
[this](auto& def, const auto& name, const auto& file) {
return loadEntity(def, name, file);
}
);
}
static inline void foreach_file( static inline void foreach_file(
const io::path& dir, std::function<void(const io::path&)> handler const io::path& dir, std::function<void(const io::path&)> handler
) { ) {