Passing Entites through Lua Modules.

I cant seem to figure out specifically what class type is being pointed at by lua userdata.



int testLuaFunc( lua_State *state ){
    UserData *ud = (UserData*)LUA->GetUserdata( 1 );
    CBaseHandle *hent = (CBaseHandle*)ud->data;
    if( !hent ){
        Warning( "Failed to find ent
" );
        return 0;
    }
    edict_t *ent = engine->PEntityOfEntIndex( hent->GetEntryIndex() );
    Msg( "%s
", ent->GetUnknown()->GetBaseEntity()->GetModelName().ToCStr() );
    return 0;
}


That is bound to a global test function in lua and when called with an entity it does properly get the entities model. So I presume the userdata.data member points to a CBaseHandle object.
Buuuut when I try to do it the other way around and push a entity from C to lua it crashes (after like 3-10 seconds). Looking with a debugger it looks like the CBaseHandle pointer coming from lua points to some class that just so happens to have the entities CHandle 32bit UID.



// player is defined further up as `CBaseEntity *player`
CBaseHandle hPly = player->GetRefEHandle();


edict_t *ent = engine->PEntityOfEntIndex( hPly.GetEntryIndex() );
Msg( "debug: %s
", ent->GetUnknown()->GetBaseEntity()->GetModelName().ToCStr() ); // this does print out the model of the player as it should


GarrysMod::Lua::UserData *playerUd = (GarrysMod::Lua::UserData*)LUA->NewUserdata( sizeof( GarrysMod::Lua::UserData ) );
playerUd->data = new CBaseHandle( player->GetRefEHandle() );
playerUd->type = GarrysMod::Lua::Type::ENTITY;
LUA->ReferencePush( PlayerMeta_RefID ); // This pushes _R.Player properly I promise.
LUA->SetMetaTable( -2 );



So does anyone know what class is being pointed at by Garry’s code when sending an entity through C?

EDIT:
Looks like it’s a heap corruption issue. Apparently something in tier0 is trying to access/free my CBaseHandle…
Anyone know of the ‘appropriate’ method for passing CBaseHandle back to lua? This is becoming an extreme pain.

EDITEDIT: Decided to compile on linux and check if everything works still and valgrind is saying that there’s nothing wrong with how my dll is accessing memory. Looking back at windows its something in ntdll.dll that’s creating a INT3 breakpoint (keep in mind it does this like 3-10 seconds after I call this function) for whatever reason it feels like and ‘crashing’ the server…

Not sure, but if you need a ghetto fix, you can return the index of the entity. There’s a func in CBaseEntity called Index();

Not sure what you mean by that, needs to be a userdata for any of the Player metamethods to work on it. Unless you’re suggesting I just push the entindex and let the user do Entity( entIndex ). That would work but I’d rather have my hook do this properly since I have access to all of the engine internals.

Lua entities are "C_BaseEntity"s, I’m not really sure why the first code example works, but I’m willing to bet you’re being fooled by outdated SDK headers. Specifically in the construction of the CBaseHandle.

Have you tried simply pushing the entity like in the following?


playerUd->data = player;

print( TestFunc( Player(2) ) ) prints Player [NULL] and then crashes. Also Isn’t C_BaseEntity clientside? Is there a difference between CBaseEntity and C_BaseEntity?

C_BaseEntity is the clientside part while CBaseEntity is the serverside one.
Valve usually has an include file clientside which defines C_BaseEntity as CBaseEntity so they don’t have to put ifdefs all over the place everytime they use it in the code.



// Hacky macros to allow shared code to work without even worse macro-izing
#if defined( CLIENT_DLL )

#define CBaseEntity				C_BaseEntity
#define CBaseCombatCharacter	C_BaseCombatCharacter
#define CBaseAnimating			C_BaseAnimating
#define CBasePlayer				C_BasePlayer

#endif


It’s completely fine to use CBaseEntity in the code if you have the right includes.

Hrm well _Kilburn responded to my PM letting me know CBaseHandle is the proper object to be passing through the userdata.data member. So the code checks out, the crash must be caused by some protection library that visual studio is linking my module against.

In a lot of other gmod modules I see people disable the libcmt default library. When I try that myself I get a lot of missing symbols. What would be the reason for disabling libcmt? (Not sure if it’s related at all, but I’ve got no other ideas.)

FUCKIT I’ll just fucking use Entity( entIndex ) to get the userdata on windows.



LUA->PushSpecial( GarrysMod::Lua::SPECIAL_GLOB );
LUA->GetField( -1, "Entity" );
LUA->PushNumber( player->entindex() );
LUA->Call( 1, 1 );
GarrysMod::Lua::UserData *playerUd = (GarrysMod::Lua::UserData*)LUA->GetUserdata( -1 );
LUA->Pop(2);