chore: do not only load infostring arrays as pairs but n entries

This commit is contained in:
Jan 2024-04-21 18:44:28 +02:00
parent 199be31835
commit 191965a970
No known key found for this signature in database
GPG Key ID: 44B581F78FF5C57C
5 changed files with 317 additions and 75 deletions

View File

@ -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;

View File

@ -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;
}

View File

@ -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;

View File

@ -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());

View File

@ -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);