From 2ffc991062e86f37566d8a8b18940c0f4eb3e92a Mon Sep 17 00:00:00 2001 From: mittorn Date: Sun, 14 Oct 2018 17:01:20 +0000 Subject: [PATCH] Persistent registration and login --- dlls/client.cpp | 5 +- dlls/enttools.cpp | 11 +- dlls/enttools.h | 5 +- dlls/gravgunmod.cpp | 263 +++++++++++++++++++++++++++++++++++++------- dlls/gravgunmod.h | 6 + dlls/weapons.cpp | 3 +- 6 files changed, 242 insertions(+), 51 deletions(-) diff --git a/dlls/client.cpp b/dlls/client.cpp index 9264f9b1..33e5092a 100644 --- a/dlls/client.cpp +++ b/dlls/client.cpp @@ -694,10 +694,7 @@ void ClientUserInfoChanged( edict_t *pEntity, char *infobuffer ) // prevent keeping other's uid on saverestore CBasePlayer *pPlayer = GetClassPtr((CBasePlayer *)&pEntity->v); - const char *uid = GETPLAYERAUTHID( pPlayer->edict() ); - if( !uid || strstr(uid, "PENDING") ) - uid = g_engfuncs.pfnInfoKeyValue( g_engfuncs.pfnGetInfoKeyBuffer( pPlayer->edict() ), "ip" ); - + const char *uid = GGM_GetAuthID( pPlayer ); if( !pPlayer->gravgunmod_data.pState || !pPlayer->gravgunmod_data.pState->registered || pPlayer->gravgunmod_data.m_state != STATE_SPAWNED ) { GGMPlayerState *pState = GGM_GetState(uid, name); diff --git a/dlls/enttools.cpp b/dlls/enttools.cpp index 47a3f061..d1b9156d 100644 --- a/dlls/enttools.cpp +++ b/dlls/enttools.cpp @@ -62,7 +62,6 @@ void Ent_ClearBlacklist_f( void ) } } - bool Ent_CheckFire( edict_t *player, edict_t *ent, const char *command ) { if( !mp_enttools_players.value && ENTINDEX( ent ) < gpGlobals->maxClients + 1 ) @@ -75,11 +74,13 @@ bool Ent_CheckFire( edict_t *player, edict_t *ent, const char *command ) if( mp_enttools_lockmapentities.value && !pEntity->enttools_data.enttools ) return false; - // only if player online + // only if player online or registered if( mp_enttools_checkowner.value == 1 ) { if( GGM_PlayerByID( pEntity->enttools_data.ownerid ) ) return !strcmp( pEntity->enttools_data.ownerid, GGM_GetPlayerID( player ) ); + if( pEntity->enttools_data.enttools == 2 ) + return false; } if( mp_enttools_checkowner.value == 2 ) @@ -1087,7 +1088,11 @@ void Ent_Create_f( edict_t *player ) if( entity ) { const char *plid = GGM_GetPlayerID( player ); - entity->enttools_data.enttools = true; + CBasePlayer *pPlayer = (CBasePlayer*)CBaseEntity::Instance( player ); + entity->enttools_data.enttools = 1; + if( pPlayer && pPlayer->IsPlayer() && pPlayer->gravgunmod_data.pState && pPlayer->gravgunmod_data.pState->registered ) + entity->enttools_data.enttools = 2; + if( plid ); strcpy( entity->enttools_data.ownerid, plid ); } diff --git a/dlls/enttools.h b/dlls/enttools.h index d8e5e122..31349754 100644 --- a/dlls/enttools.h +++ b/dlls/enttools.h @@ -7,7 +7,10 @@ bool Ent_ProcessClientCommand( edict_t *player ); void ENT_RegisterCVars( void ); struct EntoolsEntData { - bool enttools; // created by enttools + // 0 - not created by enttools + // 1 - created by anonymous user + // 2 - created by registered user + char enttools; char ownerid[33]; }; diff --git a/dlls/gravgunmod.cpp b/dlls/gravgunmod.cpp index 88088a00..bbf8f83a 100644 --- a/dlls/gravgunmod.cpp +++ b/dlls/gravgunmod.cpp @@ -41,7 +41,7 @@ cvar_t mp_maxdecals = { "mp_maxdecals", "-1", FCVAR_SERVER }; cvar_t mp_enttools_checkmodels = { "mp_enttools_checkmodels", "0", FCVAR_SERVER }; cvar_t mp_errormdl = { "mp_errormdl", "0", FCVAR_SERVER }; cvar_t mp_errormdlpath = { "mp_errormdlpath", "models/error.mdl", FCVAR_SERVER }; - +static char gamedir[MAX_PATH]; void Ent_RunGC_f( void ); static bool Q_starcmp( const char *pattern, const char *text ) @@ -142,6 +142,7 @@ void GGM_RegisterCVars( void ) g_engfuncs.pfnAddServerCommand( "ent_rungc", Ent_RunGC_f ); g_engfuncs.pfnAddServerCommand( "mp_lightstyle", GGM_LightStyle_f ); + GET_GAME_DIR(gamedir); } @@ -223,7 +224,7 @@ void Ent_RunGC( int flags, const char *userid, const char *pattern ) continue; } - if( (flags & GC_ENTTOOLS) && entity->enttools_data.enttools ) + if( (flags & GC_ENTTOOLS) && entity->enttools_data.enttools == 1 ) { if( !userid || !strcmp( userid, entity->enttools_data.ownerid ) ) { @@ -350,23 +351,60 @@ void GGM_ChatPrintf( CBasePlayer *pPlayer, const char *format, ... ) CLIENT_PRINTF( pPlayer->edict(), print_chat, string ); } +bool GGM_FilterFileName( const char *name ) +{ + while( name && *name ) + { + if( *name >= 'A' && *name <= 'z' || *name >= '0' && *name <= '9' || *name == '_' ) + { + name++; + continue; + } + return false; + } -void GGM_ClientPutinServer(edict_t *pEntity, CBasePlayer *pPlayer) + return true; +} +const char *GGM_GetAuthID( CBasePlayer *pPlayer ) +{ + static char uid[33]; + const char *authid = GETPLAYERAUTHID( pPlayer->edict() ); + + if( !authid || strstr(authid, "PENDING") ) + { + const char *ip = g_engfuncs.pfnInfoKeyValue( g_engfuncs.pfnGetInfoKeyBuffer( pPlayer->edict() ), "ip" ); + if( ip ) + { + char *pUid; + + snprintf( uid, 32, "IP_%s", ip ); + + for( pUid = uid; *pUid; pUid++ ) + if( *pUid == '.' ) *pUid = '_'; + } + else + return "UNKNOWN"; + } + else strncpy( uid, authid, 32 ); + + if( GGM_FilterFileName( uid ) ) + return uid; + + return "UNKNOWN"; +} + +void GGM_ClientPutinServer( edict_t *pEntity, CBasePlayer *pPlayer ) { if( mp_touchmenu.value && pPlayer->gravgunmod_data.m_state == STATE_UNINITIALIZED ) g_engfuncs.pfnQueryClientCvarValue2( pEntity, "touch_enable", 111 ); pPlayer->gravgunmod_data.m_state = STATE_CONNECTED; - const char *uid = GETPLAYERAUTHID( pPlayer->edict() ); - if( !uid || strstr(uid, "PENDING") ) - uid = g_engfuncs.pfnInfoKeyValue( g_engfuncs.pfnGetInfoKeyBuffer( pPlayer->edict() ), "ip" ); - pPlayer->gravgunmod_data.m_flEntTime = 0; pPlayer->gravgunmod_data.m_flEntScope = 0; pPlayer->gravgunmod_data.menu.pPlayer = pPlayer; pPlayer->gravgunmod_data.menu.Clear(); - pPlayer->gravgunmod_data.pState = GGM_GetState( uid, STRING(pEntity->v.netname) ); + pPlayer->gravgunmod_data.pState = GGM_GetState( GGM_GetAuthID(pPlayer), STRING(pEntity->v.netname) ); } void GGM_ClientFirstSpawn(CBasePlayer *pPlayer) @@ -430,18 +468,162 @@ struct GGMPlayerState *GGM_FindState( GGMPlayerState *list, const char *uid ) return NULL; } +void GGM_WritePersist( GGMPlayerState *pState ) +{ + FILE *f; + char path[64] = ""; + + if( !pState->registered ) + return; + + snprintf( path, 63, "%s/ggm/registrations/%s", gamedir, pState->p.uid ); + + f = fopen( path, "wb" ); + + if( !f ) + return; + + fwrite( &pState->p, 1, sizeof( pState->p ), f ); + fclose( f ); +} + +void GGM_ReadPersist( GGMPlayerState *pState ) +{ + FILE *f; + char path[64] = ""; + + if( !pState->registered ) + return; + + snprintf( path, 63, "%s/ggm/registrations/%s", gamedir, pState->p.uid ); + + f = fopen( path, "rb" ); + + if( !f ) + return; + + fread( &pState->p, 1, sizeof( pState->p ), f ); + fclose( f ); +} + +struct GGMPlayerState *GGM_GetRegistration( const char *name ) +{ + struct GGMPlayerState *pState = GGM_FindState( registered_list, name ); + + if( pState ) + { + GGM_ReadPersist( pState ); + return pState; + } + else + { + FILE *f; + char path[64] = ""; + + snprintf( path, 63, "%s/ggm/registrations/%s", gamedir, name ); + + f = fopen( path, "rb" ); + + if( !f ) + return NULL; + + pState = (struct GGMPlayerState*)calloc( 1, sizeof( struct GGMPlayerState ) ); + memset( pState, 0, sizeof( struct GGMPlayerState ) ); + + fread( &pState->p, 1, sizeof( pState->p ), f ); + fclose( f ); + pState->pNext = registered_list; + pState->registered = true; + registered_list = pState; + return pState; + } +} + +unsigned int GGM_HashString( const char *s ) +{ + unsigned int hashval; + + for( hashval = 0; *s; s++ ) + hashval = *s + 31*hashval; + return hashval; +} + +void GGM_WriteLogin( struct GGMLogin *pLogin ) +{ + FILE *f; + char path[64] = ""; + + if( !pLogin->pState ) + return; + + if( !GGM_FilterFileName( pLogin->f.uid ) || !GGM_FilterFileName( pLogin->f.name ) ) + snprintf( path, 63, "%s/ggm/logins/%d.%d", gamedir, GGM_HashString( pLogin->f.uid ), GGM_HashString( pLogin->f.name ) ); + else + snprintf( path, 63, "%s/ggm/logins/%s.%s", gamedir, pLogin->f.uid, pLogin->f.name ); + + f = fopen( path, "wb" ); + + if( !f ) + return; + + fwrite( &pLogin->f, 1, sizeof( pLogin->f ), f ); + fwrite( &pLogin->pState->p.uid, 1, 33, f ); + fclose( f ); +} + +struct GGMLogin *GGM_LoadLogin( const char *uid, const char *name ) +{ + FILE *f; + char path[64] = ""; + struct GGMLogin *pLogin; + + for( pLogin = login_list; pLogin; pLogin = pLogin->pNext ) + { + if( !strcmp( name, pLogin->f.name ) && !strcmp(uid, pLogin->f.uid ) ) + { + return pLogin; + } + } + + if( !GGM_FilterFileName( uid ) || !GGM_FilterFileName( name ) ) + snprintf( path, 63, "%s/ggm/logins/%d.%d", gamedir, GGM_HashString( uid ), GGM_HashString( name ) ); + else + snprintf( path, 63, "%s/ggm/logins/%s.%s", gamedir, uid, name ); + + f = fopen( path, "rb" ); + + if( !f ) + return NULL; + + pLogin = (struct GGMLogin*)calloc(1, sizeof( struct GGMLogin ) ); + fread( &pLogin->f, 1, sizeof( pLogin->f ), f ); + fread( path, 1, 33, f ); + path[32] = 0; + fclose( f ); + pLogin->pState = GGM_GetRegistration(path); + pLogin->pNext = login_list; + login_list = pLogin; + return pLogin; +} + + struct GGMPlayerState *GGM_GetState( const char *uid, const char *name ) { struct GGMPlayerState *pState; + struct GGMLogin *pLogin = GGM_LoadLogin( uid, name ); - for( struct GGMLogin *login = login_list; login; login = login->pNext ) + if( pLogin ) { - if( !strcmp( name, login->name ) ) + return pLogin->pState; + } + else + { + for( struct GGMLogin *login = login_list; login; login = login->pNext ) { - if( !strncmp(uid, login->uid, 32 ) ) - return login->pState; - else - return NULL; // ask for login or nickname change + if( !strcmp( name, login->f.name ) ) + { + return NULL; + } } } @@ -508,6 +690,8 @@ bool GGM_RestoreState(CBasePlayer *pPlayer) if( !pState ) return false; + GGM_ReadPersist( pState ); + pPlayer->pev->frags = pState->t.iFrags; pPlayer->m_iDeaths = pState->t.iDeaths; if( pState->t.flHealth < 1 ) @@ -593,31 +777,17 @@ bool GGM_PlayerSpawn( CBasePlayer *pPlayer ) return pPlayer->gravgunmod_data.m_state != STATE_SPAWNED; } -bool GGM_FilterFileName( const char *name ) -{ - while( name && *name ) - { - if( *name >= 'A' && *name <= 'z' || *name >= '0' && *name <= '9' ) - { - name++; - continue; - } - return false; - } - - return true; -} - void GGM_Logout( CBasePlayer *pPlayer ) { struct GGMLogin *pLogin, *pPrevLogin = NULL; - const char *uid = GETPLAYERAUTHID( pPlayer->edict() ); + const char *uid = GGM_GetAuthID( pPlayer ); const char *name = STRING( pPlayer->pev->netname ); + char path[64] = ""; // unlink from list and free for( pLogin = login_list; pLogin; pLogin = pLogin->pNext ) { - if( strncmp( uid, pLogin->uid, 32 ) || strncmp( name, pLogin->name, 32 ) ) + if( strcmp( uid, pLogin->f.uid ) || strcmp( name, pLogin->f.name ) ) { pPrevLogin = pLogin; continue; @@ -643,6 +813,13 @@ void GGM_Logout( CBasePlayer *pPlayer ) pPlayer->gravgunmod_data.pState = GGM_GetState(uid, name); if( pPlayer->gravgunmod_data.m_state == STATE_SPAWNED ) GGM_RestoreState( pPlayer ); + + // remove login record + if( !GGM_FilterFileName( uid ) || !GGM_FilterFileName( name ) ) + snprintf( path, 63, "%s/ggm/logins/%d.%d", gamedir, GGM_HashString( uid ), GGM_HashString( name ) ); + else + snprintf( path, 63, "%s/ggm/logins/%s.%s", gamedir, uid, name ); + remove(path); } void GGM_FreeState( const char *uid ) @@ -657,7 +834,7 @@ void GGM_FreeState( const char *uid ) if( pPlayer && pPlayer->IsPlayer() && pPlayer->gravgunmod_data.pState ) { - if( !pPlayer->gravgunmod_data.pState->registered && !strncmp( uid, pPlayer->gravgunmod_data.pState->p.uid, 32 ) ) + if( !pPlayer->gravgunmod_data.pState->registered && !strcmp( uid, pPlayer->gravgunmod_data.pState->p.uid ) ) pPlayer->gravgunmod_data.pState = NULL; } } @@ -665,7 +842,7 @@ void GGM_FreeState( const char *uid ) // unlink from list and free for( pState = anonymous_list; pState; pState = pState->pNext ) { - if( strncmp( uid, pState->p.uid, 32 ) ) + if( strcmp( uid, pState->p.uid ) ) { pPrevState = pState; continue; @@ -708,7 +885,7 @@ bool GGM_CheckUserName( CBasePlayer *pPlayer, const char *name, bool exist ) return false; } - if( exist && GGM_FindState( registered_list, name ) ) + if( exist && GGM_GetRegistration( name ) ) { GGM_ChatPrintf( pPlayer, "Name %s busy!\n", name ); return false; @@ -745,12 +922,14 @@ void GGM_Register( CBasePlayer *pPlayer, const char *name, const char *password pState->t = pPlayer->gravgunmod_data.pState->t; pState->pNext = registered_list; registered_list = pState; + GGM_WritePersist( pState ); pLogin = (struct GGMLogin*)calloc(1, sizeof( struct GGMLogin ) ); pLogin->pState = pState; - strncpy( pLogin->name, STRING(pPlayer->pev->netname ), 32 ); - strncpy( pLogin->uid, pPlayer->gravgunmod_data.pState->p.uid, 32 ); + strncpy( pLogin->f.name, STRING(pPlayer->pev->netname ), 32 ); + strncpy( pLogin->f.uid, pPlayer->gravgunmod_data.pState->p.uid, 32 ); pLogin->pNext = login_list; login_list = pLogin; + GGM_WriteLogin( pLogin ); GGM_FreeState( pPlayer->gravgunmod_data.pState->p.uid ); pPlayer->gravgunmod_data.pState = pState; GGM_ChatPrintf( pPlayer, "Successfully registered as %s!\n", name ); @@ -817,13 +996,13 @@ void GGM_Login( CBasePlayer *pPlayer, const char *name, const char *password ) if( !GGM_CheckUserName( pPlayer, name, false ) ) return; - pState = GGM_FindState( registered_list, name ); + pState = GGM_GetRegistration( name ); if( !pPlayer->gravgunmod_data.pState ) { for( pLogin = login_list; pLogin; pLogin = pLogin->pNext ) { - if( !strncmp( pLogin->name, STRING(pPlayer->pev->netname ), 32 ) ) + if( !strcmp( pLogin->f.name, STRING(pPlayer->pev->netname ) ) ) { if( pState == pLogin->pState ) // same person break; @@ -844,11 +1023,13 @@ void GGM_Login( CBasePlayer *pPlayer, const char *name, const char *password ) } pLogin = (struct GGMLogin*)calloc(1, sizeof( struct GGMLogin ) ); pLogin->pState = pState; - strncpy( pLogin->name, STRING(pPlayer->pev->netname ), 32 ); - strncpy( pLogin->uid, pPlayer->gravgunmod_data.pState->p.uid, 32 ); + strncpy( pLogin->f.name, STRING(pPlayer->pev->netname ), 32 ); + strncpy( pLogin->f.uid, GGM_GetAuthID(pPlayer), 32 ); pLogin->pNext = login_list; login_list = pLogin; - GGM_FreeState( pPlayer->gravgunmod_data.pState->p.uid ); + GGM_WriteLogin( pLogin ); + if( pPlayer->gravgunmod_data.pState ) + GGM_FreeState( pPlayer->gravgunmod_data.pState->p.uid ); pPlayer->gravgunmod_data.pState = pState; GGM_ChatPrintf( pPlayer, "Successfully logged in as %s\n", name ); diff --git a/dlls/gravgunmod.h b/dlls/gravgunmod.h index 59a60754..750bfa29 100644 --- a/dlls/gravgunmod.h +++ b/dlls/gravgunmod.h @@ -104,11 +104,15 @@ public: }; + + struct GGMLogin { struct GGMLogin *pNext; + struct { char uid[33]; char name[32]; + } f; struct GGMPlayerState *pState; }; @@ -145,6 +149,7 @@ struct GGMPlayerState struct GGMPersist p; struct GGMTempState t; bool registered; + bool fNeedWrite; }; @@ -166,5 +171,6 @@ struct GGMPlayerState *GGM_GetState(const char *uid, const char *name); bool GGM_RestoreState( CBasePlayer *pPlayer ); void GGM_SaveState( CBasePlayer *pPlayer ); bool GGM_PlayerSpawn( CBasePlayer *pPlayer ); +const char *GGM_GetAuthID( CBasePlayer *pPlayer ); #endif // GRAVGUNMOD_H diff --git a/dlls/weapons.cpp b/dlls/weapons.cpp index cd777036..949cf42d 100644 --- a/dlls/weapons.cpp +++ b/dlls/weapons.cpp @@ -828,8 +828,7 @@ void CBasePlayerItem::AttachToPlayer( CBasePlayer *pPlayer ) pev->nextthink = 0;// Remove think - prevents futher attempts to materialize SetTouch( NULL ); SetThink( NULL ); - - enttools_data.enttools = false; + enttools_data.enttools = 0; } // CALLED THROUGH the newly-touched weapon's instance. The existing player weapon is pOriginal