Calling player functions via module

I’m having some troubles calling Player functions, specifically Nick via a c++ module.



// getting the localplayer (works fine as far as I can tell)
LUA->PushSpecial(SPECIAL_GLOB);
LUA->GetField(-1, "LocalPlayer");
LUA->Call(0, 1);

void* ply = LUA->GetUserdata(-1);
LUA->Pop(2);

// getting nick
LUA->GetField(-1, "Player");
LUA->GetField(-1, "Nick"); // crashes here
int ref = LUA->ReferenceCreate();
LUA->Pop(2);

LUA->ReferencePush(ref);
LUA->PushUserdata(ply);

LUA->Call(1, 1);

const char* nick = LUA->GetString(-1);

LUA->Pop();
LUA->ReferenceFree(ref);


I’ve also tried this but it didn’t work (I guess its an approach similar to how it would be in lua)



LUA->PushSpecial(SPECIAL_GLOB);
LUA->PushUserdata(ply);
LUA->GetField(-1, "Nick");
LUA->Call(1, 1);

const char* nick = LUA->GetString(-1);
LUA->Pop();


I’m pretty clueless right now, so I’d appreciate any sort of help.
Thanks

You are partially on the right track. Calling the Lua function is the only practical way to do it without some unpleasant reverse-engineering. But, you have to remember that Entities are not tables. They are userdata. Userdata doesn’t have fields like a table does. What they DO have are metatables. The metatable defines how the language operators should work with the userdata. In the case of gmod Players (and Entities), the metatable defines itself as the lookup table for indexing operations, giving the userdata table-like behavior. But, most of the C API functions for Lua will ignore the metatable. So, instead of trying to index the userdata directly, as you would with Lua code, you must grab the desired function from its actual location (the Player metatable).

EDIT:

Entity metatables are actually more complicated than this, this is just a simplified explanation.

Your code is so weird. Just put the player on the top of the stack and do this.
[cpp]
LUA->GetField(-1, “Nick”);
LUA->Push(-2);
LUA->Call(1, 1);
[/cpp]
The name is then at the top of the stack. Don’t forget to pop everything you need and such. I’m just posting the minimum working code. The lua equivalent to the above code is this.
[lua]ply.Nick(ply)[/lua]

That’s not true at all. He can index the userdata just fine because of the metatable’s __index. Unless it’s a “raw” function, it obeys the metatable. lua_getfield is not a raw function. Specifically what functions are you talking about?

I suppose that’s what I get for trying to give Lua help under time constraints. :v:



// getting the localplayer (works fine as far as I can tell)
LUA->PushSpecial(SPECIAL_GLOB);
LUA->GetField(-1, "LocalPlayer");
LUA->Call(0, 1);

void* ply = LUA->GetUserdata(-1); // This is for interacting with the userdata in C. We can't without prior mentioned reverse-engineering. Remove.
LUA->Pop(2); // Remove this, we need to keep the userdata on the stack to get anything from it

// getting nick
LUA->GetField(-1, "Player"); // remove this
LUA->GetField(-1, "Nick"); // keep this
int ref = LUA->ReferenceCreate(); // You can use references if you really want (but this references the wrong stack item), or you could simply use PushValue or Insert

LUA->ReferencePush(ref);
LUA->PushUserdata(ply); // This is a bad idea. The pushed userdata wouldn't have the proper metatable. It's best to stick with the one you started with.

// Once you have the function at -2 and the userdata at -1, you can call it.

LUA->Call(1, 1);

const char* nick = LUA->GetString(-1);

LUA->Pop(); // pop everything that is left here. If you used Insert, this should just be the returned string and the global table. If you used PushValue, then you will also have another userdata to clean up.
LUA->ReferenceFree(ref); // only keep this if you used references


I’ve given some partial commentary on the code to get you started.

Thank you both for the explanations & guidance. Managed to get it working like this, which I’m pretty sure is the way you guys we’re trying to get me to do it.



LUA->PushSpecial(SPECIAL_GLOB);
LUA->GetField(-1, "LocalPlayer");
LUA->Call(0, 1);
LUA->GetField(-1, "Nick");
LUA->Push(-2);
LUA->Call(1, 1);

const char* nick = LUA->GetString(-1);
LUA->Pop(3);