Skip to content
This repository was archived by the owner on Jan 1, 2025. It is now read-only.

Commit 49977d9

Browse files
authored
Bug Bash 5/24 (#36)
* stamp * stamp * TPS support * big commit
1 parent 92746be commit 49977d9

10 files changed

+196
-138
lines changed

src/BL2-SDK.cpp

+41-24
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@ namespace BL2SDK
3737
UObject *engine = nullptr;
3838
CHookManager *HookManager = nullptr;
3939
bool injectedCallNext = false;
40+
bool CallPostEdit = true;
4041

4142
CPythonInterface *Python;
4243

@@ -318,6 +319,11 @@ namespace BL2SDK
318319
}
319320
};
320321

322+
void KeepAlive(UObject *obj) {
323+
for (UObject *outer = obj; outer; outer = outer->Outer)
324+
outer->ObjectFlags.A |= 0x4000;
325+
}
326+
321327
UObject *ConstructObject(UClass* Class, UObject* Outer, FName Name, unsigned int SetFlags, unsigned int InternalSetFlags, UObject* Template, FOutputDevice *Error, void* InstanceGraph, int bAssumeTemplateIsArchetype)
322328
{
323329
if (!Error) {
@@ -345,28 +351,39 @@ namespace BL2SDK
345351
return HookManager->Remove(funcName, hookName);
346352
}
347353

348-
UObject *LoadTexture(char *Filename, char *TextureName) {
349-
UTexture2D *NewTexture = (UTexture2D *)UObject::Find("Texture2D", std::string("Transient.") + TextureName);
350-
if (NewTexture)
351-
return NewTexture;
352-
int x, y, n;
353-
unsigned char *data = stbi_load(Filename, &x, &y, &n, 4);
354-
if (!data)
355-
throw std::exception("Unable to parse image file");
356-
NewTexture = (UTexture2D *)ConstructObject(UObject::FindClass("Texture2D"), GetEngine()->Outer, FName(TextureName), 0x83, 0, nullptr, nullptr, nullptr, false);
357-
if (!NewTexture)
358-
return nullptr;
359-
NewTexture->ObjectFlags.A |= 0x4000;
360-
NewTexture->SizeX = x;
361-
NewTexture->OriginalSizeX = x;
362-
NewTexture->SizeY = y;
363-
NewTexture->OriginalSizeY = y;
364-
NewTexture->Format = 2;
365-
NewTexture->Mips.Data.Dummy = (int)data;
366-
NewTexture->Mips.ArrayMax = 1;
367-
NewTexture->Mips.ArrayNum = 1;
368-
NewTexture->ResidentMips = 1;
369-
NewTexture->RequestedMips = 1;
370-
return (UObject *)NewTexture;
371-
}
354+
//UObject *LoadTexture(char *Filename, char *TextureName) {
355+
// UTexture2D *NewTexture = (UTexture2D *)UObject::Find("Texture2D", std::string("Transient.") + TextureName);
356+
// if (NewTexture)
357+
// return NewTexture;
358+
// int x, y, n;
359+
// unsigned char *data = stbi_load(Filename, &x, &y, &n, 4);
360+
// if (!data)
361+
// throw std::exception("Unable to parse image file");
362+
// NewTexture = (UTexture2D *)ConstructObject(UObject::FindClass("Texture2D"), GetEngine()->Outer, FName(TextureName), 0x83, 0, nullptr, nullptr, nullptr, false);
363+
// UTexture2D *DefaultTexture = (UTexture2D *)UObject::Find("Texture2D", "Engine.Default__Texture2D ");
364+
// if (!NewTexture)
365+
// return nullptr;
366+
// NewTexture->ObjectFlags.A |= 0x4000;
367+
// NewTexture->SizeX = x;
368+
// NewTexture->OriginalSizeX = x;
369+
// NewTexture->SizeY = y;
370+
// NewTexture->OriginalSizeY = y;
371+
// NewTexture->Format = 2;
372+
// FTexture2DMipMap *MipsData = (FTexture2DMipMap *)calloc(1, sizeof(FTexture2DMipMap));
373+
// MipsData->SizeX = x;
374+
// MipsData->SizeY = y;
375+
// memcpy(&MipsData->Data, &DefaultTexture->Mips.Data[0]->Data, sizeof(FUntypedBulkData_Mirror));
376+
// MipsData->Data.bShouldFreeOnEmpty = 0;
377+
// MipsData->Data.BulkData.Dummy = (int)data;
378+
// NewTexture->Mips.Data = (FTexture2DMipMap **)malloc(sizeof(FTexture2DMipMap *));
379+
// NewTexture->Mips.Data[0] = MipsData;
380+
// NewTexture->Mips.Count = 1;
381+
// NewTexture->Mips.Max = 1;
382+
// NewTexture->ResidentMips = 1;
383+
// FPropertyChangedEvent ChangeEvent {};
384+
// ChangeEvent.Property = (UProperty *)UObject::Find("BoolProperty", "Engine.Texture.SRGB");
385+
// ChangeEvent.ChangeType = 1;
386+
// NewTexture->PostEditChangeProperty(&ChangeEvent);
387+
// return (UObject *)NewTexture;
388+
//}
372389
}

src/BL2SDK/Core_functions.cpp

+82-80
Original file line numberDiff line numberDiff line change
@@ -115,99 +115,96 @@ pybind11::object FHelper::GetProperty(UProperty *prop) {
115115
return py::none();
116116
}
117117

118-
bool FHelper::SetProperty(class UStructProperty *prop, py::object val) {
118+
void FHelper::SetProperty(class UStructProperty *prop, py::object val) {
119119
if (py::isinstance<py::tuple>(val))
120120
{
121121
py::tuple tup = (py::tuple)val;
122122

123123
unsigned int currentIndex = 0;
124+
for (UProperty* Child = (UProperty *)prop->GetStruct()->Children; Child; Child = (UProperty *)Child->Next)
125+
currentIndex++;
126+
127+
if (tup.size() > currentIndex) {
128+
throw std::exception(Util::Format("FHelper::SetProperty: Not all tuple values converted for struct!\n").c_str());
129+
}
130+
131+
currentIndex = 0;
124132
for (UProperty* Child = (UProperty *)prop->GetStruct()->Children; Child; Child = (UProperty *)Child->Next) {
125133
Logging::LogD("Child = %s, %d\n", Child->GetFullName().c_str(), Child->Offset_Internal);
126134
if (currentIndex < tup.size())
127135
((FHelper *)(((char *)this) + prop->Offset_Internal))->SetProperty(Child, tup[currentIndex++]);
128136
}
129-
if (tup.size() > currentIndex) {
130-
Logging::LogF("Not all tuple values converted for struct!\n");
131-
return false;
132-
}
133-
return true;
134137
}
135-
else if (py::isinstance<FStruct>(val)) {
136-
Logging::LogD("FSTRUCT OMG\n");
137-
}
138-
return false;
138+
else
139+
throw std::exception(Util::Format("FHelper::SetProperty: Got unexpected type, expected tuple!\n").c_str());
139140
}
140141

141-
bool FHelper::SetProperty(class UStrProperty *prop, py::object val) {
142+
void FHelper::SetProperty(class UStrProperty *prop, py::object val) {
142143
if (!py::isinstance<py::str>(val))
143-
return false;
144+
throw std::exception(Util::Format("FHelper::SetProperty: Got unexpected type, expected string!\n").c_str());
144145
memcpy(((char *)this) + prop->Offset_Internal, &FString(val.cast<std::string>().c_str()), sizeof(FString));
145-
return true;
146146
}
147147

148-
bool FHelper::SetProperty(class UObjectProperty *prop, py::object val) {
149-
if (!py::isinstance<UObject>(val))
150-
return false;
148+
void FHelper::SetProperty(class UObjectProperty *prop, py::object val) {
149+
if (!py::isinstance<UObject>(val) && !py::isinstance<py::none>(val))
150+
throw std::exception(Util::Format("FHelper::SetProperty: Got unexpected type, expected UObject!\n").c_str());
151151
((UObject **)(((char *)this) + prop->Offset_Internal))[0] = val.cast<UObject *>();
152-
return true;
153152
}
154153

155-
bool FHelper::SetProperty(class UComponentProperty *prop, py::object val) {
156-
if (!py::isinstance<UComponent>(val))
157-
return false;
154+
void FHelper::SetProperty(class UComponentProperty *prop, py::object val) {
155+
if (!py::isinstance<UComponent>(val) && !py::isinstance<py::none>(val))
156+
throw std::exception(Util::Format("FHelper::SetProperty: Got unexpected type, expected UComponent!\n").c_str());
158157
((UComponent **)(((char *)this) + prop->Offset_Internal))[0] = val.cast<UComponent *>();
159-
return true;
160158
}
161159

162-
bool FHelper::SetProperty(class UClassProperty *prop, py::object val) {
163-
if (!py::isinstance<UClass>(val))
164-
return false;
160+
void FHelper::SetProperty(class UClassProperty *prop, py::object val) {
161+
if (!py::isinstance<UClass>(val) && !py::isinstance<py::none>(val))
162+
throw std::exception(Util::Format("FHelper::SetProperty: Got unexpected type, expected UClass!\n").c_str());
165163
((UClass **)(((char *)this) + prop->Offset_Internal))[0] = val.cast<UClass *>();
166-
return true;
167164
}
168165

169-
bool FHelper::SetProperty(class UNameProperty *prop, py::object val) {
166+
void FHelper::SetProperty(class UNameProperty *prop, py::object val) {
170167
if (!py::isinstance<py::str>(val))
171-
return false;
168+
throw std::exception(Util::Format("FHelper::SetProperty: Got unexpected type, expected string!\n").c_str());
172169
memcpy(((char *)this) + prop->Offset_Internal, &FName(val.cast<std::string>().c_str()), sizeof(FName));
173-
return true;
174170
}
175171

176-
bool FHelper::SetProperty(class UInterfaceProperty *prop, py::object val) {
177-
if (!py::isinstance<UInterface>(val))
178-
return false;
179-
((UInterface **)(((char *)this) + prop->Offset_Internal))[0] = val.cast<UInterface *>();
180-
return true;
172+
void FHelper::SetProperty(class UInterfaceProperty *prop, py::object val) {
173+
if (!py::isinstance<UObject>(val) && !py::isinstance<py::none>(val))
174+
throw std::exception(Util::Format("FHelper::SetProperty: Got unexpected type, expected UObject!\n").c_str());
175+
if (py::isinstance<py::none>(val))
176+
((FScriptInterface *)(((char *)this) + prop->Offset_Internal))[0] = FScriptInterface{0, 0};
177+
else {
178+
UObject *ObjVal = val.cast<UObject *>();
179+
FScriptInterface interf = ObjVal->QueryInterface(prop->GetInterfaceClass());
180+
((FScriptInterface *)(((char *)this) + prop->Offset_Internal))[0] = interf;
181+
}
181182
}
182183

183-
bool FHelper::SetProperty(class UDelegateProperty *prop, py::object val) {
184+
void FHelper::SetProperty(class UDelegateProperty *prop, py::object val) {
184185
if (!py::isinstance<FScriptDelegate>(val))
185-
return false;
186+
throw std::exception(Util::Format("FHelper::SetProperty: Got unexpected type, expected FScriptDelegate!\n").c_str());
186187
memcpy(((char *)this) + prop->Offset_Internal, &FScriptDelegate(val.cast<FScriptDelegate>()), sizeof(FScriptDelegate));
187-
return true;
188188
}
189189

190-
bool FHelper::SetProperty(class UFloatProperty *prop, py::object val) {
190+
void FHelper::SetProperty(class UFloatProperty *prop, py::object val) {
191191
Logging::LogD("Set %f\n", val.cast<float>());
192192
((float *)(((char *)this) + prop->Offset_Internal))[0] = val.cast<float>();
193-
return true;
194193
}
195194

196-
bool FHelper::SetProperty(class UIntProperty *prop, py::object val) {
195+
void FHelper::SetProperty(class UIntProperty *prop, py::object val) {
197196
if (!py::isinstance<py::int_>(val))
198-
return false;
197+
throw std::exception(Util::Format("FHelper::SetProperty: Got unexpected type, expected int!\n").c_str());
199198
((int *)(((char *)this) + prop->Offset_Internal))[0] = val.cast<int>();
200-
return true;
201199
}
202200

203-
bool FHelper::SetProperty(class UByteProperty *prop, py::object val) {
204-
if (!py::isinstance<int>(val) && val.cast<int>() <= 255)
205-
return false;
201+
void FHelper::SetProperty(class UByteProperty *prop, py::object val) {
202+
if (!py::isinstance<py::int_>(val))
203+
throw std::exception(Util::Format("FHelper::SetProperty: Got unexpected type, expected (char!\n").c_str());
206204
(((char *)this) + prop->Offset_Internal)[0] = (char)val.cast<int>();
207-
return true;
208205
}
209206

210-
bool FHelper::SetProperty(class UBoolProperty *prop, py::object val) {
207+
void FHelper::SetProperty(class UBoolProperty *prop, py::object val) {
211208
try {
212209
Logging::LogD("SetBoolProperty %d, mask: 0x%x, base: 0x%x, offset: 0x%x\n", val.cast<bool>(), prop->GetMask(), this, prop->Offset_Internal);
213210
if (val.cast<bool>())
@@ -216,60 +213,59 @@ bool FHelper::SetProperty(class UBoolProperty *prop, py::object val) {
216213
((unsigned int *)(((char *)this) + prop->Offset_Internal))[0] &= ~prop->GetMask();
217214
}
218215
catch (std::exception e) {
219-
Logging::LogF(e.what());
216+
throw std::exception(Util::Format("FHelper::SetProperty: %s\n", e.what()).c_str());
220217
}
221-
return true;
222218
}
223219

224-
bool FHelper::SetProperty(class UArrayProperty *prop, py::object val) {
220+
void FHelper::SetProperty(class UArrayProperty *prop, py::object val) {
225221
if (!py::isinstance<py::sequence>(val))
226-
return false;
222+
throw std::exception(Util::Format("FHelper::SetProperty: Got unexpected type, expected list!\n").c_str());
227223
auto s = py::reinterpret_borrow<py::sequence>(val);
228-
Logging::LogD("A\n");
229-
char *Data = (char *)((tMalloc)BL2SDK::pGMalloc[0]->VfTable[1])(BL2SDK::pGMalloc[0], prop->GetInner()->ElementSize * s.size(), 8);
230-
Logging::LogD("C %d %d %p %p %d %p\n", prop->GetInner()->ElementSize, prop->Offset_Internal, this, Data, s.size(), (TArray<void *> *)(((char *)this) + prop->Offset_Internal));
231-
memset(Data, 0, prop->GetInner()->ElementSize * s.size());
232-
((TArray<void *> *)(((char *)this) + prop->Offset_Internal))->Data = (void **)Data;
233-
((TArray<void *> *)(((char *)this) + prop->Offset_Internal))->Count = s.size();
234-
((TArray<void *> *)(((char *)this) + prop->Offset_Internal))->Max = s.size();
224+
if (s.size() > ((TArray<void *> *)(((char *)this) + prop->Offset_Internal))->Count) {
225+
char *Data = (char *)((tMalloc)BL2SDK::pGMalloc[0]->VfTable[1])(BL2SDK::pGMalloc[0], prop->GetInner()->ElementSize * s.size(), 8);
226+
memset(Data, 0, prop->GetInner()->ElementSize * s.size());
227+
((TArray<char> *)(((char *)this) + prop->Offset_Internal))->Data = Data;
228+
((TArray<char> *)(((char *)this) + prop->Offset_Internal))->Max = s.size();
229+
}
230+
((TArray<char> *)(((char *)this) + prop->Offset_Internal))->Count = s.size();
231+
char *Data = ((TArray<char> *)(((char *)this) + prop->Offset_Internal))->Data;
235232
int x = 0;
236233
for (auto it : val) {
237-
Logging::LogD("%x\n", (Data + prop->GetInner()->ElementSize * x));
238234
((FHelper *)(Data + prop->GetInner()->ElementSize * x++))->SetProperty(prop->GetInner(), py::reinterpret_borrow<py::object>(it));
239235
}
240-
return true;
241236
}
242237

243-
bool FHelper::SetProperty(class UProperty *prop, py::object val) {
238+
void FHelper::SetProperty(class UProperty *prop, py::object val) {
244239
Logging::LogD("FHelper::SetProperty Called with '%s'\n", prop->GetFullName().c_str());
240+
bool ret = false;
245241
if (!strcmp(prop->Class->GetName().c_str(), "StructProperty"))
246-
return SetProperty((UStructProperty *)prop, val);
242+
SetProperty((UStructProperty *)prop, val);
247243
else if (!strcmp(prop->Class->GetName().c_str(), "StrProperty"))
248-
return SetProperty((UStrProperty *)prop, val);
244+
SetProperty((UStrProperty *)prop, val);
249245
else if (!strcmp(prop->Class->GetName().c_str(), "ObjectProperty"))
250-
return SetProperty((UObjectProperty *)prop, val);
246+
SetProperty((UObjectProperty *)prop, val);
251247
else if (!strcmp(prop->Class->GetName().c_str(), "ComponentProperty"))
252-
return SetProperty((UComponentProperty *)prop, val);
248+
SetProperty((UComponentProperty *)prop, val);
253249
else if (!strcmp(prop->Class->GetName().c_str(), "ClassProperty"))
254-
return SetProperty((UClassProperty *)prop, val);
250+
SetProperty((UClassProperty *)prop, val);
255251
else if (!strcmp(prop->Class->GetName().c_str(), "NameProperty"))
256-
return SetProperty((UNameProperty *)prop, val);
252+
SetProperty((UNameProperty *)prop, val);
257253
else if (!strcmp(prop->Class->GetName().c_str(), "IntProperty"))
258-
return SetProperty((UIntProperty *)prop, val);
254+
SetProperty((UIntProperty *)prop, val);
259255
else if (!strcmp(prop->Class->GetName().c_str(), "InterfaceProperty"))
260-
return SetProperty((UInterfaceProperty *)prop, val);
256+
SetProperty((UInterfaceProperty *)prop, val);
261257
else if (!strcmp(prop->Class->GetName().c_str(), "FloatProperty"))
262-
return SetProperty((UFloatProperty *)prop, val);
258+
SetProperty((UFloatProperty *)prop, val);
263259
else if (!strcmp(prop->Class->GetName().c_str(), "DelegateProperty"))
264-
return SetProperty((UDelegateProperty *)prop, val);
260+
SetProperty((UDelegateProperty *)prop, val);
265261
else if (!strcmp(prop->Class->GetName().c_str(), "ByteProperty"))
266-
return SetProperty((UByteProperty *)prop, val);
262+
SetProperty((UByteProperty *)prop, val);
267263
else if (!strcmp(prop->Class->GetName().c_str(), "BoolProperty"))
268-
return SetProperty((UBoolProperty *)prop, val);
264+
SetProperty((UBoolProperty *)prop, val);
269265
else if (!strcmp(prop->Class->GetName().c_str(), "ArrayProperty"))
270-
return SetProperty((UArrayProperty *)prop, val);
271-
throw std::exception(Util::Format("FHelper::SetProperty got unexpected property type '%s'", prop->GetFullName().c_str()).c_str());
272-
return false;
266+
SetProperty((UArrayProperty *)prop, val);
267+
else
268+
throw std::exception(Util::Format("FHelper::SetProperty got unexpected property type '%s'", prop->GetFullName().c_str()).c_str());
273269
}
274270

275271
TArray< UObject* >* UObject::GObjects()
@@ -429,15 +425,21 @@ pybind11::object UObject::GetProperty(std::string PropName) {
429425
return pybind11::none();
430426
}
431427

432-
bool UObject::SetProperty(std::string& PropName, py::object val) {
428+
void UObject::SetProperty(std::string& PropName, py::object val) {
433429
class UObject *obj = this->Class->FindChildByName(FName(PropName));
434430
if (!obj)
435-
return false;
431+
return;
436432
auto prop = reinterpret_cast<UProperty *>(obj);
437433
if (!strcmp(obj->Class->GetName().c_str(), "Function"))
438-
return ((FHelper *)((char *)this))->SetProperty((UObjectProperty *)prop, val);
434+
((FHelper *)((char *)this))->SetProperty((UObjectProperty *)prop, val);
439435
else
440-
return ((FHelper *)((char *)this))->SetProperty(prop, val);
436+
((FHelper *)((char *)this))->SetProperty(prop, val);
437+
if (BL2SDK::CallPostEdit) {
438+
FPropertyChangedEvent ChangeEvent{};
439+
ChangeEvent.Property = prop;
440+
ChangeEvent.ChangeType = 1;
441+
PostEditChangeProperty(&ChangeEvent);
442+
}
441443
}
442444

443445

@@ -3865,7 +3867,7 @@ FScriptInterface UObject::QueryInterface(class UClass* InterfaceClass)
38653867
{
38663868
static auto fn = (UFunction *)UObject::Find("Function", "Core.Object.QueryInterface");
38673869

3868-
UObject_QueryInterface_Params params;
3870+
struct UObject_QueryInterface_Params params;
38693871
params.InterfaceClass = InterfaceClass;
38703872

38713873
auto flags = fn->FunctionFlags;

src/BL2SDK/GFxUI_functions.cpp

-2
Original file line numberDiff line numberDiff line change
@@ -209,7 +209,6 @@ class UAkEvent* UGFxManager::LookupSound(const struct FName& UIEvent)
209209
return params.ReturnValue;
210210
}
211211

212-
213212
// Function GFxUI.GFxManager.ShowDialog
214213
// (Event, Public)
215214
// Parameters:
@@ -232,7 +231,6 @@ FScriptInterface UGFxManager::ShowDialog(class APlayerController* PC)
232231
return params.ReturnValue;
233232
}
234233

235-
236234
// Function GFxUI.GFxManager.Init
237235
// (Defined, Event, Public)
238236
// Parameters:

src/CPythonInterface.cpp

+3-1
Original file line numberDiff line numberDiff line change
@@ -75,11 +75,12 @@ PYBIND11_EMBEDDED_MODULE(bl2sdk, m)
7575

7676
m.def("Log", [](std::string in) { Logging::LogPy(in.c_str()); });
7777
m.def("LoadPackage", &BL2SDK::LoadPackage, py::arg("filename"), py::arg("flags") = 0, py::arg("force") = false);
78+
m.def("KeepAlive", &BL2SDK::KeepAlive);
7879
m.def("FindObject", [](char *ClassName, char *ObjectFullName) { return UObject::Find(ClassName, ObjectFullName); }, py::return_value_policy::reference);
7980
m.def("FindObject", [](UClass *Class, char *ObjectFullName) { return UObject::Find(Class, ObjectFullName); }, py::return_value_policy::reference);
8081
m.def("LoadObject", [](char *ClassName, char *ObjectFullName) { return UObject::Load(ClassName, ObjectFullName); }, py::return_value_policy::reference);
8182
m.def("LoadObject", [](UClass *Class, char *ObjectFullName) { return UObject::Load(Class, ObjectFullName); }, py::return_value_policy::reference);
82-
m.def("LoadTexture", &BL2SDK::LoadTexture, py::return_value_policy::reference);
83+
//m.def("LoadTexture", &BL2SDK::LoadTexture, py::return_value_policy::reference);
8384
m.def("SetLoggingLevel", &Logging::SetLoggingLevel);
8485
m.def("ConstructObject", &BL2SDK::ConstructObject, "Construct Objects", py::arg("Class"), py::arg("Outer") = BL2SDK::GetEngine()->Outer, py::arg("Name") = FName(), py::arg("SetFlags") = 0x1, py::arg("InternalSetFlags") = 0x00, py::arg("Template") = (UObject*)nullptr, py::arg("Error") = (FOutputDevice *)nullptr, py::arg("InstanceGraph") = (void*)nullptr, py::arg("bAssumeTemplateIsArchetype") = (int)0, py::return_value_policy::reference);
8586
m.def("ConstructObject", [](char *ClassName, UObject* Outer, FName Name, unsigned int SetFlags, unsigned int InternalSetFlags, UObject* Template, FOutputDevice *Error, void* InstanceGraph, int bAssumeTemplateIsArchetype) {
@@ -90,6 +91,7 @@ PYBIND11_EMBEDDED_MODULE(bl2sdk, m)
9091
m.def("RemoveHook", [](const std::string& funcName, const std::string& hookName) { BL2SDK::RemoveHook(funcName, hookName); });
9192
m.def("DoInjectedCallNext", &BL2SDK::doInjectedCallNext);
9293
m.def("LogAllCalls", &BL2SDK::LogAllCalls);
94+
m.def("CallPostEdit", [](bool NewValue) { BL2SDK::CallPostEdit = NewValue; });
9395
}
9496

9597
void AddToConsoleLog(UConsole *console, FString input) {

0 commit comments

Comments
 (0)