feat: add ipak and iwd zone definition metadata to replace type

This commit is contained in:
Jan 2024-10-14 20:44:54 +02:00
parent 973ff73554
commit 2182196730
No known key found for this signature in database
GPG Key ID: 44B581F78FF5C57C
6 changed files with 176 additions and 52 deletions

View File

@ -157,10 +157,6 @@ class LinkerImpl final : public Linker
return nullptr; return nullptr;
} }
// If no type was defined explicitly make it fastfile
if (zoneDefinition->m_type == ProjectType::NONE)
zoneDefinition->m_type = ProjectType::FASTFILE;
if (!IncludeAdditionalZoneDefinitions(targetName, *zoneDefinition, sourceSearchPath)) if (!IncludeAdditionalZoneDefinitions(targetName, *zoneDefinition, sourceSearchPath))
return nullptr; return nullptr;
@ -338,29 +334,11 @@ class LinkerImpl final : public Linker
if (!zoneDefinition) if (!zoneDefinition)
return false; return false;
auto result = true; const auto& gameName = GameId_Names[static_cast<unsigned>(zoneDefinition->m_game)];
if (zoneDefinition->m_type != ProjectType::NONE) auto assetSearchPaths = m_search_paths.GetAssetSearchPathsForProject(gameName, projectName);
{ auto gdtSearchPaths = m_search_paths.GetGdtSearchPathsForProject(gameName, projectName);
const auto& gameName = GameId_Names[static_cast<unsigned>(zoneDefinition->m_game)];
auto assetSearchPaths = m_search_paths.GetAssetSearchPathsForProject(gameName, projectName);
auto gdtSearchPaths = m_search_paths.GetGdtSearchPathsForProject(gameName, projectName);
switch (zoneDefinition->m_type) auto result = BuildFastFile(projectName, targetName, *zoneDefinition, assetSearchPaths, gdtSearchPaths, sourceSearchPaths);
{
case ProjectType::FASTFILE:
result = BuildFastFile(projectName, targetName, *zoneDefinition, assetSearchPaths, gdtSearchPaths, sourceSearchPaths);
break;
case ProjectType::IPAK:
result = BuildIPak(projectName, *zoneDefinition, assetSearchPaths);
break;
default:
assert(false);
result = false;
break;
}
}
m_search_paths.UnloadProjectSpecificSearchPaths(); m_search_paths.UnloadProjectSpecificSearchPaths();

View File

@ -3,6 +3,7 @@
#include "Parsing/ZoneDefinition/Matcher/ZoneDefinitionMatcherFactory.h" #include "Parsing/ZoneDefinition/Matcher/ZoneDefinitionMatcherFactory.h"
#include "Utils/StringUtils.h" #include "Utils/StringUtils.h"
#include <cstdint>
#include <format> #include <format>
#include <optional> #include <optional>
@ -13,6 +14,9 @@ namespace
constexpr auto METADATA_NAME = "name"; constexpr auto METADATA_NAME = "name";
constexpr auto METADATA_TYPE = "type"; constexpr auto METADATA_TYPE = "type";
constexpr auto METADATA_IPAK = "ipak";
constexpr auto METADATA_IWD = "iwd";
std::optional<GameId> GetGameByName(const std::string& gameName) std::optional<GameId> GetGameByName(const std::string& gameName)
{ {
auto upperGameName = gameName; auto upperGameName = gameName;
@ -27,6 +31,21 @@ namespace
return std::nullopt; return std::nullopt;
} }
enum class ProjectType : std::uint8_t
{
NONE,
FASTFILE,
IPAK,
COUNT
};
constexpr const char* ProjectType_Names[]{
"none",
"fastfile",
"ipak",
};
static_assert(std::extent_v<decltype(ProjectType_Names)> == static_cast<unsigned>(ProjectType::COUNT));
std::optional<ProjectType> GetProjectTypeByName(const std::string& projectTypeName) std::optional<ProjectType> GetProjectTypeByName(const std::string& projectTypeName)
{ {
auto lowerProjectTypeName = projectTypeName; auto lowerProjectTypeName = projectTypeName;
@ -54,16 +73,9 @@ SequenceZoneDefinitionMetaData::SequenceZoneDefinitionMetaData()
}); });
} }
void SequenceZoneDefinitionMetaData::ProcessMatch(ZoneDefinitionParserState* state, SequenceResult<ZoneDefinitionParserValue>& result) const namespace
{ {
const auto& keyToken = result.NextCapture(CAPTURE_KEY); void ProcessMetaDataGame(ZoneDefinitionParserState* state, const ZoneDefinitionParserValue& valueToken, const std::string& value)
auto key = keyToken.FieldValue();
const auto& valueToken = result.NextCapture(CAPTURE_VALUE);
const auto& value = valueToken.FieldValue();
utils::MakeStringLowerCase(key);
if (key == METADATA_GAME)
{ {
const auto game = GetGameByName(value); const auto game = GetGameByName(value);
if (!game) if (!game)
@ -75,6 +87,52 @@ void SequenceZoneDefinitionMetaData::ProcessMatch(ZoneDefinitionParserState* sta
state->SetGame(*game); state->SetGame(*game);
} }
void ProcessMetaDataType(ZoneDefinitionParserState* state, const ZoneDefinitionParserValue& keyToken, const ZoneDefinitionParserValue& valueToken)
{
const auto projectType = GetProjectTypeByName(valueToken.FieldValue());
if (!projectType)
throw ParsingException(valueToken.GetPos(), "Unknown project type name");
// TODO: Remove deprecated type
std::string deprecationSuggestedAction;
if (*projectType == ProjectType::IPAK)
{
deprecationSuggestedAction = "Use \">ipak,name_of_ipak\" instead.";
state->StartIPak(state->m_definition->m_name);
}
else if (*projectType == ProjectType::FASTFILE)
{
deprecationSuggestedAction = "A fastfile will always be built when appropriate assets have been added.";
}
else
{
deprecationSuggestedAction = "It now has no effect.";
}
const auto keyPos = keyToken.GetPos();
std::cerr << std::format("Warning: {} L{}: Zone definition \">type,{}\" is deprecated and should be removed. {}\n",
keyPos.m_filename.get(),
keyPos.m_line,
keyToken.FieldValue(),
deprecationSuggestedAction);
}
} // namespace
void SequenceZoneDefinitionMetaData::ProcessMatch(ZoneDefinitionParserState* state, SequenceResult<ZoneDefinitionParserValue>& result) const
{
const auto& keyToken = result.NextCapture(CAPTURE_KEY);
auto key = keyToken.FieldValue();
const auto& valueToken = result.NextCapture(CAPTURE_VALUE);
const auto& value = valueToken.FieldValue();
utils::MakeStringLowerCase(key);
if (key == METADATA_GAME)
{
ProcessMetaDataGame(state, valueToken, value);
}
else if (key == METADATA_GDT) else if (key == METADATA_GDT)
{ {
state->m_definition->m_gdts.emplace_back(value); state->m_definition->m_gdts.emplace_back(value);
@ -85,9 +143,21 @@ void SequenceZoneDefinitionMetaData::ProcessMatch(ZoneDefinitionParserState* sta
} }
else if (key == METADATA_TYPE) else if (key == METADATA_TYPE)
{ {
const auto projectType = GetProjectTypeByName(value); ProcessMetaDataType(state, keyToken, valueToken);
if (!projectType) }
throw ParsingException(valueToken.GetPos(), "Unknown project type name"); else if (key == METADATA_IPAK)
{
if (!value.empty())
state->StartIPak(value);
else
throw ParsingException(valueToken.GetPos(), "IPak must have a name");
}
else if (key == METADATA_IWD)
{
if (!value.empty())
state->StartIwd(value);
else
throw ParsingException(valueToken.GetPos(), "IWD must have a name");
} }
else else
{ {

View File

@ -1,5 +1,7 @@
#include "ZoneDefinitionParserState.h" #include "ZoneDefinitionParserState.h"
#include <algorithm>
ZoneDefinitionParserState::ZoneDefinitionParserState(std::string targetName) ZoneDefinitionParserState::ZoneDefinitionParserState(std::string targetName)
: m_asset_name_resolver(nullptr), : m_asset_name_resolver(nullptr),
m_definition(std::make_unique<ZoneDefinition>()) m_definition(std::make_unique<ZoneDefinition>())
@ -12,3 +14,50 @@ void ZoneDefinitionParserState::SetGame(const GameId game)
m_definition->m_game = game; m_definition->m_game = game;
m_asset_name_resolver = IAssetNameResolver::GetResolverForGame(game); m_asset_name_resolver = IAssetNameResolver::GetResolverForGame(game);
} }
namespace
{
void AddCurrentObjContainerToDefinitionIfNecessary(ZoneDefinition& zoneDefinition, std::optional<ZoneDefinitionObjContainer>& maybeObjContainer)
{
if (!maybeObjContainer)
return;
maybeObjContainer->m_asset_end = zoneDefinition.m_assets.size();
zoneDefinition.m_obj_containers.emplace_back(std::move(*maybeObjContainer));
maybeObjContainer = std::nullopt;
}
ZoneDefinitionObjContainer DefineNewObjContainer(const ZoneDefinition& zoneDefinition, std::string name, const ZoneDefinitionObjContainerType type)
{
return ZoneDefinitionObjContainer(std::move(name), type, zoneDefinition.m_assets.size());
}
void SortObjContainer(ZoneDefinition& zoneDefinition)
{
std::ranges::sort(zoneDefinition.m_obj_containers,
[](const ZoneDefinitionObjContainer& obj0, const ZoneDefinitionObjContainer& obj1)
{
return obj0.m_asset_start < obj1.m_asset_start;
});
}
} // namespace
void ZoneDefinitionParserState::StartIPak(std::string ipakName)
{
AddCurrentObjContainerToDefinitionIfNecessary(*m_definition, m_current_ipak);
m_current_ipak = DefineNewObjContainer(*m_definition, std::move(ipakName), ZoneDefinitionObjContainerType::IPAK);
}
void ZoneDefinitionParserState::StartIwd(std::string iwdName)
{
AddCurrentObjContainerToDefinitionIfNecessary(*m_definition, m_current_iwd);
m_current_iwd = DefineNewObjContainer(*m_definition, std::move(iwdName), ZoneDefinitionObjContainerType::IWD);
}
void ZoneDefinitionParserState::Finalize()
{
AddCurrentObjContainerToDefinitionIfNecessary(*m_definition, m_current_ipak);
AddCurrentObjContainerToDefinitionIfNecessary(*m_definition, m_current_iwd);
SortObjContainer(*m_definition);
}

View File

@ -4,6 +4,7 @@
#include "Zone/Definition/ZoneDefinition.h" #include "Zone/Definition/ZoneDefinition.h"
#include <memory> #include <memory>
#include <optional>
class ZoneDefinitionParserState class ZoneDefinitionParserState
{ {
@ -12,6 +13,15 @@ public:
void SetGame(GameId game); void SetGame(GameId game);
void StartIPak(std::string ipakName);
void StartIwd(std::string iwdName);
void Finalize();
const IAssetNameResolver* m_asset_name_resolver; const IAssetNameResolver* m_asset_name_resolver;
std::optional<ZoneDefinitionObjContainer> m_current_ipak;
std::optional<ZoneDefinitionObjContainer> m_current_iwd;
std::unique_ptr<ZoneDefinition> m_definition; std::unique_ptr<ZoneDefinition> m_definition;
}; };

View File

@ -1,5 +1,13 @@
#include "ZoneDefinition.h" #include "ZoneDefinition.h"
ZoneDefinitionObjContainer::ZoneDefinitionObjContainer(std::string name, const ZoneDefinitionObjContainerType type, const unsigned start)
: m_name(std::move(name)),
m_type(type),
m_asset_start(start),
m_asset_end(0u)
{
}
ZoneDefinitionAsset::ZoneDefinitionAsset(const asset_type_t type, std::string name, const bool isReference) ZoneDefinitionAsset::ZoneDefinitionAsset(const asset_type_t type, std::string name, const bool isReference)
: m_asset_type(type), : m_asset_type(type),
m_asset_name(std::move(name)), m_asset_name(std::move(name)),
@ -21,8 +29,7 @@ void ZoneDefinitionProperties::Include(const ZoneDefinitionProperties& otherProp
} }
ZoneDefinition::ZoneDefinition() ZoneDefinition::ZoneDefinition()
: m_type(ProjectType::NONE), : m_game(GameId::COUNT)
m_game(GameId::COUNT)
{ {
} }

View File

@ -4,25 +4,35 @@
#include "Zone/AssetList/AssetList.h" #include "Zone/AssetList/AssetList.h"
#include "Zone/ZoneTypes.h" #include "Zone/ZoneTypes.h"
#include <cstdint>
#include <string> #include <string>
#include <unordered_map> #include <unordered_map>
#include <vector> #include <vector>
enum class ProjectType enum class ZoneDefinitionObjContainerType : uint8_t
{ {
NONE, IWD,
FASTFILE, IPAK
IPAK,
COUNT
}; };
static constexpr const char* ProjectType_Names[]{ class ZoneDefinitionObjContainer
"none", {
"fastfile", public:
"ipak", std::string m_name;
ZoneDefinitionObjContainerType m_type;
/**
* \brief The first asset (inclusive) to include in the obj container.
*/
unsigned m_asset_start;
/**
* \brief The last asset (exclusive) to include in the obj container.
*/
unsigned m_asset_end;
ZoneDefinitionObjContainer(std::string name, ZoneDefinitionObjContainerType type, unsigned start);
}; };
static_assert(std::extent_v<decltype(ProjectType_Names)> == static_cast<unsigned>(ProjectType::COUNT));
class ZoneDefinitionAsset class ZoneDefinitionAsset
{ {
@ -54,7 +64,6 @@ public:
void Include(const ZoneDefinition& definitionToInclude); void Include(const ZoneDefinition& definitionToInclude);
std::string m_name; std::string m_name;
ProjectType m_type;
GameId m_game; GameId m_game;
ZoneDefinitionProperties m_properties; ZoneDefinitionProperties m_properties;
std::vector<std::string> m_includes; std::vector<std::string> m_includes;
@ -63,4 +72,5 @@ public:
std::vector<std::string> m_targets_to_build; std::vector<std::string> m_targets_to_build;
std::vector<std::string> m_gdts; std::vector<std::string> m_gdts;
std::vector<ZoneDefinitionAsset> m_assets; std::vector<ZoneDefinitionAsset> m_assets;
std::vector<ZoneDefinitionObjContainer> m_obj_containers;
}; };