Add InfoString loading

This commit is contained in:
Jan 2021-03-25 11:14:51 +01:00
parent 613943b28c
commit 55f48c9bc2
10 changed files with 499 additions and 47 deletions

View File

@ -96,10 +96,90 @@ void InfoString::ToGdtProperties(const std::string& prefix, GdtEntry& gdtEntry)
gdtEntry.m_properties["configstringFileType"] = prefix; gdtEntry.m_properties["configstringFileType"] = prefix;
} }
void InfoString::FromString() class InfoStringInputStream
{ {
std::istream& m_stream;
public:
explicit InfoStringInputStream(std::istream& stream)
: m_stream(stream)
{
}
bool NextField(std::string& value) const
{
std::ostringstream str;
auto c = m_stream.get();
if (c == EOF)
return false;
while (c != EOF && c != '\\')
{
str << static_cast<char>(c);
c = m_stream.get();
}
value = str.str();
return true;
}
};
bool InfoString::FromStream(std::istream& stream)
{
const InfoStringInputStream infoStream(stream);
std::string key;
while (infoStream.NextField(key))
{
std::string value;
if (!infoStream.NextField(value))
return false;
const auto existingEntry = m_values.find(key);
if (existingEntry == m_values.end())
{
m_keys_by_insertion.push_back(key);
m_values.emplace(std::make_pair(key, value));
}
else
{
existingEntry->second = value;
}
}
return true;
} }
void InfoString::FromString(const std::string& prefix) bool InfoString::FromStream(const std::string& prefix, std::istream& stream)
{ {
const InfoStringInputStream infoStream(stream);
std::string readPrefix;
if (!infoStream.NextField(readPrefix))
return false;
if (prefix != readPrefix)
return false;
std::string key;
while(infoStream.NextField(key))
{
std::string value;
if (!infoStream.NextField(value))
return false;
const auto existingEntry = m_values.find(key);
if(existingEntry == m_values.end())
{
m_keys_by_insertion.push_back(key);
m_values.emplace(std::make_pair(key, value));
}
else
{
existingEntry->second = value;
}
}
return true;
} }

View File

@ -1,4 +1,5 @@
#pragma once #pragma once
#include <istream>
#include <unordered_map> #include <unordered_map>
#include <string> #include <string>
#include <vector> #include <vector>
@ -23,6 +24,6 @@ public:
_NODISCARD std::string ToString(const std::string& prefix) const; _NODISCARD std::string ToString(const std::string& prefix) const;
void ToGdtProperties(const std::string& prefix, GdtEntry& gdtEntry) const; void ToGdtProperties(const std::string& prefix, GdtEntry& gdtEntry) const;
void FromString(); bool FromStream(std::istream& stream);
void FromString(const std::string& prefix); bool FromStream(const std::string& prefix, std::istream& stream);
}; };

View File

@ -2,14 +2,3 @@
using namespace IW4; using namespace IW4;
void InfoStringToStructConverter::FillStructure()
{
}
InfoStringToStructConverter::InfoStringToStructConverter(const InfoString& infoString, void* structure,
const cspField_t* fields, const size_t fieldCount)
: InfoStringToStructConverterBase(infoString, structure),
m_fields(fields),
m_field_count(fieldCount)
{
}

View File

@ -1,4 +1,5 @@
#pragma once #pragma once
#include "AssetLoading/IAssetLoadingManager.h"
#include "InfoString/InfoStringToStructConverterBase.h" #include "InfoString/InfoStringToStructConverterBase.h"
#include "Game/IW4/IW4.h" #include "Game/IW4/IW4.h"
@ -6,13 +7,19 @@ namespace IW4
{ {
class InfoStringToStructConverter : public InfoStringToStructConverterBase class InfoStringToStructConverter : public InfoStringToStructConverterBase
{ {
protected:
IAssetLoadingManager* m_loading_manager;
const cspField_t* m_fields; const cspField_t* m_fields;
size_t m_field_count; size_t m_field_count;
protected: static bool GetHashValue(const std::string& value, unsigned int& hash);
void FillStructure() override;
virtual bool ConvertExtensionField(const cspField_t& field, const std::string& value) = 0;
bool ConvertBaseField(const cspField_t& field, const std::string& value);
public: public:
InfoStringToStructConverter(const InfoString& infoString, void* structure, const cspField_t* fields, size_t fieldCount); InfoStringToStructConverter(const InfoString& infoString, void* structure, ZoneScriptStrings& zoneScriptStrings, MemoryManager* memory, IAssetLoadingManager* manager, const cspField_t* fields,
size_t fieldCount);
bool Convert() override;
}; };
} }

View File

@ -1,17 +1,226 @@
#include "InfoStringToStructConverter.h" #include "InfoStringToStructConverter.h"
#include <cassert> #include <cassert>
#include <iostream>
#include "Game/T6/CommonT6.h"
using namespace T6; using namespace T6;
void InfoStringToStructConverter::FillStructure() 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)
{ {
} }
InfoStringToStructConverter::InfoStringToStructConverter(const InfoString& infoString, void* structure, bool InfoStringToStructConverter::GetHashValue(const std::string& value, unsigned& hash)
const cspField_t* fields, const size_t fieldCount)
: InfoStringToStructConverterBase(infoString, structure),
m_fields(fields),
m_field_count(fieldCount)
{ {
if (!value.empty() && value[0] == '@')
{
char* endPtr;
hash = strtoul(&value[1], &endPtr, 16);
return endPtr == &value[value.size()];
}
hash = CommonT6::Com_HashString(value.c_str());
return true;
}
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_UINT:
return ConvertUint(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 << "\"" << std::endl;
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 << "\"" << std::endl;
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:
case CSPFT_MATERIAL_STREAM:
{
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 << "\"" << std::endl;
return false;
}
m_dependencies.emplace(material);
*reinterpret_cast<void**>(reinterpret_cast<uintptr_t>(m_structure) + field.iOffset) = material->m_ptr;
return true;
}
case CSPFT_PHYS_PRESET:
{
if (value.empty())
{
*reinterpret_cast<void**>(reinterpret_cast<uintptr_t>(m_structure) + field.iOffset) = nullptr;
return true;
}
auto* physPreset = m_loading_manager->LoadDependency(ASSET_TYPE_PHYSPRESET, value);
if (physPreset == nullptr)
{
std::cout << "Failed to load physpreset asset \"" << value << "\"" << std::endl;
return false;
}
m_dependencies.emplace(physPreset);
*reinterpret_cast<void**>(reinterpret_cast<uintptr_t>(m_structure) + field.iOffset) = physPreset->m_ptr;
return true;
}
case CSPFT_SCRIPT_STRING:
return ConvertScriptString(value, field.iOffset);
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 << "\"" << std::endl;
return false;
}
m_dependencies.emplace(tracer);
*reinterpret_cast<void**>(reinterpret_cast<uintptr_t>(m_structure) + field.iOffset) = tracer->m_ptr;
return true;
}
case CSPFT_SOUND_ALIAS_ID:
{
unsigned int soundAliasHash;
if (!GetHashValue(value, soundAliasHash))
{
std::cout << "Failed to parse value \"" << value << "\" as hash" << std::endl;
return false;
}
*reinterpret_cast<unsigned int*>(reinterpret_cast<uintptr_t>(m_structure) + field.iOffset) = soundAliasHash;
return true;
}
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

@ -1,4 +1,5 @@
#pragma once #pragma once
#include "AssetLoading/IAssetLoadingManager.h"
#include "InfoString/InfoStringToStructConverterBase.h" #include "InfoString/InfoStringToStructConverterBase.h"
#include "Game/T6/T6.h" #include "Game/T6/T6.h"
@ -6,13 +7,19 @@ namespace T6
{ {
class InfoStringToStructConverter : public InfoStringToStructConverterBase class InfoStringToStructConverter : public InfoStringToStructConverterBase
{ {
protected:
IAssetLoadingManager* m_loading_manager;
const cspField_t* m_fields; const cspField_t* m_fields;
size_t m_field_count; size_t m_field_count;
protected: static bool GetHashValue(const std::string& value, unsigned int& hash);
void FillStructure() override;
virtual bool ConvertExtensionField(const cspField_t& field, const std::string& value) = 0;
bool ConvertBaseField(const cspField_t& field, const std::string& value);
public: public:
InfoStringToStructConverter(const InfoString& infoString, void* structure, const cspField_t* fields, size_t fieldCount); InfoStringToStructConverter(const InfoString& infoString, void* structure, ZoneScriptStrings& zoneScriptStrings, MemoryManager* memory, IAssetLoadingManager* manager, const cspField_t* fields,
size_t fieldCount);
bool Convert() override;
}; };
} }

View File

@ -1,15 +1,155 @@
#include "InfoStringToStructConverterBase.h" #include "InfoStringToStructConverterBase.h"
InfoStringToStructConverterBase::InfoStringToStructConverterBase(const InfoString& infoString, void* structure) #include <cstring>
#include <iostream>
InfoStringToStructConverterBase::InfoStringToStructConverterBase(const InfoString& infoString, void* structure, ZoneScriptStrings& zoneScriptStrings, MemoryManager* memory)
: m_info_string(infoString), : m_info_string(infoString),
m_structure(structure) m_zone_script_strings(zoneScriptStrings),
m_memory(memory),
m_structure(structure)
{ {
} }
InfoStringToStructConverterBase::~InfoStringToStructConverterBase() bool InfoStringToStructConverterBase::ConvertString(const std::string& value, const size_t offset)
= default;
void InfoStringToStructConverterBase::Convert()
{ {
FillStructure(); *reinterpret_cast<const char**>(reinterpret_cast<uintptr_t>(m_structure) + offset) = m_memory->Dup(value.c_str());
return true;
}
bool InfoStringToStructConverterBase::ConvertStringBuffer(const std::string& value, const size_t offset, const size_t bufferSize)
{
strncpy(reinterpret_cast<char*>(reinterpret_cast<uintptr_t>(m_structure) + offset), value.c_str(), bufferSize);
return true;
}
bool InfoStringToStructConverterBase::ConvertInt(const std::string& value, const size_t offset)
{
char* endPtr;
*reinterpret_cast<int*>(reinterpret_cast<uintptr_t>(m_structure) + offset) = strtol(value.c_str(), &endPtr, 0);
if(endPtr != &value[value.size()])
{
std::cout << "Failed to parse value \"" << value << "\" as int" << std::endl;
return false;
}
return true;
}
bool InfoStringToStructConverterBase::ConvertUint(const std::string& value, const size_t offset)
{
char* endPtr;
*reinterpret_cast<unsigned int*>(reinterpret_cast<uintptr_t>(m_structure) + offset) = strtoul(value.c_str(), &endPtr, 0);
if (endPtr != &value[value.size()])
{
std::cout << "Failed to parse value \"" << value << "\" as uint" << std::endl;
return false;
}
return true;
}
bool InfoStringToStructConverterBase::ConvertBool(const std::string& value, const size_t offset)
{
char* endPtr;
const auto intValue = strtol(value.c_str(), &endPtr, 0);
*reinterpret_cast<bool*>(reinterpret_cast<uintptr_t>(m_structure) + offset) = intValue != 0;
if (endPtr != &value[value.size()])
{
std::cout << "Failed to parse value \"" << value << "\" as bool" << std::endl;
return false;
}
return true;
}
bool InfoStringToStructConverterBase::ConvertQBoolean(const std::string& value, const size_t offset)
{
char* endPtr;
const auto intValue = strtol(value.c_str(), &endPtr, 0);
*reinterpret_cast<int*>(reinterpret_cast<uintptr_t>(m_structure) + offset) = intValue != 0 ? 1 : 0;
if (endPtr != &value[value.size()])
{
std::cout << "Failed to parse value \"" << value << "\" as qboolean" << std::endl;
return false;
}
return true;
}
bool InfoStringToStructConverterBase::ConvertFloat(const std::string& value, const size_t offset)
{
char* endPtr;
*reinterpret_cast<float*>(reinterpret_cast<uintptr_t>(m_structure) + offset) = strtof(value.c_str(), &endPtr);
if (endPtr != &value[value.size()])
{
std::cout << "Failed to parse value \"" << value << "\" as float" << std::endl;
return false;
}
return true;
}
bool InfoStringToStructConverterBase::ConvertMilliseconds(const std::string& value, const size_t offset)
{
char* endPtr;
*reinterpret_cast<unsigned int*>(reinterpret_cast<uintptr_t>(m_structure) + offset) = static_cast<unsigned int>(strtof(value.c_str(), &endPtr) * 1000.0f);
if (endPtr != &value[value.size()])
{
std::cout << "Failed to parse value \"" << value << "\" as milliseconds" << std::endl;
return false;
}
return true;
}
bool InfoStringToStructConverterBase::ConvertScriptString(const std::string& value, const size_t offset)
{
auto scrStrValue = m_zone_script_strings.AddOrGetScriptString(value);
m_used_script_string_list.emplace(scrStrValue);
*reinterpret_cast<scr_string_t*>(reinterpret_cast<uintptr_t>(m_structure) + offset) = scrStrValue;
return true;
}
bool InfoStringToStructConverterBase::ConvertEnumInt(const std::string& value, const size_t offset, const char** enumValues, const size_t enumSize)
{
for(auto i = 0u; i < enumSize; i++)
{
if(value == enumValues[i])
{
*reinterpret_cast<int*>(reinterpret_cast<uintptr_t>(m_structure) + offset) = static_cast<int>(i);
return true;
}
}
return false;
}
std::vector<scr_string_t> InfoStringToStructConverterBase::GetUsedScriptStrings() const
{
std::vector<scr_string_t> scrStringList;
for(auto scrStr : m_used_script_string_list)
{
scrStringList.push_back(scrStr);
}
return scrStringList;
}
std::vector<XAssetInfoGeneric*> InfoStringToStructConverterBase::GetDependencies() const
{
std::vector<XAssetInfoGeneric*> dependencyList;
for (auto* dependency : m_dependencies)
{
dependencyList.push_back(dependency);
}
return dependencyList;
} }

View File

@ -1,22 +1,44 @@
#pragma once #pragma once
#include <string>
#include <unordered_set>
#include "Utils/ClassUtils.h"
#include "InfoString/InfoString.h" #include "InfoString/InfoString.h"
#include "Pool/XAssetInfo.h"
#include "Utils/MemoryManager.h"
#include "Zone/ZoneScriptStrings.h"
class InfoStringToStructConverterBase class InfoStringToStructConverterBase
{ {
protected: protected:
const InfoString& m_info_string; const InfoString& m_info_string;
ZoneScriptStrings& m_zone_script_strings;
std::unordered_set<scr_string_t> m_used_script_string_list;
std::unordered_set<XAssetInfoGeneric*> m_dependencies;
MemoryManager* m_memory;
void* m_structure; void* m_structure;
virtual void FillStructure() = 0; bool ConvertString(const std::string& value, size_t offset);
bool ConvertStringBuffer(const std::string& value, size_t offset, size_t bufferSize);
bool ConvertInt(const std::string& value, size_t offset);
bool ConvertUint(const std::string& value, size_t offset);
bool ConvertBool(const std::string& value, size_t offset);
bool ConvertQBoolean(const std::string& value, size_t offset);
bool ConvertFloat(const std::string& value, size_t offset);
bool ConvertMilliseconds(const std::string& value, size_t offset);
bool ConvertScriptString(const std::string& value, size_t offset);
bool ConvertEnumInt(const std::string& value, size_t offset, const char** enumValues, size_t enumSize);
public: public:
InfoStringToStructConverterBase(const InfoString& infoString, void* structure); InfoStringToStructConverterBase(const InfoString& infoString, void* structure, ZoneScriptStrings& zoneScriptStrings, MemoryManager* memory);
virtual ~InfoStringToStructConverterBase(); virtual ~InfoStringToStructConverterBase() = default;
InfoStringToStructConverterBase(const InfoStringToStructConverterBase& other) = delete; InfoStringToStructConverterBase(const InfoStringToStructConverterBase& other) = delete;
InfoStringToStructConverterBase(InfoStringToStructConverterBase&& other) noexcept = delete; InfoStringToStructConverterBase(InfoStringToStructConverterBase&& other) noexcept = delete;
InfoStringToStructConverterBase& operator=(const InfoStringToStructConverterBase& other) = delete; InfoStringToStructConverterBase& operator=(const InfoStringToStructConverterBase& other) = delete;
InfoStringToStructConverterBase& operator=(InfoStringToStructConverterBase&& other) noexcept = delete; InfoStringToStructConverterBase& operator=(InfoStringToStructConverterBase&& other) noexcept = delete;
void Convert(); virtual bool Convert() = 0;
_NODISCARD std::vector<scr_string_t> GetUsedScriptStrings() const;
_NODISCARD std::vector<XAssetInfoGeneric*> GetDependencies() const;
}; };

View File

@ -19,9 +19,6 @@ InfoStringFromStructConverterBase::InfoStringFromStructConverterBase(const void*
{ {
} }
InfoStringFromStructConverterBase::~InfoStringFromStructConverterBase()
= default;
InfoString InfoStringFromStructConverterBase::Convert() InfoString InfoStringFromStructConverterBase::Convert()
{ {
FillInfoString(); FillInfoString();

View File

@ -28,7 +28,7 @@ protected:
public: public:
explicit InfoStringFromStructConverterBase(const void* structure); explicit InfoStringFromStructConverterBase(const void* structure);
InfoStringFromStructConverterBase(const void* structure, std::function<std::string(scr_string_t)> scriptStringValueCallback); InfoStringFromStructConverterBase(const void* structure, std::function<std::string(scr_string_t)> scriptStringValueCallback);
virtual ~InfoStringFromStructConverterBase(); virtual ~InfoStringFromStructConverterBase() = default;
InfoStringFromStructConverterBase(const InfoStringFromStructConverterBase& other) = delete; InfoStringFromStructConverterBase(const InfoStringFromStructConverterBase& other) = delete;
InfoStringFromStructConverterBase(InfoStringFromStructConverterBase&& other) noexcept = delete; InfoStringFromStructConverterBase(InfoStringFromStructConverterBase&& other) noexcept = delete;
InfoStringFromStructConverterBase& operator=(const InfoStringFromStructConverterBase& other) = delete; InfoStringFromStructConverterBase& operator=(const InfoStringFromStructConverterBase& other) = delete;