Restructure ZoneDefinitionWriting

This commit is contained in:
Jan 2021-03-08 17:28:24 +01:00
parent e6a91c0305
commit d96f813e73
18 changed files with 285 additions and 221 deletions

View File

@ -1,13 +1,21 @@
#pragma once
#include "GameLanguage.h"
#include <vector>
#include "GameLanguage.h"
class Zone;
class IGame
{
public:
virtual const std::string& GetName() = 0;
IGame() = default;
virtual ~IGame() = default;
IGame(const IGame& other) = default;
IGame(IGame&& other) noexcept = default;
IGame& operator=(const IGame& other) = default;
IGame& operator=(IGame&& other) noexcept = default;
virtual std::string GetFullName() = 0;
virtual std::string GetShortName() = 0;
virtual void AddZone(Zone* zone) = 0;
virtual void RemoveZone(Zone* zone) = 0;
virtual std::vector<Zone*> GetZones() = 0;

View File

@ -8,11 +8,14 @@ using namespace IW4;
GameIW4 g_GameIW4;
const std::string GameIW4::NAME = "IW4";
const std::string& GameIW4::GetName()
std::string GameIW4::GetFullName()
{
return NAME;
return "Call Of Duty: Modern Warfare 2";
}
std::string GameIW4::GetShortName()
{
return "IW4";
}
void GameIW4::AddZone(Zone* zone)

View File

@ -3,11 +3,11 @@
class GameIW4 : public IGame
{
static const std::string NAME;
std::vector<Zone*> m_zones;
public:
const std::string& GetName() override;
std::string GetFullName() override;
std::string GetShortName() override;
void AddZone(Zone* zone) override;
void RemoveZone(Zone* zone) override;
std::vector<Zone*> GetZones() override;

View File

@ -8,11 +8,14 @@ using namespace T6;
GameT6 g_GameT6;
const std::string GameT6::NAME = "T6";
const std::string& GameT6::GetName()
std::string GameT6::GetFullName()
{
return NAME;
return "Call Of Duty: Black Ops II";
}
std::string GameT6::GetShortName()
{
return "T6";
}
void GameT6::AddZone(Zone* zone)

View File

@ -3,11 +3,11 @@
class GameT6 : public IGame
{
static const std::string NAME;
std::vector<Zone*> m_zones;
public:
const std::string& GetName() override;
std::string GetFullName() override;
std::string GetShortName() override;
void AddZone(Zone* zone) override;
void RemoveZone(Zone* zone) override;
std::vector<Zone*> GetZones() override;

View File

@ -8,7 +8,7 @@ ContentPrinter::ContentPrinter(Zone* zone)
void ContentPrinter::PrintContent() const
{
const auto* pools = m_zone->m_pools.get();
printf("Zone '%s' (%s)\n", m_zone->m_name.c_str(), m_zone->m_game->GetName().c_str());
printf("Zone '%s' (%s)\n", m_zone->m_name.c_str(), m_zone->m_game->GetShortName().c_str());
puts("Content:");
for(const auto& asset : *pools)

View File

@ -1,29 +1,13 @@
#include "ZoneDefWriter.h"
const std::string AbstractZoneDefWriter::META_DATA_KEY_GAME = "game";
AbstractZoneDefWriter::AbstractZoneDefWriter(Zone* zone, std::ostream& stream)
: m_zone(zone),
m_stream(stream)
void AbstractZoneDefWriter::WriteZoneDef(std::ostream& stream, Zone* zone) const
{
}
ZoneDefinitionOutputStream out(stream);
void AbstractZoneDefWriter::EmptyLine() const
{
m_stream << "\n";
}
out.WriteComment(zone->m_game->GetFullName());
out.WriteMetaData(META_DATA_KEY_GAME, zone->m_game->GetShortName());
out.EmptyLine();
void AbstractZoneDefWriter::WriteComment(const std::string& comment) const
{
m_stream << "// " << comment << "\n";
}
void AbstractZoneDefWriter::WriteMetaData(const std::string& metaDataKey, const std::string& metaDataValue) const
{
m_stream << ">" << metaDataKey << "," << metaDataValue << "\n";
}
void AbstractZoneDefWriter::WriteEntry(const std::string& entryKey, const std::string& entryValue) const
{
m_stream << entryKey << "," << entryValue << "\n";
}
WriteMetaData(out, zone);
WriteContent(out, zone);
}

View File

@ -1,31 +1,30 @@
#pragma once
#include <ostream>
#include "Zone/Zone.h"
class AbstractZoneDefWriter
{
protected:
Zone* m_zone;
std::ostream& m_stream;
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;
AbstractZoneDefWriter(Zone* zone, std::ostream& stream);
public:
virtual void WriteZoneDef() = 0;
};
#include "Zone/Definition/ZoneDefinitionStream.h"
class IZoneDefWriter
{
public:
IZoneDefWriter() = default;
virtual ~IZoneDefWriter() = default;
IZoneDefWriter(const IZoneDefWriter& other) = default;
IZoneDefWriter(IZoneDefWriter&& other) noexcept = default;
IZoneDefWriter& operator=(const IZoneDefWriter& other) = default;
IZoneDefWriter& operator=(IZoneDefWriter&& other) noexcept = default;
virtual bool CanHandleZone(Zone* zone) const = 0;
virtual void WriteZoneDef(Zone* zone, std::ostream& stream) const = 0;
virtual void WriteZoneDef(std::ostream& stream, Zone* zone) const = 0;
};
class AbstractZoneDefWriter : public IZoneDefWriter
{
protected:
static constexpr const char* META_DATA_KEY_GAME = "game";
virtual void WriteMetaData(ZoneDefinitionOutputStream& stream, Zone* zone) const = 0;
virtual void WriteContent(ZoneDefinitionOutputStream& stream, Zone* zone) const = 0;
public:
void WriteZoneDef(std::ostream& stream, Zone* zone) const override;
};

View File

@ -1,70 +1,45 @@
#include "ZoneDefWriterIW4.h"
#include "Game/IW4/GameIW4.h"
#include "Game/IW4/CommonIW4.h"
#include "Game/IW4/GameAssetPoolIW4.h"
#include <sstream>
#include <iomanip>
#include <cassert>
#include "Game/IW4/GameIW4.h"
#include "Game/IW4/GameAssetPoolIW4.h"
using namespace IW4;
namespace IW4
{
class ZoneDefWriterInternal final : public AbstractZoneDefWriter
{
void WriteContent() const
{
const auto* pools = dynamic_cast<GameAssetPoolIW4*>(m_zone->m_pools.get());
assert(pools);
if (!pools)
return;
// Localized strings are all collected in one string file. So only add this to the zone file.
if (!pools->m_localize->m_asset_lookup.empty())
{
WriteEntry(pools->GetAssetTypeName(ASSET_TYPE_LOCALIZE_ENTRY), m_zone->m_name);
}
for (const auto& asset : *pools)
{
switch (asset->m_type)
{
case ASSET_TYPE_LOCALIZE_ENTRY:
break;
default:
WriteEntry(pools->GetAssetTypeName(asset->m_type), asset->m_name);
break;
}
}
}
public:
ZoneDefWriterInternal(Zone* zone, std::ostream& stream)
: AbstractZoneDefWriter(zone, stream)
{
}
void WriteZoneDef() override
{
WriteComment("Call Of Duty: Modern Warfare 2");
WriteMetaData(META_DATA_KEY_GAME, "iw4");
EmptyLine();
WriteContent();
}
};
}
bool ZoneDefWriter::CanHandleZone(Zone* zone) const
{
return zone->m_game == &g_GameIW4;
}
void ZoneDefWriter::WriteZoneDef(Zone* zone, std::ostream& stream) const
void ZoneDefWriter::WriteMetaData(ZoneDefinitionOutputStream& stream, Zone* zone) const
{
ZoneDefWriterInternal writer(zone, stream);
writer.WriteZoneDef();
}
void ZoneDefWriter::WriteContent(ZoneDefinitionOutputStream& stream, Zone* zone) const
{
const auto* pools = dynamic_cast<GameAssetPoolIW4*>(zone->m_pools.get());
assert(pools);
if (!pools)
return;
// Localized strings are all collected in one string file. So only add this to the zone file.
if (!pools->m_localize->m_asset_lookup.empty())
{
stream.WriteEntry(pools->GetAssetTypeName(ASSET_TYPE_LOCALIZE_ENTRY), zone->m_name);
}
for (const auto& asset : *pools)
{
switch (asset->m_type)
{
case ASSET_TYPE_LOCALIZE_ENTRY:
break;
default:
stream.WriteEntry(pools->GetAssetTypeName(asset->m_type), asset->m_name);
break;
}
}
}

View File

@ -4,10 +4,13 @@
namespace IW4
{
class ZoneDefWriter final : public IZoneDefWriter
class ZoneDefWriter final : public AbstractZoneDefWriter
{
protected:
void WriteMetaData(::ZoneDefinitionOutputStream& stream, ::Zone* zone) const override;
void WriteContent(::ZoneDefinitionOutputStream& stream, ::Zone* zone) const override;
public:
bool CanHandleZone(Zone* zone) const override;
void WriteZoneDef(Zone* zone, std::ostream& stream) const override;
};
}

View File

@ -11,104 +11,25 @@ using namespace T6;
namespace T6
{
class ZoneDefWriterInternal final : public AbstractZoneDefWriter
class KeyValuePairKnownKey
{
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);
}
void WriteContent() const
{
const auto* pools = dynamic_cast<GameAssetPoolT6*>(m_zone->m_pools.get());
assert(pools);
if (!pools)
return;
// Localized strings are all collected in one string file. So only add this to the zone file.
if (!pools->m_localize->m_asset_lookup.empty())
{
WriteEntry(pools->GetAssetTypeName(ASSET_TYPE_LOCALIZE_ENTRY), m_zone->m_name);
}
for (const auto& asset : *pools)
{
switch (asset->m_type)
{
case ASSET_TYPE_LOCALIZE_ENTRY:
case ASSET_TYPE_KEYVALUEPAIRS: // KeyValuePairs should be included as zone file metadata and not as content
break;
default:
WriteEntry(pools->GetAssetTypeName(asset->m_type), asset->m_name);
break;
}
}
}
public:
ZoneDefWriterInternal(Zone* zone, std::ostream& stream)
: AbstractZoneDefWriter(zone, stream)
std::string m_key;
int m_hash;
explicit KeyValuePairKnownKey(std::string key)
{
m_key = std::move(key);
m_hash = CommonT6::Com_HashKey(m_key.c_str(), 64);
}
};
void WriteZoneDef() override
{
WriteComment("Call Of Duty: Black Ops II");
WriteMetaData(META_DATA_KEY_GAME, "t6");
EmptyLine();
auto* assetPoolT6 = dynamic_cast<GameAssetPoolT6*>(m_zone->m_pools.get());
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();
}
const KeyValuePairKnownKey KEY_VALUE_PAIR_KNOWN_KEYS[]
{
KeyValuePairKnownKey("ipak_read"),
KeyValuePairKnownKey("ipak_write"),
KeyValuePairKnownKey("initial_xmodels"),
KeyValuePairKnownKey("initial_materials"),
};
}
@ -117,8 +38,66 @@ bool ZoneDefWriter::CanHandleZone(Zone* zone) const
return zone->m_game == &g_GameT6;
}
void ZoneDefWriter::WriteZoneDef(Zone* zone, std::ostream& stream) const
void ZoneDefWriter::WriteKeyValuePair(ZoneDefinitionOutputStream& stream, KeyValuePair* kvp)
{
ZoneDefWriterInternal writer(zone, stream);
writer.WriteZoneDef();
for (const auto& knownKey : KEY_VALUE_PAIR_KNOWN_KEYS)
{
if (knownKey.m_hash == kvp->keyHash)
{
stream.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;
stream.WriteMetaData(str.str(), kvp->value);
}
void ZoneDefWriter::WriteMetaData(ZoneDefinitionOutputStream& stream, Zone* zone) const
{
auto* assetPoolT6 = dynamic_cast<GameAssetPoolT6*>(zone->m_pools.get());
if (assetPoolT6 && !assetPoolT6->m_key_value_pairs->m_asset_lookup.empty())
{
for (const auto* kvpAsset : *assetPoolT6->m_key_value_pairs)
{
const auto* keyValuePairs = kvpAsset->Asset();
for (auto varIndex = 0; varIndex < keyValuePairs->numVariables; varIndex++)
{
WriteKeyValuePair(stream, &keyValuePairs->keyValuePairs[varIndex]);
}
}
stream.EmptyLine();
}
}
void ZoneDefWriter::WriteContent(ZoneDefinitionOutputStream& stream, Zone* zone) const
{
const auto* pools = dynamic_cast<GameAssetPoolT6*>(zone->m_pools.get());
assert(pools);
if (!pools)
return;
// Localized strings are all collected in one string file. So only add this to the zone file.
if (!pools->m_localize->m_asset_lookup.empty())
{
stream.WriteEntry(pools->GetAssetTypeName(ASSET_TYPE_LOCALIZE_ENTRY), zone->m_name);
}
for (const auto& asset : *pools)
{
switch (asset->m_type)
{
case ASSET_TYPE_LOCALIZE_ENTRY:
case ASSET_TYPE_KEYVALUEPAIRS: // KeyValuePairs should be included as zone file metadata and not as content
break;
default:
stream.WriteEntry(pools->GetAssetTypeName(asset->m_type), asset->m_name);
break;
}
}
}

View File

@ -1,13 +1,19 @@
#pragma once
#include "ContentLister/ZoneDefWriter.h"
#include "Game/T6/T6.h"
namespace T6
{
class ZoneDefWriter final : public IZoneDefWriter
class ZoneDefWriter final : public AbstractZoneDefWriter
{
static void WriteKeyValuePair(ZoneDefinitionOutputStream& stream, KeyValuePair* kvp);
protected:
void WriteMetaData(ZoneDefinitionOutputStream& stream, Zone* zone) const override;
void WriteContent(ZoneDefinitionOutputStream& stream, Zone* zone) const override;
public:
bool CanHandleZone(Zone* zone) const override;
void WriteZoneDef(Zone* zone, std::ostream& stream) const override;
};
}
}

View File

@ -168,7 +168,7 @@ class Unlinker::Impl
{
if (zoneDefWriter->CanHandleZone(zone))
{
zoneDefWriter->WriteZoneDef(zone, zoneDefinitionFile);
zoneDefWriter->WriteZoneDef(zoneDefinitionFile, zone);
result = true;
break;
}
@ -234,7 +234,7 @@ class Unlinker::Impl
return false;
auto gdt = std::make_unique<GdtOutputStream>(gdtStream);
gdt->BeginStream();
gdt->WriteVersion(GdtVersion(zone->m_game->GetName(), 1));
gdt->WriteVersion(GdtVersion(zone->m_game->GetShortName(), 1));
context.m_gdt = std::move(gdt);
}

View File

@ -24,4 +24,9 @@ public:
{
return static_cast<T*>(m_ptr);
}
const T* Asset() const
{
return static_cast<const T*>(const_cast<const void*>(m_ptr));
}
};

View File

@ -0,0 +1,13 @@
#include "ZoneDefinition.h"
ZoneDefinitionEntry::ZoneDefinitionEntry()
: m_is_reference(false)
{
}
ZoneDefinitionEntry::ZoneDefinitionEntry(std::string type, std::string name, bool isReference)
: m_asset_type(std::move(type)),
m_asset_name(std::move(name)),
m_is_reference(isReference)
{
}

View File

@ -0,0 +1,22 @@
#pragma once
#include <unordered_map>
#include <vector>
class ZoneDefinitionEntry
{
public:
std::string m_asset_type;
std::string m_asset_name;
bool m_is_reference;
ZoneDefinitionEntry();
ZoneDefinitionEntry(std::string type, std::string name, bool isReference);
};
class ZoneDefinition
{
public:
std::unordered_map<std::string, std::string> m_metadata;
std::vector<ZoneDefinitionEntry> m_assets;
};

View File

@ -0,0 +1,36 @@
#include "ZoneDefinitionStream.h"
ZoneDefinitionInputStream::ZoneDefinitionInputStream(std::istream& stream)
: m_stream(stream)
{
}
std::unique_ptr<ZoneDefinition> ZoneDefinitionInputStream::ReadDefinition()
{
return nullptr;
}
ZoneDefinitionOutputStream::ZoneDefinitionOutputStream(std::ostream& stream)
: m_stream(stream)
{
}
void ZoneDefinitionOutputStream::EmptyLine() const
{
m_stream << "\n";
}
void ZoneDefinitionOutputStream::WriteComment(const std::string& comment) const
{
m_stream << "// " << comment << "\n";
}
void ZoneDefinitionOutputStream::WriteMetaData(const std::string& metaDataKey, const std::string& metaDataValue) const
{
m_stream << ">" << metaDataKey << "," << metaDataValue << "\n";
}
void ZoneDefinitionOutputStream::WriteEntry(const std::string& entryKey, const std::string& entryValue) const
{
m_stream << entryKey << "," << entryValue << "\n";
}

View File

@ -0,0 +1,28 @@
#pragma once
#include <iostream>
#include <memory>
#include "ZoneDefinition.h"
class ZoneDefinitionInputStream
{
std::istream& m_stream;
public:
explicit ZoneDefinitionInputStream(std::istream& stream);
std::unique_ptr<ZoneDefinition> ReadDefinition();
};
class ZoneDefinitionOutputStream
{
std::ostream& m_stream;
public:
explicit ZoneDefinitionOutputStream(std::ostream& stream);
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;
};