mirror of
https://github.com/izzy2lost/Torch.git
synced 2026-07-06 00:18:35 -07:00
Added asset mods support
This commit is contained in:
+89
-3
@@ -18,6 +18,7 @@
|
||||
#include "factories/LightsFactory.h"
|
||||
#include "factories/mk64/WaypointFactory.h"
|
||||
#include "spdlog/spdlog.h"
|
||||
#include "hj/sha1.h"
|
||||
|
||||
#include <fstream>
|
||||
#include <iostream>
|
||||
@@ -79,7 +80,29 @@ void Companion::ExtractNode(YAML::Node& node, std::string& name, SWrapper* binar
|
||||
return;
|
||||
}
|
||||
|
||||
auto result = factory->get()->parse(this->gRomData, node);
|
||||
auto impl = factory->get();
|
||||
|
||||
std::optional<std::shared_ptr<IParsedData>> result;
|
||||
if(this->gConfig.modding) {
|
||||
if(impl->SupportModdedAssets() && this->gModdedAssetPaths.contains(name)) {
|
||||
|
||||
auto path = fs::path(this->gConfig.moddingPath) / this->gModdedAssetPaths[name];
|
||||
if(!fs::exists(path)) {
|
||||
SPDLOG_ERROR("Modded asset {} not found", this->gModdedAssetPaths[name]);
|
||||
return;
|
||||
}
|
||||
|
||||
std::ifstream input(path, std::ios::binary);
|
||||
std::vector<uint8_t> data = std::vector<uint8_t>( std::istreambuf_iterator( input ), {});
|
||||
input.close();
|
||||
|
||||
result = factory->get()->parse_modding(data, node);
|
||||
} else {
|
||||
result = factory->get()->parse(this->gRomData, node);
|
||||
}
|
||||
} else {
|
||||
result = factory->get()->parse(this->gRomData, node);
|
||||
}
|
||||
if(!result.has_value()){
|
||||
SPDLOG_ERROR("Failed to process {}", name);
|
||||
return;
|
||||
@@ -117,6 +140,29 @@ void Companion::ExtractNode(YAML::Node& node, std::string& name, SWrapper* binar
|
||||
binary->CreateFile(name, std::vector(data.begin(), data.end()));
|
||||
break;
|
||||
}
|
||||
case ExportType::Modding: {
|
||||
stream.str("");
|
||||
stream.clear();
|
||||
std::string ogname = name;
|
||||
exporter->get()->Export(stream, result.value(), name, node, &name);
|
||||
|
||||
auto data = stream.str();
|
||||
if(data.empty()) {
|
||||
break;
|
||||
}
|
||||
|
||||
std::string dpath = Instance->GetOutputPath() + "/" + name;
|
||||
if(!exists(fs::path(dpath).parent_path())){
|
||||
create_directories(fs::path(dpath).parent_path());
|
||||
}
|
||||
|
||||
this->gModdedAssetPaths[ogname] = name;
|
||||
|
||||
std::ofstream file(dpath, std::ios::binary);
|
||||
file.write(data.c_str(), data.size());
|
||||
file.close();
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
exporter->get()->Export(stream, result.value(), name, node, &name);
|
||||
|
||||
@@ -141,6 +187,20 @@ void Companion::ExtractNode(YAML::Node& node, std::string& name, SWrapper* binar
|
||||
}
|
||||
}
|
||||
|
||||
void Companion::ParseModdingConfig() {
|
||||
auto path = fs::path(this->gConfig.moddingPath) / "modding.yml";
|
||||
if(!fs::exists(path)) {
|
||||
throw std::runtime_error("No modding config found, please run in export mode first");
|
||||
}
|
||||
auto modding = YAML::LoadFile(path);
|
||||
for(auto assets = modding["assets"].begin(); assets != modding["assets"].end(); ++assets) {
|
||||
auto name = assets->first.as<std::string>();
|
||||
auto asset = assets->second.as<std::string>();
|
||||
this->gModdedAssetPaths[name] = asset;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void Companion::ParseCurrentFileConfig(YAML::Node node) {
|
||||
if(node["segments"]) {
|
||||
for(auto segment = node["segments"].begin(); segment != node["segments"].end(); ++segment) {
|
||||
@@ -214,7 +274,9 @@ void Companion::Process() {
|
||||
auto path = rom["path"].as<std::string>();
|
||||
auto opath = cfg["output"];
|
||||
auto gbi = cfg["gbi"];
|
||||
auto modding_path = opath && opath["modding"] ? opath["modding"].as<std::string>() : "modding";
|
||||
|
||||
this->gConfig.moddingPath = modding_path;
|
||||
switch (this->gConfig.exporterType) {
|
||||
case ExportType::Binary: {
|
||||
this->gConfig.outputPath = opath && opath["binary"] ? opath["binary"].as<std::string>() : "generic.otr";
|
||||
@@ -228,6 +290,10 @@ void Companion::Process() {
|
||||
this->gConfig.outputPath = opath && opath["code"] ? opath["code"].as<std::string>() : "code";
|
||||
break;
|
||||
}
|
||||
case ExportType::Modding: {
|
||||
this->gConfig.outputPath = modding_path;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if(gbi) {
|
||||
@@ -264,6 +330,10 @@ void Companion::Process() {
|
||||
};
|
||||
}
|
||||
|
||||
if(this->gConfig.exporterType == ExportType::Code && this->gConfig.modding) {
|
||||
this->ParseModdingConfig();
|
||||
}
|
||||
|
||||
if(std::holds_alternative<std::vector<std::string>>(this->gWriteOrder)) {
|
||||
for (auto& [key, _] : this->gFactories) {
|
||||
auto entries = std::get<std::vector<std::string>>(this->gWriteOrder);
|
||||
@@ -415,8 +485,20 @@ void Companion::Process() {
|
||||
spdlog::set_pattern(line);
|
||||
}
|
||||
|
||||
if(this->gConfig.exporterType != ExportType::Binary){
|
||||
auto fsout = fs::path(this->gConfig.outputPath);
|
||||
auto fsout = fs::path(this->gConfig.outputPath);
|
||||
|
||||
if(this->gConfig.exporterType == ExportType::Modding) {
|
||||
fsout /= "modding.yml";
|
||||
YAML::Node modding;
|
||||
|
||||
for (const auto& [key, value] : this->gModdedAssetPaths) {
|
||||
modding["assets"][key] = value;
|
||||
}
|
||||
|
||||
std::ofstream file(fsout.string(), std::ios::binary);
|
||||
file << modding;
|
||||
file.close();
|
||||
} else if(this->gConfig.exporterType != ExportType::Binary){
|
||||
std::string filename = this->gCurrentDirectory.filename().string();
|
||||
|
||||
switch (this->gConfig.exporterType) {
|
||||
@@ -627,4 +709,8 @@ std::optional<std::tuple<std::string, YAML::Node>> Companion::GetNodeByAddr(cons
|
||||
std::string Companion::NormalizeAsset(const std::string& name) const {
|
||||
auto path = fs::path(this->gCurrentFile).stem().string() + "_" + name;
|
||||
return path;
|
||||
}
|
||||
|
||||
std::string Companion::CalculateHash(const std::vector<uint8_t>& data) {
|
||||
return Chocobo1::SHA1().addData(data).finalize().toString();
|
||||
}
|
||||
Reference in New Issue
Block a user