Skip to content

Commit 0c399b1

Browse files
committed
fix(lua): add TMap userdata round-trip support
- Implement TMap userdata handling in push_mapproperty Operation::Set - Support copying TMap userdata with proper key-value pair handling - Handle empty maps and rehashing after copy - Enable passing TMap properties as function parameters Completes container userdata support for TSet, TArray, and TMap
1 parent df2a19a commit 0c399b1

File tree

1 file changed

+65
-2
lines changed

1 file changed

+65
-2
lines changed

UE4SS/src/LuaType/LuaUObject.cpp

Lines changed: 65 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1275,9 +1275,72 @@ namespace RC::LuaType
12751275
case Operation::GetNonTrivialLocal:
12761276
map_to_lua_table(params.lua, params.property, params.data);
12771277
return;
1278-
case Operation::Set:
1279-
lua_table_to_map();
1278+
case Operation::Set: {
1279+
if (params.lua.is_userdata(params.stored_at_index))
1280+
{
1281+
// Handle TMap userdata
1282+
auto& lua_tmap = params.lua.get_userdata<TMap>(params.stored_at_index);
1283+
Unreal::FScriptMap* source_map = lua_tmap.get_remote_cpp_object();
1284+
1285+
Unreal::FMapProperty* map_property = static_cast<Unreal::FMapProperty*>(params.property);
1286+
FScriptMapInfo info(map_property->GetKeyProp(), map_property->GetValueProp());
1287+
if (!info.key || !info.value)
1288+
{
1289+
params.throw_error("push_mapproperty", "Invalid key or value property");
1290+
}
1291+
1292+
auto dest_map = new(params.data) Unreal::FScriptMap{};
1293+
1294+
// Copy elements from source to destination
1295+
Unreal::int32 max_index = source_map->GetMaxIndex();
1296+
for (Unreal::int32 i = 0; i < max_index; i++)
1297+
{
1298+
if (!source_map->IsValidIndex(i))
1299+
{
1300+
continue;
1301+
}
1302+
1303+
// Get source key/value pair
1304+
void* src_pair = source_map->GetData(i, info.layout);
1305+
1306+
// Add new entry to destination map
1307+
Unreal::int32 dest_index = dest_map->AddUninitialized(info.layout);
1308+
void* dest_pair = dest_map->GetData(dest_index, info.layout);
1309+
1310+
// Initialize the destination memory
1311+
Unreal::FMemory::Memzero(dest_pair, info.layout.SetLayout.Size);
1312+
1313+
// Copy key
1314+
info.key->CopySingleValueToScriptVM(dest_pair, src_pair);
1315+
1316+
// Copy value
1317+
void* src_value = static_cast<uint8_t*>(src_pair) + info.layout.ValueOffset;
1318+
void* dest_value = static_cast<uint8_t*>(dest_pair) + info.layout.ValueOffset;
1319+
info.value->CopySingleValueToScriptVM(dest_value, src_value);
1320+
}
1321+
1322+
// Rehash the destination map
1323+
dest_map->Rehash(info.layout,
1324+
[&](const void* src) -> Unreal::uint32 {
1325+
return info.key->GetValueTypeHash(src);
1326+
});
1327+
}
1328+
else if (params.lua.is_table(params.stored_at_index))
1329+
{
1330+
// TMap as table
1331+
lua_table_to_map();
1332+
}
1333+
else if (params.lua.is_nil(params.stored_at_index))
1334+
{
1335+
// Empty map
1336+
new(params.data) Unreal::FScriptMap{};
1337+
}
1338+
else
1339+
{
1340+
params.throw_error("push_mapproperty", "Parameter must be of type 'TMap' or table");
1341+
}
12801342
return;
1343+
}
12811344
case Operation::GetParam:
12821345
RemoteUnrealParam::construct(params.lua, params.data, params.base, params.property);
12831346
return;

0 commit comments

Comments
 (0)