mirror of
https://github.com/Laupetin/OpenAssetTools.git
synced 2025-04-19 15:52:53 +00:00
feat: add ipak and iwd zone definition metadata to replace type
This commit is contained in:
parent
973ff73554
commit
2182196730
@ -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();
|
||||||
|
|
||||||
|
@ -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
|
||||||
{
|
{
|
||||||
|
@ -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);
|
||||||
|
}
|
||||||
|
@ -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;
|
||||||
};
|
};
|
||||||
|
@ -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)
|
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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;
|
||||||
};
|
};
|
||||||
|
Loading…
x
Reference in New Issue
Block a user