mirror of
https://github.com/Laupetin/OpenAssetTools.git
synced 2025-04-21 00:25:44 +00:00
chore: do not only load infostring arrays as pairs but n entries
This commit is contained in:
parent
199be31835
commit
191965a970
@ -84,8 +84,8 @@ namespace
|
|||||||
|
|
||||||
_NODISCARD bool ConvertNotetrackMap(const cspField_t& field, const std::string& value, const char* mapName, const size_t keyAndValueCount)
|
_NODISCARD bool ConvertNotetrackMap(const cspField_t& field, const std::string& value, const char* mapName, const size_t keyAndValueCount)
|
||||||
{
|
{
|
||||||
std::vector<std::pair<std::string, std::string>> pairs;
|
std::vector<std::array<std::string, 2>> pairs;
|
||||||
if (!ParseAsPairs(value, pairs))
|
if (!ParseAsArray(value, pairs))
|
||||||
{
|
{
|
||||||
std::cerr << "Failed to parse notetrack" << mapName << "map as pairs\n";
|
std::cerr << "Failed to parse notetrack" << mapName << "map as pairs\n";
|
||||||
return false;
|
return false;
|
||||||
@ -110,9 +110,9 @@ namespace
|
|||||||
for (; currentEntryNum < pairs.size(); currentEntryNum++)
|
for (; currentEntryNum < pairs.size(); currentEntryNum++)
|
||||||
{
|
{
|
||||||
const auto& currentValue = pairs[currentEntryNum];
|
const auto& currentValue = pairs[currentEntryNum];
|
||||||
const auto keyScriptString = !currentValue.first.empty() ? m_zone_script_strings.AddOrGetScriptString(currentValue.first)
|
const auto keyScriptString = !currentValue[0].empty() ? m_zone_script_strings.AddOrGetScriptString(currentValue[0])
|
||||||
: m_zone_script_strings.AddOrGetScriptString(nullptr);
|
: m_zone_script_strings.AddOrGetScriptString(nullptr);
|
||||||
const auto valueScriptString = !currentValue.second.empty() ? m_zone_script_strings.AddOrGetScriptString(currentValue.second)
|
const auto valueScriptString = !currentValue[1].empty() ? m_zone_script_strings.AddOrGetScriptString(currentValue[1])
|
||||||
: m_zone_script_strings.AddOrGetScriptString(nullptr);
|
: m_zone_script_strings.AddOrGetScriptString(nullptr);
|
||||||
|
|
||||||
keys[currentEntryNum] = keyScriptString;
|
keys[currentEntryNum] = keyScriptString;
|
||||||
|
@ -1,3 +1,230 @@
|
|||||||
#include "InfoStringToStructConverter.h"
|
#include "InfoStringToStructConverter.h"
|
||||||
|
|
||||||
|
#include <cassert>
|
||||||
|
#include <iostream>
|
||||||
|
|
||||||
using namespace IW5;
|
using namespace IW5;
|
||||||
|
|
||||||
|
InfoStringToStructConverter::InfoStringToStructConverter(const InfoString& infoString,
|
||||||
|
void* structure,
|
||||||
|
ZoneScriptStrings& zoneScriptStrings,
|
||||||
|
MemoryManager* memory,
|
||||||
|
IAssetLoadingManager* manager,
|
||||||
|
const cspField_t* fields,
|
||||||
|
const size_t fieldCount)
|
||||||
|
: InfoStringToStructConverterBase(infoString, structure, zoneScriptStrings, memory),
|
||||||
|
m_loading_manager(manager),
|
||||||
|
m_fields(fields),
|
||||||
|
m_field_count(fieldCount)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
bool InfoStringToStructConverter::ConvertBaseField(const cspField_t& field, const std::string& value)
|
||||||
|
{
|
||||||
|
switch (static_cast<csParseFieldType_t>(field.iFieldType))
|
||||||
|
{
|
||||||
|
case CSPFT_STRING:
|
||||||
|
return ConvertString(value, field.iOffset);
|
||||||
|
|
||||||
|
case CSPFT_STRING_MAX_STRING_CHARS:
|
||||||
|
return ConvertStringBuffer(value, field.iOffset, 1024);
|
||||||
|
|
||||||
|
case CSPFT_STRING_MAX_QPATH:
|
||||||
|
return ConvertStringBuffer(value, field.iOffset, 64);
|
||||||
|
|
||||||
|
case CSPFT_STRING_MAX_OSPATH:
|
||||||
|
return ConvertStringBuffer(value, field.iOffset, 256);
|
||||||
|
|
||||||
|
case CSPFT_INT:
|
||||||
|
return ConvertInt(value, field.iOffset);
|
||||||
|
|
||||||
|
case CSPFT_BOOL:
|
||||||
|
return ConvertBool(value, field.iOffset);
|
||||||
|
|
||||||
|
case CSPFT_QBOOLEAN:
|
||||||
|
return ConvertQBoolean(value, field.iOffset);
|
||||||
|
|
||||||
|
case CSPFT_FLOAT:
|
||||||
|
return ConvertFloat(value, field.iOffset);
|
||||||
|
|
||||||
|
case CSPFT_MILLISECONDS:
|
||||||
|
return ConvertMilliseconds(value, field.iOffset);
|
||||||
|
|
||||||
|
case CSPFT_FX:
|
||||||
|
{
|
||||||
|
if (value.empty())
|
||||||
|
{
|
||||||
|
*reinterpret_cast<void**>(reinterpret_cast<uintptr_t>(m_structure) + field.iOffset) = nullptr;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto* fx = m_loading_manager->LoadDependency(ASSET_TYPE_FX, value);
|
||||||
|
|
||||||
|
if (fx == nullptr)
|
||||||
|
{
|
||||||
|
std::cout << "Failed to load fx asset \"" << value << "\"\n";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_dependencies.emplace(fx);
|
||||||
|
*reinterpret_cast<void**>(reinterpret_cast<uintptr_t>(m_structure) + field.iOffset) = fx->m_ptr;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
case CSPFT_XMODEL:
|
||||||
|
{
|
||||||
|
if (value.empty())
|
||||||
|
{
|
||||||
|
*reinterpret_cast<void**>(reinterpret_cast<uintptr_t>(m_structure) + field.iOffset) = nullptr;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto* xmodel = m_loading_manager->LoadDependency(ASSET_TYPE_XMODEL, value);
|
||||||
|
|
||||||
|
if (xmodel == nullptr)
|
||||||
|
{
|
||||||
|
std::cout << "Failed to load xmodel asset \"" << value << "\"\n";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_dependencies.emplace(xmodel);
|
||||||
|
*reinterpret_cast<void**>(reinterpret_cast<uintptr_t>(m_structure) + field.iOffset) = xmodel->m_ptr;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
case CSPFT_MATERIAL:
|
||||||
|
{
|
||||||
|
if (value.empty())
|
||||||
|
{
|
||||||
|
*reinterpret_cast<void**>(reinterpret_cast<uintptr_t>(m_structure) + field.iOffset) = nullptr;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto* material = m_loading_manager->LoadDependency(ASSET_TYPE_MATERIAL, value);
|
||||||
|
|
||||||
|
if (material == nullptr)
|
||||||
|
{
|
||||||
|
std::cout << "Failed to load material asset \"" << value << "\"\n";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_dependencies.emplace(material);
|
||||||
|
*reinterpret_cast<void**>(reinterpret_cast<uintptr_t>(m_structure) + field.iOffset) = material->m_ptr;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
case CSPFT_TRACER:
|
||||||
|
{
|
||||||
|
if (value.empty())
|
||||||
|
{
|
||||||
|
*reinterpret_cast<void**>(reinterpret_cast<uintptr_t>(m_structure) + field.iOffset) = nullptr;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto* tracer = m_loading_manager->LoadDependency(ASSET_TYPE_TRACER, value);
|
||||||
|
|
||||||
|
if (tracer == nullptr)
|
||||||
|
{
|
||||||
|
std::cout << "Failed to load tracer asset \"" << value << "\"\n";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_dependencies.emplace(tracer);
|
||||||
|
*reinterpret_cast<void**>(reinterpret_cast<uintptr_t>(m_structure) + field.iOffset) = tracer->m_ptr;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
case CSPFT_MPH_TO_INCHES_PER_SEC:
|
||||||
|
{
|
||||||
|
char* endPtr;
|
||||||
|
*reinterpret_cast<float*>(reinterpret_cast<uintptr_t>(m_structure) + field.iOffset) = strtof(value.c_str(), &endPtr) * 17.6f;
|
||||||
|
|
||||||
|
if (endPtr != &value[value.size()])
|
||||||
|
{
|
||||||
|
std::cout << "Failed to parse value \"" << value << "\" as mph\n";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
case CSPFT_PHYS_COLLMAP:
|
||||||
|
{
|
||||||
|
if (value.empty())
|
||||||
|
{
|
||||||
|
*reinterpret_cast<void**>(reinterpret_cast<uintptr_t>(m_structure) + field.iOffset) = nullptr;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto* collmap = m_loading_manager->LoadDependency(ASSET_TYPE_PHYSCOLLMAP, value);
|
||||||
|
|
||||||
|
if (collmap == nullptr)
|
||||||
|
{
|
||||||
|
std::cout << "Failed to load collmap asset \"" << value << "\"\n";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_dependencies.emplace(collmap);
|
||||||
|
*reinterpret_cast<void**>(reinterpret_cast<uintptr_t>(m_structure) + field.iOffset) = collmap->m_ptr;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
case CSPFT_SOUND:
|
||||||
|
{
|
||||||
|
if (value.empty())
|
||||||
|
{
|
||||||
|
reinterpret_cast<SndAliasCustom*>(reinterpret_cast<uintptr_t>(m_structure) + field.iOffset)->name = nullptr;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto* name = static_cast<snd_alias_list_name*>(m_memory->Alloc(sizeof(snd_alias_list_name)));
|
||||||
|
name->soundName = m_memory->Dup(value.c_str());
|
||||||
|
|
||||||
|
reinterpret_cast<SndAliasCustom*>(reinterpret_cast<uintptr_t>(m_structure) + field.iOffset)->name = name;
|
||||||
|
|
||||||
|
m_indirect_asset_references.emplace(ASSET_TYPE_SOUND, value);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
case CSPFT_SCRIPT_STRING:
|
||||||
|
return ConvertScriptString(value, field.iOffset);
|
||||||
|
|
||||||
|
case CSPFT_NUM_BASE_FIELD_TYPES:
|
||||||
|
default:
|
||||||
|
assert(false);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool InfoStringToStructConverter::Convert()
|
||||||
|
{
|
||||||
|
for (auto fieldIndex = 0u; fieldIndex < m_field_count; fieldIndex++)
|
||||||
|
{
|
||||||
|
const auto& field = m_fields[fieldIndex];
|
||||||
|
assert(field.iFieldType >= 0);
|
||||||
|
|
||||||
|
auto foundValue = false;
|
||||||
|
const auto& value = m_info_string.GetValueForKey(std::string(field.szName), &foundValue);
|
||||||
|
|
||||||
|
if (foundValue)
|
||||||
|
{
|
||||||
|
if (field.iFieldType < CSPFT_NUM_BASE_FIELD_TYPES)
|
||||||
|
{
|
||||||
|
if (!ConvertBaseField(field, value))
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (!ConvertExtensionField(field, value))
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
@ -81,8 +81,8 @@ namespace T6
|
|||||||
|
|
||||||
_NODISCARD bool ConvertNotetrackSoundMap(const cspField_t& field, const std::string& value)
|
_NODISCARD bool ConvertNotetrackSoundMap(const cspField_t& field, const std::string& value)
|
||||||
{
|
{
|
||||||
std::vector<std::pair<std::string, std::string>> pairs;
|
std::vector<std::array<std::string, 2>> pairs;
|
||||||
if (!ParseAsPairs(value, pairs))
|
if (!ParseAsArray(value, pairs))
|
||||||
{
|
{
|
||||||
std::cerr << "Failed to parse notetracksoundmap as pairs\n";
|
std::cerr << "Failed to parse notetracksoundmap as pairs\n";
|
||||||
return false;
|
return false;
|
||||||
@ -106,9 +106,9 @@ namespace T6
|
|||||||
for (; currentEntryNum < pairs.size(); currentEntryNum++)
|
for (; currentEntryNum < pairs.size(); currentEntryNum++)
|
||||||
{
|
{
|
||||||
const auto& currentValue = pairs[currentEntryNum];
|
const auto& currentValue = pairs[currentEntryNum];
|
||||||
const auto keyScriptString = !currentValue.first.empty() ? m_zone_script_strings.AddOrGetScriptString(currentValue.first)
|
const auto keyScriptString = !currentValue[0].empty() ? m_zone_script_strings.AddOrGetScriptString(currentValue[0])
|
||||||
: m_zone_script_strings.AddOrGetScriptString(nullptr);
|
: m_zone_script_strings.AddOrGetScriptString(nullptr);
|
||||||
const auto valueScriptString = !currentValue.second.empty() ? m_zone_script_strings.AddOrGetScriptString(currentValue.second)
|
const auto valueScriptString = !currentValue[1].empty() ? m_zone_script_strings.AddOrGetScriptString(currentValue[1])
|
||||||
: m_zone_script_strings.AddOrGetScriptString(nullptr);
|
: m_zone_script_strings.AddOrGetScriptString(nullptr);
|
||||||
|
|
||||||
keys[currentEntryNum] = keyScriptString;
|
keys[currentEntryNum] = keyScriptString;
|
||||||
|
@ -41,68 +41,6 @@ bool InfoStringToStructConverterBase::ParseAsArray(const std::string& value, std
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool InfoStringToStructConverterBase::ParseAsPairs(const std::string& value, std::vector<std::pair<std::string, std::string>>& valueArray)
|
|
||||||
{
|
|
||||||
std::string key;
|
|
||||||
auto isKey = true;
|
|
||||||
|
|
||||||
for (auto ci = 0u; ci < value.size(); ci++)
|
|
||||||
{
|
|
||||||
auto c = value[ci];
|
|
||||||
|
|
||||||
if (c == '\r' && ci + 1 < value.size() && value[ci + 1] == '\n')
|
|
||||||
c = value[++ci];
|
|
||||||
|
|
||||||
if (c == '\n' && !isKey)
|
|
||||||
{
|
|
||||||
std::cout << "Expected value but got new line\n";
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (isspace(c))
|
|
||||||
continue;
|
|
||||||
|
|
||||||
int separator;
|
|
||||||
const auto startPos = ci;
|
|
||||||
while (true)
|
|
||||||
{
|
|
||||||
ci++;
|
|
||||||
if (ci >= value.size())
|
|
||||||
{
|
|
||||||
separator = EOF;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
c = value[ci];
|
|
||||||
if (c == '\r' && ci + 1 < value.size() && value[ci + 1] == '\n')
|
|
||||||
c = value[++ci];
|
|
||||||
if (isspace(c))
|
|
||||||
{
|
|
||||||
separator = static_cast<int>(static_cast<unsigned char>(c));
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (isKey)
|
|
||||||
{
|
|
||||||
if (separator == '\n' || separator == EOF)
|
|
||||||
{
|
|
||||||
std::cout << "Expected value but got new line\n";
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
key = std::string(value, startPos, ci - startPos);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
auto parsedValue = std::string(value, startPos, ci - startPos);
|
|
||||||
valueArray.emplace_back(std::make_pair(std::move(key), std::move(parsedValue)));
|
|
||||||
key = std::string();
|
|
||||||
}
|
|
||||||
isKey = !isKey;
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool InfoStringToStructConverterBase::ConvertString(const std::string& value, const size_t offset)
|
bool InfoStringToStructConverterBase::ConvertString(const std::string& value, const size_t offset)
|
||||||
{
|
{
|
||||||
*reinterpret_cast<const char**>(reinterpret_cast<uintptr_t>(m_structure) + offset) = m_memory->Dup(value.c_str());
|
*reinterpret_cast<const char**>(reinterpret_cast<uintptr_t>(m_structure) + offset) = m_memory->Dup(value.c_str());
|
||||||
|
@ -6,6 +6,8 @@
|
|||||||
#include "Utils/MemoryManager.h"
|
#include "Utils/MemoryManager.h"
|
||||||
#include "Zone/ZoneScriptStrings.h"
|
#include "Zone/ZoneScriptStrings.h"
|
||||||
|
|
||||||
|
#include <array>
|
||||||
|
#include <iostream>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <unordered_set>
|
#include <unordered_set>
|
||||||
#include <utility>
|
#include <utility>
|
||||||
@ -22,7 +24,82 @@ protected:
|
|||||||
void* m_structure;
|
void* m_structure;
|
||||||
|
|
||||||
static bool ParseAsArray(const std::string& value, std::vector<std::string>& valueArray);
|
static bool ParseAsArray(const std::string& value, std::vector<std::string>& valueArray);
|
||||||
static bool ParseAsPairs(const std::string& value, std::vector<std::pair<std::string, std::string>>& valueArray);
|
|
||||||
|
template<size_t ARRAY_SIZE> static bool ParseAsArray(const std::string& value, std::vector<std::array<std::string, ARRAY_SIZE>>& valueArray)
|
||||||
|
{
|
||||||
|
static_assert(ARRAY_SIZE >= 1);
|
||||||
|
|
||||||
|
std::array<std::string, ARRAY_SIZE> currentEntry;
|
||||||
|
auto currentEntryOffset = 0u;
|
||||||
|
|
||||||
|
for (auto ci = 0u; ci < value.size(); ci++)
|
||||||
|
{
|
||||||
|
auto c = value[ci];
|
||||||
|
|
||||||
|
if (c == '\r' && ci + 1 < value.size() && value[ci + 1] == '\n')
|
||||||
|
c = value[++ci];
|
||||||
|
|
||||||
|
if (c == '\n' && currentEntryOffset != ARRAY_SIZE)
|
||||||
|
{
|
||||||
|
std::cerr << "Expected value but got new line\n";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isspace(c))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
int separator;
|
||||||
|
const auto startPos = ci;
|
||||||
|
while (true)
|
||||||
|
{
|
||||||
|
ci++;
|
||||||
|
|
||||||
|
// If value ends we use EOF as separator
|
||||||
|
if (ci >= value.size())
|
||||||
|
{
|
||||||
|
separator = EOF;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
c = value[ci];
|
||||||
|
|
||||||
|
// Skip \r from \r\n
|
||||||
|
if (c == '\r' && ci + 1 < value.size() && value[ci + 1] == '\n')
|
||||||
|
c = value[++ci];
|
||||||
|
|
||||||
|
// Newline is considered space
|
||||||
|
if (isspace(c))
|
||||||
|
{
|
||||||
|
separator = static_cast<int>(static_cast<unsigned char>(c));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const auto isNextEntrySeparator = separator == '\n' || separator == EOF;
|
||||||
|
const auto isLastEntry = currentEntryOffset >= (ARRAY_SIZE - 1);
|
||||||
|
if (isNextEntrySeparator != isLastEntry)
|
||||||
|
{
|
||||||
|
std::cout << "Expected " << ARRAY_SIZE << " values but got new line\n";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
currentEntry[currentEntryOffset++] = std::string(value, startPos, ci - startPos);
|
||||||
|
|
||||||
|
if (isLastEntry)
|
||||||
|
{
|
||||||
|
valueArray.emplace_back(std::move(currentEntry));
|
||||||
|
currentEntryOffset = 0u;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (currentEntryOffset > 0)
|
||||||
|
{
|
||||||
|
std::cout << "Expected " << ARRAY_SIZE << " values but got new line\n";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
bool ConvertString(const std::string& value, size_t offset);
|
bool ConvertString(const std::string& value, size_t offset);
|
||||||
bool ConvertStringBuffer(const std::string& value, size_t offset, size_t bufferSize);
|
bool ConvertStringBuffer(const std::string& value, size_t offset, size_t bufferSize);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user