Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[ResourceLib] Fully implement UICB support #31

Merged
merged 5 commits into from
Feb 18, 2024
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 1 addition & 4 deletions Libraries/ResourceLib/Src/Resources.cpp
Original file line number Diff line number Diff line change
@@ -34,6 +34,7 @@ std::unordered_map<std::string, Resource> g_Resources = {
REGISTER_RESOURCE(ATMD, ZAMDTake)
REGISTER_RESOURCE(VIDB, SVideoDatabaseData)
REGISTER_RESOURCE(RTLV, SLocalizedVideoDataDecrypted)
REGISTER_RESOURCE(UICB, SUIControlBlueprint)
#endif

REGISTER_RESOURCE(CBLU, SCppEntityBlueprint)
@@ -47,10 +48,6 @@ std::unordered_map<std::string, Resource> g_Resources = {
#if ZHM_TARGET != 2016 && ZHM_TARGET != 2012
REGISTER_RESOURCE(ECPB, SExtendedCppEntityBlueprint)
#endif

#if ZHM_TARGET == 3
REGISTER_RESOURCE(UICB, SUIControlBlueprint)
#endif

#if ZHM_TARGET == 3 || ZHM_TARGET == 2
REGISTER_RESOURCE(ENUM, SEnumType)
168 changes: 109 additions & 59 deletions Libraries/ResourceLib/Src/ZHM/ZHMCustomTypes.cpp
Original file line number Diff line number Diff line change
@@ -334,117 +334,167 @@ void SAudioStateBlueprintData::Serialize(void* p_Object, ZHMSerializer& p_Serial
TArray<ZString>::Serialize(&s_Object->m_aStates, p_Serializer, p_OwnOffset + offsetof(SAudioStateBlueprintData, m_aStates));
}

ZHMTypeInfo SUIControlBlueprintPin::TypeInfo = ZHMTypeInfo("SUIControlBlueprintPin", sizeof(SUIControlBlueprintPin), alignof(SUIControlBlueprintPin), WriteSimpleJson, FromSimpleJson, Serialize);
ZHMTypeInfo SAttributeInfo::TypeInfo = ZHMTypeInfo("SAttributeInfo", sizeof(SAttributeInfo), alignof(SAttributeInfo), WriteSimpleJson, FromSimpleJson, Serialize);

void SUIControlBlueprintPin::WriteSimpleJson(void* p_Object, std::ostream& p_Stream)
std::map<int32_t, std::string> EAttributeKind = {
{ 0, "E_ATTRIBUTE_KIND_PROPERTY" },
{ 1, "E_ATTRIBUTE_KIND_INPUT_PIN" },
{ 2, "E_ATTRIBUTE_KIND_OUTPUT_PIN" },
};

std::map<int32_t, std::string> EAttributeType = {
{ 0, "E_ATTRIBUTE_TYPE_VOID" },
{ 1, "E_ATTRIBUTE_TYPE_INT" },
{ 2, "E_ATTRIBUTE_TYPE_FLOAT" },
{ 3, "E_ATTRIBUTE_TYPE_STRING" },
{ 4, "E_ATTRIBUTE_TYPE_BOOL" },
{ 5, "E_ATTRIBUTE_TYPE_ENTITYREF" },
{ 6, "E_ATTRIBUTE_TYPE_OBJECT" },
};

void SAttributeInfo::WriteSimpleJson(void* p_Object, std::ostream& p_Stream)
{
p_Stream << "{";
auto s_Object = static_cast<SAttributeInfo*>(p_Object);

auto s_Object = static_cast<SUIControlBlueprintPin*>(p_Object);
p_Stream << "{";

p_Stream << "\"m_nUnk00\"" << ":" << simdjson::as_json_string(s_Object->m_nUnk00) << ",";
p_Stream << "\"m_nUnk01\"" << ":" << simdjson::as_json_string(s_Object->m_nUnk01) << ",";
p_Stream << "\"m_eKind\"" << ":" << simdjson::as_json_string(EAttributeKind.at(s_Object->m_eKind)) << ",";
p_Stream << "\"m_eType\"" << ":" << simdjson::as_json_string(EAttributeType.at(s_Object->m_eType)) << ",";
p_Stream << "\"m_sName\"" << ":" << simdjson::as_json_string(s_Object->m_sName);

p_Stream << "}";
}

void SUIControlBlueprintPin::FromSimpleJson(simdjson::ondemand::value p_Document, void* p_Target)
void SAttributeInfo::FromSimpleJson(simdjson::ondemand::value p_Document, void* p_Target)
{
SUIControlBlueprintPin s_Object;


*reinterpret_cast<SUIControlBlueprintPin*>(p_Target) = s_Object;
}
SAttributeInfo s_Object;

void SUIControlBlueprintPin::Serialize(void* p_Object, ZHMSerializer& p_Serializer, zhmptr_t p_OwnOffset)
{
auto* s_Object = static_cast<SUIControlBlueprintPin*>(p_Object);

}
auto GetEnumValue = [](std::map<int32_t, std::string> map, std::string_view name)
{
for (auto s_Pair : map)
if (s_Pair.second == name)
return s_Pair.first;

ZHMTypeInfo SUIControlBlueprintProperty::TypeInfo = ZHMTypeInfo("SUIControlBlueprintProperty", sizeof(SUIControlBlueprintProperty), alignof(SUIControlBlueprintProperty), WriteSimpleJson, FromSimpleJson, Serialize);
return -1;
};

void SUIControlBlueprintProperty::WriteSimpleJson(void* p_Object, std::ostream& p_Stream)
{
p_Stream << "{";
s_Object.m_sName = std::string_view(p_Document["m_sName"]);

auto s_Object = static_cast<SUIControlBlueprintProperty*>(p_Object);
// This could be simplified by just outputting a number, but this is a bit more friendly.
int32_t s_Value = GetEnumValue(EAttributeKind, std::string_view(p_Document["m_eKind"]));
if (s_Value == -1)
throw std::runtime_error("Invalid m_eKind enum.");
s_Object.m_eKind = s_Value;

p_Stream << "\"m_nUnk00\"" << ":" << simdjson::as_json_string(s_Object->m_nUnk00) << ",";
p_Stream << "\"m_nUnk01\"" << ":" << simdjson::as_json_string(s_Object->m_nUnk01) << ",";
p_Stream << "\"m_sName\"" << ":" << simdjson::as_json_string(s_Object->m_sName) << ",";
p_Stream << "\"m_nUnk02\"" << ":" << simdjson::as_json_string(s_Object->m_nUnk02) << ",";
p_Stream << "\"m_nPropertyId\"" << ":" << simdjson::as_json_string(s_Object->m_nPropertyId) << ",";
s_Value = GetEnumValue(EAttributeType, std::string_view(p_Document["m_eType"]));
if (s_Value == -1)
throw std::runtime_error("Invalid m_eType enum.");
s_Object.m_eType = s_Value;

p_Stream << "}";
*reinterpret_cast<SAttributeInfo*>(p_Target) = s_Object;
}

void SUIControlBlueprintProperty::FromSimpleJson(simdjson::ondemand::value p_Document, void* p_Target)
void SAttributeInfo::Serialize(void* p_Object, ZHMSerializer& p_Serializer, zhmptr_t p_OwnOffset)
{
SUIControlBlueprintProperty s_Object;
auto* s_Object = static_cast<SAttributeInfo*>(p_Object);

*reinterpret_cast<SUIControlBlueprintProperty*>(p_Target) = s_Object;
}
// Write the kind and type
p_Serializer.PatchValue<int32_t>(p_OwnOffset + offsetof(SAttributeInfo, m_eKind), s_Object->m_eKind);
p_Serializer.PatchValue<int32_t>(p_OwnOffset + offsetof(SAttributeInfo, m_eType), s_Object->m_eType);

void SUIControlBlueprintProperty::Serialize(void* p_Object, ZHMSerializer& p_Serializer, zhmptr_t p_OwnOffset)
{
auto* s_Object = static_cast<SUIControlBlueprintProperty*>(p_Object);

// And now the name
ZString::Serialize(&s_Object->m_sName, p_Serializer, p_OwnOffset + offsetof(SAttributeInfo, m_sName));
}

ZHMTypeInfo SUIControlBlueprint::TypeInfo = ZHMTypeInfo("SUIControlBlueprint", sizeof(SUIControlBlueprint), alignof(SUIControlBlueprint), WriteSimpleJson, FromSimpleJson, Serialize);

void SUIControlBlueprint::WriteSimpleJson(void* p_Object, std::ostream& p_Stream)
{
p_Stream << "{";
auto s_Object = *static_cast<SUIControlBlueprint*>(p_Object);

p_Stream << "{" << "\"m_aPins\":[";

// We do it this way since it's all actually just 1 array of a "control type" (SAttributeInfo)
// in all games, pins come before properties, so that's how the commas work.
for (size_t i = 0; i < s_Object.m_aAttributes.size(); ++i)
{
auto& s_Attribute = s_Object.m_aAttributes[i];

// Skip properties
if (s_Attribute.m_eKind == 0) continue;

auto s_Object = static_cast<SUIControlBlueprint*>(p_Object);
// Add comma
if (i != 0) p_Stream << ",";

p_Stream << "\"m_aPins\"" << ":[";
SAttributeInfo::WriteSimpleJson(&s_Attribute, p_Stream);
}

for (size_t i = 0; i < s_Object->m_aPins.size(); ++i)
p_Stream << "]," << "\"m_aProperties\":[";

for (size_t i = 0; i < s_Object.m_aAttributes.size(); ++i)
{
auto& s_Item = s_Object->m_aPins[i];
auto& s_Attribute = s_Object.m_aAttributes[i];

// Skip pins
if (s_Attribute.m_eKind != 0) continue;

SUIControlBlueprintPin::WriteSimpleJson(&s_Item, p_Stream);
SAttributeInfo::WriteSimpleJson(&s_Attribute, p_Stream);

if (i < s_Object->m_aPins.size() - 1)
// Add comma
if (i < s_Object.m_aAttributes.size() - 1)
p_Stream << ",";
}

p_Stream << "],";
p_Stream << "]}";
}

p_Stream << "\"m_aProperties\"" << ":[";
void SUIControlBlueprint::FromSimpleJson(simdjson::ondemand::value p_Document, void* p_Target)
{
SUIControlBlueprint s_Object;

for (size_t i = 0; i < s_Object->m_aProperties.size(); ++i)
{
auto& s_Item = s_Object->m_aProperties[i];
uint32_t s_Size = 0;

simdjson::ondemand::array s_Pins = p_Document["m_aPins"];
s_Size += s_Pins.count_elements();

SUIControlBlueprintProperty::WriteSimpleJson(&s_Item, p_Stream);
simdjson::ondemand::array s_Properties = p_Document["m_aProperties"];
s_Size += s_Properties.count_elements();

if (i < s_Object->m_aProperties.size() - 1)
p_Stream << ",";
s_Object.m_aAttributes.resize(s_Size);
}

p_Stream << "]";
size_t s_Index = 0;
{
simdjson::ondemand::array s_Pins = p_Document["m_aPins"];

p_Stream << "}";
}
for (simdjson::ondemand::value s_Pin : s_Pins)
{
SAttributeInfo s_Attribute;
SAttributeInfo::FromSimpleJson(s_Pin, &s_Attribute);
s_Object.m_aAttributes[s_Index++] = s_Attribute;
}
}

void SUIControlBlueprint::FromSimpleJson(simdjson::ondemand::value p_Document, void* p_Target)
{
throw std::runtime_error("Serializing SUIControlBlueprints is not currently supported.");
{
simdjson::ondemand::array s_Properties = p_Document["m_aProperties"];

/*SUIControlBlueprint s_Object;
for (simdjson::ondemand::value s_Property : s_Properties)
{
SAttributeInfo s_Attribute;
SAttributeInfo::FromSimpleJson(s_Property, &s_Attribute);
s_Object.m_aAttributes[s_Index++] = s_Attribute;
}
}

*reinterpret_cast<SUIControlBlueprint*>(p_Target) = s_Object;*/
*reinterpret_cast<SUIControlBlueprint*>(p_Target) = s_Object;
}

void SUIControlBlueprint::Serialize(void* p_Object, ZHMSerializer& p_Serializer, zhmptr_t p_OwnOffset)
{
auto* s_Object = static_cast<SUIControlBlueprint*>(p_Object);


TArray<SAttributeInfo>::Serialize(&s_Object->m_aAttributes, p_Serializer, p_OwnOffset + offsetof(SUIControlBlueprint, m_aAttributes));
}

ZHMTypeInfo SEnumType::TypeInfo = ZHMTypeInfo("SEnumType", sizeof(SEnumType), alignof(SEnumType), WriteSimpleJson, FromSimpleJson, Serialize);
25 changes: 4 additions & 21 deletions Libraries/ResourceLib/Src/ZHM/ZHMCustomTypes.h
Original file line number Diff line number Diff line change
@@ -69,35 +69,19 @@ class SAudioStateBlueprintData
TArray<ZString> m_aStates;
};

class SUIControlBlueprintPin
class SAttributeInfo
{
public:
static ZHMTypeInfo TypeInfo;
static void WriteSimpleJson(void* p_Object, std::ostream& p_Stream);
static void FromSimpleJson(simdjson::ondemand::value p_Document, void* p_Target);
static void Serialize(void* p_Object, ZHMSerializer& p_Serializer, zhmptr_t p_OwnOffset);

int32_t m_nUnk00;
int32_t m_nUnk01;
uint32_t m_eKind;
uint32_t m_eType;
ZString m_sName;
};

class SUIControlBlueprintProperty
{
public:
static ZHMTypeInfo TypeInfo;
static void WriteSimpleJson(void* p_Object, std::ostream& p_Stream);
static void FromSimpleJson(simdjson::ondemand::value p_Document, void* p_Target);
static void Serialize(void* p_Object, ZHMSerializer& p_Serializer, zhmptr_t p_OwnOffset);

int32_t m_nUnk00;
int32_t m_nUnk01;
ZString m_sName;
uint64_t m_nUnk02;
uint32_t m_nPropertyId;
char _pad[4];
};

class SUIControlBlueprint
{
public:
@@ -106,8 +90,7 @@ class SUIControlBlueprint
static void FromSimpleJson(simdjson::ondemand::value p_Document, void* p_Target);
static void Serialize(void* p_Object, ZHMSerializer& p_Serializer, zhmptr_t p_OwnOffset);

TArray<SUIControlBlueprintPin> m_aPins;
TArray<SUIControlBlueprintProperty> m_aProperties;
TArray<SAttributeInfo> m_aAttributes;
};

class SEnumType
2 changes: 1 addition & 1 deletion Libraries/ResourceLib/Src/ZHM/ZString.cpp
Original file line number Diff line number Diff line change
@@ -53,7 +53,7 @@ void ZString::Serialize(void* p_Object, ZHMSerializer& p_Serializer, zhmptr_t p_

// Some strings can have the allocated flag, so we rewrite the length without it
// cause otherwise the game will try to do some weird re-allocation shit and crash spectacularly.
p_Serializer.PatchValue<int32_t>(p_OwnOffset + offsetof(ZString, m_nLength), s_Object->size() | 0x40000000);
p_Serializer.PatchValue<int64_t>(p_OwnOffset + offsetof(ZString, m_nLength), s_Object->size() | 0x40000000);
p_Serializer.PatchPtr(p_OwnOffset + offsetof(ZString, m_pChars), s_StrDataOffset);
}

6 changes: 3 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
@@ -15,9 +15,9 @@ Currently supported games and resource types:

| Game | Supported Resources |
| ---- | ------------------- |
| Hitman 3 | `TEMP`, `TBLU`, `AIRG`, `ATMD`*, `CBLU`, `CPPT`, `CRMD`, `DSWB`, `ECPB`, `GFXF`, `GIDX`, `VIDB`, `WSGB`, `ENUM`, `RTLV` |
| Hitman 2 | `TEMP`, `TBLU`, `AIRG`, `ATMD`*, `CBLU`, `CPPT`, `CRMD`, `DSWB`, `ECPB`, `GFXF`, `GIDX`, `VIDB`, `WSGB`, `ENUM`, `RTLV` |
| Hitman 2016 | `TEMP`, `TBLU`, `AIRG`, `ATMD`*, `CBLU`, `CPPT`, `CRMD`, `DSWB`, `GFXF`, `GIDX`, `VIDB`, `WSGB`, `RTLV` |
| Hitman 3 | `TEMP`, `TBLU`, `AIRG`, `ATMD`*, `CBLU`, `CPPT`, `CRMD`, `DSWB`, `ECPB`, `GFXF`, `GIDX`, `VIDB`, `WSGB`, `ENUM`, `RTLV`, `UICB` |
| Hitman 2 | `TEMP`, `TBLU`, `AIRG`, `ATMD`*, `CBLU`, `CPPT`, `CRMD`, `DSWB`, `ECPB`, `GFXF`, `GIDX`, `VIDB`, `WSGB`, `ENUM`, `RTLV`, `UICB` |
| Hitman 2016 | `TEMP`, `TBLU`, `AIRG`, `ATMD`*, `CBLU`, `CPPT`, `CRMD`, `DSWB`, `GFXF`, `GIDX`, `VIDB`, `WSGB`, `RTLV`, `UICB` |
| Hitman Absolution* | `TEMP`, `TBLU`, `AIRG`, `CBLU`, `CPPT`, `CRMD`, `DSWB`, `GFXF`, `GIDX`, `WSGB` |

*`*` Experimental*