[ZoneBuilder] Add support for empty assets

This commit is contained in:
momo5502 2017-01-13 15:44:46 +01:00
parent d7f16bdec1
commit b8aa24b19d
8 changed files with 77 additions and 8 deletions

View File

@ -274,7 +274,7 @@ namespace Components
} }
} }
Game::XAssetHeader AssetHandler::FindAssetForZone(Game::XAssetType type, std::string filename, ZoneBuilder::Zone* builder) Game::XAssetHeader AssetHandler::FindAssetForZone(Game::XAssetType type, std::string filename, ZoneBuilder::Zone* builder, bool isSubAsset)
{ {
Game::XAssetHeader header = { 0 }; Game::XAssetHeader header = { 0 };
if (type >= Game::XAssetType::ASSET_TYPE_COUNT) return header; if (type >= Game::XAssetType::ASSET_TYPE_COUNT) return header;
@ -296,6 +296,11 @@ namespace Components
} }
} }
if (!header.data && isSubAsset)
{
header = ZoneBuilder::GetEmptyAssetIfCommon(type, filename, builder);
}
if (!header.data) if (!header.data)
{ {
header = Game::DB_FindXAssetHeader(type, filename.data()); header = Game::DB_FindXAssetHeader(type, filename.data());

View File

@ -34,7 +34,7 @@ namespace Components
static void ZoneMark(Game::XAsset asset, ZoneBuilder::Zone* builder); static void ZoneMark(Game::XAsset asset, ZoneBuilder::Zone* builder);
static Game::XAssetHeader FindOriginalAsset(Game::XAssetType type, const char* filename); static Game::XAssetHeader FindOriginalAsset(Game::XAssetType type, const char* filename);
static Game::XAssetHeader FindAssetForZone(Game::XAssetType type, std::string filename, ZoneBuilder::Zone* builder); static Game::XAssetHeader FindAssetForZone(Game::XAssetType type, std::string filename, ZoneBuilder::Zone* builder, bool isSubAsset = true);
static void ClearTemporaryAssets(); static void ClearTemporaryAssets();
static void StoreTemporaryAsset(Game::XAssetType type, Game::XAssetHeader asset); static void StoreTemporaryAsset(Game::XAssetType type, Game::XAssetHeader asset);

View File

@ -125,7 +125,10 @@ namespace Assets
Game::DB_EnumXAssets_Internal(Game::XAssetType::ASSET_TYPE_MATERIAL, [](Game::XAssetHeader header, void* data) Game::DB_EnumXAssets_Internal(Game::XAssetType::ASSET_TYPE_MATERIAL, [](Game::XAssetHeader header, void* data)
{ {
Game::Material* material = reinterpret_cast<Game::Material*>(data); Game::Material* material = reinterpret_cast<Game::Material*>(data);
if (std::string(material->techniqueSet->name) == header.material->techniqueSet->name) const char* name = material->techniqueSet->name;
if (name[0] == ',') ++name;
if (std::string(name) == header.material->techniqueSet->name)
{ {
material->sortKey = header.material->sortKey; material->sortKey = header.material->sortKey;

View File

@ -129,8 +129,8 @@ namespace Components
int Materials::MaterialComparePrint(Game::Material* m1, Game::Material* m2) int Materials::MaterialComparePrint(Game::Material* m1, Game::Material* m2)
{ {
static Game::Material* a = m1; static Game::Material* a,* b;
static Game::Material* b = m2; a = m1, b = m2;
return Utils::Hook::Call<int(Game::Material*, Game::Material*)>(0x5235B0)(m1, m2); return Utils::Hook::Call<int(Game::Material*, Game::Material*)>(0x5235B0)(m1, m2);
} }

View File

@ -7,6 +7,8 @@ namespace Components
std::string ZoneBuilder::TraceZone; std::string ZoneBuilder::TraceZone;
std::vector<std::pair<Game::XAssetType, std::string>> ZoneBuilder::TraceAssets; std::vector<std::pair<Game::XAssetType, std::string>> ZoneBuilder::TraceAssets;
std::vector<std::pair<Game::XAssetType, std::string>> ZoneBuilder::CommonAssets;
ZoneBuilder::Zone::Zone(std::string name) : dataMap("zone_source/" + name + ".csv"), zoneName(name), indexStart(0), externalSize(0), branding { 0 }, ZoneBuilder::Zone::Zone(std::string name) : dataMap("zone_source/" + name + ".csv"), zoneName(name), indexStart(0), externalSize(0), branding { 0 },
// Reserve 100MB by default. // Reserve 100MB by default.
@ -172,7 +174,11 @@ namespace Components
bool ZoneBuilder::Zone::loadAsset(Game::XAssetType type, void* data, bool isSubAsset) bool ZoneBuilder::Zone::loadAsset(Game::XAssetType type, void* data, bool isSubAsset)
{ {
Game::XAsset asset{ type, { data } }; Game::XAsset asset{ type, { data } };
return this->loadAsset(type, Game::DB_GetXAssetName(&asset), isSubAsset);
const char* name = Game::DB_GetXAssetName(&asset);
if (name) return this->loadAsset(type, std::string(name), isSubAsset);
else return false;
} }
bool ZoneBuilder::Zone::loadAsset(Game::XAssetType type, std::string name, bool isSubAsset) bool ZoneBuilder::Zone::loadAsset(Game::XAssetType type, std::string name, bool isSubAsset)
@ -184,6 +190,9 @@ namespace Components
{ {
Game::XAssetType type = Game::DB_GetXAssetNameType(typeName.data()); Game::XAssetType type = Game::DB_GetXAssetNameType(typeName.data());
// Sanitize name for empty assets
if (name[0] == ',') name.erase(name.begin());
if (this->findAsset(type, name) != -1 || this->findSubAsset(type, name).data) return true; if (this->findAsset(type, name) != -1 || this->findSubAsset(type, name).data) return true;
if (type == Game::XAssetType::ASSET_TYPE_INVALID || type >= Game::XAssetType::ASSET_TYPE_COUNT) if (type == Game::XAssetType::ASSET_TYPE_INVALID || type >= Game::XAssetType::ASSET_TYPE_COUNT)
@ -192,7 +201,7 @@ namespace Components
return false; return false;
} }
Game::XAssetHeader assetHeader = AssetHandler::FindAssetForZone(type, name, this); Game::XAssetHeader assetHeader = AssetHandler::FindAssetForZone(type, name, this, isSubAsset);
if (!assetHeader.data) if (!assetHeader.data)
{ {
Logger::Error("Error: Missing asset '%s' of type '%s'\n", name.data(), Game::DB_GetXAssetTypeName(type)); Logger::Error("Error: Missing asset '%s' of type '%s'\n", name.data(), Game::DB_GetXAssetTypeName(type));
@ -220,6 +229,8 @@ namespace Components
int ZoneBuilder::Zone::findAsset(Game::XAssetType type, std::string name) int ZoneBuilder::Zone::findAsset(Game::XAssetType type, std::string name)
{ {
if (name[0] == ',') name.erase(name.begin());
for (unsigned int i = 0; i < this->loadedAssets.size(); ++i) for (unsigned int i = 0; i < this->loadedAssets.size(); ++i)
{ {
Game::XAsset* asset = &this->loadedAssets[i]; Game::XAsset* asset = &this->loadedAssets[i];
@ -227,6 +238,7 @@ namespace Components
if (asset->type != type) continue; if (asset->type != type) continue;
const char* assetName = Game::DB_GetXAssetName(asset); const char* assetName = Game::DB_GetXAssetName(asset);
if (assetName[0] == ',') ++assetName;
if (name == assetName) if (name == assetName)
{ {
@ -239,6 +251,8 @@ namespace Components
Game::XAssetHeader ZoneBuilder::Zone::findSubAsset(Game::XAssetType type, std::string name) Game::XAssetHeader ZoneBuilder::Zone::findSubAsset(Game::XAssetType type, std::string name)
{ {
if (name[0] == ',') name.erase(name.begin());
for (unsigned int i = 0; i < this->loadedSubAssets.size(); ++i) for (unsigned int i = 0; i < this->loadedSubAssets.size(); ++i)
{ {
Game::XAsset* asset = &this->loadedSubAssets[i]; Game::XAsset* asset = &this->loadedSubAssets[i];
@ -246,6 +260,7 @@ namespace Components
if (asset->type != type) continue; if (asset->type != type) continue;
const char* assetName = Game::DB_GetXAssetName(asset); const char* assetName = Game::DB_GetXAssetName(asset);
if (assetName[0] == ',') ++assetName;
if (name == assetName) if (name == assetName)
{ {
@ -298,7 +313,7 @@ namespace Components
asset.header = this->findSubAsset(type, name); asset.header = this->findSubAsset(type, name);
if (!asset.header.data) if (!asset.header.data)
{ {
Logger::Error("Missing required asset '%s' (%s). Export failed!", name, Game::DB_GetXAssetTypeName(type)); Logger::Error("Missing required asset '%s' (%s). Export failed!", name.data(), Game::DB_GetXAssetTypeName(type));
} }
#ifdef DEBUG #ifdef DEBUG
@ -635,6 +650,33 @@ namespace Components
return AssetTrace; return AssetTrace;
} }
Game::XAssetHeader ZoneBuilder::GetEmptyAssetIfCommon(Game::XAssetType type, std::string name, ZoneBuilder::Zone* builder)
{
Game::XAssetHeader header = { 0 };
if (type >= 0 && type < Game::XAssetType::ASSET_TYPE_COUNT)
{
for (auto& asset : ZoneBuilder::CommonAssets)
{
if (asset.first == type && asset.second == name)
{
// Allocate an empty asset (filled with zeros),
header.data = builder->getAllocator()->allocate(Game::DB_GetXAssetSizeHandlers[type]());
// Set the name to the original name, so it can be stored
Game::DB_SetXAssetNameHandlers[type](&header, name.data());
AssetHandler::StoreTemporaryAsset(type, header);
// Set the name to the empty name
Game::DB_SetXAssetNameHandlers[type](&header, builder->getAllocator()->duplicateString("," + name));
break;
}
}
}
return header;
}
int ZoneBuilder::StoreTexture(Game::GfxImageLoadDef **loadDef, Game::GfxImage *image) int ZoneBuilder::StoreTexture(Game::GfxImageLoadDef **loadDef, Game::GfxImage *image)
{ {
size_t size = 16 + (*loadDef)->resourceSize; size_t size = 16 + (*loadDef)->resourceSize;
@ -714,6 +756,12 @@ namespace Components
AssetHandler::OnLoad([](Game::XAssetType type, Game::XAssetHeader /*asset*/, std::string name, bool* /*restrict*/) AssetHandler::OnLoad([](Game::XAssetType type, Game::XAssetHeader /*asset*/, std::string name, bool* /*restrict*/)
{ {
// This is used to track which assets can be stored as empty assets
if (FastFiles::Current() == "common_mp")
{
ZoneBuilder::CommonAssets.push_back({ type, name });
}
if (!ZoneBuilder::TraceZone.empty() && ZoneBuilder::TraceZone == FastFiles::Current()) if (!ZoneBuilder::TraceZone.empty() && ZoneBuilder::TraceZone == FastFiles::Current())
{ {
ZoneBuilder::TraceAssets.push_back({ type, name }); ZoneBuilder::TraceAssets.push_back({ type, name });
@ -812,5 +860,6 @@ namespace Components
ZoneBuilder::~ZoneBuilder() ZoneBuilder::~ZoneBuilder()
{ {
assert(ZoneBuilder::MemAllocator.empty()); assert(ZoneBuilder::MemAllocator.empty());
ZoneBuilder::CommonAssets.clear();
} }
} }

View File

@ -100,9 +100,13 @@ namespace Components
static std::string TraceZone; static std::string TraceZone;
static std::vector<std::pair<Game::XAssetType, std::string>> TraceAssets; static std::vector<std::pair<Game::XAssetType, std::string>> TraceAssets;
static std::vector<std::pair<Game::XAssetType, std::string>> CommonAssets;
static void BeginAssetTrace(std::string zone); static void BeginAssetTrace(std::string zone);
static std::vector<std::pair<Game::XAssetType, std::string>> EndAssetTrace(); static std::vector<std::pair<Game::XAssetType, std::string>> EndAssetTrace();
static Game::XAssetHeader GetEmptyAssetIfCommon(Game::XAssetType type, std::string name, Zone* builder);
private: private:
static Utils::Memory::Allocator MemAllocator; static Utils::Memory::Allocator MemAllocator;
static int StoreTexture(Game::GfxImageLoadDef **loadDef, Game::GfxImage *image); static int StoreTexture(Game::GfxImageLoadDef **loadDef, Game::GfxImage *image);

View File

@ -57,6 +57,8 @@ namespace Game
DB_ReadXFile_t DB_ReadXFile = (DB_ReadXFile_t)0x445460; DB_ReadXFile_t DB_ReadXFile = (DB_ReadXFile_t)0x445460;
DB_ReadXFileUncompressed_t DB_ReadXFileUncompressed = (DB_ReadXFileUncompressed_t)0x4705E0; DB_ReadXFileUncompressed_t DB_ReadXFileUncompressed = (DB_ReadXFileUncompressed_t)0x4705E0;
DB_ReleaseXAssetHandler_t* DB_ReleaseXAssetHandlers = (DB_ReleaseXAssetHandler_t*)0x799AB8; DB_ReleaseXAssetHandler_t* DB_ReleaseXAssetHandlers = (DB_ReleaseXAssetHandler_t*)0x799AB8;
DB_SetXAssetName_t DB_SetXAssetName = (DB_SetXAssetName_t)0x453580;
DB_SetXAssetNameHandler_t* DB_SetXAssetNameHandlers = (DB_SetXAssetNameHandler_t*)0x7993D8;
DB_XModelSurfsFixup_t DB_XModelSurfsFixup = (DB_XModelSurfsFixup_t)0x5BAC50; DB_XModelSurfsFixup_t DB_XModelSurfsFixup = (DB_XModelSurfsFixup_t)0x5BAC50;
Dvar_RegisterBool_t Dvar_RegisterBool = (Dvar_RegisterBool_t)0x4CE1A0; Dvar_RegisterBool_t Dvar_RegisterBool = (Dvar_RegisterBool_t)0x4CE1A0;

View File

@ -138,6 +138,12 @@ namespace Game
typedef void(__cdecl * DB_ReleaseXAssetHandler_t)(XAssetHeader header); typedef void(__cdecl * DB_ReleaseXAssetHandler_t)(XAssetHeader header);
extern DB_ReleaseXAssetHandler_t* DB_ReleaseXAssetHandlers; extern DB_ReleaseXAssetHandler_t* DB_ReleaseXAssetHandlers;
typedef void(__cdecl * DB_SetXAssetName_t)(XAsset* asset, const char* name);
extern DB_SetXAssetName_t DB_SetXAssetName;
typedef void(__cdecl * DB_SetXAssetNameHandler_t)(XAssetHeader* header, const char* name);
extern DB_SetXAssetNameHandler_t* DB_SetXAssetNameHandlers;
typedef void(__cdecl * DB_XModelSurfsFixup_t)(XModel* model); typedef void(__cdecl * DB_XModelSurfsFixup_t)(XModel* model);
extern DB_XModelSurfsFixup_t DB_XModelSurfsFixup; extern DB_XModelSurfsFixup_t DB_XModelSurfsFixup;