Unlinker: Make zone files creators game dependent and in the unlinker project instead of the ObjWriting component

This commit is contained in:
Jan 2020-02-18 17:15:51 +01:00
parent 992e9cea30
commit 9572391082
18 changed files with 217 additions and 40 deletions

View File

@ -5,26 +5,10 @@
#include "ObjLoading.h"
#include "Image/Texture.h"
#include "Image/IwiLoader.h"
#include "Game/T6/CommonT6.h"
const int ObjLoaderT6::IPAK_READ_HASH = Com_HashKey("ipak_read", 64);
const int ObjLoaderT6::GLOBAL_HASH = Com_HashKey("GLOBAL", 64);
int ObjLoaderT6::Com_HashKey(const char* str, const int maxLen)
{
if (str == nullptr)
return 0;
int hash = 0;
for (int i = 0; i < maxLen; i++)
{
if (str[i] == '\0')
break;
hash += str[i] * (0x77 + i);
}
return hash ^ ((hash ^ (hash >> 10)) >> 10);
}
const int ObjLoaderT6::IPAK_READ_HASH = CommonT6::Com_HashKey("ipak_read", 64);
const int ObjLoaderT6::GLOBAL_HASH = CommonT6::Com_HashKey("GLOBAL", 64);
bool ObjLoaderT6::SupportsZone(Zone* zone) const
{
@ -122,7 +106,7 @@ void ObjLoaderT6::LoadCommonIPaks(ISearchPath* searchPath, Zone* zone)
void ObjLoaderT6::LoadReferencedContainersForZone(ISearchPath* searchPath, Zone* zone) const
{
auto* assetPoolT6 = dynamic_cast<GameAssetPoolT6*>(zone->GetPools());
const int zoneNameHash = Com_HashKey(zone->m_name.c_str(), 64);
const int zoneNameHash = CommonT6::Com_HashKey(zone->m_name.c_str(), 64);
LoadCommonIPaks(searchPath, zone);

View File

@ -8,7 +8,6 @@ class ObjLoaderT6 final : public IObjLoader
{
static const int IPAK_READ_HASH;
static const int GLOBAL_HASH;
static int Com_HashKey(const char* str, int maxLen);
static void LoadIPakForZone(ISearchPath* searchPath, const std::string& ipakName, Zone* zone);

View File

@ -1,7 +1,6 @@
#pragma once
#include "Zone/Zone.h"
#include "Utils/FileAPI.h"
class IZoneDumper
{
@ -10,5 +9,4 @@ public:
virtual bool CanHandleZone(Zone* zone) const = 0;
virtual bool DumpZone(Zone* zone, const std::string& basePath) const = 0;
virtual bool WriteZoneDefinition(Zone* zone, FileAPI::File* file) const = 0;
};

View File

@ -79,8 +79,3 @@ bool ZoneDumperT6::DumpZone(Zone* zone, const std::string& basePath) const
#undef DUMP_ASSET_POOL
}
bool ZoneDumperT6::WriteZoneDefinition(Zone* zone, FileAPI::File* file) const
{
return true;
}

View File

@ -6,5 +6,4 @@ class ZoneDumperT6 final : public IZoneDumper
public:
bool CanHandleZone(Zone* zone) const override;
bool DumpZone(Zone* zone, const std::string& basePath) const override;
bool WriteZoneDefinition(Zone* zone, FileAPI::File* file) const override;
};

View File

@ -27,8 +27,3 @@ bool ObjWriting::DumpZone(Zone* zone, const std::string& basePath)
return false;
}
bool ObjWriting::WriteZoneDefinition(Zone* zone, FileAPI::File* file)
{
return file->Printf("// %s", "Insert zone definition here") > 0;
}

View File

@ -1,7 +1,6 @@
#pragma once
#include "Zone/Zone.h"
#include "Utils/FileAPI.h"
#include <string>
class ObjWriting
@ -18,10 +17,8 @@ public:
bool Verbose = false;
ImageOutputFormat_e ImageOutputFormat = ImageOutputFormat_e::DDS;
bool MinimalZoneFileOutput = false;
} Configuration;
static bool DumpZone(Zone* zone, const std::string& basePath);
static bool WriteZoneDefinition(Zone* zone, FileAPI::File* file);
};

View File

@ -0,0 +1,39 @@
#include "ZoneDefWriter.h"
const std::string AbstractZoneDefWriter::META_DATA_KEY_GAME = "game";
AbstractZoneDefWriter::AbstractZoneDefWriter(Zone* zone, FileAPI::IFile* file)
{
m_zone = zone;
m_file = file;
}
void AbstractZoneDefWriter::EmptyLine() const
{
m_file->Printf("\n");
}
void AbstractZoneDefWriter::WriteComment(const std::string& comment) const
{
m_file->Printf("// %s\n", comment.c_str());
}
void AbstractZoneDefWriter::WriteMetaData(const std::string& metaDataKey, const std::string& metaDataValue) const
{
m_file->Printf(">%s,%s\n", metaDataKey.c_str(), metaDataValue.c_str());
}
void AbstractZoneDefWriter::WriteEntry(const std::string& entryKey, const std::string& entryValue) const
{
m_file->Printf("%s,%s\n", entryKey.c_str(), entryValue.c_str());
}
void AbstractZoneDefWriter::WriteContent() const
{
auto zoneContent = m_zone->GetPools()->GetContent();
for(const auto& asset : zoneContent.m_assets)
{
WriteEntry(asset.m_asset_type_name, asset.m_asset_name);
}
}

View File

@ -0,0 +1,30 @@
#pragma once
#include "Utils/FileAPI.h"
#include "Zone/Zone.h"
class AbstractZoneDefWriter
{
protected:
Zone* m_zone;
FileAPI::IFile* m_file;
static const std::string META_DATA_KEY_GAME;
void EmptyLine() const;
void WriteComment(const std::string& comment) const;
void WriteMetaData(const std::string& metaDataKey, const std::string& metaDataValue) const;
void WriteEntry(const std::string& entryKey, const std::string& entryValue) const;
void WriteContent() const;
AbstractZoneDefWriter(Zone* zone, FileAPI::IFile* file);
public:
virtual void WriteZoneDef() = 0;
};
class IZoneDefWriter
{
public:
virtual bool CanHandleZone(Zone* zone) const = 0;
virtual void WriteZoneDef(Zone* zone, FileAPI::IFile* file) const = 0;
};

View File

@ -0,0 +1,91 @@
#include "ZoneDefWriterT6.h"
#include "Game/T6/GameT6.h"
#include "Game/T6/CommonT6.h"
#include "Game/T6/GameAssetPoolT6.h"
#include <sstream>
#include <iomanip>
using namespace T6;
class ZoneDefWriterT6Impl final : public AbstractZoneDefWriter
{
class KnownKey
{
public:
std::string m_key;
int m_hash;
explicit KnownKey(std::string key)
{
m_key = std::move(key);
m_hash = CommonT6::Com_HashKey(m_key.c_str(), 64);
}
};
inline static const KnownKey KNOWN_KEYS[]
{
KnownKey("ipak_read"),
KnownKey("ipak_write"),
KnownKey("initial_xmodels"),
KnownKey("initial_materials"),
};
void WriteKeyValuePair(KeyValuePair* kvp) const
{
for (const auto& knownKey : KNOWN_KEYS)
{
if(knownKey.m_hash == kvp->keyHash)
{
WriteMetaData("level." + knownKey.m_key, kvp->value);
return;
}
}
std::ostringstream str;
str << "level.@" << std::setfill('0') << std::setw(sizeof(int) * 2) << std::hex << kvp->keyHash;
WriteMetaData(str.str(), kvp->value);
}
public:
ZoneDefWriterT6Impl(Zone* zone, FileAPI::IFile* file)
: AbstractZoneDefWriter(zone, file)
{
}
void WriteZoneDef() override
{
WriteComment("Call Of Duty: Black Ops II");
WriteMetaData(META_DATA_KEY_GAME, "t6");
EmptyLine();
auto* assetPoolT6 = dynamic_cast<GameAssetPoolT6*>(m_zone->GetPools());
if(assetPoolT6 && !assetPoolT6->m_key_value_pairs->m_asset_lookup.empty())
{
for (auto kvpAsset : *assetPoolT6->m_key_value_pairs)
{
KeyValuePairs* keyValuePairs = kvpAsset->Asset();
for(int varIndex = 0; varIndex < keyValuePairs->numVariables; varIndex++)
{
WriteKeyValuePair(&keyValuePairs->keyValuePairs[varIndex]);
}
}
EmptyLine();
}
WriteContent();
}
};
bool ZoneDefWriterT6::CanHandleZone(Zone* zone) const
{
return zone->m_game == &g_GameT6;
}
void ZoneDefWriterT6::WriteZoneDef(Zone* zone, FileAPI::IFile* file) const
{
ZoneDefWriterT6Impl writer(zone, file);
writer.WriteZoneDef();
}

View File

@ -0,0 +1,10 @@
#pragma once
#include "ContentLister/ZoneDefWriter.h"
class ZoneDefWriterT6 final : public IZoneDefWriter
{
public:
bool CanHandleZone(Zone* zone) const override;
void WriteZoneDef(Zone* zone, FileAPI::IFile* file) const override;
};

View File

@ -3,12 +3,14 @@
#include "Utils/Arguments/ArgumentParser.h"
#include "ZoneLoading.h"
#include "ObjWriting.h"
#include "ContentPrinter.h"
#include "ContentLister/ContentPrinter.h"
#include "Utils/PathUtils.h"
#include "Utils/FileAPI.h"
#include "ObjLoading.h"
#include "SearchPath/SearchPaths.h"
#include "SearchPath/SearchPathFilesystem.h"
#include "ContentLister/ZoneDefWriter.h"
#include "Game/T6/ZoneDefWriterT6.h"
#include <set>
#include <regex>
@ -16,6 +18,11 @@
#include "ObjContainer/IWD/IWD.h"
#include "UnlinkerArgs.h"
const IZoneDefWriter* const ZONE_DEF_WRITERS[]
{
new ZoneDefWriterT6()
};
class Unlinker::Impl
{
UnlinkerArgs m_args;
@ -158,7 +165,14 @@ class Unlinker::Impl
if (zoneDefinitionFile.IsOpen())
{
ObjWriting::WriteZoneDefinition(zone, &zoneDefinitionFile);
for (auto zoneDefWriter : ZONE_DEF_WRITERS)
{
if (zoneDefWriter->CanHandleZone(zone))
{
zoneDefWriter->WriteZoneDef(zone, &zoneDefinitionFile);
break;
}
}
ObjWriting::DumpZone(zone, outputFolderPath);
}
else

View File

@ -206,7 +206,7 @@ bool UnlinkerArgs::ParseArgs(const int argc, const char** argv)
SetVerbose(m_argument_parser.IsOptionSpecified(OPTION_VERBOSE));
// -min; --minimal-zone
ObjWriting::Configuration.MinimalZoneFileOutput = m_argument_parser.IsOptionSpecified(OPTION_MINIMAL_ZONE_FILE);
m_minimal_zone_def = m_argument_parser.IsOptionSpecified(OPTION_MINIMAL_ZONE_FILE);
// -l; --list
if (m_argument_parser.IsOptionSpecified(OPTION_LIST))

View File

@ -37,6 +37,7 @@ public:
ProcessingTask m_task;
std::string m_output_folder;
bool m_minimal_zone_def;
bool m_verbose;

View File

@ -0,0 +1,18 @@
#include "CommonT6.h"
int CommonT6::Com_HashKey(const char* str, const int maxLen)
{
if (str == nullptr)
return 0;
int hash = 0;
for (int i = 0; i < maxLen; i++)
{
if (str[i] == '\0')
break;
hash += str[i] * (0x77 + i);
}
return hash ^ ((hash ^ (hash >> 10)) >> 10);
}

View File

@ -0,0 +1,7 @@
#pragma once
class CommonT6
{
public:
static int Com_HashKey(const char* str, int maxLen);
};