Install Steam
login
|
language
简体中文 (Simplified Chinese)
繁體中文 (Traditional Chinese)
日本語 (Japanese)
한국어 (Korean)
ไทย (Thai)
Български (Bulgarian)
Čeština (Czech)
Dansk (Danish)
Deutsch (German)
Español - España (Spanish - Spain)
Español - Latinoamérica (Spanish - Latin America)
Ελληνικά (Greek)
Français (French)
Italiano (Italian)
Bahasa Indonesia (Indonesian)
Magyar (Hungarian)
Nederlands (Dutch)
Norsk (Norwegian)
Polski (Polish)
Português (Portuguese - Portugal)
Português - Brasil (Portuguese - Brazil)
Română (Romanian)
Русский (Russian)
Suomi (Finnish)
Svenska (Swedish)
Türkçe (Turkish)
Tiếng Việt (Vietnamese)
Українська (Ukrainian)
Report a translation problem
It appears that the API simply does not permit for-pairs-do loops on these tables, I don't know why 🤷
So I did the same as other mods: copy every key-value pair by explicitly naming it. For track tables it's ridiculous, 70+ hard-coded lines to copy a table 😖
but here are some the ingredients, I copied the sample code from several code pieces.
Technical for sol objects you want to get the metatable.
if (key ~= "new") then
local ok, v = pcall(tryUserdataObjGet, o, key)
if (ok) then
newobj[key] = dosomethingwithobj(v)
end
end
end
end
end
end[/code]
CommonAPI2 has a buildin dumper, and will be loaded technical in most lua states:
commonapi.dmp(object) So you can see the technical details
for trackTypeIndex, trackFileName in pairs(trackFileNames) do
local trackType = api.res.trackTypeRep.get(trackTypeIndex)
...
Thanks, yes I was just looking at that mod.lua a few minutes ago, but it looks like you did the same thing I did. When making a new track or module from existing ones, you copy each key-value pair explictly line by line. For example:
module.availability.yearFrom = props.yearFrom
module.availability.yearTo = props.yearTo
module.description.icon = props.icon
instead of something like: for k, v in pairs(props) do module[k] = v end, which is what I want to do. But the API rejects that kind of code on these tables.
Thanks, I think there is a lot of new info here that I need to learn...
I did not know that "userdata" is a Lua concept. I thought it was something unique to TpF2. I should have googled it 🤦♂️ I see not that userdata is described in the Lua programming manual so I need to study that...
I thought all these api.res.xTypeRep.get() results were already Lua tables, but you are saying they are not. This explains a lot of mysteries for me, because I am trying to use them like Lua tables.
What does "sol object" mean? I googled it but didn't find an answer for this context.
I read about Lua metatables before but I have not used them. I need to study this more. Thanks for the example.
Tracks have 70+ properties... That's 70+ hard-coded lines to do a 1-line copy.
But based on other reply it looks like I misunderstood what api.res.trackTypeRep.get() returns, I thought it was a Lua table, but apparently it's something else and I just need to learn the correct Lua commands to process it.
It will tell you the metatable name of the thing.
userdata => a opaque object created from the other side (binary, c interface)
metatable => a table with metafunctions and data that tells lua what to do with a table or object
SOL2 => wraps c++ objects into lua userdata together with some helpers ( https://github.com/ThePhD/sol2 )
The binary game is a compiled C++ binary, most languages uses 0 as first array index. LUA uses 1 as first array index.
SOL2 objects represent a pointer to some c++ object in TPF2 memory.
This means, most api functions will return some kind of object and you won't get simple lua tables.
Any pointer you received from a map to a the object will get invalid, if you alter the map or vector, like adding something. So special care need to taken.
Good example, it's not possible to hold entity components between game_script handleEvent function calls.
tr = api.res.trackTypeRep.get(0)
mt = getmetatable(tr)
for _, v in pairs(mt.__members) do print(v, tr[v]) end -- print track keys and values
I hate (the abuse of) metatables, but this could be a use case for them.
The original question about looping over a long list of pairs is only part of the topic now... "userdata" has always been a brick wall for me, couldn't even find read access to it, and didn't find any answers when I asked UG. But this thread is showing me that userdata can be accessed if I know the right syntax...
Ok so using the track example, here's its metatable:
First thing I noted is that __members is not in the list, but I can still access it:
I don't know why __members is "hidden". This is one of the most frustrating things about this API for me. I would not know it exists if @eis_os didn't mention it.
Anyhow using this then I could use code similar to @lollus' example. Note some of the values are also userdata, so maybe some nested ops are required here to access everything.
But what's really catching my eye is this in the metatable: __pairs = <function>
Based on what little I have learned about Lua, that looks like a custom pairs function defined for that table. So I think maybe I can call that __pairs function on the track table from api...get() to loop over its key-value pairs. But I haven't found the correct syntax. For example these don't work:
I realize @lollus' code works, but I am trying to discover what that __pairs meta function does, because it could be more direct access to the data.
SOL2 glue code is not 100% perfect.
Not all containers even if they look like having pairs will be useable with pairs.
The reason my sample code uses pcall to decide if pairs works, and if not uses members.
You can't be 100% be sure of the behaviour of userdata objects.
And if you doubt my code, look into comonapi2 utils deepcopy2table.
In helperscript.lua of commonapi2 I do create real (deep) copies of objects, but this is limited really for this specific use case and only works with the tested parts for the vehiclescript system.
If you have more questions, you can use transportfever.net as I really don't want to use the steam discussion system.
Don't be afraid to ask, but sometimes the answer is simply more complex then using one simple function. I am sorry...
A TrackType is a c++ object / structure not a iterable container in c++. So it has __members...
Not all members are bound or useable from lua for all objects
__members is something UG uses for console autocompletion.